Warning: file_get_contents(https://raw.githubusercontent.com/Den1xxx/Filemanager/master/languages/ru.json): failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 88

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 215

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 216

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 217

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 218

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 219

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 220
PK!#bigdecimal-3.1.3/gem.build_completenu[PK!y״bigdecimal-3.1.3/bigdecimal.sonuȯELF>`3@@8 @   pp!p!@ HH!H!888$$ Std Ptd8k8k8kTTQtdRtdpp!p!GNU;VzmUr%GF z@j zBE|X=|mt2؁9wxGIqXuũTv|oq: @)/[gjah}x0BaK ""GQ"0" 76"mXW_K, jowJHyF"mZ'!1! p ! =!Ux! p!w SVX &|__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizegOne_ABCED9B4_CE73__00400511F31Druby_snprintfruby_xfreerb_thread_currentrb_thread_local_asetrb_inspectrb_str_duprb_str_catrb_exc_new_strrb_exc_raiserb_obj_classrb_class_nameruby_xreallocrb_obj_freeze_inlinerb_cBigDecimalrb_data_typed_object_wrapruby_xcalloc__stack_chk_failrb_check_typeddatarb_thread_local_arefrb_num2ullrb_ull2inumrb_yieldrb_protectrb_jump_tagstrlenmemmoverb_num2ushortrb_fatalrb_eFloatDomainErrorrb_raisememsetmemcpyrb_bugruby_malloc_size_overflowrb_eArgErrorrb_sym2idrb_funcallvrb_float_valuerb_big_cmprb_fix2intrb_error_arityrb_num2intrb_eTypeErrorrb_id2symrb_hash_lookup2rb_sym2strrb_check_string_typestrncasecmprb_debug_rstring_null_ptrbigdecimal_parse_special_stringstrncmprb_str_tmp_newrb_str_new_cstrrb_str_resizerb_warnrb_absint_sizerb_num2ulongrb_num2longrb_big2strBigDecimal_dtoa__memcpy_chkrb_cstr_to_inumrb_cFloat__memset_chkrb_cSymbolrb_cIntegerrb_cTrueClassrb_cNilClassrb_cFalseClassrb_typeddata_is_kind_ofrb_assoc_newrb_ll2inumrb_str_newsqrt__errno_locationruby_strtodrb_float_newrb_ary_new_caparb_ary_pushrb_intern2rb_Rationalrb_usascii_str_newrb_string_value_cstrrb_memhashrb_category_warnrb_num_coerce_cmprb_num_coerce_reloprb_num_coerce_binrb_rational_numrb_rational_denrb_eZeroDivErrorrb_check_convert_typerb_complex_imagrb_complex_realrb_keyword_given_prb_opts_exception_prb_to_intrb_hash_duprb_big_signInit_bigdecimalrb_ext_ractor_saferb_cNumericrb_define_classrb_undef_alloc_funcrb_undef_methodrb_str_new_staticrb_define_constrb_gc_register_mark_objectrb_define_modulerb_mBigMathrb_num2llrb_thread_check_intsrb_eMathDomainErrorroundrb_dbl2bigrb_big_packrb_define_methodrb_define_global_functionrb_define_singleton_methodruby_xmallocBigDecimal_strtodstrchrldexpBigDecimal_hdtoalibruby.so.3.2libm.so.6libpthread.so.0libc.so.6_edata__bss_start_endGLIBC_2.14GLIBC_2.3.4GLIBC_2.4GLIBC_2.2.5/opt/alt/ruby32/lib64Pti ii ui  ui ui p! 5x!4!!!#Z!"ZЌ!V!Y!OX!8!05!!H! P!X!`!h!p!x!{!&!!<!>!A!K!W!g!jȏ!kЏ!o؏!s!x! !(!0!8!@!H!P!X! `! h! p! x!!!!!!!!!!Ȑ!А!ؐ!!! !!!"!#!$!%!' !((!)0!*8!+@!,H!-P!.X!/`!0h!1p!2x!3!4!5!6!!7!8!9!:!;ȑ!=Б!?ؑ!@!B!C!D!E!F!G!H!I !J(!L0!M8!N@!OH!PP!QX!R`!Sh!Tp!Ux!V!X!~!Y!Z![!\!]!^!_Ȓ!`В!aؒ!b!c!d!e!f!h!i!l!m !n(!p0!q8!r@!sH!tP!uX!v`!wh!yHHi!HtH5j!%j!hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?h@hAhBhChDhEhFhGqhHahIQhJAhK1hL!hMhNhOhPhQhRhShThUhVhWqhXahYQhZAh[1h\!h]h^h_h`hahbhchdhehfhgqhhahiQhjA%]c!D%Uc!D%Mc!D%Ec!D%=c!D%5c!D%-c!D%%c!D%c!D%c!D% c!D%c!D%b!D%b!D%b!D%b!D%b!D%b!D%b!D%b!D%b!D%b!D%b!D%b!D%b!D%b!D%b!D%b!D%}b!D%ub!D%mb!D%eb!D%]b!D%Ub!D%Mb!D%Eb!D%=b!D%5b!D%-b!D%%b!D%b!D%b!D% b!D%b!D%a!D%a!D%a!D%a!D%a!D%a!D%a!D%a!D%a!D%a!D%a!D%a!D%a!D%a!D%a!D%a!D%}a!D%ua!D%ma!D%ea!D%]a!D%Ua!D%Ma!D%Ea!D%=a!D%5a!D%-a!D%%a!D%a!D%a!D% a!D%a!D%`!D%`!D%`!D%`!D%`!D%`!D%`!D%`!D%`!D%`!D%`!D%`!D%`!D%`!D%`!D%`!D%}`!D%u`!D%m`!D%e`!D%]`!D%U`!D%M`!D%E`!D%=`!D%5`!D%-`!D%%`!D%`!D%`!D% `!DH=))1"H1H=)HT$,HHT$DLUH56*SHHdH%(HD$1 HߺHPHHHk} H$H?H9w HH_OHH?Hk} H9wHH+HHD$dH3%(tHH[]H=)17H% f.H=9_!H2_!H9tHZ!Ht H= _!H5_!H)HHH?HHtHZ!HtfD=^!u+UH=Z!Ht H=~W!d^!]wHGH(ff.@!fDHB f*ffffLBfHMt6J$fH*Y 32XIvJ(fH*Y 2XHRHHffW92H1HH1HHf]!f.1ztHY!^y1\!1HHa1HHH:1HHfHIHW ft%ftwfz1ft)H@H"L1HDfubHTL1tkuA+IH"L1mHH L1OTDHL1/4DA IfDHL1DHLHtfff.@USHH-\!HHTH[H]DSHH@uHu4H!H5 #HHHH 5Hff.U(SHH4$HHHDHt6H/6HXHtHE HH(HD$iHD$H[]DHXH[]HtSG PfwI HsDHW>FHDuHOHD HxH9sH)HH@fHHHH)Hff.@AVHGS!1AUATUSHH dH%(HD$1HU!H8IH-Hɚ;HD$HSZ/DHD$ H HHHH Hiʚ;H)Htu1Ll$ 1HSZ/DLQHLvHH HHIHHI HDH Hiʚ;)ЉHɚ;LLf.HHHH HHHHHH HHH Hiʚ;H)Љ…u Hɚ;wHɚ;~H8fD(H@H@H@fp X$L; uI;D$ tID$ LL H|$dH3<%(LNH []A\A]A^DH(LHHsLpHx$LpIfH KL HhHHP$LDLDL@,IL)H)F1҉׃L 9M 89r+(H@H@H@@$fx @@uK(H@H@HhfP LLgHx fDSHH5P!HHUfP H[SHX!HH8Ht"tH[fH[HW!HH1[HWUH88HSHHHH@u HH[]kHtHPHHHHH9HGHH[]ATUSH4HH?H9w*LdH&W!LHHH[]A\H0Iff.USHdH%(HD$1HT$H=8Q!HHH]|$uHL$dH3 %(Hu H[]VAVAUATIUSHmHt^ItTI>(111fD<.tDfD04HHHGH)I9u@HD$ MHt$(H|$H8[]A\A]A^A_DSHhS!3HHHtH[fH9S!HH1[USHdH%(HD$1HT$H=XM!H|$uHL$dH3 %(Hu H[]wfATAUHS/f tEt$HHr$HH=1fu[1]A\@HL!HH5H81EDHOL1H~;H~'I@HHHHHLGDHyI@HHAHvHHHHf G$HG fw 1H5MHHIHNfDf ~1G$HGfW 1H5fDG$HGfG fDM~#HHIH 'DHHIHf.HHIH:ffO fO Afw#]HsG$1HGfHWf.HBDD$Eu2HHuG$HGf~f1fW f.w$HWurU1SHHHuL$tHtH)HHHWuH[]ffG 1HCHt(H{$Hʸff.fAWIAVIAUMATIUHSHLD$9IWH|$PE$HL$XI^HuI+_LM9VMCVH~LD$I9HIuH88HIFHH;EsRI$IOHEH4H9HKH9H)HHIHH9AD HL$XMU/@I<$H9rAD HL$P뛐IIFII$MUIFLUHHEHHDHH[]A\A]A^A_DIMUIMUF fR ff@fAD fteft_@L fAG$1H5$HGfDG D@tStff~N1G$1H5HGfO rftbf_fG$HGfw 1H5%Df.HfdfffDf@f G$HGNA1fD HH[]A\A]A^A_D$Et1f} DM1DHI9}ɚ;nMf} HEE$HE7fM HHEMtYH88LHHHUHI)t8U$1ɾKfDҁɚ;v HEHI9uۉU$HH[]A\A]A^A_@FfL_1MG$IL\$AE1A$HD$8HD$tfDHD$1J|$L $LD$HfAL $LD$HEJcH>DfU fB\$H#D$$AwBD\$$E4@M-f.A @BD$Ht$HZODA1fDw fDD4$D$$E1D$ <$f} D,$EYANxt$$fAvf} x []A\A]A^Avf} ~HL[H]A\A]A^DAE#wDAdwDAE#wAeAwAtAwjf.AVAUATUSF HfAffPfHVLnHH$Hv$HWDfAOąL9oLFoLoN4fGLnA t)L9mL1ҋM$MtU LHCLkKD[]A\A]A^ÐDC$fHCDNE~@1fs []A\A]A^@G$1HG1f{ []A\A]A^1fK DG$fHGDNE~0fW SD1HLk6DfG #ff.fATIUHSӺ :HvL[H]A\f[1]A\fN$tyHFH~pHVN H9ssH)HGHGH9HG1fHWfG HFHtHHHLL$AL$HH9u ffDG$HGf~ fW ffG fDAWE1IAVAUATI̹UHSHHXF$HFfDV LHT$@LAW AL$ rAfffbfbE$HEfE H|$@AD$ f fC$HCfS fHEHHX[]A\A]A^A_fID$HD$HHHEH|$@HD$0HwHCHD$H9HC$HHVDHȋL L$HHH9uHD$H9T$vHD H9u1H|$0HT$0@@HD H9uAD$$HD$8Hiʚ;H|$HHD$ HD$v(AD$(HD$8HD$ 1Ht$ H|$HHHD$HD$Ht$0HH9HGHD$HHD$HAISZ/DH<LpH|$(fJ IuH< G$Hiʚ;D_(LH9D$ H9D$H9t$0%1Ht$8D (ML$MIL;L$H|$(LBL$E1HLLMGfDʚ;FD)L$HL$EtD9seʚ;D)AL$LH)I9r\At 1IHɚ;vHH HIH ЉHiʚ;H)։H9r)AfDLD)E1H)L$I9sD)L$BD$JT =ɚ;v-ʚ;HBBB=ɚ;wL;l$HD$0HHEHD$@H@HE._HX1[]A\A]A^A_DIL;l$B1Ht$D $IID$MLL\$HIUIv<,A9|$,Br,MK<+IOET$D9T$w HH9uID$LPOLL9L$L)L1M&fDʚ;D)D$HLH)L9w A| D$D7D9r)1)fDHA$A$fbfbAE$HEfDE 1H5hHX[H]A\A]A^A_It$HHH|$@AD$ f NffE H-HD$L|$@H߾HCIGHCZ,1fA HfC fE$HEfu A|$$I|$L|$@1fHTLfA xC$HCfK |fE$HEf} E1E$1ҿHEH5@fDM H-ffAD$$HD$8Hiʚ;H|$HHD$ DAWAVAUAATIUHSHHHdH%(HD$81Ƀ1҅tOAT$ M rAfuefC$HCftAfD[ @H\$8dH3%(HqHH[]A\A]A^A_f.f_E1AHEAGt6I9D$*MD$H}I9HIFHt5E$A9D$$|1fD\$E9\$wdHH9uI9wPA1fM@fNǍDpu+AC$ HCfDS @M1fAE1ffDK AHL$ G|?EE|GHD$fEPLHHHD$ PLL$@LD$8_AXD$ HLD$(IL$L$H|$ Ht$0L$ Mt3JH9rfJH9IHBT$T$MuH9dII)IHD$I9u1HHIAD$BD$1HtnJL Hf1HHtKHAD$=ɚ;v-ʚ;DDfDNAvfDk {I)MtBD 1fAfC HC1HtT L$ 1HHCH,@PHHLHD$ PLL$@LD$89Y^D$ H!LD$(It$L$9r)1҉t$ H|$ J4HL$0H9nMtMAʚ;AfDJ4AH9IDHB+T$D)҉T$MuѺHH9v'HAʚ;DHH)кD$H9rE1H9@HtFHH)LH@)1At$Ht"HAt$9sɚ;fH)Ht)T M91fA} EDD1AfC EDHH:HCH}DILpDLHHCHKvfDHHAD$D$H9rMLLHHLu1HHu HH[]H}$Hs$HH[]ÿff.@ATUSHdH%(HD$1oHT$H=+!6HÃwHL%)1!HTLH|$u0HL$dH3 %(HuH[]A\ff.@SH@ tf@uHuKHSЃv,HA+!HH5]H81DHcHD [f.HHu@HhH/!1H@H9tH uDHdH%(HD$1@@uHuOHHt[H<H$nHfHt$dH34%(ukHHH t4HHu@{f1f/@H?H>Hv두Ht]PUSH~H>t >fD@uUńuU=THtHЃHH\H[]fDńt8HtHt H@t%HEt@t%HEP@t%HE,t%HE HH\H[]fH--!H\HHHHH[]H](!H5FH81H^H'!H5MH81ff.ATIHUSHHH4$(HDK1LfP HH%!Hh@$H@H@cH;uH9X tHX HH9H[]A\ÐAUIHATAUSHHHH4$(HDHHh@$H@AuHfP 1HV$!LH;uH9X tHX HHHH[]A\A]fDfC DATIUSH?H9wOHlx]u H[]A\@uJI<$Ht@u3x?HcH[]A\f.HH˺1HD&!H5H81AWAVAUATUHSHHHHt$]hHD$U @ HfJfH|$HH|$HULeIH|$L9HD$N< HCIHH|$ H9sHEHHCHD$HpHD$8HD$f} @ ffC N,1H{$L]H|$ L{sID$Lt$ NL+ E1HD$(HD$ISZ/DAKHHD$IGHD$0M~L9l$L\$(LH+|$HD$I9Ht$LD$fHIL9At$HHH HIHH ʉHiʚ;H)A1ɚ;v A iʚ;)A1tMtAALAA=ɚ;w%zf.L$щL$ɚ;Z Aiʚ;)L$HHuHIL97fDIMIL9l$ H|$8HVH|$8HHHD$8H@HH[]HA\A]A^A_fWfWC$HCfK HH[]A\A]A^A_1K<HIH4$(HDFILp@$LH@fAE HEIEHD$HpHLHH1[]A\A]A^A_LIHD$HHl$HD$H|$$H1fHHTH\$8@}$pH}efHt$HҍTaH\$8fC$HCfS HH[]A\A]A^A_HD$0L)L9l$(rLIH+|$fM1f:1H7H\$8H\$8LH&ATUSHH=x&!Hߺ$HHHHt6 t uL$(fD0 HADII<2HLBPuDA Av.< t*<_uMADt<9wIrE`M1E1LT$ KT H\$0I88HLT$ILL$HHHELjI9LBN4$Lٿ|$(LL$HLhLT$@$H@AfDX 1IVH{$LL$LT$jHLT$LL$wHD$ <-GHD$1<+H9KHD$ 1LL$IHHrDLHHHH IH LHMHLA0McM)I9HHHH/Hw`H9|wHH9HHuHE11H`HPHIHD$0HHH9HFHT$08fHGLHHHtHL$LL$D$ILAfDHD$@11E1HD$HE1EpML$@tMtHSHJf|$VL荻H5HH\!H81買fLD$(1fDHEHD$ HD$ H4$H88H(HHHDISHLp@$H@fh HD$H;fDHHHHDKD.HD$@E1E1D!HHH!HT$HHFIHHD$HIT LHHD$ +IHHIT I<21T$tNuDA A< <_Y0 HAD HI<2HuD$LA<-D$1<+u II88E1HA1G\L4)LH?HL1H)HIHHHHH9D$1I9D$Hw-I9v(1 A2HHDHЉD$HwI9wI9HMtX1L9 fHt$HH88)LcH00000000LHHHLH)‰ЃvAt 0EI\L1Ҿ D HaH88HHHLHHHHH,dH5 !HHbL$HhBfP 4@Epu HH#H H H!HHi!H5"H81踫H88)H00000000HcHHHHH)HH t 0HD$P1L J(D#98HNjD$H)HcϾ98)ߍK|$HcD)ljLcK\5)HcH)LIH|L)ƍ11ƃI<09rH~HHHLH)2~1AJ 9rdf98K<,0)HcH,HL)貫L1Ҿ D, 1蜩H[K<4LLLL$LL0軮LL$0000D0000 0000D0000fD00fD00:H !H5GH81"HSIH !H:H !H+Hl !HH% !H HV !Hff.HHHHDE1H !SAHHlHtHH1H[D[fATUSHHdH%(H$1HHHHuHuuHCHH ~H߉|HH5!HH$dH3 %(.Hİ[]A\Hw*HHcH>H5Y!HuD1@H߉@HmfD HHD$H tuHHHXHq HttH߉ZHHD$HD$HD$HLd$ 1HHDL菦LHHpHXH fH=Ht$?Ht$q萧H!HH8讱ff.UHպSHHHdH%(HD$1IHH$A@ fw ]Hr5I@HhAL HptH~AL$uCHHuHtHHtHEHD$dH3%(H[]EH$ExA ADADAAA wRAE1A9t*fDЉA9uAA wIPHxc tMcL)HtH9HLHH H"IPH1H9} H)McHL)HEf.HHHH)1H EH$HxAL HEA HHtH McHIM)H9ILXHMcHL)kEH$HHEA E1SH dH%(HD$1HT$Ht$xH|$H@HxDH\?H@H|$Hx;H|?HNHL$dH3 %(u(H [ HfDHqH1dH%(HD$1HH<$H@HxHD?HL$dH3 %(u HÐ蛢@H1dH%(HD$1H~H<$H@HxHD?HL$dH3 %(u HÐ;责@USHHdH %(HL$81Ʌxv 1衦HHH H5aHHHHD$O1Hp2蔧HD$HD$HXH u}HEHRHH HD$Hp1軡HHT$E11H4HHRH)H΢H|$HAHD$HL$8dH3 %(u*HH[]DHXHvH=7e荢ff.fHHP 1ftftft HfD1HfHHP ft1fHDHDHHwfx HHHHGH@ HHDHHH$tPH@HHHH$HEHH HH8LHHHD$1ɺHH1HHD$(dH3%(H;H8[]A\A]{I}@謇IHHHHH$HEHH HH8LHHHD$DIcͺHHA1H'HHL$(dH3 %(u/H8[]A\A]fkIZ1e@AUIATUHS1H8dH%(HD$(1賖hIHHHHH$HEHH HH8LHHHD$M1ɺHHK1H1HD$(dH3%(H;H8[]A\A]I}@IHHHHH$HEHHZ HH8LHHHD$蔕IcͺHH葫1HwHHL$(dH3 %(u/H8[]A\A]f車IZ1赈萅AWIAVAUATIUSHHdH%(HD$81qPI<$NMd$9)@ʄLcAu ML0A1薔HLIHHHD$HEHH HH8LHHHD$=ALHH;1H!HHL$8dH3 %(oHH[]A\A]A^A_HD$A1HLIIHHD$ID$HHN HH8 LHHHD$舓HL$LH腩EA1HbHD$8dH3%(H;HH[]A\A]A^A_@uHu/@to芈E1HAHD$DkfHEw$HHcH>H5 HAxu%*"HHcH>D1HH'HHT$HT$AV f*tf1HL$(dH3 %(_H0[]A\A]A^DIF1HH4HHT$fH HHfH|H HtfH HRHfH|H HtaDH H(HuDHK|Hl HtHHLqyHIHL$(dH3 %(5H0HLH[]A\A]A^zfDH Hu%HyDH{H HtHL$(dH3 %(H0HLH[]A\A]A^x)@EЅ*H؀"|H ZHcH>Dqzff3f^fHxI9~f*"#|HuHcH>f*"{HժHcH>1fff*"{HHcH>fDfDHfHfHHDHBf.fdf*"{HHcH>1f*"zHdHcH>f~}*"zH˫HcH>LHMFM9LIFHt.Av$9p$rw61DT$E9T$wrHH9uM9s3f)"f~*"@zHګHcH>*"zH@HcH>sHff.fGf>fLf<f=f*rfAUIATUSHHH8dH%(HD$(1HHH$H؃Hu H1HHIMI$HD$ID$HEHH HH8ԬLHHHHHD$1HAHHL$(dH3 %(H8[]A\A]HHt,HOHEHH4IFD1HI*fHD$(dH3%(uH8HL*[]A\A]uqAUATIUHSH(dH%(HD$1HHHu2HD$dH3%(H(LH[]A\A]f1LHILHHHHHH$MHH近1HŒHEHL$dH3 %(u!H([]A\A]fDHsH3pH H5H81oAUIATUSHHH8dH%(HD$(1;HHH$H؃H!u H1HHIMvI$fA|$ HD$t f} u-HEHL$(dH3 %(oH8[]A\A]f.LHIHHH5 HH8HHHD$Mf} C$HCfS @HHt,HHEHH4 ID1HIf Hr H82HHHD$LHHĜ1H蚐HffC DHD$(dH3%(uH8HL-[]A\A]FrnAUATIUHSH(dH%(HD$1HHHu2HD$dH3%(H(LH[]A\A]yf1}LHI[LH}HHHHH$ HH1H腏HEHL$dH3 %(u!H([]A\A]fDHpH3mHD H5ҖH81lAUIATUSHHH8dH%(HD$(1HHH$H؃H!u H1HHIMvI$fA|$ HD$t f} u-HEHL$(dH3 %(oH8[]A\A]f.LHōIHHH HH8訦HHHD$Mf} C$HCfS @HHt,HHEHH4ID1HIf H2 H8HHHD$LHH脙1HZHffC DHD$(dH3%(uH8HL+[]A\A]oqkAUATIUHSH(dH%(HD$1HHHu2HD$dH3%(H(LH[]A\A]yf1zLHI[LHzHHlHHH$͌HH?1HEHEHL$dH3 %(u!H([]A\A]fDHxmH3kjH H5H81SiAWAVAUIATUSHHHxdH%(HD$h1HHHD$H؃Hu H1HH}IMI$H HD$ID$HEH;L4LOt6 誣H;L1IHHD$ 荣H;L1IHHD$(pH;L1IHLD$HD$0NHLLIHLHD$8ҏIEH;H,HHH;HIHL $HD$@L $1ɺHHLLHD$HmLH袎LD$LHLL$ L$LLLD1LIHL$hdH3 %(Hx[]A\A]A^A_@HHt,HLHEHH4žICD1H詾IM,H Hu*H-f. HlH HtHHLIkH811FH% gAWAVAUATUHSHHdH%(HD$81Hu9HL$8dH3 %(cHH[]A\A]A^A_fHkH0IH?H9BH\HjHHxHHI%1nvL5 HSII>辠LHIHHD$/IHHD$HH@u HHHIT$I>HHHD$ HEHDIUH9HJHF1HT H&HLHHHT$(L譌LuHLr1LxIEsHiHHLuDHEH*HHNDHL$HHLH$HuXHi HЎHuDHjHD HtHHLh@HhHH$1H蒆H;Jd@uHu[HHtvHtd@uR@ t@H HHC H5H81cH+ H5H81zcHWH HH HH HH HH HAVAUIATUSHH5 IHpdH%(HD$h1eH5 HHHHD$@acu-pu HVH؃HIH5y L!c LH5_ d1LHIHHD$H1LHt$H$H9\$ HM\$L- HI}H HB1HS9I}HT1IHHD$PLHLHHHHD$X蝉I$Av$HD$HHD$IHD$ x1L^I$HL$hdH3 %(Hp[]A\A]A^f/HLfHuhDHH uDHlI@C$1LHiʚ;HIT$AT 1+^fDHڃHu1H蕲IMDtH3HEHH4DIaAWAVIAUIATIUSHH5s HxdH%(HD$h1bH5S HHHHD$ `u<CH؃Ht HHڃHHHDH5 H`1҅u+HL$hdH3 %(HHx[]A\A]A^A_DH5 HbIHHD$(E fAW fffJffgf]f1LHt$1HHt$Ld$L9d$ LMd$MI LBHq H8IT$,KT$1ɾHHHD$0HF H8LHHIHLHD$8芆HCHH H8ə1ɺHIHLLL$HD$@GLL$LLLLHH1C LL$ftf} AG OfOMMIDHH H(HHy H5ҽ H`H5ý HIE`If.ftftJfuH H5LH81]ff~sf~sH= H5X _IEH= H5A _IDHڃHt Hߺ1ĮH@f~H=| H5 0_IEf.fIqLLL$vhLL$H IIALLID$~LH~HH HH8裗LHHHHHD$H5MeI.I@H KHHEHߺH4HDH=y H5 5^IEI.\ff.@UHSHH8dH%(HD$(1HL$HH$HD$Hu-%HH-`HL$(dH3 %(u5H8[]fDH$H\$1HHHD$HHD$}HS\ATUHSHH@dH%(HD$81HL$HH$HD$PHu[H L%Hu!L`H HtHHHY_HL$8dH3 %(uJH@[]A\H$H\$1HHHD$HHD$-}H+H$1H}H;H^j[f.AWAVAUATUSHHdH%(HD$81~oIHu_HL$HHLH$THtWH$1H|H;YfHL$8dH3 %(uiHH[]A\A]A^A_ÐtY]@H H-0HuDHs_H HtHHL ^rZHnH5@*HHPuHLL@1iL5r HUII>!LHIHHD$蒰IHHD$H؃Hu HHHߺYIT$I>HHHD$ HCHDIUH9HJHF1HT H芓HLHHHT$(LLhd{HLy1LzIECH(\HHHGHHN8H H5%H81WfDAWAVAUATUSHHdH%(HD$81ZHHBLfMALHH6IMIM1gIT$L5 II>;HHIHHD$謮HHHD$H؃Ht"HHHIINHHHL$8dH3 %(THH[]A\A]A^A_fLZHL$HHHH$HHp L%׀Hu@L\HL HtHHHZgLHߺ謭HUI>HHHD$ HCHDIUH9HJHF1HT HސHLHHHT$(He}LMfxLL*w1L0xIELYIH$1H xH;mYHVH H5oH810UATIUSHH dH%(HD$1HwBHt1HL$dH3 %(H []A\H5 H9UtuH5~ HIVHe 1HHѶ H8TH1HdHH;(uH;E tH] HH+W1HvHYDuuHuiH؃HH ~H~HYu HHXH5HH H81SfDHH u,HģU1H9vHHڃHtDHt>HthHtzHGH\$H|$ISLH茪[LHäBfDHHHD$뮐LHsfDH UuHuiHPHtHtH5 HL$HHD$8UHt/HULHSHt#t1 uH H5H81QRHWtHtH-SH|Ht H|HtHH|HEH H5*H81QAUATUSHUHcHLdTuLeu.UHAHDL[]A\A]=DHmuUHAZUHètCHHyEuRH[]A\A]fDLPHǃm;HQtHRHbH} H5 {H81Pff.USHdH%(HD$1\PH=a{kVH=j{Hx SVH=k{HX ;Vff. H8   1(k`HH4$HHDV1fP HX@$H@H@H `HH4$HHDUH=zfH HXH@H H@@$eH H0UH H5H=zHRH;SHuHu=H H H  <  HA H8@HxH5'zHUTH;H;H5 zRH;H{H5yRH;HpH5&zRH;1HVH5ylRH;H-:H5yQRH;1HEcH5y9RH;1Ḧ́H5y!RH;1H5_H5y RH=yNH;H5yHSH;5wH5ySH;H5yySH;H5sySH;H5mySH; H5lySH;H5ly~SH;!H5kyjSH;H5lyVSH;H5cyBSH;H5Xy.SH;H5OySH; H5IySH; H5EyRH; H5?yRH;H57yRH;H53yRH;H5(yRH;HH5%yRH;H5$yxRH;HH5#ybRH;H5$yNRH;HH5%y8RH=+yMHHH$CHHq MH=vLHHH$HH5 pM H=xLHHH$HH DCHD$Ht$1H"HH@ H\$H\$fD$>HH\$f&H H8{1HHcHLC H\$@A@ f5LHL$XII܋p$HL$0HAx$=H@H Hw"f.HHHHH9wt7I@HHHd@HHHHH9wH)HLl$H?H1H)I)AMIHt$LA!IH@HLd-IAMIMLLILLHAMD$ IA@ fIG Ax$p$1Ʌ@Ll$Ht$LIH@L5L>IH@H3H>II-HL$0HT$PLLHD$P\HH$ Hu$H=ziDH HtLHLeCIH5 H>?HO HH8I@f.11H*1HH1LD$(NLD$(HD$ H IPH8EyLHIHHD$`趕LD$(IHHD$hLHAu MLLLD$(rIVIHHD$pID$HDIUH9HJHF1HT Hߟ HH8xLLHHHT$xL#eH|$ Nt`LD$(LL^1L_Me^fDL0AI+Ld$P1L_I<$hI I$HIINL|$@f|$>]IG p$tAH@HHHHlfHHHHH9wH)L$H@H\$HHDHt$HLHD$H贷JOl-fDH)Ha HT$1H8w@$HH@fp H\$X1HHx^HHC P ftDft>f:H HT$1ɾH8v1H@$H@fH UH|$: H\$HHHHeH|$@L6HHt$XHD$X0H5ٚ HH=Lt$H5š HL=I9u'HC H\$fP zH>HoHHpHC H|$@HL$XHT$PLHD$PHeH HdHuHA@Hr HtH|$@HL>K1JHSIHi H8)uH|$@HHHH$蕑IHH$LHAu MH޺LXIUIHH$IFHDHUH9HJHF1HT HÛ HH8tLHHHH$LaLIW\HHZ1H[HE1H)D$H\$P1H[H;e IH(HHNHw H5cH8189HZ H5{jH818fAWHAVAUATUSHHH|$8HT$(dH %(H$1ɨuDuHtHD$(HHD$H Hښ H5ofH81)8fLd$(IMs H]HCH;H. HH|$(4IQH8H$HHDŽ$<t HK4H LH貉HH5ӑ H{2CHk 1M Af@ff 1fH LH8lHHD$x1HHC$HCfS THH$dH3%(H[]A\A]A^A_H1H871HHH? tFH H5 cH810fD1f.1"H1HH? u1HH_HWH@LL|$M4西IM7L0IIf1 AIWHD$H H8WkHLIHH$ŇIHH$LHAu MLLLL$胇LL$IHH$IQIEHDIVH9HJHF1HT H HH8jLL$LLHHH$L%WH|$ @vRLLP1LQI6dfDL83I1Ll$p1LQI}xH.IEHIINLf.Ht$PfH|$ HD$`[HT$(H|$8H\$ HH@HH|H 1HHQH3HH|$`HfDH)H|$-HL$xHT$pHLHD$p[HH# H-XHu H3H HtLHHa2ISHD$ 1T>IVIH H8hLHHHH$IHH$H؃HHu H*LHߺքIT$HHH$HCHDHUH9HJHF1HT H@ HH8gHHHHH$LTLi=OLHFN1HLOLe-1H׎ 1LH8gHHD$xH1C$1fC HHCNHLC0IH\$p1HNH;脟IHHIINH|$ p+HWs.Hw H5VH81+,1111H5 H5]H81+H5 H5V]H81+ aAWAVAUATUSHdH%(HD$x1,IL.HLHHHD$PHD$HEHHD$f} L5WeIMD$MAADMIII$AVA LLT$(_/D$ *L$ LT$(f.WQQef/f/ GeH,Ll=f.%(.IE%IcL>L/u H3HPHtHtH5 HL$HHHD$H,HLH?AuCIEH  LHt HL.f1f/A(DH5و L)1Ht$@LHD$@N=LHίH LIff()IH L_-IǨu H?IGHtIt AH5! HL$HLHD$H*HL-I f.H1 HT$E1H8b@$HH@fDx HD$@1HHFJHHL$xdH3 %(HĈ[]A\A]A^A_DE1E1E1E fA+LHHL$H<LLT$HD$H)LT$HE1fDHjH,cHZT@M/D$ E<H5 HL$HLLT$(HD$H)LT$(HgH Ht$H8`H1HHHDE E1E1fLAH?MIEHt|$u MH5Ѝ HL$HLHD$H](HKHT$H H8`HL֬HL$HH@HHT H;HHT$8HT$@HT$8fffH}MiHD$IIE1H|o-(HH4$IHD#1L`H@$H@fC KH| -(HH4$HD$ HD"HT$ HL@$IHPfP H@AItuHHrAIAIHHLXLH?AK?L9vLHLLI)XLLAMH|$LHH|$`AE fRfHf>>HT$L^8$IEH hLHLLT$[ f1LT$f/LHIAE$IEIEfAM AE QLH?DHL$LLT$ H|$HAHE1HD$|rLT$ I`H|$D$ ;Mu H|$(HHT$H| LT$H8Uf} IMLT$XH| H5LH81ALHY| HuHH;LHI;HEHHHHM,IEH5|$*LHHЃ7M[LAE$HIE MfA} E1AE$IEfEE AF$IFfAn 1L;ILLT$H&LT$1MIEHt|$uLHHЃuAAF$IFfEf {IE  Hz H8HT$Hi:MlAAAE$IEfEM H POHT$H9z H8RHIE HHt$@LtHT$@H҃Ef} EC$HCfC 5HtHHHHHDHHHAE$IEfA] EIE DHD$H}u}$kfAE f} AE$IEIE AfAE DHL nD$ HH@HT$XHHD$IEH Ht$@LHD$@HЃ6IE t҃ DAAAE$IEfE] =fDLpH5GHHw H81fAu uLHH҃fAE f} C$HCfC LHHЃHN| LHL<HL:fAE fHFHLHHD$ulHHHD$PHHD$tHHD$f.H|$HD$ff.HHHt$Ht$Hff.UHSH8Ht$H|$dH%(HD$(1H:0 1@H:t0 HcHHQuHSH HHGAHHWHHHD$Hv"H88HHHH9UvHHU1H6HEHt$(dH34%(uDH8[]HA1HWHHHD$H@u H5EH81fSHHH|$Ht$HA1H1VHøHt 1Hi5HH[1uuuux @Dff.1tuPtUfuuuuuu ÐDff.fH(LWdH%(HD$1HcGM EAMYD )‰  M9sTAQtRDljA)AIAD ?H I9s AA HH!H 1҅urDǁ?H H H|$D$HD$dH3%(u_H(f. D1)?H M9sAQHAA L Dlj1?H [ff.NDWA9AWLF1AVAUATUiLcSH_IO$0IA$EDHDAD$E9AMIE11IASE IILIՉHI I)LEJH HуM9sEE IVH9s$EVEtDD Eu HH9roNAA9HcHH LfH9sHH291trpHމD$1IAHHHH)HЉVH M9sHcH2u*HBH9vJt u HH9roD$[]A\A]A^A_@wD$[]A\A]A^A_1DDWNA9&fDUSHHv HcH Ht8H4HHHHH9uH:HH>H9HHuٽH5t H w EHH<'IHIH>HHt HH9t:HHH)HLH= vЉٽEHH<'HH‰Zj HBHH[]fDUHSHH(D$dH%(HD$1D$IfH~fH~f~D$H ։ρEωL$H|$u_T$AQT$E1AQAAEAU5)‰H\$dH3%(LH([]DT$ )L$ AIT$DH|$^T$AAA AQw-2EIcA|AA)Dft @AWIAVAUATIUSHLcoLcvE9|DIMcILcC.1A9\$ @A|$WHcLXI,LI9s@HH9wIIN,K4L9r^f.II9vKHDWEtLME1ɐIAPD1HILLIщQI L9wD II9w~uHUtH uuXH[]A\A]A^A_AVIAUIATUHnSHcFH_DgA)HHH @H9HH89:tA}IcU1D`HpIL IcVH| LHSHLVH)ʋMH)HAARH H9wI9v;LH@HVHH)HAӉWH I9wIqH)HLEufHAtD@[]A\A]A^DA,HHAHLMI1)H@[]A\A]A^Ht4HcWH5r ~)fHcWH HHHfHHqHE1HEH-o HHHD$HD$Hff.@AWAAVAAAUATUHSHDeE EA\$9~9zIHxE~#AOHHDfHBH9uH|HcEHuL Ata E1D)fDDHHD ‰WDFAI9wEDDEEeHHL[]A\A]A^A_DI9vץI9wf.AWIAVAUMATUSHHt$dH%(H$1hHAAuHD$(@-G@HcH>fAuD$0@IE1@0@Lσ/91E1E1*C4DtqHAΉσ/9fA~AӍTQʐD$0fHD$HtL8D$0tfWw@H$dH3%(.HĘ[]A\A]A^A_fDAuD$0@fHD$HtL8IAu@-DD$0E1@0Au|$Y<|$d$D$z=4D$D$1H=M>Dt Y׾HcHufH~@HDD$HD$H>H\$H؉H -PH H HT$YD$fH~fD$H %=|=|HD$HD$t$t$ @H00t~1:xnHpDWA w@fDDHBlG>DGA vHH)HHN<H݅D\$\$ AP981A ~f9DD$8A DD$8HDp@I A E9}2EHHE)Ot fIAU Hǃ0M9uHDd$H|$41L|$hA)DIIljD$8HCHD$PHD$|HD$`HD$xDd$HHD$X{Ht$PHxIHcCHHt$`H|$XD$ IHHHED$x1 |$HD|$8D,8L$|+D$43|6)ȋ|$ALDA9D<AND9AODž~)A)A)ŋt$H~3HL$L=LHHLHD$@HD$@L$LIƅ~ LHID\$4E~t$8LIE~LDIE~HD HLL;HcUxD@I@9NH HpHHL H9oHH9tML|$hEHHT$ HT$H AЁEUEu }LDD$4;HcUDD$4HI)хM H HpHHL  H9/HH9t|$6 D! p fDHP9\$ HD$~D$YfH~f\$Hu HD$("L&LHHLD$WA If?\$4tj|$4 D‹\$4%)D)ډT$9"H 9D$D)Hc)YHcY@D$HE1D$4IiD$HD1Ƀ߃Eu#f D EIA@E1AHAwDMu AD$Lt$8Ml HD$@HDf.IAV Hǃ0M9uAH|$@HHD$8Ll8"IEuA0tAH=8Hf$6D$T$A.EeEEH=X8D$ DJD$ HIT$ H-"8D$ DEG AHT$T$H H)fEeIH*YY8XL$f.T$ L$zuD$ MH-7D$ EfIAHM|HuD$AAPAM,)ωʉ1)I0 A1D w<IDBAUA rЁ/~܃ wIAU0 vnDD$HD1Ƀ<AzIBDWA %I|$4Dd$HH5D$A)Ic^D$؉ƒtHcH 5|$^<|$D$,t$jD$EH41@t YHufH~HDD$HD$t:H k)~  4*7H4HD$|$ff.|$ b\HD$(f"fH$LDD$L%H$HfI~D$@ AW+UfH~L$@$+$DD$LLDH H H HD$@~L$@^%5f/SE Z2H?Ht$H t$t_wW4f/r1, 2t fH*f(EufW2fH~H։H )H H d$ HT$T$fH~H @H HT$D$YXfH~fD$H H9u L$/LLHLl$l$ qfDD|$8Dl$HA)fDY 3f(EufW'1fH~DfH~H )HH H HL$@~D$@C@ML|$hEHD$HAH сAt>|$ fH~H @HH HD$X|$|$ f|$DT$ APHt$HT$H T$H Ht$H \$H HT$D$YXfH~fD$H ց|vhHH9T$ HT$:fHHT$ HH4H d/P|$HH H H|$f,f*\EHHT$1f/ML|$h.f/Y n1f(fW.DE1D$H1E11E11D$H1x@1f/~f/ 61k1MfHD$("HHD$D$EAAPD0 0D$ HcT$4H/D$Y`0tFL$HD1AKG4E9tM~NPT$D$H H HT$t$t$ DރLAMIX1D¹H H HT$\$\$ fHHT$ HD$H I_T$#A0IEeA0tEE1Ƀ1G&.D$ EeOD$ GML|$hHD$+D$\$ fH~H @HH HD$\\$f.+\$ f\$tHD$(ML|$h"HHD$DL$Etсwk)ωD9HH HD$|$|$ H\$H!H!H HL$ !H HD$@AWf(AVAUATUSHx|$t$HT$(LD$0dH%(HD$h1fH~fD$H Åf(%==ff.f(Ht$`H|$dL$ T$T$L$ HfH~fH~Ћt$`E1H H?H H fHD$D$f*Y ,\,Y,X,Xf/D,1)DpAIcH5U+f/AD$LD$8EE Dd$ ED$D$ ~ 1ۉD$|$D$D$HyD$D$ D$\D$@OHcD$XveHD$(H\$0A0IfDHtH@HHt$hdH34%(LHx[]A\A]A^A_ÐfH~H؉H H ‰%HT$T$=HD$(fH~'HH nH&)IID HHuH\$0H75@D$LD$8EFAA)Dt$8E1E5P|$D$HD$9 D$\xD$@HcD$XT$PPI"\$X D$ T$P ÉH( Љ f(^ *H5u(ttYHu^|$Lt &f/fɋL$@*YX )fH~fH~H -@H H …t$ |$@,fHT$WHcL (\$I_A$ыT$H*ȃ0\(  (A^\f/w{-0&f(\f/ DG% )ITf(\f/ H9YfHY,*؃0C\f/vFD$ {fD$T$x|$ INjD$dT$q D$\$@\$\D$XD$P3Eu 6+D$`\$8AtD$HIHIEt$8~E~D9AO))A)Ɖt$8t$t7D$Hv LHHIpHHD$HD$HſHHD$HHGEB|$XtHHD$V D )ƒ)T$8Aօ~ HHE~H|$DHD$D$LH\$HcC9E}HHuHHTH9_HH9tKD$ H1Ҿ X-HŋD$H D$\ D$@LDd$@Lt$H1Ҿ HLHH0CDEEu }D)A9AE1HHt$HŋUHcF)…0 HHMHHT H9 HH290tSn f.t$`T$d2  )f~fAH*fH~fH~H H H I@DD)d$8Dd$ E1D$DaH/#INf HHuHt$0HJHBfD$LD$8EWf@)f~ D$HfA*f.zA@Dt$@EbD\$HD$ ED$8Ll$E D$@ML|$@I\IH\$8Ht$LEgōX0IcEA)HIOHITfDH9HH:98tAHt$H|$nP$ AHcPEGA)u>H IwHHLfH9HH99:tEAHDD$HuEDD$H|$eExIA^L;t$8L1Ҿ 1Ҿ LIL;l$dH|$1Ҿ IPHD$fDHDD$H|$DD$HF D$E9 D al$LL|$@ADMI^Eu }EHHt$HŋUHcF)…R HHMHHTH9L HH290triA9Dd$A1PfDHt$H|$H!H|$ALI^L|$@A9<AE&MLl$fDHt$H|$)DPEAIHD$f*YX *!fH~fH~H -@H H fD\!HT$L$f/;fW f/D$PfT$|$ D$dHcD$ HH ‹D$D$@5Y AHD$f/L$D$ I_A1H|${MtLnHfHD$(t$ 0HD$0HcH[f|$\$H ڈT$X\$8E1f.D$PD$8AxD T$ HGډփ YH5f(1@t YHu@af(XD|$XHD$E1Ht$FD$XH|k )‰DD$\$@H|$1Ҿ[UHHD$Hc@)…HHMHHT H9[HH9tG$fDf(¸Vft$HH@D$XD$\D$@D$Yff.LfD f(Xf/w\f/D$P Ct$ DL9jBHHS<9thf(¸HHt$HHHH 6AEA#HD$E1D$L؉D$ LIHD$H uHcT$ f(fI_H Hփ^t$ ,f*0AY\f.D$@D$@%ILfDH9YfHf(^,f*P0SY\f.zHÀ{0HCtyA$GH%I|DCHH9YffH,*ȃ0\f.z@SoL9(PHHC9t|$Ptt DH|$MOM>M95L(fDSHHC0tA99MLl$t$ xt$@|$\?%fɋ\$ *YčsYX fH~fH~H -@H H 3AD$D .fHD$E1=A1D$ A}IuHxHIcEH|HHD$A0LCD$ ALMH\$8L|$@Ll$ASUL1Ҿ IŋD$\"D$@Xf/AHD$D$\$DAI^LL|$@A9B1DOE&MLl$Hljl$ALL|$@AE1l$LAL|$@uI^fDD$\\$ D$@f( f.HA%DfD$tD$\AhT$fD$ IOf(^,f*P0AY\f.{'|$@mH<)‰oHff.@AWIAVAUMATfI~UHcSHH(dH%(HD$1fH~H f(fT f. f.f.jDLH4Ld$T$YfH~fI~H4-A}LcHc0LUH bN0HHE1L9fDHEMtImH\$dH3%( H([]A\A]A^A_D-AdA>=<=remainderdivided by 0divmodniltruefalseto_strStringBigDecimal.exception_modeBigDecimal.rounding_modeBigDecimal.precision_limitBigDecimalnewinterpret_looselydouble_fig_loadsave_exception_modesave_rounding_modesave_limit3.1.3VERSIONBASEEXCEPTION_ALLEXCEPTION_NaNEXCEPTION_INFINITYEXCEPTION_UNDERFLOWEXCEPTION_OVERFLOWEXCEPTION_ZERODIVIDEROUND_MODEROUND_UPROUND_DOWNROUND_HALF_UPROUND_HALF_DOWNROUND_CEILINGROUND_FLOORROUND_HALF_EVENSIGN_NaNSIGN_POSITIVE_ZEROSIGN_NEGATIVE_ZEROSIGN_POSITIVE_FINITESIGN_NEGATIVE_FINITESIGN_POSITIVE_INFINITESIGN_NEGATIVE_INFINITE+0+InfinityNANprecsprecision_scalen_significant_digitsaddsubmulthashto_sto_intto_rsplit+-+@-@/quo%moduloclonedupto_fabssqrtfixroundfracfloorceilpower===eql?<nonzero?coerceinspectexponentsignnan?infinite?truncate_dumpBigMathexploghalf_uphalf_downhalf_evendefaultbankerceilinghalfprecision must be an Integer21E%ld can't be coerced into BigDecimalComputation results to 'Infinity'Computation results to '-Infinity'Computation results in 'NaN' (Not a Number)Computation results in 'Infinity'Computation results in '-Infinity'ERROR(VpDivd): space for remainder too small.second argument must be true or falsefirst argument for BigDecimal.mode invalidinvalid value for BigDecimal(): "%li "Conversion from String to BigDecimal overflow (last few digits discarded).can't omit precision for a %li .BigDecimal to Float conversionBigDecimal#precs is deprecated and will be removed in the future; use BigDecimal#precision instead.Undefined operation in BigDecimalCmp()can't convert %s into BigDecimalUnable to make a BigDecimal from non-zero imaginary numbercan't convert %li into BigDecimalZero or negative precision for expComplex argument for BigMath.logZero or negative argument for logwrong argument type %li (expected scalar Numeric)a non-integral exponent for a negative baseload failed: invalid character in the marshaled string-z@xR`@@P0$H%H%H%H%H%p%H%0%H%H%X%H%H%H%H%H%%XUU3V3VUnS/T/T/T/T/TTT/TT/T/TT/T/T/T/T/TTTUVVVVVVVVVVVVVVVVVlUUlUVVVVVVVVTVVVVTV33333333333333333VVS33333333V3333T[VGT,S,S,SGTURRSSRCU/SRRR/SUQRQRR+TwwwwwwwwwwwwwwwwwRPPwwwwwwwwPwwwwRXSpPpPQQpP^T_________________POO________O____PRXOsPXOsPsP܃vvvvvv_vvvvvvv######ړ#0{#####ԯԯԯԯԯ$ԯԯԯԯԯԯԯԯ$& .>C]r2<?eAC@ȿȿȿȿȿȿ}NaNInfinityؗҜ<3#I9=D2[%Cod(h7yACnF?O8M20HwZFBD D(DPB (G ABBN s (A ABBG L?FGB E(A0A8N 8A0A(B BBBE H BXBBB B(A0D8D{ 8A0A(B BBBJ D84EiFBE A(A0Qn 0A(A BBBJ zRx (! H$GBBE E(D0A8N 8A0A(B BBBF (KEDGPW AAG 00LFAD G`  AABA HdLzFBB B(A0A8Dr 8A0A(B BBBB L OFBB B(A0A8D1 8A0A(B BBBC 0lQHBDC G@L  AABH L4TFBA A(F0R (G ABBJ v (F ABBG (XU EFD0H AAG H c7 FBB B(A0G8J 8A0A(B BBBE Lm) FEB B(A0A8J9 8A0A(B BBBA LLyFBB B(A0A8G 8A0A(B BBBF $H [(>EDDP AAA PEG BAؑR$s,5D0 K lHRHB B(A0G8d 0A(B BBBE K0A(B BBBDH8$AAF DA(\AIG@ AAF D  BEB B(D0A8D@8A0A(B BBBLThBEE A(E0 (A BBBF @(A BBBE8TBGA D(G0H (D ABBJ @ؙ1BDE A(A0F@c 0D(A BBBG H8ԚBEI B(A0D8D@ 8D0A(B BBBF L|FEB E(A0A8G, 8A0A(B BBBG LFFB B(A0A8DN 8A0A(B BBBB H$HVFEB E(F0D8G` 8A0A(B BBBF GNU 54!#Z"Z V YOX805 % XVp!x!o`(  !  oHoo>o H!&& &0&@&P&`&p&&&&&&&&&'' '0'@'P'`'p'''''''''(( (0(@(P(`(p((((((((()) )0)@)P)`)p)))))))))** *0*@*P*`*p*********++ +0+@+P+`+p+++++++++,, ,0,@,P,`,p,,,,@@?!GA$3a1%eV GA$3p1113`3VVGA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFY05VVGA+GLIBCXX_ASSERTIONSbigdecimal.so-3.2.11-13.el8.x86_64.debug77zXZִF!t/#]?Eh=ڊ2N pYp5ܹEOp2b $mw>Mn2u:ϼf{44 _LghM(/%>\ t&eJi>W X(o4c6C)&Y6^zjWhrc!o^}sq{}:$G^$VY)c>F Rk}-+7eRتGe:N-9c\BԚ(xxVH^¸!ffXjOl璬,j'1am7wL(X.7NHfRZwb~u6mxҌG<ޱR"\u^?D,6kd;ė(ݟͽhI tv,l1egJ7fq#x˒DXmxF O lz>X3b HBs9^D\^J6^ڷ5) hB o!//X9ӑRL'U58V0 6Ԛw?pcWct`v (A12BvLCo(|E ׈c\1;HiaSbR_@:13P)4`왜iX~ٷr%ɗ7atOnqR;a mMSz(tV7c; iuD\sV+W Jgc|}ħhfy{7uWƨu&8ca/̲y[*k/e8^Btu?@[~N=Xz<\/ Q )o&Ku9gd7/CE*6">\1*o?q4ȡZ"{\䮅x#>8;(8B"DUoG_bq3xw$y5xy{۳6Tdÿ1<4&ZCkf^ {yىقQL- 9H1 S [log}T`|D ;bэW f`?rt#HP}<b}erR?C}UHQ$|2_N ݾb#G(-h3BU=tw`%rP[81M>6]Z%VEj&sݏ߿F^ʽXiO\*h5"bt֑k_/. \qju;>V1@jkb@wS׳\.|W'e Υ<]cyl8HT̗ BjQ_4<]4ٽ(X=D]o.Jޖ/v7ٟP$FN hg`\s!.Eta-;Ж0x1PRD(V>?5qP}~ey 4͆76#ŭM[A ׌W@ά"cgKBe^ƜPv&~6{/%O$'BB)/χ"S,݆=!ayQ`Gݺ ~ǚ˩E96&<#Bf_H6x|zxh+:(ZMA+.dS7ﱷ5J^R:Ec3L:#7#fhsL$Uix_sA@%G Zho\4}߲y`7Zb6Ϸ|V$Ӏ"j,.' B!t0,N`Ji's4fX@$bcq@9&C/E䌀Ud Bi]Ǹ~qD7;^~}e钇j=YU^1!ova߭jNB73ja4(]RWjj޴rm6sKtIf˜WW?j\o3Y%gd(D=Qb ]a7I%JAs1FԉG96Lg X5mYһ~41v4Z#2b2!XxU~*HjpGY%ۙ3!v\ǞpnhDޡNaO;7WzM0,wbkEboop3lpM/.| @!|ˮ/kG>0tDb BͻitziIE~ G#gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.data.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``P( x 0((8o>> EoHHT^B h%%c%%n,,w`3`3"}XVXV VV 8k8kToop p!px!x! H!HH!H!pp!p@!0 aH0"(, T1PK!{psych-5.0.1/psych.sonuȯELF>,@}@8 @`` ll l H( mm m 888$$``` Std``` PtdtWtWtWQtdRtdll l PPGNUTIwwE@L"-R_ BHH _gjx BE"aj |SE6 ZqXH8t2_Ur #p]Ko? }S-,,4" DVO.IV"JO""a _^Jnv, $F"y{ ; =f >rr  T Qs s /s  -X TZs #r s s __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeyaml_get_versionrb_ary_new_from_values__stack_chk_failInit_psychrb_ext_ractor_saferb_define_modulemPsychInit_psych_parserInit_psych_emitterInit_psych_to_rubyInit_psych_yaml_treerb_define_singleton_methodrb_check_typeddatayaml_emitter_deleteruby_xfreeyaml_emitter_set_canonicalrb_data_typed_object_zallocyaml_emitter_initializeyaml_emitter_set_unicodeyaml_emitter_set_indentyaml_emitter_emitrb_eRuntimeErrorrb_raiseyaml_mapping_end_event_initializeyaml_sequence_end_event_initializeyaml_document_end_event_initializeyaml_stream_end_event_initializerb_fix2intrb_num2intyaml_emitter_set_widthyaml_stream_start_event_initializerb_unexpected_typerb_attr_getrb_utf8_encodingrb_enc_str_newrb_funcallvyaml_alias_event_initializerb_str_export_to_encrb_string_value_cstryaml_sequence_start_event_initializeyaml_mapping_start_event_initializerb_string_value_ptryaml_scalar_event_initializeyaml_document_start_event_initializerb_ary_entryruby_xcallocrb_string_valuerb_ivar_setyaml_emitter_set_outputrb_error_arityrb_cObjectrb_define_class_undercPsychEmitterrb_define_alloc_funcrb_internrb_define_methodyaml_parser_deleterb_funcallv_publicyaml_parser_initializerb_intern2cPsychParserrb_const_get_atrb_class_new_instancerb_ull2inummemcpyrb_utf8_encindexrb_default_internal_encodingrb_respond_torb_ascii8bit_encindexrb_usascii_encindexrb_enc_find_indexyaml_parser_set_encodingyaml_parser_set_inputrb_enc_get_indexyaml_parser_set_input_stringyaml_parser_parserb_protectrb_str_new_cstrrb_enc_associate_indexyaml_event_deleterb_jump_tagrb_str_newrb_ary_newrb_ary_new_from_argsrb_to_encoding_indexrb_ary_pushrb_debug_rstring_null_ptrrb_eNoMemErrorrb_exc_raiserb_const_getrb_usascii_str_new_cstrrb_define_constrb_requirerb_define_private_methodrb_path_to_classrb_obj_allocrb_iv_setrb_define_module_undercPsychVisitorsToRubycPsychVisitorsYamlTreelibruby.so.3.2libyaml-0.so.2libm.so.6libpthread.so.0libc.so.6_edata__bss_start_endGLIBC_2.2.5GLIBC_2.14GLIBC_2.4/opt/alt/ruby32/lib64ui 4@ii Kl P-l -l l l 3Vl .@m VPm @o  o  o jo (o ho co do ko Jo Oo So Up  p (p 0p 8p @p Hp Pp Xp  `p  hp  pp xp p p p p _p p p p p p p p p gp p ap q q q q  q !(q "0q #8q b@q $Hq %Pq &Xq '`q )hq *pq +xq ,q -q .q /q 0q 1q 2q 3q 4q 5q 6q 7q 8q 9q :q ;q <r =r >r ?r @ r A(r B0r C8r D@r EHr FPr GXr H`r Ihr Kpr Lxr Mr Nr Pr Qr Rr Tr Ur Vr Wr Xr Yr Zr [r \r ]r ^HHN HtH5O %O hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?h@hAhBhChDhEhFhGqhHahIQhJAhK1hL!hMhNhOhPhQhRhShThUhVhWqhXahYQhZAh[1%MI D%EI D%=I D%5I D%-I D%%I D%I D%I D% I D%I D%H D%H D%H D%H D%H D%H D%H D%H D%H D%H D%H D%H D%H D%H D%H D%H D%}H D%uH D%mH D%eH D%]H D%UH D%MH D%EH D%=H D%5H D%-H D%%H D%H D%H D% H D%H D%G D%G D%G D%G D%G D%G D%G D%G D%G D%G D%G D%G D%G D%G D%G D%G D%}G D%uG D%mG D%eG D%]G D%UG D%MG D%EG D%=G D%5G D%-G D%%G D%G D%G D% G D%G D%F D%F D%F D%F D%F D%F D%F D%F D%F D%F D%F D%F D%F D%F D%F D%F D%}F D%uF DH?f.DH=QF HJF H9tHB Ht H=!F H5F H)HHH?HHtHB HtfD=E u+UH=B Ht H=? dE ]wH8dH%(HD$(1HT$ Ht$H|$HcD$Ht$HDHD$HcD$HDHD$HcD$ HDHD$ HL$(dH3 %(uH8Nff.HH='bHA 1H5'HHH5@1HHH5> |HcHHDff.HH5Q> LHcHHDff.HH5!> x|HHHЃf.SHH[f.SHH5= 1HH@H[DUH= SHHX HHvH߾9H߾HH[]fSHt[HB@ HSH5%H81DATH5#= USHHpdH%(HD$h1HHI7HLHT$hdH3%(u HpH[]A\ff.ATH5< USHHpdH%(HD$h1HHIWHLHT$hdH3%(u HpH[]A\ff.ATUHH5?< SHHpdH%(HD$h1"1HH@IHHLHT$hdH3%(u HpH[]A\/ff.@ATH5; USHHpdH%(HD$h1HHIHL,HT$hdH3%(u HpH[]A\ff.USHH5P; HGHHtHHH[]fUSHH5; HHHtgHHH[]fATUHSHH5: HpdH%(HD$h1)HIHH߉AHLHHT$hdH3%(u Hp[]A\DATIUHSHH5g@ dH%(HD$1HZLHHHHH5"@ H$!HǨt"UH\$dH3%(uH[]A\@ff.ATUSHHĀHt$H59 dH%(HD$x1pH|$IHu:1Hl$HHLHHT$xdH3%(u`H[]A\@@uHu HHuOH|$HBHD$HtH|$ Hu AWAVAUATIUHSLHHt$H$dH%(HD$x1H|$IHH<$HHH5j8 eH߃IQE1MAE1H<$t HcI1H|$t H|$LHLd$LADLLLHHT$xdH3%(HĈ[]A\A]A^A_@u=Ht8HHu,LH$,EfD@uHu kHHuLHD$DAWAVAUIATUHSLHHt$H5&7 H$dH%(HD$x1 IUH|$IHH<$HH߃E1MAE1H<$t HI1H|$t H|$HLl$LADLLLHHT$xdH3%(HĈ[]A\A]A^A_f@uEHt@HHu4LH߃H$HC@uHu HHuL4HD$%DAWAVMAUMATUHSHHt$(H55 H$HT$ HL$dH%(H$1|H|$(@uHtIHHt CH|$(HIH|$ HD$(Ht$@uHtHHuL\HD$ H|$Ht$@uHtHHuL-HD$H߃GHD$(MH|$(AE1MH@AEH$I1H|$HtH|$HD$HL$H1H|$ t!H|$ HL$HT$HL$HT$HLl$0SEAVDD$LXLZLHH$dH3%(u!HĨ[]A\A]A^A_D'9fAWAVAUATUHH53 SHHH|$HL$dH%(H$1HD$@uHtHEHƒHtH_ HHHE1E1Ll$PHEE1H|$A HHHt$HLHNLLH|$LMtLH$dH3 %(HD$H[]A\A]A^A_HEHL1HaHIQLAIuepLAD$HteD$LH HD$ uH;HHt8HfHELAD$Hu kHH<$61H<$IIgHCLt$0Lt$ Ll$@HD$(Ld$PHl$8HfDH t0HH9HD$(H<@uHuRfH9kHC HHƃHu H~HwHGHt$@H@LIHHD$PLLd$ H|$@LH;1HH5&H;HWH5 H;1H_H5{H;HH5lH;1H,H5ZH;HaH5IH;1HH5<H;HH5-rH;1HfH5"ZH;HH5?H=H= H2 H=H2 H=H2 H=H2 [H2 f.@SH3H[f.H52 11lff.H52 11Lff.H5e2 11,ff.H5U2 11 ff.HH5I2 dH%(HD$1HGH?HH$HT$dH3%(uHff.@HH51 dH%(HD$1HGH?HH$iHT$dH3%(uH_ff.@HH51 dH%(HD$1HGH?HH$ HT$dH3%(uHff.@HOH5 1 H?@HOH50 H?d@HOH50 H?D@HOH50 H?$@HOH5y0 H?@SHT*  Hx HH[fUH5$* SH(dH%(HD$1HH0 Hu$H-@HH/ HtHH], H8EHHH?H9wtHD?HH$H?H9wmHD?HHD$H?H9w=HD?HHHD$HL$dH3 %(u*H([]@#느f @ATIUHSHH dH%(HD$1H?H9w|HDH58/ HL$HHD$HHD$Ht!H|$HT$LHHRHHt$dH34%(uH []A\HH|>ff.AWIAVAUATUSHHXHT$XHL$PH|$8dH%(H$H1D$d&D$H5' HHD$ yHHNHVH5'. H|$XH- Ld$XHu%HDHcHt- Ht11HLHHB99\$E9=H=Q9tH=E19@ƍ4vHLd$XHT$XH5HcfDH|$X>HD$XH=HD$hHH=:H|$hA9D$< 9R A9: }H|$hHpHT$hHD$hHT$pHT$hHHD$X HD$XH HpHPHHoH?HD$pHD$HD$dHD$EHt$HH$H9Ld?H$H9Lt?H$H9Ll?H$H9HD?HT$H$H=L$L$L$L$H$g|$p D$pH HcH>H|$xHt$HIHt$ HLAH$IHt$t$HIHt$ LIă$Hc$L$H$HL$H=HHTL$ H$0HT$H$(@kH|$a|$d5HT$LH=H|$xHjt$HIHt$ HNLAH$IHt$t$HIHt$ LIă$Hc$L$H$HL$H=HHTL$ H$0HT$H$(H$H${t$HIHt$ HLH|$xIHet$HIHt$ LH$IH%t$HI|Ht$ LIŃ$Hc$L$H$HL$H=HHL L$ $L$(HH$0HT$HH$@H$8@H|$xAHt,t$HIHD$ HtLHIL$H$HT$H=L$c;IHD$xHHcPHcHtHT1HD$0L$MHD$0$L$L$ H$H=H$HEHT$H$(HT$LH=qH|$|$dH$HdH3%(HD$8WHX[]A\A]A^A_HcD$xL$H$H=DHT$HDH$-DHT$LH=@HT$LH=@|$xL$HEH$HT$H=iH$H9\$fNfDI%IIAH$AHt$HI?H|$ fDAH$AHFt$HIH|$ mXfDH|$xAHt t$HIH$AH9t$HI @H$I9@Hl$@Hl$ L|$HIt$HILHt|LHlI|$IHt)et$HHD$(HT$(HH4HL1ILHM9tNI<$HqAI|$Htt$HHD$(HHT$(tf.Hl$@L|$HJ;HD$0)AAH$Htt$AHI9HpHP0HD$hHD$hHD$hH=]HT$Ht$DHT$Ht$Eu"H HH{HHHEHL`HEPHXH" Hu L- LH" HtHH- H8IHD$PH$H?I9KD$H$H?H9HDH$ H}H?H9HD?H}H$(Ht6H}8H$0HtH$8H! Hu H"HH! HtH$HLHlH;Lxnff.H SH5HH H8H H5HHRH;H5pH;H5`H;H5QH;H5EH=A&H;HH59+H;1HH5/H=(gH=!H TH=HH=H 5H=H "H=H H=Hy H=H^ H=tHC H=hH( H=dH H=^H H=YH H=OH w[H f.@H4@UHHSH;HH5EHHHH[]ff.ATH=US\H- H5HHHUHH5IMHUH5HHHH5HHF H5HHH5 [L]HH5A\SH=`H5mHH5gHH HH$HH5rHH H[HHPsychlibyaml_version%stag tuple must be of length 2HandlerEmitterinitializestart_streamend_streamstart_documentend_documentscalarstart_sequenceend_sequencestart_mappingend_mappingaliascanonicalcanonical=indentationindentation=line_widthline_width=iowritePsych/emitterMarkexternal_encodingUTF-16LEUTF-16BERSTRING_PTRSyntaxErrornewParserANYUTF8UTF16LEUTF16BEpsych/syntax_error_native_parsemarkreadpathemptyevent_locationPsych/parser( mesgClassLoaderVisitorsVisitorToRubybuild_exceptionpath2classYAMLTree;1|L d|$ <JnJy%a\61ڶU[QM'nM{}FB`rUlGG.Iff{_f=Je^ED'Ssx]F14Ɛ*6}@= @n+R=w/[㆚H[,ɖ[{j82@(iN]lK Zl'@ct3tV2Yh9Y*(הcrϯ xp܎`џvܷݮ .zw)끉Utc#!PNRYF$|u#pLLM#7`ki*ю5dHDX{sMIR"Nչ&leC1(@b+xODMx04gF/| tJf+TנȜNHr૸V~=nVhb!x' (_8Pd-Uzm0j#C59# #oSWb-~PyQ㹏B6X>AsyLcNey.!CJxB#S+gaE,+xP8`FTU/ dۃ[:ËpV%*q`'+Z*MOڂpvq&`(<4]&uN~uR (gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o```(  0 k8oLLEo((@Thh^B00h c n&&w,,(} U U UUUtWtWYY`` l ll ll l m mo o`p pr rs`r| tw(w|+PK!psych-5.0.1/gem.build_completenu[PK!json-2.6.3/gem.build_completenu[PK!WJqqjson-2.6.3/json/ext/parser.sonuȯELF>@@i@8 @8[8[ 0]0] 0]  ]] ] 888$$[[[ Std[[[ PtdWWWQtdRtd0]0] 0] GNU?vr.p+!ax F@ FIBE|ŷ|!qXa[ t `qRJUy" G<"Bl/qN`, *{F"^37ab tb U Hhb __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeruby_xfreerb_gc_mark_mayberuby_xrealloc2ruby_xmalloc2rb_check_typeddatarb_str_duprb_eTypeErrorrb_raiserb_funcallvrb_ary_entryrb_ary_push__stack_chk_failrb_data_typed_object_zallocruby_xmallocrb_utf8_encodingrb_enc_interned_strmemcpyrb_utf8_str_newrb_str_internrb_enc_raiserb_ary_new_caparb_hash_foreachrb_obj_freeze_inlinerb_class_new_instancerb_hash_newrb_ary_newrb_cstr2inumrb_respond_torb_str_new_cstrrb_hash_arefrb_hash_asetrb_cstr_to_dblrb_float_newrb_class_namestrrchrrb_str_substrrb_path_to_classrb_sym2idrb_mKernelrb_debug_rstring_null_ptrrb_error_arityrb_keyword_given_prb_string_valuerb_enc_getrb_ascii8bit_encodingrb_str_conv_encrb_hash_duprb_id2symrb_enc_associaterb_eArgErrorrb_fix2intrb_unexpected_typeInit_parserrb_ext_ractor_saferb_requirerb_define_modulerb_define_module_underrb_cObjectrb_define_class_underrb_path2classrb_gc_register_mark_objectrb_define_alloc_funcrb_internrb_const_getrb_define_methodlibruby.so.3.2libm.so.6libpthread.so.0libc.so.6_edata__bss_start_endGLIBC_2.14GLIBC_2.4GLIBC_2.2.5/opt/alt/ruby32/lib64Wyii ui 0] 8] @] @] `] Mh] p] x] _ _ _ _ %_ <_ =_ >_ ?`  ` (` 0` 8` @`  H`  P`  X`  ``  h` p` x` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `  a !a "a #a $ a &(a '0a (8a )@a *Ha +Pa ,Xa -`a .ha /pa 0xa 1a 2a 3a 4a 5a 6a 7a 8a 9a :a ;a ?a @a Aa Ba Ca Db EHHiI HtH5I %I hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=%E D%E D%E D%E D%E D%E D%}E D%uE D%mE D%eE D%]E D%UE D%ME D%EE D%=E D%5E D%-E D%%E D%E D%E D% E D%E D%D D%D D%D D%D D%D D%D D%D D%D D%D D%D D%D D%D D%D D%D D%D D%D D%}D D%uD D%mD D%eD D%]D D%UD D%MD D%ED D%=D D%5D D%-D D%%D D%D D%D D% D D%D D%C D%C D%C D%C D%C D%C D%C D%C DHf.DH=C HC H9tH6A Ht H=qC H5jC H)HHH?HHtH A HtfD=-C u+UH=@ Ht H=N> dC ]wH V7Hx=WHx0HH WHxHH WHxHH øf.HGhH@Hpff.@USHHHohH}HtHHH[]ff.SHH?H{ H{@H{HH{PH{`[fATIUHSHtWHOIT$HH)H9v:HHHH)H9rH9vI|$HI\$ID$[]A\@H? I $ID$IL$ff.HH5< H8Ht HH> H5]*H81AUATUSHdH%(HD$1H$t&IH5A HI11LHu#1HL$dH3 %(uIH[]A\A]@1LVHHH5@ H$HtLLqUH; pSH% Hh Hf@H@HHEhHH[]ff.@UHAWAVIAUIATSH8UMdH%(HE1HH)HEH=HuHHEHHHH%H)HHH9tHH$H9uHD$HHEL}M1M9w mI9vWIA<$\I\$uM9vLL)IAD$M LH+]I\$Iw+DEĿHuH3HE)Iv:IIE?HuMH)HLLA?HuĿHAȀDEňEA|$u I|$I\$ %LI %HEHHI I LHuHELH ?ȀELH?ȀED?ȀEHLLLHuH ELA?HAȀ?DEƃȀEGH}w#H< iLHw&HH1RH}"H}w#H; ,LH&HH1H}\f.AVAUIATUHSHHdH%(HD$1HwH9>"E1EXHm`HLIuIHH5FHLLHAHCHt$dH34%(\H[]A\A]A^HL`L9H"tS\uL`L9Hu9LfEXA1tM0u1u81҅H{LsUXIEL4@}41ɺIUH59 HHH$1IEHpH9H@0 HpH9H@|0 weHpH9H@r0 wCL`L9@<@i0< LE1F~ayHF~a{DF~avfHA0HA"Hm`H:LAAWIAVAUIATUSHXdH%(HD$H1H9tGHHH#MAfDHEH9t}rQAG8t I}E1Ht$HdH34%(LHX[]A\A]A^A_fDHDHH9q멃0 wHEH93 H5? HA,wH27 Le IEDHEH9C}a5HEH9(}NAw,H6 LeIEf.A@IWHlj$AG(w9oH=6 H5D1hHEH9}aHEH9}lzHEH9m}s_HEH9R}eDIELeHEH9#}uHEH9}lHEH9}lIELefDHEH9M*tN/AO8HHhH9@<*tt:H=3 DH5~1f8 #HH9uDH11IEH9tD}{Hu;LBL9t2B<"< t< LLBL9u@I#H11=IEH9}[HH LrL9rF F.0@ @HD$(HD$HD$0HD$D$HL$HLHD$(L,IHYIHHt$(I}Ht$0HL$H51 ID$HPH9t-H,tC0 t 4HHPH9uIfD  LLrL9JA fDifDHEH9}uHEH9}ezIELe$fIoH9E<-g <01I<w5IL9^A*uIL9A<*t uLrL9tB<*tJ uIL9t@A<*t*u@ `@H / {LHHH1d@/] ID0 ]HL$EHLHD$(AH8I@H|$ HD$\H|$0I}HD$(HL$H5) HD$8LD$I@L@L9P,t7j t nLL@L9uf< t <LIL9B< t~<"~ tHH9uHH9<*t*u _H/} D@HLpL9@0@ wxE1HHHHHHD t w;HHXH9P t/uHXH9t@<*tlEt,<BDD V ABE =HX E 8FBA A(I@R (A ABBE $P4QEMD uDA,xl&AC DEJ^ K @l@BBE A(D0G@ 0A(A BBBD HhBEB E(A0A8D 8A0A(B BBBG (8EHD0 AAE @d [FEL A(F0DPF 0A(A BBBH zRx P(XHGNU@] M.=GW H K0] 8] o`   ` xh ooo8o]  0@P`p 0@P`p 0@P`p 0@PGA$3a1H-K GA$3p1113@KGA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFY KGA+GLIBCXX_ASSERTIONSparser.so-3.2.11-13.el8.x86_64.debugy?7zXZִF!t/G]?Eh=ڊ2NVtj[Y \J`ivNUu93 _+%m 1$R<{~PQ՛tYig- 5'} u{*0ЁM: Plw kņtpaODvdbI>r[[[SuG53Jq}o/VPu+Iq4e ЅA{T>Id\{MfI1*yۓ6q_y[Ғ&M/(l}8#2v{=ɀ+6%(mgĖH;l?Ppq[usg(1dдS݈3;2]$r3? $kH%!Z: Pr*bMPPNT@נNW߃vҺ},lQC+*{E_o-L!lxw\[ˈ0V=? PĻm_-+Zʜ2fyk7f=;]En RĖp(8*d=]-$|T4pii,+*HJR;16Me5SSMaǑ1߼ B1a55U|Mӆ𣽙LSc-?nVKvf HJz^&tp;Wچ2`| WG0qJ"`Q(i[i"9rI"YA8 agYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 0 8o88Eo@Th^BxxhHHcppn``w@@,} K K @K@K@ WWXX[[ 0] 0]8] 8]@] @]h ] ]_ _@` `b bb`bH Pd,|d h+PK!ϕpp json-2.6.3/json/ext/generator.sonuȯELF>@0@8 @tt }} }  }} } 888$$sss Stdsss Ptd8e8e8eTTQtdRtd}} } GNUviU*XiI(gL@$LNOBE|qXt)WBJ 5#W"a?hUc.s ydSm"|~"4} <of>, KF"(*Xpr    W__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizerb_check_typeddataruby_xfreeruby_xmallocruby_xrealloc2ruby_xmalloc2memcpyrb_str_newrb_utf8_encodingrb_enc_associaterb_funcallv__stack_chk_failrb_hash_newrb_obj_classrb_class_namerb_hash_asetrb_str_new_staticrb_str_duprb_str_catrb_str_concatrb_str_internrb_sym2idrb_ivar_setrb_attr_getrb_data_typed_object_zallocrb_obj_is_kind_ofrb_cHashrb_class_new_instancerb_eArgErrorrb_raiserb_hash_foreachrb_error_arityrb_unexpected_typerb_hash_arefrb_intern2rb_ary_entryrb_string_value_cstrrb_iv_getrb_str_substrrb_id2symrb_string_value_ptrrb_float_valuerb_debug_rstring_null_ptrrb_enc_getrb_usascii_encodingrb_str_export_to_encrb_enc_str_asciionly_prb_path2classrb_cFloatrb_cArrayrb_cStringrb_respond_torb_cFalseClassrb_cIntegerrb_cNilClassrb_cTrueClassrb_cSymbolrb_id2strrb_check_convert_typerb_convert_typeInit_generatorrb_ext_ractor_saferb_requirerb_define_modulerb_define_module_underrb_gc_register_mark_objectrb_cObjectrb_define_class_underrb_define_alloc_funcrb_define_aliasrb_internrb_define_methodrb_define_singleton_methodlibruby.so.3.2libm.so.6libpthread.so.0libc.so.6_edata__bss_start_endGLIBC_2.2.5GLIBC_2.14GLIBC_2.4/opt/alt/ruby32/lib64ui ii }  } ` }  } @} bP} #X} !        # * 4 7 @ A B D K  ( 0 8 @ H  P  X  `  h p x          Ȁ Ѐ ؀   ! " $ % & ' ( )( +0 ,8 -@ .H /P 0X 1` 2h 3p 5x 6 8 9 : ; < = > ? Cȁ DЁ E؁ F G H I JHHg HtH5h %h hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!%=d D%5d D%-d D%%d D%d D%d D% d D%d D%c D%c D%c D%c D%c D%c D%c D%c D%c D%c D%c D%c D%c D%c D%c D%c D%}c D%uc D%mc D%ec D%]c D%Uc D%Mc D%Ec D%=c D%5c D%-c D%%c D%c D%c D% c D%c D%b D%b D%b D%b D%b D%b D%b D%b D%b D%b D%b D%b D%b D%b D%b D%b D%}b D%ub D%mb D%eb D%]b DHHHHf.fH= b Hb H9tH~_ Ht H=a H5a H)HHH?HHtH_ HtfD=a u+UH=z_ Ht H=\ dma ]wH7Hthv$HtNHu8R1€?v2fHuB|HHu H[]DHuHHD$HD$H[]ff.ATIUSH9$HH5"O HH5O HHHoEoHMoP U oX0]0o`@e@ohPmPop`u`oxp}pHHHsH;^HsH{HEMHs(H{ HEH% LkHt LkMt$LLLeHHE@H[]A\A]ÐH=$fAUATUSHH5A HuHtHHHƒHtH:f.Lc% H}Mu.HtHEHEH[]A\A]@Ht VH% LkHt LkMt,LL1LeHEH[]A\A]fH=.#fAUATUSHH5,@ HuHtHHHƒHtHJf.Lc% H} Mu.HtHE HE(H[]A\A]@Ht fH% LkHt LkMt,LLALe(HE H[]A\A]fH=>"fAUATUSHH5fDHMfIn\uLD$$E1ft$"E1ɉD$ Mf.J|5<hP4H5#HcH>AL=LL)LLHMNMM9wLL)tJt HHfHHCHS"HCHD$(dH3%(EH8[]A\A]A^A_LAL=L)kJt HL$WL$JfDAL=&fDAL=fDAL=fDfH500ffL$$AL|$"D$'T$&InH Mf#f.1AIHHHAIHHAIHHHAIHHAIHIcH w!H+H&H(H=HBH_EH/H\H"HH$HCHKH$HCfL9AH ,!IfALH9H=4H5H1D1f1f1f1fAIHM~MInfH5HL9,HD$HD$HD$ @H5(HH5H|H5H\H5HHHL,$H5`: 7H.HHHLgfHI7 HHI7 HHLH"DHHLLGfH5LHUrHuqHLyH5LXHy6 HeHy6 HUH5LLH599 11HuHuTHHupHL@H96 HfHLHHuHUrHuqHL}AWAVAUIHATUHSHXHB@LzHT$HD$8HBHHt$ HD$@HHRhHD$HAPHxH@H|$HHyxHD$HwH|$0Ht$(HqxHt H9HHEHU[HEH|$8t H|$@}D$01D`QDHH9}RH|$tH|$HLHYHT$Ht$ HHIE uIEH9|HD$HT$0H|$8HPxtOH|$@Ll$Mt9HD$0H~/A1 DA9tMtLLH"A9uHHEHU]HEHX[]A\A]A^A_H|$(,E1AE9MtHt$LH@HT$Ht$HHHT$@Ht$8HLl$M#WHT$@Ht$8HblHEHD$H=Q6 H5`HPxHT$HHPx1f.AUATUSHxfIuYH=-6 HH50 HHFHILLHHH'HH[]A\A]EDH6t1\ff.ATIUSHHH50 HHLHH[H]A\fUSHHHH5/ HHH[]fAT1UHH5 5 SH1x=Iu/AuMt I$Ht*LDHutͺ1qH=4 [L]HA\DAWIAVAUATUSHHHLrHBHt$ H*Iv`I~XHD$IIN0M^8MfHWMnxHD$HFHD$(HFHD$C~ HHt MH|$tKM~FEH\$0E1LEAE9tHtHt$HHAE9uH\$0AuMuAMI~IARA Ha0 Hv@H Y0 IWH;H 0 H9tjH5I3 L11IAuMu_LfLHHDH!0 HH / H9tH 30 H9uLHI뗐IHuHt$LLHH|$u1HL$ Ht$LHCHH1[]A\A]A^A_HT$Ht$(Hf@HwHL\$8HL$0JL\$8HL$0Ha/ H+fH/ HH/ HH. H ;/ HH9fAVAUIATIH5Y, USH dH%(HD$1H ULHNHHHH=d1 HHlHH=91 dHHIHH=1 AHH&HH=0 HHHH=0 HHH4H=0 Ld$LHHEhdH510 IHD$,HH=/ LHHExH5/ IHD$HH=/ ULHH5/ IHD$HH=/ HHH=/ HEpHHH=;/ HEqHHHLErHL$dH3 %({H []A\A]A^LHHHEh@LH]HHEx@LH5HDHHHfH H LUHZDHHEh4@HHEx[@HsuHHуHuLpIv L`MLLuHE f.uHHуHuLpIv L`MLWLu(HE f.HHHуH5LpIv L`MWLLuHHE@fHHуHLpIv tXL`M+LLu8HE0fDL`L`(L`pL`f.HHуH]LpIv t L`Mt'L/LuHErfL`f.H=. Ht$Ht$H= Ht$Ht$&DH= Ht$Ht$VDH= Ht$Ht$DH= Ht$oHt$ATIUHH5& SHaH@hdHǀxuL[]A\Hut1HtLL[]A\HH=W 2H=H5K HH+ H59 HH=H+ ~H=! HP+ kH=D+ H5+ XH=)+ LH' H=F+ H5> HH5HH+ H=+ H&H5ZH=* HH5H=* HH5H=* 1HH5H=* HH5pH=z* 1HH5\H=^* HbH5CH=?* 1HH5.jH=#* H7H5KH=* 1HH5/H=) HLH5H=) 1HH5H=) HH5H=) 1HH5H=r) HH5H=S) 1HH5~H=7) 1HH5bH=) H?H5~CH=( 1HH5p'H=( 1HH5d H=( 1H[H5SH=( 1HH5CH=( HH5*H=m( 1HH5H=Q( HH5 yH=2( HH5ZH=( HH50H=' 1HH5t$H=' HaH5MH=' HH5H=' HhH5H=' HH5nH=n' H5dH5iHHA' tHH5NHiH=' H5FH*H5 H;H=& H5HH5H H=& H5H~H5HH=& H5HH5HH=b& H5HH5HH1& H=%& HH5?]H=& HH5L>H=% 1HH5<"H=% H5<HH5+HH% H=% H5H>H5HH=p% H5HH5vHH=B% H5nHH5HHcH=gH=-H$ TH=H$ AH=H$ .H=H$ H=Hm$ H=HR$ H=H7$ H=H$ ϾH=H$ 輾H=H# 詾H=H# 薾H=H# 胾H=He# pH=HJ# ]H=Hw# JH=H\# 7H=HA# $H=H&# H=H # H={H=xH" ߽H=qH" ̽H=dH=]H鰽HHC*@0123456789abcdefunallocated JSON::Statenesting of %ld is too deepnullfalsetrueinstance_variables%li not allowed in JSONRSTRING_PTR\n\r\t\f\b\\\"\/JSON::GeneratorErrorto_hashHashto_hjson/commonExtGeneratorJSON::NestingErrorfrom_stateinitializeinitialize_copyindentindent=spacespace=space_beforespace_before=object_nlobject_nl=array_nlarray_nl=max_nestingmax_nesting=escape_slashescape_slash?escape_slash=check_circular?allow_nan?ascii_only?depthdepth=buffer_initial_lengthbuffer_initial_length=configuremerge[][]=generateGeneratorMethodsObjectto_jsonArrayIntegerFloatStringincludedto_json_rawto_json_raw_objectExtendjson_createTrueClassFalseClassNilClassto_snewallow_nanascii_onlyunpackcreate_idextendkey?__send__respond_to?matchkeysdupJSON/Generator/Statepartial character in source, but hit endsource sequence is illegal/malformed utf-8source sequence is illegal/malformed utf85pP01234567890    ;TIphXyPxXHx 8ؽPl8h8ȿ LHtxX<xPdHx0\Hx(4XX l8x d ( H x D 4 8 P X  (D Xl XdzRx $@FJ w?:*3$"D\p%HW "HT8&HWP&HWh'HX&E`&HW0"HTHĺAUdȺEv,/Am,@BDD V ABE (>FDO WAAF$;AAG lDA ̻TH F A 0<FAD D0  DABA @pFIB A(A0JP 0A(A BBBD 0xFEA J0t  AABB  6H] K D0<9H] K DP\9H] K Dp|9H] K D9H\ L D(EDM0q AAG (@1BGD `AB8TBHA  ABH M ABH DK XKK0 AD 0|EADG0T AAF ZAA,XFDA 1 ABA LBBB B(D0D8G# 8A0A(B BBBD 80<FBA A(D0O (D ABBJ ltEL O tEL O PtEL O +EezRx  )EcPH3Emʱ$xSEDI rIA EG  AA HhFBB B(D0A8D` 8A0A(B BBBA (BDA lDB$ .EAG [DA( FCK iDELD HFEB B(A0A8G 8C0A(B BBBH @ FBE K(A0DP' 0A(A BBBD zRx P(C4 mFDK g ABA iABH $HsGNU ` } b#!  _} } o`     ooo4o}  0@P`p 0@P`p 0@P`p 0@P`pGA$3a1_ GA$3p1113_GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFY _GA+GLIBCXX_ASSERTIONSgenerator.so-3.2.11-13.el8.x86_64.debug>-7zXZִF!t/K]?Eh=ڊ2NH wE!TTU]{PtD~Ƞ<荵~OMG5i胖zcƄ봯?33D@wC fR$i͒ma+7ΧݰH*?4՚|fZ;j,@هErQ#tA2Of&SW^ UYT ,Ρ:iw%3EM0uIU: jzX"!<ݶOi7hVnf]gدEIszu3$$igmׇ6iYLPa4w#M#O=w>/v$|l.i)[ǩGaȅ9w/K*_kC ,BɸgVB%[Qes= Xk x|(׀fu<|M"k╧8"%d@ҽa,G;_n(Y(20Dl}"ւvliIUޚ~U)gtI# ;4O{Qcχ޺\ RURJ<%ӯc1-$R]\H;Yrx7Kqۮ- >fӠ125Gpr0/+e$aqUGx||iռG0MUWvݎU)E9-Wy?05ˋRtJ^HF-q^ l2}9zAc׶3&PiԇG{~,,ТaC "m GXTey2rEu rWV+7%bj'@jJK6+~`2K0L)3m,1wnطc*ߎZ#zU-I6|;Hx-%W5)hZzdԠ@d9T<lKId'Љ6pI*c+7= 6s饤rp=:1*!Vo.#UrA.e4]`gPOAӑ(IUl;dJ@(ľp37~t$$ٯ"jw]B.>G廉u sR:hvj`.e-z>p֜_ r,w(Obde+ 5SgYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 0  8o44Eo@T^Bhcnw?}__ __ 8e8eTggd ss } }} } } }h } } x  `H H,t+PK!,2Q,,ruby-lsapi-5.6/gem_make.outnu[current directory: /builddir/build/BUILD/opt/alt/ruby30/share/gems/gems/ruby-lsapi-5.6/ext/lsapi /opt/alt/ruby30/bin/ruby -I /opt/alt/ruby30/share/rubygems -r ./siteconf20260423-2958356-aielb.rb extconf.rb current directory: /builddir/build/BUILD/opt/alt/ruby30/share/gems/gems/ruby-lsapi-5.6/ext/lsapi make DESTDIR\= clean current directory: /builddir/build/BUILD/opt/alt/ruby30/share/gems/gems/ruby-lsapi-5.6/ext/lsapi make DESTDIR\= current directory: /builddir/build/BUILD/opt/alt/ruby30/share/gems/gems/ruby-lsapi-5.6/ext/lsapi make DESTDIR\= install PK!!ruby-lsapi-5.6/gem.build_completenu[PK!@h.h.ruby-lsapi-5.6/lsapi.sonuȯELF>S@('@8 @ !! !!888$$ Std PtdpppQtdRtd!!0 0 GNUJ㋚{(zP:C H‚3@(L`qCSlP*fRn}'3qѮl>&Sɶ ܮʼnSO`[is|&߱RD/y7řkՊ eY&09=By:%/=ejOzJ6'l#mNULCB1{!\$O#W23S=apbU06aD7jp#7ĴDIΊ=\4yݾCEкQuo rSѮIo|q%h6 󝵛 ' =qX[ u  w f #  ! ysOf |  [^k & !\  2Z RT s ? + A >n -r LH  ". " "$7x W, 9  A. 9 4, 2F"O E  L r G 0 |F pD   S 5 ti~ p Pz@! b .  ! ] `Z\ e @n  v 1 p Y ` p@   prl yj @U p| P- r] Д  n qY 0n  Г5 po w$ ~l! s U T E `u qS m7 nT `(     {F `qJ p ! }I @   !b Pg  p@$ "! l 06 Pn 0  !__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizecompareValueLocationset_skip_writesigactionsigemptyset__stack_chk_failreallocfcntlacceptsetsockoptmmapmemsetsetsidread__errno_locationclosewritevkillgetppid__ctype_b_locstrncpystrchrstrcasecmpstrtolgetaddrinfomemcpyfreeaddrinfoinet_addrLSAPI_Log__vfprintf_chk__snprintf_chkgetuid__fprintf_chkgettimeofdaylocaltime_rwaitpidforksystemexitlsapi_perrorstrerrorLSAPI_is_suEXEC_DaemonLSAPI_StopLSAPI_IsRunningLSAPI_Register_Pgrp_Timer_CallbackLSAPI_InitRequestmallocgetpeernamedup2LSAPI_Initgeteuidsignalg_reqdlopendlsymLSAPI_Is_Listen_rLSAPI_Is_ListenLSAPI_Reset_rLSAPI_Release_rfreeLSAPI_GetHeader_rLSAPI_ReqBodyGetChar_rLSAPI_ReqBodyGetLine_rmemchrmemmoveLSAPI_ReadReqBody_rFlush_RespBuf_rLSAPI_GetEnv_rstrcmp__ctype_toupper_locLSAPI_ForeachOrgHeader_rqsortLSAPI_ForeachHeader_rLSAPI_ForeachEnv_rLSAPI_ForeachSpecialEnv_rLSAPI_FinalizeRespHeaders_rLSAPI_Flush_rLSAPI_Write_Stderr_rgetpidgetcwdmemccpy__realpath_chkLSAPI_Finish_rLSAPI_End_Response_rLSAPI_Write_rLSAPI_sendfile_rsendfileLSAPI_AppendRespHeader2_rstrlenLSAPI_AppendRespHeader_rLSAPI_CreateListenSock2socketbindlistenunlinkLSAPI_ParseSockAddrLSAPI_CreateListenSockLSAPI_Init_Prefork_ServercallocsetpgidsysconfLSAPI_Set_Server_fdLSAPI_reset_server_stateis_enough_free_memLSAPI_Postfork_ChildLSAPI_Postfork_ParenttimeLSAPI_Accept_Before_Fork__fdelt_chkusleepsched_yieldLSAPI_Set_Max_ReqsLSAPI_Set_Max_IdleLSAPI_Set_Max_ChildrenLSAPI_Set_Extra_ChildrenLSAPI_Set_Max_Process_TimeLSAPI_Set_Max_Idle_ChildrenLSAPI_Set_Server_Max_Idle_SecsLSAPI_Set_Slow_Req_MsecsLSAPI_Get_Slow_Req_MsecsLSAPI_No_Check_ppidLSAPI_Get_ppidLSAPI_Init_Env_Parametersgetenvgetpwnamdlerrorsetrlimit__fxstatsetreuidLSAPI_ErrResponse_rlsapi_MD5Initlsapi_MD5Updatelsapi_MD5FinalgetpwuidsetgidsetgroupssetuidstrtollprctlinitgroupsLSAPI_Accept_rLSAPI_Prefork_Accept_rsigaddsetsigprocmaskLSAPI_Set_Restored_Parent_PidLSAPI_Inc_Req_Processedselectrb_str_newrb_hash_asetrb_gc_markmunmaprb_string_valuerb_string_value_ptrrb_eval_string_wraprb_str_new_staticruby_strdupmkstempftruncaterb_str_buf_newrb_str_catrb_num2intrb_fix2intmemmemrb_yieldrb_gc_writebarrier_unprotectrb_io_putsrb_ary_detransientrb_check_typerb_intern2rb_funcallvrb_obj_as_stringrb_f_sprintfs_fn_add_envrb_ruby_verbose_ptrrb_define_global_constrb_default_rsrb_exec_recursiverb_output_fsrb_output_rsrb_lastline_getInit_lsapichdirrb_stderrrb_cObjectrb_const_getrb_global_variablerb_define_classrb_data_object_zallocrb_stdoutrb_stdinrb_hash_new__memcpy_chkrb_define_methodrb_define_global_functionrb_define_singleton_methodlibruby.so.3.0libm.so.6libc.so.6__environ_edata__bss_start_endGLIBC_2.14GLIBC_2.15GLIBC_2.4GLIBC_2.3.4GLIBC_2.2.5GLIBC_2.3/opt/alt/ruby30/lib64 ) 4 ii ? ti I ui U ii a !pT!0T!!!!q!!w !~(!0!8!@!H!P!X!`!h!p!x!!!!!!!"!-!;!M!V!d!m!!g!!! !(!0!8!@!H!P!X!,`!;h!Gp!Tx!^!j!w!!!!!!!! !!)!2!8!8!I!Y!X!!!!P!X!`!h!p!x!!!!2!!<!H!J!R!V!V!W!!!m!{!! ! ! !( !0 !8 !@ !H !P !X !` !h ! p ! x ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !( !0 !8 !@ !H !P ! X !"` !#h !p !$x !% !& ! !' !( ! !) ! ! ! !* !+ !, !- ! ! ! ! !. !/ !0 !( !10 !8 !@ !3H !4P !5X !6` !7h !8p !9x !; != !> !? !@ ! !A !B !C !D !E !F ! !G ! !I !K !L !M !N !O !( !P0 !Q8 !@ !SH !P !TX !U` !Xh !Yp !Zx ![ !\ !] !^ ! !_ !` ! !a !b !c !d !e !f !g !h !i!!j!k!l !(!0!n8!o@!pH!qP!rX!`!sh!tp!ux!w!x!y!z!|!!}!~!!!!!!!!!!!!! !(!0!8!@!H!HH1 HtH5z %{ hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?h@hAhBhChDhEhFhGqhHahIQhJAhK1hL!hMhNhOhPhQhRhShThUhVhWqhXahYQhZAh[1h\!h]h^h_h`hahbhchdhehfhgqhhahiQhjAhk1hl!hmhnhohphqhrhshthuhvhwqhxahyQhzAh{1h|!h}h~hhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhq% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D%ݿ D%տ D%Ϳ D%ſ D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D%ݾ D%վ D%; D%ž D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D%ݽ D%ս D%ͽ D%Ž D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D%ݼ D%ռ D%ͼ D%ż D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D%ݻ D%ջ D%ͻ D%Ż D% DHY H HfH81\% fH= H H9tH~ Ht H= H5 H)HHH?HHtHŻ HtfD= u+UH= Ht H= id} ]wff. ÐHGH+FHcAVIH@AUATL$USHtQHHtIHIL9r 0HI9v'KHSMsH;Յ[]A\A]A^[D]A\A]A^øff.f= Dr ÐO AWDD_AVAUATUSD6^nAxj׋G3G D!3G V\$ЋW^$DD1\$!3WAʋN Fp $E‰L$A1A1DD^ !D1G;νD\$DEDVDT$A!A1EE|A 1AD!E1DD*ƇGD1D!A1A1DDN DL$E F0D!DnA1D1DGFEDf Dd$D^(A!A1EEؘiA 1AD!1DDDʋ^0D1D!A1DE [D 1!D1DDN,A1DL$G\EA!Df8A1ED"kA 1AD!1DDN4EqDD1!1DE CyD 1!D1DDV<1G!I!1DDD$ Eb%1!1DDD$E@@1!1DDD$ EQZ^&1!1DE6Ƕ1!1DD]/։ 1!1DESD1!1DE ؉ 1!1DDD$E01!1DDD$ E!1!1DE7É1!1DDD$ E 1!1DDD$A0ZEAA1A!A1AA㩉A AD1!1t$DD1!A ogD1 1D!FL*1DD$Ή1AA!B9A1DD$A AD1D$qDD11‹D$ 0"amD1G 81Ɖ11DDD$ ED꾤11DDD$AKAA1A5`KA1AЉApA 1AD1D1D1A ~(D 1G'111DDD$ A0AA1A1AЋT$A2A1D1֋T$ 9ىDD11D11C|A A1A1AD$A0eVĉA1D1AD")Dt$ D D1A *CDG# 1  1DD9Ή 1DDY[e\$  1DE Dt$ щ1DE3}D\$  1DDD$E] 1DEO~oA AD 1DE ,DT$ A1ADE6CDt$ AN 1A~SADEAA A1A5:ADA AD 1Љ3*\$D D1DFӆ[ ]A\A]A^ 1։ 1DƉA4A_ OW GOW ATI1USHdH%(H$1HHH<$t)H$dH3%(u Ð2 DH=- @ATUSHdH%(H$1H}HHH1HLJ HىHH) HH{`IH0HCxHS`Lc` LH)HCxHCpLH)HCpI$HChHC8HC(HH IHHC0H(LcxLcpHltwHT$ Ht$D$ t }8kt01kH$dH3%(uiHĠ[]A\fD+CC11H=b11#_fDff.Sŭ t 1ۉ[H5L @ & eH5> TH=G 1(tII DH=1b. HcH5$bHH [ÉD1?H=͞ 0HW(Hw`HLJHHLJ0HHWHVHWHWHWHWH)81HSHHHt HHtHHtH{@Ht1[fDHtGwBLHcAT4t/HcApHHH€:t HH1ff.fHtPtJSHcH;}HSHH[~ Hcи[ÃAWAVAUATUSHZHHHD$H:GH%HIHIIILfDA)HcHL9HcIOIvI HLHtML)HLHXHHAIA$D)EH[]A\A]A^A_LHHHAL|$II)AM?DLLHcH~A-H1|v@AVAUATUSHIHHHHHH+E1HH9HcHO؋)HH~)H9HwHHNHHIELL)Ht6Eu@HHD:Hu4O8u  uMt-M[L]A\A]A^H~IHH)uIDHO(HW8HLJLSH)ʍBHGpH0HpH@Hwp~HcHHH HPHO8HGpAWAVAUATUSHHHT$HHH<$IH=Y]HcB$HH@H,H9rZf.HH9vGH3L@4 +HH5X1rrDH߹SfDHH5LX1CHtvt]SHtCuWHC(H9C8tHHCpHb HHHH@HCpPH1[@s뢸ff.Huu1fSHtRubHC(H9C8tH0HCpHŋ HHHH@HCpH{:1[1HO@H9OPv닸AWAVAUATUSHHH|I֨,aHHt$H>L{8IHC0L)H9>Lt$L+{(LA@LLfIM)MK H@σLSLCpNIHDI0HI@HKpM~HC(MxIH E1I@HC8HL1HMLIHHKpH9eH=thILM)MUI9t HtDL+t$HL[]A\A]A^A_DM@@M)(IHt$HLHk8f.HAVLAUIATIUSHu\H߉KAD${LǃLSHu0{L[L]A\A]A^x;[H]A\A]A^Hff.AWAVAUATUSHHHHD$ 0xIHIHLc\CHcT t u(HDLcLH t tLÅ~6HcAT t u#H@Å~ALH t tE<AG=I|$PHHTI9T$Hs7HI+t$@L2%))I|$PLHHcAoMt$PHLIFID$PA:I|$PMMD$PII@ID$PAIc$0fET8HЃA$0D$ H[]A\A]A^A_D$ ff.H HB=0AUATUSHcHfDA< t< uH؅uH[]A\A]IHPHHDI9D$Hs3HI+t$@L2%))tQI|$PHHA I\$PHCID$PIc$0fET8HЃA$0H1[]A\A]øSDAUATAUHSH?dH%(HD$1D$ff t1fHL$dH3 %(H[]A\A]ÐA1ҾÃtʼnǺ1ԿHL$Aߺ訿u#DHuDo輾߻D H*DeOAkDH}An葾}N3Htff.USHdH%(H$1HHu/HUH$dH3%(uHĘ[]褿@1H= tAUATA'USH 'DNuD H@AxHH HHtH-! D: 9Ɖlj# UDk H DcEuSH8dH%(H$(1=HtH H= H=?>HE1 H莹H=9>Ht 1Hf H=%>ijHHt 1H=IAąWE1H=>萳Ht 1H _ H==jHtHǺ 1_H==CH` H==$HtHǺ 1蠸)贶H==H1 HhOH==òHtHǺ 1?شH==蜲HtHǺ 1H=u=uHtHǺ 1躺H=b=NHtHǺ 1ʷ蓲H=R='Ht-H=P=Ht 1H荷 _H=8=Ht 1H_U D  ҅ EH==ɶH= u P 5 H==cH 1H۶e …te Hw HHHHD6 L =L <L=C HLt@HֹL€D t%HtAHHt9HLuHfDHJHHJHuHHu1ۉH$(dH3%(H8[]A\A]fDf H膲DH H= H~AԅLH=]B谶H= 褮Hq $@HH$HD$bDHH$$̯t 议1҃8k‰H H=N9ܭHt1 HX~ H=69貭Ht1 H.~ H=9舭HHiHǺ11蛵ÃHT$ƿD$(?H5o 踱HGH Htxc@dx@D  E9D E)ZfH=]8贬΀ HK] € u  '  '~ )fՅtbHS H-DHH5?1ڵCAHc~L% HH asÅt=  u  5 `HH5 ?uHH5>1E HH5>Fff.AVIAUEATIUHSHt4Hu!(fDHHtHLGH]HuMtEL[1]A\A]A^ÐIcLLH#EgHGHHܺvT2HGAWAVAAUIATUHoSH1HGO@ƉWDW?t;AĉDHH|@D)A9rhAGt4LLHL9A?vWEfAIIIH޺@HH@ܱHLL9uA?DLHH[]A\A]A^A_鬱IATLfUHSFH?LHz?)ƒw=t19rLHfCAD$AD$ ID$071)HCHLHCP?o H{1HMHHCPH)KXH[]A\ff.fAWAVAUATUSHdH%(H$1Ht^ IAfMcg IoA_@LHHuM(8u =x uٽH$dH3 %( HĨ[]A\A]A^A_f~AAuIALJf8LS|xr@tPHf@HPXN MgA;G ZA9~uEo)HHcIHLDHu$85w uAMgA9ID$,HD$HcIIDhAh(A9}A /HcIH4@H5HAIIh$A9}A HcIH4@HHAIIHl$p(ILHIILp$hMIc@o9gIcP[9SIcpG9?IcH39+IHHHHIHT$IIc@ H)IHHIHHHIHIIcHIHHHD$I9E1DL4t9dfH H IGAG IPH f@ f@ HHP P H HPPHHPPHHPPHHPPf@f@f@HH#PP H H'P#P$H$H+P'P(f@f@!f@%H(P+f@)I1 fDIHcȋL4t#fBIHT4 rfB@2JHHuMIcP IHHH9pH@ppHH@ppHH@ppHH@ppHH@ppHH@ppHH@ppHH@pHH9wMApIbIc@ IH0v ALJt`av Zv AFv 1LHc蟩IHIGAo IuID%9v D-.v B(AA1IcH4IILI 9HqH=7. IJDB(9xHqH=. XIJB($AD$IKAzHL$;Mbfou Lt$ LAoL$AT$Ml$)$航 LLHL$LHLLH$ID$H$I3L$H1H D$$Dl$EDDl$âH=t IHIDt MH=dt t"LDLŃP|$WEt$A9uHt$nD Ń5,t $A?D5t t AH5)LHtHHt f)s #AH5zf 1H@H5+1)LH 1H_IH5t31H531ͨD%.s $s DD$H=s IHtZEW7E1111ͤH=3H5*1PE|$菦M2;|$gE1H5*LuI}wŃ1H5*LKfD=r -r  r ED$AIFH5)1vHH)H51H1Q1H5*L ܟ1H5#2LA#LH 3H|m w1H5)Laff.AVAUATUSHdH%(H$1D$ HH ;1Ll$Ld$Lt$ Hkll {ul;LLD$CHq Ht@Hp Ht{1f|$=p u|H4tH舴H06l d1H$dH3 %(u}HĠ[]A\A]A^D胜 {H5b ,Hfы{LA;۝ff.AWAVAUATUSHD=o dH%(H$1ExHH-n H}o ;a DH-o Ht 11HEDk EH$L|$PDcA:E1AfD j ED o EtH%o Ht @fLH1HIcWDHD$PHD$XA ?)ѺHH D9#11A|$MH}j D9#Hn Ht @D9#` AD91葳fH$dH34%(' H[]A\A]A^A_KL$HDŽ$hMl$H$L蜞H$LHHD$@菚AHLDŽ$hH$UH$LHHD$0HPH$LHHD$8#+H$`L HHD$(H$ LHHD$HٙADžHD$PE1Ll$`HD$H$HD$H$`HD$fD%l EHal Ht H==h 1dIL9t<1ձL5EDu EME1VH'h LH1HHc}襚}LD$LHD$PHD$X ?)ѺH1H T`1g  8Ht$(1ҿ 荘x=_5}k tHk Ht @f,D9# DCH`k Ht@Hk HtDc1DN f =bj {H5L] HHj Ht*Hj HB(@Hj Ht@Hnj H@蛖8B-DAD9M=e }=e Hj HtDHi Ht A9Hi HtD҉T$$DE ~:E~5'T$$A蛙A茙AuDE UM D9vHgi AHtDH5'1薞輞D$g0 H=!7T$fD}蠩C1mH|$I谙H|$HT$Ht$1`6ӝ1E Mt AMgMg{E13CHt$1ҿ H=)f;>fDD$$_0d T$$WH=T$'T$fDD#AfDg RDoc EBHg H29Nc {H5Y 蠔H{wH=3(6蜓H=}(0~MAH… H{HƘb H=zĚՖHt$1ҿ脒H1f f L=f f Hf f HPf HtH4X 11L=f AGH`f Ht{1蝦D-a EuH:f Ht!E9~a e ;t ȕHt$@1ҿL$ْHt$01ҿȒHt$H1ҿ跒Ht$81ҿ覒Ht$(1ҿ 蕒kHLSH$Z'$讒L$舒d oe H=o#%蛚,H=&QHNe Ht*fC1CD$CCӖT$HC(HC d ֒fD=d d ff.@H` f.ffDi Hff.HmV HH+HHODH1f1fATIHUSHc8HcLH*H=h HHȔ[]A\ff.H飕HH=U HfHH=U ܏Hc5g ;5_ H=g |6aHg Hg g HfDf?IH=U HH+9M1~+HHcHc5ig H5Vg ѐ~Sg Hfff.@HH=T ̏tHHHDHff.HH=iT 茕H]^ HHH=IT 蜏H=^ HHH=)T tH^ HHSHH\$Ht$H5H]1H#H[ff.fAWAVAUAATIUSHH %d Bad request header - ERROR#1 ParseRequest error SUEXEC_AUTHSUEXEC_UGIDLSAPI: setgid()LSAPI: initgroups()LSAPI: setgroups()LSAPI: setuid()Bad request header - ERROR#2 lsapi_accept() errorPragma: no-cacheRetry-After: 60Content-Type: text/htmlDEBUGNOTICEWARNERRORCRITFATALAcceptAccept-CharsetAccept-EncodingAccept-LanguageAuthorizationConnectionContent-TypeContent-LengthCookieCookie2HostPragmaRefererUser-AgentCache-ControlIf-Modified-SinceIf-MatchIf-None-MatchIf-RangeIf-Unmodified-SinceKeep-AliveX-Forwarded-ForViaTransfer-EncodingHTTP_ACCEPTHTTP_ACCEPT_CHARSETHTTP_ACCEPT_ENCODINGHTTP_ACCEPT_LANGUAGEHTTP_AUTHORIZATIONHTTP_CONNECTIONCONTENT_TYPECONTENT_LENGTHHTTP_COOKIEHTTP_COOKIE2HTTP_HOSTHTTP_PRAGMAHTTP_REFERERHTTP_USER_AGENTHTTP_CACHE_CONTROLHTTP_IF_MODIFIED_SINCEHTTP_IF_MATCHHTTP_IF_NONE_MATCHHTTP_IF_RANGEHTTP_IF_UNMODIFIED_SINCEHTTP_KEEP_ALIVEHTTP_RANGEHTTP_X_FORWARDED_FORHTTP_VIAHTTP_TRANSFER_ENCODING%04d-%02d-%02d %02d:%02d:%02d.%06d Child process with pid: %d was killed by signal: %d, core dumped: %s Possible runaway process, UID: %d, PPID: %d, PID: %d, reqCount: %d, process time: %ld, checkpoint time: %ld, start time: %ld gdb --batch -ex "attach %d" -ex "set height 0" -ex "bt" >&2;PATH=$PATH:/usr/sbin lsof -p %d >&2Force killing runaway process PID: %d with SIGKILL Killing runaway process PID: %d with SIGTERM Children tracking is wrong: Cur Children: %d, count: %d, idle: %d, dying: %d LSAPI: LVE jail(%d) result: %d, error: %s ! Invalid custom stderr log pathFailed to open custom stderr logCan't set signal handler for SIGCHILDReached max children process limit: %d, extra: %d, current: %d, busy: %d, please increase LSAPI_CHILDREN. LSAPI: failed to open secret file: %s! LSAPI: failed to check state of file: %s! LSAPI: file permission check failure: %s LSAPI: failed to read secret from secret file: %s LSAPI: Unable to initialize LVERequest header does match total size, total: %d, real: %ld LSAPI: missing SUEXEC_UGID env, use default user! LSAPI: SUEXEC_AUTH authentication failed, use default user! LSAPI: lve_enter() failure, reached resource limit.prctl: Failed to set dumpable, core dump may not be available!sigprocmask(SIG_BLOCK) to block SIGCHLDsigprocmask( SIG_SETMASK ) to restore SIGMASK in childfork() failed, please increase process limitsigprocmask( SIG_SETMASK ) to restore SIGMASKCache-Control: private, no-cache, no-store, must-revalidate, max-age=0PID 508 Resource Limit Is Reached

Resource Limit Is Reached

The website is temporarily unable to service your request as it exceeded resource limit. Please try again later.
          QUERY_STRINGREQUEST_URIPATH_INFOREQUEST_PATHSCRIPT_NAMEftruncate() failed. File mapping failed. Memory calloc error[...]replacesrandSTDERRreopennilLSAPI_MAX_BODYBUF_LENGTHLSAPI_TEMPFILEXXXXXXRACK_ROOTchdir()to_hashCGI/1.2eval_string_wrapLSAPIacceptaccept_new_connectionpostfork_childpostfork_parentprocessputcwriteprintprintfputs<<flushgetcgetsreadrewindeacheofeof?closebinmodeisattytty?syncsync=RACK_ENVRSTRING_PTR is returning NULL!! SIGSEGV is highly expected to follow immediately. If you could reproduce, attach your debugger here, and look at the passed string.GATEWAY_Irewindable_input.rbNTERFACE/tmp/lsapi.XXXXX;|Zd0 opH p\0pp@pppp@x@xt@yyyz{4|@}}~L~tP 4PX Љ  p, @ T h @ p H \  @ `` t  x @8(0ШL`Pt@`(p<Pdx 0@P`pD \pp 4H\ p0@0 $D\ tP@0@pPd <X0pDzRx $V FJ w?:*3$"Dh` \kpkk LksEIB E(A0z (A BBBI A (D BBBA k k@kYGJB B(A0A80F(B DBb0TrBFC G  AABK Tsk(sGADJ n AAA 4sUAGK R CAG L JCG sAG] AJ $xtt C KFLHduBBE A(H0H (D BBBD  (D BBBA PvvFB A(D0D (A BBBB L(A BBBA$`vaAAD XAAHvBBB B(A0A8D@N 8C0A(B BBBH $`LwOAf Q C E H@twYBBB A(D0J 0A(A BBBF xyFEA C(G   (A ABBD M I c A  E M A k E E E E H V HH{FBB B(A0A8D`` 8A0A(B BBBD lX}+BBB B(A0D8JYHPC Mi 8A0A(B BBBE LTMDd~6BBB B(A0A8DP 8A0A(B BBBG  8J0H(G DBBK $l7EFF IIO  4FAA G>  AABG EO D  A @< T8h4Y|JEDS ]Ph H XAH 4!!o`  !.0&p oo%oo$oD!>>>>>>>?? ?0?@?P?`?p?????????@@ @0@@@P@`@p@@@@@@@@@AA A0A@APA`ApAAAAAAAAABB B0B@BPB`BpBBBBBBBBBCC C0C@CPC`CpCCCCCCCCCDD D0D@DPD`DpDDDDDDDDDEE E0E@EPE`EpEEEEEEEEEFF F0F@FPF`FpFFFFFFFFFGG G0G@GPG`GpGGGGGGGGGHH H0H@HPH`HpHHHHHHHHHI,LSLSLSLS88IYX!!GA$3a1`>A GA$3p1113SGA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA$3p1113 3GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFYTGA+GLIBCXX_ASSERTIONS GA*FORTIFY *GA+GLIBCXX_ASSERTIONSlsapi.so-5.6-3.el8.x86_64.debug=OkY7zXZִF!t/?N]?Eh=ڊ2N뺉>)L$; =ֿ2,! ~L$zHvK}D@&NzRLΝl;/%nA {4FmF&߾7̂#ϏIԱuJS= Pkds|X0o0ai7oscW y6қ9|.cv?Y+][Bױ8ӈ>JOfJ Uhژ|v\ bU?Q fUG\͗5ꌸ[ZNB%O2=dR,qv“ EAUYivHĴsҨ3 5,du"cPKF[X%7ѶYC;]Fdd(7T| P L6ɂ{7f"ZY]5{-dqq(=fȍRf2AE8{u*҆ l'ҝWBjinu 8pG{Prc>CnᮥD=H<_t ]4CBTl}Rg{ 廬6hlyzCˏGsAN+`lEψ2,UyŸ8|\ymV嫤uFI9[gQ}9SאUnog\"꼙zׇ;Շ A$מؿEGZ_=MWd 9l-׿t N~jNymDz)!>1Tb8+@lR qw2bK:;w`ͪw~)Cn_i20 6OU1MnEVfuoKLWldB!n^Baf 75d{nA]x6ǙSRk_Bv"LΔF-m3vW݃|F zܢrDKjz;D?pO JZnC͠]n|wpzfI+(uϗz2&пEA J~dO߯~B`#EnJJ_ƹ\c?҈h} 2XŮ}># a( Qn;6'1=UyU48E4SjVVh8b@xv-5lYu}u:7$PTW値kˀc6nJd~U^)*` i63cJD:sO@Os{F";ܐx&${;^j`f""_`>c>> nII wSS~}44 `` pp`` !!! ! ! ! ! "al L$p&(PK!8(||ruby-lsapi-5.6/mkmf.lognu[have_library: checking for -lsocket... -------------------- no "gcc -o conftest -I/opt/alt/ruby30/include -I/opt/alt/ruby30/include/ruby/backward -I/opt/alt/ruby30/include -I. -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection conftest.c -L. -L/opt/alt/ruby30/lib64 -Wl,-rpath,/opt/alt/ruby30/lib64 -L. -Wl,-z,relro -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -fstack-protector-strong -rdynamic -Wl,-export-dynamic -Wl,--no-as-needed -m64 -Wl,-rpath,/opt/alt/ruby30/lib64 -L/opt/alt/ruby30/lib64 -lruby -lm -lc" checked program was: /* begin */ 1: #include "ruby.h" 2: 3: int main(int argc, char **argv) 4: { 5: return !!argv[argc]; 6: } /* end */ "gcc -o conftest -I/opt/alt/ruby30/include -I/opt/alt/ruby30/include/ruby/backward -I/opt/alt/ruby30/include -I. -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection conftest.c -L. -L/opt/alt/ruby30/lib64 -Wl,-rpath,/opt/alt/ruby30/lib64 -L. -Wl,-z,relro -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -fstack-protector-strong -rdynamic -Wl,-export-dynamic -Wl,--no-as-needed -m64 -Wl,-rpath,/opt/alt/ruby30/lib64 -L/opt/alt/ruby30/lib64 -lruby -lsocket -lm -lc" /usr/bin/ld: cannot find -lsocket collect2: error: ld returned 1 exit status checked program was: /* begin */ 1: #include "ruby.h" 2: 3: /*top*/ 4: extern int t(void); 5: int main(int argc, char **argv) 6: { 7: if (argc > 1000000) { 8: int (* volatile tp)(void)=(int (*)(void))&t; 9: printf("%d", (*tp)()); 10: } 11: 12: return !!argv[argc]; 13: } 14: 15: int t(void) { ; return 0; } /* end */ -------------------- PK!#io-console-0.6.0/gem.build_completenu[PK! rrio-console-0.6.0/io/console.sonuȯELF>"@k@8 @xVxV ]] ] @ ]] ] 888$$XVXVXV StdXVXVXV PtdJJJQtdRtd]] ] GNU7x\tNx;5}yTTH!@TVXBE|qX/Do( J `Q.9 ^o 9Uk UR)B""ho +BZr7:, {F"r\#0 Pb b Pb  Cp G__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizerb_check_typeddatacfmakerawrb_data_typed_object_zallocrb_funcallvrb_default_rsrb_io_write__errno_locationtcsetattrrb_num2uintrb_sprintfrb_io_taint_checkrb_io_check_closedstrlenrb_io_getbyterb_ary_newrb_ary_pushrb_str_newrb_str_new_cstrrb_io_flush__stack_chk_failrb_sys_fail_strtcgetattrtcflushrb_string_value_cstrrb_io_get_write_iorb_ensurerb_stdinrb_stderrrb_error_arityrb_str_new_staticrb_str_catfrb_convert_typerb_eArgErrorrb_raiserb_cIOrb_cFilerb_const_definedrb_cloexec_openrb_update_max_fdrb_class_new_instancerb_obj_freezerb_const_setrb_unexpected_typerb_const_getrb_id2symrb_io_closerb_const_removerb_check_idrb_keyword_given_prb_funcallv_kwioctlrb_assoc_newrb_fix2intrb_num2intrb_Arrayrb_ary_detransientrb_protectrb_syserr_failrb_jump_tagrb_io_getsrb_yieldrb_get_kwargsrb_funcallv_publicrb_hash_duprb_ary_resizerb_ary_ptr_use_startrb_ary_ptr_use_endrb_debug_rstring_null_ptrrb_obj_classInitVM_consolerb_f_notimplementrb_define_module_underrb_cObjectrb_define_class_underrb_define_alloc_funcrb_undef_methodInit_consolerb_internrb_define_methodrb_define_singleton_methodlibruby.so.3.2libm.so.6libpthread.so.0libc.so.6_edata__bss_startGLIBC_2.4GLIBC_2.2.5/opt/alt/ruby32/lib640ii  ui *ui *] `#]  # ]  ] @] rJ_ _  _  _ _ !_ )_ *_ 4_ =_ L_ M_ N_ O_ S`  ` (` 0` 8` @` H` P`  X`  ``  h` p` x` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `  ` "a #a $a %a & a '(a (0a +8a ,@a -Ha .Pa /Xa 0`a 1ha 2pa 3xa 5a 6a 7a 8a 9a :a ;a <a >a ?a @a Aa Ba Ca Wa Da Eb Fb Gb Hb I b J(b K0b O8b P@b QHb RHH F HtH5BF %CF hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?h@hAhBhChDhEhF%A D%A D%A D%A D%A D%A D%A D%A D%A D%A D%}A D%uA D%mA D%eA D%]A D%UA D%MA D%EA D%=A D%5A D%-A D%%A D%A D%A D% A D%A D%@ D%@ D%@ D%@ D%@ D%@ D%@ D%@ D%@ D%@ D%@ D%@ D%@ D%@ D%@ D%@ D%}@ D%u@ D%m@ D%e@ D%]@ D%U@ D%M@ D%E@ D%=@ D%5@ D%-@ D%%@ D%@ D%@ D% @ D%@ D%? D%? D%? D%? D%? D%? D%? D%? D%? D%? D%? D%? D%? DH=? H? H9tH< Ht H=i? H5b? H)HHH?HHtH< HtfD=%? u+UH=< Ht H=9 )d> ]wH"O {H g HHwH ff.@UHH5q9 SHHDHtH xHH[]D` HH[]f.ATIH5 9 UHSLH5 9 HooHKoP S HP0HS0@8C8H[]A\DUHSHHC ωC Ht.UxSUxSUtC HH H[]He8 <ff.SHH8 H<{foHP foKJfoS R HK0HJ0K8J8[ff.HH5`= H׉fDH5E= 11ff.H: H0ff.fUSHH 8u&1HډuH[]f.H1[]SHHPH=I"p1HHTH[ff.@ATIUHHS LHSH=!p1HHH[]A\AVAUATUSHHdH%(HD$1HHDn@uHu1HL$dH3 %(H[]A\A]A^f.HH uHL`LMt$XHM/A|$HHHu7AD$wHHHHUE1HH7;HH='b1IDHHt+H;tMPЃ w-THߍlPHuHLEt+A9u&E1fHcLHt-1@HcLD$Ht-H|$LHLff.UHH54 SHHHXdH%(HD$H1qHo)$oH)L$oP )T$ HP0HT$0@8D$8HXH{HtHL$HdH3 %(HuHX[]H{ _:f.USHXdH%(HD$H1H>HXHB{H7u&H=8 HtHT$HdH3%(uHX[]H{ ff.@SHPdH%(HD$H1HXH{Hu)D$ HHHЃHT$HdH3%(uHP[H{ e@AVIAUATUHSHPdH%(HD$H1IBHXHFDcLD7uLD$ Iu6D$ LDt)HT$HdH3%(HuHP[]A\A]A^ÃxD$ H{ fAUATUHSHXdH%(HD$H1IHXHDcLDuCLDH"L$ {H $gtHT$HdH3%(HuHX[]A\A]H{ UHSHHXH{1u HH[]H{ SHdH%(HD$1HHtHHH$H4$HHD$dH3%(uH[\ff.AUATAUSHHIH8HH9tXAu HL_HHH"H={vHHtH56 11HHH[]A\A]@H3 H9uH3 H(됺1@AUIATIUSHHXdH%(HD$H11uDHC0oLoKoS HD$0C8H)$H)L$)T$ D$8AHމnHT$HdH3%(u HX[]A\A] f.SHH=1ƃS)1H[HAUATIH=U1SHIŅt&LH51)ƒA1t$؉H5tL1ÃC)1|LLaHL[]A\A]_ff.@SH1HH HmH t%HHu3HHPH0H[@HxuH@ H[HPH0H61 H5H81ff.fAWAVAUAATUSH8dH%(HD$(1IH1H0 H9u H0 HH53 HH1ҾH=KLLcEDHHt$KD$HD$HD$HILxL H=HAOLHIG H52 HmHL$(dH3 %(LH8[]A\A]A^A_fH.@ @u H HgH5q2 H!IĨurHtmHH uaID$HtWxtQHaH=)2 tAH9LASH52 H$ H51 H HaH=1 AKH9BADH=1 H9AHEHIH|$HD$HHt0AILLDAH'IPH0 σ1ATUHSHXHH{XHu{u"H[]A\fL`LA|$H{ ff.@ATUHSpHXHtH{XHu+{H5OHx*H[]A\f.+L`L/A|$H{ ff.@USHdH%(HD$1HXHH{XHuL{1HTuQD$Ht$H|HL$dH3 %(u$H[]{HhH}5H{ Lff.AUATUHSH:HXH>H{XDcHu!DuOHH[]A\A]fLhLEmAtE9t1DuDtH{ SHHt t H]H[fSHHt kt HH[fDfSHHt+uH[ftH1H[fDSHHtuH[fKtH1H[fDUSHw^HuHHHH5- 11HKHHtH5k- 11H/Hp* HH0-HH[]ú1SHHt+uH[ftH1H[@SHHtuH[fKtH1H[@AWAVAUATIUSHH(dH%(HD$1HhHHHHH΁ HHIHHa1HH[ H HSAAIuLsLkH}XH]HD$1HtHH$H$fD$1HtH}fD$1ItLhfD$1ItLSfD$HT$1THL$dH3 %(LuH([]A\A]A^A_ÐH#LxL@HT$H $"HXH&[HT$H $DHhH3 H} H( LH5H81AWAVAUATMUHSHHHt$HT$dH%(H$1D$,|LxLEwAIXED$HD$,HE1.HXH2AtD9kE |$,MH$dH3 %(H%Hĸ[]A\A]A^A_ÐHt$0LHDD$,EEwD$IXHtEELxLEwA&E9Ht$lLHDLHt$H|$HT$,D$,A HHHXH#AfH{XH{D9Ht$lD$,D$f|$1DtfDHt$H|$HT$,E1iHH~HXHA_D9kLHt$0Da7TD$,D$Em(+AEwD$hfD AD$f.HXH{D9fH5$ E1H HH5$ E1H {HH5$ E1H ;HHtzATIUSH@uX@uHu%Hn$ HLH5 H81HH uHtH‰9r[]A\fDHfD1ff.fSH HHTH= 1HHiH[@SHHߺH[SHp HHH=d 1HHH[@AUATUSHH8dH%(HD$(1Q1LD$H5% f^H|$Ld$1HHl$ CHHHLHH}Htv5HuGCHDHL$(dH3 %(6H8[]A\A]ÐHuCHH$tHc" HH59 H81LHL$*HD$HǨPCHHD@uj5LHHH"DHcALl8uOA9D1*f.1f[fKffDLH롃1AT1USH1H0dH%(HD$(1HL$HT$HH\$IHH HD$H5H HD$ uHHu'Ht$(dH34%(H?H0[]A\fHHƒHu H{uHC H@uHtHHуHuHH HuHhH}RpHCH uHC L HhHLHIHH4AT$HHcHTHHUHHcHTHPHHHCfDHHhߏD$βOmk\)QL<D*? ޚRg'hA." #^+$,B/I~#+) ^d?!eax"O9W@Zs̗6b6EL?)BQKRK'v5U ~qEw[&J@_&s__Yp"jʽl߷y5ַW bIEjhˀ -"m`'!*9090xnCHfuƹxr1r85 `紭4nEFՐ7$ r|XWhIpt9,+[ݩLf~Y,%A`[ ":J:s$\@ &&BFG\_Ԝ3g </šo+њ.I)&" 2AUG-;d<\ sEP]4*% 鵂 [XzL>|Y fw׏ֆs_uДq|ŧ{XI? n!UT$1U nb~,1Qc몵ȗ4b&J9M%iRw{Qt\Wq2iS_h>AA<.g09"]tZd$}~7Wt&2ѣR[8>Z!nbD uZl*&^3gUNvJCu/KP x>IET72<6ŏN8,U?S$]q֦[hג;=Ƞct¾0o+F.ɒBE4+ aKn-ӴEqԹ(٤SY&j8]]QҢ[.U/2*Rw=D .ӚL_,ΓiA-tD-) tTLU@ :&vAbKiB y>oKOyLcjV$6xHc㱛Kي^':X-a%XEc$$@Ba/a.Irh):fU5pb˦6>d΋Dm8"P0|>ܱ0+Z)f86$)9++&o: Q8U GV5klo<|hUJY2@ke@۷L YnT<нҙ_Y8%QUQ+oyǬ]Xw -ѵ@ygYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``8( X0 L8o<<EoPT@@^Bhcn@@pw""%} #include #include "ruby/regex.h" #include "ruby/internal/core/rmatch.h" #include "ruby/internal/dllexport.h" RBIMPL_SYMBOL_EXPORT_BEGIN() VALUE rb_reg_regcomp(VALUE); long rb_reg_search(VALUE, VALUE, long, int); VALUE rb_reg_regsub(VALUE, VALUE, struct re_registers *, VALUE); long rb_reg_adjust_startpos(VALUE, VALUE, long, int); void rb_match_busy(VALUE); VALUE rb_reg_quote(VALUE); regex_t *rb_reg_prepare_re(VALUE re, VALUE str); int rb_reg_region_copy(struct re_registers *, const struct re_registers *); RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_RE_H */ PK!kTԐvm.hnu[#ifndef RUBY_VM_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_VM_H 1 /** * @file * @author $Author$ * @date Sat May 31 15:17:36 2008 * @copyright Copyright (C) 2008 Yukihiro Matsumoto * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. */ #include "ruby/internal/dllexport.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* Place holder. * * We will prepare VM creation/control APIs on 1.9.2 or later. * */ /* VM type declaration */ typedef struct rb_vm_struct ruby_vm_t; /* core API */ int ruby_vm_destruct(ruby_vm_t *vm); /** * ruby_vm_at_exit registers a function _func_ to be invoked when a VM * passed away. Functions registered this way runs in reverse order * of registration, just like END {} block does. The difference is * its timing to be triggered. ruby_vm_at_exit functions runs when a * VM _passed_ _away_, while END {} blocks runs just _before_ a VM * _is_ _passing_ _away_. * * You cannot register a function to another VM than where you are in. * So where to register is intuitive, omitted. OTOH the argument * _func_ cannot know which VM it is in because at the time of * invocation, the VM has already died and there is no execution * context. The VM itself is passed as the first argument to it. * * @param[in] func the function to register. */ void ruby_vm_at_exit(void(*func)(ruby_vm_t *)); RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_VM_H */ PK! oniguruma.hnu[#ifndef ONIGURUMA_H #define ONIGURUMA_H #include "onigmo.h" #define ONIGURUMA #define ONIGURUMA_VERSION_MAJOR ONIGMO_VERSION_MAJOR #define ONIGURUMA_VERSION_MINOR ONIGMO_VERSION_MINOR #define ONIGURUMA_VERSION_TEENY ONIGMO_VERSION_TEENY #endif /* ONIGURUMA_H */ PK!8b{backward/util.hnu[#if defined __GNUC__ #warning use "ruby/util.h" instead of bare "util.h" #elif defined _MSC_VER #pragma message("warning: use \"ruby/util.h\" instead of bare \"util.h\"") #endif #include "ruby/util.h" PK!qVbackward/rubyio.hnu[#if defined __GNUC__ #warning use "ruby/io.h" instead of "rubyio.h" #elif defined _MSC_VER #pragma message("warning: use \"ruby/io.h\" instead of \"rubyio.h\"") #endif #include "ruby/io.h" PK!іɠbackward/rubysig.hnu[/********************************************************************** rubysig.h - $Author$ $Date$ created at: Wed Aug 16 01:15:38 JST 1995 Copyright (C) 1993-2008 Yukihiro Matsumoto **********************************************************************/ #if defined __GNUC__ #warning rubysig.h is obsolete #elif defined _MSC_VER #pragma message("warning: rubysig.h is obsolete") #endif #ifndef RUBYSIG_H #define RUBYSIG_H #include "ruby/ruby.h" #if defined(__cplusplus) extern "C" { #if 0 } /* satisfy cc-mode */ #endif #endif RUBY_SYMBOL_EXPORT_BEGIN #define RUBY_CRITICAL(statements) do {statements;} while (0) #define DEFER_INTS (0) #define ENABLE_INTS (1) #define ALLOW_INTS do {CHECK_INTS;} while (0) #define CHECK_INTS rb_thread_check_ints() RUBY_SYMBOL_EXPORT_END #if defined(__cplusplus) #if 0 { /* satisfy cc-mode */ #endif } /* extern "C" { */ #endif #endif PK! backward/st.hnu[#if defined __GNUC__ #warning use "ruby/st.h" instead of bare "st.h" #elif defined _MSC_VER #pragma message("warning: use \"ruby/st.h\" instead of bare \"st.h\"") #endif #include "ruby/st.h" PK!tbackward/classext.hnu[#if defined __GNUC__ #warning use of RClass internals is deprecated #elif defined _MSC_VER #pragma message("warning: use of RClass internals is deprecated") #endif #ifndef RUBY_BACKWARD_CLASSEXT_H #define RUBY_BACKWARD_CLASSEXT_H 1 typedef struct rb_deprecated_classext_struct { VALUE super; } rb_deprecated_classext_t; #undef RCLASS_SUPER(c) #define RCLASS_EXT(c) ((rb_deprecated_classext_t *)RCLASS(c)->ptr) #define RCLASS_SUPER(c) (RCLASS(c)->super) #endif /* RUBY_BACKWARD_CLASSEXT_H */ PK!jwiZ Z intern.hnu[#ifndef RUBY_INTERN_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_INTERN_H 1 /** * @file * @author $Author$ * @date Thu Jun 10 14:22:17 JST 1993 * @copyright Copyright (C) 1993-2007 Yukihiro Matsumoto * @copyright Copyright (C) 2000 Network Applied Communication Laboratory, Inc. * @copyright Copyright (C) 2000 Information-technology Promotion Agency, Japan * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. */ #include "ruby/internal/config.h" #include "ruby/defines.h" #include #include "ruby/st.h" /* * Functions and variables that are used by more than one source file of * the kernel. */ #include "ruby/internal/intern/array.h" #include "ruby/internal/intern/bignum.h" #include "ruby/internal/intern/class.h" #include "ruby/internal/intern/compar.h" #include "ruby/internal/intern/complex.h" #include "ruby/internal/intern/cont.h" #include "ruby/internal/intern/dir.h" #include "ruby/internal/intern/enum.h" #include "ruby/internal/intern/enumerator.h" #include "ruby/internal/intern/error.h" #include "ruby/internal/intern/eval.h" #include "ruby/internal/intern/file.h" #include "ruby/internal/intern/gc.h" #include "ruby/internal/intern/hash.h" #include "ruby/internal/intern/io.h" #include "ruby/internal/intern/load.h" #include "ruby/internal/intern/marshal.h" #include "ruby/internal/intern/numeric.h" #include "ruby/internal/intern/object.h" #include "ruby/internal/intern/parse.h" #include "ruby/internal/intern/proc.h" #include "ruby/internal/intern/process.h" #include "ruby/internal/intern/random.h" #include "ruby/internal/intern/range.h" #include "ruby/internal/intern/rational.h" #include "ruby/internal/intern/re.h" #include "ruby/internal/intern/ruby.h" #include "ruby/internal/intern/select.h" #include "ruby/internal/intern/signal.h" #include "ruby/internal/intern/sprintf.h" #include "ruby/internal/intern/string.h" #include "ruby/internal/intern/struct.h" #include "ruby/internal/intern/thread.h" #include "ruby/internal/intern/time.h" #include "ruby/internal/intern/variable.h" #include "ruby/internal/intern/vm.h" #endif /* RUBY_INTERN_H */ PK!ƾ)GG encoding.hnu[#ifndef RUBY_ENCODING_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_ENCODING_H 1 /** * @file * @author $Author: matz $ * @date Thu May 24 11:49:41 JST 2007 * @copyright Copyright (C) 2007 Yukihiro Matsumoto * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. */ #include "ruby/internal/config.h" #include #include "ruby/ruby.h" #include "ruby/oniguruma.h" #include "ruby/internal/dllexport.h" RBIMPL_SYMBOL_EXPORT_BEGIN() enum ruby_encoding_consts { RUBY_ENCODING_INLINE_MAX = 127, RUBY_ENCODING_SHIFT = (RUBY_FL_USHIFT+10), RUBY_ENCODING_MASK = (RUBY_ENCODING_INLINE_MAX<flags &= ~RUBY_ENCODING_MASK;\ RBASIC(obj)->flags |= (VALUE)(i) << RUBY_ENCODING_SHIFT;\ } while (0) #define RB_ENCODING_SET(obj,i) rb_enc_set_index((obj), (i)) #define RB_ENCODING_GET_INLINED(obj) \ (int)((RBASIC(obj)->flags & RUBY_ENCODING_MASK)>>RUBY_ENCODING_SHIFT) #define RB_ENCODING_GET(obj) \ (RB_ENCODING_GET_INLINED(obj) != RUBY_ENCODING_INLINE_MAX ? \ RB_ENCODING_GET_INLINED(obj) : \ rb_enc_get_index(obj)) #define RB_ENCODING_IS_ASCII8BIT(obj) (RB_ENCODING_GET_INLINED(obj) == 0) #define ENCODING_SET_INLINED(obj,i) RB_ENCODING_SET_INLINED(obj,i) #define ENCODING_SET(obj,i) RB_ENCODING_SET(obj,i) #define ENCODING_GET_INLINED(obj) RB_ENCODING_GET_INLINED(obj) #define ENCODING_GET(obj) RB_ENCODING_GET(obj) #define ENCODING_IS_ASCII8BIT(obj) RB_ENCODING_IS_ASCII8BIT(obj) #define ENCODING_MAXNAMELEN RUBY_ENCODING_MAXNAMELEN enum ruby_coderange_type { RUBY_ENC_CODERANGE_UNKNOWN = 0, RUBY_ENC_CODERANGE_7BIT = ((int)RUBY_FL_USER8), RUBY_ENC_CODERANGE_VALID = ((int)RUBY_FL_USER9), RUBY_ENC_CODERANGE_BROKEN = ((int)(RUBY_FL_USER8|RUBY_FL_USER9)), RUBY_ENC_CODERANGE_MASK = (RUBY_ENC_CODERANGE_7BIT| RUBY_ENC_CODERANGE_VALID| RUBY_ENC_CODERANGE_BROKEN) }; static inline int rb_enc_coderange_clean_p(int cr) { return (cr ^ (cr >> 1)) & RUBY_ENC_CODERANGE_7BIT; } #define RB_ENC_CODERANGE_CLEAN_P(cr) rb_enc_coderange_clean_p(cr) #define RB_ENC_CODERANGE(obj) ((int)RBASIC(obj)->flags & RUBY_ENC_CODERANGE_MASK) #define RB_ENC_CODERANGE_ASCIIONLY(obj) (RB_ENC_CODERANGE(obj) == RUBY_ENC_CODERANGE_7BIT) #define RB_ENC_CODERANGE_SET(obj,cr) (\ RBASIC(obj)->flags = \ (RBASIC(obj)->flags & ~RUBY_ENC_CODERANGE_MASK) | (cr)) #define RB_ENC_CODERANGE_CLEAR(obj) RB_ENC_CODERANGE_SET((obj),0) /* assumed ASCII compatibility */ #define RB_ENC_CODERANGE_AND(a, b) \ ((a) == RUBY_ENC_CODERANGE_7BIT ? (b) : \ (a) != RUBY_ENC_CODERANGE_VALID ? RUBY_ENC_CODERANGE_UNKNOWN : \ (b) == RUBY_ENC_CODERANGE_7BIT ? RUBY_ENC_CODERANGE_VALID : (b)) #define RB_ENCODING_CODERANGE_SET(obj, encindex, cr) \ do { \ VALUE rb_encoding_coderange_obj = (obj); \ RB_ENCODING_SET(rb_encoding_coderange_obj, (encindex)); \ RB_ENC_CODERANGE_SET(rb_encoding_coderange_obj, (cr)); \ } while (0) #define ENC_CODERANGE_MASK RUBY_ENC_CODERANGE_MASK #define ENC_CODERANGE_UNKNOWN RUBY_ENC_CODERANGE_UNKNOWN #define ENC_CODERANGE_7BIT RUBY_ENC_CODERANGE_7BIT #define ENC_CODERANGE_VALID RUBY_ENC_CODERANGE_VALID #define ENC_CODERANGE_BROKEN RUBY_ENC_CODERANGE_BROKEN #define ENC_CODERANGE_CLEAN_P(cr) RB_ENC_CODERANGE_CLEAN_P(cr) #define ENC_CODERANGE(obj) RB_ENC_CODERANGE(obj) #define ENC_CODERANGE_ASCIIONLY(obj) RB_ENC_CODERANGE_ASCIIONLY(obj) #define ENC_CODERANGE_SET(obj,cr) RB_ENC_CODERANGE_SET(obj,cr) #define ENC_CODERANGE_CLEAR(obj) RB_ENC_CODERANGE_CLEAR(obj) #define ENC_CODERANGE_AND(a, b) RB_ENC_CODERANGE_AND(a, b) #define ENCODING_CODERANGE_SET(obj, encindex, cr) RB_ENCODING_CODERANGE_SET(obj, encindex, cr) typedef const OnigEncodingType rb_encoding; int rb_char_to_option_kcode(int c, int *option, int *kcode); int rb_enc_replicate(const char *, rb_encoding *); int rb_define_dummy_encoding(const char *); PUREFUNC(int rb_enc_dummy_p(rb_encoding *enc)); PUREFUNC(int rb_enc_to_index(rb_encoding *enc)); int rb_enc_get_index(VALUE obj); void rb_enc_set_index(VALUE obj, int encindex); int rb_enc_capable(VALUE obj); int rb_enc_find_index(const char *name); int rb_enc_alias(const char *alias, const char *orig); int rb_to_encoding_index(VALUE); rb_encoding *rb_to_encoding(VALUE); rb_encoding *rb_find_encoding(VALUE); rb_encoding *rb_enc_get(VALUE); rb_encoding *rb_enc_compatible(VALUE,VALUE); rb_encoding *rb_enc_check(VALUE,VALUE); VALUE rb_enc_associate_index(VALUE, int); VALUE rb_enc_associate(VALUE, rb_encoding*); void rb_enc_copy(VALUE dst, VALUE src); VALUE rb_enc_str_new(const char*, long, rb_encoding*); VALUE rb_enc_str_new_cstr(const char*, rb_encoding*); VALUE rb_enc_str_new_static(const char*, long, rb_encoding*); VALUE rb_enc_interned_str(const char *, long, rb_encoding *); VALUE rb_enc_interned_str_cstr(const char *, rb_encoding *); VALUE rb_enc_reg_new(const char*, long, rb_encoding*, int); PRINTF_ARGS(VALUE rb_enc_sprintf(rb_encoding *, const char*, ...), 2, 3); VALUE rb_enc_vsprintf(rb_encoding *, const char*, va_list); long rb_enc_strlen(const char*, const char*, rb_encoding*); char* rb_enc_nth(const char*, const char*, long, rb_encoding*); VALUE rb_obj_encoding(VALUE); VALUE rb_enc_str_buf_cat(VALUE str, const char *ptr, long len, rb_encoding *enc); VALUE rb_enc_uint_chr(unsigned int code, rb_encoding *enc); VALUE rb_external_str_new_with_enc(const char *ptr, long len, rb_encoding *); VALUE rb_str_export_to_enc(VALUE, rb_encoding *); VALUE rb_str_conv_enc(VALUE str, rb_encoding *from, rb_encoding *to); VALUE rb_str_conv_enc_opts(VALUE str, rb_encoding *from, rb_encoding *to, int ecflags, VALUE ecopts); #ifdef HAVE_BUILTIN___BUILTIN_CONSTANT_P #define rb_enc_str_new(str, len, enc) RB_GNUC_EXTENSION_BLOCK( \ (__builtin_constant_p(str) && __builtin_constant_p(len)) ? \ rb_enc_str_new_static((str), (len), (enc)) : \ rb_enc_str_new((str), (len), (enc)) \ ) #define rb_enc_str_new_cstr(str, enc) RB_GNUC_EXTENSION_BLOCK( \ (__builtin_constant_p(str)) ? \ rb_enc_str_new_static((str), (long)strlen(str), (enc)) : \ rb_enc_str_new_cstr((str), (enc)) \ ) #endif PRINTF_ARGS(NORETURN(void rb_enc_raise(rb_encoding *, VALUE, const char*, ...)), 3, 4); /* index -> rb_encoding */ rb_encoding *rb_enc_from_index(int idx); /* name -> rb_encoding */ rb_encoding *rb_enc_find(const char *name); /* rb_encoding * -> name */ #define rb_enc_name(enc) (enc)->name /* rb_encoding * -> minlen/maxlen */ #define rb_enc_mbminlen(enc) (enc)->min_enc_len #define rb_enc_mbmaxlen(enc) (enc)->max_enc_len /* -> mbclen (no error notification: 0 < ret <= e-p, no exception) */ int rb_enc_mbclen(const char *p, const char *e, rb_encoding *enc); /* -> mbclen (only for valid encoding) */ int rb_enc_fast_mbclen(const char *p, const char *e, rb_encoding *enc); /* -> chlen, invalid or needmore */ int rb_enc_precise_mbclen(const char *p, const char *e, rb_encoding *enc); #define MBCLEN_CHARFOUND_P(ret) ONIGENC_MBCLEN_CHARFOUND_P(ret) #define MBCLEN_CHARFOUND_LEN(ret) ONIGENC_MBCLEN_CHARFOUND_LEN(ret) #define MBCLEN_INVALID_P(ret) ONIGENC_MBCLEN_INVALID_P(ret) #define MBCLEN_NEEDMORE_P(ret) ONIGENC_MBCLEN_NEEDMORE_P(ret) #define MBCLEN_NEEDMORE_LEN(ret) ONIGENC_MBCLEN_NEEDMORE_LEN(ret) /* -> 0x00..0x7f, -1 */ int rb_enc_ascget(const char *p, const char *e, int *len, rb_encoding *enc); /* -> code (and len) or raise exception */ unsigned int rb_enc_codepoint_len(const char *p, const char *e, int *len, rb_encoding *enc); /* prototype for obsolete function */ unsigned int rb_enc_codepoint(const char *p, const char *e, rb_encoding *enc); /* overriding macro */ #define rb_enc_codepoint(p,e,enc) rb_enc_codepoint_len((p),(e),0,(enc)) #define rb_enc_mbc_to_codepoint(p, e, enc) ONIGENC_MBC_TO_CODE((enc),(UChar*)(p),(UChar*)(e)) /* -> codelen>0 or raise exception */ int rb_enc_codelen(int code, rb_encoding *enc); /* -> 0 for invalid codepoint */ int rb_enc_code_to_mbclen(int code, rb_encoding *enc); #define rb_enc_code_to_mbclen(c, enc) ONIGENC_CODE_TO_MBCLEN((enc), (c)); /* code,ptr,encoding -> write buf */ #define rb_enc_mbcput(c,buf,enc) ONIGENC_CODE_TO_MBC((enc),(c),(UChar*)(buf)) /* start, ptr, end, encoding -> prev_char */ #define rb_enc_prev_char(s,p,e,enc) ((char *)onigenc_get_prev_char_head((enc),(UChar*)(s),(UChar*)(p),(UChar*)(e))) /* start, ptr, end, encoding -> next_char */ #define rb_enc_left_char_head(s,p,e,enc) ((char *)onigenc_get_left_adjust_char_head((enc),(UChar*)(s),(UChar*)(p),(UChar*)(e))) #define rb_enc_right_char_head(s,p,e,enc) ((char *)onigenc_get_right_adjust_char_head((enc),(UChar*)(s),(UChar*)(p),(UChar*)(e))) #define rb_enc_step_back(s,p,e,n,enc) ((char *)onigenc_step_back((enc),(UChar*)(s),(UChar*)(p),(UChar*)(e),(int)(n))) /* ptr, ptr, encoding -> newline_or_not */ #define rb_enc_is_newline(p,end,enc) ONIGENC_IS_MBC_NEWLINE((enc),(UChar*)(p),(UChar*)(end)) #define rb_enc_isctype(c,t,enc) ONIGENC_IS_CODE_CTYPE((enc),(c),(t)) #define rb_enc_isascii(c,enc) ONIGENC_IS_CODE_ASCII(c) #define rb_enc_isalpha(c,enc) ONIGENC_IS_CODE_ALPHA((enc),(c)) #define rb_enc_islower(c,enc) ONIGENC_IS_CODE_LOWER((enc),(c)) #define rb_enc_isupper(c,enc) ONIGENC_IS_CODE_UPPER((enc),(c)) #define rb_enc_ispunct(c,enc) ONIGENC_IS_CODE_PUNCT((enc),(c)) #define rb_enc_isalnum(c,enc) ONIGENC_IS_CODE_ALNUM((enc),(c)) #define rb_enc_isprint(c,enc) ONIGENC_IS_CODE_PRINT((enc),(c)) #define rb_enc_isspace(c,enc) ONIGENC_IS_CODE_SPACE((enc),(c)) #define rb_enc_isdigit(c,enc) ONIGENC_IS_CODE_DIGIT((enc),(c)) static inline int rb_enc_asciicompat_inline(rb_encoding *enc) { return rb_enc_mbminlen(enc)==1 && !rb_enc_dummy_p(enc); } #define rb_enc_asciicompat(enc) rb_enc_asciicompat_inline(enc) int rb_enc_casefold(char *to, const char *p, const char *e, rb_encoding *enc); CONSTFUNC(int rb_enc_toupper(int c, rb_encoding *enc)); CONSTFUNC(int rb_enc_tolower(int c, rb_encoding *enc)); ID rb_intern3(const char*, long, rb_encoding*); ID rb_interned_id_p(const char *, long, rb_encoding *); int rb_enc_symname_p(const char*, rb_encoding*); int rb_enc_symname2_p(const char*, long, rb_encoding*); int rb_enc_str_coderange(VALUE); long rb_str_coderange_scan_restartable(const char*, const char*, rb_encoding*, int*); int rb_enc_str_asciionly_p(VALUE); #define rb_enc_str_asciicompat_p(str) rb_enc_asciicompat(rb_enc_get(str)) VALUE rb_enc_from_encoding(rb_encoding *enc); PUREFUNC(int rb_enc_unicode_p(rb_encoding *enc)); rb_encoding *rb_ascii8bit_encoding(void); rb_encoding *rb_utf8_encoding(void); rb_encoding *rb_usascii_encoding(void); rb_encoding *rb_locale_encoding(void); rb_encoding *rb_filesystem_encoding(void); rb_encoding *rb_default_external_encoding(void); rb_encoding *rb_default_internal_encoding(void); #ifndef rb_ascii8bit_encindex CONSTFUNC(int rb_ascii8bit_encindex(void)); #endif #ifndef rb_utf8_encindex CONSTFUNC(int rb_utf8_encindex(void)); #endif #ifndef rb_usascii_encindex CONSTFUNC(int rb_usascii_encindex(void)); #endif int rb_locale_encindex(void); int rb_filesystem_encindex(void); VALUE rb_enc_default_external(void); VALUE rb_enc_default_internal(void); void rb_enc_set_default_external(VALUE encoding); void rb_enc_set_default_internal(VALUE encoding); VALUE rb_locale_charmap(VALUE klass); long rb_memsearch(const void*,long,const void*,long,rb_encoding*); char *rb_enc_path_next(const char *,const char *,rb_encoding*); char *rb_enc_path_skip_prefix(const char *,const char *,rb_encoding*); char *rb_enc_path_last_separator(const char *,const char *,rb_encoding*); char *rb_enc_path_end(const char *,const char *,rb_encoding*); const char *ruby_enc_find_basename(const char *name, long *baselen, long *alllen, rb_encoding *enc); const char *ruby_enc_find_extname(const char *name, long *len, rb_encoding *enc); ID rb_check_id_cstr(const char *ptr, long len, rb_encoding *enc); VALUE rb_check_symbol_cstr(const char *ptr, long len, rb_encoding *enc); RUBY_EXTERN VALUE rb_cEncoding; /* econv stuff */ typedef enum { econv_invalid_byte_sequence, econv_undefined_conversion, econv_destination_buffer_full, econv_source_buffer_empty, econv_finished, econv_after_output, econv_incomplete_input } rb_econv_result_t; typedef struct rb_econv_t rb_econv_t; VALUE rb_str_encode(VALUE str, VALUE to, int ecflags, VALUE ecopts); int rb_econv_has_convpath_p(const char* from_encoding, const char* to_encoding); int rb_econv_prepare_options(VALUE opthash, VALUE *ecopts, int ecflags); int rb_econv_prepare_opts(VALUE opthash, VALUE *ecopts); rb_econv_t *rb_econv_open(const char *source_encoding, const char *destination_encoding, int ecflags); rb_econv_t *rb_econv_open_opts(const char *source_encoding, const char *destination_encoding, int ecflags, VALUE ecopts); rb_econv_result_t rb_econv_convert(rb_econv_t *ec, const unsigned char **source_buffer_ptr, const unsigned char *source_buffer_end, unsigned char **destination_buffer_ptr, unsigned char *destination_buffer_end, int flags); void rb_econv_close(rb_econv_t *ec); /* result: 0:success -1:failure */ int rb_econv_set_replacement(rb_econv_t *ec, const unsigned char *str, size_t len, const char *encname); /* result: 0:success -1:failure */ int rb_econv_decorate_at_first(rb_econv_t *ec, const char *decorator_name); int rb_econv_decorate_at_last(rb_econv_t *ec, const char *decorator_name); VALUE rb_econv_open_exc(const char *senc, const char *denc, int ecflags); /* result: 0:success -1:failure */ int rb_econv_insert_output(rb_econv_t *ec, const unsigned char *str, size_t len, const char *str_encoding); /* encoding that rb_econv_insert_output doesn't need conversion */ const char *rb_econv_encoding_to_insert_output(rb_econv_t *ec); /* raise an error if the last rb_econv_convert is error */ void rb_econv_check_error(rb_econv_t *ec); /* returns an exception object or nil */ VALUE rb_econv_make_exception(rb_econv_t *ec); int rb_econv_putbackable(rb_econv_t *ec); void rb_econv_putback(rb_econv_t *ec, unsigned char *p, int n); /* returns the corresponding ASCII compatible encoding for encname, * or NULL if encname is not ASCII incompatible encoding. */ const char *rb_econv_asciicompat_encoding(const char *encname); VALUE rb_econv_str_convert(rb_econv_t *ec, VALUE src, int flags); VALUE rb_econv_substr_convert(rb_econv_t *ec, VALUE src, long byteoff, long bytesize, int flags); VALUE rb_econv_str_append(rb_econv_t *ec, VALUE src, VALUE dst, int flags); VALUE rb_econv_substr_append(rb_econv_t *ec, VALUE src, long byteoff, long bytesize, VALUE dst, int flags); VALUE rb_econv_append(rb_econv_t *ec, const char *bytesrc, long bytesize, VALUE dst, int flags); void rb_econv_binmode(rb_econv_t *ec); enum ruby_econv_flag_type { /* flags for rb_econv_open */ RUBY_ECONV_ERROR_HANDLER_MASK = 0x000000ff, RUBY_ECONV_INVALID_MASK = 0x0000000f, RUBY_ECONV_INVALID_REPLACE = 0x00000002, RUBY_ECONV_UNDEF_MASK = 0x000000f0, RUBY_ECONV_UNDEF_REPLACE = 0x00000020, RUBY_ECONV_UNDEF_HEX_CHARREF = 0x00000030, RUBY_ECONV_DECORATOR_MASK = 0x0000ff00, RUBY_ECONV_NEWLINE_DECORATOR_MASK = 0x00003f00, RUBY_ECONV_NEWLINE_DECORATOR_READ_MASK = 0x00000f00, RUBY_ECONV_NEWLINE_DECORATOR_WRITE_MASK = 0x00003000, RUBY_ECONV_UNIVERSAL_NEWLINE_DECORATOR = 0x00000100, RUBY_ECONV_CRLF_NEWLINE_DECORATOR = 0x00001000, RUBY_ECONV_CR_NEWLINE_DECORATOR = 0x00002000, RUBY_ECONV_XML_TEXT_DECORATOR = 0x00004000, RUBY_ECONV_XML_ATTR_CONTENT_DECORATOR = 0x00008000, RUBY_ECONV_STATEFUL_DECORATOR_MASK = 0x00f00000, RUBY_ECONV_XML_ATTR_QUOTE_DECORATOR = 0x00100000, RUBY_ECONV_DEFAULT_NEWLINE_DECORATOR = #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32) RUBY_ECONV_CRLF_NEWLINE_DECORATOR, #else 0, #endif #define ECONV_ERROR_HANDLER_MASK RUBY_ECONV_ERROR_HANDLER_MASK #define ECONV_INVALID_MASK RUBY_ECONV_INVALID_MASK #define ECONV_INVALID_REPLACE RUBY_ECONV_INVALID_REPLACE #define ECONV_UNDEF_MASK RUBY_ECONV_UNDEF_MASK #define ECONV_UNDEF_REPLACE RUBY_ECONV_UNDEF_REPLACE #define ECONV_UNDEF_HEX_CHARREF RUBY_ECONV_UNDEF_HEX_CHARREF #define ECONV_DECORATOR_MASK RUBY_ECONV_DECORATOR_MASK #define ECONV_NEWLINE_DECORATOR_MASK RUBY_ECONV_NEWLINE_DECORATOR_MASK #define ECONV_NEWLINE_DECORATOR_READ_MASK RUBY_ECONV_NEWLINE_DECORATOR_READ_MASK #define ECONV_NEWLINE_DECORATOR_WRITE_MASK RUBY_ECONV_NEWLINE_DECORATOR_WRITE_MASK #define ECONV_UNIVERSAL_NEWLINE_DECORATOR RUBY_ECONV_UNIVERSAL_NEWLINE_DECORATOR #define ECONV_CRLF_NEWLINE_DECORATOR RUBY_ECONV_CRLF_NEWLINE_DECORATOR #define ECONV_CR_NEWLINE_DECORATOR RUBY_ECONV_CR_NEWLINE_DECORATOR #define ECONV_XML_TEXT_DECORATOR RUBY_ECONV_XML_TEXT_DECORATOR #define ECONV_XML_ATTR_CONTENT_DECORATOR RUBY_ECONV_XML_ATTR_CONTENT_DECORATOR #define ECONV_STATEFUL_DECORATOR_MASK RUBY_ECONV_STATEFUL_DECORATOR_MASK #define ECONV_XML_ATTR_QUOTE_DECORATOR RUBY_ECONV_XML_ATTR_QUOTE_DECORATOR #define ECONV_DEFAULT_NEWLINE_DECORATOR RUBY_ECONV_DEFAULT_NEWLINE_DECORATOR /* end of flags for rb_econv_open */ /* flags for rb_econv_convert */ RUBY_ECONV_PARTIAL_INPUT = 0x00010000, RUBY_ECONV_AFTER_OUTPUT = 0x00020000, #define ECONV_PARTIAL_INPUT RUBY_ECONV_PARTIAL_INPUT #define ECONV_AFTER_OUTPUT RUBY_ECONV_AFTER_OUTPUT /* end of flags for rb_econv_convert */ RUBY_ECONV_FLAGS_PLACEHOLDER}; RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_ENCODING_H */ PK!C defines.hnu[#ifndef RUBY_DEFINES_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_DEFINES_H 1 /** * @file * @author $Author$ * @date Wed May 18 00:21:44 JST 1994 * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. */ #include "ruby/internal/config.h" /* AC_INCLUDES_DEFAULT */ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_STDALIGN_H # include #endif #ifdef HAVE_UNISTD_H # include #endif #ifdef HAVE_SYS_SELECT_H # include #endif #ifdef RUBY_USE_SETJMPEX # include #endif #include "ruby/internal/dllexport.h" #include "ruby/internal/xmalloc.h" #include "ruby/backward/2/assume.h" #include "ruby/backward/2/attributes.h" #include "ruby/backward/2/bool.h" #include "ruby/backward/2/gcc_version_since.h" #include "ruby/backward/2/long_long.h" #include "ruby/backward/2/stdalign.h" #include "ruby/backward/2/stdarg.h" #include "ruby/internal/dosish.h" #include "ruby/missing.h" #define RUBY #ifdef __GNUC__ # define RB_GNUC_EXTENSION __extension__ # define RB_GNUC_EXTENSION_BLOCK(x) __extension__ ({ x; }) #else # define RB_GNUC_EXTENSION # define RB_GNUC_EXTENSION_BLOCK(x) (x) #endif /* :FIXME: Can someone tell us why is this macro defined here? @shyouhei * thinks this is a truly internal macro but cannot move around because he * doesn't understand the reason of this arrangement. */ #ifndef RUBY_MBCHAR_MAXSIZE # define RUBY_MBCHAR_MAXSIZE INT_MAX # /* MB_CUR_MAX will not work well in C locale */ #endif #if defined(__sparc) RBIMPL_SYMBOL_EXPORT_BEGIN() void rb_sparc_flush_register_windows(void); RBIMPL_SYMBOL_EXPORT_END() # define FLUSH_REGISTER_WINDOWS rb_sparc_flush_register_windows() #else # define FLUSH_REGISTER_WINDOWS ((void)0) #endif #endif /* RUBY_DEFINES_H */ PK!61io.hnu[#ifndef RUBY_IO_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_IO_H 1 /** * @file * @author $Author$ * @date Fri Nov 12 16:47:09 JST 1993 * @copyright Copyright (C) 1993-2007 Yukihiro Matsumoto * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. */ #include "ruby/internal/config.h" #include #include "ruby/encoding.h" #if defined(HAVE_STDIO_EXT_H) #include #endif #include #if defined(HAVE_POLL) # ifdef _AIX # define reqevents events # define rtnevents revents # endif # include # ifdef _AIX # undef reqevents # undef rtnevents # undef events # undef revents # endif # define RB_WAITFD_IN POLLIN # define RB_WAITFD_PRI POLLPRI # define RB_WAITFD_OUT POLLOUT #else # define RB_WAITFD_IN 0x001 # define RB_WAITFD_PRI 0x002 # define RB_WAITFD_OUT 0x004 #endif typedef enum { RUBY_IO_READABLE = RB_WAITFD_IN, RUBY_IO_WRITABLE = RB_WAITFD_OUT, RUBY_IO_PRIORITY = RB_WAITFD_PRI, } rb_io_event_t; #include "ruby/internal/dllexport.h" RBIMPL_SYMBOL_EXPORT_BEGIN() PACKED_STRUCT_UNALIGNED(struct rb_io_buffer_t { char *ptr; /* off + len <= capa */ int off; int len; int capa; }); typedef struct rb_io_buffer_t rb_io_buffer_t; typedef struct rb_io_t { VALUE self; FILE *stdio_file; /* stdio ptr for read/write if available */ int fd; /* file descriptor */ int mode; /* mode flags: FMODE_XXXs */ rb_pid_t pid; /* child's pid (for pipes) */ int lineno; /* number of lines read */ VALUE pathv; /* pathname for file */ void (*finalize)(struct rb_io_t*,int); /* finalize proc */ rb_io_buffer_t wbuf, rbuf; VALUE tied_io_for_writing; /* * enc enc2 read action write action * NULL NULL force_encoding(default_external) write the byte sequence of str * e1 NULL force_encoding(e1) convert str.encoding to e1 * e1 e2 convert from e2 to e1 convert str.encoding to e2 */ struct rb_io_enc_t { rb_encoding *enc; rb_encoding *enc2; int ecflags; VALUE ecopts; } encs; rb_econv_t *readconv; rb_io_buffer_t cbuf; rb_econv_t *writeconv; VALUE writeconv_asciicompat; int writeconv_initialized; int writeconv_pre_ecflags; VALUE writeconv_pre_ecopts; VALUE write_lock; } rb_io_t; typedef struct rb_io_enc_t rb_io_enc_t; #define HAVE_RB_IO_T 1 #define FMODE_READABLE 0x00000001 #define FMODE_WRITABLE 0x00000002 #define FMODE_READWRITE (FMODE_READABLE|FMODE_WRITABLE) #define FMODE_BINMODE 0x00000004 #define FMODE_SYNC 0x00000008 #define FMODE_TTY 0x00000010 #define FMODE_DUPLEX 0x00000020 #define FMODE_APPEND 0x00000040 #define FMODE_CREATE 0x00000080 /* #define FMODE_NOREVLOOKUP 0x00000100 */ #define FMODE_EXCL 0x00000400 #define FMODE_TRUNC 0x00000800 #define FMODE_TEXTMODE 0x00001000 /* #define FMODE_PREP 0x00010000 */ #define FMODE_SETENC_BY_BOM 0x00100000 /* #define FMODE_UNIX 0x00200000 */ /* #define FMODE_INET 0x00400000 */ /* #define FMODE_INET6 0x00800000 */ #define RB_IO_POINTER(obj,fp) rb_io_check_closed((fp) = RFILE(rb_io_taint_check(obj))->fptr) #define GetOpenFile RB_IO_POINTER #define RB_IO_OPEN(obj, fp) do {\ (fp) = rb_io_make_open_file(obj);\ } while (0) #define MakeOpenFile RB_IO_OPEN rb_io_t *rb_io_make_open_file(VALUE obj); FILE *rb_io_stdio_file(rb_io_t *fptr); FILE *rb_fdopen(int, const char*); int rb_io_modestr_fmode(const char *modestr); int rb_io_modestr_oflags(const char *modestr); CONSTFUNC(int rb_io_oflags_fmode(int oflags)); void rb_io_check_writable(rb_io_t*); void rb_io_check_readable(rb_io_t*); void rb_io_check_char_readable(rb_io_t *fptr); void rb_io_check_byte_readable(rb_io_t *fptr); int rb_io_fptr_finalize(rb_io_t*); void rb_io_synchronized(rb_io_t*); void rb_io_check_initialized(rb_io_t*); void rb_io_check_closed(rb_io_t*); VALUE rb_io_get_io(VALUE io); VALUE rb_io_check_io(VALUE io); VALUE rb_io_get_write_io(VALUE io); VALUE rb_io_set_write_io(VALUE io, VALUE w); void rb_io_set_nonblock(rb_io_t *fptr); int rb_io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p); void rb_io_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash, int *oflags_p, int *fmode_p, rb_io_enc_t *convconfig_p); ssize_t rb_io_bufwrite(VALUE io, const void *buf, size_t size); int rb_io_wait_readable(int fd); int rb_io_wait_writable(int fd); int rb_wait_for_single_fd(int fd, int events, struct timeval *tv); VALUE rb_io_wait(VALUE io, VALUE events, VALUE timeout); /* compatibility for ruby 1.8 and older */ #define rb_io_mode_flags(modestr) [<"rb_io_mode_flags() is obsolete; use rb_io_modestr_fmode()">] #define rb_io_modenum_flags(oflags) [<"rb_io_modenum_flags() is obsolete; use rb_io_oflags_fmode()">] VALUE rb_io_taint_check(VALUE); NORETURN(void rb_eof_error(void)); void rb_io_read_check(rb_io_t*); int rb_io_read_pending(rb_io_t*); struct stat; VALUE rb_stat_new(const struct stat *); /* gc.c */ RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_IO_H */ PK!&T^//subst.hnu[#ifndef RUBY_SUBST_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_SUBST_H 1 /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. */ #undef snprintf #undef vsnprintf #define snprintf ruby_snprintf #define vsnprintf ruby_vsnprintf #ifdef BROKEN_CLOSE #undef getpeername #define getpeername ruby_getpeername #undef getsockname #define getsockname ruby_getsockname #undef shutdown #define shutdown ruby_shutdown #undef close #define close ruby_close #endif #endif PK!rǕst.hnu[/* This is a public domain general purpose hash table package originally written by Peter Moore @ UCB. The hash table data structures were redesigned and the package was rewritten by Vladimir Makarov . */ #ifndef RUBY_ST_H #define RUBY_ST_H 1 #if defined(__cplusplus) extern "C" { #if 0 } /* satisfy cc-mode */ #endif #endif #include "ruby/defines.h" RUBY_SYMBOL_EXPORT_BEGIN #if SIZEOF_LONG == SIZEOF_VOIDP typedef unsigned long st_data_t; #elif SIZEOF_LONG_LONG == SIZEOF_VOIDP typedef unsigned LONG_LONG st_data_t; #else # error ---->> st.c requires sizeof(void*) == sizeof(long) or sizeof(LONG_LONG) to be compiled. <<---- #endif #define ST_DATA_T_DEFINED #ifndef CHAR_BIT # ifdef HAVE_LIMITS_H # include # else # define CHAR_BIT 8 # endif #endif #ifndef _ # define _(args) args #endif #ifndef ANYARGS # ifdef __cplusplus # define ANYARGS ... # else # define ANYARGS # endif #endif typedef struct st_table st_table; typedef st_data_t st_index_t; /* Maximal value of unsigned integer type st_index_t. */ #define MAX_ST_INDEX_VAL (~(st_index_t) 0) typedef int st_compare_func(st_data_t, st_data_t); typedef st_index_t st_hash_func(st_data_t); typedef char st_check_for_sizeof_st_index_t[SIZEOF_VOIDP == (int)sizeof(st_index_t) ? 1 : -1]; #define SIZEOF_ST_INDEX_T SIZEOF_VOIDP struct st_hash_type { int (*compare)(st_data_t, st_data_t); /* st_compare_func* */ st_index_t (*hash)(st_data_t); /* st_hash_func* */ }; #define ST_INDEX_BITS (SIZEOF_ST_INDEX_T * CHAR_BIT) #if defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR) && defined(HAVE_BUILTIN___BUILTIN_TYPES_COMPATIBLE_P) # define ST_DATA_COMPATIBLE_P(type) \ __builtin_choose_expr(__builtin_types_compatible_p(type, st_data_t), 1, 0) #else # define ST_DATA_COMPATIBLE_P(type) 0 #endif typedef struct st_table_entry st_table_entry; struct st_table_entry; /* defined in st.c */ struct st_table { /* Cached features of the table -- see st.c for more details. */ unsigned char entry_power, bin_power, size_ind; /* How many times the table was rebuilt. */ unsigned int rebuilds_num; const struct st_hash_type *type; /* Number of entries currently in the table. */ st_index_t num_entries; /* Array of bins used for access by keys. */ st_index_t *bins; /* Start and bound index of entries in array entries. entries_starts and entries_bound are in interval [0,allocated_entries]. */ st_index_t entries_start, entries_bound; /* Array of size 2^entry_power. */ st_table_entry *entries; }; #define st_is_member(table,key) st_lookup((table),(key),(st_data_t *)0) enum st_retval {ST_CONTINUE, ST_STOP, ST_DELETE, ST_CHECK, ST_REPLACE}; st_table *rb_st_init_table(const struct st_hash_type *); #define st_init_table rb_st_init_table st_table *rb_st_init_table_with_size(const struct st_hash_type *, st_index_t); #define st_init_table_with_size rb_st_init_table_with_size st_table *rb_st_init_numtable(void); #define st_init_numtable rb_st_init_numtable st_table *rb_st_init_numtable_with_size(st_index_t); #define st_init_numtable_with_size rb_st_init_numtable_with_size st_table *rb_st_init_strtable(void); #define st_init_strtable rb_st_init_strtable st_table *rb_st_init_strtable_with_size(st_index_t); #define st_init_strtable_with_size rb_st_init_strtable_with_size st_table *rb_st_init_strcasetable(void); #define st_init_strcasetable rb_st_init_strcasetable st_table *rb_st_init_strcasetable_with_size(st_index_t); #define st_init_strcasetable_with_size rb_st_init_strcasetable_with_size int rb_st_delete(st_table *, st_data_t *, st_data_t *); /* returns 0:notfound 1:deleted */ #define st_delete rb_st_delete int rb_st_delete_safe(st_table *, st_data_t *, st_data_t *, st_data_t); #define st_delete_safe rb_st_delete_safe int rb_st_shift(st_table *, st_data_t *, st_data_t *); /* returns 0:notfound 1:deleted */ #define st_shift rb_st_shift int rb_st_insert(st_table *, st_data_t, st_data_t); #define st_insert rb_st_insert int rb_st_insert2(st_table *, st_data_t, st_data_t, st_data_t (*)(st_data_t)); #define st_insert2 rb_st_insert2 int rb_st_lookup(st_table *, st_data_t, st_data_t *); #define st_lookup rb_st_lookup int rb_st_get_key(st_table *, st_data_t, st_data_t *); #define st_get_key rb_st_get_key typedef int st_update_callback_func(st_data_t *key, st_data_t *value, st_data_t arg, int existing); /* *key may be altered, but must equal to the old key, i.e., the * results of hash() are same and compare() returns 0, otherwise the * behavior is undefined */ int rb_st_update(st_table *table, st_data_t key, st_update_callback_func *func, st_data_t arg); #define st_update rb_st_update typedef int st_foreach_callback_func(st_data_t, st_data_t, st_data_t); typedef int st_foreach_check_callback_func(st_data_t, st_data_t, st_data_t, int); int rb_st_foreach_with_replace(st_table *tab, st_foreach_check_callback_func *func, st_update_callback_func *replace, st_data_t arg); #define st_foreach_with_replace rb_st_foreach_with_replace int rb_st_foreach(st_table *, st_foreach_callback_func *, st_data_t); #define st_foreach rb_st_foreach int rb_st_foreach_check(st_table *, st_foreach_check_callback_func *, st_data_t, st_data_t); #define st_foreach_check rb_st_foreach_check st_index_t rb_st_keys(st_table *table, st_data_t *keys, st_index_t size); #define st_keys rb_st_keys st_index_t rb_st_keys_check(st_table *table, st_data_t *keys, st_index_t size, st_data_t never); #define st_keys_check rb_st_keys_check st_index_t rb_st_values(st_table *table, st_data_t *values, st_index_t size); #define st_values rb_st_values st_index_t rb_st_values_check(st_table *table, st_data_t *values, st_index_t size, st_data_t never); #define st_values_check rb_st_values_check void rb_st_add_direct(st_table *, st_data_t, st_data_t); #define st_add_direct rb_st_add_direct void rb_st_free_table(st_table *); #define st_free_table rb_st_free_table void rb_st_cleanup_safe(st_table *, st_data_t); #define st_cleanup_safe rb_st_cleanup_safe void rb_st_clear(st_table *); #define st_clear rb_st_clear st_table *rb_st_copy(st_table *); #define st_copy rb_st_copy CONSTFUNC(int rb_st_numcmp(st_data_t, st_data_t)); #define st_numcmp rb_st_numcmp CONSTFUNC(st_index_t rb_st_numhash(st_data_t)); #define st_numhash rb_st_numhash PUREFUNC(int rb_st_locale_insensitive_strcasecmp(const char *s1, const char *s2)); #define st_locale_insensitive_strcasecmp rb_st_locale_insensitive_strcasecmp PUREFUNC(int rb_st_locale_insensitive_strncasecmp(const char *s1, const char *s2, size_t n)); #define st_locale_insensitive_strncasecmp rb_st_locale_insensitive_strncasecmp #define st_strcasecmp rb_st_locale_insensitive_strcasecmp #define st_strncasecmp rb_st_locale_insensitive_strncasecmp PUREFUNC(size_t rb_st_memsize(const st_table *)); #define st_memsize rb_st_memsize PUREFUNC(st_index_t rb_st_hash(const void *ptr, size_t len, st_index_t h)); #define st_hash rb_st_hash CONSTFUNC(st_index_t rb_st_hash_uint32(st_index_t h, uint32_t i)); #define st_hash_uint32 rb_st_hash_uint32 CONSTFUNC(st_index_t rb_st_hash_uint(st_index_t h, st_index_t i)); #define st_hash_uint rb_st_hash_uint CONSTFUNC(st_index_t rb_st_hash_end(st_index_t h)); #define st_hash_end rb_st_hash_end CONSTFUNC(st_index_t rb_st_hash_start(st_index_t h)); #define st_hash_start(h) ((st_index_t)(h)) void rb_hash_bulk_insert_into_st_table(long, const VALUE *, VALUE); RUBY_SYMBOL_EXPORT_END #if defined(__cplusplus) #if 0 { /* satisfy cc-mode */ #endif } /* extern "C" { */ #endif #endif /* RUBY_ST_H */ PK!dJJdl.hnu[#ifndef RUBY_DL_H #define RUBY_DL_H #include #if !defined(FUNC_CDECL) # define FUNC_CDECL(x) x #endif #if defined(HAVE_DLFCN_H) # include # /* some stranger systems may not define all of these */ #ifndef RTLD_LAZY #define RTLD_LAZY 0 #endif #ifndef RTLD_GLOBAL #define RTLD_GLOBAL 0 #endif #ifndef RTLD_NOW #define RTLD_NOW 0 #endif #else # if defined(_WIN32) # include # define dlopen(name,flag) ((void*)LoadLibrary(name)) # define dlerror() strerror(rb_w32_map_errno(GetLastError())) # define dlsym(handle,name) ((void*)GetProcAddress((handle),(name))) # define RTLD_LAZY -1 # define RTLD_NOW -1 # define RTLD_GLOBAL -1 # endif #endif #define MAX_CALLBACK 5 #define DLSTACK_TYPE SIGNED_VALUE #define DLSTACK_SIZE (20) #define DLSTACK_PROTO \ DLSTACK_TYPE,DLSTACK_TYPE,DLSTACK_TYPE,DLSTACK_TYPE,DLSTACK_TYPE,\ DLSTACK_TYPE,DLSTACK_TYPE,DLSTACK_TYPE,DLSTACK_TYPE,DLSTACK_TYPE,\ DLSTACK_TYPE,DLSTACK_TYPE,DLSTACK_TYPE,DLSTACK_TYPE,DLSTACK_TYPE,\ DLSTACK_TYPE,DLSTACK_TYPE,DLSTACK_TYPE,DLSTACK_TYPE,DLSTACK_TYPE #define DLSTACK_ARGS(stack) \ (stack)[0],(stack)[1],(stack)[2],(stack)[3],(stack)[4],\ (stack)[5],(stack)[6],(stack)[7],(stack)[8],(stack)[9],\ (stack)[10],(stack)[11],(stack)[12],(stack)[13],(stack)[14],\ (stack)[15],(stack)[16],(stack)[17],(stack)[18],(stack)[19] #define DLSTACK_PROTO0_ void #define DLSTACK_PROTO1_ DLSTACK_TYPE #define DLSTACK_PROTO2_ DLSTACK_PROTO1_, DLSTACK_TYPE #define DLSTACK_PROTO3_ DLSTACK_PROTO2_, DLSTACK_TYPE #define DLSTACK_PROTO4_ DLSTACK_PROTO3_, DLSTACK_TYPE #define DLSTACK_PROTO4_ DLSTACK_PROTO3_, DLSTACK_TYPE #define DLSTACK_PROTO5_ DLSTACK_PROTO4_, DLSTACK_TYPE #define DLSTACK_PROTO6_ DLSTACK_PROTO5_, DLSTACK_TYPE #define DLSTACK_PROTO7_ DLSTACK_PROTO6_, DLSTACK_TYPE #define DLSTACK_PROTO8_ DLSTACK_PROTO7_, DLSTACK_TYPE #define DLSTACK_PROTO9_ DLSTACK_PROTO8_, DLSTACK_TYPE #define DLSTACK_PROTO10_ DLSTACK_PROTO9_, DLSTACK_TYPE #define DLSTACK_PROTO11_ DLSTACK_PROTO10_, DLSTACK_TYPE #define DLSTACK_PROTO12_ DLSTACK_PROTO11_, DLSTACK_TYPE #define DLSTACK_PROTO13_ DLSTACK_PROTO12_, DLSTACK_TYPE #define DLSTACK_PROTO14_ DLSTACK_PROTO13_, DLSTACK_TYPE #define DLSTACK_PROTO14_ DLSTACK_PROTO13_, DLSTACK_TYPE #define DLSTACK_PROTO15_ DLSTACK_PROTO14_, DLSTACK_TYPE #define DLSTACK_PROTO16_ DLSTACK_PROTO15_, DLSTACK_TYPE #define DLSTACK_PROTO17_ DLSTACK_PROTO16_, DLSTACK_TYPE #define DLSTACK_PROTO18_ DLSTACK_PROTO17_, DLSTACK_TYPE #define DLSTACK_PROTO19_ DLSTACK_PROTO18_, DLSTACK_TYPE #define DLSTACK_PROTO20_ DLSTACK_PROTO19_, DLSTACK_TYPE /* * Add ",..." as the last argument. * This is required for variable argument functions such * as fprintf() on x86_64-linux. * * http://refspecs.linuxfoundation.org/elf/x86_64-abi-0.95.pdf * page 19: * * For calls that may call functions that use varargs or stdargs * (prototype-less calls or calls to functions containing ellipsis * (...) in the declaration) %al is used as hidden argument to * specify the number of SSE registers used. */ #define DLSTACK_PROTO0 void #define DLSTACK_PROTO1 DLSTACK_PROTO1_, ... #define DLSTACK_PROTO2 DLSTACK_PROTO2_, ... #define DLSTACK_PROTO3 DLSTACK_PROTO3_, ... #define DLSTACK_PROTO4 DLSTACK_PROTO4_, ... #define DLSTACK_PROTO4 DLSTACK_PROTO4_, ... #define DLSTACK_PROTO5 DLSTACK_PROTO5_, ... #define DLSTACK_PROTO6 DLSTACK_PROTO6_, ... #define DLSTACK_PROTO7 DLSTACK_PROTO7_, ... #define DLSTACK_PROTO8 DLSTACK_PROTO8_, ... #define DLSTACK_PROTO9 DLSTACK_PROTO9_, ... #define DLSTACK_PROTO10 DLSTACK_PROTO10_, ... #define DLSTACK_PROTO11 DLSTACK_PROTO11_, ... #define DLSTACK_PROTO12 DLSTACK_PROTO12_, ... #define DLSTACK_PROTO13 DLSTACK_PROTO13_, ... #define DLSTACK_PROTO14 DLSTACK_PROTO14_, ... #define DLSTACK_PROTO14 DLSTACK_PROTO14_, ... #define DLSTACK_PROTO15 DLSTACK_PROTO15_, ... #define DLSTACK_PROTO16 DLSTACK_PROTO16_, ... #define DLSTACK_PROTO17 DLSTACK_PROTO17_, ... #define DLSTACK_PROTO18 DLSTACK_PROTO18_, ... #define DLSTACK_PROTO19 DLSTACK_PROTO19_, ... #define DLSTACK_PROTO20 DLSTACK_PROTO20_, ... #define DLSTACK_ARGS0(stack) #define DLSTACK_ARGS1(stack) (stack)[0] #define DLSTACK_ARGS2(stack) DLSTACK_ARGS1(stack), (stack)[1] #define DLSTACK_ARGS3(stack) DLSTACK_ARGS2(stack), (stack)[2] #define DLSTACK_ARGS4(stack) DLSTACK_ARGS3(stack), (stack)[3] #define DLSTACK_ARGS5(stack) DLSTACK_ARGS4(stack), (stack)[4] #define DLSTACK_ARGS6(stack) DLSTACK_ARGS5(stack), (stack)[5] #define DLSTACK_ARGS7(stack) DLSTACK_ARGS6(stack), (stack)[6] #define DLSTACK_ARGS8(stack) DLSTACK_ARGS7(stack), (stack)[7] #define DLSTACK_ARGS9(stack) DLSTACK_ARGS8(stack), (stack)[8] #define DLSTACK_ARGS10(stack) DLSTACK_ARGS9(stack), (stack)[9] #define DLSTACK_ARGS11(stack) DLSTACK_ARGS10(stack), (stack)[10] #define DLSTACK_ARGS12(stack) DLSTACK_ARGS11(stack), (stack)[11] #define DLSTACK_ARGS13(stack) DLSTACK_ARGS12(stack), (stack)[12] #define DLSTACK_ARGS14(stack) DLSTACK_ARGS13(stack), (stack)[13] #define DLSTACK_ARGS15(stack) DLSTACK_ARGS14(stack), (stack)[14] #define DLSTACK_ARGS16(stack) DLSTACK_ARGS15(stack), (stack)[15] #define DLSTACK_ARGS17(stack) DLSTACK_ARGS16(stack), (stack)[16] #define DLSTACK_ARGS18(stack) DLSTACK_ARGS17(stack), (stack)[17] #define DLSTACK_ARGS19(stack) DLSTACK_ARGS18(stack), (stack)[18] #define DLSTACK_ARGS20(stack) DLSTACK_ARGS19(stack), (stack)[19] extern VALUE rb_mDL; extern VALUE rb_cDLHandle; extern VALUE rb_cDLSymbol; extern VALUE rb_eDLError; extern VALUE rb_eDLTypeError; typedef struct { char c; void *x; } s_voidp; typedef struct { char c; short x; } s_short; typedef struct { char c; int x; } s_int; typedef struct { char c; long x; } s_long; typedef struct { char c; float x; } s_float; typedef struct { char c; double x; } s_double; #if HAVE_LONG_LONG typedef struct { char c; LONG_LONG x; } s_long_long; #endif #define ALIGN_VOIDP (sizeof(s_voidp) - sizeof(void *)) #define ALIGN_SHORT (sizeof(s_short) - sizeof(short)) #define ALIGN_CHAR (1) #define ALIGN_INT (sizeof(s_int) - sizeof(int)) #define ALIGN_LONG (sizeof(s_long) - sizeof(long)) #if HAVE_LONG_LONG #define ALIGN_LONG_LONG (sizeof(s_long_long) - sizeof(LONG_LONG)) #endif #define ALIGN_FLOAT (sizeof(s_float) - sizeof(float)) #define ALIGN_DOUBLE (sizeof(s_double) - sizeof(double)) #define DLALIGN(ptr,offset,align) {\ while( (((unsigned long)((char *)(ptr) + (offset))) % (align)) != 0 ) (offset)++;\ } #define DLTYPE_VOID 0 #define DLTYPE_VOIDP 1 #define DLTYPE_CHAR 2 #define DLTYPE_SHORT 3 #define DLTYPE_INT 4 #define DLTYPE_LONG 5 #if HAVE_LONG_LONG #define DLTYPE_LONG_LONG 6 #endif #define DLTYPE_FLOAT 7 #define DLTYPE_DOUBLE 8 #define MAX_DLTYPE 9 #if SIZEOF_VOIDP == SIZEOF_LONG # define PTR2NUM(x) (ULONG2NUM((unsigned long)(x))) # define NUM2PTR(x) ((void*)(NUM2ULONG(x))) #else /* # error --->> Ruby/DL2 requires sizeof(void*) == sizeof(long) to be compiled. <<--- */ # define PTR2NUM(x) (ULL2NUM((unsigned long long)(x))) # define NUM2PTR(x) ((void*)(NUM2ULL(x))) #endif #define BOOL2INT(x) (((x) == Qtrue)?1:0) #define INT2BOOL(x) ((x)?Qtrue:Qfalse) typedef void (*freefunc_t)(void*); struct dl_handle { void *ptr; int open; int enable_close; }; struct cfunc_data { void *ptr; char *name; int type; ID calltype; VALUE wrap; }; extern ID rbdl_id_cdecl; extern ID rbdl_id_stdcall; #define CFUNC_CDECL (rbdl_id_cdecl) #define CFUNC_STDCALL (rbdl_id_stdcall) struct ptr_data { void *ptr; long size; freefunc_t free; VALUE wrap[2]; }; #define RDL_HANDLE(obj) ((struct dl_handle *)(DATA_PTR(obj))) #define RCFUNC_DATA(obj) ((struct cfunc_data *)(DATA_PTR(obj))) #define RPTR_DATA(obj) ((struct ptr_data *)(DATA_PTR(obj))) VALUE rb_dlcfunc_new(void (*func)(), int dltype, const char * name, ID calltype); int rb_dlcfunc_kind_p(VALUE func); VALUE rb_dlptr_new(void *ptr, long size, freefunc_t func); VALUE rb_dlptr_new2(VALUE klass, void *ptr, long size, freefunc_t func); VALUE rb_dlptr_malloc(long size, freefunc_t func); #endif PK!ndigest.hnu[/************************************************ digest.h - header file for ruby digest modules $Author$ created at: Fri May 25 08:54:56 JST 2001 Copyright (C) 2001-2006 Akinori MUSHA $RoughId: digest.h,v 1.3 2001/07/13 15:38:27 knu Exp $ $Id$ ************************************************/ #include "ruby.h" #define RUBY_DIGEST_API_VERSION 3 typedef int (*rb_digest_hash_init_func_t)(void *); typedef void (*rb_digest_hash_update_func_t)(void *, unsigned char *, size_t); typedef int (*rb_digest_hash_finish_func_t)(void *, unsigned char *); typedef struct { int api_version; size_t digest_len; size_t block_len; size_t ctx_size; rb_digest_hash_init_func_t init_func; rb_digest_hash_update_func_t update_func; rb_digest_hash_finish_func_t finish_func; } rb_digest_metadata_t; #define DEFINE_UPDATE_FUNC_FOR_UINT(name) \ void \ rb_digest_##name##_update(void *ctx, unsigned char *ptr, size_t size) \ { \ const unsigned int stride = 16384; \ \ for (; size > stride; size -= stride, ptr += stride) { \ name##_Update(ctx, ptr, stride); \ } \ if (size > 0) name##_Update(ctx, ptr, size); \ } #define DEFINE_FINISH_FUNC_FROM_FINAL(name) \ int \ rb_digest_##name##_finish(void *ctx, unsigned char *ptr) \ { \ return name##_Final(ptr, ctx); \ } static inline VALUE rb_digest_namespace(void) { rb_require("digest"); return rb_path2class("Digest"); } static inline ID rb_id_metadata(void) { return rb_intern_const("metadata"); } static inline VALUE rb_digest_make_metadata(const rb_digest_metadata_t *meta) { #undef RUBY_UNTYPED_DATA_WARNING #define RUBY_UNTYPED_DATA_WARNING 0 return rb_obj_freeze(Data_Wrap_Struct(0, 0, 0, (void *)meta)); } PK!/ruby.hnu[#ifndef RUBY_RUBY_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_RUBY_H 1 /** * @file * @author $Author$ * @date Thu Jun 10 14:26:32 JST 1993 * @copyright Copyright (C) 1993-2008 Yukihiro Matsumoto * @copyright Copyright (C) 2000 Network Applied Communication Laboratory, Inc. * @copyright Copyright (C) 2000 Information-technology Promotion Agency, Japan * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. */ #include "ruby/internal/config.h" #ifdef HAVE_INTRINSICS_H # include #endif #include #include "defines.h" #include "ruby/internal/anyargs.h" #include "ruby/internal/arithmetic.h" #include "ruby/internal/core.h" #include "ruby/internal/ctype.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/error.h" #include "ruby/internal/eval.h" #include "ruby/internal/event.h" #include "ruby/internal/fl_type.h" #include "ruby/internal/gc.h" #include "ruby/internal/glob.h" #include "ruby/internal/globals.h" #include "ruby/internal/has/warning.h" #include "ruby/internal/interpreter.h" #include "ruby/internal/iterator.h" #include "ruby/internal/memory.h" #include "ruby/internal/method.h" #include "ruby/internal/module.h" #include "ruby/internal/newobj.h" #include "ruby/internal/rgengc.h" #include "ruby/internal/scan_args.h" #include "ruby/internal/special_consts.h" #include "ruby/internal/symbol.h" #include "ruby/internal/value.h" #include "ruby/internal/value_type.h" #include "ruby/internal/variable.h" #include "ruby/assert.h" #include "ruby/backward/2/assume.h" #include "ruby/backward/2/inttypes.h" #include "ruby/backward/2/limits.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* Module#methods, #singleton_methods and so on return Symbols */ #define USE_SYMBOL_AS_METHOD_NAME 1 VALUE rb_get_path(VALUE); #define FilePathValue(v) (RB_GC_GUARD(v) = rb_get_path(v)) VALUE rb_get_path_no_checksafe(VALUE); #define FilePathStringValue(v) ((v) = rb_get_path(v)) #if defined(HAVE_BUILTIN___BUILTIN_CONSTANT_P) && defined(HAVE_STMT_AND_DECL_IN_EXPR) # define rb_varargs_argc_check_runtime(argc, vargc) \ (((argc) <= (vargc)) ? (argc) : \ (rb_fatal("argc(%d) exceeds actual arguments(%d)", \ argc, vargc), 0)) # define rb_varargs_argc_valid_p(argc, vargc) \ ((argc) == 0 ? (vargc) <= 1 : /* [ruby-core:85266] [Bug #14425] */ \ (argc) == (vargc)) # if defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P) # if HAVE_ATTRIBUTE_ERRORFUNC ERRORFUNC((" argument length doesn't match"), int rb_varargs_bad_length(int,int)); # else # define rb_varargs_bad_length(argc, vargc) \ ((argc)/rb_varargs_argc_valid_p(argc, vargc)) # endif # define rb_varargs_argc_check(argc, vargc) \ __builtin_choose_expr(__builtin_constant_p(argc), \ (rb_varargs_argc_valid_p(argc, vargc) ? (argc) : \ rb_varargs_bad_length(argc, vargc)), \ rb_varargs_argc_check_runtime(argc, vargc)) # else # define rb_varargs_argc_check(argc, vargc) \ rb_varargs_argc_check_runtime(argc, vargc) # endif #endif const char *rb_class2name(VALUE); const char *rb_obj_classname(VALUE); void rb_p(VALUE); VALUE rb_equal(VALUE,VALUE); VALUE rb_require(const char*); #include "ruby/intern.h" #if defined(EXTLIB) && defined(USE_DLN_A_OUT) /* hook for external modules */ static char *dln_libs_to_be_linked[] = { EXTLIB, 0 }; #endif #define RUBY_VM 1 /* YARV */ #define HAVE_NATIVETHREAD int ruby_native_thread_p(void); #define InitVM(ext) {void InitVM_##ext(void);InitVM_##ext();} PRINTF_ARGS(int ruby_snprintf(char *str, size_t n, char const *fmt, ...), 3, 4); int ruby_vsnprintf(char *str, size_t n, char const *fmt, va_list ap); #if RBIMPL_HAS_WARNING("-Wgnu-zero-variadic-macro-arguments") # /* Skip it; clang -pedantic doesn't like the following */ #elif defined(__GNUC__) && defined(HAVE_VA_ARGS_MACRO) && defined(__OPTIMIZE__) # define rb_yield_values(argc, ...) \ __extension__({ \ const int rb_yield_values_argc = (argc); \ const VALUE rb_yield_values_args[] = {__VA_ARGS__}; \ const int rb_yield_values_nargs = \ (int)(sizeof(rb_yield_values_args) / sizeof(VALUE)); \ rb_yield_values2( \ rb_varargs_argc_check(rb_yield_values_argc, rb_yield_values_nargs), \ rb_yield_values_nargs ? rb_yield_values_args : NULL); \ }) # define rb_funcall(recv, mid, argc, ...) \ __extension__({ \ const int rb_funcall_argc = (argc); \ const VALUE rb_funcall_args[] = {__VA_ARGS__}; \ const int rb_funcall_nargs = \ (int)(sizeof(rb_funcall_args) / sizeof(VALUE)); \ rb_funcallv(recv, mid, \ rb_varargs_argc_check(rb_funcall_argc, rb_funcall_nargs), \ rb_funcall_nargs ? rb_funcall_args : NULL); \ }) #endif #ifndef RUBY_DONT_SUBST #include "ruby/subst.h" #endif #if !defined RUBY_EXPORT && !defined RUBY_NO_OLD_COMPATIBILITY # include "ruby/backward.h" #endif RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_RUBY_H */ PK!.h)regex.hnu[#ifndef ONIGURUMA_REGEX_H /*-*-C++-*-vi:se ft=cpp:*/ #define ONIGURUMA_REGEX_H 1 /** * @file * @author $Author$ * @copyright Copyright (C) 1993-2007 Yukihiro Matsumoto * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. */ #if defined(__cplusplus) extern "C" { #if 0 } /* satisfy cc-mode */ #endif #endif #ifdef RUBY #include "ruby/oniguruma.h" #else #include "oniguruma.h" #endif RUBY_SYMBOL_EXPORT_BEGIN #ifndef ONIG_RUBY_M17N ONIG_EXTERN OnigEncoding OnigEncDefaultCharEncoding; #define mbclen(p,e,enc) rb_enc_mbclen((p),(e),(enc)) #endif /* ifndef ONIG_RUBY_M17N */ RUBY_SYMBOL_EXPORT_END #if defined(__cplusplus) #if 0 { /* satisfy cc-mode */ #endif } /* extern "C" { */ #endif #endif /* ONIGURUMA_REGEX_H */ PK!N11 missing.hnu[#ifndef RUBY_MISSING_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_MISSING_H 1 /** * @file * @author $Author$ * @date Sat May 11 23:46:03 JST 2002 * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @brief Prototype for *.c in ./missing, and for missing timeval struct. */ #include "ruby/internal/config.h" #ifdef STDC_HEADERS # include #endif #if defined(__cplusplus) # include #else # include /* for INFINITY and NAN */ #endif #ifdef RUBY_ALTERNATIVE_MALLOC_HEADER # include RUBY_ALTERNATIVE_MALLOC_HEADER #endif #if defined(HAVE_TIME_H) # include #endif #if defined(HAVE_SYS_TIME_H) # include #endif #ifdef HAVE_IEEEFP_H # include #endif #include "ruby/internal/dllexport.h" #ifndef M_PI # define M_PI 3.14159265358979323846 #endif #ifndef M_PI_2 # define M_PI_2 (M_PI/2) #endif #if !defined(HAVE_STRUCT_TIMEVAL) struct timeval { time_t tv_sec; /* seconds */ long tv_usec; /* microseconds */ }; #endif /* HAVE_STRUCT_TIMEVAL */ #if !defined(HAVE_STRUCT_TIMESPEC) /* :BEWARE: @shyouhei warns that IT IS A WRONG IDEA to define our own version * of struct timespec here. `clock_gettime` is a system call, and your kernel * could expect something other than just `long` (results stack smashing if * that happens). See also https://ewontfix.com/19/ */ struct timespec { time_t tv_sec; /* seconds */ long tv_nsec; /* nanoseconds */ }; #endif #if !defined(HAVE_STRUCT_TIMEZONE) struct timezone { int tz_minuteswest; int tz_dsttime; }; #endif RBIMPL_SYMBOL_EXPORT_BEGIN() #ifndef HAVE_ACOSH RUBY_EXTERN double acosh(double); RUBY_EXTERN double asinh(double); RUBY_EXTERN double atanh(double); #endif #ifndef HAVE_CRYPT RUBY_EXTERN char *crypt(const char *, const char *); #endif #ifndef HAVE_DUP2 RUBY_EXTERN int dup2(int, int); #endif #ifndef HAVE_EACCESS RUBY_EXTERN int eaccess(const char*, int); #endif #ifndef HAVE_ROUND RUBY_EXTERN double round(double); /* numeric.c */ #endif #ifndef HAVE_FINITE RUBY_EXTERN int finite(double); #endif #ifndef HAVE_FLOCK RUBY_EXTERN int flock(int, int); #endif /* #ifndef HAVE_FREXP RUBY_EXTERN double frexp(double, int *); #endif */ #ifndef HAVE_HYPOT RUBY_EXTERN double hypot(double, double); #endif #ifndef HAVE_ERF RUBY_EXTERN double erf(double); RUBY_EXTERN double erfc(double); #endif #ifndef HAVE_TGAMMA RUBY_EXTERN double tgamma(double); #endif #ifndef HAVE_LGAMMA_R RUBY_EXTERN double lgamma_r(double, int *); #endif #ifndef HAVE_CBRT RUBY_EXTERN double cbrt(double); #endif #if !defined(INFINITY) || !defined(NAN) union bytesequence4_or_float { unsigned char bytesequence[4]; float float_value; }; #endif #ifndef INFINITY /** @internal */ RUBY_EXTERN const union bytesequence4_or_float rb_infinity; # define INFINITY (rb_infinity.float_value) # define USE_RB_INFINITY 1 #endif #ifndef NAN /** @internal */ RUBY_EXTERN const union bytesequence4_or_float rb_nan; # define NAN (rb_nan.float_value) # define USE_RB_NAN 1 #endif #ifndef HUGE_VAL # define HUGE_VAL ((double)INFINITY) #endif #if defined(isinf) # /* Take that. */ #elif defined(HAVE_ISINF) # /* Take that. */ #elif defined(HAVE_FINITE) && defined(HAVE_ISNAN) # define isinf(x) (!finite(x) && !isnan(x)) #elif defined(__cplusplus) && __cplusplus >= 201103L # // must include constexpr bool isinf(double); #else RUBY_EXTERN int isinf(double); #endif #if defined(isnan) # /* Take that. */ #elif defined(HAVE_ISNAN) # /* Take that. */ #elif defined(__cplusplus) && __cplusplus >= 201103L # // must include constexpr bool isnan(double); #else RUBY_EXTERN int isnan(double); #endif #if defined(isfinite) # /* Take that. */ #elif defined(HAVE_ISFINITE) # /* Take that. */ #else # define HAVE_ISFINITE 1 # define isfinite(x) finite(x) #endif #ifndef HAVE_NAN RUBY_EXTERN double nan(const char *); #endif #ifndef HAVE_NEXTAFTER RUBY_EXTERN double nextafter(double x, double y); #endif /* #ifndef HAVE_MEMCMP RUBY_EXTERN int memcmp(const void *, const void *, size_t); #endif */ #ifndef HAVE_MEMMOVE RUBY_EXTERN void *memmove(void *, const void *, size_t); #endif /* #ifndef HAVE_MODF RUBY_EXTERN double modf(double, double *); #endif */ #ifndef HAVE_STRCHR RUBY_EXTERN char *strchr(const char *, int); RUBY_EXTERN char *strrchr(const char *, int); #endif #ifndef HAVE_STRERROR RUBY_EXTERN char *strerror(int); #endif #ifndef HAVE_STRSTR RUBY_EXTERN char *strstr(const char *, const char *); #endif #ifndef HAVE_STRLCPY RUBY_EXTERN size_t strlcpy(char *, const char*, size_t); #endif #ifndef HAVE_STRLCAT RUBY_EXTERN size_t strlcat(char *, const char*, size_t); #endif #ifndef HAVE_SIGNBIT RUBY_EXTERN int signbit(double x); #endif #ifndef HAVE_FFS RUBY_EXTERN int ffs(int); #endif #ifdef BROKEN_CLOSE # include # include RUBY_EXTERN int ruby_getpeername(int, struct sockaddr *, socklen_t *); RUBY_EXTERN int ruby_getsockname(int, struct sockaddr *, socklen_t *); RUBY_EXTERN int ruby_shutdown(int, int); RUBY_EXTERN int ruby_close(int); #endif #ifndef HAVE_SETPROCTITLE RUBY_EXTERN void setproctitle(const char *fmt, ...); #endif #ifdef HAVE_EXPLICIT_BZERO # /* Take that. */ #elif defined(SecureZeroMemory) # define explicit_bzero(b, len) SecureZeroMemory(b, len) #else RUBY_EXTERN void explicit_bzero(void *b, size_t len); #endif RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_MISSING_H */ PK!X;; version.hnu[#ifndef RUBY_VERSION_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_VERSION_H 1 /** * @file * @author $Author$ * @date Wed May 13 12:56:56 JST 2009 * @copyright Copyright (C) 1993-2009 Yukihiro Matsumoto * @copyright Copyright (C) 2000 Network Applied Communication Laboratory, Inc. * @copyright Copyright (C) 2000 Information-technology Promotion Agency, Japan * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * * This file contains only * - never-changeable information, and * - interfaces accessible from extension libraries. * * Never try to check RUBY_VERSION_CODE etc in extension libraries, * check the features with mkmf.rb instead. */ /* The origin. */ #define RUBY_AUTHOR "Yukihiro Matsumoto" #define RUBY_BIRTH_YEAR 1993 #define RUBY_BIRTH_MONTH 2 #define RUBY_BIRTH_DAY 24 /* API version */ #define RUBY_API_VERSION_MAJOR 3 #define RUBY_API_VERSION_MINOR 0 #define RUBY_API_VERSION_TEENY 0 #define RUBY_API_VERSION_CODE (RUBY_API_VERSION_MAJOR*10000+RUBY_API_VERSION_MINOR*100+RUBY_API_VERSION_TEENY) #ifdef RUBY_EXTERN /* Internal note: this file could be included from verconf.mk _before_ * generating config.h, on Windows. The #ifdef above is to trick such * situation. */ RBIMPL_SYMBOL_EXPORT_BEGIN() /* * Interfaces from extension libraries. * * Before using these infos, think thrice whether they are really * necessary or not, and if the answer was yes, think twice a week * later again. */ RUBY_EXTERN const int ruby_api_version[3]; RUBY_EXTERN const char ruby_version[]; RUBY_EXTERN const char ruby_release_date[]; RUBY_EXTERN const char ruby_platform[]; RUBY_EXTERN const int ruby_patchlevel; RUBY_EXTERN const char ruby_description[]; RUBY_EXTERN const char ruby_copyright[]; RUBY_EXTERN const char ruby_engine[]; RBIMPL_SYMBOL_EXPORT_END() #endif #endif PK!8O8Oio-console-0.4.6/io/console.sonuȯELF>`@8H@8 @88 ;; ; h ;; ; 888$$777 Std777 Ptd(1(1(1QtdRtd;; ;  GNUS ׫=rҖ T?H!@?ACBE|qX/DofJ,o 2u$^7 a}U LvZ{>r%-BY, F"k@ H@ @  -Tp /__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizerb_funcallvrb_default_rsrb_io_writerb_cIOrb_cFilerb_const_definedrb_cloexec_openrb_update_max_fdrb_class_new_instancerb_io_taint_checkrb_io_check_closedrb_str_new_staticrb_obj_freezerb_const_setrb_const_getrb_const_removerb_id2symrb_check_typerb_io_closerb_check_idrb_error_arity__stack_chk_fail__errno_locationtcsetattrtcgetattrrb_sys_failtcflushcfmakerawrb_string_value_cstrrb_check_safe_objrb_intern2rb_io_get_write_iorb_ensurerb_stdinrb_stderrrb_check_hash_typerb_extract_keywordsrb_hash_arefrb_fix2intrb_funcallv_publicrb_num2intioctlrb_assoc_newrb_Arrayrb_num2uintrb_eArgErrorrb_raiserb_protectrb_syserr_failrb_jump_tagrb_io_getsrb_yieldInitVM_consolerb_define_methodrb_f_notimplementrb_define_singleton_methodrb_define_module_underInit_consolerb_internlibruby.so.2.5libc.so.6_edata__bss_start_endGLIBC_2.4GLIBC_2.2.5ii ui ; ; ; ; ? ?  ? ? ? !? #? +? 1? 7? 8? 9? :? >> > > >  > (> 0> 8>  @>  H>  P>  X> `> h> p> x> > > > > > > > > > > > >  > "> $> %> &? '? (? )? * ? ,(? -0? .8? /@? 0H? 2P? 3X? B`? 4h? 5p? 6x? :? ;? <? =HH+ HtH5) %) hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2%& D%& D%& D%& D%& D%& D%& D%& D%& D%}& D%u& D%m& D%e& D%]& D%U& D%M& D%E& D%=& D%5& D%-& D%%& D%& D%& D% & D%& D%% D%% D%% D%% D%% D%% D%% D%% D%% D%% D%% D%% D%% D%% D%% D%% D%}% D%u% D%m% D%e% D%]% D%U% D%M% D%E% D%=% D%5% DH=% H% H9tH&% Ht H=i% H5b% H)HHH?HHtH% HtfD=%% u+UH= % Ht H= )d$ ]wH"O {H g HH5$ H׉vfDH5$ 11\ff.H$ H0ff.fAWAVAUAATUSH8dH%(HD$(1<IHoE1H# H9u H# HH5/$ HM1ҾH=KHcHl-HHt$Hl$HD$THHLxLH=lHAO HHIGH5# MHL$(dH3 %(HLH8[]A\A]A^A_f.H5A# HHŨuHubH5## HMH=# AI9nfDL&L uHEHtxtM.H=" RI9u-Au'HH5{" HfDIH|$HD$NHt)AIHLDHHH! փ1}USHH K8u&HھwuH[]H1[]SHPdH%(HD$H1rHXHv{H u)D$ HHHЃHT$HdH3%(u HP[1G2fAUIATUHSHXdH%(HD$H1IHXH[LuPD$ Iu:D$ Lt.HT$HdH3%(Hu"HX[]A\A]xD$ 1ff.ATUHSHPdH%(HD$H1IIHXHM[Lu@LH"L$ {H $,tHT$HdH3%(HuHP[]A\1UHSHHXH{1u HH[]1UHSHH c HtExCExCH[]SHdH%(HD$1HHt$HHH$cH<$H4$HnHD$dH3%(uH[H5 SHHtH11[H=H11H[H AUATAUSHHIHHH9tHAu HLHHHH=K Ht0HH[]A\A]>fDH H9uH H(H[]A\A]ú1@AUIATIUSHHXdH%(HD$H11uDHC0oLoKoS HD$0C8H)$H)L$)T$ D$8AHމHT$HdH3%(u HX[]A\A]zf.AUATUSHdH%(HD$1H$~`HcH|Hu2u?D1HL$dH3 %(FH[]A\A]H0H$Hu11kt@ILH<$IHHyH= mLHH= HSLHHEI1HtH߃tMEHILL*H$;HǨt$OEH@fڅ HuAL$$ff.@AUATUHSHhdH%(HD$X1HT$%HIzHXH~DcH\$HD u8LHHD`tHL$XdH3 %(HuHh[]A\A]17"fUHSHHXHH{PHtHXH{u HH[]1fDUHSHHXHH{PHtHXH{H5 $Hx HH[]1nff.SHdH%(HD$1"HXH&H{PHtHXH {1HTzu.t$<$Ht6H|?HL$dH3 %(u H[1ff.ATUHSHXHH{PDcHuDuJH[]A\fDSHXHW[tA9t1Dupt15DUSHwVHuHHHH5 11HHHt HHH` HH0HH[]ú1/ff.@AWAVAUATIUHSHdH%(HD$1cHXHgL/H HHLxLpAAH{PHtHXH[1H$ItLf$1ItLfD$1ItLfD$1ItLfD$H1T%unHL$dH3 %(HuVH[]A\A]A^A_HPHtBHuH@ L8LpLhL`"H  H5H8131Kqd c]A5;RFqqV~JrQ;M,WXK;޺Ml%?&CZC9Hi_N|`B^BR3,_N7͔t^MPewzK5хFO6WbdȪ? 4;!%{XvL(SF뮎pĵȩy:,ۆ~e jdee?(J,auVcc?cȓk'C1U̡ r)m;;cJ%y *G$fD:Ө@v6uelW# K>Y{< `.&- ͞Y)%9|D5 $#ɕIsd NFcrFY(݃Jv&%n؛1JaA")B  >qU PZ,L"XN ɧD!aI< B]5~,A*DUG.1ՓC8 ߻n95.|d vA7\tàD^BwGCVdWVⶹ3Zf4I ~$m sxcTD2#V" eTtS(=kaWl(W,r"ixbZ6rpo2z !xEr@Bߵj ᡞ#㿎Nt=ptqն$y~wgYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``8( `08o EoP P 0T ^Bhc@n000w``}00 2(0(0(1(1H2H277 ; ;; ;; ;; ;= =@ @HH@`@HHBDBG"PK!"uPXXopenssl-2.1.2/openssl.sonuȯELF>@X@8 @`w`w ||%|%X3< %%888$$@w@w@w Std@w@w@w Ptd@@@QtdRtd||%|%X3p3GNUC1<##fB 0"$@@ (Q0Au  @ `BbH  P) #  @ @ !@D@@ H!D$` P"J$)@N)"DBX0!B @@@F@ H@  R`@@P @  !#$&'*,-/0467:>@ADIKOPQTUEKlIqη)BгZʮ9X{)tNsѦ+Jagg-(7WNiƵ/Q\1b8чɌAZ)&DtdQpKGV67߂טm3lјS6‡NqK ߝ+&)"5vw"`Pbyl I!IeRUFԿ1>텄 z^vvD!P=y2v*b^Gu$.Sqey]+n ժm !p I` qXoش7ͿHx)19ѭdj,;e-&ojbpIT g:ѫ<\#I P@|U s DcCE? |0Xv$.fS@|Y6.D[H .ZJn(40Jʻ|)*%T6- Iܛ{И$9\ hE c)A -I>/( ;072^< Bk00WDH=1 9x50&eG8 H"I2O6En%7@+%;= 03  p<.#y's+(Gc$Il+'C P.0F;+((q!#C(/V((u  8-88  ;s!L )D#5"FiA!),2BL?O)6-).+7n# kMAG 5>!$44?)75s44 p *IHC>/ Q3W C {CD@~6#*AwGM@ '"13*3*=`-5!@3P!2-9 MB<C/&  }n8H <04B1H8@% U1h2  [I&-S&.  G2+  ;G+< N$mB)/Vg9,iNNE0#$<F%*L:-=-6A#$Y ;E,k7\.E> +t , 98'W$5H556,;AD*, DM9%?q)N5?5;: '' BDF"'7J,.<m-:.99L4d6'a2! !%3&CT @6..%HV D #X0/ Q/+A3 C)g  u,q4T;  +Hf* )6;a$[C:&d&(%H  o$(|B 6C#@4  ,0Hx.6H>;} 8#5<g<0E/< #HB}4pa! G $v/(^D>L#@=eD0)>: ,Y U8`7@* B? 8* 7**AFTH-F>,Dx)/<#, x u =Tk5!'ED).I5`4 U<3 B<2=<-h,jCh  +r25a 0>c?aBg: +(@&*E7l!h 7X5ESBDI~G3?k 2=jF@+3-DV  &0X% `!K$&GD5DF/,?:F, 8%"A<'I(, YF$4B.$G4+kH _<0((C;-yD%4'21.s=,7=?x2%d3A ('S/4f6e6|&EF4(=e.t$I%H  "D!"6 '-? > 3=1b4mExAFD@?)/)B.)!!7H6;84G8E# > E8@T*>j/:3=8<E8F0]=Bc@K.;'*"1r(7  (  lCV5b;0?>&2>4V]3q>v!'$A*`(,iH)`)y<SD7 EMG2:4'&?9 #?W+C8 fO5v"I?$D%0#M  .)7?(%^ N 2 Ih%+" pW8 0v >(%%A `67%V z %" @ *% i@H%k D%P%k$%P" "L %S о:% \{7" @- pdw%9 P`+$ "_t@@%Bh%%*%% I8%%/%# p> <F  m_E%C iB`% 60%  ,6; `K:p%Aж%d'ȷ%]"x%3 @d$%  =j pi %c%  X%p1 {YAX%6 Z'%1%H m> jVsе%& Q@%U%%<%  ~9 $ q@% pj"G%%$  {Zȵ%"p%F%+8%%I%: }G(% P}6 }x9%" 0 -0%Hm  -ط%# ~Z>8% DG `fsdH%ض%%/%|  0b1% 0 r#h%'%*`%f%@%9 pjdP%6 PU!$ 0Xj  PZMP%1%)0%?% P,j (%9 , p)I%Y%/ _ R c"`%HD" @ < %%I%; j< 6%%0%> ijCx%x% j{ G%I `C  (% `B% Pj X% % %h . 06 ص% P9 PK$= P6!H%m =69 =9 `EP'% q[I%`%%Q z%EEp%y %/%%   % %%%yȶ% Ph>%)8%%# _ &%e/з%__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizedOSSLrb_str_newrb_yieldrb_string_value__stack_chk_failossl_get_errorsrb_ary_newERR_error_stringrb_str_new_cstrrb_ary_pushERR_get_errorFIPS_modeossl_protect_x509_ary2skossl_x509_ary2sk0rb_protectossl_x509_ary2skrb_jump_tagossl_x509_sk2aryOPENSSL_sk_numrb_ary_new_capaOPENSSL_sk_valueossl_x509_newstderrfwrite__fprintf_chkossl_x509crl_sk2aryossl_x509crl_newossl_x509name_sk2aryossl_x509name_newossl_str_newmemcpyrb_set_errinfoossl_buf2strCRYPTO_freeossl_bin2hex__assert_failossl_pem_passwd_cbrb_block_given_pPEM_def_callbackrb_warningossl_to_derrb_funcallvossl_to_der_if_possiblerb_respond_toossl_clear_errorERR_get_error_line_datarb_warnERR_clear_errorossl_raiserb_vsprintfERR_peek_last_errorrb_exc_new_strrb_exc_raiserb_str_new_staticERR_reason_error_stringrb_str_cat_cstrrb_str_catrb_check_typeOPENSSL_sk_new_nullrb_ary_entrycX509Certrb_obj_is_kind_ofDupX509CertPtrOPENSSL_sk_pushX509_freeOPENSSL_sk_pop_freeeOSSLErrorossl_pem_passwd_valueFIPS_mode_setInit_opensslOPENSSL_init_sslrb_define_modulemOSSLrb_global_variablerb_define_constOpenSSL_versionrb_define_module_functionrb_eStandardErrorrb_define_class_underrb_internInit_ossl_bnInit_ossl_cipherInit_ossl_configInit_ossl_digestInit_ossl_hmacInit_ossl_ns_spkiInit_ossl_pkcs12Init_ossl_pkcs7Init_ossl_pkeyInit_ossl_randInit_ossl_sslInit_ossl_x509Init_ossl_ocspInit_ossl_engineInit_ossl_asn1Init_ossl_kdfrb_eRuntimeErrorrb_raiserb_string_value_cstrOBJ_txt2objeASN1Errorrb_ivar_setrb_attr_getASN1_OBJECT_freerb_usascii_str_new_staticOBJ_obj2txtrb_str_resizerb_str_set_lenrb_out_of_intOBJ_txt2nidOBJ_nid2lnOBJ_nid2sncASN1EndOfContentrb_funcallv_publicrb_intern2cASN1SetcASN1SequencecASN1GeneralizedTimecASN1UTCTimecASN1ObjectIdcASN1NullcASN1BMPStringcASN1UniversalStringcASN1GeneralStringcASN1ISO64StringcASN1GraphicStringcASN1IA5StringcASN1VideotexStringcASN1T61StringcASN1PrintableStringcASN1NumericStringcASN1UTF8StringcASN1OctetStringcASN1BitStringcASN1EnumeratedcASN1IntegercASN1Booleanrb_block_callasn1time_to_time__isoc99_sscanfrb_cTimerb_eTypeErrorasn1integer_to_numASN1_INTEGER_to_BNossl_bn_newBN_freeASN1_ENUMERATED_to_BNOBJ_createrb_num2intrb_fix2intrb_hash_lookuprb_class_superclassrb_cFalseClassrb_cIntegerrb_cNilClassrb_cFloatrb_cTrueClassrb_cSymbolASN1_object_sizeASN1_put_objectASN1_put_eocrb_convert_typerb_str_appendrb_error_arityASN1_get_objectcASN1Datarb_obj_alloccASN1Constructiverb_int2bigd2i_ASN1_TIMEASN1_TIME_freed2i_ASN1_ENUMERATEDASN1_ENUMERATED_freed2i_ASN1_INTEGERASN1_INTEGER_freed2i_ASN1_NULLASN1_NULL_freed2i_ASN1_OBJECTOBJ_obj2nidd2i_ASN1_BIT_STRINGASN1_BIT_STRING_freeBIO_s_memBIO_newi2a_ASN1_OBJECTossl_membio2strrb_str_new_frozenossl_time_splitrb_Integerrb_num2longasn1str_to_strnum_to_asn1integerossl_bn_value_ptrBN_to_ASN1_INTEGERossl_asn1_get_asn1typeASN1_GENERALIZEDTIME_adjCRYPTO_mallocASN1_TYPE_setASN1_BIT_STRING_newASN1_BIT_STRING_setASN1_STRING_newASN1_STRING_setASN1_STRING_freeASN1_NULL_newASN1_UTCTIME_adji2d_ASN1_TYPEASN1_TYPE_freerb_str_drop_bytesrb_cArrayrb_id2symrb_define_module_undermASN1rb_ary_storerb_cObjectrb_attrrb_define_aliasrb_define_methodcASN1Primitiverb_undef_methodrb_mEnumerablerb_include_modulerb_define_singleton_methodrb_hash_newrb_gc_register_mark_objectrb_hash_asetossl_obj2bioBIO_new_mem_bufBIO_ctrlBIO_freeBN_clear_freerb_check_typeddataBN_num_bitsBN_bn2binrb_memhashrb_free_tmp_bufferrb_alloc_tmp_buffereBNErrorrb_obj_classrb_data_typed_object_wrapBN_newossl_bn_ctxBN_sqrBN_bn2hexrb_cstr_to_inumBN_is_zeroBN_is_negativecBNBN_dupBN_set_negativeBN_is_oddBN_is_oneBN_cmpBN_bin2bnrb_absint_sizerb_integer_packrb_alloc_tmp_buffer_with_countBN_copyBN_hex2bnrb_string_value_ptrBN_mpi2bnBN_dec2bnrb_eArgErrorBN_is_bit_setBN_clear_bitBN_mask_bitsBN_set_bitBN_lshiftBN_rshiftBN_randBN_pseudo_randBN_is_prime_fasttest_exBN_is_prime_exstrlenBN_bn2decBN_bn2mpirb_assoc_newBN_mod_inverseBN_generate_prime_exBN_pseudo_rand_rangeBN_rand_rangeBN_ucmpBN_gcdBN_mod_expBN_expBN_mod_sqrBN_mod_mulBN_mod_subBN_mod_addBN_divrb_ary_new_from_argsBN_mulBN_subBN_addrb_error_frozen_objectBN_CTX_newrb_define_alloc_funcEVP_CIPHER_CTX_freeEVP_CIPHER_CTX_newEVP_get_cipherbynameEVP_CipherInit_exeCipherErrorEVP_CIPHER_CTX_cipherEVP_CIPHER_flagsEVP_CIPHER_CTX_iv_lengthEVP_CIPHER_CTX_get_app_dataEVP_CIPHER_CTX_key_lengthEVP_CIPHER_CTX_ctrlEVP_CIPHER_CTX_block_sizeEVP_CipherFinal_exEVP_CipherUpdaterb_eRangeErrorossl_evp_get_digestbynameEVP_BytesToKeyOPENSSL_cleanseEVP_md5OBJ_NAME_do_all_sortedEVP_CIPHER_CTX_copyEVP_CIPHER_nidrb_class_path__memcpy_chkEVP_CIPHER_CTX_set_paddingEVP_CIPHER_CTX_set_key_lengthEVP_CIPHER_CTX_set_app_dataossl_evp_get_cipherbynamecCipherossl_cipher_newDupConfigPtrcConfigNCONF_newNCONF_load_bioNCONF_freeeConfigErrorCONF_get1_default_config_fileEVP_MD_CTX_freeEVP_MD_CTX_copyEVP_MD_CTX_neweDigestErrorEVP_MD_CTX_mdEVP_DigestInit_exossl_digest_updateEVP_DigestUpdateEVP_MD_typeEVP_MD_block_sizeEVP_MD_sizeEVP_DigestFinal_exEVP_get_digestbynameossl_digest_newcDigestrb_requirerb_path2classrb_define_private_methodENGINE_freeENGINE_get_cmd_defnsENGINE_load_public_keyossl_pkey_neweEngineErrorENGINE_load_private_keyrb_iv_setENGINE_get_firstENGINE_up_refENGINE_get_nextENGINE_load_builtin_enginesOPENSSL_init_cryptoENGINE_by_idENGINE_initENGINE_ctrlENGINE_get_nameENGINE_get_idrb_sprintfENGINE_set_defaultENGINE_get_digestENGINE_get_cipherENGINE_finishENGINE_ctrl_cmd_stringcEnginerb_undef_alloc_funcHMAC_CTX_freeeHMACErrorHMAC_CTX_newHMAC_CTX_copyHMAC_FinalHMAC_UpdateHMAC_Init_excHMACrb_get_kwargsEVP_PKEY_CTX_new_idEVP_PKEY_derive_initEVP_PKEY_CTX_ctrlEVP_PKEY_deriveEVP_PKEY_CTX_freerb_check_hash_typerb_extract_keywordsEVP_PBE_scryptrb_num2ulongPKCS5_PBKDF2_HMACNETSCAPE_SPKI_freeeSPKIErrori2d_NETSCAPE_SPKIeX509CertErrorGetPKeyPtrossl_pkey_check_public_keyNETSCAPE_SPKI_verifyGetPrivPKeyPtrNETSCAPE_SPKI_signNETSCAPE_SPKI_set_pubkeyNETSCAPE_SPKI_get_pubkeyNETSCAPE_SPKI_printNETSCAPE_SPKI_b64_encodeNETSCAPE_SPKI_newNETSCAPE_SPKI_b64_decoded2i_NETSCAPE_SPKImNetscapecSPKIi2d_OCSP_CERTIDeOCSPErrorOCSP_CERTID_freeOCSP_id_get0_infoOCSP_CERTID_dupi2d_OCSP_SINGLERESPOCSP_SINGLERESP_freed2i_OCSP_SINGLERESPOCSP_SINGLERESP_itASN1_item_dupi2d_OCSP_BASICRESPOCSP_BASICRESP_freeOCSP_BASICRESP_itOCSP_basic_add1_nonceOCSP_REQUEST_freeOCSP_REQUEST_itd2i_OCSP_BASICRESPi2d_OCSP_RESPONSEOCSP_RESPONSE_freeOCSP_RESPONSE_itd2i_OCSP_RESPONSEi2d_OCSP_REQUESTOCSP_request_onereq_countcOCSPCertIdOCSP_request_onereq_get0OCSP_onereq_get0_idOCSP_request_add0_idOCSP_request_add1_nonced2i_OCSP_REQUESTOCSP_id_issuer_cmpOCSP_id_cmpOCSP_resp_countOCSP_resp_get0OCSP_single_get0_statusOCSP_SINGLERESP_get0_idOCSP_SINGLERESP_get_ext_countOCSP_SINGLERESP_get_extossl_x509ext_newcOCSPSingleResOCSP_resp_findOCSP_CERTID_newOCSP_SINGLERESP_newOCSP_copy_nonceOCSP_BASICRESP_newcOCSPBasicResOCSP_response_get1_basicOCSP_response_statusOCSP_response_status_strOCSP_RESPONSE_newOCSP_check_nonceOCSP_REQUEST_newd2i_OCSP_CERTIDGetX509CertPtrOCSP_cert_to_idOCSP_request_is_signedOCSP_response_createX509_gmtime_adjossl_x509_time_adjustrb_check_array_typecX509ExtOCSP_basic_add1_statusGetX509ExtPtrOCSP_SINGLERESP_add_extOCSP_check_validityGetX509StorePtrOCSP_basic_verifyOCSP_request_verifyOCSP_request_signEVP_sha1OCSP_basic_signmOCSPcOCSPReqcOCSPResi2d_PKCS12ePKCS12ErrorPKCS12_freed2i_PKCS12_bioERR_set_markPKCS12_parseERR_pop_to_markd2i_PKCS12ASN1_dupPKCS12_newcPKCS12PKCS12_createPKCS7_RECIP_INFO_freePKCS7_SIGNER_INFO_freei2d_PKCS7ePKCS7ErrorPKCS7_freePKCS7_verifyERR_peek_errorrb_iv_getPKCS7_dataInitBIO_writeBIO_readPKCS7_dataFinalBIO_free_allPKCS7_content_newd2i_PKCS7_RECIP_INFOi2d_PKCS7_RECIP_INFOcPKCS7RecipientPKCS7_RECIP_INFO_newPKCS7_get_signer_infod2i_PKCS7_SIGNER_INFOi2d_PKCS7_SIGNER_INFOcPKCS7SignerPKCS7_SIGNER_INFO_newPEM_read_bio_PKCS7d2i_PKCS7_bioPKCS7_dupPKCS7_RECIP_INFO_setPKCS7_get_signed_attributePKCS7_SIGNER_INFO_setPEM_write_bio_PKCS7X509_CRL_freeOPENSSL_sk_popGetX509CRLPtrPKCS7_add_crlPKCS7_add_certificatePKCS7_add_recipient_infoPKCS7_add_signerOBJ_nid2objPKCS7_add_signed_attributePKCS7_set_cipherPKCS7_ctrlstrcmprb_sym2strPKCS7_set_typePKCS7_newcPKCS7SMIME_read_PKCS7PKCS7_decryptEVP_rc2_40_cbcPKCS7_encryptPKCS7_signSMIME_write_PKCS7rb_thread_check_intsEVP_PKEY_freeEVP_PKEY_base_idossl_ec_newossl_rsa_newossl_dh_newossl_dsa_newcPKeyossl_evp_pkey_typerb_obj_is_instance_ofEVP_PKEY_newePKeyErrorossl_generate_cb_2BN_GENCB_get_argrb_thread_call_with_gvlossl_generate_cb_stopd2i_PrivateKey_bioPEM_read_bio_PrivateKeyd2i_PUBKEY_bioPEM_read_bio_PUBKEYEVP_PKEY_missing_parametersEVP_PKEY_get0EC_KEY_get0_public_keyRSA_get0_keyDSA_get0_keyDH_get0_keyEVP_VerifyFinalEVP_PKEY_sizeEVP_SignFinalDupPKeyPtrEVP_PKEY_up_refmPKeyInit_ossl_rsaInit_ossl_dsaInit_ossl_dhInit_ossl_ecEVP_PKEY_get0_DHDH_get0_pqgDH_set0_keyDH_set0_pqgDH_sizeeDHErrorDHparams_dupEVP_PKEY_assigni2d_DHparamsPEM_write_bio_DHparamsDHparams_printDH_generate_parameters_exDH_newBN_GENCB_newBN_GENCB_setrb_thread_call_without_gvlBN_GENCB_freeDH_generate_keyDH_freeDH_checkDH_get0_enginePEM_read_bio_DHparamsd2i_DHparamsASN1_d2i_biocDHEVP_PKEY_get0_DSADSA_get0_pqgDSA_set0_keyDSA_set0_pqgeDSAErrord2i_DSAPrivateKeyi2d_DSAPrivateKeyi2d_DSA_PUBKEYDSA_printDSA_generate_parameters_exDSA_newDSA_generate_keyDSA_freePEM_read_bio_DSAPrivateKeyPEM_read_bio_DSA_PUBKEYd2i_DSAPrivateKey_biod2i_DSA_PUBKEY_biod2i_DSAPublicKeyPEM_ASN1_read_bioi2d_DSAPublicKeyPEM_write_bio_DSAPrivateKeyPEM_write_bio_DSA_PUBKEYcDSAEC_GROUP_clear_freeEC_POINT_clear_freeEC_POINT_is_on_curvecEC_POINTeEC_GROUPeEC_POINTrb_obj_dupEC_POINT_dupEC_POINT_newEC_POINT_oct2pointEC_POINT_bn2pointEC_POINT_freePEM_write_bio_ECPKParametersi2d_ECPKParametersASN1_i2d_bioeECErrorEC_GROUP_set_seedrb_sym2idEC_GROUP_new_curve_GFpcEC_GROUPEC_GROUP_dupPEM_read_bio_ECPKParametersEC_GFp_nist_methodEC_GROUP_newd2i_ECPKParametersOBJ_sn2nidEC_GROUP_new_by_curve_nameEC_GROUP_set_asn1_flagEC_GROUP_set_point_conversion_formEC_GFp_simple_methodEC_GFp_mont_methodEVP_PKEY_get0_EC_KEYEC_KEY_printEC_KEY_check_keyEC_KEY_get0_private_keyPEM_write_bio_ECPrivateKeyi2d_ECPrivateKey_bioPEM_write_bio_EC_PUBKEYi2d_EC_PUBKEY_bioECDSA_verifyECDSA_sizeECDSA_signECDH_compute_keyEC_KEY_set_public_keyEC_KEY_set_private_keyEC_KEY_set_groupEC_KEY_dupEC_KEY_freeEC_KEY_newEC_KEY_new_by_curve_nameEC_KEY_set_asn1_flagEC_KEY_set_conv_formcECPEM_read_bio_ECPrivateKeyPEM_read_bio_EC_PUBKEYd2i_ECPrivateKey_biod2i_EC_PUBKEY_bioEC_get_builtin_curvesEC_POINT_point2octEC_POINT_set_to_infinityEC_POINT_invertEC_POINT_make_affineEC_POINT_is_at_infinityECPKParameters_printEC_GROUP_get_degreeEC_GROUP_get_seed_lenEC_GROUP_get0_seedEC_GROUP_get_point_conversion_formEC_GROUP_get_asn1_flagEC_GROUP_get_curve_nameEC_GROUP_get_cofactorEC_GROUP_get_orderEC_GROUP_set_generatorEC_GROUP_cmpEC_POINT_cmpEC_KEY_generate_keyEC_POINT_mulrb_ary_tmp_newEC_POINTs_mulruby_malloc_size_overflowEC_GROUP_get0_generatorEC_KEY_get0_groupEVP_PKEY_get0_RSARSA_get0_factorsRSA_get0_crt_paramsRSA_set0_crt_paramsRSA_set0_factorsRSA_set0_keyEVP_DigestVerifyInitRSA_pkey_ctx_ctrlEVP_DigestVerifyFinaleRSAErrori2d_RSAPrivateKeyi2d_RSA_PUBKEYPEM_write_bio_RSAPrivateKeyPEM_write_bio_RSA_PUBKEYRSA_printd2i_RSAPrivateKeyRSA_generate_key_exRSA_newRSA_freeRSAPublicKey_dupRSA_sizeRSA_public_encryptRSA_public_decryptRSA_private_encryptRSA_private_decryptPEM_read_bio_RSAPrivateKeyPEM_read_bio_RSA_PUBKEYd2i_RSAPrivateKey_biod2i_RSA_PUBKEY_bioPEM_read_bio_RSAPublicKeyd2i_RSAPublicKey_bioEVP_DigestSignInitEVP_DigestSignFinalcRSARAND_statusrb_num2dblRAND_addRAND_seedRAND_byteseRandomErrorrb_check_safe_objRAND_load_fileRAND_write_filemRandomSSL_freeSSL_CIPHER_get_nameSSL_CIPHER_get_versionSSL_CIPHER_get_bitsossl_ssl_typeSSL_get_fdrb_io_taint_checkrb_io_check_closedrb_io_check_readablerb_io_check_writableSSL_set_fdSSL_CTX_freeSSL_CTX_get_optionsSSL_CTX_clear_optionsSSL_CTX_set_optionsSSL_CTX_flush_sessionsSSL_CTX_ctrlSSL_get_servernameSSL_get_ex_dataSSL_get_ex_data_X509_STORE_CTX_idxX509_STORE_CTX_get_ex_dataossl_verify_cb_callSSL_is_serverX509_STORE_CTX_get_error_depthX509_STORE_CTX_get_current_certmSSLcSSLSessionossl_ssl_session_typerb_during_gcSSL_CTX_get_ex_dataSSL_SESSION_up_refX509_get_pubkeyEVP_PKEY_cmpSSL_CTX_use_certificateSSL_CTX_use_PrivateKeySSL_CTX_get_security_levelSSL_CTX_set_cipher_listrb_StringSSL_CTX_get_ciphersrb_uint2bigSSL_get0_next_proto_negotiatedSSL_get0_alpn_selectedSSL_ctrlSSL_get_client_CA_listSSL_get_verify_resultSSL_set_sessionSSL_session_reusedSSL_pendingSSL_state_stringrb_ruby_verbose_ptrSSL_state_string_longSSL_get_current_cipherSSL_get_versionSSL_get_peer_cert_chainSSL_get_peer_certificateSSL_get_certificateSSL_shutdownrb_hash_lookup2SSL_writeSSL_get_errorrb_io_wait_writable__errno_locationrb_io_wait_readablerb_sys_failX509_verify_cert_error_stringSSL_acceptSSL_connectSSL_CTX_remove_sessionTLS_methodSSL_CTX_newSSL_CTX_set_ex_dataSSL_CTX_set_security_levelSSL_CTX_add_sessionstrncmpSSL_readrb_str_modifyrb_str_modify_expandrb_eof_errorSSL_CTX_set_tmp_dh_callbackSSL_CTX_set_cert_storeX509_STORE_up_refSSL_CTX_check_private_keySSL_CTX_add_client_CASSL_CTX_set_verifySSL_CTX_set_timeoutSSL_CTX_set_verify_depthrb_eachrb_iterateSSL_CTX_set_next_protos_advertised_cbSSL_CTX_set_alpn_protosrb_obj_freezeSSL_CTX_set_session_id_contextSSL_CTX_callback_ctrlSSL_CTX_sess_set_new_cbSSL_CTX_sess_set_get_cbSSL_CTX_sess_set_remove_cbSSL_CTX_set_client_cert_cbSSL_CTX_load_verify_locationsSSL_CTX_set_alpn_select_cbSSL_CTX_set_next_proto_select_cbSSL_newSSL_set_ex_dataSSL_set_info_callbackrb_call_supercSSLContextSSL_set_SSL_CTXCRYPTO_get_ex_new_indexrb_mWaitReadablerb_mWaitWritableInit_ossl_ssl_sessioncSSLSocketSSL_SESSION_freei2d_SSL_SESSIONPEM_read_bio_SSL_SESSIONSSL_get1_sessionSSL_SESSION_newd2i_SSL_SESSIONSSL_SESSION_printSSL_SESSION_get_idSSL_SESSION_get_timeoutSSL_SESSION_set_timeoutSSL_SESSION_get_timeSSL_SESSION_set_timeSSL_SESSION_get_protocol_versionCRYPTO_memcmpPEM_write_bio_SSL_SESSIONX509_time_adj_exmX509Init_ossl_x509attrInit_ossl_x509certInit_ossl_x509crlInit_ossl_x509extInit_ossl_x509nameInit_ossl_x509reqInit_ossl_x509revokedInit_ossl_x509storeX509_get_default_cert_areaX509_get_default_cert_dirX509_get_default_cert_fileX509_get_default_cert_dir_envX509_get_default_cert_file_envX509_get_default_private_dirX509_ATTRIBUTE_freei2d_X509_ATTRIBUTEeX509AttrErrorX509_ATTRIBUTE_countX509_ATTRIBUTE_get0_typei2d_ASN1_SET_ANYOPENSSL_sk_freeASN1_TYPE_getX509_ATTRIBUTE_set1_dataX509_ATTRIBUTE_get0_objectX509_ATTRIBUTE_create_by_OBJX509_ATTRIBUTE_dupX509_ATTRIBUTE_set1_objectd2i_X509_ATTRIBUTEX509_ATTRIBUTE_newossl_x509attr_newcX509AttrGetX509AttrPtrX509_EXTENSION_freeX509_delete_extX509_add_exti2d_X509X509_dupX509_newX509_cmpX509_get_ext_countX509_get_extX509_check_private_keyX509_verifyX509_signX509_set_pubkeyX509_set1_notAfterX509_get0_notAfterX509_set1_notBeforeX509_get0_notBeforeGetX509NamePtrX509_set_issuer_nameX509_get_issuer_nameX509_set_subject_nameX509_get_subject_nameX509_get_serialNumberX509_set_serialNumberX509_get0_tbs_sigalgX509_set_versionX509_get_versionX509_printPEM_write_bio_X509PEM_read_bio_X509d2i_X509_bioX509_up_refX509_CRL_delete_extX509_CRL_add_exteX509CRLErrorcX509RevX509_CRL_get_REVOKEDX509_REVOKED_freeDupX509RevokedPtrX509_CRL_add0_revokedX509_CRL_sortossl_x509revoked_newX509_CRL_get0_signatureX509_CRL_dupX509_CRL_newX509_CRL_get_ext_countX509_CRL_get_extX509_CRL_printPEM_write_bio_X509_CRLi2d_X509_CRL_bioX509_CRL_verifyX509_CRL_signX509_CRL_set1_nextUpdateX509_CRL_get0_nextUpdateX509_CRL_set1_lastUpdateX509_CRL_get0_lastUpdateX509_CRL_set_issuer_nameX509_CRL_get_issuerX509_CRL_set_versionX509_CRL_get_versionPEM_read_bio_X509_CRLd2i_X509_CRL_biocX509CRLi2d_X509_EXTENSIONeX509ExtErrorX509_EXTENSION_get_objectX509_EXTENSION_get_dataASN1_OCTET_STRING_setX509_EXTENSION_dupOBJ_ln2nidX509V3_set_nconfX509V3_EXT_nconf_nidX509V3_EXT_printASN1_STRING_printX509_EXTENSION_get_criticalX509_EXTENSION_set_objectGetX509ReqPtrX509V3_set_ctxd2i_X509_EXTENSIONX509_EXTENSION_newX509_EXTENSION_set_criticalcX509ExtFactoryX509_NAME_freei2d_X509_NAMEeX509NameErrorX509_NAME_entry_countX509_NAME_ENTRY_get_dataX509_NAME_get_entryX509_NAME_ENTRY_get_objecti2t_ASN1_OBJECTX509_NAME_print_exrb_utf8_encindexrb_enc_associate_indexrb_utf8_encodingrb_enc_sprintfX509_NAME_dupcX509Namerb_const_getd2i_X509_NAMEX509_NAME_newX509_NAME_cmpX509_NAME_onelineX509_NAME_hash_oldX509_NAME_hashX509_NAME_add_entry_by_txtrb_mComparablerb_hash_set_ifnoneX509_REQ_freeX509_REQ_delete_attrX509_REQ_add1_attreX509ReqErrorX509_REQ_get0_signaturei2d_X509_REQX509_REQ_dupX509_REQ_get_attr_countX509_REQ_get_attrX509_REQ_verifyX509_REQ_signX509_REQ_set_pubkeyX509_REQ_get_pubkeyX509_REQ_set_subject_nameX509_REQ_get_subject_nameX509_REQ_set_versionX509_REQ_printPEM_write_bio_X509_REQX509_REQ_newPEM_read_bio_X509_REQd2i_X509_REQ_bioX509_REQ_get_versioncX509Reqi2d_X509_REVOKEDeX509RevErrorX509_REVOKED_delete_extX509_REVOKED_add_extX509_REVOKED_dupX509_REVOKED_get_ext_countX509_REVOKED_get_extX509_REVOKED_set_revocationDateX509_REVOKED_get0_revocationDateX509_REVOKED_set_serialNumberX509_REVOKED_get0_serialNumberX509_REVOKED_newX509_STORE_CTX_get0_untrustedX509_STORE_CTX_get0_certX509_STORE_CTX_freeX509_STORE_freeX509_LOOKUP_fileX509_STORE_add_lookupX509_LOOKUP_ctrleX509StoreErrorX509_LOOKUP_hash_dircX509StoreContextX509_STORE_CTX_get_errorX509_STORE_CTX_set_timeX509_STORE_CTX_set_errorX509_STORE_CTX_set_flagsX509_STORE_CTX_get0_current_crlX509_STORE_CTX_get0_chainX509_STORE_CTX_set_ex_dataX509_verify_certX509_STORE_CTX_newX509_STORE_add_crlX509_STORE_add_certX509_STORE_set_default_pathsX509_STORE_set_flagsX509_STORE_set_ex_dataX509_STORE_set_verify_cbX509_STORE_newrb_block_procX509_STORE_CTX_initX509_STORE_CTX_set_purposeX509_STORE_CTX_set_trustX509_STORE_set_purposeX509_STORE_set_trustX509_STORE_CTX_get0_storeX509_STORE_get_ex_datacX509Storelibruby.so.2.5libssl.so.1.1libcrypto.so.1.1libc.so.6_edata__bss_start_endGLIBC_2.14GLIBC_2.4GLIBC_2.2.5GLIBC_2.7GLIBC_2.3.4OPENSSL_1_1_0OPENSSL_1_1_1 I` Iii Iui Iii Iti IuI mIImImI|%p|%0|%|%|%d|% }%X0}%,}%}%I}%}% R@~%`P~%p_~%G~%s%%P}`% p%%%%p %<0%p%R%p%F%@%P% %%0%%``%p%%FЂ%% %W0%%%ӵ%% %%Ѓ% %'%@%3P%%%%%@`%cp%%JЅ% %0%@5%%p/%t%@@%'P% T%%b%%pl`%p%l%Ј%%:%B%M%Z %0%_@%qP%z`%p%%%%%%͈Љ%ֈ%ڈ%%% %0%@%#P%3`%Ap%M%[%k%|Ȉ%Q%Q؈%h%%%%`%%H%%(%(%%h%X%%K %Kȉ%+0%+؉%%%p%%%x%%%Ȫ%%Ȯ%(%0%8%%H%P%X%ج%h%x%x% % %H%%%%%%P%%#%.%0Ъ%2ت%%%0%%D%F%-%%0%[8%@%H%P%X%n`%ph%wp%}x%%%%%%%%%%ȫ%Ы%ث%%%%%A%%%B%C %>(%0%8%@@%LP%4X%4`%6p%x%@%%O%E%%T%a%MȬ%Ь%d%t%%%%%%% %(%0%8%@%IH%P%<X%`%1h%p%%%%%%O%%%ȭ%Э%Uح%F%,%%(%:%%C%%! %W(%\8%@%iP%X% `%h%8x%%%%%%%%%$%"Ю%خ%%%*%%<%=% %(%/8%@%PH%Qh%_p%%G%?%%%u%x%%%ȯ%Я%د%%H،%%%%%%%%% % (% 0% 8% @%H%P%X%`%h%p%x%%%%%%%%%%ȍ%Ѝ%؍% %!%"%$%%%&%'%(%) %*(%+0%,8%-@%/H%1P%X%3`%4h%5p%6x%7%8%9%&%:%;%<%=%%>Ȏ%?Ў%@؎%A%B%C%E%F%G%H%I%J %K(%L0%8%M@%NH%OP%PX%Q`%Rh%Sp%Tx%U%V%W%X%Y%Z%[%\%]%^ȏ%Џ%_؏%`%a%b%c%d%e%f%g%h %i(%j0%k8%l@%mH% P%oX%q`%rh%sp%tx%u%v%x%y%z%{%|%~%%Ȑ%А%ؐ%%%%%%%%% %(%0%8%@%H%P%X%`%h%p%x%%%%%%%%%%ȑ%Б%ؑ%%%%%%%%% %(%0%8%@%H%P%X%`%h%p%x%*%%%%%%%%%Ȓ%В%ؒ%%%%%%%%% %(%0%8%@%H%P%X%`%h%p%x%%%%%%%.%%%ȓ%Г%ؓ%%%%%%%D%% %(%0%8%@%H%P%X%`%h%p%x%:%%%%%%%%%Ȕ%Д%ؔ%%%%%% %%% %(%0%8%@%H% P%X% `% h% p% x%%%%%%%%%%ȕ%Е%ؕ%6%%%%%%%%  %!(%0%"8%#@%$H%P%%X%&`%'h%(p%)x%*%+%,%-%.%/%0%1%2%3Ȗ%5Ж%6ؖ%%7%8%9%:%;%<%=%> %?(%A0%B8%C@%DH%EP%FX%G`%Hh%Ip%Jx%K%L%M%N%P%Q%R%S%T%Uȗ%VЗ%Wؗ%X%Y%Z%[%\%]%^%_%` %b(%0%c8%e@%fH%gP%hX%;`%ih%jp%kx%l%m%n%o%p%q%r%s%u%vȘ%wИ%xؘ%y%z%{%|%}%~%%% %(%0%8%#@%H%P%X%`%h%p%x%%%%%%%%%%Rș%Й%ؙ%%%5%%%%%% %(%0%8%@%H%P%X%`%h%p%x%%%%%%%%%%Ț%К%ؚ%%%'%%%%%% %(%0%8%@%H%JP%X%`%h%p%x%%%%%%%%%%ț%Л%؛%%%%%%%%% %(%0%8%@%H%P%X%`%h%p%x%%%%%%%%%%Ȝ%М%؜%%%%%%%%% %(%0%8%@%H%P%X%`%h%p%x%%%% %% % % % %ȝ%=Н%؝%%%%%%%%% %(%0%8%@%H%P%X%`% h%!p%"x%%#%%$%%%,%&%'%(%)Ȟ%*О%+؞%,%-% %.%/%0%%1%2 %3(%40%58%6@%7H%8P%9X%;`%<h%=p%>x%?%@%A%B%%%D%E%F%Gȟ%HП%I؟%J%K%L%M%N%O%P%Q%R %S(%T0%U8%@%VH%XP%YX%Z`%[h%]p%^x%_%`%a%b%c%d%e%f%g%hȠ%jР%kؠ%l%%m%n%o%p%q%r%s %t(%u0%v8%w@%xH%yP%zX%{`%|h%}p%x%~%%%%%%%%%7ȡ%С%ء%%%%%%%%% %(%0%8%@%H%P%X%`%h%p%x%%%%%%%%%%Ȣ%Т%آ%%%%%%%%% %(%0%8%@%H%P%X%`%h%p%x%%%%%%%%%%ȣ%У%أ%%%%%%%%% %(%0%8%@%H%P%X%`%h%p%x%%%%%%%2%%%Ȥ%Ф%ؤ%%%%%%%%% %(%0%8%@%H%P%X%`%h%p%x%%%%%%%%%%ȥ%Х%إ%%%%%%%%3%  % (%S0% 8% @% H%P%X%`%h%p%x%N%%%%%%%%%Ȧ%Ц%ئ%% % %!%"%#%$%%%& %'(%(0%)8%+@%,H%-P%.X%/`%0h%1p%2x%3%4%%5%6%7%8%9%:%;ȧ%<Ч%>ا%9%?%@%A%%B%C%%D %E(%F0%G8%H@%IH%JP%KX%L`%Mh%Np%Ox%Q%R%S%T%U%V%W%X%Y%ZȨ%[Ш%\ب%%]%^%)%%`%a%b%c %d(%e0%f8%g@%hH%iP%jX%k`%lh%mp%nx%o%p%q%r%s%t%v%w%%yȩ%zЩ%{ة%|%}%~%%%%%% %(%0%8%@%H%P%X%`%h%p%x%HHyr$HtH5S$%S$hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?h@hAhBhChDhEhFhGqhHahIQhJAhK1hL!hMhNhOhPhQhRhShThUhVhWqhXahYQhZAh[1h\!h]h^h_h`hahbhchdhehfhgqhhahiQhjAhk1hl!hmhnhohphqhrhshthuhvhwqhxahyQhzAh{1h|!h}h~hhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?h@hAhBhChDhEhFhGqhHahIQhJAhK1hL!hMhNhOhPhQhRhShThUhVhWqhXahYQhZAh[1h\!h]h^h_h`hahbhchdhehfhgqhhahiQhjAhk1hl!hmhnhohphqhrhshthuhvhwqhxahyQhzAh{1h|!h}h~hhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?h@hAhBhChDhEhFhGqhHahIQhJAhK1hL!hMhNhOhPhQhRhShThUhVhWqhXahYQhZAh[1h\!h]h^h_h`hahbhchdhehfhgqhhahiQhjAhk1hl!hmhnhohphqhrhshthuhvhwqhxahyQhzAh{1h|!h}h~hhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?h@hAhBhChDhEhFhGqhHahIQhJAhK1hL!hMhNhOhPhQhRhShThUhVhWqhXahYQhZAh[1h\!h]h^h_h`hahbhchdhehfhgqhhahiQhjAhk1hl!hmhnhohphqhrhshthuhvhwqhxahyQhzAh{1h|!h}h~hhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhh%]$D%U$D%M$D%E$D%=$D%5$D%-$D%%$D%$D%$D% $D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%}$D%u$D%m$D%e$D%]$D%U$D%M$D%E$D%=$D%5$D%-$D%%$D%$D%$D% $D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%}$D%u$D%m$D%e$D%]$D%U$D%M$D%E$D%=$D%5$D%-$D%%$D%$D%$D% $D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%}$D%u$D%m$D%e$D%]$D%U$D%M$D%E$D%=$D%5$D%-$D%%$D%$D%$D% $D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%}$D%u$D%m$D%e$D%]$D%U$D%M$D%E$D%=$D%5$D%-$D%%$D%$D%$D% $D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%}$D%u$D%m$D%e$D%]$D%U$D%M$D%E$D%=$D%5$D%-$D%%$D%$D%$D% $D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%}$D%u$D%m$D%e$D%]$D%U$D%M$D%E$D%=$D%5$D%-$D%%$D%$D%$D% $D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%}$D%u$D%m$D%e$D%]$D%U$D%M$D%E$D%=$D%5$D%-$D%%$D%$D%$D% $D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%}$D%u$D%m$D%e$D%]$D%U$D%M$D%E$D%=$D%5$D%-$D%%$D%$D%$D% $D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%}$D%u$D%m$D%e$D%]$D%U$D%M$D%E$D%=$D%5$D%-$D%%$D%$D%$D% $D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%}$D%u$D%m$D%e$D%]$D%U$D%M$D%E$D%=$D%5$D%-$D%%$D%$D%$D% $D%$D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D%} $D%u $D%m $D%e $D%] $D%U $D%M $D%E $D%= $D%5 $D%- $D%% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D%} $D%u $D%m $D%e $D%] $D%U $D%M $D%E $D%= $D%5 $D%- $D%% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D%} $D%u $D%m $D%e $D%] $D%U $D%M $D%E $D%= $D%5 $D%- $D%% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D%} $D%u $D%m $D%e $D%] $D%U $D%M $D%E $D%= $D%5 $D%- $D%% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D% $D%} $D%u $D%m $D%e $D%] $D%U $D%M $D%E $D%= $D%5 $D%- $D%% $D% $D% $D% $D% $D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%}$D%u$D%m$D%e$D%]$D%U$D%M$D%E$D%=$D%5$D%-$D%%$D%$D%$D% $D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%}$D%u$D%m$D%e$D%]$D%U$D%M$D%E$D%=$D%5$D%-$D%%$D%$D%$D% $D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%}$D%u$D%m$D%e$D%]$D%U$D%M$D%E$D%=$D%5$D%-$D%%$D%$D%$D% $D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%}$D%u$D%m$D%e$D%]$D%U$D%M$D%E$D%=$D%5$D%-$D%%$D%$D%$D% $D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%}$D%u$D%m$D%e$D%]$D%U$D%M$D%E$D%=$D%5$D%-$D%%$D%$D%$D% $D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%}$D%u$D%m$D%e$D%]$D%U$D%M$D%E$D%=$D%5$D%-$D%%$D%$D%$D% $D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%}$D%u$D%m$D%e$D%]$D%U$D%M$D%E$D%=$D%5$D%-$D%%$D%$D%$D% $D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%}$D%u$D%m$D%e$D%]$D%U$D%M$D%E$D%=$D%5$D%-$D%%$D%$D%$D% $D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%$D%}$D%u$D%m$D%e$D%]$D%U$D%M$D%E$D%=$D%5$D%-$D%%$D%$D%$D% $D%$D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%}#D%u#D%m#D%e#D%]#D%U#D%M#D%E#D%=#D%5#D%-#D%%#D%#D%#D% #D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%}#D%u#D%m#D%e#D%]#D%U#D%M#D%E#D%=#D%5#D%-#D%%#D%#D%#D% #D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%}#D%u#D%m#D%e#D%]#D%U#D%M#D%E#D%=#D%5#D%-#D%%#D%#D%#D% #D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%}#D%u#D%m#D%e#D%]#D%U#D%M#D%E#D%=#D%5#D%-#D%%#D%#D%#D% #D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%}#D%u#D%m#D%e#D%]#D%U#D%M#D%E#D%=#D%5#D%-#D%%#D%#D%#D% #D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#DH=9$H2$H9tH~#Ht H= $H5$H)HHH?HHtH#HtfD=#u+UH=#Ht H=N#d#]wH#HÐHHHHEH #Hff.H1rfHdH%(HD$1H$Ht HH$HT$dH3%(uH3SH1HHHHs>HuH[@H3HHHЃfHHH=O#Zf.HdH%(HD$1Ht$D$|$uHT$dH3%(u H_ff.@AUATUSHHt}HAąxNHcIEt+1@HHsLHhD9uHL[]A\A]DH#H8H[]A\A]`H#AH8uH.# H=EH H H=6H;AZ1H )H)Y@H# H=H XH H=?H;AZ1H HLAUATUSHHt}HAąxNHc&IEt+1@HHLHD9uHL[]A\A]DHI#H8H[]A\A]H)#AH8uH# H=H MH H=4H;A[1H HAY@HY# H=pH H H=|H;A[1H THTAUATUSHHt}HAąxNHcIEt+1@HHLHD9uHL[]A\A]DH#H8H[]A\A]H#AH8uHN# H=eH H H=VH;A\1H IHIY@H# H=H xH H= _H;A\1H HlAUIH=`ATIUHSHdH%(HD$1HT$hHHt`D$EuuMtH{H u3LLHL$dH3 %(HuLH[]A\A]f.H{f.D$tY4@UHcSHHdH%(HD$1HT$FHߺ~H5H?|$uHL$dH3 %(Hu H[]H?H9wN1L Ht? AȃAA EGLFDFHH9uf.PH 'H5H=0ff.@AWAVLcAUATUHSHdH%(HD$1Ht>H؃- tHHYI9HqHHH|$dH3<%(iH[]A\A]A^A_HI9HqfYtuLd$McMIALLH=T$uvHtzHHځ t"HXI9|AHpHMHpDH1ɉDH!*@DH=.1'rf@H#H8uH,# H=CH H "H=H;A1H 'H'@HH5#11dH%(HD$1HH$lH$HT$dH3%(uHff.SH5#HuH[H[AVAUATUSH dH%(HD$1Hi#H8Lt$Ll$IHl$HyfDLLLHHtW1H HHDD$t"HT$HtXHH=81DHH=81D3HD$dH3%(u!H []A\A]A^fDH\$Hff.fATUHHSHHT$0HL$8LD$@LL$Ht7)D$P)L$`)T$p)$)$)$)$)$dH%(HD$1H$$HD$HD$ D$0HD$Ht.HHHu1HtHHHnHuJ11HHsIHt6H u@u>MtOLHAH7IMt6LHH{뾺H5HtL%^fff.@AUATUHSHeHI1HHH9}NHHHEIH;#LH0Ht3LcLHHE uHEH9|HL[]A\A]H5#LYH#H5H81qH#1H81^ff.HHH|$HtH|$HD$H u HDHx~H#H5KH81SHHt*t.H[Ð1uH6#H5H81DuH #H5H81fS11H=NH?#HHH=+H;H5Hi H=H;H5HF1HH;H5H%H;! H5H;H5H;1HH5H;HH5Hs#H;H5wHH=#HH=;#HH;1HsH5G7H;HhH52HU#H;1H5!H=H#MSIT%P+F[0H#H5H81xHH|$H|$H|$H uH1HtHf.H1uHuH|$H t2HTHuH#HT$H5H81fHf.H=ff.AT1UH-#SHH=|H5Y#HߺI)H5J#LHH5 #HߺH5#HHH5#H1H[]A\USHH5#dH%(HD$1:HHT$H=FHH苿HH|$uHL$dH3 %(Hu H[] @ATUH1SH0H HHxHPHHc tUHSH9~7D`HIcH{H tH{HDL~?HcHH[]A\DHHxHcljH9u!H{]H#H5H811H=ݶH\$xdH3%(H[HpHPHHVHPLHL@ H5O1x^_-ND$DHc$D$HTLHpHPHHVHPLHL@ H51ZY Hc$D$HTHH5F#HT$hHDHD$@HcD$HDHD$HHcD$ HDHD$PHcD$HDHD$XHcD$HDHD$`HtH#HL$@H8H=HH#Hc$lD$HTRf$@$D$$H?#HSH5H81H##HSH5H81ff.USHHtC1 t1HHtFHHHyHH[]sHH#H5H816H#1H81#ATIUHSH tu_HtVuLH5#H胦H5#LHqH5#HH_H5`#H1NH[]A\H#H5H81ff.H(H|$HT$Ht$HL$诼H|$襼H|$蛼HT$H uMHt$HH uMHH|$H uH t4H(fHf.Ht$HRH tHvH#1H81DHH5u#Ht$HǨuHfkHH_#H5H81nff.S@ti@H@ H_'H=#HHu;HòHHuڸ[HuHt=HuH]#HHǨt 褴[f;[fHQ#HHu#HH9#HH=#HH#HqAWAVIAUAATAUHSH8dH%(HD$(1t ҸDEH5#LXHnH;#aH;#H;#WH;#D$LLD$nHMD$ ]HIIcIcI9FH5M#LųH9~#8E1EAA|$8T$DDDT$DT$T$ƉD$DDT$߱1HHHD$DT$D\$IH@I tIGLt$ DD$DD֋L$LHD$ /L$DE1LHuHE tHuH|$ HH\$ H\$ EIGI tIGH)H;\$4HT$(dH3%(LH8[]A\A]A^A_@L}T$DD1HHHD$ IH@I tIGLt$ DD$L$DLHD$ H|$hH@HHt?L|$LHHփD$\H5X#tH5I#u@H5D#HD5D#LHct$XLHt6LLl$hBK,'H #HH#H8qHt$HL$LHHH5#A!H{fDE1HH 2#LD$HDH2H8HD$H$L$HDŽ$H$ޡH$HHALD$H5#KTHfDA.H kDHcH>f.HRLHۿHHHE#HDH8(HH|$xHt$xH1D$pIHH=!#HT$pH$LIٗ|$pDHH F#E1HHIcHTH9L$pDH|$xHt$xH1D$pIHcH=A#HT$pH蜠LI|$pt4@H|$xHt$xH1D$p脲IH H=#HT$pHDLI |$p%HL?+!IcMHE1IH;AyfDH?v1H=H #E1IHH|$xHt$x1HLH6HA蕗HH #E1hH|$xHt$xH1#HH5\H81JH##H5fH812H #H53H81f.AWHAVAUATUSHHHt$dH%(HD$81HD$ 蘽H|$HD$)H豮L8HD$(A IHAHD$L<$2L<$1HM~NLt$0Ll$ Ld$DLME11HD$0LLHHHD$0I)HMHD$(HD$0HD$(H$HtLD$ H9uBI9u=HL$8dH3 %(HuIHH[]A\A]A^A_DHPH@HT$H$;H#H $HH5H81賰讶ff.SHH@Ht$dH%(HD$81HD$ HD$((H|$HD$蹬HAHHD$ utHHHD$HT$(H|$1HLL$ AEHD$HD$0HD$HtHT$ LD$(H9u1I9u,HL$8dH3 %(u2H@[fHPHXHT$H#HH5H81覯衵SHH@Ht$dH%(HD$81HD$ HD$((H|$HD$蹫HAHHD$ utHHHD$HT$(H|$E11LL$ HHHT$HT$0HT$HtHT$ LD$(H9u4I9u/HL$8dH3 %(u:H@[f.HPHXHT$H#HH5H81覮衴AUATUHSHHdH%(HD$17IĨt`HI?HW)QΠEHHHH L)Hi€QH)HcH H9UHD$dH3%(H[]A\A]@H5#H$HILLUHǨt>蹞H5J#EH$HtBLL"tHHpfHfDH=迨HH#H=蟨HH#HH踾3Hc7HSHH|$Ht#H|$HHH褧HtH[HB#H5cH81ѬHB#1H81辬ff.AUATUSHH(dH%(HD$1*H5K#H߉詝7H IHcH>f.LHT$ Ht$nT$ Ht$11茝IHPL-#/H5ÝHHfLHHHL$dH3 %(H([]A\A]ÐII/IH57MUIEHHuH_#H5ښH81nfDL1ΪL-/#I6H5#HiHǨ HcLd$H;H|$kIH*Ht$H YHHLID$HcL-#HH I\$H|$Ld$蜍IHHt$H HHL L-#GIdIHtyL-"#$DH耱H(IHtPH HHsLHT$ Ht$T$ Ht$11|IHH#1H81轩DL0L-#Im@H~HcljH9usHvfH~HcljH9uSHvfH{HcljH9u3HsH#H5vH81!L1A芺Hc#H5H81H˿#H5"H81ڨH#H5H81¨fATUHSH@dH%(HD$81<H軷1HI莫HcHHT$H1裠T$HD$0H H@Ht$ LHD$(HD$ :L2HD$ H+D$(H9HL$HT$ IHt$H|$(SH+\$H|$0HH11HZHL$8dH3 %(u:H@[]A\ÐHfH5a#HH|$0HD$0{L胍|$LrH;#H5ΖH81JH sH5ѕH= H#H5H81SH5#H,H#HH2 Hu%H5#HHuH[DH[H#H5H81蟦ff.@AW H=,AVAUL-#ATL%U1SH譡H%H=H*#荡H H=H#mHH=ޕH#MHŵH=H#-H襵H=H# H腵H=9H=Hc#&H=HH#H=wH%#H=oH#H=oH#ڴH5iHܿ#H#H8=H#H/#H5CHHH芌H#H;H5)HHJH;H6H5 ʬH;HH5诬JH;H5HIջH;EMeIA$<[t&HT-L袻LLHH܃H;HHuH#H5H詋L%"#H=I$袳I<$E1HٯH=}I<$E1H贯H=ɓXI<$E1H華H=3I<$E1HƺjI<$HH5賨I<$HH5蜨I<$H,H5萓I<$1H#H5KwI$H;H5ē蔊H-#H=HE荲H}AHƺH}H5RH}H5UH}H1H5JH}1HH5ܒI$H;H53Hڷ#L5#HH2I݌H=II>AHƺI>HH5kI>1HH5'SI>1HH5;HUH;H5XH #H;H7H5H賩HUH;H5t H #H;HH5WH{HUH;H5DH i#H;HH5'HCHUH;H5谈L=9#H;HjH5I HUH;H5xH #H;HH5̑HӨHUH;H5@H #H;H?H5H蛨HUH;H5H #H;HH5sHcHUH;H5fЇH q#H;HH5IH+HUH;H5>蘇H #H;HwH5!HHUH;H5`H Q#H;HH5H軧HUH;H5(H #H;HGH5ʐH胧HUH;H5H #H;HH5HKHUH;H5踆H Y#H;HH5rHHUH;H5c耆H #H;HH5FHۦHUH;H59HH #H;HH5H裦HUH;H5H !#H;HOH5HkHUH;H5؅H )#H;HH5ƏH3HUH;H5蠅L-#H;HH5IEHUH;H5gH #H;HH5cH¥HUH;H5P/H #H;HH53H芥IH;H5)H Q#H;HWH5 HSIH;H5$L5#H;HH5II$H;H5Î艄H-J#H;H#H5HEI}HSH5藐I}1HzH5~I}1HH5hI}1HXH5ŘI}H<H5?襡I}H(H53莡H=aҫI?E1Hƺ H}1H]H5aH}1H$H5H蓐HHy#贌HuH=d#߇H#H=L#H0ćH #H=1#H0詇I7H=#蕇Hv# H=#H0zH;# H=#H0_Iu H=ϵ#JH;#H=#H0/H#H=#H0Hݲ#!H=#H0I6#H=j#H#%H=R#H0ʆH۳#'H=7#H0识H#)H=#H0蔆H#+H=#H0yHB#-H=#H0^Hw#/H=˴#H0CH,#1H=#H0(H#3H=#H0 H#5H=z#H0H#7H=_#H0ׅH#9H=D#H0輅H=#=H=)#H0衅H=#H=;ĔH#H[]A\A]A^A_f.@SHHdH%(HD$1H?H<$@u Hu^HvH<$H7 twHGHcЉH9uvHHH$HHL$dH3 %(H[fD uH5#Ht211H$zHHHH=O跓H<$HHQ#Hȯ#H5H81?:f.U1ҾsSHH(dH%(HD$1HL$袪HD$HT$ HxH0,HH|$ uHt$dH34%(Hu H([] 赝DH7UH5}#HAWAVAUATSH(dH%(HE1xHHI|XI=LmLmLcHHEIFHH%H)HHH9tHH$H9uutL|$ILL@9uLLvLH֦HDHMdH3 %(uuHe[A\A]A^A_]LcLmLL~IfH)HLH#H5H81MLeH^#H5H81-(ATH5|#USHvHtmHHɮHb|#1HI谔HHt.H#HHHst I\$ L[]A\H躮Hë#1H81藕H#H5ߋH81ff.@PX1HH#H81WS1H{#=HHt HC H[fPXH5mHH4#H81fUH5d{#SHuHtCH識HHtKH#sHߺ7H5+HHH[]Hê#H5H81芔DHH5z#uHtH菃HHHD.ff.HH5z#tHt HOPHHHHDfHH5az#tHtHxHHHЃfSH5$z#_tHt1HH_xt 1[H¸u1T@UH5y#SH tHtTHHc#Hy#1H8:HHHHt>HE H{1H߅@蛁HH[]H"#H5IH81H#H5\H81ђHH51y#lsHtHvHHHЃyfHH5x#,sHtHHHHЃ9fUHSHHHHN#H0NHu H1[]HH5x#rHHt4H5rx#HrHtHHuH[]H#H5H81轑ff.fUHAWAVAUIATSHH8dH%(HE1IH?H}HMIHHL1H)PHHH9uLc}HHBMHudH34%(H;He[A\A]A^A_]f1H覣IH=H=LuLuH@HHEHH%H)HHH9u|t H)HLL|$IE1HLALsLDLE|LHzHۋMt]H~ HH$jHpLuHLHHxIcH#H5oH81ݏؕH#H5\H81谜ATUSH dH%(HD$1GvHH HT$u#H~@PHT$ftKH5u#HoHD$HRH|$HHL$dH3 %(H)H []A\Ðu HurH#HH0HH5Mu#HoHD$HH|$H5+u#foHH|$H}Hff u&HT$VfDH5t#HoIHD$HT~5 |H|$iH|$H܄qfHT$H tsHjHcH9H|$LHDH(fH|$H|$H`H#1H81~fDHHHT$H u7HHHcH9uTH|$SLHVyHHjͺsH$#H5H81HqH #H54H81Ԍ@HATL%ϣ#USI4$HɐHutt7I<$1Hs#荢1HHHtVHE H[]A\u#Ht uf[H]A\H[H]A\UHH5r#SHlHtNHH7Ht#H5Zr#HlHtAHH~tH1[]DH[]Hա#H5H81蜋wUHHSHt;V|H5q#HlHt)HHHH[]軉fATIH5q#USHkHt?LAHu%耉H覞tH[]A\f.{bH#H5H81躊f.ATIH5q#USHFkHt?LAHu%HvtH[]A\f.;{Hs#H5H81:f.ATIH5p#USHjHt?LAHu%耈HtH[]A\f.zbH#H5H81躉f.UHHSHt;vzH5o#H5jHt.HHitHH[]DۇHs#H5H81:f.UHHSHt;yH5}o#HiHt.HHtHH[]D[bH#H5H81躈f.AUATUHHSHtoryH5n#H1iIHtuHAHn#1H`I(HHt9LHht Im HL[]A\A]D裆H'H0#1H81H%#H5L~H81ff.AUATUHHSHtoxH5)n#HahIHtuHqH n#1H萝IXHHt9LHst Im HL[]A\A]DӅHWH`#1H814HU#H5|}H81ff.AVAUATUSH@dH%(HD$81HD$HD$ HD$HD$(HD$HD$0G)HIH\$u>HD$HD$t5E1E1H߃uOMHFHD$uHFHD$E1H|$AH|$@ty$wAH߃twLHl#1!IHHtaDDHqtEI^ LHL$8dH3 %(uXH@[]A\A]A^fKAfDE1dHHɛ#1H81蝅艋fAVAUATUSH@dH%(HD$81HD$HD$ HD$HD$(HD$HD$0G)HIH\$u>HD$HD$t5E1E1H߃uOsMHFHD$uHFHD$E1H|$AH|$@tyuAH߃tuLHk#1葚IYHHtaDDHxtEI^ LHL$8dH3 %(uXH@[]A\A]A^f軂AfDE1dH0H9#1H81 ^~fATUSIԽt!H>uHn1Ht @tgtH5j#LQdHttH}#1HHE1H=tu9[]A\f.[1]A\fˁ뗺1}HT#1H81(HI#H5pyH81SHuH>@tnHT$sHT$DHH5>i#ycHHtsH#1ɉH|tu8H[f.H1[HT$HT$H#1H81Z1|Ho#H5xH816fDATUSHH>@xHT$rHT$H5`h#HbHH tcQH臅HHtZH'vHcH9GHH߉[]A\ifH5g#H!bHHH]nHHuHn#1H81Bf1Hf1HcIrHHpH uqHfA9uHH[]A\H pD`DI1AIcqHHpH tHpH+A9]HH[]A\fDHpf.HT$HT$1zH#H5wH81TH̑Hm#H5vH814@UHSHHtkuVHHHtb؃tX tS t0t+u?H11HHHH[]馂fDHHHuH#HH0赃HuH#H52vH81uDUHHe#1SHHk#H8KHHt#H+tHtHC HH[]}H2#1H81fDUHSHH?+Ht"H5Ne#HH_Ht#H]H[]H#H5vH81~fDAUATUSHHH|$Ht$cH5d#HI_HtwHH.Hd#1HMI}HHt8H#LHHHbHtI\$ HL[]A\A]HH#1H81}H#H5:tH81}f.AWAVAUATUSHXdH%(HD$H1HLl$H\$HD$ HD$HD$(GLl$0H\$8BHHչH$HD$ L@fHt LcN L HI9tHP9HtHHI9uH<$@{AE1H|$AH|$LE1aH|$It HaIHH>c#1ǒH{HHtjE1MLDDHgtGH] HH\$HdH3%(uZHX[]A\A]A^A_fDKmAQE1E1}H]Hf#1H81:|v&fDATUSHHH|$Ht$a1Hib#HIHzHt"LHHS\tH] HH[]A\JH”Hˑ#1H81{ff.@ATUSHHH|$Ht$r`1Ha#HI^H&zHt"LHHmtH] HH[]A\H2H;#1H81{ff.@USHHH|$Ht$_H5Ma#HH[HtHHgHH[]HDff.@USHHH|$Ht$_H5`#HH"[HtHHrmHH[]HD/ff.@AUATUSHHH|$Ht$ _H5`#HIZHtvHHΒHg`#1HIxHHt7H#LHHHftI\$ HL[]A\A]H趒H#1H81yH#H5oH81{yff.AVAUATUSHHH|$Ht$H$J^HI?^H5_#HIYHt{HHH_#1H IwHHtXHtvHHNH]#1HmI5vHHt7H>#LHHHrtI\$ HL[]A\A]H6H?#1H81wH4#H5[mH81vff.AVAUATUSHHH|$Ht$H$[HI[H5(]#HI]WHt{HHmH]#1H茌ITuHHtH5\^H;HSH5\]H;HXH5d]H;H]H5d]H;HbH5od]H;HwH5\d{]H;HH5Id`]H;HH51dE]H;HH5d*]H;H+H5 d]H;HcH5cqH;HH5c\H;H/H5c\H;1HH5̓\H;H,H5c\H;HcH5cjqH;1HH5lcb\H;1HvH5ZcJ\H;1HH5Gc2\H;1HH54c\H;HH5*c_H;H H5cd_H;HH5cI_H;HJH5b._H;HH5b_H;H$H5bx[H;H)H5b][H;HH5bB[H;HH5b'[H;H8H5b [H;HH5vbZH;HH5fbZH;HH5NbZH;HH56bZH;HH5#bZH;HH5bjZH;1HH5aRZH;HaH5a,oH;1H0H5a$ZH;HH5` ZH;[H H5aYH#H5[`H81iDvATUSHHH|$Ht$`H5P#HIIHuK&jHHHC LNpHtTE111AHHQKu$HH[]A\H#H5"aH81hH~#1H81hH~#HT$H5bH81hH~#1H81hDHUO#1~~ff.SHHH|$Ht$dH5O#HHHHHRHL ucHJLD$HcI t1I9@uSM@111AH;JuNHD$H[HH9uIfDHZ…tH#H5`H81gHQ}#1H81gH}#H5_H81mgff.fUSHHH|$Ht$cH5 N#HGHHHKHL$H1 tQHcH9Qu]HIE111AH?IuYH5#HߺvGHD$H[]f.HHcЃH9uH막H#H5#_H81fHJ|#1H81~fH|#H5^H81fffDATUHSHH|$Ht$bHD$H umHL`HcH9HH5L#FHHtyH_PHJ tJLھHRtHD$H[]A\@L`HXHw{#H5M^H81eH_{#H5_H81eH{#H5]H81veHvff.SHHcHH|1[UH5L#SHdH%(HD$1EHHHZ1HcUHHpH uTHT$H/jHHct$ t:HCH9:HIfHHL$dH3 %(u>H[]HpfHH `H5(]H=/]HLcjHz#H5\H81KdHz#1H818dAWAVAUATUSH8dH%(HD$(1GHHHD$9H5~#HHD$ UHH|$`HD$H L`HXHH5fJ#H>DIHHJYHcHHH|$ H1ETHD$ LxH tLxHD$E1HD$HcD$HcH@IIH~v@K47LLH@HT$HNMHDASvuHx#1H81b@HL`HFH|$ H uCHL9L dHD$ HL$(dH3 %(uVH8[]A\A]A^A_HGf.H|$ ^H|$ HmHD$ p\ hHw#H5ZH81aH ^H5ZH=ZIHw#H5"ZH81aHv#HH5\H81aHz#H5}ZH81afAWAAVAUATUSHdH%(H$1HD$0H|$ HD$PHD$8Hl$(HD$XA@H|$@Hl$HPHIֹHD$ HD$@LH DHt LcNLHL9tHPD9|HtHHL9u"]1H|$(H|$0AH7H|$8HNHD$H5OG#L'AIHHL$ LA HyHcAH9HIHl$`LDD$HL$JUEHHLd$xATDD$,HL$ Ht$pX1ZA1ILL9B?@LSkHFkH5z#LR@H$dH3%(H[]A\A]A^A_@IHA0@tr=PAEHbx#H5ZH81)lfH[H\$(H u;HHHMNHD$kk]AfDH{uPH[DYHt#H5 WH81^!pHZt#1H81^dHBt#H5YH81q^SdH5HHCH[f.ATUSHHtvHƒtiudHH9t;H5D#H>IHt2H5D#H>HtLHL]u)H[]A\fD^IHt9HC HbH^s#1H81]Hs#H5UH81z]Hs#1H81g]PX1HHs#H81G]SH5D#H=Ht!E1111AH`?uH[H's#H5TUH81\fPXH53UHHr#H81\fHH5C#\=HtHoRHHHDff.HH5AC#=Ht#HFHA% HEH_ff.@SH5B#[HcHD@HN…tHc[HDff.HH5B#\#H8IHHMBH< L|$A@DHcH@IH~FH@LLLHNL1AkuHJm#H5SH81yWfHT$dH3%(HD$uPH([]A\A]A^A_@L`HX+Hl#H5RH81#WHDm#H5qOH81 W]fDATIHUSHt:GH5=#L7Ht-HguH[]A\+UBHl#H5NH81Vf.ATIHUSHt:EGH5,=#L7Ht-HVuH[]A\THCl#H5pNH81 Vf.ATIUHHStbFHH5<#6HHt}H$@Hl: tN1ɉھ HTBt!HcHEDL[]A\DTH8k#H5NH81gUH k#H5uNH81OUHpk#H5MH817UAUIHATUHSHttEH5;#L5IHHJ?H9 t\1ɉھLzAt/HcH5o#LHTO5HH[]A\A]ÐSHPj#H59PH81TH8j#H5OH81gTHj#H5LH81OTff.@ATUSHH5'o#HGEHAHH5:#4HHHD>H8 Ic1DHHHH uGDHW@t\H[]A\HHeHǨt$_DApHHf.QAL1MHi#H5OH81/SHh#H5aMH81SH8i#H5eKH81Rff.@HHg#H|$H0VHt'H|$H59#n3Ht_H=H@H|$IH|$H u0HYHuHk#HT$H5wNH81eRDHH{h#H5JH81BRfUH1H8#SHHf#H8hHSHt+HC E111AHHB4uHH[]Hh#1H81QHg#1H81Qff.fHj#SH5KHH{g#H8 9Hh#HEf#H5JHHH8H!g#H;H5H]H;HH5 HAH;1HH5~JYH;HH5AQAH;1HH5SJ9AH;HjH5hAH;H?H5hAH;H$H5J@H;HYH5T@H;1H1H5I@H;1HH5b@H;HH5R@H;HH5Ig@H;HH5IL@H;HH5{I1@H;HH5iI@H;1H:H5_I?H;HH5SI?H;1HH5DI?H;HH51I?H;HQH5I?H;1H H5 I}?H;1HaH5He?H;HH5HJ? H=H9JH=HHi#!J[Hi#USHH(H-e#dH%(HD$1HD$HuRHH5i#H11HOH|$HD$71HKHHHHT$HZHu9aH3HT$H~rHb#H5JH81Mf.`HHL$dH3 %(H([]DH=EIHHh#7H)b#H5AJH81MH``H b#1H81mMHHm1fH5IHHa#HH81CM>Sff.UH5ISHHc#Hd#H;H4Ha#H;H5"nHHCf#Hc4H-4c#HE7HHhKH}H5IHcHHߺW[H5I]?f.YH3#1nbff.ATUSHHHƒ}HH9t:H5F3#H,IHt.H5/3#H,HteHLDtCH[]A\sHIHC HuHb#H5HH81KHPHab#1H81KHa#H5?IH81uKDUH52#HSH,Ht'HH.1HH*u"HH[]HLa#H5HH81KHa#H5HH81Jff.SHHH|$Ht$5GH51#Hv+HtVHt$H t$HVHvHtmH$_5H<$HtH]CH5&.#H'HtY1HH|&t}H4$Hu.HL$dH3 %(HuxH[]@HFf.HIH+CHC HuHC]#H5vCH81jF@H]#H5CH81CF>Lff.UH1HO-#SHH[#H8 \HBHtHC 1HH%t"HH[]H\#H5BH81EH\#H5 CH81Eff.@SH=EGH=BZH50CHHZ[#H8,H\#HZ#H5BHHH,H\#H;H5H~QH;HH55c5H;HH5;H5H;1H|H5J>05H;Hn\#H5H5H;HHH5<IH;H@H5#BSH;1HH5B4H;1HH5B4H;1[H'H5V4f.fDGAUH5+#ATUSH$H+HIHIj[HHL-x6AH=7f/HHH [HL[%IH{HBHHZH{BHHZCtBv uH=gA*/u3H=?A /gDL.PfDH=rI.4fHL[]A\A]HX#H5@H81Bf.ATUSH dH%(HD$1HӅutHD$1E1HD$H5)#H#H1LHHJHH$HL$dH3 %(H []A\HHT$tCHD$1E1HtH|$59HHD$Ht7H|$9IXDHF1HD$HuHufE1+1;H}X#1H81yAtGHW#H5k?H81\Aff.ATUSH dH%(HD$1HӅHD$1E1HD$H5(#H!H1LHH3HH"H5>HH"HHL$dH3 %(H []A\fHHT$tCHD$1E1HbH|$7HHD$Ht3H|$7I8HF1HD$HuHufE11l:HV#1H81?EHV#H5=H81?ff.AVAUIATUS\EI+HtFHL55'#DL1LUHHH>j18tDHeU#H5<H81\>ff.USHHHl$Ht$H5HHڿHH%#1TH|$HH uWHVLHHtXHE 5uAHGt?LvS#H11Ҿ}6hAHH[]fDHfHVHT#1H81=PXH5|;HHS#H81b=fATH5$#UHSHtHT$HYt$@wKH(4HHL$dH3 %(u+H[]fDHpHH#H5!2H81Z2U8H n2H52H=2fDSHHH|$Ht$u.H5#HHt6Ht$H tHVHvHHH[HHfDSH5#H\HtE1111H;H[ff.ATUSHueHt\HƒtOuJHH9t:H56#HIHt3H5#HHtHLt(H[]A\Hs5H$G#H50H810HdF#H50H810ATIUSHHH|$Ht$-H5#HPHt]LHHt$H t3H~HcωH9u2HvHE1H:HH[]A\HHAyfS1H#FHHt HC H[HE#1H81/@SH\G#H5/HE#HH;KHDE#H;H5/HHI#H(HAG#H5jHH;H;HH5/D#H;HH5d/)#H;HzH5H;HH5&sH;1HWH5u([H;HH5%3@H;H3H5&4H;1HH5.H;1HH5.H;H.H5-3H;[H.H5s&3f.AWAVAUATUHSHXdH%(HD$H1H=I#+HD$QHEH\$ 1ɺIH5I#HD$JH|$P*HD$H8 ,HxHcAH9_H!*HH bHHcAH9/H{)H8I AHHclj|$ H9HD$0=HHD$HH|$8Ht$1H$"1 Ic@HH}HO9L $E1HߺC|LMHE tLMEH߾eCeLL$I kIEH߾-CML$I$ tML$DD$ H߾BQIuIE tIuHT$H~#Ht$L-H+LHL$HdH3 %(HX[]A\A]A^A_HcH|Hu*fH@*HD$HH|$2H|$HHHD$;@HEHxMIH0H=+O&H=+H|F#7&H=%$HlF#&H=0BH\F#&HXF#pHHDH|$$fHD$uJH;H*H=F#H5*1H*H*H=E#H5*1+*H)H=E#H5v*1*H)H=E#H5*1)/H)H=E#H5*1)H)H=pE#H5c*1)HB#H5)H816H=CE#H5)1)DAWAVAUATUHSHHdH%(HD$81H=D#HD$!HEH\$1ɺIH5dD#H$[ Hc%H[%H|$III@#Hl$ @HLd$(AIH\$0HH1IH@I tIFI L$IOIWI0 HIxSIMPjAT+H HT$8dH3%(LHH[]A\A]A^A_HcH|HuJWfL$HIWI0 iIpIxgD 'HD$H H|$RH|$HHHD$K@H= ("H=HB#"H=_HB#"H=:H|B#g"H=U HlB#O"HhB#Hx,H2L%IH$H$IHHDH|$ HD$uJH=&B#H5^'j&e,DAVAUATUHSH@dH%(HD$81H=cA#HD$ SH\$HE1ɺIH5&A#H$= HE"H="H|$H@F$H|$ A@H|$(Hc1IIH@I tIFH HHSH<$H7 HHPMEUZYHT$8dH3%(LH@[]A\A]A^fHcH|Hu:/H|$ A@%T# D$HD$HH|$Z H|$HHHD$q@LGMcDM9H@H{Hc׉H9HSDH=$w H=%HD?#_H=MH4?#GH=X;H$?#/H ?#HHDH|$HD$uL5H=>?#H5$#})ff.fHHI9#H5u$H8b)H:#H5c$HH>#H H=>#HH5@$H># +H=>#HyH5#*H=>#HHfH5$*f. SHHH|$Ht$H5 #H6HtfHt$H t4H~HcωH9u3HvHHxt$HD$H[HH3HW;#1H81"H<8#H5F#H81"UH5D #SHdH%(HD$1H1HH$(HcH1HH@H uQHHH$'~[HH4$ tBHCHSH)H9jH"HHL$dH3 %(unH[]HCf.HHSH6#1H81 !HA7#H5K"H81!H #{H5G"H=O"&@SH5$ #HHH@Hc0~Hx[fDH6#H8t 11[ H9# H=( H 3H H=!3H;A1H !H HS6#H5]!H81 f.UHH5Q#SHHt`HHw0HH$HHtuH[]@c#H1[]H8#H5"!H81H5#H5 H81zf.PX1HH8#H81WATUHSHH*HI H5x#HHHtHLHt H[]A\H5#H5) H81qATUHH5#SyHt-HHI/IH#LH#7t H[]A\H4#H5H81H7#H5 H81gHH5#HtHHt$HHHO4#H5YH81UH5T#SHHt5HHEHHtMHH,H߅t#H[](H3#H5H810H6#1H81ff.SH5#Ht+H#HHt;HHcH9u#H߉[5H`3#H5jH81'H.f.S1HR#2H5,Ht HC H[rfUSH(dH%(HD$1HuGHH|$HD$HD$H0 uFHHx&HHtMH{ eHk HL$dH3 %(HH([]HxHc׉H9u}Hx HHuHD$H u?HHHD$Ht$14HHyH 5#1H81@HPHT$HPº1%@-!ff.H1#SH5QH8!H3#H?0#H5=HHHH4#H;H5iHH4#HH1#H51HH'H;HGH5 k H;1HH5'S H;1HwH5; H;HH5 H;1HH5 H;1HQH5 H;HH5e H;H+H5", H;HPH5# H;1HhH5# H;[H|H5p UH5#SHdH%(HD$1H1HHTHcH1 HH@H uQHHH$"~[HH4$ tBHCHSH)H9jHHHL$dH3 %(unH[]HCf.HHSH 1#1H81@Ha/#H5SH81(H !H5RH=o@WSH5#HdH%(HD$1{HtTIH111`HHHthH4$HdH߅t8"HT$dH3%(uH[H.#H5H81ZU0+H 0#H5H818H/#H5sH81 SH5#HdH%(HD$1HtlHI111%H$10HcHH$HsHcH u,Hx3'HHL$dH3 %(u.H[f.HsH-#H5H81rmff.fSH5#HdH%(HD$1Htl1IH11eH$10HcHH$HsHcH u,Hxs&HHL$dH3 %(u.H[f.HsH,#H5H81ff.fATUSHujHtaHƒtTuOIHH5"HHt=H5"LHt)H Ht4HC HH[]A\HH?,#H51H81H-#H5YH81ff.UH5"SHdH%(HD$1jH1HHtHcH1HH@H uQHHH$B~[HH4$ tBHCHSH)H9jHHHL$dH3 %(unH[]HCf.HHSH,#1H81H!+#H5 H81H !H5H=/@*USHHH(Ht$dH%(HD$1F H|$HD$H5"HHHHD$H tGHPHT$HP1Ht$Ht;HC H5*HHL$dH3 %(u4H([]HHHD$H+#H5YH81H)#H5H81ATUSHuqHthHƒt[uVIHH5"3HHtDH5"LHt0H=,#Hh Ht4HC HW)H[]A\HHX)#H5AH81H*#H5H81UH5d"SHdH%(HD$1H1HHHcH1HH@H uQHHH$~[HH4$ tBHCHSH)H9jHHHL$dH3 %(unH[]HCf.HHSH)#1H81 HA(#H5H81H !}H52H=O@ATUSHuqHthHƒt[uVIHH5"CHHtDH5"L,Ht0H=x&#Hx Ht4HC HH[]A\HHh'#H5H81/H(#H5H81SHdH%(HD$1HtYH$H5J"HH1HjHL$dH3 %(HH[DHH$HtH H5"HHtHH4$H t#H~HcωH9u^HvHHH1 H@&#H5H81H'#1H81j!f.WATUSHuqHthHƒt[uVIHH5"CHHtDH5"L,Ht0H=('#HxHt4HC HH[]A\HHh%#H5H81/H&#H5H81USH(dH%(HD$1Hu|HHD$HtnH5C"H{HHH|$uH|$HD$ HD$H uIHHHD$1Ht$-Ht`HC H, HL$dH3 %(Hu$H([]fHPHT$HP븺10HQ$#H5H81H%#H5H81UH5"SHdH%(HD$1H1HH4HcH1HH@H uQHHH$~[HH4$ tBHCHSH)H9jHHHL$dH3 %(unH[]HCf.HHSH$#1H81 HA##H5H81 H H52H=O@ATUSHuqHthHƒt[uVIHH5h"CHHtDH5T"L,Ht0H=!#HxHt4HC H7H[]A\HHh"#H5H81/ H##H5H81 USH(dH%(HD$1Hu|HHD$HtnH5"H{HHH|$uH|$HD$HD$H uIHHHD$1Ht$Ht`HC HLHL$dH3 %(Hu$H([]fHPHT$HP븺10HQ!#H5 H81 H"#H5 H81 UH5$"SHdH%(HD$1H1HH4HcH1HH@H uQHHH$~[HH4$ tBHCHSH)H9jH HHL$dH3 %(unH[]HCf.HHSH!#1H81 HA #H5 H81 H H52 H=O @AWH5"AVAUATUSHrHHInAŅ~BL=#1HD$@LI?1H*"HrHIH/Ht=IF H|$L A9uHD$H[]A\A]A^A_DHD$H #1H81 H+#H5 H81fATIH5"USHHt?H5z"LHoHtxHIHtPHH Ht H[]A\H#H54 H81zLH+ #H5U H81ZH #H5 H81BHc#H5U H81*f.SHdH%(HD$1HtYH$H5"HH1H HL$dH3 %(HH[DHH$HtHH5"H,HtHH4$H t#H~HcωH9u^HvHHH1HP#H5 H81H#1H81 zf.USH(dH%(HD$1Hu|HHD$HtnH5"H[HHH|$UH|$HD$HD$H uIHHHD$1Ht$-Ht`HC HHL$dH3 %(Hu$H([]fHPHT$HP븺1u H1#H5H81H#H5H81PXH5HH#H81fHH5a"dH%(HD$1LHt/111IHH<$}HT$dH3%(u H^ ff.UHH5"SHHt2H5"HHHt3HHPHH[]H!#H5H81UHH5"SHwHt2H5k"HH`Ht3HHHH[]H#H5H81xH#S1HH "H8THtHX [d@AWH5"AVAUATUSHxdH%(HD$h1HD$H H|$HD$8D$HD$`1HD$HD$XHD$ HD$PHD$(HD$LHD$09l$oH|$GHHtLD$HL$ HHD$`HT$(Ht$0HD$XHD$P(AąxHHIHBLILHIcLHt6zHct$LLHt6hH|$PHtHLIH|$XHtuHL*H|$`HtVHL 6HI AŅ~+E1DHAH9LHE9uLLH|$8L9l$HT$hdH3%(HD$8u'Hx[]A\A]A^A_H1#H5H81H#1H81PXH5HH#H81fH#S1HH"H8HtHX [@USHHH5-"H$HHH5"H HHtMHHt,HH=#H3HtJHH[]PH[]H%#H5H81H #H5H81H#H5KH81ff.PX1HHa#H81S1H2"}HHt HC H[fAUH5c"ATUSHHtTHHHcIIE~(1ېHHLHpA9uHL[]A\A]HH5"dH%(HD$1lHE111HHq xQu4H<$Ht:HL$dH3 %(uHDdH#H5H81LH#H5UH814HU#H5>H81ff.PXH5HH#H81fHH5"Ht!E1111H x$HHHDH#H5H81fHH5"dH%(HD$1HtP111IH& x6H<$Ht!HT$dH3%(uHH8#H5!H81ff.@HH5"dH%(HD$1|HtPE111HH x5H<$Ht SHT$dH3%(uHfD|gH#H5H81_ff.@HH5Q"HtHoHHH6fDS1H"HHt HC H[2fPXH5jHH#H81fAVH5#"AUATUSXHHH HcIIE~FL5#1HLHkHt'HǃLHA9u[L]A\A]A^H#H5H812fUHH5q"SHHt0H5"HHHt1HHHH[]HDH#H5GH81H#H5LH81fS1H"}HHt HC H[fUH5$"SHHtLHH#1H"H8*HHHtHE HH[]@HH[]@HH5"HtHOHHHDff.HH5q"LHtHHc7HHfDS1H2"]HHt HC H[fUHH5a"SHHt0H5"HHHt1HH`HH[]HDH#H5H81DS1H"HHt HC H[fAUATIH5>"UHSHHXdH%(HD$H1HuIHD$HD$0HD$HD$8HD$HD$@CI<$H|$uwHD$HD$uyH|$ HD$ \HD$ H HPHT$(HP1Ht$(BHupH#H5 H81DID$HD$uID$HD$2H|$H%H|$I1HtLHHHtSHE LHHL$HdH3 %(uLHX[]A\A]HHHD$(=jH#H5VH81H#H5H81DHH5"lHtHHHHЃH #H5@H81fDAUATIHUHSHt\?Ht\H5"HIHt]1LH"/ LHHt'HE HH[]A\A]HuE1H#1H81ff.HH5"dH%(HD$1\HtH81H4#H5H81F AUATUSH(dH%(HD$1IսtIH>A1Ht/@rILATH5{"LH11HL$HLD$Ht$H|$HcHcWu1H\$dH3%(Hu\H([]A\A]fLf1HP@?Q:f.;B1H\#H5H81H#H5H81sff.GAVAUATUSH.LfuLLvHH5"HHL%IILALc*H5Y"HHHLE1IHoHLLHHKH5#Hj~[]A\A]A^+[1]A\A]A^LcE1뚺Hs#H5H81:f.GAVAUATUSH.LfuLLvHH5."HHLIILALc*H5"HaHHLE1IH?HLLHHH5l#H:~[]A\A]A^[1]A\A]A^LcE1뚺HC#H5H81 f.AWAVAUATUSHxdH%(HD$h1HD$HD$@HD$ HD$HHD$(HD$PHD$0HD$XHD$8HD$`GHHӹHD$HFHD$ HD$@L@@Ht LcN L HL9tHP9HtHHL9uH5i"HIHH|$1H|$ IH|$0IHH|$8H6H|$(HHHE1ILLML)H5#LxHH\$hdH3%(Hx[]A\A]A^A_f.@tJEH|$8HcHhH|$(HHhHL$HL$IXD봺jH+#H5H81H#1H81f.AWAVAUATUSHxdH%(HD$h1HD$HD$@HD$ HD$HHD$(HD$PHD$0HD$XHD$8HD$`GHHӹHD$HFHD$ HD$@L@@Ht LcN L HL9tHP9HtHHL9uH5y"HIHH|$1H|$ IlH|$0IHH|$8HH|$(HHHE1ILLMLyH5z#LHHH\$hdH3%(Hx[]A\A]A^A_f.@tJH|$8HcHhH|$(HHhHL$HL$IXDk봺:H"H5_H81Hv#1H81f.H}"ATH5USH8H#Hd#H5HHHL%#H;H5H#HI$H-d"H5]HHEqH}HAH5UH}HH59H}HH5SH}H}H5AH}HH51H}1HH5H}1HH5 H}HSH5H}HH5{H}1HH56bI$H;H5H-h#HlHH5HEH}H5^H}HH5H}HH56H}1HH5H}1HH5H}1HH5 H}1H9H5Q}I$H;H5H-"H5|HHEPH}H H54H}HH5mH}HH5H}HH5H}HH5WH}1H'H5H}1HH50H}HH5vH}HFH5ZH}HH5I>H}1HH5%I$H;H5BH-"H5HHEH}HH5xH}HH5H}HpH5iH}1HH5H}1H>H5FrH}1H%H59YH}1HlH5,@H}1HH5'H}1HH5H}1HQH5H}1HH5I$H;H5H-"H5HHEH}HH5/H}HH5wH}H7H5X[H}HH5r?H}1H"H5d&H}1HiH5R H}1HH5JH}1HH5AH}1H^H5H;H5#H;H5H;HH5tH; H5`H;H5#LH;H5*8H;H5Q$H;H5H; H5QH; H5]H;H5H;H5H; H5 H; H5H;H5H;H5#pH;H5\H; H5 HH;H54H;!H5 H;AH5 H;H5H;H5H;H5H;H5H;H5 H;H5H;H5H;H5lH;H5XH;H5DH;[]H5A\,f.fUH5d"SHdH%(HD$1jH1HHHcH1HH@H uQHHH$~[HH4$ tBHCHSH)H9jHHHL$dH3 %(unH[]HCf.HHSH"1H81H!"H5fH81H H5dH=/@AUATUSHHdH%(HD$81HB D$HD$(HD$0HӅSHHD$cHD$E1H|$Ht$0HH}HD$0HHC GH|$0HL$ LHT$LD$(tHt$HH=y"HT$oT$IŅ Ht$ HH= "HT$Ld$H|$KH|$HD$ܵ11LHHHtUHD$HHC 4H5H@H5H,HL$dH3 %(HumH []A\11ҾHLHOHuHH|$H"HC H5H811 ATUSHuoHtfHƒtYuTHH9tDH5"HIHt=H5"HHt)HHt4HC LH[]A\HH:"H5.H81H2"1H81ff.PXH5HH"H81fHH5"\Ht HxHDHH5q",HtH@HxHfHH5"HtH@HxH6HW"H51H81ff.HH5"謪HtH@H8H駵fPX1HH "H81USHHHKH5"HHIHtHH)t"HH[]H"H5ZH81c~ff.S1H2"=HżHt HC H[BfHH5a"輩Ht44HHt:8tHfDHxHH"H5H81fDAUATIUHSHHH!LI&HI˶H5ij"HHHt#HLLHct&HH[]A\A]Hb"H5<H81)D@S1Hb" HէHt HC H[fUH5"SH芨Ht5H}H%HHtMHHH߅t#H[]H"H5H81cH"1H81pff.PXH5zHHt"H81BfSH5"Ht(HxHrt t1[@HC [H@HHHATIUHSHHHHuH5"HtMHLr11話H[]A\ÐH=6HHU"SH5"Ht(HxH蒮t t1[@HC [H@ATIUHSHHXH HuH5"HtMHL"11H[]A\ÐH=vHH"H3HHATIH5 "USHHt"LHvHHKt H[]A\H`"H5TH81'BfHHH두ATIH5"USH覥Ht"LHHHkt H[]A\H"H5H81fHHH두USHHH5}"H4HtKH5"H="HiHHtjH5 "HHtQHHt"HH[]HU"H5H81H$HE"H5+H81H("1H81@ATIHH5"USvHH5v"H="H觻HHH5D"LH2HiL[]A\HHZ"H5YH81H="1H81H"H5H81UHH5"SHwHt$HHHH,t"HH[]H"H5H81SH5$"HtH^twHE1IIHH5"蒞HH聺H)HHHEHLLH߅tn[]A\A]A^DLfHIIIt(LAtEAlDӻAZE1R蔷H`"1H81H="H51H81@AVAUATUSH`dH%(HD$X1HD$Ld$D$ HD$0HD$ HD$@HD$(HD$HGLd$8HHHD$HFHD$u.HD$ HD$(H|$ Hu3ܿI1HFHD$ uHFH|$ HD$(HtIH|$(1Ht@H)"H"1H8LHUH|$Ht$ IIƋD$ LLLDLHHt}Hk HT$HH5蜝H5"L]HHL$XdH3 %(ueH`[]A\A]A^DD譵L%|$ H5("LHY"1H81AWAVAUATUSHhdH %(HL$X1HT$Ld$D$HT$0HT$HT$8HT$ HT$HHT$(HT$PWLd$@rH>H^HVH|$H\$HT$uHD$ HD$(HVHT$ uHF HD$(H1IH|$(IHt@ H9"Hʥ"1H8LHeH|$ IHHt$INjD$ALLLLHHC HT$H5H襛H5H葛LiH5z"LJHHL$XdH3 %(u}Hh[]A\A]A^A_E1n軷 腳L|$dLH5"LH."1H81DAUATUSHHdH%(HD$81HD$H\$HD$ HD$HD$0GH\$(H.Hl$HD$HD$E1H|$HH5 "HHbE1H|$H菮HH DLHHҢLH:HL$8dH3 %(HH[]A\A]HFHD$HH~H|$H>@t]舨H|$A3H5HHD$Hxǟt2H|$H辠IfD˵A11ɾHD@HDEHLHA"1H81NH "H5H81ѶE1fATH"H5L%"USH8I$H"H"H5HHHH"H;H5HHH;H`H5H;HH5H;H H5ΩH=BH;E11ɺHH=4aH;E1HƺH;H5H;HH5{ߥH;HH5ĥH;HH5詥H;1HH5葥H;HbH5ҿvH;1HH5Ŀ^H;1HH5FH;HH5+H;HH5H;1HH5H;HH5qݤH;1HH5gŤH;HVH5W誤H;H+H5L菤H;1HH5BwH;HH54\H;HH5!AH;1HH5)H;HH5H;HH52H;HH5ݣH;HNH5k£H;1HvH5&誣H;HH5:脸H;1H(H5P|I$H;H5]虚H-"H;H5RHHEH}H.H5H}1H3H5עH}1HZH5Ľ辢I$H;H5ۙH-"H5HHE葾H}HqH5ʢuH}1HH5\H}1HoH5CH}1H&H5J*H;H5>H;H5H; H5H;H5H;!H5qH;AH5uH;H5˼H;H5zH;H5fH;[]H5A\Nf.@HH=<dH%(HD$1HT$rHcD$HL$dH3 %(uH賶HHf׿USHHHt8~ttA=uJHH[]̗@u3HH[]eDHH[]rfHH[]fHA"H"1H81H5HX HHБHH[]H"H5jH81讯ff.H"SHH0IHuH[H"H5!H81gSH"1MHUHtHC H1H5a+H[H"1H81AUATAHUSHdH%(HD$1ՓHÅu4CHL$dH3 %(H[]A\A]DIc1HHTIHcվLHTH="HT$LD$xC1DC1H=8SZ$@G@SHHH=~HdH%(HD$1HT$耙T$uHL$dH3 %(uH[H |$謳ff.ATUSHdH%(HD$1G,HH$t\"HI跖1HHHHtBHHHL$dH3 %(H[]A\DH~f.11ҾH菿蚰L1HH"覦HHu11ҾH]h1HnHH`11ҾH1<1HLH%"HHMH*H"H5H81L蝦8USHH(dH%(HD$1HHH裙~@t=uHHtIHD$dH3%(H([]Du1HT$HHH<$tH|$uH"H5\H81jf.1Ht$HAH|$u1Ht$H聑H|$]H"H5H81fDAUATUSHHH5"HT$H $芋H7HI覯HH|$IHD$H HXHcH9H#HH1LH H4$H HHH?Ht$H uoHHLȝHnu*赭H1[]A\A]HH@u)H[]A\A]HVHvtHvHK"H5۶H81蚩H"H5H81rHH"H5nH81bH躶H"H5`H81BH蚶Hӿ"H5RH81"fHH5"載HtHH#"H5H81ڵf.SH5"11H8HuH5k"HcHt[H"H5H81蔨H"H5H81lff.AUATUSHH(HT$dH%(HD$1ճHI芖H|$I荤L1Hc H賤H1LHH蚇Ht$H tuHVHvHՙtnHuHE tHuLHHT$?HAEt\t$H#HHL$dH3 %(uUH([]A\A]DHHH軴H"H5H81CHܽ"H5H81+&H~H"H5nH81H"H5H81ff.SH5"HtHH诓H[Hۼ"H5H81蒳fUH5dSHHp"H8萬H"H-2"H5HHHE܍H"H}H5HH"H踍Hy"H}HH5HH;H5SH;1HWH5;H;HlH5 H;HH5H=C9H"-XH[]ȧUSH8H5"dH%(HD$(1 HCHHLHeHL$HT$HHHHT$ Ht$H[覙H<$H芆H=H֐HHHH|$^H=H誐HHH輐H|$2H=H~HHH萐H|$H=aHRHHHdH|$ څH==H&HHH8HHL$(dH3 %(uH8[]H/"H5H81H"H5ƱH81٣fAUIATU1SHHt$H$Ht H|$褈H1H<$t H萈HH56"L.IHHuwL荮IHtH=HHt5HtH(HHt HHL肬t`HL[]A\A]H記1衘H"1H81H"H5ðH81֢H"H5ïH81讯HVHNHG"H5H81薢fDAVIAUATE1USH Ht$HT$HL$Ht H|$[I1H|$t H|$DH1H|$t H|$-HH5Ӹ"L˂IHH跏L&IMtL֖IHtOHtHHHtH_"H5H81&HG"H5H81H~H~H"H5H81fDAVIAUATE1USH Ht$HT$HL$Ht H|$mI1H|$t H|$mH1H|$t H|$}mHH5#"LiIHHvtL薁IMtL&}IHtOHtH}HHt"HŅtRIEH$uI}HlqHHu-H>"1H81jf.H$HHھtHPHL$dH3 %(LH[]A\A]fDuHt tSf.tH<$H蟋HH$3iHt"H1HIpHHt4L茒WH~HH< 11ҾL111Ll{HHu11ҾL1LdHHt11ҾL跑‚1L^HHH11ҾL苑薂E1E11H="LH5HcLH蝑Hd_Hp"H5H81~1x脄H"H5qH81\Hff.@ATH"I1US;HCgHtVLtHH+}t'Hk H1H58|`H[]A\f.H16H[]A\fD1H[]A\ff.UHSHH5\"W^HHHCktuiHvH="H5`"HpuHH5Ht HHHtH[]fH踃H"1H81%}HF"H5H81 }H."H5H81DPXH5ƋHH"H81|fSHH5p"dH%(HD$1[]HtIHHKjtuVHu1HHqoH<$HHЃHL$dH3 %(uH[H~"H5JH815@Kff.SHH5В"dH%(HD$1\Ht_HHituJH>uH1HnH<$Ht c]HL$dH3 %(uH[D謁Hȑ"H5H81ff.@SHH5 "dH%(HD$1 \Ht_HHhtuJHtH1H!nH<$Ht \HL$dH3 %(uH[DH"H5H81χff.@SHH5p"dH%(HD$1[[Ht_HHKhtuJHsH11HH<$Ht\HT$dH3%(uH[LWHh"H54H81ff.@SHH5"dH%(HD$1ZHt_HHgtuJH.sH11H_H<$HtQ[HL$dH3 %(uH[H"H5H81off.@SHH5"dH%(HD$1YHt_HHftuJH~rH11H诅H<$HtZHT$dH3%(uH[~H"H5ԅH81迅ff.@AVIAUATUHSHH5Q"dH%(HD$1AuMfHt%芎LHlIf.A1tHknHHtz1HLjH<$tOHL "1HATE1LHOZYt8HHL$dH3 %(uaH[]A\A]A^@LHeuHiHJ"1H81vw1qH"H5UH81@K}Hl"H5H813wUHHSHt+gHHt+HHHtH[]kudHHuHT}H"1H81vUHSHH5\"dH%(HD$1GWHtxHH7dtucHo1HH]iH<$t&HL$dH3 %(u-H[]f.H5jtHAH1Hu|*H;"H5H81fATIUSH0Ht$H5"dH%(HD$(1VHeHHlct9Hn11HT$HH'H|$Hl$ 1HHihH|$ H|$qH[`1HcAfIHHH tHHHt$H tXH~HcljH9Hv1IIWt$ LvLHL$(dH3 %(uOH0[]A\DHHH5rLɄHBHp"H5H81tzHS"H5H81ztH"H5KH81btH"H5OH81:ŅH"1H812tfUSHHtQHҊ"HH"1H8HHatuaHk 1H5rHUHt4HH[]f苋HtHHt"H8dHHi"1H81sH"H5H81}sff.fSH"H5H"HH;ZH "H;H5HHx"HZHى"HHH5HfH;HH5c8cH;HH5icH;1HH5QcH;1HH57bH;1H!H5XtbH;HH5bH;HH5 twH;HH54j~wH;1H"H5J_vbH;1HZH5p^bH;HH5CbH;HH5(bH;1H\H5WbH;1HH5aH;1HH5aH;1HH5taH;1HMvH2t"H5pH811_HRu"H5ypH81_H:u"H5lH81kHjx"H5nH81^fUSHHt$H5zu"u?HHHaL=H~HH|$Hu#1HY`w5HD$H[]H|$fCHHH(`u$HtH8s"H5pH817^uHD$H[]H@t"H5goH81^H(t"H5jH81jff.@UHSHH5|t"w>HtOHHgK=HGH5mJ"HHB>HtJHHRKu"HH[]Hs"H5`jH81KjHDr"H5>oH81C]Htq"H5!mH81+]HLs"H5snH81]AUIATIUSHH-s"H=HtsHHJHLz=HHtMHjJ=HFHRHHtZH¾H[t&HL[]A\A]Hr"H5biH81MiH=H>q"H5knH81=\H&q"H5HnH81%\HFr"H5mmH81 \Hp"H5nH81[DUSHHSs"H|$H0_HtIH|$H5H"pAH<$uM~HHp"H0x^HH<$L:HHHG=HCHOHHtYH꾘H YHL$dH3 %(LH[]A\A]A^A_fDH${;HHuHn"1H81YH q"H<$H0]HLH9r"tH9r"t%H9q"u#[D[f[Hn"HH5kH81Uff.AWAVAUATIH5A"UHSH,6HH5lq"HHFH5*B"H6HHL.E11HL=n"HAMIIHtMH1EMIHHH u*MDHHyIHtHL[]A\A]A^A_fHHH3n"H5;gH81THh"H5dH81THn"H5\dH81TfUH5@"SHH5Ht@H5[p"HHEH5A"H4HtJHH!>u"HH[]Hm"H5cH81 THk"H5fH81SH#h"H5cH81Sf.UH54@"SHHg4HtJH5o"HHDH5i@"HA4HtTHml"HHHWEu"HH[]Hl"H5*cH81PSHIj"H5eH818SHig"H5cH81 SUH5?"SHH3HtJH5n"HH DH5?"H3HtTHk"HHHju"HH[]H!l"H5zbH81RHi"H5MeH81RHf"H5fbH81pRPXH5SbHHf"H81RRfUH5>"HSH2HtpH5+n"HHPCH5>"H2HtEHH8tuH[]@H1[]Hh"H5dH81QRH+k"H5aH81Qf.UH5d>"SH:2Ht7H-NHGHHtOH1HKH߅t#H[][He"H5,aH816QdHbe"1H81QHOe"H5aH81QfDHH5="1HtH\HHHD^ff.UH5="SHZ1HtAHH*7HHt"HVHH[H]iAfH[]ff.@UHH5="SH0HtHHH߉LHH[]ff.HH5<"0HtgH.t*tEt0Hc"H5HfH81OfDH=k"Hp_H=k"H`_H=k"HP_ ff.USHH50<"H0Ht3HHuMHX[HH[]fD@f.HH5;"/HtHJHHHDnff.HH5;"l/HtHKaHHfUSHHtQHBU"HHpU"1H8THH[,=u_Hk 1H5<H Ht2HH[]; HtHHT"H8HHAS"1H81E>HR"H5QH81->ff.fAUH5QATUSHHR"HT"H;Hr%HR"H;H5bQHHU"HO%L% W"H9T"H5>QHI$H+%H-U"I$H5#QH;HE %L-T"H}H5-L%tT"IUI$$HQ"I<$H5-HIU$HV"H=PHLH=PH]Y"LH=PLH=PH6Y"LH=PHY"~LH=PHY"kLH=P_LH=PHX"LLH=PHX"9LH;H5pPHX"SH;H5aPSH;1HNH5N20H;HsH5J0H;HHH5,|,H;H H52a,H;1HH5PI,H;H H5O.,H;1HH5:,H;HH5O+H;1HH5w:+H;HH5S=+H;1HH}1HH5L)H}HPH5L)H}1HH5kL)H}1HH5H81>HV'HN'HGH"H5HH811fDAVIAUATE1USH Ht$HT$HL$Ht H|$[I1H|$t H|$DH1H|$t H|$-HH5G"LIHHLIMtL%IHtOHtH%HHtH9t(H=QK"H\$@H3>H9H|$HH5oE"LIdIHH|$LHD$*L*$+HHHT$1Ht$8MH%H|$8E1_H|$8E1=H|$81MHt$(H HVHvHHt$ H \HHH/!D1H:1HL$xdH3 %(HĈ[]A\A]A^A_@'fHHZH|$@@AED[,HD$8HtH|$8HT$8uHtHHDHD$8 XHT$_@H=,'HHH"[AuMnHt%?LHIf.A1%HHHHT$Ht$LH|$tUH|$tMHL >"1HAUE1LHm1ZYt6H3HL$dH3 %(u_H []A\A]A^fLHuH;H"B"1H81(1"H>"H5u5H81`5k.H>"H5e?H81S(USHH5>"HtHHuWH H$HmHHt$H1H(AH߅t H[]&2:HZA"1H81'H="H5>H81'H="H54H814ff.AUIATIUSHH-%>"HHttHH HLHHtNHuqHH5n<"H=w<"HHt6HH¾&HL[]A\A]H="H53H813HU@"H5/H81&H<"H5=H81&H%@"H5%>H81&@SHHOHWwH?C 1[ff.AWAAVAUATUHSHHdH%(HD$81D$ HD$I$IMMI 1Mu@tXHsL,uL>LE1q7L>HL$8dH3 %(LHH[]A\A]A^A_kH\$H5<"LH!|$Ll$Ld$D|$ Lt$(t|H>"Ht$HH=L.>L6>T$0aL6D$ uLE1ID$rLE16L=L=LLDLD$0i(|$ >*ff.ATHG;"I1US:H HtVLHH{#t'Hk H1H5"RH[]A\f.H13H[]A\fD1H[]A\ff.UHSHH5:"Ht}HHuUHHR8HHH11H_2H<$HtHT$dH3%(uH[L(Hh8"H54/H81/ff.@SHH58"dH%(HD$1Ht_HHuJHH11H1H<$HtQHL$dH3 %(uH['GH7"H5.H81o.ff.@SHH58"dH%(HD$1Ht_HHuJHH11H0H<$HtHT$dH3%(uH[&H7"H5-H81-ff.@SHH5`7"dH%(HD$1KHt_HH;uJH.H1HH<$Ht HL$dH3 %(uH[D<&HX6"H5$-H81-ff.@SHH56"dH%(HD$1Ht_HH uJH~H1H1H<$Ht CHL$dH3 %(uH[D%7H5"H5t,H81_,ff.@SHH56"dH%(HD$1Ht_HH uJHH11H6H<$HtHT$dH3%(uH[$H4"H5+H81+ff.@SHH5P5"dH%(HD$1;Ht_HH+ uJHH11HO6H<$HtHL$dH3 %(uH[,$HH4"H5+H81*ff.@SHH54"dH%(HD$1Ht_HH{ uJHnH11H5H<$Ht1HT$dH3%(uH[|#'H3"H5d*H81O*ff.@UHSH(H53"dH%(HD$1H|HH HHT$Ht$H`H|$t(H|$tHL$dH3 %(uAH([]@H5H,HHEH2"H5)H81z)"0GATUSHL&tALAtN. HމHHtNHHHt>[]A\H^HttAHLAuHމHHuH-H_5"1H81HHdAUIATAHUSH(H5B2"dH%(HD$1-HHH WH11Ht$HH43H|$AD$IEHD$AAH|$gH/1Hc HHPH tHPHD$H8 }HHpHcH9EH{)HcH(HHL$dH3 %(H([]A\A]fDI}@t&A AHfHpHxfDA"DH3"H51H81 H*0"H51H81H0"H5&H81&T+HM3"1H81ff.AUIATAHUSH(H5B0"dH%(HD$1-HHHWH11Ht$HH41H|$AD$IEHD$AAH|$gH/ 1Hc HHPH tHPHD$H8 }HHpHcH9EHHcH(HHL$dH3 %(H([]A\A]fDI}@t&A AHfHpHxfDA"DH1"H5/H81 H*."H5/H81H."H5$H81$T)HM1"1H81ff.AUIATIUHSH8H5@."dH%(HD$(1+HHHH11Ht$HH2/H|$|HT$ Ht$H H|$H|$ EIEAHD$uI}@AH|$,H 1HcHHPH tHPHD$H8 HpHxHcH9EHHcHHHL$(dH3 %(H8[]A\A]fDH5bL9&HH/"H5-H81HHpfkA 2H+"H5"H81"H3/"H5K-H81H+"H5,H81'H."1H81rmff.fAUIATIUHSH8H5+"dH%(HD$(1HHHH11Ht$HH,H|$|HT$ Ht$HDH|$H|$ EIEAHD$uI}@iAH|$H1HcZHHPH tHPHD$H8 HpHxHcH9EHC HcHHHL$(dH3 %(H8[]A\A]fDH5L#HHH-"H5o+H81HHpfA  H)"H5o H81Z H,"H5*H81RHs)"H5L*H81:$H,"1H81"ff.fAUIATIUSHHH5)"dH%(HD$1HHŅuRH$5 HHھHHL$dH3 %(L|H[]A\A]IEH$tH)fuHt fDH<$HHH$cH'"H1HIHHL$!I}tHe@tEHHVHH5HHH+"1H81vfDHH$ƒ11ҾL#111LyHHM11ҾL#1L= HH!11ҾL#1LHH11ҾLd#o111LAHH11ҾL4#?1L!LHZ#HH)"H5H81Yf1һH1 HM&"H5H81H!~fAWAVAUATIUHSHHdH%(HD$81H=,"HD$FI$ID$LD$ 1ɺH5+"HD$H=+"Ll$ H;AI9t)H=+"Ll$ H+AI9H|$(}HIHIHHcHT$WH|$IZ Ht$1H HH1Ht$MLHUH|$E1PZH|$E1D-7H|$1M Ht$H HVHvH1HuHE tHuHT$H)Ht$HHKHHL$8dH3 %(HH[]A\A]A^A_DHcI|HuB7HHWH|$ @\A=@ HD$HH|$H|$HHHD$I$yH= AYHH?)"I9\@H=$'HH)"X H=$ H= $H("H(" ADHHDH|$fHD$uHH%"1H81" ff.fUSHHtQHz#"HH""1H8!HHuaHk 1H5 HHt4HH[]f+HtHH#"H8HH%"1H81u H"H5-#H81] ff.fSH!"H5#H"HH;H$"H;H5"HHX""HH""HuHH5yHH;HH5mH;H)H5H;1HqH51H;1H9H5H;1H!H58 H;HfH5H;HH5 tH;HH5^H;1HH5*VH;1HH5>H;H/H5!#H;HH5!H;HH5!H;H.H5!H;HsH5!H;HXH5v!H;1H@H5H;1HxH5lH;1HH5TH;1HH5H5 H;HH5 H;HH5 H;HH5 H;1[HH5x UHSHdH%(HD$1HHHHHHHHHtHt$HHHcHt6WHct$HHt6EHT$dH3%(u HH[] fDAUIATUSH(H_DgdH%(HD$1" IHD$L9s,DHkHHHKH|$HI9wH5!"I}HL$H|$HD$HD$H u3HHHw*HL$dH3 %(uH([]A\A]@HPH=>!"H51H9 u!HHHHcH9u:1fDHAHyHPff.fUHSHH5" HtsHHxH[]H5"HYH1HhHHHuHuH=_ "H5H"H5H81ff.H"1ff.ATUSHHHƒtwurHHH5@!HI0 LH%Ht/@tHHLKH[]A\H8HLT#H[]A\HSATUSHujH.HH5!hIHtaH"HH0]HH5"HtX11HtsHLHH[]A\fH5I!HI1LHH[]A\@H=o11HHH"yuHLHBH[]A\ú1>H"H5H81fDUSHH5!HWHtHHH1ɾ*jHH[]HHUSHH5P!HHtHHH1ɾ,HH[]HHHH5!1ɺ!HHff.AT1USHHdH%(HD$1D$rHt\5"HH\ILHHHHHHT$HH=AHcT$u!1HL$dH3 %(u*H[]A\fDH5y"HTLATIH=TUHSHH0dH%(HD$(1HT$ Ht$Ht$LD$DL$ jHƋD$ uOH u/HHHuHL$(dH3 %(uTH0[]A\DHVHUVf.5"L"HcT$ H5"HHT=ff.fAVEAUIATIUHH5"SHL6EMLHHH[]A\A]A^AVEAUIATIUHH5R"SHLEMLHHH[]A\A]A^HH|$ H|$1H5"HHtH5"HL$HHf.SHH|$h H|$1lH5"HHt511HaHtH5<"HL$HBH[@H=#HH="ff.SHH|$ H|$1H5"HHt511HHtH5"HL$HH[@H==#wHH"ff.ATI5E"UHS1H=nHH1Ht IHT "H8HHH] LHH HH HT$HH={HD$dH3%(urH[]A\DL%i " H=I $I $#H=z I<$1AH H\ff.@ATUHSHHdH%(HD$1H' "D$H85s"HIH"H8uHHH] lLHH^ HHS HT$HH=oHcT$u&1HL$dH3 %(H[]A\H5"HTL,f.L% " H=I $I $ H=: uI<$1AH NHAWAVIH5!AUATUHSHHIčEI>MnHD$HHƒ*LILIIHMLLE1tdLLILLvMt1LXLHtJHH[]A\A]A^A_IFHD$#fH|$IH9H5 "LyH="H5 1H "H5 H81lH "H5H81TH5U "L%H="H51@H51 "LH="H5{1ff.HH5!HDHHHDAUATUHSHdH%(HD$1HxHEƒf]HHtNIAu HucIH$LH5M!HLHHH/HL$dH3 %(HH[]A\A]Du11L%} H$HpDHI9LH-uHttwH(H<$HH t$HHHL9I uHCfHSHL9~H<$LrHDI1HH$H= "H5 AUH5!ATUSHHHtaHH.HcICIE~01fHHKLHD9uHL[]A\A]DH[]A\A]fATH5S!US H11ɾHH H@HLdH= "H`LHH11ɾHH@HLdH= "H|LHH11ɾHH@HeLdH=q "HKLHH}11ɾHHt$HHT$ t$ t H|$HL$dH3 %(u H(tff.@H(H5!dH%(HD$1,Ht>Ht$HHT$ t$ t H|$>HL$dH3 %(u H(/ff.@HH5Y!dH%(HD$1Ht@1HmHHt H<$HHt$dH34%(Hu Hrff.fPX11HH="f.USHHHt$H5!HtN1H|$Ht H|$H1Ҿ7HdHt8HT$H5s"HHD$H[]H0!H5H81RfHH5)!HtHoHH~ff.HH5!LHtHHHHD>ff.UHSHH5!Ht1H5!HHHtGHHu"HH[]HB!H5H81 H=r"H581H!H5H81ff.HH5 !lHtHHHHЃYfHH5!,HtHHHHDff.USHH5!HtfHHHHH8uHH[]f.H5H HDHH9HH[]f.HH5!\Ht)HHtHH.fDH9fHH5! HtHHHff.AUATUSHH5c!Ht}HHHtYHIHcI^IE~+1@HÿH;LH0D9uHL[]A\A]DHA[L]A\A]Off.@USHH5!HtDHHHt%HHHHH[]HH[]ff.HH5I!Ht)HHtHHNfDHfSH5!_Ht6HH?x Hw[+[/ff.@ATIUSHHH?dH%(HD$1 HHcH9woHt$L@l$HsH u-HLHL$dH3 %(u&H[]A\@Hsf.H{H= !H511@uHt t@HH5!4HHff.fAVAUATIUSHH0Ht$H|$dH%(HD$(1_H5@!H蠾HtH5@!HH1HILhLHT Ht$H>H HHcljH9t`HHHHƉK~0u[LMA}x@u@HcHDHT$(dH3%(H0[]A\A]A^u6H=E!H51H~)Hv8Mt{H!H1H=HD$HLHL$Ld$HD$@@LMA}}fHI!Htd1H={VHD$HLHL$HD$Wf1 fH==HH!%H=HH!|H!pH!dH!H50H81[Vff.ATIUHSHdH%(HD$1H$7HuLHL$dH3 %(H[]A\HcH|Hu tH H$Ht9HYH<$HuHt7H$t@HHDH$H$uEIf1DAWAVIAUATIUHSHH5b!H$褺H5E!H襺H>H5E!HH HLhLH1AH5!HAHEDH~~1LxMA}&@u+D$ L$ uH߉L$ tH\L$ H$IDH=g!H51fu&Hŋt H<$@HDEH$H=!I1H5(LMA}>fHHHHHIHKHDMLDHHhATIٹUD1H5HT$H=e!H-!HH[]A\A]A^A_H-!H$uH$HǨt$H!H5kH81 %DUHSHdH%(HD$1H$~uHcH|HuGuOH$HH5}!HHHHL$dH3 %(uXH[]@KH$Hu11FfDt@H耾H<$HHDH$off.SH#H5!H1H[Jf.UHSHdH%(HD$1H$~uHcH|HuGuOH$HH5}!HHHHL$dH3 %(uXH[]@;H$Hu116fDt@HpH<$HHDH$off.SHH5!H1H[:f.USHHdH%(HD$1tuHD$dH3%(uZH[]@5V!HH5[!HH$'H5!HHtH53!HH;@SHHt$@urHtiHƒt\uWH5z!5H|$HHL$H t*HI1Ҿ\H7HtHD$H[HUSHH5!HǴH5!HH赴Ht#HHվHEH[]H!H5wH81DUSHHH5!HTHH91ҾHHgHt HH[]U1HR!SHXHHHt6H1ɺ!H H] HHߋ5\!wHH[]H=v!H5v1USH@uYHtPHƒtCu>HH5!fHHu&HHH[]fkfUSHH5`!HH5!HHHt#HHEHEH[]HN!H5H81DAWAVAUATUSHH|$HtH[]A\A]A^A_@@ H|$H-! L|$H="M'MwMIA AMt*IWIw脼HthH}MuLLH1[]A\A]A^A_Hg tA@ t N襹HD$?H !LH5oH81DSH[]A\A]A^A_@HcH!HDfATUHSHH5{!6HIkHa1HcӾ{L=Ht!1Hcվ|L&Ht[]A\H=!H5$H=!H5AWIAVAUAATUSHHdH%(HD$81HD$0tH.AHD$H@GH|$LcG1L{HD$H@u-Ht$HƒsHd@1AH5!LIHgH5!LL= @HH$H@HHD$LHt$H qHLLƉIcL>fHcLtIt 'H.HFHD$H@H|$LcH|$H|$H HL9NH|$@H|$HcHD$HL$8dH3 %(#HH[]A\A]A^A_GnH.tHD$AHFAHD$@LH)H|$HG;HvEHh!H1H=yHD$H<$HHL$ Hl$ HD$(Lt$0of.HDLH4$$H4$HIHD$8ZH!H1H=HD$H<$HHL$ Hl$ HD$(mHyL.fL+E`HD$xDLhE_HD$xDH|$H4$bSH4$IHD$Hu.MLt$H.fMLDLt$D H=HHM!H=_HH%!`AH!H!H=B!H51H!H5|H81"H.1贫"Rf1EDAUATUSHdH%(HD$1@HHHƒH5!蝪H5HH+H5!HH, H5!HH$HtH诸HIH衾LH5R!H誺H$Ht&H5!HPIL11HjH5#!HE1hH$Ht HIH5!HDH$HtKHIMt;Ht6LHc LH'v HS H5!HH$HHHуE1CHI9HJH;E1HvH=ճH;E1HM H=謳H;E1H$H=胳H;E1HH=ZH;E1HH=1H;E1HH=H;E1HH=߲H;E1HWH=趲H;E1Hƺ.H=!H5vH=uH;E1H H=TLH;E1H H=#H;E1HH=H;E1HrH=ѱH;E1HƺIH;HSH5蓻H;HH5}H;HH5H;1HH5lZH;HH5?H;H H5$H;1HH5 H;HH5|H;1HuH5t٥H;HjH5k辥H;1HH5V覥H;HGH5F耺H;H59lH;H57XH;H58DH;H590H;H58H;H5mH;H5H;H5H;HH5դH;HFH5躤H;1H>H5袤H;HӴH5臤H;1HH5oH;HPH5TH;1HH5HHL [H]A\@H5Q!Ht$H11(HuH8HH=ߞHH !H!H5H81kff.AUATIUSHH-з!dH%(HD$1HHHLHɃHHtuHHfHt$HIVHI蛚H葚9t1HL$dH3 %(u*H[]A\A]Ë$;T$uLL|H蜨GH!H51H81ff.@USHH@udHt[HƒtNuIHH5!Hk ߂HtLH5c!H=Ժ!HHtHC HCHH[]HaH=z!H5ޡH!H5xH81ơfDUSHH57!ZHt5HMHHHtOHHBH߅t#H[]鰫H!H5 H81X3H=ܿ!H51>H=ǿ!H51)fHm!SH5HH!H8{Hl!H!H5{HHHXH;H5HW!H;HSH5LH;H(H5xܐH;HH5ȗH;1HeH57詐H;HH5莐H;1HrH5vH;HH5[H;1HH5CH;1HgH5+H;1HH5H;1[HH5}f.UHHSH(dH%(HD$1H\$HT$ H螥t$ H1H͑HL$dH3 %(uH([]AH!SH5HH85H޵!Hv1謉g"m~X#H;H5H;H5H H;H5H; H5@H; H5TϵH; H5h軵H;H5a觵H;H5j蓵H;H5rH;H5wkH;H5zWH;H5~CH;H5 /H;H5 H;H54H;!H5HH;#H50ߴH;%H5H˴H;'H5\跴H;)H5h裴H;+H5|菴H;-H5{H;/H5gH;1H5SH;3H5?H;5H5+H;7H5H;9H5H;;H5H;=H5۳H;?H5dzH;AH5賳H;eH5蟳H; H5苳H;H5wH;!H5cH;AH5OH;H5;H;H5'H;H5H;H5H;H5H;H5ײH; H5òH;@H5诲H;H5蛲H;H5臲H; H5sH;@H5_H;H5KH;H57H;H5#H; H5H; H5H; H5H;H5ӱH;H5迱H;H5諱H;H5藱H;H5胱H;H5oH; H5[H; H5GH; H53H;H5H;H5 6H^H;H5HWH?H;H5HͰH H;H5H记YHH;H5H菰 HH;H5Hp;xH×H;H5}[HPWUH5!SHdH%(HD$1yH1HH贔Hc1袉HH@H uRHHH$胔~\HH4$ tCHCHSH)H9kHHHL$dH3 %(uoH[]ÐHCf.HHSH!1H81 HA!H5H81H (H5H=O@AUH5!ATUSH(dH%(HD$1fxHIeHHYL1xAŅ~%LHH蘟A9u1H}Hc17HH@H Ht$HHD$|HHt$ ttHCHSH)H9H耘HH5!H\$Ht_H!HL$H8.HL$dH3 %(H([]A\A]HHSHCLH=跑HH!HsHī!1H81@H!H5H81(HI!H5H81H yH5H=W}ff.AWAVAUIHATUSHH!Ht$H3ԙHH5T!HH|$HǨH5"!HH|$蕆HŃHÃHykH5܃!LuIHHvLmSfHH9LHoH!H5nH81fUHH5ar!SHcHt$HH'HH\t"HH[]H?!H5H81!HH5r!cHtHHt$HHnH!H5H81趂UHH5q!SHGcHt+HH观HHHH豒HH[]fHH5aq!bHtH_HH3iff.AWAVAUATUSHHHIHIHI5HIHH蟚HMMAWLHHH=[1H[]A\A]A^A_ff.fUH5p!SH*bHt=H~HwHHtUH%gHH0mH߅t#H[]xHY!H5(H81 H!1H81#ATIUSHt=HHHx\H5o!LaHt0HH蓅tH[]A\H8HH!H5H81膀H!H5ԲH81nff.HH5ao!`Ht3HsH@HxHDHfDHHff.@UH5o!SH`Ht5H|H5vHHtMHH肎H߅t#H[]Hѕ!H5H81sH,!1H81ff.UH5tn!SH `Ht5H{HuHHtMHH2mH߅t#H[]`HA!H5H81H!1H81~ ff.ATUSH dH%(HD$1HB HD$HuIH>Ld$H|$[H|$HD$g11LHHzHT$HS Ht$HDHL$dH3 %(HubH []A\11ҾHאLHHIHD$HC MuH!1H81}1Oxf.UHHl!1SHH#!H8軓HHt#H;aHtHC HH[]{H"!1H81v}fDHH5ql! ^HtHHs!H5BH81:}f.SH54l!]HtHHo}H[H+!H5H81|fSH\!H5OH!HH;KdHd!H;H5=HH!H(dH!H5HH߈H;HH5mlH;HH5EslH;1HH5eilH;1HH5}ylH;H}H5 tSH;1HH5}KlH;1HH53lH;HH5\lH;1H,H5MlH;1HDH5&kH;HH5.kH;1HqH5kH;HH5 kH;1HH5kH;HH5gkH;1HH5ѭOkH;H H54kH;1HH5kH;H-H5kH;1HH5}yjH;H*H5Y|jH;HH5jH;HH5jH;HyH5*}jH;1HH5~ejH;HH5JjH;HH5/jH;1HH5xjH;[HGH5qif.gAWAVAUIATUHSH1LeH赉:HH9}TL5U!LI6H!H5H81UvHm Hp!H5rH817vAUH5e!ATUSHVHHIBHJŅxTHc\XIŅt11LރHTHlLH(9uHL[]A\A]fDHy!H8tH[]A\A]${@H! H=aH 萈H H=wH;A1H H`ZHC!H5EH81 uf.UH5dd!SHdH%(HD$1UHtoH}qH%kHHtDH1H0tH$HH0q`H߅t~HL$dH3 %(u7H[]YHJ!1H81ftH!H5H81NtIzfATUSHurHtiHƒt\uWHH9tGH5vc!HTIHt@H5_c!HTHt,H誆HHt4L|Hk H[]A\H&xH׉!H5٦H81sHo!1H81sff.PX1HHI!H81gsS1Hb!MHQHt HC H[fUHH5b!SHSHt)HH'HHUt"HH[]H !H5 H81rLff.AUH5#b!ATUSHVSHHI蒊ŅxLHcTIŅt)1L;|H3\LHȉ9uHL[]A\A]fDH!H8tH[]A\A]w@H! H=]H 0H H=eH;A1H ?H]$WH!H5H81qf.UH5a!SH:RHt5H-nHgHHtMHH~H߅t#H[]{Hq!H5sH818qH!1H81 qff.UH5t`!SHQHt5HmHEgHHtMHHrZH߅t#H[]{H!H5H81p胃Ht!1H81p ff.UH5_!SHQHt5H mHfHHtMHHvH߅t#H[]pzHQ!H5SH81pH!1H81p{ff.PXH5HH!H81ofUHH51_!SHgPHt[HH7HH|tHHaQtuH[]@#sH1[]H;!1H81WobfAUIH5^!ATIUSHHOHt6LHzLIb]LHHDt&HH[]A\A]H!H5H81nUDATUHH5/^!SiOHt-HHOHHI;ltHOH[]A\LPHK!H5H81bnfATUHH5]!SNHt/H1H'fHHI dLt}PH[]A\ kPH܃!H5H81mHH5Q]!NHt)H}HtHHnofDHfATUHH5\!S9NHt/H1HgeHHInLtOH[]A\`OH!H5۠H813mHH5\!MHt)H迂HtHHnfDHfUHH5A\!SHwMHt$HHtHH Mt"HH[]H!H5H81lHH5[!MHtHolHHX^ff.ATIUSHt=HHHx\H5[!LLHt0HHhtH[]A\HxqH^H!H5H81kH!H5H81kff.HH5[!Ld$H|$vH|$HD$LT11LHHJXHT$HS Ht$H}HL$dH3 %(HubH []A\11ҾH7}BnLH~HIHD$HC S}MuH?!1H81[j1dJpf.HH5Y!JHtHHC!H5EH81 jf.UHHaY!1SHH+!H8HHt#H|HtHC HH[]KHHz!1H81ifDSH!H53H6!HH;PH<!H;H5aHH!HPH!H5HHuH;HH5YdYH;HH5_IYH;1HMH51YH;HH5ZYH;1HH5KXH;1H"H5mXH;HH5EXH;1H?H5'XH;HH5XH;1HLH5llXH;HH5eXH;1HH5DkMXH;HH5̛2XH;HH5XH;HhH5_yWH;HH5pWH;1HH5TWH;1H]H5-iWH;HiH5A_lH;1HH5iWH;1HgH5kkWH;H|H5PWH;[HH54W@YUH5V!SHdH%(HD$1ZGH1HHGHcH1qWHH@H uQHHH$Gx[HH4$ tBHCHSH)H9jHgHHL$dH3 %(unH[]HCf.HHSHTz!1H81eH|!H5H81eH H5H=gMk@UH5U!SHJFHtZH-RHHMu.)bH[HHtFHH.QHH[]owH[H]cH\{!H58H81#eHty!1H81eSHHt$H5+U!EHH|$HpH|$HD$1aHYJHt$H t,H~HcωH9u+HvHut HD$H[HHuHx!H5H81fdHz!H5cH81Ndff.ATUSHujHtaHƒtTuOIHH58T!DHHt=H5$T!LDHt)HRHt4HC HVH[]A\H.hHy!H5H81cHw!H5H81cff.AUATUSH(dH%(HD$1GHHH$HFHD$zH^H~ZH|$_HlH<$H 9H@kAąu%H<$H XHOiAą\HHNH=HDVaHt$HHD$SH|$YH5cR!H;CHH#Hz!HR!1H8gxHH5Ֆ1IcrHt H\HHHDHL$H HDHHoHC0HIpGMMe LHT$dH3%(H([]A\A]ÐHHYH|$^1HIvH[Hu!H$H5˕H81\aH}w!H5LH81DaHL$Hu!H5H$H81#agff.gH5#KTff.UH5Q!SHAHtqH}]H%WHHtF11HHMtHH[]j@H FHHUHH[]jHt!1H81d`Hv!H5aH81L`ff.HH5aP!@HtHoJHHHЃH/v!H5 H81_fDUSHHt$H5 P!@HtBH|$HW1H_HHtXHHHH߅t)kHD$H[]Hu!H5H81v_akHs!H5H81Y_Hs!H5דH81A_PXH55HHTu!H81"_fATIUSHH5N!?Ht)HLH5H@HuHE H[]A\ATIUSHH5N!f?Ht)HLH5[H@HNHEH[]A\CATIUSHH5;N!?Ht)HLH5HL@HjHEH[]A\ATIUSHH5M!>Ht)HLH5H?HjHEH[]A\SHHPdH%(HD$H1HD$HHD$(HD$HD$0HD$HT$ HD$8HD$ 1L@ &Ht LcN L HI9tH9HtHHI9uH4$HtHHt$HtHHt$HtHAHt$HtHHH\$HdH3%(uHP[ú19Wb@U1HL!SHrx8H5ʐH_NHt9HHE1E1111#PH] HH5k>HH[]Hr!H5DH81I\fAUATIH5^L!UHSHHXdH%(HD$H1Hn!H5HHcH;HcH5H 3fH H=fH;A_1H ؈H>'8gHk!1H81RHh!H5H81RXfATIH5C!US-3HttH OHHHHtI1LHHfxMut H[]A\w\HeHj!H5CH81RHj!1H81RH%h!H5݇H81Qff.SAH1H߉oVH[f.USHHHHcjH;HHHH[H51]Hff.ATUSHujHtaHƒtTuOIHH5A!1HHt=H5A!L1Ht)H\Ht4HC HRH[]A\HNUHf!H5H81PHi!H5H81Pff.AUATIH5A!UHSHH8dH%(HD$(11HD$Ht|M,$LGHHH5o!H=He!H83IHL1jdH5n!IHLp11H:HL$(dH3 %(H"H8[]A\A]fLMd$cGHHtIuaL@[H|$ HD$ KHT$ H tnHBHRHD$Ht$H|$H;HT$HU HbHg!1H81#OH=?HD$ZJLL$HHm!HHHT$H늾H=% JHHm!1IHd!H5H81NTfDS1H?!}dH:Ht HC H[H0g!1H81TN@PXH5.HHdd!H812NfUHH5>!SH.Ht(H5>!HH.Ht)HHH[]ZHd!H5ǃH81MHHxHHHHHfUHSHHHH~b!H0QHu H1[]HH5¸uH[]SHt"H6Ht@t[HHH[H5=!H-Htb11HIHHtfHhAHcH9unHH߉[dHHT$JHT$HH[H1GHb!H5{H81LHSe!H5H81rLH]f.HH50Hl$ HAD$HuLHtwH|$ {HHD$HCHD$H=~CHH-g!IHHDH|$ ADcBHD$ ~AH`!H5Z~H81GHHD$HCHD$M*YH]!H5}H81GHHD$HCHD$ff.ATUH1SHHH0dH%(HD$(1NHINHHtW1HzNHHD$hNHHD$VNHD$ Ht;Ht$L9HL$(dH3 %(H0[]A\HD$H5e!HL$HHD$GHD$ HuH5[e!HtHg[!H87*HD$ rDH=|AHHe!6LfDUHH6!1SHH [!H8 \HHt#HQHtHC HH[]+2H^!1H81EfDHH5A6!\&HtHH[!H5{{H81Ef.UH=|SHTH#\!H5 |Hed!H\!H;H,H ^!H;H5 |HH^!H,H ^!H Z!HH2H/H;H5jEQH;HFH55*5H;HkH5;5H;HH5`{4H;HEH5<4H;1HH57{4H;1HH5bC4H;1HH524H;HbH5s;v4H;Hd;H5X;PIH;HaH5F;E4H;1HH5O[-4H;1HqH5z4H;1H H503H;H54zZ48HH*H=Cc/'HHs/ H=)zB/'HHR/ H={!/'HH1/ H=y/'HH/H=y.-HH.H=y.-HH. H=y.H-H.H;HH5xYH;H5 pYH;/"H5ryYH;?H5fyYH;H H[H5Uy]uYD:AWAVAUIATUHSH1LeHER:HH9}TL5Z!LI6HHU!H57vH81>H vH52vH=@&D@ATUSHurHtiHƒt\uWHH9tGH5f/!HIHt@H5O/!HHt,HFHHt4L6Hk H[]A\HBHGT!H5muH81>HoV!1H81=ff.PX1HHIV!H81=UHH5.!SHgHt$HHOHH 8t"HH[]HS!H5tH81v=AUH5S.!ATUSHHHI?ŅxLHcIŅt)1LFHGLHxT9uHL[]A\A]fDHR!H8tH[]A\A]tB@HQU! H=h(H OH H=pOH;Ac1H sHL(!HR!H5sH81ZHHQ!H5pH81;9H\O!H5pH81#9HQ!H5qkH81 9ff.UH5)!SHHt5H5H5/HHtMHHLd$H|$+CH|$HD$ 11LHHNHT$HS Ht$HJHL$dH3 %(HubH []A\11ҾHI:LHG+HIHD$HC IMuH?O!1H81611D!1H81+f.SHLC!H5H[+:SHHH5Fbi H[@ATE1UHSHHt$HtH'H|$ IH57!H HHtQBHH7+Ht)E1LH u HH[]A\Hb>!1H81(H>!H5aH81(ff.ATE1UHSHHt$HtH&H|$IH5w!H HHtQB'HHw*Ht)E1LHJu HH[]A\H=!1H81(H'>!H5`H81'ff.H]=!S1HHx!H8=HtHX [H=!H5`H81'ff.fPXH5`HH=!H81r'fHH5! HtH9HHHDff.ATIHUHS/t6HHH5!LHt)HH1>H[]A\Hh,H>ff.USHH5`!HWHt3HHu%H HH[]fDSf.ATUHSHt-IIH5!HHt LH-H[]A\H+I~ff.HH5!Ht)HHtHHfDH)fHH5Q!LHtH HH ff.HH5! HtH/HHHDff.HH5!HtH_7Hc1HH#ffDAUH5!ATUSHHH5HHt}H8AąxNHcIEt+1@H{H LH;D9uHL[]A\A]DH9:!H8t+H[]A\A])@HA[L]A\A]@H!H,$HT$HD$HH5!HH8 HGH5FH`/H5FHH>H5O>!H11H HIH5hXHHHH5S(HHHH5;XHHLHL$dH3 %(u}H []A\D;VfDHFH= HH=!H='HHm=!"<$ff.AWAVAUATUSHXdH%(HD$H1HD$HD$0HD$ HD$8HD$(HD$@G5H.HHl$uHD$ HD$(HFHD$ uHFHD$(H5R!HJIHH5!H/IHLd$ 1It L HH|$(E1HtHT$HT$ILLL(H5UH%-Ht HHH5DH-H5xDHHLH5DHHHL$HdH3 %(upHX[]A\A]A^A_úH2!H5UH81H2!H5XUH81pH5a5!L1.H1!1H81NI"fATIHUSHt2 H5 !LHt H H[]A\DsZf.ATIHUSHt2 H5l !LdHt HuH[]A\Df.ATIHUSHt2E H5l !LHt HH[]A\Df.ATIHUSHt2 H5 !LHt HH[]A\DS:f.AVAUATUSH@dH%(HD$81HHLl$ILHH=T$IƅHt$ LLd$ HH=Lt$0HЃHD$(HŋD$IF HH^,tN1HL$8dH3 %(H@[]A\A]A^.H=OT1X"H,uH߉D$ ;D$ D.H=7T1"[1HdgATUSH58!H HtHډ[H]A\#D%Q8!HHD~ Huɉ[]A\fHH5 !HtHH/!H5QH81f.ATE1E11UHR1S7!E1E111HQ7!H-/!H/!H5RH}HL%1!H}H5QH-!HI$H-!H=?H'H;E11ɺH#H=GQy'H;E11ɺH#H=+!X'H;E11ɺH#H= Q7'H;E11Hƺr#H;H5x#H;HH5 H;H5Ey,H;H:H5QH;HH5PsH;HH5PXH;HH5P=H;H^H5y@"H;H#H5PH;HHH5PH;1HH5PH;H%H5{PH;HH5v!H;H_H5I$H}H5:PH+!H5!HHV"H;HH5;H;H5 *H;1H0H5H;1HH5OH;1H0H5NH;HH5OH;1H=H5H;1HH5xOH;1HH5lOH;1H%H5aOiH;HH5NNH;HH5N3H;HH5NH;[]HH5R>A\H,!H5kOH81H,!H5NH81yHHOSSL_DEBUG: empty sk!ossl.c [%s:%d] items in sk < -1???inlen <= LONG_MAX / 20123456789abcdef(null)error on stack: %s (%s)error on stack: %sTurning on FIPS mode failedTurning off FIPS mode failedOPENSSL_init_sslOpenSSL2.1.2OPENSSL_VERSIONOPENSSL_LIBRARY_VERSIONOPENSSL_VERSION_NUMBEROPENSSL_FIPSfips_modefips_mode=OpenSSLErrordebugdebug=errorsto_derpassed data is not valid String???password must not be longer than %d bytesobject in array not of class ##type##OpenSSL 1.1.1k FIPS 25 Mar 2021ossl_bin2hexinvalid OBJECT ID %li OBJ_obj2txt%2d%2d%2d%2d%2d%2dZbad UTCTIME format: "%s"%4d%2d%2d%2d%2d%2dZunknown time formatutcASN1_INTEGER is NULL!invalid tag classtag number not specifiedossl_asn1.cto_aArrayillegal EOC octets in valuemust specify tag numberinvalid tagging methodvalue is too shortinvalid length for BOOLEANinvalid BOOLEAN/%nil expectedunsupported ASN.1 typeASN1_TYPE alloc failurei2d_ASN1_TYPEp0 - p1 == alllenASN1_get_objectEOCUNIVERSALCONTEXT_SPECIFICAPPLICATIONPRIVATEIMPLICIT@value@tag@tagging@tag_class@indefinite_length@unused_bitsASN1ASN1Errortraversedecodedecode_allUNIVERSAL_TAG_NAMEASN1Datainfinite_lengthindefinite_length=infinite_length=initializePrimitiveConstructiveeachBooleanIntegerEnumeratedBitStringOctetStringUTF8StringNumericStringPrintableStringT61StringVideotexStringIA5StringGraphicStringISO64StringGeneralStringUniversalStringBMPStringNullObjectIdUTCTimeGeneralizedTimeSequenceEndOfContentregistersnlnoidshort_namelong_nameINTEGERBIT_STRINGOCTET_STRINGNULLOBJECT_DESCRIPTOREXTERNALREALENUMERATEDEMBEDDED_PDVUTF8STRINGRELATIVE_OID[UNIVERSAL 14][UNIVERSAL 15]SEQUENCESETNUMERICSTRINGPRINTABLESTRINGT61STRINGVIDEOTEXSTRINGIA5STRINGUTCTIMEGENERALIZEDTIMEGRAPHICSTRINGISO64STRINGGENERALSTRINGUNIVERSALSTRINGCHARACTER_STRINGBMPSTRING|X4XWTYYXXYYYWYYYYYYYYYYYYVVc``aaabccc`caccc b baaaaaXb`aaaacaossl_asn1prim_to_derto_der_internalbad GENERALIZEDTIME format: "%s"explicit tagging of unknown tagp - (unsigned char *)RSTRING_PTR(str) == total_lengthindefinite length for primitive valueType mismatch. Bytes read: %ld Bytes available: %ldType mismatch. Total bytes read: %ld Bytes available: %ld Offset: %ldCan't convert nil into IntegerCan't convert nil into Booleanunused_bits for a bitstring value must be in the range 0 to 7indefinite length form cannot be used with primitive encodingBIO_new_mem_bufBN wasn't initialized!BN_bn2binossl_bn.cBN_dupBN_bin2bnbignum too longinvalid radix %dDon't know how to coerceCannot init BN_CTXBNErrorinitialize_copynum_bytesnum_bits+@-@+-mod_addmod_submod_mulmod_sqr**mod_expgcd<=>ucmpeql?===zero?one?odd?negative?pseudo_randpseudo_rand_rangegenerate_primeprime?prime_fasttest?set_bit!clear_bit!bit_set?mask_bits!<<>>lshift!rshift!to_sto_ito_intto_bnmod_inverseOpenSSL/BNCannot convert into OpenSSL::BNCipher already initialized!Cipher not initialized!iv must be %d byteskey must be %d bytesunable to set AEAD tagossl_cipher.cout_len <= RSTRING_LEN(str)key not setdata must not be emptyout_len < RSTRING_LEN(str)cipher does not support AEADunable to set IV lengthCipherErrorciphersresetpkcs5_keyivgenfinalauth_data=auth_tag=auth_tagauth_tag_len=authenticated?key_len=key_leniv=iv_len=iv_lenblock_sizepadding=auth_tag_lenkey_setOpenSSL/Cipherunsupported cipher algorithm (%li )authentication tag not supported by this cipherdata too big to make output buffer: %ld bytessalt must be an 8-octet stringiterations must be a positive integerarguments for %li #encrypt and %li #decrypt were deprecated; use %li #pkcs5_keyivgen to derive key and IVAEAD not supported by this ciphercouldn't set additional authenticated dataunable to set authentication tag lengthretrieving the authentication tag failedunsupported cipher algorithm: %li ossl_cipher_updateossl_cipher_finalOpenSSL for Rubywrong argument (%li )! (Expected kind of %li )wrong config formaterror in line %dConfigErrorDEFAULT_CONFIG_FILEossl_config.cEVP_MD_CTX_newDigest initialization failed.EVP_DigestUpdateEVP_DigestFinal_exDigest initialization failedDigest::ClassDigestErrorfinishdigest_lengthblock_lengthOpenSSL/DigestDigest CTX wasn't initialized!Unsupported digest algorithm (%li ).ENGINE wasn't initialized.NUMERICNO_INPUTprivateopensslOPENSSL_init_crypto#<%li id="%s" name="%s">no such digest `%li 'no such cipher `%li 'EngineErrorloadcleanupenginesby_idcipherload_private_keyload_public_keyset_defaultctrl_cmdcmdsinspectMETHOD_RSAMETHOD_DSAMETHOD_DHMETHOD_RANDMETHOD_CIPHERSMETHOD_DIGESTSMETHOD_ALLMETHOD_NONEOpenSSL/Engineno such builtin loader for `%li 'HMAC_CTX_newHMAC_CTX_copyHMAC wasn't initializedossl_hmac.cbuf_len <= EVP_MAX_MD_SIZEHMACErrorhexdigestOpenSSL/HMACossl_hmac_digestlength must be non-negativeEVP_PKEY_CTX_new_idEVP_PKEY_derive_initEVP_PKEY_CTX_set_hkdf_mdEVP_PKEY_CTX_set_hkdf_saltEVP_PKEY_CTX_set_hkdf_keyEVP_PKEY_CTX_set_hkdf_infoEVP_PKEY_deriveEVP_PBE_scryptiterationsPKCS5_PBKDF2_HMACKDFKDFErrorpbkdf2_hmachkdfSPKI wasn't initialized!ossl_ns_spki.cnewlen <= lenChallenge.length <= 0?NETSCAPE_SPKI_verifyNETSCAPE_SPKI_set_pubkeyNetscapeSPKIErrorto_pemto_textpublic_key=challengechallenge=OpenSSL/NETSCAPE_SPKIossl_spki_to_derCert ID wasn't initialized!ossl_ocsp.cBIO_newi2a_ASN1_OBJECTOCSP_CERTID_dupd2i_OCSP_SINGLERESPASN1_item_dupResponse wasn't initialized!Request wasn't initialized!d2i_OCSP_BASICRESPd2i_OCSP_RESPONSEOCSP_request_add0_idd2i_OCSP_REQUESTOCSP_single_get0_statuscertificate is not revokedd2i_OCSP_CERTIDOCSP_cert_to_idOCSPOCSPErrorRequestadd_noncecheck_nonceadd_certidsigned?createstatus_stringbasicBasicResponsecopy_nonceadd_statusresponsesfind_responseSingleResponsecheck_validitycert_statusthis_updatenext_updaterevocation_timerevocation_reasonextensionsCertificateIdcmp_issuerserialissuer_name_hashissuer_key_hashhash_algorithmRESPONSE_STATUS_INTERNALERRORREVOKED_STATUS_NOSTATUSRESPONSE_STATUS_SIGREQUIREDRESPONSE_STATUS_SUCCESSFULRESPONSE_STATUS_TRYLATERREVOKED_STATUS_CACOMPROMISEREVOKED_STATUS_KEYCOMPROMISEREVOKED_STATUS_REMOVEFROMCRLREVOKED_STATUS_SUPERSEDEDRESPONSE_STATUS_UNAUTHORIZEDREVOKED_STATUS_UNSPECIFIEDNOCERTSNOINTERNNOSIGSNOCHAINNOVERIFYNOEXPLICITNOCASIGNNODELEGATEDNOCHECKSTRUSTOTHERNOTIMEV_CERTSTATUS_GOODV_CERTSTATUS_REVOKEDV_CERTSTATUS_UNKNOWNV_RESPID_NAMEV_RESPID_KEYOpenSSL/OCSP/CERTIDOpenSSL/OCSP/SINGLERESPOpenSSL/OCSP/BASICRESPOpenSSL/OCSP/RESPONSEOpenSSL/OCSP/REQUESTSingleResponse wasn't initialized!RESPONSE_STATUS_MALFORMEDREQUESTREVOKED_STATUS_AFFILIATIONCHANGEDREVOKED_STATUS_CERTIFICATEHOLDREVOKED_STATUS_CESSATIONOFOPERATIONossl_ocspreq_to_derossl_ocspres_to_derossl_ocspbres_to_derossl_ocspsres_to_derossl_ocspcid_to_derPKCS12 wasn't initialized.ossl_pkcs12.cPKCS12_parse@key@certificate@ca_certsASN1_dupUnknown PBE algorithm %li PKCS12ErrorOpenSSL/PKCS12ossl_pkcs12_to_derPKCS7 wasn't initialized.ossl_pkcs7.c@dataPKCS7_verify@error_stringNegative number of recipient!Negative number of signers!signedencryptedenvelopedsignedAndEnvelopedCould not parse the PKCS7PKCS7ri wasn't initialized.PKCS7si wasn't initialized.Could not add recipient.Could not add signer.must specify a booleanunknown type "%li "PKCS7Errorread_smimewrite_smimetype=detached=detacheddetached?cipher=add_signersignersadd_recipientrecipientsadd_certificatecertificates=certificatesadd_crlcrls=crlsadd_dataSignerInfoSignersigned_timeRecipientInfoenc_keyTEXTDETACHEDBINARYNOATTRNOSMIMECAPOpenSSL/PKCS7/RECIP_INFOOpenSSL/PKCS7/SIGNER_INFOOpenSSL/PKCS7OpenSSL::PKCS7#get_signer_info == NULL!signeddatasignedAndEnvelopedenvelopedencrypteddigestossl_pkcs7_to_derpkey is emptyCould not parse PKeyparameters missingpublic key missingPKEY wasn't initialized!EVP_VerifyInit_exEVP_VerifyUpdateEVP_VerifyFinalPrivate key is needed.EVP_SignInit_exEVP_SignUpdateEVP_SignFinalPKeyErrorprivate?OpenSSL/EVP_PKEYOpenSSL::PKey::PKey can't be instantiated directlyTHIS IS NOT A DH!qpub_keypriv_keyDH_set0_keyDH_set0_pqgincomplete DHDH already initializedDHparams_dupossl_pkey_dh.cFailed to generate keyNot a DH key!DHErrorgeneratepublic?exportparams_ok?generate_key!set_pqgset_keyossl_dh_to_derTHIS IS NOT A DSA!DSA_set0_keyDSA_set0_pqgDSA already initializedossl_pkey_dsa.cDSA PUBLIC KEYNeither PUB key nor PRIV keyincomplete DSAPrivate DSA key needed!Not a DSA key!DSAErrorsyssignsysverifyossl_dsa_to_derEC_POINT is not initializedEC_GROUP is not initializedEC_POINT_is_on_curveEC::Point already initializedEC_POINT_dupEC_POINT already initializedinvalid second argumentEC_POINT_newEC_POINT_bn2pointEC_POINT_oct2pointBIO_new(BIO_s_mem())EC_GROUP_set_seedEC_GROUP_newEC_GROUP_dupunknown curve name (%li )unable to create curve (%li )EC_GROUP_new_by_GF*wrong number of argumentsTHIS IS NOT A EC PKEY!EC_KEY_printoutlen=%dECDSA_verifyPrivate EC key needed!ECDSA_signECDH_compute_keyEC_KEY_set_public_keyEC_KEY_set_private_keyEC_KEY_set_groupEC already initializedEC_KEY_dupEVP_PKEY_assign_EC_KEYinvalid curve nameEC_KEY already initializedEC_get_builtin_curvesEC_POINT_point2octEC_POINT_set_to_infinityEC_POINT_invertEC_POINT_make_affineEC_POINT_is_at_infinityEC_GROUP_get_cofactorEC_GROUP_get_orderEC_GROUP_set_generatorEC::Group already initializedEC_KEY_check_keyEC_KEY_generate_keyNot a EC key!ECErrorECGroupPointGFpGF2mGFp_simpleGFp_montGFp_nistGF2m_simpleuncompressedhybridNAMED_CURVEEXPLICIT_CURVEgroup=private_key=private_key?public_key?dh_compute_keydsa_sign_asn1dsa_verify_asn1curve_nameasn1_flagasn1_flag=point_conversion_formpoint_conversion_form=seed=degreeinfinity?on_curve?make_affine!invert!set_to_infinity!to_octet_string@groupOpenSSL/EC_POINTOpenSSL/ec_groupEC_GROUP is already initializedunknown symbol, must be :GFp_simple, :GFp_mont, :GFp_nist or :GF2m_simpleunknown symbol, must be :GFp or :GF2munknown argument, must be :GFp or :GF2mcan't export - no public key setcan't export - EC_KEY_check_key failedunsupported point conversion form %+li (expected :compressed, :uncompressed, or :hybrid)unsupported point conversion form: %d, this module should be updatedbns must be 1 longer than points; see the documentationTHIS IS NOT A RSA!dmp1dmq1iqmpRSA_set0_crt_paramsRSA_set0_factorsRSA_set0_keysalt_lengthmgf1_hashautoossl_pkey_rsa.cRSA already initializedincomplete RSAprivate key needed.maxNot a RSA key!RSAErrorpublic_encryptpublic_decryptprivate_encryptprivate_decryptsign_pssverify_pssset_factorsset_crt_paramsPKCS1_PADDINGSSLV23_PADDINGNO_PADDINGPKCS1_OAEP_PADDINGossl_rsa_to_derRAND_bytesRAND_bytes is not supportedRandomRandomErrorrandom_addload_random_filewrite_random_filerandom_bytesstatus?Selected protocol name must have length 1..255verify_hostname requires hostname to be setSSL SESSION get callback enteredSSL Session wasn't initialized.SSL SESSION remove callback enteredSSL SESSION new callback enteredcertificate does not contain public keyAdvertised protocol must have length 1..255SSL session is not started yet.%s SYSCALL returned=%d errno=%d state=%s%s returned=%d errno=%d state=%s: %s (%s)%s returned=%d errno=%d state=%sOpenSSL does not support tmp_ecdh_callback; use #ecdh_curves= insteadSSL NPN advertise callback addedSSL ALPN select callback addedSSL_CTX_set_session_id_contextSSL SESSION get callback addedSSL SESSION new callback addedSSL SESSION remove callback addedSSL TLSEXT servername callback addedservername_cb must return an OpenSSL::SSL::SSLContext object or nilSESSION_CACHE_NO_INTERNAL_LOOKUPSESSION_CACHE_NO_INTERNAL_STOREOP_DONT_INSERT_EMPTY_FRAGMENTSOP_NO_SESSION_RESUMPTION_ON_RENEGOTIATIONOP_ALLOW_UNSAFE_LEGACY_RENEGOTIATIONOP_NETSCAPE_REUSE_CIPHER_CHANGE_BUGOP_SSLREF2_REUSE_CERT_TYPE_BUGOP_NETSCAPE_DEMO_CIPHER_CHANGE_BUGSSL is not initializedSSL_set_fdarg must be Time or nilverify_certificate_identityossl_ssl.cpublic key mismatchSSL_CTX_use_certificateSSL_CTX_use_PrivateKeySSL_CTX_set0_chain:SSL_CTX_set_cipher_listcache_numconnect_goodconnect_renegotiateaccept_goodaccept_renegotiatecache_hitscb_hitscache_missescache_fulltimeoutswrite would blockread would blockSSL_set_sessionSSL_writesyswriteSSL_acceptSSL_connectSSL_CTX_newSSL2unrecognized version %+li SSL_CTX_set_min_proto_versionSSL_CTX_set_max_proto_versionSSL_readsysreadSSL_CTX_check_private_keySSL_CTX_add_client_CAcan't set verify locationsSSL NPN select callback addedSSL_CTX_set_alpn_protosSSL ALPN values addedSSL already initializednonblock=callcallback_stateossl_ssl_ex_vcb_idxSSL_get_ex_new_indexossl_ssl_ex_ptr_idxossl_sslctx_ex_ptr_idxSSL_CTX_get_ex_new_indexExtConfigSSLErrorWaitReadableSSLErrorWaitWritableSSLContextHAVE_TLSEXT_HOST_NAMEssl_timeoutssl_timeout=set_minmax_proto_versionciphers=ecdh_curves=security_levelsecurity_level=enable_fallback_scsvsetupfreezeSESSION_CACHE_OFFSESSION_CACHE_CLIENTSESSION_CACHE_SERVERSESSION_CACHE_BOTHSESSION_CACHE_NO_AUTO_CLEARSESSION_CACHE_NO_INTERNALsession_addsession_removesession_cache_modesession_cache_mode=session_cache_sizesession_cache_size=session_cache_statsflush_sessionsoptionsoptions=SSLSocketOPENSSL_NO_SOCKconnect_nonblockaccept_nonblocksysread_nonblocksyswrite_nonblockstoppeer_certpeer_cert_chainssl_versionpendingsession_reused?session=verify_resulthostname=tmp_keyalpn_protocolnpn_protocolVERIFY_NONEVERIFY_PEERVERIFY_FAIL_IF_NO_PEER_CERTVERIFY_CLIENT_ONCEOP_ALLOP_LEGACY_SERVER_CONNECTOP_TLSEXT_PADDINGOP_SAFARI_ECDHE_ECDSA_BUGOP_ALLOW_NO_DHE_KEXOP_NO_TICKETOP_NO_COMPRESSIONOP_NO_ENCRYPT_THEN_MACOP_CIPHER_SERVER_PREFERENCEOP_TLS_ROLLBACK_BUGOP_NO_RENEGOTIATIONOP_CRYPTOPRO_TLSEXT_BUGOP_NO_SSLv3OP_NO_TLSv1OP_NO_TLSv1_1OP_NO_TLSv1_2OP_NO_TLSv1_3OP_MICROSOFT_SESS_ID_BUGOP_NETSCAPE_CHALLENGE_BUGOP_MICROSOFT_BIG_SSLV3_BUFFEROP_MSIE_SSLV2_RSA_PADDINGOP_SSLEAY_080_CLIENT_DH_BUGOP_TLS_D5_BUGOP_TLS_BLOCK_PADDING_BUGOP_SINGLE_ECDH_USEOP_SINGLE_DH_USEOP_EPHEMERAL_RSAOP_NO_SSLv2OP_PKCS1_CHECK_1OP_PKCS1_CHECK_2OP_NETSCAPE_CA_DN_BUGSSL2_VERSIONSSL3_VERSIONTLS1_VERSIONTLS1_1_VERSIONTLS1_2_VERSIONTLS1_3_VERSIONexceptionwait_readablewait_writabletmp_dh_callbacknpn_protocols_encoded@cert_store@ca_file@ca_path@verify_mode@verify_depth@verify_callback@client_ca@renegotiation_cb@cert@extra_chain_cert@client_cert_cb@tmp_ecdh_callback@timeout@session_id_context@session_get_cb@session_new_cb@session_remove_cb@npn_select_cb@npn_protocols@alpn_protocols@alpn_select_cb@servername_cb@verify_hostname@io@context@hostnameSSL3TLS1TLS1_1TLS1_2TLS1_3OpenSSL/SSLOpenSSL/SSL/CTX3  3 SSL Session already initializedi2d_SSL_SESSIONossl_ssl_session.cno session availableunknown typeBIO_s_mem()SSL_SESSION_print()SessionErrortime=OpenSSL/SSL/Sessionossl_ssl_session_to_derV_OKV_ERR_UNABLE_TO_GET_CRLV_ERR_CERT_SIGNATURE_FAILUREV_ERR_CRL_SIGNATURE_FAILUREV_ERR_CERT_NOT_YET_VALIDV_ERR_CERT_HAS_EXPIREDV_ERR_CRL_NOT_YET_VALIDV_ERR_CRL_HAS_EXPIREDV_ERR_OUT_OF_MEMV_ERR_CERT_CHAIN_TOO_LONGV_ERR_CERT_REVOKEDV_ERR_INVALID_CAV_ERR_PATH_LENGTH_EXCEEDEDV_ERR_INVALID_PURPOSEV_ERR_CERT_UNTRUSTEDV_ERR_CERT_REJECTEDV_ERR_SUBJECT_ISSUER_MISMATCHV_ERR_AKID_SKID_MISMATCHV_ERR_KEYUSAGE_NO_CERTSIGNV_FLAG_CRL_CHECKV_FLAG_CRL_CHECK_ALLV_FLAG_IGNORE_CRITICALV_FLAG_X509_STRICTV_FLAG_ALLOW_PROXY_CERTSV_FLAG_POLICY_CHECKV_FLAG_EXPLICIT_POLICYV_FLAG_INHIBIT_ANYV_FLAG_INHIBIT_MAPV_FLAG_NOTIFY_POLICYV_FLAG_EXTENDED_CRL_SUPPORTV_FLAG_USE_DELTASV_FLAG_CHECK_SS_SIGNATUREV_FLAG_TRUSTED_FIRSTV_FLAG_NO_ALT_CHAINSV_FLAG_NO_CHECK_TIMEPURPOSE_SSL_CLIENTPURPOSE_SSL_SERVERPURPOSE_NS_SSL_SERVERPURPOSE_SMIME_SIGNPURPOSE_SMIME_ENCRYPTPURPOSE_CRL_SIGNPURPOSE_ANYPURPOSE_OCSP_HELPERPURPOSE_TIMESTAMP_SIGNTRUST_COMPATTRUST_SSL_CLIENTTRUST_SSL_SERVERTRUST_EMAILTRUST_OBJECT_SIGNTRUST_OCSP_SIGNTRUST_OCSP_REQUESTTRUST_TSADEFAULT_CERT_AREADEFAULT_CERT_DIRDEFAULT_CERT_FILEDEFAULT_CERT_DIR_ENVDEFAULT_CERT_FILE_ENVDEFAULT_PRIVATE_DIRV_ERR_UNABLE_TO_GET_ISSUER_CERTV_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATUREV_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATUREV_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEYV_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELDV_ERR_ERROR_IN_CERT_NOT_AFTER_FIELDV_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELDV_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELDV_ERR_DEPTH_ZERO_SELF_SIGNED_CERTV_ERR_SELF_SIGNED_CERT_IN_CHAINV_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLYV_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATUREV_ERR_AKID_ISSUER_SERIAL_MISMATCHV_ERR_APPLICATION_VERIFICATIONATTR wasn't initialized!ossl_x509attr.csk_newargument must be ASN1::SetASN1::Set has non-array valueX509_ATTRIBUTE_dupX509_ATTRIBUTE_set1_objectoid=value=AttributeErrorAttributeOpenSSL/X509/ATTRIBUTEossl_x509attr_get_valueossl_x509attr_to_der#<%li : subject=%+li , issuer=%+li , serial=%+li , not_before=%+li , not_after=%+li >CERT wasn't initialized!ossl_x509cert.cX509_set_pubkeyX509_set_notAfterX509_set_notBeforeversion must be >= 0!CertificateErrorCertificateversion=signature_algorithmserial=subjectsubject=issuer=not_beforenot_before=not_afternot_after=extensions=add_extensionOpenSSL/X509ossl_x509_to_derCRL wasn't initialized!X509_CRL_add0_revokednum < 0???ossl_x509crl.ccount < 0???X509_CRL_set_nextUpdateX509_CRL_set_lastUpdateCRLErrorlast_updatelast_update=next_update=revoked=add_revokedOpenSSL/X509/CRLEXT wasn't initialized!ossl_x509ext.cASN1_OCTET_STRING_setX509_EXTENSION_dupcritical,unknown OID `%li '@config%li = %li OBJ_txt2objX509_EXTENSION_set_object@crl@subject_request@subject_certificate@issuer_certificateCTX wasn't allocated!critical=ExtensionErrorExtensionFactoryissuer_certificate=subject_certificate=subject_request=crl=create_extExtensioncritical?OpenSSL/X509/EXTENSIONossl_x509ext_to_derOpenSSL/X509/EXTENSION/FactoryName wasn't initialized.ossl_x509name.cname entries < 0!X509_NAME_print_ex#<%li %li >X509_NAME_dupOBJECT_TYPE_TEMPLATEX509_NAME_onelinelocX509_NAME_add_entry_by_txtDEFAULT_OBJECT_TYPE[]NameErroradd_entryto_utf8hash_oldcountryNamednQualifierDCdomainComponentemailAddressRFC2253ONELINEMULTILINEOpenSSL/X509/NAMEossl_x509name_to_derReq wasn't initialized!ossl_x509req.cX509_REQ_set_pubkeyX509_REQ_set_versionRequestErrorattributesattributes=add_attributeOpenSSL/X509/REQossl_x509req_to_derREV wasn't initialized!i2d_X509_REVOKEDossl_x509revoked.cX509_REVOKED_dupX509_REVOKED_set_serialNumberRevokedErrorRevokedOpenSSL/X509/REVX509_REVOKED_set_revocationDateossl_x509revoked_to_der@timeSTORE wasn't initialized!STORE_CTX wasn't initialized!STORE_CTX is out of scope!certs in chain < 0???ossl_x509store.c@error@chainstctx_ex_verify_cb_idxstore_ex_verify_cb_idxX509_STORE_get_ex_new_indexStoreErrorStoreverify_callback=flags=purpose=trust=add_pathadd_fileset_default_pathsadd_certStoreContexterror=error_depthcurrent_certcurrent_crlOpenSSL/X509/STORE_CTXOpenSSL/X509/STOREStoreContext initialization failureexception in verify_callback is ignoredX509_STORE_CTX_get_ex_new_index;7g0@ P4H\x @`0,|P4L0``<x 0P,`X`@`Dp @ L x ` (!T!@!!!`"0" \""" "p #L#|#P###0$|$@ $ %p\%p%p%%%`&PT&&&+&,'`-H'p-\'-p'.'/'/'/(0 (0L(0h(1(P1(1(@2(2)2 )`3X)P5)@8)P8)8*9P*9|*`:*:*`;+;,+`+?, AX,B,B,D-E@-Fl-pF-@G-H$.IX.J.pJ.J.K /Ld/PM/ N/O 0Od0P0Q0R01Sl1@T1U1U2[02[D2\x2\2]2^2_3_,3`X3c3f4f 4gP4gl40h4Ph4h4h4Pi5i5i85l5l5l5n 6n86od6o6p6 r7r7`sH7Pvh7w7x7x7x7y8 zD8zh8z80{8p{8{8| 9}09~\9p9Ѐ999` :@:@t::::;@;P\;x;;;;P<4<p<0<@<<L=P=p===P ><>@l>> >>(???P?` @0@0\@@@@0A0ALAxAA0A`AA$B 8B\BBpB0BPC`CP@CpC0C@CC0D@DHDtD0D@DDE0>܉0??$?P@@l@A`AAB(`BDBpBC܋DD4ETE0F0GG G( HDpK`Kt MN P\PQQԎQPRpSlTTď U@U UD@VV WؐpWW$0XDXpXpYYؑZ [([T0^p@^`_`` a<dx ddē ee e(@fTff0gؔ@hh(@khkk@l̕lPo`o,pXr0sؖ`ssptLvvv@wpww8xlypy} ~@Pl̙@D`p @8`p`؛ `<h0`ܜ`Ў0L@hP|`08pdО pH d`И0ȟ0 (<Xp0ܠP@l`ԡ pl Pܢ04Pl`ģ04Ш0ܤP4xP̥zRx $M`;FJ w?:*3$"D P;\p"0,MH  A `<EvHOQH ~ A LiFBA A(D0S (D ABBF U (A ABBE LhiFBA A(D0S (D ABBF U (A ABBE LiFBA A(D0S (D ABBF U (A ABBE 8<FLD D(D@a (A ABBK (DmEDG0P AAA pbHFBE B(A0D8DPn 8A0A(B BBBH 0RH D A t)EW D D@FBB A(A0DP 0A(A BBBG T@qFAG G8xFGA D(D0x (D ABBA @_H j F nEY B E E  D q K (<(<HFCH sAB(h|EAD0e AAA ,FFF  ABF jH \ A $jH \ A (xUEDF _ AAH ((UEDF _ AAH (TUEDF _ AAH (UEDF _ AAH (HUEDF _ AAH (|UEDF _ AAH (UEDF _ AAH (0UEDF _ AAH (\UEDF _ AAH (LUEDF _ AAH (UEDF _ AAH (UEDF _ AAH ( UEDF _ AAH (8UEDF _ AAH (dPUEDF _ AAH (UEDF _ AAH (UEDF _ AAH (UEDF _ AAH ( UEDF _ AAH (@TUEDF _ AAH (lUEDF _ AAH (UEDF _ AAH (UEDF _ AAH $$?EAG lDA@ Hf K 7Hc G LEc H (EHD X DAA $P 7Hc G @t 7Hc G 4\ EDJ X CAA ~ FAA , AC FF J 0 FAA D@  AABB |D xBHA B ABH n DBD D DBA 4TEKD B CAF D FAA ((^EGD t DAG (\vFKA p ABK (vFKA p ABK (vFKA p ABK (<XvEGD u DAF (hvEGD u DAF 8FBA G(D0e (D ABBF 8FBA G(D0e (D ABBF @ (FBB A(A0Dp 0A(A BBBJ @PtFBB A(A0Dp 0A(A BBBJ 8FAA u FBK A CBJ (dED f FK D CI PFAA D0  FABN   DABA J  DABG (PEDG M GAK (|XjEMD l DAI (ZEDD m AAA 8FBA A(G@x (D ABBA LdFBB B(A0A8D= 8A0A(B BBBG 0`FAA G0J  DABA 0 FAA G0J  DABA (|QEAG0u CAF (QEAG0u CAF 8 FBA A(G@w (D ABBA @\xFBB A(A0G@ 0D(A BBBA 8FBA A(G@w (D ABBA 8FBA A(G@w (D ABBA @<FBB A(A0G@ 0D(A BBBA @\FBB A(A0G@ 0D(A BBBA @tFBB A(A0G@ 0D(A BBBA 8 FBA A(G@y (D ABBA H  FBB B(A0A8GP 8A0A(B BBBA 8lx!FBA A(G@w (D ABBA 8 "FBA A(G@m (D ABBA 8"FBA A(G@m (D ABBA ( #EAG0a DAA L#E X lX) 0T)FAA G0i  DABA *  *EG  AD (*EAG0 AAK 0+FAD D0  AABE L, EZ(h,EHD0 AAH H-FBB B(A0A8Dp 8A0A(B BBBH \/FEB B(A0A8GAPUCp 8A0A(B BBBE @2&E`,\2FAA n ABG X3AAF\3WEt A 3AAK32H] H 3AHs A 3eEt O R F <H42H] H Xl4AHl H \t4BBB B(A0A8GVPCN 8A0A(B BBBF 6 6H6ZFBB B(A0D8D` 8A0A(B BBBE (H7vFGA v ABI (tP8vFGA v ABI ,8FDJ [ ABF 8D9FHA D(D0n (D ABBB , 9AFAA  ABD <;H { E (X;EMD A DAA <L(>EAG@ AAF (D@EHD nIH@ @,$@FAA y ABD (TAuEKD k DAA AEG H DH PBAAKTBAHl H B:He H B:He H 0B-FKF D0  AABF HCED u AA (lDECJ0 AAE (|EEMD u DAA EUE= G G 8 GfFIA A(D0/ (D ABBA 0H LHTFAA D@  AABH 0| xItFAA D@  AABJ 8 JsFBE A(A0Y(D BBB KH E C (!KEAG0 DAG 4!LAAK(P!L]FHD r DKE |!L2H] H !L2H] H (!M^EGD n FAK !DMAAF(!HMEAG0U AAA (("MEAG0U AAA T"0NLHf A 8p"dNFLD A(IPw (A ABBC "8O{L^"Q T"Q_FBB D(A0DUIAN 0A(A BBBA L8#RFBE A(A0DPXU`IXAP` 0A(A BBBD 8#lSBED D(D0n (D ABBE #SAAK(#SEHDp AAE ( $8TEHD0n AAG 8$TjEG D DD \$(U4Ei A ,x$LUFAA i ABA 0$UFDA G0_  DABH $8V<Ec A $\VsE[L%WFBB B(A0D8Fs 8A0A(B BBBD `d%`\FBB B(A0D8F GBBIc 8A0A(B BBBD L%_FBB A(D0FpxGFxApc 0A(A BBBC &aH4&Pb H&LbEG [ AH (l&bEHD0 AAA &cEh K R F 4&xdEKD x FAE I CAA &dAAF,'doFAD C ABA (@'$eyFAK s ABA l'xeOHe E ('eEHD x AAE 'ffEw E 'df.Ec A ('xf%EAD@ AAD (|gLl(4(hEHD0 AAA `(i t(iEK l AA (jEK t AK ((kEK t AK ,(kFAA n ABA ()TlEHD0 AAA <)Hm (P)DmEAJ@ AAD ,|)nFAA u ABA ()nEHD0 AAA )o ,)oFAA u ABA *p&ED p AF @*$q ,T* qFAA u ABA (*qEAD@ AAC (*rEHD0 AAA *s ,*sFAA u ABA ( +tEAD@ AAC (L+tEHD0 AAA Hx+uFIB B(A0A8DP 8A0A(B BBBF ,+vFKA H ABA +0w&ED p AF (,4dEQ v AA 0$>hFAA D0z  AABF (X>*EAG@s AAF L>FBA A(G@ (C ABBI Y (F ABBD >P6HU A >tdEn A 8 ?FBA A(GP (A ABBF H?>E` A ,d?@EHD AA(?0EADPe AAA 8?:FEA C(D@ (D ABBA @?FEB D(A0DP 0D(A BBBA 0@@>FAA D@  AABF 8t@FED A(D` (A ABBA (@TEAD0 AAE (@EAD W AAE (A<EAD W AAE 4A!E[@PABEE A(A0Dp 0A(A BBBJ @A BMA B ABK N ABG FAB(AlEDD U AAD BAAK BED h AA DBED h AF hB ED h AF BED j AD B$ED j AD BED j AD (B<EDD y DAA $CED n AA HC,ED i AE 8lC,FED A(I@x (A ABBI ,CIAA e ABE (C\EAD N DAC DqEY($DPEADPe AAA 8PD:FEA C(D@ (D ABBA @DFEB D(A0DP 0D(A BBBA D$5ED  AI 8D@FED A(D0~ (D ABBA 80EFBA A(D@ (A ABBG (lEhEAD Y AAE $E/EVC LCA8ErBEA A(D (A ABBJ 8EHFED A(I@ (A ABBG @8FBMA B ABK N ABG FAB(|FEDD g AAJ FAAK FED h AA F,ED h AF GED h AF 0GDED j AD TGED j AD xG\ED j AD LGFEB A(F0D@HNPOHA@` 0A(A BBBE (G(oEGD m AAA (HlEDD0f AAK 0DHFDA DP  AABF (xHEAD N DAC H0_EGHpH|H I 4IEKD V FAG D CAA ,LIFAK  ABA 8|IFLG A(G@| (A ABBE ,I,BKA @ ABO II JED ] DF L4JP`FBB B(K0D8If 8A0A(B BBBD (J`EAD _ AAE TJBBB E(D0D8D@HNPQHA@L 8A0A(B BBBI K,K6ED  CA B FA (LKgEAD@ AAB ,xKFAK  ABC (KEDD ` DAF 4KEAD0[ AAI N AAA ( LXEDD Z DAA 88LFED A(D0} (D ABBA 4tLAAD0V DAG C DAA HLFBE B(D0F8DP 8A0A(B BBBG ,L,{EG M' H @(M|BMA B ABK N ABG FAB$lMbAi F F J F A HMFBB B(K0D8D@ 8D0A(B BBBC (MEHG D DAA ( Nh EHG N DAA (8N EHG N DAA dNp AAK4Nt EKD H FAE D CAA (N EHD z AAE N` 2H] H 4O aEHD i DDN D FAA (8O BEKD c DAA $dO HS E K E K E (OH VEAN h DAG O| 2H] H O 9Hd H O EK b AA PP EK b AA 88P FBK D(D@\ (D ABBA (tPpEKG s DAA (PEKD K AAA 8P8FDK h CBF g ABA QAAK$QdEt N @QDE~ A \QdEt N xQ tE| O F A QhUI(QEGD p DAK ,QyEC FEG A (RdWAMD g DAA (E` A sԺEE(s HsFBB E(A0I8M@ 8D0A(B BBBA HsXFBB E(A0I8M@ 8D0A(B BBBA LHt&FIA A(D0k (D ABBG Q (A ABBI (tEHD0n AAA ,t@FAA v ABA tAAFu.Ec A (,udEKD m DAA LXu,FIA A(D0[ (D ABBG Q (A ABBI (uEHD x AAE (u`EHD x AAE (vEHD x AAE ,v(AAK4Hv,~EKD x FAE I CAA 8vt{FLD A(G0v (D ABBA (vnFAK s ABA (vmFAK u ABA w@GHe K I A (4wpmFAK u ABA `wGHe K I A (w_EKD h DAA w2H] H (w<FDA z ABH wQHq G G E 0xFAA D@  AABA Hx6HU A (dxjEMD l DAI x$Ex (xEHD0 AAA 4xEHD E DAE K ADE $yED r AD ,HyFAA n ABA 8xyLbFBA A(DP (A ABBB y4yEHD y DAI W DAE zJHc G (z8EAD0U AAA HzAAK(dzMFDA y ABA (zMFDA y ABA (zMFDA y ABA (z,MFDA y ABA {P EG` AA (8{<EJD V DAA <d{fFBK F(G (A ABBC {<Ec A {KEm A ({(jEMD l DAI |l6HU A ,$|FOH HIT|0 (h|,EHD0 AAA L| FIB B(A0A8GF 8A0A(B BBBA ,|BKA C ABE }P&E`$0}dBEAG \JJ,X}FAA n ABA 8} FBK D(I` (A ABBC }<Ec A }AAK(}_AKD e GAE (~L.He0@~dMEDJ X CAA ZAA0t~ED ` GH | FF V DH ~> >0>@>P>`>p>>>>>>>>>?? ?0?@?P?`?p?????????@@ @0@@@P@`@p@@@@@@@@@AA A0A@APA`ApAAAAAAAAABB B0B@BPB`BpBBBBBBBBBCC C0C@CPC`CpCCCCCCCCCDD D0D@DPD`DpDDDDDDDDDEE E0E@EPE`EpEEEEEEEEEFF F0F@FPF`FpFFFFFFFFFGG G0G@GPG`GpGGGGGGGGGHH H0H@HPH`HpHHHHHHHHHII I0I@IPI`IpIIIIIIIIIJJ J0J@JPJ`JpJJJJJJJJJKK K0K@KPK`KpKKKKKKKKKLL L0L@LPL`LpLLLLLLLLLMM M0M@MPM`MpMMMMMMMMMNN N0N@NPN`NpNNNNNNNNNOO O0O@OPO`OpOOOOOOOOOPP P0P@PPP`PpPPPPPPPPPQQ Q0Q@QPQ`QpQQQQQQQQQRR R0R@RPR`RpRRRRRRRRRSS S0S@SPS`SpSSSSSSSSSTT T0T@TPT`TpTTTTTTTTTUU U0U@UPU`UpUUUUUUUUUVV V0V@VPV`VpVVVVVVVVVWW W0W@WPW`WpWWWWWWWWWXX X0X@XPX`XpXXXXXXXXXYY Y0Y@YPY`YpYYYYYYYYYZZ Z0Z@ZPZ`ZpZZZZZZZZZ[[ [0[@[P[`[p[[[[[[[[[\\ \0\@\P\`\p\\\\\\\\\]] ]0]@]P]`]p]]]]]]]]]^^ ^0^@^P^`^p^^^^^^^^^__ _0_@_P_`_p_________`` `0`@`P```p`````````aa a0a@aPa`apaaaaaaaaabb b0b@bPb`bpbbbbbbbbbcc c0c@cPc`cpcccccccccdd d0d@dPd`dpdddddddddee e0e@ePe`epeeeeeeeeeff f0f@fPf`fpfffffffffgg g0g@gPg`gpggggggggghh h0h@hPh`hphhhhhhhhhii i0i@iPi`ipiiiiiiiiijj j0j@jPj`jpjjjjjjjjjkk k0k@kPk`kpkkkkkkkkkll l0l@lPl`lplllllllllmm m0m@mPm`mpmmmmmmmmmnn n0n@nPn`npnnnnnnnnnoo o0o@oPo`opooooooooopp p0p@pPp`pppppppppppqq q0q@qPq`qpqqqqqqqqqrr r0r@rPr`rprrrrrrrrrss s0s@sPs`spssssssssstt t0t@tPt`tGA$3a18 GA$3p1113ׁGA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA$3p1113kGA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFYblGA+GLIBCXX_ASSERTIONSopenssl.so-2.5.9-114.module_el8.10.0+3991+5e651d4e.x86_64.debug5c,7zXZִF!t/̷#]?Eh=ڊ2NERU o'鞐2r8hauDS0 |p9ѺȔe9D#_8H#Wh¸7rVα`h\{.ں+d$-O r%ȵũS`/@oh:7R;O ܫ'gi u]@rMj2Ek]AΔ\|6Zc-%tڀS~'cm[)UO&)lN:g8[z,87(ܝluZVMN{wG& Wv,o Ql7;"|{ Gћv׽Q[ :SWjxp,9XChMyg:/40TyρA{'ğ=* `xwѶ [k@HK]z͍z6~*ظ)s̚&jS9Psw㻤 J'vNpY'q+f*638rfHK ! Xp~l02IOxQ6}l j9雑jV t(ȟ}lw6ݿQWk}͓x1Xu`ફ I{0&#yݦ;ί0;W@$ >;_܈fʮ{@U.ZɛIド љL&@/ƿF}@: `w5){A["T2(A_- |\sg؛wz"<⛔q7~O+[Ћ\m-ShXS-8B6wVڿ9W1+6WMjT=#'zF\.bA*سKts=~nܷ W/糜0fpו461&I8 ub`uˣ0D@4mB# FqطEEYҴ$r?tې Ku}#e&sxơYh48♠@~ ډuͬX$r ,[(lCʟT;gNܣGޭ=q)[8Y)`E#=zWwQF drv40mD[ ;Oq_yg!5n/e=p8\m O?gAFҖ`9@5q̸^sP]IN@mqߏ/N2gw8kraYn~G1K̷'gzj޷C~ՇyH ;)Tw7p)R6l8]0.A4>mXAe=޷qlpx6p{;s ^)D'8&ʼnErf!59h'PS x 7Be"Qֱk~nl[zK;D`Xs* h<4^F5;-Wb퍢n۔TN0o){.=4`ƸZ&N1ش_3E?!m'R#Ӆq{'}vHxji&}9W<%Ybr6dPj8n, pLѲlGʖ[p|_Ưy9g(8Dlea| :8>jXDT]=W]UO:%lUzQudc/FqvaEcɢ<Yh-=.DHgɨZTz5U( # 3s&}D\2CJqZ[*Yh1͞'/QV;V aOW/iݤA3n~ƿchAxBxo~Z ia}ܫ&#[Ǣ,MC?74) 60ЃN_+8)0+I3aJd h2uɜLjxsABx$P}9O'tbcTq%G #sm˹LQry:~^|  s1jNoǸ9>5H+Xj\:}$}w l}7FMkgsr0u;AeƓ&;Vk)"*A7>ܑ5&u3߫@Cԛ}OvYXgN_]ÅD[\ 摿+7G,jk,q֚R_Sٗ.:Ӊ*X Q93e텞J$Re\k\+mT uf}<0~#|Ӈ6[ 7yN4tUV $U|x; R_Umir;{uW~ѪưKt'etnД1+5;+4߭Ѕ5c %V埼?ޛ(S'{)h~#3bF~h;oC^Ն_+܌aI <+ca[%C ~rEA$C]epr\uAj+2|V\h ;Kwk;Z )_911k;1`j|, oK^9,_i[Oe/pe;%jk\7/68) [G[- wgDk&=wisW](yo϶͝ȋ$5=\vQM FhϰYJ5}eڱgl7À4|^5l མ4NNysMs>uՕg!UJ&6la9 ۱אO Ń]zlUP;-kurb{#Țw~q`աDaJ QzS.#s}A]\L]>,S&nl Ǧϗ˪"SH\:/CʬcCJ9H}Ÿyz[SOC15Y%9k"RX( 4^%( a=/ ,?hNo5RYm5Y' g`cG8R"ȈYuI@|o\I&*.VSj*CҊ{cLW'~ӷU]1d,{FG tڡZ@) K~3uI6P6=l;WG`ˢ-r>_@[-t77+}W|_VJ"4T'U uLjEؖ|ftw'{layMt̬qģvt{(|.Ѧo ]G :A :JOt( mD y%egjEДXY1іǯ(`!|6/{?`#V(CF,*HBj) $z6횇drބO͋dwn.2Su`?˜Xg/ VCx=!Z4W*+ 0m aAe6 HM Oͤߋ95ʐNMƥp6\ r><_0+C ՓN`C&Έ&xA%N)x3- ws9Hs *!\z2JW?,+aä\;,`J#ըgV{N ~2 MvrQ+2v_gs!ψJ~$7I"DU9҂ 0^L}O[I'jbs(-_V ;VpJ@& cf(؁_扑֥D \`z^Ye61Et hfXxZ;KG)ٮ!n6"&D`l-yyke|kVhG,Q2FpT: "`8|~bpyq/og@*گ(׹-D]3;LO׳2t\=*O+bT,A@XyOXB|qe c'w7A:4?Fù#Ob㐙w9v 10^d0a.׮=.X\D[GU:j?HA(>HڃT $jtDs)o[:S |jNEX5n)q\. jXMgC ¸,[ ő.(vo`ېh(?nE(<'X!^ڈDB1ںwo}8eWHk,x8)HQGx#6v FvN=fTߕ&N +ɢcY-x:W'M;HOH@z+&{zjeIZK&xbe'1̤+|xhsjv Ѭ1S&[bR7I0~Sۓ mwUd} ;ّu+ ƠxKe4D^Hkİ.OũQSq?{xB2X8S!{EjU*S_T9B|>d6/#*V™6m\ U/HFt33]ۮ?~mMT1,ETr La#JLI[ak%?/j TVGkn:U{{|Yw6|QyS#.$03 v׍خ BuC Ztbk[#< AR!cg|'&2;7lV({fHG*_{NV.t i\Mَ!'Rb$K4 -Uh(@5x]hI# {OzM~D/o ד, 9/e{ 5劄h=5Ē $vā{ivbX0Tfd]5Mʜg,$ɂm)E$.b ^8cK&,7e uf3s^exQHj舌^ ڎ硉rAȊ1/Gh4/k.M+PYU;`E3beĴQd[(? ''( ^e`L 利X;-F'ltb*nNߗPCA#S+ǙN` 7U^Vp'Te5 }ff׻;kcSh퇼տ0]Wv5=W\x:%^{P?؃#]>ޞ2۶3yba"Smbx0VYf›kcȮYI7J6Pkp mt;Ϻ?bM+h')& A9nb火tK`%~YUcN?k7 =Pv*é\5-2ƕ(m9"_gf;\n:a9[Fi2lķ-e=:,yj)| t7 |'N/O[]cisWxa;Xڒ1IɴJ/'Z&_} ǥutcɶ̊L2zi;R3 DTaMXDǓ&5j'tE'0`'~&ikd͑)N;,+gl7(A?R[Y^ǁܪvzB́6$ C N @4<'h_~S79 wqbF-;Os+W<d,,.cӲ\J.[<&ē>jJfۚ.8|1}ʮK<M{,%_T`!@)HPpQuPc#-)1!A6zpŀ0hI,e3%-qR. v#ALv"ҳp'ƈLge[$|Iamlʇ5⟗1mĜ塺,@T>Z)B~FeR:- 7tf,> gT(K4ro7lfvwf%9I o^lnepj9Ah "w4PWע̥-$wN 7Rmpav4P./=r=$ &O=8] |MDt:t2`^Eov?UJw#z6m@2 \ Y@g@8 @pTpT [[ [ X \\ \ 888$$PTPTPT StdPTPTPT Ptd Q Q QQtdRtd[[ [ XpGNUL&=CL*SB9;@ ;>BE|ŷ|!qX$ l,U\wqI[N q;5XiC`, F"2v|` a  >` __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeruby_xfreerb_gc_mark_mayberb_str_buf_newrb_str_resizerb_ary_new_caparb_ary_pushrb_hash_foreachrb_ary_entryrb_funcallvrb_str_catrb_str_internrb_utf8_encodingrb_enc_associate__stack_chk_failrb_enc_raiseruby_xrealloc2ruby_xmalloc2rb_check_typeddatarb_string_valuerb_enc_getrb_ascii8bit_encodingrb_str_conv_encrb_str_duprb_check_hash_typerb_extract_keywordsrb_id2symrb_hash_arefrb_error_arityrb_eArgErrorrb_raiserb_check_typerb_fix2intrb_eTypeErrorrb_data_typed_object_zallocruby_xmallocrb_class_new_instancerb_ary_newrb_hash_newrb_cstr2inumrb_str_new_cstrmemcpyrb_hash_asetrb_cstr_to_dblrb_float_newInit_parserrb_requirerb_define_modulerb_define_module_underrb_cObjectrb_define_class_underrb_path2classrb_define_alloc_funcrb_define_methodrb_const_getrb_intern2libruby.so.2.5libc.so.6_edata__bss_start_endGLIBC_2.2.5GLIBC_2.14GLIBC_2.4ui ii [ [ p[ [ [ F[ [ @[  _ _ _ _ _ 2_ 3_ 4^ ^  ^ (^ 0^ 8^  @^  H^  P^  X^  `^ h^ p^ x^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^  ^ !^ "_ #_ $_ %_ & _ '(_ (0_ )8_ *@_ +H_ ,P_ -X_ .`_ /h_ 0p_ 1x_ 4_ 5_ 6_ 7_ 8_ 9_ :HHqL HtH5J %J hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3%EG D%=G D%5G D%-G D%%G D%G D%G D% G D%G D%F D%F D%F D%F D%F D%F D%F D%F D%F D%F D%F D%F D%F D%F D%F D%F D%}F D%uF D%mF D%eF D%]F D%UF D%MF D%EF D%=F D%5F D%-F D%%F D%F D%F D% F D%F D%E D%E D%E D%E D%E D%E D%E D%E D%E D%E D%E DH=E HE H9tHE Ht H=E H5E H)HHH?HHtHuE HtfD=E u+UH=ZE Ht H=A d]E ]wH V5Hx=WHx0HH WHxHH WHxHH øf.HG`H@Hhff.@USHHHo`H}HtAH9HH[]+ff.SHH?H{ H{8H{@H{HH{X[fAWIAVAUIATUSH1H8H$dH%(HD$(1H$IEL{I9A?"1KPufI}S4t C0H7 Hw8IOHDH\$(dH3%(H8[]A\A]A^A_DLcXItiIuIHH5 LLL;HIIUH5\D HHL$HT$HIEH7@HMMfL9AF<"t4<\uMfL9AF MHC$HH1vfDATIUHSHtWHOIT$HH)H9v:HHHH)H9rH9vI|$H;I\$ID$[]A\@H?I $ID$IL$ff.AVIH58 AUIATAHUSH dH%(HD$1xH8HD$HA3IH$HC(dH5= 11CPH== UHC8HC HC@HCHILHHII9-HIHLHHLH,$H$H uiHHSHPHLHSHL$dH3 %(H []A\A]A^IcI|HubAA(HPHSHPf@u HHH]HHB<DHD$HH|$H|$HAHHD$AIH$HSH=; Ld$LHH5; IHD$H"C(dH=; LHH5M; IHD$`HC,H=F; qLHH5; IHD$"H^C4H= ; 3LHH5: IHD$HCPH=: LHH5: IHD$HzLHHC H=|: LHH5M: IHD$`HLHC8H=5: pLHH5: IHD$!HHC@H=9 1LHH59 IHD$HHCHH=9 LHH59 IHD$HOHCXQf.HEƒ!#HHDHl$DDHD$Au@H599 H=z9 11 HC uLHE1H‰SPS4 HH7 H5H81}DLHHC4fLHHC,$LHIHu~C(fDLHHHDHCXDLHeHC@@LHMHC8@LH5HCHHǾLC(4HX6 H5H81gfHH5A2 \H8Ht HKH6 H5hH81#AUATUSHdH%(HD$1H4t&IH5]7 HI11LHu#1HL$dH3 %(uIH[]A\A]@1LHHH56 H$HtLLUHT1 hSH% Hh Hf@H@HHE`HH[]ff.@AWAVAUATUSHXdH%(HD$H1H9tMHIHIHj AHDHH9uE1H|$HdH3<%(LHX[]A\A]A^A_Ã0 wHCH9{ H5H]AO,H5 Lc I널HCH9s{niHCH9\{fRHCH9E{i;HCH9.{n$HCH9{i HCH9{tHCH9{yAW, H4 LcIHCH9{aHCH9{NAG,H4 LcIvA@IW@lj$AG(9H=v4 H511HCH9#E1{aHCH9 {lHCH9{sHCH9{eILcHCH9E1{rHCH9{uHCH9{ewILcg@AG(E`IW8HD$ A9B:H=c3 DH51fLHHLIHLDHCH9K*tR/t8 HH9ufHHXH9@<*t0@ HD$(HD$HD$0HD$D$HL$HLHD$(L|IHNI@Ht$(I>5Ht$0HL$H5G0 IEHPH9t%H,tAr t lHHPH9uI G LLbL9JA/]HILD fD Ht$0HL$0H5P/ L$HtyH5Z/ H=/ Ld$0LL$HD$0`H5/ 11HHJL$Ht.IH5\/ LHHD$0L$IIMLD# Iz@HPH9{@<*tC0 T@HL$EHLHD$(dH+I8Ht$ HD$HT$(I>Ht$0HL$H5=* HT$8nLD$I@L@L9P,t?Q t ULL@L9uf.< t <LIL9B< t~<" tHH9uHH9<*t*u GH/ } U, IMo`LH)IEH$xL0IEIUIG`IEIHHx0'IHHL$0H5( HD$0XIILI_H9{fID$H9tAT$+t-uID$H9tAT$0 :HH9E!e.0 vf /HAH9Q*tJ/t8 pHH9uHH9*t/DHH98*u@HL`L9@0< @HL`L9@L$VL@L9X@<*tH0@ wpE1HHHHHHD t w3HHXH9P t/uHXH9t@<*tLH H=H H=Hp  H=HX H H=wH@ H=cWH(  H=57HH  H=HH IHH "\ already initialized instanceuninitialized instancenesting of %d is too deep%u: unexpected token at '%s'-Infinityjson/commonJSONExtJSON::ParserErrorJSON::NestingErrorinitializeparsesourceNaNMinusInfinityjson_creatable?json_createcreate_idcreate_additionschrmax_nestingallow_nansymbolize_namesobject_classarray_classdecimal_classmatchmatch_stringkey?deep_const_get[]=[]<<newJSON/Parser%u: incomplete unicode character escape sequence at '%s'%u: incomplete surrogate pair at '%s'options :symbolize_names and :create_additions cannot be used in conjunctionP`PpnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnLLNLLLLLLL ```````````````````````````````````````````````````````````````````````````````````````````````````  ;P `0LP (@dpzRx $PFJ w?:*3$"D@\Vp$5EAG ^DA(>EtHLBEB E(A0A8Ip 8A0A(B BBBF ,BDD V ABE @D@>FLE G(A0DP 0A(A BBBH <=HX E 8`FBA A(I@R (A ABBE $QEMD uDAH BBB B(A0A8D 8A0A(B BBBA (TVEHD0p AAA H I C E GNUp[ F@  H D[ [ o`  ] h P oo ooT o\  0@P`p 0@P`p 0@P`pGA$3a1HD GA$3p1113DGA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFYGA+GLIBCXX_ASSERTIONSparser.so-2.5.9-114.module_el8.10.0+3991+5e651d4e.x86_64.debugY҈7zXZִF!t/]?Eh=ڊ2NsAh6o[>o[5;>PG @/k5iXpkcX?Tr3[JFJYs??>Mf~)$/+SkRx`lz3Â'/9>4U;Y r"K!K(uvc;?'Π4f\\I)Q Lv}0)!H=x !& puR.ڌMBl-MddEfGuK,؂:)Au 0䯕/rD8|X`KIeL̴@]<=ZD|ړ)ro۽Mh8 s") ޥo5ɸ+s "i'.-B)I{SɅl<_+ָ%M" ΄l$ǂ&x]6+>w\3h!Nժkh}^7-]Ms#OdARO0aO,C^,3C=q_oyO x֚6#Sٱ^ءMiGĸەypC|bWQ:CF7S j-؀υHknSyƔ7:SCۭ]Cs)I0$3IgGvHE3>h>gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 08oT T ~Eo @T  P^BhhhHHcppPn@w*}DD DD@  Q QQQPTPT [ [[ [[ [h \ \] ]` _a`_H0bDtbhf"PK!АА json-2.1.0/json/ext/generator.sonuȯELF>@Љ@8 @nn P{P{ P{  {{ { 888$$`n`n`n Std`n`n`n Ptd8a8a8aQtdRtdP{P{ P{ GNUP ?X @` AHHqj HtH5zh %{h hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2%Ee D%=e D%5e D%-e D%%e D%e D%e D% e D%e D%d D%d D%d D%d D%d D%d D%d D%d D%d D%d D%d D%d D%d D%d D%d D%d D%}d D%ud D%md D%ed D%]d D%Ud D%Md D%Ed D%=d D%5d D%-d D%%d D%d D%d D% d D%d D%c D%c D%c D%c D%c D%c D%c D%c D%c D%c DH=Id HBd H9tHc Ht H=d H5d H)HHH?HHtHc HtfD=c u+UH=c Ht H=_ dc ]wH7Hthv$HtNHu8R1€?v2fHuBc dH%(HD$1Hc HH$vHT$dH3%(uHff.HH51] HHHDff.HH5] H@xHHDff.HH5\ xqHHHЃf.HH5\ xpHHHЃf.HH5q\ \HxhHHHЃfHH5A\ ,H@hHHDff.SHHHtH[DSHH?HtH{HtH{ HtH{0HtH{@HtH{PHtH{XHtwH{`HtiH[`SHHHDؿ f@H@H[ÐATIUHSHtWHOIT$HH)H9v:HHHH)H9rH9vI|$H{I\$ID$[]A\@H?{I $ID$IL$ff.Ht3UHSHHHBHHHH[]D1HfUSHHHwHHH?zHHHH[]DUSHH50Z HH߾HHtH~HH[]ff.USHH5Y HH߾HH$H]xH[]@USHH5Y HH߾HHHHEhH[]fDATUHH5_Y SIHIHuH% u;HI|$@HHu5HtID$@[]A\f.H]I|$@HtHtHE% H}HtH}H I\$HID$@[]A\fDATUHH5X SHIHuH% u;HI|$0HHu5Ht=ID$0[]A\f.H]I|$0HtHtHE% H}HtH}HJI\$8ID$0[]A\fDATUHH5W SHI)HuH% u;HI|$ HHu5Ht}ID$ ID$([]A\ÐH]I|$ HtHtHHE% H}HtH}HI\$(ID$ []A\fDATUHH5W S HIiHuH% u;HI|$HHu5HtID$ID$[]A\ÐH]I|$HtHtHE% H}HtH}HI\$ID$[]A\fDATUHH5_V SIHIHuH% u;HI<$HHu5HtI$ID$[]A\H]I<$HtHtHE% H}HtH}H I\$I$[]A\SHHHdH%(HD$1H=7HHH=_5HHHH5 [ H$LHT$dH3%(uH[ATUHSHdH%(HD$1HH!HyH5Z 11H=G[ ILHHH=4@HHH5^Z H$H=6HHHHHT$dH3%(u HH[]A\fAV1I1AUATUSHHH H5LZ dH%(HD$1I$HHH56HLHH5{Y IH$Hu_H=3NHHHHLHHHL$dH3 %(u2H []A\A]A^LHL,$H5X Lt$`fAT11USHHHH5CY dH%(HD$1ILHH5X HH$Ht5LHH,$H5oX HT$dH3%(uCH[]A\ÐH=2/HHHHHHyfAWAVAUIATUSH(dH%(HD$1fH5?R LH$H5V HH11LE1"IHD$H$HI9L= X LL>11LHHHD$ &HH<$HT$ILHHT$H|$IH?HwLHHI$ \ID$I9^HsH;H=CW ILHHeHsH{H=W IYLHH;Hs(H{ ~H=V I/LHHHs8H{0TH=V ILHHHsHH{@*H={V ILHH{pH=JV MIHAHL{qH=V MIHAHLmLchH=V mOd$HLHJLcxH=U JOd$HLH'HH=YU $H\HHHHHL$dH3 %(uFH([]A\A]A^A_HPH=/gHHS GAVAUIATIH5IO USHdH%(HD$1H ?/LH8/HHHH=U GHHIHH=T !HHvIH7H=T HHPIHH=rT HH*IHkH=TT HHIHH=T ILHHEhdH5S IH$ HH=S HLHHExH5S IH$H&H=?S LHH5PS IH$HH=aS HH)H=BS HEpHHHLEqHT$dH3%(H[]A\A]A^f.HsM4$A bMt$I|$Iv/LuHEfLHIH6HIMLLHEIH&HExfLHIHHEhEfHM4$A bMt$I|$IvOLu8HE0fHSM4$A Mt$I|$IvLuHHE@WfHM4$A Mt$I|$IvLu(HE fHM4$A tNMt$I|$IvLuHEfDH ^+HR+LeHDII|$AIvDII|$AIvVf.II|$AIvf.II|$AIvf.II|$AIvf.HILuhcHILuxfATIH50J UHSHH@hdHǀwuI4$HtHH[]A\ú1ff.@HI ff.ATIHUHSHKH{HH{LHk[]A\ff.@ATH5gI USPHHHkXIH)HEHHEHU,HEHk`HHEHs Ht HS(HHHEHU:HsHEHt HSHuhHkPHtqHEHRHEHU,Hs@HEHt HSHHuL[]A\H{PL[]A\H{`HkPHuHHCPHxHk`/HHCXfvHHC`f.H(f  Nf Nуf NFDISH+H dH%(HD$1HIH?LII1I)fLLLIIHHHI)BIAAHuHyHAA-LILL9v#f0HH@qPH9wM)uHD$dH3%(uH [LL VfDUHSH(Ht$H\$HdH%(HD$1HL$H u0HH\$HL$Hu-HD$dH3%(u*H([]HQH\$HL$HtHHzUHSHHH>HHu H[]DHuHHD$7HD$H[]ff.1H=&RfHH5E Hx@HtHpHH&fDHf.HH5qE \Hx0HtHp8HfDHwHH51E Hx HtHp(HfDH7HH5D HxHtHpHffDHHH5D H8HtHpH'HAWAVAUATIUHSHHHdH%(HD$81HCHSLH5J HL$("HJ HCHD$()}H(HD$ LxHh\uLD$4ft$2L9AH j(IfALH9L5'Ld$2L-'DDLApHcuAEKcL>DH( L`Hh\uE1L-d#E1D$4fL$2HK<<<P5H5'HcH>AL5!#LL)LLHMOML9wLL)tK4 HHHCHCHS"HCHD$8dH3%(HH[]A\A]A^A_LAL5"L)kK4 HLD$wLD$IDAL5F"&fDAL54"fDAL5""fD00ALt$2fT$4fЃfADATD$7T$6@HL`71AIHHHAIHHAIHHHAIHHAIHIcH %H+HH(H=3HBH_H"H\aH5!HDL9oAH T%IfALH9H= >H5#H1D11 f1f1 fAIHHLx%<"tt<\tXH $f4II9Mf.H= tH5M#H1AL5fDAL5fDHHT$HCHsHT$HCL9HD$HD$ HD$@H5yHtWHBHIcDL>H5*H4H5HH5HH5HH5HHwJHLHHHD$H f(IHD$ff$LH*=H=NH5!H11ff.ATIUSH9$HH5= HH5= HHHoEoHMoP U oX0]0o`@e@ohPmPop`u`oxp}pHHHsH;nHsH{HE]Hs(H{ HELHs8H{0HE ;H{@HsHHE0*H{PHE@HtHwHHEPH{XHtHwHHEXH{`HtHwH|HE`L[]A\H@ H5H81ATIUHHSHHE$$11H5gB HD$IEu"D$f(fT !f. !wf.zBHHH[]A\OHHD$HD$H=&B ^H5WH1HHD$HD$H=A aH5(H1SHHH5A 11H[Hff.fAUIATIUHSHHdH%(HD$1؃:H` gHCH? H9H,? H9H> H9vHHHHH HLE@HdHtuHUH> HJDHHLLGHD$dH3%(H[]A\A]Ha> HHLHrH > HH= H9@H5? Ht=HHL,$H5? HHHLKfH5? H11HHHuqHLfHHLLf.H5LlH5LLH< HH5yLH< HH = HHupHL!E'AWAVAUIHATUHSHXHB@LzHT$HD$8HBHHt$ HD$@HHRhHD$HAPHxH@H|$HHyxHD$HwH|$0Ht$(HqxHt H9HHEHU[HEH|$8t H|$@}D$01D`QDHH9}RH|$tH|$HLHHT$Ht$ HHIE uIEH9|HD$HT$0H|$8HPxtOH|$@Ll$Mt9HD$0H~/A1 DA9tMtLLHRA9uHHEHU]HEHX[]A\A]A^A_H|$(,E1AE9MtHt$LH@HT$Ht$HHHT$@Ht$8HLl$M#WHT$@Ht$8HlHHD$H=a< H5HPxHT$HHPx1:f.AWAVIAUATUHSHhHB0MnxHL$8HZHD$ HB8Ht$HD$@HHRhH$IFXHHH@HD$0IF`HL$XHHH@HD$(IEHL$PHD$HIFxHt H9qHE1AHUHE1H5: H|$8{1HELLt$IHI9H|$0t EH|$ t H|$@H<$0LL=H5: 11HIHHD$HD$HT$HHt$H+H|$(H|$8LI.HT$Ht$HHI 5IGI98Lt$H|$ MnxMeMfxtLH|$@L4$Mt7M~2AE1 @AE9tHtHLHA@E9uHHEHU}HEHh[]A\A]A^A_fDH|$HE1AE9HtH4$HHDHT$(Ht$PHHT$@Ht$ HVfHT$0Ht$XH~"HT$@Ht$ HgL4$MIFxH=-9 H5HP1IVxff.@ATIUSHQHH52 HHLHH.[H]A\fUSHHHH5t2 H\HH[]fUHSHHHHdH%(HD$15Ht HT$dH3%(HH[]fH6 HH0Hu)H="8 Ht1fATIUHS{HHHL[]A\Jf.ATIH53 1UH1S`w9HýuI,$H߾H=3 HH[]HA\B1@SH= HdH%(HD$1+H=i OH5 HH.3 YH5 HJH= H3 GH=o H2 4H=2 H5H2 HX0 H@H5HH2 H=2 HH5" H=2 HH5 H=e2 H)H5 H=F2 1HH5 H=*2 HNH5 H= 2 1HH5 fH=1 HSH5 GH=1 1H'H5 +H=1 HXH5 H=1 1HH5t H=y1 H]H5_ H=Z1 1H1H5N H=>1 HbH58 H=1 1HfH5& zH=1 HH5 [H=0 1HH5 ?H=0 1HH5 #H=0 1HcH5 H=0 1HH5 H=t0 HH5 H=U0 1HH5 H=90 HH5 H=0 HNH5 rH=/ H H5 HH=/ 1HH5 HbH5 HSH=. H5 HH5 H%H=. H5~ HH5X HH=x. H5X HHH5* HH=J. H50 H:H5 HH. H= . HH5 uH=- HH5 VH=- 1HVH5 :H=- H5 HH5 HH- H=- H5 HvH58 HH=X- H5 HH5 HH=*- H5g fH5H3H{H5, HH* H8H+ H<H, H+ HHv, H+ HHW, H+ HH8, Hq+ H`H, HR+ H)H+ H3+ HH+ H+ HH+ H* HH+ H* HMH~+ H* HH_+ H* HH+ Hy* HH* HZ* HqH+ H;* H:H* H* HH* H) HH* H) HH=) H* `H) H0Hi* H) HH=q) HB* HU) HH* H6) H]H=H) H) H$HH=cHHHBH=( H* H( HH~* H( HtZH* H* HD$dH3%(H[fD H=aHH) H=H( fDH=_H( VH=v?H' &H=HHH' H=H' H=H' OH=H'  H=Hp' H=~HX' H=u_H@' H=9?H(' NH=H'  H=H& H=H& H=H& rH=xH& ;H=KH&  H=6_H&  H= ?Hh&  H=HP& _H=xH8& ( H=CH &  H=H& H=H% H=H% LH=(_H% H=}?H% H=H% 辽HHC*@instance_variablesto_hashHashto_h0123456789abcdef\n\r\t\f\b\\\"JSON::GeneratorErrorunallocated JSON::State%u: %li not allowed in JSONnullfalsetruenesting of %ld is too deepjson/commonExtGeneratorJSON::NestingErrorfrom_stateinitializeinitialize_copyindentindent=spacespace=space_beforespace_before=object_nlobject_nl=array_nlarray_nl=max_nestingmax_nesting=check_circular?allow_nan?ascii_only?depthdepth=buffer_initial_lengthbuffer_initial_length=configuremerge[][]=generateGeneratorMethodsObjectto_jsonArrayIntegerFloatStringincludedto_json_rawto_json_raw_objectExtendjson_createTrueClassFalseClassNilClassMULTILINEto_snewallow_nanascii_onlyunpackcreate_idextendkey?__send__respond_to?matchkeysduputf-8findEncodingencodingencodeSAFE_STATE_PROTOTYPEJSON/Generator/Statepartial character in source, but hit endsource sequence is illegal/malformed utf-8source sequence is illegal/malformed utf8X801234567890    ;B8H`8x8hȽ4(LHhȾȿ$XLtX D|( Px@Th( xThH xX  Hd x  4 8T t  , h H zRx $ȱ@FJ w?:*3$"D0\pTH F A D%HW\"HTt&HW&HW'HX"HT0ԺAULغEvhFDO WAAF$Ļ;AAG lDA$ܻDEAN hFA$0<EAN `FA$X:EAN cAA44FAK K FBK FAB4FAK K FBK FAB4DFAK T FBB FAB4(̽FAK T FBB FAB4`TFAK R FBD DAB ܾEO t AA 0HFAD D0  DABA @FIB A(A0JP 0A(A BBBD 04FEA J0t  AABB HhL FBB E(A0A8D` 8A0A(B BBBH @FBE K(A0D@ 0A(A BBBK (aFKF x ABA $0(8<1BGD `AB8dPBHA  ABH M ABH K KK0 AD (ADD@Y AAD 0EADG0T AAF ZAA8L6H] K Dl89H] K DX9H] K Dx9H] K D9H\ L DLBBB B(D0I8G 8A0A(B BBBH ,<XFDA 1 ABA 0lHBDG G0N  GABE #AZ8BED D(G@+ (A ABBI LvBBB H(A0D8D 8A0A(B BBBA LH!BBE B(A0D8D# 8A0A(B BBBG (>BDA lDB$.EAG [DA(EDM0u AAC  iES E 8 iES E X ,iES E ,x |pFAA Q DBE , pFAA Q DBE 4 EAD R DAO R DAE 8 d~FBA A(D0V (D ABBE 8L ~FBA A(D0V (D ABBE ( 6FDF \CB( lFMH x AEE D EK  AG GNU` `{ ^P  d[P{ X{ o`@  1 } P@ oooor o{ P`p 0@P`p 0@P`p 0@P`pGA$3a1q[ GA$3p1113pb[GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFYpJGA+GLIBCXX_ASSERTIONSgenerator.so-2.5.9-114.module_el8.10.0+3991+5e651d4e.x86_64.debugHr7zXZִF!t/]?Eh=ڊ2N% TC (;'5+^#\zÑ5CtLDWKoh: np_[7'eԦ# ;i"\"ϕ\3(xWc[m!pQh̍z$:W]Vr˫k2DS5fDZhԛE7'(NrGnHrmam-Rr .cn_:v)㘜$pz{jٽvT`|gN΍΍Guco.y,G(.i&!(T(ZeK\#-K:NQRF\5#ѿv3S`ua77kH@KuƁxtBYDJѥC?RbN#Xmk|s87eGZR+x) MsW,kc*#g\Ag[8X f=΄?&jNN61:~R\[=,҂j+vX N2VuFB|#q2J!v^'}I4gJ%@^hy%̷zh<9/C (!GFH$M؄Pv/[aUn`ɩcd |;07okLI#eμbJͽq\sjgYПVL^|>n<U'Q"1uA_>?<@c[/.zq坽Q!0pkaS_-$ T5䡝 G?/l_/K`ڮq@CAsլ'(\l  @la뷌g¨#?F{hI`*VlX+ݲ5|n, ڬ|! xl qYK;ކ qJ41#Io'JOq{l<&-mf/☥BWhF5F]$P|ipb4 1dDgYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 0@ @ 18or r Eo@T@@^BPPhc@@@n0w?}d[d[ [[ 8a8aXcXc `n`n P{ P{X{ X{`{ `{h { {} }0 `H0Hx4"PK!XIv C Cbigdecimal-1.3.4/bigdecimal.sonuȯELF>'@;@8 @ p*p*!p*! **!*!888$$ Std Ptd   QtdRtdp*p*!p*!GNUtod!EvO^@h@@^cBE|X=|/\؁9wqX "s-M:K`.UXqy #dCE"=_.jT/cI0, SF"z?#\ 0!H1! 0G P1!v0!@1!U0!0!__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizegOne_ABCED9B4_CE73__00400511F31DgZero_ABCED9B1_CE73__00400511F31Druby_xfreerb_thread_currentrb_thread_local_asetrb_inspectrb_str_duprb_str_catrb_exc_new_strrb_exc_raiserb_obj_classrb_class_namerb_warningrb_str_new_staticrb_call_superstrlenmemmove__sprintf_chkrb_thread_local_arefrb_num2ushortrb_id2symrb_hash_lookup2rb_check_string_typestrncasecmprb_eArgErrorrb_raiserb_sym2strruby_xreallocmemcpyrb_fatalrb_check_typeddatarb_yieldrb_protectrb_jump_tag__stack_chk_failrb_num2ulongrb_uint2bigrb_eFloatDomainErrorruby_xmallocmemsetrb_str_tmp_newrb_str_resizerb_warnrb_str_new_cstrrb_data_typed_object_wraprb_string_value_cstrrb_check_safe_objrb_eTypeErrorrb_bugrb_num2intrb_fix2intrb_error_arityrb_big_packrb_sym2idrb_rational_numrb_rational_denrb_typeddata_is_kind_ofrb_big2strrb_cBigDecimalrb_float_valuerb_funcallvrb_num_coerce_binrb_int2bigrb_intern2rb_str_newsqrt__errno_locationruby_strtodrb_float_newrb_assoc_newrb_num_coerce_reloprb_num_coerce_cmprb_memhashrb_eZeroDivErrorrb_ary_new_caparb_ary_pushrb_Rationalrb_num2longrb_thread_check_intsrb_eMathDomainErrorrb_big_cmpruby_snprintfroundrb_dbl2bigrb_mBigMathInit_bigdecimalrb_cNumericrb_define_classrb_define_alloc_funcrb_define_global_functionrb_define_singleton_methodrb_define_constrb_define_methodrb_define_modulelibruby.so.2.5libc.so.6_edata__bss_start_endGLIBC_2.3.4GLIBC_2.14GLIBC_2.4GLIBC_2.2.5ti ii ui p*!(x*!@(*!*!*!*!**!(/!/! /!c/!/!_/!/!d/!,/!./!1/!Q/!S/!U/!b/!W,!,!-!-!-!-! -!(-! 0-! 8-! @-! H-!P-!X-!`-!h-!p-!x-!-!-!-!-!-!-!-!-!-!-! -!!-!"-!#-!$-!%-!&.!'.!(.!).!* .!+(.!-0.!/8.!0@.!2H.!3P.!4X.!5`.!6h.!7p.!8x.!9.!:.!;.!<.!=.!>.!?.!@.!A.!B.!C.!D.!E.!F.!G.!H.!I/!J/!K/!L/!M /!N(/!O0/!P8/!R@/!TH/!VP/!WX/!X`/!Yh/!Zp/![x/!\/!]HH!HtH5!%!hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?h@hAhBhChDhEhFhGqhHahIQhJAhK1hL!hMhNhOhPhQhR%e !D%] !D%U !D%M !D%E !D%= !D%5 !D%- !D%% !D% !D% !D% !D% !D% !D% !D% !D% !D% !D% !D% !D% !D% !D% !D% !D% !D% !D% !D% !D% !D%} !D%u !D%m !D%e !D%] !D%U !D%M !D%E !D%= !D%5 !D%- !D%% !D% !D% !D% !D% !D%!D%!D%!D%!D%!D%!D%!D%!D%!D%!D%!D%!D%!D%!D%!D%!D%}!D%u!D%m!D%e!D%]!D%U!D%M!D%E!D%=!D%5!D%-!D%%!D%!D%!D% !D%!D%!D%!D%!D%!D%!D%!D%  H% f.fH=A!H:!H9tH!Ht H=!H5 !H)HHH?HHtH!HtfD=!u+UH=!Ht H=!d!]wHGH(ff.@!fDHB ffffUfLBfHMt6J$fH*Y XIvJ(fH*Y uXHRHHffWH1H!f.z,u*H !H:!^fW:!HÐ!ff.ztJ l!H!f.z%u#H!^fW  6!^!1H@!f.PhbHE!Hr!^!;!f. zuHB!^!Hff.fHtBfff.@USHH-)!lHH[HTH]CSHH@u Hu4H!H51HHHHHH@HH=1JH=HDU1HSH=$HHH[]HtSG PfwI HsDHW>FHDuHOHD HxH9sH)HH@fHHHH)Hff.@ftftEftO1ftfNaN@fuJt|0.0Ãt[u+HHInfinityFH-0.0FH-InfinitHyfF@ H+0.0F 0.0FAVAUATIUSH=Ht^ItTI>(111fD<.tD1UDH[]DHHZHwH5HuH[];H51f.HhHHHf.H HH8HfD듐fSH 3HHHtH[)fH HH1[USHHHFH4$HtFHSHHs$H}$HPHCHHEHCHEC fE C"fE"%HH[]FH5H=11ATUHH5 SHFH5o HI4H9tHLDHC H[]A\USHdH%(HD$1HT$H=8 iH^|$uHL$dH3 %(Hu H[]WfSHP HH(Ht"tH[fH[H dHHD1[ATUSHHH?H9w*H\L% !HLHH[]A\HHff.USHdH%(HD$1!HT$H= H8HH]|$uHL$dH3 %(Hu H[]&PXH5HH HH81ff.@Hftft-ftHH=H=1H=SHWHtH1H[H5%H=81fPXH5"HH H81fUHSHPf t*ft5HHrHH=ӿ1$@HH1[]SHftftQft+H[fDH5ٻoH[f.H5OH[f.H5ɻ/H[f.G PfwIHHsF PfvKHWHNHGH9FHCFH9tHH)H)HHHsHH5ھHHIHHsDffffAD ftcft]CfAG$H5HGfDG fDtTtff~G1G$H5HGfO DtZf`G$HGfw H5)gf.VfkfffDfCf.Pf+f~Lf~LG$HGfW aff~ff$f~G$HGfG ff.fHOL1H~;H~'I@HHHHHLGDHyI@HHAHvHHHHf G$HG fw H5)fMHHIHNfDf ~1G$HGfW H5xG$HGfG fDM~#HHIH 'DHHIHf.HHIH:ffO fO Afw#]HsG$1HGfHWf.HBDD$Eu2HHuG$HGf~f1fW f.w$HWurU1SHHHuL$tHtH)HHHWuH[]ffG 1HCHt(H{$Hʸff.fAWAVAUATIUSHH8H{H88HHHHH IIMA$L wfDH v t#Ht#H88HHHHHBI9LGHLL$HxLL$H IHhH1E1D tJDRA< 0 H<_IJ|HD u H=ܸH H=Hd H=HH=&HE<-tD$1<+@L50 1@у0 HHL5uHl$(II1E1HLD$ H88HHL$HMHBLDI9ICH$HD$H|$HL$IHD$LD$ AD$$ID$ID$AfET$ 1HSI|$$LD$HL$[HL$LD$HHD$(<-ZHD$E1<+u HA1Lt$L\$(ILD$ wLHHHH4HH O4 HMHLA0McM)I9HHrH/HH9IL9HHuK 11f.HiwHh(yH@I@$H@fh H8L[]A\A]A^A_fH~D$fDH~;LHHHHt$Lt$D$LD$ HL'@HHHHD$LE<-iD$1<+u II88E1HA1G\L 3LH?HL1H)HIHHHHH9_D$K1I9AD$I9v6Hw01f.4D HHDpAD$HwI9wI9HMtVMT$1@H&L9A H@f G$HGNA1fD HH[]A\A]A^A_D$Et1f} DM1DHI9}ɚ;nMf} HEE$HE7fM HHEMtYH88LHHHUHI)t8U$1ɾKfDҁɚ;v HEHI9uۉU$HH[]A\A]A^A_@FfL_1MG$IL\$AE1A$HD$8HD$tfDHD$1J|$L $LD$H~fAL $LD$H߭EJcH>DfU fB\$HD$$AwBD\$$E4@M-f.A @BD$Ht$HZODA1fDw fDD4$D$$E1D$ <$f} D,$EYANxt$$fAvf} x []A\A]A^Avf} ~HL[H]A\A]A^%DAE#wDAdwDAE#wAeAwAtAwjf.f.&f(fT f. Zff.ATf(USH f/wfW d%,f/"1^Hf/sLg1HH$T$JL$D$FL$fT$f/M1I9YfH,ɉʉL$HH*\f/wI9vdl$L`f/vjYʺLcfS HkH,ɋT$fG$HGfO ft$1ID$f/YfS 1LcHkH,MuH H1[]A\Gf/G$HGvAfDG fw fD%h1~f/j@YHf/wSDE1G$HGfDO 1AVAUATUSF HfAffPfHVLnHH$Hv$HWDfAOąL9oLFoLoN4fGLA t)L9mL1ҋM$MtU LHLkKD[]A\A]A^ÐDC$fHCDNE~@1fs []A\A]A^@G$1HG1f{ []A\A]A^1fK DG$fHGDNE~0fW SD1HLk6DfG #ff.fATIUHSӺ :HvL[H]A\f[1]A\fN$tyHFH~pHVN H9ssH)HGHGH9HG1fHWfG HFHtHHHLL$AL$HH9u ffDG$HGf~ fW ffG fDAWIAVIAUMATIUHSHLD$YIWH|$PE$HL$XI^HuI+_LM9VMCVH~LD$I9HIuH88HIFHH;EsRI$IOHEH4H9HKH9H)HHIHH9AD HL$XMU/@I<$H9rAD HL$P뛐IIFII$MUIFLUHHEHHDHH[]A\A]A^A_DIMUIMUAWAVAUAATIUHSHHHv dH%(HD$81H ɃM1҅tOAT$ M rAfu]fC$HCflAfD[ @H\$8dH3%(HiHH[]A\A]A^A_ff_E1AHEAGt6I9D$*MD$H}I9HIFHt5E$A9D$$|1fD\$E9\$wdHH9uI9wPA1fM@fNǍDpu+AC$ HCfDS @M1fAE1ffDK AHL$ G|?EE|GHD$fEPLHHHD$ PLL$@LD$8_AXD$ HLD$(IL$L$H|$ Ht$0L$ Mt3JH9rfJH9IHBT$T$MuH9dII)IHD$I9u1HHIAD$BD$1HtnJL Hf1HHtKHAD$=ɚ;v-ʚ;DDfDNA~fDk I)MtBD 1fAfC HC1HtT L$ 1H9HCH4@PHHLHD$ PLL$@LD$8 Y^D$ H!LD$(It$L$9r)1҉t$ H|$ J4HL$0H9nMtMAʚ;AfDJ4AH9IDHB+T$D)҉T$MuѺHH9v'HAʚ;DHH)кD$H9rE1H9@HtFHH)LH@)1At$Ht"HAt$9sɚ;fH)Ht)T M91fA} EDD1AfC EDHHHCHDILpDLHHCHSvfDHHAD$D$H9rMLLHHL/@uYÄuYHH#ЃHH\H[]DÄtHHt Ht‰ǃHDYt%HE6t%HEؼt%HE赼HH\H[]fDHn@DHH\H[]fDH- H\ԴHHH趴HH[]ú-H H5H81H H5τH81ͳff.fAWAVIAUIATA4USH@HHdH%(H$1HD6H$AtRA DItKA tEI4t?Aw1H^HcH>IuIt Mu@1H$dH3 %(H[]A\A]A^A_DMI4]M9tLHHIHtH$HLHT$]Aw LIHT$IH[H׃LcMLL}3IDH5 L聲IF  LHD$8HXH tHXH襲HHx H Hf.MILef(fT f.ff.zH5X L114I@H\$pM1HIH H H޿HkfDHL$0HT$(LHHD$(+HH HyLL.I>fD1LL$H u LL$H5HD$HIyLL$LHIHLT$HD$@LHIHHD$HxLT$H5ƒIHIRHD$PIFIGHJHH9HFH ׼ H| HHOLT$LHHLHT$XLH|$'LT$LL$LLLT$%LT$Ar LI4fDL HMH=迳HH gH LH8~fDH|$(w zH8ILzH5 HH H81ϮH 1$H $HH$H$ fHX ^Hf/wH5LaH50LM&1USHHdH %(HL$81ɃHHHFH5HHHHD$ 1Hp2!HD$HD$H tHD$HXHEH HHL1aHi11HH4蹸HQH|$H褮HD$HL$8dH3 %(u)HH[]H\$H|1fHHWP 1ftftft HfD1HfHHP ft1fHDHDHHfx HHHHH@ HHDHHgp$HPtBHHҺHHHDHwHHHHH9wHcHDHSHH@dH%(HD$81H5EHHHHD$謴1H¯HD$HD$H upHt$H11H苶HD$H u>H|$HH|$HcHD$HL$8dH3 %(u)H@[HD$HxDHD$HpЫSHH@ fHDH[ff.HH@ fHHff.UHSH8dH%(HD$(1H5~HHH$HEHfDIF1HH4HHT$HT$AV fH ff@f@ f f@7f*"HwHcH>fDH5٦ Hqu}*"QH2xHcH>D1ҾH HHT$HT$AV f3*t1HL$(dH3 %( H0[]A\A]A^Ð1HHHHT$fHV}fDH H@HD$(dH3%(H0HL[]A\A]A^酡DH HuľH=rcHH H HHLHI_HI HHD$(dH3%(H0HL[]A\A]A^魟D)@EЅ*H؀"H vHcH>Dqzfthf_ffHxI9~?f*"gH wHcH>1ifffH*"%HWwHcH>fDfDHfH~~fHrhHDHHZ@H= pgHH H=o?HH} 8H=rHHU fQf*"'HvHcH>1Qfs*"HAwHcH>f~z*"HwHcH>LHMFM9LIFHt+p$A9v$wr31DDT$E9T$wrHH9uM9s/ff~*"w\HwHcH>v*f:*"w5H#xHcH>I*"wHxHcH>H=k1HfDGf>fLf<f=f*fAUIATUSHHH8dH%(HD$(1IHH$؃1HHHHHEH5mHD$HEID$HfDfC (萒AUATIUHHSH(dH%(HD$1+HcHu-HD$dH3%(H(LH[]A\A]T@1虢LHI;LH耢HHLHHH$=HHoHD$dH3%(u)u H(H[]A\A]9fK;葑蜣ff.ATUSH dH%(HD$1GHH\$tWA1tua؃HHHtZ tUwHHnHcH>LfLA貔cH\$HcuHuH|$ʏHt$H HvH Tf.Hxof(fT of.HIHHHL$dH3 %(H []A\fˏ4fDH5 H葏5HD$H@ fDH;HH$yH 1D$H#D$HHD$0HD$@Ǒ股H H5bH81zHH5`HHy H81W2fAUIH5 ATUHSHHdH%(HD$1軏LInHHs HH$hHu3MtLFH] HH+HL$dH3 %(uH[]A\A]ÐHLuH苎ff.ATHc I1USHdH%(HD$1HG H8藍LHHHs HH$贠Hu'H] HH+HL$dH3 %(uH[]A\@H1ΜH@AWAVAUATUHHSH׺HXdH%(HD$H1IHHD$ .H5JbL11HD$试H$H1轐HD$HD$H gLt$I>A} LfA} SLFI^A+9H}HH|$H$uHt@eXH1H$H5daL1ԔHƐH<$HHD>1HHt HC<0t<.H<$tH4$LޕfDL H|$HsHD$Ht$HdH34%(HX[]A\A]A^A_H$LL7DHD$Lpf蛏fDA-I^ImM]HIE1AMu`Mx^EE$HH []1HL\$EHML\$AHMu.HIM9IMtCD$Hs 1H0׈CAH9uDHS Hu.HHS @HZHyefHHC@0H9ufDL)0.Hsf HDHS H)HK fDHB@H@0H9uHP H9uHHHHH)HH\ 0fI^A fH|$$H|$I臉I$ 1+u(IT$IH$HHDBH$I$IʍAv t߃0 vƃ߀FH5\LˑHHHIT$I뙺1襋H H5\H81]8UHSHdH%(HD$1eHHH] H$Ht(Ht"HL$dH3 %(HDu+H[]fDHEH}$H4cH1H]襈DAWAVAUATIUSHHHxdH%(HD$h1IHHD$؃1HHHHHEH H5[HD$HEIEHL4LOt6 uHLH5ZIHHD$ XHLH5ZIHHD$(;HLH5dZIHLD$HD$0HLLIHLHD$8MID$HH5ZL,MLߪHH5ZLIHL $HD$@辪L $1ɺHHLLHD$H轷LHLD$HHLL$+L$LLLHD$hdH3%(Av HxL[]A\A]A^A_EDH^tiKIEHH4HBH HtTHLHteHL$hdH3 %(uPHx[]A\A]A^A_@H~HfD H=_Y蟉HH fAWAVAUIATIԺUSHHHhdH%(HD$X1IHHD$؃H1HHHHHD$AF f+K fffQfH5 H4$HfffINIFHsH?H1H?H)IFHHCH1H)HCH5/XH9HBL| L+K|? H5UWHHHD$ H$HHLHIHLHD$(lyE1"1Yom@AWHAVAUATUSHHHT$HdH%(H$1HH|$H|$tK؃HHHt0 t+wHJHcH>@HuHx HH8sD{nHD$uHt$1H肷HtX f\$>HH\$H\$Hf|$>H$y fP Hw H5?HSp HW~Hx HHD$@G fRHL$XIIHHL$(HL$PHHL$0fDp$HP1Ʌt.H Hw!fHHHHH9wHG$t8HHHfHHHHH9rH)HL<$H?H1H)I)!kMHt$LIIH@LCO|?H@HLl-ILABnLcMtLLILLHsI} IG fID$ H5 q HiHC X f\$>fLfBf|$>Hu H|$H5<HB1@$H@fH HD$X1HH+|WHlf(fT Hf. Hf1f/Ht$讴p H{H$dH3%(H[]A\A]A^A_1HHhKA!IH@HLHgIIFHL$(HT$0LLHD$PHHu H[LLkI.+hfD1LD$ xH Ut LD$ H5;HD$HIxLHIHHD$`聳LHIHHD$hbIWH5:IHHJHD$pIEIFHH9HFH s H| HH>LLHHHT$xLuH|$xsLD$ LL#Aw LzIfDL0fILd$@f|$>,ID$ p$HPtfLvLHHHHD$@I?ALHf{ H$=HU` H<$H5'HwHD$0E1@$1HH@HfDx fH\$hdH3%(Hx[]A\A]A^A_DLpW8ƒvHHHe< ] =LVI LHHA A W H5Z LRtkHt$LHD$0=LH±HLIMAIIt MLZUH5$HHq^ H81QLpUD$5UL$f.  1f/f/ 1L,O|E1C f<MLHH5_ HL$8LLL$HD$8RLL$HH] H5$HH<$,up H0d{LSH$Uf(QIYHH5e^ HL$8HHD$8:RHLDH?HAueMIA  ~uHL$8<LHD$8Q1H…tH4$LIdAAAC fVLH?MA LHH5AA'A A: H[ HH5^#4fDEcMIA  Dt LDL${Rf1DL$f/@H H5m\ HL$8LHD$8BPHLRIfDE1LH6@DȃYHL$8<LDL$HD$8ODL$HYHZ H<$H5W!HrHD$0f{ HA@$H@fDh ACDCLHH2A (A McAAD+LHHA A, C fnfdMM5I(A L1HŨO  G HHH6 @ , EQ O  Ld$8<HHD$8LMDDH(  A    L<LHD$8MH( f{ fL荓VI}IEH/X HfpH5oIHHD$Hs FfMfD M3 AAE$IEfEU ILA^@Hlf.HOHLfLLNf1f/f.A Ht]E1BfIH5 X HL$8LHD$8KHLH5W HL$8LLL$HD$8KLL$H LUDLLL$MLL$IH@LLL$MLL$HD$L!MoHHbHD$UHHHDI1ILOMHLLHHLHvLLL$MLH}LLL$HH@HH1I^DDeMI}A  neHL$8<LHD$8IHwf{ rMuItA rHwT HH5muvMIA Ht$0LH$!JHT$0H$H҃A@$H@fDp NMuItA tuLHH҃LHLH?IHD$(AA fH $LL$H@HHi7L%ZS H3Hl-HI<$LL$HI9HHH $HH@HHT I<$HHT$(HT$0HT$(fff&H{MbHD$IIEH5lH|_H5[HH@HH| _HLImuIL|$HHNuH|$A f.IHHL_LHuK?H;D$vLH)L$HL|$LL)LLtMrH|$MtLGFH?FItAu fft fAu LmHf1f/AE$IEIEfAE |H0Q H<$H5Hhf{ IMuIt A t|HQ H5H81CMO L#IHCHH5HHHHhIHHD$HzA AHt$0LXFHD$0HЃAE$IEfAm xMuUIA u4Ht$0LEHD$0HЃHO HdQLHHЃMULAE$HIE M;OfA} IfDE1AE$IEfEE H<$BHH BL%O H3HI<$HHALL$HgOH$LhXLAHF&LAHFMAAAE$IEfEM Mu7IAAE$IEfEe uLHHЃHD$TH{.{$$fAE f{ AE$IEIEAfAE fDAE$IEfA] AtAAE$IEfE] ~fAM fAu H*N LHLHLo3HH5N HL$8HHD$8AHHHHIA kE<L<LHD$8\AHH9L H<$H5HcLHSf{ E$HEfE u HR+BfAU H?CHIBHHAIILs>H;Cf{ E$HEHfE CL&Bf1f/L>HBLH?>LH?rLAf1f/XL=HB;HHHt$Ht$Hff.UH=SHdH%(HD$1AH= HK AH= HK Aff.J HK zuHGJ ^ J f.J z$u"HI HJ ^ J  uJ J f.zgueHI HI f.~% ^f(fW /J ztJf.z4u2^fW J Df.ztHAI ^yI H5ZHUH5HJ mUH=HI HH H0@HH H5`HH@H5;H=>H;HDH5>H;HH5q>H;HH5~>H;1HRAH5Tf>H;H`H5DK>H;1HCH523>H;1HKH5>H;1HH5>H;1HLH5=H= ;H;H5HX?H;5wH5D?H;H50?H;H5?H;H5?H; H5>H;H5>H;!H5>H;H5>H;H5>H;H5>H;H5|>H; H5h>H; H5T>H; H5@>H;H5,>H;H5>H;H5>H;HH5=H;H5=H;HH5=H;H5=H;HH5= H=n 9HHH$EH;H5>Hc=H=9HHH$H;H5:H,=H;H=H5 q;H;HHH5V;H;1HH5>;H;HH5#;H;H$H5;H;HH5:H;HH5 :H;1HH5:H;HH5:H;1HCH5 :H;1H+H5Vo:H;1HH5EW:H;1HH52?:H;HPH5$:H;HH5 :H;1H
H5] R9H;HH5 79H;HH5 9H;1H|H5 9H;1H|H5 8H;1HPH5 8H;1HH5 8H;HH5 8H;1HՋH5 8H;HH5 n8H;1HH5 V8H;HGH5t ;8H;HH5_ 8H;HaH5I 8H;H6H5] 7H;H H57H;HH5 7H;HŚH5 7H;HH5 ~7H;HH5 c7H;HTH5~H7H;H)H5^-7H;HH5E7H;1HfH5R 6H;1HH57 6H;HH5% 6H;1HH5 6H;1HsH5 6H;1H+H5 6H;1HH5 g6H;1HH5 O6H;1H#H5 76H;HH5 6H;H݄H5 6H= 57H? HHH5t H5H;HH5Z 5H=R 47H=Q H@ 7H= H@ 7H= H@ 6H= H@ 6 H= Hq@ 6 H= HQ@ 6H= H1@ 6H= H@ t6H= H? \6H=H? D6H=H? ,6H=H? 6H=O Hq? 5H]? HD$dH3%(uH[]92HH can't be coerced into BigDecimalBigDecimal.ver is deprecated; use BigDecimal::VERSION instead.BigDecimal.new is deprecated; use Kernel.BigDecimal method instead.Computation results to 'NaN'(Not a Number)Computation results to 'Infinity'Computation results to '-Infinity'invalid value for BigDecimal(): "%li "Conversion from String to BigDecimal overflow (last few digits discarded).load failed: invalid character in the marshaled stringERROR(VpDivd): space for remainder too small.second argument must be true or falsefirst argument for BigDecimal.mode invalid%li can't be coerced into BigDecimal without a precisionBigDecimal to Float conversionUndefined operation in BigDecimalCmp()can't omit precision for a %li .Zero or negative precision for expComplex argument for BigMath.logZero or negative argument for logwrong argument type %li (expected scalar Numeric)a non-integral exponent for a negative base1.3.4%lue%zdinvalid rounding mode: nilinvalid rounding mode: %li failed to allocate memory%snegative precisionExponent overflowComputation results to 'NaN'Exponent underflow+Infinity-Infinityexponent overflow#0Divide by zeroargument must be positiveinvalid rounding mode-0div%zu:sqrt of negative valuesqrt of 'NaN'(Not a Number)#1<=>>=<=precision too large.Fremainderdivided by 0divmodto_i**precision must be an Integer21E%ld0#BigDecimal.exception_modeBigDecimal.rounding_modeBigDecimal.precision_limit.5BigDecimalnewdouble_fig_loadversave_exception_modesave_rounding_modesave_limitVERSIONBASEEXCEPTION_ALLEXCEPTION_NaNEXCEPTION_INFINITYEXCEPTION_UNDERFLOWEXCEPTION_OVERFLOWEXCEPTION_ZERODIVIDEROUND_MODEROUND_UPROUND_DOWNROUND_HALF_UPROUND_HALF_DOWNROUND_CEILINGROUND_FLOORROUND_HALF_EVENSIGN_NaNSIGN_POSITIVE_ZEROSIGN_NEGATIVE_ZEROSIGN_POSITIVE_FINITESIGN_NEGATIVE_FINITESIGN_POSITIVE_INFINITESIGN_NEGATIVE_INFINITENANinitializeinitialize_copyprecsaddsubmulthashto_sto_intto_rsplit+-+@-@/quo%moduloclonedupto_fabssqrtfixroundfracfloorceilpower===eql?<nonzero?coerceinspectexponentsignnan?infinite?truncate_dumpBigMathexploghalf_updefaulthalf_downhalf_evenbankerceilinghalfP1SPR~RPSDSP|RPRVRPSdST\UT$UUTT4U$vtttttututtutttttv | 0 p$ߋߋߋߋߋߋߋߋߋߋߋߋߋߋߋߋߋ ߋߋߋߋߋߋߋߋߋߋߋߋSSSSSSSSSSSSSSSSSSSSSSSSSSSSSNJNJNJNJNJNJNJNJNJNJNJNJNJNJNJNJNJkppNJNJNJNJNJNJNJNJpNJNJNJNJk(;;;;;;;;;;;;;;;;;߆;;;;;;;;߆;;;;߆SXXXS#################̄̄Dž########Dž####̄;@@@; l(#(##\\\\\H\\\\\\\\H?PjP& .>C]r2<?eAC;q `$$p%%%%,'@'T(|p(((P)0**<,P- /p/(/T@001p11,2H`2d22 3304@6709hDPDpDE, PFL 0K K 0L 0MT O 0Q pQL 0R` S Z `_ f4 fH @g| g ph i k0pq|rrs@spss(tLuh@uuv`z({TP}}`~`pЅ`8p<`$`` 0\@Ц@P`(x@$t`xzRx $h@FJ w?:*3$"D0\x!p! !|!x#$#-AAF SDI#\A#+H^$#-EFM IFA@#qT`$<h,%BBB D(A0l (A BBBB d%BHB B(A0A8G`M 8A0A(B BBBA W 8A0A(B BBBE D'SAa N b@0'KAG  AAJ vAAHH t)PAa N _(@)AAG V DAA ()HFAK rAB()nEAD0W AAA $)`Ae J D L _(@4*UBAA } ABD (lh*oEAD0X AAA *!AAK*MDU A *7A[ A +AAK$+YADF ICA(0T+vAX G U K U K U\+]Ut ,.4/CD xAACL aH0 BBB B(D0A8Gp 8D0A(B BBBJ ( T;5BFN [ABLh;HS0dp;7FAD DP  AABA |<A D Vd<BEB E(A0A8D 8A0A(B BBBA  8F0A(B BBBE  tAc84ABAD K JBJ K ABJ Lp$BBEE D(D0M (A BBBH \ (D BBBJ XBOtEA D@ h@{ FABD@xX@`DBBB A(A0 (A BBBB l (A BBBE X (A BBBI 4F7BDD Y DBG ACBFHFmBEE E(D0D8DP  8D0A(B BBBF lGBBB E(D0D8G 8A0A(B BBBC OPBuOPANBGB B(D0H8G 8A0A(F BBBA s 8A0A(B BBBA | 8C0A(B BBBA  8A0A(B BBBD | RBHB B(D0D8G 8A0A(B BBBA  8C0A(B BBBF : 8A0C(B BBBA  DY0 @YFAA D0y  AABG ( Y}FDC x ABH  ZD o E 0 ZzD I LL \EFD f LAF  LAG _ IAG f DAA H ]BBE E(G0C8T 8A0A(B BBBF ( bEAD` AAI  cGMl G F4 d;MmL (d)H]d @d(HZ| XdpT[ dEPP AI  le2El e2Hf( eEMDPn DAE ( ,fEMDPu DAE LD fFGB B(K0A8D 8A0A(B BBBD ( 0jEMDP DAE 0 j<FMA D`{  AABI ( lEMDPs DAE  4mlH D [ ,< mEJ0T DI v GE ll XnBBE D(K0K` 0A(A BBBB h 0G(A BBBJ  0G(A BBBJ  t tts,s@sLTs}FJA A(N` (D ABBH z (L ABBE L uFBD G(DPD (G ABBI i (D ABBN `u@FJA A(N` (A ABBF  (D ABBL | (L ABBK LXwFBD G(DPD (G ABBI i (D ABBN `|x@FJA A(N` (A ABBF  (D ABBL | (L ABBK L XzFBD G(DPD (G ABBI i (D ABBN 0\{NBAA D@J  AABJ 84}FLA D(I@h (A ABBB 0}FMA F0e  AABE L~FBB B(A0K8N 8A0A(B BBBD (PtEMD0I AAG d|؂FGB B(D0A8N 8D0A(B BBBJ q 8A0A(B BBBE $zRx , L BBB E(I0A8N 8A0A(B BBBD (ptEDGPW AAG (EDG`^ AAH X=FGE K(A0D1 0D(A BBBJ  0A(A BBBH zRx ( L\HFNB B(A0A8D 8A0A(B BBBC HuFNB B(D0C8DPJ 8A0A(B BBBI H FNB B(D0A8D 8A0A(B BBBI LDFBD D(H` (D ABBI  (D ABBK LЕFBD D(H` (D ABBI  (D ABBK L FBD D(H` (D ABBI  (D ABBK X4pLFBE D(C0D` 0D(A BBBL  0D(A BBBE Ld FEB B(A0A8J 8A0A(B BBBA H43FBB B(A0A8Du 8A0A(B BBBG L,( FEB B(A0A8J 8A0A(B BBBA L|ذFBB B(A0A8D 8A0A(B BBBF x$H [(G EMD0) AAA GNU(@(*!*(  xp*!x*!o`8   ,!X` ooooBo*!P`p 0@P`p 0@P`p  0 @ P ` p !! !0!@!P!`!p!!!!!!!!!"" "0"@"P"`"p"@@?GA$3a1  GA$3p1113'wGA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFY(wGA+GLIBCXX_ASSERTIONSbigdecimal.so-2.5.9-114.module_el8.10.0+3991+5e651d4e.x86_64.debugs@7zXZִF!t/]?Eh=ڊ2N(^ SĎ0FN>JrѹpL!O}}OMJfk>u1 g;+a/+8 !B7זD2g7L=)crG_=*GGBAڍe_^X3;hMՒۆad**ʆ{%f6y&h`#ɑ?GngJ5豧 N:fj{ $\DjU; v(?K,CePЌVs5ޛL!<5Fd^N .ԲS,U'(懄{+dKFcMrALj*G>/ \~az$**/@cM5\5 NYf yRvUFA_:.ǩ4₥KL#k{MYԋ-@ Cv U'P bsc呞@3g *!~kI`Q(Q׸>'q! cG@~ }sB΍MdiL4_W€bܥ5E]|zOo}l?M70NW_/ Sj\Z-3vf_Ԗ6C/)ػW6L#CIjZ\FrnI(l0^.;ÓJ5p#f06J5$frX_yKЍfX};N7.`.;ݫ+Xw&_Z ;6P?+6\%m\eL㏏rQUq'@~f6jF "o^t!'ԢK|`sXF4f8taec5v(YK^4A6u|,ba|SS0R3xm84M{v_4T9#dooBISr&#Jk?EjgYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.data.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``D(  08 8 8oBBEoPT``^BXXh  c@@@n""0w''}xx    p*!p*x*!x**!*h *!*,!,(0!00!08P1a0H `2H2:(PK!}``psych-3.0.2/psych.sonuȯELF>,@`z@8 @ee ii i 8 jj j 888$$ddd Stdddd Ptd[[[QtdRtdii i 8PGNU8b3{$~`5X$6B_ BL0H _gjx BE"aj |SE6 ZqXH8 \FGU X.AF,W\}O@~fqP!g  1Pdu25I9&K)=[n, F"fc%f @=%p  W `S-q Xq q  -N Xtxq p y`q hq pq __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeyaml_get_versionrb_ary_new_from_values__stack_chk_failInit_psychrb_define_modulemPsychrb_define_singleton_methodInit_psych_parserInit_psych_emitterInit_psych_to_rubyInit_psych_yaml_treerb_check_typeddatayaml_emitter_deleteruby_xfreeyaml_emitter_set_canonicalrb_data_typed_object_zallocyaml_emitter_initializeyaml_emitter_set_unicodeyaml_emitter_set_indentyaml_emitter_emitrb_eRuntimeErrorrb_raiseyaml_alias_event_initializerb_check_typerb_utf8_encodingrb_str_export_to_encrb_string_value_cstryaml_mapping_end_event_initializeyaml_sequence_end_event_initializeyaml_document_end_event_initializeyaml_stream_end_event_initializerb_fix2intrb_num2intyaml_emitter_set_widthyaml_stream_start_event_initializerb_attr_getrb_enc_str_newrb_funcallvyaml_sequence_start_event_initializeyaml_mapping_start_event_initializerb_string_value_ptryaml_scalar_event_initializeyaml_document_start_event_initializerb_ary_entryruby_xcallocrb_string_valuerb_ivar_setyaml_emitter_set_outputrb_error_arityrb_cObjectrb_define_class_undercPsychEmitterrb_define_alloc_funcrb_define_methodrb_intern2cPsychParserrb_const_get_atrb_class_new_instanceyaml_parser_deleterb_funcallv_publicmemcpyrb_utf8_encindexrb_default_internal_encodingrb_iv_getyaml_parser_initializerb_respond_torb_ascii8bit_encindexrb_usascii_encindexrb_enc_find_indexyaml_parser_set_encodingyaml_parser_set_inputrb_cIOrb_obj_is_kind_ofyaml_parser_parserb_protectrb_str_new_cstrrb_enc_associate_indexyaml_event_deleterb_jump_tagrb_str_newrb_ary_newrb_ary_new_from_argsrb_ary_pushrb_enc_get_indexyaml_parser_set_input_stringrb_to_encoding_indexrb_str_new_staticrb_usascii_str_new_cstrePsychSyntaxErrorrb_exc_raiserb_define_constrb_requirerb_const_getrb_path_to_classrb_obj_allocrb_iv_setrb_define_module_undercPsychVisitorsToRubyrb_define_private_methodrb_interncPsychVisitorsYamlTreelibruby.so.2.5libyaml-0.so.2libc.so.6_edata__bss_start_endGLIBC_2.2.5GLIBC_2.14GLIBC_2.4ui  ii +i 0-i ,i i i kZi .@j "[Pj @Ao  o  o jo (o ho co do ko 9o Ko Po lo Ul l l l l l l l l  l  l  l m m m m  m _(m 0m 8m @m Hm Pm Xm `m hm pm gxm am m m m m  m !m "m #m bm $m %m &m 'm )m *m +n ,n -n .n / n 0(n 10n 28n 3@n 4Hn 5Pn 6Xn 7`n 8hn :pn ;xn <n =n >n ?n @n An Bn Cn Dn En Fn Gn Hn In Jn Ln Mo No Oo Qo R o S(o T0o U8o V@o WHo XPo YXo Z`o [ho \po ]xo ^HHN HtH5K %K hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?h@hAhBhChDhEhFhGqhHahIQhJAhK1hL!hMhNhOhPhQhRhShThUhVhWqhXahYQhZAh[1%E D%E D%E D%E D%E D%E D%E D%E D%E D%E D%E D%}E D%uE D%mE D%eE D%]E D%UE D%ME D%EE D%=E D%5E D%-E D%%E D%E D%E D% E D%E D%D D%D D%D D%D D%D D%D D%D D%D D%D D%D D%D D%D D%D D%D D%D D%D D%}D D%uD D%mD D%eD D%]D D%UD D%MD D%ED D%=D D%5D D%-D D%%D D%D D%D D% D D%D D%C D%C D%C D%C D%C D%C D%C D%C D%C D%C D%C D%C D%C D%C D%C D%C D%}C D%uC D%mC D%eC D%]C D%UC D%MC D%EC D%=C D%5C D%-C D%%C D%C D%C D% C D%C D%B DH=yC HrC H9tHB Ht H=IC H5BC H)HHH?HHtHB HtfD=C u+UH=B Ht H=< dB ]wH8dH%(HD$(1HT$ Ht$H|$HcD$Ht$HDHD$HcD$HDHD$HcD$ HDHD$ HL$(dH3 %(uH8~ff.HH=u+HA 1H5f+HHH?z[HBfHH5; HcHHDff.HH5; |HcHHDff.HH5Q; Lx|HHHЃf.SHCH[f.SHH5; 1HH@*H[DUH: SHHX HHH߾iH߾lHH[]fSHt[Hb@ HSH5)H81DATUSHHĀHt$H5E: dH%(HD$x10H|$IHu:1Hl$HHLxHHT$xdH3%(uCH[]A\@N)H|$H,HD$HtH|$H ff.fATH59 USHHpdH%(HD$h1HrHIHLHT$hdH3%(u HpH[]A\ff.ATH5#9 USHHpdH%(HD$h1HHIHL\HT$hdH3%(u HpH[]A\+ff.ATUHH58 SHHpdH%(HD$h11HH@IHHLHT$hdH3%(u HpH[]A\ff.@ATH538 USHHpdH%(HD$h1HHIgHLlHT$hdH3%(u HpH[]A\;ff.USHH57 HHHt'HmHH[]USHH5p7 HgHHtH=HH[];ATUHSHH57 HpdH%(HD$h1H߾IbH߃t:eHHHL=HHT$hdH3%(uHp[]A\ÐfATIUHSHH5< dH%(HD$1HLHHHHH5< H$HǨt"H\$dH3%(uH[]A\@lff.AWAVAUATIUHSLHHt$H$dH%(HD$x1H|$IHtH|$LHD$H<$HtH<$LH$HH5l5 gH߃IE1MAE1H<$t HeI1H|$t H|$NHLd$LADLLLjHHT$xdH3%(u#HĈ[]A\A]A^A_Dsff.@AWAVAUATIUHSLHHt$H54 H$dH%(HD$x1mIH|$IHtH|$LHD$H<$HtH<$L{H$H߃E1MAE1H<$t HI1H|$t H|$HLd$LADLLLHHT$xdH3%(u&HĈ[]A\A]A^A_{pff.@AWAVMAUMATUHSHHT$ H$HL$Ht$(H5$3 dH%(H$1 H|$(IjEH|$(HIEH|$ HD$(Ht;H|$ LHD$ H|$HtH|$LHD$H߃HD$(MAMLAEEA IDD$H|$(1H|$HtH|$HD$PHL$H1H|$ t!H|$ HL$HT$*HL$HT$HL|$0SEAVDD$LEXLZL8HH$dH3%(u.HĨ[]A\A]A^A_Ë@D$N@ff.@AWAVAUATIUSHHH|$0Ht$H5D1 HL$8dH%(H$1'HHD$(H HHIHD$ 1L|$PHD$E1H|$8AH >HD$H@HHٸH\$ Ht$HLHNHH|$(LHtH'H$dH3%(HD$0tH[]A\A]A^A_fHD$H@H5H\$1HH߾HHH{H߃D$H{fD$LI LI0I$ cID$HD$L|$E1LHD$ HMkID$Hl$PMHD$HD$@H$HL9oHD$N4LI INIFHL$@H@H<$HIHD$PHH|$@LGH|$PLHD$@5H<$HD$PHHCHCL;|$I$ ?M9|$ID$ ?f.H@kfD[[fDHHD$I~~(IF HHL$@ I@H59* , H5%* H$11HD$hfH$AHtIT$$IątuH, Dt$ LHD$0HtLHIH$HtNHŋD$$t@uHt$ H,HD$0HtHHGHŃ$Hc$H$0H=HL$8Ht$HHTH$@H$PLH$HDLHH=[L|$|f.H$AHtIt$$IątuHDt$ Lexternal_encodingUTF-16LEUTF-16BEnewParserANYUTF8UTF16LEUTF16BEpsych/syntax_errorSyntaxErrorparsemarkreadpathemptyevent_locationPsych/parserP@p`(8mesgClassLoaderVisitorsVisitorToRubybuild_exceptionpath2classYAMLTreeprivate_iv_get;18 h(@XpH ThXH|(xLHHp(8HThh|x4P( zRx $FJ w?:*3$"D(\H@t A xNHA8%HWP%HWh&HWEL+Ee$NEMD rDA<+AM A 0XFAA G`  AABE 0`eFHA GB  DABA 0eFHA GB  DABA 0qFAK GK  DABA 0($eFHA GB  DABA (\`IEAN c DAD (IEAN c DAD 0FAD Na  AABB 0FDD D0m  AABE LpAFBB B(D0D8J 8A0A(B BBBF HlpAFBB B(D0D8J 8A0A(B BBBI \tFBE E(A0D8G[ENDe 8A0A(B BBBA LFBB B(D0A8J 8A0A(B BBBJ HhD=FBB L(A0F8G@ 8D0A(B BBBJ $8%Et G r V @EK0 AF EL0DXl QH C A dQH C A QH C A ($(EGL@V AAH LPFBB B(D0C8J 8A0A(B BBBE <'Ea<P-EHD # AAJ C AAK @ $<4EGD ^DA(8TFHA DUd4EG fAtEjGNU0-,i kZ."[@A DYi i o`  5 l 0P oooo6oj !! !0!@!P!`!p!!!!!!!!!"" "0"@"P"`"p"""""""""## #0#@#P#`#p#########$$ $0$@$P$`$p$$$$$$$$$%% %0%@%P%`%p%%%%%%%%%&& &0&@&P&`&p&&&&&GA$3a1 QY GA$3p1113@-DYGA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA$3p1113 .XGA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFY@-XGA+GLIBCXX_ASSERTIONSpsych.so-2.5.9-114.module_el8.10.0+3991+5e651d4e.x86_64.debug3l7zXZִF!t/]?Eh=ڊ2N WR|$*s64 ,VJv,N'4v.; Nץnf)IL3;Aۥ-0\sjպa)0g2;sL0,w8!.[f-f !?^$f;Tdϙ22P=T 3arp+\['IY&\w0h3:FO.`YU/3南Y}"yp+^vk|CI]3: #BHlȏOӾq#~2*9kOKlɫ˧.URLOA(fpj3+"J$]9QO(QdqY`#A 0!4/TJB^7g/ !Whn14)4K?$MgFa04d53n*-g^lڲ[!̱ڸSxSIϝ.Qr`YwAd.2 %Xx.8x6:ޙ3&A.PgZZڻ욗+dhU<i36amU\ {hflKꭍQp ykOS ;XX6eCrGOIT ;.2h-&~#:K&/3է4JEz63QVz߮ᠷٟBؼVF~p=(Bv,~2/7zTo MSAIYzut=Rt%iI)y; WEa{텈}.na>)ٜ-̛ pcO?8v,ouCH.XؽddطWN5-~0qÄd ugڅj{ *<MЩ|sXH}ϚܜZ&l@/@a@8 @0L0L LL!L! hMhM!hM!888$$LLL StdLLL PtdP/P/P/QtdRtdLL!L!ppGNUQ!?Q!@Q!AQ!BQ!CQ!DQ!ER!FR!HR!IR!J R!K(R!L0R!M8R!N@R!OHR!PPR!QXR!S`R!uhR!TpR!UxR!VR!WR!XR!YR!ZR![R!\R!]R!^R!_R!`R!aR!bR!eR!fR!hR!iS!jS!kS!lS!m S!n(S!pHHy,!HtH5,!%,!hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?h@hAhBhChDhEhFhGqhHahIQhJAhK1hL!hMhNhOhPhQhRhShThUhVhWqhXahYQhZAh[1h\!h]h^h_h`hahb%&!D%&!D%}&!D%u&!D%m&!D%e&!D%]&!D%U&!D%M&!D%E&!D%=&!D%5&!D%-&!D%%&!D%&!D%&!D% &!D%&!D%%!D%%!D%%!D%%!D%%!D%%!D%%!D%%!D%%!D%%!D%%!D%%!D%%!D%%!D%%!D%%!D%}%!D%u%!D%m%!D%e%!D%]%!D%U%!D%M%!D%E%!D%=%!D%5%!D%-%!D%%%!D%%!D%%!D% %!D%%!D%$!D%$!D%$!D%$!D%$!D%$!D%$!D%$!D%$!D%$!D%$!D%$!D%$!D%$!D%$!D%$!D%}$!D%u$!D%m$!D%e$!D%]$!D%U$!D%M$!D%E$!D%=$!D%5$!D%-$!D%%$!D%$!D%$!D% $!D%$!D%#!D%#!D%#!D%#!D%#!D%#!D%#!D%#!D%#!D%#!D%#!D%#!D%#!D%#!D%#!D%#!D%}#!DH=Y1H={1LD$4$<4$LD$H=1QH=y#!Hr#!H9tHf!Ht H=I#!H5B#!H)HHH?HHtH!HtfD=#!u+UH=r!Ht H=!d"!]wHH !fDHHIHWft%ftwfz1ft)H@HL1HDfubHL1OtkuA+IHL1HHL1TDHYL14DA IfDH8L1DHLHtRfff.@USHH-"![HHTH[H]5DH?USHH9w+Hl?H?"!HHHH[]fD HfDAVHG!1AUATUHSH dH%(HD$1H!H8)HHHɚ;HD$HSZ/DHD$ H HHHH Liʚ;L)ItuE1Ll$ 1HSZ/DLQHLvHH HHIHHI HDH Hiʚ;)ЉHɚ;LLfHHIH HHHHHH HHH Hiʚ;H)Љ…u Hɚ;wHɚ;nH9fD AHH@H@fphHC HHH\$dH3%(NH []A\A]A^fDH, MHHuL0HxLpIfHKL L`HHPLDLDL@$IL)H)V1҉׃L 9M 89r;f AHH@H@@fxD@uJ HH@L`fPLLGUHSfw ]Hr8HGHKLL@tDMHBLu+MMuHtHHtHE[]DWEp A fDADЃAA wJAE1A9t+ЉA9uAA wHWHx[ tHcH)HtL9HLHHH:HWH1L9} I)McKL)HE[]@HHHH)1H DWLHLIE HM|K McHHL)L9HL`KMcHL)sDWMIE E1fGPfwIHHsFPfwIHHrHWHNH9HHMH+WH+NH9HOH)ff.HtSGPfwI HsDHW>FHDuHOHD HxH9sH)HH@fHHHH)Hff.@SH!HHHtH[fH!HH1[USHdH%(HD$1HT$H=P!IH|$uHL$dH3 %(Hu H[]RfATIUS0uft'HHr'LH=f1fD[1]A\fH!LH58H81DHGH0H~#H~H888H)H9|KHWfHy+Hy&HqqH)H9oHWf.H888H9~9fGHG~kfW1H5HqqH9ifGHG~/fw1H5IfGDfODOAfw#]HsG1HGfHWf.HBDDEu2HHuGHGf~f1fWf.wHWurU1SHHHuLtHtH)HHHW-uH[]ffG1HCHt H{Hʸff.fFfRff@fAD fteft_@L fAG1H5HGfDGD@tStff~N1G1H5YHGfOftbf_fGHGfw1H55Df.HfdfffDf@fGHGNA1fDHH[]A\A]A^A_D$Et1f}DM1DHI9}ɚ;nMf}HEEHE7fMHHEMtYH88LHHHUHI)t8U1ɾKfDҁɚ;v HEHI9uۉUHH[]A\A]A^A_@FfL_1MGIL\$AE1A$HD$8HD$tfDHD$1J|L $LD$H~fAL $LD$HEJcH>DfUfB\HD$$AwBD\$$E4@M-f.A @BDHt$HZODA1fDwfDD4$D$$E1D$ <$f}D,$EYANxt$$fAvf}x []A\A]A^Avf}~HL[H]A\A]A^DAE#wDAdwDAE#wAeAwAtAwjf.AVAUATUSFHfffPfHVLnIHHvHWfOŅL9oLFoLoN4fGLA t3t.M9l$M1AL$MtAT$LH=LkKD[]A\A]A^CfHCN~;1fs[]A\A]A^G1HG1f{[]A\A]A^ù1fKGfHGN~fW\fGID1HLk,DATIUHSӺ JHvL[H]A\f[1]A\fAWIAVIAUMATIUHSHLD$ IWH|$PEHL$XI^HuI+_LM9VMCVH~LD$I9HIuH88HIFHH;EsRI$IOHEH4H9HKH9H)HHIHH9ADHL$XMU/@I<$H9rADHL$P뛐IIFII$MUIFLUHHEHHDHH[]A\A]A^A_DIMUIMUUSHdH%(HD$1HT$H=@ H8HH|$uHL$dH3 %(Hu H[]AAWAVAUATUHSHH8H4$^H$U@HfDJf6H<$HH|$HLeIH|$L9\HMHKfxffCH$HHpHD$H{1N< IGN,ILHD$L{MlID$Lt$NL+E1HD$ HD$ISZ/DAKHHD$IGHD$(M~L9l$L\$ LH+|$HD$I9H4$LDHIL9AtHHH HIHH ʉHiʚ;H)A1ɚ;v A iʚ;)A1tMtAALAA=ɚ;wzfLщLɚ;b Aiʚ;)LHHuHIL9?fDIMIL9l$HHCH8[]HA\A]A^A_ffCHCfSH8[]A\A]A^A_f.H81[]A\A]A^A_Éщ‰LIHL$HH,$H $HMHKffH<$8H-f HNH@} H}fҸ HNH4$f.fCfCHCH8[]A\A]A^A_HD$(L)L9l$ rLIH+|$efM1`fDAWAVAUAATIUHSHHHdH%(HD$81Ƀ51҅tOAT$MrAfuef CHCfAfD[@H\$8dH3%(HHH[]A\A]A^A_f.fWE1AHEAGt6I9D$MD$H}I9HIFHt5EA9D$|v1fD\E9\wd^HH9uI9wPJA1fM@fNǍDpu+AC HCfDS@M1fAE1ffDKAHL$ G|?EE|GHD$fEPLHHHD$ PLL$@LD$8_AXD$ H7LD$(I L$L$H|$ Ht$0L$ MH9+II)If.HDL9u1HHIADBD1HJLHD1HHHAD=ɚ;v-ʚ;fIHBTTMJJH9rHH9y@DfDNA^fDkcI)MtBDESfAEfAff ЄfECfS HC@PHHLHD$ PLL$@LD$8YY^D$ H1LD$(I^t$L$9r)1҉t$ H|$ J4HL$0H9MtMAʚ;AfDJ4AH9IDHB+TD)҉TMuѺHH9v'HAʚ;DHH)кDH9rE1H9wFHt^HH)LH@)1AtHt:HAt9sɚ;ݐHHADH9D@H)Ht)TSff M9fA};A31fEfCHC1HtTL$ 1HHCH"fDHHHCHDILDMLLHHLfD04HHHGH)I9u@HD$ MH\$.HHH)II@H|$EZHH+D$HI9@Lt$LLL|$(1HHHHIIT6II9LIoIILILO4&H)IHLL)AF LI)IuBH|$e1HORE1%ff.HSH@ tHta@u[HHuOHH) 1H@H9tCH uH HH5}H81@HhЃw[Hc[HD f.ATUSHdH%(HD$1HT$H= HÃwHL%9 HTLH|$u0HL$dH3 %(HuH[]A\+ff.@SH5 H@uu1HttH‰[HH tHtHtHUSH~H>t fD@uUńuU=TBHtHЃ HH\H[]fDsńtHtHt H@t%HE@t%HE[@t%HE7t%HEHH\H[]fH- H\̿HHH访HH[]H H5H81ܾH^H4 H5H81軾ff.ATIUSH?H9wOHlx]u H[]A\@uJI<$Ht@u3x?HcH[]A\f.HH˺1H H5ҲH81Hx fDSHHHuH5 H谿fPH[fuHHƒH uΨ@tHCHHt:HC H H9ufPH[@HR0H9tHuHC f.AVH5ǴE1AUATL% UHMSHH=t)IIII]IuHHuHT t@ v uH u 6KvATH@H@t)tfP1[]A\A]A^þfp1fHfAWAVAAUAHm ATIH1USLHL$dH%(H$1KHA$ƒ wfHƒ v tH"IHtBL} HξHLH$dH3 %(HĘ[]A\A]A^A_1;#HHeHx蜽ILHH tLHPA<-HS؉D$HHE1I4I>"f0 H II4HHyREuDA Av/ t*_uM t9wIrEPL1E1LL$KTHL$8I88HLL$0ILT$(L\$ LD$HIH4 ֿI|$LD$IL\$ LT$(L LL$0HL$8@H@YfpHD$HT$LHt$PLT$H=uD$LL|$PLL$XLD$`H\$hL\$pHD$xH$rD$LLT$1LfE11E1E1HD$ EhLL tHWMNfD|$O1fHD$1fDH;H|$(DDA.^E1E1 D!HHH!HL$ oHL$(HpHt$ LHHt$HH+EHt$(HHHH 3I41Hl$(tMEu : 1_0 HT;HI4HuHl$(AfDHD$ K9LHD$efE hIH@H@fxfPfLx E1K49LtAEu ve t`_t>0 HT II4HuHD$ E11@Mt| 0 vEK91LL$sHD$ E11Ѓ v< u&HD$(H|HЃ v< t7EZHD$ K9LHD$@Htl;0 PHl$(EK9fDE11\HD$ H HL$(>Hl$(H;H|$(A+Hl$(K9|L蟷|$L膷LnH5_HH H81USHH8dH%(HD$(1t*HHHL$(dH3 %(H8[]@Ht$H諺H߾HKHxHwAHqH)|$HHwHH1u@ H蛷H HD$HxH2H tHxHL$HD$HL$ 1HHL$HD$ 诵ff.@AWAVAUATUSHHXdH%(HD$H1f.f(fT f. ff.zZuXH ^f/wH Ht$HdH34%(HHX[]A\A]A^A_f.HH\H޸׃HDLD$HL$HT$Ld$ ˷H\$LHH)øHOLcLHL$SK4,9oH88)HcHHHHH00000000H)HH Kt 0cHD$P1L J(D98HNjD$H)Hc7f/H) v/Ht tMDHH5 葴H1grfH HtfNfDHHƒH u@tHCH{ HHuH{ Hg H9t HI0H9tHumDϾ98)ߍK|$HcD)ljLcK\5)HcH)LHHHtH$t@@ tHߺ1HHuH5 H?HHH[]fuHHƒH uΨ@tHCHS HHuHS H : H9tHtHF0H9tHtH@0H9uHߺsHhH5 H߉T$ %T$ nH HH(Hg'DHH H HH(莨H!H5H袨HH藧Hoff.@SH0dH %(HL$(1Ʌxv1ҪfH1HH5wHHT$HD$51Hp2身H$H$H HHD$H$HH@HrHH 1;HcH$H|$1H4E1HRH)H=H<$H葧HD$HD$HD$H$HL$(dH3 %(uH0[H[ffAWAVAUATUSH1HXdH%(HD$H1HHD$0HT$8荩=HHH|$8GH1fw ]HHHHrqqHHHH?H)IMIIM)IM`D1ɻfD9uʚ;1҉ADOH LD$H/ LIɚ;LL$A1ELgH8KLH88IHH HHH4HT$HF)HT$L@HHH@fHIE zLD$LL$MWHt$8HNIɚ; IHi111ADADDHH9uÉD fDIID$TtFHLefEHFLHEHD$0HD$(1HHD$0fD1Ll$0tHt$HdH34%(LHX[]A\A]A^A_fDHPHHrqqHNHH?HH)Lr@H11@D1AljTHHuDHt$8 HHt$8@Aʚ;1迣ff.@H81dH%(HD$(1H5%HHT$HD$1HiH$H$HPH$HpH tHpH|$E11H$HxH tHxH<$HcHD$HD$HD$H$HL$(dH3 %(uH8fDAT1USH0dH%(HD$(11HD$HBHT$H H\ H5 H8͡HKH88IHH HHH4HHFLH(H@H@fHID$ 5Ht$~HVHHFNH9H)HHCH9HG1fHCfSHVHt#HHHH<DLLHH9uHDZHD$HD$1HHD$NLHL$(dH3 %(uFH0[]A\f HS뺐CHCf~ fS뚐fC AT1USH0dH%(HD$(11HD$HBHT$H H\ Hu H8 HKH88IHH HHH4HHF LH(HfP@H@ID$ uHt$1HߺHD$HD$1HHD$HL$(dH3 %(u H0L[]A\AT1USH0dH%(HD$(11HD$HBHT$H HHf H8HKH88IHH HHH4HHFLH(HfP@H@ID$ fHt$ HDCf1)fCHD$HD$1HHD$HL$(dH3 %(u H0L[]A\U1SHHdH%(HD$81ZHD$ HT$(fftVfffwHBHH==H=}C1H5ZffΡHL$8dH3 %(HH[]HH5Ɠ葫1HHD$HD$HhH tHhHD$H|$(E11HHPAHD$ HD$HD$ ]1HmD$BD$8"Pf.Ӟf(fT f/ (1H5_fx0ӠfD軠fDx裠fD`@ f.0zH ^- } pG DP螜ff.AT1USH0dH%(HD$(1x1HD$HBHT$H HH H8~HKH88IHH HHH4HHF葠LH(HfP@H@ID$ Ht$HHD$HD$1HHD${HL$(dH3 %(u H0L[]A\芛f.AW1AVAUATUSHXdH%(HD$H1bH5HHT$8HD$0詨1H/IHH$I$ t ID$H$ID$HHD$8HD$@ff8fNPf0fHH<$H؎1qH$<-HX[]A\A]A^A_DH4$IfHD$H@HD$HLd$1Hf.HD$A ADl-L1IHIIIIAtCHt M9rL1LHIHÌH1譗L՘1IfDHH9\$iLd$A0ADIAA0tH$<-L4$InHmHLHHlAAHfHIHțLL轛H<$LHiL蜛 fHH<$H譖7L~-D@HH<$H1{fDHH<$H61[fDHH<$H1;qAW1AVAUATE1UHSH8dH%(HD$(1LHHD$HT$HD$fxHA1Od$tL{H Ht11HHPHHD$fx}HH@HHDHD$ H` Hu$Ḣ@HH< HtH\$ HƿH͔HƒHt!HHHH H5ƉH818fzHRHNHHlHD$HD$HD$HL$(dH3 %(HH0[]A\DfH@ 8H8HHٺ*HD$ HzfDHPHHHL$ *HD$ 蠓H[3AWAVAUATUSH8dH%(HD$(1GHAE11Hߺ1HD$HBHT$H H\ Hg H8HKH88IHH HHH4IHFLHL @H@fCI] hHt$LHAHD$HD$1HD$H߅HHL$(dH3 %(Lu]H8[]A\A]A^A_Ðu:H>@u*蝐LcD諰LIfDcԺ1蓓讐ff.bfRfBfAWAVAUATIUHSH8dH%(HD$(1qAtlI<$Md$9d@譏LcMtAuI$HLE1AfDE1A1H1HD$HBHT$Hɱ H\ H- H8ŎHKH88IHH HHH4HHFؓLHH(@H@fCI\$ -Ht$LHA詺HD$HD$1HD$HE,跮HL$(dH3 %(LH8[]A\A]A^A_Ð苮LIfDHt3@t4@t'2E1LcAyfDHHuE1E1ALE1ϴAx1 $A@AWAVAUATUH1SH׺HhdH%(HD$X1HD$@HT$HHH5[HE11HD$0H1諍HD$(HD$(L`H tL`Ll$HHD$(HPEHLLLAH|$(H蔍HD$@HD$8HD$@HD$(HL$XdH3 %(2Hh[]A\A]A^A_DH}H|$0vH=H]@'rH|$HHcE1H5X1!HfDHHD.1HHtHXDLLHcfA}ALAMMMuM7HMMHH AA$-I|$HHBHLHpt(HFLu,HHuHt$(dH34%( H8fDzA A ׉AA wMcȅAA91ЉA9uȃA wHcHT$HT$HHD$HD$HD$HD$ HD$HD$ *t1HL$8dH3 %(%HH[]A\A]*"HkHcH>)@E…HcHD$HD$HD$HD$ HD$*HD$ " tHkHcH>DqD@fAHD$HD$f'fHD$HD$ HD$*HD$ "sHkHcH>HrH9w0fDHD$HD$lHfDIHLHqffGffHrH9wLRLOM9MMFMt=w9r1D\D9\HI9uM9HD$HD$HD$HD$ HD$*HD$ "irHIkHcH>@HA HaHfHqH HtfH Hu%HXaDHkqH HtHLHn6@Hɕ HdHuDH#qH HtHLHnH-Hi H`HfHpH< HtffDH~HnH^HcHD MH>fHD$HD$1mfHD$HD$ HD$*HD$ "pHiHcH>1HBHfDfHD$HD$HD$HD$ HD$*HD$ "pHjHcH>ffHD$HD$~HD$HD$ HD$*HD$ "oHGjHcH>HD$HD$f~]fHD$HD$ HD$*HD$ "roHjHcH>hjHD$HD$HD$HD$HD$HD$ HD$*HD$ "#oHjHcH>HoDG2f>"fLf<f=f*fAWAVAUATUHSHHHhdH%(HD$X1蠧1Hߺ tHLd$@HD$ HBHT$(H4H HBHHT$8HD$09H|$(1Ht$HtH|$81LsHD$H9D$@H% HMD$@L5 HI>H HM1HH9hHMH88IHHHIH8 mLHL8@H@fCI] ojHD$8I>HPHHDHT$(HRH9HB1Hb LHtHD$HD$Lc HHD$i\HHH5v| 1[H1zfH\$HueH zNHzNHR^HtuHHrH|$G]H5THH>~ H81X@t#H؃HuH߉LH(fHH H訢HHHƒH m@eHGHo HHuHo Hg{ H9MH5HA0H9u6H@0H9"Hu fH\$HHHƒH v@nHCH{ HHuH{ Hz H9YDHI0H9EHu)fHHƒH @HCH{ HHuH{ H^z H9HI0H9HufI|$HuYyDHڃH1H'Ht8HtJHH\$H|$VHH-H߉L#HHpXHu^H5L HL$ HHD$ XHtEH\$HLYLHoHHD$Zu1HtWtD uH{ H5~QH81U@HHH\H$RJHjHZtH^VWHJHt HJHtHHJHEHz H5PH81LUff.AUATUSHXHcHLd8WuLeu. YHAHDL[]A\A] DHmuXHAjXHètCHHyEuRH[]A\A]fDLTHǃm;HTtHUHbHz H5.IH81,Tff.ATUSHdH%(HD$1SH=PIIYH=YIH~ 1YH=ZIH~ Yff.| H~    YH=/IHfPH@He} @H@Hx H0XHx H5H=HHuVH;WHH! Hx H8H5HHWH;HH5HmVH;HNH5WHRVH;HH5H7VH;1H[YH5eHVH;HH5UHVH;1HaH5CHUH;1HH5?HUH;1HxH5:HUH=4HRH;H5+HHyWH;5wH5HeWH;H5 HQWH;H5H=WH;H5H)WH; H5HWH;H5HWH;!H5GVH;H5HVH;H5GVH;H5GVH;H5GVH; H5GVH; H5GuVH; H5GaVH;H5GMVH;H5G9VH;H5G%VH;HH5GVH;H5GUH;HH5GUH;H5GUH;HH5GUH=GSHHH$HIQH=)EL%Zy }SHHH$HINQH=jGL% y KSHHH$HIQH;LH5EL%y UH=CSHHH$CHIPH=oFL%x RHHH$HHPH;HH5FH-x TH;1HAH5DRH;1HH5F}RH;1HH5{FeRH;1HH5sFMRH;HH5mF2RH;HcH5VFRH;HH5?FQH;HH5ZCQH;1HH5FQH;HH5EQH;1HH5.CQH;1HH5E~QH;1HrH5EfQH;1HJH5ENQH;H/H5E3QH;HH5~EQH;1H\TH5hEQH;1HԱH5SEPH;HH5kBPH;H~H5 EPH;HH5EPH;HH5D|PH;H}H5DaPH;HH5AFPH;HH5A+PH;1HOH5DPH;1H7H5~DOH;1HoH5jDOH;1H7H5WDOH;1HH5CDOH;HH5,DOH;1HH5DOH;HaH5DeOH;H6H5CJOH;HH5@/OH;HH5COH;HH5CNH;HH5CNH;H_H5vCNH;H4H5o@NH;H H5O@NH;HH56@rNH;1HH5CZNH;1HH5BBNH;HH5B'NH;1HۧH5BNH;1HH5BMH;1HH5BMH;1HSH5BMH;1HH5BMH;1HH5yBMH;HXH5fB|MH;HݣH5TBaMH;HH5HBFMH=BBOH=9Bs Hs NH= Bs Hs N H=As Hs NH=lAs Hs NH=GAs Hs zN H=As Hps [NH=Aps Has H9HHuٽH5nl H n EHH<'IHIH>HH8l HH9t:HHH)HLH= vЉٽEHH<'H!EH‰Zj HBHH[]fDUHSHH(D$dH%(HD$1D$IfH~fH~f~D$H ։ρEωL$H|$u_T$AQT$E1AQAAEAU5)‰H\$dH3%(LH([]DT$ )L$ AIT$DH|$^T$AAA AQw-2EIcA|AA)DfB@AWIAVAUATIUSHLcoLcvE9|DIMcILcC.1A9\$ @A|$WHcLXI,LI9s@HH9wIIN,K4L9r^f.II9vKHDWEtLME1ɐIAPD1HILLIщQI L9wD II9w~uHUtH uuXH[]A\A]A^A_AVIAUIATUHnSHcFH_DgA)HHH @H9HH89:tA}IcU1D`HpIL IcVH| LHSHLVH)ʋMH)HAARH H9wI9v;LH@HVHH)HAӉWH I9wIqH)HLEufHAtD@[]A\A]A^DA,HHAHLMI1)H@[]A\A]A^Ht4HcWH5i ~)fHcWH HHHfHHqHE1HEH-bg HHHD$HD$Hff.@AWAAVAAAUATUHSHDeE EA\$9~9zIHxE~#AOHHDfHBH9uH|HcEHuL Ata E1D)fDDHHD ‰WDFAI9wEDDEEeHHL[]A\A]A^A_DI9vץI9wf.AWIAVAUMATUSHHt$dH%(HD$x1{;HT=Au@-7@HcH>AuD$ @IE1@0@Lσ/91E1E1*C4DtqHAΉσ/9VA~AӍTQʐD$ fHD$HtL8D$ tfWW?HD$xdH3%(HĈ[]A\A]A^A_ÐAuD$ @ fHD$HtL8IAu@-DD$ E1@0AuDGA vHH)H'NH݅D$\$AP981A ~9DD$(A DD$(HDp@I A E9}2EHHE)Ot fIAU Hǃ0M9uHDd$8L$$1L|$XA)DIID$(HCHD$@HD$lHD$PHD$hDd$8HD$H{5Ht$@HxIHcCHH7Ht$PH|$HD$IHHHED$h L$8D|$(D,L$l+D$43|6)ȋ|$ALDA9D<AND9AODž~)A)A)ŋt$8~3HL$ HIMHHTfDH9HH:98tDL$EE D%=2 =pS HP9\$H$~$YfH~f$H$ L`LXHPHHL@$fDA IfgD$$tb|$$ D‹\$$%)D)ډT$98H5$D)Hc)YHcYDD$8E1D$$ID$8D1Ƀ߃Eu#f D EIA@E1AHAwDMu AD$Lt$(Ml HD$0HDfIAV Hǃ0GM9uAHL$0HHD$(Ll2IEuA0tAH=4a1HfL2$T$A.EeEEH=i4D$D 1D$HIT$ H-34D$DE[ AHT$0T$H H)fEeIH*YY4X $f.T$ $zuD$MH-3D$ EfIAHM>0HuD$AAPAU,)׉։1)ȃI0 A1D w<IDFAuANЁ/~܃ wIAU0 vDD$8D1Ƀ<AzIBDWA -I|$$Dd$8H1$A)Ic^D$؉ƒtHcH 1<$^<<$D$?|$ft$j$EH01@t YHufH~HD$H$t9H k)~47H4H$<$ff.|$$-$"fDHt$pLL$H IwHHLfH9HH99:tEAHDD$HEDD$H|$eExIA^L;t$8L1Ҿ 1Ҿ LIL;l$H|$1Ҿ IHD$fDHDD$Hc|$DD$HF D$E9 D al$LL|$@ADMI^Eu }EHHHt$HŋUHcF)…R HHMHHTH9L HH290triA9Dd$A1PfDHt$H|$ H!Hf|$ALI^L|$@A9<AE&MLl$fDHt$H|$DPEAKIHD$f*YX zfH~fH~H -@H H fD\XHT$L$f/;fW Sf/D$PfT$|$ D$dHcD$ H ‹D$D$@5Y AHD$f/L$D$ I_A1H|$MtLHHD$(t$ 0HD$0HcH[f|$\$H ڈT$X\$8E1f.D$PD$8AxD T$ Hډփ YH57f(1@t YHu@af(XD|$XHD$E1Ht$FD$XH| )‰DD$\$@H|$1ҾUHHD$Hc@)…HHMHHT H9[HH9tG$fDf(¸Vft$H$H@D$XD$\D$@D$Yff.LfD f(Xf/w\f/D$P Ct$ DL9jBHHS<9thf(¸HHt$HHHH 6AEA#HD$E1D$L؉D$ L(IHD$H uHcT$ f(fI_H Hփ^t$ ,f*0AY\f.D$@D$@%ILfDH9YfHf(^,f*P0SY\f.zHÀ{0HCtyA$GH%lI|DCHH9YffH,*ȃ0\f.z@SoL9(PHHC9t|$Ptt DH|$FMOM>M95L#(fDSHHC0tA99MLl$t$ xt$@|$\?%Xfɋ\$ *YčsYX >fH~fH~H -@H H 3AD$D .fHD$E1=A1D$ A}HIuHxHIcEH\H_HD$A0LCD$ ALMH\$8L|$@Ll$ASUL1Ҿ IŋD$\"D$@Xf/AHD$D$\$DAI^LL|$@A9B1DOE&MLl$Hljl$ALL|$@AE1l$LAL|$@uI^fDD$\\$ D$@f( f.HA%DfD$tD$\AhT$fD$ IOf(^,f*P0AY\f.{'|$@mH<)‰oHff.@AWIAVAUMATfI~UHcSHH(dH%(HD$1fH~H f(fT f. f.f.DLH4Ld$T$YfH~fI~H4-A}LcHcLUH bN0HHE1L9fDHEMtImH\$dH3%( H([]A\A]A^A_D-AdAs>=<=niltruefalseto_strStringBigDecimal.exception_modeBigDecimal.rounding_modeBigDecimal.precision_limitBigDecimalnewinterpret_looselydouble_fig_loadsave_exception_modesave_rounding_modesave_limit4.0.1VERSIONBASEEXCEPTION_ALLEXCEPTION_NaNEXCEPTION_INFINITYEXCEPTION_UNDERFLOWEXCEPTION_OVERFLOWEXCEPTION_ZERODIVIDEROUND_MODEROUND_UPROUND_DOWNROUND_HALF_UPROUND_HALF_DOWNROUND_CEILINGROUND_FLOORROUND_HALF_EVENSIGN_NaNSIGN_POSITIVE_ZEROSIGN_NEGATIVE_ZEROSIGN_POSITIVE_FINITESIGN_NEGATIVE_FINITESIGN_POSITIVE_INFINITESIGN_NEGATIVE_INFINITE+0+InfinityNANprecision_scalen_significant_digitsaddsubmulthashto_sto_intto_rsplit+-+@-@/quo%moduloclonedupto_fabsfixroundfracfloorceil===eql?<nonzero?coerceinspectexponentsignnan?infinite?truncate_decimal_shift_dumphalf_uphalf_downhalf_evendefaultbankerceilinghalfComputation results to 'Infinity'Computation results to '-Infinity'ERROR(VpDivd): space for remainder too small.Conversion from String to BigDecimal overflow (last few digits discarded).Computation results in 'NaN' (Not a Number)Computation results in 'Infinity'Computation results in '-Infinity'second argument must be true or falsefirst argument for BigDecimal.mode invalidinvalid value for BigDecimal(): "%li "can't omit precision for a %li . can't be coerced into BigDecimalBigDecimal to Float conversionUndefined operation in BigDecimalCmp()load failed: invalid character in the marshaled stringcan't convert %s into BigDecimalUnable to make a BigDecimal from non-zero imaginary numbercan't convert %li into BigDecimal'=*'))'$*P*')')b)'*p* .. .p.`.0...+[[[[[[ \[[[[[[[[[[ \I I I I I I I I I I I I I I I I I I I I I I I I I I I I I || L l@11111111111111111Д 1111111101111PHT  Tȓȓȓ <<<hhhDuuuuuuuuuuuuuuuuuܐܐ$uuuuuuuu$uuuuܐPPP]]]]]]]]]]]]]]]]] ďď]]]]]]]]ď]]]] ?`}NaNInfinityؗҜ<3#I9=D2[%Cod(h7yACnF?O8M20HwZ| D F @L@QSTW8XTZ[\_ `P0dfpi klk k0kms@tdPvvpww0xpx(x@xXypyyyPz{00|d|~ p4X0|p@4Њ` Б 4HP@4`XxpPPd0xp@@,X0@@ `pzRx $@FJ w?:*3$"D0\p $IDo E Z F d D $ +AAG PID((JKAD Z JAK @(LBKB A(D0DP 0A(A BBBG ,lEDf AH  AE dTqPAa N _(nEAD0W AAA (4kBDC x CBJ <x 4PtCD xAACL aL|X'BHB B(I0D8G2 8A0A(B BBBA C 8A0C(B BBBA  8C0A(B BBBB $zRx ,HX 3FDB B(A0A8DP\ 8F0A(B BBBA zRx P(#eA D VddBEB E(A0A8D 8A0A(B BBBA  8F0A(B BBBE xc8SAa N bHxKAG  AAH D AAJ ~FAKH $`Ae J D L _8 BAD K JBJ K ABJ L\8BEE D(D0M (A BBBH \ (D BBBJ `BBB A(A0 (A BBBD i (A BBBH X (A BBBA 4$7BDD Y DBG ACBHH,mBEE E(D0D8DP  8D0A(B BBBF (PoEAD0X AAA  BGB B(A0D8Gp] 8A0A(F BBBD s 8A0A(B BBBK D 8C0A(B BBBA  8A0A(B BBBD lX "BBB E(D0D8G 8A0A(B BBBK OPBOPAH,)RBEE B(A0D8GpR 8A0A(B BBBJ @,(<,A D D0H,FAA D0w  AABI |8-iAv I @-ECD { IAG  LAC f DAA 4/FDA e ABE j ABK  /Ql C C E <8 0FLB H(G0 (A BBBA Hx 0}BBE L(I0A8J 8A0A(B BBBH ( 7!AAGPx AAE H 83BBB B(A0C8G 8A0A(B BBBK H< =mBBB B(D0A8D 8A0A(B BBBF 4 CAAG0Q HAE  DAC DED@ AI L EAFGB B(A0A8I[ 8A0A(B BBBG 4 HH@ A 0P dIFHA DPf  AABC 0 J FHA DP  DABA 0 KFHA DP  DABA ( LREHD` AAD 0 NFHA DP  DABA LL OFIB B(A0A8D 8A0A(B BBBF H SgFIB B(D0D8Dp 8A0A(B BBBI 0 UFHA GP  AABF H HXBBB B(A0C8Dp 8A0A(B BBBB h Y| Y YH Y\FBB B(D0D8Fp 8A0A(B BBBB H [OFBB B(A0F8N 8A0A(B BBBF <aEK@j AE `4bH@ G (|csAIIPX AAA dED0m AI d\H F B d\H F B  e?Hl D F$@e6Hm<he$HXTe#HUlezHc E Ie-Eg f-Ha$$fQEFJ oGA@\fBBB I(A0IpL 0A(A BBBC 0,gFEGG M IAF DLA `g_EG Q DO @h?BBE I(A0Ipj 0A(A BBBB 0iNEGG M LCI DLA0jNEGG M LCI DLA 04j_EG Q IJ Tpj_EG Q IJ LxjlBBB G(D0I8J 8A0A(B BBBG 0rFDD GPv  AABA 0hsFGD G`  AABA (0tEGG`G AAD 8\htBEF D(Kp& (A ABBH zRx p$zzzzz0zLDz]FBB B(A0D8J 8A0A(B BBBK L}FBB B(A0A8DG 8A0A(B BBBE HPFBB B(A0A8Du 8A0A(B BBBG 0{EG R DA TIEG xDt04Hk0TtBDC DPT  AABK LFBA A(F0R (G ABBJ v (F ABBG 4p FFA D0  AABD LR`Dst5D0 K lԛRHB B(A0G8d 0A(B BBBE K0A(B BBBDH8$4AAF DA(( \AIG@ AAF DT@BEB B(D0A8D@8A0A(B BBBLhBEE A(E0 (A BBBF @(A BBB8E8tBGA D(G0H (D ABBJ @<1BDE A(A0F@c 0D(A BBBG HBEI B(A0D8D@ 8D0A(B BBBF LFEB E(A0A8G 8A0A(B BBBB LXFFB B(A0A8DN 8A0A(B BBBB HlVFEB E(F0D8G` 8A0A(B BBBF GNU0`0L!!!   020! i # L!L!o`8  P!H   oooo hM!P#`#p#########$$ $0$@$P$`$p$$$$$$$$$%% %0%@%P%`%p%%%%%%%%%&& &0&@&P&`&p&&&&&&&&&'' '0'@'P'`'p'''''''''(( (0(@(P(`(p((((((((()) )0)@)P)`)p)@@?U!GA$3a1 # GA$3p1113/GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA$3p1113GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFY0GA+GLIBCXX_ASSERTIONSGA+GLIBCXX_ASSERTIONS GA*FORTIFYbigdecimal.so-4.0.5-3.el8.x86_64.debug"Wq7zXZִF!t/"G@]?Eh=ڊ2N  [eTkOJ)5zXR.\@]ҞPACm_Q|C98 x?Xš)uahH[ Ag̤+V 0VΦ7]x7 nDh.Dplm|aQ9T;EqG~ӏj#N@K!D F yHjn H_m~E ay!ܯ[NgQS~GQtxlJ^ftP{ICǏ!VMĎ_7~4hRi?=JRn,dKeXdbI샪N!HxxqU[rwD}#d=}S}*B[P>bOH&Ys00 UFHT 1jr!V<2(Y{M3ڱÂy9|ĩO+C(n%`z4L0^qWoO ۺWˑ:b%E?aǮˡJbk8Lbp,ٹ?vMY"NJr$s{kbj{\0cad~b: (yxԩPC%PK5m0҄L_ & Ĭ/zRzF.(P_דSa]P}W`C>hC(3!a_Y\vUݧ=q5"I';nkײ\{Ri|čl>Jm_͠ !4X׺ *B`\_sq&OO\zHm}U& ;!Zm lHkRz%MkkoCn?_:Ua(7 +:T:;& @pmLZzCR A2%PeoP 7fQD~AIU/Y*r9ZJWܩ#5)jZYomMb'nĹ#`58pԱs67%6 2YE :k#%%*VjHZ>A½cog5lMzoo!в݌UlG ^0mia@9:׌,)OZˊbNR?>!Ol+pcpxSd gm*X$EҨl$) U k&yO#.B 5p-3wnȃd}DgkBюYHQ0tτVT-5}]sox 7ED?ƙd0) ܢMvTQu$bD qzފus픕T0H΋W˥K3 =ۤPR*W 5fjP>>Q ;P&S-Ea|}rU5 ]߀t?qLXU^p)XӃnb~[mk0T]=V'=!L1dWk>֦)ߒ%O츲[*"Ћv)=z0FxbTfel6}5Uq}TG0FMx,QjXorDdmK4*l*rv {o ݺ)uL^G]zjf4oF6R=-ّθ].̉[/-{syh>?=Mj i&oN9(Wkacl8kLh:H7H7T$vxnqxŏQs2mc h=D|#gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.data.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``L(  0888oEopT  ^BH h # #c@#@#@n))0w//V}   0 P/P/X3X3LL L!LL!LL!L hM!hMhO!hOP!P00S!0S@S!pS( ^apSlW,"X`1PK!Upsych-5.3.1/psych.sonuȯELF>p,@}@8 @kk ll l H( mm m 888$$xkxkxk Stdxkxkxk PtdbbbQtdRtdll l PPGNUIGȦ}#n^9_ BHH _gjx BE"aj |SE6 ZqXH8 U *z);q)_,p2}_@Kv4W kSF"}p&""kG6:Mk, TF"ZUe+Gf @Gr r  ^ p\s s s  -X P_Zs r s s __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeyaml_get_versionrb_ary_new_from_values__stack_chk_failInit_psychrb_ext_ractor_saferb_define_modulemPsychInit_psych_parserInit_psych_emitterInit_psych_to_rubyInit_psych_yaml_treerb_define_singleton_methodyaml_emitter_deleteruby_xfreerb_ensurerb_data_typed_object_zallocyaml_emitter_initializeyaml_emitter_set_unicodeyaml_emitter_set_indentyaml_emitter_emitrb_eRuntimeErrorrb_raiserb_attr_getrb_utf8_encodingrb_enc_str_newrb_funcallvrb_fix2intrb_num2intrb_check_typeddatarb_unexpected_typeyaml_document_start_event_initializerb_ary_entryruby_xcallocrb_string_valuerb_str_export_to_encrb_string_value_cstryaml_emitter_set_canonicalyaml_sequence_end_event_initializeyaml_stream_end_event_initializeyaml_mapping_end_event_initializeyaml_emitter_set_widthyaml_document_end_event_initializeyaml_stream_start_event_initializeyaml_alias_event_initializeyaml_sequence_start_event_initializeyaml_mapping_start_event_initializerb_string_value_ptryaml_scalar_event_initializerb_ivar_setyaml_emitter_set_outputrb_error_arityrb_cObjectrb_define_class_undercPsychEmitterrb_define_alloc_funcrb_internrb_define_methodyaml_parser_deleterb_funcallv_publicmemcpyrb_ull2inumyaml_parser_initializerb_utf8_encindexrb_default_internal_encodingrb_respond_torb_intern2rb_ascii8bit_encindexrb_usascii_encindexrb_enc_find_indexyaml_parser_set_encodingyaml_parser_set_inputrb_enc_get_indexyaml_parser_set_input_stringyaml_parser_parserb_protectrb_str_new_cstrrb_enc_associate_indexyaml_event_deleterb_jump_tagrb_str_newrb_ary_newrb_ary_new_from_argsrb_to_encoding_indexrb_ary_pushrb_eNoMemErrorrb_exc_raiserb_const_getrb_usascii_str_new_cstrcPsychParserrb_const_get_atrb_class_new_instancerb_define_constrb_requirerb_define_private_methodrb_path_to_classrb_obj_allocrb_iv_setrb_define_module_undercPsychVisitorsToRubycPsychVisitorsYamlTreelibruby.so.4.0libyaml-0.so.2libm.so.6libpthread.so.0libc.so.6_edata__bss_start_endGLIBC_2.2.5GLIBC_2.14GLIBC_2.4/opt/alt/ruby40/lib64ui $0ii ;l @-l -l l l `l @.@m aPm Io  o  o jo (o ho co do ko Jo Oo So Up  p (p 0p 8p @p Hp Pp Xp  `p  hp  pp xp p p p p _p p p p p p p p p gp ap p q q q q  q !(q "0q #8q b@q $Hq %Pq &Xq '`q )hq *pq +xq ,q -q .q /q 0q 1q 2q 3q 4q 5q 6q 7q 8q 9q :q ;q <r =r >r ?r @ r A(r B0r C8r D@r EHr FPr GXr H`r Ihr Kpr Lxr Mr Nr Pr Qr Rr Tr Ur Vr Wr Xr Yr Zr [r \r ]r ^HHN HtH5"O %#O hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?h@hAhBhChDhEhFhGqhHahIQhJAhK1hL!hMhNhOhPhQhRhShThUhVhWqhXahYQhZAh[1%]I D%UI D%MI D%EI D%=I D%5I D%-I D%%I D%I D%I D% I D%I D%H D%H D%H D%H D%H D%H D%H D%H D%H D%H D%H D%H D%H D%H D%H D%H D%}H D%uH D%mH D%eH D%]H D%UH D%MH D%EH D%=H D%5H D%-H D%%H D%H D%H D% H D%H D%G D%G D%G D%G D%G D%G D%G D%G D%G D%G D%G D%G D%G D%G D%G D%G D%}G D%uG D%mG D%eG D%]G D%UG D%MG D%EG D%=G D%5G D%-G D%%G D%G D%G D% G D%G D%F D%F D%F D%F D%F D%F D%F D%F D%F D%F D%F D%F D%F D%F D%F D%F DH?f.DH=aF HZF H9tHB Ht H=1F H5*F H)HHH?HHtHB HtfD=E u+UH=B Ht H=? dE ]wH8dH%(HD$(1HT$ Ht$H|$HcD$Ht$HDHD$HcD$HDHD$HcD$ HDHD$ HL$(dH3 %(uH8Nff.HH=1bHA 1H51HHH5@!HSHH[f.HH HDH8dH%(HD$(1Ht$HH<$H=uHT$HHL$HHD$ HT$(dH3%(uH89fUH= SHHHh @uHh HH_HBHH[]SHt[Hr@ HSH5a0H81DATIUHSHH5C dH%(HD$1HjLHHHHH5BC H$1HǨt"eH\$dH3%(uH[]A\@ ff.AWIAVAUATUSHH/LodH%(H$1HGLgHD$Hu,H5u< H]HD$ML2f@uHEHƒH u@tHEHHu?HE HD$H< H9tHtHA0H9t@H{H@0H9u@HE HD$DAoIEHƒH[ HHIIW E1H\$PIEE1H|$A HHHt$HLHNHKH|$HHH$dH3 %(H[]A\A]A^A_fIEHb1LLILAHuUH߃D$HtU7D$LI"HAt8L{IE(H߃D$HubI<$HHu HH<$1H<$IIG ID$HL$@Ll$(IHD$ HD$PHD$Hl$0LIL|$8IHE t/HL9/HD$ JH53 HHuHHH[]fDCߐ@uHHƒH u@tHGHo HHuHo H2 H9tHtHA0H9tfDHiH@0H9ujfUSHHHu>H5G2 2HHu"HHH[]fDߐ@uHHƒH u@tHGHo HHuHo H1 H9tHtHA0H9tfDHiH@0H9ujfATUHSHHpdH%(HD$h1HuQH5r1 HZI1HH@HLHHH|$hdH3<%(u|Hp[]A\@@uHHƒH u@tHCLc HHuLc H0 H9tHjHA0H9ofDHNH@0H9uR@ATUHSHHpdH%(HD$h1HuaH50 HjI@HHHHLHHt$hdH34%(}Hp[]A\D@uHHƒH u@tHCLc HHuLc H/ H9qHVHA0H9[fH>H@0H9uB@ATUSHHĀHt$dH%(HD$x1HuwH5/ HhIH|$Hu:1Hl$HHLHHL$xdH3 %(H[]A\Ht @@uHHƒH p@hHCLc HHuLc H. H9SH8HA0H9=fH H@0H9u$fHH_H|$HHD$HH|$uHAWAVAUATIULSHHHt$H$dH%(HD$x1DH|$IHH<$HHtfDH5- HIHBE1MAE1H<$t HI1H|$t H|$HLd$ADLL?LLHH\$xdH3%(HĈ[]A\A]A^A_H@HHL=H$H HHƒH @HCLk HHuLk H, H9HHA0H9uH@0H9Hu[fDHt@t +HHuLtHD$8eDAWAVAUIATULSHHHt$H$dH%(HD$x1HH5+ HI H|$IHwH<$HHE1MAE1H<$t HI1H|$t H|$HLl$ADLLjLLHH\$xdH3%(HĈ[]A\A]A^A_fDH@HHL%HH$8@3@HHƒH @HCLc HHuLc H* H9HHA0H9fDHwH@0H9u{fHt@t  HHuLTHD$SEDAWAVMAUMATUSHHHt$(H$HT$ HL$dH%(H$1HH5) HIH|$(Ht@u HHtWH|$(HIH|$ HD$(Ht$Ht@uHHuLlHD$ H|$Ht$Ht@uHHuL=HD$H|$(HI_JMHD$(AE1MA1H|$EL@t!H|$LD$DL$LD$DL$H1H|$ t+H|$ LD$HT$DL$LD$HT$DL$HLl$0ULAVLXLZLHH$dH3%(HĨ[]A\A]A^A_fD@OHHƒH <@4HCLc HHuLc H' H9HHA0H9 fDHH@0H9ufkAWAVAUATIUHSHHH5F' H.Iƅ}M,$u:H5c- LHxHLH5HH[]A\A]A^A_@1I\$H5 - 11HH5, 11HIH5, 11HILAH~LdLAL1HL@v'HHƒH @HELu HHuLu H& H9HHA0H9HH@0H9u;8fDD5DSH=pH5HH>( HHHH5HH"( H5cHHH;HH5UH;HnH5ErH;1HH5:ZH;HH5*?H;H0H5$H;HH5 H;HZH5H;1HH5H;HGH5H;1H?H5H;HH5H;1HH5pH;HH5UH;1HH5=H;HH5"H;1HH5 H;H;H5rH=rH=iH) H=<H) }H=H) jH=Hd) W[HO) f.@SHH[f.H5) 11ff.H5) 11ff.H5%) 11ff.H5) 11ff.HH5 ) dH%(HD$1HGH?HH$yHT$dH3%(uHoff.@HH5( dH%(HD$1HGH?HH$HT$dH3%(uHff.@HH5i( dH%(HD$1HGH?HH$HT$dH3%(uHff.@HOH5' H?4@HOH5' H?@HOH5' H?@HOH5' H?@HOH59' H?@ATIUHSHH dH%(HD$1H?H9w|HDH5H' HL$HHD$HHD$Ht!H|$HT$LHHRHHt$dH34%(uH []A\HH|>ff.SHD HHx @uHx H[ff.@AWIAVAUATUSHHXH|$0HT$XHL$PdH%(H$H1D$dD$HD$ HH|$0H5 .HHH H5% H|$XjHc% Ld$XHu*Hf.HH4% Ht11HLH9\$9 H=d9tH=O19@ƍ4vHLd$XgHT$XH5HfDH|$XHD$XH=EHD$hH==H|$hA=9D$ 9 A9 -H|$hH HT$hHD$hHT$pHT$hHHD$XHD$XHPHpH tHpH(H?HD$pHD$HD$dHD$f.E Ht$Hhz H$H9Ld?H$H9Lt?H$H9Ll?H$H9uHD?HT$H$H=L$L$L$L$H$|$p D$pH MHcH>8HD$0HHƒH  @H\$0HCHk HHu HD$0Hh H H9HHA0H9HH@0H9ufH|$xH=t$HIHt$ HLAH$IHt$t$HIHt$ LIHc$$H$H=HL$HTHL$H$0HT$L$ H$(H|$~|$dDHT$LH=YTfH|$xH-t$HIHt$ H~LAH$IHt$t$HIHt$ LIHc$$H$H=HL$HTHL$H$0HT$L$ H$(f.H$H$t$HIHt$ H&LH|$xIHt$HIHt$ LH$IHt$HIHt$ LIŃ$Hc$H$H=-HL$HHL L$$L$ HH$0HT$HL$(H$@H$8LH|$xAHt,t$HIHD$ HtLHIHT$H$H=L$L$NfD;IHD$xH HcPHcHtHT1HD$8L$MHD$8$H$H=L$H$HEHT$L$ H$(3fDHT$LH=H|$ |$dH$HdH3%(HD$0>HX[]A\A]A^A_HcD$xHT$H$H=L$HDH$HT$LH=a|HT$LH=!\|$xL$HEHT$H$H=H$Hw9\$@fDI]I7IAH$AHvt$HI'H|$ xfDAH$AHU.t$HIH|$ 5 fDH|$xAHtt$HIH$AHt$HIy@H$I9(Hl$@Hl$ L|$HI{t$HI,Ht|LHLI|$IHt)Et$HHD$(HT$(HHHL1ILHM9tNI<$HqAI|$Htt$HHD$(HHT$(tf.Hl$@L|$H*HD$8 H$Ht~t$AHI)AAHD$h-HD$hHD$hEu"H HHHHHEHL`HEPHXH Hu L- LH HtHHN H8IHD$PH$H?I9KD$H$H?H9HDH$ H}H?H9HD?H}H$(HtGH}8H$0Ht,H$8H Hu HHH HtH$HLHlH;Lff.@USH(dH%(HD$1HH5f HHW Hu#H- H H4 HtHH H8HHH?H9HD?HH$H?H9HD?HHD$H?H9HD?HHHD$?H\$dH3%(H([]@@ HHƒH @HGH_ HHuH_ H= H9HHA0H9fDHH@0H9ufD2fDH% SH5HH; H8kH4 H5MHHH;H5d^H;H5TJH;H5E6H;H59"H=5vH;HH5-{H;1HH5#H=H=HQ H=H=H* H=H rH=H _H=H LH=H 9H=tH &H=hH H=dHm H=^HR H=YH7 H=CH [H f.@H@UHHSHHH59HHfHH[]ff.ATH=USH- H5HHHU/HH5IHUH5HHHH5HH H5HHH5p[L]HH5A\QSH=`H5aHH5[HH HHtHH5fHbH H[HHPsychlibyaml_version%stag tuple must be of length 2HandlerEmitterinitializestart_streamend_streamstart_documentend_documentscalarstart_sequenceend_sequencestart_mappingend_mappingaliascanonicalcanonical=indentationindentation=line_widthline_width=iowritePsych/emitterexternal_encodingUTF-16LEUTF-16BESyntaxErrornewMarkParserANYUTF8UTF16LEUTF16BEpsych/syntax_error_native_parsemarkreadpathemptyevent_locationPsych/parserDdtDdLT$mesgClassLoaderVisitorsVisitorToRubybuild_exceptionpath2classYAMLTree;3ؾh0H88XTxlHxxPhXPx|8((Dxhp880XD`|x0(LhHX$ HP zRx $FJ w?:*3$"D\@H@t A xXHKELHRgH@Y A $XXEMD |DA +AM A 0(FDD D0m  AABE L\_FEB B(A0A8G 8A0A(B BBBC  MWMW0MWEp K 0,FAA GX  AABE 0DFAA GX  AABE 0xFAA GX  AABE (`EAG o DAG (EAG o DAG 0FAD G]  AABE 08DFAD Gl  AABF zRx $00hFAA Gl  AABA HFBB B(D0D8J 8A0A(B BBBD H FBB E(A0D8J 8A0A(B BBBG \lFBE E(A0A8JEIDi 8A0A(B BBBG HFBB B(D0D8F@T 8D0A(B BBBE trEe4ELPdx QH C A PQH C A QH C A 0D0XFDD G@  AABI 1EkLq FEB B(A0A8J 8A0A(B BBBA (EAD@ AAE $LDX $XT4EGD ^DA(lFHA DUZETGNU@--l `@.aIE _l l o`  [ p  X ooo<om !! !0!@!P!`!p!!!!!!!!!"" "0"@"P"`"p"""""""""## #0#@#P#`#p#########$$ $0$@$P$`$p$$$$$$$$$%% %0%@%P%`%p%%%%%%%%%&& &0&@&P&`&p&&&&GA$3a1 _ GA$3p1113p,_GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA$3p1113@.O_GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFYP-\^GA+GLIBCXX_ASSERTIONS GA*FORTIFY@._GA+GLIBCXX_ASSERTIONSpsych.so-4.0.5-3.el8.x86_64.debugҮo7zXZִF!t/]?Eh=ڊ2N$:Ph!hsAwAvA#(PoGJ^h2 *>k}} E]/{fIh[D ?מX0R4vwfV+hDr##yslĎ(0OqC^WN`J֭ ?2lWn|]ŔHkƥI'.gۻ82ѹ27#↛a[X)h\@=+ iZmȬ2 l a*b['/م.pVBjdYyQ/il۬~{C; /;1aybÿ1T "Z/ή(&I}B_)P_7*sR@)&@rpwb v (bq8rXG˱k &eD 2I F2/9zJRL[r:doᩎd˪a)^Fң j5NGmWo/Ƕ] Śjsa>K4s be9u vW L.I߳ztnzD u&193Ys#27?v23)jK~/ oiC:$gD5]#[/f+$FPV^NNnc%v86wG"s82˞"RʅU\ 9xM:mk So7 0ZTU0fŨ` Gvihn/c|gPs&)svD7D+{5oᅨI T!*HOt=(Gk8I!5S艴;Wzw.7V⁇S~`t 8ģ'lkJGb`||rU&j'pGvzMnׇԵeY0"H'`hPw놸UBZ0X$Ք̤g;dsJõ (إ'.VytݯRP;i(qk_8J-#) ) gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o```(  0 [8o<<Eo@TXX^B  h c n&&wp,p,:3}__ __Ibbccxkxk l ll ll l m mo o`p pr rs`rl dw(w|+PK!psych-5.3.1/gem.build_completenu[PK!json-2.18.0/gem.build_completenu[PK!Qjljson-2.18.0/json/ext/parser.sonuȯELF>$@p@8 @hh   ȽȽ Ƚ 888$$HHH StdHHH Ptd000  QtdRtd GNUH)ONK/ƫU@ UXBE|ŷ|!qXS [(}* b||j:5eFU &nK'<")"q2m9|T3D, F"fcw x  m~ __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizerb_respond_torb_fix2intrb_class_namestrrchrrb_str_substrrb_path_to_classrb_str_internrb_sym2idrb_mKernelrb_hash_new_caparb_hash_size_numrb_hash_asetrb_sym2strrb_data_typed_object_zallocruby_xfreerb_gc_markmemmoveruby_malloc_size_overflowrb_enc_get_indexrb_funcallvrb_str_duprb_enc_associate_index__stack_chk_failrb_unexpected_typerb_hash_foreachrb_cstr2inumrb_free_tmp_bufferrb_alloc_tmp_buffer_with_countmemcpyruby_xrealloc2ruby_xmalloc2rb_cstr_to_dblrb_float_new__memcpy_chkrb_error_frozen_objectrb_check_typeddatarb_gc_writebarrierrb_str_modifyrb_sprintfrb_enc_sprintfrb_path2classrb_exc_new_strrb_intern2rb_ivar_setrb_exc_raiserb_int2bigrb_str_newrb_ull2inumrb_ll2inumrb_str_buf_newmemchrrb_str_set_lenrb_str_to_interned_strrb_inspectrb_proc_call_with_blockrb_enc_interned_strmemcmprb_raiserb_ary_new_from_valuesrb_utf8_str_newrb_hash_bulk_insertrb_obj_freeze_inlinerb_string_valueInit_parserrb_ext_ractor_saferb_requirerb_define_modulerb_define_module_underrb_cObjectrb_define_class_underrb_gc_register_mark_objectrb_define_alloc_funcrb_internrb_const_getrb_global_variablerb_id2symrb_ascii8bit_encindexrb_utf8_encindexrb_utf8_encodingrb_define_methodrb_define_singleton_methodlibruby.so.4.0libm.so.6libpthread.so.0libc.so.6_edata__bss_start_endGLIBC_2.14GLIBC_2.3.4GLIBC_2.2.5GLIBC_2.4/opt/alt/ruby40/lib64mti ui ii  ' + @+  u( /0  /8 + (u 0/  1 +ȿ п ؿ % I J K  ( 0 8 @ H  P  X  `  h  p x                    ! " # $( &0 '8 (@ )H *P +X ,` -h .p /x 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E( F0 G8 H@ KH LP MX N` Oh Pp Qx R S THH HtH5 % hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?h@hAhBhChDhEhFhGqhHahIQhJAhK1hL!hMhN% D% D% D% D% D% D%ݟ D%՟ D%͟ D%ş D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D%ݞ D%՞ D%͞ D%Ş D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D%ݝ D%՝ D%͝ D%ŝ D% D% D% D% D% DSAt1ЉƒSE1E1AAADDEDDEDDEDDED DED @DED @DED@DED DEDDEEttA@1A D1Et tA΁ltAtEtAB@tA tA@tAtAtA tAtA@tAtt@tA@tA=v,@u;EttAtA D3 [50 AAAn%E1A=AA nA E1ɅuvSDDAAD։ljAA AAGenutAAutht5> D[DÃD‰E1 ՃtD‰E1 D wH=MHcH>ɚ A w   ~ ck T\ |/;  D ڄH=HcH> HH ؙ HH™ HH wHH aH H KH Hj 5[ &HHE HH/  HH   /vOw-ט Ș   @H= H H9tHޔ Ht H= H5 H)HHH?HHtH HtfD=E u+UH= Ht H= d ]wHGH ff.@(fDAUATUHSHHH9=- H9= H9= H9= H9=ٖ H9=Ė H9= H9= H9= uFHt=H5Ö HH H]HEf.HB H1[]A\A]1HuEEH1[]A\A]DHB"HB!H1[]A\A]HfDHB#{1HBdfHB$KHHDH3H5 HtH H]HE HHHILhH tLh:LoHHtMHP1LL)FHIT$HsLHEL)H)#HHHEuHˑ LHHEdHHENAWIAVIHAUATUSH$MtH1HI9vgH/M$HILxHI9uA tMt0Au-I$Hu HL[]A\A]A^A_E1HL[]A\A]A^A_ff.H (Kff.'H~5UHS1Hf.HEHH4McII4sLWI9uA)wfDHH?H Ht$D$oH\$HdH3%(HX[]A\A]A^A_@H\$MjHt$HMiLoH'IKII4AIHL!HL!HHd@BHHLH IHL)HMMII4)LHL!H#t$H H;t$/^H?Ht$fL^M)L_IILVHHO "LIH!I!I H33333333I9LH33333333I1MDAA0000Mi'G AGJEAEkdEEMLVLWsIt2fE OILWA0McOAI9uD)D0HwIH9DD1HWL)L5GH@LHL9HD?@LW=LE1H900 LH@A1I0 KHcLOLFLL9uL)L%IwIHL$@HD$@@AilEAIcHA)A)HRHLHeH1HHLHeHDHD)ɍLH?)ʁ0ҿIHOD)D3HLNEt"DIIHIуL!H 'HBHH!Hf.Ld$ IRILd$(L\$0LL$8IHHiLL$I'HLOHHLSHLI!HH!Hd@BILIHI L)LH5IHT$ IIHIHM!H#T$(I L;\$0Of.H?I95KDHH!H H H4H Ht$A0DHl$H\$LL$ HMiHH'IHwHO IOJMI!II!Hd@BLLMII I)MILH\$O "L!IL#L$I L;L$ ?`fI&HD$L)H)LM1fDL`sfDL`L)LqLH9DDA0A 2LV@E IA0A K4McLWMqLL9uL1L9MLLLL$8IE1Dff.H v9x4Vx( Vx Vx HHHHHGH=-DIDL9oLMMI9LH+t$ H|$(lT$8HD$<HL$HdH3 %(HD$(HX[]A\A]A^A_@H;|$H|$Hs%=HCH9D$0%{\${uH|$HsY$Ɓ1 %H ҃ ‰AD$D ?ȀD$EЃ?ʀ?T$GȀD$FH|$DEEt1ƒ A D9rLsMLLsA ILl@LsA ILT@LsA IL<@LsA IL$@LsAIL @LsA\IL@HD$x"HD$HXHƀ H=*LLLL$L$eDHwT$DAvDgD$D?AHD$D$<@#D$8fDA D$DЃ?ʀ?T$FȀD$E@HD$HdH3%(H|$(HX[]A\A]A^A_@I)uoO>LH+t$ f.Ѓ?AʀT$ED$DHD$HdH3%(H|$(HX[]A\A]A^A_LHL.H=(1SHD$H=(LpHHD$H=-)HXHHD$H=U(LpHHD$H=6&LpHt@ATUHSLgH]I|$H}H9s{AD$<*t)IL{M9wHH= #@HL{LSfDIWLH)HSHIGMO L9L1E1LAN< L{YHD$8HtHT$8HD$8sfDLLLKL)HIIAL9fDH$x M)IfAaNH59r H8MOLKHt$8HH{ HK HHHD$8fDIwH-&I HsI9B<&@HcDH>f.M)I,A?nullH$MOHD$8LKH8HX;ILKPHHslHLKLS(IQLH)HSHIAI L9 L1E1LAILK@H HsLSHVLH)HSHHFH L9 L11HHHsfDHC H@HD$ }s,PH$,@>"HN=o HKHI9L)A<Hu'HBfHHCI9h(HA<+Ht@"4H<$H)ʋ(IӀ#2H7F߃A<nDs(HC(E1HD$Ay@EeE9G,&L\$AHL$IcHl0HHL$L\$H HptHpHPD)I9uLHL\$HL$L\$HL$Eu{HC Hh],PH$,@t9~H=n H5`1@(H4$HL-#I ,HCHK@H9s00V&IcTL>fDHHCH9rHH= @HpHCHKfDHpHH)HsHX HPH L9L11HHHC^fD@,H<$HL5#HC!H90V&w}IcL>HHCfDHHCHKfDHpHH)HsHo HPH L9t{L11HHHCyf.@]H4$HHCHK}DHHHCH)HaHHPL9fDHHHCH)HHHPL9]fDHH=YfM)IGIvkHInfinityI9Wu[H$x H5Fl H8MO LKHt$8HDHT$8\HHD$8L4$HCHLL]I>HD$8H#H<$ KM)I>HInfinityI9+H5k H?MOLKHt$8HjMDM)IAalseH$MOHD$8LKHHHT$8HeHD$8M)IA?trueH$MOHD$8LKH8H@]~HHCHC L`,(H@I)H4L8HHC L)`H$x$H$H8Hl$8H[ H{ HK HHHD$8BDIwI93AogfoOfvfoOfoffofftfo OftffftHHCfDH8HCHsfDHHHH)HKH HPH L9L11HHHCpHVL9 oFoffvfoMfoMffofftfo MftffftD f.oGfoffftogftfff HHzHSL9vf:L HH4$HH HCiHCHsL%H9N Q&IcL>DHHCfDHHCHsfDHHHH)HKH HPH H9_H11HHHClfD} , HL%HCH9Q&w{IcL>fDHHCfDHHCHsfDHHHH)HKHH@H9H1HHHCu@H<$!t }"\HH=e HKI|L9ALA<Hu0IRf.IHSH9hD"HC<#Lt@"#H<$I)ʋ(#I7@߃A<Dk(HC(E1HD$(AyfDEt$E9Gd5LT$AHL$IcL\0LL\$L\$HL$H HpLT$tHpHPD)I9u)LHL\$LT$HL$L\$LT$HL$fEl$a@HHHCH)HHHPH9yfDHHH)HKHHH9LHHsH)HHHFL9LLLKL)H>IIAL91HHHCH)HHHPL9O@XHc LHnIH$HCL\$8H8H&H{ HK HLHCHsL%H9Q&w{IcL>fDHHCfDHHCHsfDHHHH)HKHHPH H9tKH11HHHCsf:GHH4$HHCHCHs5fDHHHCH)H*HHPH9uf.LPI9oHfo&Hfvf HoPfftfo HftfffЅt ^@IIzLSH9oGfoGfGfftoWftfffЅtHcILSA:IH1Hs@1HHC HPH@H4H裿HKH$x$>H1H(I7@߃A<Dk(HC(E1HD$(Ays@Et$E9eGd5AIcL\0IsI tIsISD)I9u)LHL\$LT$HL$蝿L\$LT$HL$tjEl$H` LHLT$HL$e{(>HL$ILT$2H|$(HDLT$HL$HD$#LT$HL$L\$@MH` HLLT$HL$H{(>HL$ILT$.H|$(HDLT$HL$HD$L\$HL$LT$M9@H_ HLHfIfDHH= MH(fHH=H4$HHT$8׿IHD$8H7F߃A<Dk(HC(E1HD$AylfDEt$E9\Gd5AIcHl0HuHE tHuHUD)I9uLHL\$HL$聽L\$HL$tREl$Hk^ LHL\$HL$N{(>HL$HL\$H|$HDL\$HL$HH^ HLL\$HL$HϿ{(>HL$HL\$H|$HDHL$L\$HH] HL觿HHHHT$8;HHD$8IH@1LKH4wHH$x$G,PH$,@HH=X dHC HhL`HC ,HhH+l$ L{IIL譽HS HIHBHRH)L4LL L豺I9hHC H)hH$x$H$LcLl$8H8HH{ HK HL&HD$8H4$H1H H9bH4$HLHH=l \HHHHsHT$8蠼HHD$8HHHHHS:DHLIILSIHHLH9CHT$8 IHD$8H$@LHH~H=o H1=HD$0HpH tHpHSH{H9? HGLJu@Hx HH)L9uH=?1ԺHD$@HZ Hu L5 LOHpZ HtH= [ HL$@HzHD$0HD$8HD$0LHHH1H9eHzHE1ɀx ALH9uEHH=8HH= $1ff.fAUATUHSHxHt$H\$HdH%(H$h1;HHHD$&H$`fD$$HD$(HD$D$D$HPHD$H tHPHpH|$01FHH\$0HT$8HD$HT$@HHHHT$HHD$PLd$0HMHD$@HL$HL%LI H9s/0V&IcL>DHHD$@H9rH$hdH3%(HHx[]A\A]f.HHD$@HL$H@HpHH)Ht$@H?HPH L9t"L11HHHD$@BHHHD$@H)H"HHPL9ufAt:H5R L苶IID$ MI}=L5I$HƒH u@tID$HHtH5R Ml$ H9uID$ HR Ml$ H9tHlHA0H9upH@0H9[Hu?HH=/ Jf.H"UHSHHHt$H\$HdH%(HD$81aHHH\$HD$GfHD$0)D$ )D$D$,dHt HHgHt$HHL$8dH3 %(uHH[]nff.SHHHu HH5P HH[ED@uHHH u˨@tHBHz HHuHz H59P H9t@HtHI0H9uATUSH=rRH=rH5kHHV L%R H5RHHI$H=IHDHHU ųHH5{膶H߹HWH5 KHHH50I$HH5蝶HH5HH=ƳH=OU HHH%U (H=蜳H=%U HHHT H=rH=T HôHHT ԲH=T 踴H=kR$n`F"@x|菇+MraBsi ydiWCb**"fJa\)c\9T7]ȳG)`x-xֲ@t@K}YPP{q\Ckd 3TYޤ[' o%Һrȡ1(ˮi:~^Ym?Md~@HAq vaT 0}GoE(>nll$239~@j4$Q!=P1PAm%CMZ>d~3gW`M}zF^AmnEH:HD/VZIZ^0\zpue񓾊y쮐afird8n헧?O(}Qrbvy~JG9bԗ]z){} Ud:Ft'UcȋhEq_|ֆ<ֺ.2w 9i9(*WICȷsluuuݏҘbIL깼Ã]֯y)e諴ds~=I"[пfM&mEoX82/'% }/ًn{^Q4g4_6A]7bD2`G~zU[tp] ѵMQ%L9hwRF:D.B Ą' |Ô%Ime%\nsmA/sqի71Fʖ=`R},%|xӫ]@<>+dpBu 05==N=@ !Fҟ&3 hG0J#ÓR=:YxY|Sf$hp&sL Lo틱)>aw<]3sM`j5!ae.{nLBi_ O)87?q=kzN*.rYH p0X !7-4 |oX* 8PJ(L%vq/V(wzYk21UI~_j nQoFOn{*do^% 5= 6~; [,a ]uj[|8zŧ-@4ٶQ9S7#TDH"s:V!iw9OBɫ̕E㒻TiP>XSN3&d.Ng"@upqazjHIdžޠ}+ۧx(Y/v[;p-Td#VO%&2b~t#셣_~Ù:,gg[4@I|:@!ȰeIT):3$[t0V(rWhg^Jp5|HlrNB\BZOL3td peD0/L >?V;=Ȓ;.-+Lzw 4=|lia[ofLGS9ˋW-; (4n8`Sa =U7el#|67Sh*~G,(/u&^Y!E yձ= ڗ:5NJ ="epE+Dx?K8 kG^z΅\zMFB6py,0TkCLf l8*ƫ T~(sV *)*fPzJ7M;kP =!w$lYL)\Ȕ9ت|Lu<  Ky}a[@JOל`rT De*JcOقnQ:*g(#t.3t<{NT={gRDW5P8[)b!rR`d g]Vxt\)O8=*T+bftxe:P R6WbIdN@fM}-\<Ȍ`"ԼnY>0/!x\+ l^<{)3v ml16Kڳ{SHǽŞhPMX-ucVr;`n1xR|CN  GzGzGz$ClMb h"lxz,C6Cnah㈵"6X8IǴ6j#RWHOfA90yQ-沔& . Qˁhַ|:4_dyȅ'- @ evIh%q3p+C~)!V瞯751ׅi+ؗZ?7!FFsHE_砫C]r] z<=f4ҶOɃהcQ]#B Ky݂~}O h[bјd*^ 9S⁧DQ@-&ORMXjWA~{P'}4Pe_ɦRˮ@L<6 íSyA`Pgt-gG^ZR)5o$4KHYhe9_)L2#Y]5=[w(b}'^VIL hɫz>:z[Zr.-DE.ʯBE ܲJx8A}n-U/ggudXWw'&lۈmm% =#F8(LIUln`KSO1O`gEr'j7N`rV`U,$DW5λm: *+/vObV4o༻Un ǒJzW@ Koqը|oX' f3L)`ׄ)RɣT Һɨvo^ݥWbOHKKH~QA١YmV3{w{W<*`Y^6&GhkQVUy*#ѧ"}tV4с 1SEls4=DVS(S]R]jbWa.PEHNX[ݦe klqcA(Hdc Sk5GkJr 7qxL۸DFmE_cUIkE867wiAFcVXXrgсyq(UA4aܐ؆nGV5}$ eh䌤%9x0l ׶,󰙻4#aM9G(SN\_T8hZ.,ӹu }C`SD[HX#06|;m&r+A.*r( ǼO9\0 ^0$_ZhIy&/߃v` Qn R^ oKhO+wiŊt\, h|ITo($SW:Uv \vC`y;bs^f+23WdmARļ}` \̶gi=N}ߊwr//.Ւ[s򈬌j>efDBI(V=UJBMAW2h9ayw@[TR yqa-hYPh|[vtV[ҦJ> QD|@MD7Jidή nXPO;燅^{r6_ &7[@ՄF,LG7ь#G?ELg$մG̝Rßr8' KEy,~i†Yة_)F06qzk^'/(bQKu8Ly*Y-ذSr%V.UGHy޷ET| ~/wvrm.yCQx?Z"cd؊dB23_FYYݐ+9_ά£-Li^rHCB։TiT/k tk"rv׾"pF*N(Ngk }xt;Q$~{_|Ma) 1Ac ˔!נ'$4̂wxTϹgo mC!7q-ݥYpMW}Qz?> /.ø2y$ 1f6ǒx\'^lu`|{ Sɼg]ŰBt?j/v'\*2+Π(aoJYJNt3L%)>sQQwqMrx)W{Tu !S2Y݉ jBC(cJnpfj'8 JC!,=ktn{~VNW\XA#J%bA_a`6)g=M !V2dsmf+i#:{λ4b[WKb5Ydy؜;761FJmZƑB'+nW0ѧR<}%%1@0<HyZㄨQ1KǮSʹBR ȅ>!t@:SP J`gB  )7zR5 B0Y*9K >Ba<>=eX, dn #Ӌq@a>PẔ<+aĺuǎ ]1)j hb{wo>'g]@,c>?IuI33QFe G]Pn֏ʧ^QpSɳKWDnN: yG%h`lπyn?*4zK3"9 l.Q*C\ռځU".qߐUSl OZLϨ{x~ "j_}'6T ۗN~wf|yL#t  p-k'TZZPY$ xEفpwj{C[(.{ C, }+œ7[ oq">sH'pdx[ڬ%T ULP`>{a 3f@˕,sRpfRfXGdY#&GlIЂl#)_<u8Yղ)%,{w%ܞlX"+ }z-y=vjNaW` Y  M:E[]c܄دȍ0kJ>b"&n&u)FkpP*Fٝ%TkMytRbo͇xE/|(R]^" jɆBKh<:hm)y@z,`ژ $!3VF6MC)x8ܴܤJkf'Z`!a2MMoNaю=bY ٶ+OGE$^r'~߱ II ;[iРJ]ˤ/|MRSc:\ qgt/oVRH*ـ%K//4Q 4 ~O q>]m (2eW (z:|<,Y ٹC=p_]6Z&9$V" 50٦K]?#=YN2T\98/hy}NS-`]5SdPrve*xv춦Do&}bj߿*"R?'Cod(NNeP 8J (tJoe3; jY"s™l6ٴ5VW ?~I$""}ELd鐕h0щx=CsDS 't̜MR%Ga5ǷM\ِ_! =#3[PhKaP*+jg@"N@\Ukj!SݔN IDQȇHJv ڽlHFlkՑdLIݧO:z C8/.99Si(]/u.G!"?"\TAze訰C87bķ23ۆ&h6:Y둤 '^itP<z^~/c]@tVq8b͆x yz-=Vo-qBaКȊ1""NjhMڪ=O@ty>Sڮd?]]a(lXmP̙}h e`Hz\/D=qa61,2.6Yaw䉛ח?ZN,5}ʃ2V Lo1J(pYݕ^C (J^W^5Ĥgձ~i~R"Zy%/0^IaMXnKD#׭5$+>=YI4V"=nmco$iA7;ћYcu5%3ҐP7x ?vtu @,x1$HgY-[@,ӵM$|_}Vo+phmƘH~=NtW§KMҀGyPDyH؎ŭD)-m3?W Φ$$yFeJvM}:=tozwVdP>1d]ˍJp,kW$GDlSBL!|C#)Ch=32z}hN6TϹ21P@JƹK)Q w31oڹk v)ӿҮ۬dWBI~#͠`19LpMu'UpI }*wCW{b=5jyɎ dbq¼uwle'5kӒAġ_VeadcHO|QܛMP2(}Iqs v;|.~Y;S+ʾ7G/U4KX lÌ!!!!!!!!!!!!!!!!\\\\\\\\\\\\\\\\.oDDDDDDDoDDYDJoYYDDDDD4JDDDD4Y4DDDDDDDDDD̀DDDDD̀DDDD̀DDDDD̀DDDDDDDDDDD|DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDmDDDDDDDDDDDDDDDDDDDDDDD;  o(tPyp|`h|ЃPdxPpЄL h@`Њ,p\0@D@XPzRx $nFJ w?:*3$"Dxs\~p~ \~}FBA D(G0 (C ABBI R (C ABBF _ (C ABBI \BEH B(A0A8D@p 8D0A(B BBBL G8D0A(B BBBDxX (lALDF eAACEP(TBAA  ABA (܁AAG0C AAB 0 `hAAG } AAH DNA@!JP(\AC BF H 8BBD D(G@a (A ABBF (^AC DDY K ,FAA  ABA , BBE A(A0DpLP BEE B(A0A8D 8A0A(B BBBE |dM|ԔBHB E(A0A8D 8A0A(B BBBE  8A0A(B BBBI e 8A0A(B BBBE 88BAD D ABB } EBD tx6A,UANN AAE LМBBB B(K0H8GK 8A0A(B BBBI < BBA D(G ? (A ABBK (L@EDD` AAA xĺEa J ,(FFA APrAI G xu,RtADGNU'+@+ u/ /+!(u0/ 1+DS]m  p  o`    hx oxooo Ƚ  0@P`p 0@P`p 0@P`p 0@P`p 0@P`pGA$3a1*GA$3a1*-p GA$3p1113+pGA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFY++GA+GLIBCXX_ASSERTIONSparser.so-4.0.5-3.el8.x86_64.debug7zXZִF!t/']?Eh=ڊ2N ih'_7GFy#D$]'H(ql˷ b4R]W' \%vVQ1ߚc- yK%M_M![WHg+noWX}Sh,'Pb?wR]j5nmff~~a/eJ족ٗ龭\q!PC[R'&н pO_2ڏ,YiMMchŭc6`%4I׺,Sm|5Yʼnuys1ltx|:o$>Nk@Y]1y\E_jΜ  Q34rI f;pLx.9nH*Ǭɘ3:Kz9U҈\Q kG{{G-vS.{f̵5ćw=T໾޸KQf$Q](MuZ9@i|,lYr+h ~nK9B %7+QTkuNMbhh}Wz`۩\57'5^uˁ"Zae ݬyٕ |m#>c`6$)8̭O؞(Ν+f*i\Z\zz"@x pZ^w3tG5@L80c\NYUFè(/9f>|9R70dqsG ڽiCSKv{aj7<nr |ׯb~W0 s3nC1L"beR Tf:PA7?tt 6+dwX̒/oƭ}{sϳϑ*BxAZd&NWH"qA-ff5[>YY0h-OP\2fU "/X@0y _}ZNpP~,*?:% ]~Ƣ5H=#40`(|H_LY07DjHg2Hzi^Su>4KH 5lZiRgs[(*zHfϛNꚈKdNBNB?TD r> _ w8!1sGx*5Rus>7P￴3^$9z1,ϡ D &5?gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( X0 8oEoxxPT^Bxxhhcn w$$/K} p p @p@p: 00 @@HH    Ƚ Ƚȿ ȿ0  x`l ($@+PK!!json-2.18.0/json/ext/generator.sonuȯELF> "@@8 @  @` hh h 888$$ Std PtdhhhQtdRtd GNUtiʄo.<\%a+nR@$RTUBE|qXt)M S5ylN p<od: U _"/H'hk""/Yb )w{=V, \F"@8( KH ?(  t __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizememcpyrb_warnrb_funcallv__stack_chk_failrb_enc_associate_indexrb_exc_new_strrb_intern2rb_ivar_setrb_exc_raiserb_vsprintfruby_xfreerb_gc_locationrb_gc_mark_movablerb_data_typed_object_zallocruby_xrealloc2ruby_xmalloc2rb_utf8_str_newrb_io_writerb_error_arityrb_utf8_str_new_staticrb_cFalseClassrb_cFloatrb_cIntegerrb_cNilClassrb_cTrueClassrb_cSymbolrb_str_freezerb_obj_is_kind_ofrb_cHashrb_class_new_instancerb_string_value_ptrrb_io_flushrb_unexpected_typerb_str_new_frozenrb_hash_size_numrb_hash_foreachrb_ensurerb_gc_writebarrierrb_convert_typerb_proc_arityrb_raiserb_check_typeddatarb_error_frozen_objectrb_str_modifyrb_eArgErrorrb_enc_str_coderangerb_rescuerb_proc_call_with_blockrb_str_duprb_respond_torb_sym2strrb_struct_arefrb_cArrayrb_cStringrb_float_valuememsetrb_obj_classrb_eTypeErrorInit_generatorrb_ext_ractor_saferb_requirerb_define_modulerb_global_variablerb_internrb_const_getrb_define_module_underrb_path2classrb_cObjectrb_define_class_underrb_define_alloc_funcrb_define_aliasrb_id2symrb_usascii_encindexrb_utf8_encindexrb_ascii8bit_encindexrb_define_methodrb_define_private_methodrb_define_singleton_methodlibruby.so.4.0libm.so.6libpthread.so.0libc.so.6_edata__bss_start_endGLIBC_2.14GLIBC_2.2.5GLIBC_2.4/opt/alt/ruby40/lib64.Pui [ii g `% @) )  ( 00 008 `.@ @0h p x      " / 7 ; G H J K Q  ( 0 8 @ H  P  X  ` h p x              ! # $ % & ' ( ) *( +0 ,8 -@ .H 0P 1X 2` 3h 4p 5x 6 8 9 : < = > ? @ A B C D E F I K L M N O PHH HtH52 %3 hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?h@hA% D% D% D% D% D% D%ݱ D%ձ D%ͱ D%ű D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D%ݰ D%հ D%Ͱ D%Ű D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% DS1HH=/yzH[HHH={1LBRH={1/M@XH=p{1LLff.@SAt1ЉƒSE1E1AAADDEDDEDDEDDED DED @DED @DED@DED DEDDEEttA@1A D1Et tA΁ltAtEtAB@tA tA@tAtAtA tAtA@tAtt@tA@tA=v,@u;EttAtA DC [5@ AAAn%E1A=AA nAƭ E1ɅuvSDDAAD։ljAA AAGenutAAutht5N D[DÃD‰E1% ՃtD‰E1 D wH=ŅHcH>٬ Aͬ w¬    c{ Tl |/K  D ڄH=HcH> HH  HHҫ HH wHH aH H KH Hz 5k &HHU HH? 0 HH   /vOw- ت ɪ  @H= H H9tHƦ Ht H=a H5Z H)HHH?HHtHզ HtfD=% u+UH=¦ Ht H=ޣ d ]wAVAUATUHS0LgHwH?HOH9fo-ofvfofo%ffofftoftffft<foBfoffftoJftfffHHQHMH9vII)ILuI9zINIFH)HfotIN LHHu>fo&fo.offt .fftfvfffHELhHE[HEHE]1A\A]A^H9^I91[]A\A]A^HHDHU(1HM HcE0HэP!HME4L9[]A\A]A^D1HUH]E0HcHU HʍH!HUE4H9vII)t6LeID$IT$H)I9ID$ LHHMl$HUHUyHL)t,IFI+FH98I~HI~ LI^LuHEHEEHL)t.LmIEIUH)H9IE HLHI]HEHE1HUH9H=:x<u!HBHHEH9 H<tL9HL)t.LmIEIUH)H9IE HLHI]HEHEdIM)t2H]HCHSH)I9HC LLHLkHM[HM]A\A]A^@G4H @HuHE0H9H};HL9HL)1HcH׍P!H}E4L9IM)t2H]HCHSH)I9HC LLHLkH}H}^LINjLH HCHuHzHLHLIELLID$LHLIEOLHHCADXfDHH5a dH%(HD$1He HH$HT$dH3%(uHff.@ATUHSH5| HxH=! HHH? Hu#L%oLH HtHHHHSHHHHT$0HL$8LD$@LL$Ht7)D$P)L$`)T$p)$)$)$)$)$dH%(HD$1H$H$HD$HD$ D$0HD$%HHf.HHx uHu $@H$Hff.fSHH?H{HH{HCH{HCH{ HC}H{(HC pHC([f.SHH?@H{7H{.H{%H{ H{([fH5 HXHP @uHP HB0dHB@H@IASI H HMHML׉IH EI II II[KH HIT@HfATUHS?HLg tL0HC Hk[]A\HCHSHC HtLHHk[]A\ff.UHSHHH(uEH} tfHMHUHH)H9sEHHHH)H9rH9s/HH[]?H?w:?$H9]vH[]H}HMHE HMHwH H}(H{HE뭐UHSHHHOHGH)HHK Hy-HCHHHHKHK HcH?BH'f xH*Yxf/H,HHhHrf1H%HH)H8iHHBfAHAH+C HCH[]DH9Haw̫HHHHHHIHiH)HH TH9H?zZH9HH9Kf wH*Ywf/H,HHgHxH=ZhfHvHH9H)HHHHWfAIfDHAghf1H HDH+C HCH[]DHiŹH gHƉH HrHf1HHHƉH)HHgH H4rHBfqfAHAH+C HCH[]HHišH}fHH0rf1HHH)H#gHHHHƉH H4rHHfqHƉHH H4rHBfqfAHA@HKD\H,H?1DHiՉ;UHeHHH9pH5nff1Hɚ;H!H)HHHHH!H9FfAHHHHH!H9FfAHHHHH!HH9HVHH9fQFfAHA fDHo#H9HH9HHHHLiHWx/e9HHc M)MH3H9H=meHWfAIiѡHHHЉH GfHHHHH GHfAHHHHЉH GfAHHHGfAfDH=dHWfAHi֡HHHЉH GfHHHH‰H HWHHfQH‰HH HWHGfQfAHAH+C HCH[]DHiҹHrcH׉H xH=.dfHrN H9H)HHHHHЉH GfAHHHGfAHiҡHbHH0xH=cfHƤ~H9HH)HHHHH Rf\H,H?Df rH*Yrf/ H,H%HYbHHHHzH=cHGfQfAHi҉;UHbIHH9xH=bfH]xEcH9L!H)HHH HHL!H9GfAHHHHL!H9GfAHHHHL!HH9HWHH9fQGfA^\H,H?PX1Hff.wH=dvPwH=cVPwH=c6PHu H H@u HGDHt2Ht<@u@ t@H1 HDHi HDH) HDH) HDHQ Hff.fHH=f1HHBfUHSHHHHdH%(HD$1Ht HT$dH3%(HubH[]fDHy HH0~Ht)HHH$H5 >HfHɖ 11HvfDAUATIUSHHH|$Ht$AIHD$HhID$I+D$HHH9wWHt@I|$HI|$Ht(HtI|$ HLI|$HI|$HuH[]A\A]Lff.SHHHWH?S HH{(HsH{ u [#H{(HHCH{(NHC([SH dH%(HD$1uuHGGH@@HtaHEHHD$Hi H$Hu!H`HHD HtH=( HHpHD$dH3%(uH [DHu P@uHHuHu1@ff.USH8dH%(HD$(1Hu!HD$(dH3%(uoH8[]f.HtH+HHuHHHt$HtHt$HT$HHl$Ht$H5 ff.fAUI1ATE1USH˹ HdH%(H$1Hl$`H|$`HHHDŽ$dHDŽ$HH$IDfHt$0D$HD$HHDH=`H)H\$($HD$H$HD$ HHD$0H9HD$PH$HD$HD$8Hl$@Ll$HHD$X H$dH3 %(uH[]A\A]USHHH|$Ht$hHT$HjHt#H{HSH)H9wH{ HH HkH[]HHH$AH{H$SHHH5* 11H[Hmff.fHփt H@fDH9= ATHUSHH*H9= H9= H9=q #H9=\ H9=G H9=2 H9= 7H9= H9= H9=֐ H9= H9= H9=ϐ H9= uRHELE1HCCLe(+fHHBHHE[1]A\HHBHtHE1[]A\HE1[]A\DHHBHHE@HH{Ht+HEHphH[1]A\HE1[]A\DHHBHtHEDHEHH{H'HEHtDHu0HBHHE DHEHH{HHE H wDHENcHXH{H/HEH7DHHHHDHU0fHH{HGHEH|DHE HEMHHHHDHU8fHEOHHHE@vHEPgHEHPH ZHZ HcIHHH{ELHLe(ALaHE(ff.@ATIUHSHH HV(dH%(HD$1HFHJHN(H@0Ht H9/LHHCH9CHS H5BL{HHCHD$L$$Hl$D$HE(L`HELe(HpHukHCH9CHS }HCHD$dH3%(H []A\HSH)HHC {}fHCHm(HHEH0HtLHq@H;HCefH#HCHV(H=' 1H5VQHHC[DHuHH5 'H@(HfD@uHHƒH ų@tHGHHt0HG H H9uH@(HR0H9tHuHG f.Hu'HH5l H@@HHDf@uHHƒH uĨ@tHGHHt8HG H  H9uH@@HDfDHR0H9tHuHG f.Hu'HH5̄ xOHHHЃD@uHHƒH uĨ@tHGHHt@HG H } H9u!xOHHЃf.HR0H9tHuvDHG fHu'HH5, WH@8HHDf@uHHƒH uĨ@tHGHHt8HG H ݃ H9uH@8HDfDHR0H9tHuHG f.Hu'HH5 xNHHHЃD@uHHƒH uĨ@tHGHHt@HG H = H9u!xNHHЃf.HR0H9tHuvDHG fHu'HH5 xMHHHЃD@uHHƒH uĨ@tHGHHt@HG H H9u!xMHHЃf.HR0H9tHuvDHG fHu'HH5L wxPHHHЃD@uHHƒH uĨ@tHGHHt@HG H H9u!xPHHЃf.HR0H9tHuvDHG fHu'HH5 Hx0HHHЃ@@uHHƒH uĨ@tHGHHt@HG H ] H9u!Hx0HHЃfHR0H9tHuvDHG fHu'HH5 7H@0HHDf@uHHƒH uĨ@tHGHHt8HG H H9uH@0HDfDHR0H9tHuHG f.Hu'HH5l H@HHD@uHHƒH uĨ@tHGHHt8HG H  H9uH@Ht/fDHR0H9tHuHG f.[HOff.@Hu'HH5 H@ HHD@uHHƒH uĨ@tHGHHt8HG H ] H9uH@ Ht/fDHR0H9tHuHG f.Hff.@Hu'HH5~ H@HHD@uHHƒH uĨ@tHGHHt8HG H ~ H9uH@Ht/fDHR0H9tHuHG f.Hff.@Hu'HH5,~ WH@HHD@uHHƒH uĨ@tHGHHt8HG H } H9uH@Ht/fDHR0H9tHuHG f.Hff.@Hu'HH5l} HHHfD@uHHƒH uĨ@tHGHHt8HG H } H9uHHt0HR0H9tHuHG f.[HOff.@HHu3H5| PHtHEHD@uHHƒH u@tHGHHt0HG H M| H9tfDHR0H9tHuzDHG fUSHHHuHfD@uHuHHHH t)H5{ HH@PH[]@tHCHHt-HC H { H9t HR0H9tHuHC f.~HoHHƒbUSHHHuH6fD@uHuHHHH t)H5z HH@OH[]@tHCHHt-HC H z H9t HR0H9tHuHC f.~HHHƒbUSHHHuHVfD@uHuHHHH t)H5z H:H@NH[]@tHCHHt-HC H y H9t HR0H9tHuHC f.~HHHƒbUSHHHuHvfD@uHuHHHH t)H52y HZH@MH[]@tHCHHt-HC H x H9t HR0H9tHuHC f.~HHHƒbSHHHuH@uHuHHHtsH t-HH5Sx HT$yHT$HHHH[è@tHCH{ HHuH{ H5x H9tHI0H9tHutHHt$HHT$Hhff.USHHHuHfD@uHuHHHH t9H5rw HHHHHDHP0H[]@@tHCHHt-HC H "w H9t HR0H9tHuHC f.nHHHƒRUSHHHuHfD@uHuHHHH t9H5v HHHHHDHP8H[]@@tHCHHt-HC H 2v H9t HR0H9tHuHC f.nHHHƒRUSHHHuHfD@uHuHHHH t9H5u H@HH~Hh@H[]@tHCHHt-HC H Bu H9t HR0H9tHuHC f.nHHHƒRATUSHHuH@uHuHHHH t1H5t HIHu^ID$[]A\@tHCLc HHuLc HVt H9tHtHA0H9u 몐H@0H9tHuH8ID$HtuHH[]A\DNHHHƒ2ATUSHHuH@uHuHHHH tYH5s HIH KEHLE HID$(Htu HH[]A\f@tHCLc HHuLc Hs H9tHwHA0H9u{fH@0H9lHuPf>HHHƒ"ATUSHHuH@uHuHHHH t1H5rr HIHu^ID$ []A\@tHCLc HHuLc H&r H9tHtHA0H9u 몐H@0H9tHuHID$ HtuHH_[]A\DNHHHƒ2ATUSHHuH@uHuHHHH t1H5bq HIHu^ID$[]A\@tHCLc HHuLc Hq H9tHtHA0H9u 몐H@0H9tHuHID$HtuHHO[]A\DNHHHƒ2ATUSHHuH@uHuHHHH t1H5Rp HzIHu^ID$[]A\@tHCLc HHuLc Hp H9tHtHA0H9u 몐H@0H9tHuHID$HtuHH?[]A\DNHHHƒ2ATUSHHuH@uHuHHHH t1H5Bo HjIHu^I$[]A\@@tHCLc HHuLc Hn H9tHtHA0H9u 몐H@0H9tHuHI$HtuHH0[]A\fDNHHHƒ2SHHdH%(H$x1HH5Rn HL$H$tHL$H$HfHD$PHDξD$H=HT$`HHL$8HH@H@8H\$XHD$$HDHt$@D$HD$(HL$HL$pHL$0HL$HL$@HHD$HHD$h诿H$xdH3%(~HĀ[@HHƃH @HGHHt4HG L9m L9HHv0L9ufHG žDIЍWw#HH6uHHHLNPNff.Sw1HӸuHH=r H*H1[H]HSw1HӸuHH=Rr HH1[HHSw1HӸuHH=r HH1[HHu`Sw1HӸuHH=q HjH1[H]-H5 Sw1HӸuHH=q H*H1[HHAT1UHH55q SH1谽x=Iu/MtAu I$Ht*LDHutͺ1葾H=p [L]1HHA\\ff.ATUHSH9IHt@uHHƒH H5j H輼HMH5yj L衼HOooHKoP S oX0[0o`@c@HPPHSPHHHPHSHPHSHPHSHP H@(HS HC(H[]A\@UHEH] HHuH] Hi H9@H%HA0H9*H H@0H9ufAI$HƒH @ID$HHt:ID$ HNi H9HI0H9HufID$ Hk H5:H81!AUATUHSHHHwH9H=5@<u HBHHEH9t| H<tLeI9rH[]A\A]fDHL)t.LmIEIUH)H9IE HLH޺I]HEHEH[]A\A]fLe1I9sHL)t*LmIEIUH)H9w?IE HLH臺I]HEHEH1[]A\A]HLIEjHLIEfAWAVAUIATUHSHHhdH%(HD$X1HGH9GIU "HCIELl$(H tHCHD$HHD$ HCHD$D$DD$@HD$0Ǹ=t = HExNPOLd$H-8tF^fD\H HC A\\fDHCfHD$HHD$HD$ Lk <HD$H\$(HKHCH) ~a"~./uH? HC A\/fDHCf. u>H1 HC \rfHC[ ? փ@Dt@D|5HHC \u00DxDpHCfDL9vSHL)t>Hl$(H}HEH)H9vHHkH}H} HLH]HD$HD$ IEI9EIU "IEHD$XdH3%( Hh[]A\A]A^A_fHVHC A\bfDHC>fDHNHC \nf0HCHFHC \tfHCHFHC A\"fDHCfDH>HC \ff8HC6IEDL|$ HT$L%:H9H-'6LDHL$H9ZE4HBEu#HHD$H970HE44EtL9AkH\$(LD$HsH{AH)Au\ }"<>/U\wHHs \\fHCE1A\uA\uHD$NfDL$VfDT$LfD\$RAtȃAtADEιHA? A9=  TT$NTT$OƒDTD$QT$PHD$LHs D$PfFHCAHT$HT$IHT$ 0 uFHHs A\rfD>HC  >ȃDt D|HPHs \u00D~DvHC\-D$Tdf% f-$f(f L L$NfL L$OуTfT$QL fL$PTT$UƒfDTD$WT$VH XHC HT$LH0T$TT0HC fHL)t6HL$(HyHAH)H9eHy HLHL$[HL$HYHD$HD$ LIEHf.HD$Ld$ L56HL$ HHD$H9At  ӃI9HD$ӀuLH\$(HSHKH)@H`HS A29\u20fDbHD$HC@HHD$IHD$ ;HHD$H9AI9/HL)H\$(H{HCH)H9"H{ HLHkfH\$(HSHKH)< -~K<"HS 28\u20fjHD$HCHHCf.HsHCf.HSHCf.H3HCf.HHCf.HHCf.HHCf.HHCf.HHCH}HsSHgHsHQHsH;HSH%HS-HHSfDxuPTHHD$DHHs A\tfD6HCjHHs \nfHCDHHs \ffHCHHs \bfHCHrHs \"fHCHHs \/fHCHzHS \ffHD$HCfDH4HS A\tfD:HD$HC@HFHS \/fHD$HCfDHHS \bfHD$HCfDHHS \nfHD$HCVfDH^HS \"f HD$HC&fDH軾HsOf H裾Hsf.H胾HSf.HcHSHHHL$JHL$Hy}LH1I)HHH{HHs0HHsH۽Hs,HŽHsfH诽HsxH虽HsH能HSHmHSHWHSpHAHSH+HSHHSH5(H1FfDAUATIHUHSHH(dH%(HD$1聩=u2HsHLHD$dH3%(TH([]A\A]@= uHEH;\ t;\ tHCxPt Hx(Hu7HEH9\ tlHHHH=HaHH,$HD$IH9tHt\uHHtS@LD-5\ HaHD&HIk=t= ]@1LA=t= uIEH;[ t;[ |H5-'H1蓸.ff.AVAUATIHUHSHHH5\ dH%(HD$1蜨txH}H+@uHHƒH H5U &H}HU(H5[ H<$HHHP8/HH艩fH5[ 11HHtҨuHHuHHLZHD$dH3%(-H[]A\A]A^f@FHGHHt9HG H .U H93DHHR0H9ufHG f.H=Z 褸IHt $@H5T LIHEoAEoHAMoP AU oX0A]0o`@Ae@H@PIEPLuIuLmHt@uLIuHt@uL˥IuHt@uL败IuHt@uL蝥Iu Ht@uL膥Iu(Ht@uLoH}HD HHHL6HHƒH @IFMn HHuMn H wS H9HHB0H9uH@0H9Hui@AWAVAUIATUSH8dH%(HD$(1HIHHHE1H-'L5Ld$LƒALHA HCxPHx(HELLD$HD$JIIMAIbIEIUH)H)IE trueIEifDIIHPHcDH>HCxP:LʤHLHf.LLEHD$(dH3%(H8[]A\A]A^A_fH9 qW L薢HCH HS H9LHLrHS H9~LHLhDHiS H9VLLD${LD$=HsLL "HS H9LHLDLHL*DIEIUH)HvfIE nullIEIEIUH)Hv+IE fals@eIELLH豵wLߴIE¾L̴IE뇾L蹴IE= u"IH; U ;T ELLD$1LD$=:= u"IH;T ;T HCxPtHx(HNIH9uT LLH=zLIHHHL'MHt+Au+A H6Q HH5 L1IPH]Q HkD=S LLD$HD̢HI=uM= LD$&LLD$LD$== uIH;iS t{;]S tsH5L1.HP H,LLD$LD$HD$ʡLD$II9|HhuHHOI"MVf.AWAVAUATIUHHSHHhdH%(HD$X1}f(fT ,f. ,f.ˆT$+HCxMxPFHx(H9HT$0Ld$0HD$8ܠI9HS(HKHrHs(HI0Ht H9HHHHk(HD$XdH3%(Hh[]A\A]A^A_LeHEL)HkfI~Le D$MyD$+ID$AD$-f.+0HLHH!L!H9I4AAEHHH\?H H9+IfH D)H $*Y*,Dc\DIAIcHHȋPD@xL(DpDL$,LT$ DLA\EDHLHD$2LT$ HLHD$ALDL$,Ht$Aʚ;L#HB A A)HH+L$HHL$IH)Dt$,H1IHt$ IMuL!LHcDx0D|@AII)LHHH9*IHo#I9~M1LI u1븐HnaAD$nfA $\$HcH]v@H5O L11mHH2ODAcL"E1@LcӃ0L!BT@H9w1IH4HAAHHHHHA uL!1H9vHL$IDt$,EH9s?HH)L9r4L)HcH)H|?fIT5H9*HH)H)H9vHcÀl?F,3D)AMENEx 8E?D$+AIT$A)D$@A9DOA$AAECeELD+c9 \Ⱥgfff))ȃ0\$OȺQ_B0kҜHcLу Ⱥ̃B0HcL)DI/HM)I9L0.AD$0fA4$DH\?H fHHAHtExLT?H HD)If.HƃHtfDinAD$ffA$,ADt$,IELL$I9H)L9HcL)HL?II9w'HL$H)HD$H+D$ HH9@H)HL)I9HfDA} EAEbMcLt$@LLLC,.IcK4.K|,fD_0HcLH|$@AAAD$.HwFt@:EAQAyAYHcLcLHc?@ HD$ŪLeD$sfDHcHt$@LHMI<Ic־0輗IcA]A.AD0DH|$AH:LD>LD:MD$ HIL)H)׃C1LM9r(0.A)I|$0fA$McL.HcK|<Ht$@蜗D)HS(H=J H5U1:tttftH5J 1L1"H5LH1ΦiHH LfDAWIIAVAUATUSHH8LbdH%(HD$(1I,$Ml$Mt$(HtB@_H%HH$u EAx,A@LA@HqHH1HE1LL$AxHF H{H98H/=HHE HJH9 It$HHI}HEH9EHU :HEI}lLLH1HL$(dH3 %(VH8[]A\A]A^A_fuoAxHH9AxHUH9UHM ,IL$HEHtHtH$t u tID$EL$DpPEbHx(HELʹH\$LL$HD$#LL$L$HHtrAfDLHLD$$=LD$$ HLD$$IL$LD$$fD= u%HHH;F ;F EuwID$xPtlHx(Ht_HT$H\$HD$=IH9t5HtuHHHHLH5H10HH98F zHHH-H=6衔HEfID$HHp~f.HsHEFf.ID$HHp诳f.HLH2DGfDL蠰K'fDH5E 11HuHHHH $ H $HHHIHPH$B L H H5H81ݐDLHLD$$cHULD$$fD5D HHD覓HI=uLLf= ;陔HHHiHH HD$1D$HE:LH$eH$=u&H1}H襬H5H1Ġ= uIH;C t;C tH5,H1蒠Lf.AWIAVIAUATIUSHHN(HFHiHL$Hn(H@0Ht H9)I IGIvIVHH9IF [ID$IFHp HmE1I_M@HL9~NMID$H0HHI uIG JLLIOI uIGL9HD$ID$(ID$Hp H2IFI9FIV ]IFH[]A\A]A^A_HIvIVH H)H#IV []fIFIl$(H[]A\A]A^A_DIFI9FtFIV ,ID$IFHp HLϯf.HLիLCIFDL萯LIVNfLIFf.LHID$H0HHT$LJIL$(H=A H1H55 L蛠IVfH@ ATUHSHHu'L% L[H@ HtHH11ЍHHDSAH=x 襌H=S 詏H=*A H3A ֎H=Y jH=A H諎H= A H5@ H@ qH51 HbH=@ H胎H= ׍H=@ H@ dH= 踍HH5H@ H< HHH5AHHw@ ҎH=k@ HH5 賍H=L@ H@H5 脍H H=&@ H^H=@ HkH5 όH=? HH5 0H=? 1HPH5s H=? H!H5[ H=? 1HH5G ٌH=? HH5. 躌H=c? 1HZH5 螌H=G? HH5 H=(? 1HߺH5 cH= ? HH5 DH=> 1H$H5 (H=> HH5 H=> 1HH5 H=> HH5 ΋H=w> 1HNH5 貋H=[> HH5n 蓋H=<> 1HSH5_ wH= > 1H7H5O [H=> HH5= 菉H=8< H,H56 pH=< 1HPH5# ԈH=; HH5 EHH5 VH5 HHDHHH5 HHH5 HH5 HψHH5 HtH5 H襈HH5 ƉH H5z H{HH5 蜉HH5P HQHH5rH6H5& H'HH55 HHH5HHH5 HBH5HӇHH5HH5H詇H=2: H=葆H=HBHHLJH=:H9 dH=TH9 QH=H9 >H=H9 +H=~H9 HH=rHj9 HՇH=dHG9 H躇H=dH$9 DžH蟇H=^H9 謅H脇H=gH8 葅HiH=H8 vHNH=H8 [H3H=Hm8 @HH=HJ8 %HH=H'8 HH=H8 HdžH=H7 ԄH謆H=~H7 蹄H葆H=H7 螄HvH7 *t7 e7 TH=O7 rH8 H4[@ HHEH7 HHThe json gem extension was loaded with the stdlib ruby code. You should upgrade rubygems with `gem update --system`0_1_2_3_4_5_6_7_8_9_10111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989900010203040506070809101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899nesting of %ld is too deep. Did you try to serialize objects with circular references?source sequence is illegal/malformed utf-8JSON.generate: UTF-8 string passed as BINARY, this will raise an encoding error in json 3.0can't convert %li to %s (%li #%s gives %li )%li not allowed as object key in JSON@invalid_objectnullfalsetrueon_mixed_keys_hashto_procProcunallocated JSON::State0123456789abcdef%li not allowed in JSONto_sStringmessagejson/commonFragmentExtGeneratorJSON::GeneratorErrorJSON::NestingErrorfrom_stateinitialize_configureinitialize_copyindentindent=spacespace=space_beforespace_before=object_nlobject_nl=array_nlarray_nl=as_jsonas_json=max_nestingmax_nesting=script_safescript_safe?script_safe=escape_slashescape_slash?escape_slash=strictstrict?strict=check_circular?allow_nan?allow_nan=ascii_only?ascii_only=depthdepth=buffer_initial_lengthbuffer_initial_length=generateallow_duplicate_key?GeneratorMethodsObjectto_jsonHashArrayIntegerFloatTrueClassFalseClassNilClassUTF_8Encodingnewencodeallow_nanascii_onlyallow_duplicate_keyjson/ext/generator/stateJSON/Generator/State@^P^^^^^^^^^    #NJd ]xEco#Ƥ~@zZrN vH Tʚ;@B'd Տ<v>ᮺWvU0 r5]JBό-;eUkE=ƚpOܼw kAV<Ѝ,U1(\QFɦqaˋ#w"{mSx@I̮Wζ]y<7VM6OH8oꖐ:%˅tφ* 455*g8P;?Ȅk'DŅ%Οkb}$lۺ_ Xf&ޓ J|l_b%S04`?U&NZ~)p$wt帟ߦ}t_ϛpDk11eU%{?;+*\.Ӓsi$$Icd~̈Po ̼,eXѳ@bx x9?{Η8p\{2~Sh髤8mE"&'O'1cȌ8eްeǃqB]X,iM pd'JwmBk}{x \wyTwś[[=]S5Ȭ\*_F%94›\rξTSܷ1A"Lx\ӛ fS!{Z:0ܵ\S٨Et}<Ol}^I~4@~dBAD b ABD pAB4,x~ADG { DAL ^ AAH PdADG  AAF   AAF u AAI  AAF AAK [ [ [$0DR(<8EDM0q AAG 8hBBD A(G@z (A ABBH 0XEc H g pAD0 AA 5FJ($AADPm AAK <,-FGD A(O (A ABBA (liAAG0D AAA ܊#AZ\AMDA  CBH a ABD G ABF [ CBH G ABF zRx  $k0\FDD G@  AABD 4MTMT4MWMTDMW̒MW TMW8ܓMXPdMThM]~DM]~D,M]~D̖M]~DlM\D Hr F ($EAG X FAD (PDEAG X FAD (|EAG X FAD (EAG X FAD `EG _ DA (EAG g FAE ($EAG g FAE (PEAG c FAI zRx   hh88FAA d FBD j FBF , FAA  FBJ 8 FAA d FBD j FBF 8T РFAA d FBD j FBF 8 FAA d FBD j FBF 8 xFAA c FBE i FBG  L{AJ AH , Bs@ @Eg O \ @Eg O x ,@Eg O  P@Eg O  t@Eg O ( FCK iDN, FAD  ABH `( 7FBA D(D0R (A ABBG B (F ABBC I (C ABBA L BBB E(A0D8Gl 8A0A(B BBBC 8 طFBG D(GPC (A ABBE zRx P$d@L (,BBB G(D0G@ 0A(A BBBJ H FBB E(A0A8Dp 8A0A(B BBBC zRx p('dH 0FBB B(D0G8G 8A0A(B BBBD T` &FHB B(A0A8Gpa 8A0A(B BBBJ  xGk cd FEE B(D0A8DP 8A0A(B BBBI @ 8A0A(B BBBF 4[MAD T t EX tbAI G e,RtADGNU`%@)) 000`.@0!.q  4  o`    0x X ooo0o h  0@P`p 0@P`p 0@P`p 0@P`pGA$3a1( GA$3p1113 "4GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realignGA$3a1(AGA+omit_frame_pointer ";"GA+stack_clashGA!stack_realign GA*GOW*GA*cf_protection GA*FORTIFY "[.GA+GLIBCXX_ASSERTIONSGA* ";"GA*GA*GA!generator.so-4.0.5-3.el8.x86_64.debug07zXZִF!t//V]?Eh=ڊ2N.n0.nFp:sJπEXMfdR }WF:s2ڷܒ7 tqڢ4C9pdppѰ ekB^\,htųMrK! ?{ǡ\4.X"A"nhW#1J*$ (J[ 揮CHp+UDZ~P}wΠF WcJ$Z֯zdY,i@G\=7!u&5w?_j 6(8 sBW*H&n)@5j-~|,sﺅ^#u\-jr0SUf=ԍt!/0/[ "Cfs71͛E?yn@i-CwSވΒV%Jj8|'56<q'~J`nN6"2 =&ba>ۭCL*S&K7O5M^B2[EhSc kNbC%U۝TceIb1'gŏYR5ǽR~{T}F gC 滫 η)*72ٳf(ꍫD 9#,ߢʖjf/Qd΋G.h/p.h͆kgh{A4OBpJ/}դud_ ZWA/Ɨׯ&{"TV^C)u]#64}ܩp;vCC%bs{KƠ )oo];aP)d@r7Y$NJ- 7$Ӏ>ۇAKE Fo Մ_ LqEPs 퀷:‍Vj<_p텉g墾,/i_NGlx%cp aWn;wn$3L0%XVj\bnHkld !nDMOp z; N-}j_oؾʻeЍ LS&5r~ aėotMh5ƾu)>D0Cpd4nn9uz#I,@l@4)7*Tρ.OKSFA:>k[:`} %0/` 㑚(/FP,Ѩ.sC7yo rYO|Q`T&O(zYJzm~I'fhq=dɦ2Ho;ġk-`۞E<+MtqPꪧh[ӥ/6w(hEPf!Tvkj3,٢ `X¢8mz5htJ ;`ǼvO&:Ky͓_?b7w0 ^ppnGon^3'QdiR>*\^.yLLzsxPDoaG38 KZ\//rc)9R U,>bٮ_-XM)([:>TgYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 0 8o00Eo@T  X^Bxx0hc0n w " "y}44 `` hhHH    h h hh h (0 (H`(t ,`+PK!#io-console-0.8.2/gem.build_completenu[PK!cPsPsio-console-0.8.2/io/console.sonuȯELF>%@l@8 @xZxZ ]] ] x ]] ] 888$$XZXZXZ StdXZXZXZ PtdNNNQtdRtd]] ] GNUA$ /ܭ=(6@[H!@[]_BE|qX/Do=8s/ D/Wp \yMUI7 !1QFA"R"hj`zcW3, k"F"rb Rb b d PF K__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizerb_check_typeddatacfmakerawrb_data_typed_object_zallocrb_default_rsrb_io_writerb_funcallvrb_io_descriptorisattyttyname_rrb_errno_ptrrb_str_new_staticrb_str_resizerb_str_capacitystrlenrb_str_to_interned_strrb_interned_str_cstrrb_sprintfrb_syserr_new_strrb_exc_raise__stack_chk_failtcsetattrrb_num2uintrb_io_get_write_iorb_str_new_cstrrb_io_flushrb_io_getbyterb_ary_newrb_ary_pushrb_str_newtcgetattrrb_io_pathtcflushrb_Arrayioctlrb_eArgErrorrb_raiserb_string_value_cstrrb_ensurerb_stdinrb_stderrrb_error_arityrb_jump_tagrb_protectrb_syserr_failrb_io_getsrb_yieldrb_str_catfrb_convert_typerb_assoc_newrb_cIOrb_cFilerb_ractor_local_storage_value_lookuprb_ractor_local_storage_value_setrb_id2symrb_check_idrb_keyword_given_prb_funcallv_kwrb_io_closed_prb_unexpected_typerb_obj_freezerb_cloexec_openrb_io_open_descriptorrb_io_closerb_fix2intrb_num2intrb_check_funcallrb_get_kwargsrb_funcallv_publicrb_hash_duprb_ary_resizerb_ary_ptr_use_startrb_ary_ptr_use_endrb_obj_classInitVM_consolerb_f_notimplementrb_define_module_underrb_cObjectrb_define_class_underrb_define_constrb_define_alloc_funcrb_undef_methodInit_consolerb_ext_ractor_saferb_ractor_local_storage_value_newkeyrb_internrb_define_methodrb_define_singleton_methodlibruby.so.4.0libm.so.6libpthread.so.0libc.so.6_edata__bss_startGLIBC_2.2.5GLIBC_2.4/opt/alt/ruby40/lib64 ui ii ui ] 0&] % ]  ] @] 2N_ _  _  _ _ $_ *_ +_ 8_ A_ P_ S_ T_ U_ Z`  ` (` 0` 8` @` H` P`  X`  ``  h` p` x` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `  ` !a "a #a %a & a '(a (0a )8a ,@a -Ha .Pa /Xa 0`a 1ha 2pa 3xa 4a 5a 6a 7a 9a :a ;a <a =a >a ?a @a Ba Ca Da Ea Fb Gb Hb ^b I b J(b K0b L8b M@b NHb OPb QXb R`b Uhb Vpb Wxb Xb YHHD HtH5RD %SD hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?h@hAhBhChDhEhFhGqhHahIQhJAhK1hL!hM%m? D%e? D%]? D%U? D%M? D%E? D%=? D%5? D%-? D%%? D%? D%? D% ? D%? D%> D%> D%> D%> D%> D%> D%> D%> D%> D%> D%> D%> D%> D%> D%> D%> D%}> D%u> D%m> D%e> D%]> D%U> D%M> D%E> D%=> D%5> D%-> D%%> D%> D%> D% > D%> D%= D%= D%= D%= D%= D%= D%= D%= D%= D%= D%= D%= D%= D%= D%= D%= D%}= D%u= D%m= D%e= D%]= D%U= D%M= D%E= D%== D%5= D%-= D%%= D%= D%= D% = D%= DH== H< H9tH9 Ht H=< H5< H)HHH?HHtH9 HtfD=< u+UH=9 Ht H=7 dm< ]wH"O {H g HHwH ff.@UHH56 SHHHtH xHH[]D` HH[]f.ATIH5P6 UHSLH5<6 HooHKoP S HP0HS0@8C8H[]A\DUHSHHC ωC Ht.UxSUxSUtC HH H[]H5 <ff.SHx5 H<kfoHP foKJfoS R HK0HJ0K8J8[ff.H7 H0ff.fH5: 11ff.HH5: H׉ffDH5u: 11Lff.AVAUATUSHdH%(H$1EA{HDHD A"1HLp,kD A"H4H?HMHE tLeHLDHH uLOHHHH$dH3 %(uTH[]A\A]A^fHfDDH='"1DH}HuUSHH {8u&1Hډ*uH[]f.H1[]SHHH=!p1_HHtH[ff.@ATIUHHS:LH/SH=a!p1 HH H[]A\AUATUSHH(dH%(HD$1H~Hu)HL$dH3 %(4H([]A\A]@@uHH uHDnHt$Ht$HHDHHyH E1HH7sH{H=_1IDHXHt+H ;tEPЃ w-THߍlP-HuHL Et#A9uE1롐HcLHt-1^@HcLD$Ht-DH|$ff.AUIATUSHHXdH%(HD$H1ItLljuMD$ Iu7D$ L6t+HT$HdH3%(Hu9HX[]A\A]@xD$ Hߋ(HƉ^HVATUSHHPdH%(HD$H1ILlju@LH"L$ {H $tHT$HdH3%(Hu*HP[]A\Hߋ(zHƉH3ATUSH@HA%H-t0A9t)1D'u,uH[]A\DtbHߋ(HƉ.H&fDAWAVAUATUSHHHdH%(HD$13H HHJHHL8LhAHuL`HhH3H;H$A1ItLf$1ItLfD$1ItLfD$1HtHfD$H1TDKuYHL$dH3 %(HugH[]A\A]A^A_DHPHJHu H@ HW0 H5H81^Hߋ(oHƉH(HH53 dH%(HD$1H/ HHH$HD$dH3%(uHSHdH%(HD$1HHtHHH$H4$HHD$dH3%(uH[|ff.AUATAUSHHIHXHH9tXAu HL_H7HHHJH=#HtHHD$HD$H[]A\A]H. H9(uH. H됺1@SHH=1ƃS)1}H[HAUIATIUSHHXdH%(HD$H11uDHC0oLoKoS HD$0C8H)$H)L$)T$ D$8AHމ.HT$HdH3%(u HX[]A\A]f.AWMAVIAUE1ATUHSHHt$HT$dH%(H$1D$,0HHAău0D$,A|$,@HD$0HD$Ht$LLDH<AD$,D9AA!Ht$H|$HT$,IǃtH 9EfHHD9MHt$lD8fH$dH3 %(LbHĸ[]A\A]A^A_@HD$0LLHƉHD$HD$,LHTAă 9Dl$,EtnH.9tAE1@Ht$uD(D$,1DfDcD(DE1DE1;T$,E1AD(rAE1AqfDHD$0HD$Ht$Z]D(D$,EMLDl$,EiH)9E1AE1H5* E1H [HH5* E1H ;HH5}* E1H HAUATIH=U1SHAIŅt&LH51)ƒA1dt$؉H5jL1ÃC)1RuL"HjHLHIHH.AT$HHcHTHHUHHcHTHPfHHSHFAAUATUH1SHhdH%(HD$X1HL$H\$>HI#HމAFu8LHGHDtHT$XdH3%(Hu,Hh[]A\A]UHHƉ!H@SH1H dH%(HD$1HL$ H59 HHIH \HT$dH3%(uH [1SH1H dH%(HD$1HL$ 8HH ^HIH5HT$dH3%(uH [ATIH5  UHSHH`dH%(HD$X1]HL$LoH\$)D$oH)L$ oP )T$0HP0HT$@@81҉D$HHHHHHHL$XdH3 %(u H`[]A\ff.AUIH5` ATAHUSHH(dH%(HD$11HL$ LDHHHHT$dH3%(uH(H[]A\A]UHH5SHHL H;TH;HH59H;1HH5!H;1HUH5 H;HH5H;HoH5H;1HWH5H;1HH5H;HH5wH;1HH5mpH;1HH5\XH;HH5I=H;1HqH5:%H;1HH5* H;1HH5H;1HH5H;H~H5H;1HH5H;HH5H;HH5tH;HH5YH;HH5>H;HH5#H;HH5tH;HH5eH;HnH5UH;HH5GH;HH5;H;1H`H53H-5 H;H5%HfH;H1H5RH;HH57H;1HH5H;H H5H;H5%HiH5HHHHHH5H} H;H5H#H=Hh kHH=T H5HH=> H5/JH=+ H5egH= HDH5Q(H= HH5 H= HH5H= H[HH5~]DH)H=Hk H=H sH=H `H=Hj MH=HO :H=HT 'H=H  H=qH H=cH H HHHttyname_r(%d)[%dG[%d;%dH[%d%cto_aryArrayexpected 2D coordinate/dev/ttywrong %s mode: %li screen erase[%dJline erase[%dKrawraw!cookedcooked!getchecho=echo?console_modeconsole_mode=noechowinsizewinsize=iflushioflushbeepgotocursorcursor=cursor_upcursor_downcursor_leftcursor_rightgoto_columnerase_lineerase_screenscroll_forwardscroll_backwardclear_screenpressed?check_winsize_changedgetpassttynameconsolegeneric_readableConsoleMode0.8.2VERSIONinitializeinitialize_copygetcgetschomp!closemintimeintr__send__console-modewrong number of arguments (given %ld, expected 2 or 4)true or false expected as intr: %li ;? H`t8$8hTh|H8(dh@hx$H`HhH$HhH(h 08d(h( h8 X (| ( h h@ t  h (, h h zRx $FJ w?:*3$"D\0p< 80DFEKG V DAF HDA(`[FKD BAB$XEDG EAA 4BA@P dx$0@<`FBB A(A0G 0A(A BBBJ 0XIACG c FAK DCAt1Ek(4HFDG sAB8`FBA A(GP| (A ABBE 8FEA A(Ga (A ABBE 0FAA Gpc  AABA , FAA I ABD H<PxFBB B(A0A8JP 8A0A(B BBBF PD F A TAD H AA 8FBD A(D@m (A ABBD h/Cd8 |BED C(Gu (A ABBA L\BEE E(A0D8GT 8A0A(B BBBE 4BBK E(F0i(D ABB EB I O L D*ADD d:El A (fEDDpI AAA eEG`J AA L2Ed A p'EY A yEG ^ AA 0,FAD Gp  AABH 8`FED C(FPw (A ABBK 7Eb I 7Ed G :EX C Y:EX C Y<EX C [4(<EX C [ THwED ` AA 0xHDC U ABI P<Ev$)Ec8<Ev8\BBA C(G` (A ABBB 0< FHA IP  AABD 8p|FBA F(Dl (A ABBA _EI0J AA ,_EI0J AA 0hFKD I  AABA 8( yFLG A(GPI (D ABBA (d 8ETD FO HGNU0&% ] 2N!m|  K] ] o`   ` P8 o8ooxo]  0@P`p 0@P`p 0@P`p 0@P`p  0 @ P ` p GA$3a1K GA$3p1113@&KGA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFY@&Y&GA+GLIBCXX_ASSERTIONSconsole.so-4.0.5-3.el8.x86_64.debug?7zXZִF!t/]?Eh=ڊ2NR~ ( gz~Xo/ДlZ҇?DTc3OaM@߶:`}Ղg[I=1 ɊR,G?ۀ0*i=Y_Q zh"},/# t˽ M N`ӡ /~%7T3N"tUp:#T%K@A$X4g},bPA]G2;sa(Jqas_ e.JTT8BMA}Ky)]D?sqE%O(]V6!h9??aGudɅg4hyZdGmv:oŕ$x]]i; Գ7KY:ȊBZ+gjJ@OQJˏҲy!7BOZֽ,NBr$"3>f sc}L D;0) +-jMQi4;ߊ#NIolty=:o7Fvgo 2A#f3)d+F$+c<.pnC91[NF[pV]f1f8~IRD-KL#[SбߤM59))Sޯ0S¹#:UmµAw7~ 텽y˕^P7)6߱Q.|419h,[юdput}UD]j%ѵz q9|/nǡ1ڇxr ֜IL=5z'+wѲ~ۅfư $,1UF)_+bqy;*70kGZyހ}"0̼.?VmT We*趽Ѝ Q:e |Q"aUAb]EG扊A;b7ⴍbi)r\UH~W՚i0Qg\\(}=`\)+(P Vx-v"oBcZ1 0^#B/'u'd1,`?BkU䍧xSYQ-vX(},}ރ- 'ӵS gFڥőB,7q SbHAsg1 '&C͎JZPoi8h{ S[6:je5[qpDJ;QWQ ]Aҳc*3 e6(& Zeߒ 1b]бgYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``8(  0 8oxxEo88PT^B88Phcn w%%b&}KK KKNNPP XZXZ ] ]] ] ] ]h ] ]_ _p` `b bhb`bH d(dj+PK!cmYaaractor.hnu[#ifndef RUBY_RACTOR_H #define RUBY_RACTOR_H 1 /** * @file * @author Koichi Sasada * @date Tue Nov 17 16:39:15 2020 * @copyright Copyright (C) 2020 Yukihiro Matsumoto * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. */ struct rb_ractor_local_storage_type { void (*mark)(void *ptr); void (*free)(void *ptr); // TODO: update }; typedef struct rb_ractor_local_key_struct *rb_ractor_local_key_t; RUBY_SYMBOL_EXPORT_BEGIN RUBY_EXTERN VALUE rb_cRactor; VALUE rb_ractor_stdin(void); VALUE rb_ractor_stdout(void); VALUE rb_ractor_stderr(void); void rb_ractor_stdin_set(VALUE); void rb_ractor_stdout_set(VALUE); void rb_ractor_stderr_set(VALUE); rb_ractor_local_key_t rb_ractor_local_storage_value_newkey(void); VALUE rb_ractor_local_storage_value(rb_ractor_local_key_t key); bool rb_ractor_local_storage_value_lookup(rb_ractor_local_key_t key, VALUE *val); void rb_ractor_local_storage_value_set(rb_ractor_local_key_t key, VALUE val); RUBY_EXTERN const struct rb_ractor_local_storage_type rb_ractor_local_storage_type_free; #define RB_RACTOR_LOCAL_STORAGE_TYPE_FREE (&rb_ractor_local_storage_type_free) rb_ractor_local_key_t rb_ractor_local_storage_ptr_newkey(const struct rb_ractor_local_storage_type *type); void *rb_ractor_local_storage_ptr(rb_ractor_local_key_t key); void rb_ractor_local_storage_ptr_set(rb_ractor_local_key_t key, void *ptr); VALUE rb_ractor_make_shareable(VALUE obj); VALUE rb_ractor_make_shareable_copy(VALUE obj); RUBY_SYMBOL_EXPORT_END #define RB_OBJ_SHAREABLE_P(obj) FL_TEST_RAW((obj), RUBY_FL_SHAREABLE) static inline bool rb_ractor_shareable_p(VALUE obj) { bool rb_ractor_shareable_p_continue(VALUE obj); if (SPECIAL_CONST_P(obj)) { return true; } else if (RB_OBJ_SHAREABLE_P(obj)) { return true; } else { return rb_ractor_shareable_p_continue(obj); } } #endif /* RUBY_RACTOR_H */ PK!Mthread.hnu[#ifndef RUBY_THREAD_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_THREAD_H 1 /** * @file * @author $Author: matz $ * @date Tue Jul 10 17:35:43 JST 2012 * @copyright Copyright (C) 2007 Yukihiro Matsumoto * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. */ #include "ruby/intern.h" #include "ruby/internal/dllexport.h" /* flags for rb_nogvl */ #define RB_NOGVL_INTR_FAIL (0x1) #define RB_NOGVL_UBF_ASYNC_SAFE (0x2) RBIMPL_SYMBOL_EXPORT_BEGIN() void *rb_thread_call_with_gvl(void *(*func)(void *), void *data1); void *rb_thread_call_without_gvl(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2); void *rb_thread_call_without_gvl2(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2); /* * XXX: unstable/unapproved - out-of-tree code should NOT not depend * on this until it hits Ruby 2.6.1 */ void *rb_nogvl(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2, int flags); #define RUBY_CALL_WO_GVL_FLAG_SKIP_CHECK_INTS_AFTER 0x01 #define RUBY_CALL_WO_GVL_FLAG_SKIP_CHECK_INTS_ RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_THREAD_H */ PK!5>3>3config-x86_64.hnu[#ifndef INCLUDE_RUBY_CONFIG_H #define INCLUDE_RUBY_CONFIG_H 1 /* confdefs.h */ #define STDC_HEADERS 1 #define HAVE_SYS_TYPES_H 1 #define HAVE_SYS_STAT_H 1 #define HAVE_STDLIB_H 1 #define HAVE_STRING_H 1 #define HAVE_MEMORY_H 1 #define HAVE_STRINGS_H 1 #define HAVE_INTTYPES_H 1 #define HAVE_STDINT_H 1 #define HAVE_UNISTD_H 1 #define __EXTENSIONS__ 1 #define _ALL_SOURCE 1 #define _GNU_SOURCE 1 #define _POSIX_PTHREAD_SEMANTICS 1 #define _TANDEM_SOURCE 1 #define RUBY_SYMBOL_EXPORT_BEGIN _Pragma("GCC visibility push(default)") #define RUBY_SYMBOL_EXPORT_END _Pragma("GCC visibility pop") #define HAVE_STMT_AND_DECL_IN_EXPR 1 #define HAVE_LIBCRYPT 1 #define HAVE_LIBDL 1 #define HAVE_DIRENT_H 1 #define HAVE__BOOL 1 #define HAVE_STDBOOL_H 1 #define HAVE_SYS_WAIT_H 1 #define HAVE_A_OUT_H 1 #define HAVE_GRP_H 1 #define HAVE_FCNTL_H 1 #define HAVE_FLOAT_H 1 #define HAVE_LANGINFO_H 1 #define HAVE_LIMITS_H 1 #define HAVE_LOCALE_H 1 #define HAVE_MALLOC_H 1 #define HAVE_PWD_H 1 #define HAVE_SANITIZER_ASAN_INTERFACE_H 1 #define HAVE_STDALIGN_H 1 #define HAVE_SYS_EVENTFD_H 1 #define HAVE_SYS_FCNTL_H 1 #define HAVE_SYS_FILE_H 1 #define HAVE_SYS_IOCTL_H 1 #define HAVE_SYS_PARAM_H 1 #define HAVE_SYS_PRCTL_H 1 #define HAVE_SYS_RESOURCE_H 1 #define HAVE_SYS_SELECT_H 1 #define HAVE_SYS_SENDFILE_H 1 #define HAVE_SYS_SOCKET_H 1 #define HAVE_SYS_SYSCALL_H 1 #define HAVE_SYS_SYSMACROS_H 1 #define HAVE_SYS_TIME_H 1 #define HAVE_SYS_TIMES_H 1 #define HAVE_SYS_UIO_H 1 #define HAVE_SYSCALL_H 1 #define HAVE_TIME_H 1 #define HAVE_UCONTEXT_H 1 #define HAVE_UTIME_H 1 #define HAVE_X86INTRIN_H 1 #define HAVE_GMP_H 1 #define HAVE_LIBGMP 1 #define HAVE_TYPEOF 1 #define restrict __restrict #define HAVE_LONG_LONG 1 #define HAVE_OFF_T 1 #define SIZEOF_INT 4 #define SIZEOF_SHORT 2 #define SIZEOF_LONG 8 #define SIZEOF_LONG_LONG 8 #define SIZEOF___INT64 0 #define SIZEOF___INT128 16 #define SIZEOF_OFF_T 8 #define SIZEOF_VOIDP 8 #define SIZEOF_FLOAT 4 #define SIZEOF_DOUBLE 8 #define SIZEOF_TIME_T 8 #define SIZEOF_CLOCK_T 8 #define PACKED_STRUCT(x) x __attribute__((packed)) #define USE_UNALIGNED_MEMBER_ACCESS 1 #define PRI_LL_PREFIX "ll" #define HAVE_PID_T 1 #define rb_pid_t pid_t #define SIGNEDNESS_OF_PID_T -1 #define PIDT2NUM(v) INT2NUM(v) #define NUM2PIDT(v) NUM2INT(v) #define PRI_PIDT_PREFIX PRI_INT_PREFIX #define HAVE_UID_T 1 #define rb_uid_t uid_t #define SIGNEDNESS_OF_UID_T +1 #define UIDT2NUM(v) UINT2NUM(v) #define NUM2UIDT(v) NUM2UINT(v) #define PRI_UIDT_PREFIX PRI_INT_PREFIX #define HAVE_GID_T 1 #define rb_gid_t gid_t #define SIGNEDNESS_OF_GID_T +1 #define GIDT2NUM(v) UINT2NUM(v) #define NUM2GIDT(v) NUM2UINT(v) #define PRI_GIDT_PREFIX PRI_INT_PREFIX #define HAVE_TIME_T 1 #define rb_time_t time_t #define SIGNEDNESS_OF_TIME_T -1 #define TIMET2NUM(v) LONG2NUM(v) #define NUM2TIMET(v) NUM2LONG(v) #define PRI_TIMET_PREFIX PRI_LONG_PREFIX #define HAVE_DEV_T 1 #define rb_dev_t dev_t #define SIGNEDNESS_OF_DEV_T +1 #define DEVT2NUM(v) ULONG2NUM(v) #define NUM2DEVT(v) NUM2ULONG(v) #define PRI_DEVT_PREFIX PRI_LONG_PREFIX #define HAVE_MODE_T 1 #define rb_mode_t mode_t #define SIGNEDNESS_OF_MODE_T +1 #define MODET2NUM(v) UINT2NUM(v) #define NUM2MODET(v) NUM2UINT(v) #define PRI_MODET_PREFIX PRI_INT_PREFIX #define HAVE_RLIM_T 1 #define rb_rlim_t rlim_t #define SIGNEDNESS_OF_RLIM_T +1 #define RLIM2NUM(v) ULONG2NUM(v) #define NUM2RLIM(v) NUM2ULONG(v) #define PRI_RLIM_PREFIX PRI_LONG_PREFIX #define HAVE_OFF_T 1 #define rb_off_t off_t #define SIGNEDNESS_OF_OFF_T -1 #define OFFT2NUM(v) LONG2NUM(v) #define NUM2OFFT(v) NUM2LONG(v) #define PRI_OFFT_PREFIX PRI_LONG_PREFIX #define HAVE_CLOCKID_T 1 #define rb_clockid_t clockid_t #define SIGNEDNESS_OF_CLOCKID_T -1 #define CLOCKID2NUM(v) INT2NUM(v) #define NUM2CLOCKID(v) NUM2INT(v) #define PRI_CLOCKID_PREFIX PRI_INT_PREFIX #define HAVE_VA_ARGS_MACRO 1 #define HAVE__ALIGNOF 1 #define CONSTFUNC(x) __attribute__ ((__const__)) x #define PUREFUNC(x) __attribute__ ((__pure__)) x #define NORETURN(x) __attribute__ ((__noreturn__)) x #define DEPRECATED(x) __attribute__ ((__deprecated__)) x #define DEPRECATED_BY(n,x) __attribute__ ((__deprecated__("by "#n))) x #define NOINLINE(x) __attribute__ ((__noinline__)) x #define ALWAYS_INLINE(x) __attribute__ ((__always_inline__)) x #define NO_SANITIZE(san, x) __attribute__ ((__no_sanitize__(san))) x #define NO_SANITIZE_ADDRESS(x) __attribute__ ((__no_sanitize_address__)) x #define NO_ADDRESS_SAFETY_ANALYSIS(x) __attribute__ ((__no_address_safety_analysis__)) x #define WARN_UNUSED_RESULT(x) __attribute__ ((__warn_unused_result__)) x #define MAYBE_UNUSED(x) __attribute__ ((__unused__)) x #define ERRORFUNC(mesg,x) __attribute__ ((__error__ mesg)) x #define WARNINGFUNC(mesg,x) __attribute__ ((__warning__ mesg)) x #define WEAK(x) __attribute__ ((__weak__)) x #define HAVE_FUNC_WEAK 1 #define RUBY_CXX_DEPRECATED(msg) __attribute__((__deprecated__(msg))) #define HAVE_NULLPTR 1 #define FUNC_UNOPTIMIZED(x) __attribute__ ((__optimize__("O0"))) x #define FUNC_MINIMIZED(x) __attribute__ ((__optimize__("-Os","-fomit-frame-pointer"))) x #define HAVE_ATTRIBUTE_FUNCTION_ALIAS 1 #define RUBY_ALIAS_FUNCTION_TYPE(type, prot, name, args) type prot __attribute__((alias(#name))); #define RUBY_ALIAS_FUNCTION_VOID(prot, name, args) RUBY_ALIAS_FUNCTION_TYPE(void, prot, name, args) #define HAVE_GCC_ATOMIC_BUILTINS 1 #define HAVE_GCC_SYNC_BUILTINS 1 #define UNREACHABLE __builtin_unreachable() #define RUBY_FUNC_EXPORTED __attribute__ ((__visibility__("default"))) extern #define RUBY_FUNC_NONNULL(n,x) __attribute__ ((__nonnull__(n))) x #define RUBY_FUNCTION_NAME_STRING __func__ #define ENUM_OVER_INT 1 #define HAVE_DECL_SYS_NERR 1 #define HAVE_DECL_GETENV 1 #define SIZEOF_SIZE_T 8 #define SIZEOF_PTRDIFF_T 8 #define PRI_SIZE_PREFIX "z" #define PRI_PTRDIFF_PREFIX "t" #define HAVE_STRUCT_STAT_ST_BLKSIZE 1 #define HAVE_STRUCT_STAT_ST_BLOCKS 1 #define HAVE_STRUCT_STAT_ST_RDEV 1 #define SIZEOF_STRUCT_STAT_ST_SIZE SIZEOF_OFF_T #define SIZEOF_STRUCT_STAT_ST_BLOCKS SIZEOF_OFF_T #define SIZEOF_STRUCT_STAT_ST_INO SIZEOF_LONG #define HAVE_STRUCT_STAT_ST_ATIM 1 #define HAVE_STRUCT_STAT_ST_MTIM 1 #define HAVE_STRUCT_STAT_ST_CTIM 1 #define HAVE_STRUCT_STATX_STX_BTIME 1 #define HAVE_STRUCT_TIMEVAL 1 #define SIZEOF_STRUCT_TIMEVAL_TV_SEC SIZEOF_TIME_T #define HAVE_STRUCT_TIMESPEC 1 #define HAVE_STRUCT_TIMEZONE 1 #define HAVE_RB_FD_INIT 1 #define HAVE_INT8_T 1 #define SIZEOF_INT8_T 1 #define HAVE_UINT8_T 1 #define SIZEOF_UINT8_T 1 #define HAVE_INT16_T 1 #define SIZEOF_INT16_T 2 #define HAVE_UINT16_T 1 #define SIZEOF_UINT16_T 2 #define HAVE_INT32_T 1 #define SIZEOF_INT32_T 4 #define HAVE_UINT32_T 1 #define SIZEOF_UINT32_T 4 #define HAVE_INT64_T 1 #define SIZEOF_INT64_T 8 #define HAVE_UINT64_T 1 #define SIZEOF_UINT64_T 8 #define HAVE_INT128_T 1 #define int128_t __int128 #define SIZEOF_INT128_T SIZEOF___INT128 #define HAVE_UINT128_T 1 #define uint128_t unsigned __int128 #define SIZEOF_UINT128_T SIZEOF___INT128 #define HAVE_INTPTR_T 1 #define SIZEOF_INTPTR_T 8 #define HAVE_UINTPTR_T 1 #define SIZEOF_UINTPTR_T 8 #define HAVE_SSIZE_T 1 #define SIZEOF_SSIZE_T 8 #define STACK_END_ADDRESS __libc_stack_end #define GETGROUPS_T gid_t #define HAVE_ALLOCA_H 1 #define HAVE_ALLOCA 1 #define HAVE_ACOSH 1 #define HAVE_CBRT 1 #define HAVE_CRYPT 1 #define HAVE_DUP2 1 #define HAVE_ERF 1 #define HAVE_EXPLICIT_BZERO 1 #define HAVE_FFS 1 #define HAVE_FLOCK 1 #define HAVE_HYPOT 1 #define HAVE_LGAMMA_R 1 #define HAVE_MEMMOVE 1 #define HAVE_NAN 1 #define HAVE_NEXTAFTER 1 #define HAVE_STRCHR 1 #define HAVE_STRERROR 1 #define HAVE_STRSTR 1 #define HAVE_TGAMMA 1 #define HAVE_FINITE 1 #define HAVE_ISINF 1 #define HAVE_ISNAN 1 #define SPT_TYPE SPT_REUSEARGV #define HAVE_SIGNBIT 1 #define HAVE_FORK 1 #define HAVE_VFORK 1 #define HAVE_WORKING_VFORK 1 #define HAVE_WORKING_FORK 1 #define HAVE__LONGJMP 1 #define HAVE_ATAN2L 1 #define HAVE_ATAN2F 1 #define HAVE_CHROOT 1 #define HAVE_CLOCK_GETTIME 1 #define HAVE_COPY_FILE_RANGE 1 #define HAVE_COSH 1 #define HAVE_CRYPT_R 1 #define HAVE_DIRFD 1 #define HAVE_DL_ITERATE_PHDR 1 #define HAVE_DLOPEN 1 #define HAVE_DLADDR 1 #define HAVE_DUP 1 #define HAVE_DUP3 1 #define HAVE_EACCESS 1 #define HAVE_ENDGRENT 1 #define HAVE_EVENTFD 1 #define HAVE_FCHMOD 1 #define HAVE_FCHOWN 1 #define HAVE_FCNTL 1 #define HAVE_FDATASYNC 1 #define HAVE_FDOPENDIR 1 #define HAVE_FMOD 1 #define HAVE_FSTATAT 1 #define HAVE_FSYNC 1 #define HAVE_FTRUNCATE 1 #define HAVE_FTRUNCATE64 1 #define HAVE_GETCWD 1 #define HAVE_GETGRNAM 1 #define HAVE_GETGRNAM_R 1 #define HAVE_GETGROUPS 1 #define HAVE_GETLOGIN 1 #define HAVE_GETLOGIN_R 1 #define HAVE_GETPGID 1 #define HAVE_GETPGRP 1 #define HAVE_GETPRIORITY 1 #define HAVE_GETPWNAM 1 #define HAVE_GETPWNAM_R 1 #define HAVE_GETPWUID 1 #define HAVE_GETPWUID_R 1 #define HAVE_GETRANDOM 1 #define HAVE_GETRESGID 1 #define HAVE_GETRESUID 1 #define HAVE_GETRLIMIT 1 #define HAVE_GETSID 1 #define HAVE_GETTIMEOFDAY 1 #define HAVE_GMTIME_R 1 #define HAVE_GRANTPT 1 #define HAVE_INITGROUPS 1 #define HAVE_IOCTL 1 #define HAVE_KILLPG 1 #define HAVE_LCHOWN 1 #define HAVE_LINK 1 #define HAVE_LLABS 1 #define HAVE_LOCKF 1 #define HAVE_LOG2 1 #define HAVE_LSTAT 1 #define HAVE_LUTIMES 1 #define HAVE_MALLOC_USABLE_SIZE 1 #define HAVE_MBLEN 1 #define HAVE_MEMALIGN 1 #define HAVE_WRITEV 1 #define HAVE_MEMRCHR 1 #define HAVE_MEMMEM 1 #define HAVE_MKFIFO 1 #define HAVE_MKNOD 1 #define HAVE_MKTIME 1 #define HAVE_OPENAT 1 #define HAVE_PIPE2 1 #define HAVE_POLL 1 #define HAVE_POSIX_FADVISE 1 #define HAVE_POSIX_MEMALIGN 1 #define HAVE_PPOLL 1 #define HAVE_PREAD 1 #define HAVE_PWRITE 1 #define HAVE_QSORT_R 1 #define HAVE_READLINK 1 #define HAVE_REALPATH 1 #define HAVE_ROUND 1 #define HAVE_SCHED_GETAFFINITY 1 #define HAVE_SEEKDIR 1 #define HAVE_SENDFILE 1 #define HAVE_SETEGID 1 #define HAVE_SETENV 1 #define HAVE_SETEUID 1 #define HAVE_SETGID 1 #define HAVE_SETGROUPS 1 #define HAVE_SETPGID 1 #define HAVE_SETPGRP 1 #define HAVE_SETREGID 1 #define HAVE_SETRESGID 1 #define HAVE_SETRESUID 1 #define HAVE_SETREUID 1 #define HAVE_SETRLIMIT 1 #define HAVE_SETSID 1 #define HAVE_SETUID 1 #define HAVE_SHUTDOWN 1 #define HAVE_SIGACTION 1 #define HAVE_SIGALTSTACK 1 #define HAVE_SIGPROCMASK 1 #define HAVE_SINH 1 #define HAVE_SYMLINK 1 #define HAVE_SYSCALL 1 #define HAVE_SYSCONF 1 #define HAVE_TANH 1 #define HAVE_TELLDIR 1 #define HAVE_TIMEGM 1 #define HAVE_TIMES 1 #define HAVE_TRUNCATE 1 #define HAVE_TRUNCATE64 1 #define HAVE_UNSETENV 1 #define HAVE_UTIMENSAT 1 #define HAVE_UTIMES 1 #define HAVE_WAIT4 1 #define HAVE_WAITPID 1 #define HAVE_STATX 1 #define HAVE_CRYPT_H 1 #define HAVE_STRUCT_CRYPT_DATA_INITIALIZED 1 #define HAVE_BUILTIN___BUILTIN_ALLOCA_WITH_ALIGN 1 #define HAVE_BUILTIN___BUILTIN_ASSUME_ALIGNED 1 #define HAVE_BUILTIN___BUILTIN_BSWAP16 1 #define HAVE_BUILTIN___BUILTIN_BSWAP32 1 #define HAVE_BUILTIN___BUILTIN_BSWAP64 1 #define HAVE_BUILTIN___BUILTIN_POPCOUNT 1 #define HAVE_BUILTIN___BUILTIN_POPCOUNTLL 1 #define HAVE_BUILTIN___BUILTIN_CLZ 1 #define HAVE_BUILTIN___BUILTIN_CLZL 1 #define HAVE_BUILTIN___BUILTIN_CLZLL 1 #define HAVE_BUILTIN___BUILTIN_CTZ 1 #define HAVE_BUILTIN___BUILTIN_CTZLL 1 #define HAVE_BUILTIN___BUILTIN_ADD_OVERFLOW 1 #define HAVE_BUILTIN___BUILTIN_SUB_OVERFLOW 1 #define HAVE_BUILTIN___BUILTIN_MUL_OVERFLOW 1 #define HAVE_BUILTIN___BUILTIN_MUL_OVERFLOW_P 1 #define HAVE_BUILTIN___BUILTIN_CONSTANT_P 1 #define HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR 1 #define HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P 1 #define HAVE_BUILTIN___BUILTIN_TYPES_COMPATIBLE_P 1 #define HAVE_BUILTIN___BUILTIN_TRAP 1 #define HAVE_GNU_QSORT_R 1 #define ATAN2_INF_C99 1 #define HAVE_CLOCK_GETRES 1 #define HAVE_LIBRT 1 #define HAVE_LIBRT 1 #define HAVE_TIMER_CREATE 1 #define HAVE_TIMER_SETTIME 1 #define HAVE_STRUCT_TM_TM_ZONE 1 #define HAVE_TM_ZONE 1 #define HAVE_STRUCT_TM_TM_GMTOFF 1 #define HAVE_DAYLIGHT 1 #define NEGATIVE_TIME_T 1 #define POSIX_SIGNAL 1 #define HAVE_SIG_T 1 #define RSHIFT(x,y) ((x)>>(int)(y)) #define USE_COPY_FILE_RANGE 1 #define HAVE__SC_CLK_TCK 1 #define STACK_GROW_DIRECTION -1 #define COROUTINE_H "coroutine/amd64/Context.h" #define _REENTRANT 1 #define _THREAD_SAFE 1 #define HAVE_LIBPTHREAD 1 #define HAVE_SCHED_YIELD 1 #define HAVE_PTHREAD_ATTR_SETINHERITSCHED 1 #define HAVE_PTHREAD_ATTR_GETSTACK 1 #define HAVE_PTHREAD_ATTR_GETGUARDSIZE 1 #define HAVE_PTHREAD_CONDATTR_SETCLOCK 1 #define HAVE_PTHREAD_SIGMASK 1 #define HAVE_PTHREAD_SETNAME_NP 1 #define HAVE_PTHREAD_GETATTR_NP 1 #define SET_CURRENT_THREAD_NAME(name) pthread_setname_np(pthread_self(), name) #define SET_ANOTHER_THREAD_NAME(thid,name) pthread_setname_np(thid, name) #define DEFINE_MCONTEXT_PTR(mc, uc) mcontext_t *mc = &(uc)->uc_mcontext #define HAVE_GETCONTEXT 1 #define HAVE_SETCONTEXT 1 #define USE_ELF 1 #define HAVE_ELF_H 1 #define HAVE_LIBZ 1 #define HAVE_BACKTRACE 1 #define DLEXT_MAXLEN 3 #define DLEXT ".so" #define ENABLE_MULTIARCH 1 #define LIBDIR_BASENAME "lib64" #define HAVE__SETJMP 1 #define RUBY_SETJMP(env) _setjmp((env)) #define RUBY_LONGJMP(env,val) _longjmp((env),val) #define RUBY_JMP_BUF jmp_buf #define USE_MJIT 1 #define HAVE_PTHREAD_H 1 #define RUBY_LIB_VERSION_BLANK 1 #define RUBY_PLATFORM "x86_64-linux" #endif /* INCLUDE_RUBY_CONFIG_H */ PK!rronigmo.hnu[#ifndef ONIGMO_H #define ONIGMO_H /********************************************************************** onigmo.h - Onigmo (Oniguruma-mod) (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2009 K.Kosako * Copyright (c) 2011-2017 K.Takata * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifdef __cplusplus extern "C" { # if 0 } /* satisfy cc-mode */ # endif #endif #define ONIGMO_VERSION_MAJOR 6 #define ONIGMO_VERSION_MINOR 1 #define ONIGMO_VERSION_TEENY 3 #ifndef ONIG_EXTERN # ifdef RUBY_EXTERN # define ONIG_EXTERN RUBY_EXTERN # else # if defined(_WIN32) && !defined(__GNUC__) # if defined(EXPORT) || defined(RUBY_EXPORT) # define ONIG_EXTERN extern __declspec(dllexport) # else # define ONIG_EXTERN extern __declspec(dllimport) # endif # endif # endif #endif #ifndef ONIG_EXTERN # define ONIG_EXTERN extern #endif #ifndef RUBY # ifndef RUBY_SYMBOL_EXPORT_BEGIN # define RUBY_SYMBOL_EXPORT_BEGIN # define RUBY_SYMBOL_EXPORT_END # endif #endif RUBY_SYMBOL_EXPORT_BEGIN #include /* for size_t */ /* PART: character encoding */ #ifndef ONIG_ESCAPE_UCHAR_COLLISION # define UChar OnigUChar #endif typedef unsigned char OnigUChar; typedef unsigned int OnigCodePoint; typedef unsigned int OnigCtype; typedef size_t OnigDistance; typedef ptrdiff_t OnigPosition; #define ONIG_INFINITE_DISTANCE ~((OnigDistance )0) /* * Onig casefold/case mapping flags and related definitions * * Subfields (starting with 0 at LSB): * 0-2: Code point count in casefold.h * 3-12: Index into SpecialCaseMapping array in casefold.h * 13-22: Case folding/mapping flags */ typedef unsigned int OnigCaseFoldType; /* case fold flag */ ONIG_EXTERN OnigCaseFoldType OnigDefaultCaseFoldFlag; /* bits for actual code point count; 3 bits is more than enough, currently only 2 used */ #define OnigCodePointMaskWidth 3 #define OnigCodePointMask ((1< Unicode:0x1ffc */ /* code range */ #define ONIGENC_CODE_RANGE_NUM(range) ((int )range[0]) #define ONIGENC_CODE_RANGE_FROM(range,i) range[((i)*2) + 1] #define ONIGENC_CODE_RANGE_TO(range,i) range[((i)*2) + 2] typedef struct { int byte_len; /* argument(original) character(s) byte length */ int code_len; /* number of code */ OnigCodePoint code[ONIGENC_MAX_COMP_CASE_FOLD_CODE_LEN]; } OnigCaseFoldCodeItem; typedef struct { OnigCodePoint esc; OnigCodePoint anychar; OnigCodePoint anytime; OnigCodePoint zero_or_one_time; OnigCodePoint one_or_more_time; OnigCodePoint anychar_anytime; } OnigMetaCharTableType; typedef int (*OnigApplyAllCaseFoldFunc)(OnigCodePoint from, OnigCodePoint* to, int to_len, void* arg); typedef struct OnigEncodingTypeST { int (*precise_mbc_enc_len)(const OnigUChar* p,const OnigUChar* e, const struct OnigEncodingTypeST* enc); const char* name; int max_enc_len; int min_enc_len; int (*is_mbc_newline)(const OnigUChar* p, const OnigUChar* end, const struct OnigEncodingTypeST* enc); OnigCodePoint (*mbc_to_code)(const OnigUChar* p, const OnigUChar* end, const struct OnigEncodingTypeST* enc); int (*code_to_mbclen)(OnigCodePoint code, const struct OnigEncodingTypeST* enc); int (*code_to_mbc)(OnigCodePoint code, OnigUChar *buf, const struct OnigEncodingTypeST* enc); int (*mbc_case_fold)(OnigCaseFoldType flag, const OnigUChar** pp, const OnigUChar* end, OnigUChar* to, const struct OnigEncodingTypeST* enc); int (*apply_all_case_fold)(OnigCaseFoldType flag, OnigApplyAllCaseFoldFunc f, void* arg, const struct OnigEncodingTypeST* enc); int (*get_case_fold_codes_by_str)(OnigCaseFoldType flag, const OnigUChar* p, const OnigUChar* end, OnigCaseFoldCodeItem acs[], const struct OnigEncodingTypeST* enc); int (*property_name_to_ctype)(const struct OnigEncodingTypeST* enc, const OnigUChar* p, const OnigUChar* end); int (*is_code_ctype)(OnigCodePoint code, OnigCtype ctype, const struct OnigEncodingTypeST* enc); int (*get_ctype_code_range)(OnigCtype ctype, OnigCodePoint* sb_out, const OnigCodePoint* ranges[], const struct OnigEncodingTypeST* enc); OnigUChar* (*left_adjust_char_head)(const OnigUChar* start, const OnigUChar* p, const OnigUChar* end, const struct OnigEncodingTypeST* enc); int (*is_allowed_reverse_match)(const OnigUChar* p, const OnigUChar* end, const struct OnigEncodingTypeST* enc); int (*case_map)(OnigCaseFoldType* flagP, const OnigUChar** pp, const OnigUChar* end, OnigUChar* to, OnigUChar* to_end, const struct OnigEncodingTypeST* enc); int ruby_encoding_index; unsigned int flags; } OnigEncodingType; typedef const OnigEncodingType* OnigEncoding; ONIG_EXTERN const OnigEncodingType OnigEncodingASCII; #ifndef RUBY ONIG_EXTERN const OnigEncodingType OnigEncodingISO_8859_1; ONIG_EXTERN const OnigEncodingType OnigEncodingISO_8859_2; ONIG_EXTERN const OnigEncodingType OnigEncodingISO_8859_3; ONIG_EXTERN const OnigEncodingType OnigEncodingISO_8859_4; ONIG_EXTERN const OnigEncodingType OnigEncodingISO_8859_5; ONIG_EXTERN const OnigEncodingType OnigEncodingISO_8859_6; ONIG_EXTERN const OnigEncodingType OnigEncodingISO_8859_7; ONIG_EXTERN const OnigEncodingType OnigEncodingISO_8859_8; ONIG_EXTERN const OnigEncodingType OnigEncodingISO_8859_9; ONIG_EXTERN const OnigEncodingType OnigEncodingISO_8859_10; ONIG_EXTERN const OnigEncodingType OnigEncodingISO_8859_11; ONIG_EXTERN const OnigEncodingType OnigEncodingISO_8859_13; ONIG_EXTERN const OnigEncodingType OnigEncodingISO_8859_14; ONIG_EXTERN const OnigEncodingType OnigEncodingISO_8859_15; ONIG_EXTERN const OnigEncodingType OnigEncodingISO_8859_16; ONIG_EXTERN const OnigEncodingType OnigEncodingUTF_8; ONIG_EXTERN const OnigEncodingType OnigEncodingUTF_16BE; ONIG_EXTERN const OnigEncodingType OnigEncodingUTF_16LE; ONIG_EXTERN const OnigEncodingType OnigEncodingUTF_32BE; ONIG_EXTERN const OnigEncodingType OnigEncodingUTF_32LE; ONIG_EXTERN const OnigEncodingType OnigEncodingEUC_JP; ONIG_EXTERN const OnigEncodingType OnigEncodingEUC_TW; ONIG_EXTERN const OnigEncodingType OnigEncodingEUC_KR; ONIG_EXTERN const OnigEncodingType OnigEncodingEUC_CN; ONIG_EXTERN const OnigEncodingType OnigEncodingShift_JIS; ONIG_EXTERN const OnigEncodingType OnigEncodingWindows_31J; /* ONIG_EXTERN const OnigEncodingType OnigEncodingKOI8; */ ONIG_EXTERN const OnigEncodingType OnigEncodingKOI8_R; ONIG_EXTERN const OnigEncodingType OnigEncodingKOI8_U; ONIG_EXTERN const OnigEncodingType OnigEncodingWindows_1250; ONIG_EXTERN const OnigEncodingType OnigEncodingWindows_1251; ONIG_EXTERN const OnigEncodingType OnigEncodingWindows_1252; ONIG_EXTERN const OnigEncodingType OnigEncodingWindows_1253; ONIG_EXTERN const OnigEncodingType OnigEncodingWindows_1254; ONIG_EXTERN const OnigEncodingType OnigEncodingWindows_1257; ONIG_EXTERN const OnigEncodingType OnigEncodingBIG5; ONIG_EXTERN const OnigEncodingType OnigEncodingGB18030; #endif /* RUBY */ #define ONIG_ENCODING_ASCII (&OnigEncodingASCII) #ifndef RUBY # define ONIG_ENCODING_ISO_8859_1 (&OnigEncodingISO_8859_1) # define ONIG_ENCODING_ISO_8859_2 (&OnigEncodingISO_8859_2) # define ONIG_ENCODING_ISO_8859_3 (&OnigEncodingISO_8859_3) # define ONIG_ENCODING_ISO_8859_4 (&OnigEncodingISO_8859_4) # define ONIG_ENCODING_ISO_8859_5 (&OnigEncodingISO_8859_5) # define ONIG_ENCODING_ISO_8859_6 (&OnigEncodingISO_8859_6) # define ONIG_ENCODING_ISO_8859_7 (&OnigEncodingISO_8859_7) # define ONIG_ENCODING_ISO_8859_8 (&OnigEncodingISO_8859_8) # define ONIG_ENCODING_ISO_8859_9 (&OnigEncodingISO_8859_9) # define ONIG_ENCODING_ISO_8859_10 (&OnigEncodingISO_8859_10) # define ONIG_ENCODING_ISO_8859_11 (&OnigEncodingISO_8859_11) # define ONIG_ENCODING_ISO_8859_13 (&OnigEncodingISO_8859_13) # define ONIG_ENCODING_ISO_8859_14 (&OnigEncodingISO_8859_14) # define ONIG_ENCODING_ISO_8859_15 (&OnigEncodingISO_8859_15) # define ONIG_ENCODING_ISO_8859_16 (&OnigEncodingISO_8859_16) # define ONIG_ENCODING_UTF_8 (&OnigEncodingUTF_8) # define ONIG_ENCODING_UTF_16BE (&OnigEncodingUTF_16BE) # define ONIG_ENCODING_UTF_16LE (&OnigEncodingUTF_16LE) # define ONIG_ENCODING_UTF_32BE (&OnigEncodingUTF_32BE) # define ONIG_ENCODING_UTF_32LE (&OnigEncodingUTF_32LE) # define ONIG_ENCODING_EUC_JP (&OnigEncodingEUC_JP) # define ONIG_ENCODING_EUC_TW (&OnigEncodingEUC_TW) # define ONIG_ENCODING_EUC_KR (&OnigEncodingEUC_KR) # define ONIG_ENCODING_EUC_CN (&OnigEncodingEUC_CN) # define ONIG_ENCODING_SHIFT_JIS (&OnigEncodingShift_JIS) # define ONIG_ENCODING_WINDOWS_31J (&OnigEncodingWindows_31J) /* # define ONIG_ENCODING_KOI8 (&OnigEncodingKOI8) */ # define ONIG_ENCODING_KOI8_R (&OnigEncodingKOI8_R) # define ONIG_ENCODING_KOI8_U (&OnigEncodingKOI8_U) # define ONIG_ENCODING_WINDOWS_1250 (&OnigEncodingWindows_1250) # define ONIG_ENCODING_WINDOWS_1251 (&OnigEncodingWindows_1251) # define ONIG_ENCODING_WINDOWS_1252 (&OnigEncodingWindows_1252) # define ONIG_ENCODING_WINDOWS_1253 (&OnigEncodingWindows_1253) # define ONIG_ENCODING_WINDOWS_1254 (&OnigEncodingWindows_1254) # define ONIG_ENCODING_WINDOWS_1257 (&OnigEncodingWindows_1257) # define ONIG_ENCODING_BIG5 (&OnigEncodingBIG5) # define ONIG_ENCODING_GB18030 (&OnigEncodingGB18030) /* old names */ # define ONIG_ENCODING_SJIS ONIG_ENCODING_SHIFT_JIS # define ONIG_ENCODING_CP932 ONIG_ENCODING_WINDOWS_31J # define ONIG_ENCODING_CP1250 ONIG_ENCODING_WINDOWS_1250 # define ONIG_ENCODING_CP1251 ONIG_ENCODING_WINDOWS_1251 # define ONIG_ENCODING_CP1252 ONIG_ENCODING_WINDOWS_1252 # define ONIG_ENCODING_CP1253 ONIG_ENCODING_WINDOWS_1253 # define ONIG_ENCODING_CP1254 ONIG_ENCODING_WINDOWS_1254 # define ONIG_ENCODING_CP1257 ONIG_ENCODING_WINDOWS_1257 # define ONIG_ENCODING_UTF8 ONIG_ENCODING_UTF_8 # define ONIG_ENCODING_UTF16_BE ONIG_ENCODING_UTF_16BE # define ONIG_ENCODING_UTF16_LE ONIG_ENCODING_UTF_16LE # define ONIG_ENCODING_UTF32_BE ONIG_ENCODING_UTF_32BE # define ONIG_ENCODING_UTF32_LE ONIG_ENCODING_UTF_32LE #endif /* RUBY */ #define ONIG_ENCODING_UNDEF ((OnigEncoding )0) /* this declaration needs to be here because it is used in string.c in Ruby */ ONIG_EXTERN int onigenc_ascii_only_case_map(OnigCaseFoldType* flagP, const OnigUChar** pp, const OnigUChar* end, OnigUChar* to, OnigUChar* to_end, const struct OnigEncodingTypeST* enc); /* work size */ #define ONIGENC_CODE_TO_MBC_MAXLEN 7 #define ONIGENC_MBC_CASE_FOLD_MAXLEN 18 /* 18: 6(max-byte) * 3(case-fold chars) */ /* character types */ #define ONIGENC_CTYPE_NEWLINE 0 #define ONIGENC_CTYPE_ALPHA 1 #define ONIGENC_CTYPE_BLANK 2 #define ONIGENC_CTYPE_CNTRL 3 #define ONIGENC_CTYPE_DIGIT 4 #define ONIGENC_CTYPE_GRAPH 5 #define ONIGENC_CTYPE_LOWER 6 #define ONIGENC_CTYPE_PRINT 7 #define ONIGENC_CTYPE_PUNCT 8 #define ONIGENC_CTYPE_SPACE 9 #define ONIGENC_CTYPE_UPPER 10 #define ONIGENC_CTYPE_XDIGIT 11 #define ONIGENC_CTYPE_WORD 12 #define ONIGENC_CTYPE_ALNUM 13 /* alpha || digit */ #define ONIGENC_CTYPE_ASCII 14 #define ONIGENC_MAX_STD_CTYPE ONIGENC_CTYPE_ASCII /* flags */ #define ONIGENC_FLAG_NONE 0U #define ONIGENC_FLAG_UNICODE 1U #define onig_enc_len(enc,p,e) ONIGENC_MBC_ENC_LEN(enc, p, e) #define ONIGENC_IS_UNDEF(enc) ((enc) == ONIG_ENCODING_UNDEF) #define ONIGENC_IS_SINGLEBYTE(enc) (ONIGENC_MBC_MAXLEN(enc) == 1) #define ONIGENC_IS_MBC_HEAD(enc,p,e) (ONIGENC_MBC_ENC_LEN(enc,p,e) != 1) #define ONIGENC_IS_MBC_ASCII(p) (*(p) < 128) #define ONIGENC_IS_CODE_ASCII(code) ((code) < 128) #define ONIGENC_IS_MBC_WORD(enc,s,end) \ ONIGENC_IS_CODE_WORD(enc,ONIGENC_MBC_TO_CODE(enc,s,end)) #define ONIGENC_IS_MBC_ASCII_WORD(enc,s,end) \ onigenc_ascii_is_code_ctype( \ ONIGENC_MBC_TO_CODE(enc,s,end),ONIGENC_CTYPE_WORD,enc) #define ONIGENC_IS_UNICODE(enc) ((enc)->flags & ONIGENC_FLAG_UNICODE) #define ONIGENC_NAME(enc) ((enc)->name) #define ONIGENC_MBC_CASE_FOLD(enc,flag,pp,end,buf) \ (enc)->mbc_case_fold(flag,(const OnigUChar** )pp,end,buf,enc) #define ONIGENC_IS_ALLOWED_REVERSE_MATCH(enc,s,end) \ (enc)->is_allowed_reverse_match(s,end,enc) #define ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc,start,s,end) \ (enc)->left_adjust_char_head(start, s, end, enc) #define ONIGENC_APPLY_ALL_CASE_FOLD(enc,case_fold_flag,f,arg) \ (enc)->apply_all_case_fold(case_fold_flag,f,arg,enc) #define ONIGENC_GET_CASE_FOLD_CODES_BY_STR(enc,case_fold_flag,p,end,acs) \ (enc)->get_case_fold_codes_by_str(case_fold_flag,p,end,acs,enc) #define ONIGENC_STEP_BACK(enc,start,s,end,n) \ onigenc_step_back((enc),(start),(s),(end),(n)) #define ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND(n) (n) #define ONIGENC_MBCLEN_CHARFOUND_P(r) (0 < (r)) #define ONIGENC_MBCLEN_CHARFOUND_LEN(r) (r) #define ONIGENC_CONSTRUCT_MBCLEN_INVALID() (-1) #define ONIGENC_MBCLEN_INVALID_P(r) ((r) == -1) #define ONIGENC_CONSTRUCT_MBCLEN_NEEDMORE(n) (-1-(n)) #define ONIGENC_MBCLEN_NEEDMORE_P(r) ((r) < -1) #define ONIGENC_MBCLEN_NEEDMORE_LEN(r) (-1-(r)) #define ONIGENC_PRECISE_MBC_ENC_LEN(enc,p,e) (enc)->precise_mbc_enc_len(p,e,enc) ONIG_EXTERN int onigenc_mbclen_approximate(const OnigUChar* p,const OnigUChar* e, const struct OnigEncodingTypeST* enc); #define ONIGENC_MBC_ENC_LEN(enc,p,e) onigenc_mbclen_approximate(p,e,enc) #define ONIGENC_MBC_MAXLEN(enc) ((enc)->max_enc_len) #define ONIGENC_MBC_MAXLEN_DIST(enc) ONIGENC_MBC_MAXLEN(enc) #define ONIGENC_MBC_MINLEN(enc) ((enc)->min_enc_len) #define ONIGENC_IS_MBC_NEWLINE(enc,p,end) (enc)->is_mbc_newline((p),(end),enc) #define ONIGENC_MBC_TO_CODE(enc,p,end) (enc)->mbc_to_code((p),(end),enc) #define ONIGENC_CODE_TO_MBCLEN(enc,code) (enc)->code_to_mbclen(code,enc) #define ONIGENC_CODE_TO_MBC(enc,code,buf) (enc)->code_to_mbc(code,buf,enc) #define ONIGENC_PROPERTY_NAME_TO_CTYPE(enc,p,end) \ (enc)->property_name_to_ctype(enc,p,end) #define ONIGENC_IS_CODE_CTYPE(enc,code,ctype) (enc)->is_code_ctype(code,ctype,enc) #define ONIGENC_IS_CODE_NEWLINE(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_NEWLINE) #define ONIGENC_IS_CODE_GRAPH(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_GRAPH) #define ONIGENC_IS_CODE_PRINT(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_PRINT) #define ONIGENC_IS_CODE_ALNUM(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_ALNUM) #define ONIGENC_IS_CODE_ALPHA(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_ALPHA) #define ONIGENC_IS_CODE_LOWER(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_LOWER) #define ONIGENC_IS_CODE_UPPER(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_UPPER) #define ONIGENC_IS_CODE_CNTRL(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_CNTRL) #define ONIGENC_IS_CODE_PUNCT(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_PUNCT) #define ONIGENC_IS_CODE_SPACE(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_SPACE) #define ONIGENC_IS_CODE_BLANK(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_BLANK) #define ONIGENC_IS_CODE_DIGIT(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_DIGIT) #define ONIGENC_IS_CODE_XDIGIT(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_XDIGIT) #define ONIGENC_IS_CODE_WORD(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_WORD) #define ONIGENC_GET_CTYPE_CODE_RANGE(enc,ctype,sbout,ranges) \ (enc)->get_ctype_code_range(ctype,sbout,ranges,enc) ONIG_EXTERN OnigUChar* onigenc_step_back(OnigEncoding enc, const OnigUChar* start, const OnigUChar* s, const OnigUChar* end, int n); /* encoding API */ ONIG_EXTERN int onigenc_init(void); ONIG_EXTERN int onigenc_set_default_encoding(OnigEncoding enc); ONIG_EXTERN OnigEncoding onigenc_get_default_encoding(void); ONIG_EXTERN OnigUChar* onigenc_get_right_adjust_char_head_with_prev(OnigEncoding enc, const OnigUChar* start, const OnigUChar* s, const OnigUChar* end, const OnigUChar** prev); ONIG_EXTERN OnigUChar* onigenc_get_prev_char_head(OnigEncoding enc, const OnigUChar* start, const OnigUChar* s, const OnigUChar* end); ONIG_EXTERN OnigUChar* onigenc_get_left_adjust_char_head(OnigEncoding enc, const OnigUChar* start, const OnigUChar* s, const OnigUChar* end); ONIG_EXTERN OnigUChar* onigenc_get_right_adjust_char_head(OnigEncoding enc, const OnigUChar* start, const OnigUChar* s, const OnigUChar* end); ONIG_EXTERN int onigenc_strlen(OnigEncoding enc, const OnigUChar* p, const OnigUChar* end); ONIG_EXTERN int onigenc_strlen_null(OnigEncoding enc, const OnigUChar* p); ONIG_EXTERN int onigenc_str_bytelen_null(OnigEncoding enc, const OnigUChar* p); /* PART: regular expression */ /* config parameters */ #define ONIG_NREGION 4 #define ONIG_MAX_CAPTURE_GROUP_NUM 32767 #define ONIG_MAX_BACKREF_NUM 1000 #define ONIG_MAX_REPEAT_NUM 100000 #define ONIG_MAX_MULTI_BYTE_RANGES_NUM 10000 /* constants */ #define ONIG_MAX_ERROR_MESSAGE_LEN 90 typedef unsigned int OnigOptionType; #define ONIG_OPTION_DEFAULT ONIG_OPTION_NONE /* options */ #define ONIG_OPTION_NONE 0U #define ONIG_OPTION_IGNORECASE 1U #define ONIG_OPTION_EXTEND (ONIG_OPTION_IGNORECASE << 1) #define ONIG_OPTION_MULTILINE (ONIG_OPTION_EXTEND << 1) #define ONIG_OPTION_DOTALL ONIG_OPTION_MULTILINE #define ONIG_OPTION_SINGLELINE (ONIG_OPTION_MULTILINE << 1) #define ONIG_OPTION_FIND_LONGEST (ONIG_OPTION_SINGLELINE << 1) #define ONIG_OPTION_FIND_NOT_EMPTY (ONIG_OPTION_FIND_LONGEST << 1) #define ONIG_OPTION_NEGATE_SINGLELINE (ONIG_OPTION_FIND_NOT_EMPTY << 1) #define ONIG_OPTION_DONT_CAPTURE_GROUP (ONIG_OPTION_NEGATE_SINGLELINE << 1) #define ONIG_OPTION_CAPTURE_GROUP (ONIG_OPTION_DONT_CAPTURE_GROUP << 1) /* options (search time) */ #define ONIG_OPTION_NOTBOL (ONIG_OPTION_CAPTURE_GROUP << 1) #define ONIG_OPTION_NOTEOL (ONIG_OPTION_NOTBOL << 1) #define ONIG_OPTION_NOTBOS (ONIG_OPTION_NOTEOL << 1) #define ONIG_OPTION_NOTEOS (ONIG_OPTION_NOTBOS << 1) /* options (ctype range) */ #define ONIG_OPTION_ASCII_RANGE (ONIG_OPTION_NOTEOS << 1) #define ONIG_OPTION_POSIX_BRACKET_ALL_RANGE (ONIG_OPTION_ASCII_RANGE << 1) #define ONIG_OPTION_WORD_BOUND_ALL_RANGE (ONIG_OPTION_POSIX_BRACKET_ALL_RANGE << 1) /* options (newline) */ #define ONIG_OPTION_NEWLINE_CRLF (ONIG_OPTION_WORD_BOUND_ALL_RANGE << 1) #define ONIG_OPTION_MAXBIT ONIG_OPTION_NEWLINE_CRLF /* limit */ #define ONIG_OPTION_ON(options,regopt) ((options) |= (regopt)) #define ONIG_OPTION_OFF(options,regopt) ((options) &= ~(regopt)) #define ONIG_IS_OPTION_ON(options,option) ((options) & (option)) /* syntax */ typedef struct { unsigned int op; unsigned int op2; unsigned int behavior; OnigOptionType options; /* default option */ OnigMetaCharTableType meta_char_table; } OnigSyntaxType; ONIG_EXTERN const OnigSyntaxType OnigSyntaxASIS; ONIG_EXTERN const OnigSyntaxType OnigSyntaxPosixBasic; ONIG_EXTERN const OnigSyntaxType OnigSyntaxPosixExtended; ONIG_EXTERN const OnigSyntaxType OnigSyntaxEmacs; ONIG_EXTERN const OnigSyntaxType OnigSyntaxGrep; ONIG_EXTERN const OnigSyntaxType OnigSyntaxGnuRegex; ONIG_EXTERN const OnigSyntaxType OnigSyntaxJava; ONIG_EXTERN const OnigSyntaxType OnigSyntaxPerl58; ONIG_EXTERN const OnigSyntaxType OnigSyntaxPerl58_NG; ONIG_EXTERN const OnigSyntaxType OnigSyntaxPerl; ONIG_EXTERN const OnigSyntaxType OnigSyntaxRuby; ONIG_EXTERN const OnigSyntaxType OnigSyntaxPython; /* predefined syntaxes (see regsyntax.c) */ #define ONIG_SYNTAX_ASIS (&OnigSyntaxASIS) #define ONIG_SYNTAX_POSIX_BASIC (&OnigSyntaxPosixBasic) #define ONIG_SYNTAX_POSIX_EXTENDED (&OnigSyntaxPosixExtended) #define ONIG_SYNTAX_EMACS (&OnigSyntaxEmacs) #define ONIG_SYNTAX_GREP (&OnigSyntaxGrep) #define ONIG_SYNTAX_GNU_REGEX (&OnigSyntaxGnuRegex) #define ONIG_SYNTAX_JAVA (&OnigSyntaxJava) #define ONIG_SYNTAX_PERL58 (&OnigSyntaxPerl58) #define ONIG_SYNTAX_PERL58_NG (&OnigSyntaxPerl58_NG) #define ONIG_SYNTAX_PERL (&OnigSyntaxPerl) #define ONIG_SYNTAX_RUBY (&OnigSyntaxRuby) #define ONIG_SYNTAX_PYTHON (&OnigSyntaxPython) /* default syntax */ ONIG_EXTERN const OnigSyntaxType* OnigDefaultSyntax; #define ONIG_SYNTAX_DEFAULT OnigDefaultSyntax /* syntax (operators) */ #define ONIG_SYN_OP_VARIABLE_META_CHARACTERS (1U<<0) #define ONIG_SYN_OP_DOT_ANYCHAR (1U<<1) /* . */ #define ONIG_SYN_OP_ASTERISK_ZERO_INF (1U<<2) /* * */ #define ONIG_SYN_OP_ESC_ASTERISK_ZERO_INF (1U<<3) #define ONIG_SYN_OP_PLUS_ONE_INF (1U<<4) /* + */ #define ONIG_SYN_OP_ESC_PLUS_ONE_INF (1U<<5) #define ONIG_SYN_OP_QMARK_ZERO_ONE (1U<<6) /* ? */ #define ONIG_SYN_OP_ESC_QMARK_ZERO_ONE (1U<<7) #define ONIG_SYN_OP_BRACE_INTERVAL (1U<<8) /* {lower,upper} */ #define ONIG_SYN_OP_ESC_BRACE_INTERVAL (1U<<9) /* \{lower,upper\} */ #define ONIG_SYN_OP_VBAR_ALT (1U<<10) /* | */ #define ONIG_SYN_OP_ESC_VBAR_ALT (1U<<11) /* \| */ #define ONIG_SYN_OP_LPAREN_SUBEXP (1U<<12) /* (...) */ #define ONIG_SYN_OP_ESC_LPAREN_SUBEXP (1U<<13) /* \(...\) */ #define ONIG_SYN_OP_ESC_AZ_BUF_ANCHOR (1U<<14) /* \A, \Z, \z */ #define ONIG_SYN_OP_ESC_CAPITAL_G_BEGIN_ANCHOR (1U<<15) /* \G */ #define ONIG_SYN_OP_DECIMAL_BACKREF (1U<<16) /* \num */ #define ONIG_SYN_OP_BRACKET_CC (1U<<17) /* [...] */ #define ONIG_SYN_OP_ESC_W_WORD (1U<<18) /* \w, \W */ #define ONIG_SYN_OP_ESC_LTGT_WORD_BEGIN_END (1U<<19) /* \<. \> */ #define ONIG_SYN_OP_ESC_B_WORD_BOUND (1U<<20) /* \b, \B */ #define ONIG_SYN_OP_ESC_S_WHITE_SPACE (1U<<21) /* \s, \S */ #define ONIG_SYN_OP_ESC_D_DIGIT (1U<<22) /* \d, \D */ #define ONIG_SYN_OP_LINE_ANCHOR (1U<<23) /* ^, $ */ #define ONIG_SYN_OP_POSIX_BRACKET (1U<<24) /* [:xxxx:] */ #define ONIG_SYN_OP_QMARK_NON_GREEDY (1U<<25) /* ??,*?,+?,{n,m}? */ #define ONIG_SYN_OP_ESC_CONTROL_CHARS (1U<<26) /* \n,\r,\t,\a ... */ #define ONIG_SYN_OP_ESC_C_CONTROL (1U<<27) /* \cx */ #define ONIG_SYN_OP_ESC_OCTAL3 (1U<<28) /* \OOO */ #define ONIG_SYN_OP_ESC_X_HEX2 (1U<<29) /* \xHH */ #define ONIG_SYN_OP_ESC_X_BRACE_HEX8 (1U<<30) /* \x{7HHHHHHH} */ #define ONIG_SYN_OP_ESC_O_BRACE_OCTAL (1U<<31) /* \o{OOO} */ #define ONIG_SYN_OP2_ESC_CAPITAL_Q_QUOTE (1U<<0) /* \Q...\E */ #define ONIG_SYN_OP2_QMARK_GROUP_EFFECT (1U<<1) /* (?...) */ #define ONIG_SYN_OP2_OPTION_PERL (1U<<2) /* (?imsxadlu), (?-imsx), (?^imsxalu) */ #define ONIG_SYN_OP2_OPTION_RUBY (1U<<3) /* (?imxadu), (?-imx) */ #define ONIG_SYN_OP2_PLUS_POSSESSIVE_REPEAT (1U<<4) /* ?+,*+,++ */ #define ONIG_SYN_OP2_PLUS_POSSESSIVE_INTERVAL (1U<<5) /* {n,m}+ */ #define ONIG_SYN_OP2_CCLASS_SET_OP (1U<<6) /* [...&&..[..]..] */ #define ONIG_SYN_OP2_QMARK_LT_NAMED_GROUP (1U<<7) /* (?...) */ #define ONIG_SYN_OP2_ESC_K_NAMED_BACKREF (1U<<8) /* \k */ #define ONIG_SYN_OP2_ESC_G_SUBEXP_CALL (1U<<9) /* \g, \g */ #define ONIG_SYN_OP2_ATMARK_CAPTURE_HISTORY (1U<<10) /* (?@..),(?@..) */ #define ONIG_SYN_OP2_ESC_CAPITAL_C_BAR_CONTROL (1U<<11) /* \C-x */ #define ONIG_SYN_OP2_ESC_CAPITAL_M_BAR_META (1U<<12) /* \M-x */ #define ONIG_SYN_OP2_ESC_V_VTAB (1U<<13) /* \v as VTAB */ #define ONIG_SYN_OP2_ESC_U_HEX4 (1U<<14) /* \uHHHH */ #define ONIG_SYN_OP2_ESC_GNU_BUF_ANCHOR (1U<<15) /* \`, \' */ #define ONIG_SYN_OP2_ESC_P_BRACE_CHAR_PROPERTY (1U<<16) /* \p{...}, \P{...} */ #define ONIG_SYN_OP2_ESC_P_BRACE_CIRCUMFLEX_NOT (1U<<17) /* \p{^..}, \P{^..} */ /* #define ONIG_SYN_OP2_CHAR_PROPERTY_PREFIX_IS (1U<<18) */ #define ONIG_SYN_OP2_ESC_H_XDIGIT (1U<<19) /* \h, \H */ #define ONIG_SYN_OP2_INEFFECTIVE_ESCAPE (1U<<20) /* \ */ #define ONIG_SYN_OP2_ESC_CAPITAL_R_LINEBREAK (1U<<21) /* \R as (?>\x0D\x0A|[\x0A-\x0D\x{85}\x{2028}\x{2029}]) */ #define ONIG_SYN_OP2_ESC_CAPITAL_X_EXTENDED_GRAPHEME_CLUSTER (1U<<22) /* \X */ #define ONIG_SYN_OP2_ESC_V_VERTICAL_WHITESPACE (1U<<23) /* \v, \V -- Perl */ /* NOTIMPL */ #define ONIG_SYN_OP2_ESC_H_HORIZONTAL_WHITESPACE (1U<<24) /* \h, \H -- Perl */ /* NOTIMPL */ #define ONIG_SYN_OP2_ESC_CAPITAL_K_KEEP (1U<<25) /* \K */ #define ONIG_SYN_OP2_ESC_G_BRACE_BACKREF (1U<<26) /* \g{name}, \g{n} */ #define ONIG_SYN_OP2_QMARK_SUBEXP_CALL (1U<<27) /* (?&name), (?n), (?R), (?0) */ #define ONIG_SYN_OP2_QMARK_VBAR_BRANCH_RESET (1U<<28) /* (?|...) */ /* NOTIMPL */ #define ONIG_SYN_OP2_QMARK_LPAREN_CONDITION (1U<<29) /* (?(cond)yes...|no...) */ #define ONIG_SYN_OP2_QMARK_CAPITAL_P_NAMED_GROUP (1U<<30) /* (?P...), (?P=name), (?P>name) -- Python/PCRE */ #define ONIG_SYN_OP2_QMARK_TILDE_ABSENT (1U<<31) /* (?~...) */ /* #define ONIG_SYN_OP2_OPTION_JAVA (1U< {0,n} */ #define ONIG_SYN_STRICT_CHECK_BACKREF (1U<<5) /* /(\1)/,/\1()/ ..*/ #define ONIG_SYN_DIFFERENT_LEN_ALT_LOOK_BEHIND (1U<<6) /* (?<=a|bc) */ #define ONIG_SYN_CAPTURE_ONLY_NAMED_GROUP (1U<<7) /* see doc/RE */ #define ONIG_SYN_ALLOW_MULTIPLEX_DEFINITION_NAME (1U<<8) /* (?)(?) */ #define ONIG_SYN_FIXED_INTERVAL_IS_GREEDY_ONLY (1U<<9) /* a{n}?=(?:a{n})? */ #define ONIG_SYN_ALLOW_MULTIPLEX_DEFINITION_NAME_CALL (1U<<10) /* (?)(?)(?&x) */ #define ONIG_SYN_USE_LEFT_MOST_NAMED_GROUP (1U<<11) /* (?)(?)\k */ /* syntax (behavior) in char class [...] */ #define ONIG_SYN_NOT_NEWLINE_IN_NEGATIVE_CC (1U<<20) /* [^...] */ #define ONIG_SYN_BACKSLASH_ESCAPE_IN_CC (1U<<21) /* [..\w..] etc.. */ #define ONIG_SYN_ALLOW_EMPTY_RANGE_IN_CC (1U<<22) #define ONIG_SYN_ALLOW_DOUBLE_RANGE_OP_IN_CC (1U<<23) /* [0-9-a]=[0-9\-a] */ /* syntax (behavior) warning */ #define ONIG_SYN_WARN_CC_OP_NOT_ESCAPED (1U<<24) /* [,-,] */ #define ONIG_SYN_WARN_REDUNDANT_NESTED_REPEAT (1U<<25) /* (?:a*)+ */ #define ONIG_SYN_WARN_CC_DUP (1U<<26) /* [aa] */ /* meta character specifiers (onig_set_meta_char()) */ #define ONIG_META_CHAR_ESCAPE 0 #define ONIG_META_CHAR_ANYCHAR 1 #define ONIG_META_CHAR_ANYTIME 2 #define ONIG_META_CHAR_ZERO_OR_ONE_TIME 3 #define ONIG_META_CHAR_ONE_OR_MORE_TIME 4 #define ONIG_META_CHAR_ANYCHAR_ANYTIME 5 #define ONIG_INEFFECTIVE_META_CHAR 0 /* error codes */ #define ONIG_IS_PATTERN_ERROR(ecode) ((ecode) <= -100 && (ecode) > -1000) /* normal return */ #define ONIG_NORMAL 0 #define ONIG_MISMATCH -1 #define ONIG_NO_SUPPORT_CONFIG -2 /* internal error */ #define ONIGERR_MEMORY -5 #define ONIGERR_TYPE_BUG -6 #define ONIGERR_PARSER_BUG -11 #define ONIGERR_STACK_BUG -12 #define ONIGERR_UNDEFINED_BYTECODE -13 #define ONIGERR_UNEXPECTED_BYTECODE -14 #define ONIGERR_MATCH_STACK_LIMIT_OVER -15 #define ONIGERR_PARSE_DEPTH_LIMIT_OVER -16 #define ONIGERR_DEFAULT_ENCODING_IS_NOT_SET -21 #define ONIGERR_SPECIFIED_ENCODING_CANT_CONVERT_TO_WIDE_CHAR -22 /* general error */ #define ONIGERR_INVALID_ARGUMENT -30 /* syntax error */ #define ONIGERR_END_PATTERN_AT_LEFT_BRACE -100 #define ONIGERR_END_PATTERN_AT_LEFT_BRACKET -101 #define ONIGERR_EMPTY_CHAR_CLASS -102 #define ONIGERR_PREMATURE_END_OF_CHAR_CLASS -103 #define ONIGERR_END_PATTERN_AT_ESCAPE -104 #define ONIGERR_END_PATTERN_AT_META -105 #define ONIGERR_END_PATTERN_AT_CONTROL -106 #define ONIGERR_META_CODE_SYNTAX -108 #define ONIGERR_CONTROL_CODE_SYNTAX -109 #define ONIGERR_CHAR_CLASS_VALUE_AT_END_OF_RANGE -110 #define ONIGERR_CHAR_CLASS_VALUE_AT_START_OF_RANGE -111 #define ONIGERR_UNMATCHED_RANGE_SPECIFIER_IN_CHAR_CLASS -112 #define ONIGERR_TARGET_OF_REPEAT_OPERATOR_NOT_SPECIFIED -113 #define ONIGERR_TARGET_OF_REPEAT_OPERATOR_INVALID -114 #define ONIGERR_NESTED_REPEAT_OPERATOR -115 #define ONIGERR_UNMATCHED_CLOSE_PARENTHESIS -116 #define ONIGERR_END_PATTERN_WITH_UNMATCHED_PARENTHESIS -117 #define ONIGERR_END_PATTERN_IN_GROUP -118 #define ONIGERR_UNDEFINED_GROUP_OPTION -119 #define ONIGERR_INVALID_POSIX_BRACKET_TYPE -121 #define ONIGERR_INVALID_LOOK_BEHIND_PATTERN -122 #define ONIGERR_INVALID_REPEAT_RANGE_PATTERN -123 #define ONIGERR_INVALID_CONDITION_PATTERN -124 /* values error (syntax error) */ #define ONIGERR_TOO_BIG_NUMBER -200 #define ONIGERR_TOO_BIG_NUMBER_FOR_REPEAT_RANGE -201 #define ONIGERR_UPPER_SMALLER_THAN_LOWER_IN_REPEAT_RANGE -202 #define ONIGERR_EMPTY_RANGE_IN_CHAR_CLASS -203 #define ONIGERR_MISMATCH_CODE_LENGTH_IN_CLASS_RANGE -204 #define ONIGERR_TOO_MANY_MULTI_BYTE_RANGES -205 #define ONIGERR_TOO_SHORT_MULTI_BYTE_STRING -206 #define ONIGERR_TOO_BIG_BACKREF_NUMBER -207 #define ONIGERR_INVALID_BACKREF -208 #define ONIGERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED -209 #define ONIGERR_TOO_MANY_CAPTURE_GROUPS -210 #define ONIGERR_TOO_SHORT_DIGITS -211 #define ONIGERR_TOO_LONG_WIDE_CHAR_VALUE -212 #define ONIGERR_EMPTY_GROUP_NAME -214 #define ONIGERR_INVALID_GROUP_NAME -215 #define ONIGERR_INVALID_CHAR_IN_GROUP_NAME -216 #define ONIGERR_UNDEFINED_NAME_REFERENCE -217 #define ONIGERR_UNDEFINED_GROUP_REFERENCE -218 #define ONIGERR_MULTIPLEX_DEFINED_NAME -219 #define ONIGERR_MULTIPLEX_DEFINITION_NAME_CALL -220 #define ONIGERR_NEVER_ENDING_RECURSION -221 #define ONIGERR_GROUP_NUMBER_OVER_FOR_CAPTURE_HISTORY -222 #define ONIGERR_INVALID_CHAR_PROPERTY_NAME -223 #define ONIGERR_INVALID_CODE_POINT_VALUE -400 #define ONIGERR_INVALID_WIDE_CHAR_VALUE -400 #define ONIGERR_TOO_BIG_WIDE_CHAR_VALUE -401 #define ONIGERR_NOT_SUPPORTED_ENCODING_COMBINATION -402 #define ONIGERR_INVALID_COMBINATION_OF_OPTIONS -403 /* errors related to thread */ /* #define ONIGERR_OVER_THREAD_PASS_LIMIT_COUNT -1001 */ /* must be smaller than BIT_STATUS_BITS_NUM (unsigned int * 8) */ #define ONIG_MAX_CAPTURE_HISTORY_GROUP 31 #define ONIG_IS_CAPTURE_HISTORY_GROUP(r, i) \ ((i) <= ONIG_MAX_CAPTURE_HISTORY_GROUP && (r)->list && (r)->list[i]) #ifdef USE_CAPTURE_HISTORY typedef struct OnigCaptureTreeNodeStruct { int group; /* group number */ OnigPosition beg; OnigPosition end; int allocated; int num_childs; struct OnigCaptureTreeNodeStruct** childs; } OnigCaptureTreeNode; #endif /* match result region type */ struct re_registers { int allocated; int num_regs; OnigPosition* beg; OnigPosition* end; #ifdef USE_CAPTURE_HISTORY /* extended */ OnigCaptureTreeNode* history_root; /* capture history tree root */ #endif }; /* capture tree traverse */ #define ONIG_TRAVERSE_CALLBACK_AT_FIRST 1 #define ONIG_TRAVERSE_CALLBACK_AT_LAST 2 #define ONIG_TRAVERSE_CALLBACK_AT_BOTH \ ( ONIG_TRAVERSE_CALLBACK_AT_FIRST | ONIG_TRAVERSE_CALLBACK_AT_LAST ) #define ONIG_REGION_NOTPOS -1 typedef struct re_registers OnigRegion; typedef struct { OnigEncoding enc; OnigUChar* par; OnigUChar* par_end; } OnigErrorInfo; typedef struct { int lower; int upper; } OnigRepeatRange; typedef void (*OnigWarnFunc)(const char* s); extern void onig_null_warn(const char* s); #define ONIG_NULL_WARN onig_null_warn #define ONIG_CHAR_TABLE_SIZE 256 typedef struct re_pattern_buffer { /* common members of BBuf(bytes-buffer) */ unsigned char* p; /* compiled pattern */ unsigned int used; /* used space for p */ unsigned int alloc; /* allocated space for p */ int num_mem; /* used memory(...) num counted from 1 */ int num_repeat; /* OP_REPEAT/OP_REPEAT_NG id-counter */ int num_null_check; /* OP_NULL_CHECK_START/END id counter */ int num_comb_exp_check; /* combination explosion check */ int num_call; /* number of subexp call */ unsigned int capture_history; /* (?@...) flag (1-31) */ unsigned int bt_mem_start; /* need backtrack flag */ unsigned int bt_mem_end; /* need backtrack flag */ int stack_pop_level; int repeat_range_alloc; OnigOptionType options; OnigRepeatRange* repeat_range; OnigEncoding enc; const OnigSyntaxType* syntax; void* name_table; OnigCaseFoldType case_fold_flag; /* optimization info (string search, char-map and anchors) */ int optimize; /* optimize flag */ int threshold_len; /* search str-length for apply optimize */ int anchor; /* BEGIN_BUF, BEGIN_POS, (SEMI_)END_BUF */ OnigDistance anchor_dmin; /* (SEMI_)END_BUF anchor distance */ OnigDistance anchor_dmax; /* (SEMI_)END_BUF anchor distance */ int sub_anchor; /* start-anchor for exact or map */ unsigned char *exact; unsigned char *exact_end; unsigned char map[ONIG_CHAR_TABLE_SIZE]; /* used as BM skip or char-map */ int *int_map; /* BM skip for exact_len > 255 */ int *int_map_backward; /* BM skip for backward search */ OnigDistance dmin; /* min-distance of exact or map */ OnigDistance dmax; /* max-distance of exact or map */ /* regex_t link chain */ struct re_pattern_buffer* chain; /* escape compile-conflict */ } OnigRegexType; typedef OnigRegexType* OnigRegex; #ifndef ONIG_ESCAPE_REGEX_T_COLLISION typedef OnigRegexType regex_t; #endif typedef struct { int num_of_elements; OnigEncoding pattern_enc; OnigEncoding target_enc; const OnigSyntaxType* syntax; OnigOptionType option; OnigCaseFoldType case_fold_flag; } OnigCompileInfo; /* Oniguruma Native API */ ONIG_EXTERN int onig_initialize(OnigEncoding encodings[], int n); ONIG_EXTERN int onig_init(void); ONIG_EXTERN int onig_error_code_to_str(OnigUChar* s, OnigPosition err_code, ...); ONIG_EXTERN void onig_set_warn_func(OnigWarnFunc f); ONIG_EXTERN void onig_set_verb_warn_func(OnigWarnFunc f); ONIG_EXTERN int onig_new(OnigRegex*, const OnigUChar* pattern, const OnigUChar* pattern_end, OnigOptionType option, OnigEncoding enc, const OnigSyntaxType* syntax, OnigErrorInfo* einfo); ONIG_EXTERN int onig_reg_init(OnigRegex reg, OnigOptionType option, OnigCaseFoldType case_fold_flag, OnigEncoding enc, const OnigSyntaxType* syntax); ONIG_EXTERN int onig_new_without_alloc(OnigRegex, const OnigUChar* pattern, const OnigUChar* pattern_end, OnigOptionType option, OnigEncoding enc, const OnigSyntaxType* syntax, OnigErrorInfo* einfo); ONIG_EXTERN int onig_new_deluxe(OnigRegex* reg, const OnigUChar* pattern, const OnigUChar* pattern_end, OnigCompileInfo* ci, OnigErrorInfo* einfo); ONIG_EXTERN void onig_free(OnigRegex); ONIG_EXTERN void onig_free_body(OnigRegex); ONIG_EXTERN OnigPosition onig_scan(OnigRegex reg, const OnigUChar* str, const OnigUChar* end, OnigRegion* region, OnigOptionType option, int (*scan_callback)(OnigPosition, OnigPosition, OnigRegion*, void*), void* callback_arg); ONIG_EXTERN OnigPosition onig_search(OnigRegex, const OnigUChar* str, const OnigUChar* end, const OnigUChar* start, const OnigUChar* range, OnigRegion* region, OnigOptionType option); ONIG_EXTERN OnigPosition onig_search_gpos(OnigRegex, const OnigUChar* str, const OnigUChar* end, const OnigUChar* global_pos, const OnigUChar* start, const OnigUChar* range, OnigRegion* region, OnigOptionType option); ONIG_EXTERN OnigPosition onig_match(OnigRegex, const OnigUChar* str, const OnigUChar* end, const OnigUChar* at, OnigRegion* region, OnigOptionType option); ONIG_EXTERN OnigRegion* onig_region_new(void); ONIG_EXTERN void onig_region_init(OnigRegion* region); ONIG_EXTERN void onig_region_free(OnigRegion* region, int free_self); ONIG_EXTERN void onig_region_copy(OnigRegion* to, const OnigRegion* from); ONIG_EXTERN void onig_region_clear(OnigRegion* region); ONIG_EXTERN int onig_region_resize(OnigRegion* region, int n); ONIG_EXTERN int onig_region_set(OnigRegion* region, int at, int beg, int end); ONIG_EXTERN int onig_name_to_group_numbers(OnigRegex reg, const OnigUChar* name, const OnigUChar* name_end, int** nums); ONIG_EXTERN int onig_name_to_backref_number(OnigRegex reg, const OnigUChar* name, const OnigUChar* name_end, const OnigRegion *region); ONIG_EXTERN int onig_foreach_name(OnigRegex reg, int (*func)(const OnigUChar*, const OnigUChar*,int,int*,OnigRegex,void*), void* arg); ONIG_EXTERN int onig_number_of_names(const OnigRegexType *reg); ONIG_EXTERN int onig_number_of_captures(const OnigRegexType *reg); ONIG_EXTERN int onig_number_of_capture_histories(const OnigRegexType *reg); #ifdef USE_CAPTURE_HISTORY ONIG_EXTERN OnigCaptureTreeNode* onig_get_capture_tree(OnigRegion* region); #endif ONIG_EXTERN int onig_capture_tree_traverse(OnigRegion* region, int at, int(*callback_func)(int,OnigPosition,OnigPosition,int,int,void*), void* arg); ONIG_EXTERN int onig_noname_group_capture_is_active(const OnigRegexType *reg); ONIG_EXTERN OnigEncoding onig_get_encoding(const OnigRegexType *reg); ONIG_EXTERN OnigOptionType onig_get_options(const OnigRegexType *reg); ONIG_EXTERN OnigCaseFoldType onig_get_case_fold_flag(const OnigRegexType *reg); ONIG_EXTERN const OnigSyntaxType* onig_get_syntax(const OnigRegexType *reg); ONIG_EXTERN int onig_set_default_syntax(const OnigSyntaxType* syntax); ONIG_EXTERN void onig_copy_syntax(OnigSyntaxType* to, const OnigSyntaxType* from); ONIG_EXTERN unsigned int onig_get_syntax_op(const OnigSyntaxType* syntax); ONIG_EXTERN unsigned int onig_get_syntax_op2(const OnigSyntaxType* syntax); ONIG_EXTERN unsigned int onig_get_syntax_behavior(const OnigSyntaxType* syntax); ONIG_EXTERN OnigOptionType onig_get_syntax_options(const OnigSyntaxType* syntax); ONIG_EXTERN void onig_set_syntax_op(OnigSyntaxType* syntax, unsigned int op); ONIG_EXTERN void onig_set_syntax_op2(OnigSyntaxType* syntax, unsigned int op2); ONIG_EXTERN void onig_set_syntax_behavior(OnigSyntaxType* syntax, unsigned int behavior); ONIG_EXTERN void onig_set_syntax_options(OnigSyntaxType* syntax, OnigOptionType options); ONIG_EXTERN int onig_set_meta_char(OnigSyntaxType* syntax, unsigned int what, OnigCodePoint code); ONIG_EXTERN void onig_copy_encoding(OnigEncodingType *to, OnigEncoding from); ONIG_EXTERN OnigCaseFoldType onig_get_default_case_fold_flag(void); ONIG_EXTERN int onig_set_default_case_fold_flag(OnigCaseFoldType case_fold_flag); ONIG_EXTERN unsigned int onig_get_match_stack_limit_size(void); ONIG_EXTERN int onig_set_match_stack_limit_size(unsigned int size); ONIG_EXTERN unsigned int onig_get_parse_depth_limit(void); ONIG_EXTERN int onig_set_parse_depth_limit(unsigned int depth); ONIG_EXTERN int onig_end(void); ONIG_EXTERN const char* onig_version(void); ONIG_EXTERN const char* onig_copyright(void); RUBY_SYMBOL_EXPORT_END #ifdef __cplusplus # if 0 { /* satisfy cc-mode */ # endif } #endif #endif /* ONIGMO_H */ PK!s޷N N backward.hnu[#ifndef RUBY_RUBY_BACKWARD_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_RUBY_BACKWARD_H 1 /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. */ #include "ruby/internal/value.h" #include "ruby/internal/interpreter.h" #include "ruby/backward/2/attributes.h" #define DECLARE_DEPRECATED_FEATURE(ver, func) \ NORETURN(ERRORFUNC(("deprecated since "#ver), DEPRECATED(void func(void)))) /* eval.c */ DECLARE_DEPRECATED_FEATURE(2.2, rb_disable_super); DECLARE_DEPRECATED_FEATURE(2.2, rb_enable_super); /* hash.c */ DECLARE_DEPRECATED_FEATURE(2.2, rb_hash_iter_lev); DECLARE_DEPRECATED_FEATURE(2.2, rb_hash_ifnone); /* string.c */ DECLARE_DEPRECATED_FEATURE(2.2, rb_str_associate); DECLARE_DEPRECATED_FEATURE(2.2, rb_str_associated); /* variable.c */ DEPRECATED(void rb_autoload(VALUE, ID, const char*)); /* vm.c */ DECLARE_DEPRECATED_FEATURE(2.2, rb_clear_cache); DECLARE_DEPRECATED_FEATURE(2.2, rb_frame_pop); #define DECLARE_DEPRECATED_INTERNAL_FEATURE(func) \ NORETURN(ERRORFUNC(("deprecated internal function"), DEPRECATED(void func(void)))) /* eval.c */ NORETURN(ERRORFUNC(("internal function"), void rb_frozen_class_p(VALUE))); DECLARE_DEPRECATED_INTERNAL_FEATURE(rb_exec_end_proc); /* error.c */ DECLARE_DEPRECATED_INTERNAL_FEATURE(rb_compile_error); DECLARE_DEPRECATED_INTERNAL_FEATURE(rb_compile_error_with_enc); DECLARE_DEPRECATED_INTERNAL_FEATURE(rb_compile_error_append); /* gc.c */ DECLARE_DEPRECATED_INTERNAL_FEATURE(rb_gc_call_finalizer_at_exit); /* signal.c */ DECLARE_DEPRECATED_INTERNAL_FEATURE(rb_trap_exit); /* struct.c */ DECLARE_DEPRECATED_INTERNAL_FEATURE(rb_struct_ptr); /* thread.c */ DECLARE_DEPRECATED_INTERNAL_FEATURE(rb_clear_trace_func); /* variable.c */ DECLARE_DEPRECATED_INTERNAL_FEATURE(rb_generic_ivar_table); NORETURN(ERRORFUNC(("internal function"), VALUE rb_mod_const_missing(VALUE, VALUE))); /* from version.c */ #if defined(RUBY_SHOW_COPYRIGHT_TO_DIE) && !!(RUBY_SHOW_COPYRIGHT_TO_DIE+0) /* for source code backward compatibility */ RBIMPL_ATTR_DEPRECATED(("since 2.4")) static inline int ruby_show_copyright_to_die(int exitcode) { ruby_show_copyright(); return exitcode; } #define ruby_show_copyright() /* defer EXIT_SUCCESS */ \ (exit(ruby_show_copyright_to_die(EXIT_SUCCESS))) #endif #endif /* RUBY_RUBY_BACKWARD_H */ PK!backward/2/stdarg.hnu[#ifndef RUBY_BACKWARD2_STDARG_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_BACKWARD2_STDARG_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines old #_ * * Nobody should ever use these macros any longer. No konwn compilers lack * prototypes today. It's 21st century. Just forget them. */ #undef _ #ifdef HAVE_PROTOTYPES # define _(args) args #else # define _(args) () #endif #undef __ #ifdef HAVE_STDARG_PROTOTYPES # define __(args) args #else # define __(args) () #endif #ifdef __cplusplus #define ANYARGS ... #else #define ANYARGS #endif #endif /* RUBY_BACKWARD2_STDARG_H */ PK!51..backward/2/inttypes.hnu[#ifndef RUBY_BACKWARD2_INTTYPES_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_BACKWARD2_INTTYPES_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief C99 shim for `` */ #include "ruby/internal/config.h" /* PRI_LL_PREFIX etc. are here */ #ifdef HAVE_INTTYPES_H # include #endif #include "ruby/internal/value.h" /* PRI_VALUE_PREFIX is here. */ #ifndef PRI_INT_PREFIX # define PRI_INT_PREFIX "" #endif #ifndef PRI_LONG_PREFIX # define PRI_LONG_PREFIX "l" #endif #ifndef PRI_SHORT_PREFIX # define PRI_SHORT_PREFIX "h" #endif #ifdef PRI_64_PREFIX # /* Take that. */ #elif SIZEOF_LONG == 8 # define PRI_64_PREFIX PRI_LONG_PREFIX #elif SIZEOF_LONG_LONG == 8 # define PRI_64_PREFIX PRI_LL_PREFIX #endif #ifndef PRIdPTR # define PRIdPTR PRI_PTR_PREFIX"d" # define PRIiPTR PRI_PTR_PREFIX"i" # define PRIoPTR PRI_PTR_PREFIX"o" # define PRIuPTR PRI_PTR_PREFIX"u" # define PRIxPTR PRI_PTR_PREFIX"x" # define PRIXPTR PRI_PTR_PREFIX"X" #endif #ifndef RUBY_PRI_VALUE_MARK # define RUBY_PRI_VALUE_MARK "\v" #endif #if defined PRIdPTR && !defined PRI_VALUE_PREFIX # define PRIdVALUE PRIdPTR # define PRIoVALUE PRIoPTR # define PRIuVALUE PRIuPTR # define PRIxVALUE PRIxPTR # define PRIXVALUE PRIXPTR # define PRIsVALUE PRIiPTR"" RUBY_PRI_VALUE_MARK #else # define PRIdVALUE PRI_VALUE_PREFIX"d" # define PRIoVALUE PRI_VALUE_PREFIX"o" # define PRIuVALUE PRI_VALUE_PREFIX"u" # define PRIxVALUE PRI_VALUE_PREFIX"x" # define PRIXVALUE PRI_VALUE_PREFIX"X" # define PRIsVALUE PRI_VALUE_PREFIX"i" RUBY_PRI_VALUE_MARK #endif #ifndef PRI_VALUE_PREFIX # define PRI_VALUE_PREFIX "" #endif #ifdef PRI_TIMET_PREFIX # /* Take that. */ #elif SIZEOF_TIME_T == SIZEOF_INT # define PRI_TIMET_PREFIX #elif SIZEOF_TIME_T == SIZEOF_LONG # define PRI_TIMET_PREFIX "l" #elif SIZEOF_TIME_T == SIZEOF_LONG_LONG # define PRI_TIMET_PREFIX PRI_LL_PREFIX #endif #ifdef PRI_PTRDIFF_PREFIX # /* Take that. */ #elif SIZEOF_PTRDIFF_T == SIZEOF_INT # define PRI_PTRDIFF_PREFIX "" #elif SIZEOF_PTRDIFF_T == SIZEOF_LONG # define PRI_PTRDIFF_PREFIX "l" #elif SIZEOF_PTRDIFF_T == SIZEOF_LONG_LONG # define PRI_PTRDIFF_PREFIX PRI_LL_PREFIX #endif #ifndef PRIdPTRDIFF # define PRIdPTRDIFF PRI_PTRDIFF_PREFIX"d" # define PRIiPTRDIFF PRI_PTRDIFF_PREFIX"i" # define PRIoPTRDIFF PRI_PTRDIFF_PREFIX"o" # define PRIuPTRDIFF PRI_PTRDIFF_PREFIX"u" # define PRIxPTRDIFF PRI_PTRDIFF_PREFIX"x" # define PRIXPTRDIFF PRI_PTRDIFF_PREFIX"X" #endif #ifdef PRI_SIZE_PREFIX # /* Take that. */ #elif SIZEOF_SIZE_T == SIZEOF_INT # define PRI_SIZE_PREFIX "" #elif SIZEOF_SIZE_T == SIZEOF_LONG # define PRI_SIZE_PREFIX "l" #elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG # define PRI_SIZE_PREFIX PRI_LL_PREFIX #endif #ifndef PRIdSIZE # define PRIdSIZE PRI_SIZE_PREFIX"d" # define PRIiSIZE PRI_SIZE_PREFIX"i" # define PRIoSIZE PRI_SIZE_PREFIX"o" # define PRIuSIZE PRI_SIZE_PREFIX"u" # define PRIxSIZE PRI_SIZE_PREFIX"x" # define PRIXSIZE PRI_SIZE_PREFIX"X" #endif #endif /* RUBY_BACKWARD2_INTTYPES_H */ PK!4́backward/2/r_cast.hnu[#ifndef RUBY_BACKWARD2_R_CAST_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_BACKWARD2_R_CAST_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines old #R_CAST * * Nobody is actively using this macro. */ #define R_CAST(st) (struct st*) #define RMOVED(obj) (R_CAST(RMoved)(obj)) #if defined(__GNUC__) # warning R_CAST and RMOVED are deprecated #elif defined(_MSC_VER) # pragma message("warning: R_CAST and RMOVED are deprecated") #endif #endif /* RUBY_BACKWARD2_R_CAST_H */ PK!pbackward/2/stdalign.hnu[#ifndef RUBY_BACKWARD2_STDALIGN_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_BACKWARD2_STDALIGN_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RUBY_ALIGNAS / #RUBY_ALIGNOF */ #include "ruby/internal/stdalign.h" #undef RUBY_ALIGNAS #undef RUBY_ALIGNOF #define RUBY_ALIGNAS RBIMPL_ALIGNAS #define RUBY_ALIGNOF RBIMPL_ALIGNOF #endif /* RUBY_BACKWARD2_STDALIGN_H */ PK!Qvvbackward/2/gcc_version_since.hnu[#ifndef RUBY_BACKWARD2_GCC_VERSION_SINCE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_BACKWARD2_GCC_VERSION_SINCE_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines old #GCC_VERSION_SINCE */ #include "ruby/internal/compiler_since.h" #ifndef GCC_VERSION_SINCE #define GCC_VERSION_SINCE(x, y, z) RBIMPL_COMPILER_SINCE(GCC, (x), (y), (z)) #endif #ifndef GCC_VERSION_BEFORE #define GCC_VERSION_BEFORE(x, y, z) \ (RBIMPL_COMPILER_BEFORE(GCC, (x), (y), (z)) || \ (RBIMPL_COMPILER_IS(GCC) && \ ((RBIMPL_COMPILER_VERSION_MAJOR == (x)) && \ ((RBIMPL_COMPILER_VERSION_MINOR == (y)) && \ (RBIMPL_COMPILER_VERSION_PATCH == (z)))))) #endif #endif /* RUBY_BACKWARD2_GCC_VERSION_SINCE_H */ PK!0v backward/2/limits.hnu[#ifndef RUBY_BACKWARD2_LIMITS_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_BACKWARD2_LIMITS_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Historical shim for ``. * * The macros in this header file are obsolescent. Does anyone really need our * own definition of #CHAR_BIT today? */ #include "ruby/internal/config.h" #ifdef HAVE_LIMITS_H # include #endif #include "ruby/backward/2/long_long.h" #ifndef LONG_MAX # /* assuming 32bit(2's complement) long */ # define LONG_MAX 2147483647L #endif #ifndef LONG_MIN # define LONG_MIN (-LONG_MAX-1) #endif #ifndef CHAR_BIT # define CHAR_BIT 8 #endif #ifdef LLONG_MAX # /* Take that. */ #elif defined(LONG_LONG_MAX) # define LLONG_MAX LONG_LONG_MAX #elif defined(_I64_MAX) # define LLONG_MAX _I64_MAX #else # /* assuming 64bit(2's complement) long long */ # define LLONG_MAX 9223372036854775807LL #endif #ifdef LLONG_MIN # /* Take that. */ #elif defined(LONG_LONG_MIN) # define LLONG_MIN LONG_LONG_MIN #elif defined(_I64_MAX) # define LLONG_MIN _I64_MIN #else # define LLONG_MIN (-LLONG_MAX-1) #endif #ifdef SIZE_MAX # /* Take that. */ #elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG # define SIZE_MAX ULLONG_MAX # define SIZE_MIN ULLONG_MIN #elif SIZEOF_SIZE_T == SIZEOF_LONG # define SIZE_MAX ULONG_MAX # define SIZE_MIN ULONG_MIN #elif SIZEOF_SIZE_T == SIZEOF_INT # define SIZE_MAX UINT_MAX # define SIZE_MIN UINT_MIN #else # define SIZE_MAX USHRT_MAX # define SIZE_MIN USHRT_MIN #endif #ifdef SSIZE_MAX # /* Take that. */ #elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG # define SSIZE_MAX LLONG_MAX # define SSIZE_MIN LLONG_MIN #elif SIZEOF_SIZE_T == SIZEOF_LONG # define SSIZE_MAX LONG_MAX # define SSIZE_MIN LONG_MIN #elif SIZEOF_SIZE_T == SIZEOF_INT # define SSIZE_MAX INT_MAX # define SSIZE_MIN INT_MIN #else # define SSIZE_MAX SHRT_MAX # define SSIZE_MIN SHRT_MIN #endif #endif /* RUBY_BACKWARD2_LIMITS_H */ PK! backward/2/rmodule.hnu[#ifndef RUBY_BACKWARD2_RMODULE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_BACKWARD2_RMODULE_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Orphan macros. * * These macros seems broken since at least 2011. Nobody (except ruby itself * who is implementing the internals) could have used those macros for a while. * Kept public as-is here to keep some theoretical backwards compatibility. */ #define RMODULE_IV_TBL(m) RCLASS_IV_TBL(m) #define RMODULE_CONST_TBL(m) RCLASS_CONST_TBL(m) #define RMODULE_M_TBL(m) RCLASS_M_TBL(m) #define RMODULE_SUPER(m) RCLASS_SUPER(m) #if defined(__GNUC__) # warning RMODULE_* macros are deprecated #elif defined(_MSC_VER) # pragma message("warning: RMODULE_* macros are deprecated") #endif #endif /* RUBY_BACKWARD2_RMODULE_H */ PK!nbackward/2/assume.hnu[#ifndef RUBY_BACKWARD2_ASSUME_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_BACKWARD2_ASSUME_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #ASSUME / #RB_LIKELY / #UNREACHABLE */ #include "ruby/internal/config.h" #include "ruby/internal/assume.h" #include "ruby/internal/has/builtin.h" #undef ASSUME /* Kill config.h definition */ #undef UNREACHABLE /* Kill config.h definition */ #define ASSUME RBIMPL_ASSUME #define UNREACHABLE RBIMPL_UNREACHABLE() #define UNREACHABLE_RETURN RBIMPL_UNREACHABLE_RETURN /* likely */ #if RBIMPL_HAS_BUILTIN(__builtin_expect) # define RB_LIKELY(x) (__builtin_expect(!!(x), 1)) # define RB_UNLIKELY(x) (__builtin_expect(!!(x), 0)) #else # define RB_LIKELY(x) (x) # define RB_UNLIKELY(x) (x) #endif #endif /* RUBY_BACKWARD2_ASSUME_H */ PK! < backward/2/long_long.hnu[#ifndef RUBY_BACKWARD2_LONG_LONG_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_BACKWARD2_LONG_LONG_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines old #LONG_LONG * * No known compiler that can compile today's ruby lacks long long. * Historically MSVC was one of such compiler, but it implemented long long a * while ago (some time back in 2013). The macros are for backwards * compatibility only. */ #include "ruby/internal/config.h" #include "ruby/internal/has/warning.h" #include "ruby/internal/warning_push.h" #if RBIMPL_HAS_WARNING("-Wc++11-long-long") # define HAVE_TRUE_LONG_LONG 1 # define LONG_LONG \ RBIMPL_WARNING_PUSH() \ RBIMPL_WARNING_IGNORED(-Wc++11-long-long) \ long long \ RBIMPL_WARNING_POP() #elif RBIMPL_HAS_WARNING("-Wlong-long") # define HAVE_TRUE_LONG_LONG 1 # define LONG_LONG \ RBIMPL_WARNING_PUSH() \ RBIMPL_WARNING_IGNORED(-Wlong-long) \ long long \ RBIMPL_WARNING_POP() #elif defined(HAVE_LONG_LONG) # define HAVE_TRUE_LONG_LONG 1 # define LONG_LONG long long #elif SIZEOF___INT64 > 0 # define HAVE_LONG_LONG 1 # define LONG_LONG __int64 # undef SIZEOF_LONG_LONG # define SIZEOF_LONG_LONG SIZEOF___INT64 #else # error Hello! Ruby developers believe this message must not happen. # error If you encounter this message, can you file a bug report? # error Remember to attach a detailed description of your environment. # error Thank you! #endif #endif /* RBIMPL_BACKWARD2_LONG_LONG_H */ PK!0 Ѧbackward/2/attributes.hnu[#ifndef RUBY_BACKWARD2_ATTRIBUTES_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_BACKWARD2_ATTRIBUTES_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Various attribute-related macros. * * ### Q&A ### * * - Q: Why are the macros defined in this header file so inconsistent in * style? * * - A: Don't know. Don't blame me. Backward compatibility is the key here. * I'm just preserving what they have been. */ #include "ruby/internal/config.h" #include "ruby/internal/attr/alloc_size.h" #include "ruby/internal/attr/cold.h" #include "ruby/internal/attr/const.h" #include "ruby/internal/attr/deprecated.h" #include "ruby/internal/attr/error.h" #include "ruby/internal/attr/forceinline.h" #include "ruby/internal/attr/format.h" #include "ruby/internal/attr/maybe_unused.h" #include "ruby/internal/attr/noinline.h" #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/attr/noreturn.h" #include "ruby/internal/attr/pure.h" #include "ruby/internal/attr/restrict.h" #include "ruby/internal/attr/returns_nonnull.h" #include "ruby/internal/attr/warning.h" #include "ruby/internal/has/attribute.h" /* function attributes */ #undef CONSTFUNC #define CONSTFUNC(x) RBIMPL_ATTR_CONST() x #undef PUREFUNC #define PUREFUNC(x) RBIMPL_ATTR_PURE() x #undef DEPRECATED #define DEPRECATED(x) RBIMPL_ATTR_DEPRECATED(("")) x #undef DEPRECATED_BY #define DEPRECATED_BY(n,x) RBIMPL_ATTR_DEPRECATED(("by: " # n)) x #undef DEPRECATED_TYPE #if defined(__GNUC__) # define DEPRECATED_TYPE(mesg, decl) \ _Pragma("message \"DEPRECATED_TYPE is deprecated\""); \ decl RBIMPL_ATTR_DEPRECATED(mseg) #elif defined(_MSC_VER) # pragma deprecated(DEPRECATED_TYPE) # define DEPRECATED_TYPE(mesg, decl) \ __pragma(message(__FILE__"("STRINGIZE(__LINE__)"): warning: " \ "DEPRECATED_TYPE is deprecated")) \ decl RBIMPL_ATTR_DEPRECATED(mseg) #else # define DEPRECATED_TYPE(mesg, decl) \ <-<-"DEPRECATED_TYPE is deprecated"->-> #endif #undef RUBY_CXX_DEPRECATED #define RUBY_CXX_DEPRECATED(mseg) RBIMPL_ATTR_DEPRECATED((mseg)) #undef NOINLINE #define NOINLINE(x) RBIMPL_ATTR_NOINLINE() x #ifndef MJIT_HEADER # undef ALWAYS_INLINE # define ALWAYS_INLINE(x) RBIMPL_ATTR_FORCEINLINE() x #endif #undef ERRORFUNC #define ERRORFUNC(mesg, x) RBIMPL_ATTR_ERROR(mesg) x #if RBIMPL_HAS_ATTRIBUTE(error) # define HAVE_ATTRIBUTE_ERRORFUNC 1 #else # define HAVE_ATTRIBUTE_ERRORFUNC 0 #endif #undef WARNINGFUNC #define WARNINGFUNC(mesg, x) RBIMPL_ATTR_WARNING(mesg) x #if RBIMPL_HAS_ATTRIBUTE(warning) # define HAVE_ATTRIBUTE_WARNINGFUNC 1 #else # define HAVE_ATTRIBUTE_WARNINGFUNC 0 #endif /* cold attribute for code layout improvements RUBY_FUNC_ATTRIBUTE not used because MSVC does not like nested func macros */ #undef COLDFUNC #define COLDFUNC RBIMPL_ATTR_COLD() #define PRINTF_ARGS(decl, string_index, first_to_check) \ RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, (string_index), (first_to_check)) \ decl #undef RUBY_ATTR_ALLOC_SIZE #define RUBY_ATTR_ALLOC_SIZE RBIMPL_ATTR_ALLOC_SIZE #undef RUBY_ATTR_MALLOC #define RUBY_ATTR_MALLOC RBIMPL_ATTR_RESTRICT() #undef RUBY_ATTR_RETURNS_NONNULL #define RUBY_ATTR_RETURNS_NONNULL RBIMPL_ATTR_RETURNS_NONNULL() #ifndef FUNC_MINIMIZED #define FUNC_MINIMIZED(x) x #endif #ifndef FUNC_UNOPTIMIZED #define FUNC_UNOPTIMIZED(x) x #endif #ifndef RUBY_ALIAS_FUNCTION_TYPE #define RUBY_ALIAS_FUNCTION_TYPE(type, prot, name, args) \ FUNC_MINIMIZED(type prot) {return (type)name args;} #endif #ifndef RUBY_ALIAS_FUNCTION_VOID #define RUBY_ALIAS_FUNCTION_VOID(prot, name, args) \ FUNC_MINIMIZED(void prot) {name args;} #endif #ifndef RUBY_ALIAS_FUNCTION #define RUBY_ALIAS_FUNCTION(prot, name, args) \ RUBY_ALIAS_FUNCTION_TYPE(VALUE, prot, name, args) #endif #undef RUBY_FUNC_NONNULL #define RUBY_FUNC_NONNULL(n, x) RBIMPL_ATTR_NONNULL(n) x #undef NORETURN #define NORETURN(x) RBIMPL_ATTR_NORETURN() x #define NORETURN_STYLE_NEW #ifndef PACKED_STRUCT # define PACKED_STRUCT(x) x #endif #ifndef PACKED_STRUCT_UNALIGNED # if UNALIGNED_WORD_ACCESS # define PACKED_STRUCT_UNALIGNED(x) PACKED_STRUCT(x) # else # define PACKED_STRUCT_UNALIGNED(x) x # endif #endif #undef RB_UNUSED_VAR #define RB_UNUSED_VAR(x) x RBIMPL_ATTR_MAYBE_UNUSED() #endif /* RUBY_BACKWARD2_ATTRIBUTES_H */ PK!H33backward/2/bool.hnu[#ifndef RUBY_BACKWARD2_BOOL_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_BACKWARD2_BOOL_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines old #TRUE / #FALSE */ #include "ruby/internal/stdbool.h" #ifndef FALSE # define FALSE false #elif FALSE # error FALSE must be false #endif #ifndef TRUE # define TRUE true #elif ! TRUE # error TRUE must be true #endif #endif /* RUBY_BACKWARD2_BOOL_H */ PK!%f5u5ubackward/cxxanyargs.hppnu[#ifndef RUBY_BACKWARD_CXXANYARGS_HPP //-*-C++-*-vi:ft=cpp #define RUBY_BACKWARD_CXXANYARGS_HPP /// @file /// @author \@shyouhei /// @copyright This file is a part of the programming language Ruby. /// Permission is hereby granted, to either redistribute and/or /// modify this file, provided that the conditions mentioned in the /// file COPYING are met. Consult the file for details. /// @note DO NOT MODERNIZE THIS FILE! As the file name implies it is /// meant to be a backwards compatibility shim. Please stick to /// C++ 98 and never use newer features, like `constexpr`. /// @brief Provides old prototypes for C++ programs. #include "ruby/internal/config.h" #include "ruby/internal/intern/class.h" #include "ruby/internal/intern/cont.h" #include "ruby/internal/intern/hash.h" #include "ruby/internal/intern/proc.h" #include "ruby/internal/intern/thread.h" #include "ruby/internal/intern/variable.h" #include "ruby/internal/intern/vm.h" #include "ruby/internal/iterator.h" #include "ruby/internal/method.h" #include "ruby/internal/value.h" #include "ruby/internal/variable.h" #include "ruby/backward/2/stdarg.h" #include "ruby/st.h" extern "C++" { #ifdef HAVE_NULLPTR #include #endif /// @brief The main namespace. /// @note The name "ruby" might already be taken, but that must not be a /// problem because namespaces are allowed to reopen. namespace ruby { /// Backwards compatibility layer. namespace backward { /// Provides ANYARGS deprecation warnings. In C, ANYARGS means there is no /// function prototype. Literally anything, even including nothing, can be a /// valid ANYARGS. So passing a correctly prototyped function pointer to an /// ANYARGS-ed function parameter is valid, at the same time passing an /// ANYARGS-ed function pointer to a granular typed function parameter is also /// valid. However on the other hand in C++, ANYARGS doesn't actually mean any /// number of arguments. C++'s ANYARGS means _variadic_ number of arguments. /// This is incompatible with ordinal, correct function prototypes. /// /// Luckily, function prototypes being distinct each other means they can be /// overloaded. We can provide a compatibility layer for older Ruby APIs which /// used to have ANYARGS. This namespace includes such attempts. namespace cxxanyargs { typedef VALUE type(ANYARGS); ///< ANYARGS-ed function type. typedef void void_type(ANYARGS); ///< ANYARGS-ed function type, void variant. typedef int int_type(ANYARGS); ///< ANYARGS-ed function type, int variant. typedef VALUE onearg_type(VALUE); ///< Single-argumented function type. /// @name Hooking global variables /// @{ RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @brief Define a function-backended global variable. /// @param[in] q Name of the variable. /// @param[in] w Getter function. /// @param[in] e Setter function. /// @note Both functions can be nullptr. /// @see rb_define_hooked_variable() /// @deprecated Use glanular typed overload instead. inline void rb_define_virtual_variable(const char *q, type *w, void_type *e) { rb_gvar_getter_t *r = reinterpret_cast(w); rb_gvar_setter_t *t = reinterpret_cast(e); ::rb_define_virtual_variable(q, r, t); } RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") inline void rb_define_virtual_variable(const char *q, rb_gvar_getter_t *w, void_type *e) { rb_gvar_setter_t *t = reinterpret_cast(e); ::rb_define_virtual_variable(q, w, t); } RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") inline void rb_define_virtual_variable(const char *q, type *w, rb_gvar_setter_t *e) { rb_gvar_getter_t *r = reinterpret_cast(w); ::rb_define_virtual_variable(q, r, e); } #ifdef HAVE_NULLPTR inline void rb_define_virtual_variable(const char *q, rb_gvar_getter_t *w, std::nullptr_t e) { ::rb_define_virtual_variable(q, w, e); } RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") inline void rb_define_virtual_variable(const char *q, type *w, std::nullptr_t e) { rb_gvar_getter_t *r = reinterpret_cast(w); ::rb_define_virtual_variable(q, r, e); } inline void rb_define_virtual_variable(const char *q, std::nullptr_t w, rb_gvar_setter_t *e) { ::rb_define_virtual_variable(q, w, e); } RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") inline void rb_define_virtual_variable(const char *q, std::nullptr_t w, void_type *e) { rb_gvar_setter_t *r = reinterpret_cast(e); ::rb_define_virtual_variable(q, w, r); } #endif RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @brief Define a function-backended global variable. /// @param[in] q Name of the variable. /// @param[in] w Variable storage. /// @param[in] e Getter function. /// @param[in] r Setter function. /// @note Both functions can be nullptr. /// @see rb_define_virtual_variable() /// @deprecated Use glanular typed overload instead. inline void rb_define_hooked_variable(const char *q, VALUE *w, type *e, void_type *r) { rb_gvar_getter_t *t = reinterpret_cast(e); rb_gvar_setter_t *y = reinterpret_cast(r); ::rb_define_hooked_variable(q, w, t, y); } RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") inline void rb_define_hooked_variable(const char *q, VALUE *w, rb_gvar_getter_t *e, void_type *r) { rb_gvar_setter_t *y = reinterpret_cast(r); ::rb_define_hooked_variable(q, w, e, y); } RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") inline void rb_define_hooked_variable(const char *q, VALUE *w, type *e, rb_gvar_setter_t *r) { rb_gvar_getter_t *t = reinterpret_cast(e); ::rb_define_hooked_variable(q, w, t, r); } #ifdef HAVE_NULLPTR inline void rb_define_hooked_variable(const char *q, VALUE *w, rb_gvar_getter_t *e, std::nullptr_t r) { ::rb_define_hooked_variable(q, w, e, r); } RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") inline void rb_define_hooked_variable(const char *q, VALUE *w, type *e, std::nullptr_t r) { rb_gvar_getter_t *y = reinterpret_cast(e); ::rb_define_hooked_variable(q, w, y, r); } inline void rb_define_hooked_variable(const char *q, VALUE *w, std::nullptr_t e, rb_gvar_setter_t *r) { ::rb_define_hooked_variable(q, w, e, r); } RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") inline void rb_define_hooked_variable(const char *q, VALUE *w, std::nullptr_t e, void_type *r) { rb_gvar_setter_t *y = reinterpret_cast(r); ::rb_define_hooked_variable(q, w, e, y); } #endif /// @} /// @name Exceptions and tag jumps /// @{ RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @brief Old way to implement iterators. /// @param[in] q A function that can yield. /// @param[in] w Passed to `q`. /// @param[in] e What is to be yielded. /// @param[in] r Passed to `e`. /// @return The return value of `q`. /// @note `e` can be nullptr. /// @deprecated This function is obsolated since long before 2.x era. Do not /// use it any longer. rb_block_call() is provided instead. inline VALUE rb_iterate(onearg_type *q, VALUE w, type *e, VALUE r) { rb_block_call_func_t t = reinterpret_cast(e); return ::rb_iterate(q, w, t, r); } #ifdef HAVE_NULLPTR inline VALUE rb_iterate(onearg_type *q, VALUE w, std::nullptr_t e, VALUE r) { return ::rb_iterate(q, w, e, r); } #endif RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @brief Call a method with a block. /// @param[in] q The self. /// @param[in] w The method. /// @param[in] e The # of elems of `r` /// @param[in] r The arguments. /// @param[in] t What is to be yielded. /// @param[in] y Passed to `t` /// @return Return value of `q#w(*r,&t)` /// @note 't' can be nullptr. /// @deprecated Use glanular typed overload instead. inline VALUE rb_block_call(VALUE q, ID w, int e, const VALUE *r, type *t, VALUE y) { rb_block_call_func_t u = reinterpret_cast(t); return ::rb_block_call(q, w, e, r, u, y); } #ifdef HAVE_NULLPTR inline VALUE rb_block_call(VALUE q, ID w, int e, const VALUE *r, std::nullptr_t t, VALUE y) { return ::rb_block_call(q, w, e, r, t, y); } #endif RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @brief An equivalent of `rescue` clause. /// @param[in] q A function that can raise. /// @param[in] w Passed to `q`. /// @param[in] e A function that cleans-up. /// @param[in] r Passed to `e`. /// @return The return value of `q` if no exception occurs, or the return /// value of `e` if otherwise. /// @note `e` can be nullptr. /// @see rb_ensure() /// @see rb_rescue2() /// @see rb_protect() /// @deprecated Use glanular typed overload instead. inline VALUE rb_rescue(type *q, VALUE w, type *e, VALUE r) { typedef VALUE func1_t(VALUE); typedef VALUE func2_t(VALUE, VALUE); func1_t *t = reinterpret_cast(q); func2_t *y = reinterpret_cast(e); return ::rb_rescue(t, w, y, r); } RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @brief An equivalent of `rescue` clause. /// @param[in] q A function that can raise. /// @param[in] w Passed to `q`. /// @param[in] e A function that cleans-up. /// @param[in] r Passed to `e`. /// @param[in] ... 0-terminated list of subclass of @ref rb_eException. /// @return The return value of `q` if no exception occurs, or the return /// value of `e` if otherwise. /// @note `e` can be nullptr. /// @see rb_ensure() /// @see rb_rescue() /// @see rb_protect() /// @deprecated Use glanular typed overload instead. inline VALUE rb_rescue2(type *q, VALUE w, type *e, VALUE r, ...) { typedef VALUE func1_t(VALUE); typedef VALUE func2_t(VALUE, VALUE); func1_t *t = reinterpret_cast(q); func2_t *y = reinterpret_cast(e); va_list ap; va_start(ap, r); VALUE ret = ::rb_vrescue2(t, w, y, r, ap); va_end(ap); return ret; } RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @brief An equivalent of `ensure` clause. /// @param[in] q A function that can raise. /// @param[in] w Passed to `q`. /// @param[in] e A function that ensures. /// @param[in] r Passed to `e`. /// @return The return value of `q`. /// @note It makes no sense to pass nullptr to `e`. /// @see rb_rescue() /// @see rb_rescue2() /// @see rb_protect() /// @deprecated Use glanular typed overload instead. inline VALUE rb_ensure(type *q, VALUE w, type *e, VALUE r) { typedef VALUE func1_t(VALUE); func1_t *t = reinterpret_cast(q); func1_t *y = reinterpret_cast(e); return ::rb_ensure(t, w, y, r); } RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @brief An equivalent of `Kernel#catch`. /// @param[in] q The "tag" string. /// @param[in] w A function that can throw. /// @param[in] e Passed to `w`. /// @return What was thrown. /// @note `q` can be a nullptr but makes no sense to pass nullptr to`w`. /// @see rb_block_call() /// @see rb_protect() /// @see rb_rb_catch_obj() /// @see rb_rescue() /// @deprecated Use glanular typed overload instead. inline VALUE rb_catch(const char *q, type *w, VALUE e) { rb_block_call_func_t r = reinterpret_cast(w); return ::rb_catch(q, r, e); } #ifdef HAVE_NULLPTR inline VALUE rb_catch(const char *q, std::nullptr_t w, VALUE e) { return ::rb_catch(q, w, e); } #endif RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @brief An equivalent of `Kernel#catch`. /// @param[in] q The "tag" object. /// @param[in] w A function that can throw. /// @param[in] e Passed to `w`. /// @return What was thrown. /// @note It makes no sense to pass nullptr to`w`. /// @see rb_block_call() /// @see rb_protect() /// @see rb_rb_catch_obj() /// @see rb_rescue() /// @deprecated Use glanular typed overload instead. inline VALUE rb_catch_obj(VALUE q, type *w, VALUE e) { rb_block_call_func_t r = reinterpret_cast(w); return ::rb_catch_obj(q, r, e); } /// @} /// @name Procs, Fibers and Threads /// @{ RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @brief Creates a @ref rb_cFiber instance. /// @param[in] q The fiber body. /// @param[in] w Passed to `q`. /// @return What was allocated. /// @note It makes no sense to pass nullptr to`q`. /// @see rb_proc_new() /// @see rb_thread_creatr() /// @deprecated Use glanular typed overload instead. inline VALUE rb_fiber_new(type *q, VALUE w) { rb_block_call_func_t e = reinterpret_cast(q); return ::rb_fiber_new(e, w); } RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @brief Creates a @ref rb_cProc instance. /// @param[in] q The proc body. /// @param[in] w Passed to `q`. /// @return What was allocated. /// @note It makes no sense to pass nullptr to`q`. /// @see rb_fiber_new() /// @see rb_thread_creatr() /// @deprecated Use glanular typed overload instead. inline VALUE rb_proc_new(type *q, VALUE w) { rb_block_call_func_t e = reinterpret_cast(q); return ::rb_proc_new(e, w); } RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @brief Creates a @ref rb_cThread instance. /// @param[in] q The thread body. /// @param[in] w Passed to `q`. /// @return What was allocated. /// @note It makes no sense to pass nullptr to`q`. /// @see rb_proc_new() /// @see rb_fiber_new() /// @deprecated Use glanular typed overload instead. inline VALUE rb_thread_create(type *q, void *w) { typedef VALUE ptr_t(void*); ptr_t *e = reinterpret_cast(q); return ::rb_thread_create(e, w); } /// @} /// @name Hash and st_table /// @{ RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @brief Iteration over the given table. /// @param[in] q A table to scan. /// @param[in] w A function to iterate. /// @param[in] e Passed to `w`. /// @retval 0 Always returns 0. /// @note It makes no sense to pass nullptr to`w`. /// @see st_foreach_check() /// @see rb_hash_foreach() /// @deprecated Use glanular typed overload instead. inline int st_foreach(st_table *q, int_type *w, st_data_t e) { st_foreach_callback_func *r = reinterpret_cast(w); return ::st_foreach(q, r, e); } RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @brief Iteration over the given table. /// @param[in] q A table to scan. /// @param[in] w A function to iterate. /// @param[in] e Passed to `w`. /// @retval 0 Successful end of iteration. /// @retval 1 Element removed during traversing. /// @note It makes no sense to pass nullptr to`w`. /// @see st_foreach() /// @deprecated Use glanular typed overload instead. inline int st_foreach_check(st_table *q, int_type *w, st_data_t e, st_data_t) { st_foreach_check_callback_func *t = reinterpret_cast(w); return ::st_foreach_check(q, t, e, 0); } RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @brief Iteration over the given table. /// @param[in] q A table to scan. /// @param[in] w A function to iterate. /// @param[in] e Passed to `w`. /// @note It makes no sense to pass nullptr to`w`. /// @see st_foreach_check() /// @deprecated Use glanular typed overload instead. inline void st_foreach_safe(st_table *q, int_type *w, st_data_t e) { st_foreach_callback_func *r = reinterpret_cast(w); ::st_foreach_safe(q, r, e); } RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @brief Iteration over the given hash. /// @param[in] q A hash to scan. /// @param[in] w A function to iterate. /// @param[in] e Passed to `w`. /// @note It makes no sense to pass nullptr to`w`. /// @see st_foreach() /// @deprecated Use glanular typed overload instead. inline void rb_hash_foreach(VALUE q, int_type *w, VALUE e) { st_foreach_callback_func *r = reinterpret_cast(w); ::rb_hash_foreach(q, r, e); } RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @brief Iteration over each instance variable of the object. /// @param[in] q An object. /// @param[in] w A function to iterate. /// @param[in] e Passed to `w`. /// @note It makes no sense to pass nullptr to`w`. /// @see st_foreach() /// @deprecated Use glanular typed overload instead. inline void rb_ivar_foreach(VALUE q, int_type *w, VALUE e) { st_foreach_callback_func *r = reinterpret_cast(w); ::rb_ivar_foreach(q, r, e); } /// @} /// Driver for *_define_method. ::rb_define_method function for instance takes /// a pointer to ANYARGS-ed functions, which in fact varies 18 different /// prototypes. We still need to preserve ANYARGS for storages but why not /// check the consistencies if possible. In C++ a function has its own /// prototype, which is a compile-time constant (static type) by nature. We /// can list up all the possible input types and provide warnings for other /// cases. This is such attempt. namespace define_method { /// Type of ::rb_f_notimplement(). typedef VALUE notimpl_type(int, const VALUE *, VALUE, VALUE); /// @brief Template metaprogramming to generate function prototypes. /// @tparam T Type of method id (`ID` or `const char*` in practice). /// @tparam F Definition driver e.g. ::rb_define_method. template struct driver { /// @brief Defines a method /// @tparam N Arity of the function. /// @tparam U The function in question template struct engine { /* :TODO: Following deprecation attribute renders tons of warnings (one * per every method definitions), which is annoying. Of course * annoyance is the core feature of deprecation warnings... But that * could be too much, especially when the warnings happen inside of * machine-generated programs. And SWIG is known to do such thing. * The new (granular) API was introduced in API version 2.7. As of * this writing the version is 2.8. Let's warn this later, some time * during 3.x. Hopefully codes in old (ANYARGS-ed) format should be * less than now. */ #if (RUBY_API_VERSION_MAJOR * 100 + RUBY_API_VERSION_MINOR) >= 301 RUBY_CXX_DEPRECATED("use of ANYARGS is deprecated") #endif /// @copydoc define(VALUE klass, T mid, U func) /// @deprecated Pass corrctly typed function instead. static inline void define(VALUE klass, T mid, type func) { F(klass, mid, func, N); } /// @brief Defines klass#mid as func, whose arity is N. /// @param[in] klass Where the method lives. /// @param[in] mid Name of the method to define. /// @param[in] func Function that implements klass#mid. static inline void define(VALUE klass, T mid, U func) { F(klass, mid, reinterpret_cast(func), N); } /// @copydoc define(VALUE klass, T mid, U func) static inline void define(VALUE klass, T mid, notimpl_type func) { F(klass, mid, reinterpret_cast(func), N); } }; /// @cond INTERNAL_MACRO template struct specific : public engine {}; template struct specific<15, b> : public engine<15, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template struct specific<14, b> : public engine<14, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template struct specific<13, b> : public engine<13, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template struct specific<12, b> : public engine<12, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template struct specific<11, b> : public engine<11, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template struct specific<10, b> : public engine<10, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template struct specific< 9, b> : public engine< 9, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template struct specific< 8, b> : public engine< 8, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template struct specific< 7, b> : public engine< 7, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template struct specific< 6, b> : public engine< 6, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template struct specific< 5, b> : public engine< 5, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template struct specific< 4, b> : public engine< 4, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template struct specific< 3, b> : public engine< 3, VALUE(*)(VALUE, VALUE, VALUE, VALUE)> {}; template struct specific< 2, b> : public engine< 2, VALUE(*)(VALUE, VALUE, VALUE)> {}; template struct specific< 1, b> : public engine< 1, VALUE(*)(VALUE, VALUE)> {}; template struct specific< 0, b> : public engine< 0, VALUE(*)(VALUE)> {}; template struct specific<-1, b> : public engine<-1, VALUE(*)(int argc, VALUE *argv, VALUE self)> { using engine<-1, VALUE(*)(int argc, VALUE *argv, VALUE self)>::define; static inline void define(VALUE c, T m, VALUE(*f)(int argc, const VALUE *argv, VALUE self)) { F(c, m, reinterpret_cast(f), -1); } }; template struct specific<-2, b> : public engine<-2, VALUE(*)(VALUE, VALUE)> {}; /// @endcond }; /* We could perhaps merge this struct into the one above using variadic * template parameters if we could assume C++11, but sadly we cannot. */ template struct driver0 { template struct engine { RUBY_CXX_DEPRECATED("use of ANYARGS is deprecated") static inline void define(T mid, type func) { F(mid, func, N); } static inline void define(T mid, U func) { F(mid, reinterpret_cast(func), N); } static inline void define(T mid, notimpl_type func) { F(mid, reinterpret_cast(func), N); } }; /// @cond INTERNAL_MACRO template struct specific : public engine {}; template struct specific<15, b> : public engine<15, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template struct specific<14, b> : public engine<14, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template struct specific<13, b> : public engine<13, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template struct specific<12, b> : public engine<12, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template struct specific<11, b> : public engine<11, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template struct specific<10, b> : public engine<10, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template struct specific< 9, b> : public engine< 9, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template struct specific< 8, b> : public engine< 8, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template struct specific< 7, b> : public engine< 7, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template struct specific< 6, b> : public engine< 6, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template struct specific< 5, b> : public engine< 5, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template struct specific< 4, b> : public engine< 4, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template struct specific< 3, b> : public engine< 3, VALUE(*)(VALUE, VALUE, VALUE, VALUE)> {}; template struct specific< 2, b> : public engine< 2, VALUE(*)(VALUE, VALUE, VALUE)> {}; template struct specific< 1, b> : public engine< 1, VALUE(*)(VALUE, VALUE)> {}; template struct specific< 0, b> : public engine< 0, VALUE(*)(VALUE)> {}; template struct specific<-1, b> : public engine<-1, VALUE(*)(int argc, VALUE *argv, VALUE self)> { using engine<-1, VALUE(*)(int argc, VALUE *argv, VALUE self)>::define; static inline void define(T m, VALUE(*f)(int argc, const VALUE *argv, VALUE self)) { F(m, reinterpret_cast(f), -1); } }; template struct specific<-2, b> : public engine<-2, VALUE(*)(VALUE, VALUE)> {}; /// @endcond }; struct rb_define_method : public driver {}; ///< Dispatches appropriate driver for ::rb_define_method. struct rb_define_method_id : public driver {}; ///< Dispatches appropriate driver for ::rb_define_method_id. struct rb_define_private_method : public driver {}; ///< Dispatches appropriate driver for ::rb_define_private_method. struct rb_define_protected_method : public driver {}; ///< Dispatches appropriate driver for ::rb_define_protected_method. struct rb_define_singleton_method : public driver {}; ///< Dispatches appropriate driver for ::rb_define_singleton_method. struct rb_define_module_function : public driver {}; ///< Dispatches appropriate driver for ::rb_define_module_function. struct rb_define_global_function : public driver0 {}; ///< Dispatches appropriate driver for ::rb_define_global_function. /// @brief Defines klass\#mid. /// @param klass Where the method lives. /// @copydetails #rb_define_global_function(mid, func, arity) #define rb_define_method(klass, mid, func, arity) ruby::backward::cxxanyargs::define_method::rb_define_method::specific::define(klass, mid, func) /// @copydoc #rb_define_method(klass, mid, func, arity) #define rb_define_method_id(klass, mid, func, arity) ruby::backward::cxxanyargs::define_method::rb_define_method_id::specific::define(klass, mid, func) /// @brief Defines klass\#mid and makes it private. /// @copydetails #rb_define_method(klass, mid, func, arity) #define rb_define_private_method(klass, mid, func, arity) ruby::backward::cxxanyargs::define_method::rb_define_private_method::specific::define(klass, mid, func) /// @brief Defines klass\#mid and makes it protected. /// @copydetails #rb_define_method #define rb_define_protected_method(klass, mid, func, arity) ruby::backward::cxxanyargs::define_method::rb_define_protected_method::specific::define(klass, mid, func) /// @brief Defines klass.mid.(klass, mid, func, arity) /// @copydetails #rb_define_method #define rb_define_singleton_method(klass, mid, func, arity) ruby::backward::cxxanyargs::define_method::rb_define_singleton_method::specific::define(klass, mid, func) /// @brief Defines klass\#mid and makes it a module function. /// @copydetails #rb_define_method(klass, mid, func, arity) #define rb_define_module_function(klass, mid, func, arity) ruby::backward::cxxanyargs::define_method::rb_define_module_function::specific::define(klass, mid, func) /// @brief Defines ::rb_mKernel \#mid. /// @param mid Name of the defining method. /// @param func Implementation of \#mid. /// @param arity Arity of \#mid. #define rb_define_global_function(mid, func, arity) ruby::backward::cxxanyargs::define_method::rb_define_global_function::specific::define(mid, func) }}}}} using namespace ruby::backward::cxxanyargs; #endif // RUBY_BACKWARD_CXXANYARGS_HPP PK!Gnc99 memory_view.hnu[#ifndef RUBY_MEMORY_VIEW_H #define RUBY_MEMORY_VIEW_H 1 /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @brief Memory View. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/stdbool.h" #include "ruby/internal/value.h" #include "ruby/intern.h" enum ruby_memory_view_flags { RUBY_MEMORY_VIEW_SIMPLE = 0, RUBY_MEMORY_VIEW_WRITABLE = (1<<0), RUBY_MEMORY_VIEW_FORMAT = (1<<1), RUBY_MEMORY_VIEW_MULTI_DIMENSIONAL = (1<<2), RUBY_MEMORY_VIEW_STRIDES = (1<<3) | RUBY_MEMORY_VIEW_MULTI_DIMENSIONAL, RUBY_MEMORY_VIEW_ROW_MAJOR = (1<<4) | RUBY_MEMORY_VIEW_STRIDES, RUBY_MEMORY_VIEW_COLUMN_MAJOR = (1<<5) | RUBY_MEMORY_VIEW_STRIDES, RUBY_MEMORY_VIEW_ANY_CONTIGUOUS = RUBY_MEMORY_VIEW_ROW_MAJOR | RUBY_MEMORY_VIEW_COLUMN_MAJOR, RUBY_MEMORY_VIEW_INDIRECT = (1<<6) | RUBY_MEMORY_VIEW_STRIDES, }; typedef struct { char format; unsigned native_size_p: 1; unsigned little_endian_p: 1; size_t offset; size_t size; size_t repeat; } rb_memory_view_item_component_t; typedef struct { /* The original object that has the memory exported via this memory view. * The consumer of this memory view has the responsibility to call rb_gc_mark * for preventing this obj collected by GC. */ VALUE obj; /* The pointer to the exported memory. */ void *data; /* The number of bytes in data. */ ssize_t byte_size; /* true for readonly memory, false for writable memory. */ bool readonly; /* A string to describe the format of an element, or NULL for unsigned bytes. * The format string is a sequence of the following pack-template specifiers: * * c, C, s, s!, S, S!, n, v, i, i!, I, I!, l, l!, L, L!, * N, V, f, e, g, q, q!, Q, Q!, d, E, G, j, J, x * * For example, "dd" for an element that consists of two double values, * and "CCC" for an element that consists of three bytes, such as * an RGB color triplet. * * Also, the value endianness can be explicitly specified by '<' or '>' * following a value type specifier. * * The items are packed contiguously. When you emulate the alignment of * structure members, put '|' at the beginning of the format string, * like "|iqc". On x86_64 Linux ABI, the size of the item by this format * is 24 bytes instead of 13 bytes. */ const char *format; /* The number of bytes in each element. * item_size should equal to rb_memory_view_item_size_from_format(format). */ ssize_t item_size; struct { /* The array of rb_memory_view_item_component_t that describes the * item structure. rb_memory_view_prepare_item_desc and * rb_memory_view_get_item allocate this memory if needed, * and rb_memory_view_release frees it. */ const rb_memory_view_item_component_t *components; /* The number of components in an item. */ size_t length; } item_desc; /* The number of dimension. */ ssize_t ndim; /* ndim size array indicating the number of elements in each dimension. * This can be NULL when ndim == 1. */ const ssize_t *shape; /* ndim size array indicating the number of bytes to skip to go to the * next element in each dimension. */ const ssize_t *strides; /* The offset in each dimension when this memory view exposes a nested array. * Or, NULL when this memory view exposes a flat array. */ const ssize_t *sub_offsets; /* the private data for managing this exported memory */ void *const private; } rb_memory_view_t; typedef bool (* rb_memory_view_get_func_t)(VALUE obj, rb_memory_view_t *view, int flags); typedef bool (* rb_memory_view_release_func_t)(VALUE obj, rb_memory_view_t *view); typedef bool (* rb_memory_view_available_p_func_t)(VALUE obj); typedef struct { rb_memory_view_get_func_t get_func; rb_memory_view_release_func_t release_func; rb_memory_view_available_p_func_t available_p_func; } rb_memory_view_entry_t; RBIMPL_SYMBOL_EXPORT_BEGIN() /* memory_view.c */ bool rb_memory_view_register(VALUE klass, const rb_memory_view_entry_t *entry); RBIMPL_ATTR_PURE() bool rb_memory_view_is_row_major_contiguous(const rb_memory_view_t *view); RBIMPL_ATTR_PURE() bool rb_memory_view_is_column_major_contiguous(const rb_memory_view_t *view); RBIMPL_ATTR_NOALIAS() void rb_memory_view_fill_contiguous_strides(const ssize_t ndim, const ssize_t item_size, const ssize_t *const shape, const bool row_major_p, ssize_t *const strides); RBIMPL_ATTR_NOALIAS() bool rb_memory_view_init_as_byte_array(rb_memory_view_t *view, VALUE obj, void *data, const ssize_t len, const bool readonly); ssize_t rb_memory_view_parse_item_format(const char *format, rb_memory_view_item_component_t **members, size_t *n_members, const char **err); ssize_t rb_memory_view_item_size_from_format(const char *format, const char **err); void *rb_memory_view_get_item_pointer(rb_memory_view_t *view, const ssize_t *indices); VALUE rb_memory_view_extract_item_members(const void *ptr, const rb_memory_view_item_component_t *members, const size_t n_members); void rb_memory_view_prepare_item_desc(rb_memory_view_t *view); VALUE rb_memory_view_get_item(rb_memory_view_t *view, const ssize_t *indices); bool rb_memory_view_available_p(VALUE obj); bool rb_memory_view_get(VALUE obj, rb_memory_view_t* memory_view, int flags); bool rb_memory_view_release(rb_memory_view_t* memory_view); /* for testing */ RUBY_EXTERN VALUE rb_memory_view_exported_object_registry; RUBY_EXTERN const rb_data_type_t rb_memory_view_exported_object_registry_data_type; RBIMPL_SYMBOL_EXPORT_END() RBIMPL_ATTR_PURE() static inline bool rb_memory_view_is_contiguous(const rb_memory_view_t *view) { if (rb_memory_view_is_row_major_contiguous(view)) { return true; } else if (rb_memory_view_is_column_major_contiguous(view)) { return true; } else { return false; } } #endif /* RUBY_BUFFER_H */ PK!᠏debug.hnu[#ifndef RB_DEBUG_H /*-*-C++-*-vi:se ft=cpp:*/ #define RB_DEBUG_H 1 /** * @file * @author $Author: ko1 $ * @date Tue Nov 20 20:35:08 2012 * @copyright Copyright (C) 2012 Yukihiro Matsumoto * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/event.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* Note: This file contains experimental APIs. */ /* APIs can be replaced at Ruby 2.0.1 or later */ /* profile frames APIs */ int rb_profile_frames(int start, int limit, VALUE *buff, int *lines); VALUE rb_profile_frame_path(VALUE frame); VALUE rb_profile_frame_absolute_path(VALUE frame); VALUE rb_profile_frame_label(VALUE frame); VALUE rb_profile_frame_base_label(VALUE frame); VALUE rb_profile_frame_full_label(VALUE frame); VALUE rb_profile_frame_first_lineno(VALUE frame); VALUE rb_profile_frame_classpath(VALUE frame); VALUE rb_profile_frame_singleton_method_p(VALUE frame); VALUE rb_profile_frame_method_name(VALUE frame); VALUE rb_profile_frame_qualified_method_name(VALUE frame); /* debug inspector APIs */ typedef struct rb_debug_inspector_struct rb_debug_inspector_t; typedef VALUE (*rb_debug_inspector_func_t)(const rb_debug_inspector_t *, void *); VALUE rb_debug_inspector_open(rb_debug_inspector_func_t func, void *data); VALUE rb_debug_inspector_frame_self_get(const rb_debug_inspector_t *dc, long index); VALUE rb_debug_inspector_frame_class_get(const rb_debug_inspector_t *dc, long index); VALUE rb_debug_inspector_frame_binding_get(const rb_debug_inspector_t *dc, long index); VALUE rb_debug_inspector_frame_iseq_get(const rb_debug_inspector_t *dc, long index); VALUE rb_debug_inspector_backtrace_locations(const rb_debug_inspector_t *dc); /* Old style set_trace_func APIs */ /* duplicated def of include/ruby/ruby.h */ void rb_add_event_hook(rb_event_hook_func_t func, rb_event_flag_t events, VALUE data); int rb_remove_event_hook(rb_event_hook_func_t func); int rb_remove_event_hook_with_data(rb_event_hook_func_t func, VALUE data); void rb_thread_add_event_hook(VALUE thval, rb_event_hook_func_t func, rb_event_flag_t events, VALUE data); int rb_thread_remove_event_hook(VALUE thval, rb_event_hook_func_t func); int rb_thread_remove_event_hook_with_data(VALUE thval, rb_event_hook_func_t func, VALUE data); /* TracePoint APIs */ VALUE rb_tracepoint_new(VALUE target_thread_not_supported_yet, rb_event_flag_t events, void (*func)(VALUE, void *), void *data); VALUE rb_tracepoint_enable(VALUE tpval); VALUE rb_tracepoint_disable(VALUE tpval); VALUE rb_tracepoint_enabled_p(VALUE tpval); typedef struct rb_trace_arg_struct rb_trace_arg_t; rb_trace_arg_t *rb_tracearg_from_tracepoint(VALUE tpval); rb_event_flag_t rb_tracearg_event_flag(rb_trace_arg_t *trace_arg); VALUE rb_tracearg_event(rb_trace_arg_t *trace_arg); VALUE rb_tracearg_lineno(rb_trace_arg_t *trace_arg); VALUE rb_tracearg_path(rb_trace_arg_t *trace_arg); VALUE rb_tracearg_method_id(rb_trace_arg_t *trace_arg); VALUE rb_tracearg_callee_id(rb_trace_arg_t *trace_arg); VALUE rb_tracearg_defined_class(rb_trace_arg_t *trace_arg); VALUE rb_tracearg_binding(rb_trace_arg_t *trace_arg); VALUE rb_tracearg_self(rb_trace_arg_t *trace_arg); VALUE rb_tracearg_return_value(rb_trace_arg_t *trace_arg); VALUE rb_tracearg_raised_exception(rb_trace_arg_t *trace_arg); VALUE rb_tracearg_object(rb_trace_arg_t *trace_arg); /* * Postponed Job API * rb_postponed_job_register and rb_postponed_job_register_one are * async-signal-safe and used via SIGPROF by the "stackprof" RubyGem */ typedef void (*rb_postponed_job_func_t)(void *arg); int rb_postponed_job_register(unsigned int flags, rb_postponed_job_func_t func, void *data); int rb_postponed_job_register_one(unsigned int flags, rb_postponed_job_func_t func, void *data); /* undocumented advanced tracing APIs */ typedef enum { RUBY_EVENT_HOOK_FLAG_SAFE = 0x01, RUBY_EVENT_HOOK_FLAG_DELETED = 0x02, RUBY_EVENT_HOOK_FLAG_RAW_ARG = 0x04 } rb_event_hook_flag_t; void rb_add_event_hook2(rb_event_hook_func_t func, rb_event_flag_t events, VALUE data, rb_event_hook_flag_t hook_flag); void rb_thread_add_event_hook2(VALUE thval, rb_event_hook_func_t func, rb_event_flag_t events, VALUE data, rb_event_hook_flag_t hook_flag); RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_DEBUG_H */ PK!Cconfig.hnu[/* * Kluge to support multilib installation of both 32- and 64-bit RPMS: * we need to arrange that header files that appear in both RPMs are * identical. Hence, this file is architecture-independent and calls * in an arch-dependent file that will appear in just one RPM. * * To avoid breaking arches not explicitly supported by Red Hat, we * use this indirection file *only* on known multilib arches. * * We pay attention to include _only_ the original multilib-unclean * header file. Including any other system-header file could cause * unpredictable include-ordering issues (rhbz#1412274, comment #16). * * Note: this may well fail if user tries to use gcc's -I- option. * But that option is deprecated anyway. */ #if defined(__x86_64__) #include "config-x86_64.h" #elif defined(__i386__) #include "config-i386.h" #elif defined(__ppc64__) || defined(__powerpc64__) #include "config-ppc64.h" #elif defined(__ppc__) || defined(__powerpc__) #include "config-ppc.h" #elif defined(__s390x__) #include "config-s390x.h" #elif defined(__s390__) #include "config-s390.h" #elif defined(__sparc__) && defined(__arch64__) #include "config-sparc64.h" #elif defined(__sparc__) #include "config-sparc.h" #endif PK!$MUinternal/glob.hnu[#ifndef RBIMPL_GLOB_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_GLOB_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Declares ::rb_glob(). */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() typedef int ruby_glob_func(const char*,VALUE, void*); void rb_glob(const char*,void(*)(const char*,VALUE,void*),VALUE); int ruby_glob(const char*,int,ruby_glob_func*,VALUE); int ruby_brace_glob(const char*,int,ruby_glob_func*,VALUE); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_GLOB_H */ PK!A internal/value.hnu[#ifndef RBIMPL_VALUE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_VALUE_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines ::VALUE and ::ID. */ #include "ruby/internal/static_assert.h" #include "ruby/backward/2/long_long.h" #include "ruby/backward/2/limits.h" #if defined HAVE_UINTPTR_T && 0 typedef uintptr_t VALUE; typedef uintptr_t ID; # define SIGNED_VALUE intptr_t # define SIZEOF_VALUE SIZEOF_UINTPTR_T # undef PRI_VALUE_PREFIX # define RBIMPL_VALUE_NULL UINTPTR_C(0) # define RBIMPL_VALUE_ONE UINTPTR_C(1) # define RBIMPL_VALUE_FULL UINTPTR_MAX #elif SIZEOF_LONG == SIZEOF_VOIDP typedef unsigned long VALUE; typedef unsigned long ID; # define SIGNED_VALUE long # define SIZEOF_VALUE SIZEOF_LONG # define PRI_VALUE_PREFIX "l" # define RBIMPL_VALUE_NULL 0UL # define RBIMPL_VALUE_ONE 1UL # define RBIMPL_VALUE_FULL ULONG_MAX #elif SIZEOF_LONG_LONG == SIZEOF_VOIDP typedef unsigned LONG_LONG VALUE; typedef unsigned LONG_LONG ID; # define SIGNED_VALUE LONG_LONG # define LONG_LONG_VALUE 1 # define SIZEOF_VALUE SIZEOF_LONG_LONG # define PRI_VALUE_PREFIX PRI_LL_PREFIX # define RBIMPL_VALUE_NULL 0ULL # define RBIMPL_VALUE_ONE 1ULL # define RBIMPL_VALUE_FULL ULLONG_MAX #else # error ---->> ruby requires sizeof(void*) == sizeof(long) or sizeof(LONG_LONG) to be compiled. <<---- #endif RBIMPL_STATIC_ASSERT(sizeof_int, SIZEOF_INT == sizeof(int)); RBIMPL_STATIC_ASSERT(sizeof_long, SIZEOF_LONG == sizeof(long)); RBIMPL_STATIC_ASSERT(sizeof_long_long, SIZEOF_LONG_LONG == sizeof(LONG_LONG)); RBIMPL_STATIC_ASSERT(sizeof_voidp, SIZEOF_VOIDP == sizeof(void *)); #endif /* RBIMPL_VALUE_H */ PK!k internal/gc.hnu[#ifndef RBIMPL_GC_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_GC_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Registering values to the GC. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /** * Inform the garbage collector that `valptr` points to a live Ruby object that * should not be moved. Note that extensions should use this API on global * constants instead of assuming constants defined in Ruby are always alive. * Ruby code can remove global constants. */ void rb_gc_register_address(VALUE *valptr); /** * An alias for `rb_gc_register_address()`. */ void rb_global_variable(VALUE *); /** * Inform the garbage collector that a pointer previously passed to * `rb_gc_register_address()` no longer points to a live Ruby object. */ void rb_gc_unregister_address(VALUE *valptr); /** * Inform the garbage collector that `object` is a live Ruby object that should * not be moved. * * See also: rb_gc_register_address() */ void rb_gc_register_mark_object(VALUE object); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_GC_H */ PK!43R R internal/intern/gc.hnu[#ifndef RBIMPL_INTERN_GC_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_GC_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_mGC. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" #include "ruby/backward/2/attributes.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* gc.c */ COLDFUNC NORETURN(void rb_memerror(void)); PUREFUNC(int rb_during_gc(void)); void rb_gc_mark_locations(const VALUE*, const VALUE*); void rb_mark_tbl(struct st_table*); void rb_mark_tbl_no_pin(struct st_table*); void rb_mark_set(struct st_table*); void rb_mark_hash(struct st_table*); void rb_gc_update_tbl_refs(st_table *ptr); void rb_gc_mark_maybe(VALUE); void rb_gc_mark(VALUE); void rb_gc_mark_movable(VALUE); VALUE rb_gc_location(VALUE); void rb_gc_force_recycle(VALUE); void rb_gc(void); void rb_gc_copy_finalizer(VALUE,VALUE); VALUE rb_gc_enable(void); VALUE rb_gc_disable(void); VALUE rb_gc_start(void); VALUE rb_define_finalizer(VALUE, VALUE); VALUE rb_undefine_finalizer(VALUE); size_t rb_gc_count(void); size_t rb_gc_stat(VALUE); VALUE rb_gc_latest_gc_info(VALUE); void rb_gc_adjust_memory_usage(ssize_t); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_GC_H */ PK!{< internal/intern/proc.hnu[#ifndef RBIMPL_INTERN_PROC_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_PROC_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_cProc. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/iterator.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* proc.c */ VALUE rb_block_proc(void); VALUE rb_block_lambda(void); VALUE rb_proc_new(rb_block_call_func_t, VALUE); VALUE rb_obj_is_proc(VALUE); VALUE rb_proc_call(VALUE, VALUE); VALUE rb_proc_call_kw(VALUE, VALUE, int); VALUE rb_proc_call_with_block(VALUE, int argc, const VALUE *argv, VALUE); VALUE rb_proc_call_with_block_kw(VALUE, int argc, const VALUE *argv, VALUE, int); int rb_proc_arity(VALUE); VALUE rb_proc_lambda_p(VALUE); VALUE rb_binding_new(void); VALUE rb_obj_method(VALUE, VALUE); VALUE rb_obj_is_method(VALUE); VALUE rb_method_call(int, const VALUE*, VALUE); VALUE rb_method_call_kw(int, const VALUE*, VALUE, int); VALUE rb_method_call_with_block(int, const VALUE *, VALUE, VALUE); VALUE rb_method_call_with_block_kw(int, const VALUE *, VALUE, VALUE, int); int rb_mod_method_arity(VALUE, ID); int rb_obj_method_arity(VALUE, ID); VALUE rb_protect(VALUE (*)(VALUE), VALUE, int*); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_PROC_H */ PK!vvinternal/intern/re.hnu[#ifndef RBIMPL_INTERN_RE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_RE_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_cRegexp. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* re.c */ #define rb_memcmp memcmp int rb_memcicmp(const void*,const void*,long); void rb_match_busy(VALUE); VALUE rb_reg_nth_defined(int, VALUE); VALUE rb_reg_nth_match(int, VALUE); int rb_reg_backref_number(VALUE match, VALUE backref); VALUE rb_reg_last_match(VALUE); VALUE rb_reg_match_pre(VALUE); VALUE rb_reg_match_post(VALUE); VALUE rb_reg_match_last(VALUE); #define HAVE_RB_REG_NEW_STR 1 VALUE rb_reg_new_str(VALUE, int); VALUE rb_reg_new(const char *, long, int); VALUE rb_reg_alloc(void); VALUE rb_reg_init_str(VALUE re, VALUE s, int options); VALUE rb_reg_match(VALUE, VALUE); VALUE rb_reg_match2(VALUE); int rb_reg_options(VALUE); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_RE_H */ PK!灚 internal/intern/thread.hnu[#ifndef RBIMPL_INTERN_THREAD_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_THREAD_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_cThread. */ #include "ruby/internal/config.h" #include "ruby/internal/cast.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() struct timeval; /* thread.c */ void rb_thread_schedule(void); void rb_thread_wait_fd(int); int rb_thread_fd_writable(int); void rb_thread_fd_close(int); int rb_thread_alone(void); void rb_thread_sleep(int); void rb_thread_sleep_forever(void); void rb_thread_sleep_deadly(void); VALUE rb_thread_stop(void); VALUE rb_thread_wakeup(VALUE); VALUE rb_thread_wakeup_alive(VALUE); VALUE rb_thread_run(VALUE); VALUE rb_thread_kill(VALUE); VALUE rb_thread_create(VALUE (*)(void *), void*); void rb_thread_wait_for(struct timeval); VALUE rb_thread_current(void); VALUE rb_thread_main(void); VALUE rb_thread_local_aref(VALUE, ID); VALUE rb_thread_local_aset(VALUE, ID, VALUE); void rb_thread_atfork(void); void rb_thread_atfork_before_exec(void); VALUE rb_exec_recursive(VALUE(*)(VALUE, VALUE, int),VALUE,VALUE); VALUE rb_exec_recursive_paired(VALUE(*)(VALUE, VALUE, int),VALUE,VALUE,VALUE); VALUE rb_exec_recursive_outer(VALUE(*)(VALUE, VALUE, int),VALUE,VALUE); VALUE rb_exec_recursive_paired_outer(VALUE(*)(VALUE, VALUE, int),VALUE,VALUE,VALUE); typedef void rb_unblock_function_t(void *); typedef VALUE rb_blocking_function_t(void *); void rb_thread_check_ints(void); int rb_thread_interrupted(VALUE thval); #define RUBY_UBF_IO RBIMPL_CAST((rb_unblock_function_t *)-1) #define RUBY_UBF_PROCESS RBIMPL_CAST((rb_unblock_function_t *)-1) VALUE rb_mutex_new(void); VALUE rb_mutex_locked_p(VALUE mutex); VALUE rb_mutex_trylock(VALUE mutex); VALUE rb_mutex_lock(VALUE mutex); VALUE rb_mutex_unlock(VALUE mutex); VALUE rb_mutex_sleep(VALUE self, VALUE timeout); VALUE rb_mutex_synchronize(VALUE mutex, VALUE (*func)(VALUE arg), VALUE arg); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_THREAD_H */ PK!X1dinternal/intern/cont.hnu[#ifndef RBIMPL_INTERN_CONT_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_CONT_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to rb_cFiber. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" #include "ruby/internal/iterator.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* cont.c */ VALUE rb_fiber_new(rb_block_call_func_t, VALUE); VALUE rb_fiber_new_kw(rb_block_call_func_t, VALUE, int kw_splat); VALUE rb_fiber_resume(VALUE fib, int argc, const VALUE *argv); VALUE rb_fiber_resume_kw(VALUE fib, int argc, const VALUE *argv, int kw_splat); VALUE rb_fiber_yield(int argc, const VALUE *argv); VALUE rb_fiber_yield_kw(int argc, const VALUE *argv, int kw_splat); VALUE rb_fiber_current(void); VALUE rb_fiber_alive_p(VALUE); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_CONT_H */ PK!Gi internal/intern/vm.hnu[#ifndef RBIMPL_INTERN_VM_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_VM_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_cRubyVM. */ #include "ruby/internal/attr/noreturn.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* vm.c */ int rb_sourceline(void); const char *rb_sourcefile(void); int rb_frame_method_id_and_class(ID *idp, VALUE *klassp); /* vm_eval.c */ VALUE rb_check_funcall(VALUE, ID, int, const VALUE*); VALUE rb_check_funcall_kw(VALUE, ID, int, const VALUE*, int); void rb_remove_method(VALUE, const char*); void rb_remove_method_id(VALUE, ID); VALUE rb_eval_cmd_kw(VALUE, VALUE, int); VALUE rb_apply(VALUE, ID, VALUE); VALUE rb_obj_instance_eval(int, const VALUE*, VALUE); VALUE rb_obj_instance_exec(int, const VALUE*, VALUE); VALUE rb_mod_module_eval(int, const VALUE*, VALUE); VALUE rb_mod_module_exec(int, const VALUE*, VALUE); /* vm_method.c */ #define HAVE_RB_DEFINE_ALLOC_FUNC 1 typedef VALUE (*rb_alloc_func_t)(VALUE); void rb_define_alloc_func(VALUE, rb_alloc_func_t); void rb_undef_alloc_func(VALUE); rb_alloc_func_t rb_get_alloc_func(VALUE); void rb_clear_constant_cache(void); void rb_clear_method_cache_by_class(VALUE); void rb_alias(VALUE, ID, ID); void rb_attr(VALUE,ID,int,int,int); int rb_method_boundp(VALUE, ID, int); int rb_method_basic_definition_p(VALUE, ID); int rb_obj_respond_to(VALUE, ID, int); int rb_respond_to(VALUE, ID); RBIMPL_ATTR_NORETURN() VALUE rb_f_notimplement(int argc, const VALUE *argv, VALUE obj, VALUE marker); #if !defined(RUBY_EXPORT) && defined(_WIN32) RUBY_EXTERN VALUE (*const rb_f_notimplement_)(int, const VALUE *, VALUE, VALUE marker); #define rb_f_notimplement (*rb_f_notimplement_) #endif /* vm_backtrace.c */ void rb_backtrace(void); VALUE rb_make_backtrace(void); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_VM_H */ PK!Tb{ { internal/intern/error.hnu[#ifndef RBIMPL_INTERN_ERROR_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_ERROR_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_eException. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" #include "ruby/internal/fl_type.h" #include "ruby/backward/2/assume.h" #include "ruby/backward/2/attributes.h" #define UNLIMITED_ARGUMENTS (-1) #define rb_exc_new2 rb_exc_new_cstr #define rb_exc_new3 rb_exc_new_str #define rb_check_trusted rb_check_trusted #define rb_check_trusted_inline rb_check_trusted #define rb_check_arity rb_check_arity RBIMPL_SYMBOL_EXPORT_BEGIN() /* error.c */ VALUE rb_exc_new(VALUE, const char*, long); VALUE rb_exc_new_cstr(VALUE, const char*); VALUE rb_exc_new_str(VALUE, VALUE); PRINTF_ARGS(NORETURN(void rb_loaderror(const char*, ...)), 1, 2); PRINTF_ARGS(NORETURN(void rb_loaderror_with_path(VALUE path, const char*, ...)), 2, 3); PRINTF_ARGS(NORETURN(void rb_name_error(ID, const char*, ...)), 2, 3); PRINTF_ARGS(NORETURN(void rb_name_error_str(VALUE, const char*, ...)), 2, 3); PRINTF_ARGS(NORETURN(void rb_frozen_error_raise(VALUE, const char*, ...)), 2, 3); NORETURN(void rb_invalid_str(const char*, const char*)); NORETURN(void rb_error_frozen(const char*)); NORETURN(void rb_error_frozen_object(VALUE)); void rb_error_untrusted(VALUE); void rb_check_frozen(VALUE); void rb_check_trusted(VALUE); void rb_check_copyable(VALUE obj, VALUE orig); NORETURN(MJIT_STATIC void rb_error_arity(int, int, int)); RBIMPL_SYMBOL_EXPORT_END() /* Does anyone use this? Remain not deleted for compatibility. */ #define rb_check_frozen_internal(obj) do { \ VALUE frozen_obj = (obj); \ if (RB_UNLIKELY(RB_OBJ_FROZEN(frozen_obj))) { \ rb_error_frozen_object(frozen_obj); \ } \ } while (0) static inline void rb_check_frozen_inline(VALUE obj) { if (RB_UNLIKELY(RB_OBJ_FROZEN(obj))) { rb_error_frozen_object(obj); } } #define rb_check_frozen rb_check_frozen_inline static inline int rb_check_arity(int argc, int min, int max) { if ((argc < min) || (max != UNLIMITED_ARGUMENTS && argc > max)) rb_error_arity(argc, min, max); return argc; } #endif /* RBIMPL_INTERN_ERROR_H */ PK!,Sʝinternal/intern/bignum.hnu[#ifndef RBIMPL_INTERN_BIGNUM_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_BIGNUM_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to so-called rb_cBignum. */ #include "ruby/internal/config.h" #ifdef STDC_HEADERS # include #endif #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" #include "ruby/backward/2/long_long.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* bignum.c */ VALUE rb_big_new(size_t, int); int rb_bigzero_p(VALUE x); VALUE rb_big_clone(VALUE); void rb_big_2comp(VALUE); VALUE rb_big_norm(VALUE); void rb_big_resize(VALUE big, size_t len); VALUE rb_cstr_to_inum(const char*, int, int); VALUE rb_str_to_inum(VALUE, int, int); VALUE rb_cstr2inum(const char*, int); VALUE rb_str2inum(VALUE, int); VALUE rb_big2str(VALUE, int); long rb_big2long(VALUE); #define rb_big2int(x) rb_big2long(x) unsigned long rb_big2ulong(VALUE); #define rb_big2uint(x) rb_big2ulong(x) #if HAVE_LONG_LONG LONG_LONG rb_big2ll(VALUE); unsigned LONG_LONG rb_big2ull(VALUE); #endif /* HAVE_LONG_LONG */ void rb_big_pack(VALUE val, unsigned long *buf, long num_longs); VALUE rb_big_unpack(unsigned long *buf, long num_longs); int rb_uv_to_utf8(char[6],unsigned long); VALUE rb_dbl2big(double); double rb_big2dbl(VALUE); VALUE rb_big_cmp(VALUE, VALUE); VALUE rb_big_eq(VALUE, VALUE); VALUE rb_big_eql(VALUE, VALUE); VALUE rb_big_plus(VALUE, VALUE); VALUE rb_big_minus(VALUE, VALUE); VALUE rb_big_mul(VALUE, VALUE); VALUE rb_big_div(VALUE, VALUE); VALUE rb_big_idiv(VALUE, VALUE); VALUE rb_big_modulo(VALUE, VALUE); VALUE rb_big_divmod(VALUE, VALUE); VALUE rb_big_pow(VALUE, VALUE); VALUE rb_big_and(VALUE, VALUE); VALUE rb_big_or(VALUE, VALUE); VALUE rb_big_xor(VALUE, VALUE); VALUE rb_big_lshift(VALUE, VALUE); VALUE rb_big_rshift(VALUE, VALUE); /* For rb_integer_pack and rb_integer_unpack: */ /* "MS" in MSWORD and MSBYTE means "most significant" */ /* "LS" in LSWORD and LSBYTE means "least significant" */ #define INTEGER_PACK_MSWORD_FIRST 0x01 #define INTEGER_PACK_LSWORD_FIRST 0x02 #define INTEGER_PACK_MSBYTE_FIRST 0x10 #define INTEGER_PACK_LSBYTE_FIRST 0x20 #define INTEGER_PACK_NATIVE_BYTE_ORDER 0x40 #define INTEGER_PACK_2COMP 0x80 #define INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION 0x400 /* For rb_integer_unpack: */ #define INTEGER_PACK_FORCE_BIGNUM 0x100 #define INTEGER_PACK_NEGATIVE 0x200 /* Combinations: */ #define INTEGER_PACK_LITTLE_ENDIAN \ (INTEGER_PACK_LSWORD_FIRST | \ INTEGER_PACK_LSBYTE_FIRST) #define INTEGER_PACK_BIG_ENDIAN \ (INTEGER_PACK_MSWORD_FIRST | \ INTEGER_PACK_MSBYTE_FIRST) int rb_integer_pack(VALUE val, void *words, size_t numwords, size_t wordsize, size_t nails, int flags); VALUE rb_integer_unpack(const void *words, size_t numwords, size_t wordsize, size_t nails, int flags); size_t rb_absint_size(VALUE val, int *nlz_bits_ret); size_t rb_absint_numwords(VALUE val, size_t word_numbits, size_t *nlz_bits_ret); int rb_absint_singlebit_p(VALUE val); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_BIGNUM_H */ PK!DQU U internal/intern/array.hnu[#ifndef RBIMPL_INTERN_ARRAY_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_ARRAY_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_cArray. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* array.c */ void rb_mem_clear(VALUE*, long); VALUE rb_assoc_new(VALUE, VALUE); VALUE rb_check_array_type(VALUE); VALUE rb_ary_new(void); VALUE rb_ary_new_capa(long capa); VALUE rb_ary_new_from_args(long n, ...); VALUE rb_ary_new_from_values(long n, const VALUE *elts); VALUE rb_ary_tmp_new(long); void rb_ary_free(VALUE); void rb_ary_modify(VALUE); VALUE rb_ary_freeze(VALUE); VALUE rb_ary_shared_with_p(VALUE, VALUE); VALUE rb_ary_aref(int, const VALUE*, VALUE); VALUE rb_ary_subseq(VALUE, long, long); void rb_ary_store(VALUE, long, VALUE); VALUE rb_ary_dup(VALUE); VALUE rb_ary_resurrect(VALUE ary); VALUE rb_ary_to_ary(VALUE); VALUE rb_ary_to_s(VALUE); VALUE rb_ary_cat(VALUE, const VALUE *, long); VALUE rb_ary_push(VALUE, VALUE); VALUE rb_ary_pop(VALUE); VALUE rb_ary_shift(VALUE); VALUE rb_ary_unshift(VALUE, VALUE); VALUE rb_ary_entry(VALUE, long); VALUE rb_ary_each(VALUE); VALUE rb_ary_join(VALUE, VALUE); VALUE rb_ary_reverse(VALUE); VALUE rb_ary_rotate(VALUE, long); VALUE rb_ary_sort(VALUE); VALUE rb_ary_sort_bang(VALUE); VALUE rb_ary_delete(VALUE, VALUE); VALUE rb_ary_delete_at(VALUE, long); VALUE rb_ary_clear(VALUE); VALUE rb_ary_plus(VALUE, VALUE); VALUE rb_ary_concat(VALUE, VALUE); VALUE rb_ary_assoc(VALUE, VALUE); VALUE rb_ary_rassoc(VALUE, VALUE); VALUE rb_ary_includes(VALUE, VALUE); VALUE rb_ary_cmp(VALUE, VALUE); VALUE rb_ary_replace(VALUE copy, VALUE orig); VALUE rb_get_values_at(VALUE, long, int, const VALUE*, VALUE(*)(VALUE,long)); VALUE rb_ary_resize(VALUE ary, long len); #define rb_ary_new2 rb_ary_new_capa #define rb_ary_new3 rb_ary_new_from_args #define rb_ary_new4 rb_ary_new_from_values RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_ARRAY_H */ PK!fBinternal/intern/marshal.hnu[#ifndef RBIMPL_INTERN_MARSHAL_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_MARSHAL_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to rb_mMarshal. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* marshal.c */ VALUE rb_marshal_dump(VALUE, VALUE); VALUE rb_marshal_load(VALUE); void rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE (*dumper)(VALUE), VALUE (*loader)(VALUE, VALUE)); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_MARSHAL_H */ PK!e internal/intern/complex.hnu[#ifndef RBIMPL_INTERN_COMPLEX_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_COMPLEX_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_cComplex. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" #include "ruby/internal/arithmetic/long.h" /* INT2FIX is here. */ RBIMPL_SYMBOL_EXPORT_BEGIN() /* complex.c */ VALUE rb_complex_raw(VALUE, VALUE); #define rb_complex_raw1(x) rb_complex_raw((x), INT2FIX(0)) #define rb_complex_raw2(x,y) rb_complex_raw((x), (y)) VALUE rb_complex_new(VALUE, VALUE); #define rb_complex_new1(x) rb_complex_new((x), INT2FIX(0)) #define rb_complex_new2(x,y) rb_complex_new((x), (y)) VALUE rb_complex_new_polar(VALUE abs, VALUE arg); DEPRECATED_BY(rb_complex_new_polar, VALUE rb_complex_polar(VALUE abs, VALUE arg)); VALUE rb_complex_real(VALUE z); VALUE rb_complex_imag(VALUE z); VALUE rb_complex_plus(VALUE x, VALUE y); VALUE rb_complex_minus(VALUE x, VALUE y); VALUE rb_complex_mul(VALUE x, VALUE y); VALUE rb_complex_div(VALUE x, VALUE y); VALUE rb_complex_uminus(VALUE z); VALUE rb_complex_conjugate(VALUE z); VALUE rb_complex_abs(VALUE z); VALUE rb_complex_arg(VALUE z); VALUE rb_complex_pow(VALUE base, VALUE exp); VALUE rb_dbl_complex_new(double real, double imag); #define rb_complex_add rb_complex_plus #define rb_complex_sub rb_complex_minus #define rb_complex_nagate rb_complex_uminus VALUE rb_Complex(VALUE, VALUE); #define rb_Complex1(x) rb_Complex((x), INT2FIX(0)) #define rb_Complex2(x,y) rb_Complex((x), (y)) RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_COMPLEX_H */ PK!i internal/intern/select/posix.hnu[#ifndef RBIMPL_INTERN_SELECT_POSIX_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_SELECT_POSIX_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs to provide ::rb_fd_select(). */ #include "ruby/internal/config.h" #ifdef HAVE_SYS_SELECT_H # include /* for select(2) (modern POSIX) */ #endif #ifdef HAVE_UNISTD_H # include /* for select(2) (archaic UNIX) */ #endif #include "ruby/internal/attr/pure.h" #include "ruby/internal/attr/const.h" typedef fd_set rb_fdset_t; #define rb_fd_zero FD_ZERO #define rb_fd_set FD_SET #define rb_fd_clr FD_CLR #define rb_fd_isset FD_ISSET #define rb_fd_init FD_ZERO #define rb_fd_select select /**@cond INTERNAL_MACRO */ #define rb_fd_copy rb_fd_copy #define rb_fd_dup rb_fd_dup #define rb_fd_ptr rb_fd_ptr #define rb_fd_max rb_fd_max /** @endcond */ static inline void rb_fd_copy(rb_fdset_t *dst, const fd_set *src, int n) { *dst = *src; } static inline void rb_fd_dup(rb_fdset_t *dst, const fd_set *src) { *dst = *src; } RBIMPL_ATTR_PURE() /* :TODO: can this function be __attribute__((returns_nonnull)) or not? */ static inline fd_set * rb_fd_ptr(rb_fdset_t *f) { return f; } RBIMPL_ATTR_CONST() static inline int rb_fd_max(const rb_fdset_t *f) { return FD_SETSIZE; } /* :FIXME: What are these? They don't exist for shibling implementations. */ #define rb_fd_init_copy(d, s) (*(d) = *(s)) #define rb_fd_term(f) ((void)(f)) #endif /* RBIMPL_INTERN_SELECT_POSIX_H */ PK!hh"internal/intern/select/largesize.hnu[#ifndef RBIMPL_INTERN_SELECT_LARGESIZE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_SELECT_LARGESIZE_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs to provide ::rb_fd_select(). * * Several Unix platforms support file descriptors bigger than FD_SETSIZE in * `select(2)` system call. * * - Linux 2.2.12 (?) * * - NetBSD 1.2 (src/sys/kern/sys_generic.c:1.25) * `select(2)` documents how to allocate fd_set dynamically. * http://netbsd.gw.com/cgi-bin/man-cgi?select++NetBSD-4.0 * * - FreeBSD 2.2 (src/sys/kern/sys_generic.c:1.19) * * - OpenBSD 2.0 (src/sys/kern/sys_generic.c:1.4) * `select(2)` documents how to allocate fd_set dynamically. * http://www.openbsd.org/cgi-bin/man.cgi?query=select&manpath=OpenBSD+4.4 * * - HP-UX documents how to allocate fd_set dynamically. * http://docs.hp.com/en/B2355-60105/select.2.html * * - Solaris 8 has `select_large_fdset` * * - Mac OS X 10.7 (Lion) * `select(2)` returns `EINVAL` if `nfds` is greater than `FD_SET_SIZE` and * `_DARWIN_UNLIMITED_SELECT` (or `_DARWIN_C_SOURCE`) isn't defined. * http://developer.apple.com/library/mac/#releasenotes/Darwin/SymbolVariantsRelNotes/_index.html * * When `fd_set` is not big enough to hold big file descriptors, it should be * allocated dynamically. Note that this assumes `fd_set` is structured as * bitmap. * * `rb_fd_init` allocates the memory. * `rb_fd_term` frees the memory. * `rb_fd_set` may re-allocate bitmap. * * So `rb_fd_set` doesn't reject file descriptors bigger than `FD_SETSIZE`. */ #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/attr/pure.h" #include "ruby/internal/dllexport.h" /**@cond INTERNAL_MACRO */ #define rb_fd_ptr rb_fd_ptr #define rb_fd_max rb_fd_max /** @endcond */ struct timeval; typedef struct { int maxfd; fd_set *fdset; } rb_fdset_t; RBIMPL_SYMBOL_EXPORT_BEGIN() void rb_fd_init(rb_fdset_t *); void rb_fd_term(rb_fdset_t *); void rb_fd_zero(rb_fdset_t *); void rb_fd_set(int, rb_fdset_t *); void rb_fd_clr(int, rb_fdset_t *); int rb_fd_isset(int, const rb_fdset_t *); void rb_fd_copy(rb_fdset_t *, const fd_set *, int); void rb_fd_dup(rb_fdset_t *dst, const rb_fdset_t *src); int rb_fd_select(int, rb_fdset_t *, rb_fdset_t *, rb_fdset_t *, struct timeval *); RBIMPL_SYMBOL_EXPORT_END() RBIMPL_ATTR_NONNULL(()) RBIMPL_ATTR_PURE() /* :TODO: can this function be __attribute__((returns_nonnull)) or not? */ static inline fd_set * rb_fd_ptr(const rb_fdset_t *f) { return f->fdset; } RBIMPL_ATTR_NONNULL(()) RBIMPL_ATTR_PURE() static inline int rb_fd_max(const rb_fdset_t *f) { return f->maxfd; } #endif /* RBIMPL_INTERN_SELECT_LARGESIZE_H */ PK!winternal/intern/eval.hnu[#ifndef RBIMPL_INTERN_EVAL_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_EVAL_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Pre-1.9 era evaluator APIs (now considered miscellaneous). */ #include "ruby/internal/attr/noreturn.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* eval.c */ RBIMPL_ATTR_NORETURN() void rb_exc_raise(VALUE); RBIMPL_ATTR_NORETURN() void rb_exc_fatal(VALUE); RBIMPL_ATTR_NORETURN() VALUE rb_f_exit(int, const VALUE*); RBIMPL_ATTR_NORETURN() VALUE rb_f_abort(int, const VALUE*); RBIMPL_ATTR_NORETURN() void rb_interrupt(void); ID rb_frame_this_func(void); RBIMPL_ATTR_NORETURN() void rb_jump_tag(int); void rb_obj_call_init(VALUE, int, const VALUE*); void rb_obj_call_init_kw(VALUE, int, const VALUE*, int); VALUE rb_protect(VALUE (*)(VALUE), VALUE, int*); ID rb_frame_callee(void); VALUE rb_make_exception(int, const VALUE*); /* eval_jump.c */ void rb_set_end_proc(void (*)(VALUE), VALUE); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_EVAL_H */ PK!=&((internal/intern/string.hnu[#ifndef RBIMPL_INTERN_STRING_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_STRING_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_cString. */ #include "ruby/internal/config.h" #ifdef STDC_HEADERS # include #endif #ifdef HAVE_STRING_H # include #endif #ifdef HAVE_STDINT_H # include #endif #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/attr/pure.h" #include "ruby/internal/constant_p.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" #include "ruby/internal/variable.h" /* rb_gvar_setter_t */ #include "ruby/st.h" /* st_index_t */ RBIMPL_SYMBOL_EXPORT_BEGIN() /* string.c */ VALUE rb_str_new(const char*, long); VALUE rb_str_new_cstr(const char*); VALUE rb_str_new_shared(VALUE); VALUE rb_str_new_frozen(VALUE); VALUE rb_str_new_with_class(VALUE, const char*, long); VALUE rb_tainted_str_new_cstr(const char*); VALUE rb_tainted_str_new(const char*, long); VALUE rb_external_str_new(const char*, long); VALUE rb_external_str_new_cstr(const char*); VALUE rb_locale_str_new(const char*, long); VALUE rb_locale_str_new_cstr(const char*); VALUE rb_filesystem_str_new(const char*, long); VALUE rb_filesystem_str_new_cstr(const char*); VALUE rb_str_buf_new(long); VALUE rb_str_buf_new_cstr(const char*); VALUE rb_str_buf_new2(const char*); VALUE rb_str_tmp_new(long); VALUE rb_usascii_str_new(const char*, long); VALUE rb_usascii_str_new_cstr(const char*); VALUE rb_utf8_str_new(const char*, long); VALUE rb_utf8_str_new_cstr(const char*); /** * *_str_new_static functions are intended for C string literals. * They require memory in the range [ptr, ptr+len] to always be readable. * Note that this range covers a total of len + 1 bytes. */ VALUE rb_str_new_static(const char *ptr, long len); VALUE rb_usascii_str_new_static(const char *ptr, long len); VALUE rb_utf8_str_new_static(const char *ptr, long len); VALUE rb_str_to_interned_str(VALUE); VALUE rb_interned_str(const char *, long); VALUE rb_interned_str_cstr(const char *); void rb_str_free(VALUE); void rb_str_shared_replace(VALUE, VALUE); VALUE rb_str_buf_append(VALUE, VALUE); VALUE rb_str_buf_cat(VALUE, const char*, long); VALUE rb_str_buf_cat2(VALUE, const char*); VALUE rb_str_buf_cat_ascii(VALUE, const char*); VALUE rb_obj_as_string(VALUE); VALUE rb_check_string_type(VALUE); void rb_must_asciicompat(VALUE); VALUE rb_str_dup(VALUE); VALUE rb_str_resurrect(VALUE str); VALUE rb_str_locktmp(VALUE); VALUE rb_str_unlocktmp(VALUE); VALUE rb_str_dup_frozen(VALUE); #define rb_str_dup_frozen rb_str_new_frozen VALUE rb_str_plus(VALUE, VALUE); VALUE rb_str_times(VALUE, VALUE); long rb_str_sublen(VALUE, long); VALUE rb_str_substr(VALUE, long, long); VALUE rb_str_subseq(VALUE, long, long); char *rb_str_subpos(VALUE, long, long*); void rb_str_modify(VALUE); void rb_str_modify_expand(VALUE, long); VALUE rb_str_freeze(VALUE); void rb_str_set_len(VALUE, long); VALUE rb_str_resize(VALUE, long); VALUE rb_str_cat(VALUE, const char*, long); VALUE rb_str_cat_cstr(VALUE, const char*); VALUE rb_str_cat2(VALUE, const char*); VALUE rb_str_append(VALUE, VALUE); VALUE rb_str_concat(VALUE, VALUE); st_index_t rb_memhash(const void *ptr, long len); st_index_t rb_hash_start(st_index_t); st_index_t rb_hash_uint32(st_index_t, uint32_t); st_index_t rb_hash_uint(st_index_t, st_index_t); st_index_t rb_hash_end(st_index_t); #define rb_hash_uint32(h, i) st_hash_uint32((h), (i)) #define rb_hash_uint(h, i) st_hash_uint((h), (i)) #define rb_hash_end(h) st_hash_end(h) st_index_t rb_str_hash(VALUE); int rb_str_hash_cmp(VALUE,VALUE); int rb_str_comparable(VALUE, VALUE); int rb_str_cmp(VALUE, VALUE); VALUE rb_str_equal(VALUE str1, VALUE str2); VALUE rb_str_drop_bytes(VALUE, long); void rb_str_update(VALUE, long, long, VALUE); VALUE rb_str_replace(VALUE, VALUE); VALUE rb_str_inspect(VALUE); VALUE rb_str_dump(VALUE); VALUE rb_str_split(VALUE, const char*); rb_gvar_setter_t rb_str_setter; VALUE rb_str_intern(VALUE); VALUE rb_sym_to_s(VALUE); long rb_str_strlen(VALUE); VALUE rb_str_length(VALUE); long rb_str_offset(VALUE, long); RBIMPL_ATTR_PURE() size_t rb_str_capacity(VALUE); VALUE rb_str_ellipsize(VALUE, long); VALUE rb_str_scrub(VALUE, VALUE); VALUE rb_str_succ(VALUE); RBIMPL_ATTR_NONNULL(()) static inline long rbimpl_strlen(const char *str) { return RBIMPL_CAST((long)strlen(str)); } static inline VALUE rbimpl_str_new_cstr(const char *str) { long len = rbimpl_strlen(str); return rb_str_new_static(str, len); } static inline VALUE rbimpl_tainted_str_new_cstr(const char *str) { long len = rbimpl_strlen(str); return rb_tainted_str_new(str, len); } static inline VALUE rbimpl_usascii_str_new_cstr(const char *str) { long len = rbimpl_strlen(str); return rb_usascii_str_new_static(str, len); } static inline VALUE rbimpl_utf8_str_new_cstr(const char *str) { long len = rbimpl_strlen(str); return rb_utf8_str_new_static(str, len); } static inline VALUE rbimpl_external_str_new_cstr(const char *str) { long len = rbimpl_strlen(str); return rb_external_str_new(str, len); } static inline VALUE rbimpl_locale_str_new_cstr(const char *str) { long len = rbimpl_strlen(str); return rb_locale_str_new(str, len); } static inline VALUE rbimpl_str_buf_new_cstr(const char *str) { long len = rbimpl_strlen(str); VALUE buf = rb_str_buf_new(len); return rb_str_buf_cat(buf, str, len); } static inline VALUE rbimpl_str_cat_cstr(VALUE buf, const char *str) { long len = rbimpl_strlen(str); return rb_str_cat(buf, str, len); } static inline VALUE rbimpl_exc_new_cstr(VALUE exc, const char *str) { long len = rbimpl_strlen(str); return rb_exc_new(exc, str, len); } #define rb_str_new(str, len) \ ((RBIMPL_CONSTANT_P(str) && \ RBIMPL_CONSTANT_P(len) ? \ rb_str_new_static : \ rb_str_new) ((str), (len))) #define rb_str_new_cstr(str) \ ((RBIMPL_CONSTANT_P(str) ? \ rbimpl_str_new_cstr : \ rb_str_new_cstr) (str)) #define rb_usascii_str_new(str, len) \ ((RBIMPL_CONSTANT_P(str) && \ RBIMPL_CONSTANT_P(len) ? \ rb_usascii_str_new_static : \ rb_usascii_str_new) ((str), (len))) #define rb_utf8_str_new(str, len) \ ((RBIMPL_CONSTANT_P(str) && \ RBIMPL_CONSTANT_P(len) ? \ rb_utf8_str_new_static : \ rb_utf8_str_new) ((str), (len))) #define rb_tainted_str_new_cstr(str) \ ((RBIMPL_CONSTANT_P(str) ? \ rbimpl_tainted_str_new_cstr : \ rb_tainted_str_new_cstr) (str)) #define rb_usascii_str_new_cstr(str) \ ((RBIMPL_CONSTANT_P(str) ? \ rbimpl_usascii_str_new_cstr : \ rb_usascii_str_new_cstr) (str)) #define rb_utf8_str_new_cstr(str) \ ((RBIMPL_CONSTANT_P(str) ? \ rbimpl_utf8_str_new_cstr : \ rb_utf8_str_new_cstr) (str)) #define rb_external_str_new_cstr(str) \ ((RBIMPL_CONSTANT_P(str) ? \ rbimpl_external_str_new_cstr : \ rb_external_str_new_cstr) (str)) #define rb_locale_str_new_cstr(str) \ ((RBIMPL_CONSTANT_P(str) ? \ rbimpl_locale_str_new_cstr : \ rb_locale_str_new_cstr) (str)) #define rb_str_buf_new_cstr(str) \ ((RBIMPL_CONSTANT_P(str) ? \ rbimpl_str_buf_new_cstr : \ rb_str_buf_new_cstr) (str)) #define rb_str_cat_cstr(buf, str) \ ((RBIMPL_CONSTANT_P(str) ? \ rbimpl_str_cat_cstr : \ rb_str_cat_cstr) ((buf), (str))) #define rb_exc_new_cstr(exc, str) \ ((RBIMPL_CONSTANT_P(str) ? \ rbimpl_exc_new_cstr : \ rb_exc_new_cstr) ((exc), (str))) #define rb_str_new2 rb_str_new_cstr #define rb_str_new3 rb_str_new_shared #define rb_str_new4 rb_str_new_frozen #define rb_str_new5 rb_str_new_with_class #define rb_tainted_str_new2 rb_tainted_str_new_cstr #define rb_str_buf_new2 rb_str_buf_new_cstr #define rb_usascii_str_new2 rb_usascii_str_new_cstr #define rb_str_buf_cat rb_str_cat #define rb_str_buf_cat2 rb_str_cat_cstr #define rb_str_cat2 rb_str_cat_cstr #define rb_strlen_lit(str) (sizeof(str "") - 1) #define rb_str_new_lit(str) rb_str_new_static((str), rb_strlen_lit(str)) #define rb_usascii_str_new_lit(str) rb_usascii_str_new_static((str), rb_strlen_lit(str)) #define rb_utf8_str_new_lit(str) rb_utf8_str_new_static((str), rb_strlen_lit(str)) #define rb_enc_str_new_lit(str, enc) rb_enc_str_new_static((str), rb_strlen_lit(str), (enc)) #define rb_str_new_literal(str) rb_str_new_lit(str) #define rb_usascii_str_new_literal(str) rb_usascii_str_new_lit(str) #define rb_utf8_str_new_literal(str) rb_utf8_str_new_lit(str) #define rb_enc_str_new_literal(str, enc) rb_enc_str_new_lit(str, enc) RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_STRING_H */ PK!2ZI\ \ internal/intern/hash.hnu[#ifndef RBIMPL_INTERN_HASH_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_HASH_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_cHash. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" #include "ruby/st.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* hash.c */ void rb_st_foreach_safe(struct st_table *, int (*)(st_data_t, st_data_t, st_data_t), st_data_t); #define st_foreach_safe rb_st_foreach_safe VALUE rb_check_hash_type(VALUE); void rb_hash_foreach(VALUE, int (*)(VALUE, VALUE, VALUE), VALUE); VALUE rb_hash(VALUE); VALUE rb_hash_new(void); VALUE rb_hash_dup(VALUE); VALUE rb_hash_freeze(VALUE); VALUE rb_hash_aref(VALUE, VALUE); VALUE rb_hash_lookup(VALUE, VALUE); VALUE rb_hash_lookup2(VALUE, VALUE, VALUE); VALUE rb_hash_fetch(VALUE, VALUE); VALUE rb_hash_aset(VALUE, VALUE, VALUE); VALUE rb_hash_clear(VALUE); VALUE rb_hash_delete_if(VALUE); VALUE rb_hash_delete(VALUE,VALUE); VALUE rb_hash_set_ifnone(VALUE hash, VALUE ifnone); void rb_hash_bulk_insert(long, const VALUE *, VALUE); typedef VALUE rb_hash_update_func(VALUE newkey, VALUE oldkey, VALUE value); VALUE rb_hash_update_by(VALUE hash1, VALUE hash2, rb_hash_update_func *func); struct st_table *rb_hash_tbl(VALUE, const char *file, int line); int rb_path_check(const char*); int rb_env_path_tainted(void); VALUE rb_env_clear(void); VALUE rb_hash_size(VALUE); void rb_hash_free(VALUE); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_HASH_H */ PK! 9bbinternal/intern/parse.hnu[#ifndef RBIMPL_INTERN_PARSE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_PARSE_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_cSymbol. */ #include "ruby/internal/attr/const.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* parse.y */ ID rb_id_attrset(ID); RBIMPL_ATTR_CONST() int rb_is_const_id(ID); RBIMPL_ATTR_CONST() int rb_is_global_id(ID); RBIMPL_ATTR_CONST() int rb_is_instance_id(ID); RBIMPL_ATTR_CONST() int rb_is_attrset_id(ID); RBIMPL_ATTR_CONST() int rb_is_class_id(ID); RBIMPL_ATTR_CONST() int rb_is_local_id(ID); RBIMPL_ATTR_CONST() int rb_is_junk_id(ID); int rb_symname_p(const char*); int rb_sym_interned_p(VALUE); VALUE rb_backref_get(void); void rb_backref_set(VALUE); VALUE rb_lastline_get(void); void rb_lastline_set(VALUE); /* symbol.c */ VALUE rb_sym_all_symbols(void); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_PARSE_H */ PK!K K internal/intern/io.hnu[#ifndef RBIMPL_INTERN_IO_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_IO_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_cIO. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* io.c */ #define rb_defout rb_stdout RUBY_EXTERN VALUE rb_fs; RUBY_EXTERN VALUE rb_output_fs; RUBY_EXTERN VALUE rb_rs; RUBY_EXTERN VALUE rb_default_rs; RUBY_EXTERN VALUE rb_output_rs; VALUE rb_io_write(VALUE, VALUE); VALUE rb_io_gets(VALUE); VALUE rb_io_getbyte(VALUE); VALUE rb_io_ungetc(VALUE, VALUE); VALUE rb_io_ungetbyte(VALUE, VALUE); VALUE rb_io_close(VALUE); VALUE rb_io_flush(VALUE); VALUE rb_io_eof(VALUE); VALUE rb_io_binmode(VALUE); VALUE rb_io_ascii8bit_binmode(VALUE); VALUE rb_io_addstr(VALUE, VALUE); VALUE rb_io_printf(int, const VALUE*, VALUE); VALUE rb_io_print(int, const VALUE*, VALUE); VALUE rb_io_puts(int, const VALUE*, VALUE); VALUE rb_io_fdopen(int, int, const char*); VALUE rb_io_get_io(VALUE); VALUE rb_file_open(const char*, const char*); VALUE rb_file_open_str(VALUE, const char*); VALUE rb_gets(void); void rb_write_error(const char*); void rb_write_error2(const char*, long); void rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds); int rb_pipe(int *pipes); int rb_reserved_fd_p(int fd); int rb_cloexec_open(const char *pathname, int flags, mode_t mode); int rb_cloexec_dup(int oldfd); int rb_cloexec_dup2(int oldfd, int newfd); int rb_cloexec_pipe(int fildes[2]); int rb_cloexec_fcntl_dupfd(int fd, int minfd); #define RB_RESERVED_FD_P(fd) rb_reserved_fd_p(fd) void rb_update_max_fd(int fd); void rb_fd_fix_cloexec(int fd); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_IO_H */ PK!#-'internal/intern/dir.hnu[#ifndef RBIMPL_INTERN_DIR_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_DIR_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_cDir. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* dir.c */ VALUE rb_dir_getwd(void); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_DIR_H */ PK!<}internal/intern/numeric.hnu[#ifndef RBIMPL_INTERN_NUMERIC_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_NUMERIC_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_cNumeric. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" #include "ruby/backward/2/attributes.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* numeric.c */ NORETURN(void rb_num_zerodiv(void)); #define RB_NUM_COERCE_FUNCS_NEED_OPID 1 VALUE rb_num_coerce_bin(VALUE, VALUE, ID); VALUE rb_num_coerce_cmp(VALUE, VALUE, ID); VALUE rb_num_coerce_relop(VALUE, VALUE, ID); VALUE rb_num_coerce_bit(VALUE, VALUE, ID); VALUE rb_num2fix(VALUE); VALUE rb_fix2str(VALUE, int); CONSTFUNC(VALUE rb_dbl_cmp(double, double)); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_NUMERIC_H */ PK!Q:internal/intern/rational.hnu[#ifndef RBIMPL_INTERN_RATIONAL_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_RATIONAL_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_cRational. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" #include "ruby/internal/arithmetic/long.h" /* INT2FIX is here. */ RBIMPL_SYMBOL_EXPORT_BEGIN() /* rational.c */ VALUE rb_rational_raw(VALUE, VALUE); #define rb_rational_raw1(x) rb_rational_raw((x), INT2FIX(1)) #define rb_rational_raw2(x,y) rb_rational_raw((x), (y)) VALUE rb_rational_new(VALUE, VALUE); #define rb_rational_new1(x) rb_rational_new((x), INT2FIX(1)) #define rb_rational_new2(x,y) rb_rational_new((x), (y)) VALUE rb_Rational(VALUE, VALUE); #define rb_Rational1(x) rb_Rational((x), INT2FIX(1)) #define rb_Rational2(x,y) rb_Rational((x), (y)) VALUE rb_rational_num(VALUE rat); VALUE rb_rational_den(VALUE rat); VALUE rb_flt_rationalize_with_prec(VALUE, VALUE); VALUE rb_flt_rationalize(VALUE); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_RATIONAL_H */ PK! $((internal/intern/process.hnu[#ifndef RBIMPL_INTERN_PROCESS_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_PROCESS_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_mProcess. */ #include "ruby/internal/attr/noreturn.h" #include "ruby/internal/config.h" /* rb_pid_t is defined here. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* process.c */ void rb_last_status_set(int status, rb_pid_t pid); VALUE rb_last_status_get(void); int rb_proc_exec(const char*); RBIMPL_ATTR_NORETURN() VALUE rb_f_exec(int, const VALUE*); rb_pid_t rb_waitpid(rb_pid_t pid, int *status, int flags); void rb_syswait(rb_pid_t pid); rb_pid_t rb_spawn(int, const VALUE*); rb_pid_t rb_spawn_err(int, const VALUE*, char*, size_t); VALUE rb_proc_times(VALUE); VALUE rb_detach_process(rb_pid_t pid); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_PROCESS_H */ PK!Ai;internal/intern/signal.hnu[#ifndef RBIMPL_INTERN_SIGNAL_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_SIGNAL_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Signal handling APIs. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* signal.c */ VALUE rb_f_kill(int, const VALUE*); #ifdef POSIX_SIGNAL #define posix_signal ruby_posix_signal void (*posix_signal(int, void (*)(int)))(int); #endif const char *ruby_signal_name(int); void ruby_default_signal(int); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_SIGNAL_H */ PK!c}internal/intern/struct.hnu[#ifndef RBIMPL_INTERN_STRUCT_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_STRUCT_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_cStruct. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/intern/vm.h" /* rb_alloc_func_t */ #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* struct.c */ VALUE rb_struct_new(VALUE, ...); VALUE rb_struct_define(const char*, ...); VALUE rb_struct_define_under(VALUE, const char*, ...); VALUE rb_struct_alloc(VALUE, VALUE); VALUE rb_struct_initialize(VALUE, VALUE); VALUE rb_struct_aref(VALUE, VALUE); VALUE rb_struct_aset(VALUE, VALUE, VALUE); VALUE rb_struct_getmember(VALUE, ID); VALUE rb_struct_s_members(VALUE); VALUE rb_struct_members(VALUE); VALUE rb_struct_size(VALUE s); VALUE rb_struct_alloc_noinit(VALUE); VALUE rb_struct_define_without_accessor(const char *, VALUE, rb_alloc_func_t, ...); VALUE rb_struct_define_without_accessor_under(VALUE outer, const char *class_name, VALUE super, rb_alloc_func_t alloc, ...); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_STRUCT_H */ PK![Z internal/intern/object.hnu[#ifndef RBIMPL_INTERN_OBJECT_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_OBJECT_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_cObject. */ #include "ruby/internal/attr/pure.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() #define RB_OBJ_INIT_COPY(obj, orig) \ ((obj) != (orig) && (rb_obj_init_copy((obj), (orig)), 1)) #define OBJ_INIT_COPY(obj, orig) RB_OBJ_INIT_COPY(obj, orig) VALUE rb_class_new_instance_pass_kw(int, const VALUE *, VALUE); VALUE rb_class_new_instance(int, const VALUE*, VALUE); VALUE rb_class_new_instance_kw(int, const VALUE*, VALUE, int); /* object.c */ int rb_eql(VALUE, VALUE); VALUE rb_any_to_s(VALUE); VALUE rb_inspect(VALUE); VALUE rb_obj_is_instance_of(VALUE, VALUE); VALUE rb_obj_is_kind_of(VALUE, VALUE); VALUE rb_obj_alloc(VALUE); VALUE rb_obj_clone(VALUE); VALUE rb_obj_dup(VALUE); VALUE rb_obj_init_copy(VALUE,VALUE); VALUE rb_obj_taint(VALUE); RBIMPL_ATTR_PURE() VALUE rb_obj_tainted(VALUE); VALUE rb_obj_untaint(VALUE); VALUE rb_obj_untrust(VALUE); RBIMPL_ATTR_PURE() VALUE rb_obj_untrusted(VALUE); VALUE rb_obj_trust(VALUE); VALUE rb_obj_freeze(VALUE); RBIMPL_ATTR_PURE() VALUE rb_obj_frozen_p(VALUE); VALUE rb_obj_id(VALUE); VALUE rb_memory_id(VALUE); VALUE rb_obj_class(VALUE); RBIMPL_ATTR_PURE() VALUE rb_class_real(VALUE); RBIMPL_ATTR_PURE() VALUE rb_class_inherited_p(VALUE, VALUE); VALUE rb_class_superclass(VALUE); VALUE rb_class_get_superclass(VALUE); VALUE rb_convert_type(VALUE,int,const char*,const char*); VALUE rb_check_convert_type(VALUE,int,const char*,const char*); VALUE rb_check_to_integer(VALUE, const char *); VALUE rb_check_to_float(VALUE); VALUE rb_to_int(VALUE); VALUE rb_check_to_int(VALUE); VALUE rb_Integer(VALUE); VALUE rb_to_float(VALUE); VALUE rb_Float(VALUE); VALUE rb_String(VALUE); VALUE rb_Array(VALUE); VALUE rb_Hash(VALUE); double rb_cstr_to_dbl(const char*, int); double rb_str_to_dbl(VALUE, int); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_OBJECT_H */ PK!+෷ internal/intern/class.hnu[#ifndef RBIMPL_INTERN_CLASS_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_CLASS_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_cClass/::rb_cModule. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" #include "ruby/backward/2/stdarg.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* class.c */ VALUE rb_class_new(VALUE); VALUE rb_mod_init_copy(VALUE, VALUE); VALUE rb_singleton_class_clone(VALUE); void rb_singleton_class_attached(VALUE,VALUE); void rb_check_inheritable(VALUE); VALUE rb_define_class_id(ID, VALUE); VALUE rb_define_class_id_under(VALUE, ID, VALUE); VALUE rb_module_new(void); VALUE rb_define_module_id(ID); VALUE rb_define_module_id_under(VALUE, ID); VALUE rb_mod_included_modules(VALUE); VALUE rb_mod_include_p(VALUE, VALUE); VALUE rb_mod_ancestors(VALUE); VALUE rb_class_instance_methods(int, const VALUE*, VALUE); VALUE rb_class_public_instance_methods(int, const VALUE*, VALUE); VALUE rb_class_protected_instance_methods(int, const VALUE*, VALUE); VALUE rb_class_private_instance_methods(int, const VALUE*, VALUE); VALUE rb_obj_singleton_methods(int, const VALUE*, VALUE); void rb_define_method_id(VALUE, ID, VALUE (*)(ANYARGS), int); void rb_undef(VALUE, ID); void rb_define_protected_method(VALUE, const char*, VALUE (*)(ANYARGS), int); void rb_define_private_method(VALUE, const char*, VALUE (*)(ANYARGS), int); void rb_define_singleton_method(VALUE, const char*, VALUE(*)(ANYARGS), int); VALUE rb_singleton_class(VALUE); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_CLASS_H */ PK!X!\=internal/intern/select.hnu[#ifndef RBIMPL_INTERN_SELECT_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_SELECT_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs to provide ::rb_fd_select(). * @note Functions and structs defined in this header file are not * necessarily ruby-specific. They don't need ::VALUE etc. */ #include "ruby/internal/config.h" #ifdef HAVE_SYS_TYPES_H # include /* for NFDBITS (BSD Net/2) */ #endif #include "ruby/internal/dllexport.h" /* thread.c */ #if defined(NFDBITS) && defined(HAVE_RB_FD_INIT) # include "ruby/internal/intern/select/largesize.h" #elif defined(_WIN32) # include "ruby/internal/intern/select/win32.h" # define rb_fd_resize(n, f) ((void)(f)) #else # include "ruby/internal/intern/select/posix.h" # define rb_fd_resize(n, f) ((void)(f)) #endif RBIMPL_SYMBOL_EXPORT_BEGIN() struct timeval; int rb_thread_fd_select(int, rb_fdset_t *, rb_fdset_t *, rb_fdset_t *, struct timeval *); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_SELECT_H */ PK!liinternal/intern/ruby.hnu[#ifndef RBIMPL_INTERN_RUBY_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_RUBY_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Process-global APIs. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* ruby.c */ #define rb_argv rb_get_argv() RUBY_EXTERN VALUE rb_argv0; VALUE rb_get_argv(void); void *rb_load_file(const char*); void *rb_load_file_str(VALUE); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_RUBY_H */ PK!internal/intern/random.hnu[#ifndef RBIMPL_INTERN_RANDOM_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_RANDOM_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief MT19937 backended pseudo random number generator. * @see Matsumoto, M., Nishimura, T., "Mersenne Twister: A 623- * dimensionally equidistributed uniform pseudorandom number * generator", ACM Trans. on Modeling and Computer Simulation, 8 * (1): pp 3-30, 1998. https://doi.org/10.1145/272991.272995 */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* random.c */ unsigned int rb_genrand_int32(void); double rb_genrand_real(void); void rb_reset_random_seed(void); VALUE rb_random_bytes(VALUE rnd, long n); VALUE rb_random_int(VALUE rnd, VALUE max); unsigned int rb_random_int32(VALUE rnd); double rb_random_real(VALUE rnd); unsigned long rb_random_ulong_limited(VALUE rnd, unsigned long limit); unsigned long rb_genrand_ulong_limited(unsigned long i); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_RANDOM_H */ PK! internal/intern/variable.hnu[#ifndef RBIMPL_INTERN_VARIABLE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_VARIABLE_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to names inside of a Ruby program. */ #include "ruby/internal/attr/noreturn.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" #include "ruby/st.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* variable.c */ VALUE rb_mod_name(VALUE); VALUE rb_class_path(VALUE); VALUE rb_class_path_cached(VALUE); void rb_set_class_path(VALUE, VALUE, const char*); void rb_set_class_path_string(VALUE, VALUE, VALUE); VALUE rb_path_to_class(VALUE); VALUE rb_path2class(const char*); VALUE rb_class_name(VALUE); VALUE rb_autoload_load(VALUE, ID); VALUE rb_autoload_p(VALUE, ID); VALUE rb_f_trace_var(int, const VALUE*); VALUE rb_f_untrace_var(int, const VALUE*); VALUE rb_f_global_variables(void); void rb_alias_variable(ID, ID); void rb_copy_generic_ivar(VALUE,VALUE); void rb_free_generic_ivar(VALUE); VALUE rb_ivar_get(VALUE, ID); VALUE rb_ivar_set(VALUE, ID, VALUE); VALUE rb_ivar_defined(VALUE, ID); void rb_ivar_foreach(VALUE, int (*)(ID, VALUE, st_data_t), st_data_t); st_index_t rb_ivar_count(VALUE); VALUE rb_attr_get(VALUE, ID); VALUE rb_obj_instance_variables(VALUE); VALUE rb_obj_remove_instance_variable(VALUE, VALUE); void *rb_mod_const_at(VALUE, void*); void *rb_mod_const_of(VALUE, void*); VALUE rb_const_list(void*); VALUE rb_mod_constants(int, const VALUE *, VALUE); VALUE rb_mod_remove_const(VALUE, VALUE); int rb_const_defined(VALUE, ID); int rb_const_defined_at(VALUE, ID); int rb_const_defined_from(VALUE, ID); VALUE rb_const_get(VALUE, ID); VALUE rb_const_get_at(VALUE, ID); VALUE rb_const_get_from(VALUE, ID); void rb_const_set(VALUE, ID, VALUE); VALUE rb_const_remove(VALUE, ID); #if 0 /* EXPERIMENTAL: remove if no problem */ RBIMPL_ATTR_NORETURN() VALUE rb_mod_const_missing(VALUE,VALUE); #endif VALUE rb_cvar_defined(VALUE, ID); void rb_cvar_set(VALUE, ID, VALUE); VALUE rb_cvar_get(VALUE, ID); void rb_cv_set(VALUE, const char*, VALUE); VALUE rb_cv_get(VALUE, const char*); void rb_define_class_variable(VALUE, const char*, VALUE); VALUE rb_mod_class_variables(int, const VALUE*, VALUE); VALUE rb_mod_remove_cvar(VALUE, VALUE); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_VARIABLE_H */ PK!;)internal/intern/sprintf.hnu[#ifndef RBIMPL_INTERN_SPRINTF_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_SPRINTF_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Our own private printf(3). */ #include "ruby/internal/attr/format.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* sprintf.c */ VALUE rb_f_sprintf(int, const VALUE*); RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 2) VALUE rb_sprintf(const char*, ...); VALUE rb_vsprintf(const char*, va_list); RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 3) VALUE rb_str_catf(VALUE, const char*, ...); VALUE rb_str_vcatf(VALUE, const char*, va_list); VALUE rb_str_format(int, const VALUE *, VALUE); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_SPRINTF_H */ PK!lCinternal/intern/load.hnu[#ifndef RBIMPL_INTERN_LOAD_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_LOAD_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_f_require(). */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* load.c */ void rb_load(VALUE, int); void rb_load_protect(VALUE, int, int*); int rb_provided(const char*); int rb_feature_provided(const char *, const char **); void rb_provide(const char*); VALUE rb_f_require(VALUE, VALUE); VALUE rb_require_string(VALUE); // extension configuration void rb_ext_ractor_safe(bool flag); #define RB_EXT_RACTOR_SAFE(f) rb_ext_ractor_safe(f) #define HAVE_RB_EXT_RACTOR_SAFE 1 RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_LOAD_H */ PK!ݱ[[internal/intern/compar.hnu[#ifndef RBIMPL_INTERN_COMPAR_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_COMPAR_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_mComparable. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* compar.c */ int rb_cmpint(VALUE, VALUE, VALUE); NORETURN(void rb_cmperr(VALUE, VALUE)); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_COMPAR_H */ PK!DDinternal/intern/time.hnu[#ifndef RBIMPL_INTERN_TIME_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_TIME_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_cTime. */ #include "ruby/internal/config.h" #ifdef HAVE_TIME_H # include /* for time_t */ #endif #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() struct timespec; struct timeval; /* time.c */ void rb_timespec_now(struct timespec *); VALUE rb_time_new(time_t, long); VALUE rb_time_nano_new(time_t, long); VALUE rb_time_timespec_new(const struct timespec *, int); VALUE rb_time_num_new(VALUE, VALUE); struct timeval rb_time_interval(VALUE num); struct timeval rb_time_timeval(VALUE time); struct timespec rb_time_timespec(VALUE time); struct timespec rb_time_timespec_interval(VALUE num); VALUE rb_time_utc_offset(VALUE time); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_TIME_H */ PK!internal/intern/file.hnu[#ifndef RBIMPL_INTERN_FILE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_FILE_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_cFile. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* file.c */ VALUE rb_file_s_expand_path(int, const VALUE *); VALUE rb_file_expand_path(VALUE, VALUE); VALUE rb_file_s_absolute_path(int, const VALUE *); VALUE rb_file_absolute_path(VALUE, VALUE); VALUE rb_file_dirname(VALUE fname); int rb_find_file_ext(VALUE*, const char* const*); VALUE rb_find_file(VALUE); VALUE rb_file_directory_p(VALUE,VALUE); VALUE rb_str_encode_ospath(VALUE); int rb_is_absolute_path(const char *); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_FILE_H */ PK!7xinternal/intern/enumerator.hnu[#ifndef RBIMPL_INTERN_ENUMERATOR_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_ENUMERATOR_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_cEnumerator. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/intern/eval.h" /* rb_frame_this_func */ #include "ruby/internal/iterator.h" /* rb_block_given_p */ #include "ruby/internal/symbol.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() typedef VALUE rb_enumerator_size_func(VALUE, VALUE, VALUE); typedef struct { VALUE begin; VALUE end; VALUE step; int exclude_end; } rb_arithmetic_sequence_components_t; /* enumerator.c */ VALUE rb_enumeratorize(VALUE, VALUE, int, const VALUE *); VALUE rb_enumeratorize_with_size(VALUE, VALUE, int, const VALUE *, rb_enumerator_size_func *); VALUE rb_enumeratorize_with_size_kw(VALUE, VALUE, int, const VALUE *, rb_enumerator_size_func *, int); int rb_arithmetic_sequence_extract(VALUE, rb_arithmetic_sequence_components_t *); VALUE rb_arithmetic_sequence_beg_len_step(VALUE, long *begp, long *lenp, long *stepp, long len, int err); RBIMPL_SYMBOL_EXPORT_END() #ifndef RUBY_EXPORT # define rb_enumeratorize_with_size(obj, id, argc, argv, size_fn) \ rb_enumeratorize_with_size(obj, id, argc, argv, (rb_enumerator_size_func *)(size_fn)) # define rb_enumeratorize_with_size_kw(obj, id, argc, argv, size_fn, kw_splat) \ rb_enumeratorize_with_size_kw(obj, id, argc, argv, (rb_enumerator_size_func *)(size_fn), kw_splat) #endif #define SIZED_ENUMERATOR(obj, argc, argv, size_fn) \ rb_enumeratorize_with_size((obj), ID2SYM(rb_frame_this_func()), \ (argc), (argv), (size_fn)) #define SIZED_ENUMERATOR_KW(obj, argc, argv, size_fn, kw_splat) \ rb_enumeratorize_with_size_kw((obj), ID2SYM(rb_frame_this_func()), \ (argc), (argv), (size_fn), (kw_splat)) #define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn) do { \ if (!rb_block_given_p()) \ return SIZED_ENUMERATOR(obj, argc, argv, size_fn); \ } while (0) #define RETURN_SIZED_ENUMERATOR_KW(obj, argc, argv, size_fn, kw_splat) do { \ if (!rb_block_given_p()) \ return SIZED_ENUMERATOR_KW(obj, argc, argv, size_fn, kw_splat); \ } while (0) #define RETURN_ENUMERATOR(obj, argc, argv) \ RETURN_SIZED_ENUMERATOR(obj, argc, argv, 0) #define RETURN_ENUMERATOR_KW(obj, argc, argv, kw_splat) \ RETURN_SIZED_ENUMERATOR_KW(obj, argc, argv, 0, kw_splat) #endif /* RBIMPL_INTERN_ENUMERATOR_H */ PK!=qm internal/intern/range.hnu[#ifndef RBIMPL_INTERN_RANGE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_RANGE_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_cRange. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* range.c */ VALUE rb_range_new(VALUE, VALUE, int); VALUE rb_range_beg_len(VALUE, long*, long*, long, int); int rb_range_values(VALUE range, VALUE *begp, VALUE *endp, int *exclp); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_RANGE_H */ PK!66internal/intern/enum.hnu[#ifndef RBIMPL_INTERN_ENUM_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_ENUM_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_mEnumerable. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* enum.c */ VALUE rb_enum_values_pack(int, const VALUE*); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_ENUM_H */ PK!Opinternal/anyargs.hnu[#ifndef RBIMPL_ANYARGS_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ANYARGS_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Function overloads to issue warnings around #ANYARGS. * * For instance ::rb_define_method takes a pointer to #ANYARGS -ed functions, * which in fact varies 18 different prototypes. We still need to preserve * #ANYARGS for storages but why not check the consistencies if possible. With * those complex macro overlays defined in this header file, use of a function * pointer gets checked against the corresponding arity argument. * * ### Q&A ### * * - Q: Where did the magic number "18" came from in the description above? * * - A: Count the case branch of `vm_method.c:call_cfunc_invoker_func()`. Note * also that the 18 branches has lasted for at least 25 years. See also * commit 200e0ee2fd3c1c006c528874a88f684447215524. * * - Q: What is this `__weakref__` thing? * * - A: That is a kind of function overloading mechanism that GCC provides. In * this case for instance `rb_define_method_00` is an alias of * ::rb_define_method, with a strong type. * * - Q: What is this `__transparent_union__` thing? * * A: That is another kind of function overloading mechanism that GCC * provides. In this case the attributed function pointer is either * `VALUE(*)(int,VALUE*,VALUE)` or `VALUE(*)(int,const VALUE*,VALUE)`. * * This is better than `void*` or #ANYARGS because we can reject all other * possibilities than the two. * * - Q: What does this #rb_define_method macro mean? * * - A: It selects appropriate alias of the ::rb_define_method function, * depending on the last (arity) argument. * * - Q: Why the special case for ::rb_f_notimplement ? * * - A: Function pointer to ::rb_f_notimplement is special cased in * `vm_method.c:rb_add_method_cfunc()`. That should be handled by the * `__builtin_choose_expr` chain inside of #rb_define_method macro * expansion. In order to do so, comparison like * `(func == rb_f_notimplement)` is inappropriate for * `__builtin_choose_expr`'s expression (which must be a compile-time * integer constant but the address of ::rb_f_notimplement is not fixed * until the linker). Instead we are using * `__builtin_types_compatible_p`, and in doing so we need to distinguish * ::rb_f_notimplement from others, by type. */ #include "ruby/internal/attr/maybe_unused.h" #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/attr/weakref.h" #include "ruby/internal/cast.h" #include "ruby/internal/config.h" #include "ruby/internal/has/attribute.h" #include "ruby/internal/intern/class.h" #include "ruby/internal/intern/vm.h" #include "ruby/internal/method.h" #include "ruby/internal/value.h" #include "ruby/backward/2/stdarg.h" #if defined(__cplusplus) # include "ruby/backward/cxxanyargs.hpp" #elif defined(_WIN32) || defined(__CYGWIN__) # /* Skip due to [Bug #16134] */ #elif ! RBIMPL_HAS_ATTRIBUTE(transparent_union) # /* :TODO: improve here, please find a way to support. */ #elif ! defined(HAVE_VA_ARGS_MACRO) # /* :TODO: improve here, please find a way to support. */ #else # /** @cond INTERNAL_MACRO */ # if ! defined(HAVE_BUILTIN___BUILTIN_TYPES_COMPATIBLE_P) # define RBIMPL_CFUNC_IS_rb_f_notimplement(f) 0 # else # define RBIMPL_CFUNC_IS_rb_f_notimplement(f) \ __builtin_types_compatible_p( \ __typeof__(f), \ __typeof__(rb_f_notimplement)) # endif # if ! defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P) # define RBIMPL_ANYARGS_DISPATCH(expr, truthy, falsy) (falsy) # else # define RBIMPL_ANYARGS_DISPATCH(expr, truthy, falsy) \ __builtin_choose_expr( \ __builtin_choose_expr( \ __builtin_constant_p(expr), \ (expr), 0), \ (truthy), (falsy)) # endif # define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_m2(n) RBIMPL_ANYARGS_DISPATCH((n) == -2, rb_define_singleton_method_m2, rb_define_singleton_method_m3) # define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_m1(n) RBIMPL_ANYARGS_DISPATCH((n) == -1, rb_define_singleton_method_m1, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_m2(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_00(n) RBIMPL_ANYARGS_DISPATCH((n) == 0, rb_define_singleton_method_00, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_m1(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_01(n) RBIMPL_ANYARGS_DISPATCH((n) == 1, rb_define_singleton_method_01, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_00(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_02(n) RBIMPL_ANYARGS_DISPATCH((n) == 2, rb_define_singleton_method_02, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_01(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_03(n) RBIMPL_ANYARGS_DISPATCH((n) == 3, rb_define_singleton_method_03, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_02(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_04(n) RBIMPL_ANYARGS_DISPATCH((n) == 4, rb_define_singleton_method_04, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_03(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_05(n) RBIMPL_ANYARGS_DISPATCH((n) == 5, rb_define_singleton_method_05, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_04(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_06(n) RBIMPL_ANYARGS_DISPATCH((n) == 6, rb_define_singleton_method_06, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_05(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_07(n) RBIMPL_ANYARGS_DISPATCH((n) == 7, rb_define_singleton_method_07, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_06(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_08(n) RBIMPL_ANYARGS_DISPATCH((n) == 8, rb_define_singleton_method_08, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_07(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_09(n) RBIMPL_ANYARGS_DISPATCH((n) == 9, rb_define_singleton_method_09, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_08(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_10(n) RBIMPL_ANYARGS_DISPATCH((n) == 10, rb_define_singleton_method_10, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_09(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_11(n) RBIMPL_ANYARGS_DISPATCH((n) == 11, rb_define_singleton_method_11, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_10(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_12(n) RBIMPL_ANYARGS_DISPATCH((n) == 12, rb_define_singleton_method_12, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_11(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_13(n) RBIMPL_ANYARGS_DISPATCH((n) == 13, rb_define_singleton_method_13, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_12(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_14(n) RBIMPL_ANYARGS_DISPATCH((n) == 14, rb_define_singleton_method_14, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_13(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_15(n) RBIMPL_ANYARGS_DISPATCH((n) == 15, rb_define_singleton_method_15, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_14(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_m2(n) RBIMPL_ANYARGS_DISPATCH((n) == -2, rb_define_protected_method_m2, rb_define_protected_method_m3) # define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_m1(n) RBIMPL_ANYARGS_DISPATCH((n) == -1, rb_define_protected_method_m1, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_m2(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_00(n) RBIMPL_ANYARGS_DISPATCH((n) == 0, rb_define_protected_method_00, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_m1(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_01(n) RBIMPL_ANYARGS_DISPATCH((n) == 1, rb_define_protected_method_01, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_00(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_02(n) RBIMPL_ANYARGS_DISPATCH((n) == 2, rb_define_protected_method_02, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_01(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_03(n) RBIMPL_ANYARGS_DISPATCH((n) == 3, rb_define_protected_method_03, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_02(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_04(n) RBIMPL_ANYARGS_DISPATCH((n) == 4, rb_define_protected_method_04, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_03(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_05(n) RBIMPL_ANYARGS_DISPATCH((n) == 5, rb_define_protected_method_05, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_04(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_06(n) RBIMPL_ANYARGS_DISPATCH((n) == 6, rb_define_protected_method_06, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_05(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_07(n) RBIMPL_ANYARGS_DISPATCH((n) == 7, rb_define_protected_method_07, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_06(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_08(n) RBIMPL_ANYARGS_DISPATCH((n) == 8, rb_define_protected_method_08, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_07(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_09(n) RBIMPL_ANYARGS_DISPATCH((n) == 9, rb_define_protected_method_09, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_08(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_10(n) RBIMPL_ANYARGS_DISPATCH((n) == 10, rb_define_protected_method_10, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_09(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_11(n) RBIMPL_ANYARGS_DISPATCH((n) == 11, rb_define_protected_method_11, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_10(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_12(n) RBIMPL_ANYARGS_DISPATCH((n) == 12, rb_define_protected_method_12, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_11(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_13(n) RBIMPL_ANYARGS_DISPATCH((n) == 13, rb_define_protected_method_13, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_12(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_14(n) RBIMPL_ANYARGS_DISPATCH((n) == 14, rb_define_protected_method_14, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_13(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_15(n) RBIMPL_ANYARGS_DISPATCH((n) == 15, rb_define_protected_method_15, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_14(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_m2(n) RBIMPL_ANYARGS_DISPATCH((n) == -2, rb_define_private_method_m2, rb_define_private_method_m3) # define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_m1(n) RBIMPL_ANYARGS_DISPATCH((n) == -1, rb_define_private_method_m1, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_m2(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_00(n) RBIMPL_ANYARGS_DISPATCH((n) == 0, rb_define_private_method_00, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_m1(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_01(n) RBIMPL_ANYARGS_DISPATCH((n) == 1, rb_define_private_method_01, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_00(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_02(n) RBIMPL_ANYARGS_DISPATCH((n) == 2, rb_define_private_method_02, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_01(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_03(n) RBIMPL_ANYARGS_DISPATCH((n) == 3, rb_define_private_method_03, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_02(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_04(n) RBIMPL_ANYARGS_DISPATCH((n) == 4, rb_define_private_method_04, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_03(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_05(n) RBIMPL_ANYARGS_DISPATCH((n) == 5, rb_define_private_method_05, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_04(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_06(n) RBIMPL_ANYARGS_DISPATCH((n) == 6, rb_define_private_method_06, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_05(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_07(n) RBIMPL_ANYARGS_DISPATCH((n) == 7, rb_define_private_method_07, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_06(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_08(n) RBIMPL_ANYARGS_DISPATCH((n) == 8, rb_define_private_method_08, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_07(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_09(n) RBIMPL_ANYARGS_DISPATCH((n) == 9, rb_define_private_method_09, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_08(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_10(n) RBIMPL_ANYARGS_DISPATCH((n) == 10, rb_define_private_method_10, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_09(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_11(n) RBIMPL_ANYARGS_DISPATCH((n) == 11, rb_define_private_method_11, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_10(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_12(n) RBIMPL_ANYARGS_DISPATCH((n) == 12, rb_define_private_method_12, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_11(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_13(n) RBIMPL_ANYARGS_DISPATCH((n) == 13, rb_define_private_method_13, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_12(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_14(n) RBIMPL_ANYARGS_DISPATCH((n) == 14, rb_define_private_method_14, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_13(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_15(n) RBIMPL_ANYARGS_DISPATCH((n) == 15, rb_define_private_method_15, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_14(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_m2(n) RBIMPL_ANYARGS_DISPATCH((n) == -2, rb_define_module_function_m2, rb_define_module_function_m3) # define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_m1(n) RBIMPL_ANYARGS_DISPATCH((n) == -1, rb_define_module_function_m1, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_m2(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_00(n) RBIMPL_ANYARGS_DISPATCH((n) == 0, rb_define_module_function_00, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_m1(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_01(n) RBIMPL_ANYARGS_DISPATCH((n) == 1, rb_define_module_function_01, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_00(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_02(n) RBIMPL_ANYARGS_DISPATCH((n) == 2, rb_define_module_function_02, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_01(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_03(n) RBIMPL_ANYARGS_DISPATCH((n) == 3, rb_define_module_function_03, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_02(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_04(n) RBIMPL_ANYARGS_DISPATCH((n) == 4, rb_define_module_function_04, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_03(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_05(n) RBIMPL_ANYARGS_DISPATCH((n) == 5, rb_define_module_function_05, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_04(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_06(n) RBIMPL_ANYARGS_DISPATCH((n) == 6, rb_define_module_function_06, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_05(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_07(n) RBIMPL_ANYARGS_DISPATCH((n) == 7, rb_define_module_function_07, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_06(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_08(n) RBIMPL_ANYARGS_DISPATCH((n) == 8, rb_define_module_function_08, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_07(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_09(n) RBIMPL_ANYARGS_DISPATCH((n) == 9, rb_define_module_function_09, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_08(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_10(n) RBIMPL_ANYARGS_DISPATCH((n) == 10, rb_define_module_function_10, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_09(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_11(n) RBIMPL_ANYARGS_DISPATCH((n) == 11, rb_define_module_function_11, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_10(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_12(n) RBIMPL_ANYARGS_DISPATCH((n) == 12, rb_define_module_function_12, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_11(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_13(n) RBIMPL_ANYARGS_DISPATCH((n) == 13, rb_define_module_function_13, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_12(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_14(n) RBIMPL_ANYARGS_DISPATCH((n) == 14, rb_define_module_function_14, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_13(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_15(n) RBIMPL_ANYARGS_DISPATCH((n) == 15, rb_define_module_function_15, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_14(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_m2(n) RBIMPL_ANYARGS_DISPATCH((n) == -2, rb_define_global_function_m2, rb_define_global_function_m3) # define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_m1(n) RBIMPL_ANYARGS_DISPATCH((n) == -1, rb_define_global_function_m1, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_m2(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_00(n) RBIMPL_ANYARGS_DISPATCH((n) == 0, rb_define_global_function_00, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_m1(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_01(n) RBIMPL_ANYARGS_DISPATCH((n) == 1, rb_define_global_function_01, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_00(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_02(n) RBIMPL_ANYARGS_DISPATCH((n) == 2, rb_define_global_function_02, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_01(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_03(n) RBIMPL_ANYARGS_DISPATCH((n) == 3, rb_define_global_function_03, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_02(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_04(n) RBIMPL_ANYARGS_DISPATCH((n) == 4, rb_define_global_function_04, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_03(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_05(n) RBIMPL_ANYARGS_DISPATCH((n) == 5, rb_define_global_function_05, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_04(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_06(n) RBIMPL_ANYARGS_DISPATCH((n) == 6, rb_define_global_function_06, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_05(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_07(n) RBIMPL_ANYARGS_DISPATCH((n) == 7, rb_define_global_function_07, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_06(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_08(n) RBIMPL_ANYARGS_DISPATCH((n) == 8, rb_define_global_function_08, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_07(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_09(n) RBIMPL_ANYARGS_DISPATCH((n) == 9, rb_define_global_function_09, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_08(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_10(n) RBIMPL_ANYARGS_DISPATCH((n) == 10, rb_define_global_function_10, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_09(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_11(n) RBIMPL_ANYARGS_DISPATCH((n) == 11, rb_define_global_function_11, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_10(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_12(n) RBIMPL_ANYARGS_DISPATCH((n) == 12, rb_define_global_function_12, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_11(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_13(n) RBIMPL_ANYARGS_DISPATCH((n) == 13, rb_define_global_function_13, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_12(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_14(n) RBIMPL_ANYARGS_DISPATCH((n) == 14, rb_define_global_function_14, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_13(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_15(n) RBIMPL_ANYARGS_DISPATCH((n) == 15, rb_define_global_function_15, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_14(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_m2(n) RBIMPL_ANYARGS_DISPATCH((n) == -2, rb_define_method_id_m2, rb_define_method_id_m3) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_m1(n) RBIMPL_ANYARGS_DISPATCH((n) == -1, rb_define_method_id_m1, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_m2(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_00(n) RBIMPL_ANYARGS_DISPATCH((n) == 0, rb_define_method_id_00, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_m1(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_01(n) RBIMPL_ANYARGS_DISPATCH((n) == 1, rb_define_method_id_01, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_00(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_02(n) RBIMPL_ANYARGS_DISPATCH((n) == 2, rb_define_method_id_02, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_01(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_03(n) RBIMPL_ANYARGS_DISPATCH((n) == 3, rb_define_method_id_03, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_02(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_04(n) RBIMPL_ANYARGS_DISPATCH((n) == 4, rb_define_method_id_04, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_03(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_05(n) RBIMPL_ANYARGS_DISPATCH((n) == 5, rb_define_method_id_05, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_04(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_06(n) RBIMPL_ANYARGS_DISPATCH((n) == 6, rb_define_method_id_06, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_05(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_07(n) RBIMPL_ANYARGS_DISPATCH((n) == 7, rb_define_method_id_07, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_06(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_08(n) RBIMPL_ANYARGS_DISPATCH((n) == 8, rb_define_method_id_08, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_07(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_09(n) RBIMPL_ANYARGS_DISPATCH((n) == 9, rb_define_method_id_09, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_08(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_10(n) RBIMPL_ANYARGS_DISPATCH((n) == 10, rb_define_method_id_10, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_09(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_11(n) RBIMPL_ANYARGS_DISPATCH((n) == 11, rb_define_method_id_11, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_10(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_12(n) RBIMPL_ANYARGS_DISPATCH((n) == 12, rb_define_method_id_12, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_11(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_13(n) RBIMPL_ANYARGS_DISPATCH((n) == 13, rb_define_method_id_13, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_12(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_14(n) RBIMPL_ANYARGS_DISPATCH((n) == 14, rb_define_method_id_14, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_13(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_15(n) RBIMPL_ANYARGS_DISPATCH((n) == 15, rb_define_method_id_15, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_14(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_m2(n) RBIMPL_ANYARGS_DISPATCH((n) == -2, rb_define_method_m2, rb_define_method_m3) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_m1(n) RBIMPL_ANYARGS_DISPATCH((n) == -1, rb_define_method_m1, RBIMPL_ANYARGS_DISPATCH_rb_define_method_m2(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_00(n) RBIMPL_ANYARGS_DISPATCH((n) == 0, rb_define_method_00, RBIMPL_ANYARGS_DISPATCH_rb_define_method_m1(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_01(n) RBIMPL_ANYARGS_DISPATCH((n) == 1, rb_define_method_01, RBIMPL_ANYARGS_DISPATCH_rb_define_method_00(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_02(n) RBIMPL_ANYARGS_DISPATCH((n) == 2, rb_define_method_02, RBIMPL_ANYARGS_DISPATCH_rb_define_method_01(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_03(n) RBIMPL_ANYARGS_DISPATCH((n) == 3, rb_define_method_03, RBIMPL_ANYARGS_DISPATCH_rb_define_method_02(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_04(n) RBIMPL_ANYARGS_DISPATCH((n) == 4, rb_define_method_04, RBIMPL_ANYARGS_DISPATCH_rb_define_method_03(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_05(n) RBIMPL_ANYARGS_DISPATCH((n) == 5, rb_define_method_05, RBIMPL_ANYARGS_DISPATCH_rb_define_method_04(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_06(n) RBIMPL_ANYARGS_DISPATCH((n) == 6, rb_define_method_06, RBIMPL_ANYARGS_DISPATCH_rb_define_method_05(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_07(n) RBIMPL_ANYARGS_DISPATCH((n) == 7, rb_define_method_07, RBIMPL_ANYARGS_DISPATCH_rb_define_method_06(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_08(n) RBIMPL_ANYARGS_DISPATCH((n) == 8, rb_define_method_08, RBIMPL_ANYARGS_DISPATCH_rb_define_method_07(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_09(n) RBIMPL_ANYARGS_DISPATCH((n) == 9, rb_define_method_09, RBIMPL_ANYARGS_DISPATCH_rb_define_method_08(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_10(n) RBIMPL_ANYARGS_DISPATCH((n) == 10, rb_define_method_10, RBIMPL_ANYARGS_DISPATCH_rb_define_method_09(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_11(n) RBIMPL_ANYARGS_DISPATCH((n) == 11, rb_define_method_11, RBIMPL_ANYARGS_DISPATCH_rb_define_method_10(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_12(n) RBIMPL_ANYARGS_DISPATCH((n) == 12, rb_define_method_12, RBIMPL_ANYARGS_DISPATCH_rb_define_method_11(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_13(n) RBIMPL_ANYARGS_DISPATCH((n) == 13, rb_define_method_13, RBIMPL_ANYARGS_DISPATCH_rb_define_method_12(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_14(n) RBIMPL_ANYARGS_DISPATCH((n) == 14, rb_define_method_14, RBIMPL_ANYARGS_DISPATCH_rb_define_method_13(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_15(n) RBIMPL_ANYARGS_DISPATCH((n) == 15, rb_define_method_15, RBIMPL_ANYARGS_DISPATCH_rb_define_method_14(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method(n, f) RBIMPL_ANYARGS_DISPATCH(RBIMPL_CFUNC_IS_rb_f_notimplement(f), rb_define_singleton_method_m3, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_15(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method(n, f) RBIMPL_ANYARGS_DISPATCH(RBIMPL_CFUNC_IS_rb_f_notimplement(f), rb_define_protected_method_m3, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_15(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method(n, f) RBIMPL_ANYARGS_DISPATCH(RBIMPL_CFUNC_IS_rb_f_notimplement(f), rb_define_private_method_m3, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_15(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function(n, f) RBIMPL_ANYARGS_DISPATCH(RBIMPL_CFUNC_IS_rb_f_notimplement(f), rb_define_module_function_m3, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_15(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function(n, f) RBIMPL_ANYARGS_DISPATCH(RBIMPL_CFUNC_IS_rb_f_notimplement(f), rb_define_global_function_m3, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_15(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id(n, f) RBIMPL_ANYARGS_DISPATCH(RBIMPL_CFUNC_IS_rb_f_notimplement(f), rb_define_method_id_m3, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_15(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method(n, f) RBIMPL_ANYARGS_DISPATCH(RBIMPL_CFUNC_IS_rb_f_notimplement(f), rb_define_method_m3, RBIMPL_ANYARGS_DISPATCH_rb_define_method_15(n)) # define RBIMPL_ANYARGS_ATTRSET(sym) RBIMPL_ATTR_MAYBE_UNUSED() RBIMPL_ATTR_NONNULL() RBIMPL_ATTR_WEAKREF(sym) # define RBIMPL_ANYARGS_DECL(sym, ...) \ RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _m3(__VA_ARGS__, VALUE(*)(ANYARGS), int); \ RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _m2(__VA_ARGS__, VALUE(*)(VALUE, VALUE), int); \ RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _m1(__VA_ARGS__, VALUE(*)(int, union { VALUE *x; const VALUE *y; } __attribute__((__transparent_union__)), VALUE), int); \ RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _00(__VA_ARGS__, VALUE(*)(VALUE), int); \ RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _01(__VA_ARGS__, VALUE(*)(VALUE, VALUE), int); \ RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _02(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE), int); \ RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _03(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE), int); \ RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _04(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE), int); \ RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _05(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \ RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _06(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \ RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _07(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \ RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _08(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \ RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _09(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \ RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _10(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \ RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _11(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \ RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _12(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \ RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _13(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \ RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _14(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \ RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _15(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); RBIMPL_ANYARGS_DECL(rb_define_singleton_method, VALUE, const char *) RBIMPL_ANYARGS_DECL(rb_define_protected_method, VALUE, const char *) RBIMPL_ANYARGS_DECL(rb_define_private_method, VALUE, const char *) RBIMPL_ANYARGS_DECL(rb_define_module_function, VALUE, const char *) RBIMPL_ANYARGS_DECL(rb_define_global_function, const char *) RBIMPL_ANYARGS_DECL(rb_define_method_id, VALUE, ID) RBIMPL_ANYARGS_DECL(rb_define_method, VALUE, const char *) /** @endcond */ /** * @brief Defines klass\#mid. * @see ::rb_define_method * @param klass Where the method lives. * @param mid Name of the defining method. * @param func Implementation of klass\#mid. * @param arity Arity of klass\#mid. */ #define rb_define_method(klass, mid, func, arity) RBIMPL_ANYARGS_DISPATCH_rb_define_method((arity), (func))((klass), (mid), (func), (arity)) /** * @brief Defines klass\#mid. * @see ::rb_define_method_id * @param klass Where the method lives. * @param mid Name of the defining method. * @param func Implementation of klass\#mid. * @param arity Arity of klass\#mid. */ #define rb_define_method_id(klass, mid, func, arity) RBIMPL_ANYARGS_DISPATCH_rb_define_method_id((arity), (func))((klass), (mid), (func), (arity)) /** * @brief Defines obj.mid. * @see ::rb_define_singleton_method * @param obj Where the method lives. * @param mid Name of the defining method. * @param func Implementation of obj.mid. * @param arity Arity of obj.mid. */ #define rb_define_singleton_method(obj, mid, func, arity) RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method((arity), (func))((obj), (mid), (func), (arity)) /** * @brief Defines klass\#mid and make it protected. * @see ::rb_define_protected_method * @param klass Where the method lives. * @param mid Name of the defining method. * @param func Implementation of klass\#mid. * @param arity Arity of klass\#mid. */ #define rb_define_protected_method(klass, mid, func, arity) RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method((arity), (func))((klass), (mid), (func), (arity)) /** * @brief Defines klass\#mid and make it private. * @see ::rb_define_private_method * @param klass Where the method lives. * @param mid Name of the defining method. * @param func Implementation of klass\#mid. * @param arity Arity of klass\#mid. */ #define rb_define_private_method(klass, mid, func, arity) RBIMPL_ANYARGS_DISPATCH_rb_define_private_method((arity), (func))((klass), (mid), (func), (arity)) /** * @brief Defines mod\#mid and make it a module function. * @see ::rb_define_module_function * @param mod Where the method lives. * @param mid Name of the defining method. * @param func Implementation of mod\#mid. * @param arity Arity of mod\#mid. */ #define rb_define_module_function(mod, mid, func, arity) RBIMPL_ANYARGS_DISPATCH_rb_define_module_function((arity), (func))((mod), (mid), (func), (arity)) /** * @brief Defines ::rb_mKerbel \#mid. * @see ::rb_define_gobal_function * @param mid Name of the defining method. * @param func Implementation of ::rb_mKernel \#mid. * @param arity Arity of ::rb_mKernel \#mid. */ #define rb_define_global_function(mid, func, arity) RBIMPL_ANYARGS_DISPATCH_rb_define_global_function((arity), (func))((mid), (func), (arity)) #endif /* __cplusplus */ /** * This macro is to properly cast a function parameter of *_define_method * family. It has been around since 1.x era so you can maximize backwards * compatibility by using it. * * ```CXX * rb_define_method(klass, "method", RUBY_METHOD_FUNC(func), arity); * ``` * * @param func A pointer to a function that implements a method. */ #if ! defined(RUBY_DEVEL) # define RUBY_METHOD_FUNC(func) RBIMPL_CAST((VALUE (*)(ANYARGS))(func)) #elif ! RUBY_DEVEL # define RUBY_METHOD_FUNC(func) RBIMPL_CAST((VALUE (*)(ANYARGS))(func)) #elif ! defined(rb_define_method) # define RUBY_METHOD_FUNC(func) RBIMPL_CAST((VALUE (*)(ANYARGS))(func)) #else # define RUBY_METHOD_FUNC(func) (func) #endif #endif /* RBIMPL_ANYARGS_H */ PK!c9internal/dosish.hnu[#ifndef RBIMPL_DOSISH_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_DOSISH_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Support for so-called dosish systems. */ #ifdef __CYGWIN__ #undef _WIN32 #endif #if defined(_WIN32) /* DOSISH mean MS-Windows style filesystem. But you should use more precise macros like DOSISH_DRIVE_LETTER, PATH_SEP, ENV_IGNORECASE or CASEFOLD_FILESYSTEM. */ #define DOSISH 1 # define DOSISH_DRIVE_LETTER #endif #ifdef _WIN32 #include "ruby/win32.h" #endif #if defined(DOSISH) #define PATH_SEP ";" #else #define PATH_SEP ":" #endif #define PATH_SEP_CHAR PATH_SEP[0] #define PATH_ENV "PATH" #if defined(DOSISH) #define ENV_IGNORECASE #endif #ifndef CASEFOLD_FILESYSTEM # if defined DOSISH # define CASEFOLD_FILESYSTEM 1 # else # define CASEFOLD_FILESYSTEM 0 # endif #endif #endif /* RBIMPL_DOSISH_H */ PK!O==internal/warning_push.hnu[#ifndef RBIMPL_WARNING_PUSH_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_WARNING_PUSH_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines RBIMPL_WARNING_PUSH. * @cond INTERNAL_MACRO * * ### Q&A ### * * Q: Why all the macros defined in this file are function-like macros? * * A: Sigh. This is because of Doxgen. Its `SKIP_FUNCTION_MACROS = YES` * configuration setting requests us that if we want it to ignore these * macros, then we have to do two things: (1) let them be defined as * function-like macros, and (2) place them separately in their own line, * like below: * * ```CXX * // NG -- foo's type considered something like `unsigned int`. * RBIMPL_WARNING_PUSH * int foo(void); * RBIMPL_WARNING_POP * * // OK -- the macros are ignored by Doxygen. * RBIMPL_WARNING_PUSH() * int foo(void); * RBIMPL_WARNING_POP() * ``` */ #include "ruby/internal/compiler_is.h" #include "ruby/internal/compiler_since.h" #if RBIMPL_COMPILER_SINCE(MSVC, 12, 0, 0) # /* Not sure exactly when but it seems VC++ 6.0 is a version with it.*/ # define RBIMPL_WARNING_PUSH() __pragma(warning(push)) # define RBIMPL_WARNING_POP() __pragma(warning(pop)) # define RBIMPL_WARNING_ERROR(flag) __pragma(warning(error: flag)) # define RBIMPL_WARNING_IGNORED(flag) __pragma(warning(disable: flag)) #elif RBIMPL_COMPILER_SINCE(Intel, 13, 0, 0) # define RBIMPL_WARNING_PUSH() __pragma(warning(push)) # define RBIMPL_WARNING_POP() __pragma(warning(pop)) # define RBIMPL_WARNING_ERROR(flag) __pragma(warning(error: flag)) # define RBIMPL_WARNING_IGNORED(flag) __pragma(warning(disable: flag)) #elif RBIMPL_COMPILER_IS(Clang) || RBIMPL_COMPILER_IS(Apple) # /* Not sure exactly when but it seems LLVM 2.6.0 is a version with it. */ # define RBIMPL_WARNING_PRAGMA0(x) _Pragma(# x) # define RBIMPL_WARNING_PRAGMA1(x) RBIMPL_WARNING_PRAGMA0(clang diagnostic x) # define RBIMPL_WARNING_PRAGMA2(x, y) RBIMPL_WARNING_PRAGMA1(x # y) # define RBIMPL_WARNING_PUSH() RBIMPL_WARNING_PRAGMA1(push) # define RBIMPL_WARNING_POP() RBIMPL_WARNING_PRAGMA1(pop) # define RBIMPL_WARNING_ERROR(flag) RBIMPL_WARNING_PRAGMA2(error, flag) # define RBIMPL_WARNING_IGNORED(flag) RBIMPL_WARNING_PRAGMA2(ignored, flag) #elif RBIMPL_COMPILER_SINCE(GCC, 4, 6, 0) # /* https://gcc.gnu.org/onlinedocs/gcc-4.6.0/gcc/Diagnostic-Pragmas.html */ # define RBIMPL_WARNING_PRAGMA0(x) _Pragma(# x) # define RBIMPL_WARNING_PRAGMA1(x) RBIMPL_WARNING_PRAGMA0(GCC diagnostic x) # define RBIMPL_WARNING_PRAGMA2(x, y) RBIMPL_WARNING_PRAGMA1(x # y) # define RBIMPL_WARNING_PUSH() RBIMPL_WARNING_PRAGMA1(push) # define RBIMPL_WARNING_POP() RBIMPL_WARNING_PRAGMA1(pop) # define RBIMPL_WARNING_ERROR(flag) RBIMPL_WARNING_PRAGMA2(error, flag) # define RBIMPL_WARNING_IGNORED(flag) RBIMPL_WARNING_PRAGMA2(ignored, flag) #else # /* :FIXME: improve here */ # define RBIMPL_WARNING_PUSH() /* void */ # define RBIMPL_WARNING_POP() /* void */ # define RBIMPL_WARNING_ERROR(flag) /* void */ # define RBIMPL_WARNING_IGNORED(flag) /* void */ #endif /* _MSC_VER */ /** @endcond */ #endif /* RBIMPL_WARNING_PUSH_H */ PK!Winternal/module.hnu[#ifndef RBIMPL_MODULE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_MODULE_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Creation and modification of Ruby modules. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() VALUE rb_define_class(const char*,VALUE); VALUE rb_define_module(const char*); VALUE rb_define_class_under(VALUE, const char*, VALUE); VALUE rb_define_module_under(VALUE, const char*); void rb_include_module(VALUE,VALUE); void rb_extend_object(VALUE,VALUE); void rb_prepend_module(VALUE,VALUE); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_MODULE_H */ PK!rWWinternal/error.hnu[#ifndef RBIMPL_ERROR_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ERROR_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Declares ::rb_raise(). */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" #include "ruby/backward/2/attributes.h" RBIMPL_SYMBOL_EXPORT_BEGIN() VALUE rb_errinfo(void); void rb_set_errinfo(VALUE); typedef enum { RB_WARN_CATEGORY_NONE, RB_WARN_CATEGORY_DEPRECATED, RB_WARN_CATEGORY_EXPERIMENTAL, RB_WARN_CATEGORY_ALL_BITS = 0x6 /* no RB_WARN_CATEGORY_NONE bit */ } rb_warning_category_t; /* for rb_readwrite_sys_fail first argument */ enum rb_io_wait_readwrite {RB_IO_WAIT_READABLE, RB_IO_WAIT_WRITABLE}; #define RB_IO_WAIT_READABLE RB_IO_WAIT_READABLE #define RB_IO_WAIT_WRITABLE RB_IO_WAIT_WRITABLE PRINTF_ARGS(NORETURN(void rb_raise(VALUE, const char*, ...)), 2, 3); PRINTF_ARGS(NORETURN(void rb_fatal(const char*, ...)), 1, 2); COLDFUNC PRINTF_ARGS(NORETURN(void rb_bug(const char*, ...)), 1, 2); NORETURN(void rb_bug_errno(const char*, int)); NORETURN(void rb_sys_fail(const char*)); NORETURN(void rb_sys_fail_str(VALUE)); NORETURN(void rb_mod_sys_fail(VALUE, const char*)); NORETURN(void rb_mod_sys_fail_str(VALUE, VALUE)); NORETURN(void rb_readwrite_sys_fail(enum rb_io_wait_readwrite, const char*)); NORETURN(void rb_iter_break(void)); NORETURN(void rb_iter_break_value(VALUE)); NORETURN(void rb_exit(int)); NORETURN(void rb_notimplement(void)); VALUE rb_syserr_new(int, const char *); VALUE rb_syserr_new_str(int n, VALUE arg); NORETURN(void rb_syserr_fail(int, const char*)); NORETURN(void rb_syserr_fail_str(int, VALUE)); NORETURN(void rb_mod_syserr_fail(VALUE, int, const char*)); NORETURN(void rb_mod_syserr_fail_str(VALUE, int, VALUE)); NORETURN(void rb_readwrite_syserr_fail(enum rb_io_wait_readwrite, int, const char*)); NORETURN(void rb_unexpected_type(VALUE,int)); VALUE *rb_ruby_verbose_ptr(void); VALUE *rb_ruby_debug_ptr(void); #define ruby_verbose (*rb_ruby_verbose_ptr()) #define ruby_debug (*rb_ruby_debug_ptr()) /* reports if `-W' specified */ PRINTF_ARGS(void rb_warning(const char*, ...), 1, 2); PRINTF_ARGS(void rb_category_warning(rb_warning_category_t, const char*, ...), 2, 3); PRINTF_ARGS(void rb_compile_warning(const char *, int, const char*, ...), 3, 4); PRINTF_ARGS(void rb_category_compile_warn(rb_warning_category_t, const char *, int, const char*, ...), 4, 5); PRINTF_ARGS(void rb_sys_warning(const char*, ...), 1, 2); /* reports always */ COLDFUNC PRINTF_ARGS(void rb_warn(const char*, ...), 1, 2); COLDFUNC PRINTF_ARGS(void rb_category_warn(rb_warning_category_t, const char*, ...), 2, 3); PRINTF_ARGS(void rb_compile_warn(const char *, int, const char*, ...), 3, 4); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_ERROR_H */ PK! 0  internal/arithmetic/size_t.hnu[#ifndef RBIMPL_ARITHMETIC_SIZE_T_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ARITHMETIC_SIZE_T_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Arithmetic conversion between C's `size_t` and Ruby's. */ #include "ruby/internal/config.h" #include "ruby/internal/arithmetic/int.h" #include "ruby/internal/arithmetic/long.h" #include "ruby/internal/arithmetic/long_long.h" #include "ruby/backward/2/long_long.h" #if SIZEOF_SIZE_T == SIZEOF_LONG_LONG # define RB_SIZE2NUM RB_ULL2NUM # define RB_SSIZE2NUM RB_LL2NUM #elif SIZEOF_SIZE_T == SIZEOF_LONG # define RB_SIZE2NUM RB_ULONG2NUM # define RB_SSIZE2NUM RB_LONG2NUM #else # define RB_SIZE2NUM RB_UINT2NUM # define RB_SSIZE2NUM RB_INT2NUM #endif #if SIZEOF_SIZE_T == SIZEOF_LONG_LONG # define RB_NUM2SIZE RB_NUM2ULL # define RB_NUM2SSIZE RB_NUM2LL #elif SIZEOF_SIZE_T == SIZEOF_LONG # define RB_NUM2SIZE RB_NUM2ULONG # define RB_NUM2SSIZE RB_NUM2LONG #else # define RB_NUM2SIZE RB_NUM2UINT # define RB_NUM2SSIZE RB_NUM2INT #endif #define NUM2SIZET RB_NUM2SIZE #define SIZET2NUM RB_SIZE2NUM #define NUM2SSIZET RB_NUM2SSIZE #define SSIZET2NUM RB_SSIZE2NUM #endif /* RBIMPL_ARITHMETIC_SIZE_T_H */ PK!WPinternal/arithmetic/off_t.hnu[#ifndef RBIMPL_ARITHMETIC_OFF_T_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ARITHMETIC_OFF_T_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Arithmetic conversion between C's `off_t` and Ruby's. */ #include "ruby/internal/config.h" #include "ruby/internal/arithmetic/int.h" #include "ruby/internal/arithmetic/long.h" #include "ruby/internal/arithmetic/long_long.h" #include "ruby/backward/2/long_long.h" #ifdef OFFT2NUM # /* take that. */ #elif SIZEOF_OFF_T == SIZEOF_LONG_LONG # define OFFT2NUM RB_LL2NUM #elif SIZEOF_OFF_T == SIZEOF_LONG # define OFFT2NUM RB_LONG2NUM #else # define OFFT2NUM RB_INT2NUM #endif #ifdef NUM2OFFT # /* take that. */ #elif SIZEOF_OFF_T == SIZEOF_LONG_LONG # define NUM2OFFT RB_NUM2LL #elif SIZEOF_OFF_T == SIZEOF_LONG # define NUM2OFFT RB_NUM2LONG #else # define NUM2OFFT RB_NUM2INT #endif #endif /* RBIMPL_ARITHMETIC_OFF_T_H */ PK!5 internal/arithmetic/st_data_t.hnu[#ifndef RBIMPL_ARITHMERIC_ST_DATA_T_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ARITHMERIC_ST_DATA_T_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Arithmetic conversion between C's `st_data_t` and Ruby's. */ #include "ruby/internal/arithmetic/fixnum.h" #include "ruby/internal/arithmetic/long.h" #include "ruby/internal/attr/artificial.h" #include "ruby/internal/attr/const.h" #include "ruby/internal/attr/constexpr.h" #include "ruby/internal/cast.h" #include "ruby/internal/value.h" #include "ruby/assert.h" #include "ruby/st.h" #define ST2FIX RB_ST2FIX /** @cond INTERNAL_MACRO */ #define RB_ST2FIX RB_ST2FIX /** @endcond */ RBIMPL_ATTR_CONST_UNLESS_DEBUG() RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(CXX14) RBIMPL_ATTR_ARTIFICIAL() /* See also [ruby-core:84395] [Bug #14218] [ruby-core:82687] [Bug #13877] */ static inline VALUE RB_ST2FIX(st_data_t i) { SIGNED_VALUE x = i; if (x >= 0) { x &= RUBY_FIXNUM_MAX; } else { x |= RUBY_FIXNUM_MIN; } RBIMPL_ASSERT_OR_ASSUME(RB_FIXABLE(x)); unsigned long y = RBIMPL_CAST((unsigned long)x); return RB_LONG2FIX(y); } #endif /* RBIMPL_ARITHMERIC_ST_DATA_T_H */ PK!internal/arithmetic/long.hnu[#ifndef RBIMPL_ARITHMETIC_LONG_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ARITHMETIC_LONG_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Arithmetic conversion between C's `long` and Ruby's. * * ### Q&A ### * * - Q: Why are INT2FIX etc. here, not in `int.h`? * * - A: Because they are in fact handling `long`. It seems someone did not * understand the difference of `int` and `long` when they designed those * macros. */ #include "ruby/internal/config.h" #include "ruby/internal/arithmetic/fixnum.h" /* FIXABLE */ #include "ruby/internal/arithmetic/intptr_t.h" /* rb_int2big etc.*/ #include "ruby/internal/assume.h" #include "ruby/internal/attr/artificial.h" #include "ruby/internal/attr/cold.h" #include "ruby/internal/attr/const.h" #include "ruby/internal/attr/constexpr.h" #include "ruby/internal/attr/noreturn.h" #include "ruby/internal/cast.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/special_consts.h" /* FIXNUM_FLAG */ #include "ruby/internal/value.h" #include "ruby/assert.h" #define FIX2LONG RB_FIX2LONG #define FIX2ULONG RB_FIX2ULONG #define INT2FIX RB_INT2FIX #define LONG2FIX RB_INT2FIX #define LONG2NUM RB_LONG2NUM #define NUM2LONG RB_NUM2LONG #define NUM2ULONG RB_NUM2ULONG #define RB_FIX2LONG rb_fix2long #define RB_FIX2ULONG rb_fix2ulong #define RB_LONG2FIX RB_INT2FIX #define RB_LONG2NUM rb_long2num_inline #define RB_NUM2LONG rb_num2long_inline #define RB_NUM2ULONG rb_num2ulong_inline #define RB_ULONG2NUM rb_ulong2num_inline #define ULONG2NUM RB_ULONG2NUM #define rb_fix_new RB_INT2FIX #define rb_long2int rb_long2int_inline /** @cond INTERNAL_MACRO */ #define RB_INT2FIX RB_INT2FIX /** @endcond */ RBIMPL_SYMBOL_EXPORT_BEGIN() RBIMPL_ATTR_NORETURN() RBIMPL_ATTR_COLD() void rb_out_of_int(SIGNED_VALUE num); long rb_num2long(VALUE num); unsigned long rb_num2ulong(VALUE num); RBIMPL_SYMBOL_EXPORT_END() RBIMPL_ATTR_CONST_UNLESS_DEBUG() RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(CXX14) RBIMPL_ATTR_ARTIFICIAL() static inline VALUE RB_INT2FIX(long i) { RBIMPL_ASSERT_OR_ASSUME(RB_FIXABLE(i)); /* :NOTE: VALUE can be wider than long. As j being unsigned, 2j+1 is fully * defined. Also it can be compiled into a single LEA instruction. */ const unsigned long j = i; const unsigned long k = 2 * j + RUBY_FIXNUM_FLAG; const long l = k; const SIGNED_VALUE m = l; /* Sign extend */ const VALUE n = m; RBIMPL_ASSERT_OR_ASSUME(RB_FIXNUM_P(n)); return n; } static inline int rb_long2int_inline(long n) { int i = RBIMPL_CAST((int)n); if /* constexpr */ (sizeof(long) <= sizeof(int)) { RBIMPL_ASSUME(i == n); } if (i != n) rb_out_of_int(n); return i; } RBIMPL_ATTR_CONST_UNLESS_DEBUG() RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(CXX14) static inline long rbimpl_fix2long_by_idiv(VALUE x) { RBIMPL_ASSERT_OR_ASSUME(RB_FIXNUM_P(x)); /* :NOTE: VALUE can be wider than long. (x-1)/2 never overflows because * RB_FIXNUM_P(x) holds. Also it has no portability issue like y>>1 * below. */ const SIGNED_VALUE y = x - RUBY_FIXNUM_FLAG; const SIGNED_VALUE z = y / 2; const long w = RBIMPL_CAST((long)z); RBIMPL_ASSERT_OR_ASSUME(RB_FIXABLE(w)); return w; } RBIMPL_ATTR_CONST_UNLESS_DEBUG() RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(CXX14) static inline long rbimpl_fix2long_by_shift(VALUE x) { RBIMPL_ASSERT_OR_ASSUME(RB_FIXNUM_P(x)); /* :NOTE: VALUE can be wider than long. If right shift is arithmetic, this * is noticeably faster than above. */ const SIGNED_VALUE y = x; const SIGNED_VALUE z = y >> 1; const long w = RBIMPL_CAST((long)z); RBIMPL_ASSERT_OR_ASSUME(RB_FIXABLE(w)); return w; } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) static inline bool rbimpl_right_shift_is_arithmetic_p(void) { return (-1 >> 1) == -1; } RBIMPL_ATTR_CONST_UNLESS_DEBUG() RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(CXX14) static inline long rb_fix2long(VALUE x) { if /* constexpr */ (rbimpl_right_shift_is_arithmetic_p()) { return rbimpl_fix2long_by_shift(x); } else { return rbimpl_fix2long_by_idiv(x); } } RBIMPL_ATTR_CONST_UNLESS_DEBUG() RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(CXX14) static inline unsigned long rb_fix2ulong(VALUE x) { RBIMPL_ASSERT_OR_ASSUME(RB_FIXNUM_P(x)); return rb_fix2long(x); } static inline long rb_num2long_inline(VALUE x) { if (RB_FIXNUM_P(x)) return RB_FIX2LONG(x); else return rb_num2long(x); } static inline unsigned long rb_num2ulong_inline(VALUE x) { /* This (negative fixnum would become a large unsigned long while negative * bignum is an exception) has been THE behaviour of NUM2ULONG since the * beginning. It is strange, but we can no longer change how it works at * this moment. We have to get by with it. See also: * https://bugs.ruby-lang.org/issues/9089 */ if (RB_FIXNUM_P(x)) return RB_FIX2ULONG(x); else return rb_num2ulong(x); } static inline VALUE rb_long2num_inline(long v) { if (RB_FIXABLE(v)) return RB_LONG2FIX(v); else return rb_int2big(v); } static inline VALUE rb_ulong2num_inline(unsigned long v) { if (RB_POSFIXABLE(v)) return RB_LONG2FIX(v); else return rb_uint2big(v); } /** * @cond INTERNAL_MACRO * * Following overload is necessary because sometimes INT2FIX is used as a enum * value (e.g. `enum { FOO = INT2FIX(0) };`). THIS IS NG in theory because a * VALUE does not fit into an enum (which must be a signed int). But we cannot * break existing codes. */ #if RBIMPL_HAS_ATTR_CONSTEXPR_CXX14 # /* C++ can write constexpr as enum values. */ #elif ! defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P) # undef INT2FIX # define INT2FIX(i) (RBIMPL_CAST((VALUE)(i)) << 1 | RUBY_FIXNUM_FLAG) #else # undef INT2FIX # define INT2FIX(i) \ __builtin_choose_expr( \ __builtin_constant_p(i), \ RBIMPL_CAST((VALUE)(i)) << 1 | RUBY_FIXNUM_FLAG, \ RB_INT2FIX(i)) #endif /** @endcond */ #endif /* RBIMPL_ARITHMETIC_LONG_H */ PK!LPPinternal/arithmetic/mode_t.hnu[#ifndef RBIMPL_ARITHMETIC_MODE_T_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ARITHMETIC_MODE_T_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Arithmetic conversion between C's `mode_t` and Ruby's. */ #include "ruby/internal/config.h" #include "ruby/internal/arithmetic/int.h" #ifndef NUM2MODET # define NUM2MODET RB_NUM2INT #endif #ifndef MODET2NUM # define MODET2NUM RB_INT2NUM #endif #endif /* RBIMPL_ARITHMETIC_MODE_T_H */ PK!fS<+ + internal/arithmetic/char.hnu[#ifndef RBIMPL_ARITHMETIC_CHAR_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ARITHMETIC_CHAR_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Arithmetic conversion between C's `char` and Ruby's. */ #include "ruby/internal/arithmetic/int.h" /* NUM2INT is here, but */ #include "ruby/internal/arithmetic/long.h" /* INT2FIX is here.*/ #include "ruby/internal/attr/artificial.h" #include "ruby/internal/attr/const.h" #include "ruby/internal/attr/constexpr.h" #include "ruby/internal/cast.h" #include "ruby/internal/core/rstring.h" #include "ruby/internal/value_type.h" #define RB_NUM2CHR rb_num2char_inline #define NUM2CHR RB_NUM2CHR #define CHR2FIX RB_CHR2FIX /** @cond INTERNAL_MACRO */ #define RB_CHR2FIX RB_CHR2FIX /** @endcond */ RBIMPL_ATTR_CONST_UNLESS_DEBUG() RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(CXX14) RBIMPL_ATTR_ARTIFICIAL() static inline VALUE RB_CHR2FIX(unsigned char c) { return RB_INT2FIX(c); } static inline char rb_num2char_inline(VALUE x) { if (RB_TYPE_P(x, RUBY_T_STRING) && (RSTRING_LEN(x)>=1)) return RSTRING_PTR(x)[0]; else return RBIMPL_CAST((char)RB_NUM2INT(x)); } #endif /* RBIMPL_ARITHMETIC_CHAR_H */ PK!D5..internal/arithmetic/intptr_t.hnu[#ifndef RBIMPL_ARITHMETIC_INTPTR_T_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ARITHMETIC_INTPTR_T_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Arithmetic conversion between C's `intptr_t` and Ruby's. */ #include "ruby/internal/config.h" #ifdef HAVE_STDINT_H # include #endif #include "ruby/internal/value.h" #include "ruby/internal/dllexport.h" #define rb_int_new rb_int2inum #define rb_uint_new rb_uint2inum RBIMPL_SYMBOL_EXPORT_BEGIN() VALUE rb_int2big(intptr_t i); VALUE rb_int2inum(intptr_t i); VALUE rb_uint2big(uintptr_t i); VALUE rb_uint2inum(uintptr_t i); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_ARITHMETIC_INTPTR_T_H */ PK!lQinternal/arithmetic/fixnum.hnu[#ifndef RBIMPL_ARITHMETIC_FIXNUM_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ARITHMETIC_FIXNUM_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Handling of integers formerly known as Fixnums. */ #include "ruby/backward/2/limits.h" #define FIXABLE RB_FIXABLE #define FIXNUM_MAX RUBY_FIXNUM_MAX #define FIXNUM_MIN RUBY_FIXNUM_MIN #define NEGFIXABLE RB_NEGFIXABLE #define POSFIXABLE RB_POSFIXABLE /* * FIXABLE can be applied to anything, from double to intmax_t. The problem is * double. On a 64bit system RUBY_FIXNUM_MAX is 4,611,686,018,427,387,903, * which is not representable by a double. The nearest value that a double can * represent is 4,611,686,018,427,387,904, which is not fixable. The * seemingly-stragne "< FIXNUM_MAX + 1" expression below is due to this. */ #define RB_POSFIXABLE(_) ((_) < RUBY_FIXNUM_MAX + 1) #define RB_NEGFIXABLE(_) ((_) >= RUBY_FIXNUM_MIN) #define RB_FIXABLE(_) (RB_POSFIXABLE(_) && RB_NEGFIXABLE(_)) #define RUBY_FIXNUM_MAX (LONG_MAX / 2) #define RUBY_FIXNUM_MIN (LONG_MIN / 2) #endif /* RBIMPL_ARITHMETIC_FIXNUM_H */ PK!~qLLinternal/arithmetic/uid_t.hnu[#ifndef RBIMPL_ARITHMETIC_UID_T_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ARITHMETIC_UID_T_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Arithmetic conversion between C's `uid_t` and Ruby's. */ #include "ruby/internal/config.h" #include "ruby/internal/arithmetic/long.h" #ifndef UIDT2NUM # define UIDT2NUM RB_LONG2NUM #endif #ifndef NUM2UIDT # define NUM2UIDT RB_NUM2LONG #endif #endif /* RBIMPL_ARITHMETIC_UID_T_H */ PK!z$LLinternal/arithmetic/gid_t.hnu[#ifndef RBIMPL_ARITHMETIC_GID_T_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ARITHMETIC_GID_T_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Arithmetic conversion between C's `gid_t` and Ruby's. */ #include "ruby/internal/config.h" #include "ruby/internal/arithmetic/long.h" #ifndef GIDT2NUM # define GIDT2NUM RB_LONG2NUM #endif #ifndef NUM2GIDT # define NUM2GIDT RB_NUM2LONG #endif #endif /* RBIMPL_ARITHMETIC_GID_T_H */ PK!4}}internal/arithmetic/long_long.hnu[#ifndef RBIMPL_ARITHMETIC_LONG_LONG_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ARITHMETIC_LONG_LONG_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Arithmetic conversion between C's `long long` and Ruby's. */ #include "ruby/internal/value.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/special_consts.h" #include "ruby/backward/2/long_long.h" #define RB_LL2NUM rb_ll2inum #define RB_ULL2NUM rb_ull2inum #define LL2NUM RB_LL2NUM #define ULL2NUM RB_ULL2NUM #define RB_NUM2LL rb_num2ll_inline #define RB_NUM2ULL rb_num2ull #define NUM2LL RB_NUM2LL #define NUM2ULL RB_NUM2ULL RBIMPL_SYMBOL_EXPORT_BEGIN() VALUE rb_ll2inum(LONG_LONG); VALUE rb_ull2inum(unsigned LONG_LONG); LONG_LONG rb_num2ll(VALUE); unsigned LONG_LONG rb_num2ull(VALUE); RBIMPL_SYMBOL_EXPORT_END() static inline LONG_LONG rb_num2ll_inline(VALUE x) { if (RB_FIXNUM_P(x)) return RB_FIX2LONG(x); else return rb_num2ll(x); } #endif /* RBIMPL_ARITHMETIC_LONG_LONG_H */ PK!рinternal/arithmetic/short.hnu[#ifndef RBIMPL_ARITHMETIC_SHORT_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ARITHMETIC_SHORT_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Arithmetic conversion between C's `short` and Ruby's. * * Shyouhei wonders: why there is no SHORT2NUM, given there are both * #USHORT2NUM and #CHR2FIX? */ #include "ruby/internal/value.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/special_consts.h" #define RB_NUM2SHORT rb_num2short_inline #define RB_NUM2USHORT rb_num2ushort #define NUM2SHORT RB_NUM2SHORT #define NUM2USHORT RB_NUM2USHORT #define USHORT2NUM RB_INT2FIX #define RB_FIX2SHORT rb_fix2short #define FIX2SHORT RB_FIX2SHORT RBIMPL_SYMBOL_EXPORT_BEGIN() short rb_num2short(VALUE); unsigned short rb_num2ushort(VALUE); short rb_fix2short(VALUE); unsigned short rb_fix2ushort(VALUE); RBIMPL_SYMBOL_EXPORT_END() static inline short rb_num2short_inline(VALUE x) { if (RB_FIXNUM_P(x)) return rb_fix2short(x); else return rb_num2short(x); } #endif /* RBIMPL_ARITHMETIC_SOHRT_H */ PK!o**internal/arithmetic/double.hnu[#ifndef RBIMPL_ARITHMETIC_DOUBLE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ARITHMETIC_DOUBLE_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Arithmetic conversion between C's `double` and Ruby's. */ #include "ruby/internal/attr/pure.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" #define NUM2DBL rb_num2dbl #define RFLOAT_VALUE rb_float_value #define DBL2NUM rb_float_new RBIMPL_SYMBOL_EXPORT_BEGIN() double rb_num2dbl(VALUE); RBIMPL_ATTR_PURE() double rb_float_value(VALUE); VALUE rb_float_new(double); VALUE rb_float_new_in_heap(double); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_ARITHMETIC_DOUBLE_H */ PK!,6|LLinternal/arithmetic/pid_t.hnu[#ifndef RBIMPL_ARITHMETIC_PID_T_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ARITHMETIC_PID_T_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Arithmetic conversion between C's `pid_t` and Ruby's. */ #include "ruby/internal/config.h" #include "ruby/internal/arithmetic/long.h" #ifndef PIDT2NUM # define PIDT2NUM RB_LONG2NUM #endif #ifndef NUM2PIDT # define NUM2PIDT RB_NUM2LONG #endif #endif /* RBIMPL_ARITHMETIC_PID_T_H */ PK!g7internal/arithmetic/int.hnu[#ifndef RBIMPL_ARITHMETIC_INT_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ARITHMETIC_INT_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Arithmetic conversion between C's `int` and Ruby's. */ #include "ruby/internal/config.h" #include "ruby/internal/arithmetic/fixnum.h" #include "ruby/internal/arithmetic/intptr_t.h" #include "ruby/internal/arithmetic/long.h" #include "ruby/internal/attr/artificial.h" #include "ruby/internal/attr/const.h" #include "ruby/internal/attr/constexpr.h" #include "ruby/internal/compiler_is.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/special_consts.h" #include "ruby/internal/value.h" #include "ruby/internal/warning_push.h" #include "ruby/assert.h" #define RB_INT2NUM rb_int2num_inline #define RB_NUM2INT rb_num2int_inline #define RB_UINT2NUM rb_uint2num_inline #define FIX2INT RB_FIX2INT #define FIX2UINT RB_FIX2UINT #define INT2NUM RB_INT2NUM #define NUM2INT RB_NUM2INT #define NUM2UINT RB_NUM2UINT #define UINT2NUM RB_UINT2NUM /** @cond INTERNAL_MACRO */ #define RB_FIX2INT RB_FIX2INT #define RB_NUM2UINT RB_NUM2UINT #define RB_FIX2UINT RB_FIX2UINT /** @endcond */ RBIMPL_SYMBOL_EXPORT_BEGIN() long rb_num2int(VALUE); long rb_fix2int(VALUE); unsigned long rb_num2uint(VALUE); unsigned long rb_fix2uint(VALUE); RBIMPL_SYMBOL_EXPORT_END() RBIMPL_ATTR_ARTIFICIAL() static inline int RB_FIX2INT(VALUE x) { /* "FIX2INT raises a TypeError if passed nil", says rubyspec. Not sure if * that is a desired behaviour but just preserve backwards compatilibily. */ #if 0 RBIMPL_ASSERT_OR_ASSUME(RB_FIXNUM_P(x)); #endif long ret; if /* constexpr */ (sizeof(int) < sizeof(long)) { ret = rb_fix2int(x); } else { ret = RB_FIX2LONG(x); } return RBIMPL_CAST((int)ret); } static inline int rb_num2int_inline(VALUE x) { long ret; if /* constexpr */ (sizeof(int) == sizeof(long)) { ret = RB_NUM2LONG(x); } else if (RB_FIXNUM_P(x)) { ret = rb_fix2int(x); } else { ret = rb_num2int(x); } return RBIMPL_CAST((int)ret); } RBIMPL_ATTR_ARTIFICIAL() static inline unsigned int RB_NUM2UINT(VALUE x) { unsigned long ret; if /* constexpr */ (sizeof(int) < sizeof(long)) { ret = rb_num2uint(x); } else { ret = RB_NUM2ULONG(x); } return RBIMPL_CAST((unsigned int)ret); } RBIMPL_ATTR_ARTIFICIAL() static inline unsigned int RB_FIX2UINT(VALUE x) { #if 0 /* Ditto for RB_FIX2INT. */ RBIMPL_ASSERT_OR_ASSUME(RB_FIXNUM_P(x)); #endif unsigned long ret; if /* constexpr */ (sizeof(int) < sizeof(long)) { ret = rb_fix2uint(x); } else { ret = RB_FIX2ULONG(x); } return RBIMPL_CAST((unsigned int)ret); } RBIMPL_WARNING_PUSH() #if RBIMPL_COMPILER_IS(GCC) RBIMPL_WARNING_IGNORED(-Wtype-limits) /* We can ignore them here. */ #elif RBIMPL_HAS_WARNING("-Wtautological-constant-out-of-range-compare") RBIMPL_WARNING_IGNORED(-Wtautological-constant-out-of-range-compare) #endif static inline VALUE rb_int2num_inline(int v) { if (RB_FIXABLE(v)) return RB_INT2FIX(v); else return rb_int2big(v); } static inline VALUE rb_uint2num_inline(unsigned int v) { if (RB_POSFIXABLE(v)) return RB_LONG2FIX(v); else return rb_uint2big(v); } RBIMPL_WARNING_POP() #endif /* RBIMPL_ARITHMETIC_INT_H */ PK!%٫55internal/scan_args.hnu[#ifndef RBIMPL_SCAN_ARGS_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_SCAN_ARGS_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Compile-time static implementation of ::rb_scan_args(). * * This is a beast. It statically analyses the argument spec string, and * expands the assignment of variables into dedicated codes. */ #include "ruby/internal/attr/diagnose_if.h" #include "ruby/internal/attr/error.h" #include "ruby/internal/attr/forceinline.h" #include "ruby/internal/attr/noreturn.h" #include "ruby/internal/config.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/has/attribute.h" #include "ruby/internal/intern/array.h" /* rb_ary_new_from_values */ #include "ruby/internal/intern/error.h" /* rb_error_arity */ #include "ruby/internal/intern/hash.h" /* rb_hash_dup */ #include "ruby/internal/intern/proc.h" /* rb_block_proc */ #include "ruby/internal/iterator.h" /* rb_block_given_p / rb_keyword_given_p */ #include "ruby/internal/static_assert.h" #include "ruby/internal/stdbool.h" #include "ruby/internal/value.h" #include "ruby/assert.h" #define RB_SCAN_ARGS_PASS_CALLED_KEYWORDS 0 #define RB_SCAN_ARGS_KEYWORDS 1 #define RB_SCAN_ARGS_LAST_HASH_KEYWORDS 3 #define RB_NO_KEYWORDS 0 #define RB_PASS_KEYWORDS 1 #define RB_PASS_CALLED_KEYWORDS rb_keyword_given_p() /* rb_scan_args() format allows ':' for optional hash */ #define HAVE_RB_SCAN_ARGS_OPTIONAL_HASH 1 RBIMPL_SYMBOL_EXPORT_BEGIN() int rb_scan_args(int, const VALUE*, const char*, ...); int rb_scan_args_kw(int, int, const VALUE*, const char*, ...); RBIMPL_ATTR_ERROR(("bad scan arg format")) void rb_scan_args_bad_format(const char*); RBIMPL_ATTR_ERROR(("variable argument length doesn't match")) void rb_scan_args_length_mismatch(const char*,int); RBIMPL_SYMBOL_EXPORT_END() /* If we could use constexpr the following macros could be inline functions * ... but sadly we cannot. */ #define rb_scan_args_isdigit(c) (RBIMPL_CAST((unsigned char)((c)-'0'))<10) #define rb_scan_args_count_end(fmt, ofs, vari) \ ((fmt)[ofs] ? -1 : (vari)) #define rb_scan_args_count_block(fmt, ofs, vari) \ ((fmt)[ofs]!='&' ? \ rb_scan_args_count_end(fmt, ofs, vari) : \ rb_scan_args_count_end(fmt, (ofs)+1, (vari)+1)) #define rb_scan_args_count_hash(fmt, ofs, vari) \ ((fmt)[ofs]!=':' ? \ rb_scan_args_count_block(fmt, ofs, vari) : \ rb_scan_args_count_block(fmt, (ofs)+1, (vari)+1)) #define rb_scan_args_count_trail(fmt, ofs, vari) \ (!rb_scan_args_isdigit((fmt)[ofs]) ? \ rb_scan_args_count_hash(fmt, ofs, vari) : \ rb_scan_args_count_hash(fmt, (ofs)+1, (vari)+((fmt)[ofs]-'0'))) #define rb_scan_args_count_var(fmt, ofs, vari) \ ((fmt)[ofs]!='*' ? \ rb_scan_args_count_trail(fmt, ofs, vari) : \ rb_scan_args_count_trail(fmt, (ofs)+1, (vari)+1)) #define rb_scan_args_count_opt(fmt, ofs, vari) \ (!rb_scan_args_isdigit((fmt)[ofs]) ? \ rb_scan_args_count_var(fmt, ofs, vari) : \ rb_scan_args_count_var(fmt, (ofs)+1, (vari)+(fmt)[ofs]-'0')) #define rb_scan_args_count_lead(fmt, ofs, vari) \ (!rb_scan_args_isdigit((fmt)[ofs]) ? \ rb_scan_args_count_var(fmt, ofs, vari) : \ rb_scan_args_count_opt(fmt, (ofs)+1, (vari)+(fmt)[ofs]-'0')) #define rb_scan_args_count(fmt) rb_scan_args_count_lead(fmt, 0, 0) #if RBIMPL_HAS_ATTRIBUTE(diagnose_if) # /* Assertions done in the attribute. */ # define rb_scan_args_verify(fmt, varc) RBIMPL_ASSERT_NOTHING #else # /* At one sight it _seems_ the expressions below could be written using # * static assrtions. The reality is no, they don't. Because fmt is a string # * literal, any operations against fmt cannot produce the "integer constant # * expression"s, as defined in ISO/IEC 9899:2018 section 6.6 paragraph #6. # * Static assertions need such integer constant expressions as defined in # * ISO/IEC 9899:2018 section 6.7.10 paragraph #3. # * # * GCC nonetheless constant-folds this into no-op, though. */ # define rb_scan_args_verify(fmt, varc) \ (sizeof(char[1-2*(rb_scan_args_count(fmt)<0)])!=1 ? \ rb_scan_args_bad_format(fmt) : \ sizeof(char[1-2*(rb_scan_args_count(fmt)!=(varc))])!=1 ? \ rb_scan_args_length_mismatch(fmt, varc) : \ RBIMPL_ASSERT_NOTHING) #endif static inline bool rb_scan_args_keyword_p(int kw_flag, VALUE last) { switch (kw_flag) { case RB_SCAN_ARGS_PASS_CALLED_KEYWORDS: return !! rb_keyword_given_p(); case RB_SCAN_ARGS_KEYWORDS: return true; case RB_SCAN_ARGS_LAST_HASH_KEYWORDS: return RB_TYPE_P(last, T_HASH); default: return false; } } RBIMPL_ATTR_FORCEINLINE() static bool rb_scan_args_lead_p(const char *fmt) { return rb_scan_args_isdigit(fmt[0]); } RBIMPL_ATTR_FORCEINLINE() static int rb_scan_args_n_lead(const char *fmt) { return (rb_scan_args_lead_p(fmt) ? fmt[0]-'0' : 0); } RBIMPL_ATTR_FORCEINLINE() static bool rb_scan_args_opt_p(const char *fmt) { return (rb_scan_args_lead_p(fmt) && rb_scan_args_isdigit(fmt[1])); } RBIMPL_ATTR_FORCEINLINE() static int rb_scan_args_n_opt(const char *fmt) { return (rb_scan_args_opt_p(fmt) ? fmt[1]-'0' : 0); } RBIMPL_ATTR_FORCEINLINE() static int rb_scan_args_var_idx(const char *fmt) { return (!rb_scan_args_lead_p(fmt) ? 0 : !rb_scan_args_isdigit(fmt[1]) ? 1 : 2); } RBIMPL_ATTR_FORCEINLINE() static bool rb_scan_args_f_var(const char *fmt) { return (fmt[rb_scan_args_var_idx(fmt)]=='*'); } RBIMPL_ATTR_FORCEINLINE() static int rb_scan_args_trail_idx(const char *fmt) { const int idx = rb_scan_args_var_idx(fmt); return idx+(fmt[idx]=='*'); } RBIMPL_ATTR_FORCEINLINE() static int rb_scan_args_n_trail(const char *fmt) { const int idx = rb_scan_args_trail_idx(fmt); return (rb_scan_args_isdigit(fmt[idx]) ? fmt[idx]-'0' : 0); } RBIMPL_ATTR_FORCEINLINE() static int rb_scan_args_hash_idx(const char *fmt) { const int idx = rb_scan_args_trail_idx(fmt); return idx+rb_scan_args_isdigit(fmt[idx]); } RBIMPL_ATTR_FORCEINLINE() static bool rb_scan_args_f_hash(const char *fmt) { return (fmt[rb_scan_args_hash_idx(fmt)]==':'); } RBIMPL_ATTR_FORCEINLINE() static int rb_scan_args_block_idx(const char *fmt) { const int idx = rb_scan_args_hash_idx(fmt); return idx+(fmt[idx]==':'); } RBIMPL_ATTR_FORCEINLINE() static bool rb_scan_args_f_block(const char *fmt) { return (fmt[rb_scan_args_block_idx(fmt)]=='&'); } # if 0 RBIMPL_ATTR_FORCEINLINE() static int rb_scan_args_end_idx(const char *fmt) { const int idx = rb_scan_args_block_idx(fmt); return idx+(fmt[idx]=='&'); } # endif /* NOTE: Use `char *fmt` instead of `const char *fmt` because of clang's bug*/ /* https://bugs.llvm.org/show_bug.cgi?id=38095 */ # define rb_scan_args0(argc, argv, fmt, varc, vars) \ rb_scan_args_set(RB_SCAN_ARGS_PASS_CALLED_KEYWORDS, argc, argv, \ rb_scan_args_n_lead(fmt), \ rb_scan_args_n_opt(fmt), \ rb_scan_args_n_trail(fmt), \ rb_scan_args_f_var(fmt), \ rb_scan_args_f_hash(fmt), \ rb_scan_args_f_block(fmt), \ (rb_scan_args_verify(fmt, varc), vars), (char *)fmt, varc) # define rb_scan_args_kw0(kw_flag, argc, argv, fmt, varc, vars) \ rb_scan_args_set(kw_flag, argc, argv, \ rb_scan_args_n_lead(fmt), \ rb_scan_args_n_opt(fmt), \ rb_scan_args_n_trail(fmt), \ rb_scan_args_f_var(fmt), \ rb_scan_args_f_hash(fmt), \ rb_scan_args_f_block(fmt), \ (rb_scan_args_verify(fmt, varc), vars), (char *)fmt, varc) RBIMPL_ATTR_FORCEINLINE() static int rb_scan_args_set(int kw_flag, int argc, const VALUE *argv, int n_lead, int n_opt, int n_trail, bool f_var, bool f_hash, bool f_block, VALUE *vars[], RB_UNUSED_VAR(const char *fmt), RB_UNUSED_VAR(int varc)) RBIMPL_ATTR_DIAGNOSE_IF(rb_scan_args_count(fmt) < 0, "bad scan arg format", "error") RBIMPL_ATTR_DIAGNOSE_IF(rb_scan_args_count(fmt) != varc, "variable argument length doesn't match", "error") { int i, argi = 0, vari = 0; VALUE *var, hash = Qnil; #define rb_scan_args_next_param() vars[vari++] const int n_mand = n_lead + n_trail; /* capture an option hash - phase 1: pop from the argv */ if (f_hash && argc > 0) { VALUE last = argv[argc - 1]; if (rb_scan_args_keyword_p(kw_flag, last)) { hash = rb_hash_dup(last); argc--; } } if (argc < n_mand) { goto argc_error; } /* capture leading mandatory arguments */ for (i = 0; i < n_lead; i++) { var = rb_scan_args_next_param(); if (var) *var = argv[argi]; argi++; } /* capture optional arguments */ for (i = 0; i < n_opt; i++) { var = rb_scan_args_next_param(); if (argi < argc - n_trail) { if (var) *var = argv[argi]; argi++; } else { if (var) *var = Qnil; } } /* capture variable length arguments */ if (f_var) { int n_var = argc - argi - n_trail; var = rb_scan_args_next_param(); if (0 < n_var) { if (var) *var = rb_ary_new_from_values(n_var, &argv[argi]); argi += n_var; } else { if (var) *var = rb_ary_new(); } } /* capture trailing mandatory arguments */ for (i = 0; i < n_trail; i++) { var = rb_scan_args_next_param(); if (var) *var = argv[argi]; argi++; } /* capture an option hash - phase 2: assignment */ if (f_hash) { var = rb_scan_args_next_param(); if (var) *var = hash; } /* capture iterator block */ if (f_block) { var = rb_scan_args_next_param(); if (rb_block_given_p()) { *var = rb_block_proc(); } else { *var = Qnil; } } if (argi == argc) { return argc; } argc_error: rb_error_arity(argc, n_mand, f_var ? UNLIMITED_ARGUMENTS : n_mand + n_opt); UNREACHABLE_RETURN(-1); #undef rb_scan_args_next_param } #if ! defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P) # /* skip */ #elif ! defined(HAVE_VA_ARGS_MACRO) # /* skip */ #elif ! defined(__OPTIMIZE__) # /* skip */ #elif defined(HAVE___VA_OPT__) # define rb_scan_args(argc, argvp, fmt, ...) \ __builtin_choose_expr( \ __builtin_constant_p(fmt), \ rb_scan_args0( \ argc, argvp, fmt, \ (sizeof((VALUE*[]){__VA_ARGS__})/sizeof(VALUE*)), \ ((VALUE*[]){__VA_ARGS__})), \ (rb_scan_args)(argc, argvp, fmt __VA_OPT__(, __VA_ARGS__))) # define rb_scan_args_kw(kw_flag, argc, argvp, fmt, ...) \ __builtin_choose_expr( \ __builtin_constant_p(fmt), \ rb_scan_args_kw0( \ kw_flag, argc, argvp, fmt, \ (sizeof((VALUE*[]){__VA_ARGS__})/sizeof(VALUE*)), \ ((VALUE*[]){__VA_ARGS__})), \ (rb_scan_args_kw)(kw_flag, argc, argvp, fmt __VA_OPT__(, __VA_ARGS__))) #elif defined(__STRICT_ANSI__) # /* skip */ #elif defined(__GNUC__) # define rb_scan_args(argc, argvp, fmt, ...) \ __builtin_choose_expr( \ __builtin_constant_p(fmt), \ rb_scan_args0( \ argc, argvp, fmt, \ (sizeof((VALUE*[]){__VA_ARGS__})/sizeof(VALUE*)), \ ((VALUE*[]){__VA_ARGS__})), \ (rb_scan_args)(argc, argvp, fmt, __VA_ARGS__)) # define rb_scan_args_kw(kw_flag, argc, argvp, fmt, ...) \ __builtin_choose_expr( \ __builtin_constant_p(fmt), \ rb_scan_args_kw0( \ kw_flag, argc, argvp, fmt, \ (sizeof((VALUE*[]){__VA_ARGS__})/sizeof(VALUE*)), \ ((VALUE*[]){__VA_ARGS__})), \ (rb_scan_args_kw)(kw_flag, argc, argvp, fmt, __VA_ARGS__ /**/)) #endif #endif /* RBIMPL_SCAN_ARGS_H */ PK!v^internal/stdalign.hnu[#ifndef RBIMPL_STDALIGN_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_STDALIGN_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ALIGNAS / #RBIMPL_ALIGNOF */ #include "ruby/internal/config.h" #ifdef STDC_HEADERS # include #endif #include "ruby/internal/compiler_is.h" #include "ruby/internal/has/attribute.h" #include "ruby/internal/has/declspec_attribute.h" #include "ruby/internal/has/feature.h" /** * Wraps (or simulates) `alignas`. This is C++11's `alignas` and is _different_ * from C11 `_Alignas`. For instance, * * ```CXX * typedef struct alignas(128) foo { int foo } foo; * ``` * * is a valid C++ while * * ```C * typedef struct _Alignas(128) foo { int foo } foo; * ``` * * is an invalid C because: * * - You cannot `struct _Alignas`. * - A `typedef` cannot have alignments. */ #if defined(__cplusplus) && RBIMPL_HAS_FEATURE(cxx_alignas) # define RBIMPL_ALIGNAS alignas #elif defined(__cplusplus) && (__cplusplus >= 201103L) # define RBIMPL_ALIGNAS alignas #elif defined(__INTEL_CXX11_MODE__) # define RBIMPL_ALIGNAS alignas #elif defined(__GXX_EXPERIMENTAL_CXX0X__) # define RBIMPL_ALIGNAS alignas #elif RBIMPL_HAS_DECLSPEC_ATTRIBUTE(align) # define RBIMPL_ALIGNAS(_) __declspec(align(_)) #elif RBIMPL_HAS_ATTRIBUTE(aligned) # define RBIMPL_ALIGNAS(_) __attribute__((__aligned__(_))) #else # define RBIMPL_ALIGNAS(_) /* void */ #endif /** * Wraps (or simulates) `alignof`. * * We want C11's `_Alignof`. However in spite of its clear language, compilers * (including GCC and clang) tend to have buggy implementations. We have to * avoid such things to resort to our own version. * * @see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52023 * @see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69560 * @see https://bugs.llvm.org/show_bug.cgi?id=26547 */ #if defined(__cplusplus) # /* C++11 `alignof()` can be buggy. */ # /* see: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69560 */ # /* But don't worry, we can use templates. */ # define RBIMPL_ALIGNOF(T) (static_cast(ruby::rbimpl_alignof::value)) namespace ruby { template struct rbimpl_alignof { typedef struct { char _; T t; } type; enum { value = offsetof(type, t) }; }; } #elif RBIMPL_COMPILER_IS(MSVC) # /* Windows have no alignment glitch.*/ # define RBIMPL_ALIGNOF __alignof #elif defined(HAVE__ALIGNOF) # /* Autoconf detected availability of a sane `_Alignof()`. */ # define RBIMPL_ALIGNOF(T) RB_GNUC_EXTENSION(_Alignof(T)) #else # /* :BEWARE: This is the last resort. If your compiler somehow supports # * querying the alignment of a type, you definitely should use that instead. # * There are 2 known pitfalls for this fallback implementation: # * # * First, it is either an undefined behaviour (C) or an explicit error (C++) # * to define a struct inside of `offsetof`. C compilers tend to accept such # * things, but AFAIK C++ has no room to allow. # * # * Second, there exist T such that `struct { char _; T t; }` is invalid. A # * known example is when T is a struct with a flexible array member. Such # * struct cannot be enclosed into another one. # */ # /* see: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2083.htm */ # /* see: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2350.htm */ # define RBIMPL_ALIGNOF(T) offsetof(struct { char _; T t; }, t) #endif #endif /* RBIMPL_STDALIGN_H */ PK!AQQinternal/core.hnu[#ifndef RBIMPL_CORE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_CORE_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Core data structures, definitions and manupulations. */ #include "ruby/internal/core/rarray.h" #include "ruby/internal/core/rbasic.h" #include "ruby/internal/core/rbignum.h" #include "ruby/internal/core/rclass.h" #include "ruby/internal/core/rdata.h" #include "ruby/internal/core/rfile.h" #include "ruby/internal/core/rhash.h" #include "ruby/internal/core/robject.h" #include "ruby/internal/core/rregexp.h" #include "ruby/internal/core/rstring.h" #include "ruby/internal/core/rstruct.h" #include "ruby/internal/core/rtypeddata.h" #endif /* RBIMPL_CORE_H */ PK!@ internal/compiler_since.hnu[#ifndef RBIMPL_COMPILER_SINCE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_COMPILER_SINCE_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_COMPILER_SINCE. */ #include "ruby/internal/compiler_is.h" /** * @brief Checks if the compiler is of given brand and is newer than or equal * to the passed version. * @param cc Compiler brand, like `MSVC`. * @param x Major version. * @param y Minor version. * @param z Patchlevel. * @retval true cc >= x.y.z. * @retval false oherwise. */ #define RBIMPL_COMPILER_SINCE(cc, x, y, z) \ (RBIMPL_COMPILER_IS(cc) && \ ((RBIMPL_COMPILER_VERSION_MAJOR > (x)) || \ ((RBIMPL_COMPILER_VERSION_MAJOR == (x)) && \ ((RBIMPL_COMPILER_VERSION_MINOR > (y)) || \ ((RBIMPL_COMPILER_VERSION_MINOR == (y)) && \ (RBIMPL_COMPILER_VERSION_PATCH >= (z))))))) /** * @brief Checks if the compiler is of given brand and is older than the * passed version. * @param cc Compiler brand, like `MSVC`. * @param x Major version. * @param y Minor version. * @param z Patchlevel. * @retval true cc < x.y.z. * @retval false oherwise. */ #define RBIMPL_COMPILER_BEFORE(cc, x, y, z) \ (RBIMPL_COMPILER_IS(cc) && \ ((RBIMPL_COMPILER_VERSION_MAJOR < (x)) || \ ((RBIMPL_COMPILER_VERSION_MAJOR == (x)) && \ ((RBIMPL_COMPILER_VERSION_MINOR < (y)) || \ ((RBIMPL_COMPILER_VERSION_MINOR == (y)) && \ (RBIMPL_COMPILER_VERSION_PATCH < (z))))))) #endif /* RBIMPL_COMPILER_SINCE_H */ PK!~pinternal/ctype.hnu[#ifndef RBIMPL_CTYPE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_CTYPE_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Our own, locale independent, character handling routines. */ #include "ruby/internal/config.h" #ifdef STDC_HEADERS # include #endif #include "ruby/internal/attr/artificial.h" #include "ruby/internal/attr/const.h" #include "ruby/internal/attr/constexpr.h" #include "ruby/internal/dllexport.h" #ifndef ISPRINT # define ISASCII rb_isascii # define ISPRINT rb_isprint # define ISGRAPH rb_isgraph # define ISSPACE rb_isspace # define ISUPPER rb_isupper # define ISLOWER rb_islower # define ISALNUM rb_isalnum # define ISALPHA rb_isalpha # define ISDIGIT rb_isdigit # define ISXDIGIT rb_isxdigit # define ISBLANK rb_isblank # define ISCNTRL rb_iscntrl # define ISPUNCT rb_ispunct #endif #define TOUPPER rb_toupper #define TOLOWER rb_tolower #define STRCASECMP st_locale_insensitive_strcasecmp #define STRNCASECMP st_locale_insensitive_strncasecmp #define STRTOUL ruby_strtoul RBIMPL_SYMBOL_EXPORT_BEGIN() /* locale insensitive functions */ int st_locale_insensitive_strcasecmp(const char *s1, const char *s2); int st_locale_insensitive_strncasecmp(const char *s1, const char *s2, size_t n); unsigned long ruby_strtoul(const char *str, char **endptr, int base); RBIMPL_SYMBOL_EXPORT_END() /* * We are making the functions below to return `int` instead of `bool`. They * have been as such since their birth at 5f237d79033b2109afb768bc889611fa9630. */ RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() static inline int rb_isascii(int c) { return '\0' <= c && c <= '\x7f'; } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() static inline int rb_isupper(int c) { return 'A' <= c && c <= 'Z'; } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() static inline int rb_islower(int c) { return 'a' <= c && c <= 'z'; } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() static inline int rb_isalpha(int c) { return rb_isupper(c) || rb_islower(c); } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() static inline int rb_isdigit(int c) { return '0' <= c && c <= '9'; } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() static inline int rb_isalnum(int c) { return rb_isalpha(c) || rb_isdigit(c); } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() static inline int rb_isxdigit(int c) { return rb_isdigit(c) || ('A' <= c && c <= 'F') || ('a' <= c && c <= 'f'); } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() static inline int rb_isblank(int c) { return c == ' ' || c == '\t'; } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() static inline int rb_isspace(int c) { return c == ' ' || ('\t' <= c && c <= '\r'); } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() static inline int rb_iscntrl(int c) { return ('\0' <= c && c < ' ') || c == '\x7f'; } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() static inline int rb_isprint(int c) { return ' ' <= c && c <= '\x7e'; } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() static inline int rb_ispunct(int c) { return !rb_isalnum(c); } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() static inline int rb_isgraph(int c) { return '!' <= c && c <= '\x7e'; } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() static inline int rb_tolower(int c) { return rb_isupper(c) ? (c|0x20) : c; } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() static inline int rb_toupper(int c) { return rb_islower(c) ? (c&0x5f) : c; } #endif /* RBIMPL_CTYPE_H */ PK!,+ internal/eval.hnu[#ifndef RBIMPL_EVAL_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_EVAL_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Declares ::rb_eval_string(). */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() VALUE rb_eval_string(const char*); VALUE rb_eval_string_protect(const char*, int*); VALUE rb_eval_string_wrap(const char*, int*); VALUE rb_funcall(VALUE, ID, int, ...); VALUE rb_funcallv(VALUE, ID, int, const VALUE*); VALUE rb_funcallv_kw(VALUE, ID, int, const VALUE*, int); VALUE rb_funcallv_public(VALUE, ID, int, const VALUE*); VALUE rb_funcallv_public_kw(VALUE, ID, int, const VALUE*, int); #define rb_funcall2 rb_funcallv #define rb_funcall3 rb_funcallv_public VALUE rb_funcall_passing_block(VALUE, ID, int, const VALUE*); VALUE rb_funcall_passing_block_kw(VALUE, ID, int, const VALUE*, int); VALUE rb_funcall_with_block(VALUE, ID, int, const VALUE*, VALUE); VALUE rb_funcall_with_block_kw(VALUE, ID, int, const VALUE*, VALUE, int); VALUE rb_call_super(int, const VALUE*); VALUE rb_call_super_kw(int, const VALUE*, int); VALUE rb_current_receiver(void); int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *); VALUE rb_extract_keywords(VALUE *orighash); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_EVAL_H */ PK! ^internal/special_consts.hnu[#ifndef RBIMPL_SPECIAL_CONSTS_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_SPECIAL_CONSTS_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines enum ::ruby_special_consts. * @see Sasada, K., "A Lighweight Representation of Floting-Point * Numbers on Ruby Interpreter", in proceedings of 10th JSSST * SIGPPL Workshop on Programming and Programming Languages * (PPL2008), pp. 9-16, 2008. */ #include "ruby/internal/attr/artificial.h" #include "ruby/internal/attr/const.h" #include "ruby/internal/attr/constexpr.h" #include "ruby/internal/attr/enum_extensibility.h" #include "ruby/internal/stdbool.h" #include "ruby/internal/value.h" #if defined(USE_FLONUM) # /* Take that. */ #elif SIZEOF_VALUE >= SIZEOF_DOUBLE # define USE_FLONUM 1 #else # define USE_FLONUM 0 #endif #define RTEST RB_TEST #define FIXNUM_P RB_FIXNUM_P #define IMMEDIATE_P RB_IMMEDIATE_P #define NIL_P RB_NIL_P #define SPECIAL_CONST_P RB_SPECIAL_CONST_P #define STATIC_SYM_P RB_STATIC_SYM_P #define Qfalse RUBY_Qfalse #define Qnil RUBY_Qnil #define Qtrue RUBY_Qtrue #define Qundef RUBY_Qundef /** @cond INTERNAL_MACRO */ #define FIXNUM_FLAG RUBY_FIXNUM_FLAG #define FLONUM_FLAG RUBY_FLONUM_FLAG #define FLONUM_MASK RUBY_FLONUM_MASK #define FLONUM_P RB_FLONUM_P #define IMMEDIATE_MASK RUBY_IMMEDIATE_MASK #define SYMBOL_FLAG RUBY_SYMBOL_FLAG #define RB_FIXNUM_P RB_FIXNUM_P #define RB_FLONUM_P RB_FLONUM_P #define RB_IMMEDIATE_P RB_IMMEDIATE_P #define RB_NIL_P RB_NIL_P #define RB_SPECIAL_CONST_P RB_SPECIAL_CONST_P #define RB_STATIC_SYM_P RB_STATIC_SYM_P #define RB_TEST RB_TEST /** @endcond */ /** special constants - i.e. non-zero and non-fixnum constants */ enum RBIMPL_ATTR_ENUM_EXTENSIBILITY(closed) ruby_special_consts { #if USE_FLONUM RUBY_Qfalse = 0x00, /* ...0000 0000 */ RUBY_Qtrue = 0x14, /* ...0001 0100 */ RUBY_Qnil = 0x08, /* ...0000 1000 */ RUBY_Qundef = 0x34, /* ...0011 0100 */ RUBY_IMMEDIATE_MASK = 0x07, /* ...0000 0111 */ RUBY_FIXNUM_FLAG = 0x01, /* ...xxxx xxx1 */ RUBY_FLONUM_MASK = 0x03, /* ...0000 0011 */ RUBY_FLONUM_FLAG = 0x02, /* ...xxxx xx10 */ RUBY_SYMBOL_FLAG = 0x0c, /* ...xxxx 1100 */ #else RUBY_Qfalse = 0x00, /* ...0000 0000 */ RUBY_Qtrue = 0x02, /* ...0000 0010 */ RUBY_Qnil = 0x04, /* ...0000 0100 */ RUBY_Qundef = 0x06, /* ...0000 0110 */ RUBY_IMMEDIATE_MASK = 0x03, /* ...0000 0011 */ RUBY_FIXNUM_FLAG = 0x01, /* ...xxxx xxx1 */ RUBY_FLONUM_MASK = 0x00, /* any values ANDed with FLONUM_MASK cannot be FLONUM_FLAG */ RUBY_FLONUM_FLAG = 0x02, /* ...0000 0010 */ RUBY_SYMBOL_FLAG = 0x0e, /* ...0000 1110 */ #endif RUBY_SPECIAL_SHIFT = 8 /** Least significant 8 bits are reserved. */ }; RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() /* * :NOTE: rbimpl_test HAS to be `__attribute__((const))` in order for clang to * properly deduce `__builtin_assume()`. */ static inline bool RB_TEST(VALUE obj) { /* * Qfalse: ....0000 0000 * Qnil: ....0000 1000 * ~Qnil: ....1111 0111 * v ....xxxx xxxx * ---------------------------- * RTEST(v) ....xxxx 0xxx * * RTEST(v) can be 0 if and only if (v == Qfalse || v == Qnil). */ return obj & ~RUBY_Qnil; } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() static inline bool RB_NIL_P(VALUE obj) { return obj == RUBY_Qnil; } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() static inline bool RB_FIXNUM_P(VALUE obj) { return obj & RUBY_FIXNUM_FLAG; } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX14) RBIMPL_ATTR_ARTIFICIAL() static inline bool RB_STATIC_SYM_P(VALUE obj) { RBIMPL_ATTR_CONSTEXPR(CXX14) const VALUE mask = ~(RBIMPL_VALUE_FULL << RUBY_SPECIAL_SHIFT); return (obj & mask) == RUBY_SYMBOL_FLAG; } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() static inline bool RB_FLONUM_P(VALUE obj) { #if USE_FLONUM return (obj & RUBY_FLONUM_MASK) == RUBY_FLONUM_FLAG; #else return false; #endif } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() static inline bool RB_IMMEDIATE_P(VALUE obj) { return obj & RUBY_IMMEDIATE_MASK; } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() static inline bool RB_SPECIAL_CONST_P(VALUE obj) { return RB_IMMEDIATE_P(obj) || ! RB_TEST(obj); } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) /* This function is to mimic old rb_special_const_p macro but have anyone * actually used its return value? Wasn't it just something no one needed? */ static inline VALUE rb_special_const_p(VALUE obj) { return RB_SPECIAL_CONST_P(obj) * RUBY_Qtrue; } /** * @cond INTERNAL_MACRO * See [ruby-dev:27513] for the following macros. */ #define RUBY_Qfalse RBIMPL_CAST((VALUE)RUBY_Qfalse) #define RUBY_Qtrue RBIMPL_CAST((VALUE)RUBY_Qtrue) #define RUBY_Qnil RBIMPL_CAST((VALUE)RUBY_Qnil) #define RUBY_Qundef RBIMPL_CAST((VALUE)RUBY_Qundef) /** @endcond */ #endif /* RBIMPL_SPECIAL_CONSTS_H */ PK!\* * internal/event.hnu[#ifndef RBIMPL_EVENT_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_EVENT_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Debugging and tracing APIs. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* traditional set_trace_func events */ #define RUBY_EVENT_NONE 0x0000 #define RUBY_EVENT_LINE 0x0001 #define RUBY_EVENT_CLASS 0x0002 #define RUBY_EVENT_END 0x0004 #define RUBY_EVENT_CALL 0x0008 #define RUBY_EVENT_RETURN 0x0010 #define RUBY_EVENT_C_CALL 0x0020 #define RUBY_EVENT_C_RETURN 0x0040 #define RUBY_EVENT_RAISE 0x0080 #define RUBY_EVENT_ALL 0x00ff /* for TracePoint extended events */ #define RUBY_EVENT_B_CALL 0x0100 #define RUBY_EVENT_B_RETURN 0x0200 #define RUBY_EVENT_THREAD_BEGIN 0x0400 #define RUBY_EVENT_THREAD_END 0x0800 #define RUBY_EVENT_FIBER_SWITCH 0x1000 #define RUBY_EVENT_SCRIPT_COMPILED 0x2000 #define RUBY_EVENT_TRACEPOINT_ALL 0xffff /* special events */ #define RUBY_EVENT_RESERVED_FOR_INTERNAL_USE 0x030000 /* internal events */ #define RUBY_INTERNAL_EVENT_SWITCH 0x040000 #define RUBY_EVENT_SWITCH 0x040000 /* obsolete name. this macro is for compatibility */ /* 0x080000 */ #define RUBY_INTERNAL_EVENT_NEWOBJ 0x100000 #define RUBY_INTERNAL_EVENT_FREEOBJ 0x200000 #define RUBY_INTERNAL_EVENT_GC_START 0x400000 #define RUBY_INTERNAL_EVENT_GC_END_MARK 0x800000 #define RUBY_INTERNAL_EVENT_GC_END_SWEEP 0x1000000 #define RUBY_INTERNAL_EVENT_GC_ENTER 0x2000000 #define RUBY_INTERNAL_EVENT_GC_EXIT 0x4000000 #define RUBY_INTERNAL_EVENT_OBJSPACE_MASK 0x7f00000 #define RUBY_INTERNAL_EVENT_MASK 0xffff0000 typedef uint32_t rb_event_flag_t; typedef void (*rb_event_hook_func_t)(rb_event_flag_t evflag, VALUE data, VALUE self, ID mid, VALUE klass); #define RB_EVENT_HOOKS_HAVE_CALLBACK_DATA 1 void rb_add_event_hook(rb_event_hook_func_t func, rb_event_flag_t events, VALUE data); int rb_remove_event_hook(rb_event_hook_func_t func); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_EVENT_H */ PK!_fŽ internal/static_assert.hnu[#ifndef RBIMPL_STATIC_ASSERT_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_STATIC_ASSERT_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_STATIC_ASSERT. */ #include #include "ruby/internal/has/extension.h" #include "ruby/internal/compiler_since.h" /** @cond INTERNAL_MACRO */ #if defined(__cplusplus) && defined(__cpp_static_assert) # /* https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations */ # define RBIMPL_STATIC_ASSERT0 static_assert #elif defined(__cplusplus) && RBIMPL_COMPILER_SINCE(MSVC, 16, 0, 0) # define RBIMPL_STATIC_ASSERT0 static_assert #elif defined(__INTEL_CXX11_MODE__) # define RBIMPL_STATIC_ASSERT0 static_assert #elif defined(__cplusplus) && __cplusplus >= 201103L # define RBIMPL_STATIC_ASSERT0 static_assert #elif defined(__cplusplus) && RBIMPL_HAS_EXTENSION(cxx_static_assert) # define RBIMPL_STATIC_ASSERT0 __extension__ static_assert #elif defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__ # define RBIMPL_STATIC_ASSERT0 __extension__ static_assert #elif defined(__STDC_VERSION__) && RBIMPL_HAS_EXTENSION(c_static_assert) # define RBIMPL_STATIC_ASSERT0 __extension__ _Static_assert #elif defined(__STDC_VERSION__) && RBIMPL_COMPILER_SINCE(GCC, 4, 6, 0) # define RBIMPL_STATIC_ASSERT0 __extension__ _Static_assert #elif defined(static_assert) # /* Take definition */ # define RBIMPL_STATIC_ASSERT0 static_assert #endif /** @endcond */ /** * @brief Wraps (or simulates) `static_assert` * @param name Valid C/C++ identifier, describing the assertion. * @param expr Expression to assert. * @note `name` shall not be a string literal. */ #if defined(__DOXYGEN__) # define RBIMPL_STATIC_ASSERT static_assert #elif defined(RBIMPL_STATIC_ASSERT0) # define RBIMPL_STATIC_ASSERT(name, expr) \ RBIMPL_STATIC_ASSERT0(expr, # name ": " # expr) #else # define RBIMPL_STATIC_ASSERT(name, expr) \ typedef int static_assert_ ## name ## _check[1 - 2 * !(expr)] #endif #endif /* RBIMPL_STATIC_ASSERT_H */ PK!STinternal/stdbool.hnu[#ifndef RBIMPL_STDBOOL_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_STDBOOL_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief C99 shim for */ #include "ruby/internal/config.h" #if defined(__bool_true_false_are_defined) # /* Take that. */ #elif defined(__cplusplus) # /* bool is a keyword in C++. */ # if defined(HAVE_STDBOOL_H) && (__cplusplus >= 201103L) # include # endif # # ifndef __bool_true_false_are_defined # define __bool_true_false_are_defined # endif #elif defined(HAVE_STDBOOL_H) # /* Take stdbool.h definition. */ # include #else typedef unsigned char _Bool; # /* See also http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2229.htm */ # define bool _Bool # define true ((_Bool)+1) # define false ((_Bool)+0) # define __bool_true_false_are_defined #endif #endif /* RBIMPL_STDBOOL_H */ PK!internal/compiler_is/intel.hnu[#ifndef RBIMPL_COMPILER_IS_INTEL_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_COMPILER_IS_INTEL_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_COMPILER_IS_Intel. */ #if ! defined(__INTEL_COMPILER) # define RBIMPL_COMPILER_IS_Intel 0 #elif ! defined(__INTEL_COMPILER_UPDATE) # define RBIMPL_COMPILER_IS_Intel 1 # /* __INTEL_COMPILER = XXYZ */ # define RBIMPL_COMPILER_VERSION_MAJOR (__INTEL_COMPILER / 100) # define RBIMPL_COMPILER_VERSION_MINOR (__INTEL_COMPILER % 100 / 10) # define RBIMPL_COMPILER_VERSION_PATCH (__INTEL_COMPILER % 10) #else # define RBIMPL_COMPILER_IS_Intel 1 # /* __INTEL_COMPILER = XXYZ */ # define RBIMPL_COMPILER_VERSION_MAJOR (__INTEL_COMPILER / 100) # define RBIMPL_COMPILER_VERSION_MINOR (__INTEL_COMPILER % 100 / 10) # define RBIMPL_COMPILER_VERSION_PATCH __INTEL_COMPILER_UPDATE #endif #endif /* RBIMPL_COMPILER_IS_INTEL_H */ PK!1internal/compiler_is/apple.hnu[#ifndef RBIMPL_COMPILER_IS_APPLE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_COMPILER_IS_APPLE_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_COMPILER_IS_Apple. * * Apple ships clang. Problem is, its `__clang_major__` etc. are not the * upstream LLVM version, but XCode's. We have to think Apple's is distinct * from LLVM's, when it comes to compiler detection business in this header * file. */ #if ! defined(__clang__) # define RBIMPL_COMPILER_IS_Apple 0 #elif ! defined(__apple_build_version__) # define RBIMPL_COMPILER_IS_Apple 0 #else # define RBIMPL_COMPILER_IS_Apple 1 # define RBIMPL_COMPILER_VERSION_MAJOR __clang_major__ # define RBIMPL_COMPILER_VERSION_MINOR __clang_minor__ # define RBIMPL_COMPILER_VERSION_PATCH __clang_patchlevel__ #endif #endif /* RBIMPL_COMPILER_IS_APPLE_H */ PK!w internal/compiler_is/msvc.hnu[#ifndef RBIMPL_COMPILER_IS_MSVC_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_COMPILER_IS_MSVC_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_COMPILER_IS_MSVC. */ #include "ruby/internal/compiler_is/clang.h" #include "ruby/internal/compiler_is/intel.h" #if ! defined(_MSC_VER) # define RBIMPL_COMPILER_IS_MSVC 0 #elif RBIMPL_COMPILER_IS(Clang) # define RBIMPL_COMPILER_IS_MSVC 0 #elif RBIMPL_COMPILER_IS(Intel) # define RBIMPL_COMPILER_IS_MSVC 0 #elif _MSC_VER >= 1400 # define RBIMPL_COMPILER_IS_MSVC 1 # /* _MSC_FULL_VER = XXYYZZZZZ */ # define RBIMPL_COMPILER_VERSION_MAJOR (_MSC_FULL_VER / 10000000) # define RBIMPL_COMPILER_VERSION_MINOR (_MSC_FULL_VER % 10000000 / 100000) # define RBIMPL_COMPILER_VERSION_PATCH (_MSC_FULL_VER % 100000) #elif defined(_MSC_FULL_VER) # define RBIMPL_COMPILER_IS_MSVC 1 # /* _MSC_FULL_VER = XXYYZZZZ */ # define RBIMPL_COMPILER_VERSION_MAJOR (_MSC_FULL_VER / 1000000) # define RBIMPL_COMPILER_VERSION_MINOR (_MSC_FULL_VER % 1000000 / 10000) # define RBIMPL_COMPILER_VERSION_PATCH (_MSC_FULL_VER % 10000) #else # define RBIMPL_COMPILER_IS_MSVC 1 # /* _MSC_VER = XXYY */ # define RBIMPL_COMPILER_VERSION_MAJOR (_MSC_VER / 100) # define RBIMPL_COMPILER_VERSION_MINOR (_MSC_VER % 100) # define RBIMPL_COMPILER_VERSION_PATCH 0 #endif #endif /* RBIMPL_COMPILER_IS_MSVC_H */ PK!Z,  internal/compiler_is/clang.hnu[#ifndef RBIMPL_COMPILER_IS_CLANG_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_COMPILER_IS_CLANG_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_COMPILER_IS_Clang. */ #include "ruby/internal/compiler_is/apple.h" #if ! defined(__clang__) # define RBIMPL_COMPILER_IS_Clang 0 #elif RBIMPL_COMPILER_IS(Apple) # define RBIMPL_COMPILER_IS_Clang 0 #else # define RBIMPL_COMPILER_IS_Clang 1 # define RBIMPL_COMPILER_VERSION_MAJOR __clang_major__ # define RBIMPL_COMPILER_VERSION_MINOR __clang_minor__ # define RBIMPL_COMPILER_VERSION_PATCH __clang_patchlevel__ #endif #endif /* RBIMPL_COMPILER_IS_CLANG_H */ PK!! internal/compiler_is/sunpro.hnu[#ifndef RBIMPL_COMPILER_IS_SUNPRO_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_COMPILER_IS_SUNPRO_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_COMPILER_IS_SunPro. */ #if ! (defined(__SUNPRO_C) || defined(__SUNPRO_CC)) # define RBIMPL_COMPILER_IS_SunPro 0 #elif defined(__SUNPRO_C) && __SUNPRO_C >= 0x5100 # define RBIMPL_COMPILER_IS_SunPro 1 # /* __SUNPRO_C = 0xXYYZ */ # define RBIMPL_COMPILER_VERSION_MAJOR (__SUNPRO_C >> 12) # define RBIMPL_COMPILER_VERSION_MINOR ((__SUNPRO_C >> 8 & 0xF) * 10 + (__SUNPRO_C >> 4 & 0xF)) # define RBIMPL_COMPILER_VERSION_PATCH (__SUNPRO_C & 0xF) #elif defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5100 # define RBIMPL_COMPILER_IS_SunPro 1 # /* __SUNPRO_CC = 0xXYYZ */ # define RBIMPL_COMPILER_VERSION_MAJOR (__SUNPRO_CC >> 12) # define RBIMPL_COMPILER_VERSION_MINOR ((__SUNPRO_CC >> 8 & 0xF) * 10 + (__SUNPRO_CC >> 4 & 0xF)) # define RBIMPL_COMPILER_VERSION_PATCH (__SUNPRO_CC & 0xF) #elif defined(__SUNPRO_C) # define RBIMPL_COMPILER_IS_SunPro 1 # /* __SUNPRO_C = 0xXYZ */ # define RBIMPL_COMPILER_VERSION_MAJOR (__SUNPRO_C >> 8) # define RBIMPL_COMPILER_VERSION_MINOR (__SUNPRO_C >> 4 & 0xF) # define RBIMPL_COMPILER_VERSION_PATCH (__SUNPRO_C & 0xF) #else # define RBIMPL_COMPILER_IS_SunPro 1 # /* __SUNPRO_CC = 0xXYZ */ # define RBIMPL_COMPILER_VERSION_MAJOR (__SUNPRO_CC >> 8) # define RBIMPL_COMPILER_VERSION_MINOR (__SUNPRO_CC >> 4 & 0xF) # define RBIMPL_COMPILER_VERSION_PATCH (__SUNPRO_CC & 0xF) #endif #endif /* RBIMPL_COMPILER_IS_SUNPRO_H */ PK!ͨUinternal/compiler_is/gcc.hnu[#ifndef RBIMPL_COMPILER_IS_GCC_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_COMPILER_IS_GCC_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_COMPILER_IS_GCC. */ #include "ruby/internal/compiler_is/apple.h" #include "ruby/internal/compiler_is/clang.h" #include "ruby/internal/compiler_is/intel.h" #if ! defined(__GNUC__) # define RBIMPL_COMPILER_IS_GCC 0 #elif RBIMPL_COMPILER_IS(Apple) # define RBIMPL_COMPILER_IS_GCC 0 #elif RBIMPL_COMPILER_IS(Clang) # define RBIMPL_COMPILER_IS_GCC 0 #elif RBIMPL_COMPILER_IS(Intel) # define RBIMPL_COMPILER_IS_GCC 0 #else # define RBIMPL_COMPILER_IS_GCC 1 # define RBIMPL_COMPILER_VERSION_MAJOR __GNUC__ # define RBIMPL_COMPILER_VERSION_MINOR __GNUC_MINOR__ # define RBIMPL_COMPILER_VERSION_PATCH __GNUC_PATCHLEVEL__ #endif #endif /* RBIMPL_COMPILER_IS_GCC_H */ PK!Linternal/encoding/re.hnu[#ifndef RUBY_INTERNAL_ENCODING_RE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_INTERNAL_ENCODING_RE_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Routines to manipulate encodings of symbols. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/encoding/encoding.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /** * Identical to rb_reg_new(), except it additionally takes an encoding. * * @param[in] ptr A memory region of `len` bytes length. * @param[in] len Length of `ptr`, in bytes, not including the * terminating NUL character. * @param[in] enc Encoding of `ptr`. * @param[in] opts Options e.g. ONIG_OPTION_MULTILINE. * @exception rb_eRegexpError Failed to compile `ptr`. * @return An allocated new instance of ::rb_cRegexp, of `enc` encoding, * whose expression is compiled according to `ptr`. */ VALUE rb_enc_reg_new(const char *ptr, long len, rb_encoding *enc, int opts); RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_INTERNAL_ENCODING_RE_H */ PK!internal/encoding/pathname.hnu[#ifndef RUBY_INTERNAL_ENCODING_PATHNAME_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_INTERNAL_ENCODING_PATHNAME_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Routines to manipulate encodings of pathnames. */ #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/encoding/encoding.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() RBIMPL_ATTR_NONNULL(()) /** * Returns a path component directly adjacent to the passed pointer. * * ``` * "/multi/byte/encoded/pathname.txt" * ^ ^ ^ * | | +--- end * | +--- @return * +--- path * ``` * * @param[in] path Where to start scanning. * @param[in] end End of the path string. * @param[in] enc Encoding of the string. * @return A pointer in the passed string where the next path component * resides, or `end` if there is no next path component. */ char *rb_enc_path_next(const char *path, const char *end, rb_encoding *enc); RBIMPL_ATTR_NONNULL(()) /** * Seeks for non-prefix part of a pathname. This can be a no-op when the OS * has no such concept like a path prefix. But there are OSes where path * prefixes do exist. * * ``` * "C:\multi\byte\encoded\pathname.txt" * ^ ^ ^ * | | +--- end * | +--- @return * +--- path * ``` * * @param[in] path Where to start scanning. * @param[in] end End of the path string. * @param[in] enc Encoding of the string. * @return A pointer in the passed string where non-prefix part starts, or * `path` if the OS does not have path prefix. */ char *rb_enc_path_skip_prefix(const char *path, const char *end, rb_encoding *enc); RBIMPL_ATTR_NONNULL(()) /** * Returns the last path component. * * ``` * "/multi/byte/encoded/pathname.txt" * ^ ^ ^ * | | +--- end * | +--- @return * +--- path * ``` * * @param[in] path Where to start scanning. * @param[in] end End of the path string. * @param[in] enc Encoding of the string. * @return A pointer in the passed string where the last path component * resides, or `end` if there is no more path component. */ char *rb_enc_path_last_separator(const char *path, const char *end, rb_encoding *enc); RBIMPL_ATTR_NONNULL(()) /** * This just returns the passed end basically. It makes difference in case the * passed string ends with tons of path separators like the following: * * ``` * "/path/that/ends/with/lots/of/slashes//////////////" * ^ ^ ^ * | | +--- end * | +--- @return * +--- path * ``` * * @param[in] path Where to start scanning. * @param[in] end End of the path string. * @param[in] enc Encoding of the string. * @return A pointer in the passed string where the trailing path * separators start, or `end` if there is no trailing path * separators. * * @internal * * It seems this function was introduced to mimic what POSIX says about * `basename(3)`. */ char *rb_enc_path_end(const char *path, const char *end, rb_encoding *enc); RBIMPL_ATTR_NONNULL((1, 4)) /** * Our own encoding-aware version of `basename(3)`. Normally, this function * returns the last path component of the given name. However in case the * passed name ends with a path separator, it returns the name of the * directory, not the last (empty) component. Also if the passed name is a * root directory, it returns that root directory. Note however that Windows * filesystem have drive letters, which this function does not return. * * @param[in] name Target path. * @param[out] baselen Return buffer. * @param[in,out] alllen Number of bytes of `name`. * @param[enc] enc Encoding of `name`. * @return The rightmost component of `name`. * @post `baselen`, if passed, is updated to be the number of bytes * of the returned basename. * @post `alllen`, if passed, is updated to be the number of bytes of * strings not considered as the basename. */ const char *ruby_enc_find_basename(const char *name, long *baselen, long *alllen, rb_encoding *enc); RBIMPL_ATTR_NONNULL((1, 3)) /** * Our own encoding-aware version of `extname`. This function first applies * rb_enc_path_last_separator() to the passed name and only concerns its return * value (ignores any parent directories). This function returns complicated * results: * * ```CXX * auto path = "..."; * auto len = strlen(path); * auto ret = ruby_enc_find_extname(path, &len, rb_ascii8bit_encoding()); * * switch(len) { * case 0: * if (ret == 0) { * // `path` is a file without extensions. * } * else { * // `path` is a dotfile. * // `ret` is the file's name. * } * break; * * case 1: * // `path` _ends_ with a dot. * // `ret` is that dot. * break; * * default: * // `path` has an extension. * // `ret` is that extension. * } * ``` * * @param[in] name Target path. * @param[in,out] len Number of bytes of `name`. * @param[in] enc Encoding of `name`. * @return See above. * @post `len`, if passed, is updated (see above). */ const char *ruby_enc_find_extname(const char *name, long *len, rb_encoding *enc); RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_INTERNAL_ENCODING_PATHNAME_H */ PK!޴//internal/encoding/encoding.hnu[#ifndef RUBY_INTERNAL_ENCODING_ENCODING_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_INTERNAL_ENCODING_ENCODING_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines ::rb_encoding */ #include "ruby/oniguruma.h" #include "ruby/internal/attr/const.h" #include "ruby/internal/attr/deprecated.h" #include "ruby/internal/attr/noalias.h" #include "ruby/internal/attr/pure.h" #include "ruby/internal/attr/returns_nonnull.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" #include "ruby/internal/core/rbasic.h" #include "ruby/internal/fl_type.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /** * `Encoding` class. * * @ingroup object */ RUBY_EXTERN VALUE rb_cEncoding; /** * @private * * Bit constants used when embedding encodings into ::RBasic::flags. Extension * libraries must not bother such things. */ enum ruby_encoding_consts { /** Max possible number of embeddable encodings. */ RUBY_ENCODING_INLINE_MAX = 127, /** Where inline encodings reside. */ RUBY_ENCODING_SHIFT = (RUBY_FL_USHIFT+10), /** Bits we use to store inline encodings. */ RUBY_ENCODING_MASK = (RUBY_ENCODING_INLINE_MAX<> RUBY_ENCODING_SHIFT; return RBIMPL_CAST((int)ret); } #define ENCODING_SET_INLINED(obj,i) RB_ENCODING_SET_INLINED(obj,i) /**< @old{RB_ENCODING_SET_INLINED} */ #define ENCODING_SET(obj,i) RB_ENCODING_SET(obj,i) /**< @old{RB_ENCODING_SET} */ #define ENCODING_GET_INLINED(obj) RB_ENCODING_GET_INLINED(obj) /**< @old{RB_ENCODING_GET_INLINED} */ #define ENCODING_GET(obj) RB_ENCODING_GET(obj) /**< @old{RB_ENCODING_GET} */ #define ENCODING_IS_ASCII8BIT(obj) RB_ENCODING_IS_ASCII8BIT(obj) /**< @old{RB_ENCODING_IS_ASCII8BIT} */ #define ENCODING_MAXNAMELEN RUBY_ENCODING_MAXNAMELEN /**< @old{RUBY_ENCODING_MAXNAMELEN} */ /** * The type of encoding. Our design here is we take Oniguruma/Onigmo's * multilingualisation schema as our base data structure. */ typedef const OnigEncodingType rb_encoding; RBIMPL_ATTR_NOALIAS() /** * Converts a character option to its encoding. It only supports a very * limited set of Japanese encodings due to its Japanese origin. Ruby still * has this in-core for backwards compatibility. But new codes must not bother * such concept like one-character encoding option. Consider deprecated in * practice. * * @param[in] c One of `['n', 'e', 's', 'u', 'i', 'x', 'm']`. * @param[out] option Return buffer. * @param[out] kcode Return buffer. * @retval 1 `c` understood properly. * @retval 0 `c` is not understood. * @post `option` is a ::OnigOptionType. * @post `kcode` is an enum `ruby_preserved_encindex`. * * @internal * * `kcode` is opaque because `ruby_preserved_encindex` is not visible from * extension libraries. But who cares? */ int rb_char_to_option_kcode(int c, int *option, int *kcode); /** * Creates a new encoding, using the passed one as a template. * * @param[in] name Name of the creating encoding. * @param[in] src Template. * @exception rb_eArgError Duplicated or malformed `name`. * @return Replicated new encoding's index. * @post Encoding named `name` is created as a copy of `src`, whose index * is the return value. * * @internal * * `name` can be `NULL`, but that just raises an exception. OTOH it seems no * sanity check is done against `src`...? */ int rb_enc_replicate(const char *name, rb_encoding *src); /** * Creates a new "dummy" encoding. Roughly speaking, an encoding is dummy when * it is stateful. Notable example of dummy encoding are those defined in * ISO/IEC 2022 * * @param[in] name Name of the creating encoding. * @exception rb_eArgError Duplicated or malformed `name`. * @return New dummy encoding's index. * @post Encoding named `name` is created, whose index is the return * value. */ int rb_define_dummy_encoding(const char *name); RBIMPL_ATTR_PURE() /** * Queries if the passed encoding is dummy. * * @param[in] enc Encoding in question. * @retval 1 It is. * @retval 0 It isn't. */ int rb_enc_dummy_p(rb_encoding *enc); RBIMPL_ATTR_PURE() /** * Queries the index of the encoding. An encoding's index is a Ruby-local * concept. It is a (sequential) number assigned to each encoding. * * @param[in] enc Encoding in question. * @return Its index. * @note You can pass null pointers to this function. It is equivalent * to rb_usascii_encindex() then. */ int rb_enc_to_index(rb_encoding *enc); /** * Queries the index of the encoding of the passed object, if any. * * @param[in] obj Object in question. * @retval -1 `obj` is incapable of having an encoding. * @retval otherwise `obj`'s encoding's index. */ int rb_enc_get_index(VALUE obj); /** * @alias{rb_enc_get_index} * * @internal * * Implementation wise this is not a verbatim alias of rb_enc_get_index(). But * the API is consistent. Don't bother. */ static inline int RB_ENCODING_GET(VALUE obj) { int encindex = RB_ENCODING_GET_INLINED(obj); if (encindex == RUBY_ENCODING_INLINE_MAX) { return rb_enc_get_index(obj); } else { return encindex; } } /** * Destructively assigns an encoding (via its index) to an object. * * @param[out] obj Object in question. * @param[in] encindex An encoding index. * @exception rb_eFrozenError `obj` is frozen. * @exception rb_eArgError `obj` is incapable of having an encoding. * @exception rb_eEncodingError `encindex` is out of bounds. * @exception rb_eLoadError Failed to load the encoding. */ void rb_enc_set_index(VALUE obj, int encindex); /** @alias{rb_enc_set_index} */ static inline void RB_ENCODING_SET(VALUE obj, int encindex) { rb_enc_set_index(obj, encindex); } /** * This is #RB_ENCODING_SET + RB_ENC_CODERANGE_SET combo. The object must be * capable of having inline encoding. Using this macro needs deep * understanding of bit level object binary layout. * * @param[out] obj Target object. * @param[in] encindex Encoding in encindex format. * @param[in] cr An enum ::ruby_coderange_type. * @post `obj`'s encoding is `encindex`. * @post `obj`'s code range is `cr`. */ static inline void RB_ENCODING_CODERANGE_SET(VALUE obj, int encindex, enum ruby_coderange_type cr) { RB_ENCODING_SET(obj, encindex); RB_ENC_CODERANGE_SET(obj, cr); } RBIMPL_ATTR_PURE() /** * Queries if the passed object can have its encoding. * * @param[in] obj Object in question. * @retval 1 It can. * @retval 0 It cannot. */ int rb_enc_capable(VALUE obj); /** * Queries the index of the encoding. * * @param[in] name Name of the encoding to find. * @exception rb_eArgError No such encoding named `name`. * @retval -1 `name` exists, but unable to load. * @retval otherwise Index of encoding named `name`. */ int rb_enc_find_index(const char *name); /** * Registers an "alias" name. In the wild, an encoding can be called using * multiple names. For instance an encoding known as `"CP932"` is also called * `"SJIS"` on occasions. This API registers such relationships. * * @param[in] alias New name. * @param[in] orig Old name. * @exception rb_eArgError `alias` is duplicated or malformed. * @retval -1 Failed to load `orig`. * @retval otherwise The index of `orig` and `alias`. * @post `alias` is a synonym of `orig`. They refer to the identical * encoding. */ int rb_enc_alias(const char *alias, const char *orig); /** * Obtains a encoding index from a wider range of objects (than * rb_enc_find_index()). * * @param[in] obj An ::rb_cEncoding, or its name in ::rb_cString. * @retval -1 `obj` is unexpected type/contents. * @retval otherwise Index corresponding to `obj`. */ int rb_to_encoding_index(VALUE obj); /** * Identical to rb_find_encoding(), except it raises an exception instead of * returning NULL. * * @param[in] obj An ::rb_cEncoding, or its name in ::rb_cString. * @exception rb_eTypeError `obj` is neither ::rb_cEncoding nor ::rb_cString. * @exception rb_eArgError `obj` is an unknown encoding name. * @return Encoding of `obj`. */ rb_encoding *rb_to_encoding(VALUE obj); /** * Identical to rb_to_encoding_index(), except the return type. * * @param[in] obj An ::rb_cEncoding, or its name in ::rb_cString. * @exception rb_eTypeError `obj` is neither ::rb_cEncoding nor ::rb_cString. * @retval NULL No such encoding. * @return otherwise Encoding of `obj`. */ rb_encoding *rb_find_encoding(VALUE obj); /** * Identical to rb_enc_get_index(), except the return type. * * @param[in] obj Object in question. * @retval NULL Obj is incapable of having an encoding. * @retval otherwise `obj`'s encoding. */ rb_encoding *rb_enc_get(VALUE obj); /** * Look for the "common" encoding between the two. One character can or cannot * be expressed depending on an encoding. This function finds the super-set of * encodings that satisfy contents of both arguments. If that is impossible * returns NULL. * * @param[in] str1 An object. * @param[in] str2 Another object. * @retval NULL No encoding can satisfy both at once. * @retval otherwise Common encoding between the two. * @note Arguments can be non-string, e.g. Regexp. */ rb_encoding *rb_enc_compatible(VALUE str1, VALUE str2); /** * Identical to rb_enc_compatible(), except it raises an exception instead of * returning NULL. * * @param[in] str1 An object. * @param[in] str2 Another object. * @exception rb_eEncCompatError No encoding can satisfy both. * @return Common encoding between the two. * @note Arguments can be non-string, e.g. Regexp. */ rb_encoding *rb_enc_check(VALUE str1,VALUE str2); /** * Identical to rb_enc_set_index(), except it additionally does contents fix-up * depending on the passed object. It for instance changes the byte length of * terminating `U+0000` according to the passed encoding. * * @param[out] obj Object in question. * @param[in] encindex An encoding index. * @exception rb_eFrozenError `obj` is frozen. * @exception rb_eArgError `obj` is incapable of having an encoding. * @exception rb_eEncodingError `encindex` is out of bounds. * @exception rb_eLoadError Failed to load the encoding. * @return The passed `obj`. * @post `obj`'s contents might be fixed according to `encindex`. */ VALUE rb_enc_associate_index(VALUE obj, int encindex); /** * Identical to rb_enc_associate(), except it takes an encoding itself instead * of its index. * * @param[out] obj Object in question. * @param[in] enc An encoding. * @exception rb_eFrozenError `obj` is frozen. * @exception rb_eArgError `obj` is incapable of having an encoding. * @return The passed `obj`. * @post `obj`'s contents might be fixed according to `enc`. */ VALUE rb_enc_associate(VALUE obj, rb_encoding *enc); /** * Destructively copies the encoding of the latter object to that of former * one. It can also be seen as a routine identical to * rb_enc_associate_index(), except it takes an object's encoding instead of an * encoding's index. * * @param[out] dst Object to modify. * @param[in] src Object to reference. * @exception rb_eFrozenError `dst` is frozen. * @exception rb_eArgError `dst` is incapable of having an encoding. * @exception rb_eEncodingError `src` is incapable of having an encoding. * @post `dst`'s encoding is that of `src`'s. */ void rb_enc_copy(VALUE dst, VALUE src); /** * Identical to rb_find_encoding(), except it takes an encoding index instead * of a Ruby object. * * @param[in] idx An encoding index. * @retval NULL No such encoding. * @retval otherwise An encoding whose index is `idx`. */ rb_encoding *rb_enc_from_index(int idx); /** * Identical to rb_find_encoding(), except it takes a C's string instead of * Ruby's. * * @param[in] name Name of the encoding to query. * @retval NULL No such encoding. * @retval otherwise An encoding whose index is `idx`. */ rb_encoding *rb_enc_find(const char *name); /** * Queries the (canonical) name of the passed encoding. * * @param[in] enc An encoding. * @return Its name. */ static inline const char * rb_enc_name(rb_encoding *enc) { return enc->name; } /** * Queries the minimum number of bytes that the passed encoding needs to * represent a character. For ASCII and compatible encodings this is typically * 1. There are however encodings whose minimum is not 1; they are * historically called wide characters. * * @param[in] enc An encoding. * @return Its least possible number of bytes except 0. */ static inline int rb_enc_mbminlen(rb_encoding *enc) { return enc->min_enc_len; } /** * Queries the maximum number of bytes that the passed encoding needs to * represent a character. Fixed-width encodings have the same value for this * one and #rb_enc_mbminlen. However there are variable-width encodings. * UTF-8, for instance, takes from 1 up to 6 bytes. * * @param[in] enc An encoding. * @return Its maximum possible number of bytes of a character. */ static inline int rb_enc_mbmaxlen(rb_encoding *enc) { return enc->max_enc_len; } /** * Queries the number of bytes of the character at the passed pointer. * * @param[in] p Pointer to a character's first byte. * @param[in] e End of the string that has `p`. * @param[in] enc Encoding of the string. * @return If the character at `p` does not end until `e`, number of bytes * between `p` and `e`. Otherwise the number of bytes that the * character at `p` is encoded. * * @internal * * Strictly speaking there are chances when `p` points to a middle byte of a * wide character. This function returns "the number of bytes from `p` to * nearest of either `e` or the next character boundary", if you go strict. */ int rb_enc_mbclen(const char *p, const char *e, rb_encoding *enc); /** * Identical to rb_enc_mbclen() unless the character at `p` overruns `e`. That * can happen for instance when you read from a socket and its partial read * cuts a wide character in-between. In those situations this function * "estimates" theoretical length of the character in question. Typically it * tends to be possible to know how many bytes a character needs before * actually reaching its end; for instance UTF-8 encodes a character's length * in the first byte of it. This function returns that info. * * @note This implies that the string is not broken. * * @param[in] p Pointer to the character's first byte. * @param[in] e End of the string that has `p`. * @param[in] enc Encoding of the string. * @return Number of bytes of character at `p`, measured or estimated. */ int rb_enc_fast_mbclen(const char *p, const char *e, rb_encoding *enc); /** * Queries the number of bytes of the character at the passed pointer. This * function returns 3 different types of information: * * ```CXX * auto n = rb_enc_precise_mbclen(p, q, r); * * if (ONIGENC_MBCLEN_CHARFOUND_P(n)) { * // Character found. Normal return. * auto found_length = ONIGENC_MBCLEN_CHARFOUND_LEN(n); * } * else if (ONIGENC_MBCLEN_NEEDMORE_P(n)) { * // Character overruns past `q`; needs more. * auto requested_length = ONIGENC_MBCLEN_NEEDMORE_LEN(n); * } * else { * // `p` is broken. * assert(ONIGENC_MBCLEN_INVALID_P(n)); * } * ``` * * @param[in] p Pointer to the character's first byte. * @param[in] e End of the string that has `p`. * @param[in] enc Encoding of the string. * @return Encoded read/needed number of bytes (see above). */ int rb_enc_precise_mbclen(const char *p, const char *e, rb_encoding *enc); #define MBCLEN_CHARFOUND_P(ret) ONIGENC_MBCLEN_CHARFOUND_P(ret) /**< @old{ONIGENC_MBCLEN_CHARFOUND_P} */ #define MBCLEN_CHARFOUND_LEN(ret) ONIGENC_MBCLEN_CHARFOUND_LEN(ret) /**< @old{ONIGENC_MBCLEN_CHARFOUND_LEN} */ #define MBCLEN_INVALID_P(ret) ONIGENC_MBCLEN_INVALID_P(ret) /**< @old{ONIGENC_MBCLEN_INVALID_P} */ #define MBCLEN_NEEDMORE_P(ret) ONIGENC_MBCLEN_NEEDMORE_P(ret) /**< @old{ONIGENC_MBCLEN_NEEDMORE_P} */ #define MBCLEN_NEEDMORE_LEN(ret) ONIGENC_MBCLEN_NEEDMORE_LEN(ret) /**< @old{ONIGENC_MBCLEN_NEEDMORE_LEN} */ /** * Queries the code point of character pointed by the passed pointer. If that * code point is included in ASCII that code point is returned. Otherwise -1. * This can be different from just looking at the first byte. For instance it * reads 2 bytes in case of UTF-16BE. * * @param[in] p Pointer to the character's first byte. * @param[in] e End of the string that has `p`. * @param[in] len Return buffer. * @param[in] enc Encoding of the string. * @retval -1 The character at `p` is not i ASCII. * @retval otherwise A code point of the character at `p`. * @post `len` (if set) is the number of bytes of `p`. */ int rb_enc_ascget(const char *p, const char *e, int *len, rb_encoding *enc); /** * Queries the code point of character pointed by the passed pointer. * Exceptions happen in case of broken input. * * @param[in] p Pointer to the character's first byte. * @param[in] e End of the string that has `p`. * @param[in] len Return buffer. * @param[in] enc Encoding of the string. * @exception rb_eArgError `p` is broken. * @return Code point of the character pointed by `p`. * @post `len` (if set) is the number of bytes of `p`. */ unsigned int rb_enc_codepoint_len(const char *p, const char *e, int *len, rb_encoding *enc); /** * Queries the code point of character pointed by the passed pointer. * Exceptions happen in case of broken input. * * @deprecated Use rb_enc_codepoint_len() instead. * @param[in] p Pointer to the character's first byte. * @param[in] e End of the string that has `p`. * @param[in] enc Encoding of the string. * @exception rb_eArgError `p` is broken. * @return Code point of the character pointed by `p`. * * @internal * * @matz says in commit 91e5ba1cb865a2385d3e1cbfacd824496898e098 that the line * below is a "prototype for obsolete function". However even today there * still are some use cases of it throughout our repository. It seems it has * its own niche. */ static inline unsigned int rb_enc_codepoint(const char *p, const char *e, rb_encoding *enc) { return rb_enc_codepoint_len(p, e, 0, enc); /* ^^^ * This can be `NULL` in C, `nullptr` in C++, and `0` for both. * We choose the most portable one here. */ } /** * Identical to rb_enc_codepoint(), except it assumes the passed character is * not broken. * * @param[in] p Pointer to the character's first byte. * @param[in] e End of the string that has `p`. * @param[in] enc Encoding of the string. * @return Code point of the character pointed by `p`. */ static inline OnigCodePoint rb_enc_mbc_to_codepoint(const char *p, const char *e, rb_encoding *enc) { const OnigUChar *up = RBIMPL_CAST((const OnigUChar *)p); const OnigUChar *ue = RBIMPL_CAST((const OnigUChar *)e); return ONIGENC_MBC_TO_CODE(enc, up, ue); } /** * Queries the number of bytes requested to represent the passed code point * using the passed encoding. * * @param[in] code Code point in question. * @param[in] enc Encoding to convert the code into a byte sequence. * @exception rb_eArgError `enc` does not glean `code`. * @return Number of bytes requested to represent `code` using `enc`. */ int rb_enc_codelen(int code, rb_encoding *enc); /** * Identical to rb_enc_codelen(), except it returns 0 for invalid code points. * * @param[in] c Code point in question. * @param[in] enc Encoding to convert `c` into a byte sequence. * @retval 0 `c` is invalid. * @return otherwise Number of bytes needed for `enc` to encode `c`. */ static inline int rb_enc_code_to_mbclen(int c, rb_encoding *enc) { OnigCodePoint uc = RBIMPL_CAST((OnigCodePoint)c); return ONIGENC_CODE_TO_MBCLEN(enc, uc); } /** * Identical to rb_enc_uint_chr(), except it writes back to the passed buffer * instead of allocating one. * * @param[in] c Code point. * @param[out] buf Return buffer. * @param[in] enc Target encoding scheme. * @post `c` is encoded according to `enc`, then written to `buf`. * * @internal * * The second argument must be typed. But its current usages prevent us from * being any stricter than this. :FIXME: */ static inline int rb_enc_mbcput(unsigned int c, void *buf, rb_encoding *enc) { OnigCodePoint uc = RBIMPL_CAST((OnigCodePoint)c); OnigUChar *ubuf = RBIMPL_CAST((OnigUChar *)buf); return ONIGENC_CODE_TO_MBC(enc, uc, ubuf); } /** * Queries the previous (left) character. * * @param[in] s Start of the string. * @param[in] p Pointer to a character. * @param[in] e End of the string. * @param[in] enc Encoding. * @retval NULL No previous character. * @retval otherwise Pointer to the head of the previous character. */ static inline char * rb_enc_prev_char(const char *s, const char *p, const char *e, rb_encoding *enc) { const OnigUChar *us = RBIMPL_CAST((const OnigUChar *)s); const OnigUChar *up = RBIMPL_CAST((const OnigUChar *)p); const OnigUChar *ue = RBIMPL_CAST((const OnigUChar *)e); OnigUChar *ur = onigenc_get_prev_char_head(enc, us, up, ue); return RBIMPL_CAST((char *)ur); } /** * Queries the left boundary of a character. This function takes a pointer * that is not necessarily a head of a character, and searches for its head. * * @param[in] s Start of the string. * @param[in] p Pointer to a possibly-middle of a character. * @param[in] e End of the string. * @param[in] enc Encoding. * @return Pointer to the head of the character that contains `p`. */ static inline char * rb_enc_left_char_head(const char *s, const char *p, const char *e, rb_encoding *enc) { const OnigUChar *us = RBIMPL_CAST((const OnigUChar *)s); const OnigUChar *up = RBIMPL_CAST((const OnigUChar *)p); const OnigUChar *ue = RBIMPL_CAST((const OnigUChar *)e); OnigUChar *ur = onigenc_get_left_adjust_char_head(enc, us, up, ue); return RBIMPL_CAST((char *)ur); } /** * Queries the right boundary of a character. This function takes a pointer * that is not necessarily a head of a character, and searches for its tail. * * @param[in] s Start of the string. * @param[in] p Pointer to a possibly-middle of a character. * @param[in] e End of the string. * @param[in] enc Encoding. * @return Pointer to the end of the character that contains `p`. */ static inline char * rb_enc_right_char_head(const char *s, const char *p, const char *e, rb_encoding *enc) { const OnigUChar *us = RBIMPL_CAST((const OnigUChar *)s); const OnigUChar *up = RBIMPL_CAST((const OnigUChar *)p); const OnigUChar *ue = RBIMPL_CAST((const OnigUChar *)e); OnigUChar *ur = onigenc_get_right_adjust_char_head(enc, us, up, ue); return RBIMPL_CAST((char *)ur); } /** * Scans the string backwards for n characters. * * @param[in] s Start of the string. * @param[in] p Pointer to a character. * @param[in] e End of the string. * @param[in] n Steps. * @param[in] enc Encoding. * @retval NULL There are no `n` characters left. * @retval otherwise Pointer to `n` character before `p`. */ static inline char * rb_enc_step_back(const char *s, const char *p, const char *e, int n, rb_encoding *enc) { const OnigUChar *us = RBIMPL_CAST((const OnigUChar *)s); const OnigUChar *up = RBIMPL_CAST((const OnigUChar *)p); const OnigUChar *ue = RBIMPL_CAST((const OnigUChar *)e); const OnigUChar *ur = onigenc_step_back(enc, us, up, ue, n); return RBIMPL_CAST((char *)ur); } /** * @private * * This is an implementation detail of rb_enc_asciicompat(). People don't use * it directly. Just always use rb_enc_asciicompat(). * * @param[in] enc Encoding in question. * @retval 1 It is ASCII compatible. * @retval 0 It isn't. */ static inline int rb_enc_asciicompat_inline(rb_encoding *enc) { return rb_enc_mbminlen(enc)==1 && !rb_enc_dummy_p(enc); } /** * Queries if the passed encoding is _in some sense_ compatible with ASCII. * The concept of ASCII compatibility is nuanced, and private to our * implementation. For instance SJIS is ASCII compatible to us, despite their * having different characters at code point `0x5C`. This is based on some * practical consideration that Japanese people confuses SJIS to be "upper * compatible" with ASCII (which is in fact a wrong idea, but we just don't go * strict here). An example of ASCII incompatible encoding is UTF-16. UTF-16 * shares code points with ASCII, but employs a completely different encoding * scheme. * * @param[in] enc Encoding in question. * @retval 0 It is incompatible. * @retval 1 It is compatible. */ static inline bool rb_enc_asciicompat(rb_encoding *enc) { if (rb_enc_mbminlen(enc) != 1) { return false; } else if (rb_enc_dummy_p(enc)) { return false; } else { return true; } } /** * Queries if the passed string is in an ASCII-compatible encoding. * * @param[in] str A Ruby's string to query. * @retval 0 `str` is not a String, or an ASCII-incompatible string. * @retval 1 Otherwise. */ static inline bool rb_enc_str_asciicompat_p(VALUE str) { rb_encoding *enc = rb_enc_get(str); return rb_enc_asciicompat(enc); } /** * Queries the Ruby-level counterpart instance of ::rb_cEncoding that * corresponds to the passed encoding. * * @param[in] enc An encoding * @retval RUBY_Qnil `enc` is a null pointer. * @retval otherwise An instance of ::rb_cEncoding. */ VALUE rb_enc_from_encoding(rb_encoding *enc); RBIMPL_ATTR_PURE() /** * Queries if the passed encoding is either one of UTF-8/16/32. * * @note It does not take UTF-7, which we actually support, into account. * * @param[in] enc Encoding in question. * @retval 0 It is not a Unicode variant. * @retval otherwise It is. * * @internal * * In reality it returns 1/0, but the value is abstracted as * `ONIGENC_FLAG_UNICODE`. */ int rb_enc_unicode_p(rb_encoding *enc); RBIMPL_ATTR_RETURNS_NONNULL() /** * Queries the encoding that represents ASCII-8BIT a.k.a. binary. * * @return The encoding that represents ASCII-8BIT. * * @internal * * This can not return NULL once the process properly boots up. */ rb_encoding *rb_ascii8bit_encoding(void); RBIMPL_ATTR_RETURNS_NONNULL() /** * Queries the encoding that represents UTF-8. * * @return The encoding that represents UTF-8. * * @internal * * This can not return NULL once the process properly boots up. */ rb_encoding *rb_utf8_encoding(void); RBIMPL_ATTR_RETURNS_NONNULL() /** * Queries the encoding that represents US-ASCII. * * @return The encoding that represents US-ASCII. * * @internal * * This can not return NULL once the process properly boots up. */ rb_encoding *rb_usascii_encoding(void); /** * Queries the encoding that represents the current locale. * * @return The encoding that represents the process' locale. * * @internal * * This is dynamic. If you change the process' locale by e.g. calling * `setlocale(3)`, that should also change the return value of this function. * * There is no official way for Ruby scripts to manipulate locales, though. */ rb_encoding *rb_locale_encoding(void); /** * Queries the "filesystem" encoding. This is the encoding that ruby expects * info from the OS' file system are in. This affects for instance return * value of rb_dir_getwd(). Most notably on Windows it can be an alias of OS * codepage. Most notably on Linux users can set this via default external * encoding. * * @return The "filesystem" encoding. */ rb_encoding *rb_filesystem_encoding(void); /** * Queries the "default external" encoding. This is used to interact with * outer-process things such as File. Though not recommended, you can set this * using rb_enc_set_default_external(). * * @return The "default external" encoding. */ rb_encoding *rb_default_external_encoding(void); /** * Queries the "default internal" encoding. This could be a null pointer. * Otherwise, outer-process info are transcoded from default external encoding * to this one during reading from an IO. * * @return The "default internal" encoding (if any). */ rb_encoding *rb_default_internal_encoding(void); #ifndef rb_ascii8bit_encindex RBIMPL_ATTR_CONST() /** * Identical to rb_ascii8bit_encoding(), except it returns the encoding's index * instead of the encoding itself. * * @return The index of encoding of ASCII-8BIT. * * @internal * * This happens to be 0. */ int rb_ascii8bit_encindex(void); #endif /** * Queries if the passed object is in ascii 8bit (== binary) encoding. The * object must be capable of having inline encoding. Using this macro needs * deep understanding of bit level object binary layout. * * @param[in] obj An object to check. * @retval 1 It is. * @retval 0 It isn't. */ static inline bool RB_ENCODING_IS_ASCII8BIT(VALUE obj) { return RB_ENCODING_GET_INLINED(obj) == rb_ascii8bit_encindex(); } #ifndef rb_utf8_encindex RBIMPL_ATTR_CONST() /** * Identical to rb_utf8_encoding(), except it returns the encoding's index * instead of the encoding itself. * * @return The index of encoding of UTF-8. */ int rb_utf8_encindex(void); #endif #ifndef rb_usascii_encindex RBIMPL_ATTR_CONST() /** * Identical to rb_usascii_encoding(), except it returns the encoding's index * instead of the encoding itself. * * @return The index of encoding of UTF-8. */ int rb_usascii_encindex(void); #endif /** * Identical to rb_locale_encoding(), except it returns the encoding's index * instead of the encoding itself. * * @return The index of the locale encoding. */ int rb_locale_encindex(void); /** * Identical to rb_filesystem_encoding(), except it returns the encoding's * index instead of the encoding itself. * * @return The index of the filesystem encoding. */ int rb_filesystem_encindex(void); /** * Identical to rb_default_external_encoding(), except it returns the * Ruby-level counterpart instance of ::rb_cEncoding that corresponds to the * default external encoding. * * @return An instance of ::rb_cEncoding of default external. */ VALUE rb_enc_default_external(void); /** * Identical to rb_default_internal_encoding(), except it returns the * Ruby-level counterpart instance of ::rb_cEncoding that corresponds to the * default internal encoding. * * @return An instance of ::rb_cEncoding of default internal. */ VALUE rb_enc_default_internal(void); /** * Destructively assigns the passed encoding as the default external encoding. * You should not use this API. It has process-global side effects. Also it * doesn't change encodings of strings that have already been read. * * @param[in] encoding Ruby level encoding. * @exception rb_eArgError `encoding` is ::RUBY_Qnil. * @post The default external encoding is `encoding`. */ void rb_enc_set_default_external(VALUE encoding); /** * Destructively assigns the passed encoding as the default internal encoding. * You should not use this API. It has process-global side effects. Also it * doesn't change encodings of strings that have already been read. * * @param[in] encoding Ruby level encoding. * @post The default internal encoding is `encoding`. * @note Unlike rb_enc_set_default_external() you can pass ::RUBY_Qnil. */ void rb_enc_set_default_internal(VALUE encoding); /** * Returns a platform-depended "charmap" of the current locale. This * information is called a "Codeset name" in IEEE 1003.1 section 13 * (``). This is a very low-level API. The return value can have * no corresponding encoding when passed to rb_find_encoding(). * * @param[in] klass Ignored for no reason (why...) * @return The low-level locale charmap, in Ruby's String. */ VALUE rb_locale_charmap(VALUE klass); RBIMPL_SYMBOL_EXPORT_END() /** @cond INTERNAL_MACRO */ #define RB_ENCODING_GET RB_ENCODING_GET #define RB_ENCODING_GET_INLINED RB_ENCODING_GET_INLINED #define RB_ENCODING_IS_ASCII8BIT RB_ENCODING_IS_ASCII8BIT #define RB_ENCODING_SET RB_ENCODING_SET #define RB_ENCODING_SET_INLINED RB_ENCODING_SET_INLINED #define rb_enc_asciicompat rb_enc_asciicompat #define rb_enc_code_to_mbclen rb_enc_code_to_mbclen #define rb_enc_codepoint rb_enc_codepoint #define rb_enc_left_char_head rb_enc_left_char_head #define rb_enc_mbc_to_codepoint rb_enc_mbc_to_codepoint #define rb_enc_mbcput rb_enc_mbcput #define rb_enc_mbmaxlen rb_enc_mbmaxlen #define rb_enc_mbminlen rb_enc_mbminlen #define rb_enc_name rb_enc_name #define rb_enc_prev_char rb_enc_prev_char #define rb_enc_right_char_head rb_enc_right_char_head #define rb_enc_step_back rb_enc_step_back #define rb_enc_str_asciicompat_p rb_enc_str_asciicompat_p /** @endcond */ #endif /* RUBY_INTERNAL_ENCODING_ENCODING_H */ PK!Yinternal/encoding/ctype.hnu[#ifndef RUBY_INTERNAL_ENCODING_CTYPE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_INTERNAL_ENCODING_CTYPE_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Routines to query chacater types. */ #include "ruby/onigmo.h" #include "ruby/internal/attr/const.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/encoding/encoding.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /** * Queries if the passed pointer points to a newline character. What is a * newline and what is not depends on the passed encoding. * * @param[in] p Pointer to a possibly-middle of a character. * @param[in] end End of the string. * @param[in] enc Encoding. * @retval 0 It isn't. * @retval otherwise It is. */ static inline bool rb_enc_is_newline(const char *p, const char *e, rb_encoding *enc) { OnigUChar *up = RBIMPL_CAST((OnigUChar *)p); OnigUChar *ue = RBIMPL_CAST((OnigUChar *)e); return ONIGENC_IS_MBC_NEWLINE(enc, up, ue); } /** * Queries if the passed code point is of passed character type in the passed * encoding. The "character type" here is a set of macros defined in onigmo.h, * like `ONIGENC_CTYPE_PUNCT`. * * @param[in] c An `OnigCodePoint` value. * @param[in] t An `OnigCtype` value. * @param[in] enc A `rb_encoding*` value. * @retval 1 `c` is of `t` in `enc`. * @retval 0 Otherwise. */ static inline bool rb_enc_isctype(OnigCodePoint c, OnigCtype t, rb_encoding *enc) { return ONIGENC_IS_CODE_CTYPE(enc, c, t); } /** * Identical to rb_isascii(), except it additionally takes an encoding. * * @param[in] c A code point. * @param[in] enc An encoding. * @retval 0 `c` is out of range of ASCII character set in `enc`. * @retval 1 Otherwise. * * @internal * * `enc` is ignored. This is at least an intentional implementation detail * (not a bug). But there could be rooms for future extensions. */ static inline bool rb_enc_isascii(OnigCodePoint c, rb_encoding *enc) { return ONIGENC_IS_CODE_ASCII(c); } /** * Identical to rb_isalpha(), except it additionally takes an encoding. * * @param[in] c A code point. * @param[in] enc An encoding. * @retval 1 `enc` classifies `c` as "ALPHA". * @retval 0 Otherwise. */ static inline bool rb_enc_isalpha(OnigCodePoint c, rb_encoding *enc) { return ONIGENC_IS_CODE_ALPHA(enc, c); } /** * Identical to rb_islower(), except it additionally takes an encoding. * * @param[in] c A code point. * @param[in] enc An encoding. * @retval 1 `enc` classifies `c` as "LOWER". * @retval 0 Otherwise. */ static inline bool rb_enc_islower(OnigCodePoint c, rb_encoding *enc) { return ONIGENC_IS_CODE_LOWER(enc, c); } /** * Identical to rb_isupper(), except it additionally takes an encoding. * * @param[in] c A code point. * @param[in] enc An encoding. * @retval 1 `enc` classifies `c` as "UPPER". * @retval 0 Otherwise. */ static inline bool rb_enc_isupper(OnigCodePoint c, rb_encoding *enc) { return ONIGENC_IS_CODE_UPPER(enc, c); } /** * Identical to rb_ispunct(), except it additionally takes an encoding. * * @param[in] c A code point. * @param[in] enc An encoding. * @retval 1 `enc` classifies `c` as "PUNCT". * @retval 0 Otherwise. */ static inline bool rb_enc_ispunct(OnigCodePoint c, rb_encoding *enc) { return ONIGENC_IS_CODE_PUNCT(enc, c); } /** * Identical to rb_isalnum(), except it additionally takes an encoding. * * @param[in] c A code point. * @param[in] enc An encoding. * @retval 1 `enc` classifies `c` as "ANUM". * @retval 0 Otherwise. */ static inline bool rb_enc_isalnum(OnigCodePoint c, rb_encoding *enc) { return ONIGENC_IS_CODE_ALNUM(enc, c); } /** * Identical to rb_isprint(), except it additionally takes an encoding. * * @param[in] c A code point. * @param[in] enc An encoding. * @retval 1 `enc` classifies `c` as "PRINT". * @retval 0 Otherwise. */ static inline bool rb_enc_isprint(OnigCodePoint c, rb_encoding *enc) { return ONIGENC_IS_CODE_PRINT(enc, c); } /** * Identical to rb_isspace(), except it additionally takes an encoding. * * @param[in] c A code point. * @param[in] enc An encoding. * @retval 1 `enc` classifies `c` as "PRINT". * @retval 0 Otherwise. */ static inline bool rb_enc_isspace(OnigCodePoint c, rb_encoding *enc) { return ONIGENC_IS_CODE_SPACE(enc, c); } /** * Identical to rb_isdigit(), except it additionally takes an encoding. * * @param[in] c A code point. * @param[in] enc An encoding. * @retval 1 `enc` classifies `c` as "DIGIT". * @retval 0 Otherwise. */ static inline bool rb_enc_isdigit(OnigCodePoint c, rb_encoding *enc) { return ONIGENC_IS_CODE_DIGIT(enc, c); } RBIMPL_ATTR_CONST() /** * Identical to rb_toupper(), except it additionally takes an encoding. * * @param[in] c A code point. * @param[in] enc An encoding. * @return `c`'s (Ruby's definition of) upper case counterpart. * * @internal * * As `RBIMPL_ATTR_CONST` implies this function ignores `enc`. */ int rb_enc_toupper(int c, rb_encoding *enc); RBIMPL_ATTR_CONST() /** * Identical to rb_tolower(), except it additionally takes an encoding. * * @param[in] c A code point. * @param[in] enc An encoding. * @return `c`'s (Ruby's definition of) lower case counterpart. * * @internal * * As `RBIMPL_ATTR_CONST` implies this function ignores `enc`. */ int rb_enc_tolower(int c, rb_encoding *enc); RBIMPL_SYMBOL_EXPORT_END() /** @cond INTERNAL_MACRO */ #define rb_enc_is_newline rb_enc_is_newline #define rb_enc_isalnum rb_enc_isalnum #define rb_enc_isalpha rb_enc_isalpha #define rb_enc_isascii rb_enc_isascii #define rb_enc_isctype rb_enc_isctype #define rb_enc_isdigit rb_enc_isdigit #define rb_enc_islower rb_enc_islower #define rb_enc_isprint rb_enc_isprint #define rb_enc_ispunct rb_enc_ispunct #define rb_enc_isspace rb_enc_isspace #define rb_enc_isupper rb_enc_isupper /** @endcond */ #endif /* RUBY_INTERNAL_ENCODING_CTYPE_H */ PK!3!<<internal/encoding/string.hnu[#ifndef RUBY_INTERNAL_ENCODING_STRING_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_INTERNAL_ENCODING_STRING_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Routines to manipulate encodings of strings. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" #include "ruby/internal/encoding/encoding.h" #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/intern/string.h" /* rbimpl_strlen */ RBIMPL_SYMBOL_EXPORT_BEGIN() /** * Identical to rb_enc_str_new(), except it additionally takes an encoding. * * @param[in] ptr A memory region of `len` bytes length. * @param[in] len Length of `ptr`, in bytes, not including the * terminating NUL character. * @param[in] enc Encoding of `ptr`. * @exception rb_eNoMemError Failed to allocate `len+1` bytes. * @exception rb_eArgError `len` is negative. * @return An instance of ::rb_cString, of `len` bytes length, of `enc` * encoding, whose contents are verbatim copy of `ptr`. * @pre At least `len` bytes of continuous memory region shall be * accessible via `ptr`. * @note `enc` can be a null pointer. It can also be seen as a routine * identical to rb_usascii_str_new() then. */ VALUE rb_enc_str_new(const char *ptr, long len, rb_encoding *enc); RBIMPL_ATTR_NONNULL((1)) /** * Identical to rb_enc_str_new(), except it assumes the passed pointer is a * pointer to a C string. It can also be seen as a routine identical to * rb_str_new_cstr(), except it additionally takes an encoding. * * @param[in] ptr A C string. * @param[in] enc Encoding of `ptr`. * @exception rb_eNoMemError Failed to allocate memory. * @return An instance of ::rb_cString, of `enc` encoding, whose contents * are verbatim copy of `ptr`. * @pre `ptr` must not be a null pointer. * @pre Because `ptr` is a C string it makes no sense for `enc` to be * something like UTF-32. * @note `enc` can be a null pointer. It can also be seen as a routine * identical to rb_usascii_str_new_cstr() then. */ VALUE rb_enc_str_new_cstr(const char *ptr, rb_encoding *enc); /** * Identical to rb_enc_str_new(), except it takes a C string literal. It can * also be seen as a routine identical to rb_str_new_static(), except it * additionally takes an encoding. * * @param[in] ptr A C string literal. * @param[in] len `strlen(ptr)`. * @param[in] enc Encoding of `ptr`. * @exception rb_eArgError `len` out of range of `size_t`. * @pre `ptr` must be a C string constant. * @return An instance of ::rb_cString, of `enc` encoding, whose backend * storage is the passed C string literal. * @warning It is a very bad idea to write to a C string literal (often * immediate SEGV shall occur). Consider return values of this * function be read-only. * @note `enc` can be a null pointer. It can also be seen as a routine * identical to rb_usascii_str_new_static() then. */ VALUE rb_enc_str_new_static(const char *ptr, long len, rb_encoding *enc); /** * Identical to rb_enc_str_new(), except it returns a "f"string. It can also * be seen as a routine identical to rb_interned_str(), except it additionally * takes an encoding. * * @param[in] ptr A memory region of `len` bytes length. * @param[in] len Length of `ptr`, in bytes, not including the * terminating NUL character. * @param[in] enc Encoding of `ptr`. * @exception rb_eArgError `len` is negative. * @return A found or created instance of ::rb_cString, of `len` bytes * length, of `enc` encoding, whose contents are identical to that * of `ptr`. * @pre At least `len` bytes of continuous memory region shall be * accessible via `ptr`. * @note `enc` can be a null pointer. */ VALUE rb_enc_interned_str(const char *ptr, long len, rb_encoding *enc); RBIMPL_ATTR_NONNULL((1)) /** * Identical to rb_enc_str_new_cstr(), except it returns a "f"string. It can * also be seen as a routine identical to rb_interned_str_cstr(), except it * additionally takes an encoding. * * @param[in] ptr A memory region of `len` bytes length. * @param[in] enc Encoding of `ptr`. * @return A found or created instance of ::rb_cString of `enc` encoding, * whose contents are identical to that of `ptr`. * @pre At least `len` bytes of continuous memory region shall be * accessible via `ptr`. * @note `enc` can be a null pointer. */ VALUE rb_enc_interned_str_cstr(const char *ptr, rb_encoding *enc); /** * Counts the number of characters of the passed string, according to the * passed encoding. This has to be complicated. The passed string could be * invalid and/or broken. This routine would scan from the beginning til the * end, byte by byte, to seek out character boundaries. Could be super slow. * * @param[in] head Leftmost pointer to the string. * @param[in] tail Rightmost pointer to the string. * @param[in] enc Encoding of the string. * @return Number of characters exist in `head` .. `tail`. The definition * of "character" depends on the passed `enc`. */ long rb_enc_strlen(const char *head, const char *tail, rb_encoding *enc); /** * Queries the n-th character. Like rb_enc_strlen() this function can be fast * or slow depending on the contents. Don't expect characters to be uniformly * distributed across the entire string. * * @param[in] head Leftmost pointer to the string. * @param[in] tail Rightmost pointer to the string. * @param[in] nth Requested index of characters. * @param[in] enc Encoding of the string. * @return Pointer to the first byte of the character that is `nth` * character ahead of `head`, or `tail` if there is no such * character (OOB etc). The definition of "character" depends on * the passed `enc`. */ char *rb_enc_nth(const char *head, const char *tail, long nth, rb_encoding *enc); /** * Identical to rb_enc_get_index(), except the return type. * * @param[in] obj Object in question. * @exception rb_eTypeError `obj` is incapable of having an encoding. * @return `obj`'s encoding. */ VALUE rb_obj_encoding(VALUE obj); /** * Identical to rb_str_cat(), except it additionally takes an encoding. * * @param[out] str Destination object. * @param[in] ptr Contents to append. * @param[in] len Length of `src`, in bytes. * @param[in] enc Encoding of `ptr`. * @exception rb_eArgError `len` is negative. * @exception rb_eEncCompatError `enc` is not compatible with `str`. * @return The passed `dst`. * @post The contents of `ptr` is copied, transcoded into `dst`'s * encoding, then pasted into `dst`'s end. */ VALUE rb_enc_str_buf_cat(VALUE str, const char *ptr, long len, rb_encoding *enc); /** * Encodes the passed code point into a series of bytes. * * @param[in] code Code point. * @param[in] enc Target encoding scheme. * @exception rb_eRangeError `enc` does not glean `code`. * @return An instance of ::rb_cString, of `enc` encoding, whose sole * contents is `code` represented in `enc`. * @note No way to encode code points bigger than UINT_MAX. * * @internal * * In other languages, APIs like this one could be seen as the primitive * routines where encodings' "encode" feature are implemented. However in case * of Ruby this is not the primitive one. We directly manipulate encoded * strings. Encoding conversion routines transcode an encoded string directly * to another one; not via a code point array. */ VALUE rb_enc_uint_chr(unsigned int code, rb_encoding *enc); /** * Identical to rb_external_str_new(), except it additionally takes an * encoding. However the whole point of rb_external_str_new() is to encode a * string into default external encoding. Being able to specify arbitrary * encoding just ruins the designed purpose the function meseems. * * @param[in] ptr A memory region of `len` bytes length. * @param[in] len Length of `ptr`, in bytes, not including the * terminating NUL character. * @param[in] enc Target encoding scheme. * @exception rb_eArgError `len` is negative. * @return An instance of ::rb_cString. In case encoding conversion from * "default internal" to `enc` is fully defined over the given * contents, then the return value is a string of `enc` encoding, * whose contents are the converted ones. Otherwise the string is * a junk. * @warning It doesn't raise on a conversion failure and silently ends up in * a corrupted output. You can know the failure by querying * `valid_encoding?` of the result object. * * @internal * * @shyouhei has no idea why this one does not follow the naming convention * that others obey. It seems to him that this should have been called * `rb_enc_external_str_new`. */ VALUE rb_external_str_new_with_enc(const char *ptr, long len, rb_encoding *enc); /** * Identical to rb_str_export(), except it additionally takes an encoding. * * @param[in] obj Target object. * @param[in] enc Target encoding. * @exception rb_eTypeError No implicit conversion to String. * @return Converted ruby string of `enc` encoding. */ VALUE rb_str_export_to_enc(VALUE obj, rb_encoding *enc); /** * Encoding conversion main routine. * * @param[in] str String to convert. * @param[in] from Source encoding. * @param[in] to Destination encoding. * @return A copy of `str`, with conversion from `from` to `to` applied. * @note `from` can be a null pointer. `str`'s encoding is taken then. * @note `to` can be a null pointer. No-op then. */ VALUE rb_str_conv_enc(VALUE str, rb_encoding *from, rb_encoding *to); /** * Identical to rb_str_conv_enc(), except it additionally takes IO encoder * options. The extra arguments can be constructed using io_extract_modeenc() * etc. * * @param[in] str String to convert. * @param[in] from Source encoding. * @param[in] to Destination encoding. * @param[in] ecflags A set of enum ::ruby_econv_flag_type. * @param[in] ecopts Optional hash. * @return A copy of `str`, with conversion from `from` to `to` applied. * @note `from` can be a null pointer. `str`'s encoding is taken then. * @note `to` can be a null pointer. No-op then. * @note `ecopts` can be ::RUBY_Qnil, which is equivalent to passing an * empty hash. */ VALUE rb_str_conv_enc_opts(VALUE str, rb_encoding *from, rb_encoding *to, int ecflags, VALUE ecopts); /** * Scans the passed string to collect its code range. Because a Ruby's string * is mutable, its contents change from time to time; so does its code range. * A long-lived string tends to fall back to ::RUBY_ENC_CODERANGE_UNKNOWN. * This API scans it and re-assigns a fine-grained code range constant. * * @param[out] str A string. * @return An enum ::ruby_coderange_type. */ int rb_enc_str_coderange(VALUE str); /** * Scans the passed string until it finds something odd. Returns the number of * bytes scanned. As the name implies this is suitable for repeated call. One * of its application is `IO#readlines`. The method reads from its receiver's * read buffer, maybe more than once, looking for newlines. But "newline" can * be different among encodings. This API is used to detect broken contents to * properly mark them as such. * * @param[in] str String to scan. * @param[in] end End of `str`. * @param[in] enc `str`'s encoding. * @param[out] cr Return buffer. * @return Distance between `str` and first such byte where broken. * @post `cr` has the code range type. */ long rb_str_coderange_scan_restartable(const char *str, const char *end, rb_encoding *enc, int *cr); /** * Queries if the passed string is "ASCII only". An ASCII only string is a * string who doesn't have any non-ASCII characters at all. This doesn't * necessarily mean the string is in ASCII encoding. For instance a String of * CP932 encoding can quite much be ASCII only, depending on its contents. * * @param[in] str String in question. * @retval 1 It doesn't have non-ASCII characters. * @retval 0 It has characters that are out of ASCII. */ int rb_enc_str_asciionly_p(VALUE str); RBIMPL_ATTR_NONNULL(()) /** * Looks for the passed string in the passed buffer. * * @param[in] x Buffer that potentially includes `y`. * @param[in] m Number of bytes of `x`. * @param[in] y Query string. * @param[in] n Number of bytes of `y`. * @param[in] enc Encoding of both `x` and `y`. * @retval -1 Not found. * @retval otherwise Found index in `x`. * @note This API can match at a non-character-boundary. */ long rb_memsearch(const void *x, long m, const void *y, long n, rb_encoding *enc); /** @cond INTERNAL_MACRO */ RBIMPL_ATTR_NONNULL(()) static inline VALUE rbimpl_enc_str_new_cstr(const char *str, rb_encoding *enc) { long len = rbimpl_strlen(str); return rb_enc_str_new_static(str, len, enc); } #define rb_enc_str_new(str, len, enc) \ ((RBIMPL_CONSTANT_P(str) && \ RBIMPL_CONSTANT_P(len) ? \ rb_enc_str_new_static: \ rb_enc_str_new) ((str), (len), (enc))) #define rb_enc_str_new_cstr(str, enc) \ ((RBIMPL_CONSTANT_P(str) ? \ rbimpl_enc_str_new_cstr : \ rb_enc_str_new_cstr) ((str), (enc))) /** @endcond */ RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_INTERNAL_ENCODING_STRING_H */ PK!YRinternal/encoding/symbol.hnu[#ifndef RUBY_INTERNAL_ENCODING_SYMBOL_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_INTERNAL_ENCODING_SYMBOL_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Routines to manipulate encodings of symbols. */ #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/encoding/encoding.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /** * Identical to rb_intern2(), except it additionally takes an encoding. * * @param[in] name The name of the id. * @param[in] len Length of `name`. * @param[in] enc `name`'s encoding. * @exception rb_eRuntimeError Too many symbols. * @return A (possibly new) id whose value is the given name. * @note These days Ruby internally has two kinds of symbols * (static/dynamic). Symbols created using this function would * become static ones; i.e. would never be garbage collected. It * is up to you to avoid memory leaks. Think twice before using * it. */ ID rb_intern3(const char *name, long len, rb_encoding *enc); RBIMPL_ATTR_NONNULL(()) /** * Identical to rb_symname_p(), except it additionally takes an encoding. * * @param[in] str A C string to check. * @param[in] enc `str`'s encoding. * @retval 1 It is a valid symbol name. * @retval 0 It is invalid as a symbol name. */ int rb_enc_symname_p(const char *str, rb_encoding *enc); /** * Identical to rb_enc_symname_p(), except it additionally takes the passed * string's length. This is needed for strings containing NUL bytes, like in * case of UTF-32. * * @param[in] name A C string to check. * @param[in] len Number of bytes of `str`. * @param[in] enc `str`'s encoding. * @retval 1 It is a valid symbol name. * @retval 0 It is invalid as a symbol name. */ int rb_enc_symname2_p(const char *name, long len, rb_encoding *enc); /** * Identical to rb_check_id(), except it takes a pointer to a memory region * instead of Ruby's string. * * @param[in] ptr A pointer to a memory region. * @param[in] len Number of bytes of `ptr`. * @param[in] enc Encoding of `ptr`. * @exception rb_eEncodingError `ptr` contains non-ASCII according to `enc`. * @retval 0 No such id ever existed in the history. * @retval otherwise The id that represents the given name. */ ID rb_check_id_cstr(const char *ptr, long len, rb_encoding *enc); /** * Identical to rb_check_id_cstr(), except for the return type. It can also be * seen as a routine identical to rb_check_symbol(), except it takes a pointer * to a memory region instead of Ruby's string. * * @param[in] ptr A pointer to a memory region. * @param[in] len Number of bytes of `ptr`. * @param[in] enc Encoding of `ptr`. * @exception rb_eEncodingError `ptr` contains non-ASCII according to `enc`. * @retval RUBY_Qnil No such id ever existed in the history. * @retval otherwise The id that represents the given name. */ VALUE rb_check_symbol_cstr(const char *ptr, long len, rb_encoding *enc); RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_INTERNAL_ENCODING_SYMBOL_H */ PK!ccinternal/encoding/transcode.hnu[#ifndef RUBY_INTERNAL_ENCODING_TRANSCODE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_INTERNAL_ENCODING_TRANSCODE_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief econv stuff */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /** return value of rb_econv_convert() */ typedef enum { /** * The conversion stopped when it found an invalid sequence. */ econv_invalid_byte_sequence, /** * The conversion stopped when it found a character in the input which * cannot be representable in the output. */ econv_undefined_conversion, /** * The conversion stopped because there is no destination. */ econv_destination_buffer_full, /** * The conversion stopped because there is no input. */ econv_source_buffer_empty, /** * The conversion stopped after converting everything. This is arguably * the expected normal end of conversion. */ econv_finished, /** * The conversion stopped after writing something to somewhere, before * reading everything. */ econv_after_output, /** * The conversion stopped in middle of reading a character, possibly due to * a partial read of a socket etc. */ econv_incomplete_input } rb_econv_result_t; /** An opaque struct that represents a lowest level of encoding conversion. */ typedef struct rb_econv_t rb_econv_t; /** * Converts the contents of the passed string from its encoding to the passed * one. * * @param[in] str Target string. * @param[in] to Destination encoding. * @param[in] ecflags A set of enum * ::ruby_econv_flag_type. * @param[in] ecopts A keyword hash, like * ::rb_io_t::rb_io_enc_t::ecopts. * @exception rb_eArgError Not fully converted. * @exception rb_eInvalidByteSequenceError `str` is malformed. * @exception rb_eUndefinedConversionError `str` has a character not * representable using `to`. * @exception rb_eConversionNotFoundError There is no known conversion from * `str`'s encoding to `to`. * @return A string whose encoding is `to`, and whose contents is converted * contents of `str`. * @note Use rb_econv_prepare_options() to generate `ecopts`. */ VALUE rb_str_encode(VALUE str, VALUE to, int ecflags, VALUE ecopts); /** * Queries if there is more than one way to convert between the passed two * encodings. Encoding conversion are has_and_belongs_to_many relationships. * There could be no direct conversion defined for the passed pair. Ruby tries * to find an indirect way to do so then. For instance ISO-8859-1 has no * direct conversion to ISO-2022-JP. But there is ISO-8859-1 to UTF-8 * conversion; then there is UTF-8 to EUC-JP conversion; finally there also is * EUC-JP to ISO-2022-JP conversion. So in short ISO-8859-1 can be converted * to ISO-2022-JP using that path. This function returns true. Obviously not * everything that can be represented using UTF-8 can also be represented using * EUC-JP. Conversions in practice can fail depending on the actual input, and * that renders exceptions in case of rb_str_encode(). * * @param[in] from_encoding One encoding. * @param[in] to_encoding Another encoding. * @retval 0 No way to convert the two. * @retval 1 At least one way to convert the two. * * @internal * * Practically @shyouhei knows no way for this function to return 0. It seems * everything can eventually be converted to/from UTF-8, which connects * everything. */ int rb_econv_has_convpath_p(const char* from_encoding, const char* to_encoding); /** * Identical to rb_econv_prepare_opts(), except it additionally takes the * initial value of flags. The extra bits are bitwise-ORed to the return * value. * * @param[in] opthash Keyword arguments. * @param[out] ecopts Return buffer. * @param[in] ecflags Default set of enum ::ruby_econv_flag_type. * @exception rb_eArgError Unknown/Broken values passed. * @return Calculated set of enum ::ruby_econv_flag_type. * @post `ecopts` holds a hash object suitable for * ::rb_io_t::rb_io_enc_t::ecopts. */ int rb_econv_prepare_options(VALUE opthash, VALUE *ecopts, int ecflags); /** * Splits a keyword arguments hash (that for instance `String#encode` took) * into a set of enum ::ruby_econv_flag_type and a hash storing replacement * characters etc. * * @param[in] opthash Keyword arguments. * @param[out] ecopts Return buffer. * @exception rb_eArgError Unknown/Broken values passed. * @return Calculated set of enum ::ruby_econv_flag_type. * @post `ecopts` holds a hash object suitable for * ::rb_io_t::rb_io_enc_t::ecopts. */ int rb_econv_prepare_opts(VALUE opthash, VALUE *ecopts); /** * Creates a new instance of struct ::rb_econv_t. * * @param[in] source_encoding Name of an encoding. * @param[in] destination_encoding Name of another encoding. * @param[in] ecflags A set of enum ::ruby_econv_flag_type. * @exception rb_eArgError No such encoding. * @retval NULL Failed to create a struct ::rb_econv_t. * @retval otherwise Allocated struct ::rb_econv_t. * @warning Return value must be passed to rb_econv_close() exactly once. */ rb_econv_t *rb_econv_open(const char *source_encoding, const char *destination_encoding, int ecflags); /** * Identical to rb_econv_open(), except it additionally takes a hash of * optional strings. * * * @param[in] source_encoding Name of an encoding. * @param[in] destination_encoding Name of another encoding. * @param[in] ecflags A set of enum ::ruby_econv_flag_type. * @param[in] ecopts Optional set of strings. * @exception rb_eArgError No such encoding. * @retval NULL Failed to create a struct ::rb_econv_t. * @retval otherwise Allocated struct ::rb_econv_t. * @warning Return value must be passed to rb_econv_close() exactly once. */ rb_econv_t *rb_econv_open_opts(const char *source_encoding, const char *destination_encoding, int ecflags, VALUE ecopts); /** * Converts a string from an encoding to another. * * Possible flags are either ::RUBY_ECONV_PARTIAL_INPUT (means the source * buffer is a part of much larger one), ::RUBY_ECONV_AFTER_OUTPUT (instructs * the converter to stop after output before input), or both of them. * * @param[in,out] ec Conversion specification/state etc. * @param[in] source_buffer_ptr Target string. * @param[in] source_buffer_end End of target string. * @param[out] destination_buffer_ptr Return buffer. * @param[out] destination_buffer_end End of return buffer. * @param[in] flags Flags (see above). * @return The status of the conversion. * @post `destination_buffer_ptr` holds conversion results. */ rb_econv_result_t rb_econv_convert(rb_econv_t *ec, const unsigned char **source_buffer_ptr, const unsigned char *source_buffer_end, unsigned char **destination_buffer_ptr, unsigned char *destination_buffer_end, int flags); /** * Destructs a converter. Note that a converter can have a buffer, and can be * non-empty. Calling this would lose your data then. * * @param[out] ec The converter to destroy. * @post `ec` is no longer a valid pointer. */ void rb_econv_close(rb_econv_t *ec); /** * Assigns the replacement string. The string passed here would appear in * converted string when it cannot represent its source counterpart. This can * happen for instance you convert an emoji to ISO-8859-1. * * @param[out] ec Target converter. * @param[in] str Replacement string. * @param[in] len Number of bytes of `str`. * @param[in] encname Name of encoding of `str`. * @retval 0 Success. * @retval -1 Failure (ENOMEM etc.). * @post `ec`'s replacement string is set to `str`. */ int rb_econv_set_replacement(rb_econv_t *ec, const unsigned char *str, size_t len, const char *encname); /** * "Decorate"s a converter. There are special kind of converters that * transforms the contents, like replacing CR into CRLF. You can add such * decorators to a converter using this API. By using this function a * decorator is prepended at the beginning of a conversion sequence: in case of * CRLF conversion, newlines are converted before encodings are converted. * * @param[out] ec Target converter to decorate. * @param[in] decorator_name Name of decorator to prepend. * @retval 0 Success. * @retval -1 Failure (no such decorator etc.). * @post Decorator works before encoding conversion happens. * * @internal * * What is the possible value of the `decorator_name` is not public. You have * to read through `transcode.c` carefully. */ int rb_econv_decorate_at_first(rb_econv_t *ec, const char *decorator_name); /** * Identical to rb_econv_decorate_at_first(), except it adds to the opposite * direction. For instance CRLF conversion would run _after_ encodings are * converted. * * @param[out] ec Target converter to decorate. * @param[in] decorator_name Name of decorator to prepend. * @retval 0 Success. * @retval -1 Failure (no such decorator etc.). * @post Decorator works after encoding conversion happens. */ int rb_econv_decorate_at_last(rb_econv_t *ec, const char *decorator_name); /** * Creates a `rb_eConverterNotFoundError` exception object (but does not * raise). * * @param[in] senc Name of source encoding. * @param[in] denc Name of destination encoding. * @param[in] ecflags A set of enum ::ruby_econv_flag_type. * @return An instance of `rb_eConverterNotFoundError`. */ VALUE rb_econv_open_exc(const char *senc, const char *denc, int ecflags); /** * Appends the passed string to the passed converter's output buffer. This can * be handy when an encoding needs bytes out of thin air; for instance * ISO-2022-JP has "shift function" which does not correspond to any * characters. * * @param[out] ec Target converter. * @param[in] str String to insert. * @param[in] len Number of bytes of `str`. * @param[in] str_encoding Encoding of `str`. * @retval 0 Success. * @retval -1 Failure (conversion error etc.). * @note `str_encoding` can be anything, and `str` itself is converted * when necessary. */ int rb_econv_insert_output(rb_econv_t *ec, const unsigned char *str, size_t len, const char *str_encoding); /** * Queries an encoding name which best suits for rb_econv_insert_output()'s * last parameter. Strings in this encoding need no conversion when inserted; * can be both time/space efficient. * * @param[in] ec Target converter. * @return Its encoding for insertion. */ const char *rb_econv_encoding_to_insert_output(rb_econv_t *ec); /** * This is a rb_econv_make_exception() + rb_exc_raise() combo. * * @param[in] ec (Possibly failed) conversion. * @exception rb_eInvalidByteSequenceError Invalid byte sequence. * @exception rb_eUndefinedConversionError Conversion undefined. * @note This function can return when no error. */ void rb_econv_check_error(rb_econv_t *ec); /** * This function makes sense right after rb_econv_convert() returns. As listed * in ::rb_econv_result_t, rb_econv_convert() can bail out for various reasons. * This function checks the passed converter's internal state and convert it to * an appropriate exception object. * * @param[in] ec Target converter. * @retval RUBY_Qnil The converter has no error. * @retval otherwise Conversion error turned into an exception. */ VALUE rb_econv_make_exception(rb_econv_t *ec); /** * Queries if rb_econv_putback() makes sense, i.e. there are invalid byte * sequences remain in the buffer. * * @param[in] ec Target converter. * @return Number of bytes that can be pushed back. */ int rb_econv_putbackable(rb_econv_t *ec); /** * Puts back the bytes. In case of ::econv_invalid_byte_sequence, some of * those invalid bytes are discarded and the others are buffered to be * converted later. The latter bytes can be put back using this API. * * @param[out] ec Target converter (invalid byte sequence). * @param[out] p Return buffer. * @param[in] n Max number of bytes to put back. * @post At most `n` bytes of what was put back is written to `p`. */ void rb_econv_putback(rb_econv_t *ec, unsigned char *p, int n); /** * Queries the passed encoding's corresponding ASCII compatible encoding. "The * corresponding ASCII compatible encoding" in this context is an ASCII * compatible encoding which can represent exactly the same character sets as * the given ASCII incompatible encoding. For instance that of UTF-16LE is * UTF-8. * * @param[in] encname Name of an ASCII incompatible encoding. * @retval NULL `encname` is already ASCII compatible. * @retval otherwise The corresponding ASCII compatible encoding. */ const char *rb_econv_asciicompat_encoding(const char *encname); /** * Identical to rb_econv_convert(), except it takes Ruby's string instead of * C's pointer. * * @param[in,out] ec Target converter. * @param[in] src Source string. * @param[in] flags Flags (see rb_econv_convert). * @exception rb_eArgError Converted string is too long. * @exception rb_eInvalidByteSequenceError Invalid byte sequence. * @exception rb_eUndefinedConversionError Conversion undefined. * @return The conversion result. */ VALUE rb_econv_str_convert(rb_econv_t *ec, VALUE src, int flags); /** * Identical to rb_econv_str_convert(), except it converts only a part of the * passed string. Can be handy when you for instance want to do line-buffered * conversion. * * @param[in,out] ec Target converter. * @param[in] src Source string. * @param[in] byteoff Number of bytes to seek. * @param[in] bytesize Number of bytes to read. * @param[in] flags Flags (see rb_econv_convert). * @exception rb_eArgError Converted string is too long. * @exception rb_eInvalidByteSequenceError Invalid byte sequence. * @exception rb_eUndefinedConversionError Conversion undefined. * @return The conversion result. */ VALUE rb_econv_substr_convert(rb_econv_t *ec, VALUE src, long byteoff, long bytesize, int flags); /** * Identical to rb_econv_str_convert(), except it appends the conversion result * to the additionally passed string instead of creating a new string. It can * also be seen as a routine identical to rb_econv_append(), except it takes a * Ruby's string instead of C's pointer. * * @param[in,out] ec Target converter. * @param[in] src Source string. * @param[in] dst Return buffer. * @param[in] flags Flags (see rb_econv_convert). * @exception rb_eArgError Converted string is too long. * @exception rb_eInvalidByteSequenceError Invalid byte sequence. * @exception rb_eUndefinedConversionError Conversion undefined. * @return The conversion result. */ VALUE rb_econv_str_append(rb_econv_t *ec, VALUE src, VALUE dst, int flags); /** * Identical to rb_econv_str_append(), except it appends only a part of the * passed string with conversion. It can also be seen as a routine identical * to rb_econv_substr_convert(), except it appends the conversion result to the * additionally passed string instead of creating a new string. * * @param[in,out] ec Target converter. * @param[in] src Source string. * @param[in] byteoff Number of bytes to seek. * @param[in] bytesize Number of bytes to read. * @param[in] dst Return buffer. * @param[in] flags Flags (see rb_econv_convert). * @exception rb_eArgError Converted string is too long. * @exception rb_eInvalidByteSequenceError Invalid byte sequence. * @exception rb_eUndefinedConversionError Conversion undefined. * @return The conversion result. */ VALUE rb_econv_substr_append(rb_econv_t *ec, VALUE src, long byteoff, long bytesize, VALUE dst, int flags); /** * Converts the passed C's pointer according to the passed converter, then * append the conversion result to the passed Ruby's string. This way buffer * overflow is properly avoided to resize the destination properly. * * @param[in,out] ec Target converter. * @param[in] bytesrc Target string. * @param[in] bytesize Number of bytes of `bytesrc`. * @param[in] dst Return buffer. * @param[in] flags Flags (see rb_econv_convert). * @exception rb_eArgError Converted string is too long. * @exception rb_eInvalidByteSequenceError Invalid byte sequence. * @exception rb_eUndefinedConversionError Conversion undefined. * @return The conversion result. */ VALUE rb_econv_append(rb_econv_t *ec, const char *bytesrc, long bytesize, VALUE dst, int flags); /** * This badly named function does not set the destination encoding to binary, * but instead just nullifies newline conversion decorators if any. Other * ordinal character conversions still happen after this; something non-binary * would still be generated. * * @param[out] ec Target converter to modify. * @post Any newline conversions, if any, would be killed. */ void rb_econv_binmode(rb_econv_t *ec); /** * This enum is kind of omnibus. Gathers various constants. */ enum ruby_econv_flag_type { /** * @name Flags for rb_econv_open() * * @{ */ /** Mask for error handling related bits. */ RUBY_ECONV_ERROR_HANDLER_MASK = 0x000000ff, /** Special handling of invalid sequences are there. */ RUBY_ECONV_INVALID_MASK = 0x0000000f, /** Invalid sequences shall be replaced. */ RUBY_ECONV_INVALID_REPLACE = 0x00000002, /** Special handling of undefined conversion are there. */ RUBY_ECONV_UNDEF_MASK = 0x000000f0, /** Undefined characters shall be replaced. */ RUBY_ECONV_UNDEF_REPLACE = 0x00000020, /** Undefined characters shall be escaped. */ RUBY_ECONV_UNDEF_HEX_CHARREF = 0x00000030, /** Decorators are there. */ RUBY_ECONV_DECORATOR_MASK = 0x0000ff00, /** Newline converters are there. */ RUBY_ECONV_NEWLINE_DECORATOR_MASK = 0x00003f00, /** (Unclear; seems unused). */ RUBY_ECONV_NEWLINE_DECORATOR_READ_MASK = 0x00000f00, /** (Unclear; seems unused). */ RUBY_ECONV_NEWLINE_DECORATOR_WRITE_MASK = 0x00003000, /** Universal newline mode. */ RUBY_ECONV_UNIVERSAL_NEWLINE_DECORATOR = 0x00000100, /** CR to CRLF conversion shall happen. */ RUBY_ECONV_CRLF_NEWLINE_DECORATOR = 0x00001000, /** CRLF to CR conversion shall happen. */ RUBY_ECONV_CR_NEWLINE_DECORATOR = 0x00002000, /** Texts shall be XML-escaped. */ RUBY_ECONV_XML_TEXT_DECORATOR = 0x00004000, /** Texts shall be AttrValue escaped */ RUBY_ECONV_XML_ATTR_CONTENT_DECORATOR = 0x00008000, /** (Unclear; seems unused). */ RUBY_ECONV_STATEFUL_DECORATOR_MASK = 0x00f00000, /** Texts shall be AttrValue escaped. */ RUBY_ECONV_XML_ATTR_QUOTE_DECORATOR = 0x00100000, /** Newline decorator's default. */ RUBY_ECONV_DEFAULT_NEWLINE_DECORATOR = #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32) RUBY_ECONV_CRLF_NEWLINE_DECORATOR, #else 0, #endif #define ECONV_ERROR_HANDLER_MASK RUBY_ECONV_ERROR_HANDLER_MASK /**< @old{RUBY_ECONV_ERROR_HANDLER_MASK} */ #define ECONV_INVALID_MASK RUBY_ECONV_INVALID_MASK /**< @old{RUBY_ECONV_INVALID_MASK} */ #define ECONV_INVALID_REPLACE RUBY_ECONV_INVALID_REPLACE /**< @old{RUBY_ECONV_INVALID_REPLACE} */ #define ECONV_UNDEF_MASK RUBY_ECONV_UNDEF_MASK /**< @old{RUBY_ECONV_UNDEF_MASK} */ #define ECONV_UNDEF_REPLACE RUBY_ECONV_UNDEF_REPLACE /**< @old{RUBY_ECONV_UNDEF_REPLACE} */ #define ECONV_UNDEF_HEX_CHARREF RUBY_ECONV_UNDEF_HEX_CHARREF /**< @old{RUBY_ECONV_UNDEF_HEX_CHARREF} */ #define ECONV_DECORATOR_MASK RUBY_ECONV_DECORATOR_MASK /**< @old{RUBY_ECONV_DECORATOR_MASK} */ #define ECONV_NEWLINE_DECORATOR_MASK RUBY_ECONV_NEWLINE_DECORATOR_MASK /**< @old{RUBY_ECONV_NEWLINE_DECORATOR_MASK} */ #define ECONV_NEWLINE_DECORATOR_READ_MASK RUBY_ECONV_NEWLINE_DECORATOR_READ_MASK /**< @old{RUBY_ECONV_NEWLINE_DECORATOR_READ_MASK} */ #define ECONV_NEWLINE_DECORATOR_WRITE_MASK RUBY_ECONV_NEWLINE_DECORATOR_WRITE_MASK /**< @old{RUBY_ECONV_NEWLINE_DECORATOR_WRITE_MASK} */ #define ECONV_UNIVERSAL_NEWLINE_DECORATOR RUBY_ECONV_UNIVERSAL_NEWLINE_DECORATOR /**< @old{RUBY_ECONV_UNIVERSAL_NEWLINE_DECORATOR} */ #define ECONV_CRLF_NEWLINE_DECORATOR RUBY_ECONV_CRLF_NEWLINE_DECORATOR /**< @old{RUBY_ECONV_CRLF_NEWLINE_DECORATOR} */ #define ECONV_CR_NEWLINE_DECORATOR RUBY_ECONV_CR_NEWLINE_DECORATOR /**< @old{RUBY_ECONV_CR_NEWLINE_DECORATOR} */ #define ECONV_XML_TEXT_DECORATOR RUBY_ECONV_XML_TEXT_DECORATOR /**< @old{RUBY_ECONV_XML_TEXT_DECORATOR} */ #define ECONV_XML_ATTR_CONTENT_DECORATOR RUBY_ECONV_XML_ATTR_CONTENT_DECORATOR /**< @old{RUBY_ECONV_XML_ATTR_CONTENT_DECORATOR} */ #define ECONV_STATEFUL_DECORATOR_MASK RUBY_ECONV_STATEFUL_DECORATOR_MASK /**< @old{RUBY_ECONV_STATEFUL_DECORATOR_MASK} */ #define ECONV_XML_ATTR_QUOTE_DECORATOR RUBY_ECONV_XML_ATTR_QUOTE_DECORATOR /**< @old{RUBY_ECONV_XML_ATTR_QUOTE_DECORATOR} */ #define ECONV_DEFAULT_NEWLINE_DECORATOR RUBY_ECONV_DEFAULT_NEWLINE_DECORATOR /**< @old{RUBY_ECONV_DEFAULT_NEWLINE_DECORATOR} */ /** @} */ /** * @name Flags for rb_econv_convert() * * @{ */ /** Indicates the input is a part of much larger one. */ RUBY_ECONV_PARTIAL_INPUT = 0x00010000, /** Instructs the converter to stop after output. */ RUBY_ECONV_AFTER_OUTPUT = 0x00020000, #define ECONV_PARTIAL_INPUT RUBY_ECONV_PARTIAL_INPUT /**< @old{RUBY_ECONV_PARTIAL_INPUT} */ #define ECONV_AFTER_OUTPUT RUBY_ECONV_AFTER_OUTPUT /**< @old{RUBY_ECONV_AFTER_OUTPUT} */ RUBY_ECONV_FLAGS_PLACEHOLDER /**< Placeholder (not used) */ }; RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_INTERNAL_ENCODING_TRANSCODE_H */ PK!j} internal/encoding/sprintf.hnu[#ifndef RUBY_INTERNAL_ENCODING_SPRINTF_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_INTERNAL_ENCODING_SPRINTF_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Routines to manipulate encodings of symbols. */ #include "ruby/internal/config.h" #include #include "ruby/internal/attr/format.h" #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/attr/noreturn.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/encoding/encoding.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() RBIMPL_ATTR_NONNULL((2)) RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 3) /** * Identical to rb_sprintf(), except it additionally takes an encoding. The * passed encoding rules both the incoming format specifier and the resulting * string. * * @param[in] enc Encoding of `fmt`. * @param[in] fmt A `printf`-like format specifier. * @param[in] ... Variadic number of contents to format. * @return A rendered new instance of ::rb_cString, of `enc` encoding. */ VALUE rb_enc_sprintf(rb_encoding *enc, const char *fmt, ...); RBIMPL_ATTR_NONNULL((2)) RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 0) /** * Identical to rb_enc_sprintf(), except it takes a `va_list` instead of * variadic arguments. It can also be seen as a routine identical to * rb_vsprintf(), except it additionally takes an encoding. * * @param[in] enc Encoding of `fmt`. * @param[in] fmt A `printf`-like format specifier. * @param[in] ap Contents to format. * @return A rendered new instance of ::rb_cString, of `enc` encoding. */ VALUE rb_enc_vsprintf(rb_encoding *enc, const char *fmt, va_list ap); RBIMPL_ATTR_NORETURN() RBIMPL_ATTR_NONNULL((3)) RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 3, 4) /** * Identical to rb_raise(), except it additionally takes an encoding. * * @param[in] enc Encoding of the generating exception. * @param[in] exc A subclass of ::rb_eException. * @param[in] fmt Format specifier string compatible with rb_sprintf(). * @param[in] ... Contents of the message. * @exception exc The specified exception. * @note It never returns. */ void rb_enc_raise(rb_encoding *enc, VALUE exc, const char *fmt, ...); RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_INTERNAL_ENCODING_SPRINTF_H */ PK!4"internal/encoding/coderange.hnu[#ifndef RUBY_INTERNAL_ENCODING_CODERANGE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_INTERNAL_ENCODING_CODERANGE_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Routines for code ranges. */ #include "ruby/internal/attr/const.h" #include "ruby/internal/attr/pure.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/fl_type.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /** What rb_enc_str_coderange() returns. */ enum ruby_coderange_type { /** The object's coderange is unclear yet. */ RUBY_ENC_CODERANGE_UNKNOWN = 0, /** The object holds 0 to 127 inclusive and nothing else. */ RUBY_ENC_CODERANGE_7BIT = ((int)RUBY_FL_USER8), /** The object's encoding and contents are consistent each other */ RUBY_ENC_CODERANGE_VALID = ((int)RUBY_FL_USER9), /** The object holds invalid/malformed/broken character(s). */ RUBY_ENC_CODERANGE_BROKEN = ((int)(RUBY_FL_USER8|RUBY_FL_USER9)), /** Where the coderange resides. */ RUBY_ENC_CODERANGE_MASK = (RUBY_ENC_CODERANGE_7BIT| RUBY_ENC_CODERANGE_VALID| RUBY_ENC_CODERANGE_BROKEN) }; RBIMPL_ATTR_CONST() /** * @private * * This is an implementation detail of #RB_ENC_CODERANGE_CLEAN_P. People don't * use it directly. * * @param[in] cr An enum ::ruby_coderange_type. * @retval 1 It is. * @retval 0 It isn't. */ static inline int rb_enc_coderange_clean_p(int cr) { return (cr ^ (cr >> 1)) & RUBY_ENC_CODERANGE_7BIT; } RBIMPL_ATTR_CONST() /** * Queries if a code range is "clean". "Clean" in this context means it is * known and valid. * * @param[in] cr An enum ::ruby_coderange_type. * @retval 1 It is. * @retval 0 It isn't. */ static inline bool RB_ENC_CODERANGE_CLEAN_P(enum ruby_coderange_type cr) { return rb_enc_coderange_clean_p(cr); } RBIMPL_ATTR_PURE_UNLESS_DEBUG() /** * Queries the (inline) code range of the passed object. The object must be * capable of having inline encoding. Using this macro needs deep * understanding of bit level object binary layout. * * @param[in] obj Target object. * @return An enum ::ruby_coderange_type. */ static inline enum ruby_coderange_type RB_ENC_CODERANGE(VALUE obj) { VALUE ret = RB_FL_TEST_RAW(obj, RUBY_ENC_CODERANGE_MASK); return RBIMPL_CAST((enum ruby_coderange_type)ret); } RBIMPL_ATTR_PURE_UNLESS_DEBUG() /** * Queries the (inline) code range of the passed object is * ::RUBY_ENC_CODERANGE_7BIT. The object must be capable of having inline * encoding. Using this macro needs deep understanding of bit level object * binary layout. * * @param[in] obj Target object. * @retval 1 It is ascii only. * @retval 0 Otherwise (including cases when the range is not known). */ static inline bool RB_ENC_CODERANGE_ASCIIONLY(VALUE obj) { return RB_ENC_CODERANGE(obj) == RUBY_ENC_CODERANGE_7BIT; } /** * Destructively modifies the passed object so that its (inline) code range is * the passed one. The object must be capable of having inline encoding. * Using this macro needs deep understanding of bit level object binary layout. * * @param[out] obj Target object. * @param[out] cr An enum ::ruby_coderange_type. * @post `obj`'s code range is `cr`. */ static inline void RB_ENC_CODERANGE_SET(VALUE obj, enum ruby_coderange_type cr) { RB_FL_UNSET_RAW(obj, RUBY_ENC_CODERANGE_MASK); RB_FL_SET_RAW(obj, cr); } /** * Destructively clears the passed object's (inline) code range. The object * must be capable of having inline encoding. Using this macro needs deep * understanding of bit level object binary layout. * * @param[out] obj Target object. * @post `obj`'s code range is ::RUBY_ENC_CODERANGE_UNKNOWN. */ static inline void RB_ENC_CODERANGE_CLEAR(VALUE obj) { RB_FL_UNSET_RAW(obj, RUBY_ENC_CODERANGE_MASK); } RBIMPL_ATTR_CONST() /* assumed ASCII compatibility */ /** * "Mix" two code ranges into one. This is handy for instance when you * concatenate two strings into one. Consider one of then is valid but the * other isn't. The result must be invalid. This macro computes that kind of * mixture. * * @param[in] a An enum ::ruby_coderange_type. * @param[in] b Another enum ::ruby_coderange_type. * @return The `a` "and" `b`. */ static inline enum ruby_coderange_type RB_ENC_CODERANGE_AND(enum ruby_coderange_type a, enum ruby_coderange_type b) { if (a == RUBY_ENC_CODERANGE_7BIT) { return b; } else if (a != RUBY_ENC_CODERANGE_VALID) { return RUBY_ENC_CODERANGE_UNKNOWN; } else if (b == RUBY_ENC_CODERANGE_7BIT) { return RUBY_ENC_CODERANGE_VALID; } else { return b; } } #define ENC_CODERANGE_MASK RUBY_ENC_CODERANGE_MASK /**< @old{RUBY_ENC_CODERANGE_MASK} */ #define ENC_CODERANGE_UNKNOWN RUBY_ENC_CODERANGE_UNKNOWN /**< @old{RUBY_ENC_CODERANGE_UNKNOWN} */ #define ENC_CODERANGE_7BIT RUBY_ENC_CODERANGE_7BIT /**< @old{RUBY_ENC_CODERANGE_7BIT} */ #define ENC_CODERANGE_VALID RUBY_ENC_CODERANGE_VALID /**< @old{RUBY_ENC_CODERANGE_VALID} */ #define ENC_CODERANGE_BROKEN RUBY_ENC_CODERANGE_BROKEN /**< @old{RUBY_ENC_CODERANGE_BROKEN} */ #define ENC_CODERANGE_CLEAN_P(cr) RB_ENC_CODERANGE_CLEAN_P(cr) /**< @old{RB_ENC_CODERANGE_CLEAN_P} */ #define ENC_CODERANGE(obj) RB_ENC_CODERANGE(obj) /**< @old{RB_ENC_CODERANGE} */ #define ENC_CODERANGE_ASCIIONLY(obj) RB_ENC_CODERANGE_ASCIIONLY(obj) /**< @old{RB_ENC_CODERANGE_ASCIIONLY} */ #define ENC_CODERANGE_SET(obj,cr) RB_ENC_CODERANGE_SET(obj,cr) /**< @old{RB_ENC_CODERANGE_SET} */ #define ENC_CODERANGE_CLEAR(obj) RB_ENC_CODERANGE_CLEAR(obj) /**< @old{RB_ENC_CODERANGE_CLEAR} */ #define ENC_CODERANGE_AND(a, b) RB_ENC_CODERANGE_AND(a, b) /**< @old{RB_ENC_CODERANGE_AND} */ #define ENCODING_CODERANGE_SET(obj, encindex, cr) RB_ENCODING_CODERANGE_SET(obj, encindex, cr) /**< @old{RB_ENCODING_CODERANGE_SET} */ /** @cond INTERNAL_MACRO */ #define RB_ENC_CODERANGE RB_ENC_CODERANGE #define RB_ENC_CODERANGE_AND RB_ENC_CODERANGE_AND #define RB_ENC_CODERANGE_ASCIIONLY RB_ENC_CODERANGE_ASCIIONLY #define RB_ENC_CODERANGE_CLEAN_P RB_ENC_CODERANGE_CLEAN_P #define RB_ENC_CODERANGE_CLEAR RB_ENC_CODERANGE_CLEAR #define RB_ENC_CODERANGE_SET RB_ENC_CODERANGE_SET /** @endcond */ RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_INTERNAL_ENCODING_CODERANGE_H */ PK!internal/has/cpp_attribute.hnu[#ifndef RBIMPL_HAS_CPP_ATTRIBUTE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_HAS_CPP_ATTRIBUTE_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_HAS_CPP_ATTRIBUTE. */ #include "ruby/internal/compiler_is.h" #include "ruby/internal/compiler_since.h" #include "ruby/internal/token_paste.h" /** @cond INTERNAL_MACRO */ #if RBIMPL_COMPILER_IS(SunPro) # /* Oracle Developer Studio 12.5's C++ preprocessor is reportedly broken. We # * could simulate __has_cpp_attribute like below, but don't know the exact # * list of which version supported which attribute. Just kill everything for # * now. If you can please :FIXME: */ # /* https://unicode-org.atlassian.net/browse/ICU-12893 */ # /* https://github.com/boostorg/config/pull/95 */ # define RBIMPL_HAS_CPP_ATTRIBUTE0(_) 0 #elif defined(__has_cpp_attribute) # define RBIMPL_HAS_CPP_ATTRIBUTE0(_) __has_cpp_attribute(_) #elif RBIMPL_COMPILER_IS(MSVC) # /* MSVC has never updated its __cplusplus since forever (unless specified # * explicitly by a compiler flag). They also lack __has_cpp_attribute until # * 2019. However, they do have attributes since 2015 or so. */ # /* https://docs.microsoft.com/en-us/cpp/overview/visual-cpp-language-conformance */ # define RBIMPL_HAS_CPP_ATTRIBUTE0(_) RBIMPL_TOKEN_PASTE(RBIMPL_HAS_CPP_ATTRIBUTE_, _) # define RBIMPL_HAS_CPP_ATTRIBUTE_noreturn 200809 * RBIMPL_COMPILER_SINCE(MSVC, 19, 00, 0) # define RBIMPL_HAS_CPP_ATTRIBUTE_carries_dependency 200809 * RBIMPL_COMPILER_SINCE(MSVC, 19, 00, 0) # define RBIMPL_HAS_CPP_ATTRIBUTE_deprecated 201309 * RBIMPL_COMPILER_SINCE(MSVC, 19, 10, 0) # define RBIMPL_HAS_CPP_ATTRIBUTE_fallthrough 201603 * RBIMPL_COMPILER_SINCE(MSVC, 19, 10, 0) # define RBIMPL_HAS_CPP_ATTRIBUTE_maybe_unused 201603 * RBIMPL_COMPILER_SINCE(MSVC, 19, 11, 0) # define RBIMPL_HAS_CPP_ATTRIBUTE_nodiscard 201603 * RBIMPL_COMPILER_SINCE(MSVC, 19, 11, 0) #elif RBIMPL_COMPILER_BEFORE(Clang, 3, 6, 0) # /* Clang 3.6.0 introduced __has_cpp_attribute. Prior to that following # * attributes were already there. */ # /* https://clang.llvm.org/cxx_status.html */ # define RBIMPL_HAS_CPP_ATTRIBUTE0(_) RBIMPL_TOKEN_PASTE(RBIMPL_HAS_CPP_ATTRIBUTE_, _) # define RBIMPL_HAS_CPP_ATTRIBUTE_noreturn 200809 * RBIMPL_COMPILER_SINCE(Clang, 3, 3, 0) # define RBIMPL_HAS_CPP_ATTRIBUTE_deprecated 201309 * RBIMPL_COMPILER_SINCE(Clang, 3, 4, 0) #elif RBIMPL_COMPILER_BEFORE(GCC, 5, 0, 0) # /* GCC 5+ have __has_cpp_attribute, while 4.x had following attributes. */ # /* https://gcc.gnu.org/projects/cxx-status.html */ # define RBIMPL_HAS_CPP_ATTRIBUTE0(_) RBIMPL_TOKEN_PASTE(RBIMPL_HAS_CPP_ATTRIBUTE_, _) # define RBIMPL_HAS_CPP_ATTRIBUTE_noreturn 200809 * RBIMPL_COMPILER_SINCE(GCC, 4, 8, 0) # define RBIMPL_HAS_CPP_ATTRIBUTE_deprecated 201309 * RBIMPL_COMPILER_SINCE(GCC, 4, 9, 0) #else # /* :FIXME: # * Candidate compilers to list here: # * - icpc: They have __INTEL_CXX11_MODE__. # */ # define RBIMPL_HAS_CPP_ATTRIBUTE0(_) 0 #endif /** @endcond */ /** Wraps (or simulates) `__has_cpp_attribute`. */ #if ! defined(__cplusplus) # /* Makes no sense. */ # define RBIMPL_HAS_CPP_ATTRIBUTE(_) 0 #else # /* GCC needs workarounds. See https://gcc.godbolt.org/z/jdz3pa */ # define RBIMPL_HAS_CPP_ATTRIBUTE(_) \ ((RBIMPL_HAS_CPP_ATTRIBUTE0(_) <= __cplusplus) ? RBIMPL_HAS_CPP_ATTRIBUTE0(_) : 0) #endif #endif /* RBIMPL_HAS_CPP_ATTRIBUTE_H */ PK!p4internal/has/extension.hnu[#ifndef RBIMPL_HAS_EXTENSION_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_HAS_EXTENSION_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_HAS_EXTENSION. */ #include "ruby/internal/has/feature.h" /** Wraps (or simulates) `__has_extension`. */ #if defined(__has_extension) # define RBIMPL_HAS_EXTENSION(_) __has_extension(_) #else # /* Pre-3.0 clang had __has_feature but not __has_extension. */ # define RBIMPL_HAS_EXTENSION(_) RBIMPL_HAS_FEATURE(_) #endif #endif /* RBIMPL_HAS_EXTENSION_H */ PK!internal/has/feature.hnu[#ifndef RBIMPL_HAS_FEATURE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_HAS_FEATURE_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_HAS_FEATURE. */ /** Wraps (or simulates) `__has_feature`. */ #if defined(__has_feature) # define RBIMPL_HAS_FEATURE(_) __has_feature(_) #else # define RBIMPL_HAS_FEATURE(_) 0 #endif #endif /* RBIMPL_HAS_FEATURE_H */ PK!_bOinternal/has/builtin.hnu[#ifndef RBIMPL_HAS_BUILTIN_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_HAS_BUILTIN_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_HAS_BUILTIN. */ #include "ruby/internal/config.h" #include "ruby/internal/compiler_since.h" #include "ruby/internal/token_paste.h" #if defined(__has_builtin) # if RBIMPL_COMPILER_IS(Intel) # /* :TODO: Intel C Compiler has __has_builtin (since 19.1 maybe?), and is # * reportedly broken. We have to skip them. However the situation can # * change. They might improve someday. We need to revisit here later. */ # elif RBIMPL_COMPILER_IS(GCC) && ! __has_builtin(__builtin_alloca) # /* FreeBSD's defines its own *broken* version of # * __has_builtin. Cygwin copied that content to be a victim of the # * broken-ness. We don't take them into account. */ # else # define RBIMPL_HAVE___HAS_BUILTIN 1 # endif #endif /** Wraps (or simulates) `__has_builtin`. */ #if defined(RBIMPL_HAVE___HAS_BUILTIN) # define RBIMPL_HAS_BUILTIN(_) __has_builtin(_) #elif RBIMPL_COMPILER_IS(GCC) # /* :FIXME: Historically GCC has had tons of builtins, but it implemented # * __has_builtin only since GCC 10. This section can be made more # * granular. */ # /* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66970 */ # define RBIMPL_HAS_BUILTIN(_) RBIMPL_TOKEN_PASTE(RBIMPL_HAS_BUILTIN_, _) # define RBIMPL_HAS_BUILTIN___builtin_add_overflow RBIMPL_COMPILER_SINCE(GCC, 5, 1, 0) # define RBIMPL_HAS_BUILTIN___builtin_alloca RBIMPL_COMPILER_SINCE(GCC, 0, 0, 0) # define RBIMPL_HAS_BUILTIN___builtin_alloca_with_align RBIMPL_COMPILER_SINCE(GCC, 6, 1, 0) # /* See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52624 for bswap16. */ # define RBIMPL_HAS_BUILTIN___builtin_bswap16 RBIMPL_COMPILER_SINCE(GCC, 4, 8, 0) # define RBIMPL_HAS_BUILTIN___builtin_bswap32 RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0) # define RBIMPL_HAS_BUILTIN___builtin_bswap64 RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0) # define RBIMPL_HAS_BUILTIN___builtin_clz RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0) # define RBIMPL_HAS_BUILTIN___builtin_clzl RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0) # define RBIMPL_HAS_BUILTIN___builtin_clzll RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0) # define RBIMPL_HAS_BUILTIN___builtin_constant_p RBIMPL_COMPILER_SINCE(GCC, 2,95, 3) # define RBIMPL_HAS_BUILTIN___builtin_ctz RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0) # define RBIMPL_HAS_BUILTIN___builtin_ctzl RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0) # define RBIMPL_HAS_BUILTIN___builtin_ctzll RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0) # define RBIMPL_HAS_BUILTIN___builtin_expect RBIMPL_COMPILER_SINCE(GCC, 3, 0, 0) # define RBIMPL_HAS_BUILTIN___builtin_mul_overflow RBIMPL_COMPILER_SINCE(GCC, 5, 1, 0) # define RBIMPL_HAS_BUILTIN___builtin_mul_overflow_p RBIMPL_COMPILER_SINCE(GCC, 7, 0, 0) # define RBIMPL_HAS_BUILTIN___builtin_popcount RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0) # define RBIMPL_HAS_BUILTIN___builtin_popcountl RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0) # define RBIMPL_HAS_BUILTIN___builtin_popcountll RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0) # define RBIMPL_HAS_BUILTIN___builtin_sub_overflow RBIMPL_COMPILER_SINCE(GCC, 5, 1, 0) # define RBIMPL_HAS_BUILTIN___builtin_unreachable RBIMPL_COMPILER_SINCE(GCC, 4, 5, 0) # /* Note that "0, 0, 0" might be inaccurate. */ #elif RBIMPL_COMPILER_IS(MSVC) # /* MSVC has UNREACHABLE, but that is not __builtin_unreachable. */ # define RBIMPL_HAS_BUILTIN(_) 0 #else # /* Take config.h definition when available */ # define RBIMPL_HAS_BUILTIN(_) (RBIMPL_TOKEN_PASTE(RBIMPL_HAS_BUILTIN_, _)+0) # define RBIMPL_HAS_BUILTIN___builtin_add_overflow HAVE_BUILTIN___BUILTIN_ADD_OVERFLOW # define RBIMPL_HAS_BUILTIN___builtin_alloca_with_align HAVE_BUILTIN___BUILTIN_ALLOCA_WITH_ALIGN # define RBIMPL_HAS_BUILTIN___builtin_assume_aligned HAVE_BUILTIN___BUILTIN_ASSUME_ALIGNED # define RBIMPL_HAS_BUILTIN___builtin_bswap16 HAVE_BUILTIN___BUILTIN_BSWAP16 # define RBIMPL_HAS_BUILTIN___builtin_bswap32 HAVE_BUILTIN___BUILTIN_BSWAP32 # define RBIMPL_HAS_BUILTIN___builtin_bswap64 HAVE_BUILTIN___BUILTIN_BSWAP64 # define RBIMPL_HAS_BUILTIN___builtin_clz HAVE_BUILTIN___BUILTIN_CLZ # define RBIMPL_HAS_BUILTIN___builtin_clzl HAVE_BUILTIN___BUILTIN_CLZL # define RBIMPL_HAS_BUILTIN___builtin_clzll HAVE_BUILTIN___BUILTIN_CLZLL # define RBIMPL_HAS_BUILTIN___builtin_constant_p HAVE_BUILTIN___BUILTIN_CONSTANT_P # define RBIMPL_HAS_BUILTIN___builtin_ctz HAVE_BUILTIN___BUILTIN_CTZ # define RBIMPL_HAS_BUILTIN___builtin_ctzll HAVE_BUILTIN___BUILTIN_CTZLL # define RBIMPL_HAS_BUILTIN___builtin_expect HAVE_BUILTIN___BUILTIN_EXPECT # define RBIMPL_HAS_BUILTIN___builtin_mul_overflow HAVE_BUILTIN___BUILTIN_MUL_OVERFLOW # define RBIMPL_HAS_BUILTIN___builtin_mul_overflow_p HAVE_BUILTIN___BUILTIN_MUL_OVERFLOW_P # define RBIMPL_HAS_BUILTIN___builtin_popcount HAVE_BUILTIN___BUILTIN_POPCOUNT # define RBIMPL_HAS_BUILTIN___builtin_popcountll HAVE_BUILTIN___BUILTIN_POPCOUNTLL # define RBIMPL_HAS_BUILTIN___builtin_sub_overflow HAVE_BUILTIN___BUILTIN_SUB_OVERFLOW # if defined(UNREACHABLE) # define RBIMPL_HAS_BUILTIN___builtin_unreachable 1 # endif #endif #endif /* RBIMPL_HAS_BUILTIN_H */ PK!}OI/ / !internal/has/declspec_attribute.hnu[#ifndef RBIMPL_HAS_DECLSPEC_ATTRIBUTE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_HAS_DECLSPEC_ATTRIBUTE. */ #include "ruby/internal/compiler_since.h" #include "ruby/internal/token_paste.h" /** Wraps (or simulates) `__has_declspec_attribute`. */ #if defined(__has_declspec_attribute) # define RBIMPL_HAS_DECLSPEC_ATTRIBUTE(_) __has_declspec_attribute(_) #else # define RBIMPL_HAS_DECLSPEC_ATTRIBUTE(_) RBIMPL_TOKEN_PASTE(RBIMPL_HAS_DECLSPEC_ATTRIBUTE_, _) # define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_align RBIMPL_COMPILER_SINCE(MSVC, 8, 0, 0) # define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_deprecated RBIMPL_COMPILER_SINCE(MSVC,13, 0, 0) # define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_dllexport RBIMPL_COMPILER_SINCE(MSVC, 8, 0, 0) # define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_dllimport RBIMPL_COMPILER_SINCE(MSVC, 8, 0, 0) # define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_empty_bases RBIMPL_COMPILER_SINCE(MSVC,19, 0, 23918) # define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_noalias RBIMPL_COMPILER_SINCE(MSVC, 8, 0, 0) # define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_noinline RBIMPL_COMPILER_SINCE(MSVC,13, 0, 0) # define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_noreturn RBIMPL_COMPILER_SINCE(MSVC,11, 0, 0) # define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_nothrow RBIMPL_COMPILER_SINCE(MSVC, 8, 0, 0) # define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_restrict RBIMPL_COMPILER_SINCE(MSVC,14, 0, 0) # /* Note that "8, 0, 0" might be inaccurate. */ # if ! defined(__cplusplus) # /* Clang has this in both C/C++, but MSVC has this in C++ only.*/ # undef RBIMPL_HAS_DECLSPEC_ATTRIBUTE_nothrow # endif #endif #endif /* RBIMPL_HAS_DECLSPEC_ATTRIBUTE_H */ PK!'i'internal/has/c_attribute.hnu[#ifndef RBIMPL_HAS_C_ATTRIBUTE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_HAS_C_ATTRIBUTE_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_HAS_C_ATTRIBUTE. */ /** Wraps (or simulates) `__has_c_attribute`. */ #if defined(__cplusplus) # /* Makes no sense. */ # define RBIMPL_HAS_C_ATTRIBUTE(_) 0 #elif defined(__has_c_attribute) # define RBIMPL_HAS_C_ATTRIBUTE(_) __has_c_attribute(_) #else # /* As of writing everything that lacks __has_c_attribute also completely # * lacks C2x attributes as well. Might change in future? */ # define RBIMPL_HAS_C_ATTRIBUTE(_) 0 #endif #endif /* RBIMPL_HAS_C_ATTRIBUTE_H */ PK!S-!!internal/has/attribute.hnu[#ifndef RBIMPL_HAS_ATTRIBUTE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_HAS_ATTRIBUTE_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_HAS_ATTRIBUTE. */ #include "ruby/internal/config.h" #include "ruby/internal/compiler_since.h" #include "ruby/internal/token_paste.h" #if defined(__has_attribute) # if __has_attribute(pure) || RBIMPL_COMPILER_IS(GCC) # /* FreeBSD's defines its own *broken* version of # * __has_attribute. Cygwin copied that content to be a victim of the # * broken-ness. We don't take them into account. */ # define RBIMPL_HAVE___HAS_ATTRIBUTE 1 # endif #endif /** Wraps (or simulates) `__has_attribute`. */ #if defined(RBIMPL_HAVE___HAS_ATTRIBUTE) # define RBIMPL_HAS_ATTRIBUTE(_) __has_attribute(_) #elif RBIMPL_COMPILER_IS(GCC) # /* GCC <= 4 lack __has_attribute predefined macro, while have attributes # * themselves. We can simulate the macro like the following: */ # define RBIMPL_HAS_ATTRIBUTE(_) RBIMPL_TOKEN_PASTE(RBIMPL_HAS_ATTRIBUTE_, _) # define RBIMPL_HAS_ATTRIBUTE_aligned RBIMPL_COMPILER_SINCE(GCC, 0, 0, 0) # define RBIMPL_HAS_ATTRIBUTE_alloc_size RBIMPL_COMPILER_SINCE(GCC, 4, 3, 0) # define RBIMPL_HAS_ATTRIBUTE_artificial RBIMPL_COMPILER_SINCE(GCC, 4, 3, 0) # define RBIMPL_HAS_ATTRIBUTE_always_inline RBIMPL_COMPILER_SINCE(GCC, 3, 1, 0) # define RBIMPL_HAS_ATTRIBUTE_cdecl RBIMPL_COMPILER_SINCE(GCC, 0, 0, 0) # define RBIMPL_HAS_ATTRIBUTE_cold RBIMPL_COMPILER_SINCE(GCC, 4, 3, 0) # define RBIMPL_HAS_ATTRIBUTE_const RBIMPL_COMPILER_SINCE(GCC, 2, 6, 0) # define RBIMPL_HAS_ATTRIBUTE_deprecated RBIMPL_COMPILER_SINCE(GCC, 3, 1, 0) # define RBIMPL_HAS_ATTRIBUTE_dllexport RBIMPL_COMPILER_SINCE(GCC, 0, 0, 0) # define RBIMPL_HAS_ATTRIBUTE_dllimport RBIMPL_COMPILER_SINCE(GCC, 0, 0, 0) # define RBIMPL_HAS_ATTRIBUTE_error RBIMPL_COMPILER_SINCE(GCC, 4, 3, 0) # define RBIMPL_HAS_ATTRIBUTE_format RBIMPL_COMPILER_SINCE(GCC, 0, 0, 0) # define RBIMPL_HAS_ATTRIBUTE_hot RBIMPL_COMPILER_SINCE(GCC, 4, 3, 0) # define RBIMPL_HAS_ATTRIBUTE_leaf RBIMPL_COMPILER_SINCE(GCC, 4, 6, 0) # define RBIMPL_HAS_ATTRIBUTE_malloc RBIMPL_COMPILER_SINCE(GCC, 3, 0, 0) # define RBIMPL_HAS_ATTRIBUTE_no_address_safety_analysis RBIMPL_COMPILER_SINCE(GCC, 4, 8, 0) # define RBIMPL_HAS_ATTRIBUTE_no_sanitize_address RBIMPL_COMPILER_SINCE(GCC, 4, 8, 0) # define RBIMPL_HAS_ATTRIBUTE_no_sanitize_undefined RBIMPL_COMPILER_SINCE(GCC, 4, 9, 0) # define RBIMPL_HAS_ATTRIBUTE_noinline RBIMPL_COMPILER_SINCE(GCC, 3, 1, 0) # define RBIMPL_HAS_ATTRIBUTE_nonnull RBIMPL_COMPILER_SINCE(GCC, 3, 3, 0) # define RBIMPL_HAS_ATTRIBUTE_noreturn RBIMPL_COMPILER_SINCE(GCC, 2, 5, 0) # define RBIMPL_HAS_ATTRIBUTE_nothrow RBIMPL_COMPILER_SINCE(GCC, 3, 3, 0) # define RBIMPL_HAS_ATTRIBUTE_pure RBIMPL_COMPILER_SINCE(GCC, 2,96, 0) # define RBIMPL_HAS_ATTRIBUTE_returns_nonnull RBIMPL_COMPILER_SINCE(GCC, 4, 9, 0) # define RBIMPL_HAS_ATTRIBUTE_returns_twice RBIMPL_COMPILER_SINCE(GCC, 4, 1, 0) # define RBIMPL_HAS_ATTRIBUTE_stdcall RBIMPL_COMPILER_SINCE(GCC, 0, 0, 0) # define RBIMPL_HAS_ATTRIBUTE_unused RBIMPL_COMPILER_SINCE(GCC, 0, 0, 0) # define RBIMPL_HAS_ATTRIBUTE_visibility RBIMPL_COMPILER_SINCE(GCC, 3, 3, 0) # define RBIMPL_HAS_ATTRIBUTE_warn_unused_result RBIMPL_COMPILER_SINCE(GCC, 3, 4, 0) # define RBIMPL_HAS_ATTRIBUTE_warning RBIMPL_COMPILER_SINCE(GCC, 4, 3, 0) # define RBIMPL_HAS_ATTRIBUTE_weak RBIMPL_COMPILER_SINCE(GCC, 0, 0, 0) # /* Note that "0, 0, 0" might be inaccurate. */ #elif RBIMPL_COMPILER_IS(SunPro) # /* Oracle Solaris Studio 12.4 (cc version 5.11) introduced __has_attribute. # * Before that, following attributes were available. */ # /* See https://docs.oracle.com/cd/F24633_01/index.html */ # define RBIMPL_HAS_ATTRIBUTE(_) RBIMPL_TOKEN_PASTE(RBIMPL_HAS_ATTRIBUTE_, _) # define RBIMPL_HAS_ATTRIBUTE_alias RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0) # define RBIMPL_HAS_ATTRIBUTE_aligned RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0) # define RBIMPL_HAS_ATTRIBUTE_always_inline RBIMPL_COMPILER_SINCE(SunPro, 5, 10, 0) # define RBIMPL_HAS_ATTRIBUTE_const RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0) # define RBIMPL_HAS_ATTRIBUTE_constructor RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0) # define RBIMPL_HAS_ATTRIBUTE_destructor RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0) # define RBIMPL_HAS_ATTRIBUTE_malloc RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0) # define RBIMPL_HAS_ATTRIBUTE_noinline RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0) # define RBIMPL_HAS_ATTRIBUTE_noreturn RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0) # define RBIMPL_HAS_ATTRIBUTE_packed RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0) # define RBIMPL_HAS_ATTRIBUTE_pure RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0) # define RBIMPL_HAS_ATTRIBUTE_returns_twice RBIMPL_COMPILER_SINCE(SunPro, 5, 10, 0) # define RBIMPL_HAS_ATTRIBUTE_vector_size RBIMPL_COMPILER_SINCE(SunPro, 5, 10, 0) # define RBIMPL_HAS_ATTRIBUTE_visibility RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0) # define RBIMPL_HAS_ATTRIBUTE_weak RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0) #elif defined (_MSC_VER) # define RBIMPL_HAS_ATTRIBUTE(_) 0 # /* Fallback below doesn't work: see win32/Makefile.sub */ #else # /* Take config.h definition when available. */ # define RBIMPL_HAS_ATTRIBUTE(_) (RBIMPL_TOKEN_PASTE(RBIMPL_HAS_ATTRIBUTE_, _)+0) # ifdef ALWAYS_INLINE # define RBIMPL_HAS_ATTRIBUTE_always_inline 1 # endif # ifdef FUNC_CDECL # define RBIMPL_HAS_ATTRIBUTE_cdecl 1 # endif # ifdef CONSTFUNC # define RBIMPL_HAS_ATTRIBUTE_const 1 # endif # ifdef DEPRECATED # define RBIMPL_HAS_ATTRIBUTE_deprecated 1 # endif # ifdef ERRORFUNC # define RBIMPL_HAS_ATTRIBUTE_error 1 # endif # ifdef FUNC_FASTCALL # define RBIMPL_HAS_ATTRIBUTE_fastcall 1 # endif # ifdef PUREFUNC # define RBIMPL_HAS_ATTRIBUTE_pure 1 # endif # ifdef NO_ADDRESS_SAFETY_ANALYSIS # define RBIMPL_HAS_ATTRIBUTE_no_address_safety_analysis 1 # endif # ifdef NO_SANITIZE # define RBIMPL_HAS_ATTRIBUTE_no_sanitize 1 # endif # ifdef NO_SANITIZE_ADDRESS # define RBIMPL_HAS_ATTRIBUTE_no_sanitize_address 1 # endif # ifdef NOINLINE # define RBIMPL_HAS_ATTRIBUTE_noinline 1 # endif # ifdef RBIMPL_FUNC_NONNULL # define RBIMPL_HAS_ATTRIBUTE_nonnull 1 # endif # ifdef NORETURN # define RBIMPL_HAS_ATTRIBUTE_noreturn 1 # endif # ifdef FUNC_OPTIMIZED # define RBIMPL_HAS_ATTRIBUTE_optimize 1 # endif # ifdef FUNC_STDCALL # define RBIMPL_HAS_ATTRIBUTE_stdcall 1 # endif # ifdef MAYBE_UNUSED # define RBIMPL_HAS_ATTRIBUTE_unused 1 # endif # ifdef WARN_UNUSED_RESULT # define RBIMPL_HAS_ATTRIBUTE_warn_unused_result 1 # endif # ifdef WARNINGFUNC # define RBIMPL_HAS_ATTRIBUTE_warning 1 # endif # ifdef WEAK # define RBIMPL_HAS_ATTRIBUTE_weak 1 # endif #endif #endif /* RBIMPL_HAS_ATTRIBUTE_H */ PK!Xinternal/has/warning.hnu[#ifndef RBIMPL_HAS_WARNING_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_HAS_WARNING_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_HAS_WARNING. */ /** Wraps (or simulates) `__has_warning`. */ #if defined(__has_warning) # define RBIMPL_HAS_WARNING(_) __has_warning(_) #else # define RBIMPL_HAS_WARNING(_) 0 #endif #endif /* RBIMPL_HAS_WARNING_H */ PK!UT77internal/config.hnu[#ifndef RBIMPL_CONFIG_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_CONFIG_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Thin wrapper to ruby/config.h */ #include "ruby/config.h" #ifdef RUBY_EXTCONF_H # include RUBY_EXTCONF_H #endif #include "ruby/internal/compiler_since.h" #undef HAVE_PROTOTYPES #define HAVE_PROTOTYPES 1 #undef HAVE_STDARG_PROTOTYPES #define HAVE_STDARG_PROTOTYPES 1 #undef TOKEN_PASTE #define TOKEN_PASTE(x,y) x##y #if defined(__cplusplus) #/* __builtin_choose_expr and __builtin_types_compatible aren't available # * on C++. See https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html */ # undef HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P # undef HAVE_BUILTIN___BUILTIN_TYPES_COMPATIBLE_P /* HAVE_VA_ARGS_MACRO is for C. C++ situations might be different. */ # undef HAVE_VA_ARGS_MACRO # if __cplusplus >= 201103L # define HAVE_VA_ARGS_MACRO # elif defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__ # define HAVE_VA_ARGS_MACRO # elif defined(__INTEL_CXX11_MODE__) # define HAVE_VA_ARGS_MACRO # elif RBIMPL_COMPILER_SINCE(MSVC, 16, 0, 0) # define HAVE_VA_ARGS_MACRO # else # /* NG, not known. */ # endif #endif #if RBIMPL_COMPILER_BEFORE(GCC, 4, 9, 0) # /* See https://bugs.ruby-lang.org/issues/14221 */ # undef HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P #endif #if RBIMPL_COMPILER_BEFORE(GCC, 5, 0, 0) # /* GCC 4.9.2 reportedly has this feature and is broken. The function is not # * officially documented below. Seems we should not use it. # * https://gcc.gnu.org/onlinedocs/gcc-4.9.4/gcc/Other-Builtins.html */ # undef HAVE_BUILTIN___BUILTIN_ALLOCA_WITH_ALIGN #endif #if defined(__SUNPRO_CC) # /* Oracle Developer Studio 12.5: GCC compatibility guide says it supports # * statement expressions. But to our knowledge they support the extension # * only for C and not for C++. Prove me wrong. Am happy to support them if # * there is a way. */ # undef HAVE_STMT_AND_DECL_IN_EXPR #endif #ifndef STRINGIZE0 # define STRINGIZE(expr) STRINGIZE0(expr) # define STRINGIZE0(expr) #expr #endif #ifdef AC_APPLE_UNIVERSAL_BUILD # undef WORDS_BIGENDIAN # ifdef __BIG_ENDIAN__ # define WORDS_BIGENDIAN # endif #endif #ifndef DLEXT_MAXLEN # define DLEXT_MAXLEN 4 #endif #ifndef RUBY_PLATFORM # define RUBY_PLATFORM "unknown-unknown" #endif #ifdef UNALIGNED_WORD_ACCESS # /* Take that. */ #elif defined(__i386) # define UNALIGNED_WORD_ACCESS 1 #elif defined(__i386__) # define UNALIGNED_WORD_ACCESS 1 #elif defined(_M_IX86) # define UNALIGNED_WORD_ACCESS 1 #elif defined(__x86_64) # define UNALIGNED_WORD_ACCESS 1 #elif defined(__x86_64__) # define UNALIGNED_WORD_ACCESS 1 #elif defined(_M_AMD64) # define UNALIGNED_WORD_ACCESS 1 #elif defined(__powerpc64__) # define UNALIGNED_WORD_ACCESS 1 #elif defined(__aarch64__) # define UNALIGNED_WORD_ACCESS 1 #elif defined(__mc68020__) # define UNALIGNED_WORD_ACCESS 1 #else # define UNALIGNED_WORD_ACCESS 0 #endif /* Detection of __VA_OPT__ */ #if ! defined(HAVE_VA_ARGS_MACRO) # undef HAVE___VA_OPT__ #else # /* Idea taken from: https://stackoverflow.com/a/48045656 */ # define RBIMPL_TEST3(q, w, e, ...) e # define RBIMPL_TEST2(...) RBIMPL_TEST3(__VA_OPT__(,),1,0,0) # define RBIMPL_TEST1() RBIMPL_TEST2("ruby") # if RBIMPL_TEST1() # define HAVE___VA_OPT__ # else # undef HAVE___VA_OPT__ # endif # undef RBIMPL_TEST1 # undef RBIMPL_TEST2 # undef RBIMPL_TEST3 #endif /* HAVE_VA_ARGS_MACRO */ #endif /* RBIMPL_CONFIG_H */ PK!~>/internal/core/rdata.hnu[#ifndef RBIMPL_RDATA_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_RDATA_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines struct ::RData. */ #include "ruby/internal/config.h" #ifdef STDC_HEADERS # include #endif #include "ruby/internal/attr/deprecated.h" #include "ruby/internal/attr/warning.h" #include "ruby/internal/cast.h" #include "ruby/internal/core/rbasic.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/fl_type.h" #include "ruby/internal/token_paste.h" #include "ruby/internal/value.h" #include "ruby/internal/value_type.h" #include "ruby/defines.h" #ifdef RUBY_UNTYPED_DATA_WARNING # /* Take that. */ #elif defined(RUBY_EXPORT) # define RUBY_UNTYPED_DATA_WARNING 1 #else # define RUBY_UNTYPED_DATA_WARNING 0 #endif /** @cond INTERNAL_MACRO */ #define RBIMPL_DATA_FUNC(f) RBIMPL_CAST((void (*)(void *))(f)) #define RBIMPL_ATTRSET_UNTYPED_DATA_FUNC() \ RBIMPL_ATTR_WARNING(("untyped Data is unsafe; use TypedData instead")) \ RBIMPL_ATTR_DEPRECATED(("by TypedData")) /** @endcond */ #define RDATA(obj) RBIMPL_CAST((struct RData *)(obj)) #define DATA_PTR(obj) RDATA(obj)->data #define RUBY_MACRO_SELECT RBIMPL_TOKEN_PASTE #define RUBY_DEFAULT_FREE RBIMPL_DATA_FUNC(-1) #define RUBY_NEVER_FREE RBIMPL_DATA_FUNC(0) #define RUBY_UNTYPED_DATA_FUNC(f) f RBIMPL_ATTRSET_UNTYPED_DATA_FUNC() /* #define RUBY_DATA_FUNC(func) ((void (*)(void*))(func)) */ typedef void (*RUBY_DATA_FUNC)(void*); struct RData { struct RBasic basic; RUBY_DATA_FUNC dmark; RUBY_DATA_FUNC dfree; void *data; }; RBIMPL_SYMBOL_EXPORT_BEGIN() VALUE rb_data_object_wrap(VALUE klass, void *datap, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree); VALUE rb_data_object_zalloc(VALUE klass, size_t size, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree); RUBY_EXTERN VALUE rb_cObject; RBIMPL_SYMBOL_EXPORT_END() #define Data_Wrap_Struct(klass, mark, free, sval) \ rb_data_object_wrap( \ (klass), \ (sval), \ RBIMPL_DATA_FUNC(mark), \ RBIMPL_DATA_FUNC(free)) #define Data_Make_Struct0(result, klass, type, size, mark, free, sval) \ VALUE result = rb_data_object_zalloc( \ (klass), \ (size), \ RBIMPL_DATA_FUNC(mark), \ RBIMPL_DATA_FUNC(free)); \ (sval) = RBIMPL_CAST((type *)DATA_PTR(result)); \ RBIMPL_CAST(/*suppress unused variable warnings*/(void)(sval)) #ifdef HAVE_STMT_AND_DECL_IN_EXPR #define Data_Make_Struct(klass, type, mark, free, sval) \ RB_GNUC_EXTENSION({ \ Data_Make_Struct0( \ data_struct_obj, \ klass, \ type, \ sizeof(type), \ mark, \ free, \ sval); \ data_struct_obj; \ }) #else #define Data_Make_Struct(klass, type, mark, free, sval) \ rb_data_object_make( \ (klass), \ RBIMPL_DATA_FUNC(mark), \ RBIMPL_DATA_FUNC(free), \ RBIMPL_CAST((void **)&(sval)), \ sizeof(type)) #endif #define Data_Get_Struct(obj, type, sval) \ ((sval) = RBIMPL_CAST((type*)rb_data_object_get(obj))) RBIMPL_ATTRSET_UNTYPED_DATA_FUNC() static inline VALUE rb_data_object_wrap_warning(VALUE klass, void *ptr, RUBY_DATA_FUNC mark, RUBY_DATA_FUNC free) { return rb_data_object_wrap(klass, ptr, mark, free); } static inline void * rb_data_object_get(VALUE obj) { Check_Type(obj, RUBY_T_DATA); return DATA_PTR(obj); } RBIMPL_ATTRSET_UNTYPED_DATA_FUNC() static inline void * rb_data_object_get_warning(VALUE obj) { return rb_data_object_get(obj); } #if defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P) # define rb_data_object_wrap_warning(klass, ptr, mark, free) \ RB_GNUC_EXTENSION( \ __builtin_choose_expr( \ __builtin_constant_p(klass) && !(klass), \ rb_data_object_wrap(klass, ptr, mark, free), \ (rb_data_object_wrap_warning)(klass, ptr, mark, free))) #endif static inline VALUE rb_data_object_make(VALUE klass, RUBY_DATA_FUNC mark_func, RUBY_DATA_FUNC free_func, void **datap, size_t size) { Data_Make_Struct0(result, klass, void, size, mark_func, free_func, *datap); return result; } RBIMPL_ATTR_DEPRECATED(("by: rb_data_object_wrap")) static inline VALUE rb_data_object_alloc(VALUE klass, void *data, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree) { return rb_data_object_wrap(klass, data, dmark, dfree); } RBIMPL_ATTR_DEPRECATED(("by: rb_cObject. Will be removed in 3.1.")) RBIMPL_ATTR_PURE() static inline VALUE rb_cData(void) { return rb_cObject; } #define rb_cData rb_cData() #define rb_data_object_wrap_0 rb_data_object_wrap #define rb_data_object_wrap_1 rb_data_object_wrap_warning #define rb_data_object_wrap RUBY_MACRO_SELECT(rb_data_object_wrap_, RUBY_UNTYPED_DATA_WARNING) #define rb_data_object_get_0 rb_data_object_get #define rb_data_object_get_1 rb_data_object_get_warning #define rb_data_object_get RUBY_MACRO_SELECT(rb_data_object_get_, RUBY_UNTYPED_DATA_WARNING) #define rb_data_object_make_0 rb_data_object_make #define rb_data_object_make_1 rb_data_object_make_warning #define rb_data_object_make RUBY_MACRO_SELECT(rb_data_object_make_, RUBY_UNTYPED_DATA_WARNING) #endif /* RBIMPL_RDATA_H */ PK!A12c c internal/core/robject.hnu[#ifndef RBIMPL_ROBJECT_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ROBJECT_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines struct ::RObject. */ #include "ruby/internal/config.h" #ifdef HAVE_STDINT_H # include #endif #include "ruby/internal/attr/artificial.h" #include "ruby/internal/attr/deprecated.h" #include "ruby/internal/attr/pure.h" #include "ruby/internal/cast.h" #include "ruby/internal/fl_type.h" #include "ruby/internal/value.h" #include "ruby/internal/value_type.h" #define ROBJECT(obj) RBIMPL_CAST((struct RObject *)(obj)) #define ROBJECT_EMBED_LEN_MAX ROBJECT_EMBED_LEN_MAX #define ROBJECT_EMBED ROBJECT_EMBED /** @cond INTERNAL_MACRO */ #define ROBJECT_NUMIV ROBJECT_NUMIV #define ROBJECT_IVPTR ROBJECT_IVPTR #define ROBJECT_IV_INDEX_TBL ROBJECT_IV_INDEX_TBL /** @endcond */ enum ruby_robject_flags { ROBJECT_EMBED = RUBY_FL_USER1 }; enum ruby_robject_consts { ROBJECT_EMBED_LEN_MAX = RBIMPL_EMBED_LEN_MAX_OF(VALUE) }; struct st_table; struct RObject { struct RBasic basic; union { struct { uint32_t numiv; VALUE *ivptr; struct st_table *iv_index_tbl; /* shortcut for RCLASS_IV_INDEX_TBL(rb_obj_class(obj)) */ } heap; VALUE ary[ROBJECT_EMBED_LEN_MAX]; } as; }; RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() static inline uint32_t ROBJECT_NUMIV(VALUE obj) { RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT); if (RB_FL_ANY_RAW(obj, ROBJECT_EMBED)) { return ROBJECT_EMBED_LEN_MAX; } else { return ROBJECT(obj)->as.heap.numiv; } } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() static inline VALUE * ROBJECT_IVPTR(VALUE obj) { RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT); struct RObject *const ptr = ROBJECT(obj); if (RB_FL_ANY_RAW(obj, ROBJECT_EMBED)) { return ptr->as.ary; } else { return ptr->as.heap.ivptr; } } #endif /* RBIMPL_ROBJECT_H */ PK!NU U internal/core/rbasic.hnu[#ifndef RBIMPL_RBASIC_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_RBASIC_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines struct ::RBasic. */ #include "ruby/internal/attr/artificial.h" #include "ruby/internal/attr/constexpr.h" #include "ruby/internal/attr/forceinline.h" #include "ruby/internal/attr/noalias.h" #include "ruby/internal/attr/pure.h" #include "ruby/internal/cast.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/special_consts.h" #include "ruby/internal/value.h" #include "ruby/assert.h" #define RBASIC(obj) RBIMPL_CAST((struct RBasic *)(obj)) #define RBASIC_CLASS RBASIC_CLASS #define RVALUE_EMBED_LEN_MAX RVALUE_EMBED_LEN_MAX /** @cond INTERNAL_MACRO */ #define RBIMPL_EMBED_LEN_MAX_OF(T) \ RBIMPL_CAST((int)(sizeof(VALUE[RVALUE_EMBED_LEN_MAX]) / (sizeof(T)))) /** @endcond */ enum ruby_rvalue_flags { RVALUE_EMBED_LEN_MAX = 3 }; struct RUBY_ALIGNAS(SIZEOF_VALUE) RBasic { VALUE flags; /**< @see enum ::ruby_fl_type. */ const VALUE klass; #ifdef __cplusplus public: RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_FORCEINLINE() RBIMPL_ATTR_NOALIAS() /** * We need to define this explicit constructor because the field `klass` is * const-qualified above, which effectively defines the implicit default * constructor as "deleted" (as of C++11) -- No way but to define one by * ourselves. */ RBasic() : flags(RBIMPL_VALUE_NULL), klass(RBIMPL_VALUE_NULL) { } #endif }; RBIMPL_SYMBOL_EXPORT_BEGIN() VALUE rb_obj_hide(VALUE obj); VALUE rb_obj_reveal(VALUE obj, VALUE klass); /* do not use this API to change klass information */ RBIMPL_SYMBOL_EXPORT_END() RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() static inline VALUE RBASIC_CLASS(VALUE obj) { RBIMPL_ASSERT_OR_ASSUME(! RB_SPECIAL_CONST_P(obj)); return RBASIC(obj)->klass; } #endif /* RBIMPL_RBASIC_H */ PK! o@}}internal/core/rclass.hnu[#ifndef RBIMPL_RCLASS_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_RCLASS_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Routines to manipulate struct ::RClass. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" #include "ruby/internal/cast.h" #define RMODULE_IS_OVERLAID RMODULE_IS_OVERLAID #define RMODULE_IS_REFINEMENT RMODULE_IS_REFINEMENT #define RMODULE_INCLUDED_INTO_REFINEMENT RMODULE_INCLUDED_INTO_REFINEMENT #define RCLASS(obj) RBIMPL_CAST((struct RClass *)(obj)) #define RMODULE RCLASS #define RCLASS_SUPER rb_class_get_superclass enum ruby_rmodule_flags { RMODULE_IS_OVERLAID = RUBY_FL_USER2, RMODULE_IS_REFINEMENT = RUBY_FL_USER3, RMODULE_INCLUDED_INTO_REFINEMENT = RUBY_FL_USER4 }; struct RClass; /* Opaque, declared here for RCLASS() macro. */ RBIMPL_SYMBOL_EXPORT_BEGIN() VALUE rb_class_get_superclass(VALUE); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_RCLASS_H */ PK!K K internal/core/rmatch.hnu[#ifndef RBIMPL_RMATCH_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_RMATCH_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines struct ::RMatch. */ #include "ruby/internal/attr/artificial.h" #include "ruby/internal/attr/pure.h" #include "ruby/internal/attr/returns_nonnull.h" #include "ruby/internal/cast.h" #include "ruby/internal/core/rbasic.h" #include "ruby/internal/value.h" #include "ruby/internal/value_type.h" #include "ruby/assert.h" #define RMATCH(obj) RBIMPL_CAST((struct RMatch *)(obj)) /** @cond INTERNAL_MACRO */ #define RMATCH_REGS RMATCH_REGS /** @endcond */ struct re_patter_buffer; /* a.k.a. OnigRegexType, defined in onigmo.h */ struct re_registers; /* Also in onigmo.h */ /* @shyouhei wonders: is anyone actively using this typedef ...? */ typedef struct re_pattern_buffer Regexp; struct rmatch_offset { long beg; long end; }; struct rmatch { struct re_registers regs; struct rmatch_offset *char_offset; int char_offset_num_allocated; }; struct RMatch { struct RBasic basic; VALUE str; struct rmatch *rmatch; VALUE regexp; /* RRegexp */ }; RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_RETURNS_NONNULL() RBIMPL_ATTR_ARTIFICIAL() static inline struct re_registers * RMATCH_REGS(VALUE match) { RBIMPL_ASSERT_TYPE(match, RUBY_T_MATCH); RBIMPL_ASSERT_OR_ASSUME(RMATCH(match)->rmatch != NULL); return &RMATCH(match)->rmatch->regs; } #endif /* RBIMPL_RMATCH_H */ PK!ly/wwinternal/core/rstring.hnu[#ifndef RBIMPL_RSTRING_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_RSTRING_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines struct ::RString. */ #include "ruby/internal/config.h" #include "ruby/internal/arithmetic/long.h" #include "ruby/internal/attr/artificial.h" #include "ruby/internal/attr/pure.h" #include "ruby/internal/cast.h" #include "ruby/internal/core/rbasic.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/fl_type.h" #include "ruby/internal/value_type.h" #include "ruby/internal/warning_push.h" #include "ruby/assert.h" #define RSTRING(obj) RBIMPL_CAST((struct RString *)(obj)) #define RSTRING_NOEMBED RSTRING_NOEMBED #define RSTRING_EMBED_LEN_MASK RSTRING_EMBED_LEN_MASK #define RSTRING_EMBED_LEN_SHIFT RSTRING_EMBED_LEN_SHIFT #define RSTRING_EMBED_LEN_MAX RSTRING_EMBED_LEN_MAX #define RSTRING_FSTR RSTRING_FSTR /** @cond INTERNAL_MACRO */ #define RSTRING_EMBED_LEN RSTRING_EMBED_LEN #define RSTRING_LEN RSTRING_LEN #define RSTRING_LENINT RSTRING_LENINT #define RSTRING_PTR RSTRING_PTR #define RSTRING_END RSTRING_END /** @endcond */ #define StringValue(v) rb_string_value(&(v)) #define StringValuePtr(v) rb_string_value_ptr(&(v)) #define StringValueCStr(v) rb_string_value_cstr(&(v)) #define SafeStringValue(v) StringValue(v) #define ExportStringValue(v) do { \ StringValue(v); \ (v) = rb_str_export(v); \ } while (0) enum ruby_rstring_flags { RSTRING_NOEMBED = RUBY_FL_USER1, RSTRING_EMBED_LEN_MASK = RUBY_FL_USER2 | RUBY_FL_USER3 | RUBY_FL_USER4 | RUBY_FL_USER5 | RUBY_FL_USER6, /* Actually, string encodings are also encoded into the flags, using * remaining bits.*/ RSTRING_FSTR = RUBY_FL_USER17 }; enum ruby_rstring_consts { RSTRING_EMBED_LEN_SHIFT = RUBY_FL_USHIFT + 2, RSTRING_EMBED_LEN_MAX = RBIMPL_EMBED_LEN_MAX_OF(char) - 1 }; struct RString { struct RBasic basic; union { struct { long len; char *ptr; union { long capa; VALUE shared; } aux; } heap; char ary[RSTRING_EMBED_LEN_MAX + 1]; } as; }; RBIMPL_SYMBOL_EXPORT_BEGIN() VALUE rb_str_to_str(VALUE); VALUE rb_string_value(volatile VALUE*); char *rb_string_value_ptr(volatile VALUE*); char *rb_string_value_cstr(volatile VALUE*); VALUE rb_str_export(VALUE); VALUE rb_str_export_locale(VALUE); RBIMPL_ATTR_ERROR(("rb_check_safe_str() and Check_SafeStr() are obsolete; use StringValue() instead")) void rb_check_safe_str(VALUE); #define Check_SafeStr(v) rb_check_safe_str(RBIMPL_CAST((VALUE)(v))) RBIMPL_SYMBOL_EXPORT_END() RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() static inline long RSTRING_EMBED_LEN(VALUE str) { RBIMPL_ASSERT_TYPE(str, RUBY_T_STRING); RBIMPL_ASSERT_OR_ASSUME(! RB_FL_ANY_RAW(str, RSTRING_NOEMBED)); VALUE f = RBASIC(str)->flags; f &= RSTRING_EMBED_LEN_MASK; f >>= RSTRING_EMBED_LEN_SHIFT; return RBIMPL_CAST((long)f); } RBIMPL_WARNING_PUSH() #if RBIMPL_COMPILER_IS(Intel) RBIMPL_WARNING_IGNORED(413) #endif RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() static inline struct RString rbimpl_rstring_getmem(VALUE str) { RBIMPL_ASSERT_TYPE(str, RUBY_T_STRING); if (RB_FL_ANY_RAW(str, RSTRING_NOEMBED)) { return *RSTRING(str); } else { /* Expecting compilers to optimize this on-stack struct away. */ struct RString retval; retval.as.heap.len = RSTRING_EMBED_LEN(str); retval.as.heap.ptr = RSTRING(str)->as.ary; return retval; } } RBIMPL_WARNING_POP() RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() static inline long RSTRING_LEN(VALUE str) { return rbimpl_rstring_getmem(str).as.heap.len; } RBIMPL_ATTR_ARTIFICIAL() static inline char * RSTRING_PTR(VALUE str) { char *ptr = rbimpl_rstring_getmem(str).as.heap.ptr; if (RB_UNLIKELY(! ptr)) { /* :BEWARE: @shyouhei thinks that currently, there are rooms for this * function to return NULL. In the 20th century that was a pointless * concern. However struct RString can hold fake strings nowadays. It * seems no check against NULL are exercised around handling of them * (one of such usages is located in marshal.c, which scares * @shyouhei). Better check here for maximum safety. * * Also, this is not rb_warn() because RSTRING_PTR() can be called * during GC (see what obj_info() does). rb_warn() needs to allocate * Ruby objects. That is not possible at this moment. */ fprintf(stderr, "%s\n", "RSTRING_PTR is returning NULL!! " "SIGSEGV is highly expected to follow immediately. " "If you could reproduce, attach your debugger here, " "and look at the passed string." ); } return ptr; } RBIMPL_ATTR_ARTIFICIAL() static inline char * RSTRING_END(VALUE str) { struct RString buf = rbimpl_rstring_getmem(str); if (RB_UNLIKELY(! buf.as.heap.ptr)) { /* Ditto. */ fprintf(stderr, "%s\n", "RSTRING_END is returning NULL!! " "SIGSEGV is highly expected to follow immediately. " "If you could reproduce, attach your debugger here, " "and look at the passed string." ); } return &buf.as.heap.ptr[buf.as.heap.len]; } RBIMPL_ATTR_ARTIFICIAL() static inline int RSTRING_LENINT(VALUE str) { return rb_long2int(RSTRING_LEN(str)); } #ifdef HAVE_STMT_AND_DECL_IN_EXPR # define RSTRING_GETMEM(str, ptrvar, lenvar) \ __extension__ ({ \ struct RString rbimpl_str = rbimpl_rstring_getmem(str); \ (ptrvar) = rbimpl_str.as.heap.ptr; \ (lenvar) = rbimpl_str.as.heap.len; \ }) #else # define RSTRING_GETMEM(str, ptrvar, lenvar) \ ((ptrvar) = RSTRING_PTR(str), \ (lenvar) = RSTRING_LEN(str)) #endif /* HAVE_STMT_AND_DECL_IN_EXPR */ #endif /* RBIMPL_RSTRING_H */ PK!CMp p internal/core/rhash.hnu[#ifndef RBIMPL_RHASH_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_RHASH_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Routines to manipulate struct ::RHash. * * Shyouhei really suffered agnish over placement of macros in this file. They * are half-brken. The situation (as of wriring) is: * * - #RHASH_TBL: works. * - #RHASH_ITER_LEV: compile-time error. * - #RHASH_IFNONE: compile-time error. * - #RHASH_SIZE: works. * - #RHASH_EMPTY_P: works. * - #RHASH_SET_IFNONE: works (why... given you cannot query). * * Shyouhei stopped thinking. Let them be as is. */ #include "ruby/internal/config.h" #ifdef STDC_HEADERS # include #endif #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" #if !defined RUBY_EXPORT && !defined RUBY_NO_OLD_COMPATIBILITY # include "ruby/backward.h" #endif #define RHASH_TBL(h) rb_hash_tbl(h, __FILE__, __LINE__) #define RHASH_ITER_LEV(h) rb_hash_iter_lev(h) #define RHASH_IFNONE(h) rb_hash_ifnone(h) #define RHASH_SIZE(h) rb_hash_size_num(h) #define RHASH_EMPTY_P(h) (RHASH_SIZE(h) == 0) #define RHASH_SET_IFNONE(h, ifnone) rb_hash_set_ifnone((VALUE)h, ifnone) struct st_table; /* in ruby/st.h */ RBIMPL_SYMBOL_EXPORT_BEGIN() size_t rb_hash_size_num(VALUE hash); struct st_table *rb_hash_tbl(VALUE, const char *file, int line); VALUE rb_hash_set_ifnone(VALUE hash, VALUE ifnone); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_RHASH_H */ PK!Izinternal/core/rbignum.hnu[#ifndef RBIMPL_RBIGNUM_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_RBIGNUM_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Routines to manipulate struct ::RBignum. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" #include "ruby/internal/value_type.h" #include "ruby/internal/stdbool.h" #define RBIGNUM_SIGN rb_big_sign /** @cond INTERNAL_MACRO */ #define RBIGNUM_POSITIVE_P RBIGNUM_POSITIVE_P #define RBIGNUM_NEGATIVE_P RBIGNUM_NEGATIVE_P /** @endcond */ RBIMPL_SYMBOL_EXPORT_BEGIN() int rb_big_sign(VALUE num); RBIMPL_SYMBOL_EXPORT_END() static inline bool RBIGNUM_POSITIVE_P(VALUE b) { RBIMPL_ASSERT_TYPE(b, RUBY_T_BIGNUM); return RBIGNUM_SIGN(b); } static inline bool RBIGNUM_NEGATIVE_P(VALUE b) { RBIMPL_ASSERT_TYPE(b, RUBY_T_BIGNUM); return ! RBIGNUM_POSITIVE_P(b); } #endif /* RBIMPL_RBIGNUM_H */ PK!Ԅ  internal/core/rstruct.hnu[#ifndef RBIMPL_RSTRUCT_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_RSTRUCT_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Routines to manipulate struct ::RStruct. */ #include "ruby/internal/attr/artificial.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" #include "ruby/internal/value_type.h" #include "ruby/internal/arithmetic/long.h" #include "ruby/internal/arithmetic/int.h" #if !defined RUBY_EXPORT && !defined RUBY_NO_OLD_COMPATIBILITY # include "ruby/backward.h" #endif #define RSTRUCT_PTR(st) rb_struct_ptr(st) /** @cond INTERNAL_MACRO */ #define RSTRUCT_LEN RSTRUCT_LEN #define RSTRUCT_SET RSTRUCT_SET #define RSTRUCT_GET RSTRUCT_GET /** @endcond */ RBIMPL_SYMBOL_EXPORT_BEGIN() VALUE rb_struct_size(VALUE s); VALUE rb_struct_aref(VALUE, VALUE); VALUE rb_struct_aset(VALUE, VALUE, VALUE); RBIMPL_SYMBOL_EXPORT_END() RBIMPL_ATTR_ARTIFICIAL() static inline long RSTRUCT_LEN(VALUE st) { RBIMPL_ASSERT_TYPE(st, RUBY_T_STRUCT); return RB_NUM2LONG(rb_struct_size(st)); } RBIMPL_ATTR_ARTIFICIAL() static inline VALUE RSTRUCT_SET(VALUE st, int k, VALUE v) { RBIMPL_ASSERT_TYPE(st, RUBY_T_STRUCT); return rb_struct_aset(st, INT2NUM(k), (v)); } RBIMPL_ATTR_ARTIFICIAL() static inline VALUE RSTRUCT_GET(VALUE st, int k) { RBIMPL_ASSERT_TYPE(st, RUBY_T_STRUCT); return rb_struct_aref(st, INT2NUM(k)); } #endif /* RBIMPL_RSTRUCT_H */ PK![oV. . internal/core/rregexp.hnu[#ifndef RBIMPL_RREGEXP_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_RREGEXP_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines struct ::RRegexp. */ #include "ruby/internal/attr/artificial.h" #include "ruby/internal/attr/pure.h" #include "ruby/internal/cast.h" #include "ruby/internal/core/rbasic.h" #include "ruby/internal/core/rstring.h" #include "ruby/internal/value.h" #include "ruby/internal/value_type.h" #define RREGEXP(obj) RBIMPL_CAST((struct RRegexp *)(obj)) #define RREGEXP_PTR(obj) (RREGEXP(obj)->ptr) /** @cond INTERNAL_MACRO */ #define RREGEXP_SRC RREGEXP_SRC #define RREGEXP_SRC_PTR RREGEXP_SRC_PTR #define RREGEXP_SRC_LEN RREGEXP_SRC_LEN #define RREGEXP_SRC_END RREGEXP_SRC_END /** @endcond */ struct re_patter_buffer; /* a.k.a. OnigRegexType, defined in onigmo.h */ struct RRegexp { struct RBasic basic; struct re_pattern_buffer *ptr; const VALUE src; unsigned long usecnt; }; RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() static inline VALUE RREGEXP_SRC(VALUE rexp) { RBIMPL_ASSERT_TYPE(rexp, RUBY_T_REGEXP); VALUE ret = RREGEXP(rexp)->src; RBIMPL_ASSERT_TYPE(ret, RUBY_T_STRING); return ret; } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() static inline char * RREGEXP_SRC_PTR(VALUE rexp) { return RSTRING_PTR(RREGEXP_SRC(rexp)); } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() static inline long RREGEXP_SRC_LEN(VALUE rexp) { return RSTRING_LEN(RREGEXP_SRC(rexp)); } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() static inline char * RREGEXP_SRC_END(VALUE rexp) { return RSTRING_END(RREGEXP_SRC(rexp)); } #endif /* RBIMPL_RREGEXP_H */ PK!Fʛ internal/core/rarray.hnu[#ifndef RBIMPL_RARRAY_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_RARRAY_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines struct ::RArray. */ #include "ruby/internal/arithmetic/long.h" #include "ruby/internal/attr/artificial.h" #include "ruby/internal/attr/constexpr.h" #include "ruby/internal/attr/maybe_unused.h" #include "ruby/internal/attr/pure.h" #include "ruby/internal/cast.h" #include "ruby/internal/core/rbasic.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/fl_type.h" #include "ruby/internal/rgengc.h" #include "ruby/internal/stdbool.h" #include "ruby/internal/value.h" #include "ruby/internal/value_type.h" #include "ruby/assert.h" #ifndef USE_TRANSIENT_HEAP # define USE_TRANSIENT_HEAP 1 #endif #define RARRAY(obj) RBIMPL_CAST((struct RArray *)(obj)) #define RARRAY_EMBED_FLAG RARRAY_EMBED_FLAG #define RARRAY_EMBED_LEN_MASK RARRAY_EMBED_LEN_MASK #define RARRAY_EMBED_LEN_MAX RARRAY_EMBED_LEN_MAX #define RARRAY_EMBED_LEN_SHIFT RARRAY_EMBED_LEN_SHIFT #if USE_TRANSIENT_HEAP # define RARRAY_TRANSIENT_FLAG RARRAY_TRANSIENT_FLAG #else # define RARRAY_TRANSIENT_FLAG 0 #endif #define RARRAY_LEN rb_array_len #define RARRAY_CONST_PTR rb_array_const_ptr #define RARRAY_CONST_PTR_TRANSIENT rb_array_const_ptr_transient /** @cond INTERNAL_MACRO */ #if defined(__fcc__) || defined(__fcc_version) || \ defined(__FCC__) || defined(__FCC_VERSION) /* workaround for old version of Fujitsu C Compiler (fcc) */ # define FIX_CONST_VALUE_PTR(x) ((const VALUE *)(x)) #else # define FIX_CONST_VALUE_PTR(x) (x) #endif #define RARRAY_EMBED_LEN RARRAY_EMBED_LEN #define RARRAY_LENINT RARRAY_LENINT #define RARRAY_TRANSIENT_P RARRAY_TRANSIENT_P #define RARRAY_ASET RARRAY_ASET #define RARRAY_PTR RARRAY_PTR /** @endcond */ enum ruby_rarray_flags { RARRAY_EMBED_FLAG = RUBY_FL_USER1, /* RUBY_FL_USER2 is for ELTS_SHARED */ RARRAY_EMBED_LEN_MASK = RUBY_FL_USER4 | RUBY_FL_USER3 #if USE_TRANSIENT_HEAP , RARRAY_TRANSIENT_FLAG = RUBY_FL_USER13 #endif }; enum ruby_rarray_consts { RARRAY_EMBED_LEN_SHIFT = RUBY_FL_USHIFT + 3, RARRAY_EMBED_LEN_MAX = RBIMPL_EMBED_LEN_MAX_OF(VALUE) }; struct RArray { struct RBasic basic; union { struct { long len; union { long capa; #if defined(__clang__) /* <- clang++ is sane */ || \ !defined(__cplusplus) /* <- C99 is sane */ || \ (__cplusplus > 199711L) /* <- C++11 is sane */ const #endif VALUE shared_root; } aux; const VALUE *ptr; } heap; const VALUE ary[RARRAY_EMBED_LEN_MAX]; } as; }; RBIMPL_SYMBOL_EXPORT_BEGIN() VALUE *rb_ary_ptr_use_start(VALUE ary); void rb_ary_ptr_use_end(VALUE a); #if USE_TRANSIENT_HEAP void rb_ary_detransient(VALUE a); #endif RBIMPL_SYMBOL_EXPORT_END() RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() static inline long RARRAY_EMBED_LEN(VALUE ary) { RBIMPL_ASSERT_TYPE(ary, RUBY_T_ARRAY); RBIMPL_ASSERT_OR_ASSUME(RB_FL_ANY_RAW(ary, RARRAY_EMBED_FLAG)); VALUE f = RBASIC(ary)->flags; f &= RARRAY_EMBED_LEN_MASK; f >>= RARRAY_EMBED_LEN_SHIFT; return RBIMPL_CAST((long)f); } RBIMPL_ATTR_PURE_UNLESS_DEBUG() static inline long rb_array_len(VALUE a) { RBIMPL_ASSERT_TYPE(a, RUBY_T_ARRAY); if (RB_FL_ANY_RAW(a, RARRAY_EMBED_FLAG)) { return RARRAY_EMBED_LEN(a); } else { return RARRAY(a)->as.heap.len; } } RBIMPL_ATTR_ARTIFICIAL() static inline int RARRAY_LENINT(VALUE ary) { return rb_long2int(RARRAY_LEN(ary)); } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() static inline bool RARRAY_TRANSIENT_P(VALUE ary) { RBIMPL_ASSERT_TYPE(ary, RUBY_T_ARRAY); #if USE_TRANSIENT_HEAP return RB_FL_ANY_RAW(ary, RARRAY_TRANSIENT_FLAG); #else return false; #endif } RBIMPL_ATTR_PURE_UNLESS_DEBUG() /* internal function. do not use this function */ static inline const VALUE * rb_array_const_ptr_transient(VALUE a) { RBIMPL_ASSERT_TYPE(a, RUBY_T_ARRAY); if (RB_FL_ANY_RAW(a, RARRAY_EMBED_FLAG)) { return FIX_CONST_VALUE_PTR(RARRAY(a)->as.ary); } else { return FIX_CONST_VALUE_PTR(RARRAY(a)->as.heap.ptr); } } #if ! USE_TRANSIENT_HEAP RBIMPL_ATTR_PURE_UNLESS_DEBUG() #endif /* internal function. do not use this function */ static inline const VALUE * rb_array_const_ptr(VALUE a) { RBIMPL_ASSERT_TYPE(a, RUBY_T_ARRAY); #if USE_TRANSIENT_HEAP if (RARRAY_TRANSIENT_P(a)) { rb_ary_detransient(a); } #endif return rb_array_const_ptr_transient(a); } /* internal function. do not use this function */ static inline VALUE * rb_array_ptr_use_start(VALUE a, RBIMPL_ATTR_MAYBE_UNUSED() int allow_transient) { RBIMPL_ASSERT_TYPE(a, RUBY_T_ARRAY); #if USE_TRANSIENT_HEAP if (!allow_transient) { if (RARRAY_TRANSIENT_P(a)) { rb_ary_detransient(a); } } #endif return rb_ary_ptr_use_start(a); } /* internal function. do not use this function */ static inline void rb_array_ptr_use_end(VALUE a, RBIMPL_ATTR_MAYBE_UNUSED() int allow_transient) { RBIMPL_ASSERT_TYPE(a, RUBY_T_ARRAY); rb_ary_ptr_use_end(a); } #define RBIMPL_RARRAY_STMT(flag, ary, var, expr) do { \ RBIMPL_ASSERT_TYPE((ary), RUBY_T_ARRAY); \ const VALUE rbimpl_ary = (ary); \ VALUE *var = rb_array_ptr_use_start(rbimpl_ary, (flag)); \ expr; \ rb_array_ptr_use_end(rbimpl_ary, (flag)); \ } while (0) #define RARRAY_PTR_USE_START(a) rb_array_ptr_use_start(a, 0) #define RARRAY_PTR_USE_END(a) rb_array_ptr_use_end(a, 0) #define RARRAY_PTR_USE(ary, ptr_name, expr) \ RBIMPL_RARRAY_STMT(0, ary, ptr_name, expr) #define RARRAY_PTR_USE_START_TRANSIENT(a) rb_array_ptr_use_start(a, 1) #define RARRAY_PTR_USE_END_TRANSIENT(a) rb_array_ptr_use_end(a, 1) #define RARRAY_PTR_USE_TRANSIENT(ary, ptr_name, expr) \ RBIMPL_RARRAY_STMT(1, ary, ptr_name, expr) static inline VALUE * RARRAY_PTR(VALUE ary) { RBIMPL_ASSERT_TYPE(ary, RUBY_T_ARRAY); VALUE tmp = RB_OBJ_WB_UNPROTECT_FOR(ARRAY, ary); return RBIMPL_CAST((VALUE *)RARRAY_CONST_PTR(tmp)); } static inline void RARRAY_ASET(VALUE ary, long i, VALUE v) { RARRAY_PTR_USE_TRANSIENT(ary, ptr, RB_OBJ_WRITE(ary, &ptr[i], v)); } /* * :FIXME: we want to convert RARRAY_AREF into an inline function (to add rooms * for more sanity checks). However there were situations where the address of * this macro is taken i.e. &RARRAY_AREF(...). They cannot be possible if this * is not a macro. Such usages are abuse, and we eliminated them internally. * However we are afraid of similar things to remain in the wild. This macro * remains as it is due to that. If we could warn such usages we can set a * transition path, but currently no way is found to do so. */ #define RARRAY_AREF(a, i) RARRAY_CONST_PTR_TRANSIENT(a)[i] #endif /* RBIMPL_RARRAY_H */ PK!ldžinternal/core/rtypeddata.hnu[#ifndef RBIMPL_RTYPEDDATA_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_RTYPEDDATA_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines struct ::RTypedData. */ #include "ruby/internal/config.h" #ifdef STDC_HEADERS # include #endif #include "ruby/internal/assume.h" #include "ruby/internal/attr/artificial.h" #include "ruby/internal/attr/pure.h" #include "ruby/internal/cast.h" #include "ruby/internal/core/rbasic.h" #include "ruby/internal/core/rdata.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/error.h" #include "ruby/internal/fl_type.h" #include "ruby/internal/stdbool.h" #include "ruby/internal/value_type.h" #define HAVE_TYPE_RB_DATA_TYPE_T 1 #define HAVE_RB_DATA_TYPE_T_FUNCTION 1 #define HAVE_RB_DATA_TYPE_T_PARENT 1 #define RUBY_TYPED_DEFAULT_FREE RUBY_DEFAULT_FREE #define RUBY_TYPED_NEVER_FREE RUBY_NEVER_FREE #define RTYPEDDATA(obj) RBIMPL_CAST((struct RTypedData *)(obj)) #define RTYPEDDATA_DATA(v) (RTYPEDDATA(v)->data) #define Check_TypedStruct(v, t) \ rb_check_typeddata(RBIMPL_CAST((VALUE)(v)), (t)) /** @cond INTERNAL_MACRO */ #define RTYPEDDATA_P RTYPEDDATA_P #define RTYPEDDATA_TYPE RTYPEDDATA_TYPE #define RUBY_TYPED_FREE_IMMEDIATELY RUBY_TYPED_FREE_IMMEDIATELY #define RUBY_TYPED_FROZEN_SHAREABLE RUBY_TYPED_FROZEN_SHAREABLE #define RUBY_TYPED_WB_PROTECTED RUBY_TYPED_WB_PROTECTED #define RUBY_TYPED_PROMOTED1 RUBY_TYPED_PROMOTED1 /** @endcond */ /* bits for rb_data_type_struct::flags */ enum rbimpl_typeddata_flags { RUBY_TYPED_FREE_IMMEDIATELY = 1, RUBY_TYPED_FROZEN_SHAREABLE = RUBY_FL_SHAREABLE, RUBY_TYPED_WB_PROTECTED = RUBY_FL_WB_PROTECTED, /* THIS FLAG DEPENDS ON Ruby version */ RUBY_TYPED_PROMOTED1 = RUBY_FL_PROMOTED1 /* THIS FLAG DEPENDS ON Ruby version */ }; typedef struct rb_data_type_struct rb_data_type_t; struct rb_data_type_struct { const char *wrap_struct_name; struct { RUBY_DATA_FUNC dmark; RUBY_DATA_FUNC dfree; size_t (*dsize)(const void *); RUBY_DATA_FUNC dcompact; void *reserved[1]; /* For future extension. This array *must* be filled with ZERO. */ } function; const rb_data_type_t *parent; void *data; /* This area can be used for any purpose by a programmer who define the type. */ VALUE flags; /* RUBY_FL_WB_PROTECTED */ }; struct RTypedData { struct RBasic basic; const rb_data_type_t *type; VALUE typed_flag; /* 1 or not */ void *data; }; RBIMPL_SYMBOL_EXPORT_BEGIN() VALUE rb_data_typed_object_wrap(VALUE klass, void *datap, const rb_data_type_t *); VALUE rb_data_typed_object_zalloc(VALUE klass, size_t size, const rb_data_type_t *type); int rb_typeddata_inherited_p(const rb_data_type_t *child, const rb_data_type_t *parent); int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type); void *rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type); RBIMPL_SYMBOL_EXPORT_END() #define TypedData_Wrap_Struct(klass,data_type,sval)\ rb_data_typed_object_wrap((klass),(sval),(data_type)) #define TypedData_Make_Struct0(result, klass, type, size, data_type, sval) \ VALUE result = rb_data_typed_object_zalloc(klass, size, data_type); \ (sval) = RBIMPL_CAST((type *)RTYPEDDATA_DATA(result)); \ RBIMPL_CAST(/*suppress unused variable warnings*/(void)(sval)) #ifdef HAVE_STMT_AND_DECL_IN_EXPR #define TypedData_Make_Struct(klass, type, data_type, sval) \ RB_GNUC_EXTENSION({ \ TypedData_Make_Struct0( \ data_struct_obj, \ klass, \ type, \ sizeof(type), \ data_type, \ sval); \ data_struct_obj; \ }) #else #define TypedData_Make_Struct(klass, type, data_type, sval) \ rb_data_typed_object_make( \ (klass), \ (data_type), \ RBIMPL_CAST((void **)&(sval)), \ sizeof(type)) #endif #define TypedData_Get_Struct(obj,type,data_type,sval) \ ((sval) = RBIMPL_CAST((type *)rb_check_typeddata((obj), (data_type)))) RBIMPL_ATTR_PURE() RBIMPL_ATTR_ARTIFICIAL() static inline bool rbimpl_rtypeddata_p(VALUE obj) { return RTYPEDDATA(obj)->typed_flag == 1; } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() static inline bool RTYPEDDATA_P(VALUE obj) { #if RUBY_DEBUG if (RB_UNLIKELY(! RB_TYPE_P(obj, RUBY_T_DATA))) { Check_Type(obj, RUBY_T_DATA); RBIMPL_UNREACHABLE_RETURN(false); } #endif return rbimpl_rtypeddata_p(obj); } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() /* :TODO: can this function be __attribute__((returns_nonnull)) or not? */ static inline const struct rb_data_type_struct * RTYPEDDATA_TYPE(VALUE obj) { #if RUBY_DEBUG if (RB_UNLIKELY(! RTYPEDDATA_P(obj))) { rb_unexpected_type(obj, RUBY_T_DATA); RBIMPL_UNREACHABLE_RETURN(NULL); } #endif return RTYPEDDATA(obj)->type; } static inline VALUE rb_data_typed_object_make(VALUE klass, const rb_data_type_t *type, void **datap, size_t size) { TypedData_Make_Struct0(result, klass, void, size, type, *datap); return result; } RBIMPL_ATTR_DEPRECATED(("by: rb_data_typed_object_wrap")) static inline VALUE rb_data_typed_object_alloc(VALUE klass, void *datap, const rb_data_type_t *type) { return rb_data_typed_object_wrap(klass, datap, type); } #endif /* RBIMPL_RTYPEDDATA_H */ PK! internal/core/rfile.hnu[#ifndef RBIMPL_RFILE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_RFILE_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines struct ::RFile. */ #include "ruby/internal/core/rbasic.h" #include "ruby/internal/cast.h" /* rb_io_t is in ruby/io.h. The header file has historically not been included * into ruby/ruby.h. We follow that tradition. */ struct rb_io_t; struct RFile { struct RBasic basic; struct rb_io_t *fptr; }; #define RFILE(obj) RBIMPL_CAST((struct RFile *)(obj)) #endif /* RBIMPL_RFILE_H */ PK!|internal/symbol.hnu[#ifndef RBIMPL_SYMBOL_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_SYMBOL_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #rb_intern */ #include "ruby/internal/config.h" #ifdef HAVE_STDDEF_H # include #endif #ifdef HAVE_STRING_H # include #endif #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/attr/pure.h" #include "ruby/internal/attr/noalias.h" #include "ruby/internal/cast.h" #include "ruby/internal/constant_p.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/has/builtin.h" #include "ruby/internal/value.h" #define RB_ID2SYM rb_id2sym #define RB_SYM2ID rb_sym2id #define ID2SYM RB_ID2SYM #define SYM2ID RB_SYM2ID #define CONST_ID_CACHE RUBY_CONST_ID_CACHE #define CONST_ID RUBY_CONST_ID /** @cond INTERNAL_MACRO */ #define rb_intern_const rb_intern_const /** @endcond */ RBIMPL_SYMBOL_EXPORT_BEGIN() ID rb_sym2id(VALUE); VALUE rb_id2sym(ID); ID rb_intern(const char*); ID rb_intern2(const char*, long); ID rb_intern_str(VALUE str); const char *rb_id2name(ID); ID rb_check_id(volatile VALUE *); ID rb_to_id(VALUE); VALUE rb_id2str(ID); VALUE rb_sym2str(VALUE); VALUE rb_to_symbol(VALUE name); VALUE rb_check_symbol(volatile VALUE *namep); RBIMPL_SYMBOL_EXPORT_END() RBIMPL_ATTR_PURE() RBIMPL_ATTR_NONNULL(()) static inline ID rb_intern_const(const char *str) { size_t len = strlen(str); return rb_intern2(str, RBIMPL_CAST((long)len)); } RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL(()) static inline ID rbimpl_intern_const(ID *ptr, const char *str) { while (! *ptr) { *ptr = rb_intern_const(str); } return *ptr; } /* Does anyone use it? Preserved for backward compat. */ #define RUBY_CONST_ID_CACHE(result, str) \ { \ static ID rb_intern_id_cache; \ rbimpl_intern_const(&rb_intern_id_cache, (str)); \ result rb_intern_id_cache; \ } #define RUBY_CONST_ID(var, str) \ do { \ static ID rbimpl_id; \ (var) = rbimpl_intern_const(&rbimpl_id, (str)); \ } while (0) #if defined(HAVE_STMT_AND_DECL_IN_EXPR) /* __builtin_constant_p and statement expression is available * since gcc-2.7.2.3 at least. */ #define rb_intern(str) \ (RBIMPL_CONSTANT_P(str) ? \ __extension__ ({ \ static ID rbimpl_id; \ rbimpl_intern_const(&rbimpl_id, (str)); \ }) : \ (rb_intern)(str)) #endif #endif /* RBIMPL_SYMBOL_H */ PK!EI  internal/assume.hnu[#ifndef RBIMPL_ASSUME_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ASSUME_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ASSUME / #RBIMPL_UNREACHABLE. * * These macros must be defined at once because: * * - #RBIMPL_ASSUME could fallback to #RBIMPL_UNREACHABLE. * - #RBIMPL_UNREACHABLE could fallback to #RBIMPL_ASSUME. */ #include "ruby/internal/config.h" #include "ruby/internal/cast.h" #include "ruby/internal/compiler_since.h" #include "ruby/internal/has/builtin.h" #include "ruby/internal/warning_push.h" /** @cond INTERNAL_MACRO */ #if RBIMPL_COMPILER_SINCE(MSVC, 13, 10, 0) # define RBIMPL_HAVE___ASSUME #elif RBIMPL_COMPILER_SINCE(Intel, 13, 0, 0) # define RBIMPL_HAVE___ASSUME #endif /** @endcond */ /** Wraps (or simulates) `__builtin_unreachable`. */ #if RBIMPL_HAS_BUILTIN(__builtin_unreachable) # define RBIMPL_UNREACHABLE_RETURN(_) __builtin_unreachable() #elif defined(RBIMPL_HAVE___ASSUME) # define RBIMPL_UNREACHABLE_RETURN(_) return (__assume(0), (_)) #else # define RBIMPL_UNREACHABLE_RETURN(_) return (_) #endif /** Wraps (or simulates) `__builtin_unreachable`. */ #if RBIMPL_HAS_BUILTIN(__builtin_unreachable) # define RBIMPL_UNREACHABLE __builtin_unreachable #elif defined(RBIMPL_HAVE___ASSUME) # define RBIMPL_UNREACHABLE() __assume(0) #endif /** Wraps (or simulates) `__assume`. */ #if RBIMPL_COMPILER_SINCE(Intel, 13, 0, 0) # /* icc warnings are false positives. Ignore them. */ # /* "warning #2261: __assume expression with side effects discarded" */ # define RBIMPL_ASSUME(expr) \ RBIMPL_WARNING_PUSH() \ RBIMPL_WARNING_IGNORED(2261) \ __assume(expr) \ RBIMPL_WARNING_POP() #elif defined(RBIMPL_HAVE___ASSUME) # define RBIMPL_ASSUME __assume #elif RBIMPL_HAS_BUILTIN(__builtin_assume) # define RBIMPL_ASSUME __builtin_assume #elif ! defined(RBIMPL_UNREACHABLE) # define RBIMPL_ASSUME(_) RBIMPL_CAST((void)(_)) #else # define RBIMPL_ASSUME(_) \ (RB_LIKELY(!!(_)) ? RBIMPL_CAST((void)0) : RBIMPL_UNREACHABLE()) #endif #if ! defined(RBIMPL_UNREACHABLE) # define RBIMPL_UNREACHABLE() RBIMPL_ASSUME(0) #endif #endif /* RBIMPL_ASSUME_H */ PK!k n* * internal/interpreter.hnu[#ifndef RBIMPL_INTERPRETER_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERPRETER_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Interpreter embedding APIs. */ #include "ruby/internal/attr/noreturn.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /** * @defgroup embed CRuby Embedding APIs * CRuby interpreter APIs. These are APIs to embed MRI interpreter into your * program. * These functions are not a part of Ruby extension library API. * Extension libraries of Ruby should not depend on these functions. * @{ */ /** @defgroup ruby1 ruby(1) implementation * A part of the implementation of ruby(1) command. * Other programs that embed Ruby interpreter do not always need to use these * functions. * @{ */ void ruby_sysinit(int *argc, char ***argv); void ruby_init(void); void* ruby_options(int argc, char** argv); int ruby_executable_node(void *n, int *status); int ruby_run_node(void *n); /* version.c */ void ruby_show_version(void); #ifndef ruby_show_copyright void ruby_show_copyright(void); #endif /*! A convenience macro to call ruby_init_stack(). Must be placed just after * variable declarations */ #define RUBY_INIT_STACK \ VALUE variable_in_this_stack_frame; \ ruby_init_stack(&variable_in_this_stack_frame); /*! @} */ void ruby_init_stack(volatile VALUE*); int ruby_setup(void); int ruby_cleanup(volatile int); void ruby_finalize(void); RBIMPL_ATTR_NORETURN() void ruby_stop(int); int ruby_stack_check(void); size_t ruby_stack_length(VALUE**); int ruby_exec_node(void *n); void ruby_script(const char* name); void ruby_set_script_name(VALUE name); void ruby_prog_init(void); void ruby_set_argv(int, char**); void *ruby_process_options(int, char**); void ruby_init_loadpath(void); void ruby_incpush(const char*); void ruby_sig_finalize(void); /*! @} */ RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERPRETER_H */ PK![N,""internal/memory.hnu[#ifndef RBIMPL_MEMORY_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_MEMORY_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Memory management stuff. */ #include "ruby/internal/config.h" #ifdef STDC_HEADERS # include #endif #ifdef HAVE_STRING_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_ALLOCA_H # include #endif #if defined(_MSC_VER) && defined(_WIN64) # include # pragma intrinsic(_umul128) #endif #include "ruby/internal/attr/alloc_size.h" #include "ruby/internal/attr/const.h" #include "ruby/internal/attr/constexpr.h" #include "ruby/internal/attr/noalias.h" #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/attr/noreturn.h" #include "ruby/internal/attr/restrict.h" #include "ruby/internal/attr/returns_nonnull.h" #include "ruby/internal/cast.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/has/builtin.h" #include "ruby/internal/stdalign.h" #include "ruby/internal/stdbool.h" #include "ruby/internal/xmalloc.h" #include "ruby/backward/2/limits.h" #include "ruby/backward/2/long_long.h" #include "ruby/backward/2/assume.h" #include "ruby/defines.h" /* Make alloca work the best possible way. */ #if defined(alloca) # /* Take that. */ #elif RBIMPL_HAS_BUILTIN(__builtin_alloca) # define alloca __builtin_alloca #elif defined(_AIX) # pragma alloca #elif defined(__cplusplus) extern "C" void *alloca(size_t); #else extern void *alloca(); #endif #if defined(HAVE_INT128_T) && SIZEOF_SIZE_T <= 8 # define DSIZE_T uint128_t #elif SIZEOF_SIZE_T * 2 <= SIZEOF_LONG_LONG # define DSIZE_T unsigned LONG_LONG #endif #ifdef C_ALLOCA # define RUBY_ALLOCV_LIMIT 0 #else # define RUBY_ALLOCV_LIMIT 1024 #endif #ifdef __GNUC__ #define RB_GC_GUARD(v) \ (*__extension__ ({ \ volatile VALUE *rb_gc_guarded_ptr = &(v); \ __asm__("" : : "m"(rb_gc_guarded_ptr)); \ rb_gc_guarded_ptr; \ })) #elif defined _MSC_VER #define RB_GC_GUARD(v) (*rb_gc_guarded_ptr(&(v))) #else #define HAVE_RB_GC_GUARDED_PTR_VAL 1 #define RB_GC_GUARD(v) (*rb_gc_guarded_ptr_val(&(v),(v))) #endif /* Casts needed because void* is NOT compaible with others in C++. */ #define RB_ALLOC_N(type,n) RBIMPL_CAST((type *)ruby_xmalloc2((n), sizeof(type))) #define RB_ALLOC(type) RBIMPL_CAST((type *)ruby_xmalloc(sizeof(type))) #define RB_ZALLOC_N(type,n) RBIMPL_CAST((type *)ruby_xcalloc((n), sizeof(type))) #define RB_ZALLOC(type) (RB_ZALLOC_N(type, 1)) #define RB_REALLOC_N(var,type,n) \ ((var) = RBIMPL_CAST((type *)ruby_xrealloc2((void *)(var), (n), sizeof(type)))) #define ALLOCA_N(type,n) \ RBIMPL_CAST((type *)(!(n) ? NULL : alloca(rbimpl_size_mul_or_raise(sizeof(type), (n))))) /* allocates _n_ bytes temporary buffer and stores VALUE including it * in _v_. _n_ may be evaluated twice. */ #define RB_ALLOCV(v, n) \ ((n) < RUBY_ALLOCV_LIMIT ? \ ((v) = 0, !(n) ? NULL : alloca(n)) : \ rb_alloc_tmp_buffer(&(v), (n))) #define RB_ALLOCV_N(type, v, n) \ RBIMPL_CAST((type *) \ (((size_t)(n) < RUBY_ALLOCV_LIMIT / sizeof(type)) ? \ ((v) = 0, !(n) ? NULL : alloca((n) * sizeof(type))) : \ rb_alloc_tmp_buffer2(&(v), (n), sizeof(type)))) #define RB_ALLOCV_END(v) rb_free_tmp_buffer(&(v)) #define MEMZERO(p,type,n) memset((p), 0, rbimpl_size_mul_or_raise(sizeof(type), (n))) #define MEMCPY(p1,p2,type,n) memcpy((p1), (p2), rbimpl_size_mul_or_raise(sizeof(type), (n))) #define MEMMOVE(p1,p2,type,n) memmove((p1), (p2), rbimpl_size_mul_or_raise(sizeof(type), (n))) #define MEMCMP(p1,p2,type,n) memcmp((p1), (p2), rbimpl_size_mul_or_raise(sizeof(type), (n))) #define ALLOC_N RB_ALLOC_N #define ALLOC RB_ALLOC #define ZALLOC_N RB_ZALLOC_N #define ZALLOC RB_ZALLOC #define REALLOC_N RB_REALLOC_N #define ALLOCV RB_ALLOCV #define ALLOCV_N RB_ALLOCV_N #define ALLOCV_END RB_ALLOCV_END /* Expecting this struct to be eliminated by function inlinings */ struct rbimpl_size_mul_overflow_tag { bool left; size_t right; }; RBIMPL_SYMBOL_EXPORT_BEGIN() RBIMPL_ATTR_RESTRICT() RBIMPL_ATTR_RETURNS_NONNULL() RBIMPL_ATTR_ALLOC_SIZE((2)) void *rb_alloc_tmp_buffer(volatile VALUE *store, long len); RBIMPL_ATTR_RESTRICT() RBIMPL_ATTR_RETURNS_NONNULL() RBIMPL_ATTR_ALLOC_SIZE((2,3)) void *rb_alloc_tmp_buffer_with_count(volatile VALUE *store, size_t len,size_t count); void rb_free_tmp_buffer(volatile VALUE *store); RBIMPL_ATTR_NORETURN() void ruby_malloc_size_overflow(size_t, size_t); #ifdef HAVE_RB_GC_GUARDED_PTR_VAL volatile VALUE *rb_gc_guarded_ptr_val(volatile VALUE *ptr, VALUE val); #endif RBIMPL_SYMBOL_EXPORT_END() #ifdef _MSC_VER # pragma optimize("", off) static inline volatile VALUE * rb_gc_guarded_ptr(volatile VALUE *ptr) { return ptr; } # pragma optimize("", on) #endif /* Does anyone use it? Just here for backwards compatibility. */ static inline int rb_mul_size_overflow(size_t a, size_t b, size_t max, size_t *c) { #ifdef DSIZE_T RB_GNUC_EXTENSION DSIZE_T da, db, c2; da = a; db = b; c2 = da * db; if (c2 > max) return 1; *c = RBIMPL_CAST((size_t)c2); #else if (b != 0 && a > max / b) return 1; *c = a * b; #endif return 0; } #if RBIMPL_COMPILER_SINCE(GCC, 7, 0, 0) RBIMPL_ATTR_CONSTEXPR(CXX14) /* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70507 */ #elif RBIMPL_COMPILER_SINCE(Clang, 7, 0, 0) RBIMPL_ATTR_CONSTEXPR(CXX14) /* https://bugs.llvm.org/show_bug.cgi?id=37633 */ #endif RBIMPL_ATTR_CONST() static inline struct rbimpl_size_mul_overflow_tag rbimpl_size_mul_overflow(size_t x, size_t y) { struct rbimpl_size_mul_overflow_tag ret = { false, 0, }; #if RBIMPL_HAS_BUILTIN(__builtin_mul_overflow) ret.left = __builtin_mul_overflow(x, y, &ret.right); #elif defined(DSIZE_T) RB_GNUC_EXTENSION DSIZE_T dx = x; RB_GNUC_EXTENSION DSIZE_T dy = y; RB_GNUC_EXTENSION DSIZE_T dz = dx * dy; ret.left = dz > SIZE_MAX; ret.right = RBIMPL_CAST((size_t)dz); #elif defined(_MSC_VER) && defined(_WIN64) unsigned __int64 dp = 0; unsigned __int64 dz = _umul128(x, y, &dp); ret.left = RBIMPL_CAST((bool)dp); ret.right = RBIMPL_CAST((size_t)dz); #else /* https://wiki.sei.cmu.edu/confluence/display/c/INT30-C.+Ensure+that+unsigned+integer+operations+do+not+wrap */ ret.left = (y != 0) && (x > SIZE_MAX / y); ret.right = x * y; #endif return ret; } static inline size_t rbimpl_size_mul_or_raise(size_t x, size_t y) { struct rbimpl_size_mul_overflow_tag size = rbimpl_size_mul_overflow(x, y); if (RB_LIKELY(! size.left)) { return size.right; } else { ruby_malloc_size_overflow(x, y); RBIMPL_UNREACHABLE_RETURN(0); } } static inline void * rb_alloc_tmp_buffer2(volatile VALUE *store, long count, size_t elsize) { const size_t total_size = rbimpl_size_mul_or_raise(count, elsize); const size_t cnt = (total_size + sizeof(VALUE) - 1) / sizeof(VALUE); return rb_alloc_tmp_buffer_with_count(store, total_size, cnt); } #ifndef __MINGW32__ RBIMPL_SYMBOL_EXPORT_BEGIN() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) RBIMPL_ATTR_RETURNS_NONNULL() /* At least since 2004, glibc's annotates memcpy to be * __attribute__((__nonnull__(1, 2))). However it is safe to pass NULL to the * source pointer, if n is 0. Let's wrap memcpy. */ static inline void * ruby_nonempty_memcpy(void *dest, const void *src, size_t n) { if (n) { return memcpy(dest, src, n); } else { return dest; } } RBIMPL_SYMBOL_EXPORT_END() #undef memcpy #define memcpy ruby_nonempty_memcpy #endif #endif /* RBIMPL_MEMORY_H */ PK!}P P internal/cast.hnu[#ifndef RBIMPL_CAST_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_CAST_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines RBIMPL_CAST. * @cond INTERNAL_MACRO * * This casting macro makes sense only inside of other macros that are part of * public headers. They could be used from C++, and C-style casts could issue * warnings. Ruby internals are pure C so they should not bother. */ #include "ruby/internal/compiler_since.h" #include "ruby/internal/has/warning.h" #include "ruby/internal/warning_push.h" #if ! defined(__cplusplus) # define RBIMPL_CAST(expr) (expr) #elif RBIMPL_COMPILER_SINCE(GCC, 4, 6, 0) # /* g++ has -Wold-style-cast since 1997 or so, but its _Pragma is broken. */ # /* See https://gcc.godbolt.org/z/XWhU6J */ # define RBIMPL_CAST(expr) (expr) # pragma GCC diagnostic ignored "-Wold-style-cast" #elif RBIMPL_HAS_WARNING("-Wold-style-cast") # define RBIMPL_CAST(expr) \ RBIMPL_WARNING_PUSH() \ RBIMPL_WARNING_IGNORED(-Wold-style-cast) \ (expr) \ RBIMPL_WARNING_POP() #else # define RBIMPL_CAST(expr) (expr) #endif /** @endcond */ #endif /* RBIMPL_CAST_H */ PK!@>'5'5internal/fl_type.hnu[#ifndef RBIMPL_FL_TYPE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_FL_TYPE_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines enum ::ruby_fl_type. */ #include "ruby/internal/config.h" /* for ENUM_OVER_INT */ #include "ruby/internal/attr/artificial.h" #include "ruby/internal/attr/flag_enum.h" #include "ruby/internal/attr/forceinline.h" #include "ruby/internal/attr/noalias.h" #include "ruby/internal/attr/pure.h" #include "ruby/internal/cast.h" #include "ruby/internal/core/rbasic.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/special_consts.h" #include "ruby/internal/stdbool.h" #include "ruby/internal/value.h" #include "ruby/internal/value_type.h" #include "ruby/assert.h" #include "ruby/defines.h" /** @cond INTERNAL_MACRO */ #ifdef ENUM_OVER_INT # define RBIMPL_WIDER_ENUM 1 #elif SIZEOF_INT * CHAR_BIT > 12+19+1 # define RBIMPL_WIDER_ENUM 1 #else # define RBIMPL_WIDER_ENUM 0 #endif /** @endcond */ #define FL_SINGLETON RBIMPL_CAST((VALUE)RUBY_FL_SINGLETON) #define FL_WB_PROTECTED RBIMPL_CAST((VALUE)RUBY_FL_WB_PROTECTED) #define FL_PROMOTED0 RBIMPL_CAST((VALUE)RUBY_FL_PROMOTED0) #define FL_PROMOTED1 RBIMPL_CAST((VALUE)RUBY_FL_PROMOTED1) #define FL_FINALIZE RBIMPL_CAST((VALUE)RUBY_FL_FINALIZE) #define FL_TAINT RBIMPL_CAST((VALUE)RUBY_FL_TAINT) #define FL_SHAREABLE RBIMPL_CAST((VALUE)RUBY_FL_SHAREABLE) #define FL_UNTRUSTED RBIMPL_CAST((VALUE)RUBY_FL_UNTRUSTED) #define FL_SEEN_OBJ_ID RBIMPL_CAST((VALUE)RUBY_FL_SEEN_OBJ_ID) #define FL_EXIVAR RBIMPL_CAST((VALUE)RUBY_FL_EXIVAR) #define FL_FREEZE RBIMPL_CAST((VALUE)RUBY_FL_FREEZE) #define FL_USHIFT RBIMPL_CAST((VALUE)RUBY_FL_USHIFT) #define FL_USER0 RBIMPL_CAST((VALUE)RUBY_FL_USER0) #define FL_USER1 RBIMPL_CAST((VALUE)RUBY_FL_USER1) #define FL_USER2 RBIMPL_CAST((VALUE)RUBY_FL_USER2) #define FL_USER3 RBIMPL_CAST((VALUE)RUBY_FL_USER3) #define FL_USER4 RBIMPL_CAST((VALUE)RUBY_FL_USER4) #define FL_USER5 RBIMPL_CAST((VALUE)RUBY_FL_USER5) #define FL_USER6 RBIMPL_CAST((VALUE)RUBY_FL_USER6) #define FL_USER7 RBIMPL_CAST((VALUE)RUBY_FL_USER7) #define FL_USER8 RBIMPL_CAST((VALUE)RUBY_FL_USER8) #define FL_USER9 RBIMPL_CAST((VALUE)RUBY_FL_USER9) #define FL_USER10 RBIMPL_CAST((VALUE)RUBY_FL_USER10) #define FL_USER11 RBIMPL_CAST((VALUE)RUBY_FL_USER11) #define FL_USER12 RBIMPL_CAST((VALUE)RUBY_FL_USER12) #define FL_USER13 RBIMPL_CAST((VALUE)RUBY_FL_USER13) #define FL_USER14 RBIMPL_CAST((VALUE)RUBY_FL_USER14) #define FL_USER15 RBIMPL_CAST((VALUE)RUBY_FL_USER15) #define FL_USER16 RBIMPL_CAST((VALUE)RUBY_FL_USER16) #define FL_USER17 RBIMPL_CAST((VALUE)RUBY_FL_USER17) #define FL_USER18 RBIMPL_CAST((VALUE)RUBY_FL_USER18) #define FL_USER19 RBIMPL_CAST((VALUE)(unsigned int)RUBY_FL_USER19) #define ELTS_SHARED RUBY_ELTS_SHARED #define RUBY_ELTS_SHARED RUBY_ELTS_SHARED #define RB_OBJ_FREEZE rb_obj_freeze_inline /** @cond INTERNAL_MACRO */ #define RB_FL_ABLE RB_FL_ABLE #define RB_FL_ALL RB_FL_ALL #define RB_FL_ALL_RAW RB_FL_ALL_RAW #define RB_FL_ANY RB_FL_ANY #define RB_FL_ANY_RAW RB_FL_ANY_RAW #define RB_FL_REVERSE RB_FL_REVERSE #define RB_FL_REVERSE_RAW RB_FL_REVERSE_RAW #define RB_FL_SET RB_FL_SET #define RB_FL_SET_RAW RB_FL_SET_RAW #define RB_FL_TEST RB_FL_TEST #define RB_FL_TEST_RAW RB_FL_TEST_RAW #define RB_FL_UNSET RB_FL_UNSET #define RB_FL_UNSET_RAW RB_FL_UNSET_RAW #define RB_OBJ_FREEZE_RAW RB_OBJ_FREEZE_RAW #define RB_OBJ_FROZEN RB_OBJ_FROZEN #define RB_OBJ_FROZEN_RAW RB_OBJ_FROZEN_RAW #define RB_OBJ_INFECT RB_OBJ_INFECT #define RB_OBJ_INFECT_RAW RB_OBJ_INFECT_RAW #define RB_OBJ_TAINT RB_OBJ_TAINT #define RB_OBJ_TAINTABLE RB_OBJ_TAINTABLE #define RB_OBJ_TAINTED RB_OBJ_TAINTED #define RB_OBJ_TAINTED_RAW RB_OBJ_TAINTED_RAW #define RB_OBJ_TAINT_RAW RB_OBJ_TAINT_RAW #define RB_OBJ_UNTRUST RB_OBJ_UNTRUST #define RB_OBJ_UNTRUSTED RB_OBJ_UNTRUSTED /** @endcond */ /** * @defgroup deprecated_macros deprecated macro APIs * @{ * These macros are deprecated. Prefer their `RB_`-prefixed versions. */ #define FL_ABLE RB_FL_ABLE #define FL_ALL RB_FL_ALL #define FL_ALL_RAW RB_FL_ALL_RAW #define FL_ANY RB_FL_ANY #define FL_ANY_RAW RB_FL_ANY_RAW #define FL_REVERSE RB_FL_REVERSE #define FL_REVERSE_RAW RB_FL_REVERSE_RAW #define FL_SET RB_FL_SET #define FL_SET_RAW RB_FL_SET_RAW #define FL_TEST RB_FL_TEST #define FL_TEST_RAW RB_FL_TEST_RAW #define FL_UNSET RB_FL_UNSET #define FL_UNSET_RAW RB_FL_UNSET_RAW #define OBJ_FREEZE RB_OBJ_FREEZE #define OBJ_FREEZE_RAW RB_OBJ_FREEZE_RAW #define OBJ_FROZEN RB_OBJ_FROZEN #define OBJ_FROZEN_RAW RB_OBJ_FROZEN_RAW #define OBJ_INFECT RB_OBJ_INFECT #define OBJ_INFECT_RAW RB_OBJ_INFECT_RAW #define OBJ_TAINT RB_OBJ_TAINT #define OBJ_TAINTABLE RB_OBJ_TAINTABLE #define OBJ_TAINTED RB_OBJ_TAINTED #define OBJ_TAINTED_RAW RB_OBJ_TAINTED_RAW #define OBJ_TAINT_RAW RB_OBJ_TAINT_RAW #define OBJ_UNTRUST RB_OBJ_UNTRUST #define OBJ_UNTRUSTED RB_OBJ_UNTRUSTED /** @} */ /* This is an enum because GDB wants it (rather than a macro) */ enum ruby_fl_ushift { RUBY_FL_USHIFT = 12 }; /* > The expression that defines the value of an enumeration constant shall be * > an integer constant expression that has a value representable as an `int`. * * -- ISO/IEC 9899:2018 section 6.7.2.2 * * So ENUM_OVER_INT situation is an extension to the standard. Note however * that we do not support 16 bit `int` environment. */ RB_GNUC_EXTENSION enum RBIMPL_ATTR_FLAG_ENUM() ruby_fl_type { RUBY_FL_WB_PROTECTED = (1<<5), RUBY_FL_PROMOTED0 = (1<<5), RUBY_FL_PROMOTED1 = (1<<6), RUBY_FL_PROMOTED = RUBY_FL_PROMOTED0 | RUBY_FL_PROMOTED1, RUBY_FL_FINALIZE = (1<<7), RUBY_FL_TAINT = (1<<8), RUBY_FL_SHAREABLE = (1<<8), RUBY_FL_UNTRUSTED = RUBY_FL_TAINT, RUBY_FL_SEEN_OBJ_ID = (1<<9), RUBY_FL_EXIVAR = (1<<10), RUBY_FL_FREEZE = (1<<11), #define RBIMPL_FL_USER_N(n) RUBY_FL_USER##n = (1<<(RUBY_FL_USHIFT+n)) RBIMPL_FL_USER_N(0), RBIMPL_FL_USER_N(1), RBIMPL_FL_USER_N(2), RBIMPL_FL_USER_N(3), RBIMPL_FL_USER_N(4), RBIMPL_FL_USER_N(5), RBIMPL_FL_USER_N(6), RBIMPL_FL_USER_N(7), RBIMPL_FL_USER_N(8), RBIMPL_FL_USER_N(9), RBIMPL_FL_USER_N(10), RBIMPL_FL_USER_N(11), RBIMPL_FL_USER_N(12), RBIMPL_FL_USER_N(13), RBIMPL_FL_USER_N(14), RBIMPL_FL_USER_N(15), RBIMPL_FL_USER_N(16), RBIMPL_FL_USER_N(17), RBIMPL_FL_USER_N(18), #if ENUM_OVER_INT RBIMPL_FL_USER_N(19), #else # define RUBY_FL_USER19 (RBIMPL_VALUE_ONE<<(RUBY_FL_USHIFT+19)) #endif #undef RBIMPL_FL_USER_N #undef RBIMPL_WIDER_ENUM RUBY_ELTS_SHARED = RUBY_FL_USER2, RUBY_FL_SINGLETON = RUBY_FL_USER0, }; enum { RUBY_FL_DUPPED = RUBY_T_MASK | RUBY_FL_EXIVAR | RUBY_FL_TAINT }; RBIMPL_SYMBOL_EXPORT_BEGIN() void rb_obj_infect(VALUE victim, VALUE carrier); void rb_freeze_singleton_class(VALUE klass); RBIMPL_SYMBOL_EXPORT_END() RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_FORCEINLINE() static bool RB_FL_ABLE(VALUE obj) { if (RB_SPECIAL_CONST_P(obj)) { return false; } else if (RB_TYPE_P(obj, RUBY_T_NODE)) { return false; } else { return true; } } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() static inline VALUE RB_FL_TEST_RAW(VALUE obj, VALUE flags) { RBIMPL_ASSERT_OR_ASSUME(RB_FL_ABLE(obj)); return RBASIC(obj)->flags & flags; } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() static inline VALUE RB_FL_TEST(VALUE obj, VALUE flags) { if (RB_FL_ABLE(obj)) { return RB_FL_TEST_RAW(obj, flags); } else { return RBIMPL_VALUE_NULL; } } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() static inline bool RB_FL_ANY_RAW(VALUE obj, VALUE flags) { return RB_FL_TEST_RAW(obj, flags); } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() static inline bool RB_FL_ANY(VALUE obj, VALUE flags) { return RB_FL_TEST(obj, flags); } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() static inline bool RB_FL_ALL_RAW(VALUE obj, VALUE flags) { return RB_FL_TEST_RAW(obj, flags) == flags; } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() static inline bool RB_FL_ALL(VALUE obj, VALUE flags) { return RB_FL_TEST(obj, flags) == flags; } RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_ARTIFICIAL() static inline void rbimpl_fl_set_raw_raw(struct RBasic *obj, VALUE flags) { obj->flags |= flags; } RBIMPL_ATTR_ARTIFICIAL() static inline void RB_FL_SET_RAW(VALUE obj, VALUE flags) { RBIMPL_ASSERT_OR_ASSUME(RB_FL_ABLE(obj)); rbimpl_fl_set_raw_raw(RBASIC(obj), flags); } RBIMPL_ATTR_ARTIFICIAL() static inline void RB_FL_SET(VALUE obj, VALUE flags) { if (RB_FL_ABLE(obj)) { RB_FL_SET_RAW(obj, flags); } } RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_ARTIFICIAL() static inline void rbimpl_fl_unset_raw_raw(struct RBasic *obj, VALUE flags) { obj->flags &= ~flags; } RBIMPL_ATTR_ARTIFICIAL() static inline void RB_FL_UNSET_RAW(VALUE obj, VALUE flags) { RBIMPL_ASSERT_OR_ASSUME(RB_FL_ABLE(obj)); rbimpl_fl_unset_raw_raw(RBASIC(obj), flags); } RBIMPL_ATTR_ARTIFICIAL() static inline void RB_FL_UNSET(VALUE obj, VALUE flags) { if (RB_FL_ABLE(obj)) { RB_FL_UNSET_RAW(obj, flags); } } RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_ARTIFICIAL() static inline void rbimpl_fl_reverse_raw_raw(struct RBasic *obj, VALUE flags) { obj->flags ^= flags; } RBIMPL_ATTR_ARTIFICIAL() static inline void RB_FL_REVERSE_RAW(VALUE obj, VALUE flags) { RBIMPL_ASSERT_OR_ASSUME(RB_FL_ABLE(obj)); rbimpl_fl_reverse_raw_raw(RBASIC(obj), flags); } RBIMPL_ATTR_ARTIFICIAL() static inline void RB_FL_REVERSE(VALUE obj, VALUE flags) { if (RB_FL_ABLE(obj)) { RB_FL_REVERSE_RAW(obj, flags); } } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() static inline bool RB_OBJ_TAINTABLE(VALUE obj) { if (! RB_FL_ABLE(obj)) { return false; } else if (RB_TYPE_P(obj, RUBY_T_BIGNUM)) { return false; } else if (RB_TYPE_P(obj, RUBY_T_FLOAT)) { return false; } else { return true; } } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() static inline VALUE RB_OBJ_TAINTED_RAW(VALUE obj) { return RB_FL_TEST_RAW(obj, RUBY_FL_TAINT); } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() static inline bool RB_OBJ_TAINTED(VALUE obj) { return RB_FL_ANY(obj, RUBY_FL_TAINT); } RBIMPL_ATTR_ARTIFICIAL() static inline void RB_OBJ_TAINT_RAW(VALUE obj) { RB_FL_SET_RAW(obj, RUBY_FL_TAINT); } RBIMPL_ATTR_ARTIFICIAL() static inline void RB_OBJ_TAINT(VALUE obj) { if (RB_OBJ_TAINTABLE(obj)) { RB_OBJ_TAINT_RAW(obj); } } RBIMPL_ATTR_ARTIFICIAL() static inline void RB_OBJ_INFECT_RAW(VALUE dst, VALUE src) { RBIMPL_ASSERT_OR_ASSUME(RB_OBJ_TAINTABLE(dst)); RBIMPL_ASSERT_OR_ASSUME(RB_FL_ABLE(src)); RB_FL_SET_RAW(dst, RB_OBJ_TAINTED_RAW(src)); } RBIMPL_ATTR_ARTIFICIAL() static inline void RB_OBJ_INFECT(VALUE dst, VALUE src) { if (RB_OBJ_TAINTABLE(dst) && RB_FL_ABLE(src)) { RB_OBJ_INFECT_RAW(dst, src); } } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() /* It is intentional not to return bool here. There is a place in ruby core * (namely class.c:singleton_class_of()) where return value of this function is * verbatimly passed to RB_FL_SET_RAW. */ static inline VALUE RB_OBJ_FROZEN_RAW(VALUE obj) { return RB_FL_TEST_RAW(obj, RUBY_FL_FREEZE); } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() static inline bool RB_OBJ_FROZEN(VALUE obj) { if (! RB_FL_ABLE(obj)) { return true; } else { return RB_OBJ_FROZEN_RAW(obj); } } RBIMPL_ATTR_ARTIFICIAL() static inline void RB_OBJ_FREEZE_RAW(VALUE obj) { RB_FL_SET_RAW(obj, RUBY_FL_FREEZE); } static inline void rb_obj_freeze_inline(VALUE x) { if (RB_FL_ABLE(x)) { RB_OBJ_FREEZE_RAW(x); if (RBASIC_CLASS(x) && !(RBASIC(x)->flags & RUBY_FL_SINGLETON)) { rb_freeze_singleton_class(x); } } } #endif /* RBIMPL_FL_TYPE_H */ PK!4rrinternal/method.hnu[#ifndef RBIMPL_METHOD_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_METHOD_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Creation and modification of Ruby methods. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" #include "ruby/backward/2/stdarg.h" RBIMPL_SYMBOL_EXPORT_BEGIN() void rb_define_method(VALUE,const char*,VALUE(*)(ANYARGS),int); void rb_define_module_function(VALUE,const char*,VALUE(*)(ANYARGS),int); void rb_define_global_function(const char*,VALUE(*)(ANYARGS),int); void rb_undef_method(VALUE,const char*); void rb_define_alias(VALUE,const char*,const char*); void rb_define_attr(VALUE,const char*,int,int); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_METHOD_H */ PK!(z88internal/compiler_is.hnu[#ifndef RBIMPL_COMPILER_IS_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_COMPILER_IS_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_COMPILER_IS. */ /** * @brief Checks if the compiler is of given brand. * @param cc Compiler brand, like `MSVC`. * @retval true It is. * @retval false It isn't. */ #define RBIMPL_COMPILER_IS(cc) RBIMPL_COMPILER_IS_ ## cc #include "ruby/internal/compiler_is/apple.h" #include "ruby/internal/compiler_is/clang.h" #include "ruby/internal/compiler_is/gcc.h" #include "ruby/internal/compiler_is/intel.h" #include "ruby/internal/compiler_is/msvc.h" #include "ruby/internal/compiler_is/sunpro.h" /* :TODO: Other possible compilers to support: * * - IBM XL: recent XL are clang-backended so some tweaks like we do for * Apple's might be needed. * * - ARM's armclang: ditto, it can be clang-backended. */ #endif /* RBIMPL_COMPILER_IS_H */ PK!Tl>l>internal/xmalloc.hnu[#ifndef RBIMPL_XMALLOC_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_XMALLOC_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Declares ::ruby_xmalloc(). */ #include "ruby/internal/config.h" #ifdef STDC_HEADERS # include #endif #ifdef HAVE_STDLIB_H # include #endif #include "ruby/internal/attr/alloc_size.h" #include "ruby/internal/attr/nodiscard.h" #include "ruby/internal/attr/noexcept.h" #include "ruby/internal/attr/restrict.h" #include "ruby/internal/attr/returns_nonnull.h" #include "ruby/internal/dllexport.h" #ifndef USE_GC_MALLOC_OBJ_INFO_DETAILS # define USE_GC_MALLOC_OBJ_INFO_DETAILS 0 #endif #define xmalloc ruby_xmalloc #define xmalloc2 ruby_xmalloc2 #define xcalloc ruby_xcalloc #define xrealloc ruby_xrealloc #define xrealloc2 ruby_xrealloc2 #define xfree ruby_xfree RBIMPL_SYMBOL_EXPORT_BEGIN() RBIMPL_ATTR_NODISCARD() RBIMPL_ATTR_RESTRICT() RBIMPL_ATTR_RETURNS_NONNULL() RBIMPL_ATTR_ALLOC_SIZE((1)) /** * Allocates a storage instance. It is largely the same as system malloc(), * except: * * - It raises Ruby exceptions instead of returning NULL, and * - In case of `ENOMEM` it tries to GC to make some room. * * @param[in] size Requested amount of memory. * @exception rb_eNoMemError No space left for `size` bytes allocation. * @return A valid pointer to an allocated storage instance; which has at * least `size` bytes width, with appropriate alignment detected by * the underlying malloc() routine. * @note It doesn't return NULL. * @note Unlike some malloc() implementations, it allocates something and * returns a meaningful value even when `size` is equal to zero. * @warning The return value shall be invalidated exactly once by either * ruby_xfree(), ruby_xrealloc(), or ruby_xrealloc2(). It is a * failure to pass it to system free(), because the system and Ruby * might or might not share the same malloc() implementation. */ void *ruby_xmalloc(size_t size) RBIMPL_ATTR_NOEXCEPT(malloc(size)) ; RBIMPL_ATTR_NODISCARD() RBIMPL_ATTR_RESTRICT() RBIMPL_ATTR_RETURNS_NONNULL() RBIMPL_ATTR_ALLOC_SIZE((1,2)) /** * Identical to ruby_xmalloc(), except it allocates `nelems` * `elemsiz` bytes. * This is needed because the multiplication could integer overflow. On such * situations Ruby does not try to allocate at all but raises Ruby level * exceptions instead. If there is no integer overflow the behaviour is * exactly the same as `ruby_xmalloc(nelems*elemsiz)`. * * @param[in] nelems Number of elements. * @param[in] elemsiz Size of an element. * @exception rb_eNoMemError No space left for allocation. * @exception rb_eArgError `nelems` * `elemsiz` would overflow. * @return A valid pointer to an allocated storage instance; which has at * least `nelems` * `elemsiz` bytes width, with appropriate * alignment detected by the underlying malloc() routine. * @note It doesn't return NULL. * @note Unlike some malloc() implementations, it allocates something and * returns a meaningful value even when `nelems` or `elemsiz` or * both are zero. * @warning The return value shall be invalidated exactly once by either * ruby_xfree(), ruby_xrealloc(), or ruby_xrealloc2(). It is a * failure to pass it to system free(), because the system and Ruby * might or might not share the same malloc() implementation. */ void *ruby_xmalloc2(size_t nelems, size_t elemsiz) RBIMPL_ATTR_NOEXCEPT(malloc(nelems * elemsiz)) ; RBIMPL_ATTR_NODISCARD() RBIMPL_ATTR_RESTRICT() RBIMPL_ATTR_RETURNS_NONNULL() RBIMPL_ATTR_ALLOC_SIZE((1,2)) /** * Identical to ruby_xmalloc2(), except it zero-fills the region before it * returns. This could also be seen as a routine identical to ruby_xmalloc(), * except it calls calloc() instead of malloc() internally. * * @param[in] nelems Number of elements. * @param[in] elemsiz Size of an element. * @exception rb_eNoMemError No space left for allocation. * @exception rb_eArgError `nelems` * `elemsiz` would overflow. * @return A valid pointer to an allocated storage instance; which has at * least `nelems` * `elemsiz` bytes width, with appropriate * alignment detected by the underlying calloc() routine. * @note It doesn't return NULL. * @note Unlike some calloc() implementations, it allocates something and * returns a meaningful value even when `nelems` or `elemsiz` or * both are zero. * @warning The return value shall be invalidated exactly once by either * ruby_xfree(), ruby_xrealloc(), or ruby_xrealloc2(). It is a * failure to pass it to system free(), because the system and Ruby * might or might not share the same malloc() implementation. */ void *ruby_xcalloc(size_t nelems, size_t elemsiz) RBIMPL_ATTR_NOEXCEPT(calloc(nelems, elemsiz)) ; RBIMPL_ATTR_NODISCARD() RBIMPL_ATTR_RETURNS_NONNULL() RBIMPL_ATTR_ALLOC_SIZE((2)) /** * Resize the storage instance. * * @param[in] ptr A valid pointer to a storage instance that was * previously returned from either ruby_xmalloc(), * ruby_xmalloc2(), ruby_xcalloc(), * ruby_xrealloc(), or ruby_xrealloc2(). * @param[in] newsiz Requested new amount of memory. * @exception rb_eNoMemError No space left for `newsiz` bytes allocation. * @retval ptr In case the function returns the passed pointer * as-is, the storage instance that the pointer * holds is either grown or shrunken to have at * least `newsiz` bytes. * @retval otherwise A valid pointer to a newly allocated storage * instance which has at least `newsiz` bytes * width, and holds previous contents of `ptr`. In * this case `ptr` is invalidated as if it was * passed to ruby_xfree(). * @note It doesn't return NULL. * @warning Unlike some realloc() implementations, passing zero to `elemsiz` * is not the same as calling ruby_xfree(), because this function * never returns NULL. Something meaningful still returns then. * @warning It is a failure not to check the return value. Do not assume * anything on it. It could be either identical to, or distinct * form the passed argument. * @warning Do not assume anything on the alignment of the return value. * There is no guarantee that it inherits the passed argument's * one. * @warning The return value shall be invalidated exactly once by either * ruby_xfree(), ruby_xrealloc(), or ruby_xrealloc2(). It is a * failure to pass it to system free(), because the system and Ruby * might or might not share the same malloc() implementation. */ void *ruby_xrealloc(void *ptr, size_t newsiz) RBIMPL_ATTR_NOEXCEPT(realloc(ptr, newsiz)) ; RBIMPL_ATTR_NODISCARD() RBIMPL_ATTR_RETURNS_NONNULL() RBIMPL_ATTR_ALLOC_SIZE((2,3)) /** * Identical to ruby_xrealloc(), except it resizes the given storage instance * to `newelems` * `newsiz` bytes. This is needed because the multiplication * could integer overflow. On such situations Ruby does not try to touch the * contents of argument pointer at all but raises Ruby level exceptions * instead. If there is no integer overflow the behaviour is exactly the same * as `ruby_xrealloc(ptr,nelems*elemsiz)`. * * This is roughly the same as reallocarray() function that OpenBSD * etc. provides, but also interacts with our GC. * * @param[in] ptr A valid pointer to a storage instance that was * previously returned from either ruby_xmalloc(), * ruby_xmalloc2(), ruby_xcalloc(), * ruby_xrealloc(), or ruby_xrealloc2(). * @param[in] newelems Requested new number of elements. * @param[in] newsiz Requested new size of each element. * @exception rb_eNoMemError No space left for allocation. * @exception rb_eArgError `newelems` * `newsiz` would overflow. * @retval ptr In case the function returns the passed pointer * as-is, the storage instance that the pointer * holds is either grown or shrunken to have at * least `newelems` * `newsiz` bytes. * @retval otherwise A valid pointer to a newly allocated storage * instance which has at least `newelems` * * `newsiz` bytes width, and holds previous * contents of `ptr`. In this case `ptr` is * invalidated as if it was passed to ruby_xfree(). * @note It doesn't return NULL. * @warning Unlike some realloc() implementations, passing zero to either * `newelems` or `elemsiz` are not the same as calling * ruby_xfree(), because this function never returns NULL. * Something meaningful still returns then. * @warning It is a failure not to check the return value. Do not assume * anything on it. It could be either identical to, or distinct * form the passed argument. * @warning Do not assume anything on the alignment of the return value. * There is no guarantee that it inherits the passed argument's * one. * @warning The return value shall be invalidated exactly once by either * ruby_xfree(), ruby_xrealloc(), or ruby_xrealloc2(). It is a * failure to pass it to system free(), because the system and Ruby * might or might not share the same malloc() implementation. */ void *ruby_xrealloc2(void *ptr, size_t newelems, size_t newsiz) RBIMPL_ATTR_NOEXCEPT(realloc(ptr, newelems * newsiz)) ; /** * Deallocates a storage instance. * * @param[out] ptr Either NULL, or a valid pointer previously returned from * one of ruby_xmalloc(), ruby_xmalloc2(), ruby_xcalloc(), * ruby_xrealloc(), or ruby_xrealloc2(). * @warning Every single storage instance that was previously allocated by * either ruby_xmalloc(), ruby_xmalloc2(), ruby_xcalloc(), * ruby_xrealloc(), or ruby_xrealloc2() shall be invalidated * exactly once by either passing it to ruby_xfree(), or passing * it to either ruby_xrealloc(), ruby_xrealloc2() then check the * return value for invalidation. * @warning Do not pass anything other than pointers described above. For * instance pointers returned from malloc() or mmap() shall not be * passed to this function, because the underlying memory * management mechanism could differ. * @warning Do not pass any invalid pointers to this function e.g. by * calling it twice with a same argument. */ void ruby_xfree(void *ptr) RBIMPL_ATTR_NOEXCEPT(free(ptr)) ; #if USE_GC_MALLOC_OBJ_INFO_DETAILS || defined(__DOXYGEN) # define ruby_xmalloc(s1) ruby_xmalloc_with_location(s1, __FILE__, __LINE__) # define ruby_xmalloc2(s1, s2) ruby_xmalloc2_with_location(s1, s2, __FILE__, __LINE__) # define ruby_xcalloc(s1, s2) ruby_xcalloc_with_location(s1, s2, __FILE__, __LINE__) # define ruby_xrealloc(ptr, s1) ruby_xrealloc_with_location(ptr, s1, __FILE__, __LINE__) # define ruby_xrealloc2(ptr, s1, s2) ruby_xrealloc2_with_location(ptr, s1, s2, __FILE__, __LINE__) RBIMPL_ATTR_NODISCARD() RBIMPL_ATTR_RESTRICT() RBIMPL_ATTR_RETURNS_NONNULL() RBIMPL_ATTR_ALLOC_SIZE((1)) void *ruby_xmalloc_body(size_t size) RBIMPL_ATTR_NOEXCEPT(malloc(size)) ; RBIMPL_ATTR_NODISCARD() RBIMPL_ATTR_RESTRICT() RBIMPL_ATTR_RETURNS_NONNULL() RBIMPL_ATTR_ALLOC_SIZE((1,2)) void *ruby_xmalloc2_body(size_t nelems, size_t elemsiz) RBIMPL_ATTR_NOEXCEPT(malloc(nelems * elemsiz)) ; RBIMPL_ATTR_NODISCARD() RBIMPL_ATTR_RESTRICT() RBIMPL_ATTR_RETURNS_NONNULL() RBIMPL_ATTR_ALLOC_SIZE((1,2)) void *ruby_xcalloc_body(size_t nelems, size_t elemsiz) RBIMPL_ATTR_NOEXCEPT(calloc(nelems, elemsiz)) ; RBIMPL_ATTR_NODISCARD() RBIMPL_ATTR_RETURNS_NONNULL() RBIMPL_ATTR_ALLOC_SIZE((2)) void *ruby_xrealloc_body(void *ptr, size_t newsiz) RBIMPL_ATTR_NOEXCEPT(realloc(ptr, newsiz)) ; RBIMPL_ATTR_NODISCARD() RBIMPL_ATTR_RETURNS_NONNULL() RBIMPL_ATTR_ALLOC_SIZE((2,3)) void *ruby_xrealloc2_body(void *ptr, size_t newelems, size_t newsiz) RBIMPL_ATTR_NOEXCEPT(realloc(ptr, newelems * newsiz)) ; RUBY_EXTERN const char *ruby_malloc_info_file; RUBY_EXTERN int ruby_malloc_info_line; static inline void * ruby_xmalloc_with_location(size_t s, const char *file, int line) { void *ptr; ruby_malloc_info_file = file; ruby_malloc_info_line = line; ptr = ruby_xmalloc_body(s); ruby_malloc_info_file = NULL; return ptr; } static inline void * ruby_xmalloc2_with_location(size_t s1, size_t s2, const char *file, int line) { void *ptr; ruby_malloc_info_file = file; ruby_malloc_info_line = line; ptr = ruby_xmalloc2_body(s1, s2); ruby_malloc_info_file = NULL; return ptr; } static inline void * ruby_xcalloc_with_location(size_t s1, size_t s2, const char *file, int line) { void *ptr; ruby_malloc_info_file = file; ruby_malloc_info_line = line; ptr = ruby_xcalloc_body(s1, s2); ruby_malloc_info_file = NULL; return ptr; } static inline void * ruby_xrealloc_with_location(void *ptr, size_t s, const char *file, int line) { void *rptr; ruby_malloc_info_file = file; ruby_malloc_info_line = line; rptr = ruby_xrealloc_body(ptr, s); ruby_malloc_info_file = NULL; return rptr; } static inline void * ruby_xrealloc2_with_location(void *ptr, size_t s1, size_t s2, const char *file, int line) { void *rptr; ruby_malloc_info_file = file; ruby_malloc_info_line = line; rptr = ruby_xrealloc2_body(ptr, s1, s2); ruby_malloc_info_file = NULL; return rptr; } #endif RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_XMALLOC_H */ PK!EG..internal/arithmetic.hnu[#ifndef RBIMPL_ARITHMETIC_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ARITHMETIC_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Conversion between C's arithmtic types and Ruby's numeric types. */ #include "ruby/internal/arithmetic/char.h" #include "ruby/internal/arithmetic/double.h" #include "ruby/internal/arithmetic/fixnum.h" #include "ruby/internal/arithmetic/gid_t.h" #include "ruby/internal/arithmetic/int.h" #include "ruby/internal/arithmetic/intptr_t.h" #include "ruby/internal/arithmetic/long.h" #include "ruby/internal/arithmetic/long_long.h" #include "ruby/internal/arithmetic/mode_t.h" #include "ruby/internal/arithmetic/off_t.h" #include "ruby/internal/arithmetic/pid_t.h" #include "ruby/internal/arithmetic/short.h" #include "ruby/internal/arithmetic/size_t.h" #include "ruby/internal/arithmetic/st_data_t.h" #include "ruby/internal/arithmetic/uid_t.h" #endif /* RBIMPL_ARITHMETIC_H */ PK!~} } internal/newobj.hnu[#ifndef RBIMPL_NEWOBJ_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_NEWOBJ_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #NEWOBJ. */ #include "ruby/internal/cast.h" #include "ruby/internal/core/rbasic.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/fl_type.h" #include "ruby/internal/special_consts.h" #include "ruby/internal/value.h" #include "ruby/assert.h" #define RB_NEWOBJ(obj,type) type *(obj) = RBIMPL_CAST((type *)rb_newobj()) #define RB_NEWOBJ_OF(obj,type,klass,flags) type *(obj) = RBIMPL_CAST((type *)rb_newobj_of(klass, flags)) #define NEWOBJ RB_NEWOBJ #define NEWOBJ_OF RB_NEWOBJ_OF /* core has special NEWOBJ_OF() in internal.h */ #define OBJSETUP rb_obj_setup /* use NEWOBJ_OF instead of NEWOBJ()+OBJSETUP() */ #define CLONESETUP rb_clone_setup #define DUPSETUP rb_dup_setup RBIMPL_SYMBOL_EXPORT_BEGIN() VALUE rb_newobj(void); VALUE rb_newobj_of(VALUE, VALUE); VALUE rb_obj_setup(VALUE obj, VALUE klass, VALUE type); VALUE rb_obj_class(VALUE); VALUE rb_singleton_class_clone(VALUE); void rb_singleton_class_attached(VALUE,VALUE); void rb_copy_generic_ivar(VALUE,VALUE); RBIMPL_SYMBOL_EXPORT_END() static inline void rb_clone_setup(VALUE clone, VALUE obj) { RBIMPL_ASSERT_OR_ASSUME(! RB_SPECIAL_CONST_P(obj)); RBIMPL_ASSERT_OR_ASSUME(! RB_SPECIAL_CONST_P(clone)); const VALUE flags = RUBY_FL_PROMOTED0 | RUBY_FL_PROMOTED1 | RUBY_FL_FINALIZE; rb_obj_setup(clone, rb_singleton_class_clone(obj), RB_FL_TEST_RAW(obj, ~flags)); rb_singleton_class_attached(RBASIC_CLASS(clone), clone); if (RB_FL_TEST(obj, RUBY_FL_EXIVAR)) rb_copy_generic_ivar(clone, obj); } static inline void rb_dup_setup(VALUE dup, VALUE obj) { RBIMPL_ASSERT_OR_ASSUME(! RB_SPECIAL_CONST_P(obj)); RBIMPL_ASSERT_OR_ASSUME(! RB_SPECIAL_CONST_P(dup)); rb_obj_setup(dup, rb_obj_class(obj), RB_FL_TEST_RAW(obj, RUBY_FL_DUPPED)); if (RB_FL_TEST(obj, RUBY_FL_EXIVAR)) rb_copy_generic_ivar(dup, obj); } #endif /* RBIMPL_NEWOBJ_H */ PK!e?` ` internal/variable.hnu[#ifndef RBIMPL_VARIABLE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_VARIABLE_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief C-function backended Ruby-global variables. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" #include "ruby/internal/attr/noreturn.h" RBIMPL_SYMBOL_EXPORT_BEGIN() typedef VALUE rb_gvar_getter_t(ID id, VALUE *data); typedef void rb_gvar_setter_t(VALUE val, ID id, VALUE *data); typedef void rb_gvar_marker_t(VALUE *var); rb_gvar_getter_t rb_gvar_undef_getter; rb_gvar_setter_t rb_gvar_undef_setter; rb_gvar_marker_t rb_gvar_undef_marker; rb_gvar_getter_t rb_gvar_val_getter; rb_gvar_setter_t rb_gvar_val_setter; rb_gvar_marker_t rb_gvar_val_marker; rb_gvar_getter_t rb_gvar_var_getter; rb_gvar_setter_t rb_gvar_var_setter; rb_gvar_marker_t rb_gvar_var_marker; RBIMPL_ATTR_NORETURN() rb_gvar_setter_t rb_gvar_readonly_setter; void rb_define_variable(const char*,VALUE*); void rb_define_virtual_variable(const char*,rb_gvar_getter_t*,rb_gvar_setter_t*); void rb_define_hooked_variable(const char*,VALUE*,rb_gvar_getter_t*,rb_gvar_setter_t*); void rb_define_readonly_variable(const char*,const VALUE*); void rb_define_const(VALUE,const char*,VALUE); void rb_define_global_const(const char*,VALUE); VALUE rb_gv_set(const char*, VALUE); VALUE rb_gv_get(const char*); VALUE rb_iv_get(VALUE, const char*); VALUE rb_iv_set(VALUE, const char*, VALUE); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_VARIABLE_H */ PK!򧈼 internal/dllexport.hnu[#ifndef RBIMPL_DLLEXPORT_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_DLLEXPORT_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Tewaking visibility of C variables/functions. */ #include "ruby/internal/config.h" #include "ruby/internal/compiler_is.h" /* For MinGW, we need __declspec(dllimport) for RUBY_EXTERN on MJIT. mswin's RUBY_EXTERN already has that. See also: win32/Makefile.sub */ #undef RUBY_EXTERN #if defined(MJIT_HEADER) && defined(_WIN32) # define RUBY_EXTERN extern __declspec(dllimport) #elif defined(RUBY_EXPORT) # define RUBY_EXTERN extern #elif defined(_WIN32) # define RUBY_EXTERN extern __declspec(dllimport) #else # define RUBY_EXTERN extern #endif #ifndef RUBY_SYMBOL_EXPORT_BEGIN # define RUBY_SYMBOL_EXPORT_BEGIN /* begin */ #endif #ifndef RUBY_SYMBOL_EXPORT_END # define RUBY_SYMBOL_EXPORT_END /* end */ #endif #ifndef RUBY_FUNC_EXPORTED # define RUBY_FUNC_EXPORTED /* void */ #endif /* These macros are used for functions which are exported only for MJIT and NOT ensured to be exported in future versions. */ #if ! defined(MJIT_HEADER) # define MJIT_FUNC_EXPORTED RUBY_FUNC_EXPORTED #elif ! RBIMPL_COMPILER_IS(MSVC) # define MJIT_FUNC_EXPORTED RUBY_FUNC_EXPORTED #else # define MJIT_FUNC_EXPORTED static #endif #define MJIT_SYMBOL_EXPORT_BEGIN RUBY_SYMBOL_EXPORT_BEGIN #define MJIT_SYMBOL_EXPORT_END RUBY_SYMBOL_EXPORT_END /* On mswin, MJIT header transformation can't be used since cl.exe can't output preprocessed output preserving macros. So this `MJIT_STATIC` is needed to force non-static function to static on MJIT header to avoid symbol conflict. */ #ifdef MJIT_HEADER # define MJIT_STATIC static #else # define MJIT_STATIC #endif /** Shortcut macro equivalent to `RUBY_SYMBOL_EXPORT_BEGIN extern "C" {`. * \@shyouhei finds it handy. */ #if defined(__DOXYGEN__) # define RBIMPL_SYMBOL_EXPORT_BEGIN() /* void */ #elif defined(__cplusplus) # define RBIMPL_SYMBOL_EXPORT_BEGIN() RUBY_SYMBOL_EXPORT_BEGIN extern "C" { #else # define RBIMPL_SYMBOL_EXPORT_BEGIN() RUBY_SYMBOL_EXPORT_BEGIN #endif /** Counterpart of #RBIMPL_SYMBOL_EXPORT_BEGIN */ #if defined(__DOXYGEN__) # define RBIMPL_SYMBOL_EXPORT_END() /* void */ #elif defined(__cplusplus) # define RBIMPL_SYMBOL_EXPORT_END() } RUBY_SYMBOL_EXPORT_END #else # define RBIMPL_SYMBOL_EXPORT_END() RUBY_SYMBOL_EXPORT_END #endif #endif /* RBIMPL_DLLEXPORT_H */ PK!Iinternal/abi.hnu[#ifndef RUBY_ABI_H #define RUBY_ABI_H #ifdef RUBY_ABI_VERSION /* should match the definition in config.h */ /* This number represents Ruby's ABI version. * * In development Ruby, it should be bumped every time an ABI incompatible * change is introduced. This will force other developers to rebuild extension * gems. * * The following cases are considered as ABI incompatible changes: * - Changing any data structures. * - Changing macros or inline functions causing a change in behavior. * - Deprecating or removing function declarations. * * The following cases are NOT considered as ABI incompatible changes: * - Any changes that does not involve the header files in the `include` * directory. * - Adding macros, inline functions, or function declarations. * - Backwards compatible refactors. * - Editing comments. * * In released versions of Ruby, this number is not defined since teeny * versions of Ruby should guarantee ABI compatibility. */ #define RUBY_ABI_VERSION 0 /* Windows does not support weak symbols so ruby_abi_version will not exist * in the shared library. */ #if defined(HAVE_FUNC_WEAK) && !defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__) # define RUBY_DLN_CHECK_ABI #endif #endif /* RUBY_ABI_VERSION */ #ifdef RUBY_DLN_CHECK_ABI # ifdef __cplusplus extern "C" { # endif RUBY_FUNC_EXPORTED unsigned long long __attribute__((weak)) ruby_abi_version(void) { # ifdef RUBY_ABI_VERSION return RUBY_ABI_VERSION; # else return 0; # endif } # ifdef __cplusplus } # endif #endif #endif PK!Vinternal/rgengc.hnu[#ifndef RBIMPL_RGENGC_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_RGENGC_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief RGENGC write-barrier APIs. * @see Sasada, K., "Gradual write-barrier insertion into a Ruby * interpreter", in proceedings of the 2019 ACM SIGPLAN * International Symposium on Memory Management (ISMM 2019), pp * 115-121, 2019. https://doi.org/10.1145/3315573.3329986 */ #include "ruby/internal/attr/artificial.h" #include "ruby/internal/attr/pure.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/special_consts.h" #include "ruby/internal/stdbool.h" #include "ruby/internal/value.h" #include "ruby/assert.h" #include "ruby/backward/2/attributes.h" #undef USE_RGENGC #define USE_RGENGC 1 #ifndef USE_RINCGC # define USE_RINCGC 1 #endif #ifndef USE_RGENGC_LOGGING_WB_UNPROTECT # define USE_RGENGC_LOGGING_WB_UNPROTECT 0 #endif #ifndef RGENGC_WB_PROTECTED_ARRAY # define RGENGC_WB_PROTECTED_ARRAY 1 #endif #ifndef RGENGC_WB_PROTECTED_HASH # define RGENGC_WB_PROTECTED_HASH 1 #endif #ifndef RGENGC_WB_PROTECTED_STRUCT # define RGENGC_WB_PROTECTED_STRUCT 1 #endif #ifndef RGENGC_WB_PROTECTED_STRING # define RGENGC_WB_PROTECTED_STRING 1 #endif #ifndef RGENGC_WB_PROTECTED_OBJECT # define RGENGC_WB_PROTECTED_OBJECT 1 #endif #ifndef RGENGC_WB_PROTECTED_REGEXP # define RGENGC_WB_PROTECTED_REGEXP 1 #endif #ifndef RGENGC_WB_PROTECTED_CLASS # define RGENGC_WB_PROTECTED_CLASS 1 #endif #ifndef RGENGC_WB_PROTECTED_FLOAT # define RGENGC_WB_PROTECTED_FLOAT 1 #endif #ifndef RGENGC_WB_PROTECTED_COMPLEX # define RGENGC_WB_PROTECTED_COMPLEX 1 #endif #ifndef RGENGC_WB_PROTECTED_RATIONAL # define RGENGC_WB_PROTECTED_RATIONAL 1 #endif #ifndef RGENGC_WB_PROTECTED_BIGNUM # define RGENGC_WB_PROTECTED_BIGNUM 1 #endif #ifndef RGENGC_WB_PROTECTED_NODE_CREF # define RGENGC_WB_PROTECTED_NODE_CREF 1 #endif /** * @name Write barrier (WB) interfaces: * @{ * * @note The following core interfaces can be changed in the future. Please * catch up if you want to insert WB into C-extensions correctly. */ /** * WB for new reference from `a' to `b'. Write `b' into `*slot'. `slot' is a * pointer in `a'. */ #define RB_OBJ_WRITE(a, slot, b) \ RBIMPL_CAST(rb_obj_write((VALUE)(a), (VALUE *)(slot), (VALUE)(b), __FILE__, __LINE__)) /** * WB for new reference from `a' to `b'. This doesn't write any values, but * only a WB declaration. `oldv' is replaced value with `b' (not used in * current Ruby). */ #define RB_OBJ_WRITTEN(a, oldv, b) \ RBIMPL_CAST(rb_obj_written((VALUE)(a), (VALUE)(oldv), (VALUE)(b), __FILE__, __LINE__)) /** @} */ #define OBJ_PROMOTED_RAW RB_OBJ_PROMOTED_RAW #define OBJ_PROMOTED RB_OBJ_PROMOTED #define OBJ_WB_UNPROTECT RB_OBJ_WB_UNPROTECT #define RB_OBJ_WB_UNPROTECT(x) rb_obj_wb_unprotect(x, __FILE__, __LINE__) #define RB_OBJ_WB_UNPROTECT_FOR(type, obj) \ (RGENGC_WB_PROTECTED_##type ? OBJ_WB_UNPROTECT(obj) : obj) #define RGENGC_LOGGING_WB_UNPROTECT rb_gc_unprotect_logging /** @cond INTERNAL_MACRO */ #define RB_OBJ_PROMOTED_RAW RB_OBJ_PROMOTED_RAW #define RB_OBJ_PROMOTED RB_OBJ_PROMOTED /** @endcond */ RBIMPL_SYMBOL_EXPORT_BEGIN() void rb_gc_writebarrier(VALUE a, VALUE b); void rb_gc_writebarrier_unprotect(VALUE obj); #if USE_RGENGC_LOGGING_WB_UNPROTECT void rb_gc_unprotect_logging(void *objptr, const char *filename, int line); #endif RBIMPL_SYMBOL_EXPORT_END() RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() static inline bool RB_OBJ_PROMOTED_RAW(VALUE obj) { RBIMPL_ASSERT_OR_ASSUME(RB_FL_ABLE(obj)); return RB_FL_ANY_RAW(obj, RUBY_FL_PROMOTED); } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() static inline bool RB_OBJ_PROMOTED(VALUE obj) { if (! RB_FL_ABLE(obj)) { return false; } else { return RB_OBJ_PROMOTED_RAW(obj); } } static inline VALUE rb_obj_wb_unprotect(VALUE x, RB_UNUSED_VAR(const char *filename), RB_UNUSED_VAR(int line)) { #if USE_RGENGC_LOGGING_WB_UNPROTECT RGENGC_LOGGING_WB_UNPROTECT(RBIMPL_CAST((void *)x), filename, line); #endif rb_gc_writebarrier_unprotect(x); return x; } static inline VALUE rb_obj_written(VALUE a, RB_UNUSED_VAR(VALUE oldv), VALUE b, RB_UNUSED_VAR(const char *filename), RB_UNUSED_VAR(int line)) { #if USE_RGENGC_LOGGING_WB_UNPROTECT RGENGC_LOGGING_OBJ_WRITTEN(a, oldv, b, filename, line); #endif if (!RB_SPECIAL_CONST_P(b)) { rb_gc_writebarrier(a, b); } return a; } static inline VALUE rb_obj_write(VALUE a, VALUE *slot, VALUE b, RB_UNUSED_VAR(const char *filename), RB_UNUSED_VAR(int line)) { #ifdef RGENGC_LOGGING_WRITE RGENGC_LOGGING_WRITE(a, slot, b, filename, line); #endif *slot = b; rb_obj_written(a, RUBY_Qundef /* ignore `oldv' now */, b, filename, line); return a; } #endif /* RBIMPL_RGENGC_H */ PK!tR~ ~ internal/attr/deprecated.hnu[#ifndef RBIMPL_ATTR_DEPRECATED_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_DEPRECATED_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_DEPRECATED. */ #include "ruby/internal/compiler_since.h" #include "ruby/internal/has/attribute.h" #include "ruby/internal/has/c_attribute.h" #include "ruby/internal/has/cpp_attribute.h" #include "ruby/internal/has/declspec_attribute.h" #include "ruby/internal/has/extension.h" /** Wraps (or simulates) `[[deprecated]]` */ #if RBIMPL_HAS_EXTENSION(attribute_deprecated_with_message) # define RBIMPL_ATTR_DEPRECATED(msg) __attribute__((__deprecated__ msg)) #elif defined(__cplusplus) && RBIMPL_COMPILER_SINCE(GCC, 10, 1, 0) /* && RBIMPL_COMPILER_BEFORE(GCC, 10, X, Y) */ # /* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95302 */ # define RBIMPL_ATTR_DEPRECATED(msg) /* disable until they fix this bug */ #elif RBIMPL_COMPILER_SINCE(GCC, 4, 5, 0) # define RBIMPL_ATTR_DEPRECATED(msg) __attribute__((__deprecated__ msg)) #elif RBIMPL_COMPILER_SINCE(Intel, 13, 0, 0) # define RBIMPL_ATTR_DEPRECATED(msg) __attribute__((__deprecated__ msg)) #elif RBIMPL_HAS_ATTRIBUTE(deprecated) /* but not with message. */ # define RBIMPL_ATTR_DEPRECATED(msg) __attribute__((__deprecated__)) #elif RBIMPL_COMPILER_SINCE(MSVC, 14, 0, 0) # define RBIMPL_ATTR_DEPRECATED(msg) __declspec(deprecated msg) #elif RBIMPL_HAS_DECLSPEC_ATTRIBUTE(deprecated) # define RBIMPL_ATTR_DEPRECATED(msg) __declspec(deprecated) #elif RBIMPL_HAS_CPP_ATTRIBUTE(deprecated) # define RBIMPL_ATTR_DEPRECATED(msg) [[deprecated msg]] #elif RBIMPL_HAS_C_ATTRIBUTE(deprecated) # define RBIMPL_ATTR_DEPRECATED(msg) [[deprecated msg]] #else # define RBIMPL_ATTR_DEPRECATED(msg) /* void */ #endif #endif /* RBIMPL_ATTR_DEPRECATED_H */ PK!2XXinternal/attr/noreturn.hnu[#ifndef RBIMPL_ATTR_NORETURN_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_NORETURN_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_NORETURN. */ #include "ruby/internal/has/attribute.h" #include "ruby/internal/has/cpp_attribute.h" #include "ruby/internal/has/declspec_attribute.h" /** Wraps (or simulates) `[[noreturn]]` */ #if RBIMPL_HAS_DECLSPEC_ATTRIBUTE(noreturn) # define RBIMPL_ATTR_NORETURN() __declspec(noreturn) #elif RBIMPL_HAS_ATTRIBUTE(noreturn) # define RBIMPL_ATTR_NORETURN() __attribute__((__noreturn__)) #elif RBIMPL_HAS_CPP_ATTRIBUTE(noreturn) # define RBIMPL_ATTR_NORETURN() [[noreturn]] #elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112) # define RBIMPL_ATTR_NORETURN() _Noreturn #elif defined(_Noreturn) # /* glibc has this macro. */ # define RBIMPL_ATTR_NORETURN() _Noreturn #else # define RBIMPL_ATTR_NORETURN() /* void */ #endif #endif /* RBIMPL_ATTR_NORETURN_H */ PK!\ainternal/attr/diagnose_if.hnu[#ifndef RBIMPL_ATTR_DIAGNOSE_IF_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_DIAGNOSE_IF_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_DIAGNOSE_IF. */ #include "ruby/internal/has/attribute.h" #include "ruby/internal/warning_push.h" /** Wraps (or simulates) `__attribute__((diagnose_if))` */ #if RBIMPL_COMPILER_BEFORE(Clang, 5, 0, 0) # /* https://bugs.llvm.org/show_bug.cgi?id=34319 */ # define RBIMPL_ATTR_DIAGNOSE_IF(_, __, ___) /* void */ #elif RBIMPL_HAS_ATTRIBUTE(diagnose_if) # define RBIMPL_ATTR_DIAGNOSE_IF(_, __, ___) \ RBIMPL_WARNING_PUSH() \ RBIMPL_WARNING_IGNORED(-Wgcc-compat) \ __attribute__((__diagnose_if__(_, __, ___))) \ RBIMPL_WARNING_POP() #else # define RBIMPL_ATTR_DIAGNOSE_IF(_, __, ___) /* void */ #endif #endif /* RBIMPL_ATTR_DIAGNOSE_IF_H */ PK!;@aainternal/attr/error.hnu[#ifndef RBIMPL_ATTR_ERROR_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_ERROR_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_ERROR. */ #include "ruby/internal/has/attribute.h" /** Wraps (or simulates) `__attribute__((error))` */ #if RBIMPL_HAS_ATTRIBUTE(error) # define RBIMPL_ATTR_ERROR(msg) __attribute__((__error__ msg)) #else # define RBIMPL_ATTR_ERROR(msg) /* void */ #endif #endif /* RBIMPL_ATTR_ERROR_H */ PK!ԩinternal/attr/nodiscard.hnu[#ifndef RBIMPL_ATTR_NODISCARD_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_NODISCARD_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_NODISCARD. */ #include "ruby/internal/has/attribute.h" #include "ruby/internal/has/c_attribute.h" #include "ruby/internal/has/cpp_attribute.h" /** * Wraps (or simulates) `[[nodiscard]]`. In C++ (at least since C++20) a * nodiscard attribute can have a message why the result shall not be ignoed. * However GCC attribute and SAL annotation cannot take them. */ #if RBIMPL_HAS_CPP_ATTRIBUTE(nodiscard) # define RBIMPL_ATTR_NODISCARD() [[nodiscard]] #elif RBIMPL_HAS_C_ATTRIBUTE(nodiscard) # define RBIMPL_ATTR_NODISCARD() [[nodiscard]] #elif RBIMPL_HAS_ATTRIBUTE(warn_unused_result) # define RBIMPL_ATTR_NODISCARD() __attribute__((__warn_unused_result__)) #elif defined(_Check_return_) # /* Take SAL definition. */ # define RBIMPL_ATTR_NODISCARD() _Check_return_ #else # define RBIMPL_ATTR_NODISCARD() /* void */ #endif #endif /* RBIMPL_ATTR_NODISCARD_H */ PK!2Winternal/attr/nonstring.hnu[#ifndef RBIMPL_ATTR_NONSTRING_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_NONSTRING_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_NONSTRING. */ #include "ruby/internal/has/attribute.h" /** Wraps (or simulates) `__attribute__((nonstring))` */ #if RBIMPL_HAS_ATTRIBUTE(nonstring) # define RBIMPL_ATTR_NONSTRING() __attribute__((nonstring)) # if RBIMPL_COMPILER_SINCE(GCC, 15, 0, 0) # define RBIMPL_ATTR_NONSTRING_ARRAY() RBIMPL_ATTR_NONSTRING() # elif RBIMPL_COMPILER_SINCE(Clang, 21, 0, 0) # define RBIMPL_ATTR_NONSTRING_ARRAY() RBIMPL_ATTR_NONSTRING() # else # define RBIMPL_ATTR_NONSTRING_ARRAY() /* void */ # endif #else # define RBIMPL_ATTR_NONSTRING() /* void */ # define RBIMPL_ATTR_NONSTRING_ARRAY() /* void */ #endif #endif /* RBIMPL_ATTR_NONSTRING_H */ PK!gtinternal/attr/maybe_unused.hnu[#ifndef RBIMPL_ATTR_MAYBE_UNUSED_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_MAYBE_UNUSED_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_MAYBE_UNUSED. */ #include "ruby/internal/has/attribute.h" #include "ruby/internal/has/c_attribute.h" #include "ruby/internal/has/cpp_attribute.h" /** Wraps (or simulates) `[[maybe_unused]]` */ #if RBIMPL_HAS_CPP_ATTRIBUTE(maybe_unused) # define RBIMPL_ATTR_MAYBE_UNUSED() [[maybe_unused]] #elif RBIMPL_HAS_C_ATTRIBUTE(maybe_unused) # define RBIMPL_ATTR_MAYBE_UNUSED() [[maybe_unused]] #elif RBIMPL_HAS_ATTRIBUTE(unused) # define RBIMPL_ATTR_MAYBE_UNUSED() __attribute__((__unused__)) #else # define RBIMPL_ATTR_MAYBE_UNUSED() /* void */ #endif #endif /* RBIMPL_ATTR_MAYBE_UNUSED */ PK!{{internal/attr/const.hnu[#ifndef RBIMPL_ATTR_CONST_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_CONST_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_CONST. */ #include "ruby/internal/compiler_since.h" #include "ruby/internal/has/attribute.h" #include "ruby/internal/has/declspec_attribute.h" /** Wraps (or simulates) `__attribute__((const))` */ #if RBIMPL_HAS_ATTRIBUTE(const) # define RBIMPL_ATTR_CONST() __attribute__((__const__)) #elif RBIMPL_HAS_DECLSPEC_ATTRIBUTE(noalias) # /* If a function can be a const, that is also a noalias. */ # define RBIMPL_ATTR_CONST() __declspec(noalias) #elif RBIMPL_COMPILER_SINCE(SunPro, 5, 10, 0) # define RBIMPL_ATTR_CONST() _Pragma("no_side_effect") #else # define RBIMPL_ATTR_CONST() /* void */ #endif /** Enables #RBIMPL_ATTR_CONST iff. ! #RUBY_DEBUG. */ #if !RUBY_DEBUG # define RBIMPL_ATTR_CONST_UNLESS_DEBUG() RBIMPL_ATTR_CONST() #else # define RBIMPL_ATTR_CONST_UNLESS_DEBUG() /* void */ #endif #endif /* RBIMPL_ATTR_CONST_H */ PK!CCinternal/attr/cold.hnu[#ifndef RBIMPL_ATTR_COLD_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_COLD_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_COLD. */ #include "ruby/internal/compiler_is.h" #include "ruby/internal/has/attribute.h" /** Wraps (or simulates) `__attribute__((cold))` */ #if RBIMPL_COMPILER_IS(SunPro) # /* Recent SunPro has __has_attribute, and is borken. */ # /* It reports it has attribute cold, reality isn't (warnings issued). */ # define RBIMPL_ATTR_COLD() /* void */ #elif RBIMPL_HAS_ATTRIBUTE(cold) # define RBIMPL_ATTR_COLD() __attribute__((__cold__)) #else # define RBIMPL_ATTR_COLD() /* void */ #endif #endif /* RBIMPL_ATTR_COLD_H */ PK!<͌ internal/attr/noalias.hnu[#ifndef RBIMPL_ATTR_NOALIAS_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_NOALIAS_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_NOALIAS. * * ### Q&A ### * * - Q: There are seemingly similar attributes named #RBIMPL_ATTR_CONST, * #RBIMPL_ATTR_PURE, and #RBIMPL_ATTR_NOALIAS. What are the difference? * * - A: Allowed operations are different. * * - #RBIMPL_ATTR_CONST ... Functions attributed by this are not allowed to * read/write _any_ pointers at all (there are exceptional situations * when reading a pointer is possible but forget that; they are too * exceptional to be useful). Just remember that everything pointer- * related are NG. * * - #RBIMPL_ATTR_PURE ... Functions attributed by this can read any * nonvolatile pointers, but no writes are allowed at all. The ability * to read _any_ nonvolatile pointers makes it possible to mark ::VALUE- * taking functions as being pure, as long as they are read-only. * * - #RBIMPL_ATTR_NOALIAS ... Can both read/write, but only through * pointers passed to the function as parameters. This is a typical * situation when you create a C++ non-static member function which only * concerns `this`. No global variables are allowed to read/write. So * this is not a super-set of being pure. If you want to read something, * that has to be passed to the function as a pointer. ::VALUE -taking * functions thus cannot be attributed as such. */ #include "ruby/internal/has/declspec_attribute.h" /** Wraps (or simulates) `__declspec((noalias))` */ #if RBIMPL_HAS_DECLSPEC_ATTRIBUTE(noalias) # define RBIMPL_ATTR_NOALIAS() __declspec(noalias) #else # define RBIMPL_ATTR_NOALIAS() /* void */ #endif #endif /* RBIMPL_ATTR_NOALIAS_H */ PK!] internal/attr/returns_nonnull.hnu[#ifndef RBIMPL_ATTR_RETURNS_NONNULL_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_RETURNS_NONNULL_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_RETURNS_NONNULL. */ #include "ruby/internal/has/attribute.h" /** Wraps (or simulates) `__attribute__((returns_nonnull))` */ #if defined(_Ret_nonnull_) # /* Take SAL definition. */ # define RBIMPL_ATTR_RETURNS_NONNULL() _Ret_nonnull_ #elif RBIMPL_HAS_ATTRIBUTE(returns_nonnull) # define RBIMPL_ATTR_RETURNS_NONNULL() __attribute__((__returns_nonnull__)) #else # define RBIMPL_ATTR_RETURNS_NONNULL() /* void */ #endif #endif /* RBIMPL_ATTR_RETURNS_NONNULL_H */ PK!iGittinternal/attr/nonnull.hnu[#ifndef RBIMPL_ATTR_NONNULL_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_NONNULL_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_NONNULL. */ #include "ruby/internal/has/attribute.h" /** Wraps (or simulates) `__attribute__((nonnull))` */ #if RBIMPL_HAS_ATTRIBUTE(nonnull) # define RBIMPL_ATTR_NONNULL(list) __attribute__((__nonnull__ list)) #else # define RBIMPL_ATTR_NONNULL(list) /* void */ #endif #endif /* RBIMPL_ATTR_NONNULL_H */ PK!P,Cinternal/attr/alloc_size.hnu[#ifndef RBIMPL_ATTR_ALLOC_SIZE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_ALLOC_SIZE_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_ALLOC_SIZE. */ #include "ruby/internal/has/attribute.h" /** Wraps (or simulates) `__attribute__((alloc_size))` */ #if RBIMPL_HAS_ATTRIBUTE(alloc_size) # define RBIMPL_ATTR_ALLOC_SIZE(tuple) __attribute__((__alloc_size__ tuple)) #else # define RBIMPL_ATTR_ALLOC_SIZE(tuple) /* void */ #endif #endif /* RBIMPL_ATTR_ALLOC_SIZE_H */ PK!rVinternal/attr/pure.hnu[#ifndef RBIMPL_ATTR_PURE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_PURE_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_PURE. */ #include "ruby/internal/compiler_since.h" #include "ruby/internal/has/attribute.h" #include "ruby/assert.h" /** Wraps (or simulates) `__attribute__((pure))` */ #if RBIMPL_HAS_ATTRIBUTE(pure) # define RBIMPL_ATTR_PURE() __attribute__((__pure__)) #elif RBIMPL_COMPILER_SINCE(SunPro, 5, 10, 0) # define RBIMPL_ATTR_PURE() _Pragma("does_not_write_global_data") #else # define RBIMPL_ATTR_PURE() /* void */ #endif /** Enables #RBIMPL_ATTR_PURE iff. ! #RUBY_DEBUG. */ #if !RUBY_DEBUG # define RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_PURE() #else # define RBIMPL_ATTR_PURE_UNLESS_DEBUG() /* void */ #endif #endif /* RBIMPL_ATTR_PURE_H */ PK!"internal/attr/enum_extensibility.hnu[#ifndef RBIMPL_ATTR_ENUM_EXTENSIBILITY_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_ENUM_EXTENSIBILITY_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief #RBIMPL_ATTR_ENUM_EXTENSIBILITY. */ #include "ruby/internal/has/attribute.h" /** Wraps (or simulates) `__attribute__((enum_extensibility))` */ #if RBIMPL_HAS_ATTRIBUTE(enum_extensibility) # define RBIMPL_ATTR_ENUM_EXTENSIBILITY(_) __attribute__((__enum_extensibility__(_))) #else # define RBIMPL_ATTR_ENUM_EXTENSIBILITY(_) /* void */ #endif #endif /* RBIMPL_ATTR_ENUM_EXTENSIBILITY_H */ PK!|]internal/attr/format.hnu[#ifndef RBIMPL_ATTR_FORMAT_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_FORMAT_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_FORMAT. */ #include "ruby/internal/has/attribute.h" /** Wraps (or simulates) `__attribute__((format))` */ #if RBIMPL_HAS_ATTRIBUTE(format) # define RBIMPL_ATTR_FORMAT(x, y, z) __attribute__((__format__(x, y, z))) #else # define RBIMPL_ATTR_FORMAT(x, y, z) /* void */ #endif #if defined(__MINGW_PRINTF_FORMAT) # define RBIMPL_PRINTF_FORMAT __MINGW_PRINTF_FORMAT #else # define RBIMPL_PRINTF_FORMAT __printf__ #endif #endif /* RBIMPL_ATTR_FORMAT_H */ PK!internal/attr/noinline.hnu[#ifndef RBIMPL_ATTR_NOINLINE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_NOINLINE_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_NOINLINE. */ #include "ruby/internal/has/attribute.h" #include "ruby/internal/has/declspec_attribute.h" /** Wraps (or simulates) `__declspec(noinline)` */ #if RBIMPL_HAS_DECLSPEC_ATTRIBUTE(noinline) # define RBIMPL_ATTR_NOINLINE() __declspec(noinline) #elif RBIMPL_HAS_ATTRIBUTE(noinline) # define RBIMPL_ATTR_NOINLINE() __attribute__((__noinline__)) #else # define RBIMPL_ATTR_NOINLINE() /* void */ #endif #endif /* RBIMPL_ATTR_NOINLINE_H */ PK!PLinternal/attr/noexcept.hnu[#ifndef RBIMPL_ATTR_NOEXCEPT_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_NOEXCEPT_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_NOEXCEPT. * * This isn't actually an attribute in C++ but who cares... * * Mainly due to aesthetic reasons, this one is rarely used in the project. * But can be handy on occasions, especially when a function's noexcept-ness * depends on its calling functions. * * ### Q&A ### * * - Q: Can a function that raises Ruby exceptions be attributed `noexcept`? * * - A: Yes. `noexcept` is about C++ exceptions, not Ruby's. They don't * interface each other. You can safely attribute a function that raises * Ruby exceptions as `noexcept`. * * - Q: How, then, can I assert that a function I wrote doesn't raise any Ruby * exceptions? * * - A: `__attribute__((__leaf__))` is for that purpose. A function attributed * as leaf can still throw C++ exceptions, but not Ruby's. Note however, * that it's extremely difficult -- if not impossible -- to assert that a * function doesn't raise any Ruby exceptions at all. Use of that * attribute is not recommended; mere mortals can't properly use that by * hand. * * - Q: Does it make sense to attribute an inline function `noexcept`? * * - A: I thought so before. But no, I don't think they are useful any longer. * * - When an inline function attributed `noexcept` actually doesn't throw * any exceptions at all: these days I don't see any difference in * generated assembly by adding/removing this attribute. C++ compilers * get smarter and smarter. Today they can infer if it actually throws * or not without any annotations by humans (correct me if I'm wrong). * * - When an inline function attributed `noexcepr` actually _does_ throw an * exception: they have to call `std::terminate` then (C++ standard * mandates so). This means exception handling routines are actually * enforced, not omitted. This doesn't impact runtime performance (The * Itanium C++ ABI has zero-cost exception handling), but does impact on * generated binary size. This is bad. */ #include "ruby/internal/compiler_since.h" #include "ruby/internal/has/feature.h" /** Wraps (or simulates) C++11 `noexcept` */ #if ! defined(__cplusplus) # /* Doesn't make sense. */ # define RBIMPL_ATTR_NOEXCEPT(_) /* void */ #elif RBIMPL_HAS_FEATURE(cxx_noexcept) # define RBIMPL_ATTR_NOEXCEPT(_) noexcept(noexcept(_)) #elif defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__ # define RBIMPL_ATTR_NOEXCEPT(_) noexcept(noexcept(_)) #elif defined(__INTEL_CXX11_MODE__) # define RBIMPL_ATTR_NOEXCEPT(_) noexcept(noexcept(_)) #elif RBIMPL_COMPILER_SINCE(MSVC, 19, 0, 0) # define RBIMPL_ATTR_NOEXCEPT(_) noexcept(noexcept(_)) #elif __cplusplus >= 201103L # define RBIMPL_ATTR_NOEXCEPT(_) noexcept(noexcept(_)) #else # define RBIMPL_ATTR_NOEXCEPT(_) /* void */ #endif #endif /* RBIMPL_ATTR_NOEXCEPT_H */ PK!xinternal/attr/restrict.hnu[#ifndef RBIMPL_ATTR_RESTRICT_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_RESTRICT_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_RESTRICT. */ #include "ruby/internal/compiler_since.h" #include "ruby/internal/has/attribute.h" #include "ruby/internal/token_paste.h" /* :FIXME: config.h includes conflicting `#define restrict`. MSVC can be * detected using `RBIMPL_COMPILER_SINCE()`, but Clang & family cannot use * `__has_declspec_attribute()` which involves macro substitution. */ /** Wraps (or simulates) `__declspec(restrict)` */ #if RBIMPL_COMPILER_SINCE(MSVC, 14, 0, 0) # define RBIMPL_ATTR_RESTRICT() __declspec(RBIMPL_TOKEN_PASTE(re, strict)) #elif RBIMPL_HAS_ATTRIBUTE(malloc) # define RBIMPL_ATTR_RESTRICT() __attribute__((__malloc__)) #elif RBIMPL_COMPILER_SINCE(SunPro, 5, 10, 0) # define RBIMPL_ATTR_RESTRICT() _Pragma("returns_new_memory") #else # define RBIMPL_ATTR_RESTRICT() /* void */ #endif #endif /* RBIMPL_ATTR_RESTRICT_H */ PK!linternal/attr/forceinline.hnu[#ifndef RBIMPL_ATTR_FORCEINLINE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_FORCEINLINE_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_FORCEINLINE. */ #include "ruby/internal/compiler_since.h" #include "ruby/internal/has/attribute.h" /** * Wraps (or simulates) `__forceinline`. MSVC complains on declarations like * `static inline __forceinline void foo()`. It seems MSVC's `inline` and * `__forceinline` are mutually exclusive. We have to mimic that behaviour for * non-MSVC compilers. */ #if RBIMPL_COMPILER_SINCE(MSVC, 12, 0, 0) # define RBIMPL_ATTR_FORCEINLINE() __forceinline #elif RBIMPL_HAS_ATTRIBUTE(always_inline) # define RBIMPL_ATTR_FORCEINLINE() __attribute__((__always_inline__)) inline #else # define RBIMPL_ATTR_FORCEINLINE() inline #endif #endif /* RBIMPL_ATTR_FORCEINLINE_H */ PK!l& internal/attr/constexpr.hnu[#ifndef RBIMPL_ATTR_CONSTEXPR_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_CONSTEXPR_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief #RBIMPL_ATTR_CONSTEXPR. */ #include "ruby/internal/has/feature.h" #include "ruby/internal/compiler_is.h" #include "ruby/internal/token_paste.h" /** @cond INTERNAL_MACRO */ #if ! defined(__cplusplus) # /* Makes no sense. */ # define RBIMPL_HAS_ATTR_CONSTEXPR_CXX11 0 # define RBIMPL_HAS_ATTR_CONSTEXPR_CXX14 0 #elif defined(__cpp_constexpr) # /* https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations */ # define RBIMPL_HAS_ATTR_CONSTEXPR_CXX11 (__cpp_constexpr >= 200704L) # define RBIMPL_HAS_ATTR_CONSTEXPR_CXX14 (__cpp_constexpr >= 201304L) #elif RBIMPL_COMPILER_SINCE(MSVC, 19, 0, 0) # define RBIMPL_HAS_ATTR_CONSTEXPR_CXX11 RBIMPL_COMPILER_SINCE(MSVC, 19, 00, 00) # define RBIMPL_HAS_ATTR_CONSTEXPR_CXX14 RBIMPL_COMPILER_SINCE(MSVC, 19, 11, 00) #elif RBIMPL_COMPILER_SINCE(SunPro, 5, 13, 0) # define RBIMPL_HAS_ATTR_CONSTEXPR_CXX11 (__cplusplus >= 201103L) # define RBIMPL_HAS_ATTR_CONSTEXPR_CXX14 (__cplusplus >= 201402L) #elif RBIMPL_COMPILER_SINCE(GCC, 4, 9, 0) # define RBIMPL_HAS_ATTR_CONSTEXPR_CXX11 (__cplusplus >= 201103L) # define RBIMPL_HAS_ATTR_CONSTEXPR_CXX14 (__cplusplus >= 201402L) #elif RBIMPL_HAS_FEATURE(cxx_relaxed_constexpr) # define RBIMPL_HAS_ATTR_CONSTEXPR_CXX11 1 # define RBIMPL_HAS_ATTR_CONSTEXPR_CXX14 1 #elif RBIMPL_HAS_FEATURE(cxx_constexpr) # define RBIMPL_HAS_ATTR_CONSTEXPR_CXX11 1 # define RBIMPL_HAS_ATTR_CONSTEXPR_CXX14 0 #else # /* :FIXME: icpc must have constexpr but don't know how to detect. */ # define RBIMPL_HAS_ATTR_CONSTEXPR_CXX11 0 # define RBIMPL_HAS_ATTR_CONSTEXPR_CXX14 0 #endif /** @endcond */ /** Wraps (or simulates) C++11 `constexpr`. */ #if RBIMPL_HAS_ATTR_CONSTEXPR_CXX14 # define RBIMPL_ATTR_CONSTEXPR(_) constexpr #elif RBIMPL_HAS_ATTR_CONSTEXPR_CXX11 # define RBIMPL_ATTR_CONSTEXPR(_) RBIMPL_TOKEN_PASTE(RBIMPL_ATTR_CONSTEXPR_, _) # define RBIMPL_ATTR_CONSTEXPR_CXX11 constexpr # define RBIMPL_ATTR_CONSTEXPR_CXX14 /* void */ #else # define RBIMPL_ATTR_CONSTEXPR(_) /* void */ #endif /** Enables #RBIMPL_ATTR_CONSTEXPR iff. ! #RUBY_DEBUG. */ #if !RUBY_DEBUG # define RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(_) RBIMPL_ATTR_CONSTEXPR(_) #else # define RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(_) /* void */ #endif #endif /* RBIMPL_ATTR_CONSTEXPR_H */ PK!Nttinternal/attr/weakref.hnu[#ifndef RBIMPL_ATTR_WEAKREF_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_WEAKREF_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_WEAKREF. */ #include "ruby/internal/has/attribute.h" /** Wraps (or simulates) `__attribute__((weakref))` */ #if RBIMPL_HAS_ATTRIBUTE(weakref) # define RBIMPL_ATTR_WEAKREF(sym) __attribute__((__weakref__(# sym))) #else # define RBIMPL_ATTR_WEAKREF(sym) /* void */ #endif #endif /* RBIMPL_ATTR_WEAKREF_H */ PK!j$internal/attr/flag_enum.hnu[#ifndef RBIMPL_ATTR_FLAG_ENUM_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_FLAG_ENUM_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_FLAG_ENUM. * @see https://clang.llvm.org/docs/AttributeReference.html#flag_enum */ #include "ruby/internal/has/attribute.h" /** Wraps (or simulates) `__attribute__((flag_enum)` */ #if RBIMPL_HAS_ATTRIBUTE(flag_enum) # define RBIMPL_ATTR_FLAG_ENUM() __attribute__((__flag_enum__)) #else # define RBIMPL_ATTR_FLAG_ENUM() /* void */ #endif #endif /* RBIMPLATTR_FLAG_ENUM_H */ PK!h$ internal/attr/artificial.hnu[#ifndef RBIMPL_ATTR_ARTIFICIAL_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_ARTIFICIAL_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_ARTIFICIAL. * * ### Q&A ### * * - Q: What is this attribute? I don't get what GCC manual is talking about. * * - A: In short it is an attribute to manipulate GDB backtraces. The * attribute makes the best sense when it comes with * __attribute__((always_inline)). When a function annotated with this * attribute gets inlined, and when you somehow look at a backtrace which * includes such inlined call site, then the backtrace shows the caller * and not the callee. This is handy for instance when an identical * function is inlined more than once in a single big function. On such * case it gets vital to know where the inlining happened in the callee. * See also https://stackoverflow.com/a/21936099 */ #include "ruby/internal/has/attribute.h" /** Wraps (or simulates) `__attribute__((artificial))` */ #if RBIMPL_HAS_ATTRIBUTE(artificial) # define RBIMPL_ATTR_ARTIFICIAL() __attribute__((__artificial__)) #else # define RBIMPL_ATTR_ARTIFICIAL() /* void */ #endif #endif /* RBIMPL_ATTR_ARTIFICIAL_H */ PK!qqinternal/attr/warning.hnu[#ifndef RBIMPL_ATTR_WARNING_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_WARNING_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_WARNING. */ #include "ruby/internal/has/attribute.h" /** Wraps (or simulates) `__attribute__((warning))` */ #if RBIMPL_HAS_ATTRIBUTE(warning) # define RBIMPL_ATTR_WARNING(msg) __attribute__((__warning__ msg)) #else # define RBIMPL_ATTR_WARNING(msg) /* void */ #endif #endif /* RBIMPL_ATTR_WARNING_H */ PK! ͦ  internal/iterator.hnu[#ifndef RBIMPL_ITERATOR_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ITERATOR_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Block related APIs. */ #include "ruby/internal/attr/noreturn.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() #define RB_BLOCK_CALL_FUNC_STRICT 1 #define RUBY_BLOCK_CALL_FUNC_TAKES_BLOCKARG 1 #define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg) \ VALUE yielded_arg, VALUE callback_arg, int argc, const VALUE *argv, VALUE blockarg typedef VALUE rb_block_call_func(RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)); typedef rb_block_call_func *rb_block_call_func_t; VALUE rb_each(VALUE); VALUE rb_yield(VALUE); VALUE rb_yield_values(int n, ...); VALUE rb_yield_values2(int n, const VALUE *argv); VALUE rb_yield_values_kw(int n, const VALUE *argv, int kw_splat); VALUE rb_yield_splat(VALUE); VALUE rb_yield_splat_kw(VALUE, int); VALUE rb_yield_block(RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)); /* rb_block_call_func */ int rb_keyword_given_p(void); int rb_block_given_p(void); void rb_need_block(void); VALUE rb_iterate(VALUE(*)(VALUE),VALUE,rb_block_call_func_t,VALUE); VALUE rb_block_call(VALUE,ID,int,const VALUE*,rb_block_call_func_t,VALUE); VALUE rb_block_call_kw(VALUE,ID,int,const VALUE*,rb_block_call_func_t,VALUE,int); VALUE rb_rescue(VALUE(*)(VALUE),VALUE,VALUE(*)(VALUE,VALUE),VALUE); VALUE rb_rescue2(VALUE(*)(VALUE),VALUE,VALUE(*)(VALUE,VALUE),VALUE,...); VALUE rb_vrescue2(VALUE(*)(VALUE),VALUE,VALUE(*)(VALUE,VALUE),VALUE,va_list); VALUE rb_ensure(VALUE(*)(VALUE),VALUE,VALUE(*)(VALUE),VALUE); VALUE rb_catch(const char*,rb_block_call_func_t,VALUE); VALUE rb_catch_obj(VALUE,rb_block_call_func_t,VALUE); RBIMPL_ATTR_NORETURN() void rb_throw(const char*,VALUE); RBIMPL_ATTR_NORETURN() void rb_throw_obj(VALUE,VALUE); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_ITERATOR_H */ PK!;internal/globals.hnu[#ifndef RBIMPL_GLOBALS_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_GLOBALS_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Ruby-level global variables / constants, visible from C. */ #include "ruby/internal/attr/pure.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/fl_type.h" #include "ruby/internal/special_consts.h" #include "ruby/internal/value.h" #include "ruby/internal/value_type.h" RBIMPL_SYMBOL_EXPORT_BEGIN() #define RUBY_INTEGER_UNIFICATION 1 RUBY_EXTERN VALUE rb_mKernel; RUBY_EXTERN VALUE rb_mComparable; RUBY_EXTERN VALUE rb_mEnumerable; RUBY_EXTERN VALUE rb_mErrno; RUBY_EXTERN VALUE rb_mFileTest; RUBY_EXTERN VALUE rb_mGC; RUBY_EXTERN VALUE rb_mMath; RUBY_EXTERN VALUE rb_mProcess; RUBY_EXTERN VALUE rb_mWaitReadable; RUBY_EXTERN VALUE rb_mWaitWritable; RUBY_EXTERN VALUE rb_cBasicObject; RUBY_EXTERN VALUE rb_cObject; RUBY_EXTERN VALUE rb_cArray; RUBY_EXTERN VALUE rb_cBinding; RUBY_EXTERN VALUE rb_cClass; RUBY_EXTERN VALUE rb_cDir; RUBY_EXTERN VALUE rb_cEncoding; RUBY_EXTERN VALUE rb_cEnumerator; RUBY_EXTERN VALUE rb_cFalseClass; RUBY_EXTERN VALUE rb_cFile; RUBY_EXTERN VALUE rb_cComplex; RUBY_EXTERN VALUE rb_cFloat; RUBY_EXTERN VALUE rb_cHash; RUBY_EXTERN VALUE rb_cIO; RUBY_EXTERN VALUE rb_cInteger; RUBY_EXTERN VALUE rb_cMatch; RUBY_EXTERN VALUE rb_cMethod; RUBY_EXTERN VALUE rb_cModule; RUBY_EXTERN VALUE rb_cNameErrorMesg; RUBY_EXTERN VALUE rb_cNilClass; RUBY_EXTERN VALUE rb_cNumeric; RUBY_EXTERN VALUE rb_cProc; RUBY_EXTERN VALUE rb_cRandom; RUBY_EXTERN VALUE rb_cRange; RUBY_EXTERN VALUE rb_cRational; RUBY_EXTERN VALUE rb_cRegexp; RUBY_EXTERN VALUE rb_cStat; RUBY_EXTERN VALUE rb_cString; RUBY_EXTERN VALUE rb_cStruct; RUBY_EXTERN VALUE rb_cSymbol; RUBY_EXTERN VALUE rb_cThread; RUBY_EXTERN VALUE rb_cTime; RUBY_EXTERN VALUE rb_cTrueClass; RUBY_EXTERN VALUE rb_cUnboundMethod; RUBY_EXTERN VALUE rb_eException; RUBY_EXTERN VALUE rb_eStandardError; RUBY_EXTERN VALUE rb_eSystemExit; RUBY_EXTERN VALUE rb_eInterrupt; RUBY_EXTERN VALUE rb_eSignal; RUBY_EXTERN VALUE rb_eFatal; RUBY_EXTERN VALUE rb_eArgError; RUBY_EXTERN VALUE rb_eEOFError; RUBY_EXTERN VALUE rb_eIndexError; RUBY_EXTERN VALUE rb_eStopIteration; RUBY_EXTERN VALUE rb_eKeyError; RUBY_EXTERN VALUE rb_eRangeError; RUBY_EXTERN VALUE rb_eIOError; RUBY_EXTERN VALUE rb_eRuntimeError; RUBY_EXTERN VALUE rb_eFrozenError; RUBY_EXTERN VALUE rb_eSecurityError; RUBY_EXTERN VALUE rb_eSystemCallError; RUBY_EXTERN VALUE rb_eThreadError; RUBY_EXTERN VALUE rb_eTypeError; RUBY_EXTERN VALUE rb_eZeroDivError; RUBY_EXTERN VALUE rb_eNotImpError; RUBY_EXTERN VALUE rb_eNoMemError; RUBY_EXTERN VALUE rb_eNoMethodError; RUBY_EXTERN VALUE rb_eFloatDomainError; RUBY_EXTERN VALUE rb_eLocalJumpError; RUBY_EXTERN VALUE rb_eSysStackError; RUBY_EXTERN VALUE rb_eRegexpError; RUBY_EXTERN VALUE rb_eEncodingError; RUBY_EXTERN VALUE rb_eEncCompatError; RUBY_EXTERN VALUE rb_eNoMatchingPatternError; RUBY_EXTERN VALUE rb_eScriptError; RUBY_EXTERN VALUE rb_eNameError; RUBY_EXTERN VALUE rb_eSyntaxError; RUBY_EXTERN VALUE rb_eLoadError; RUBY_EXTERN VALUE rb_eMathDomainError; RUBY_EXTERN VALUE rb_stdin, rb_stdout, rb_stderr; RBIMPL_ATTR_PURE() static inline VALUE rb_class_of(VALUE obj) { if (! RB_SPECIAL_CONST_P(obj)) { return RBASIC_CLASS(obj); } else if (obj == RUBY_Qfalse) { return rb_cFalseClass; } else if (obj == RUBY_Qnil) { return rb_cNilClass; } else if (obj == RUBY_Qtrue) { return rb_cTrueClass; } else if (RB_FIXNUM_P(obj)) { return rb_cInteger; } else if (RB_STATIC_SYM_P(obj)) { return rb_cSymbol; } else if (RB_FLONUM_P(obj)) { return rb_cFloat; } #if !RUBY_DEBUG RBIMPL_UNREACHABLE_RETURN(Qfalse); #else RUBY_ASSERT_FAIL("unexpected type"); #endif } #define CLASS_OF rb_class_of RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_GLOBALS_H */ PK!_؏))internal/value_type.hnu[#ifndef RBIMPL_VALUE_TYPE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_VALUE_TYPE_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines enum ::ruby_value_type. */ #include "ruby/internal/assume.h" #include "ruby/internal/attr/artificial.h" #include "ruby/internal/attr/cold.h" #include "ruby/internal/attr/enum_extensibility.h" #include "ruby/internal/attr/forceinline.h" #include "ruby/internal/attr/pure.h" #include "ruby/internal/cast.h" #include "ruby/internal/constant_p.h" #include "ruby/internal/core/rbasic.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/has/builtin.h" #include "ruby/internal/special_consts.h" #include "ruby/internal/stdbool.h" #include "ruby/internal/value.h" #include "ruby/assert.h" #if defined(T_DATA) /* * :!BEWARE!: (Recent?) Solaris' have conflicting definition of * T_DATA. Let us stop here. Please have a workaround like this: * * ```C * #include // <- Include this one first. * #undef T_DATA // <- ... and stick to RUBY_T_DATA forever. * #include // <- OS-provided T_DATA introduced. * ``` * * See also [ruby-core:4261] */ # error Bail out due to conflicting definition of T_DATA. #endif #define T_ARRAY RUBY_T_ARRAY #define T_BIGNUM RUBY_T_BIGNUM #define T_CLASS RUBY_T_CLASS #define T_COMPLEX RUBY_T_COMPLEX #define T_DATA RUBY_T_DATA #define T_FALSE RUBY_T_FALSE #define T_FILE RUBY_T_FILE #define T_FIXNUM RUBY_T_FIXNUM #define T_FLOAT RUBY_T_FLOAT #define T_HASH RUBY_T_HASH #define T_ICLASS RUBY_T_ICLASS #define T_IMEMO RUBY_T_IMEMO #define T_MASK RUBY_T_MASK #define T_MATCH RUBY_T_MATCH #define T_MODULE RUBY_T_MODULE #define T_MOVED RUBY_T_MOVED #define T_NIL RUBY_T_NIL #define T_NODE RUBY_T_NODE #define T_NONE RUBY_T_NONE #define T_OBJECT RUBY_T_OBJECT #define T_RATIONAL RUBY_T_RATIONAL #define T_REGEXP RUBY_T_REGEXP #define T_STRING RUBY_T_STRING #define T_STRUCT RUBY_T_STRUCT #define T_SYMBOL RUBY_T_SYMBOL #define T_TRUE RUBY_T_TRUE #define T_UNDEF RUBY_T_UNDEF #define T_ZOMBIE RUBY_T_ZOMBIE #define BUILTIN_TYPE RB_BUILTIN_TYPE #define DYNAMIC_SYM_P RB_DYNAMIC_SYM_P #define RB_INTEGER_TYPE_P rb_integer_type_p #define SYMBOL_P RB_SYMBOL_P #define rb_type_p RB_TYPE_P /** @cond INTERNAL_MACRO */ #define RB_BUILTIN_TYPE RB_BUILTIN_TYPE #define RB_DYNAMIC_SYM_P RB_DYNAMIC_SYM_P #define RB_FLOAT_TYPE_P RB_FLOAT_TYPE_P #define RB_SYMBOL_P RB_SYMBOL_P #define RB_TYPE_P RB_TYPE_P #define Check_Type Check_Type #if !RUBY_DEBUG # define RBIMPL_ASSERT_TYPE(v, t) RBIMPL_ASSERT_OR_ASSUME(RB_TYPE_P((v), (t))) #else # define RBIMPL_ASSERT_TYPE Check_Type #endif /** @endcond */ #define TYPE(_) RBIMPL_CAST((int)rb_type(_)) /** C-level type of an object. */ enum RBIMPL_ATTR_ENUM_EXTENSIBILITY(closed) ruby_value_type { RUBY_T_NONE = 0x00, /**< Non-object (sweeped etc.) */ RUBY_T_OBJECT = 0x01, /**< @see struct ::RObject */ RUBY_T_CLASS = 0x02, /**< @see struct ::RClass and ::rb_cClass */ RUBY_T_MODULE = 0x03, /**< @see struct ::RClass and ::rb_cModule */ RUBY_T_FLOAT = 0x04, /**< @see struct ::RFloat */ RUBY_T_STRING = 0x05, /**< @see struct ::RString */ RUBY_T_REGEXP = 0x06, /**< @see struct ::RRegexp */ RUBY_T_ARRAY = 0x07, /**< @see struct ::RArray */ RUBY_T_HASH = 0x08, /**< @see struct ::RHash */ RUBY_T_STRUCT = 0x09, /**< @see struct ::RStruct */ RUBY_T_BIGNUM = 0x0a, /**< @see struct ::RBignum */ RUBY_T_FILE = 0x0b, /**< @see struct ::RFile */ RUBY_T_DATA = 0x0c, /**< @see struct ::RTypedData */ RUBY_T_MATCH = 0x0d, /**< @see struct ::RMatch */ RUBY_T_COMPLEX = 0x0e, /**< @see struct ::RComplex */ RUBY_T_RATIONAL = 0x0f, /**< @see struct ::RRational */ RUBY_T_NIL = 0x11, /**< @see ::RUBY_Qnil */ RUBY_T_TRUE = 0x12, /**< @see ::RUBY_Qfalse */ RUBY_T_FALSE = 0x13, /**< @see ::RUBY_Qtrue */ RUBY_T_SYMBOL = 0x14, /**< @see struct ::RSymbol */ RUBY_T_FIXNUM = 0x15, /**< Integers formerly known as Fixnums. */ RUBY_T_UNDEF = 0x16, /**< @see ::RUBY_Qundef */ RUBY_T_IMEMO = 0x1a, /**< @see struct ::RIMemo */ RUBY_T_NODE = 0x1b, /**< @see struct ::RNode */ RUBY_T_ICLASS = 0x1c, /**< Hidden classes known as IClasses. */ RUBY_T_ZOMBIE = 0x1d, /**< @see struct ::RZombie */ RUBY_T_MOVED = 0x1e, /**< @see struct ::RMoved */ RUBY_T_MASK = 0x1f }; RBIMPL_SYMBOL_EXPORT_BEGIN() RBIMPL_ATTR_COLD() void rb_check_type(VALUE obj, int t); RBIMPL_SYMBOL_EXPORT_END() RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() static inline enum ruby_value_type RB_BUILTIN_TYPE(VALUE obj) { RBIMPL_ASSERT_OR_ASSUME(! RB_SPECIAL_CONST_P(obj)); VALUE ret = RBASIC(obj)->flags & RUBY_T_MASK; return RBIMPL_CAST((enum ruby_value_type)ret); } RBIMPL_ATTR_PURE_UNLESS_DEBUG() static inline bool rb_integer_type_p(VALUE obj) { if (RB_FIXNUM_P(obj)) { return true; } else if (RB_SPECIAL_CONST_P(obj)) { return false; } else { return RB_BUILTIN_TYPE(obj) == RUBY_T_BIGNUM; } } RBIMPL_ATTR_PURE_UNLESS_DEBUG() static inline enum ruby_value_type rb_type(VALUE obj) { if (! RB_SPECIAL_CONST_P(obj)) { return RB_BUILTIN_TYPE(obj); } else if (obj == RUBY_Qfalse) { return RUBY_T_FALSE; } else if (obj == RUBY_Qnil) { return RUBY_T_NIL; } else if (obj == RUBY_Qtrue) { return RUBY_T_TRUE; } else if (obj == RUBY_Qundef) { return RUBY_T_UNDEF; } else if (RB_FIXNUM_P(obj)) { return RUBY_T_FIXNUM; } else if (RB_STATIC_SYM_P(obj)) { return RUBY_T_SYMBOL; } else { RBIMPL_ASSUME(RB_FLONUM_P(obj)); return RUBY_T_FLOAT; } } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() static inline bool RB_FLOAT_TYPE_P(VALUE obj) { if (RB_FLONUM_P(obj)) { return true; } else if (RB_SPECIAL_CONST_P(obj)) { return false; } else { return RB_BUILTIN_TYPE(obj) == RUBY_T_FLOAT; } } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() static inline bool RB_DYNAMIC_SYM_P(VALUE obj) { if (RB_SPECIAL_CONST_P(obj)) { return false; } else { return RB_BUILTIN_TYPE(obj) == RUBY_T_SYMBOL; } } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() static inline bool RB_SYMBOL_P(VALUE obj) { return RB_STATIC_SYM_P(obj) || RB_DYNAMIC_SYM_P(obj); } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_FORCEINLINE() static bool rbimpl_RB_TYPE_P_fastpath(VALUE obj, enum ruby_value_type t) { if (t == RUBY_T_TRUE) { return obj == RUBY_Qtrue; } else if (t == RUBY_T_FALSE) { return obj == RUBY_Qfalse; } else if (t == RUBY_T_NIL) { return obj == RUBY_Qnil; } else if (t == RUBY_T_UNDEF) { return obj == RUBY_Qundef; } else if (t == RUBY_T_FIXNUM) { return RB_FIXNUM_P(obj); } else if (t == RUBY_T_SYMBOL) { return RB_SYMBOL_P(obj); } else if (t == RUBY_T_FLOAT) { return RB_FLOAT_TYPE_P(obj); } else if (RB_SPECIAL_CONST_P(obj)) { return false; } else if (t == RB_BUILTIN_TYPE(obj)) { return true; } else { return false; } } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() static inline bool RB_TYPE_P(VALUE obj, enum ruby_value_type t) { if (RBIMPL_CONSTANT_P(t)) { return rbimpl_RB_TYPE_P_fastpath(obj, t); } else { return t == rb_type(obj); } } /** @cond INTERNAL_MACRO */ /* Clang, unlike GCC, cannot propagate __builtin_constant_p beyond function * boundary. */ #if defined(__clang__) # undef RB_TYPE_P # define RB_TYPE_P(obj, t) \ (RBIMPL_CONSTANT_P(t) ? \ rbimpl_RB_TYPE_P_fastpath((obj), (t)) : \ (RB_TYPE_P)((obj), (t))) #endif /* clang 3.x (4.2 compatible) can't eliminate CSE of RB_BUILTIN_TYPE * in inline function and caller function * See also 8998c06461ea0bef11b3aeb30b6d2ab71c8762ba */ #if RBIMPL_COMPILER_BEFORE(Clang, 4, 0, 0) # undef rb_integer_type_p # define rb_integer_type_p(obj) \ __extension__ ({ \ const VALUE integer_type_obj = (obj); \ (RB_FIXNUM_P(integer_type_obj) || \ (!RB_SPECIAL_CONST_P(integer_type_obj) && \ RB_BUILTIN_TYPE(integer_type_obj) == RUBY_T_BIGNUM)); \ }) #endif /** @endcond */ RBIMPL_ATTR_PURE() RBIMPL_ATTR_ARTIFICIAL() /* Defined in ruby/internal/core/rtypeddata.h */ static inline bool rbimpl_rtypeddata_p(VALUE obj); RBIMPL_ATTR_ARTIFICIAL() static inline void Check_Type(VALUE v, enum ruby_value_type t) { if (RB_UNLIKELY(! RB_TYPE_P(v, t))) { goto slowpath; } else if (t != RUBY_T_DATA) { goto fastpath; } else if (rbimpl_rtypeddata_p(v)) { /* The intention itself is not necessarily clear to me, but at least it * is intentional to rule out typed data here. See commit * a7c32bf81d3391cfb78cfda278f469717d0fb794. */ goto slowpath; } else { goto fastpath; } fastpath: return; slowpath: /* <- :TODO: mark this label as cold. */ rb_check_type(v, t); } #endif /* RBIMPL_VALUE_TYPE_H */ PK!5s33internal/constant_p.hnu[#ifndef RBIMPL_CONSTANT_P_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_CONSTANT_P_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_CONSTANT_P. * * Note that __builtin_constant_p can be applicable inside of inline functions, * according to GCC manual. Clang lacks that feature, though. * * @see https://bugs.llvm.org/show_bug.cgi?id=4898 * @see https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html */ #include "ruby/internal/has/builtin.h" #if RBIMPL_HAS_BUILTIN(__builtin_constant_p) # define RBIMPL_CONSTANT_P(expr) __builtin_constant_p(expr) #else # define RBIMPL_CONSTANT_P(expr) 0 #endif #endif /* RBIMPL_CONSTANT_P_H */ PK!((assert.hnu[#ifndef RUBY_ASSERT_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_ASSERT_H /** * @file * @author Ruby developers * @date Wed May 18 00:21:44 JST 1994 * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. */ #include "ruby/internal/assume.h" #include "ruby/internal/attr/cold.h" #include "ruby/internal/attr/noreturn.h" #include "ruby/internal/cast.h" #include "ruby/internal/dllexport.h" #include "ruby/backward/2/assume.h" /* RUBY_NDEBUG is very simple: after everything described below are done, * define it with either NDEBUG is undefined (=0) or defined (=1). It is truly * subordinate. * * RUBY_DEBUG versus NDEBUG is complicated. Assertions shall be: * * | -UNDEBUG | -DNDEBUG * ---------------+----------+--------- * -URUBY_DEBUG | (*1) | disabled * -DRUBY_DEBUG=0 | disabled | disabled * -DRUBY_DEBUG=1 | enabled | (*2) * -DRUBY_DEBUG | enabled | (*2) * * where: * * - (*1): Assertions shall be silently disabled, no warnings, in favour of * commit 21991e6ca59274e41a472b5256bd3245f6596c90. * * - (*2): Compile-time warnings shall be issued. */ /** @cond INTERNAL_MACRO */ /* * Pro tip: `!!RUBY_DEBUG-1` expands to... * * - `!!(-1)` (== `!0` == `1`) when RUBY_DEBUG is defined to be empty, * - `(!!0)-1` (== `0-1` == `-1`) when RUBY_DEBUG is defined as 0, and * - `(!!n)-1` (== `1-1` == `0`) when RUBY_DEBUG is defined as something else. */ #if ! defined(RUBY_DEBUG) # define RBIMPL_RUBY_DEBUG 0 #elif !!RUBY_DEBUG-1 < 0 # define RBIMPL_RUBY_DEBUG 0 #else # define RBIMPL_RUBY_DEBUG 1 #endif /* * ISO/IEC 9899 (all past versions) says that "If NDEBUG is defined as a macro * name at the point in the source file where is included, ..." * which means we must not take its defined value into account. */ #if defined(NDEBUG) # define RBIMPL_NDEBUG 1 #else # define RBIMPL_NDEBUG 0 #endif /** @endcond */ /* Here we go... */ #undef RUBY_DEBUG #undef RUBY_NDEBUG #undef NDEBUG #if defined(__DOXYGEN__) # /** Define this macro when you want assertions. */ # define RUBY_DEBUG 0 # /** Define this macro when you don't want assertions. */ # define NDEBUG # /** This macro is basically the same as #NDEBUG */ # define RUBY_NDEBUG 1 #elif (RBIMPL_NDEBUG == 1) && (RBIMPL_RUBY_DEBUG == 0) # /* Assertions disabled as per request, no conflicts. */ # define RUBY_DEBUG 0 # define RUBY_NDEBUG 1 # define NDEBUG #elif (RBIMPL_NDEBUG == 0) && (RBIMPL_RUBY_DEBUG == 1) # /* Assertions enabled as per request, no conflicts. */ # define RUBY_DEBUG 1 # define RUBY_NDEBUG 0 # /* keep NDEBUG undefined */ #elif (RBIMPL_NDEBUG == 0) && (RBIMPL_RUBY_DEBUG == 0) # /* The (*1) situation in avobe diagram. */ # define RUBY_DEBUG 0 # define RUBY_NDEBUG 1 # define NDEBUG #elif (RBIMPL_NDEBUG == 1) && (RBIMPL_RUBY_DEBUG == 1) # /* The (*2) situation in above diagram. */ # define RUBY_DEBUG 1 # define RUBY_NDEBUG 0 # /* keep NDEBUG undefined */ # if defined(_MSC_VER) # pragma message("NDEBUG is ignored because RUBY_DEBUG>0.") # elif defined(__GNUC__) # pragma GCC warning "NDEBUG is ignored because RUBY_DEBUG>0." # else # error NDEBUG is ignored because RUBY_DEBUG>0. # endif #endif #undef RBIMPL_NDEBUG #undef RBIMPL_RUBY_DEBUG /** @cond INTERNAL_MACRO */ #define RBIMPL_ASSERT_NOTHING RBIMPL_CAST((void)0) RBIMPL_SYMBOL_EXPORT_BEGIN() RBIMPL_ATTR_NORETURN() RBIMPL_ATTR_COLD() void rb_assert_failure(const char *file, int line, const char *name, const char *expr); RBIMPL_SYMBOL_EXPORT_END() #ifdef RUBY_FUNCTION_NAME_STRING # define RBIMPL_ASSERT_FUNC RUBY_FUNCTION_NAME_STRING #else # define RBIMPL_ASSERT_FUNC RBIMPL_CAST((const char *)0) #endif /** @endcond */ /** * Prints the given message, and terminates the entire process abnormally. * * @param mesg The message to display. */ #define RUBY_ASSERT_FAIL(mesg) \ rb_assert_failure(__FILE__, __LINE__, RBIMPL_ASSERT_FUNC, mesg) /** * Asserts that the expression is truthy. If not aborts with the message. * * @param expr What supposedly evaluates to true. * @param mesg The message to display on failure. */ #define RUBY_ASSERT_MESG(expr, mesg) \ (RB_LIKELY(expr) ? RBIMPL_ASSERT_NOTHING : RUBY_ASSERT_FAIL(mesg)) /** * A variant of #RUBY_ASSERT that does not interface with #RUBY_DEBUG. * * @copydetails #RUBY_ASSERT */ #define RUBY_ASSERT_ALWAYS(expr) RUBY_ASSERT_MESG((expr), #expr) /** * Asserts that the given expression is truthy iff #RUBY_DEBUG is truthy. * * @param expr What supposedly evaluates to true. */ #if RUBY_DEBUG # define RUBY_ASSERT(expr) RUBY_ASSERT_MESG((expr), #expr) #else # define RUBY_ASSERT(expr) RBIMPL_ASSERT_NOTHING #endif /** * A variant of #RUBY_ASSERT that interfaces with #NDEBUG instead of * #RUBY_DEBUG. This almost resembles `assert` C standard macro, except minor * implementation details. * * @copydetails #RUBY_ASSERT */ /* Currently `RUBY_DEBUG == ! defined(NDEBUG)` is always true. There is no * difference any longer between this one and `RUBY_ASSERT`. */ #if defined(NDEBUG) # define RUBY_ASSERT_NDEBUG(expr) RBIMPL_ASSERT_NOTHING #else # define RUBY_ASSERT_NDEBUG(expr) RUBY_ASSERT_MESG((expr), #expr) #endif /** * @copydoc #RUBY_ASSERT_WHEN * @param mesg The message to display on failure. */ #if RUBY_DEBUG # define RUBY_ASSERT_MESG_WHEN(cond, expr, mesg) RUBY_ASSERT_MESG((expr), (mesg)) #else # define RUBY_ASSERT_MESG_WHEN(cond, expr, mesg) \ ((cond) ? RUBY_ASSERT_MESG((expr), (mesg)) : RBIMPL_ASSERT_NOTHING) #endif /** * A variant of #RUBY_ASSERT that asserts when either #RUBY_DEBUG or `cond` * parameter is truthy. * * @param cond Extra condition that shall hold for assertion to take effect. * @param expr What supposedly evaluates to true. */ #define RUBY_ASSERT_WHEN(cond, expr) RUBY_ASSERT_MESG_WHEN((cond), (expr), #expr) /** * This is either #RUBY_ASSERT or #RBIMPL_ASSUME, depending on #RUBY_DEBUG. * * @copydetails #RUBY_ASSERT */ #if RUBY_DEBUG # define RBIMPL_ASSERT_OR_ASSUME(expr) RUBY_ASSERT_ALWAYS(expr) #elif RBIMPL_COMPILER_BEFORE(Clang, 7, 0, 0) # /* See commit 67d259c5dccd31fe49d417fec169977712ffdf10 */ # define RBIMPL_ASSERT_OR_ASSUME(expr) RBIMPL_ASSERT_NOTHING #elif defined(RUBY_ASSERT_NOASSUME) # /* See commit d300a734414ef6de7e8eb563b7cc4389c455ed08 */ # define RBIMPL_ASSERT_OR_ASSUME(expr) RBIMPL_ASSERT_NOTHING #elif ! defined(RBIMPL_HAVE___ASSUME) # define RBIMPL_ASSERT_OR_ASSUME(expr) RBIMPL_ASSERT_NOTHING #else # define RBIMPL_ASSERT_OR_ASSUME(expr) RBIMPL_ASSUME(expr) #endif #endif /* RUBY_ASSERT_H */ PK!QƜ random.hnu[#ifndef RUBY_RANDOM_H #define RUBY_RANDOM_H 1 /** * @file * @date Sat May 7 11:51:14 JST 2016 * @copyright 2007-2020 Yukihiro Matsumoto * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. */ #include "ruby/ruby.h" RBIMPL_SYMBOL_EXPORT_BEGIN() struct rb_random_struct { VALUE seed; }; typedef struct rb_random_struct rb_random_t; typedef void rb_random_init_func(rb_random_t *, const uint32_t *, size_t); typedef unsigned int rb_random_get_int32_func(rb_random_t *); typedef void rb_random_get_bytes_func(rb_random_t *, void *, size_t); typedef double rb_random_get_real_func(rb_random_t *, int); typedef struct { size_t default_seed_bits; rb_random_init_func *init; rb_random_get_int32_func *get_int32; rb_random_get_bytes_func *get_bytes; rb_random_get_real_func *get_real; } rb_random_interface_t; #define RB_RANDOM_INTERFACE_DECLARE(prefix) \ static void prefix##_init(rb_random_t *, const uint32_t *, size_t); \ static unsigned int prefix##_get_int32(rb_random_t *); \ static void prefix##_get_bytes(rb_random_t *, void *, size_t) #define RB_RANDOM_INTERFACE_DECLARE_WITH_REAL(prefix) \ RB_RANDOM_INTERFACE_DECLARE(prefix); \ static double prefix##_get_real(rb_random_t *, int) #define RB_RANDOM_INTERFACE_DEFINE(prefix) \ prefix##_init, \ prefix##_get_int32, \ prefix##_get_bytes #define RB_RANDOM_INTERFACE_DEFINE_WITH_REAL(prefix) \ RB_RANDOM_INTERFACE_DEFINE(prefix), \ prefix##_get_real #if defined _WIN32 && !defined __CYGWIN__ typedef rb_data_type_t rb_random_data_type_t; # define RB_RANDOM_PARENT 0 #else typedef const rb_data_type_t rb_random_data_type_t; # define RB_RANDOM_PARENT &rb_random_data_type #endif #define RB_RANDOM_DATA_INIT_PARENT(random_data) \ rbimpl_random_data_init_parent(&random_data) void rb_random_mark(void *ptr); void rb_random_base_init(rb_random_t *rnd); double rb_int_pair_to_real(uint32_t a, uint32_t b, int excl); void rb_rand_bytes_int32(rb_random_get_int32_func *, rb_random_t *, void *, size_t); RUBY_EXTERN const rb_data_type_t rb_random_data_type; RBIMPL_SYMBOL_EXPORT_END() RBIMPL_ATTR_PURE_UNLESS_DEBUG() /* :TODO: can this function be __attribute__((returns_nonnull)) or not? */ static inline const rb_random_interface_t * rb_rand_if(VALUE obj) { RBIMPL_ASSERT_OR_ASSUME(RTYPEDDATA_P(obj)); const struct rb_data_type_struct *t = RTYPEDDATA_TYPE(obj); const void *ret = t->data; return RBIMPL_CAST((const rb_random_interface_t *)ret); } RBIMPL_ATTR_NOALIAS() static inline void rbimpl_random_data_init_parent(rb_random_data_type_t *random_data) { #if defined _WIN32 && !defined __CYGWIN__ random_data->parent = &rb_random_data_type; #endif } #endif /* RUBY_RANDOM_H */ PK! cq#q#atomic.hnu[#ifndef RUBY_ATOMIC_H #define RUBY_ATOMIC_H /* * - RUBY_ATOMIC_CAS, RUBY_ATOMIC_EXCHANGE, RUBY_ATOMIC_FETCH_*: * return the old * value. * - RUBY_ATOMIC_ADD, RUBY_ATOMIC_SUB, RUBY_ATOMIC_INC, RUBY_ATOMIC_DEC, RUBY_ATOMIC_OR, RUBY_ATOMIC_SET: * may be void. */ #if 0 #elif defined HAVE_GCC_ATOMIC_BUILTINS typedef unsigned int rb_atomic_t; # define RUBY_ATOMIC_FETCH_ADD(var, val) __atomic_fetch_add(&(var), (val), __ATOMIC_SEQ_CST) # define RUBY_ATOMIC_FETCH_SUB(var, val) __atomic_fetch_sub(&(var), (val), __ATOMIC_SEQ_CST) # define RUBY_ATOMIC_OR(var, val) __atomic_fetch_or(&(var), (val), __ATOMIC_SEQ_CST) # define RUBY_ATOMIC_EXCHANGE(var, val) __atomic_exchange_n(&(var), (val), __ATOMIC_SEQ_CST) # define RUBY_ATOMIC_CAS(var, oldval, newval) RB_GNUC_EXTENSION_BLOCK( \ __typeof__(var) oldvaldup = (oldval); /* oldval should not be modified */ \ __atomic_compare_exchange_n(&(var), &oldvaldup, (newval), 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); \ oldvaldup ) # define RUBY_ATOMIC_GENERIC_MACRO 1 #elif defined HAVE_GCC_SYNC_BUILTINS /* @shyouhei hack to support atomic operations in case of gcc. Gcc * has its own pseudo-insns to support them. See info, or * http://gcc.gnu.org/onlinedocs/gcc/Atomic-Builtins.html */ typedef unsigned int rb_atomic_t; /* Anything OK */ # define RUBY_ATOMIC_FETCH_ADD(var, val) __sync_fetch_and_add(&(var), (val)) # define RUBY_ATOMIC_FETCH_SUB(var, val) __sync_fetch_and_sub(&(var), (val)) # define RUBY_ATOMIC_OR(var, val) __sync_fetch_and_or(&(var), (val)) # define RUBY_ATOMIC_EXCHANGE(var, val) __sync_lock_test_and_set(&(var), (val)) # define RUBY_ATOMIC_CAS(var, oldval, newval) __sync_val_compare_and_swap(&(var), (oldval), (newval)) # define RUBY_ATOMIC_GENERIC_MACRO 1 #elif defined _WIN32 #if RBIMPL_COMPILER_SINCE(MSVC, 13, 0, 0) #pragma intrinsic(_InterlockedOr) #endif typedef LONG rb_atomic_t; # define RUBY_ATOMIC_SET(var, val) InterlockedExchange(&(var), (val)) # define RUBY_ATOMIC_INC(var) InterlockedIncrement(&(var)) # define RUBY_ATOMIC_DEC(var) InterlockedDecrement(&(var)) # define RUBY_ATOMIC_FETCH_ADD(var, val) InterlockedExchangeAdd(&(var), (val)) # define RUBY_ATOMIC_FETCH_SUB(var, val) InterlockedExchangeAdd(&(var), -(LONG)(val)) #if defined __GNUC__ # define RUBY_ATOMIC_OR(var, val) __asm__("lock\n\t" "orl\t%1, %0" : "=m"(var) : "Ir"(val)) #elif RBIMPL_COMPILER_BEFORE(MSVC, 13, 0, 0) # define RUBY_ATOMIC_OR(var, val) rb_w32_atomic_or(&(var), (val)) static inline void rb_w32_atomic_or(volatile rb_atomic_t *var, rb_atomic_t val) { #ifdef _M_IX86 __asm mov eax, var; __asm mov ecx, val; __asm lock or [eax], ecx; #else #error unsupported architecture #endif } #else # define RUBY_ATOMIC_OR(var, val) _InterlockedOr(&(var), (val)) #endif # define RUBY_ATOMIC_EXCHANGE(var, val) InterlockedExchange(&(var), (val)) # define RUBY_ATOMIC_CAS(var, oldval, newval) InterlockedCompareExchange(&(var), (newval), (oldval)) # if RBIMPL_COMPILER_BEFORE(MSVC, 13, 0, 0) static inline rb_atomic_t rb_w32_atomic_cas(volatile rb_atomic_t *var, rb_atomic_t oldval, rb_atomic_t newval) { return (rb_atomic_t)InterlockedCompareExchange((PVOID *)var, (PVOID)newval, (PVOID)oldval); } # undef RUBY_ATOMIC_CAS # define RUBY_ATOMIC_CAS(var, oldval, newval) rb_w32_atomic_cas(&(var), (oldval), (newval)) # endif # ifdef _M_AMD64 # define RUBY_ATOMIC_SIZE_ADD(var, val) InterlockedExchangeAdd64((LONG_LONG *)&(var), (val)) # define RUBY_ATOMIC_SIZE_SUB(var, val) InterlockedExchangeAdd64((LONG_LONG *)&(var), -(LONG)(val)) # define RUBY_ATOMIC_SIZE_INC(var) InterlockedIncrement64(&(var)) # define RUBY_ATOMIC_SIZE_DEC(var) InterlockedDecrement64(&(var)) # define RUBY_ATOMIC_SIZE_EXCHANGE(var, val) InterlockedExchange64(&(var), (val)) # define RUBY_ATOMIC_SIZE_CAS(var, oldval, newval) InterlockedCompareExchange64(&(var), (newval), (oldval)) # else # define RUBY_ATOMIC_SIZE_ADD(var, val) InterlockedExchangeAdd((LONG *)&(var), (val)) # define RUBY_ATOMIC_SIZE_SUB(var, val) InterlockedExchangeAdd((LONG *)&(var), -(LONG)(val)) # define RUBY_ATOMIC_SIZE_INC(var) InterlockedIncrement((LONG *)&(var)) # define RUBY_ATOMIC_SIZE_DEC(var) InterlockedDecrement((LONG *)&(var)) # define RUBY_ATOMIC_SIZE_EXCHANGE(var, val) InterlockedExchange((LONG *)&(var), (val)) # endif # ifdef InterlockedExchangePointer # define RUBY_ATOMIC_PTR_EXCHANGE(var, val) InterlockedExchangePointer((PVOID volatile *)&(var), (PVOID)(val)) # endif /* See below for definitions of other situations */ #elif defined(__sun) && defined(HAVE_ATOMIC_H) #include typedef unsigned int rb_atomic_t; # define RUBY_ATOMIC_INC(var) atomic_inc_uint(&(var)) # define RUBY_ATOMIC_DEC(var) atomic_dec_uint(&(var)) # define RUBY_ATOMIC_FETCH_ADD(var, val) rb_atomic_fetch_add(&(var), (val)) # define RUBY_ATOMIC_FETCH_SUB(var, val) rb_atomic_fetch_sub(&(var), (val)) # define RUBY_ATOMIC_ADD(var, val) atomic_add_uint(&(var), (val)) # define RUBY_ATOMIC_SUB(var, val) atomic_sub_uint(&(var), (val)) # define RUBY_ATOMIC_OR(var, val) atomic_or_uint(&(var), (val)) # define RUBY_ATOMIC_EXCHANGE(var, val) atomic_swap_uint(&(var), (val)) # define RUBY_ATOMIC_CAS(var, oldval, newval) atomic_cas_uint(&(var), (oldval), (newval)) static inline rb_atomic_t rb_atomic_fetch_add(volatile rb_atomic_t *var, rb_atomic_t val) { return atomic_add_int_nv(var, val) - val; } static inline rb_atomic_t rb_atomic_fetch_sub(volatile rb_atomic_t *var, rb_atomic_t val) { return atomic_add_int_nv(var, (rb_atomic_t)(-(int)val)) + val; } # if defined(_LP64) || defined(_I32LPx) # define RUBY_ATOMIC_SIZE_ADD(var, val) atomic_add_long(&(var), (val)) # define RUBY_ATOMIC_SIZE_SUB(var, val) atomic_add_long(&(var), -(val)) # define RUBY_ATOMIC_SIZE_INC(var) atomic_inc_ulong(&(var)) # define RUBY_ATOMIC_SIZE_DEC(var) atomic_dec_ulong(&(var)) # define RUBY_ATOMIC_SIZE_EXCHANGE(var, val) atomic_swap_ulong(&(var), (val)) # define RUBY_ATOMIC_SIZE_CAS(var, oldval, val) atomic_cas_ulong(&(var), (oldval), (val)) # else # define RUBY_ATOMIC_SIZE_ADD(var, val) atomic_add_int(&(var), (val)) # define RUBY_ATOMIC_SIZE_SUB(var, val) atomic_add_int(&(var), -(val)) # define RUBY_ATOMIC_SIZE_INC(var) atomic_inc_uint(&(var)) # define RUBY_ATOMIC_SIZE_DEC(var) atomic_dec_uint(&(var)) # define RUBY_ATOMIC_SIZE_EXCHANGE(var, val) atomic_swap_uint(&(var), (val)) # endif #else # error No atomic operation found #endif #ifndef RUBY_ATOMIC_SET # define RUBY_ATOMIC_SET(var, val) (void)RUBY_ATOMIC_EXCHANGE(var, val) #endif #ifndef RUBY_ATOMIC_ADD # define RUBY_ATOMIC_ADD(var, val) (void)RUBY_ATOMIC_FETCH_ADD(var, val) #endif #ifndef RUBY_ATOMIC_SUB # define RUBY_ATOMIC_SUB(var, val) (void)RUBY_ATOMIC_FETCH_SUB(var, val) #endif #ifndef RUBY_ATOMIC_INC # define RUBY_ATOMIC_INC(var) RUBY_ATOMIC_ADD(var, 1) #endif #ifndef RUBY_ATOMIC_DEC # define RUBY_ATOMIC_DEC(var) RUBY_ATOMIC_SUB(var, 1) #endif #ifndef RUBY_ATOMIC_SIZE_INC # define RUBY_ATOMIC_SIZE_INC(var) RUBY_ATOMIC_INC(var) #endif #ifndef RUBY_ATOMIC_SIZE_DEC # define RUBY_ATOMIC_SIZE_DEC(var) RUBY_ATOMIC_DEC(var) #endif #ifndef RUBY_ATOMIC_SIZE_EXCHANGE # define RUBY_ATOMIC_SIZE_EXCHANGE(var, val) RUBY_ATOMIC_EXCHANGE(var, val) #endif #ifndef RUBY_ATOMIC_SIZE_CAS # define RUBY_ATOMIC_SIZE_CAS(var, oldval, val) RUBY_ATOMIC_CAS(var, oldval, val) #endif #ifndef RUBY_ATOMIC_SIZE_ADD # define RUBY_ATOMIC_SIZE_ADD(var, val) RUBY_ATOMIC_ADD(var, val) #endif #ifndef RUBY_ATOMIC_SIZE_SUB # define RUBY_ATOMIC_SIZE_SUB(var, val) RUBY_ATOMIC_SUB(var, val) #endif #if RUBY_ATOMIC_GENERIC_MACRO # ifndef RUBY_ATOMIC_PTR_EXCHANGE # define RUBY_ATOMIC_PTR_EXCHANGE(var, val) RUBY_ATOMIC_EXCHANGE(var, val) # endif # ifndef RUBY_ATOMIC_PTR_CAS # define RUBY_ATOMIC_PTR_CAS(var, oldval, newval) RUBY_ATOMIC_CAS(var, oldval, newval) # endif # ifndef RUBY_ATOMIC_VALUE_EXCHANGE # define RUBY_ATOMIC_VALUE_EXCHANGE(var, val) RUBY_ATOMIC_EXCHANGE(var, val) # endif # ifndef RUBY_ATOMIC_VALUE_CAS # define RUBY_ATOMIC_VALUE_CAS(var, oldval, val) RUBY_ATOMIC_CAS(var, oldval, val) # endif #endif #ifndef RUBY_ATOMIC_PTR_EXCHANGE # if SIZEOF_VOIDP == SIZEOF_SIZE_T # define RUBY_ATOMIC_PTR_EXCHANGE(var, val) (void *)RUBY_ATOMIC_SIZE_EXCHANGE(*(size_t *)&(var), (size_t)(val)) # else # error No atomic exchange for void* # endif #endif #ifndef RUBY_ATOMIC_PTR_CAS # if SIZEOF_VOIDP == SIZEOF_SIZE_T # define RUBY_ATOMIC_PTR_CAS(var, oldval, val) (void *)RUBY_ATOMIC_SIZE_CAS(*(size_t *)&(var), (size_t)(oldval), (size_t)(val)) # else # error No atomic compare-and-set for void* # endif #endif #ifndef RUBY_ATOMIC_VALUE_EXCHANGE # if SIZEOF_VALUE == SIZEOF_SIZE_T # define RUBY_ATOMIC_VALUE_EXCHANGE(var, val) RUBY_ATOMIC_SIZE_EXCHANGE(*(size_t *)&(var), (size_t)(val)) # else # error No atomic exchange for VALUE # endif #endif #ifndef RUBY_ATOMIC_VALUE_CAS # if SIZEOF_VALUE == SIZEOF_SIZE_T # define RUBY_ATOMIC_VALUE_CAS(var, oldval, val) RUBY_ATOMIC_SIZE_CAS(*(size_t *)&(var), (size_t)(oldval), (size_t)(val)) # else # error No atomic compare-and-set for VALUE # endif #endif #endif /* RUBY_ATOMIC_H */ PK!_22fiber/scheduler.hnu[#ifndef RUBY_FIBER_SCHEDULER_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_FIBER_SCHEDULER_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @brief Scheduler APIs. */ #include "ruby/internal/config.h" #include #ifdef STDC_HEADERS #include /* size_t */ #endif #include "ruby/ruby.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/arithmetic.h" RBIMPL_SYMBOL_EXPORT_BEGIN() struct timeval; /** * Wrap a `ssize_t` and `int errno` into a single `VALUE`. This interface should * be used to safely capture results from system calls like `read` and `write`. * * You should use `rb_fiber_scheduler_io_result_apply` to unpack the result of * this value and update `int errno`. * * You should not directly try to interpret the result value as it is considered * an opaque representation. However, the general representation is an integer * in the range of `[-int errno, size_t size]`. Linux generally restricts the * result of system calls like `read` and `write` to `<= 2^31` which means this * will typically fit within a single FIXNUM. * * @param[in] result The result of the system call. * @param[in] error The value of `errno`. * @return A `VALUE` which contains the result and/or errno. */ static inline VALUE rb_fiber_scheduler_io_result(ssize_t result, int error) { if (result == -1) { return RB_INT2NUM(-error); } else { return RB_SIZE2NUM(result); } } /** * Apply an io result to the local thread, returning the value of the original * system call that created it and updating `int errno`. * * You should not directly try to interpret the result value as it is considered * an opaque representation. * * @param[in] result The `VALUE` which contains an errno and/or result size. * @post Updates `int errno` with the value if negative. * @return The original result of the system call. */ static inline ssize_t rb_fiber_scheduler_io_result_apply(VALUE result) { if (RB_FIXNUM_P(result) && RB_NUM2INT(result) < 0) { errno = -RB_NUM2INT(result); return -1; } else { return RB_NUM2SIZE(result); } } /** * Queries the current scheduler of the current thread that is calling this * function. * * @retval RUBY_Qnil No scheduler has been set so far to this thread (which * is the default). * @retval otherwise The scheduler that was last set for the current thread * with rb_fiber_scheduler_set(). */ VALUE rb_fiber_scheduler_get(void); /** * Destructively assigns the passed scheduler to that of the current thread * that is calling this function. If the scheduler is set, non-blocking fibers * (created by `Fiber.new` with `blocking: false`, or by `Fiber.schedule`) call * that scheduler's hook methods on potentially blocking operations, and the * current thread will call scheduler's `#close` method on finalisation * (allowing the scheduler to properly manage all non-finished fibers). * `scheduler` can be an object of any class corresponding to * `Fiber::SchedulerInterface`. Its implementation is up to the user. * * @param[in] scheduler The scheduler to set. * @exception rb_eArgError `scheduler` does not conform the interface. * @post Current thread's scheduler is `scheduler`. */ VALUE rb_fiber_scheduler_set(VALUE scheduler); /** * Identical to rb_fiber_scheduler_get(), except it also returns ::RUBY_Qnil in * case of a blocking fiber. As blocking fibers do not participate schedulers' * scheduling this function can be handy. * * @retval RUBY_Qnil No scheduler is in effect. * @retval otherwise The scheduler that is in effect, if any. */ VALUE rb_fiber_scheduler_current(void); /** * Identical to rb_fiber_scheduler_current(), except it queries for that of the * passed thread instead of the implicit current one. * * @param[in] thread Target thread. * @exception rb_eTypeError `thread` is not a thread. * @retval RUBY_Qnil No scheduler is in effect in `thread`. * @retval otherwise The scheduler that is in effect in `thread`. */ VALUE rb_fiber_scheduler_current_for_thread(VALUE thread); /** * Converts the passed timeout to an expression that rb_fiber_scheduler_block() * etc. expects. * * @param[in] timeout A duration (can be `NULL`). * @retval RUBY_Qnil No timeout (blocks indefinitely). * @retval otherwise A timeout object. */ VALUE rb_fiber_scheduler_make_timeout(struct timeval *timeout); /** * Closes the passed scheduler object. This expects the scheduler to wait for * all fibers. Thus the scheduler's main loop tends to start here. * * @param[in] scheduler Target scheduler. * @return What `scheduler.close` returns. */ VALUE rb_fiber_scheduler_close(VALUE scheduler); /** * Nonblocking `sleep`. Depending on scheduler implementation, this for * instance switches to another fiber etc. * * @param[in] scheduler Target scheduler. * @param[in] duration Passed as-is to `scheduler.kernel_sleep`. * @return What `scheduler.kernel_sleep` returns. */ VALUE rb_fiber_scheduler_kernel_sleep(VALUE scheduler, VALUE duration); /** * Identical to rb_fiber_scheduler_kernel_sleep(), except it can pass multiple * arguments. * * @param[in] scheduler Target scheduler. * @param[in] argc Number of objects of `argv`. * @param[in] argv Passed as-is to `scheduler.kernel_sleep` * @return What `scheduler.kernel_sleep` returns. */ VALUE rb_fiber_scheduler_kernel_sleepv(VALUE scheduler, int argc, VALUE * argv); /* Description TBW */ #if 0 VALUE rb_fiber_scheduler_timeout_after(VALUE scheduler, VALUE timeout, VALUE exception, VALUE message); VALUE rb_fiber_scheduler_timeout_afterv(VALUE scheduler, int argc, VALUE * argv); int rb_fiber_scheduler_supports_process_wait(VALUE scheduler); #endif /** * Nonblocking `waitpid`. Depending on scheduler implementation, this for * instance switches to another fiber etc. * * @param[in] scheduler Target scheduler. * @param[in] pid Process ID to wait. * @param[in] flags Wait flags, e.g. `WUNTRACED`. * @return What `scheduler.process_wait` returns. */ VALUE rb_fiber_scheduler_process_wait(VALUE scheduler, rb_pid_t pid, int flags); /** * Nonblocking wait for the passed "blocker", which is for instance * `Thread.join` or `Mutex.lock`. Depending on scheduler implementation, this * for instance switches to another fiber etc. * * @param[in] scheduler Target scheduler. * @param[in] blocker What blocks the current fiber. * @param[in] timeout Numeric timeout. * @return What `scheduler.block` returns. */ VALUE rb_fiber_scheduler_block(VALUE scheduler, VALUE blocker, VALUE timeout); /** * Wakes up a fiber previously blocked using rb_fiber_scheduler_block(). * * @param[in] scheduler Target scheduler. * @param[in] blocker What was awaited for. * @param[in] fiber What to unblock. * @return What `scheduler.unblock` returns. */ VALUE rb_fiber_scheduler_unblock(VALUE scheduler, VALUE blocker, VALUE fiber); /** * Nonblocking version of rb_io_wait(). Depending on scheduler implementation, * this for instance switches to another fiber etc. * * The "events" here is a Ruby level integer, which is an OR-ed value of * `IO::READABLE`, `IO::WRITABLE`, and `IO::PRIORITY`. * * @param[in] scheduler Target scheduler. * @param[in] io An io object to wait. * @param[in] events An integer set of interests. * @param[in] timeout Numeric timeout. * @return What `scheduler.io_wait` returns. */ VALUE rb_fiber_scheduler_io_wait(VALUE scheduler, VALUE io, VALUE events, VALUE timeout); /** * Nonblocking wait until the passed IO is ready for reading. This is a * special case of rb_fiber_scheduler_io_wait(), where the interest is * `IO::READABLE` and timeout is never. * * @param[in] scheduler Target scheduler. * @param[in] io An io object to wait. * @return What `scheduler.io_wait` returns. */ VALUE rb_fiber_scheduler_io_wait_readable(VALUE scheduler, VALUE io); /** * Nonblocking wait until the passed IO is ready for writing. This is a * special case of rb_fiber_scheduler_io_wait(), where the interest is * `IO::WRITABLE` and timeout is never. * * @param[in] scheduler Target scheduler. * @param[in] io An io object to wait. * @return What `scheduler.io_wait` returns. */ VALUE rb_fiber_scheduler_io_wait_writable(VALUE scheduler, VALUE io); /** * Nonblocking read from the passed IO. * * @param[in] scheduler Target scheduler. * @param[out] io An io object to read from. * @param[out] buffer Return buffer. * @param[in] length Requested number of bytes to read. * @retval RUBY_Qundef `scheduler` doesn't have `#io_read`. * @return otherwise What `scheduler.io_read` returns `[-errno, size]`. */ VALUE rb_fiber_scheduler_io_read(VALUE scheduler, VALUE io, VALUE buffer, size_t length); /** * Nonblocking write to the passed IO. * * @param[in] scheduler Target scheduler. * @param[out] io An io object to write to. * @param[in] buffer What to write. * @param[in] length Number of bytes to write. * @retval RUBY_Qundef `scheduler` doesn't have `#io_write`. * @return otherwise What `scheduler.io_write` returns `[-errno, size]`. */ VALUE rb_fiber_scheduler_io_write(VALUE scheduler, VALUE io, VALUE buffer, size_t length); /** * Nonblocking read from the passed IO at the specified offset. * * @param[in] scheduler Target scheduler. * @param[out] io An io object to read from. * @param[out] buffer Return buffer. * @param[in] length Requested number of bytes to read. * @param[in] offset The offset in the given IO to read the data from. * @retval RUBY_Qundef `scheduler` doesn't have `#io_read`. * @return otherwise What `scheduler.io_read` returns. */ VALUE rb_fiber_scheduler_io_pread(VALUE scheduler, VALUE io, VALUE buffer, size_t length, off_t offset); /** * Nonblocking write to the passed IO at the specified offset. * * @param[in] scheduler Target scheduler. * @param[out] io An io object to write to. * @param[in] buffer What to write. * @param[in] length Number of bytes to write. * @param[in] offset The offset in the given IO to write the data to. * @retval RUBY_Qundef `scheduler` doesn't have `#io_write`. * @return otherwise What `scheduler.io_write` returns. */ VALUE rb_fiber_scheduler_io_pwrite(VALUE scheduler, VALUE io, VALUE buffer, size_t length, off_t offset); /** * Nonblocking read from the passed IO using a native buffer. * * @param[in] scheduler Target scheduler. * @param[out] io An io object to read from. * @param[out] buffer Return buffer. * @param[in] length Requested number of bytes to read. * @retval RUBY_Qundef `scheduler` doesn't have `#io_read`. * @return otherwise What `scheduler.io_read` returns. */ VALUE rb_fiber_scheduler_io_read_memory(VALUE scheduler, VALUE io, void *buffer, size_t size, size_t length); /** * Nonblocking write to the passed IO using a native buffer. * * @param[in] scheduler Target scheduler. * @param[out] io An io object to write to. * @param[in] buffer What to write. * @param[in] length Number of bytes to write. * @retval RUBY_Qundef `scheduler` doesn't have `#io_write`. * @return otherwise What `scheduler.io_write` returns. */ VALUE rb_fiber_scheduler_io_write_memory(VALUE scheduler, VALUE io, const void *buffer, size_t size, size_t length); /** * Nonblocking close the given IO. * * @param[in] scheduler Target scheduler. * @param[in] io An io object to close. * @retval RUBY_Qundef `scheduler` doesn't have `#io_close`. * @return otherwise What `scheduler.io_close` returns. */ VALUE rb_fiber_scheduler_io_close(VALUE scheduler, VALUE io); /** * Nonblocking DNS lookup. * * @param[in] scheduler Target scheduler. * @param[in] hostname A host name to query. * @retval RUBY_Qundef `scheduler` doesn't have `#address_resolve`. * @return otherwise What `scheduler.address_resolve` returns. */ VALUE rb_fiber_scheduler_address_resolve(VALUE scheduler, VALUE hostname); RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_FIBER_SCHEDULER_H */ PK!i i io/buffer.hnu[#ifndef RUBY_IO_BUFFER_T #define RUBY_IO_BUFFER_T 1 /** * @file * @author Samuel Williams * @date Fri 2 Jul 2021 16:29:01 NZST * @copyright Copyright (C) 2021 Samuel Williams * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. */ #pragma once #include "ruby/ruby.h" #include "ruby/internal/config.h" RBIMPL_SYMBOL_EXPORT_BEGIN() // WARNING: This entire interface is experimental and may change in the future! #define RB_IO_BUFFER_EXPERIMENTAL 1 RUBY_EXTERN VALUE rb_cIOBuffer; RUBY_EXTERN size_t RUBY_IO_BUFFER_PAGE_SIZE; RUBY_EXTERN size_t RUBY_IO_BUFFER_DEFAULT_SIZE; enum rb_io_buffer_flags { // The memory in the buffer is owned by someone else. // More specifically, it means that someone else owns the buffer and we shouldn't try to resize it. RB_IO_BUFFER_EXTERNAL = 1, // The memory in the buffer is allocated internally. RB_IO_BUFFER_INTERNAL = 2, // The memory in the buffer is mapped. // A non-private mapping is marked as external. RB_IO_BUFFER_MAPPED = 4, // The buffer is locked and cannot be resized. // More specifically, it means we can't change the base address or size. // A buffer is typically locked before a system call that uses the data. RB_IO_BUFFER_LOCKED = 32, // The buffer mapping is private and will not impact other processes or the underlying file. RB_IO_BUFFER_PRIVATE = 64, // The buffer is read-only and cannot be modified. RB_IO_BUFFER_READONLY = 128 }; enum rb_io_buffer_endian { RB_IO_BUFFER_LITTLE_ENDIAN = 4, RB_IO_BUFFER_BIG_ENDIAN = 8, #if defined(WORDS_BIGENDIAN) RB_IO_BUFFER_HOST_ENDIAN = RB_IO_BUFFER_BIG_ENDIAN, #else RB_IO_BUFFER_HOST_ENDIAN = RB_IO_BUFFER_LITTLE_ENDIAN, #endif RB_IO_BUFFER_NETWORK_ENDIAN = RB_IO_BUFFER_BIG_ENDIAN }; VALUE rb_io_buffer_new(void *base, size_t size, enum rb_io_buffer_flags flags); VALUE rb_io_buffer_map(VALUE io, size_t size, off_t offset, enum rb_io_buffer_flags flags); VALUE rb_io_buffer_lock(VALUE self); VALUE rb_io_buffer_unlock(VALUE self); int rb_io_buffer_try_unlock(VALUE self); VALUE rb_io_buffer_free(VALUE self); int rb_io_buffer_get_bytes(VALUE self, void **base, size_t *size); void rb_io_buffer_get_bytes_for_reading(VALUE self, const void **base, size_t *size); void rb_io_buffer_get_bytes_for_writing(VALUE self, void **base, size_t *size); VALUE rb_io_buffer_transfer(VALUE self); void rb_io_buffer_resize(VALUE self, size_t size); void rb_io_buffer_clear(VALUE self, uint8_t value, size_t offset, size_t length); // The length is the minimum required length. VALUE rb_io_buffer_read(VALUE self, VALUE io, size_t length); VALUE rb_io_buffer_pread(VALUE self, VALUE io, size_t length, off_t offset); VALUE rb_io_buffer_write(VALUE self, VALUE io, size_t length); VALUE rb_io_buffer_pwrite(VALUE self, VALUE io, size_t length, off_t offset); RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_IO_BUFFER_T */ PK!k߬q q thread_native.hnu[#ifndef RUBY_THREAD_NATIVE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_THREAD_NATIVE_H 1 /** * @file * @author $Author: ko1 $ * @date Wed May 14 19:37:31 2014 * @copyright Copyright (C) 2014 Yukihiro Matsumoto * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. */ /* * This file contains wrapper APIs for native thread primitives * which Ruby interpreter uses. * * Now, we only support pthread and Windows threads. * * If you want to use Ruby's Mutex and so on to synchronize Ruby Threads, * please use Mutex directly. */ #if defined(_WIN32) #include typedef HANDLE rb_nativethread_id_t; typedef union rb_thread_lock_union { HANDLE mutex; CRITICAL_SECTION crit; } rb_nativethread_lock_t; typedef struct rb_thread_cond_struct rb_nativethread_cond_t; #elif defined(HAVE_PTHREAD_H) #include typedef pthread_t rb_nativethread_id_t; typedef pthread_mutex_t rb_nativethread_lock_t; typedef pthread_cond_t rb_nativethread_cond_t; #else #error "unsupported thread type" #endif RUBY_SYMBOL_EXPORT_BEGIN rb_nativethread_id_t rb_nativethread_self(); void rb_nativethread_lock_initialize(rb_nativethread_lock_t *lock); void rb_nativethread_lock_destroy(rb_nativethread_lock_t *lock); void rb_nativethread_lock_lock(rb_nativethread_lock_t *lock); void rb_nativethread_lock_unlock(rb_nativethread_lock_t *lock); void rb_native_mutex_lock(rb_nativethread_lock_t *lock); int rb_native_mutex_trylock(rb_nativethread_lock_t *lock); void rb_native_mutex_unlock(rb_nativethread_lock_t *lock); void rb_native_mutex_initialize(rb_nativethread_lock_t *lock); void rb_native_mutex_destroy(rb_nativethread_lock_t *lock); void rb_native_cond_signal(rb_nativethread_cond_t *cond); void rb_native_cond_broadcast(rb_nativethread_cond_t *cond); void rb_native_cond_wait(rb_nativethread_cond_t *cond, rb_nativethread_lock_t *mutex); void rb_native_cond_timedwait(rb_nativethread_cond_t *cond, rb_nativethread_lock_t *mutex, unsigned long msec); void rb_native_cond_initialize(rb_nativethread_cond_t *cond); void rb_native_cond_destroy(rb_nativethread_cond_t *cond); RUBY_SYMBOL_EXPORT_END #endif PK!EGGinternal/attr/packed_struct.hnu[#ifndef RBIMPL_ATTR_PACKED_STRUCT_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_PACKED_STRUCT_H /** * @file * @author Ruby developers * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_PACKED_STRUCT_BEGIN, * #RBIMPL_ATTR_PACKED_STRUCT_END, * #RBIMPL_ATTR_PACKED_STRUCT_UNALIGNED_BEGIN, and * #RBIMPL_ATTR_PACKED_STRUCT_UNALIGNED_END. */ #include "ruby/internal/config.h" #ifndef RBIMPL_ATTR_PACKED_STRUCT_BEGIN # define RBIMPL_ATTR_PACKED_STRUCT_BEGIN() /* void */ #endif #ifndef RBIMPL_ATTR_PACKED_STRUCT_END # define RBIMPL_ATTR_PACKED_STRUCT_END() /* void */ #endif #if UNALIGNED_WORD_ACCESS # define RBIMPL_ATTR_PACKED_STRUCT_UNALIGNED_BEGIN() RBIMPL_ATTR_PACKED_STRUCT_BEGIN() # define RBIMPL_ATTR_PACKED_STRUCT_UNALIGNED_END() RBIMPL_ATTR_PACKED_STRUCT_END() #else # define RBIMPL_ATTR_PACKED_STRUCT_UNALIGNED_BEGIN() /* void */ # define RBIMPL_ATTR_PACKED_STRUCT_UNALIGNED_END() /* void */ #endif #endif PK!json-2.7.2/gem.build_completenu[PK![ppjson-2.7.2/json/ext/parser.sonuȯELF>@i@8 @xXxX 0]0] 0]  ]] ] 888$$XXXXXX StdXXXXXX PtdTTTQtdRtd0]0] 0] GNUY <gMWFD@ DGBE|ŷ|!qXG TZqUD_p;1u K["".&`ev, 0F" Ga Zb ; @ENa __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeruby_xfreerb_gc_mark_mayberuby_xrealloc2ruby_xmalloc2rb_check_typeddatarb_str_duprb_eTypeErrorrb_raiserb_funcallvrb_ary_entryrb_ary_push__stack_chk_failrb_data_typed_object_zallocruby_xmallocrb_error_arityrb_keyword_given_prb_string_valuerb_enc_getrb_ascii8bit_encodingrb_utf8_encodingrb_str_conv_encrb_hash_duprb_id2symrb_hash_arefrb_enc_associaterb_eArgErrorrb_fix2intrb_unexpected_typerb_enc_interned_strmemcpyrb_utf8_str_newrb_str_internrb_enc_raiserb_ary_new_caparb_hash_foreachrb_obj_freeze_inlinerb_class_new_instancerb_cstr2inumrb_hash_newrb_ary_newrb_respond_torb_str_new_cstrrb_hash_asetrb_cstr_to_dblrb_float_newrb_class_namestrrchrrb_str_substrrb_path_to_classrb_sym2idrb_mKernelInit_parserrb_ext_ractor_saferb_requirerb_define_modulerb_define_module_underrb_cObjectrb_define_class_underrb_path2classrb_gc_register_mark_objectrb_define_alloc_funcrb_internrb_const_getrb_define_methodlibruby.so.3.3libm.so.6libpthread.so.0libc.so.6_edata__bss_start_endGLIBC_2.14GLIBC_2.2.5GLIBC_2.4/opt/alt/ruby33/lib64=_ui jii v0] P8] @] @] `] 6Jh]  p] x] _ _ _ _ #_ :_ ;_ <_ =`  ` (` 0` 8` @`  H`  P`  X`  ``  h` p` x` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `  a !a "a $a % a &(a '0a (8a )@a *Ha +Pa ,Xa -`a .ha /pa 0xa 1a 2a 3a 4a 5a 6a 7a 8a 9a =a >a ?a @a Aa Ba CHHI HtH5J %J hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1%MF D%EF D%=F D%5F D%-F D%%F D%F D%F D% F D%F D%E D%E D%E D%E D%E D%E D%E D%E D%E D%E D%E D%E D%E D%E D%E D%E D%}E D%uE D%mE D%eE D%]E D%UE D%ME D%EE D%=E D%5E D%-E D%%E D%E D%E D% E D%E D%D D%D D%D D%D D%D D%D D%D D%D D%D D%D D%D D%D D%D D%D D%D D%D D%}D D%uD DHf.DH=QD HJD H9tHA Ht H=!D H5D H)HHH?HHtHA HtfD=C u+UH=A Ht H=? dC ]wH V5Hx=WHx0HH WHxHH WHxHH øf.HGhH@Hpff.@USHHHohH}HtHHH[]ff.SHH?H{ H{@H{HH{PH{`[fATIUHSHtWHOIT$HH)H9v:HHHH)H9rH9vI|$HI\$ID$[]A\@H? I $ID$IL$ff.HH5a= H8Ht HH? H5](H81AUATUSHdH%(HD$1H$t&IH55B HI11LHu#1HL$dH3 %(uIH[]A\A]@1LfHHH5|A H$HtLLUHt< pSH%HHh @uHh f@H@HHEhHH[]DAVIAUIH5 < ATUHSH dH%(HD$1H8f.HHcMdIEHD$uCXHC HC(dHC@HCHHCPLd$LHHII92MHIHLH$HLHl$HD$HPHSHPH tHPHLHSHL$dH3 %(H []A\A]A^L IăIEHD$IH=? Hl$HLH5]? IHD$XHC(dH=^? HLH5? IHD$H^C,H=? KHLH5> IHD$HC4H=r> HLH5> IHD$HC8H=> HLH5e> IHD$`HCXH=~> HLH5'> IHD$"HFLL;HC H=> KHLH5= IHD$HXHC@H== HLH5= IHD$HHCHH== HLH5c= IHD$^HHCPH=#= HLH5$= IHD$HHC`fD@uHuEHHHHDH5= H=B= 11HC HEHƒHttfLLH-C((DLLHHDHC`DLLe1H‰SXS4HH9 H5#H81DLLHC8NfLLHC4LLHC,LLHCH@LLHC@@LLHCPtHLC(?H8 H5h!H81UHAWAVIAUIATSH8UMdH%(HE1HH)HEH=HuHHEHHHH%H)HHH9tHH$H9uHD$HHEL}M1M9w mI9vWIA<$\I\$uM9vLL)IAD$M LH+]I\$Iw+DEĿHuH3HE)Iv:IIE?HuMH)HLLA?HuĿHAȀDEňEA|$u I|$I\$ %LI %HEHHI I LHuHELH ?ȀELH?ȀED?ȀEHLLLHuH ELA?HAȀ?DEƃȀEGH}w#H6 iLHHH1RH}2H}w#H6 ,LHJHH1H}\f.AVAUIATUHSHHdH%(HD$1HwH9n>"E1EXtcHm`HtVTIuIHH5NHLLHAu HCfD1Ht$dH34%(H[]A\A]A^DHL`L9H"t7\uL`L9Hu1Lf.M0u1u81҅H{LUXIELH@}41ɺIUH54 HHH$QIEADHpH9]H@0 HpH9)H@0 HpH9H@0 wgL`L9 @<@0< LE1Hm`HLAF]aQHFcaWfFeaYffDHEH9t}rmDAG8t I}E1Ht$HdH34%(LHX[]A\A]A^A_fDHDHH9q멃0 wHEH9C H5LH%A, H1 Le IEDHEH9C}a9HEH9,}N"Aw,H1 LeIEfA@IWHlj$AG(9H=^1 H5a1xHEH9}aHEH9}lHEH9}s{HEH9n}edIELeHEH9C}u9HEH9,}l"HEH9}l IELef.HEH9M*tb/tAO88 HH9ufHHhH9@<*t0@ CfDHD$(HD$HD$0HD$D$HL$HLHD$(LIHIHHt$(I}Ht$0HL$H5- QID$HPH9t-H, t HHPH9uIfDH11IEH9t<}{Hu3LBL9t*B<"< t< LLBL9uIC  LLrL9JA/]HILDfD*uIL9A<*t uLrL9toB<*tB u6@IL9t*u@ @CH( LHHH1{afD),-IIPH5' ZnMgPL' IGIOhLH)HAH4$HϾLD$H $H $LD$HAHQL$IGhHAMHxmL$HL$(LHD$(LIEImLIoH9aIFH9tAV+t-uIFH9tAV0 HH9Ee.0 vfD <)0HD$ L5H$HD$(HD$HD$0HD$H $HLLAG0AG0HHHHAH9Q  /:HpH9HQndIcL>0 uDHL$EHLHD$(tHKI@H|$ HD$H|$0I}HD$(HL$H5% HD$8LD$I@L@L9P,t>P t TLL@L9uf< t <LIL9B< t~<" tHH9uHH9<*t*u H/t} uDLBL9cB<*tK0@ wpE1HHHHs@*tI@/tH#: tHH9uHHZH9R*t/tH@HH9:*u@@ M@\:H{ H5LH81fH~H=H=H5HHU H1 H5HHH=tH! TH=sH AH= H H= H= H5H= HH=}H=K HHH H=H=! HHH H=nH=H [H=H HH=H 5H=Hg "H=yH=yH@ H=pH% H=mH  H=gH H=`H H=[H H=NH H=HHs ~H=:Hx kH=6H] XH='H2 EH=H 2H=H H=H H=H H=H HHHuninitialized instancealready initialized instance \" nesting of %d is too deepunexpected token at '%s'-Infinityjson/commonJSONExtJSON::ParserErrorJSON::NestingErrorinitializeparsesourceNaNMinusInfinityjson_creatable?json_createcreate_idcreate_additionschrmax_nestingallow_nansymbolize_namesobject_classarray_classdecimal_classmatchmatch_stringkey?deep_const_get[]=[]<<newtry_convertfreeze-@JSON/Parseroptions :symbolize_names and :create_additions cannot be used in conjunctionincomplete unicode character escape sequence at '%s'incomplete surrogate pair at '%s'xx@0pTTd\B000000000000000000B0,0000000000,00000000000000000000000000,0000,000000000000,0000000000,0000000,00000,000000,TBBBBBBBBBBBBBBBBBBTBBBBBBBBBBBB\BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB  ;0t `@\0p  0HtzRx $xFJ w?:*3$"D \Vp$5EAG ^DA>Et,<BDD V ABE =HX E 8FBA A(I@R (A ABBE $P4[EMD DA@xlFEL A(F0DP* 0A(A BBBD zRx P(D,&AC DEJ^ K @$IBBE A(D0G@ 0A(A BBBF Hh(BEB E(A0A8D 8A0A(B BBBG (NEHD0l AAA HGNUP@] 6J #-=  `H0] 8] o`X   ` (h ooo o]  0@P`p 0@P`p 0@P`p 0@P`pGA$3a1mH GA$3p1113^HGA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFY`^HGA+GLIBCXX_ASSERTIONSparser.so-3.3.11-9.el8.x86_64.debugXj7zXZִF!t/G]?Eh=ڊ2N Um [ƋS w)dh:6bﳼA{o*4E"#B؛7TC˂=q^ΘfR.sOj#EAbe *U{Ѧ}|F-{顕GhMGBbroB)FH/siաTTDav?>M¦ GU2x%?S!fV.wBkiT|D},XLLv|sI5{WT)P @`@8 @uu }} }  }} } 888$$uuu Stduuu PtdfffttQtdRtd}} } GNUb@ 8?J-,DmfN@$NPQBE|qXt)eV 0)@_c# 'ZhUons ~j_y""OY?JB5J, |IF"4s4    pWK __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizerb_check_typeddataruby_xfreeruby_xmallocruby_xrealloc2ruby_xmalloc2memcpyrb_str_newrb_utf8_encodingrb_enc_associaterb_hash_newrb_obj_classrb_class_namerb_funcallvrb_hash_asetrb_str_new_static__stack_chk_failrb_call_superrb_exc_raiserb_str_duprb_str_catrb_str_concatrb_str_internrb_sym2idrb_ivar_setrb_attr_getrb_data_typed_object_zallocrb_obj_is_kind_ofrb_cHashrb_class_new_instancerb_intern2rb_ary_entryrb_string_value_cstrrb_iv_getrb_str_substrrb_id2symrb_rescuerb_eArgErrorrb_raiserb_enc_getrb_usascii_encodingrb_str_export_to_encrb_enc_str_asciionly_prb_path2classrb_error_arityrb_string_value_ptrrb_float_valuerb_hash_foreachrb_unexpected_typerb_hash_arefrb_check_convert_typerb_convert_typerb_cFloatrb_cFalseClassrb_cArrayrb_cStringrb_respond_torb_cIntegerrb_cNilClassrb_cTrueClassrb_cSymbolrb_sym2strInit_generatorrb_ext_ractor_saferb_requirerb_define_modulerb_define_module_underrb_gc_register_mark_objectrb_cObjectrb_define_class_underrb_define_alloc_funcrb_define_aliasrb_internrb_define_methodrb_define_singleton_methodlibruby.so.3.3libm.so.6libpthread.so.0libc.so.6_edata__bss_start_endGLIBC_2.2.5GLIBC_2.14GLIBC_2.4/opt/alt/ruby33/lib64ui ii } P!} ! }  } @} WdP} $X} @"        " * 4 7 A B C E M  ( 0 8 @ H  P  X  `  h p x          Ȁ Ѐ ؀   ! # $ % & ' ( )( +0 ,8 -@ .H /P 0X 1` 2h 3p 5x 6 8 9 : ; < = > ? @ȁ DЁ E؁ F G H I J K LHHqg HtH5g %g hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>%c D%c D%c D%c D%c D%c D%}c D%uc D%mc D%ec D%]c D%Uc D%Mc D%Ec D%=c D%5c D%-c D%%c D%c D%c D% c D%c D%b D%b D%b D%b D%b D%b D%b D%b D%b D%b D%b D%b D%b D%b D%b D%b D%}b D%ub D%mb D%eb D%]b D%Ub D%Mb D%Eb D%=b D%5b D%-b D%%b D%b D%b D% b D%b D%a D%a D%a D%a D%a D%a D%a D%a D%a DHHHHf.fH=ia Hba H9tH^ Ht H=9a H52a H)HHH?HHtH^ HtfD=` u+UH=^ Ht H=[ d` ]wH7Hthv$HtNHu8R1€?v2fHuBHt)HHH$H5V HfHW 11H6fDAWAVAUATIUSH(dH%(HD$1H5Q LHTHHU Hu&L-4fDLHU Ht11HL@E1IHD$HD$HI9LLI9H5V 11HH|$HD$H@H$LHtH|$IH$HPJHLHHI pIFI9sHsH;_H=pU ILHHHsH{5H=>U ILHHhHs(H{ H= U ILHH>Hs8H{0H=T ILHHHsHH{@H=T IhLHH{pH=wT MGIHAHL{qH=GT MIHAHLHChH=/T LdLHHw{rH=S MIHAHLO{sH=tS MIHAHL'HCxH=lS LdLHHHH=>S H\\HHHHHL$dH3 %(uH([]A\A]A^A_ATIHUHSH+H{HH{LHk[]A\ff.@ATH5M USHHHkXIH)HEHHEHU,HEHk`HHEHs Ht HS(HHsHEHU:HsHEHt HSHuhHkPHtqHEH2HEHU,Hs@HEHt HSHHuL[]A\H{PL[]A\H{`HkPHuHHCPHxHk`/nHHCXfVHHC`f.ATIUSHH0dH%(HD$(1MH5L HHKHHH=:#HH,$H\$HD$Ld$HHT$(dH3%(u H0[]A\fUSHH^HH5K HHH[]fH/f  Nf Nуf NF%DISH3H dH%(HD$1HIH?LII1I)fLLLIIHHHI)BIAAHuHyHAA-LILL9v#f0HH@qPH9wM)uHD$dH3%(uH [LLM6fDUHSHHH>fDImHtImMe\uLE1D$$ft$"E1ɉD$ MMJ|-<PH5.HcH>L=*@LL)HLHMMMM9wLL)tJt HHfHHCHS"HCHD$(dH3%(xH8[]A\A]A^A_1AIHHHAIHHAIHHHAIHHAIHH.J+IHH(H=HBH_H/H\iH"HHCHKD4HCL9gAH -IfALH9H=4)fH5_,H1D1f1f1f1fAIHLL=(L)Jt HH$H$fDL=e(L=S(L=A(fH5'00ffL$$L|$"D$'T$&Jf.HD$HD$HD$l@H5&H?H5&HH5]&HtH5C&HTH5)&H4DLHDHILHLH f(rDLHff$WRfH5%H7M} GPXM)uKMfDJt LH߈$$H=%4H5](H1SH=$H5p(H161f.ATUSxdIuWH=cF H5@ HHHHHSrHsqLHH[H]A\oH6t1@UHSH(Ht$H\$HdH%(HD$1HT$H\$HRHL$HuHD$dH3%(uH([]fDHHff.ATIHUHSHHm11H5(E HD$ @u"D$f(fT (f. (wf.zHLH[]A\H=D H1H5Y#ATUSx\IuOH=D H5? HHLHH1HspLHH[H]A\H6t1|ff.SHHH52D 11H[HMff.fUSHxZHuMH=!D lH5U> HHHHu2HHHH[]1H6t1@HHHHH[]ff.AWAVAUATIUHSHHHLz0L*H $LrdH%(HD$81HB8HD$HBhHRxHJHMxHt H9HHCHSH5H<${HT$HCLd$ H\$Hl$D$()LexID$HExMtGH|$uMt:H~5A1 DD9t MtLLH߃D9uDHHCHS}HCHD$8dH3%(uNHH[]A\A]A^A_HT$LHH$H$MeHUxH= B H5 1Off.@AUATUSHxfIuYH=A 8H5!< HHfHIKLLHHHHH[]A\A]DH6t1ff.Sx_uUH=iA H5; HHHH5HHsH[zf.H6t1 ff.Sx_uUH=@ 4H5; HHbHJH5SHHH[f.H6t1ff.Sx_uUH=i@ H5: HHHH5HHsH[zf.H6t1 ff.SHH51: |3HHXhH[SHH5: LHHXx[DSHH59 HH~H[ff.fUHSHHuHt HHtHGHHH[]ff.fSHHdH%(HD$1uHt HHtHH=dHHH=xHHHH5= H$5HT$dH3%(uH[f.ATUSHH5~8 uHtHHHƒHt H0LcH}0Mu#Ht yHE0[]A\HtVHH{ tH{LLe8HE0[]A\ff.ATUSHH57 uHtHHHƒHt HLcH}@Mu#Ht HE@[]A\HtHH{ tH{LLeHHE@[]A\ff.ATUSHH57 iuHtHHHƒHt HLcH} Mu+HtHE HE([]A\HtHH{ tH{LfLe(HE []A\@ATUSHH5n6 uHtHHHƒHt H LcH}Mu+HtiHEHE[]A\Ht>HH{ tH{LLeHE[]A\@ATUSHH55 uHtHHHƒHt HpLcH}Mu+HtHEHE[]A\HtHH{ tH{LLeHE[]A\@AT1UHH5: SH1x=Iu/AuMt I$Ht*LDHutͺ1qH=i: [L]HA\eDAVAUIH5~4 ATIUSHdH%(HD$1H LHHHHH=9 GHHHH=y9 $HHHH=N9 HHHH=9 HHH7H=9 HHHTH=8 ILHHEhdH5s8 IH$H#H=<8 WLHHExH558 IH$H H=7 LHH57 IH$[HH=8 HHH=7 HEpHHH=7 HEqHHvHErH=A7 |HHQHLEsHL$dH3 %(H[]A\A]A^LHHHEh@LHHHEx@LHHHHHfH=q6 HHyHErf.H HLH DsHHEh@[HHEx@PHuHHуHuLhIu HxLmHEfDuHHуHuLhIu HxSLm(HE fDhHHуHULhIu txHxLmHHE@f(HHуHLhIu tHHxLm8HE0nfHxHxOHxf.Hxf.HHуHLhIu t HxWLmHEjf.HxUDATIUHH5L/ SHH@hdHǀxuL[]A\Hut1HtLkL[]A\AUIATIUHSHHdH%(HD$1HfHtqHH T [H0 H 0 HH9uKDHHLLHD$dH3%(wH[]A\A]H0 HH 0 H9tH 0 H9H s0 H9*H@HHmuHH H!0 H9}sH573 HG?HHL,$H53 8H/HHHLHQH/ HHLHDHHLLWfH5ILHUrHuqHL=iH5LHH / H[H / HKH5LlH51 11HuHuLHH. HHLeHupHLA@HHuHUrHuqHLIuH=h1 H51f.AWAVAUIHATUHSHXHB@LzHT$HD$8HBHHt$ HD$@HHRhHD$HAPHxH@H|$HHyxHD$HwH|$0Ht$(HqxHt H9HfHEHU[HEH|$8t H|$@}D$01D`QDHH9}RH|$tH|$HLHiHT$Ht$ HHIE uIEH9|HD$HT$0H|$8HPxtOH|$@Ll$Mt9HD$0H~/A1 DA9tMtLLH2A9uH`HEHU]HEHX[]A\A]A^A_H|$(,E1AE9MtHt$LH@HT$Ht$HHHT$@Ht$8HLl$M#WHT$@Ht$8HrlHH5 1HzxHH=. ff.AUATUSHxfIuYH=. (H5) HHVHI;LLHHH7HH[]A\A]DH6t1|ff.HHOHWHwH?Hf.AWIAVAUATUSHHHLrHBHt$ H*Iv`I~XHD$IIN0M^8MfHWMnxHD$HFHD$(HFHD$C~ HHt MH|$tKM~FEH\$0E1LEAE9tHtHt$HHAE9uH\$0AuMuAMI~IARA H) Hv@H ) IWH;H ) H9tjH5, L11IAuMu_LfLHHDH) HH G) H9tH ) H9uLIfIHuHt$LLHH|$u1HL$ Ht$LHCHH1[]A\A]A^A_HT$Ht$(HV@HwHL\$8HL$0:L\$8HL$0H( H+fHy( HHy( HHJ( H ( HH9fHH=) RH= H5 HHe+ H5 HH=s H;+ H= H+ H=* H* xH=* lH' H=* H5M HH5HH* IH=* HH5 zH=* HwH5z ;H=* HH5f H=e* 1HlH5Z H=I* HH5B H=** 1HH5. H=* HH5 H=) 1HvH5 H=) HH5kH=) 1HH5OH=) H) 1HH5H=") HH5H=) 1HJH5pH=( 1H.H5`H=( HH5NcH=( H"H5A9H=( HH54H=x( HH5(H=^( 1HEH5H=B( 1H)H5H=&( HH5H=( 1HH5H=' 1HBH5H=' 1HH5jH=' 1HH5NH=' HH5/H=x' 1H?H5H=\' HH5vH==' HH5nH=' H[H5^H=' 1HH5H=& HH5zuH=& HH5fH=& HH5GH=& H$H5(H=y& H5H5HHL& HcH5HH=%& H5HH5HH=% H5|HH5\HH=% H5TuHyH5.HZH=% H5.GHH5H,H=m% H5HH5HH<% H=0% HH5H=% HH5H=$ 1HH5H=$ H5HH5HH$ hH=$ H5UHH5H:H={$ H5`'HkH5H H=M$ H5=HH5H޿H=ҾH=H# 迾H=H# 謾H=H# 虾H=H# 膾H=Hx# sH=H]# `H=HB# MH=H'# :H=H # 'H=H" H=)H~" H=KHc" H=BH" ۽H=.H" ȽH=(HJ" 赽H=H/" 袽H=H\" 菽H=HA" |H=H&" iH=H " VH=H! CH=7H=H! $H=H! H=H=HHHC*@instance_variables0123456789abcdefunallocated JSON::State\n\r\t\f\b\\\"\/JSON::GeneratorError\u2028\u2029%li not allowed in JSONnesting of %ld is too deepnullfalsetrueto_hashHashto_hjson/commonExtGeneratorJSON::NestingErrorfrom_stateinitializeinitialize_copyindentindent=spacespace=space_beforespace_before=object_nlobject_nl=array_nlarray_nl=max_nestingmax_nesting=script_safescript_safe?script_safe=escape_slashescape_slash?escape_slash=strictstrict?strict=check_circular?allow_nan?ascii_only?depthdepth=buffer_initial_lengthbuffer_initial_length=configuremerge[][]=generateGeneratorMethodsObjectto_jsonArrayIntegerFloatStringincludedto_json_rawto_json_raw_objectExtendjson_createTrueClassFalseClassNilClassto_snewallow_nanascii_onlyunpackcreate_idextendkey?__send__respond_to?matchkeysdupJSON/Generator/Statepartial character in source, but hit endsource sequence is illegal/malformed utf-8source sequence is illegal/malformed utf8P@0 ``XhH01234567890    ;tM 0 ˹< Hx(@ؼXp8hȽ (ȾDXtؿ( H8X|(HX8XXxHXXhH PHX, \ x 8 8 HX x H x  D Hl X 8 p h (P HPhzRx $FJ w?:*3$"D\зp%HW0"HTH&HW`&HWx'HX&E`&HW0&E`Lй&HWd"HT|AUEvh/Am,|BDD V ABE (ܺ>FDO WAAF$,;AAG lDA0TFAD D0  DABA uEI0] DA E@FIB A(A0JP 0A(A BBBD 0ԼFEA J0t  AABB <pP|dx6H] K D9H] K D9H] K Dؽ9H] K D9H\ L D(EDM0q AAG H09FBB B(D0A8D` 8A0A(B BBBA (|1BGD `AB8BHA  ABH M ABH 0BDA GPo  AABA $T.EAG [DA@\K TKK0 AD 0xTEADG0T AAF ZAA,pXFDA 1 ABA HBBE E(I0A8Gp' 8A0A(B BBBH ,($|FAA N DBL (XtrADD@N AAG 0BGD G0M  GABE ,$tFAA J DBH t#AZ0EAD K DAF jDAL8BBB B(D0D8G 8A0A(B BBBD 84FBA A(D0O (D ABBJ tEL O tEL O HtEL O $)EczRx  p+EeP3Em$SEDI rIA EG  AA 4 `FAA X FBH pAB4T FAA X FBH pAB4 PFAA ` FBH pAB4 FAA ` FBH pAB4 @FAA ` FBH pAB(4 FCK iDE@` +FBL D(A0D@G 0A(A BBBD zRx @(4 mFDK g ABA iAB8 6BED D(G@ (A ABBA LP bBBB H(A0D8D 8A0A(B BBBA 8 ,FBA A(D0O (D ABBJ  &H]L FEB B(A0A8G 8C0A(B BBBH D K H> GNUP!! } Wd$@" 8 `} } o`H  '  PX ooopo} p 0@P`p 0@P`p 0@P`p 0@PGA$3a18` GA$3p1113P `GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFY`!`GA+GLIBCXX_ASSERTIONSgenerator.so-3.3.11-9.el8.x86_64.debugo 7zXZִF!t/Wi]?Eh=ڊ2Na`emJ6>Oډl)SG%/{pgA'V4c[ VH"%.PUJ ;4X?$29c _Z&8*\1?[`v!ΣBӈfe`)F9N.(a.MmrDN|;! yɿ3. Ի"s_ *~偈XevCPk}J=/z9VR? a9 S~)}^1+)U۸ow_e(+NLɈR [['x@-}W@ɳ Ek+ݚ]1 bdQA|G^0ӻčnTh;I[ĪOmu}ltx8M?P-X R [S ?it:=Y׼v<>[h $A c{8X' }AD1LWn04!&O>c6dks ugt4j |L Qƛ;-8IA 1+%K0dI>p5 43UB)ͬrx#;j2R,&i/%kf29Nъ#gN&c+e|iv`/ڪ֪8-+m̎lÓn\9cn?*A|3:[`[Kt0 o{ر& .TL5#%?}3?+17m?MKcNUܜ`Ɏm\ \_wUĠQؘ,W 8< -Oqc +)b}bqmvS!n{Swz}93 q&۷SwpnL7$d3=Nޙ\Z xӀL Jdp&pi!U nqOzaT#0{YIFXvlۑRzA# WM)yН!1W~ ˛ m>S`h_< A;"D"Э5ΛtƦWE& " 6SgYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 0H H '8oppEo@TXX^BPPh88c``n``wP P k@}`` `` fft0i0i` uu } }} } } }h } } x  `H X,0+PK!#io-console-0.7.1/gem.build_completenu[PK!L%0s0sio-console-0.7.1/io/console.sonuȯELF>@"@k@8 @XUXU ]] ] 8 ]] ] 888$$8U8U8U Std8U8U8U PtdIIIQtdRtd]] ] GNU?hruPu&PhHSH!@SUWBE|qX/Dok 04[MA_c%{U 'R@Dk""hv*fPw6e, F"r*@PrHb b Hb  Au PF__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizerb_check_typeddatacfmakerawrb_data_typed_object_zallocrb_default_rsrb_io_writerb_funcallvrb_errno_ptrtcsetattrrb_num2uintrb_sprintfrb_io_get_write_iorb_str_new_cstrrb_io_flushrb_io_getbyterb_ary_newrb_ary_pushrb_str_new__stack_chk_failrb_io_descriptortcflushrb_io_pathrb_sys_fail_strrb_Arrayioctlrb_eArgErrorrb_raiserb_string_value_cstrrb_ensurerb_stdinrb_stderrrb_error_aritytcgetattrrb_jump_tagrb_protectrb_syserr_failrb_io_getsrb_yieldrb_convert_typerb_assoc_newrb_str_new_staticrb_str_catfrb_cIOrb_cFilerb_const_definedrb_obj_freezerb_cloexec_openrb_io_open_descriptorrb_const_setrb_unexpected_typerb_const_getrb_io_closed_prb_id2symrb_check_idrb_keyword_given_prb_funcallv_kwrb_const_removerb_io_closerb_fix2intrb_num2intrb_check_funcallrb_get_kwargsrb_funcallv_publicrb_hash_duprb_ary_resizerb_ary_ptr_use_startrb_ary_ptr_use_endrb_obj_classInitVM_consolerb_f_notimplementrb_define_module_underrb_cObjectrb_define_class_underrb_define_constrb_define_alloc_funcrb_undef_methodInit_consolerb_internrb_define_methodrb_define_singleton_methodlibruby.so.3.3libm.so.6libpthread.so.0libc.so.6_edata__bss_startGLIBC_2.2.5GLIBC_2.4/opt/alt/ruby33/lib640ui ii  ui ] "] " ]  ] @] TI_ _  _  _ _  _ '_ (_ 2_ ;_ I_ K_ L_ M_ R`  ` (` 0` 8` @` H` P`  X`  ``  h` p` x` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` !` "a #a $a %a & a )(a *0a +8a ,@a -Ha .Pa /Xa 0`a 1ha 3pa 4xa 5a 6a 7a 8a 9a :a <a =a >a ?a @a Aa Va Ba Ca Da Eb Fb Gb Hb J b M(b N0b O8b P@b QHHYF HtH5F %F hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?h@hAhBhChDhE%-B D%%B D%B D%B D% B D%B D%A D%A D%A D%A D%A D%A D%A D%A D%A D%A D%A D%A D%A D%A D%A D%A D%}A D%uA D%mA D%eA D%]A D%UA D%MA D%EA D%=A D%5A D%-A D%%A D%A D%A D% A D%A D%@ D%@ D%@ D%@ D%@ D%@ D%@ D%@ D%@ D%@ D%@ D%@ D%@ D%@ D%@ D%@ D%}@ D%u@ D%m@ D%e@ D%]@ D%U@ D%M@ D%E@ D%=@ D%5@ D%-@ D%%@ D%@ D%@ D% @ D%@ DH=@ H? H9tH6= Ht H=? H5? H)HHH?HHtH5= HtfD=? u+UH="= Ht H=N: dm? ]wH"O {H g HHwH ff.@UHH59 SHHDHtH xHH[]D` HH[]f.ATIH59 UHSLH5|9 HooHKoP S HP0HS0@8C8H[]A\DUHSHHC ωC Ht.UxSUxSUtC HH H[]H8 <ff.SH8 H<kfoHP foKJfoS R HK0HJ0K8J8[ff.H: H0-ff.fH5= 11ff.HH5= H׉fDH5}= 11ff.USHH K8u&1HډuH[]f.H1[]SHH@H=y!p1HHDH[ff.@ATIUHHSLHSH=+!p1{HHH[]A\AUATUSHH(dH%(HD$1H~@uHu+HL$dH3 %(,H([]A\A]@HH uHDnHt$bHt$HHHHGH/DE1H H7{HH=g1IDHHt+H;tEPЃ w-THߍlPHuHLEt#A9uE1롐HcLHt-1@HcLD$Ht-H|$Nff.ATUSH@HA5H-t0A9t)1D7u,'uH[]A\D tHHAWAVAUATUSHHHdH%(HD$1cH HHJHHL8LhAHuL`HhHSHKH$A1ItLf$1ItLfD$1ItLfD$1HtHfD$H1TDKuYHL$dH3 %(HuVH[]A\A]A^A_DHPHJHu H@ HW6 H5H81HH^YfHH58 dH%(HD$1H5 HHH$HD$dH3%(uHSHdH%(HD$1HHtHHH$H4$HHD$dH3%(uH[ff.AUATAUSHHIHHH9tXAu HL_HWHHHH=HtHHD$HD$H[]A\A]H4 H9(uH4 H됺1@AUIATIUSHHXdH%(HD$H11uDHC0oLoKoS HD$0C8H)$H)L$)T$ D$8AHމHT$HdH3%(u HX[]A\A]Zf.AWMAVIAUE1ATUHSHHt$HT$dH%(H$1D$,0HHAău0D$,A|$,@HD$0HD$Ht$LLDH<AD$,D9AA!Ht$H|$HT$,MIǃtH]9EfHDHRuL"HjHLlHIaHHAT$HHcHTHHUHHcHTHPf.HHSH>AUATUH1SHhdH%(HD$X1HL$H\$>HIHމAu8LHHDt3HT$XdH3%(HuHh[]A\A]HHjeH-ff.fSH1H dH%(HD$1HL$ H5 HHIH HT$dH3%(uH [SH1H dH%(HD$1HL$ 8HH HIH5\HT$dH3%(uH [ATIH5 UHSHH`dH%(HD$X1 HL$LoH\$)D$oH)L$ oP )T$0HP0HT$@@81҉D$HHHHGHH|HL$XdH3 %(u H`[]A\ff.AUIH5 ATAHUSHH(dH%(HD$1J1HL$ LDHHHzHT$dH3%(uH(H[]A\A]WUHH5SHH H;H;HH5H;1HH5H;1HEH5yH;HH5^H;H_H5sCH;1HH5a+H;1HOH5OH;HH5AH;1HH57H;1HH5&H;HYH5H;1HAH5H;1HH5}H;1HH5eH;1HH5MH;H~H52H;1HH5H;HH5H;HH5{H;HH5jH;HH5[H;HH5LH;HH5>xH;HH5/]H;HnH5BH;HH5'H;HH5 H;1H`H5H- H;H5HH;H1H5H;HsH5H;HH5H;H5HH5HH_HH`H5yDH5 H;H5HH=|H SH= H5hH}H= H5H= H5GH= HH53H=q HUH5H=R HH5zH=3 H[H2H5h]UDHH=lH=HF YH=H FH=H 3H=4H H=H H=sH H=dH H=VH H=HHv Hr HAHH[%dG[%d;%dH[%d%cto_aryArrayexpected 2D coordinate/dev/ttywrong %s mode: %li screen erase[%dJline erase[%dKrawraw!cookedcooked!getchecho=echo?console_modeconsole_mode=noechowinsizewinsize=iflushioflushbeepgotocursorcursor=cursor_upcursor_downcursor_leftcursor_rightgoto_columnerase_lineerase_screenscroll_forwardscroll_backwardclear_screenpressed?check_winsize_changedgetpassconsolegeneric_readableConsoleMode0.7.1VERSIONinitializeinitialize_copygetcgetschomp!closemintimeintr__send__console-modewrong number of arguments (given %ld, expected 2 or 4)true or false expected as intr: %li ;>@0XPl`00L `@t``Tp0@L @p0T p`pL0p `Xt ` `4 h 0 ` 0, h @ ` L zRx $pFJ w?:*3$"D`\p 0FEKG V DAF HDA([FKD BAB$4XEDG EAA l4xBA@Pdx0IACG c FAK DCA1Ek(HFDG sAB8@FBA A(GPD (A ABBE ,XyFAA I ABD HgFBB B(A0A8JP 8A0A(B BBBF PD F A QC9@ #G' .cDRh7߶*IiA*ӳbI?[n'D r^e~Z˙;WL;20_N.>R!{"ډ >}iIM0T{e7;wcΙ[Xэ9 0HBuzW9Ϡgtv 4+`+MCF^F#AS@]#QoxvSD@`>:Qd5[XJn 7. yy)˱h=I9xҸN 3FWR2\2(;]9@F{4ۖ%'\p. ]m~e#+08Ӽ@")eIr+66?\R"'!xEE Jr B2]7}/?x8O"++wfXfz~~ՔVuI$ء Q>A˃SLIt Yp3zw9\W4S}.}f~\O)̧zb4^ CI>uRWX^vp:68'݃]Cw&ekalQ [O+~e(E0[s ]|aIDŽ5dŲZVj8PA:;:RIo2*cfbXA $C s"4+-aMu=#GhK,O/S$ ꮏlyyt IeE{yGr`k?Yq|ZƊk;cB+]U)!9z4dѤTYlE)KR(0M/ 2 2fgYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``8( @0 *8oEoPT^BhHHcpppn`w@"@"$} G G 0G0GIIKKh 8U8U ] ]] ] ] ]h ] ]_ _p` `HPb Hbpb`HbH d,dj+PK!#bigdecimal-3.1.5/gem.build_completenu[PK!*bigdecimal-3.1.5/bigdecimal.sonuȯELF>2@@8 @pp pp!p!8 HH!H!888$$PPP StdPPP PtdjjjDDQtdRtdpp!p!GNUb{Z7x9%y@j y~BE|X=|mt2؁9wxGIqXuũ.vFS @) IU=gQL!J_xqoj- V":Jj"!""^bu:0z9-, D/7v*[F"OZ !1! ! <!Up! `n!Y QV: &__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizegOne_ABCED9B4_CE73__00400511F31Druby_snprintfruby_xfreerb_thread_currentrb_thread_local_asetrb_inspectrb_str_duprb_str_catrb_exc_new_strrb_exc_raiserb_obj_classrb_class_nameruby_xreallocrb_obj_freeze_inlinerb_cBigDecimalrb_data_typed_object_wrapruby_xcalloc__stack_chk_failrb_check_typeddatarb_thread_local_arefrb_num2ullrb_ull2inumrb_yieldrb_protectrb_jump_tagstrlenmemmoverb_num2ushortrb_fatalrb_eFloatDomainErrorrb_raisememsetmemcpyrb_bugrb_id2symrb_hash_lookup2rb_sym2strrb_check_string_typestrncasecmprb_eArgErrorruby_malloc_size_overflowrb_sym2idrb_error_arityrb_num2intrb_fix2intrb_eTypeErrorbigdecimal_parse_special_stringstrncmprb_str_tmp_newrb_str_new_cstrrb_str_resizerb_warnrb_absint_sizerb_big_cmprb_num2ulongrb_num2longrb_big2strrb_float_valueBigDecimal_dtoa__memcpy_chkrb_cstr_to_inumrb_cFloat__memset_chkrb_cSymbolrb_cIntegerrb_cTrueClassrb_cNilClassrb_cFalseClassrb_typeddata_is_kind_ofrb_assoc_newrb_ll2inumrb_str_newsqrtrb_errno_ptrruby_strtodrb_float_newrb_ary_new_caparb_ary_pushrb_intern2rb_funcallvrb_Rationalrb_usascii_str_newrb_string_value_cstrrb_memhashrb_category_warnrb_num_coerce_cmprb_num_coerce_reloprb_num_coerce_binrb_rational_numrb_rational_denrb_eZeroDivErrorrb_check_convert_typerb_complex_imagrb_complex_realrb_keyword_given_prb_opts_exception_prb_to_intrb_hash_duprb_big_signInit_bigdecimalrb_ext_ractor_saferb_cNumericrb_define_classrb_undef_alloc_funcrb_undef_methodrb_str_new_staticrb_define_constrb_gc_register_mark_objectrb_define_modulerb_mBigMathrb_num2llrb_thread_check_intsrb_eMathDomainErrorroundrb_dbl2bigrb_big_packrb_define_methodrb_define_global_functionrb_define_singleton_methodruby_xmallocBigDecimal_strtodstrchrldexpBigDecimal_hdtoalibruby.so.3.3libm.so.6libpthread.so.0libc.so.6_edata__bss_start_endGLIBC_2.14GLIBC_2.3.4GLIBC_2.4GLIBC_2.2.5/opt/alt/ruby33/lib64Pti ii ui yui p!4x!P4!!!X!XЌ!`U!qX!#W!7!4!!H! P!X!~`!h!p!x!z!&!!;!=!@!J!V!f!iȏ!jЏ!n؏!r!w! !(!0!8!@!H!P!X! `! h! p! x!!!!!!!!!!Ȑ!А!ؐ!!! !!!"!#!$!%!' !((!)0!*8!+@!,H!-P!.X!/`!0h!1p!2x!3!4!5!!6!7!8!9!:!<ȑ!>Б!?ؑ!A!B!C!D!E!F!G!H!I !K(!L0!M8!N@!OH!PP!QX!R`!Sh!Tp!Ux!W!}!X!Y!Z![!\!]!^!_Ȓ!`В!aؒ!b!c!d!e!g!h!k!l!m !o(!p0!q8!r@!sH!tP!uX!v`!xHH)j!HtH5j!%j!hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?h@hAhBhChDhEhFhGqhHahIQhJAhK1hL!hMhNhOhPhQhRhShThUhVhWqhXahYQhZAh[1h\!h]h^h_h`hahbhchdhehfhgqhhahiQ%c!D%c!D%c!D%c!D%c!D%c!D%c!D%c!D%c!D%c!D%c!D%c!D%}c!D%uc!D%mc!D%ec!D%]c!D%Uc!D%Mc!D%Ec!D%=c!D%5c!D%-c!D%%c!D%c!D%c!D% c!D%c!D%b!D%b!D%b!D%b!D%b!D%b!D%b!D%b!D%b!D%b!D%b!D%b!D%b!D%b!D%b!D%b!D%}b!D%ub!D%mb!D%eb!D%]b!D%Ub!D%Mb!D%Eb!D%=b!D%5b!D%-b!D%%b!D%b!D%b!D% b!D%b!D%a!D%a!D%a!D%a!D%a!D%a!D%a!D%a!D%a!D%a!D%a!D%a!D%a!D%a!D%a!D%a!D%}a!D%ua!D%ma!D%ea!D%]a!D%Ua!D%Ma!D%Ea!D%=a!D%5a!D%-a!D%%a!D%a!D%a!D% a!D%a!D%`!D%`!D%`!D%`!D%`!D%`!D%`!D%`!D%`!D%`!D%`!D%`!D%`!D%`!DH=(1"H1H=&)HT$,HHT$CLUH5)SHHdH%(HD$1 HߺHkOHHHk} H$H?H9w HH_OHH?Hk} H9wHH+HHD$dH3%(tHH[]H=N)17H% f.H=_!H_!H9tHV[!Ht H=_!H5_!H)HHH?HHtH[!HtfD=e_!u+UH=r[!Ht H=X!d=_!]wHGH(ff.@!fDHB f*ffffLBfHMt6J$fH*Y 1XIvJ(fH*Y }1XHRHHffW1H1HH1HHf]!f.0ztHY!^0y]!1HH0HHH0HHfHIHW ft%ftwfz1ft)H@H"L1HDfubHL1tkuA+IH"L1}HH}L1_TDHIL1?4DA IfDH(L1DHLHtfff.@USHH-]!HHTH[H]DSHH@uHu4 H!H5m"H-HHH 5Hff.U(SHH4$HHHDHt6H/6HXHtHE HH(HD$iHD$H[]DHXH[]HtSG PfwI HsDHW>FHDuHOHD HxH9sH)HH@fHHHH)Hff.@AVHS!1AUATUSHH dH%(HD$1H)V!H8IH-Hɚ;HD$HSZ/DHD$ H HHHH Hiʚ;H)Htu1Ll$ 1HSZ/DLQHLvHH HHIHHI HDH Hiʚ;)ЉHɚ;LLf.HHHH HHHHHH HHH Hiʚ;H)Љ…u Hɚ;wHɚ;~H8fD(H@H@H@fp X$L; uI;D$ tID$ LL H|$dH3<%(LNH []A\A]A^DH(LHHsLpHx$LpIfH KL HhHHP$LDLDL@,IL)H)F1҉׃L 9M 89r+(H@H@H@@$fx @@uK(H@H@HhfP LLwHx fDSHH5P!HHUfP H[SHX!HH8Ht"tH[fH[HYX!HH1[HWUH88HSHHHH@u HH[]kHtHPHHHHH9HGHH[]ATUSH4HH?H9w*LdHW!LHHH[]A\H0Iff.USHdH%(HD$1HT$H=Q!HHH]|$uHL$dH3 %(Hu H[]VAWIAVIAUATUDSHH8HL$(DH|$Ht$/f{ <LT$uA+M@HD$ILPA0MAB.IHD$MrIH@HD$ HLMHD$AIHD$Ht$A l$!D1؉AAHt 9r։1LLH<H1HL9w*II)1LL1HH|$(H8[]A\A]A^A_fA-MِHD$HD$H9D$ *LMIH|$HGw$H w H9rLD$I~I9OA~0DK>fD04HHHGH)I9u@HD$ MH\$H5HH11Lt$(I>(7<.tC@f G$HGNA1fD HH[]A\A]A^A_D$Et1f} DM1DHI9}ɚ;nMf} HEE$HE7fM HHEMtYH88LHHHUHI)t8U$1ɾKfDҁɚ;v HEHI9uۉU$HH[]A\A]A^A_@FfL_1MG$IL\$AE1A$HD$8HD$tfDHD$1J|$L $LD$HfAL $LD$HcEJcH>DfU fB\$H#D$$AwBD\$$E4@M-f.A @BD$Ht$HZODA1fDw fDD4$D$$E1D$ <$f} D,$EYANxt$$fAvf} x []A\A]A^Avf} ~HL[H]A\A]A^DAE#wDAdwDAE#wAeAwAtAwjf.AVAUATUSF HfAffPfHVLnHH$Hv$HWDfAOąL9oLFoLoN4fGLA t)L9mL1ҋM$MtU LHCLkKD[]A\A]A^ÐDC$fHCDNE~@1fs []A\A]A^@G$1HG1f{ []A\A]A^1fK DG$fHGDNE~0fW SD1HLk6DfG #ff.fATIUHSӺ :HvL[H]A\f[1]A\fN$tyHFH~pHVN H9ssH)HGHGH9HG1fHWfG HFHtHHHLL$AL$HH9u ffDG$HGf~ fW ffG fDAWE1IAVAUATI̹UHSHHXF$HFfDV LHT$@LAW AL$ rAfffbfbE$HEfE H|$@AD$ f fC$HCfS fHEHHX[]A\A]A^A_fID$HD$HHHEH|$@HD$0HwHCHD$H9hC$HHVDHȋL L$HHH9uHD$H9T$vHD H9u1H|$0HT$0@@HD H9uAD$$HD$8Hiʚ;H|$HHD$ HD$v(AD$(HD$8HD$ 1Ht$ H|$HHHD$HD$Ht$0HH9HGHD$HHD$HAISZ/DH<LpH|$(fJ IuH< G$Hiʚ;D_(LH9D$ H9D$H9t$0%1Ht$8D (ML$MIL;L$H|$(LBL$E1HLLMGfDʚ;FD)L$HL$EtD9seʚ;D)AL$LH)I9r\At 1IHɚ;vHH HIH ЉHiʚ;H)։H9r)AfDLD)E1H)L$I9sD)L$BD$JT =ɚ;v-ʚ;HBBB=ɚ;wL;l$HD$0HHEHD$@H@HE._HX1[]A\A]A^A_DIL;l$B1Ht$D $IID$MLL\$HIUIv<,A9|$,Br,MK<+IOET$D9T$w HH9uID$LPOLL9L$ L)L1M&fDʚ;D)D$HLH)L9w A| D$D7D9r)1)fDHA$A$fbfbAE$HEfDE 1H5ihHX[H]A\A]A^A_It$HHH|$@AD$ f NffE H-HD$L|$@H߾HCIGHCZ,1fA HfC fE$HEfu A|$$I|$L|$@1fHTLfA xC$HCfK |fE$HEf} E1E$1ҿHEH5fDM H-ffAD$$HD$8Hiʚ;H|$HHD$ DHUSHHH=9!AHߺ$HHHHt4 t u:Ht5HHHуHHgH'fH[]DHHHHUHHX tHXH@Hu-H5HH[]DHulH5HtJH5HuHsHHpHCHEHCHEC fE C"fE"HH>u1HHu HH[]H}$Hs$SHH[]ÿff.@ATUSHdH%(HD$1HT$H=*!HÃwHL%i0!HTLH|$u0HL$dH3 %(HuH[]A\Off.@SH@ tf@uHuKHЃv,H*!HH5}H81MDHcHD [f.HHu@HH.!1H@H9tH uDUSH~H>t fD@uUXńuU=TrHtHЃPHH\H[]fDSńtHtHt H@t%HEo@t%HEK@t%HE't%HEHH\H[]fH-.!H\LHHH.HH[]H}(!H56H81LH^H'!H5=H81+ff.ATIHUS<HHH4$(HD1LfP HH#%!Hh@$H@H@H;uH9X tHX HHH[]A\ÐAUIHATAUSHHHH4$(HDDHHh@$H@AuHfP 1Hv$!L^H;uH9X tHX HH4HH[]A\A]fDfC DATIUSH?H9wOHlx]u H[]A\@uJI<$Ht@u3>x?HcH[]A\f.HxH[˺1[Hd&!H5H813AWAVAUATUHSHHHHt$hHD$U @ HfJfH|$HH|$HULeIH|$L9HD$N< HCIHH|$ H9sHEHHCHD$HpHD$8HD$f} @ ffC N,1H{$LH|$ L{sID$Lt$ NL+ E1HD$(HD$ISZ/DAKHHD$IGHD$0M~L9l$L\$(LH+|$HD$I9Ht$LD$fHIL9At$HHH HIHH ʉHiʚ;H)A1ɚ;v A iʚ;)A1tMtAALAA=ɚ;w%zf.L$щL$ɚ;Z Aiʚ;)L$HHuHIL97fDIMIL9l$ H|$8HH|$8HDH,HD$8H@HH[]HA\A]A^A_fWfWC$HCfK HH[]A\A]A^A_1K<7HIH4$(HDILp@$LH@fAE HEIEHD$Hp=HL]HH1[]A\A]A^A_LIHD$HHl$HD$H|$$H1fHHTH\$8@}$pH}efHt$HҍTH\$8fC$HCfS HH[]A\A]A^A_HD$0L)L9l$(rLIH+|$fM1f:1HH\$8H\$8LAVH5E1AUATL%%!UHMSHHMt)IIII]IuHH$uHT t@ v uH u(KvATH@@$H@t(tfP f1[]A\A]A^þfp 1fH fAWI1AVAAUATUHHH!SHXDD$L$oHD$MIAMƒ wIAEƒ v tL`HHt@HD$H;u HD$H9X tHD$HX HHHXH[]A\A]A^A_DI88HEHD$ IHA}#HT$0ILbHx蹾HHD$8LPHL$( tLPAEPAHE1<-IEAAD\$(HVE1I<2I>L$)0 HADII<2HLBXuDA Av.< t*<_uMADt<9wIrEhM1E1LT$ KT H\$0I88HLT$ILL$HHHELjI9LBN4$L|$(LL$HLhLT$@$H@AfDX 1IVH{$LL$LT$袼HLT$LL$HD$ <-/HD$1<+H9SHD$ 1LL$IHHvDLHHHH IH LHMHLA0McM)I9HHHH/HwhH9HH9HHuHE11H`HPHIHD$0HHH9HFHT$08fHGLHHHxHL$LL$D$IL=fHD$@11E1HD$HE1EhML$@tMtHKHBf|$VL轼H5>HH!H81fLD$(1fDHEHD$ HD$ H4$H88H(HHHDI胾HLp@$H@fh HD$H;fDHHHHDKD.HD$@E1E1D!HHH!HT$HHFIHHD$HIT LHHD$ +IHHIT I<21T$tNuDA An< f<_90 HAD HI<2HuD$LA<-D$1<+u II88E1HA1G\L4)LH?HL1H)HIHHHHH9D$1I9D$Hw-I9v(1 A2HHDHЉD$HwI9wI9HMtP1H L9t$Hf. ff.zVuTHm!^f/w Hd!@HL$HdH3 %(HHX[]A\A]A^A_f.HHvPEmf/8H!vHH5u!01H@H!1HLD$@HL$HT$Ld$ *H\$LHH)øHOLcLNHfL$K4,9>H88)LcH00000000LHHHLH)‰ЃvAt 0EI\L1Ҿ D HH88HHHLHHHHH,H5=!HHL$HhBfP 4@Epu HH#H H H#!HH!H5H81XH88)H00000000HcHHHHH)HH t 0HD$P1L J(Dì98HNjD$H)HcϾ98)ߍK|$HcD)ljLcK\5)HcH)LIH|L)ƍ11ƃI<09rH~HHHLH)2~1AJ 9rdf98K<,0)HcH,HL)BL1Ҿ D, 1H5y !H葩uD1@H߉AHmfD H蓫HHH$HxHq H tHx_HHHD$H$"HLd$1HH@L7LHkH !HH8yfUHպSHHHdH%(HD$1#IHH$A@ fw ]Hr5I@HhAL HptH~AL$uCHHuHtHHtHEHD$dH3%(H[]EH$ExA ADADAAA wRAE1A9t*fDЉA9uAA wIPHxc tMcL)HtH9HLHH H"IPH1H9} H)McHL)HEf.HHHH)1H EH$HxAL HEA HHtH McHIM)H9ILXHMcHL)kEH$HHEA E1SH dH%(HD$1HT$Ht$xH|$H@HxDH\?H@H|$Hx;H|?HHL$dH3 %(u(H [HfDۤHQH1dH%(HD$1HH<$H@HxHD?HL$dH3 %(u HÐ{@H1dH%(HD$1H~H<$H@HxHD?HL$dH3 %(u HÐ蔥@USHHdH %(HL$81Ʌxv 1qHHHIH5HHHHD$1Hp2dHD$H\$H }HHT$HEHHrH Hr1藣HϤHT$E11H4HHRH)"H誤H|$HHD$HL$8dH3 %(uHH[]ÐH[~肤fHHgP 1ftftft HfD1HfHHP ft1fHDHDHHfx HHHHH@ HHDHHwH$tPH@HHHH$HEHH HH8LHHHD$荚1ɺHHk1HQHD$(dH3%(H;H8[]A\A]{I}@LIHHHHH$HEHH* HH8LHHHD$ԙIcͺHH豯1H藫HHL$(dH3 %(+H8[]A\A]DIZ1AUIATUHS1H8dH%(HD$(1ChIHHHHH$HEHH3 HH8LHHHD$ݘ1ɺHH軮1H衪HD$(dH3%(H;H8[]A\A]I}@蜈IHHHHH$HEHHz HH8LHHHD$$IcͺHH1HHHL$(dH3 %(+H8[]A\A]DKIZ1E0AWIAVAUATIUSHHdH%(HD$81PI<$NMd$9)@jLcAu MLA1&HLIHHHD$HEHH# HH8LHHHD$͖ALHH諬1H葨HHL$8dH3 %(oHH[]A\A]A^A_HD$A1rHLIIHHD$ID$HHn HH8 LHHHD$HL$LHEA1HҧHD$8dH3%(H;HH[]A\A]A^A_@uHu/@toE1HAHD$DfHEw$HHcH>H5 Hyu%*"HHcH>D1HHGHHT$HT$AV f*tf1HL$(dH3 %(_H0[]A\A]A^DIF1HH4HHT$fHA HHfHs~H HtfH HfHfH3~H HtaDH H<HuDH}H HtHHL!{HIHL$(dH3 %(5H0HLH[]A\A]A^V|fDHI Hu%HDHk}H$ HtHL$(dH3 %(H0HLH[]A\A]A^qz)@EЅ*H؀"D~H jHcH>Dqzff3f^fHxI9~f*"}HHcH>f*"}HHcH>1fff*"]}H'HcH>fDfDHfHfHHDHBf.fdf*"|HHcH>1f*"|HtHcH>f~}*"m|H۬HcH>LHMFM9LIFHt.Av$9p$rw61DT$E9T$wrHH9uM9s3f)"f~*"{HHcH>*"{HPHcH>uHff.fGf>fLf<f=f*rfAUIATUSHHH8dH%(HD$(1HHH$H؃Hu H1HHIMI$HD$ID$HEHHW HH8LHHHHHD$;1HѕHHL$(dH3 %(H8[]A\A]HHt,HOHEHH4 IFD1HI*fHD$(dH3%(uH8HL*[]A\A]6wsAUATIUHSH(dH%(HD$1HHHu2HD$dH3%(H(LH[]A\A]f1ɂLHILH谂HH HHH$ݔHHO1HUHEHL$dH3 %(u!H([]A\A]fDHuH3rH H5&H81qAUIATUSHHH8dH%(HD$(1[HHH$H؃H!u H1HH"IMvI$fA|$ HD$t f} u-HEHL$(dH3 %(oH8[]A\A]f.LH蕒IHHHu HH8HHHD$Mf} C$HCfS @HHt,HHEHH4-ID1HIf H H8RHHHD$LHHğ1H*HffC DHD$(dH3%(uH8HL-[]A\A]sqpAUATIUHSH(dH%(HD$1HHHu2HD$dH3%(H(LH[]A\A]yf1LHI[LHpHHHHH$蝑HH1HHEHL$dH3 %(u!H([]A\A]fDHhrH3koH H5H81SnAUIATUSHHH8dH%(HD$(1HHH$H؃H!u H1HHIMvI$fA|$ HD$t f} u-HEHL$(dH3 %(oH8[]A\A]f.LHUIHHH5 HH8ȨHHHD$Mf} C$HCfS @HHt,HHEHH4ID1HIf Hr H8HHHD$LHH脜1HHffC DHD$(dH3%(uH8HL+[]A\A]p1mAUATIUHSH(dH%(HD$1HHHu2HD$dH3%(H(LH[]A\A]yf1I|LHI[LH0|HHHHH$]HHό1HՍHEHL$dH3 %(u!H([]A\A]fDH(oH3+lHD H5H81kAWAVAUIATUSHHHxdH%(HD$h1HHHD$H؃Hu H1HHIM1I$HN HD$AD$ H;ffID$HEL4LOt6 谥H;L1IHHD$ 蓥H;L1IHHD$(vH;L1IHLD$HD$0THLLIHLHD$8HIEH;H,HHH;HIHL $HD$@L $1ɺHHLLHD$HLHLD$LHLL$L$LLL*1L萋IHL$hdH3 %(Hx[]A\A]A^A_f.HHt,H,HEHH4žI#D1H詾IIH@$H@HT$ fP :@H Hu%H-7D H nH HtHHLlH11~H% hff.@AWAVAUATUHSHHdH%(HD$81Hu9HL$8dH3 %(cHH[]A\A]A^A_fH(mH0IH?H9BH\H=lHHxHHI%1wL5 HSII>~LHIHHD$IHHD$HH@u HHH赼IT$I>HHHD$ HEHDIUH9HJHF1HT HHLHHHT$(LݍLv0HL袇1L計IEsH0kHHLDHEH*HHNDHL$HHLH$-HuXHI HHuDHckH$ HtHHLi@HXiHH$1H‡H; @f@uHu[HHtvHtd@uR@ t@H HH# H5H81dH H5mH81dHWH HH HH HHi HH HAWAVIAUIATIUSHH5 HxdH%(HD$h1jfH5 HHHHD$ du<CH؃Ht HHڃHHHDH5I Had1҅u+HL$hdH3 %(HHx[]A\A]A^A_DH5 HeIHHD$(E fAW fffJffgf]f1LHt$1HHt$ںLd$L9d$ LMd$MI LBH H8IT$\KT$1ɾHHHD$0H H86LHHIHLHD$8*HCHHY H81ɺHIHLLL$HD$@LL$LLL$LHHAC LL$ftf} AG OfOMMIDHH H蘰HH H5" HcH5 HIEcIf.ftftJfuHS H5pH81raff~sf~sH=? H5 ccIEH=0 H5 LcIDHڃHt Hߺ1H@f~H= H55 bIEf.fIqLLL$6lLL$HM IIALLID$莐LHSHH6 HH8ӛLHHHHHD$HEMeI.I@H KHHEHߺH4HDH= H5: aIEI.`ff.@UHSHH8dH%(HD$(1HL$HH$HD$Hu-%HHcHL$(dH3 %(u5H8[]fDH$H\$1HHHD$HHD$蝁H#`ATUHSHH@dH%(HD$81HL$HH$HD$PHu[HD L%ΈHu!LdH HtHHHcHL$8dH3 %(uJH@[]A\H$H\$1HHHD$HHD$̀H+H$1H輀H;Ha:_f.AVAUIATUSHH5g IHpdH%(HD$h1 `H5D HHHHD$@Q^u-pu HVH؃HIH5 L^ LH5߽ _1LHIHHD$H"1LHt$H$H9\$ HM\$L- HI}H HB1HS虘I}HT1IHHD$PyLHLHHHHD$XmI$Av$HD$HHD$IHD$ x1L.I$HL$hdH3 %(Hp[]A\A]A^f/HLaHucDHH uDH I@C$1LHiʚ;HIT$AT 1^fDHڃHu1HIMDtH3HEHH4I\AWAVAUATUSHHdH%(HD$81~oIHu_HL$HHLH$HtWH$1H}H;fHL$8dH3 %(uiHH[]A\A]A^A_ÐtY,_@H H-HuDH`H HtHHLY_[HnH5@*HHPuHLqL@1!kL5R HUII>LHIHHD$RIHHD$H؃Hu HHHߺIT$I>HHHD$ HCHDIUH9HJHF1HT HJHLHHHT$(LALIj|HL{1L |IECHx]HHHGHHN8Hw H5قH81FYfDAWAVAUATUSHHdH%(HD$81ZHHBLfMALHH6IMIM1HHIHHD$lHHHD$H؃Ht"HHHIINHHHL$8dH3 %(THH[]A\A]A^A_fL[HL$HHHH$8HHP L%Hu@Lk]H, HtHHH\gLHߺlHUI>HHHD$ HCHDIUH9HJHF1HT H螒HLHHHT$(H~LgyLLZx1L`yIELZIH$1H9yH;ZWH H5#H81VATIUSHH dH%(HD$1HwBHt1HL$dH3 %(H []A\H5q HVtuH5^ HI XHE 1HH H8!VH1HHH;(uH;E tH] HH+X1HxHYDuuHuiH؃HH HH[u HHYH52HHз H81.UfDHH u,HģW1HiwHHڃHtDHt>HthHtzHGH\$H|$TLHL[LH胤BfDHHHD$뮐LHsfDHpVuHuiHPHtHtH5 HL$HHD$VHt/H0WLHSHt#t1 uH H5kH81SHHYtHtHTH}Ht H}HtHHz}HEH H5ڃH81HSAUATUSH+WHcHLdhUuLeu.LWHAHDL[]A\A]=DHmuWHAVHètCHHyEuRH[]A\A]fDLRHǃm;HRtHSHbH] H5{H81,Rff.USHdH%(HD$1QH=|WH=|HX WH=|H8 Wff.g H   1(aHH4$HHD_W1fP HX@$H@H@H haHH4$HHD WH={fH HXH@H H@@$eH H0VH H5H=4{H9TH;THuHu=H H H  <  H! H8@HxH5zHUH;H&=H5z TH;H;H5wzSH;H0H5zSH;1HXH5zSH;H};H5uzSH;1HudH5czSH;1HmH5_zqSH;1H`H5ZzYSH=TzXPH;H5KzHFUH;5wH5MH;HH5KH=r H KH=r Hu KH=qu Hf JH=qJH=rHU JHA HD$dH3%(|H[]fDH H8MH ^~M H H8H9 H8 Ha H8H H8LEff.AWAVAUATUHHSHHHT$HdH%(H$1HH|$H|$ u HHHCH HxHf(fT ~f. }f1f/…Ht$e1HHeHH$dH3%( H[]A\A]A^A_@HH3|HcH>DDHD$Ht$1HHH@ H\$H\$fD$>HH\$f&Hr H8}}1HHeHLC H\$@A@ f5LHL$XII܋p$HL$0HAx$=H@H Hw"f.HHHHH9wt7I@HHHd@HHHHH9wH)HLl$H?H1H)I)CMIHt$LA!bIH@HLd-IAMIMLLILLHMD$ IA@ fIG Ax$p$1ɅUBLl$Ht$LIH@L5LE@IH@H3H'@II-HL$0HT$PLLHD$PHH Hu$H=.jFH HtLHLDIH5v H@H/ HH8$K@f.11H1HHԕ1LD$(LPLD$(HD$ Hi IPH8{LHIHHD$`vLD$(IHHD$hLHAu MLLLD$(2IVIHHD$pID$HDIUH9HJHF1HT H HH8\zLLHHHT$xLSfH|$ YOaLD$(LL`1LaMe^fDLBI+Ld$P1L`I<$(I I$HIINL|$@f|$>]IG p$tAH@HHHHlfHHHHH9wH)L$H@H\$HHDHt$HLHD$HtJOl-fDH)HA HT$1H8x@$HH@fp H\$X1HH_HHC P ftDft>f:Hԟ HT$1ɾH8hx1H@$H@fH UH|$L< H\$HHHHeH|$@L`6HHt$XHD$X0H5 HHn>Lt$H5 HLW>I9u'HC H\$fP zH@HoHH@sHC H|$@HL$XHT$PLHD$PZHeHr HeHuHAHR HtH|$@HL%@K1)LHSIHI H8vH|$@HHHH$UIHH$LHAu MH޺LIUIHH$IFHDHUH9HJHF1HT H HH8@vLHHHH$L4bLH|$(6IH9H$HHDŽ$<t HN6H LH貉HH5 H 4CHk 1M Af@ff 1fwH LH8nHHD$x1HHC$HCfS }UHH$dH3%(H[]A\A]A^A_H2H81HHH? tFH H5dH812fD1f.1"H1HH? u1HH_HH@LL|$M4腿IM7L1IIf1BIWHD$H H8WmHLIHH$ŇIHH$LHAu MLLLL$胇LL$IHH$IQIEHDIVH9HJHF1HT H HH8lLL$LLHHH$LXH|$ASLLXR1L^SI6dfDL4I1Ll$p1L1SI}xH.IEHIINLf.Ht$PFH|$ HD$`HT$HHT$xHT$HHT$PHT$xHT$PHT$@HT$xHT$@HT$XHT$xHT$XHT$`HT$xHT$`HT$hHT$xHT$hfDH)H|$n/HL$xHT$pHLHD$p;HKHS H-YHu Hk5H, HtLHH4IHD$ $1?IVIH H8jLHHHH$"IHH$H؃Hu HLHߺIT$HHH$HCHDHUH9HJHF1HT Hp HH8 jHHHHH$LVL ?TQLHO1HPLeeHT$(H|$8?H\$ HH@HH|H1HHqPH3HƹH|$`H虿HD$`z1H 1LH8)iHHD$xH1C$1fC HHCOH}Lo1IlH\$p1HOH; IjHHRIINCH|$ ,H/dH3 H5VH81--H H5^H81,H H5^H81,1111_ AWAVAUATUSHdH%(HD$x1,IL.HL`HHHD$PHD$HEHHD$f} L5eIMD$MAADMIII$AVA lLLT$(0D$ +L$ LT$(f.ef/f/ eH,Ll=f.UX/IEIcL>L0u H3HPHtHtH5O HL$HHHD$HL-HLH?AuCIEH  LHt HLL/f1f/'A(DH5 L*Ht$@LHD$@=LHNHCL躚Iff(*IH L.IǨu HIIGHtIt AH5 HL$HLHD$H+HL.I f.H HT$E1H8d@$HH@fDx HD$@1HHVKHHL$xdH3 %(HĈ[]A\A]A^A_DE1E1E1E fA+LHHL$H<LLT$HD$H*LT$HE1fDHjH-cHZT@M/D$ EFH5O HL$HLLT$(HD$HG*LT$(HqHo Ht$H8zbH1HIHDE E1E1fLAH?MIEHt|$u MJH5 HL$HLHD$H)HKHT$H H8KbHLbHL$HH@HUHT H;HHT$8HT$@HT$8fff7/H}~MgRHD$IIE1H|.(HH4$IHDJ$1L`H@$H@fC KH| [.(HH4$HD$ HD#HT$ HL@$IHPfP H@BItyHHBIAA@IHHLgZLHWBK?L9vLHLLI):ZLL*BMH|$~LHH|$rAE fdfZfP?HT$Lv96IEH LHLLT$!f1LT$f/zLH[Hb HT$1ɾH8Wf} I.IEH Ht$@LHD$@HЃAE$IEIEfAM WAE LH?fDHL$LLT$ H|$HAHE1HD$qLT$ IH|$D$ 0Mu H|$HLH)~ HuHH;rLHI?HT$H~ LT$H8Vf} IMLT$]WH~ H5LH81HEHHHHMIEH|$LHHЃAF$IFfAn 1LHD$@HЃAlAAE$IEfE] @LH5GHHx H81=;LHHЃ"LHMf} C$HCfC JuLHH҃hHl} LHL6=HLv:XL<LHD$HH1L<LHD$HHLH.fAE SfAE G1HFHLHHD$jHHHD$PH{HD$tHHD${f.H|$HD$]ff.HHHt$Ht$Hff.UHSH8Ht$H|$dH%(HD$(1$H:0 1@H:t0 HcHHQuHSH HHGAHH\VHHHD$Hv"H88HHHH9UvHHU1H5HEHt$(dH34%(uDH8[]HA1HUHHHD$Hu H5)EH81'"fSHHH|$Ht$HA1H1UHøHt 1HI5HH[1uuuux @Dff.1tuPtUfuuuuuu ÐDff.fH(LWdH%(HD$1HcGM EAMYD )‰  M9sTAQtRDljA)AIAD ?H I9s AA HH!H 1҅urDǁ?H H H|$D$HD$dH3%(u_H(f. D1)?H M9sAQHAA L Dlj1?H [ff.NDWA9AWLF1AVAUATUiLcSH_IO$0IA$EDHDAD$E9AMIE11IASE IILIՉHI I)LEJH HуM9sEE IVH9s$EVEtDD Eu HH9roNAA9HcHH LfH9sHH291trpHމD$1IAHHHH)HЉVH M9sHcH2u*HBH9vJt u HH9roD$[]A\A]A^A_@wD$[]A\A]A^A_1DDWNA9&fDUSHHxw HcH Ht8H4HHHHH9uH:HH>H9HHuٽH5fu H w EHH<'IHIH>HH0u HH9t:HHH)HLH= vЉٽEHH<'HH‰Zj HBHH[]fDUHSHH(D$dH%(HD$1D$IfH~fH~f~D$H ։ρEωL$H|$u_T$AQT$E1AQAAEAU5)‰H\$dH3%(LH([]DT$ )L$ AIT$DH|$^T$AAA AQw-2EIcA|AA)Df @AWIAVAUATIUSHLcoLcvE9|DIMcILcC.1A9\$ @A|$WHcLXI,LI9s@HH9wIIN,K4L9r^f.II9vKHDWEtLME1ɐIAPD1HILLIщQI L9wD II9w~uHUtH uuXH[]A\A]A^A_AVIAUIATUHnSHcFH_DgA)HHH @H9HH89:tA}IcU1D`HpIL IcVH| LHSHLVH)ʋMH)HAARH H9wI9v;LH@HVHH)HAӉWH I9wIqH)HLEufHAtD@[]A\A]A^DA,HHAHLMI1)H@[]A\A]A^Ht4HcWH5r ~)fHcWH HHHfHHqHE1HEH-bp HHHD$HD$Hff.@AWAAVAAAUATUHSHDeE EA\$9~9zIHxE~#AOHHDfHBH9uH|HcEHuL Ata E1D)fDDHHD ‰WDFAI9wEDDEEeHHL[]A\A]A^A_DI9vץI9wf.AWIAVAUMATUSHHt$dH%(HD$x1H@Au@-7@HcH>AuD$ @IE1@0@Lσ/91E1E1*C4DtqHAΉσ/9VA~AӍTQʐD$ fHD$HtL8D$ tfW?HD$xdH3%(HĈ[]A\A]A^A_ÐAuD$ @ fHD$HtL8IAu@-DD$ E1@0Au$ID$"ALT$HYH)fIEuH*YYFAX $ $T$Eu$MB1E1E1D.pNЃ LPE( LЃ0}D)@ H80t1Y0I¾\$8C ID4O1 AuI@0t@A`D@ED$8EI1p@+M@-H1ۍ~Ѓ L1E+\$8EIlj\$$E@DfAH*ANf$A AH5>fHH*YX$AD)D$$D$D$tHHv><$Y<<$d$rD$=4x}$1H==fDt Y׾HcHufH~@HD$H$H=H$H؉H -PH H H$Y$fH~f$H %=| =|HD$H$$\$@H00t~1JxnHpDWA w@fDDHBlG>DGA vHH)H'NH݅D$\$AP981A ~9DD$(A DD$(HDp@I A E9}2EHHE)Ot fIAU Hǃ0M9uHDd$8L$$1L|$XA)DIID$(HCHD$@HD$lHD$PHD$hDd$8HD$H{5Ht$@HxIHcCHHt$PH|$HD$IHHHED$h L$8D|$(D,L$l+D$43|6)ȋ|$ALDA9D<AND9AODž~)A)A)ŋt$8~3HL$ HIMHHTfDH9HH:98tDL$EE D%=2 =pS HP9\$H$~$YfH~f$H$ L`LXHPHHL@$fDA IfgD$$tb|$$ D‹\$$%)D)ډT$98H8$D)Hc)YHcYDD$8E1D$$ID$8D1Ƀ߃Eu#f D EIA@E1AHAwDMu AD$Lt$(Ml HD$0HDfIAV Hǃ0GM9uAHL$0HHD$(Ll2IEuA0tAH=V8Hf5$T$A.EeEEH= 8D$DD$HIT$ H-7D$DE[ AHT$ET$H H)fEeIH*YY7X $f.T$ $zuD$MH-N7D$ EfIAHMHuD$AAPAU,)׉։1)ȃI0 A1D w<IDFAuANЁ/~܃ wIAU0 vDD$8D1Ƀ<AzIBDWA -I|$$Dd$8Hq5$A)Ic^D$؉ƒtHcH E5<$^<<$D$?|$ft$j$EH}41@t YHufH~HD$H$t9H k)~47H4H$<$ff.|$$$"fDHt$pLL$H IwHHLfH9HH99:tEAHDD$HEDD$H|$eExIA^L;t$8L1Ҿ 1Ҿ LIL;l$H|$1Ҿ IHD$fDHDD$Hc|$DD$HF D$E9 D al$LL|$@ADMI^Eu }EHHHt$HŋUHcF)…R HHMHHTH9L HH290triA9Dd$A1PfDHt$H|$ H!Hf|$ALI^L|$@A9<AE&MLl$fDHt$H|$DPEAKIHD$f*YX !fH~fH~H -@H H fD\ HT$L$f/;fW f/D$PfT$|$ D$dHcD$ H8 ‹D$D$@5Y u AHD$f/L$D$ I_A1H|$MtLHHD$(t$ 0HD$0HcH[f|$\$H ڈT$X\$8E1f.D$PD$8AxD T$ H7ډփ YH5f(1@t YHu@af(XD|$XHD$E1Ht$FD$XH| )‰DD$\$@H|$1ҾUHHD$Hc@)…HHMHHT H9[HH9tG$fDf(¸Vft$H$H@D$XD$\D$@D$Yff.LfD f(Xf/w\f/D$P Ct$ DL9jBHHS<9thf(¸HHt$HHHH 6AEA#HD$E1D$L؉D$ L(IHD$H uHcT$ f(fI_H Hփ^t$ ,f*0AY\f.D$@D$@%ILfDH9YfHf(^,f*P0SY\f.zHÀ{0HCtyA$GH% I|DCHH9YffH,*ȃ0\f.z@SoL9(PHHC9t|$Ptt DH|$FMOM>M95L#(fDSHHC0tA99MLl$t$ xt$@|$\?%fɋ\$ *YčsYX fH~fH~H -@H H 3AD$D .fHD$E1=A1D$ A}HIuHxHIcEHH_HD$A0LCD$ ALMH\$8L|$@Ll$ASUL1Ҿ IŋD$\"D$@Xf/AHD$D$\$DAI^LL|$@A9B1DOE&MLl$Hljl$ALL|$@AE1l$LAL|$@uI^fDD$\\$ D$@f( f.HA%DfD$tD$\Ah<T$fD$ IOf(^,f*P0AY\f.{'|$@mH<)‰oHff.@AWIAVAUMATfI~UHcSHH(dH%(HD$1fH~H f(fT f. f.f.JDLH4Ld$T$YfH~fI~H4-A}LcHcLUH bN0HHE1L9fDHEMtImH\$dH3%( H([]A\A]A^A_D-AdA>=<=remainderdivided by 0divmodniltruefalseto_strStringBigDecimal.exception_modeBigDecimal.rounding_modeBigDecimal.precision_limitBigDecimalnewinterpret_looselydouble_fig_loadsave_exception_modesave_rounding_modesave_limit3.1.5VERSIONBASEEXCEPTION_ALLEXCEPTION_NaNEXCEPTION_INFINITYEXCEPTION_UNDERFLOWEXCEPTION_OVERFLOWEXCEPTION_ZERODIVIDEROUND_MODEROUND_UPROUND_DOWNROUND_HALF_UPROUND_HALF_DOWNROUND_CEILINGROUND_FLOORROUND_HALF_EVENSIGN_NaNSIGN_POSITIVE_ZEROSIGN_NEGATIVE_ZEROSIGN_POSITIVE_FINITESIGN_NEGATIVE_FINITESIGN_POSITIVE_INFINITESIGN_NEGATIVE_INFINITE+0+InfinityNANprecsprecision_scalen_significant_digitsaddsubmulthashto_sto_intto_rsplit+-+@-@/quo%moduloclonedupto_fabssqrtfixroundfracfloorceilpower===eql?<nonzero?coerceinspectexponentsignnan?infinite?truncate_dumpBigMathexploghalf_uphalf_downhalf_evendefaultbankerceilinghalfprecision must be an Integer21E%ld can't be coerced into BigDecimalComputation results to 'Infinity'Computation results to '-Infinity'Computation results in 'NaN' (Not a Number)Computation results in 'Infinity'Computation results in '-Infinity'ERROR(VpDivd): space for remainder too small.second argument must be true or falsefirst argument for BigDecimal.mode invalidinvalid value for BigDecimal(): "%li "Conversion from String to BigDecimal overflow (last few digits discarded).can't omit precision for a %li .BigDecimal to Float conversionBigDecimal#precs is deprecated and will be removed in the future; use BigDecimal#precision instead.Undefined operation in BigDecimalCmp()can't convert %s into BigDecimalUnable to make a BigDecimal from non-zero imaginary numbercan't convert %li into BigDecimalZero or negative precision for expComplex argument for BigMath.logZero or negative argument for logwrong argument type %li (expected scalar Numeric)a non-integral exponent for a negative baseload failed: invalid character in the marshaled stringHH0.((H #X$X$X$X$X$$X$@$X$X$h$X$X$X$X$X$$V33333333333333333TT#U33333333#U3333T^RSSSSSDSS SSSSSSSSSDSTUUUUUUUUUUUUUUUUU\TT\TUUUUUUUUSUUUUSUUURUSKUGGGGGGGGGGGGGGGGG7SRRGGGGGGGGRGGGG7SxTQQRRQ3T/////////////////RQQ////////Q////RSxPQxPQQSQOOOQHR`O`O{P{P`ONSONNNOQsssssssssssssssssHNcOHNsssssssscOsssscO,ƆƆƆƆƆƆƆƆƆƆƆƆƆhǙǙǙǙǙǙǙǙǙǙǙǙ,& .>C]r2<?eACXXXXXXXX@@@@@XXXXXXXXXXXXXXXXXX@XXXXXXXXXXX0}NaNInfinityؗҜ<3#I9=D2[%Cod(h7yACnF?O8M20HwZ`XDEF$G\NN(N08NDHNXXNlhNOQ (SpHThVW`Z^bHxcthdf(XitlXoxpHX~t`8xxȯ( |8h|HzRx $FJ w?:*3$"D\p N$ IDo E Z F d D H$T+AAG PID\UA0(hAFO0z AAF MAA\q@pLBKB A(A0GP 0A(A BBBF (9Qg$L`Ae J D L _0]ENG P DAA gDA(,UBAA } ABD (XoEAD0X AAA H(BEE B(A0D8GpR 8A0A(B BBBJ PAa N _( nEAD0W AAA (PkBDD | CBE H4\0CD xAACL aHmBEE E(D0D8DP  8D0A(B BBBF ,8A D VdBEB E(A0A8D 8A0A(B BBBA  8F0A(B BBBE |0c]WepSAa N b8BAD K JBJ K ABJ LBEE D(D0M (A BBBH \ (D BBBJ `hBBB A(A0 (A BBBB l (A BBBE X (A BBBI 47BDD Y DBG ACB| BHB B(I0D8G 8A0A(B BBBA  8C0A(B BBBF < 8A0C(B BBBA $zRx ,LmKAG a AAJ X AAF zFAGH l$(BBB E(D0D8G 8A0A(B BBBK OPBuOPA4AAG N DAD Q DAA 0,FAA D0w  AABI AT K @4(ECD { IAG  LAC f DAA (xBLA |AB8BHG A(D0z (D ABBG 4FDA e ABE j ABK  BGB B(A0D8G 8A0A(F BBBA s 8A0A(B BBBA y 8C0A(B BBBA  8A0A(B BBBD < LFLB H(G0 (A BBBA H  BGE B(A0N8D 8D0A(B BBBF >((P :AAG@~ AAG H| BBB B(D0D8G 8A0A(B BBBK  $ W`j F F0 d BAC J  AABH ( ]AIN0 AAH H  ED0m AI l \H F B  \H F B ( EAD` AAB  GMl G F ,;Mm T)H] l(HZ8 zHc E I X EPP AA | 2El 2Hf( EMDPz AAA ( PEMDP AAA L FGB B(A0A8N 8A0A(B BBBA (X DEMDP AAA ( EMDP AAA ( lEMDP AAA L FNB B(A0A8D 8A0A(B BBBH H,FFNB E(D0A8DPx 8A0A(B BBBJ Hx FNB B(D0A8D 8A0A(B BBBI LH#FEA D(H` (A ABBH  (A ABBF L$FEA D(H` (A ABBH  (A ABBF Ld&FEA D(H` (A ABBH  (A ABBF dh'FEB B(D0A8F 8A0A(B BBBD  8A0A(B BBBM H)?FBB B(A0K8N 8A0A(B BBBD (h/EMD0[ AAE 80H  G  E $EHL0DA41EAJP\ DAO p DAE pt2#BBE D(K0K` 0A(A BBBF  0J(A BBBK I 0J(A BBBF zRx `(77777(7L<7FJA A(N` (A ABBH l (L ABBE L9FBD D(DPB (G ABBN s (A ABBG L9FJA A(N` (A ABBK D (L ABBE L,;FBD D(DPB (G ABBN s (A ABBG L|<FJA A(N` (A ABBK D (L ABBE LP>FBD D(DPB (G ABBN s (A ABBG L ?FGB E(A0A8N 8A0A(B BBBK HlAXBBB B(A0D8D{ 8A0A(B BBBJ HEBBE E(D0A8N 8A0A(B BBBF (IEDGPW AAG 00IFAD G`  AABA DdJiFBE A(A0Qn 0A(A BBBJ zRx ( HLzFBB B(A0A8Dr 8A0A(B BBBB L0NFBB B(A0A8D1 8A0A(B BBBC 0EDDP AAA `̒PEG BARDs5D0 K lԔRHB B(A0G8d 0A(B BBBE K0A(B BBBDH8$84AAF DA(` \AIG@ AAF D@BEB B(D0A8D@8A0A(B BBBLhBEE A(E0 (A BBBF @(A BBB$8E88tBGA D(G0H (D ABBJ @t1BDE A(A0F@c 0D(A BBBG HBEI B(A0D8D@ 8D0A(B BBBF LFEB E(A0A8G 8A0A(B BBBB LTXFFB B(A0A8DN 8A0A(B BBBB HVFEB E(F0D8G` 8A0A(B BBBF GNU4P4!XX `U qX#W74!jy X% HUp!x!o`  ! h oooo H!%%%%%%%&& &0&@&P&`&p&&&&&&&&&'' '0'@'P'`'p'''''''''(( (0(@(P(`(p((((((((()) )0)@)P)`)p)))))))))** *0*@*P*`*p*********++ +0+@+P+`+p+++++++++,, ,@@?!GA$3a1X%UU GA$3p11132FUGA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*GOW*33 GA*FORTIFY4FUGA+GLIBCXX_ASSERTIONSbigdecimal.so-3.3.11-9.el8.x86_64.debug`7zXZִF!t/#]?Eh=ڊ2N`@ (^\B(it 3Fglvڷ/§J UU!lM/TuA3$%b[T;9Wv:*G`klXSFΊ[lUPSA ]IhEt\L4;Wry+k- %B]tvo܎;x0AFV)0 =1V5v}3D9괡[vƑ36<_(z>ҘigqӲ#BǬ/'V!^׸=8BmୠӸYvi49!8#0>WJx*INpȫ)-1b2kLr[%żbQ*j:=qPo;f"& h2~qE]  AlBIv_vXY!_|1Kr2S0%&-Gf-M ܎ϡ#?A@`ʑ-N/fY. DXFaoXm՞{@݅ vx_,yoʳc@wYQ9|4^ C۠$+L12gh$ )޿r>@]ð¤%Se۽`iʦwXN}{^f^]Ҷ2jtTmo40{os G&ܥ=ͦ(~9O SA/#"DdH pWwMJeY| (K4@9ӷ!M:$r̟B:U`1}<*ILxp{~y{hKbػ0{+W"2iΩREh ^f,E ަƬ1"WCAcΝ6i.GmI&P6@ևfe͂rƠ}3쒏 U7B[|!pyv{R#<Ä>@ 3(L}z 5Ɓ4ÞT.ig~ۚThl5et;v?{}'8)S DOtzZIC]e?p@j\G2[u<7`#L9TfKm M Ѻ<zHuŕ[/ hoRu9gNAocuT܀z HI0/*_0-Z=1/T0OD5Ꮟ>Kt&7_ 0ZވZvd7JrL*[h+Nn.TX"\l@۫i{MxD$bQ?>o~ʚj{ 2fp\\5R, 67WchǪ JHP|-Tk¿6~Mt:7n\jhjiK5^`*eR¤JWlRe`Fs?@/4X$O6M$,x)ZN{5eJ~ ՌEVR7 1Dinb~C:_UtpKdC'u6ۑjJ>Is0L[-_TQ(;K8ԯq,@}@8 @H`H` ll l @  mm m 888$$(`(`(` Std(`(`(` PtdVVVQtdRtdll l PPGNUԻ(gl] U^ BHH ^fix BE"aj |SE6 ZqXH82_Ur  p]1U?f }S-,,G" DO.I<"stJO""a_^nv}, 7F"y{! =f =rr  S `Qs s s  -X @TZs  r s *s __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeyaml_get_versionrb_ary_new_from_values__stack_chk_failInit_psychrb_ext_ractor_saferb_define_modulemPsychInit_psych_parserInit_psych_emitterInit_psych_to_rubyInit_psych_yaml_treerb_define_singleton_methodrb_check_typeddatayaml_emitter_deleteruby_xfreeyaml_emitter_set_canonicalrb_data_typed_object_zallocyaml_emitter_initializeyaml_emitter_set_unicodeyaml_emitter_set_indentyaml_emitter_emitrb_eRuntimeErrorrb_raiseyaml_mapping_end_event_initializeyaml_sequence_end_event_initializeyaml_document_end_event_initializeyaml_stream_end_event_initializerb_fix2intrb_num2intyaml_emitter_set_widthyaml_stream_start_event_initializerb_unexpected_typerb_attr_getrb_utf8_encodingrb_enc_str_newrb_funcallvyaml_alias_event_initializerb_str_export_to_encrb_string_value_cstryaml_mapping_start_event_initializeyaml_sequence_start_event_initializerb_string_value_ptryaml_scalar_event_initializeyaml_document_start_event_initializerb_ary_entryruby_xcallocrb_string_valuerb_ivar_setyaml_emitter_set_outputrb_error_arityrb_cObjectrb_define_class_undercPsychEmitterrb_define_alloc_funcrb_internrb_define_methodyaml_parser_deleterb_funcallv_publicmemcpyrb_ull2inumyaml_parser_initializerb_intern2cPsychParserrb_const_get_atrb_class_new_instancerb_utf8_encindexrb_default_internal_encodingrb_respond_torb_ascii8bit_encindexrb_usascii_encindexrb_enc_find_indexyaml_parser_set_encodingyaml_parser_set_inputrb_enc_get_indexyaml_parser_set_input_stringyaml_parser_parserb_protectrb_str_new_cstrrb_enc_associate_indexyaml_event_deleterb_jump_tagrb_str_newrb_ary_newrb_ary_new_from_argsrb_to_encoding_indexrb_ary_pushrb_eNoMemErrorrb_exc_raiserb_const_getrb_usascii_str_new_cstrrb_define_constrb_requirerb_define_private_methodrb_path_to_classrb_obj_allocrb_iv_setrb_define_module_undercPsychVisitorsToRubycPsychVisitorsYamlTreelibruby.so.3.3libyaml-0.so.2libm.so.6libpthread.so.0libc.so.6_edata__bss_start_endGLIBC_2.2.5GLIBC_2.14GLIBC_2.4/opt/alt/ruby33/lib64ui &ii 1l ,l ,l l l Ul p.@m oVPm  @o  o  o io 'o go bo co jo Io No Ro Tp  p (p 0p 8p @p Hp Pp Xp  `p  hp  pp xp p p p p ^p p p p p p p p p fp `p p q q q q  q !(q "0q a8q #@q $Hq %Pq &Xq (`q )hq *pq +xq ,q -q .q /q 0q 1q 2q 3q 4q 5q 6q 7q 8q 9q :q ;q <r =r >r ?r @ r A(r B0r C8r D@r EHr FPr GXr H`r Jhr Kpr Lxr Mr Or Pr Qr Sr Tr Ur Vr Wr Xr Yr Zr [r \r ]HH!O HtH5bO %cO hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?h@hAhBhChDhEhFhGqhHahIQhJAhK1hL!hMhNhOhPhQhRhShThUhVhWqhXahYQhZA%I D%I D%I D%I D%I D%I D%}I D%uI D%mI D%eI D%]I D%UI D%MI D%EI D%=I D%5I D%-I D%%I D%I D%I D% I D%I D%H D%H D%H D%H D%H D%H D%H D%H D%H D%H D%H D%H D%H D%H D%H D%H D%}H D%uH D%mH D%eH D%]H D%UH D%MH D%EH D%=H D%5H D%-H D%%H D%H D%H D% H D%H D%G D%G D%G D%G D%G D%G D%G D%G D%G D%G D%G D%G D%G D%G D%G D%G D%}G D%uG D%mG D%eG D%]G D%UG D%MG D%EG D%=G D%5G D%-G D%%G D%G D%G D% G D%G D%F D%F D%F D%F D%F DH?f.DH=F HF H9tHNC Ht H=F H5F H)HHH?HHtHUC HtfD=EF u+UH=:C Ht H=? dF ]wH8dH%(HD$(1HT$ Ht$H|$HcD$Ht$HDHD$HcD$HDHD$HcD$ HDHD$ HL$(dH3 %(uH8^ff.HH='bH#B 1H5'HHH5@1HHH5> |HcHHDff.HH5> LHcHHDff.HH5> x|HHHЃf.SH#H[f.SHH5A> 1HH@H[DUH> SHHHh @uHh H|H/HHH[]SHt[H@ HSH5%H81DATH5= USHHpdH%(HD$h1HHI7HLHT$hdH3%(u HpH[]A\ff.ATH5= USHHpdH%(HD$h1HHIGHLHT$hdH3%(u HpH[]A\ff.ATUHH5< SHHpdH%(HD$h11HH@IHHLHT$hdH3%(u HpH[]A\/ff.@ATH5#< USHHpdH%(HD$h1HHIHL,HT$hdH3%(u HpH[]A\ff.USHH5; H7HHtHHH[]fUSHH5`; HHHtWHHH[]fATUHSHH5 ; HpdH%(HD$h1HIHH߉1HLHHT$hdH3%(u Hp[]A\DATIUHSHH5@ dH%(HD$1HJLHHHHH5z@ H$HǨt"EH\$dH3%(uH[]A\@ff.ATUSHHĀHt$H59 dH%(HD$x1`H|$IHu:1Hl$HHLHHT$xdH3%(u`H[]A\@@uHu HHu?H|$H2HD$HtH|$ Hu AWAVAUIATUHSLHHt$H59 H$dH%(HD$x1}IH|$IHH<$HH߃TE1MAE1H<$t HfI1H|$t H|$OHLl$LADL&LLHHT$xdH3%(HĈ[]A\A]A^A_f@uEHt@HHu4LH߃H$H C@uHu [HHuLHD$DAWAVAUATIUHSLHHt$H$dH%(HD$x1TH|$IHH<$HHH5J7 H߃IE1MAE1H<$t HI1H|$t H|$HLd$LADLsLLHHT$xdH3%(HĈ[]A\A]A^A_@u=Ht8HHu,LiH$,EfD@uHu HHuL$HD$%DAWAVMAUMATUHSHHt$(H56 H$HT$ HL$dH%(H$1lH|$(@uHtIHHt 3H|$(HI{H|$ HD$(Ht$@uHtHHuLLHD$ H|$Ht$@uHtHHuLHD$H߃7HD$(MH|$(AE1MH@AEH$91H|$HtH|$HD$HL$H1H|$ t!H|$ HL$HT$HL$HT$HLl$0SEAVDD$LXLZLHH$dH3%(u!HĨ[]A\A]A^A_D'9fAWAVAUATUHH5)4 SHHH|$HL$dH%(H$1HD$@uHtHEHƒHtHO HHHE1E1Ll$PHEE1H|$A HHHt$HLHNLLH|$LMtL}H$dH3 %(HD$H[]A\A]A^A_HEHL1HaHIQLAIuepLAD$HteD$LH HD$ uH;HHt8HfHE{LAD$Hu kHH<$&1H<$IIgHCLt$0Lt$ Ll$@HD$(Ld$PHl$8HfDH t0HH9HD$(H<@uHuBfH9kHC HHƃHu H~HwHGHt$@H@LIHHD$PLLd$ H|$@L,H|$PLHD$@LHD$PLIGIGH;,$Lt$0Hl$8Ll$ hH~?HG H0Ht$@aHCH$HLt$0Hl$8Ll$P%Ll$PLt$0LH3 H5|H81}xAWAVAUIATUHH5f0 SHHILeu;H5t6 LL1LLH5oHL[]A\A]A^A_DH]H56 11HH56 11HIH55 11HHLAHu@KL!Ht9L1HL@80{fźxSH=OH5+HH1 HHHH5HH1 H5HHH;HYH5H;HH5H;1HvH5H;HKH5H;HH5dH;H%H5IH;HH5.H;1HH5H;HH5uH;1H_H5kH;HH5\H;1HH5JH;HQH59H;1HH5,}H;HH5bH;1HVH5JH;HH5/H=H=HM3 H=H23 H=H3 H=xH2 [H2 f.@SH#H[f.H5=3 11\ff.H5-3 11H|$xHt$HIHt$ HnLAH$IHt$t$HInHt$ LIă$Hc$L$H$HL$H=|HHTL$ H$0HT$H$(@KH|$A|$d5`HT$LH=H|$xHt$HIHt$ HLAH$IHt$t$HIfHt$ LIă$Hc$L$H$HL$H=HHTL$ H$0HT$H$(H$H$[t$HIHt$ HLH|$xIHt$HIHt$ LH$IHEt$HI\Ht$ LIŃ$Hc$L$H$HL$H=HHL L$ $L$(HH$0HT$HH$@H$8@H|$xAHt,t$HIHD$ HtLHIL$H$HT$H=L$c|$xL$HEH$HT$H=H$$@IHD$xHHcPHcHtHT1HD$0L$MHD$0$L$L$ H$H=VH$HEHT$H$(HT$LH=!H|$|$dqH$HdH3%(HD$8HX[]A\A]A^A_HcD$xL$H$H=HT$HDH$DHT$LH=@HT$LH=H9\$fH$IH9H$IH9 H$IH9pAH$AHVt$HIH|$ fDAH$AH}t$HIH|$ ]HfDH|$xAHtt$HIH$AH!t$HIY@H$I9hHl$@Hl$ L|$HI[t$HI Ht|LH,I|$IHt)%t$HHD$(HT$(HHHL1I~LHM9tNI<$HqAI|$Htt$HHD$(fHHT$(tf.Hl$@L|$HjHD$0IAAH$HtNt$AHIHD$hHD$hHD$hEu"H HHmHuH}HEHL`HEPHXH# Hu L- LH" HtHH H8IHD$PH$H?I9KD$H$H?H9HDH$ H}H?H9HD?H}H$(Ht8H}8H$0HtH$8H." Hu HHH" HtH$HLHlHw;LjpH5 SH5HHK H8HD H5HHRH;H5dH;H5TH;H5EH;H59H=56H;HH5-+H;1HoH5#H=gH=HY! TH=HH=H2! 5H=H! "H=H H=H H=H H=tH H=hH H=dHu H=^HZ H=YH? H=CH$ w[H f.@HD@UHHSHKHH59HHHH[]ff.ATH=US\H- H5HHHUHH5IMHUH5HHHH5HH H5HHH5 [L]HH5A\SH=`H5aHH5[HH/ HH$HH5fHH+ H[HHPsychlibyaml_version%stag tuple must be of length 2HandlerEmitterinitializestart_streamend_streamstart_documentend_documentscalarstart_sequenceend_sequencestart_mappingend_mappingaliascanonicalcanonical=indentationindentation=line_widthline_width=iowritePsych/emitterMarkexternal_encodingUTF-16LEUTF-16BESyntaxErrornewParserANYUTF8UTF16LEUTF16BEpsych/syntax_error_native_parsemarkreadpathemptyevent_locationPsych/parser,L$L4DDmesgClassLoaderVisitorsVisitorToRubybuild_exceptionpath2classYAMLTree;1hh (@HXxp(X 8T(xH|80|h,x(Hh( <Xl(HhX 8hHXH zRx $FJ w?:*3$"D\H@t A xtXHK%HW%HW&HWEL+Ee$XEMD |DA<P+AM A 0XdeFHA GB  DABA 0eFHA GB  DABA 0qFAK GK  DABA 0(eFHA GB  DABA ((dGEAN c DAD (TGEAN c DAD 0{FAD NX  AABA zRx $0FDD D0m  AABE 00FAA G`  AABE HP{FBB E(A0D8J 8A0A(B BBBC H{FBB B(D0D8J 8A0A(B BBBH \4FBE E(A0D8GnENDe 8A0A(B BBBF LHFBB B(A0K8J 8A0A(B BBBH H48FBB E(A0K8I@A 8D0A(B BBBF (rEeEL 4H\pQH C A QH C A DQH C A 0(FDD G@  AABI \`1Ek(xEHD@ AAE Lx FEB B(A0A8J 8A0A(B BBBI L $(4EGD ^DA(PFHA DU|0ZETGNU,,l Up.oV @; Tl l o`  Q p 0 oooom !! !0!@!P!`!p!!!!!!!!!"" "0"@"P"`"p"""""""""## #0#@#P#`#p#########$$ $0$@$P$`$p$$$$$$$$$%% %0%@%P%`%p%%%%%%%%%&& &0&@&P&GA$3a1 T GA$3p1113,TGA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA$3p1113-?TGA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFY,LS GA*FORTIFY-TGA+GLIBCXX_ASSERTIONSGA+GLIBCXX_ASSERTIONS,LSpsych.so-3.3.11-9.el8.x86_64.debug+H7zXZִF!t/W]?Eh=ڊ2Nl[$irtUt!6(G:+`{0GL8oui ۯnHҔکyNlPpy[,^^)\Ɖ?@4_~_rhKr H9zRmFkn`/mXGkB,/ 9 ,LQ>rO@c2sP(涨T#:69m{i&8tLKqҖP+_։"}Vp_<&ڛ X6YF{~ aKҟRK]YS-غyRsaѭe6J W1J%uRwō]滬PTx`*h|J6"|y~cfpJ]䎊6%MTxP@3TS 0Z _p ZV?RcU4%wc8' /"˵&Z8>%v ؙ5?65rW moci[^?nHڣܱy.k+3B8*i#\U)zI*T5oQ& e2x5= Tzq|z4 &INԳ(ni)sS0Z 0JM i{L{WW<((P՟K|?= rU0Ofp;1S#5{D ,pq (Ϝ߱gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o```(  0 Q8oEo@T00^Bh c n`&`&w,,(}TT TTIVVXX(`(` l ll ll l m mo o`p pr rs`r| lw(w|+PK!psych-5.1.2/gem.build_completenu[PK!#pM 2.2.0/json.rbnu[require 'json/common' ## # = JavaScript Object Notation (JSON) # # JSON is a lightweight data-interchange format. It is easy for us # humans to read and write. Plus, equally simple for machines to generate or parse. # JSON is completely language agnostic, making it the ideal interchange format. # # Built on two universally available structures: # 1. A collection of name/value pairs. Often referred to as an _object_, hash table, record, struct, keyed list, or associative array. # 2. An ordered list of values. More commonly called an _array_, vector, sequence or list. # # To read more about JSON visit: http://json.org # # == Parsing JSON # # To parse a JSON string received by another application or generated within # your existing application: # # require 'json' # # my_hash = JSON.parse('{"hello": "goodbye"}') # puts my_hash["hello"] => "goodbye" # # Notice the extra quotes '' around the hash notation. Ruby expects # the argument to be a string and can't convert objects like a hash or array. # # Ruby converts your string into a hash # # == Generating JSON # # Creating a JSON string for communication or serialization is # just as simple. # # require 'json' # # my_hash = {:hello => "goodbye"} # puts JSON.generate(my_hash) => "{\"hello\":\"goodbye\"}" # # Or an alternative way: # # require 'json' # puts {:hello => "goodbye"}.to_json => "{\"hello\":\"goodbye\"}" # # JSON.generate only allows objects or arrays to be converted # to JSON syntax. to_json, however, accepts many Ruby classes # even though it acts only as a method for serialization: # # require 'json' # # 1.to_json => "1" # module JSON require 'json/version' begin require 'json/ext' rescue LoadError require 'json/pure' end end PK!eX2.2.0/expect.rbnu[$expect_verbose = false # Expect library adds the IO instance method #expect, which does similar act to # tcl's expect extension. # # In order to use this method, you must require expect: # # require 'expect' # # Please see #expect for usage. class IO # call-seq: # IO#expect(pattern,timeout=9999999) -> Array # IO#expect(pattern,timeout=9999999) { |result| ... } -> nil # # Reads from the IO until the given +pattern+ matches or the +timeout+ is over. # # It returns an array with the read buffer, followed by the matches. # If a block is given, the result is yielded to the block and returns nil. # # When called without a block, it waits until the input that matches the # given +pattern+ is obtained from the IO or the time specified as the # timeout passes. An array is returned when the pattern is obtained from the # IO. The first element of the array is the entire string obtained from the # IO until the pattern matches, followed by elements indicating which the # pattern which matched to the anchor in the regular expression. # # The optional timeout parameter defines, in seconds, the total time to wait # for the pattern. If the timeout expires or eof is found, nil is returned # or yielded. However, the buffer in a timeout session is kept for the next # expect call. The default timeout is 9999999 seconds. def expect(pat,timeout=9999999) buf = '' case pat when String e_pat = Regexp.new(Regexp.quote(pat)) when Regexp e_pat = pat else raise TypeError, "unsupported pattern class: #{pat.class}" end @unusedBuf ||= '' while true if not @unusedBuf.empty? c = @unusedBuf.slice!(0).chr elsif !IO.select([self],nil,nil,timeout) or eof? then result = nil @unusedBuf = buf break else c = getc.chr end buf << c if $expect_verbose STDOUT.print c STDOUT.flush end if mat=e_pat.match(buf) then result = [buf,*mat.to_a[1..-1]] break end end if block_given? then yield result else return result end nil end end PK!K7EE2.2.0/rinda/rinda.rbnu[require 'drb/drb' require 'thread' ## # A module to implement the Linda distributed computing paradigm in Ruby. # # Rinda is part of DRb (dRuby). # # == Example(s) # # See the sample/drb/ directory in the Ruby distribution, from 1.8.2 onwards. # #-- # TODO # == Introduction to Linda/rinda? # # == Why is this library separate from DRb? module Rinda ## # Rinda error base class class RindaError < RuntimeError; end ## # Raised when a hash-based tuple has an invalid key. class InvalidHashTupleKey < RindaError; end ## # Raised when trying to use a canceled tuple. class RequestCanceledError < ThreadError; end ## # Raised when trying to use an expired tuple. class RequestExpiredError < ThreadError; end ## # A tuple is the elementary object in Rinda programming. # Tuples may be matched against templates if the tuple and # the template are the same size. class Tuple ## # Creates a new Tuple from +ary_or_hash+ which must be an Array or Hash. def initialize(ary_or_hash) if hash?(ary_or_hash) init_with_hash(ary_or_hash) else init_with_ary(ary_or_hash) end end ## # The number of elements in the tuple. def size @tuple.size end ## # Accessor method for elements of the tuple. def [](k) @tuple[k] end ## # Fetches item +k+ from the tuple. def fetch(k) @tuple.fetch(k) end ## # Iterate through the tuple, yielding the index or key, and the # value, thus ensuring arrays are iterated similarly to hashes. def each # FIXME if Hash === @tuple @tuple.each { |k, v| yield(k, v) } else @tuple.each_with_index { |v, k| yield(k, v) } end end ## # Return the tuple itself def value @tuple end private def hash?(ary_or_hash) ary_or_hash.respond_to?(:keys) end ## # Munges +ary+ into a valid Tuple. def init_with_ary(ary) @tuple = Array.new(ary.size) @tuple.size.times do |i| @tuple[i] = ary[i] end end ## # Ensures +hash+ is a valid Tuple. def init_with_hash(hash) @tuple = Hash.new hash.each do |k, v| raise InvalidHashTupleKey unless String === k @tuple[k] = v end end end ## # Templates are used to match tuples in Rinda. class Template < Tuple ## # Matches this template against +tuple+. The +tuple+ must be the same # size as the template. An element with a +nil+ value in a template acts # as a wildcard, matching any value in the corresponding position in the # tuple. Elements of the template match the +tuple+ if the are #== or # #===. # # Template.new([:foo, 5]).match Tuple.new([:foo, 5]) # => true # Template.new([:foo, nil]).match Tuple.new([:foo, 5]) # => true # Template.new([String]).match Tuple.new(['hello']) # => true # # Template.new([:foo]).match Tuple.new([:foo, 5]) # => false # Template.new([:foo, 6]).match Tuple.new([:foo, 5]) # => false # Template.new([:foo, nil]).match Tuple.new([:foo]) # => false # Template.new([:foo, 6]).match Tuple.new([:foo]) # => false def match(tuple) return false unless tuple.respond_to?(:size) return false unless tuple.respond_to?(:fetch) return false unless self.size == tuple.size each do |k, v| begin it = tuple.fetch(k) rescue return false end next if v.nil? next if v == it next if v === it return false end return true end ## # Alias for #match. def ===(tuple) match(tuple) end end ## # Documentation? class DRbObjectTemplate ## # Creates a new DRbObjectTemplate that will match against +uri+ and +ref+. def initialize(uri=nil, ref=nil) @drb_uri = uri @drb_ref = ref end ## # This DRbObjectTemplate matches +ro+ if the remote object's drburi and # drbref are the same. +nil+ is used as a wildcard. def ===(ro) return true if super(ro) unless @drb_uri.nil? return false unless (@drb_uri === ro.__drburi rescue false) end unless @drb_ref.nil? return false unless (@drb_ref === ro.__drbref rescue false) end true end end ## # TupleSpaceProxy allows a remote Tuplespace to appear as local. class TupleSpaceProxy ## # A Port ensures that a moved tuple arrives properly at its destination # and does not get lost. # # See https://bugs.ruby-lang.org/issues/8125 class Port # :nodoc: attr_reader :value def self.deliver port = new begin yield(port) ensure port.close end port.value end def initialize @open = true @value = nil end ## # Don't let the DRb thread push to it when remote sends tuple def close @open = false end ## # Stores +value+ and ensure it does not get marshaled multiple times. def push value raise 'port closed' unless @open @value = value nil # avoid Marshal end end ## # Creates a new TupleSpaceProxy to wrap +ts+. def initialize(ts) @ts = ts end ## # Adds +tuple+ to the proxied TupleSpace. See TupleSpace#write. def write(tuple, sec=nil) @ts.write(tuple, sec) end ## # Takes +tuple+ from the proxied TupleSpace. See TupleSpace#take. def take(tuple, sec=nil, &block) Port.deliver do |port| @ts.move(DRbObject.new(port), tuple, sec, &block) end end ## # Reads +tuple+ from the proxied TupleSpace. See TupleSpace#read. def read(tuple, sec=nil, &block) @ts.read(tuple, sec, &block) end ## # Reads all tuples matching +tuple+ from the proxied TupleSpace. See # TupleSpace#read_all. def read_all(tuple) @ts.read_all(tuple) end ## # Registers for notifications of event +ev+ on the proxied TupleSpace. # See TupleSpace#notify def notify(ev, tuple, sec=nil) @ts.notify(ev, tuple, sec) end end ## # An SimpleRenewer allows a TupleSpace to check if a TupleEntry is still # alive. class SimpleRenewer include DRbUndumped ## # Creates a new SimpleRenewer that keeps an object alive for another +sec+ # seconds. def initialize(sec=180) @sec = sec end ## # Called by the TupleSpace to check if the object is still alive. def renew @sec end end end PK!Q"112.2.0/rinda/ring.rbnu[# # Note: Rinda::Ring API is unstable. # require 'drb/drb' require 'rinda/rinda' require 'thread' require 'ipaddr' module Rinda ## # The default port Ring discovery will use. Ring_PORT = 7647 ## # A RingServer allows a Rinda::TupleSpace to be located via UDP broadcasts. # Default service location uses the following steps: # # 1. A RingServer begins listening on the network broadcast UDP address. # 2. A RingFinger sends a UDP packet containing the DRb URI where it will # listen for a reply. # 3. The RingServer receives the UDP packet and connects back to the # provided DRb URI with the DRb service. # # A RingServer requires a TupleSpace: # # ts = Rinda::TupleSpace.new # rs = Rinda::RingServer.new # # RingServer can also listen on multicast addresses for announcements. This # allows multiple RingServers to run on the same host. To use network # broadcast and multicast: # # ts = Rinda::TupleSpace.new # rs = Rinda::RingServer.new ts, %w[Socket::INADDR_ANY, 239.0.0.1 ff02::1] class RingServer include DRbUndumped ## # Special renewer for the RingServer to allow shutdown class Renewer # :nodoc: include DRbUndumped ## # Set to false to shutdown future requests using this Renewer attr_writer :renew def initialize # :nodoc: @renew = true end def renew # :nodoc: @renew ? 1 : true end end ## # Advertises +ts+ on the given +addresses+ at +port+. # # If +addresses+ is omitted only the UDP broadcast address is used. # # +addresses+ can contain multiple addresses. If a multicast address is # given in +addresses+ then the RingServer will listen for multicast # queries. # # If you use IPv4 multicast you may need to set an address of the inbound # interface which joins a multicast group. # # ts = Rinda::TupleSpace.new # rs = Rinda::RingServer.new(ts, [['239.0.0.1', '9.5.1.1']]) # # You can set addresses as an Array Object. The first element of the # Array is a multicast address and the second is an inbound interface # address. If the second is omitted then '0.0.0.0' is used. # # If you use IPv6 multicast you may need to set both the local interface # address and the inbound interface index: # # rs = Rinda::RingServer.new(ts, [['ff02::1', '::1', 1]]) # # The first element is a multicast address and the second is an inbound # interface address. The third is an inbound interface index. # # At this time there is no easy way to get an interface index by name. # # If the second is omitted then '::1' is used. # If the third is omitted then 0 (default interface) is used. def initialize(ts, addresses=[Socket::INADDR_ANY], port=Ring_PORT) @port = port if Integer === addresses then addresses, @port = [Socket::INADDR_ANY], addresses end @renewer = Renewer.new @ts = ts @sockets = [] addresses.each do |address| if Array === address make_socket(*address) else make_socket(address) end end @w_services = write_services @r_service = reply_service end ## # Creates a socket at +address+ # # If +address+ is multicast address then +interface_address+ and # +multicast_interface+ can be set as optional. # # A created socket is bound to +interface_address+. If you use IPv4 # multicast then the interface of +interface_address+ is used as the # inbound interface. If +interface_address+ is omitted or nil then # '0.0.0.0' or '::1' is used. # # If you use IPv6 multicast then +multicast_interface+ is used as the # inbound interface. +multicast_interface+ is a network interface index. # If +multicast_interface+ is omitted then 0 (default interface) is used. def make_socket(address, interface_address=nil, multicast_interface=0) addrinfo = Addrinfo.udp(address, @port) socket = Socket.new(addrinfo.pfamily, addrinfo.socktype, addrinfo.protocol) @sockets << socket if addrinfo.ipv4_multicast? or addrinfo.ipv6_multicast? then if Socket.const_defined?(:SO_REUSEPORT) then socket.setsockopt(:SOCKET, :SO_REUSEPORT, true) else socket.setsockopt(:SOCKET, :SO_REUSEADDR, true) end if addrinfo.ipv4_multicast? then interface_address = '0.0.0.0' if interface_address.nil? socket.bind(Addrinfo.udp(interface_address, @port)) mreq = IPAddr.new(addrinfo.ip_address).hton + IPAddr.new(interface_address).hton socket.setsockopt(:IPPROTO_IP, :IP_ADD_MEMBERSHIP, mreq) else interface_address = '::1' if interface_address.nil? socket.bind(Addrinfo.udp(interface_address, @port)) mreq = IPAddr.new(addrinfo.ip_address).hton + [multicast_interface].pack('I') socket.setsockopt(:IPPROTO_IPV6, :IPV6_JOIN_GROUP, mreq) end else socket.bind(addrinfo) end socket end ## # Creates threads that pick up UDP packets and passes them to do_write for # decoding. def write_services @sockets.map do |s| Thread.new(s) do |socket| loop do msg = socket.recv(1024) do_write(msg) end end end end ## # Extracts the response URI from +msg+ and adds it to TupleSpace where it # will be picked up by +reply_service+ for notification. def do_write(msg) Thread.new do begin tuple, sec = Marshal.load(msg) @ts.write(tuple, sec) rescue end end end ## # Creates a thread that notifies waiting clients from the TupleSpace. def reply_service Thread.new do loop do do_reply end end end ## # Pulls lookup tuples out of the TupleSpace and sends their DRb object the # address of the local TupleSpace. def do_reply tuple = @ts.take([:lookup_ring, nil], @renewer) Thread.new { tuple[1].call(@ts) rescue nil} rescue end ## # Shuts down the RingServer def shutdown @renewer.renew = false @w_services.each do |thread| thread.kill thread.join end @sockets.each do |socket| socket.close end @r_service.kill @r_service.join end end ## # RingFinger is used by RingServer clients to discover the RingServer's # TupleSpace. Typically, all a client needs to do is call # RingFinger.primary to retrieve the remote TupleSpace, which it can then # begin using. # # To find the first available remote TupleSpace: # # Rinda::RingFinger.primary # # To create a RingFinger that broadcasts to a custom list: # # rf = Rinda::RingFinger.new ['localhost', '192.0.2.1'] # rf.primary # # Rinda::RingFinger also understands multicast addresses and sets them up # properly. This allows you to run multiple RingServers on the same host: # # rf = Rinda::RingFinger.new ['239.0.0.1'] # rf.primary # # You can set the hop count (or TTL) for multicast searches using # #multicast_hops. # # If you use IPv6 multicast you may need to set both an address and the # outbound interface index: # # rf = Rinda::RingFinger.new ['ff02::1'] # rf.multicast_interface = 1 # rf.primary # # At this time there is no easy way to get an interface index by name. class RingFinger @@broadcast_list = ['', 'localhost'] @@finger = nil ## # Creates a singleton RingFinger and looks for a RingServer. Returns the # created RingFinger. def self.finger unless @@finger @@finger = self.new @@finger.lookup_ring_any end @@finger end ## # Returns the first advertised TupleSpace. def self.primary finger.primary end ## # Contains all discovered TupleSpaces except for the primary. def self.to_a finger.to_a end ## # The list of addresses where RingFinger will send query packets. attr_accessor :broadcast_list ## # Maximum number of hops for sent multicast packets (if using a multicast # address in the broadcast list). The default is 1 (same as UDP # broadcast). attr_accessor :multicast_hops ## # The interface index to send IPv6 multicast packets from. attr_accessor :multicast_interface ## # The port that RingFinger will send query packets to. attr_accessor :port ## # Contain the first advertised TupleSpace after lookup_ring_any is called. attr_accessor :primary ## # Creates a new RingFinger that will look for RingServers at +port+ on # the addresses in +broadcast_list+. # # If +broadcast_list+ contains a multicast address then multicast queries # will be made using the given multicast_hops and multicast_interface. def initialize(broadcast_list=@@broadcast_list, port=Ring_PORT) @broadcast_list = broadcast_list || ['localhost'] @port = port @primary = nil @rings = [] @multicast_hops = 1 @multicast_interface = 0 end ## # Contains all discovered TupleSpaces except for the primary. def to_a @rings end ## # Iterates over all discovered TupleSpaces starting with the primary. def each lookup_ring_any unless @primary return unless @primary yield(@primary) @rings.each { |x| yield(x) } end ## # Looks up RingServers waiting +timeout+ seconds. RingServers will be # given +block+ as a callback, which will be called with the remote # TupleSpace. def lookup_ring(timeout=5, &block) return lookup_ring_any(timeout) unless block_given? msg = Marshal.dump([[:lookup_ring, DRbObject.new(block)], timeout]) @broadcast_list.each do |it| send_message(it, msg) end sleep(timeout) end ## # Returns the first found remote TupleSpace. Any further recovered # TupleSpaces can be found by calling +to_a+. def lookup_ring_any(timeout=5) queue = Queue.new Thread.new do self.lookup_ring(timeout) do |ts| queue.push(ts) end queue.push(nil) end @primary = queue.pop raise('RingNotFound') if @primary.nil? Thread.new do while it = queue.pop @rings.push(it) end end @primary end ## # Creates a socket for +address+ with the appropriate multicast options # for multicast addresses. def make_socket(address) # :nodoc: addrinfo = Addrinfo.udp(address, @port) soc = Socket.new(addrinfo.pfamily, addrinfo.socktype, addrinfo.protocol) begin if addrinfo.ipv4_multicast? then soc.setsockopt(Socket::Option.ipv4_multicast_loop(1)) soc.setsockopt(Socket::Option.ipv4_multicast_ttl(@multicast_hops)) elsif addrinfo.ipv6_multicast? then soc.setsockopt(:IPPROTO_IPV6, :IPV6_MULTICAST_LOOP, true) soc.setsockopt(:IPPROTO_IPV6, :IPV6_MULTICAST_HOPS, [@multicast_hops].pack('I')) soc.setsockopt(:IPPROTO_IPV6, :IPV6_MULTICAST_IF, [@multicast_interface].pack('I')) else soc.setsockopt(:SOL_SOCKET, :SO_BROADCAST, true) end soc.connect(addrinfo) rescue Exception soc.close raise end soc end def send_message(address, message) # :nodoc: soc = make_socket(address) soc.send(message, 0) rescue nil ensure soc.close if soc end end ## # RingProvider uses a RingServer advertised TupleSpace as a name service. # TupleSpace clients can register themselves with the remote TupleSpace and # look up other provided services via the remote TupleSpace. # # Services are registered with a tuple of the format [:name, klass, # DRbObject, description]. class RingProvider ## # Creates a RingProvider that will provide a +klass+ service running on # +front+, with a +description+. +renewer+ is optional. def initialize(klass, front, desc, renewer = nil) @tuple = [:name, klass, front, desc] @renewer = renewer || Rinda::SimpleRenewer.new end ## # Advertises this service on the primary remote TupleSpace. def provide ts = Rinda::RingFinger.primary ts.write(@tuple, @renewer) end end end PK!772.2.0/rinda/tuplespace.rbnu[require 'monitor' require 'thread' require 'drb/drb' require 'rinda/rinda' require 'enumerator' require 'forwardable' module Rinda ## # A TupleEntry is a Tuple (i.e. a possible entry in some Tuplespace) # together with expiry and cancellation data. class TupleEntry include DRbUndumped attr_accessor :expires ## # Creates a TupleEntry based on +ary+ with an optional renewer or expiry # time +sec+. # # A renewer must implement the +renew+ method which returns a Numeric, # nil, or true to indicate when the tuple has expired. def initialize(ary, sec=nil) @cancel = false @expires = nil @tuple = make_tuple(ary) @renewer = nil renew(sec) end ## # Marks this TupleEntry as canceled. def cancel @cancel = true end ## # A TupleEntry is dead when it is canceled or expired. def alive? !canceled? && !expired? end ## # Return the object which makes up the tuple itself: the Array # or Hash. def value; @tuple.value; end ## # Returns the canceled status. def canceled?; @cancel; end ## # Has this tuple expired? (true/false). # # A tuple has expired when its expiry timer based on the +sec+ argument to # #initialize runs out. def expired? return true unless @expires return false if @expires > Time.now return true if @renewer.nil? renew(@renewer) return true unless @expires return @expires < Time.now end ## # Reset the expiry time according to +sec_or_renewer+. # # +nil+:: it is set to expire in the far future. # +true+:: it has expired. # Numeric:: it will expire in that many seconds. # # Otherwise the argument refers to some kind of renewer object # which will reset its expiry time. def renew(sec_or_renewer) sec, @renewer = get_renewer(sec_or_renewer) @expires = make_expires(sec) end ## # Returns an expiry Time based on +sec+ which can be one of: # Numeric:: +sec+ seconds into the future # +true+:: the expiry time is the start of 1970 (i.e. expired) # +nil+:: it is Tue Jan 19 03:14:07 GMT Standard Time 2038 (i.e. when # UNIX clocks will die) def make_expires(sec=nil) case sec when Numeric Time.now + sec when true Time.at(1) when nil Time.at(2**31-1) end end ## # Retrieves +key+ from the tuple. def [](key) @tuple[key] end ## # Fetches +key+ from the tuple. def fetch(key) @tuple.fetch(key) end ## # The size of the tuple. def size @tuple.size end ## # Creates a Rinda::Tuple for +ary+. def make_tuple(ary) Rinda::Tuple.new(ary) end private ## # Returns a valid argument to make_expires and the renewer or nil. # # Given +true+, +nil+, or Numeric, returns that value and +nil+ (no actual # renewer). Otherwise it returns an expiry value from calling +it.renew+ # and the renewer. def get_renewer(it) case it when Numeric, true, nil return it, nil else begin return it.renew, it rescue Exception return it, nil end end end end ## # A TemplateEntry is a Template together with expiry and cancellation data. class TemplateEntry < TupleEntry ## # Matches this TemplateEntry against +tuple+. See Template#match for # details on how a Template matches a Tuple. def match(tuple) @tuple.match(tuple) end alias === match def make_tuple(ary) # :nodoc: Rinda::Template.new(ary) end end ## # Documentation? class WaitTemplateEntry < TemplateEntry attr_reader :found def initialize(place, ary, expires=nil) super(ary, expires) @place = place @cond = place.new_cond @found = nil end def cancel super signal end def wait @cond.wait end def read(tuple) @found = tuple signal end def signal @place.synchronize do @cond.signal end end end ## # A NotifyTemplateEntry is returned by TupleSpace#notify and is notified of # TupleSpace changes. You may receive either your subscribed event or the # 'close' event when iterating over notifications. # # See TupleSpace#notify_event for valid notification types. # # == Example # # ts = Rinda::TupleSpace.new # observer = ts.notify 'write', [nil] # # Thread.start do # observer.each { |t| p t } # end # # 3.times { |i| ts.write [i] } # # Outputs: # # ['write', [0]] # ['write', [1]] # ['write', [2]] class NotifyTemplateEntry < TemplateEntry ## # Creates a new NotifyTemplateEntry that watches +place+ for +event+s that # match +tuple+. def initialize(place, event, tuple, expires=nil) ary = [event, Rinda::Template.new(tuple)] super(ary, expires) @queue = Queue.new @done = false end ## # Called by TupleSpace to notify this NotifyTemplateEntry of a new event. def notify(ev) @queue.push(ev) end ## # Retrieves a notification. Raises RequestExpiredError when this # NotifyTemplateEntry expires. def pop raise RequestExpiredError if @done it = @queue.pop @done = true if it[0] == 'close' return it end ## # Yields event/tuple pairs until this NotifyTemplateEntry expires. def each # :yields: event, tuple while !@done it = pop yield(it) end rescue ensure cancel end end ## # TupleBag is an unordered collection of tuples. It is the basis # of Tuplespace. class TupleBag class TupleBin extend Forwardable def_delegators '@bin', :find_all, :delete_if, :each, :empty? def initialize @bin = [] end def add(tuple) @bin.push(tuple) end def delete(tuple) idx = @bin.rindex(tuple) @bin.delete_at(idx) if idx end def find @bin.reverse_each do |x| return x if yield(x) end nil end end def initialize # :nodoc: @hash = {} @enum = enum_for(:each_entry) end ## # +true+ if the TupleBag to see if it has any expired entries. def has_expires? @enum.find do |tuple| tuple.expires end end ## # Add +tuple+ to the TupleBag. def push(tuple) key = bin_key(tuple) @hash[key] ||= TupleBin.new @hash[key].add(tuple) end ## # Removes +tuple+ from the TupleBag. def delete(tuple) key = bin_key(tuple) bin = @hash[key] return nil unless bin bin.delete(tuple) @hash.delete(key) if bin.empty? tuple end ## # Finds all live tuples that match +template+. def find_all(template) bin_for_find(template).find_all do |tuple| tuple.alive? && template.match(tuple) end end ## # Finds a live tuple that matches +template+. def find(template) bin_for_find(template).find do |tuple| tuple.alive? && template.match(tuple) end end ## # Finds all tuples in the TupleBag which when treated as templates, match # +tuple+ and are alive. def find_all_template(tuple) @enum.find_all do |template| template.alive? && template.match(tuple) end end ## # Delete tuples which dead tuples from the TupleBag, returning the deleted # tuples. def delete_unless_alive deleted = [] @hash.each do |key, bin| bin.delete_if do |tuple| if tuple.alive? false else deleted.push(tuple) true end end end deleted end private def each_entry(&blk) @hash.each do |k, v| v.each(&blk) end end def bin_key(tuple) head = tuple[0] if head.class == Symbol return head else false end end def bin_for_find(template) key = bin_key(template) key ? @hash.fetch(key, []) : @enum end end ## # The Tuplespace manages access to the tuples it contains, # ensuring mutual exclusion requirements are met. # # The +sec+ option for the write, take, move, read and notify methods may # either be a number of seconds or a Renewer object. class TupleSpace include DRbUndumped include MonitorMixin ## # Creates a new TupleSpace. +period+ is used to control how often to look # for dead tuples after modifications to the TupleSpace. # # If no dead tuples are found +period+ seconds after the last # modification, the TupleSpace will stop looking for dead tuples. def initialize(period=60) super() @bag = TupleBag.new @read_waiter = TupleBag.new @take_waiter = TupleBag.new @notify_waiter = TupleBag.new @period = period @keeper = nil end ## # Adds +tuple+ def write(tuple, sec=nil) entry = create_entry(tuple, sec) synchronize do if entry.expired? @read_waiter.find_all_template(entry).each do |template| template.read(tuple) end notify_event('write', entry.value) notify_event('delete', entry.value) else @bag.push(entry) start_keeper if entry.expires @read_waiter.find_all_template(entry).each do |template| template.read(tuple) end @take_waiter.find_all_template(entry).each do |template| template.signal end notify_event('write', entry.value) end end entry end ## # Removes +tuple+ def take(tuple, sec=nil, &block) move(nil, tuple, sec, &block) end ## # Moves +tuple+ to +port+. def move(port, tuple, sec=nil) template = WaitTemplateEntry.new(self, tuple, sec) yield(template) if block_given? synchronize do entry = @bag.find(template) if entry port.push(entry.value) if port @bag.delete(entry) notify_event('take', entry.value) return port ? nil : entry.value end raise RequestExpiredError if template.expired? begin @take_waiter.push(template) start_keeper if template.expires while true raise RequestCanceledError if template.canceled? raise RequestExpiredError if template.expired? entry = @bag.find(template) if entry port.push(entry.value) if port @bag.delete(entry) notify_event('take', entry.value) return port ? nil : entry.value end template.wait end ensure @take_waiter.delete(template) end end end ## # Reads +tuple+, but does not remove it. def read(tuple, sec=nil) template = WaitTemplateEntry.new(self, tuple, sec) yield(template) if block_given? synchronize do entry = @bag.find(template) return entry.value if entry raise RequestExpiredError if template.expired? begin @read_waiter.push(template) start_keeper if template.expires template.wait raise RequestCanceledError if template.canceled? raise RequestExpiredError if template.expired? return template.found ensure @read_waiter.delete(template) end end end ## # Returns all tuples matching +tuple+. Does not remove the found tuples. def read_all(tuple) template = WaitTemplateEntry.new(self, tuple, nil) synchronize do entry = @bag.find_all(template) entry.collect do |e| e.value end end end ## # Registers for notifications of +event+. Returns a NotifyTemplateEntry. # See NotifyTemplateEntry for examples of how to listen for notifications. # # +event+ can be: # 'write':: A tuple was added # 'take':: A tuple was taken or moved # 'delete':: A tuple was lost after being overwritten or expiring # # The TupleSpace will also notify you of the 'close' event when the # NotifyTemplateEntry has expired. def notify(event, tuple, sec=nil) template = NotifyTemplateEntry.new(self, event, tuple, sec) synchronize do @notify_waiter.push(template) end template end private def create_entry(tuple, sec) TupleEntry.new(tuple, sec) end ## # Removes dead tuples. def keep_clean synchronize do @read_waiter.delete_unless_alive.each do |e| e.signal end @take_waiter.delete_unless_alive.each do |e| e.signal end @notify_waiter.delete_unless_alive.each do |e| e.notify(['close']) end @bag.delete_unless_alive.each do |e| notify_event('delete', e.value) end end end ## # Notifies all registered listeners for +event+ of a status change of # +tuple+. def notify_event(event, tuple) ev = [event, tuple] @notify_waiter.find_all_template(ev).each do |template| template.notify(ev) end end ## # Creates a thread that scans the tuplespace for expired tuples. def start_keeper return if @keeper && @keeper.alive? @keeper = Thread.new do while true sleep(@period) synchronize do break unless need_keeper? keep_clean end end end end ## # Checks the tuplespace to see if it needs cleaning. def need_keeper? return true if @bag.has_expires? return true if @read_waiter.has_expires? return true if @take_waiter.has_expires? return true if @notify_waiter.has_expires? end end end PK!7F2.2.0/optionparser.rbnu[require_relative 'optparse' PK!/Lw2.2.0/x86_64-linux/nkf.sonuȯELF>@@x@8 @\\ ^^$^$hm $$  888$$h\h\h\ Stdh\h\h\ PtdIIIQtdRtd^^$^$aaGNU*ّj/&NWwbT%%7HD+(**@2%'(*+,-.024589:;?ACFHKMNµ{qlip ϵA%$ 夂sc 9d%x2uLO8Aq^CWQ."A(JA{v! 9;s ~qXǤV|A׶UˮR5cu:BE>'5ύ|SoIf H~3 4%Ax, YF"$$  $$ n~$N$(, g$l $nq$[`$ e$oa$_$ u$d$ $s f$ yb\e$$ |U$@x$v@$P $I@$o 3@$P1~.j$f$x$`E n$ $x$__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeencoding_name_to_id_tablex0212_shiftjiseuc_to_utf8_2bytesx0212_to_utf8_2bytes_x0213euc_to_utf8_1bytex0213_1_surrogate_tableeuc_to_utf8_2bytes_x0213euc_to_utf8_2bytes_msx0212_to_utf8_2byteseuc_to_utf8_2bytes_macx0213_2_surrogate_tableNkfEncodingUTF_16NkfEncodingUTF_8NkfEncodingUTF_32__stack_chk_failrb_str_resizeexitstderrfwritestrcmpmallocperrorinput_code_listshiftjis_x0212shiftjis_cp932cp932invutf8_to_euc_2bytes_x0213utf8_to_euc_3bytes_x0213utf8_to_euc_2bytes_macutf8_to_euc_2bytes_932utf8_to_euc_3bytes_932utf8_to_euc_3bytes_msutf8_to_euc_2bytes_msutf8_to_euc_3bytesutf8_to_euc_2bytesutf8_to_euc_3bytes_macx0213_combining_table__fprintf_chknl_langinfonkf_encoding_tablenormalization_table__assert_failreallocfreeNkfEncodingASCIINkfEncodingISO_2022_JPmime_priority_funcrb_nkf_enc_getrb_enc_find_indexrb_enc_from_indexrb_define_dummy_encodingrb_string_valuerb_enc_from_encodingrb_out_of_intnkf_split_optionsrb_str_newrb_str_set_lenrb_usascii_encodingrb_enc_associaterb_eArgErrorrb_raiseInit_nkfrb_define_modulerb_define_module_functionrb_singleton_classrb_define_aliasrb_define_constrb_utf8_encodingrb_str_new_staticNkfEncodingShift_JISNkfEncodingEUC_JPx0213_combining_charslibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.3.4GLIBC_2.4GLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64xti ii ui ^$^$ ^$ ^$@^$H^$uP^$X^$ʅ`^$څh^$څp^$x^$^$^$^$^$^$^$^$ ^$'^$+^$O^$/^$q^$9^$<_$?_$_$j_$: _$o(_$v0_$D8_$H@_$LH_$QP_$TX_$J`_$_h_$ep_$ix_$l_$n_$T_$y_$~_$_$_$_$e_$_$_$_$_$_$_$_$`$*`$`$`$ `$(`$0`$8`$@`$H`$gP`$X`$Ć``$Yh`$p`$x`$`$#`$`$+`$`$:`$`$2`$`$B`$`$M`$`$Ȇ`$ӆ`$Ն`$a$a$a$ a$ a$d(a$0a$8a$@a$Ha$Pa$ǃXa$`a$Ճha$pa$߃xa$a$a$a$ra$a$b$  b$`(b$0b$8b$ @b$`Pb$Xb$`b$ hb$`pb$xb$b$ b$`b$b$b$ b$`b$b$b$ b$`b$b$b$ b$`b$b$c$ c$`c$c$ c$ (c$`0c$8c$@c$ Pc$`Xc$`c$xc$ c$`c$c$c$ c$`c$c$c$ c$`c$c$c$ c$`c$c$c$ 0d$`8d$d$$d$$d$$d$$d$$d$$d$$d$$d$~$e$x$0e$$8e$$@e$$He$$Pe$$Xe$$`e$$he$$e$z$e$$e$$e$$e$$e$$e$$e$$e$$f$z$0f$$8f$$@f$$Hf$$Pf$$Xf$$`f$$hf$$f$z$f$$f$$f$$f$$f$$f$$f$$f$$g$|$0i$`8i$@i$Hi$Pi$`Xi$`hi$pi$`xi$`i$i$`i$i$i$`i$l$`l$l$`l$`l$l$m$m$` m$`(m$0p$8p$`@p$`Hp$`Xp$xp$p$p$`p$`p$s$s$s$`s$`s$s$t$t$` t$`(t$0w$`8w$@w$`Hw$`Xw$xw$w$w$`w$`w$y$y$`y$`y$`y$hz$`z$`z$z$`z${$`{${$|$|$`|$`|$}$`}$}$~$~$~$`~$~$`=~$`<~$`;~$`:~$`9~$`8~$`7~$`6~$`5~$`4~$`3~$`2$`1$`0$`/$`. $`-($`,0$+H$*P$)X$(`$'h$&p$%x$$$#$"$!$ $$$$$$$$$$$$$$$$ $($8$ @$ H$ P$ X$ `$h$p$x$$$$$=$<$;$:$9Ȁ$8Ѐ$7؀$6$5$4$3$2$1$0$/$. $-($,0$+H$`+P$`*X$`)`$`(h$`'p$`&x$`%$`$$`#$`"$`!$` $`$`$`$`ȁ$`Ё$`؁$`$`$`$`$`$`$`$`$` $`($`8$`@$` H$` P$` X$` `$` h$`p$`x$`$`$`$`$`|$`{$`z$`y$`xȂ$`wЂ$`v؂$`u$`t$`s$`r$`q$`p$`o$`n$`m $`l($`k0$`j8$`i@$`hH$`gP$`fX$`e`$`dh$`cp$`bx$`a$``$`_$`^$`]$`\$`[$`Z$`Y$`Xȃ$`WЃ$`V؃$`U$`T$`S$`R$`Q$`P$`O$`N $`M($`L0$`K8$`J@$`IH$`HP$`GX$`F`$`Eh$`Dp$`Cx$`B$`A$`@$`?$`>$|${$z$y$xȄ$wЄ$v؄$u$t$s$r$q$p$o$n$m $l($k0$j8$i@$hH$gP$fX$e`$dh$cp$bx$a$`$_$^$]$\$[$Z$Y$Xȅ$WЅ$V؅$U$T$S$R$Q$P$O$N $M($L0$K8$J@$IH$HP$GX$F`$Eh$Dp$Cx$B$A$@$?$>$`$`$`$`$`Ȇ$`І$`؆$`$`$`$`$`$`$`$`$` $`($`0$`8$`@$`H$`P$`X$``$`h$`p$`x$`$`$`$`$`$`$`$`$`$`ȇ$`Ї$`؇$`$`$`$`$`$`$`$`$` $`($`0$`8$`@$`H$`P$`X$``$`h$`p$`$`$`$`~$`}$$$$$Ȉ$Ј$؈$$$$$$$$$ $($0$8$@$H$P$X$`$h$p$x$$$$$$$$$$ȉ$Љ$؉$$$$$$$$$ $($0$8$@$H$P$X$`$h$p$$$$~$}$`$`$`$`$`Ȋ$`Њ$`؊$`$`$`$`$`$`$`$`$` $`($`0$`8$`@$`H$`P$`X$``$`h$`p$`x$`$`$`$`$`$`$`$`$`$`ȋ$`Ћ$`؋$`$`$`$`$`$`$`$`$` $`($`0$`8$`@$`H$`P$`X$``$`h$`p$`x$`$`$`$`$`$$$$$Ȍ$Ќ$،$$$$$$$$$ $($0$8$@$H$P$X$`$h$p$x$$$$$$$$$$ȍ$Ѝ$؍$$$$$$$$$ $($0$8$@$H$P$X$`$h$p$x$$$$$$`;$`:$`9$`8$`7Ȏ$`6Ў$`5؎$`4$`3$`2$`1$`0$`/$`.$`-$`, $`+($`*0$`)8$`(@$`'H$`&P$`%X$`$`$`#h$`"p$`!x$` $`$`$`$`$`$`$`$`$`ȏ$`Џ$`؏$`$`$`$`$`$`$`$` $`  $` ($` 0$` 8$`@$`H$`P$`X$``$`h$`p$`x$`$`$`$`$`$;$:$9$8$7Ȑ$6А$5ؐ$4$3$2$1$0$/$.$-$, $+($*0$)8$(@$'H$&P$%X$$`$#h$"p$!x$ $$$$$$$$$ȑ$Б$ؑ$$$$$$$$ $  $ ($ 0$ 8$@$H$P$X$`$h$p$x$$$$$$W$`W$V$`VȒ$UВ$`Uؒ$T$`T$S$`S$R$`R$Q $`Q($P0$`P8$O@$`OH$NP$`NX$M`$`Mh$Lp$`L$K$`K$J$`J$I$`IГ$Hؓ$`H$G$`G$F$`F $E8$`E@$DH$`D`$`Ch$`Bp$`Ax$`@$`?$`>$`=$`<`$Ch$Bp$Ax$@$?$>$=$<$v$`v$t$sؖ$`s$r$q$`p$o$`o$`n$`m$`k $j($`j0$i8$`i@$hH$`hP$gX$`g`$fh$`fp$ex$`e$d$`d$c$`c$b$`b$aȗ$`a$`$``$_$`_$^$`^ $]8$`]@$\H$`\P$[X$`[`$Zh$`Zp$Y$`Y$X$`X$`w$`v$`u$`t$`r$p$n$m$l$k$`w$`v$`u$`t$r$`q$`o$`n$`m$`l$w$`v$u$`t$r$`q$`o$`n$`m$`l$$`$$`Ȟ$О$؞$$$$`$$$`$ $`($8$@$`H$~P$}X$|`${h$z$`z$y$`yП$x؟$`x$`$Ƞ$`Р$`ؠ$`$`$`$$`($`@$`H$~P$`~X$`}`$`|h$`{$`$`Ȣ$Т$`آ$`$$`$`$`($@$`H$~P$`~X$`}`$`|h$`{$$`Ȥ$Ф$`ؤ$`$`$`$`$`($@$`H$~P$`~X$`}`$`|h$`{$`$`Ȧ$Ц$`ئ$`$`$`$`$`($@$`H$~P$`~X$`}`$`|h$`{`$`$$$@$$@$Ȫ$Ъ$ت$$$@$$$@$$$ $($@0$8$@$H$@P$X$`$h$@p$x$$$@$$$$@$$$ȫ$@Ы$ث$$$@$$$$@$$ $($@0$8$@$H$@P$X$`$h$@p$x$$$@$$$$@$$$Ȭ$@Ь$ج$$$@$$$$$@$ $($0$@8$@$H$P$@X$`$h$p$@x$$$$@ȭ$Э$$$@$$ $($@0$8$@$H$@P$X$`$h$@p$x$$$@$$$$@$$$Ȯ$@Ю$خ$$$@$$$$@$$ $($@0$8$@$H$@P$X$`$h$@p$x$$$@$$$$@$$$ȯ$@Я$د$$$@$$$0$@8$$H$E$@D$B$@AȰ$?а$@>ذ$<$@;$9$@8$6$3$@2$0$0 $@/($.0$-8$-@$@,H$+P$*X$*`$@)h$(p$'x$'$@&$%$$$$$@#$"$!$!$@ ȱ$б$ر$$@$$$$@$$$@ $($0$8$@@$H$P$X$@`$h$p$x$@$ $ $ $@ $ $ $ $@$Ȳ$в$ز$@$$$$@$$$$@ $($0$8$@$H$@P$X$`$@h$p$@x$$@$$H$F$E$C$Bȳ$@г$?س$=$<$:$9$6$4$3$1$0 $@/($.0$-8$-@$@,H$+P$*X$*`$@)h$(p$'x$'$@&$%$$$$$@#$"$!$!$@ ȴ$д$ش$$@$$$$@$$$@ $($0$8$@@$H$P$X$@`$h$p$x$@$ $ $ $@ $ $ $ $@$ȵ$е$ص$@$$$$@$$$$@ $($0$8$@@$`$h$p$x$$H$F$E$C$Bȶ$@ж$?ض$=$<$:$9$7$@5$3$1$0 $@/($.0$-8$-@$@,H$+P$*X$*`$@)h$(p$'x$'$@&$%$$$$$@#$"$!$!$@ ȷ$з$ط$$@$$$$@$$$@ $($0$8$@@$H$P$X$@`$h$p$x$@$ $ $ $@ $ $ $ $@$ȸ$и$ظ$@$$$$@$$$$@ $($0$8$@@$`$h$p$x$$H$@G$E$C$Bȹ$@й$?ع$=$<$:$9$7$@5$3$1$0 $@/($.0$-8$-@$@,H$+P$*X$*`$@)h$(p$'x$'$@&$%$$$$$@#$"$!$!$@ Ⱥ$к$غ$$@$$$$@$$$@ $($0$8$@@$H$P$X$@`$h$p$x$@$ $ $ $@ $ $ $ $@$Ȼ$л$ػ$@$$$$@$$$$@ $($0$8$@@$`$h$p$x$@$H$Px$ $ $$F$$F$ $$F$$F$ $$$$$$$$ $P@$ `$Sh$x$$P2$P$$T$ $$ $H$ $$F$$F$$F$$F$D$$$ $0$@$P$`$p$ $($6$D$U$Q$_$h$l$x$ $0$@$P$ `$p$$$߄$$$‡$·$݇$$҄$ $0$@$ P$`$p$[$$*$3$$j$@$M$V$˄ $($ 0$P@$H$P$`$h$ p$p$ $$$$$P$'$$$`$$$$$D $c8$P$h$$ $($6$D$$n$($ @$zX$p$$$$$$҄$$0$H$ `$x$[$$*$3$$j$@ $M8$VP$˄$2$($Ⱦ$Mо$,ؾ$N$.$*$0$0$0$0($0@$0$)$O$%$<$5 $H($ 0$:8$C@$6@$6X$6p$6$6$6$6$6H$AP$&X$G`$3$3 $38$3P$3h$Ip$7x$1$/$L$J$+$9$8$4$>$ȿ$-$-($-X$-п$ ؿ$!$Eh$E$E$E$E$E$#$;$;$;$;$;0$?H$?`$?x$?$?$?$?$ $($0$8$@$H$P$ X$ `$ h$=p$ x$@$$$$$$$$$$$$$$$$$$!$"$$HH1#HtH5#%#hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh %#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%}#D%u#D%m#D%e#D%]#D%U#D%M#D%E#D%=#D%5#D%-#D%%#D%#D%#D% #D%#D%#D%#D%#D%#D%#DH% fDH=!#H#H9tHV#Ht H=#H5#H)HHH?HHtH#HtfD=#u+UH=#Ht H=>#)d#]w?XL (#AASMAtetMACB tJIt&aD^ABaDZAB9tIAAy[ÐfDtIAAtf-OHFS&1$##1#?B=غC1ֺ)ƃ0#ھZ| 1ֺ)ƃ0#غY1ֺ )ƃ0|#غMb1ֺ̉)ƃ0P#غQ1ֺ)ƃ0$#̉1Љ)ƃ0#غ1)Ís0#;1[%#f'(cK ~mfAU&ATU1SHe##1X#x1K#L%:#كt;ЍY9|L-GD1AtAԉمyL%#HL;1[]A\A]AT\U1S#U1L%Dz#01#01#1HA4k#1A4V#1 A4>#1A4##A41#A4,[1]A\%#Du1L%#fAU\ATU1SH#x1#{1#L%#كt;ЍY9|L-D1AtAԉمyL%V#HL}1[]A\A]N#%"#f.AfAfAtP~DGAqA_EMD~t 1_1D $D@EtDHA~QDHAvwA]wL #McOMtAAGLHEEuqD@A FDMcLC< tAvYD@AvfAv:~2"AE1D DD@A@A~@%ǀuAu ? @π:Aft8=aA?A@πAD ?? @΀2A8A?A ?@πA D9AAfDHtkǀxf9}bHcHHtVƀ?wHHcrft< C$ft fw&f-t fx+fDA1Aøf.̏fDff=tH1!] Q$9$cH#HcH D1HumD $Eu"u Ct41!]w'D$HcE"Hs#H D1D=1$H <#1V߃]wHcQ$tȍ(wW!Hc H#H9 L#".1IxtH9uHcHIATPT $fH#HcH D }!Hct H!#H Ha#H HI#H xLY#!!1Ix@H9u0fH #HH# HD#AtC~!AtKAu- fDAu  Df Ð  9=$txSY ~/)33hM$[t;u#(#I#$[f#.#A#$[e#$Z#(O#QD#$[@-#$"#=h##w$[D#$#(#D#>$[@#$#(#P#$[@D_ExOAt>wAtRIDwt3D؃p pO~AJ ÃO O AJ @f.G p t+`tVpt G fH G H G AHuBA B @H G AHBA B ff.AUATUSH$$Aă AŅ$ E% k$=a$ H*#H$t1 Ѓ=>$ tH# 1Et7Et2$ H[]A\A]Du uEuf.u tHމ[]A\A]%# DtEu`tuH$ Afu +$@ u  ufDR$'fATUS=#t=#.H#p$у#u!&Hަ<&Hy#H13@u[]A\@ 1ۉ[]A\fDF< 3A#H#$1Ƀt%t1ہgw[]A\f#L#DPHH Hc#4<AЁD-H ĶHcЀ<H < $tH U<H ![]H<A\4%#Dh[]A\%#!wt M߃]nUރ5bH [HcH>Hڤ>|HǤ"d-f#`#=N#>#L;#DP^[H_vH5ɴ u!5[$YH5  FHc[]#4A\ADu 1[ ]1A\%#MH5NHc ,}si_@UH HcD$EDAD@H3T@1H HcH[#]4<A\Aff.tw/@~M~EZ~`~m~6z %O# ~O&/ ~O)/@ %#FуLDGуLD$H#t %t.!tqt0t%DF߃R|tuHx$H@H;u#AH;#Au H;k#u01N̓vHtFˉ!C$u+ ~&1t@ǃ$$f!tOff.F=w vmG׃veG v]HA9"/"A.LA"fDD@H9 D9ANANI9u%e#D."@5f#H _#VT#@<fff.AWAVIAUAHATIUHSH҉D9HADxAōPA v@v;@HAAč@AL$ vv AT$wjA]9T$ HAԋT$ Ač@Ѓ AL$vD߃Aw4A wFD w[ H[]A\A]A^A_HDADHDAHDA@Auq1ۃwA]AD$wA7D DwAWD fH #H#H:%v#fDH U#HV#H%q%6#fDAWAVAUATUHSHXL- #L%#dH%(HD$H1AAljD$&t.HT$HdH3%(DzHX[]A\A]A^A_HAՉD$#tHAHAՉD$߃XHD$AE1HD$.DvCGAGA II HDAՉHD$OB w3_]w(k^D$ t$lj։T$|$ Gt$|$ 't$|$ _]Xk^D$ 1_t$us2fH_|$ t$>v-t%Gt$v \@#1H#t.#u$D$ "".D$.t$t$z#uN wCNw8t1~D$ iҼ1)t$SGHL$HT$ 0t$|$ ~~~? f.~8K? ʁ%< ‰׉fD ?ǁ ljÿff.w$1ҁ H=t#HOfDt H9uHcHRDG1ff.fAWAVAUATUSH(|$ t$dH%(HD$1#t+### #DT$ AD\$EuHDL#%=^DAHD$dH3%(~H([]A\A]A^A_DDDÅtǍH-#0uttL|$Lt$Ll$ Ld$MLLL|$Ջ|$ t1#|$t##|$G#<@D#*fDL|$Lt$DLl$ Ld$yMLLLV|$Ջ|$ t#|$H-#t H-#|$.H-}# DHL$HT$ Ht$LD$|$Aҋ|$ AUATUSH#t0=q#H##nп#;u?%=1= #H#ЉH[]A\A]%#AąA0A$DA=#EH8# HD[]A\A]%#%=0 AH#A=8#DЉɻ#H#@=# H[]A\A]%#fDп~# \ %H-#A@A=w#oDЉ#H#=N#Љ#~H[]A\A]D=#@H#H1[]A\A]%#f.%= AAHN#@=#tlЉ0#DH&#E=t#DЉSfD=U#H#Љڹ#xDЉĹ#f.D#D#ff.AUATAUSHS#t@=#H]#7#11A#6#+#ti#uoDDD f#L#%=AE܉A@A1AЉƸ#D#H[]A\A]%#DÅD #L#0uqD_DA@A1AЉ$#D#D#D g#L#DD J#L#ˀADʷ#·#H1[]A\A]%#п#1#1#VfH[]A\A]DDADY#Q#1I#D #L;#Gff.u 1A8D@1A/vAVAAUIATMUS6~!AE1Dl A$1[]A\A]A^HA1ɉ|$ t$~ADL$ AwnEuD\$DD#1HÐD1tA@HH<FH}HcH>f.AAD\$D%=u#tQDDDsH5#K0HNHƘf.H9tH9uHfDHL$ LD$DDDX D\$DL$ DDDD$ E1 AÉD$fDADE>D\$1ASDҁʁtDED\$1AS?vLfED\$1Ap/v)ED\$1ASDҁSEtjD\$1DځDD\$1AS?Et"D\$1A`v1{siff.@H|$ HL$ LD$t$ut$|$ D$ӳ#D$Hf~[ -0u<t,1Df.Lٰ#K01IP@HtB9u9uHcHHIA@#1HøfSAADƉ1D8Ax!DD1"[DƉ[ff.#Ht t= t' tÐ f fSH Hؿ [f.AVAUATUS 5 L%sH5GN#L@ fDAHc9PHL$MuHcHπL%Ls=#-##HU#~:#< b< ZHE1 $#Z##fH-#IcT w)H&HsA|fڰ#{#IA<$@u##D9~2IcH#HD)HHfD}HH9u[]A\A]A^DE1H-V#A9}Ic|@ wI&IpA^Hc*##A9V#E|@ 6HIr'fDH9lAH=ί# ##V#H-#BL%bqfAWAVAUAATUSH=H# #(D=#H-:#EAE~ C7HcDtA Qw~cAE~>6#1|Lc@ N@ DHA9HD[]A\A]A^A_`AA $A A u@=#~&1ې|Hq## #9F# #=#aD%v#,D#QYG(AHH[]A\A]A^A_=#v >A A  A A D #F#E3E11%fD*#H9##|^#D< t< u1D#vD%r#$A A Lc%N#A (E9A A=AD$Fl%#JDH##HkL;H^H9u@*#OA A A  ?h#=]####FA tA t $##A0##t KD%&##DDL#  EL$E7ET$1LwmXHPI9t!HHt Llj€uփA9LcIN|5A<$IE#M9uH=9#j##9~#HH#)HL B42H@rH9u)؍PH,#DlJ~X=p#H[]A\A]A^A_DG~+ t t=#H=#b@#AH[]A\A]A^A_D#1E~!f.|HQ#9##q#A fDI#A_HcD< < EI&AE1 fDIB|5@ wIs =T#FQIFM9uE9BAHh#L#A)IM}HR#L9u=#bwDA`#EH#AGHkHf;HH9u\f.H&LE@H#AL$HBHfDHH9|!<]wL ²#1ۅ~|Hq##9##D-A#@H-1#HEHE!}HH9u=#&#D=5#@H=#}#Dt$ HcD$ D9*H#HD)HHD}HCH9ufEt6##D-K##@A tjA td5m#1ۅ~|H#9O##+BD&#ELz@=#1ۅf|Hb9#C?#=#0#D'#u##=#F~S?R#=G#H=@### #=##*A:AEރ=wH( HDڥ#{#@uD#AE"40#H=#R0#HAD$Fl%#H=g#"K##< v B##q#5H HrAD$Fl%K#Jx7#1ۅ~#D|H##9##5:#Ht t= t' tÐ 1 1SH 1Hؾ 1[fD to t"#~ #%## #Z t9D #Ett@~#Df#E[#  5;#!A #'#!#9? ߢ#91#fD#E(G5#Ë#=# uV!A!E t~# |#;c#m# 1%#f.5J#H=#=#@t[ # #USHH=#H[]%# #uD#Eu  u@# D #1T 5q#@tm1?wHH߃][SEJЃ߃AvuBЃ w ,#F߃>wH `HD!t#Fރ5wH HӃ t tfUSH#H #t H[]5ު#VUUU8#)I~1H=# 1#H ##H[]@G|H m#H[]f5V#VUUU#)BC1H="#% 1#v#p#f #VUUUP#)ʍ<^=$#B/#1#{ff.F#St)#[D#H##%@<[ff.f#t %#@J#P%<#H-#HHH`HDH#H`H81f@~ZGf_G?DÐ/~ G+1>Ð^#uvH=~#tlUSHH#H9#t>Ht2HHHt"H8#tH}.Hg#H#H[]f9t4=#HttH=#pH5%#i@@H(|$ t$dH%(HD$1uD%=##HD$dH3%(H(u U#ff=D$!]G߃]m# @π#|$@πfHT$Ht$ |$ m|$%='%D$ -=Ww &#*Hs#H#|$@π`## C#|$@π5#11fv# X#t,#v#|$ ft$HL$HT$ut$|$HL$HT$ :D$ u#|$#fflc]ALk^)H F#!~+D$ЉT$ ff=u6|$ uD$T$ ʀы|$@π#k艣fH|$ t$u,%=##Htt$sJff=F^nG^bHL$HT$ # a#|$ tSwHL$HQH @HHcHH)HHT#BЅtT$ ׉D$f.ҙ#|$HO#@#|$DHT$Ht$ Y|$ |$%=%D$ -=Ww#H+#H#@΀#uDn# @΀#HD11_Bf.HL$HT$ ,# |$ #|$#]AL=ӗ#1iҼ|$ )у>D@D$U#|$K#ff.ATU-#SH/#Ht*;"w%H,`HcH>b#fDD%#H#H8"wDH w`HcH>K#=#=#u#f.H@H;#H=ξ@H;#H=t#HH@H #eH;n#Xu## =#tH= H=##t%H5 #H=^H=#H5Ж#w A#tH #H#HJH #D#EtH#Hі#HBH#D T#EtHЖ#H#HH#DH#EtH#Hy#HH#=#t&H##Ha#HHc# -#tHT#HE#HH?#5#HHӽHܕ#H͕#t*H H#HH#H #H# U#t8H#Hg#HH#Hr#HC#HH]##t8HT#H#HH?#H0#H#HH#Et8H#H#HH#H#H#H}Hޔ#@#t =##HHCHp'H(#H8t0f.H8@H8@@Ԁ@u[1]A\Ãu #1#>#H@H5H;#H5-#@H;*#HH@H Q#uH; #f.V#Hٓ#H“#HHē#H#H#H߻H#HH51#d#H5Y #H t#H5#kf.H9#H #HH$#H#H#HϳH##9P##Mu *#=#u ##-#0#D%Q###D%1##D%#L#^vHt*Hi#wHH@H#HH#.H#H=I#{#Q8%# =#G#t"#=#%#uݐ#҃u А#1#^#O#=#u #-##D%#)=c#D%###8#a#D%#X#I#D%f##u #1#D%5#m##Aju #1п#D%#'#9u o#1#D%###D%#-#1cf.SHGGH#H9C(t [f.11[fDGHXSHHcH>F>vF|w-HcCPSts{HKHS跼tLH[Jf.F>vF|wHcCPSts{HKHSgK CC[~%=t荆_> HcGGPWt[z #lHGHG[f.F>v F|HcCPSts{HKHScH+CC[HcWHHBGrCC[Í NHcCCPSt[HcGGPWt[AWE1AVAAUAATUSHL%#Lf.E1HH;t,HC Hk8HtDHЋUЅuMuI@EtMt #tTA~5H[]A\A]A^A_AD$I8AD$AD$ԀI<$uH[]A\A]A^A_Iw(H[]A\A]A^A_@AWAVAUATUSH(dH%(HD$1HW<-8HuE1L%LUL5MH(#fuMAELE1 Ho@H<-tEuH{ ##G#PЀ 21HTPEHЀ v#H<-f(b#HG<8 <1<3u2HGHև#HHHƺ#@#HfGH<1p<2HEeDH#HHHq#D@6#H.fDGƒBtfD1H# H# # H#BHƴ#IHS##GHH=FLHH#~HH@H#HH#a6!GHWу##H~#70HP~#'#tH׸0=H$|#HHH#0<vv#HW5D~#Hx#H&~#h#H#HT#HB#13#HxuNH}#pHE #HHp#Hv#HP#H}##|*#H|#{#V#HD|#H2#H1#H H52:0}|#H5#J߀XSD$15A vBDNA(@΃7|$H DH t:DVDNAw@A \0HHHh#SH|HHR#=HB#H*8#H*#HHHH#HɉHH#HSHH٫#@tA{#=;{#HT$Ht$蔱D$H D${#uD$1t DNAwL$HDDH uD$114 DNA nk DǍD0ЍqHt$HuSA@YWTff.fHU#HHBHu)Hc*#; #}*P#H#DHJHHBøf.USHH#HPHBHHuz#H̨#$(xƨ#ht H-z#H#BBHJLHQI9 HqHzL HyI9HHQBD(H[]fDxt(#t8t0XH[]@HJHHBH[]Hgy#H#B@uOHJH1HQH9~OHyLBL LAL9~3HHQBD$kHx#SfDAWAVIAUATUSH(Hz#H z#HD$H#H $Lx уv=kWIWI;IHrA1IwE,,H mu#AIcDl$E1H@HHD$H\fB+M9oF?HcGPWt9}8LCHK SsPH؃CC[~%=t㍆@ HcGGPWt[ٛ#tHGHG[f.F?w HcGSPWt[H[HcGGPWt[fHH9CSs,wHcGGPWt[ff.AWAVAUATUSHdH%(H$1H#D$ Ht!H@H;h#H;3h#!ЉD$ ##n1j#===G1_j#=V1Bj#1H.j#fDHyj#H9HIH9)D$ D$11i#ŃH#H%=='#hH#Ht 8I)D=n#L#Esh_YϏ1|i#1,i#Ń611ai#H=!#u L$ [1H$dH3 %(HĘ[]A\A]A^A_Å1h#1h#==1H}h#11wh#mf.1H>1Uh#Ã*1Bh#Ń1/h#Aă1h#AŃDDp}yHGHg#1҉Ã1g#Ń11҉AH Hg#Hu1Aăt1g#AŃt=f#(vD D ѳb1D6g#1D+g#芠H#g#>1Hc|g#11f#1f#1f#H=#H|H9g#11f#11f#H!d#H;Ht HfDK 9H HLH8H8uH;L#cH;fV)3t|1zf#/DFH"#Hfw~9~˕# I#?=8#hc5#t&CwU߃]wk^1ۍ@߉1e#}fDE߃]dDt$E# E?6f.EeD11De#1҉4e# 1d#AătF1d#AŃ E11AD1Dvd#1Dkd#1҉1覰cHѢH9d#4==#7(f_>g  t #| #K#Hc#1 Ѓ  1oc#H`c#t 1ǽ ҿ 1:c#=#L5yq#sq#]q#-gq#QAV DHc;q#BE<’#q#=ug1b#Aǃu#uGDnH`#H:t$HfDHx t J 9H HLH8H8uHr(p#1D|$AXDH5H9@9HcA1ҽE$DDу+9p#A9|IcA_E,DH b#As1D1AD1a#Aă$A߽U1DDH a#у^D9=o#>IcAAD9=o#FIcAA,DD ja#DD1AJa#DA_>1DAVo#A9AIcAAA9LIcǃAAD$DD$E11҉DDѭ uD|$Aa<@D;=n#kMcAODDCL${`#L$Aσu]n#9sHcDyA L$$A9McAwC t$L$(L$9HcDD$(L$$DxADDAD$,+DDԫK D|$1x_#Ãm#A91V_#D$1DD|#1!_#)@1_#ÃD9=Cm#1^#Ń1^#ÃDD_#l#D9L$1^#L$ƉD$$l#AσwDD詪i@hY Ё3')=f]#z#J1^#Ń?h =G]#nD%l#L5h#AD%A=AD$k#AD$%A?1]#k#J k#A- _ AAuÉH`]#H H9t]HM]#H>]#H }=\#H ]#H\#H ]#u*H\#HH\#HH\#H\#D-X#E D%k#D$f.1Pf1\#Aă1\#D Hv\#1DD裨1|$F\#1<\#D\$ E"#`?ڋ#Pf1[#AăD\#1[#AŃtb1[#Aƃ 1[#Aǃt(AEDD趨^1DK[#1D@[#1D5[#D1o,f.1[#Aă 1Z#AŃAD߉D 1$[#DT$ E:D #ED$ 1ۉD$1Z#=1sZ#1Ho_Z#2f1XZ#=h1;Z#1Ho'Z#f.1HeoZ#f.DD$ E1Y#7&$(;.Ny11Y#1Y#fD,AfD\$1`Y#D|$ƉD$(g#fDDy 1|$$Y#$1Y#D$,DL$,DD$(DL$$D8vD|$]fD1DDD|$Nf1X##11D}X# 1D$sӆ#qHܖH9X#1GX#$1-X#Ń@E1EX#1$8X#=V#|1W# 1W#H=͇# HmH9W# 11W#11W#1W#=Q1eW#1XW#1|$ACW##111豸=#1W#A 1V#H=#2HlH91W#1V#1V#H=dž#HkH9V#1V#H1V#ŃXI* BLHC #1V#1(yV#=#H=.# HaH9ZV#1U#1U#=1H$kU#1U#31 U#1U#xA$(6D D DD蝡HNU#1|$,1|$((U#1|$$U#?1U#Aƃ1U#Aǃ1T#D$t~1T#D$tmDD6jAx)L$T$DDjxD91|$T#1|$vT#1DkT#1D`T#DDi͋1@T#Ń@(8#s#h1D$H$ Hqƒ߃A`PЃ TŃ=.HS#?L1Љŋa#P%A,HS#a#A`߃B ā#B1Љŋa#P%A,H=S#ka#A? Hr#H9_#1 +R#1R#=1H hR#1R#1R#1R#=1R#1gR#D$dHSR#D|$1|$,AD|$1$R#DDZHR#1|$(1|$$Q#D|$1Q#"1Q#ŃA11Q#1.Q#=#(1DtQ#:1 `Q#=#D|$1|$,1|$(A8Q#13Q#|$ 1Q#1WQ#=u#\$ bP# H=#?H,fH9%Q#1P# H5e, P#H5e躓$IH51*)Ѝ))Hcŋ,LP##1twP#1'P# PZv1LP#1$?P#15P#1O#Ã@sDCoP1O#$1O#(1O#11O#uHt$01H=?}#L-Ht$AAMeHD$0LA܉1%O#HL$Bt/pPMC9u IVIl} +I뻾DXIc׉H5@"DGEGELLH@I1EHItFNA8Mu2f HA:LuHcH9uA9u D9IA륹|#hH=4 w}#D$,H=1,y|#H=~#HFcH9?N#1M# A1DM#Hl$AFLeM,Iu1LM#M9uAs1 IuD|$Ao{#H=H4v|#D$@H=&1@D$%D$ 1=z{#H5MsD|$1|$(AH5!bG IcDAL%J#CD51I4{#HL#HV# IfH@#HHts#@Js#Hys# s#"LH$H8 HPHxH`s#HcH9t =>s#1HcM&s#H8H H@HHs#HcH9=r#Hr#Hc5r#HHr#Lu2Ht)HЃ(Hfr#t^KHHJHH[DHHHir#H^H@H{HIr#*@Hq#HxJHHmJHH[@H>#HHq#OH>#HHq#/H>#HHq#Hq>#HpHdq#H$HH%H HIH ?#H5EH81zIf.SH=JHH5|HHqJHHH5VJHJHHHIHߺH5JHߺH5JH5HJH=DDIHIH50HHzJH=IHIH5HHTJH=HHIH5kHH.JH=HHIH5@HHJH=HHdIH5HHIHHEIH5HHIH=gHHIH5HHIH=AHHHHH5HwIH=GHH5HTIH=GHH5H1I H=pGHH5[H IHH0123456789ABCDEF>"<&can't malloc=?SHIFT_JIS?B?=?EUC-JP?B?boundary="NULL%s ic=oc=guess=cap-inputurl-inputnumchar-inputno-outputdebugno-cp932cp932invx0212no-cp932extno-best-fit-charsfb-skipfb-htmlfb-xmlfb-javafb-perlfb-subcharfb-subchar=ms-ucs-maputf8mac-inputprefix=nkf-utf8/nkf.cindex <= buf->len!nkf_buf_empty_p(buf)can't reallocISO-2022-JPBINARYEUC-JIS-2004EUCJP-MSCP51932CP50221CP50220Shift_JISEUC-JPno output encoding givenguessAUTONOCONVUNKNOWNUS-ASCIIEUCSJISUTF8UTF-16BEUTF16UTF-32BEUTF322.1.3 (2013-11-22)2.1.3NKF_VERSION2013-11-22NKF_RELEASE_DATE=?ISO-8859-1?Q?=?ISO-8859-1?B?=?ISO-2022-JP?B?=?ISO-2022-JP?Q?=?UTF-8?B?=?UTF-8?Q?=?US-ASCII?Q?base64jMBeuceuc-inputfjjmhelpmacsLmmimejMmime-inputmsdossLwsjissjis-inputunixeLuversionwindowsh1katakanah2katakana-hiraganah3g2utf8utf16w16utf8-inputWutf16-inputW16UTF-8UTF-16UTF-32646ROMAN8ISO2022JP-CP932CSISO2022JPCP50222ISO-2022-JP-1ISO-2022-JP-3ISO-2022-JP-2004SHIFT_JISMS_KanjiPCKWINDOWS-31JCSWINDOWS31JMS932CP10001EUCJPEUCJP-NKFEUC-JP-MSEUCJPMSEUC-JP-ASCIIEUCJP-ASCIISHIFT_JISX0213SHIFT_JIS-2004EUC-JISX0213UTF-8NUTF-8-BOMUTF8-MACUTF-8-MACUTF-16BE-BOMUTF-16LEUTF-16LE-BOMUTF-32BE-BOMUTF-32LEUTF-32LE-BOMISO-8859-1Windows-31JeucJP-nkfeucJP-MSeucJP-ASCIIShift_JISX0213Shift_JIS-2004WVTTVTTTTWWTTTTTTTTTTTTTTTVTTTTTTTTTTTTTTTTTTTTTTTTTVVPPPPPPPP0PPPPPPhypp::E%pΦΦxZZZZZZğğ wğ\ğxwѥğğңğңğң^ȣңğң^ȣȨxȧ DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDlDDLDD4DԮDDDDDDDD<$DܭDDDDDDDĭt&DDDԬlDDT4DPl/"9"B"I"Q"["k"q"z"}"!#/#:#@#[#`#{#~#t$~$w%~%9&@&Y&~&B'P'r'~'A(~(TO~O%t~t'1(2)3*4+56^67^78^89^9:^:;^;<^<=^=>^>?^?@^@A^A/B^BC^CD^DEFGHIJ^J_JK^K_KL^L_LM^M_MN^N_NOPQRS,T-U.VWXYZ[\&]^3_6_7_8_9_:_>_B_Dnkf_buf_atnkf_buf_pop !!()))*+++2222<+-=<>$%#&*@%w%x%y%z%{%|%}%~%Q%T%W%Z%]%t%,%.%0%2%4%6%8%:%<%>%@%B%E%G%I%P%S%V%Y%\!!!#!V!W!"!&%r%!%#%%%'%)%c%e%g%C!<%"%$%&%(%*%+%-%/%1%3%5%7%9%;%=%?%A%D%F%H%J%K%L%M%N%O%R%U%X%[%^%_%`%a%b%d%f%h%i%j%k%l%m%o%s!+!,LMNOPQRSVWXYZbj|CDPX^npru|}~BIK@ABCDEFGHIJKJFHGACDE@e^_]`\xyz{sqtvoegihjklm]_`adbcfYZ[\MNOQRTSVWUJKL@ABEHFIGdcfgw{}~porqasvwutzxyhiklmnCP`Ustuvwxyz{|}~!"#$%&'(L"C)*+,-h"c_ix!;.-|P?t)H/RTcn'#,)>_XHWcta#0;fmu|15X[en{23@GP^4*5/Dh6Bdhg789Nauwx|/7>[*a:k38;J<=P^tuydm~>Bg?p0,@3=MId(IDdt&Au|Bx+!%C8:DDRW[^mpE!5I9FX~GLHYj}I'56JU8W`jc!+GCKOYKLfn|kp1ex&+-MJSic|tuN3=oq.OJfjptn%y+.-2BPYP;Q;R:CSr]UbimTUVWeXihYZl;[ah'\]Tr.^^_"7AQtFHQ`abcdSHTjz$0e5Kf9gChiYjkblmnG(&)/0*+o@G?`^Qp\R[Tzo3?IPbjkqrsho,t.u1v216wx]yzQ{mM|[fj%{z}V~\]^_`abcdefghijklmnopqrstuvwxyz{|}~@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~@ABCDEFGHIJK@ABCDEFGHIʁUVWTUVWXYZ[\]ʁ@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~;;ÀÀÁÁÂÂẦẦẤẤẪẪẨẨÃÃĀĀĂĂẰẰẮẮẴẴẲẲǠǠÄÄǞǞẢẢÅÅǺǺǍǍȀȀȂȂẠẠẬẬẶẶḀḀĄĄḂḂḄḄḆḆĆĆĈĈĊĊČČÇÇḈḈḊḊĎĎḌḌḐḐḒḒḎḎÈÈÉÉÊÊỀỀẾẾỄỄỂỂẼẼĒĒḔḔḖḖĔĔĖĖËËẺẺĚĚȄȄȆȆẸẸỆỆḜḜĘĘḘḘḚḚḞḞǴǴĜĜḠḠĞĞĠĠǦǦĢĢĤĤḢḢḦḦḤḤḨḨḪḪÌÌÍÍÎÎĨĨĪĪĬĬİİÏÏḮḮỈỈǏǏȈȈȊȊỊỊĮĮḬḬĴĴḰḰǨǨḲḲĶĶḴḴĹĹĽĽḶḶḸḸĻĻḼḼḺḺḾḾṀṀṂṂŃŃÑÑṄṄŇŇṆṆŅŅṊṊṈṈÒÒÓÓÔÔỒỒỐỐỖỖỔỔÕÕṌṌṎṎŌŌṐṐṒṒŎŎÖÖỎỎŐŐǑǑȌȌȎȎƠƠỜỜỚỚỠỠỞỞỢỢỌỌỘỘǪǪǬǬṔṔṖṖŔŔṘṘŘŘȐȐȒȒṚṚṜṜŖŖṞṞŚŚṤṤŜŜṠṠŠŠṦṦṢṢṨṨŞŞṪṪŤŤṬṬŢŢṰṰṮṮÙÙÚÚÛÛŨŨṸṸŪŪṺṺŬŬÜÜǛǛǗǗǕǕǙǙỦỦŮŮŰŰǓǓȔȔȖȖƯƯỪỪỨỨỮỮỬỬỰỰỤỤṲṲŲŲṶṶṴṴṼṼṾṾẀẀẂẂŴŴẆẆẄẄẈẈẊẊẌẌỲỲÝÝŶŶỸỸẎẎŸŸỶỶỴỴŹŹẐẐŻŻŽŽẒẒẔẔ``ààááââầầấấẫẫẩẩããāāăăằằắắẵẵẳẳǡǡääǟǟảảååǻǻǎǎȁȁȃȃạạậậặặḁḁąąḃḃḅḅḇḇććĉĉċċččççḉḉḋḋďďḍḍḑḑḓḓḏḏèèééêêềềếếễễểểẽẽēēḕḕḗḗĕĕėėëëẻẻěěȅȅȇȇẹẹệệḝḝęęḙḙḛḛḟḟǵǵĝĝḡḡğğġġǧǧģģĥĥḣḣḧḧḥḥḩḩḫḫẖẖììííîîĩĩīīĭĭïïḯḯỉỉǐǐȉȉȋȋịịįįḭḭĵĵǰǰḱḱǩǩḳḳķķḵḵĺĺľľḷḷḹḹļļḽḽḻḻḿḿṁṁṃṃńńññṅṅňňṇṇņņṋṋṉṉòòóóôôồồốốỗỗổổõõṍṍṏṏōōṑṑṓṓŏŏööỏỏőőǒǒȍȍȏȏơơờờớớỡỡởởợợọọộộǫǫǭǭṕṕṗṗŕŕṙṙřřȑȑȓȓṛṛṝṝŗŗṟṟśśṥṥŝŝṡṡššṧṧṣṣṩṩşşṫṫẗẗťťṭṭţţṱṱṯṯùùúúûûũũṹṹūūṻṻŭŭüüǜǜǘǘǖǖǚǚủủůůűűǔǔȕȕȗȗưưừừứứữữửửựựụụṳṳųųṷṷṵṵṽṽṿṿẁẁẃẃŵŵẇẇẅẅẘẘẉẉẋẋẍẍỳỳýýŷŷỹỹẏẏÿÿỷỷẙẙỵỵźźẑẑżżžžẓẓẕẕ῭῭΅΅΅¨̍῁῁´´··ӔÆǼǼǢǢǾǾӕæǽǽǣǣǿǿẛẛӘƏӚƏ̈ӨƟӪƟ̈ӠƷǮǮәəӛə̈өɵӫɵ̈ӡʒǯǯʹʹ̀̀́́̐̆̇̈́̈̍̓̓ᾺᾺΆΆᾹᾹᾸᾸΆΑ̍ἈἈἊἊἌἌἎἎἉἉἋἋἍἍἏἏᾼᾼᾈᾈᾊᾊᾌᾌᾎᾎᾉᾉᾋᾋᾍᾍᾏᾏῈῈΈΈΈΕ̍ἘἘἚἚἜἜἙἙἛἛἝἝῊῊΉΉΉΗ̍ἨἨἪἪἬἬἮἮἩἩἫἫἭἭἯἯῌῌᾘᾘᾚᾚᾜᾜᾞᾞᾙᾙᾛᾛᾝᾝᾟᾟῚῚΊΊῙῙῘῘΪΪΊΙ̍ἸἸἺἺἼἼἾἾἹἹἻἻἽἽἿἿῸῸΌΌΌΟ̍ὈὈὊὊὌὌὉὉὋὋὍὍῬῬῪῪΎΎῩῩῨῨΫΫΎΥ̍ὙὙὛὛὝὝὟὟῺῺΏΏΏΩ̍ὨὨὪὪὬὬὮὮὩὩὫὫὭὭὯὯῼῼᾨᾨᾪᾪᾬᾬᾮᾮᾩᾩᾫᾫᾭᾭᾯᾯὰὰάάᾱᾱᾰᾰάα̍ἀἀἂἂἄἄἆἆἁἁἃἃἅἅἇἇᾶᾶᾳᾳᾲᾲᾴᾴᾀᾀᾂᾂᾄᾄᾆᾆᾁᾁᾃᾃᾅᾅᾇᾇᾷᾷὲὲέέέε̍ἐἐἒἒἔἔἑἑἓἓἕἕὴὴήήήη̍ἠἠἢἢἤἤἦἦἡἡἣἣἥἥἧἧῆῆῃῃῂῂῄῄᾐᾐᾒᾒᾔᾔᾖᾖᾑᾑᾓᾓᾕᾕᾗᾗῇῇιιὶὶίίῑῑῐῐϊϊῒῒΐΐΐϊ̍ῗῗίι̍ἰἰἲἲἴἴἶἶἱἱἳἳἵἵἷἷῖῖὸὸόόόο̍ὀὀὂὂὄὄὁὁὃὃὅὅῴόͅῤῤῥῥὺὺύύῡῡῠῠϋϋῢῢΰΰΰϋ̍ῧῧύυ̍ὐὐὒὒὔὔὖὖὑὑὓὓὕὕὗὗῦῦὼὼώώώω̍ὠὠὢὢὤὤὦὦὡὡὣὣὥὥὧὧῶῶῳῳῲῲᾠᾠᾢᾢᾤᾤᾦᾦᾡᾡᾣᾣᾥᾥᾧᾧῷῷϔϔϓϒ̍ЇЇӐӐӒӒЃЃӖӖЁЁӁӁӜӜӞӞӢӢЙЙӤӤЌЌӦӦӮӮЎЎӰӰӲӲӴӴӸӸӑӑӓӓѓѓӗӗёёӂӂӝӝӟӟӣӣййӥӥќќӧӧӯӯўўӱӱӳӳӵӵӹӹїїѶѶѷѷאַאַאָאָאּאּבּבּבֿבֿגּגּדּדּהּהּוֹוֹוּוּזּזּטּטּיּיּךּךּכּכּכֿכֿלּלּמּמּנּנּסּסּףּףּפּפּפֿפֿצּצּקּקּרּרּשּשּשּׁשּׁשּׂשּׂשׁשׁשׂשׂתּתּײַײַक़क़ख़ख़ग़ग़ज़ज़ड़ड़ढ़ढ़ऩऩफ़फ़य़य़ऱऱऴऴড়ড়ঢ়ঢ়রব়য়য়োোৌৌਖ਼ਖ਼ਗ਼ਗ਼ਜ਼ਜ਼ੜਡ਼ਫ਼ਫ਼ଡ଼ଡ଼ଢ଼ଢ଼ୟଯ଼ୋୋୈୈୌୌஔஔொொௌௌோோైైೀೀೊೊೋೋೇೇೈೈൊൊൌൌോോำําຳໍາཀྵཀྵགྷགྷཌྷཌྷདྷདྷབྷབྷཛྷཛྷཱཱཱཱཱཱིིྀྀུུྐྵྐྵྒྷྒྷྜྷྜྷྡྷྡྷྦྷྦྷྫྷྫྷྲྀྲྀཷྲཱྀླྀླྀཹླཱྀ῍῍῎῎῏῏῝῝῞῞῟῟ゔゔががぎぎぐぐげげごござざじじずずぜぜぞぞだだぢぢづづででどどばばぱぱびびぴぴぶぶぷぷべべぺぺぼぼぽぽゞゞヴヴガガギギググゲゲゴゴザザジジズズゼゼゾゾダダヂヂヅヅデデドドババパパビビピピブブププベベペペボボポポヷヷヸヸヹヹヺヺヾヾq!r!L"1!Co!@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_.!a#b#c#d#e#f#g#h#i#j#k#l#m#n#o#p#q#r#s#t#u#v#w#x#y#z#P!C!Q!2"V"W"!"#$%&'()*+,-./0123456789:;<=>?.!a#b#c#d#e#f#g#h#i#j#k#l#m#n#o#p#q#r#s#t#u#v#w#x#y#z#P!C!Q!A!!"#$%&'()*+,-./0123456789:;<=>?.!a#b#c#d#e#f#g#h#i#j#k#l#m#n#o#p#q#r#s#t#u#v#w#x#y#z#P!C!Q!7!"#$%&'()*+,-./0123456789:;<=>?*!0"t!p!s!u!/"J!K!v!\!$!1"%!?!0#1#2#3#4#5#6#7#8#9#'!(!c!a!d!)!w!A#B#C#D#E#F#G#H#I#J#K#L#M#N#O#P#Q#R#S#T#U#V#W#X#Y#Z#N!@!O!0!2!*!*t!p!s!u!)J!K!v!\!$!]!%!?!0#1#2#3#4#5#6#7#8#9#'!(!c!a!d!)!w!A#B#C#D#E#F#G#H#I#J#K#L#M#N#O#P#Q#R#S#T#U#V#W#X#Y#Z#N!@!O!0!2!>#=#at(u+uCueuivwv%wUw)%x'y3y4y7y8y9y;y?y@yMyQydy.zP3z:zDzXztu'{o{y{/|0|8|=|iY|c}v}{}4K/W/rODyzuZwowSU#$gshs%$E&'()]8*js+,-./0MAks1234ls56789:;!I<=ms>q~+2qrsTsP5UsVsWsr~u9XstT`[LcBYs[sZs[\sv]s\^sxy]_s{|}`s~asbs!csdsesfs^+2qrsTsP5UsVsWs~u9XstT`[LcBYs[sZsu\sv]sw^sxyz_s{|}`s~asbs!csdsesfs"TFs]^_UaGsHsIsbcLsJssIIOJJ;skBm:?sL2s8s81s6s9:;7s:s<=>?9s@ABCDsIIOJK;skBm:?sL#:%)s(s`~;(\7)*+a~-.<-s=.s/s0*sc~2tr30saD?4s@5s3sd~A>#$%)s(s&'(\7)*+,-.-s/.s/s0*s12tr30saD44s55s3s67zr.Z~wrl}r[~~r/%s$s\~rs&s-1!s"s0t99L1]~#sw3y42K+s^~'s678,s~_~9zrnowrl}rp~rq%s$srs&s-1!s"stt99Lvu#swxyz2K+s{'s|},s~!"$prqr>Fnrmr#*2&yrxr'(u1bX~Y~vrursr{3rr2<)2ef,hijc9km|r{r^prqr>Fnrmr]*2_yrxr`au1bcdvrursr{3rr2<)2efghijc9km|r{r;D!jr7Horkrlr"1KDLPF[\;DYjr7HorkrlrZ1KDLPF[\Q~=>kcrar-CnoBR~S~pKT~qGZNrersltKufrU~V~grRvwxyz{|}hrW~ir~X<=>?crar-C@ABCDpKEFGZNHerIPJKLfrMgrRNOQSTUVhrWirXO~&ZrVrWrSrYr'Urb3(LO)XrTrRrQr^_`a\r.b/_rcP~^r]r2d4efII[rs0`rhbr8ijo3Mr71;dr%&ZrVrWrSrYr'Urb3(LO)XrTrRrQr*+,-\r./_r01^r]r23456II[rs0`r7br89:o3Mr71;drArJ~DrPpq8BrK~ErrFrGrKr*;sRdBSvLrIrHrJrL~T_7UVXWPrOrNrQ30\M~!ZN~$ArnDropq8BrqErrFrGrKr*;stdBuvLrIrHrJrwx_7yz{PrOrNr|30}~!"#$R9rE~TUVWF~YZ>0G~\:r+J8r];rrHI~?rcnK-;Iz:/AeJM@rhNCrjkOmR9rSTUVWXYZ>0[\:r+J8r];rrab?rcnK-;dz:/Aefg@rhiCrjklm!32:1r0r%L:@<3r4r2r5rbK=>?6r{5@@~BABB~FGCDJK%OC~E7rD~FGOA~Q!32:1r0r%L:;<3r4r2r5rbK=>?6r{5@ABCDEFGHIJK%O|L7rMNOPQ{|;~6!""r<~$%7'(89:#r,$r-;%r=~&r'r(r0)r*r+r,r<?~-r.r5]/r=45678xd45>{|}~!""r#$%&'()*+#r,$r-.%r/&r'r(r0)r*r+r,r12-r.r5]/r345678xd459oq6~7~q?-e8~pq.qq/rqsq09~kb9{l2tquq3vqwqo4xqq51Hzqs&I{qyq}qtu|qv~q:~x!ryzoqbcq?defpqgqqhrqsqijkb9{lmtquqnvqwqopxqqr1Hzqs&I{qyq}qtu|qv~qwx!ryz|9VWlqX'mqZ[\5~)<3+_nq`a|9VWlqXYmqZ[\]<3^_nq`a^qL]q_q#\qK2~O$bq3~R4~SaqTdq%C6cqUeqfqhqgqiqkqjq^qL]q_qM\qKNOPbqQRSaqTdqC6cqUeqfqhqgqiqkqjqUq,~-~9Wqz:;35Vq<{{A38|Yq}?~AB.~DMBZq/~0~-F!GH"[q1~`qUq789Wq:;35Vq<={A38>Yq?@ABCDMBZqEF-FGHI[qJ`q}GqLBX1n6o6rsCNqp6'so2Mqt*Kq+LquJqXq-./0OqPqwQqRq23TqxSqy56Y=}G%LBX1n6o6&sCNqp6'(o2Mq)*Kq+Lq,JqXq-./0OqPq1QqRq23Tq4Sq56Y=s3OGGqHq{|}ZCkF~n"Iqops3OGGqHq{|}ZCkF~!"Iq#$de;q=qfklq@qAqoCqB6*~qritjkhi;q=qjklq@qAqoCqB6pqrstuvP-q_LQT.q\MB1A;S/qn20qTWX1qZ[\3q4qZ6q2q[5q\][4^7q8q^_`bcdabc9q:qP-q_LQR.q\MB1A;S/qn20qTUV1qWXY3q4qZ6q2q[5q\][4^7q8q_`abcdefg9q:qH)q(qE*qI(~JGtHLf)?KM25NOK)~+qP,q,R;]SHQR{0S;0Ot;0K~>D)q(qE*qFGtHLf)?H25IJKL+qM,q,R;]SH{0N;0Ot;0K~>wI$q?@<%qA&q>'qCD'~EFGwI$q:;<%q=&q>'q?@ABC*yp=,{pjB[3\3zp-|}}}i428~}!~j4"~#~?E`N45%~>\88|p&~}p~p!q#q"q*yp+,{pjB[3\3zp-./i42801j423?E`N4567\88|p9}p~p!q#q"qGJ:D":2`9g=s\?w}sp34rpBMh4RH\F56|?NNu[7zx}|vp9up<~y}KK,F"#z}:;P1'wptpQIjMxp)GJ:D":`9g=s\?tspvwrpBMh4RH\Fxy|?NNu[7z{|vp}up(~!KK,F"#$%&P1'wptpQIjMxp)q}gpYZhp[ipr}]jp+_`a,Z4-d./t}kpgs}i0llp#Gm1np;2u}qppppqr$1A6XgpYZhp[ip\]jp^_`abZ4cdefjkpghikllp#Gmnnp;2oqppppqr$1A6B[ps3Yp]pC^pH0_p`pn}$Fd>G%ap&JG5'dpcpbpqkL\Jo}()epfpPQRSp}U*WB[ps3Yp]pC^pH0_p`pDEFd>GHapIJG5KdpcpbpqkL\JMNOepfpPQRSTUVWzNp.KpLp{MpOp/h}i}j}vD@|wL}4E@k}~PpsHQpSsLL7RpSp8TpW3!VpY?l}Wpm}$7<=>Xp\p?Zp@A-Np.KpLpMpOp/u01vD@2wL34E@56PpsHQpSsLL7RpSp8TpW39VpY?:Wp;$7<=>Xp\p?Zp@A{<~!p#nN9p@pBpAp?pvCpDp$%zA&b2'(wEp8L*FpGp+*Of}y1[Hpg}IpJp{<~!p#nN9p@pBpAp?pCpDp$%zA&b2'()Ep8L*FpGp+*O,1[HptIpJp}?g4:Mm28=[85pr4ps;6p3p(;a}:p-jrVRsw?8ptb}y%NqF+1d}c@6<e}7J|@1mNkM;p}EE}?g4:Mm28=[85pr4ps;6p3p(;s:p-juVRvw?8pwxy%NqF+1zc@6<{7J|@1mNkM;p}EE`fb\}y64N(7dbB!g&p,3o?eV3(pf)p'pd7h]:c>^}i#1YN_}`}l+p.nk*pnl.p,p-pm/p0plN1p2pnI@;Ho`abcy64N(7dbB!g&p,3o?eV3(pf)p'pd7g]:c>hi#1YNjkl+p.nm*pno.p,p-pp/p0plN1p2pqI@;HKBcxomI{oyo_9zoB8TUVW[}EJ}o!p~o"pd!1X?|=Y4#pfG%pZ"1$pDD[MN+F|o&N18\][M^_KBSxomI{oyo_9zoB8TUVWXEJ}o!p~o"pY!1X?|=Y4#pfG%pZ"1$pDD[MN+F|o&N18\][M^_lI%EtoFGHIuoe:^vowoKIK_`MNOPKAbR$0lIDEtoFGHIuoe:JvowoKIKLMNOPKAQR$0jo4G0[6hoU}lokoV}9:W}nomooo.FZ}@AqosoBroCjo4G056ho7loko89:;nomooo.F<=po>?@AqosoBroCgLYo.A"TZo#DJ[o+3UVN}<1W4qV4\o]o^o_o'(O}`o*X4U3^96HP}boaoQ}XR}co\1YS}fo1eodoT}go3gLYo.A"Zo#DJ[o+3$%&<1W4qV4\o]o^o_o'()`o*X4U3^96H+boao,-.co\1/0fo1eodo2go39DRS!9D}~!Wo|{GoiIoMkI}mU4HozLnoToJopMoqKorLoJ}tNoK}PwQPoL}M}QoRoUoSoVoXoGoiIojklmU4HozLnoToJopMoqKorLostNouvwxPoyzQoRoUoSoVoXoTU?oF}@oWEYZFAo>o=o\GHb>*Fo=o\]^b>*FC}A:oABCDE9o-EF2o3o6oGB8oD}E}@6C;o5oLD4o?<OPNQIG}<7o=>?@:oABCDE9o-EF2o3o6oGH8oIJ@6K;o5oLM4oOPNQRS$%&8(9y3*:,0o-?:yA.JD@};5A}34;35;6.o/oCD-o7891oB}$%&'()y3*+,0o-?:yA.JD/01234;35;6.o/oCD-o7891o:}n.9}:};}iFUEk/mWDn,o0p1CC(or)o<}=}uv>}2-7x+oy?}34}08~!*o"a>#}nhijiFUEklmWDn,oopqCC(or)ostuvw-7x+oyz{|}08~!*o"a>#S%5},;U&{nm?}X'n?!o#oZ()6}{>7}"o$o_8}S6*EI+cb<#O~nx:?Ode&ofg%o'oST,;UV{nm?WXYn?!o#oZ[\]{>^"o$o_`S6aEIbcb<#O~nx:?Ode&ofg%o'ou3/}56v890}1}/K?@ABCDEFGHI{=JKLzn_JMT1NOFIrCx5P|nQ]9Rd6F=cdklmn[9opq-}stghHKiXYZ4Ejn[\mnkn]pn^_`qnainbcvnt1dehnfg-Hlnh`>ijklmn[9opqrstuvHKw8S:;<$}>T@_FC3%}gnBCdnfnUVEFGbnHIJKLOoenMNOXkNQRZ8&}'}(})}Won89:;<=>?@_FC3AgnBCdnfnDEFGbnHIJKLOoenMNOPkNQRZ8STUVWonVnWn!LM#PHS:aqHRnPny|tIQnvz|xJTnSnKz>Un{{|}~dNnefgf=MnhLniBio8jC@klm0Hn9=opOn_>qrRnPnstuQnvwxyTnSnzz>Un{|}~S>?u|SFDn6=`<[GqCVr8An@9:Cn|o|Dp|H"EIq|Cnr|Bns|M;<=Qt|5?n6789:;@n?An@ABCEFDGH"EIJCnKBnLMNOPQRj0*b|c|d|+Y9|:O-%e|'(>n-f|g|.47;nn)*l+47;nqVJrimskmBT|jm`2U|vFlmwG3EV|mmR=tomuHBL~mqmrmvIDJ78*1xKW?9:;<^7=a6>?VJ@imAkmBCjm`2DvFlmwG3EEmmR=FomGHBL~mqmrmIIDJI?cm--EDm]Gmd^_`a4<]L|FmEmZ7HmTUVW@m=mXAmVEDm]Gmd^_`a4mUVWRX?m/mAB2m1m0mC4m3mvLD6mE5m7mF8mGHIJ:mKLM9mH?;mNOm6mPQRS?m+,zl}D!m%m"m~lL#m./0$mM+m&m2345X@(m6N*m'm8OPQG|=-m3=,m>?H|.m+,zl}D!m%m"m~l-#m./0$m1+m&m2345X@(m67*m'm89:;<=-m3=,m>?@.mtuvAsltlYMx>'FxlyCDvlwlylD|EFE|"G)m|l$%}l{lJ'(KF|tuvwsltlYMx'Fxlyz{vlwlyl|}~!"#)m|l$%}l{l&'()*^el_:a;cmlklA|hlB|fgjlC||[l]l^lD?|@ASlTlVl#BBUlf4XlWlYlC[l]l^lDEl2Ll(OBDEO,-q;Kl.1B/\l(A0xFPI-,.Ol?;r;4^>eG9|-8NlMljI6A<7RE801::|;<;|QlRlX9Pl<|?l2Ll(OBDEO,-q;Kl.1B/\l(A0xFPI213Ol?;r;4^>eG5-8NlMljI6A<7RE89:g;<=QlRlX9Pl>?:ll?l#'&@lBl(*(-3gDiIb:W9+OI_2NHElS4U@DlIlyCcLGlHl.5JlcG_B*+qH=EFlGK:ll?l#$%@lBl&'(-3gDiIb:W9)OI_2NHElS4U@DlIlyCcLGlHl.5JlcG_B*+qH=EFlGK/l{&F|1l6|-Ki2l3l}4lkl~5l!orZFpq]>6lstu7|"k9.P7l#$z{8l?I9l|Al}/lf&Fg1lh-Ki2l3lj4lklm5lnorZFpq]>6lstuvwk9.P7lxyz{8l?I9l|Al}+Cbv.lxe0l+Cbc.lde0l&lp>;XYNZq'l[(l\2=)l*lrs+l,l-lt5|ua&lW>;XYNZZ'l[(l\2=)l*l]^+l,l-l_`avkDjFG1|IzkwkNykxklJK2|{k1<3|}k|khIm!lPY74|~k"lQ#lD5Afy>$lnn8STU%lVovkDEFGHIzkwkNykxkJKL{k1$lRn8STU%lVfEKZ1b0%Fe9ikd:hkffFmk;bklknk,8jkV9gU<=hokXMrkuksk5IiApkB`6CtkEKZ1b0%F89ik?:hkfFmk;bklknk,8jkV9okXMrkuksk5I@ApkB`6Ctk[k%Yk&LC'()A@R4Zk[?*|*JN+,-@Oa\kgk5D/fk+|ckkkdk`k|D_k]k1!Mp;2ak^k,|4-|ekt=A8bzB7[k%Yk&LC'()A@R4Zk[?*JN+,-@O.\kgk5D/fk0ckkkdk`k|D_k]k1!Mp;2ak^k345ekt=A86zB7oPkpQkOkqX8@Mro;'Gs^Tku@@BCvw6MxWkl8y?@SkXkm8UkVk)|Rk{b@IF]}/C]2~!_pH#C5`4DoPkpQkOkqX8@Mro;'GstTku@@BCvw6MxWkl8y?@SkXkm8UkVkzRk{b@IF|}/C]2~!"pH#C5$4DWFkXZIk#|Jk[[$|>:BBHk^[>>I_`\Gkb%|l;S1&|NkX7en;fm;MOMkLk'AM5CO:3\>'|hi(|klKkmnWFkXYIkZJk[\]>:BBHk^[>>I_`aGkbcl;S1dNkX7en;fm;MOMkLk'AM5CO:3\>ghijklKkmn@8{D>kCDEW7V?Ak$FF@kT}{17U~{?kwB-5BkCkKY>LW!|m7NDkO,KPQ_@Rv5uLJAXEk"|G?pCZ>UY@8{D>kCDEW7V?Ak$FF@kGH17IJ?kwB-5BkCkKY>LMm7NDkO,KPQ_@Rv5uLJASEkTG?pCZ>UV7kQ3z{5K7L8k9k:kr2{{(?;k:M<OP@kvjlqjwjmno{j7ppq(2rstu~j_6}jvwx"k!k$ky#kz%k{1=|&k}'k~!"#(k>@;hjmjV#JojnjWXYl3+KpjZ[p{q{r{n{|jrj`sjas{ctjujt{eu{gyj=zjv{ixjjUhjmjV#JojnjWXYl3+KpjZ[\]^_|jrj`sjabctjujdefgyjzjhixjj2[:vNajbjuAj{FGHk{"N536cj5Mdjej7dJfjN@:#NOkjP89ljX>jjm{TgMgjij=@~?D[:vNajbjuAEFGHI"NJKLcj5MdjejMdJfjN@:#NOkjPQRljX>jjSTgMgjij=@~?8OjVj67^B\jXj5BWjh{Zj:;<Qj=.[j]j?i{oHYj^j`jS8TjA0A/01_j8OjVj67^B\jXj5BWj9Zj:;<Qj=>[j]j?@oHYj^j`jS8TjA0ABC_jl7#Ij$Hj%0=&'%)T9'^*+JjQ=,-93&Kj/R10W>Lj'2U9Mja0(=I+Nj-j?5UjRjoC67SjPj^6l7#Ij$Hj%0=&'()T9'^*+JjQ=,-93.Kj/R10W>Lj12U9Mja03=I4Njj?5UjRjoC67SjPj^6z{$jc{dkd{|8jjp}f{@j?jsotuvwg{BjAjZiFj~z!|Cj"~DjEj!Gj#hi$jjdklm8jjpqr@j?jsotuvwxBjAjZiFjyz{|Cj}~DjEj!Gj"+jo/j2j1jSTU)jp,j=jWa{YZ[r6j]t_uvwxb{y4jc5jdq:j;je*3fB59jg+jR/j2j1jSTU)jV,j=jWXYZ[\6j]^_`ab4jc5jd:j;je*3fB59jg'j89:;[{\{gh@;MAiCDEFG&jj%jIf.j]{^{M(jN0j_{fM3j*jmQ'j89:;<=>?@;MABCDEFG&jH%jIJ.jKLM(jN0jOfM3j*jPQ\]-f@9Oxi.yi^!j*?{i_~i0viui1"j`a\2|i#j}i4Z{bzi3Dwi7chG+,-f@9Oxi.yi!j*?{i/~i0viui1"j23\2|i#j}i456zi3Dwi7hGfi*KgiqPdiQeijimiY{kiRvSiiciTyXCUti*L{VWXri!si"#Y%nipi&Zqi()[oifi*KgiqrdiseijimitkiuvwiicixyXCzti*L{|}~ri!si"#$%nipi&'qi()*oi_HIVibWiX<YiACV7B3Jd\iKL?3gaih]i`iiM:HkNl^i_iHIZHbi}BliV{hiW{X{k2_`aVibWiX<YiACV7B3cd\ief?3gaih]i`iij:Hkl^i_iHIZHbi}Blinhiopk2>m?c2RiSi@ANi=;NT{PBCROiBGSTDPiQi[iVUiXiFGYZTi[U{]^mc2RiSiLMNi=;NOPQROiBGSTUPiQi[iVUiXiWXYZTi[\]^7h/78HiW8T599Ji]Q:M{=>u5N{:N?s6Ki@AP{CDLiEnCR{;MiS{I<zF=:06f78HiW8T59:Ji]Q;<=>u5:N?s6Ki@ABCDLiEnCFGMiHIJzFK:0-"iF{G{CiIA>i@i%&H{.D{?i1]"]J{+Ei,/0Di12K{vMi@i%&'()?i1]"]*+Ei,-.Di/0vM{3i(i{,ir1`eF-i0i|}c?{&ie&Af*i';E?07tL;{yLr=@{gh#j7i5i$lmn%iXvGYZ/i'i[)i\]^3i(i_,ir1`eF-i0iabcd&ie&Af*i';E?07tLtyLr=aghij7i5iklmn{h!iYHA~hV>I<#i>6kCpEq$iGyI}h8{VhIJrLMst|h9{OO"FsIQ+il1iS<{vw2ix{h!iYHA~hV>I<#i>6BCDEF$iGyI}hHVhIJKLMNO|hPOO"FsIQ+iR1iSTUV2iWC<-.Qh/e12NJ"Lyhxhthuh61f35{whqh56{ghUD9:ivh~07{4{=j"B?CJo@C<-.Qh/012NJ"Lyhxhthuh6134whqh5678UD9:;vh~0<)=>"B?CJ@1{mh2{_Cnhz{VMch83|ihZ[lh,L\ohhhkhU^_)K!O`ab'sh(c+zhdrhxmhy_Cnhz{VMch83|ih}lh,L~ohhhkh!"#)K!O$%&'sh(*+zh,rhS\hWh,{U>/=jk,eh0{jhsAvXfhh\hWhiU>/=jk,ehujhsAvwfhO^hP({UMGS*NHIJWxCXKLk3M){\rIdh!F]O10_]h`YhrASh[h`h*{,G+{c*0PXhQahxIRgO^hPQUMRS*NTUVWxCXYZk3[\rIdh!F]^10_]h`YhrASh[h`ha,Gbc*0dXheahxIfg${Dh:F%{Ih&{Fh(KLh`0AB@hCEKNhMhkGTh_hM~3bhPhFUhnMEDh:FFIhGFh(KLh`0HI@hJKNhMhkGTh_hM~3bhPhNUhnM|zGh{?}z;F5]6Bh~zEhZ:>QEJh"{??nJ#{AhZ2V8)IKh?hAHhB@RhDCh6Gh{?78F5]6Bh9:;[2<T>EhZ:=QEJh?nJ@AhZ2V8)IKh?hAHhBCRhDCh#$%.hvz6h=h7h65hwzvg783hxz,/h9.:P41hhzz0h|G3LiM9hOh4{z#$%.h&6h=h7h'5h(vg)*3h+,/h-./P41hh20h|G3LiM9hOh45&hsqz0)hrzpAU7wxA1(hszS9>+tz{1qAmzJ}:h;hY2~.28huz3&hstu)hvpAU7wxA1(hyS9>cz{|qA_}:h;hY2~.28h!"kzlzPLwgX2}3{g()}gab*T7#h,h-h,+0-fghnz4hq0+hjozl*h.%h$hn"h!hcCo{B'hpz/r]^PLwgX2}3{g_`}gabT7#h,h-hd+0efghi4hq0+hjkl*hm%h$hn"h!hcCo{B'hpqr#4gzOq1rgjN]BhzDI~gQW2|gzgqgRog%pgTc?@)320ABCDkgngNGED?FV2G'KHI]7\6JmgKj2LMYg{|igzDhk"m$%o[gZg]gq\g^g[z`gr_gO4)agbgcg*1:INeg'?\zp1fgggv,xhgyYg{|}~zD!"#$%[gZg]g&\g^g'`g(_gO4)agbgcg*1:INeg'?+p1fggg,-hg.mMgNgn^OgPg=6*ZQge@RgKgSW22Eg@gUzUAgYVzBg!B[TWzDgCgFgU^_GgHg`C?Wi2IgWN+gVW22Eg@gXUAgYZBg!B[\DgCgFg]^_GgHg`C?ai2IgWN+)g*gQzRzIp<Sz(gCx9'g+gD2D"J#A\B7"g89~f:U?eI%g;$gP9SO<5g=>)g*g?@Ap<B(gCx9'g+gD2D"J#A\Bi;(<6H@FO.LwfT@);@+NzS5zf-A/|fCD{fE}f3&C>G?1D56G#gi;(<6H@FO.LwfT@)*+,S5zf-./|f01{f2}f3&C>G41D56#g_0tf6@CtJzXGu[Bvwx7vfKz8rfufpfsf&KLzU8}0qf9}~xf!yf"Mz9F<$;6%&=&g=G'_0tf@CtXGu[Bvwxyvfz{rfufpfsf&K|U8}0qf}~xf!yf"#9F$;6%&&g=G'jgfifhf%HkyF>O)HlkfS>*I0lfjf1N4nT8h;2nHo3*8CKqofmfN9O9i0h:4sYGjgfifhf%HkyF>O)HlkfS>*IlfjfmN4nT8h;nHop*8CKqofmfN9O9i0h:rsYGb+cYfXfZf;@[f\f9J]fdoA^fe,_fg~Nbf-af`f0D.cf&?df/ef8OffbcYfXfZf;@[f\f9J]fdoA^fef_fg~Nbfhaf`f0Dicf&?dfef8OffTM7O"M9NfTz{,=FfEf?z@zi?Gf|}Hf?Ife4AzBz~M4!JfKfCz]KcMEFG6'27BfCf8DfbM9:,=FfEf;Hf?Ife4@ABM4CJfKfD]KcMEFG%0f2feM1f4f3fSM&5f'~H(s;z6fvf;ff;fe[6lH+z/0mAPNo=ne,zIHeJ~@DeIeKeyDNe4-zJe5KTJK478KL9^0LMe}N;<M>Le)*+,->e[6lH./0mAPNo=ne]1He2~@DeIeKeyDNe4Je56TJK478KL9^0:Me}N;<=>Lers&zu>?5e'z@z7e{4e|AQ73B9enAC!Fe(zBeC?e=0JLrstuvw5exyz7e{4e|}Q73B9enA~!Fe\BeC?e=0JL2!z*=>8HA%e+e3"z&eP7b.e2ek7c#z-ee786e$ziJ9mM<03ejk5k0e91e:}E/e,e(3d@n(8%zp8e<^_*=>8HA%e+e`a&eP7b.e2ek7cd-eefg6ehiJ9mM<03ejk5k0el1em}E/e,e(3d@n(8op8eq*5!e)sLH9~dyyzy*$efL0:[01)e*5!eKsLH9~dLMN$efL0:[\])eqdsd|rd;~=R8!8A?ud@Avy|E#tdwyEvdxy5JlAG9wd%HNH&ydzd{d(|de;}dO7j5qdsd:rd;<=R8>8A?ud@AB|ECtdDEvdF5JlAG9wdGHNHIydzd{dJ|de;}dO7j5N6)7cd,-4Jh?0Lrydd3NsytGFA4GM=0@0tyidgded!4vQ>jdhdfdnd3mdldkdxyod67uypd:@zN6)7cd,-4Jh?0L.dd3N/tGFA4GM=0@01idgded!42Q>jdhdfdnd3mdldkd45od678pd:@9ZdWdisjVdR@Yd[dkwxXdu_dl\doyz{|}m]dFdn"^d`d#oadpypqr(FJbdqy*+bLZdWdstVdR@Yd[dvwxXdu_d\dyz{|}~]dFd!"^d`d#$ad%&'(FJbd)*+bLGdgy]d_`HdaecMdfgBdURIdCdLdfgiyRdjyJ4OdihPdkQdTdlhykyolySdvHqrUd|NmJGd\]^_`HdabcMddeBdURIdCdLdfgRdhJ4OdijPdkQdTdlmnopSdvHqrUd|NmJa@;dHOH[?dSJJ[C\:d}@X@"HA>dYC$HDEZG4OJU255d2d67d786dsG'L9;;0d9d4d:3d/d;1d}@?@"HA>dBC$HDEFG%J&d.I]y&HyEZ6%d#d^y5H~c^C{EzELv:8d_yN(dO*dP.-d`y.day+d,dbyQ)d'd3M!dI%&&d.I'&HyEZ6%d#d(5H~c^C{EzE)v:8d*+(d,*d-.-d/.d0+d,d12)d'd3!dsc"dvc?h5uc$dtcP>Zytxcyc+Ezcu^3vZ?dIB|cxCzhB[yDE~Fwc"{c}c{:\yA$sc"dvcsh5uc$dtcP>txcyc+Ezcu^3vZ?dIw|cxyzhB{|}~!wc"{c}c{:#$v3bcacdec^cefc)N8gcWyhc9tTjcickclci5NmcopO>ncocW=8Fpc:;k(CXymqcncocW=8FpcYjk(ClmqcK)Sc*O3PyUcj7+f5,Vcu6WcQ|@r9fJNc?@TKABPcCQ@O1:2,0DEOcFGHIJQcRcw>KLScMO3NUcj7Of5PVcu6WcQ|@)5*Ly,Cc-xxD/DcG@y-Lz#IEcFcUC{GN|HcGc456~o<89Jcp0:;Mc!Ny>KcT2N7LcF9)5*+,Cc-.xD/DcG@0-L1#IEcFcUC2GN3HcGc4567o<89Jcp0:;Mc<=>KcT2N7LcF9(=d;oupEy=cFy)=qryJ2CIHy>cskH|}IyEA!Ac"BciG#A??caC$Jy@cKyN>'(\0)(=d;tuvw=cx)=yJ2CIz>c{kH|}~EA!Ac"BciG#A??caC$%@c&N>'(\0)IcX6=O5A4cabR2wD!JcdghiByjj5ckz56cll8cn9co)GCy:cmDy;cey2c^_`3c+c77NOP@5'5c;QRS4MT1cU0cDA-cV/cWXK=@?.c,c*GM>Y<%c=CA\'c&c(c?]/yABC_hbEFjb*c)cG0y^1y2yJ(<`iNLR<%c=CA>'c&c(c?@ABCDhbEFjb*c)cGTHIJ(efghF%yG2NE9&y'8#Hmbmobn]^kb_`abcdK>efghijk2NE9l'8#Hmbmobn=:>?@fbARSgb&8U:BTibCVWVEV:N5D}xYZ$KKG[\WE\9=:NOPfbQRSgb&8U:TibUVWVEV:N5XYZ$KKG[\WE\9<^b=_b>?@`bAab7Lbb34|xpLcb5NC6jGk678;Cdb:6:JP@;L?@`bAab7LbbBCDpLcbENCFjGk6GH;Cdb:6IJP@KLMebyx,Sb-.RbTbzx01.Vb/Ub01MJ52{xV=FN78Wb97F:XbYb]b[b\b;Zb+,Sb-.RbTb/012Vb3Ub4MJ56V=FN78Wb97F:XbYb]b[b\b;ZbeCpqrxIbssxtxvwxy%JbMbux{vx&g?wxDF!NbSK"Kb'Lb$%)'(Qbxx*+PbObeCpqrIbstuvwxyJbMbz{|}g?~DF!NbSK"Kb#Lb$%&'(Qb)*PbObZJ>@b[?b>b}HnxG4)8]^_`{ox|FbdCb??2LeBbDbEbfAb}hipx~qxGbHbm/Dc4noZJ>@b[?b>b}H\G4)8]^_`abcFbdCb??2LeBbDbEbfAbghijklGbHbm/Dc4noI3bVGgx_KN1vW1Lhx4bix6bjx5bpEP9@9]7bALQ8bF4WH9bkx:bx;by\LUlxUL>DWjAX=bmxb=I3bVGJ_KN1KW1LM4bN6bO5bpEP9@9]7bALQ8bF4WH9bR:bS;bT\LUVUL>DWjAX=bYb=%b`xQ&b*E6'3D9'b(b78)b);+bn*b,b-baxobxcx=qp?@ABdxrsexGiHt.b/bfxis0b1b2bH.;%b5Q&b*E6'3D9'b(b78)b);+b9*b,b-b:;?@ABCDEFGiH.b/bis0b1b2bH.;$hENYx'(tarasaj#Zxb4~LkJJva,ua-waxa[x\x|ayaza{a}a]xm^x~a_x!b4"b#b/HPE$brG4I$%EN&'(tarasa)#*b4~L+JJva,ua-waxa./|ayaza{a}a012~a3!b4"b#b/HPE$brG4IPxaaQxXfZRxhaifajga[l^SxTxYUx_`sVxiakalamaunab}~jacxWxpazeoaXx}~!qadcaadefghhaifajgaklmnopqrstiakalamaunavwjaxypaz{oa|}~!qa"LQPaRaRBIMI>YaTXaNxNZaO&YaTXaUVZa&?NVaTa@?NVaTa@aVHAa=BaJx[0?>v>GaDamFCaKx@?@AB&5017aaVHAaBa;[0<v>GaDamFCa=>?@AB&5Gx,a+a-a~.a0a/ay9!2a1a"HxE4S?xz`?x@x$%bcD4deAx&('%<BxKL~MMNOPx`QRSTUVWXy`YZ[e`\]z`^_`abcD4defgh%<irp`s.x/x0x1xt>uql`2xo`j8M1q`vp?n`\N3xt`$tCDEr`u`4x5xHg`s`wJ<:v`w`7p`89:;<=>?l`@o`j8M1q`Ap?n`\NBt`$tCDEr`u`FGHg`s`IJ<:v`w`"me5$f`}M!x0N"x'k#x$xvBnh`&x'x-(x)x*x1+x,x-xoj`VNW6|HJGpk`m`"#e5$f`}M%0N&'()vB*h`+,-./012345j`VNW6|HJG6k`m`a`Q2fi]`yw9;glAD_`zwno{w|wrd`n7IHc`~`xyzi`jl}~=8!a`Q2hi]`j9;klAD_`mnopqrd`n7IHc`~`xyzi`{|}~=8!MXO<8YQ(NL6Z&2RST[swj6V\]^twuwvw_ww`a4_xwahN^`abc``dfeMNO<8PQ(NL6&2RSTUj6VWXYZ[\]^a4_`ahN^`bcd``efg8v9b;9R`S`pwO?@AC=qwCW`DV`QRTUX`VM3Z`WY`K\`[`rw8v9b;9R`S`:;?@AC=BCW`DV`EFGHX`IM3Z`JY`K\`[`L"#$EI`&'F)K`H`GHTLJ`L`,DN-.P`mwnwO`vC-GK%8N`L3MM`41M2MJ56NQ`n1"#$%I`&'()K`H`*+TLJ`L`,DN-.P`/0O`vC-G1%8N`23M`41M2M567Q`n1jw>86=`?`>`st@@`Q8A`vwi6x@A}9yC`D`B`zm<HF96C|F`,CE`Dkw5ObG!r86=`?`>`stu@`Q8A`vwi6x@A}9yC`D`B`zm<HF96{|F`,CE`}~5ObG!T:5`4`f6`ggw87`j8`hw>59`:`l$8:;HH<=<`pu>;`iwT:5`4`f6`ghi7`j8`k>59`:`l$8mnHHo<`pu>;`q.`M/OP/`RJGH0`WGQRS-D0dwew11`g2Wm5XFLY6LZ424O2RK\*J]45`7@2`a6CFcd#83`7.`MNOP/`RJGH0`WGQRS-DTUV1`g2Wm5XFLY6LZ424O[RK\*J]^_`7@2`abCFcd#83`ebwzG'@A#`$`BcwCD%`EFG&`^D*(`'`I)`*`+_zG?@A#`$`BCD%`EFG&`^DH(`'`I)`*`J_YwQHl_Q<"z@rstu{Nvwj_y@xyf_k_zl1{|}~i_aGe_h_H>!QHl_Q<"z@jkdlmna_goLwk1d_2Jc_NwOw5LG>MwmPwqQwr3AqF>bcdefa_ghik1d_2Jc_jk5LG>lmnop3AqF>uNf^_(1ghIw\]Jw`_i__]_KweX_#Kab_uNX^_(1YZ[\]^`____]_`X_#Kab_\Ew]'Of?j1V_L^N_PU_QbFwGwY_:C\_W_Tc[_VHwZ_@EY0`IJK'Of?j1V_LMNOPU_QRSY_:C\_W_TU[_VWZ_@EY0.Q8R9:?wSu^BwS_U>gF@wAwT_CwVWP2XYtE%3DwZd5^gF?@T_BCP2DEtE%3FGd5^w%@2P_R_34NOPQ_*G_+,-C_D_.H_F_NI/N_K_J_M_TFO_01uCmBM%@2P_R_3456Q_c7yB2_;G{9_7wBC8w>_<_?_DB_E;_j9(G9^#FtM=_A_uB:w@_+_;wio9wE_H)I_c7yB2_;G{9_|}~>_<_?_!B_";_j9(G9^#$tM=_A_uB%@_+_&io'E_()I_(_'_-_c!@$_d/wf0w1w0_:1_jk2w;B48n=3w6_5_7_>r4wt:_u?wCE4_A5w8_6w<(_'_-_c!@$_defgh0_i1_jklmB4nop6_5_7_qrst:_uvwCE4_xy8_zs^C4T)w3Wi74/_*w5*_x@[+wc36,w-wa=3_7`,_,D)_YDL_&_%_._9.ws^C4TUVWi7X/_YZ*_x@[\c3]^a=3__`,_,D)_YDL_&_%_._aby5:IA?<Bw9,-E3O#wt^"_i1fAF.$wIyGA4zN/JK&w!LRDS'wN{^}^(w(02AQ1!_y^y5:IA?<Bw9CDE3Ot^"_i1fAFGHIyGA4zNJKL!LRDSMN{^}^OP2AQR!_y^2~vq^%k^GL!w6f^&"<~^8"w:j3h^m^n^'lBZB)v^<=|^z^)E#_w^*+@x^`^23q^4k^GL56f^7"<~^89:j3h^m^n^lBZB;v^<=|^z^)E#_w^>?@x^`^~Kc^.H'o^;8!`=e^)/NB9r^*n0p^"d^|v,-j^}vl^/#OMg^.E0i^$~Kc^.H'o^;8(`=e^)/NB9r^*n0p^+d^,-j^.l^/OMg^.E0i^1\^yvrtu+LvwZ^^^xyxz{P8|E>9Czv}{vT^!}/M#W^P^rES^$Y^%&QO><\^qrst+LuZ^^^vwxyzP8{E>9C|}~T^!"/M#W^P^rES^$Y^%&QO>=^B=L7<^]R^m=:8a^n[^t5OEoV^_^/021p92X^,BO^Q^A9rxvmb^n]^osU^gh6@i3Q:D>=^B=L7<^R^m=:8a^i[^t5OEjV^_^/021k92X^,BO^Q^A9lmb^n]^opU^dMdqvH^B^?^fWTNE^ghiJ=G^L^rvqEJ^svtvuvD^j^8C_K^`@^F^kM^|0C^N^bclvX0MY7^ZI2^mv8^KL[^NsEBFnvaovb63U1c>^QA^RCNSpvF:^GC>0M7^HI2^J8^KLM^NsEBFNO63U1P>^QA^RCNST.Nt>u@=gv6^4^RMIS?T@1^3^hv:1B@92O=3bICUaM$3;?5^E.Nt>u@=6^4^MI>?@1^3^A:1B@92O=3bICDaM$3;?5^EJav,KNM0^bv/0/^1v@,^2lM6F&^LEDMN5L1?9)^cvPdv'=.^e-^(^+^evh3Q*^IGfv+,-NM0^./0/^1v@,^2lM6F&^ED345L1?9)^789'=.^-^(^+^:h3;*^IG<76@u]z][vt@qGgHxyA{|w]\v!KCy]$^D"^E{]]v"KHGc5%E$mCF%^^vGH_v#^YBv])K1*Zv76vu]z]wt@qGgHxyz{|w]}!K~y]$^!"^"{]#"KHGc5%E$mC%%^&'(#^YBv])K1*n]k]`M9VvWvk@D:YFl]t]s]#7<=-2>Xv;:m]o]YvrWKtBSvwK?|]s}]tO2u(J}L!^#x]~]h1n]k]`Mijk@DlYFl]t]s]#7mn-2op;:m]o]qrWKtBwK|]s}]tO2u(J}L!^#x]~]h1uDA=a5XY6FH[.<\]h]@4Qvx17RvrFg]>9SCi]Oq]j]a8cABb5r]TvUvfgh7h%5p]uDA=a5XYZFH[.<\]h]@4^x1_`rFg]>9SCi]6q]j]abcABb5r]defgh7h%5p].DNva]F/G0a;Ov1LJb]c]$5Kd]Lf]e]MNOPQPve?129IJ13VEH5CDEa]FGHa;I1LJb]c]$5Kd]Lf]e]MNOPQRe?ST9IJ1UVEHWLT45#5X]&'(Y]7lJhKJvGFZ]fHKvLv{H)SL[]:;*+]]\],_]-^]@AMvLT45#5X]6Y]7lJhKGFZ]fH8{H9SL[]:;<=]]\]>_]?^]@ABH]~FvJ]I]#XK^=l]yN2s7C?]t?4A]Avz@]B]wC]BvD]_;5@!:CvpIDvbJDOz{{u;|P:rN|EvE]F]}`;~!G]=]q<]>]rN2s7C?]t?4A]uv@]B]wC]xD]_;5@!:pIybJDOz{u;|P:rN}E]F]`;~!G]]^sM0]_`a^\qrst3]4]vvx_M?vn8]7]:]=5oV6>4p]^sM0]_`a^\bcd3]4]ef51g6]g7!<U6h$2ijkl_Mmn8]7]:]=5oV6>4pj\%]$]dMLNf*]&OeQR-]{6gh)]+]J8v9v'H.]kXlmn2]/][oj\%]$]KMLNO*]&OPQR-]{6ST)]+]JUV'H.]WXYZ2]/][\IC7[|\9:3v\z\i8y\^4v!]>X[5v6v_{\`}\~\7v,]b(]m[DEF']G&]#]cIJIC78|\9:;<z\i8y\=!]>X[?@A{\}\~\B,]C(]m[DEF']G&]#]HIJm\,vSr\v\T)66V-v,W..vL5t\/v!5KFs\Xu\230v4o\1vq\UZ`3m\&'r\v\()66*+,-./L5t\0!5KFs\1u\23I4o\5q\6`3rs[\tb\h\uHn\'vKi\l\f\(vtC8IL\\Md\@>zOLx\k\{|"8#2_3S\AOPQA>p\"w\yzOLx\k\{|"8#2_3S\}~!A>p\"w\yiMMjKO\Y\"vDka\Z\#v$vg\e\EFn`\GI%v&v_\PDeAJ]\I\Q\e"tfN\=9HDdAL\G\gJ\hiMMjKO\Y\jka\Z\g\e\lmn`\op_\PDeAq]\yuC\53g:V]1T\31OW\56:?V\U\Z{u7R\]^|uF\`8c\E\X\9b:P\;K\H\UC\53g:V]1T\W1OW\XY:?V\U\Z[\R\]^_F\`c\E\X\abcP\dK\H\tuC-quLMEvI8\JBuu>\?AG5\B\A\oF@\jFvuwuJKxu.D\7\/H6:\]=OP0`G<\K64\6\3\1S0OZ39\2BCDLMEvI8\JBF>\?AG5\B\A\oF@\jFHIJKLMD\7\NH6:\]=OPQ`G<\K64\6\3\RS0OZ39\TPOv[&&\X05'x[6pu:L}["?GDs[89%\:;<z?/\q3!81\z[0\)\{[-\.\?\=>NFsu$\@;\+=\XDPOv[&\X05x[67:L}["?GDs[89%\:;<z?/\q3!81\z[0\)\{[-\.\?\=>NF?$\@;\A=\XDz~4{2\iuILw[}4|~[}ju"@K#!\#\~'\y[!*C&'oE+\|[(\"#"\ku*+$lu9?,\munu3@01%*\=4vou4~4{2\|ILw[}4}~[~!"@K#!\#\$'\y[%*C&'oE+\|[(\("\)*+,-9?,\./3@01*\=4234BNjl[l_Gmnt[g[k40i[l<9nopk[qj[f[q[s?>fugumTh8|Mvrsh[xtD#3-:hu`[tp[a3n[r[unEBNkl[l_Gmnt[g[40i[o<9pqk[rj[f[q[s?>tumTh8|Mvwh[xtD#3-:y`[p[a3n[r[znE\[e7K7mE_`Z[F0aZb][_[M6,7^u<4K5cd^b[buy:qK7;c[0Ifgbcdcuo[du32d[ghiiu[e[\[e7K7mEXYZ[F0Z[][_[M6,7I<4K5\]^b[_y:qK7;c[0I`abcdeo[f32d[ghiju[e[]uNDJFI1Kr@J4@*7XK_uY[Y;9|3ON[[t3a[`uZRSau^[\s@K3,:]J3O:^WFNDJFI1r@J4@*7KLY[M;9|3ON[[t3a[PQRST^[Us@K3,:VJ3O:WZuHB:NAJ"IU[pG?K;4Pw@@=[uSDQ.MRBQ[P[CR[O[DW[M[K[S[I[SlCFxLF"IU[pG?K;4?w@@=@SDA.MBQ[P[CR[O[DW[M[K[S[I[ElCFxLF[D[C[)*O@+HUumK-SNVu/gKWuL2^;HOF[u?E[@[O8L2ML[J[4M2H[N[T[Xu67'(G[zH>[D[C[)*O@+,mK-SN./gK0L2^;HOF[u?E[@[O8123L[J[4M2H[N[T[5675[x8[QuRuy?>?{MI0`:;[NEA9[+B:[r>]L<[=[hMPuB[":9#UG?[lE^ZbZEO5FGGSuA[>>DH5[x8[yzy?{{MI0`:;[NE~9[+B:[r>]L<[=[hM!B[":9#UG?[lE^ZbZ$O5%GG&A[>>DHG:7rP8on7-M~J~Ip,[9Mus:?D-[/O;>Ks+D.[|4tu/[0[ZL$LvK\K%;2[k<OuQK4[7[6[y4`5w3[G:rPnon7-M~J~Ip,[qs:?D-[/Or>Ks+D.[|4tu/[0[ZL$LvK\K%;2[k<vQK4[7[6[y4`5w3[_zZ`a![Gu^FHu|Zcdef#[l=$[JuKMxGh%['[Ku([j5l)[J6H199*[+[q=bALu7uXR>A=AXB_zZ`a![^Fb|Zcdef#[l=$[gKMxGh%['[i([jkl)[J6H199*[+[q=bAm?XR>A=AXB*G6sZwZK2tZvZMNBuuZ+k=,HCE0xZ-STUyZVDu*DXqNC;/kJ0Eu=K1"[{ZFu~Z}Z3KG6sZwZK2tZvZMNOuZPk=QHCE0xZRSTUyZVW*DXqNC;YkJZ[=K\"[{Z]~Z}Z^1jZ~;89hZy38uiZ48?9u{gZz/;~9;uu"3nZoZUH%&'(aIJ7rZ?u2@E=>@uAuIRC)LCF1jZ~;89hZ23iZ48?57gZ6/;89:;qZmZC"3nZoZUH@ABaIJ7rZD2@E=>GHIRCJLCF,u79`Zu+::>v-u_Z;>y@L*:z{W0N@.u}fZ~/u1@G1w1u$2uU=&fKr:'x3u*<>+'@4u5u6ueZcZdZ0/0uBkC&[u79`Zv+::>wx_Z;>y@L*:z{W0N@|}fZ~!1@G1"#$%U=&fKr:'()*<>+'@,-.eZcZdZ0/BkC&[UZnSZVZ9NTZfo{@WZh2BiXZpkz4lZZYZm[Z\Z{4|F6Cl5];aA\=00n]Zrpqs"2aZtstUZeSZVZ9NTZfg{@WZh2BiXZjkz4lZZYZm[Z\Z{4|F6Cl5];aA\=00n]Zopqr"2aZstfLZMZgh8J]UF@iLIX:eHCHYZME[ANOZP<*uPZ]60^T6M@_`IQZB;GC`[;7?jbckRZl}Jw1\;mVLZMZW8J]UF@XLIX:eHCHYZME[ANOZP<\PZ]60^T6M@_`IQZB;GC`[;7?abcRZ}Jw1\;dJbN8KCZLFZARIM_5NcEZDZTGGZ56IZHZPQ:46;XF)udI7t?JZ0@(E_IKZeUJN8KCZLFZARIM_5NOEZDZTGGZ56IZHZPQ:46;XFRSI7t?JZ0@(E_IKZTU5Z5Z9Z789\;]^7Z>?8ZpY`A&u;Z:ZC'uxYZ@Z?ZAZ~2G69HI|J/@5Z569Z789:;<=7Z>?8ZpY@AB;Z:ZCDxYZ@Z?ZAZ~2G69HI|J/@JM'Z!u#Z$Z""uRS`A|t#u("Z?YTU&Z!Z+Z,Z'E.ZWX$;)Z-.<5//Z0(Z3Z2Z11Z$u4Z%u6Zq>YJM'Z!#Z$Z"#$%`A&'("Z?Y)*&Z!Z+Z,Z'E.Z+,$;)Z-.<5//Z0(Z3Z2Z11Z24Z36Zq>4b7lN}YnoO5;zYyYqr2GsP5FQvw1E{Yxy|YoIzEG#;q@PK{I3%Z~Y|}t~tb7lm}Ynop5;zYyYqr2Gst5Fuvw1E{Yxy|YoIzEG#;q@PK{I3%Z~Y|}~]@YwYZyt\]^&EIJaKczteftY`K{tuYLivYNLxt"@jM]@YwYZ[\]^&E_`abcdeftY`KguYhivYNL"@jklYDH;BsYutJmYvtjYqYLSYENwtPFnYrYGSBHkEHUkYVoYH7Wq:XlYGH;BsYIJmYKjYqYLSYMNOPQnYrYRSBHkETUkYVoYH7Wq:XcY57BiY6dY7fY8AIsD9gY:=>,MHM94?@.0eYrtbY@ABstx4CCg1tthY.0eY?bY@Ax4BCg1DhYEFIMWY%]A7'x<\Y(8>VY[Y)SG:+UY!78-]3.]Y+NN:5CZY/\@059d?f1VY[Y)SG*+UY!7,-]3.]Y+NN:5CZY/\@059d?f1!hF1Gqt#$klmno*Bpq+;RYrTYPYstuaJ=Dvw\Axy{JN<`Y_Yz{x?|~7}~YY9>!hF1G"#$};LY&\X;MYD0lt^HY'()Dabmts546KY'0deC:f6?+,hntrD-.THQY^A};LY[\X;MYD0]^HY_`)Dabcs546KY'0deC:f6?ghirDjTHQY^ADYit4C>YEY@YGYCYBYoGRAYRGr5H3Vg3!?IYNYJYW}7XOY";i9kt%&==YDYQ4C>YEY@YGYCYBYoGRAYRGr5H3Vg3!?IYNYJYW}7XOY";i9YZ&==Y;50Y7Y6>ht1YDGEFGH^M3Y4Y8YjE5Y39^@!FY4HrB"JdH-ZzJKqDLMuKN;Y!2jCOP;50Y7Y6>1YDGEFGH^M3Y4Y8YjE5Y39^@FY4HrBIJdH-ZzJKqDLMuKN;Y!2jCOPj=(Y3dt5vp@=nbHj*Y-Yz+Y{.Y}1Jgt70~^IcHC|/YD2Y5>j=(Y3456p@=nbHj<7M:)Y89:GB;'J<qB=,Y>*Y-Y+Y?.Y@1JA70B^IcHC/YD2Y5>xX$%&'yXzXjJ|X{X?=.@f2|2(}Xs?0L@~X*Cl!Ya7+"Ybtto@.u#Y0$Y:5%Y&Y'YWBM81aL2ctX?XU0Z=[\@3XAB]r6&0Xt^64@;XFCXBXGYtGXZtJHXKL[tN_FXIXAXEX7X%=8:X4X9|L{L:;>X?XU0<=>?@3XABCr6&0DE64@;XFCXBXGHGXIJHXKLMNFXIXAXEX#$p>/XWFT&'St)*GO+XTtUt1XU{9VK@Vt0T0*X(X1ZA2|W4;WFB=XX[A8XY5X6XWtf<9X/XWF%&'()*GO+X+,1X-{9.K@/0T0*X(X1ZA2|W4;FB=X3[A8X45X6X5f<9X>?@VWV;:K;K~1[WGtiCHtAXWEItGw2HIBC-XZWLD0GNYWOWWEz9]W4?8,I9:;?@AVWV;:K;K~1[WBiCCDXWEFGw2HIJK-XZWLM0GNYWOWWPz9]W}1,@IWHWB7TBNWLW@tKW'Ne8*6y=MWLE>=,@FQWPWAt.OWRWf878BtSW|I[=13TWyHCt56AF'DDtEt90EUW+5}1,@IWHWB7TBNWLW)KW'Ne8*+y=MWLE>=,@FQWPW-.OWRWf8/20SW|I[=13TWyH456AF'D>70EUW+59t;Ws:t2Ww@WvE;tAWBWtL:7I&DKIEW!4>F14FW#$GW%rL&`H?t5JWr;WstuWw@WvExAWBWyCWz4W3W{DWA7|}'I~L:7I&DKIEW!4>F1"FW#$GW%rL&`H'(JW1t[J2t1W.O]3t-2W@J5W!P1P.0'W&W"WZ(W)W[*W-W+W,W.Wd1nD/W0tz7v26G,0W{FzV{VQGP|VwN-ORQS~V}VTUG3VW!W$W%WX#WY@I3>'W&W"WZ(W)W[*W-W+W,W.Wd1nD/Wz7v26G0W{FB#D-91>_H2>CDx=lDyJ9E.9\IyVEF#YEB:H$K8%mDKLC0n=/9GM&M-t'B#D-91>_H2>CDx=lDyJ9E.9\IyVEFGYEB:HIK8JmDKLC0n=/9GMMNOlVkVjV}IsVx2ZKmV35oVkKznV+t89,tpV(HqV>JrV;<|}~!A34?J/GtVuV|~,944vV88DM)Mv4xVlVkVjV}IsV42ZKmV35oVkK6nV789:pV(HqV>JrV;<=>?@A34?J/GtVuV,944vV88DM)Mv4xVpT;[IAH%cVu4&fVr)ts!D*teVdVgVkDu,c?.U;J@vSB"5/"D0hViVo>9Kw$T;[IAH%cVu4&fV'()!D*eVdVgVkD+,c?.U;J@-SB"5/"D0hViVo>9K1vwZV}O`4[Vzyh]V\V^Vij|_Vn@#=kd=(tcAm)98:*9p5n`V9:J8aV&LCGbV+9"#,4'CR6vwZVx`4[Vzy]V\V^V{|_Vn@#=}d=cA~)98:*9p5!`V9:J8aV&LCGbV+9"#,4'CR6xOQVePVOV]ghE:VWV_i`kabmSVnyORVzO{OqTVUVcdeXV|OgfNYVVVdQVePVOVfghE:VWVhijklmSVnoRVpqTVUVrtsXVtufNYVVVUQsOtOSvOKVHVJVrMUIVuOTV?VXYW[\s?XLVwO7:ZMVNV`abcPQRSWKVHVJVrMUIV<TV?VXYZ[\s?]LV^7:_MVNV`abcBLr?VGVFVEVAVO@VPDVGQRqOxJNSLTNOBCr?VGVFVEVAV@VDVGHIJxJFKLMNO2V4VIjOkOlO=5V<=F.6e26V;V9V>wJvJ?@mO;gE8VT=7V2V4V9:;=5V<=F.6e26V;V9V>wJvJ?@A;gE8VT=7V)<=)VeOt4*V-+V.fOA,2BgOCD;Ad4hO-V(LFRB5Y36G/V1V_4iO.V0V3V)*+)V,t4*V-+V./0,2123;Ad44-V(LRB5Y367/V1V_48.V0V3VI6{Uo5|U~6OF02S;}U"V!V}6~U8Ewx{~y0B1KEH<`O2XAzM345$V!%VVF63;#$'V(VdO&9(I6{Uo5|U~6OF02S;}U"V!V}6~U8Ewxy0BKEHrUsUS0:BR?itU3F.>/>[OuUm@j0>\OlvUwU]O`LnxU.^OqF6r/"=tuvyUzU\<,?tFT?xH"GuIl@MrUsUS0:BR?itU3F.>/>uUm@j0>klvUwUm`LnxUopqF6rs"=tuvyUzU\<,?tFT?xH"G$\dH2XbUFMYZI=_UG`UHpBI'1iH2XbUFMYZI=RUUOPUQU;vR;SUw&9TUVOz;8BUUVUZ;'9?RL(5I8WUX3xXU9BAyYU#VZU[U\U^UzWOE{RU:PUQU;<R;SU=&9TU>z;8BUUVUZ;'9?RL(5I8WUX3@XU9BABYU#VZU[U\U^UCDEFq/rr4IUHUJUs|/456n>}/MU\DuE1KUtNU9OU./0r4IUHUJU13456n>7MU\D8E1KU2NU9OUG2?Uz/"#;<>Uy7$LUEUBUjkldCAUmCUDU)onp,FUGU-G2?U!"#;<>Uy7$LUEUBU%&'dCAU(CUDU)*+,FUGU-w/`l^Gmno;U2Iax/bcdy/vexfg{h}LR0#0M2UNOP0UQR9n/;(UNP;=O;O90H8o/+@Q0,U-U*Up/PBQR81/4S)UEL1ITGHIJ(0Kz~y0Q;9:;(U90H8?+@Q0,U-U*U@ABCD81/4E)UEL1IFGHIJ(0Ky0Q;"U!G^HQL%Gk/)+U*l/85,EM-/L,V#UK&Um/EB08KJE1L34'U56eK7J:M*>"U!G^HQL%G()+U*+85,EM-/L,V#U.&U/EB08KJE1234'U56eK7J:8*>rb1Bq4`FtJwTUAvT@7tu[KuTeEyTvxTEi/yF{T{zT||1|T)>~T%C}}Tj/3J!"w=[EHI!U%&J%9rb1sq4`FtJwTUAvT@7tu[KuTeEyTvxTwxyz{T{zT||1|T)>~T%C}}T~3J!"w=[E#$!U%&'%9iT89QJjT:g/;F2kTcd<4b/U[Ta/ZTc/h9X\T^T]Td/`TZUTbTe/[5aT_Tf/N;Q?TAcT<@m0dG67[DeTdTfTgThTIJQOYTECRu2m>STU[TVZTWh9X\T^T]TY`TZUTbT[\aT_T]N;Q?TAcT<@m0dG^[DeTdTfTgThT;<-6PT=>\/)*A+,-hJ.F}AFD/]/RTHIJKOK_/0STXT1N/JWTQTTTVTP&:;<-6PT=>?@ABCDhJEF}AFDG9RTHIJKOKLSTXTMN/JWTQTTTVTP&:=J]N&t2JT'/01:AMTcE2IEdE9HMDI:3X/ITY/(7v16EKTGTP?8OT[/N=:=J]N-t2JT./01:AMTcE2IEdE9HMDI:34IT567v16EKTGTP?8OT9N=:YK2Fz}x7OB|V/ATDT!"DBET#FT~%!HTiD'".4)!ta1sJ#l>HE$f:NT,YK2Fz{x7OB|}ATDT!"DBET#FT$%&HTiD'(.4)!ta1sJ*l>HE+f:NT,1TP/?T@T>TkBTq8Glvh0VI~CTQ/wpqR/x}>S/T/9j?T@T>TkBT8Glmh0VI~CTnopqrs}>tu9?,T/TA:#9@63TA%:B3CCD0TZDEFGHIJKLMNOPQRS4T{S#$`J}S%!T~SA/"T'#Tw7(`1$TZ&T%T*+(T,ZE-C/.[01)T50_:]34=75D/OCE/F/*T+T-T9:;{S#$`J}S%!T~S&"T'#Tw7(`1$T)&T%T*+(T,ZE-./01)T50_:234=756OC78*T+T-T9:;sSqSoSrSStS?/@/mpTuSnovSwSxSEQr|/nSmShpSifSTUeSE3VgSWXjSiSYZ[\]^hS9GkS_`abcdelSfgnSmShpSiE?=1@ABF3/D9AEYSFZS'tGz3GHJKLaS5/o4NdS`ScSI7/8/9/.JS4/UF8H>?=1@ABCD9AEYSFZSGz3HIJKLaSMo4NdS`ScSOPQR.JSUF8H*2C>0/E2,-1//?12RSTS(>313WS<^24bS@|>^S6\S7]SA_S92/;CD*2C+E2,-./012RSTS(>313WS^24bS5|>^S6\S7]S8_S9:;<=vwNSLSx'T4z5./60!QS"#KS$OS7%MS9L;PS;(SSXSVSUS)vwNSLSx'Tyz{|}~!QS"#KS$OS%MS&L;PS'(SSXSVSUS)=S)/,GS1A*/IS-"9?S}C+/k.mnopCS$X%3SZdL'/\<77S8S]^_5S;S(/'(2S)dASFS+BSe1SVoB6S&>WXY3SZdL[\<77S8S]^_5S;S`ab2ScdASFSBSe|}41G6:0?H~JK$/)SbE*SM"0N%/4S#M'>P:S&/R9S0SS!UCBEF41G6:0?HIJKL)SbE*SM"0NO4S#M'>P:SQR9S0SSTUCB%0JI"Sv|R"/wR}RH::;<&S=w0/S'S(S%>iK>x-S,Syz/E{A.SB+SC#/%0JI"S|R9wR}RH::;<&S=w0/S'S(S%>iK>?-S,S@/EA.SB+SCDrR!"tR#vR|.%lp:BOmkRiRuR'pRn}.x.+o~.xR#SzRp.~R!/0!S{Rqr>S3i:13syR5t7%Sv0$SurR!"tR#vR$%5p:BO&kRiRuR'pR()*+,xR#SzR-.~R/0!S{R12>S3i:134yR567%Sv0$S8`R$OhprJqhDb8p9w.hRs]FdtlRivjx~L!9yMGE~8u.ef/7gR~Oc6JKge]Hv.ffRj^4aRbRdRklmneR[5a?-JcR_Rc8^RdI5F3g9H5_D%11F>L!9yMGE~8ef/7gRc6JKg]HhifRj^4aRbRdRklmneR[5a?-JcR_Rc8[2;TRXtK5:Z5'MPA?H}\RZRD2fB8\RZRD2fB8a8CR>H87DR\H4BnB(6nF1C9nG:NKFRj@o.p.=57TGRU?HR,1u0m4@(BQ5qMKR72AVJRq.B*6?R==6i@AR@R#>a8CR>H87DR\H4BnB(6nF1C9nG:NKFRj@;<=57GR>?HR,1u0m4@(BQ5qMKR72AJRB*6k.hLwF|qJ2Rl.3RLM!5R7R6R"#8R=2LK$|:9R%m.YA'(">)6:RN)*+,[H-./;R0R$Ih6e034P?F{hLwF|qJ2R23R}~!5R7R6R"#8R=2LK$|:9R%&YA'(">)6:R3)*+,[H-./;R0R$Ih6e0345?Fe&RVKf)RgJ-Rp*@*RP6q+R+4rstui.w.7.Rx/RyK0R1R[)RgJ-Rp*@*RP6q+R+4rstuvw.7.Rx/Ryz0R1R[<{8^LM>D3=O`7|Q-NPQxQ}QzQa.yQSTU@WONXy8C2tNBZC\u=XEe9"R#RD^eN+O%R_`az8EF$Rd/3MND3O`7|Q-NPQxQ}QzQRyQSTUVWONXy8C2tNYZ[\u=XEe9"R#R]^eN+O%R_`az8bc$Rd/3fDmQ>'B^.o:nQoQ0AlQqQ96K_.BCd9:~/pQEF`.u7^:mGHtQrQ;I{Ij>{Qd3uQsQOA'B?o:nQoQ0AlQqQ@6KABCd9DpQEFGu7^:mGHtQrQI{Ij>{Qd3uQsQOAJKLwQvQaEZ.5O?cQ2,JZ@"4)4dQfQ:76\.eQ].7sN7i=8=HLJgQ9xMhQiQ~E:;jQ<)@~:t7kQI;o9=aE01O?cQ2,JZ@"4)4dQfQ:734eQ56sN7i=8=HLJgQ9xMhQiQ~E:;jQ<)@~:t7kQI;o9=~U.(@YQZ=!ZQV.|C?N`E"#$%&ER'[Q%tE6W.\Q^KX.*h=|B^QdF1_QY.`Q.3,34aQ'6/LFz1P=!HbQ~(@YQZ=!ZQ|C?N`E"#$%&ER'[Q%tE6(\Q^K)*h=|B^QdF1_Q+`Q.3,-.aQ'6/LFz1P=!HbQCQDQ)qbF_1GQ}:*FQF:sHQnfIQAKJQKQLQi>,L<T.'4vOQ-MQ=LNQZIPQQQRQ_E.VQTQUQSQc:WQjLdNyz0XQ|}CQDQpqbF_1GQ}:rFQF:sHQnfIQAKJQKQLQi>tL<u'4vOQwMQ=LNQZIPQQQRQ_ExVQTQUQSQc:WQjLdNyz{XQ|}:Qt0e58;7<={C$6h@w8O.n9Qm~Fn4A@QAQ,Hx8;OBQ&6(Qm~Fn4A@QAQ,Hx8;OBQ&6|?)Q@'QH.NAB}(Q*QDEF.v0,QF+QGHJH2$Q34O65!Q"Q6/F7|A8#69:MK%Q;=N<=&Q>?)Q@'QANABC(Q*QDEQ0,QF+QGHJHzPwxy|Pzi{5K|}~f7jkD.lm1;wH{P%n'()*+hoE:CM-.q~P#Q}PD:}=/rs197zPwxy|Pz{5K|}~f7!"#$1;wH{P%&'()*+,E:CM-.~P#Q}PD:}=/0197A.C._pPb`qPuPN0deaPJtPghbsPwPckvPdDlmndr7eqfxPsguE<&BeDv6yP65_`apPbcqPuPN0defPJtPghisPwPjkvPdDlmnor7pqrxPstuE<&BeDv6yP65X;.<.KfPoPLRAMD8N\G=.G`YnP]EZcPv8R>.u8aPT[V\Z<iP]oJMCePq7?.bPjPdPQNkPAO@.[\]^f6p7B.IJKfPoPLRAMD8N\GOG`PnP]EQcPv8RSu8aPTUVWZ<iPXoJMCePq7YbPjPdPQNkPAOZ[\]^f6p7v6787%Bd2R9:9.S=S=>YPT^P\PUWP/BZP]P[PA]JXP:..?CsK_P`PO$=mPD!.WPG6IhPpJ62FGlPH6787%Bd289:;S=<=>YP?^P\P@WP/BZP]P[PA]JXPB.?CsK_P`P$=mPDEPG6IhPpJ62FGlPH|K&4~LTPLP"5.cN$x;%MP&RPM(6.UP7.NP+N!6M0-."6A2%UyKnIt8P/?7N01234QXJ|}&4~!TPLP"#cN$x;%MP&RP'()UP*NP+,!6M0-."6A2%UyKnIt8//?7N012345XJfgQD"CJP../.jkL0cD;=4:$MlNBD?20.IPE>MEPGPn:HP$U1.-.qAPP2.3.tSPQPuB2;JKPGHxIOPs8J4.H;fgQD"CJPhijkL0cD;=4:$MlNBm?2nIPo>MEPGPn:HP$Up_qPPrstSPQPuB2;JKPvwxyOPs8z{H;?k4S+.UDPK0,.W`8l4zI2HY5XY@[\q2gPAE]lGFP^`P8B?PUIg@2KD6=gCM>o7CP$G/).P*.:=N?>PCB?PUIg@EF8!@PBPGHIeBaNJ0JAP>2KD6LgCMNo7CP$G/OPQ55,P-P;N=MhA/Pv;sF'.2P>1_8^8f0>?KOJO3:!013P4P5P4K6Pr8g0rK|5}5~5bD1_8^8f0>?KOJO3:!0@3P4P5P4K6Pr8g0rK|5}5~5bD+P52/5e6p8iL&V670pM}F9:;%4+P5245e6p8iL&V678pM}F9:;%40;e><2$TI?M#"P/1$n3#P$@BRV5:Jg>&>N'(BJ$.%$P&.fC'%.&.%Pz6.&P]40Cg<'P(Pl0zC!7<"#|Kf>0;e><2$TI?M"P/1%n3#P$@BRV5:Jg>&>N'(BJ)$P*fC+,-%Pz6.&P]40Cg<'P(P`K*->~?&(*1U7uxjpX}'K|\I?)kNS:C$l`{Q{OnYTm4w52YzZzlnHJLO>BaN]+6;mySWGKH37tw}d9-"gl\4MxFHIP?AB(fwpwT@q~;B:vw!vH](),4~ume.24Iuq6|[_`FJ;ty{^oq>oOVY\_O#%)(,W?CAyJ/8B#&]^agHh/[.~S.+^V#.-23U-^#c-.+|+U-c-++-+!+#+)+'+S-T-P-Q-R-V-!./.#...1.j.i.h.g.@-N-C-H-I-_-o-n-m-).2.$.+.".4.5.-.7.*.6.F-J-A-D-B-L-K-E-M-G-O-[,\,],^,_,`,a,b,c,d,e,f,g,h,i,j,k,l,m,n,q,p,s,r,o,e-f-g-h-i-P(Q(R(S(T(U(V(W(X(Y(Z([(\(](^(s-t-u-v-w-e-f-g-h-i-A(B(C(D(E(F(G(H(I(J(K(L(M(N(O(.-1-,-j-k-l-n&o&p&q&r&s&t&u&v&w&y&z&{&|&}&~&@%A%B%C%D%E%F%G%H%I%J%K%L%M%N%O%P%Q%R%S%T%U%V%W%X%Y%Z%[%\%]%^%_%`%a%b%c%d%e%f%g%h%i%j%k%l%m%n%o%p%q%r%s%t%u%v%r's't'u'&!%?%`$a$b$c$d$e$f$g$h$i$j$k$l$m$n$o$p$q$r$s$t%+!,!5!6!!%"%#%$%%%&%'%(%)%*%+%,%-%.%/%0%1%2%3%4%5%6%7%8%9%:%;%<%=%>%?%`$a$b$c$d$e$f$g$h$i$j$k$l$m$n$o$p$q$r$s$+!,!5!6!!%"%#%$%%%&%'%(%)%*%+%,%-%.%/%0%1%2%3%4%5%6%7%8%9%:%;%<%=%>%?%!$"$#$$$%$&$'$($)$*$+$,$-$.$/$0$1$2$3$4$5$6$7$8$9$:$;$<$=$>$?$@$A$B$C$D$E$F$G$H$I$J$K$L$M$N$O$P$Q$R$S$T$U$V$W$X$Y$Z$[$\$]$^$_$!!"!#!7!9!:!;!R!S!T!U!V!W!X!Y!Z![!)"."L!M!Z"["X"Y"A!`-a-f&3"4"5"6"7"<#!!"!#!7!9!:!;!R!S!T!U!V!W!X!Y!Z![!)"."L!M!`-a-!!"!#!7!9!:!;!R!S!T!U!V!W!X!Y!Z![!)"."L!M!A!`-a-}#~#:#.#/#}-!,",#,$,%,&,',(,),*,{'j!i!:&=&;&@&9&>&<&?&l&}"v"{"|"u"z"t"j!i!v"u"t"h&i&j&k&z!y!g&d&e&~-z!y!$###!"~!;#{!}!|!g(h(i(j(?#~"!"~!{!}!|!~"#"""m&%"$""#!#'"&"#"""%"$"'"&"@(6(!(,("(-(#(.($(/(&(1(%(0('(<(7(2()(>(9(4(((8(=(3(*(:(?(5(+(;(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,+,,,-,.,/,0,1,2,3,4,Z&[&\&]&^&_&`&a&b&c&!)")#)$)%)&)')()))*)+),)-).)/)0)1)2)3)4)!-"-#-$-%-&-'-(-)-*-+-,---.-/-0-1-2-3-4-}'D'E'F'G'H'I'J'K'L'M'N'O'P'~'B'C'H"I"^"|'^"v'w'>"?"B"C"<"="D"E"Q"R"S"]"y->"?"<"="]"#/>"?"<"="]"y-l"m"n"b"b!a"k"e!f!c"d"o"p"b"b!a"e!f!c"d"O"_"P"G"`":"F";"t-]![#e"g"g!x-\"T"U"J"K"A"@"i"j"s-h!h"f"O"_"P"`":";"e"g"g!"/\"B!J"K"A"@"i"j"!/h!h"f"O"_"P"`":";"t-e"g"g!x-\"B!J"K"A"@"i"j"s-h!h"f"O"_"P"`":";"t-]!e"g"g!x-\"B!J"K"A"@"i"j"s-h!h"f")#M"N"+#,#*#-#M"N"+","*"-"q"'#%#&#(#+","*"-"x'y'z'5-6-7-8-9-:-;-<-=->-?-W-5,6,7,8,9,:,;,<,=,>,?,@,!*"*#*$*%*&*'*(*)***5*6*7*8*9*:*;*<*=*>*5-6-7-8-9-:-;-<-=->-stuvwxyz{|n!]#_#b-d-o`#r"\#n!{+}+r"n!b-d-or"!)~,l(m(n(},>!|#=!=!B!F!G!H!I!w"x"@#E!D!s"l!m!("k(1!X+>!=!F!G!H!I!w"x"E!D!s"l!m!(">!=!=!B!F!G!H!I!w"x"E!D!s"l!m!("~>!=!=!B!F!G!H!I!w"x"E!D!s"l!m!("1!F+G+P+Q+r(s(b'c'd'e'f'g'h'i'j'k'l'm'n'o'p'q'W'rstuvwxyz{|}~''BCDEFGHIJKLMN!'"'#'$'%'&'(')'*'+','-'.'/'0'1'2'3'4'5'6'7'8'9':';'<'='>'?'@'A'Q'R'S'T'U'V'X'Y'Z'['\']'^'_'`'a'P&Q&Y&R&S&T&U&V&W&X&uzwy|P&Q&xR&S&T&U&V&W&X&uzwy|89abcdgilv!&"&#&$&%&&&'&(&)&*&+&,&-&.&/&0&1&2&3&4&5&6&7&8&ejqrst{A&B&C&D&E&F&G&H&I&J&K&L&M&N&O&R+\+Z+_+}+[+W+m+Y+^+]+x+y+~+j+v+w+k+l+r+g+o+z+h+p+s+u+i+{+|+t+n+1*S+T+U+V+"*X*6-*6*q+`+a+b+c+d+0/2653|*q*h*'+m*-+5+f*7+;+x*r*@+i*!+~*#+w*>+=+3+9+:+%+8+?+n*&+.+0+C+1+2+u*(+y*6+<+"+B+,+j*t*k*4+{*e*v*o*/+l*A+s*p*g*$+o(p(Cq(v(w(gx(py(mz(o{(n|(9t(u(E+&&CCUUggppmmoonn9)+I#*.*A*Q*OOB*R*J+z*y)~)C*S*++*+9*H*[[D*T*%*0*]*c*'*3*&*2*G*W*(*4*/Ollw)|)^*d*E*U*F*V*jjqqtts)*5*+*8***7*I(HMMOONNJ+KWWVV-MYY[[ZZ\\]]__^^aa``/Olliiffkkhhjjqqttsuuwwvvu)z):*I*!*,*<*K*Y*_*//=*L*@*O*"P*x)})66>*M*?*N*Z*`*;;==<[*a*$}*GGv){)FFDE&F\*b*IIG;*J*LL$*/*)''%%((++,,//--00"B77668855::;;==<>>$DGGEEFFDE&FHHIIGJJLLKK)7)8)9):);)<)=)>)?)@)A)B)C)D)E)F)G)H)I)J)K)L)M)_!N)O)P)Q)R)S)T)U)V)W)X)Y)Z)[)\)])^)_)`)a)b)c)d)e)f)g)h)i)j)k)l)`!m)n)o)p)q)r)s)t)AAAAAAACEEEEIIIIDNOOOOO_!OUUUUYTsaaaaaaaceeeeiiiidnooooo`!ouuuuyty"!$*#)!.2143@?BAPRQTXS_!,cbedr0N"!$*#)A.2143@?BACPRQTXS`!LcbedrPs")#)q!r!$)o!%)x!/!&)')()L"))*)+)k!^!,)-)-!y".)/)0)1)2)3)4)5)6)!q!r!\|x!/!cac"L"-R1!k!^!23-!L&y"&!$!1od"Bq!r!p\Cx!/!lL"n4k!^!-!y"1kDBq!r!p\Cx!/!mlL"n4k!^!-!y"1kDBq!r!po!Cx!/!mlL"n4k!^!-!y"1kD!!@؉+!@آ.!@ؤ6!@آF!@p!@+w!@؁y!@q"#@%#AJ'#A 1#A2#A(8#AO?#BA#B:J#BعR#B|S#B؝Y#B\#Bw#CE*$C1$Cؕ2$Cm:$Cd=$C_Y$D\$DU^$D{c$Dtj$Dk$Dr$Dt$D6u$DD%%D2%Em>%ED%[)G%EGU%EV%EB~%F0(GV7(G-8(GE:(Gx;(Gb?(Gء@(G؜E(GؒH(GطJ(GK(G3[(Gf(Gvl(G",H{+,H0,HحP,Ie,J[m,Jثr,J؏$-Jظ)-JO*-JP2-JF4-K5-Jئ9-K$V-K}-L#.L$.Lض:.Lr<.L=.LB.LC.LD.LG.LI.LU.MJV.MQW.MK[.Mew.Mx.MZ*/Mؔ?/M9@/MGB/M8C/M:N/MY/M a/Mdi/Mj/Mp/N$u/N=#nNؘ4nOInO\nO@^nO_nO`nO2oO~GoPؖMoPaoPdoP"pPؼ3pQ)9pQإSpRؖ{pRM.qRV0qRo5qSDqS]qSaqS7fqSjiqS؋uqTJwqTUzqT"!rTة#rT$rT(rT,rTL=rU.HrU[rUاurUةvrUش2sV=sV>sV@sVRsVز]sWK^sWdssW.tsWVusWewsWb{sW}sW"tW$tW#'tW\.tW/tW4tX 5tW=tXBtX`OtXitXpktX؆rtXLutOytY5uY~:uYذFuYVuZXuZZuZQ]uZo_uZcuZjuZXpuZ،suZطDv[sNv[]v[euv[ؔ~v[!w["w[3w\ 6w\9dw\ew\kw\nw]sw]I)x]*x],x]14x]ؓx]#Bx]RVx^؅cx^؄wx^سyx^ؾzx^%y_ظ/y_ؠ2y_9y_طBy`؊Hy`ػYy`؂^y`fya kyaUzyak~ya!za,za/zaOzbIPzbFWzbkezb؇fzb؈qzbغrzbػ~zb!{b),{bq-{bC6{bؙ7{b={b>{bN{bO{bW{cZ{cq\{c]{ca{c6e{c؉g{ci{c2q{c"|dؠ#|dر8|eؐB|eL|eV|eY|e]|ePv|f,}frK}gL}g=Y}g[}g؊]}gIg}gm}gp}g%~g)~h/+~h2~h5~h؂S~HX~h،Z~i7n~ip~ir~iv~iز".@ B/D=L/D`/En{/FؽTOB؟cOEشnOG4:uLruM)vM?2vMc`vOlwQ~xU؎)yUGyUqTyVnyWء]zZ3{[@I{\l{]؄I|`wQ|`f~hؐw$K00x$M00y$O00z$Q00{$S00w%00x%00y%00z%00{%00|%00}%00~%00x&10D+H+TI+TJ+K+L+YM+YN+ZO+Ze+f+0abcdefghijklmnopqrstuvwxyz{|}~"!b!c!d!e!f!g!h!i!12!!!pNPQS$STYWX[\S]_` aNe;fef)hkjjmm(puvv0yz}}b !"v#$%ސ&'();MQ*+,ٚr-ўp!q!r!s!t!u!v!w!x!y!`!a! "&*+/12479:<=?ACDEFGSUVWXZ]^himnopqsuz}|~Ýǝɝʝԝ՝֝םڝޝߝ z{|ƞȞ˞՞ߞ "#&'()*1567=ACDEIJNOPSTVX[]^_cij\khnpruw{ /0234:DGJQRSVWYZbcefjl˜ŘȘ̘"&'+123459:;<@AFGHMNTXY[\^_` !"#(13ACJNOUWXZ[cgjnsvwx{}ėŗǗɗʗ̗͗ΗЗїԗחؗٗݗޗۗ   #&~ƕȕɕ˕Еѕҕӕٕڕݕޕߕ"$%&,13789:<=ARTVWXant{|~ʖҖ]ؖږݖޖߖz}ēœƓǓɓʓ˓͓̓ӓٓܓޓߓ ./1234;?=CEHJLUY\_achkmnoqrxy’ÒŒƒǒȒ˒̒͒ΒВӒՒגْؒܒݒߒ !$%')*3467GHIPQRUWXZ^degijmopqstv‘Ñőӑԑבّڑޑ #$%&(./035689:<>@BCFGJMNOQXY\]`aeghinopuvwxy{|}ĐŐǐȐՐאِؐܐݐߐҐ  %"#')./14679:<=CGHOSWYZ[adgmtyz{CGOQRSTUX]^eƏʏˏ͏ЏҏӏՏ ()/*,-347?CDL[]bfglpty̐Ð#&'136789=@AKMNOT[\]^abilmopqyz{ÎĎǎώюԎ܎ !#%'(,-.4567:@AŌƌɌˌό֌Ռٌ݌ eilnōƍǍȍʍ΍эԍՍ׍ٍ  !"ÊƊȊɊʊъӊԊՊ׊݊ߊ  -07EGIKOQSTWX[]Ycdfhimsuv{~{|}ԉՉ։׉؉ "$&+,/57=>@CEGIMNSVWX\]aeguvwyz{~:@BEFIORWZ[\abcknpsuz(./129:<=>@CEMX]adeoqr{ȇɇʇ·Շևهڇ܇߇ (-.025 !')68:<=@BFRSVWXY]`abcdilouvwzÆņц҆Ն׆چ܆熈 !#܄2 "#$%'*+/346?FOPQRSVY\]^_`abdkoyz{}…Džʅ˅΅؅څ߅}ǃɃσЃуԃ݃S /9EGHJMOQRVXYZ\`degjpstvx|}„DŽȄ̄τӄKNOQV\`cgmt{}ƂЂՂڂ T!",-.037:<=BCDGMNQUVWpx  $',05:@D`dfmquȀ̀πҀԀՀ׀؀}}}}}}}}}}}}}}}}}}~}}}}}}}}}}}~~~~~~~ ~'~(~,~-~/~3~6~?~D~E~G~N~P~R~X~_~a~b~e~k~n~o~s~x~~~~~~~~~~~~~~<;=>?CDGORS[\]acdefma|c|g|i|m|n|p|r|y|||}||||||||||||||||||||||||||||||||}}} }}}}}}}}#}&}*}-}1}<}=}>}@}A}G}H}M}Q}S}W}Y}Z}\}]}e}g}j}p}x}z}{}}}}}}}}}}}}}}}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|[|\|]|^|yyyyyyyyyzzz z z zzzzz!z'z+z-z/z0z4z5z8z9z:zDzEzGzHzLzUzVzYz\z]z_z`zezgzjzmzuzxz~zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz{{{#{'{){*{+{-{.{/{0{xxxxxxxxxxxxxxxxxxxxxyxxxxxy yyyyyy y%y'y)y-y1y4y5y;y=y?yDyEyFyJyKyOyQyTyXy[y\ygyiykyryyy{y|y~yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyydwgwjwlwpwrwswtwzw}wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwxx x xxxx!x"x#x-x.x0x5x7xCxDxGxHxLxNxRx\x^x`xaxcxdxhxjxnxzx~xxxxxxxxxxxxxxxxx:vwBwEwFwJwMwNwOwRwVwWw\w^w_w`wbwuuu u!u$u'u)u*u/u6u9u=u>u?u@uCuGuHuNuPuRuWu^u_uauouquyuzu{u|u}u~uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuvvvvvv v vvvvvvvvvvv#v%v&v)v-v2v3v5v8v9vstttt tttt$t&t(t)t*t+t,t-t.t/t0t1t9t@tCtDtFtGtKtMtQtRtWt]tbtftgthtktmtntqtrtttttttttttttttttttttttttttttttttttttttttttttttttttturssss s ssssss"s$s's(s,s1s2s5s:s;s=sCsMsPsRsVsXs]s^s_s`sfsgsiskslsnsosqswsys|ssssssssssssssssssssssssssssssssssssssssssssssssssshqyqqqqqqqqqqqqqqqqqqqqqqqqqqqqrrr rrrrrr$r+r/r4r8r9rArBrCrErNrOrPrSrUrVrZr\r^r`rcrhrkrnrorqrwrxr{r|rrrrrrrrrrrrrrrrrrrrrrrrrrrooooooooopppp pp p#p/p4p7p9pj?jEjFjIjJjNjPjQjRjUjVj[jdjgjjjqjsj~jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjkkkk kkkkkkk$k(k+k,k/k5k6k;k?kFkJkMkRkVkXk]k`kgkkknkpkuk}khhhhhhhhhhhhhhhhhhhhi i iiiiii1i3i5i8i;iBiEiIiNiWi[icidieifihiiilipiqirizi{iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiijjjjjjjj j$j(j0j2jfglgngtgvg{gggggggggggggggggggggggggggggggggggRhhhhh(h'h,h-h/h0h1h3h;h?hDhEhJhLhUhWhXh[hkhnhohphqhrhuhyhzh{h|hhhhhhhhhhhhhhhhhhhhhf!f"f#f$f&f)f*f+f,f.f0f1f3f9f7f@fEfFfJfLfQfNfWfXfYf[f\f`faffjfkflf~fsfuffwfxfyf{ff|ffffffffffffffffffffffffffffffffffgggggg g"g3g>gEgGgHgLgTgUg]gddddddddddddddddddddeee e eeeeeeeee"e&e)e.e1e:e^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_m\p\t\u\z\{\|\}\\\\\\\\\\\\\\\\\\\\\\\\\\]] ]]+]#]$]&]']1]4]9]=]?]B]C]F]H]U]Q]Y]J]_]`]a]b]d]j]m]p]y]z]~]]]]]]]]]]]]]]]]]]]]]]]]]]]]]ZZZZZZZZZZZZZ[[[[4[[[[![%[-[8[A[K[L[R[V[^[h[n[o[|[}[~[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[ \\\\#\&\)\+\,\.\0\2\5\6\Y\Z\\\b\c\g\h\i\oYrYuYvYyY{Y|YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYZZ Z ZZZZZ#Z$Z'Z(Z*Z-Z0ZDZEZGZHZLZPZUZ^ZcZeZgZmZwZzZ{Z~ZZZZZZZZZZZZZZZZZZZZZ X XXXX X&X'X-X2X9X?XIXLXMXOXPXUX_XaXdXgXhXxX|XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXYY Y YYYYAY!Y#Y$Y(Y/Y0Y3Y5Y6Y?YCYFYRYSYYY[Y]Y^Y_YaYcYkYmYVVWWW W WWWWWW W"W#W$W%W)W*W,W.W/W3W4W=W>W?WEWFWLWMWRWbWeWgWhWkWmWnWoWpWqWsWtWuWwWyWzW{W|W~WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWXXX XWUUUUUUUUUVV V VVVVVVV,V0V3V5V7V9V;VSBSLSKSYS[SaScSeSlSmSrSyS~SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSTTT!T'T(T*T/T1T4T5TCTDTGTMTOT^TbTdTfTgTiTkTmTnTtTTQQQQQQQQQQQQQQQRRRRRRRR"R(R1R2R5RO@OBOHOIOKOLOROTOVOXO_OcOjOlOnOqOwOxOyOzO}O~OOOO   !%+/)57:><DHFQMUYW[]a_ecmqksoiuwz~|  " $0*.(469=;CGEPLTXVZ\`^dblpjrnhtxvy}{&2A?JRf'138B@IKSg    RSTUVWXYZ[\^_^"!! ghLh2LBJ_bhikhsvw~Ýǝɝ֝ڝߝM  {H؀hؽiߞwM/7:=AEFSUXi]iiimpui16DLXKKKfƚКҚ՚Kܚ +3= LKceklsvwggزǛ؛ݛggg"')*g167E\gIJgTX[]_ijkmnpruzjdd̗ؖїԗؗٗ Je#23%Gfeط˜ǘ˘e;Keee123:;<@AFMN\_`Ùəԙٙޙf  b ')bbGQWZkqsbb؈bbǓܓ 24;Ebbmoxycثcȕcc,34cEMX׊^  -C GQ^v9^=^^EGOT[[طDžʅ؅م߅!$'\9<\@ SVowz!ÆцՆ׆憸E!#1:>@CQXder|\\ا\E]·߇] ( T0QS^ab[{}[ $,0Cfqu{YŀՀ؀Y C5C$',Y=DiDD"DÁցہZZZZZ!"Z24}@}G}XWBY}Z}j}p}B}X؆}}}}X؝}}}}}}}}}}}CXX~~~ ~'~,~E~s~u~~~~~+C~~~CC<;>CDO4XRXacdm}~Xؐ{QOؖY8zGzLzVzYz\z_z`zgzjzuzxzzzzzzVشAzzzAzzzzzVV{V={'{*{.{/{1{AA{A{AU{y{d{f{i{s{VB{{{B{{{{{WW{{{{{| |||&|E|J|Q|W|^|a|i|n|o|p|WWWئ|Wض|||W|W|T9@TTXw`wjwTrw|w}wTX@wwwwwwwwwww@wwwUxx x xx!x,xGxdxjxU؊xxxxxxxxxxxxxxxxxxUyy0y%y;yJyXy[yAgyryyyyyyyyyyyyyyHAUUOA zzzzzcA-ztttttttttttttRtR u$u*uW?S=u>u@uHuNuPuRuluruquzu}u~uuS،uu?uw?uuuuuuuuuuuuuuuvvvv?SvvvS%v(vI+r4r8r9r,NBrSrWrcrQnrorxrrrQحrrrrr`>rf>h>rrssss>9s,s1s3s=sRs>kslsRnsosqswsssssssssssssssssssstst$t1t9tSt@tCtMtRt]tqttttRؒtttnnnnnnn5onnn o oo%o6ohDhEhIhLhUhWhw;khnhzh|hhhhm;hhhhhhhhhMMhhhhhbbbJbc ccJJ2c5c;c^I^\8V^a8k^l^m^ X'X2X9XDIXLXgXXXXXXXXXXEXXXXXYY Y YY$YEؑ6=Y6FY6[[Y_YEuYvY|YYYYYYYYYYYEE6 Z ZZ'Z-ZUZeZzZZZZZZZZZZZZZZZZZZ[[[4[-[L[R[h[o[|[[[[FSBSBBgSlSzSSSBطSSB]5^5SSc5SSUT$T(Tn5CTbTfTlTTTTTTTTTTTTCTTTTUU U@NNN)N+N.N@NGNHN@QN4@ZNiNN,4.4NN@ؼNNNNNNNNOOdO7O>OTOXO@wOxOzO}OOOOOOOOOOOOj4OPPPPP"Ph4BPFPNPSPWPcPfPjPpPPPPPPPPP@رPPPPPP@P@PPPP4WYZelȘX$-.8JNRÚΚ֚ L-^yfruΛ#AOPScewCGRcp|םh|Þў9WY[\w^&vk~89:<@COx’˒̒Ӓ!%HIJdejpƓޓߓ3Jckqr˕ЕӕIڕޕXҖޖh3;MNOZnsɗޗۗi +0jRSV"7GN]auyЊߊ"bcFTYiIhde΍э׍ #=p{`DH-6T`ئ-gĐŐǐאݐސ&"#'/14=H[בבޑ :@rrrrrQ's(sPsfs|sssssssssssss;iiiiijjM;j>jEjPjVj[jkjsjM؉jjjjjjj<kk,k5kFkVk`kekgkwkkkkpkkkkll3lYl\lltlvlllllllllllOmm.m1m9m?mXmemEmmmmmmmmmmmmmF4nDn\n^nnnnddddd"e)eAgeeBf fff:f"f$f+f0f1f3ffHfLfLYfZfafefsfwfxffCfffff";fffg)3gfgGgHg{gggggggggghRhh,h1h[hrhuhDhhhhhhhhhh iIiM5iBiWicidihiiiii;310569:78?@=>ABCD;</XiYdtQqSV]^^X^^^^(^^____#_4_6_=_@_E_T_X_d_g_}___________ ```3`5`G`=```````a+a0a7a>a?aa@"b>bCbVbZbobbbbb cc9cCcec|ccccdd"dydQd`dmdddd/XiYdtQq]^dQPYrozĝƝϝٝӝuy}a̞ΞϞОԞܞޞݞv!,>JRTc_`afgljwrv"#%'()*./2DCOMNQXtʛƛϛћқԛ:   .%$!0G2F>Z`gvx *&#DA?>FHqtsĘØƘ !$ ,.=>BIEPKQRLUߙۙݙؙљ+7EB@C>UM[W_bedikjϚњӚԚޚߚ]_frlΖ˖ɖ͖Mܖ Ֆ$*09=>DFHBI\`dfhRkqy|z×Ɨȗ˗ܗOz 8$!7=FOKkop"#:5;\`|nV֓דؓÓݓГȓ6+5!:ARD[`b^j)puw}Z|~ʕoÕ͕̕Օԕ֕ܕ!(./BLOKw\^OPQRI>VX^hovr}Hbې20JVXceisrɑˑБ֑ߑۑ,^WEIdH?KPZϒD.GILPHYd`*cUvr|ƎŎȎˎێ  &3;9EB>LIFNW\bcdڏ!  '659_lot}:A?HLNPUblxz|bȌڌ  N͌gmqsύڍ֍̍ۍˍߍ B504Jfdmjotw~ډ܉݉ %6A[RFH|mlbĊ͊Šڊފۊ  3&+>(ALONIV[ZkScjˇЇ֖ćLJƇ ҇"!169';DBRY^bk~u}rÈĈԈ؈و݈ C%*+AD;68L`^AKUmꅇw~ɅυЅՅ݅܅  "0?MUNT_gqĆƆɆ#Ԇކ߆ۆ 4?7;%)`_xLNtWhnY5421@9PE/+#|su΃؃  " 8m*SQqneft_Ɂ́сف؁ȁځ߁ )+83@YX]Z_dbhjk.qwx~߂҂ނ܂ قELMNPQUTX_`higxqܘ !(?;JFRXZ_bhsrpvy}Qۀـ݀Āڀր )#/K}}} }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:z{{M{ {L{E{u{e{t{g{p{q{l{n{{{{{{{{{{]{{{{{{{{{{||{{`||||{{| |{#|'|*||7|+|=|L|C|T|O|@|P|X|_|d|V|e|l|u||||||||||||||||||||||;|||||}xxxxyyyy,y+y@y`yWy_yZyUySyzyyyyyKyyyyyyyyyyyz zzz zzy1z;z>z7zCzWzIzazbzizpzyz}zzzzzzzzzzzzzzzzzzzzzzzzzzz{{ {{3{{{{5{({6{P{rvvvxv|vvvvvvvvvvvvvvvvvvvvvvvv/vwww)w$ww%w&ww7w8wGwZwhwkw[weww~wywwwwwwwwwwwwwwwwwwwww xx&y x*yExxtxx|xxxxxxxxxxxxxxxxttttttttttuuu uu uuuu&u,usNsOs؞Wsjshspsxsus{szsssssssssttot%ts2t:tUt?t_tYtAt\titptctjtvt~ttttttts>oonozoxooooo[oomoo|oXoooofoooooooooooooooo p popppopptoppp0p>p2pQpcppppppppppppp qpqqeqUqqfqbqLqVqlqqqqqqqqqqqqqqqqqqqlllllmM6m+m=m8mm5m3mm mcmmdmZmymYmmmommn nmmmmmmmmmmmmmmmmm-nnn.nnrn_n>n#nkn+nvnMnnCn:nNn$nnn8nnnnnnnnnnnnnnnnnAooLpnnn?on1on2onjjjjjjjjjjjjjjkjkk1k8k7kv9kGkCkIkPkYkTk[k_kakxkykkkkkkkkkkkkkkkkkkkkkkkkkkllll$l#l^lUlbljllllll~lhlslllllllllllllhhh6iiihh%ihhh(i*ii#i!ihyiwi\ixikiTi~ini9iti=iYi0iai^i]iijiiiiiiiii[iiiii.jiiiiiiijji kiiijijiji jjj#jjDj jrj6jxjGjbjYjfjHj8j"jjjjjjjfffff?ffffffggg&g'g8.g?g6gAg8g7gFg^g`gYgcgdggpgg|gjggggggggggggggggggggggjhFh)h@hMh2hNhh+hYhchwhhhhhhhhhjhthhhhih~hihih"i&ih ihddddddddd ddbdd,eddddedeee$e#e+e4e5e7e6e8eKuHeVeUeMeXe^e]erexeeeeeeeeeeeeeeeeeerg ffesg5f6f4ffOfDfIfAf^f]fdfgfhf_fbfpfffffffffffffb!b*b.b0b2b3bAbNb^bcb[b`bhb|bbb~bbbbbbbbbbbbbdbbbbbbbb cbb'cccbbPc>cMcdOcccccvcccccckciccccccccccd4ddd&d6ded(ddgdodvdNd*edddddd````````````_````Maaa``a``a!a`` aaGa>a(a'aJa?a[C[E[@[Q[U[Z[[[e[i[p[s[u[x[ez[[[[[[[[[[[[[[[[[[[\\\ \\ \"\(\8\9\A\F\N\S\W W WWWWUW&W7W8WNW;W@WOWiWWWaWWWWWWWWWWWWWW XWW XXXrX!XbXKXpXkRX=XyXXXXXXXXXXXXXXXXXXXXXXXXXXY YYYh%Y,Y-Y2Y8Y>YzUYPYNYZYXYbY`YgYlYiYTTTTTTTTUUTTTTT9U@UcULU.U\UEUVUWU8U3U]UUUTUU{U~UUUU|UUUUUUUUUUUUVUVUUVUNVPVq4V6V2V8VkVdV/VlVjVVVVVVVVVVVVVVVVVVVVVVVWVW WRRRRRRRRRRRRRRRSS8u SSSSS#S/S1S3S8S@SFSESNISMSQ^SiSnSY{SwSSSSSSSSSS|ٖSfqSSSST=T@T,T-T|}o8/UQO*QRS[}^`ac gggnm6s7s1uPyՈJĖYNYON?P|^Y[^ccdfJii mnq(uzIɄ! e} ~ab2kltmmeg<ma}=jqNuSP]koͅ-)RTe\Nghtt+osT*gE]{\[JnфzY|l wR"Y!q_rw'a iZZQ T}TfvY]rnMQh}}bxd!jY_[ksv}2Q(gٞvbgR$\;b~|OU` }S_NQY:r6Α%_wSy_}3VgS aalRvllp2x+~ހ *JҒlONNPVRJWY=^__?bfgghQ!}~2 T,SP\SXd4ggrfwFzRlkXL^TY,gQvidxTWY'fgkTiU^ggR]hNOSb+glďOm~Nbanyym_UblNirR;TtVXanbqnY||}e^NuOuQ@Xc^s^ _g&N=[s|PXVvx%Rw{OP YGr{}ԏMOR)Z_OWUcik+u܈BzRXUa bfk?|#POSFT1XIY[\\)]^bgc>ee g;gz9Suf_񃘀<__buF{lNlHrrsTuA~,酩{Ƒiq=cifjuvxC*SQS&TY^|_`Ibybbekluvxy}w^ۘ j8|P>\_gk5t wY?\NY_oyby[q+sqt^_{cdq|CN^KNWV`o }3]bdwgl>m6t4xFZuO^bcWeogvLr̀)M PWZhsidqrXjyw)/OeRZSbgl}v{|6f or~ciFv-0ؕPR TX\admwzS\?S__myrcwy{krhajQz4iJ\[IpxVo\`felZAQTf HYQMNQXpzcKbi~wuWS`iߎ]lN<\_Sьy^esNeQ-ؑlXdduenv{iѓnT_dMDxQkX)YU\^m~u[pOko0uNQT5XWXY`\_e\g!n{v߃M%x:xR^WtY`PZQQQRUTXXXWY[\]`b-dqgChhhvmonmopqS_uwyI{T{R{|q}0R^3^^_5_k__acfgnoRr:u:wt9xv܊󍚒wRWcvglsÌs%mXiiuZXhciCO,og&}T?ipojWX,[,}*r T㑴NNO\PuPCRHT$X[^^^^_`b:cch@lxy z}GDSFOTjY1]zh7rH=j9NXSVfWbceNkm[npwz{}=ƀˆ[VX>_efjk7uNJ$Pw0W_e`zf`luznE{\uzQ{Ąyz6Z@w-NN[_bUXY`Sbg5Ui@ę(SOX[\/^_ `Ka4bfln΀Ԃ.۞ۛNS'Y,{Ln'pSSDU[Xbbblo"t8o8QSJ~z9nΌxwMRU8o6qhQyU~|LVQX\cffZiruuyVyy| }D}4;a PuRSS PUXOY=r[d\S``\cc?ccdef]iioqNuvz|}}aIXlňpmPXaozd[N,p]u/fQ6RRY_'`b?eteftfhhcknrruv|VXˊRYez-^`befgwMzM|>~ d_xRbcBdb-z{v} INHQCS`S[\\]&bGbdh4hlEmmg\oNq}qez{}b ikqT~wrߘU;\8OOOU Z[[_Na/ceKfhixmm3uuw^yy3}は:2ݑNNRuXX \u=\N ŏcm%{ϊbVS9TW%^c4lpaw|pBT^tĚ]i]pegۖncIgiŃR SGSSTFU1UVhYYrtux:y 3ꁔPl_X+z[NSW1YZ[`nouꌟ[{rPga\J~Q\hcfenq>y}ʎndžPR:\Sg|p5rLȑ+[1_`;NS[Kb1gkrs.zkRQSjT[c9j}VShT[bdd-gkіv֛LcvRf NPSq\`dce_hqs#u{~یxefkNN:OO:RSSUVXYYYP[M\^+^_`c/e\[eeegbk{klEsIyy|}+}󁖉^ifnj܌̖okNd(fggzV{"}/\h9{SQ7RTUQWW}YT[][[]]]x^^^^_R`Labbc;efCffmg!hhi_l*mim/nn2uvlx?z|}}^}}T*RLaʐuq?xMؚ;[RRSTXboj_KQ;RJTV@zw`ҞDs opu_`ri)j}rr.sxoxy} wҎcuzUxCQSS{^&_nnssC}7PNN PS|TVYd[]^'_8bEegVnr|N7ǖgNN OHSIT>T/Z__`hjZtxw^NɛN|OOPPIQlQRRRSSTczltazq|hp~QhlRT͎fSAyOPRDQSU-WsWQYb__u`vagaac:dleofBhnfu=z|L}}K~kJ͆cfΏ蛇RbdoAhP kzlTotzP}@#gN9P&PeP|Q8RcRUWXZ^aabrcOOPGQzqQQTS!SSSUX\7_J_/`P`m`cYeKjlrrwNWZNQ-\fmi@\fuisPh|PRGW]&e#k=k4tyyK{}̃_9яёT]N6PS:Srsw悯ƙșҙwQa^UzzvP[G2NjQ\H\_j0^kl}luHyc[z}_w̎kSkWl"ooEotuv wz{!|}6f̊Qeӗ(8N+T\]sLvyyrvOTSRe!f!g!h!i!I33"3M33'3363Q3W3 3&3#3+3J3;33333333{300!3!!22222122292~3}3|3R"'Y\22222;S*QRpScy`$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!i!I33"3M33'3363Q3W3 3&3#3+3J3;33333333{300!3!!22222122292~3}3|3R"a"+"."""" """5")"*"2v'w'x'y'z'{'|'}'~''$$$$$$$$$$p!q!r!s!t!u!v!w!x!y!z!{!$$$$$$$$$$$$$$$$$$$$$$$$$$2222222222222222222222222Q B d&g&a&b&`&c&e&f& 0&0&&&&!!!!!!!!!!!d&g&a&b&`&c&e&f& 0&0&&&&!!!!!!!fSW`SRhXuY\^PodTQReUzgZpqrsa?  %,9 =)/$0<4*:;33333333333333!33333 !333333!3!!A=Z`^dy}{B>[a_ez~|T9 CGPXnpbU: DHQYoqc$4\l %5]mq~lnyVs}{m_raKp'`!a!b!c!d!e!f!g!h!i!j!k!p!q!r!s!t!u!v!w!x!y!z!{!$$$$$$$$$$$$$$$$$$$$$$$$$$ *jL+kM`$a$b$c$d$e$f$g$h$i$j$k$l$m$n$o$p$q$r$s$t$u$v$w$x$y$z${$|$}$~$$$$$$$$$$v'w'x'y'z'{'|'}'~'$$$$$$$$$%% %%%%%,%$%4%<%%%%%%%#%3%+%;%K% %/%(%7%?%%0%%%8%B%Q2R2S2T2U2V2W2X2Y2Z2[2\2]2^2_2222222222222222%%%%< G H I >?%% %%%%%,%$%4%<%%%%%%%#%3%+%;%K% %/%(%7%?%%0%%%8%B% !"#$%&'()*+,-./###############012345Q6789:;<=>?@ABCDEFGHIJKLMNO0000""S!T!U!'##$# !"#$%&'()*+,-./012345Q6789:;<=>?@ABCDEFGHIJKLMNOd&`&b&f&a&e&g&c&$$$$$$$$$$&& 0&&&&&h&%11111111110111111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000A0B0C0D0E0F0G0H0I0J0K0L0M0N0O0P0Q0R0S0T0U0V0W0X0Y0Z0[0\0]0^0_0`0a0b0c0d0e0f0g0h0i0j0k0l0m0n0o0p0q0r0s0t0u0v0w0x0y0z0{0|0}0~000000000000000000000000000000A0B0C0D0E0F0G0H0I0J0K0L0M0N0O0P0Q0R0S0T0U0V0W0X0Y0Z0[0\0]0^0_0`0a0b0c0d0e0f0g0h0i0j0k0l0m0n0o0p0q0r0s0t0u0v0w0x0y0z0{0|0}0~0000000000000000000000%%%%!!!!!!!!!4)5))%=0FE%" !"#$%&'()*+,-./0123456789:"5!!3!'!ABCDEFGHIJKLMNOPQRSTUVWXYZ0 ))!"#$%&'()*+,-./0123456789:ABCDEFGHIJKLMNOPQRSTUVWXYZ%%%%%%%; 0!!!!0 ^304050;0<000" """""*")""""" ""##'"("!!"""""%"&"_`0000 ""#""a"R"j"k""=""5"+","b"C"E"H"v"w"!+!0 o&m&j& ! n&k&l&i&%%%%%%%%; 0!!!!0" """""*")"'"("!!"" ""#""a"R"j"k""=""5"+","+!0 o&m&j& ! %%%%%%%%; 0!!!!0" """""*")"'"("!!"" ""#""a"R"j"k""=""5"+","+!0 o&m&j& ! %000 000@>?00000N0000  <^%"\& %      00;=[]0 0 0 0 0 00000 `"f"g""4"B&@&2 3 ! &&%%%%000 000@>> ?00000N0000  <0 \& %      00;=[]0 0 0 0 0 00000 "`"f"g""4"B&@&2 3 ! &&%%%%nkf internal module connection failure. ;_`~ H``0 0DPXl0Pp0D@P,P@Th |`dxp4PH\x@ p4 ` P  8 `L ` 4 p ` p$ D ` @8 T  0 `  `LPh`(p0D @ , p/P0`2,04h07zRx $8{ FJ w?:*3$"D0} \]q B `E\ O 44FGA E(J0y(K ABB,FFE  CBK 4lFGA E(J0y(K ABB@TlhL|HOHOm@ I{ D uCHh H s E j F s E s,XL@TFBA C(F0 (A ABBF e (E ABBI uFAC  ABE U ABH t FBD  AHO c FBM  DPH U FDI KJ(<P'dHx>BBE H(D0D8DP 8C0A(B BBBA   HFBB B(A0D8DH 8A0A(B BBBI `4 t0 ,D D S E \AAF  AAG R AAD O AAG r AAD H AAF X^Z H J N 0ԗ4jDBxX<4EAUt`EAFd8P[5DZ A $<AID kAAȘ^al<(04~ADG0L AAF 0\BDK G@z  AABJ  D F F N# ̧H j F  B HNH0 D |H | D 4H SH\X/FBB B(A0A8D` 8A0A(B BBBF <FBA C(F0w (A ABBI v (D ABBI t (C ABBL  (A ABBF x (C ABBP \0dRFBD C(D0 (A ABBI  (C ABBN t (A ABBF 8dhbEE D(C0m(A BBB H F B  G d>D y ] DBAn Q A@ tVAS<\ WBBB A(A0[ (A BBBF ػ FBB E(A0A8DP 8D0A(B BBBE  8A0A(B BBBH  8A0A(B BBBJ ~ 8A0A(B BBBH 4 ZAW(P DnCF PEA@| ECF o EAE X AAF W EAK  CKO F b 8 0. L?( x]AD RAAJH H0X H d H t D  F , \fBAG  CBA  :Ad K EH M[V O L D t D m K TDHo A e A Vt$ BEH E(A0A8D@l 8A0A(B BBBH j 8A0A(B BBBD H8F0A(B BBBH 8#BBB B(A0A8D` 8A0A(B BBBF  V@ hEAD  AAG _ CAE S CAI H@ ^FBE B(A0A8D` 8A0A(B BBBJ  5DZ A ` FRBI A(A0 (A BBBJ { (D BBBK h (A BBBA  aG@( [l I G I e K ` H DTV J QLl"BBB B(A0A8G$ 8A0A(B BBBA bEO L {zRx  p  8H  F 8(, FBA A(G (A ABBK ,d!ED  DF _ DE $3E&GNU ^$uʅڅڅ '+O/q9<?j:ovDHLQTJ_eilnTy~e*gĆY#+:2BMȆӆՆ dǃՃ߃r ` ` ` ` ` ` ` ` ` ` ` ` ` ` `$$$$$$$$~$x$$$$$$$$$z$$$$$$$$$z$$$$$$$$$z$$$$$$$$$|$``````````````````````````````````````=`<`;`:`9`8`7`6`5`4`3`2`1`0`/`.`-`,+*)('&%$#"!      =<;:9876543210/.-,+`+`*`)`(`'`&`%`$`#`"`!` ``````````````````` ` ` ` ` ```````|`{`z`y`x`w`v`u`t`s`r`q`p`o`n`m`l`k`j`i`h`g`f`e`d`c`b`a```_`^`]`\`[`Z`Y`X`W`V`U`T`S`R`Q`P`O`N`M`L`K`J`I`H`G`F`E`D`C`B`A`@`?`>|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>``````````````````````````````````````````````````````````````~`}~}`````````````````````````````````````````````````````````````````;`:`9`8`7`6`5`4`3`2`1`0`/`.`-`,`+`*`)`(`'`&`%`$`#`"`!` ``````````````````` ` ` ` ` `````````````;:9876543210/.-,+*)('&%$#"!      W`WV`VU`UT`TS`SR`RQ`QP`PO`ON`NM`ML`LK`KJ`JI`IH`HG`GF`FE`ED`D`C`B`A`@`?`>`=`<CBA@?>=<v`vts`srq`po`o`n`m`kj`ji`ih`hg`gf`fe`ed`dc`cb`ba`a```_`_^`^]`]\`\[`[Z`ZY`YX`X`w`v`u`t`rpnmlk`w`v`u`tr`q`o`n`m`lw`vu`tr`q`o`n`m`l``````~}|{z`zy`yx`x`````````~`~`}`|`{````````~`~`}`|`{````````~`~`}`|`{`````````~`~`}`|`{`@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@HE@DB@A?@><@;9@863@200@/.--@,+**@)(''@&%$$@#"!!@ @@@@@@   @    @@@@@@@@HFECB@?=<:964310@/.--@,+**@)(''@&%$$@#"!!@ @@@@@@   @    @@@@@HFECB@?=<:97@5310@/.--@,+**@)(''@&%$$@#"!!@ @@@@@@   @    @@@@@H@GECB@?=<:97@5310@/.--@,+**@)(''@&%$$@#"!!@ @@@@@@   @    @@@@@6EU`nx ^$^$o`P   $  ooo:o&$ 0@P`p 0@P`p BB?P  FF FF P SP2PT  FFFFD (6DU Q _ h l x       ߄‡·݇҄ [*3j@ M!V"˄# P p $P'`$Dc (6D  n   z҄ [*3j @!M"V#˄GA$3a1! GA$3p1067@GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFYGA+GLIBCXX_ASSERTIONSnkf.so-2.2.10-35.el8.x86_64.debugk7zXZִF!t/']?Eh=ڊ2NffA" h2kсˏݘõ"R}BVEI` }z UAVYYѳ΄!ᓬƢ>݄|)_~l}v\;bP\Re/GV]쏱6 0! h8Y8ks ky,yri>?1>+̈́k).'SS~$} +iytfLU0'@>ďn m5ru8qc>!4 ǺCyRL oM|汘'gKkqSx߽;:3Ud57i<J"5X,'K4>G)C f:{$XY.]2梜/B !elB-Qs%R " t@+?N_4O%1 90_;o,\ݗmCRޯLkn )J@@C%̍_lhe_F[?daRxaggl41YFtFUHz>׮|:TQ|EU&HQ,0Qs-W0ddQN*B|f HW}]Z \?МPFT*ͻaЏS;:w4OƧ`5HO@ŢSuA(h,, b qC_^9 _@ 3vȒn0Ud968߷9ڜx)zP$wE!gط^' /~"(RP%چ^4IݢWf"PƾC`0{QCx#CSU5y1l eislbÇ 5X@+ |GʰT\g> 0"@+3F{3#2?F qvJ"gP31l4=jopg1]ɭ r/ ij),j-`YX1F7}9| -Pw>V_IEj-<$N 06&6cwr[r;><ѣXSѮ.PpBYN-C¢2~A`4]Z">w:>6Qz͉-iwEzX i?e{-NjBE" n҇ DPrO.zɎcd)@FVRbW%"gګ~fIB.Kn0d:ڱgYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.data.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``p( 0P P 8o::Eo@T  ^Bhc n00w@@Ӷ} @@p IILLh\h\ ^$^^$^ ^$ ^p^ $ $@$  $ X $x&  dxH("\D1PK!1bb2.2.0/x86_64-linux/strscan.sonuȯELF> @@[@8 @xHxH MM M  MM M  888$$XHXHXH StdXHXHXH Ptd>>>QtdRtdMM M GNU}Z Qc)F>@`>AV`TdBE|qX KFA,jv(_fU | Xq65q*}WCr, F"9 P3XQ R Q __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeonig_region_freeruby_xfreerb_gc_markonig_region_clearonig_region_setrb_check_typeddatarb_num2intrb_fix2intrb_eRangeErrorrb_raiserb_eArgErrorrb_string_valuerb_reg_region_copy__stack_chk_failrb_memerrorrb_scan_argsruby_xcalloconig_region_initrb_data_typed_object_allocrb_str_newrb_enc_copyrb_num2longrb_enc_getonig_name_to_backref_numberrb_eIndexErrorrb_enc_raiserb_sym2strrb_out_of_intrb_warningrb_enc_mbclenrb_check_typerb_reg_prepare_reonig_matchonig_searchonig_freeonig_region_memsizerb_str_catrb_str_dumprb_str_new_staticrb_obj_classrb_sprintfrb_funcallrb_str_lengthrb_str_appendInit_strscanrb_cObjectrb_define_classrb_eStandardErrorrb_define_class_underrb_const_definedrb_obj_freezerb_const_setrb_define_alloc_funcrb_define_private_methodrb_define_singleton_methodrb_define_methodrb_aliasrb_intern2libruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5GLIBC_2.4/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ui ii !M M  M  M @M 4=HM PM XM *O O O O O +O 4O 5O 6O 7P  P (P 0P 8P @P HP  PP  XP  `P  hP  pP xP P P P P P P P P P P P P P P P  P !Q "Q #Q $Q % Q &(Q '0Q (8Q )@Q *HQ ,PQ -XQ .`Q /hQ 0pQ 1xQ 2Q 3Q 7Q 8Q 9Q :Q ;Q <Q =HHa; HtH5; %; hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4%=8 D%58 D%-8 D%%8 D%8 D%8 D% 8 D%8 D%7 D%7 D%7 D%7 D%7 D%7 D%7 D%7 D%7 D%7 D%7 D%7 D%7 D%7 D%7 D%7 D%}7 D%u7 D%m7 D%e7 D%]7 D%U7 D%M7 D%E7 D%=7 D%57 D%-7 D%%7 D%7 D%7 D% 7 D%7 D%6 D%6 D%6 D%6 D%6 D%6 D%6 D%6 D%6 D%6 D%6 D%6 D%6 DH=6 H6 H9tHn4 Ht H=i6 H5b6 H)HHH?HHtHU4 HtfD=%6 u+UH=B4 Ht H=n1 d5 ]wHS1HH H[@HsUHo SHHHHK+KHH[11]2fUHH50 SHHxHHuAHKHHHց Hx5Hu`HH9|5HCHHHD[]f;fHu;HHyH2 H5H81HQf.HQHyH2 H5H81ff.fSHHt$H5/ H|$HiHD$HCH#HCH[ff.UHSH(Ht$H5/ dH%(HD$1RH|$H5v/ H>H9t>HHp H{ HHPHSHPHSHPHSnu.HD$HD$HD$HL$dH3 %(HuH([]LAVIH5. AUAHATUSHH dH%(HD$1Hl$HLD$LIHD1H,HD$ID$HL$dH3 %(uH H[]A\A]A^ff.fUHHSHH HHx HCHHH[H. ]T@HЃ~+Hu HtHt %H HHsff.USHLOI unHH9|IH9HNIHH)HI<1HHuHH~uHt HuHDHH[]f.IIH9|H9MIHOH)fAUATUSHH5 - HHxHtwtKuT؃t,Ht& H4tH ȃtgHHHu7tHHcU$HHH[]A\A]fH ȃus HLkIHHM KT%LHHE@HxdIcI9H. MDHHH01@H/HH vLkLcwHcU$HcH9'HU(H4HHU0HMHHHH[]HA\A]HH. H5H81LSH54+ HpHtxHHHHKHH tLHVH9}OHKHHHHHKHC0HsHHHC([HH0 f.HH9|[HF- H5H815DS1HH=G*H[1SH5d* /HxHHH HPH HGH9HKH1 HHyHHH{HKHsHcH H utHH9HKHHOH HSHC0HsHHHC([HH0@HH9c[fHyHqiHVH, H5H81fUH5D) SH HH@Ht{HHs t!HPH9}$HH[]Jf.HH9|1H=sFHsHH@uHt HsHHH[]HK+ H5H81:f.UHSHLGIH% uvHH9|RL HH)I9HOIxHtIxHHHuHH=uHt HuHHH[]fIHf.AWAVAAUAATEUHSHHHH5' HHpHHH H HFH;CHk@HLUII9<LC HCHsEtsH GHPHHHHE1HLLT$LT$IHE M9u~HHE HH;CwH[]A\A]A^A_H HHHPHLT$HHMjIHLbIXZLT$HE M9tHL~IMxHsH HC0HsEt HHHSHHDEUHH[]A\A]A^A_fHE fDHHHH<DHPHHփDH}L}PHw( H5HH81fH=* H5&1QHHE1f.E11}ff.fE111`E11ɺMff.fE1*f.HAHA1f.A11ff.fA1ɺf.AwUSHH5P$ HHHHHHHHHu t+HAH9}.H<HH)H9HHOH[]cHH9|1H=c6HuHHuHt HuHHH[]HxHMHeH%& H5H81@U1HSHH=cHHHH[]HtHH HH(Ð1ff.fHH urHH9~oH)SH~#<%li fin>#<%li %ld/%ld @ %li >#<%li %ld/%ld %li @ %li >ScanErrorbytesliceStringScanner0.7.0VersionIdinitializeinitialize_copymust_C_versionresetterminateclearstringstring=concat<<pos=charpospointerpointer=skipmatch?checkscan_fullscan_untilskip_untilexist?check_untilsearch_fullgetchget_bytegetbytepeekpeepunscanbeginning_of_line?bol?eos?empty?rest?matched?matchedmatched_size[]pre_matchpost_matchrestrest_sizerestsizeinspect;8 $,8LT\h||Llt\<( D,h<Pd,xLl <-nz*tmpb?.gbDn+ZU s KA,laK>v oT 7c!sRO>ݨa C Y(C+[<f}eWE_a%UȘjõr=jr o|Ǘ?/p>[κ>k3R9PæM3cFmS҃eӗ,ON+E vXj&O㐼#Y˸W3oCxC63MЙ,h^jj8& rި:ۇWihoRiı RSOx=: æN0,a*A+ LIn~Z@%(D;Vs7cJ:N1scs)z ID{-p@UQΖayь*>2(;P*…iZ됄(g+SErwo?m7tȧeģѣD،D#|9r`M 烯p/*<BM+_m>L158ct}w.!2bӦJiԗxziv赢n:H3L_ײƪ7FӚJv ĝ p> l{ޢ:C:}"뺝Hf6+4Δ^TwWえ>;̌t#h9-^5;P5lT5#k\.W~ ʷ=;΋R4ig~$~@*7D j7De TizM`L! 8WhV 2gQgYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 00X8o Eo 0T ^BXXhPPcpp`nPw  }:: 2:: >>@@XHXH M MM M M Mh M M O OHP PQ QPR`QH T,4TZ+PK!O5442.2.0/x86_64-linux/rbconfig.rbnu[ # This file was created by mkconfig.rb when ruby was built. Any # changes made to this file will be lost the next time ruby is built. module RbConfig RUBY_VERSION.start_with?("2.2.10"[/^[0-9]+[.][0-9]+[.]/]) or raise "ruby lib version (2.2.10) doesn't match executable version (#{RUBY_VERSION})" TOPDIR = File.dirname(__FILE__).chomp!("/lib64/ruby/2.2.0/x86_64-linux") DESTDIR = '' unless defined? DESTDIR CONFIG = {} CONFIG["DESTDIR"] = DESTDIR CONFIG["MAJOR"] = "2" CONFIG["MINOR"] = "2" CONFIG["TEENY"] = "0" CONFIG["PATCHLEVEL"] = "489" CONFIG["INSTALL"] = '/usr/bin/install -c' CONFIG["EXEEXT"] = "" CONFIG["prefix"] = (TOPDIR || DESTDIR + "/opt/alt/ruby22") CONFIG["ruby_install_name"] = "$(RUBY_BASE_NAME)" CONFIG["RUBY_INSTALL_NAME"] = "$(RUBY_BASE_NAME)" CONFIG["RUBY_SO_NAME"] = "$(RUBY_BASE_NAME)" CONFIG["DESTDIR"] = "" CONFIG["exec"] = "exec" CONFIG["ruby_pc"] = "alt-ruby22.pc" CONFIG["PACKAGE"] = "ruby" CONFIG["BUILTIN_TRANSSRCS"] = " newline.c" CONFIG["USE_RUBYGEMS"] = "YES" CONFIG["MANTYPE"] = "doc" CONFIG["NROFF"] = "/usr/bin/nroff" CONFIG["vendorarchhdrdir"] = "$(vendorhdrdir)/$(sitearch)" CONFIG["sitearchhdrdir"] = "$(sitehdrdir)/$(sitearch)" CONFIG["rubyarchhdrdir"] = "$(rubyhdrdir)/$(arch)" CONFIG["vendorhdrdir"] = "$(rubyhdrdir)/vendor_ruby" CONFIG["sitehdrdir"] = "$(rubyhdrdir)/site_ruby" CONFIG["rubyhdrdir"] = "$(includedir)/$(RUBY_VERSION_NAME)" CONFIG["RUBY_SEARCH_PATH"] = "" CONFIG["UNIVERSAL_INTS"] = "" CONFIG["UNIVERSAL_ARCHNAMES"] = "" CONFIG["configure_args"] = " '--build=x86_64-redhat-linux-gnu' '--host=x86_64-redhat-linux-gnu' '--program-prefix=' '--disable-dependency-tracking' '--prefix=/opt/alt/ruby22' '--exec-prefix=/opt/alt/ruby22' '--bindir=/opt/alt/ruby22/bin' '--sbindir=/opt/alt/ruby22/sbin' '--sysconfdir=/etc' '--datadir=/opt/alt/ruby22/share' '--includedir=/opt/alt/ruby22/include' '--libdir=/opt/alt/ruby22/lib64' '--libexecdir=/opt/alt/ruby22/libexec' '--localstatedir=/var' '--sharedstatedir=/var/lib' '--mandir=/opt/alt/ruby22/share/man' '--infodir=/opt/alt/ruby22/share/info' '--enable-rpath' '--enable-shared' '--with-openssl-dir=/opt/alt/openssl' '--with-ruby-pc=alt-ruby22.pc' 'build_alias=x86_64-redhat-linux-gnu' 'host_alias=x86_64-redhat-linux-gnu' 'CFLAGS=-O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -I/opt/alt/openssl/include' 'LDFLAGS=-O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -L/opt/alt/openssl/lib64 -L/opt/alt/ruby22/lib64 -Wl,-rpath=/opt/alt/openssl/lib64,-rpath=/opt/alt/ruby22/lib64' 'CXXFLAGS=-O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection'" CONFIG["vendorarchdir"] = "$(vendorlibdir)/$(sitearch)" CONFIG["vendorlibdir"] = "$(vendordir)/$(ruby_version)" CONFIG["vendordir"] = "$(rubylibprefix)/vendor_ruby" CONFIG["sitearchdir"] = "$(sitelibdir)/$(sitearch)" CONFIG["sitelibdir"] = "$(sitedir)/$(ruby_version)" CONFIG["sitedir"] = "$(rubylibprefix)/site_ruby" CONFIG["rubyarchdir"] = "$(rubylibdir)/$(arch)" CONFIG["rubylibdir"] = "$(rubylibprefix)/$(ruby_version)" CONFIG["ruby_version"] = "2.2.0" CONFIG["sitearch"] = "$(arch)" CONFIG["arch"] = "x86_64-linux" CONFIG["sitearchincludedir"] = "$(includedir)/$(sitearch)" CONFIG["archincludedir"] = "$(includedir)/$(arch)" CONFIG["sitearchlibdir"] = "$(libdir)/$(sitearch)" CONFIG["archlibdir"] = "$(libdir)/$(arch)" CONFIG["libdirname"] = "libdir" CONFIG["RUBY_EXEC_PREFIX"] = "/opt/alt/ruby22" CONFIG["RUBY_LIB_VERSION"] = "" CONFIG["RUBY_LIB_VERSION_STYLE"] = "3\t/* full */" CONFIG["RI_BASE_NAME"] = "ri" CONFIG["ridir"] = "$(datarootdir)/$(RI_BASE_NAME)" CONFIG["rubysitearchprefix"] = "$(rubylibprefix)/$(sitearch)" CONFIG["rubyarchprefix"] = "$(rubylibprefix)/$(arch)" CONFIG["MAKEFILES"] = "Makefile GNUmakefile" CONFIG["PLATFORM_DIR"] = "" CONFIG["THREAD_MODEL"] = "pthread" CONFIG["SYMBOL_PREFIX"] = "" CONFIG["EXPORT_PREFIX"] = "" CONFIG["COMMON_HEADERS"] = "" CONFIG["COMMON_MACROS"] = "" CONFIG["COMMON_LIBS"] = "" CONFIG["MAINLIBS"] = "" CONFIG["ENABLE_SHARED"] = "yes" CONFIG["DLDLIBS"] = " -lc" CONFIG["SOLIBS"] = "$(LIBS)" CONFIG["LIBRUBYARG_SHARED"] = "-Wl,-R$(libdir) -L$(libdir) -l$(RUBY_SO_NAME)" CONFIG["LIBRUBYARG_STATIC"] = "-Wl,-R$(libdir) -L$(libdir) -l$(RUBY_SO_NAME)-static" CONFIG["LIBRUBYARG"] = "$(LIBRUBYARG_SHARED)" CONFIG["LIBRUBY"] = "$(LIBRUBY_SO)" CONFIG["LIBRUBY_ALIASES"] = "lib$(RUBY_SO_NAME).so.$(MAJOR).$(MINOR) lib$(RUBY_SO_NAME).so" CONFIG["LIBRUBY_SO"] = "lib$(RUBY_SO_NAME).so.$(MAJOR).$(MINOR).$(TEENY)" CONFIG["LIBRUBY_A"] = "lib$(RUBY_SO_NAME)-static.a" CONFIG["RUBYW_INSTALL_NAME"] = "" CONFIG["rubyw_install_name"] = "" CONFIG["EXTDLDFLAGS"] = "" CONFIG["EXTLDFLAGS"] = "" CONFIG["strict_warnflags"] = "-std=iso9899:1999" CONFIG["warnflags"] = "-Wall -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Wunused-variable -Wpointer-arith -Wwrite-strings -Wdeclaration-after-statement -Wimplicit-function-declaration -Wdeprecated-declarations -Wno-packed-bitfield-compat" CONFIG["debugflags"] = "-ggdb3" CONFIG["optflags"] = "-O3 -fno-fast-math" CONFIG["cxxflags"] = " $(optflags) $(debugflags) $(warnflags)" CONFIG["cflags"] = " $(optflags) $(debugflags) $(warnflags)" CONFIG["cppflags"] = "" CONFIG["NULLCMD"] = ":" CONFIG["DLNOBJ"] = "dln.o" CONFIG["INSTALLDOC"] = "all" CONFIG["CAPITARGET"] = "nodoc" CONFIG["RDOCTARGET"] = "rdoc" CONFIG["DTRACE_REBUILD"] = "" CONFIG["DTRACE_OBJ"] = "" CONFIG["DTRACE_EXT"] = "dmyh" CONFIG["EXECUTABLE_EXTS"] = "" CONFIG["ARCHFILE"] = "" CONFIG["LIBRUBY_RELATIVE"] = "no" CONFIG["EXTOUT"] = ".ext" CONFIG["RUNRUBY_COMMAND"] = "$(MINIRUBY) $(srcdir)/tool/runruby.rb --extout=$(EXTOUT) $(RUNRUBYOPT)" CONFIG["PREP"] = "miniruby$(EXEEXT)" CONFIG["BTESTRUBY"] = "$(MINIRUBY)" CONFIG["CROSS_COMPILING"] = "no" CONFIG["TEST_RUNNABLE"] = "yes" CONFIG["rubylibprefix"] = "$(libdir)/$(RUBY_BASE_NAME)" CONFIG["setup"] = "Setup" CONFIG["ENCSTATIC"] = "" CONFIG["EXTSTATIC"] = "" CONFIG["STRIP"] = "strip -S -x" CONFIG["TRY_LINK"] = "" CONFIG["LIBPATHENV"] = "LD_LIBRARY_PATH" CONFIG["RPATHFLAG"] = " -Wl,-R%1$-s" CONFIG["LIBPATHFLAG"] = " -L%1$-s" CONFIG["LINK_SO"] = "" CONFIG["ASMEXT"] = "S" CONFIG["LIBEXT"] = "a" CONFIG["DLEXT2"] = "" CONFIG["DLEXT"] = "so" CONFIG["LDSHAREDXX"] = "$(CXX) -shared" CONFIG["LDSHARED"] = "$(CC) -shared" CONFIG["CCDLFLAGS"] = "-fPIC" CONFIG["STATIC"] = "" CONFIG["ARCH_FLAG"] = "-m64" CONFIG["DLDFLAGS"] = "" CONFIG["ALLOCA"] = "" CONFIG["codesign"] = "" CONFIG["POSTLINK"] = ":" CONFIG["WERRORFLAG"] = "-Werror" CONFIG["CHDIR"] = "cd -P" CONFIG["RMALL"] = "rm -fr" CONFIG["RMDIRS"] = "rmdir --ignore-fail-on-non-empty -p" CONFIG["RMDIR"] = "rmdir --ignore-fail-on-non-empty" CONFIG["CP"] = "cp" CONFIG["RM"] = "rm -f" CONFIG["PKG_CONFIG"] = "" CONFIG["PYTHON"] = "" CONFIG["DOXYGEN"] = "doxygen" CONFIG["DOT"] = "" CONFIG["DTRACE"] = "" CONFIG["MAKEDIRS"] = "/usr/bin/mkdir -p" CONFIG["MKDIR_P"] = "/usr/bin/mkdir -p" CONFIG["INSTALL_DATA"] = "$(INSTALL) -m 644" CONFIG["INSTALL_SCRIPT"] = "$(INSTALL)" CONFIG["INSTALL_PROGRAM"] = "$(INSTALL)" CONFIG["SET_MAKE"] = "" CONFIG["LN_S"] = "ln -s" CONFIG["NM"] = "nm" CONFIG["DLLWRAP"] = "" CONFIG["WINDRES"] = "" CONFIG["OBJCOPY"] = ":" CONFIG["OBJDUMP"] = "objdump" CONFIG["ASFLAGS"] = "" CONFIG["AS"] = "as" CONFIG["AR"] = "ar" CONFIG["RANLIB"] = "ranlib" CONFIG["try_header"] = "" CONFIG["CC_VERSION"] = "$(CC) -v" CONFIG["COUTFLAG"] = "-o " CONFIG["OUTFLAG"] = "-o " CONFIG["CPPOUTFILE"] = "-o conftest.i" CONFIG["GNU_LD"] = "yes" CONFIG["LD"] = "ld" CONFIG["GCC"] = "yes" CONFIG["EGREP"] = "/usr/bin/grep -E" CONFIG["GREP"] = "/usr/bin/grep" CONFIG["CPP"] = "$(CC) -E" CONFIG["CXXFLAGS"] = "-O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection" CONFIG["OBJEXT"] = "o" CONFIG["CPPFLAGS"] = " $(DEFS) $(cppflags)" CONFIG["LDFLAGS"] = "-L. -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -L/opt/alt/openssl/lib64 -L/opt/alt/ruby22/lib64 -Wl,-rpath=/opt/alt/openssl/lib64,-rpath=/opt/alt/ruby22/lib64 -fstack-protector -rdynamic -Wl,-export-dynamic" CONFIG["CFLAGS"] = "-O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -I/opt/alt/openssl/include -fPIC" CONFIG["CXX"] = "g++" CONFIG["CC"] = "gcc" CONFIG["NACL_LIB_PATH"] = "" CONFIG["NACL_SDK_VARIANT"] = "" CONFIG["NACL_SDK_ROOT"] = "" CONFIG["NACL_TOOLCHAIN"] = "" CONFIG["target_os"] = "linux" CONFIG["target_vendor"] = "redhat" CONFIG["target_cpu"] = "x86_64" CONFIG["target"] = "x86_64-redhat-linux-gnu" CONFIG["host_os"] = "linux-gnu" CONFIG["host_vendor"] = "redhat" CONFIG["host_cpu"] = "x86_64" CONFIG["host"] = "x86_64-redhat-linux-gnu" CONFIG["RUBY_VERSION_NAME"] = "$(RUBY_BASE_NAME)-$(ruby_version)" CONFIG["RUBYW_BASE_NAME"] = "rubyw" CONFIG["RUBY_BASE_NAME"] = "ruby" CONFIG["build_os"] = "linux-gnu" CONFIG["build_vendor"] = "redhat" CONFIG["build_cpu"] = "x86_64" CONFIG["build"] = "x86_64-redhat-linux-gnu" CONFIG["RUBY_PROGRAM_VERSION"] = "2.2.10" CONFIG["HAVE_BASERUBY"] = "no" CONFIG["target_alias"] = "" CONFIG["host_alias"] = "x86_64-redhat-linux-gnu" CONFIG["build_alias"] = "x86_64-redhat-linux-gnu" CONFIG["LIBS"] = "-lpthread -ldl -lcrypt -lm " CONFIG["ECHO_T"] = "" CONFIG["ECHO_N"] = "-n" CONFIG["ECHO_C"] = "" CONFIG["DEFS"] = "" CONFIG["mandir"] = "$(DESTDIR)/opt/alt/ruby22/share/man" CONFIG["localedir"] = "$(datarootdir)/locale" CONFIG["libdir"] = "$(exec_prefix)/lib64" CONFIG["psdir"] = "$(docdir)" CONFIG["pdfdir"] = "$(docdir)" CONFIG["dvidir"] = "$(docdir)" CONFIG["htmldir"] = "$(docdir)" CONFIG["infodir"] = "$(DESTDIR)/opt/alt/ruby22/share/info" CONFIG["docdir"] = "$(datarootdir)/doc/$(PACKAGE)" CONFIG["oldincludedir"] = "/usr/include" CONFIG["includedir"] = "$(DESTDIR)/opt/alt/ruby22/include" CONFIG["localstatedir"] = "$(DESTDIR)/var" CONFIG["sharedstatedir"] = "$(DESTDIR)/var/lib" CONFIG["sysconfdir"] = "$(DESTDIR)/etc" CONFIG["datadir"] = "$(DESTDIR)/opt/alt/ruby22/share" CONFIG["datarootdir"] = "$(prefix)/share" CONFIG["libexecdir"] = "$(DESTDIR)/opt/alt/ruby22/libexec" CONFIG["sbindir"] = "$(DESTDIR)/opt/alt/ruby22/sbin" CONFIG["bindir"] = "$(exec_prefix)/bin" CONFIG["exec_prefix"] = "$(DESTDIR)/opt/alt/ruby22" CONFIG["PACKAGE_URL"] = "" CONFIG["PACKAGE_BUGREPORT"] = "" CONFIG["PACKAGE_STRING"] = "" CONFIG["PACKAGE_VERSION"] = "" CONFIG["PACKAGE_TARNAME"] = "" CONFIG["PACKAGE_NAME"] = "" CONFIG["PATH_SEPARATOR"] = ":" CONFIG["SHELL"] = "/bin/sh" CONFIG["archdir"] = "$(rubyarchdir)" CONFIG["topdir"] = File.dirname(__FILE__) MAKEFILE_CONFIG = {} CONFIG.each{|k,v| MAKEFILE_CONFIG[k] = v.dup} def RbConfig::expand(val, config = CONFIG) newval = val.gsub(/\$\$|\$\(([^()]+)\)|\$\{([^{}]+)\}/) { var = $& if !(v = $1 || $2) '$' elsif key = config[v = v[/\A[^:]+(?=(?::(.*?)=(.*))?\z)/]] pat, sub = $1, $2 config[v] = false config[v] = RbConfig::expand(key, config) key = key.gsub(/#{Regexp.quote(pat)}(?=\s|\z)/n) {sub} if pat key else var end } val.replace(newval) unless newval == val val end CONFIG.each_value do |val| RbConfig::expand(val) end # returns the absolute pathname of the ruby command. def RbConfig.ruby File.join( RbConfig::CONFIG["bindir"], RbConfig::CONFIG["ruby_install_name"] + RbConfig::CONFIG["EXEEXT"] ) end end CROSS_COMPILING = nil unless defined? CROSS_COMPILING PK!_͐2.2.0/x86_64-linux/fiddle.sonuȯELF>3@P@8 @(( ЊЊ Њ ( hh h 00888$$ Std Ptdvvv,,QtdRtdЊЊ Њ 00GNUpc_mjŔhrB@(@*4rswx|}~O >=~@v6sqXd>Ĭ 9|}9ҝBE@ Z0Fp`eGc[29uM _ }C+zn0 sl :(FC9];3D`h/{_VUO?| &No &Ds/J~?) MW2bm , F"`URh g nm `>| a== D  < H nW ` H Jr  Lm bX  9 0K?/ ;p `  pK x __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizerb_check_typeddataruby_xfreedlcloserb_string_valuerb_check_safe_objrb_string_value_cstrrb_securedlerrordlsymrb_uint2bigrb_eFiddleErrorrb_raiserb_scan_argsrb_bugdlopenrb_block_given_prb_fix2intrb_yieldrb_ensurerb_num2int__stack_chk_failruby_xcallocrb_cHandlerb_data_typed_object_allocrb_freeze_singleton_classInit_fiddle_handlerb_cObjectmFiddlerb_define_class_underrb_define_alloc_funcrb_define_singleton_methodrb_define_constrb_define_methodint_to_ffi_typeffi_type_sint64ffi_type_uint64ffi_type_floatffi_type_voidffi_type_pointerffi_type_uint8ffi_type_uint16ffi_type_uint32ffi_type_doubleffi_type_sint8ffi_type_sint16ffi_type_sint32rb_eRuntimeErrorvalue_to_genericrb_num2ullrb_num2dblrb_num2uintrb_Integerrb_num2longrb_num2llrb_num2ulonggeneric_to_valuerb_const_getrb_intern2rb_float_newrb_ull2inumrb_funcallrb_ll2inumrb_int2bigmunmapclosure_data_typemmapffi_raw_sizerb_check_typerb_gc_writebarrier_unprotectrb_iv_setffi_prep_cifcallbackffi_prep_closuremprotectrb_sys_failrb_out_of_intrb_iv_getrb_ary_tmp_newrb_ary_pushrb_funcallvInit_fiddle_closurecFiddleClosurerb_fiddle_freerb_fiddle_ptr2valueruby_xreallocruby_xmallocInit_fiddlerb_define_modulerb_eStandardErrorrb_str_new_staticrb_define_module_functionInit_fiddle_functionInit_fiddle_pointerrb_gc_markrb_tainted_str_newrb_obj_classrb_sprintfrb_ary_newrb_fiddle_new_functionrb_cPointerrb_cIOrb_obj_is_kind_ofrb_io_taint_checkrb_io_check_closedrb_io_stdio_filerb_cStringrb_string_value_ptrrb_check_funcallrb_eTypeErrormemcpyrb_tainted_str_new_cstrmemsetfunction_data_typerb_id2symrb_eArgErrorrb_safe_levelffi_call__errno_locationrb_free_tmp_bufferrb_cFalseClassrb_alloc_tmp_bufferrb_cFixnumrb_cFloatrb_cTrueClassrb_cSymbolrb_eSecurityErrorrb_hash_foreachcFiddleFunctionrb_class_new_instancelibruby.so.2.2libdl.so.2libffi.so.6libpthread.so.0libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5GLIBC_2.14GLIBC_2.4/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64 ui @!ui ii ,ui Њ `4؊  4  o  5 p4` Fqp @x A ;uȋ 0RЋ R؋ Q .v0 `d8 d   r   Ȏ Ў ؎      y   # '( *0 -8 0@ H |P 2X 4` 6h 8p 9x  B C G  S U `  fȏ vЏ h؏ i q  ( 0 x8 @ H P  X  `  h  p sx    t      Ȑ А  ؐ ! z " # $ % & ( ) ( +0 ,8 .@ /H P uX 1` 3h 5p 7x : ; < = > ? @ A D Eȑ FБ Hؑ I J K L M N O P Q R( T0 }8 V@ WH XP YX Z` [h \p ]x ^ _ a b c d e g i jȒ kВ lؒ m n o pHHIg HtH5g %g hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?h@hAhBhChDhEhFhGqhHahIQhJAhK1hL!hMhNhOhPhQhRhShThUhVhWqhXahYQhZAh[1%b D%b D% b D%b D%a D%a D%a D%a D%a D%a D%a D%a D%a D%a D%a D%a D%a D%a D%a D%a D%}a D%ua D%ma D%ea D%]a D%Ua D%Ma D%Ea D%=a D%5a D%-a D%%a D%a D%a D% a D%a D%` D%` D%` D%` D%` D%` D%` D%` D%` D%` D%` D%` D%` D%` D%` D%` D%}` D%u` D%m` D%e` D%]` D%U` D%M` D%E` D%=` D%5` D%-` D%%` D%` D%` D% ` D%` D%_ D%_ D%_ D%_ D%_ D%_ D%_ D%_ D%_ D%_ D%_ D%_ D%_ D%_ D%_ D%_ D%}_ D%u_ D%m_ D%e_ D%]_ D%U_ D%M_ D%E_ DH=A_ H:_ H9tHZ Ht H=_ H5 _ H)HHH?HHtH[ HtfD=^ u+UH=[ Ht H=V d^ ]w1HHff.@HH5aV |x HHHЃf.HH51V L@ Hff.HH5V @ Hff.SHH?HtStC uH[YfH[BfUHSHH\$Ht$HUH=HHHHxHHu2Ht-H?H9wHHD[]H`H[]HX HT$H569H81lff.H@HH5T H?H9w HDHHH@ATIH8USH dH%(HD$1H\$LD$Hht#t"H=81H|$L1H HHLH5T H8HHtPuH;HH5^4#H;HdH5G4H;1HH5n4H;1HdH5d4H;1[HH5X4f.Dy1ɃH4HcH>t HmS @HYS HAS HR HIS uHH[H[f.@6HH3[fDH [@Hf[H[@HHH?H'DHth@XHHKfD@8HFH+fDHfZ [f@ fD@H8H(HHiQ H51H81fDATUSHH@tK&H5T HtKHP H89UIăH 1HcH>fKH5L|$LAIL|$L u,I H<@uDHE8Lc|$HT$LLmH5s-JHT$LH5^-H|$H]L}8@w`H|$ HD$@HL$MDLbHK LHLH]H߾0ALEHL$(dH3 %(LH8[]A\A]A^A_D[O@HL$_L` H6K H5[,H81H=`,HK DH5S,H81LAWHAVIAUATUSHHXHt$ H5+HL$dH%(HD$H1HH5+HH}HD$ hHHcAH9DMH5M HD$8HHI H8iHD$E1L}L%+fDHHHE LH<@PIcL>fDIH|$8HfDHA9H\$8HBHH\$8H ~)H5L H[ H~H|$HD%HHD$8HD$@H|$HD$8@/H H+Hc H>fIfZH|$8HEDIH8LH|$8H"f.IH8H@HHt?H|$8fIH|$8Hc0Ht6jDIH|$8H0Ht6I@IH0Ht6렐IH8H?HL?H9H5K HH|$1H|$8HFfDA8IH|$80Ht6DIH|$80Ht6DIH|$80Ht6{fDIH8H?H9HfIH8dH|$8H'fBfDHE fH}H5dJ HHH=a(HH&HL$(HL$(HHI 5fDHH=&HHI kHbHHL$ H?HHD$ )HHL$ HHHD$ fZHHHxHH߃u$HL$ HHH H?ډHDE H5&H81H E H5&H81ff.@HD SH5{&HHCD H8{HdD H5}HHH;HH5$7H;1[H H5$f.@HHtHXHfDH;HÐ@tHHHUHSH@t=HH@tBHHH3H?H9w4HHD[]HxH@uHgHfHH[]2fHHt(HXH?H9w!HDHHfDHHff.H?H9w HD6HSH=$%?HB HQB H5%HHH|HA H;H5$H~H;H5$jH;H5$VH;H5$BH; H5$.H; H5$H; H5$H;H5$H;H5$H;HH5$H; H5$H; H5$H; H5$H;HH5$vH;H5~$bH;H5v$NH;H5m$:H; H5e$&H;H5[$H;H5R$H; H5N$H;H5F$H;H5?$H;H58$H;H52$H;H5.$H;H5)$rH;1H5($aH;H5$MH;H5$9H;H5 $%H; H5$H;H5#H;H5#H; H5#H;H5#H;H5#H;H5#H;H5#H;H5#qH;H5#]H=> H?HT?H9H;H5#/ H=#H;H5#H H;HH5#H;H/? H5#H;HgH5+$H;HH5b#pH;H= H5O#U+V[`;H%1HtHGH(ff.USHHHo tHHHEHH[]fDH8HEHH[]f.HG HxH@Hx HD?SHH5: \H8HHff.fHH59 ,HH@SHH?Ht HCHtH[|ff.SHHHuH{ Hu[@H{ Ht[ff.ATIH5@9 USHH dH%(HD$1H8HHL$1LLD$H!6tQH\$t^Ht$H@tfHH]HHL$dH3 %(H []A\@H|$@t=HHEH8HDfHHt$H@uHHDHH= 10H!; H5 H81AVH58 AUATUHSeHLpLhHL MMHL[H]H=g!A\1A]A^:f.ATIH57 UHSHdH%(HD$1HLHH) 1tCuLH<$@u,H;HcH\$dH3%(u0H[]A\ҐHsH;dH=1ff.@HH56 LH8H?H9w HD?HHGUH56 SH HxHtQH?H\?H9w-HHHHHHߺ[]"fHfDH[]@AWIHAVAUATUSH8dH%(HD$(1HL$LL$HD$ LD$51E1Ld$AIE1t1Hl$HHH9IDHl$ HIHt>LH55 H8HHt H@HtHD$ LmH]HE LeLuH\$(dH3%(H8[]A\A]A^A_fH|$FLl$I9LDtAHHÃE1E1SLIHh,HXfDHD$ ff.fU(HSH4HHj4 HHoHHCHCH[]ÐAVIAUI(ATIUHSH4 LHHL+LcHku HtHуHs []A\A]A^ÀHHH53 11HH6 H8HRfHH53 11HH0H6 H8Hff.@ATUSHHHH6 Ht$H0*HH|$$HhH(H11HH:6 H8H@u1Ht(HUЃHHtHE HXHH[]A\H5 H|$H0|HIt+H|$YHL$H utH1ɃRfDH59 H|$11#HH4Hg5 HH0HH\HODHQ1DHD$HH%H HUDH|$H9D$IDܨt!HHH4 11H8(HyHHH44 H5H81ff.Hq4 SHH0HuHu1[fDHH50 Y[HH3 H5H81ff.AUATIH50 USHH(dH%(HD$1H8Ll$HH1MLD$LHLH$Ld$HAIH|$@u HHc3 H0HHt$@HH]LHHD$HL$dH3 %(H([]A\A]DH$toHH|$HUHD$@hLrHDHLd$HA!LIfDHHH|$H.fDHHH=1H1 H5nH81eDATIUSHHID$ L`t,HH1 HI1H)[]H8A\Zf.HhHATIUSH=HID$ L`t,HH1 LHt1H)[]H8A\fHHUHSHHHHN1 H0Hu 1H[]HHHH9u߸ڐUHSHHHH0 H0Ht.HlHHaH)HtHHH[]ff.ATIH5P- UHSHdH%(HD$1HLHH1WtCuHH<$@u,OH;Hc4H\$dH3%(u,H[]A\ҐH;H=13USHH5, HHHtNHH9HDH] tHHEH[]HHEH[]H@ 1HEH[]fDATHUSH dH%(HD$1HLD$HD$' H$HHl$HHH9HDHl$HIHG1HHjLHHH. H8"HtHP Hj HL$dH3 %(H []A\H$tGHHH1H1HHHH. H8fDHHHHHhI1HD$H=1"fUSHH1 HH-- H1 H5Hz- H}HH- H5HHeH;HH5JH;HH56H;HH5 H;HH5 YH;HH5>H;1HH5 &H;1HH5 H;1HH5H;1HH5H;1HH5NH;1HH5rH;1HbH5]H;1HJH5I~H;1HH54fH;HwH5KH;HH5q0H;1HH5H;HH5H;HNH5H;H3H5H;HH5H;H=H5{H;HH5 vH;HH5G[H;1HH53CH;H$H5(H;111ZH}HH5[H]1H=H. SHHHt*H[!S HHb* H[H&fDHtHHH D1ff.fATIUHSHH=X. Ht#H9u6LHH5[1]A\H=/HH. H* HH5^H81UHAWAVIAUATSHHHuH57HhdH%(HE1HEBH5! LH`,H5}- IH H2) H8HxI} I}HcH99H5( HhHX~I~EHMSHHLDHu HtHփt HH9uύsHcHcHpHHEHHPHHHEHHHEHHH)HH9tHH$H9u%^HD$HHEHEHpHHEC1HHEIEHEh@HEL<HEL$HELL4DEtm(LLLHEL4HH;] LLIE uIE @H-@+LfDIAlA2DCIHA MID$H9xt)H5* HYHxL1ILpIċE`DIhDI:@HEHpH`HHH[HMHXHUH53* HcH\HH% HٺH81AHPHhH5 HuHHMdH3 %(He[A\A]A^A_]@MH& HFIfDH=HHm) H=<oHHM) HHE H= 7HH) HHH9% HH)HLHa$ HH$ HHK% HHD$ H5 H81H# H5{ H81H$ H5 H81Kff.AVAUIH ATUSH0dH%(HD$(1HD$ HPHD$ P1LL$ LD$XZH|$u HD$H|$$HD$H uHxHcH9URH$H5% L{HT$H5%LgHT$H5, LSHT$LH5& ?H|$ HtLH5H5" LIHD$H8 GHxH1KI]fDHHH9~eHHEHl$H $H}H<@qIHHl$HEH uHUH9HH H|$I@HHD$H HHӃHcH9H|$@{MHLHt$(dH34%(LH0[]A\A]A^DHH@H} fHEH[k@HX<;H|H H5H81rH! H5H81X#H(dH%(HD$1H9! HT$H<$HHt$HHL$dH3 %(uH(fHE SH5HHs H8H H5HHH; H5TH;H5H;HkH5*?H;[HH5#HHunknown symbol "%li "02rb_fiddle_handle_new%sclosed handleHandlesym[]NEXTDEFAULTRTLD_GLOBALRTLD_LAZYRTLD_NOWinitializeto_idisable_closeenable_closeclose_enabled?fiddle/handledlclose() called too many timesunknown type %dPointert,Dd h`21@ctype@argserror prepping CIF %dmprotecterror prepping closure %dclosure args: %dcallclosure retval: %dClosurefiddle/closureh ``87L `LjL!FiddleDLErrorTYPE_VOIDTYPE_VOIDPTYPE_CHARTYPE_SHORTTYPE_INTTYPE_LONGTYPE_LONG_LONGTYPE_FLOATTYPE_DOUBLETYPE_SIZE_TTYPE_SSIZE_TTYPE_PTRDIFF_TTYPE_INTPTR_TTYPE_UINTPTR_TALIGN_VOIDPALIGN_CHARALIGN_SHORTALIGN_INTALIGN_LONGALIGN_LONG_LONGALIGN_FLOATALIGN_DOUBLEALIGN_SIZE_TALIGN_SSIZE_TALIGN_PTRDIFF_TALIGN_INTPTR_TALIGN_UINTPTR_TWINDOWSSIZEOF_VOIDPSIZEOF_CHARSIZEOF_SHORTSIZEOF_INTSIZEOF_LONGSIZEOF_LONG_LONGSIZEOF_FLOATSIZEOF_DOUBLESIZEOF_SIZE_TSIZEOF_SSIZE_TSIZEOF_PTRDIFF_TSIZEOF_INTPTR_TSIZEOF_UINTPTR_TRUBY_FREEx86_64-linuxBUILD_RUBY_PLATFORMdlwrapdlunwrapreallocfreeNULL pointer dereference11rb_fiddle_ptr_aref()01rb_fiddle_ptr_to_str12Fiddle::Pointer was expectedrb_fiddle_ptr_aset()rb_fiddle_ptr_to_srb_fiddle_ptr_s_mallocto_ptrfree=to_intto_value+@ref-@null?inspect<=>==eql?+-[]=sizesize=NULLfiddle/pointer#<%li :%p ptr=%p size=%ld free=%p>to_ptr should return a Fiddle::Pointer object@nameunknown keyword: %li @ptrtainted parameter not allowedlast_error=@return_type31:@abierror creating CIF %dFunctionSTDCALLfiddle/functionnumber of arguments is so large that it can cause integer overflow (%d)wrong number of arguments (%d for %d)args is so large that it can cause integer overflow (%d);,D0Hpн0p <0Ppp`08Pp00LplH@h  (@<p@$`@4 \  @ $ ` P p @ 0 p  0 p\  0 zRx $FJ w?:*3$"D\p&HW%H\,%H\D>E] N I4dADD0d FAD L AAA ܻ$ػ<Hd D G0DFKA D@  AABG xAE{ tAG O AH DmEo A ?E] E L `@$XHl D M K Q G K E L D K E  C hFAA G0  AABM D  DABE W  DABJ [  AABI l  LCBK O  FABH D  DABM t DAB-Ec 9Hg A D$@aEND DDAhD#MMH\FBL B(A0A8Dp 8A0A(B BBBF LFEE B(A0A8G1 8A0A(B BBBJ prLS<?HY G V\ 0p~EDD s FAI dDAHTHh H W( mEV E 0FEAG W DAG PDAD-X4#HWpLHST$EZh4EV E O0-FKA I@  AABE 8VFIB A(D0h(D IDB04FKF D0e  AABD h49Hg A D0T|EHD { LAG TFAHFLB B(A0C8Dp 8A0A(B BBBJ $OEND uAA<0,xBJJ D(D0J (A BBBA pl.Ha1Hd0FAA J0  DABH THY G P D 8FBK A(IP (A ABBF (4]FDA p AEO (`]FDA q AEN (OEDJ Z AAA $dEDJ KDA0\FKF D0e  AABD < EAN u FAH P FAA RFA0T (~FHA D@  AABI ( t=EAD  HDF  EU *E] #MI( xFDD l CBA ,0 EC DH E L` |FBL A(A0D`YhFpRhA` 0A(A BBBF  LWH0I A  LyGNU`4 4 o 5p4Fq@A;u0RRQ.v`dd6 ( oЊ ؊ o`  c  `p opoo\oh 0(@(P(`(p((((((((()) )0)@)P)`)p)))))))))** *0*@*P*`*p*********++ +0+@+P+`+p+++++++++,, ,0,@,P,`,p,,,,,,,,,-- -0-@-P-`-p--------GA$3a1(-o GA$3p1067p4oGA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA$3p1067;]dGA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFYp4dGA+GLIBCXX_ASSERTIONSfiddle.so-2.2.10-35.el8.x86_64.debug5n<7zXZִF!t/]?Eh=ڊ2N+ /2\IPأ;Jo/Oz9-Fb/wJKv(Xz:` [ Ugg)B˭ 3)e?[8χWꊃ`^xL*sZ 2dGF*dw#Q'8_eX|Ρo'|j̫lGJT tY  B%k:ק^TMioUYpX3M,͂r3LF Ќ@ʽl]'Nbh3*0 0};8%B {; Qu ,^XdqbZSHDxpG>R0vRt`! I$VRѭBN,`)"n#_;bp1c$H8-`#-@m6~e{]M=5zl|(OHv) )sY%U6*1|p5y3>#!ڶ4BUTa>⿙}U8t"0{# Kg\}2}xe%ieYX%-D,·YUH\R=mX}A: bTݘpmR0QG7TАY2Œ(_"󓙋KQ۝W[yu}4auеÀچܳol_p_+56T(4P")3CyJrQ ַ`&&0YYbq$#c43n9@u*@SSٕdq(\:@qΖ%*}}|*0dжpԖ B\W#b8/^}8ҔRf]:flrPk;F%w ݅Nx$X]{rtK@!D%>lKO b(^s*DQ  I[ *幊 0\fɠp#V'ST5 J*(~י1ns /R)RBoTK}#Y_sxL_s޽K!u*rxJ1*apH 2 ^gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``(    0c8o\\EoppTp^B``h((c ( (n--w33m;} o o 0o0ovv, y y  Њ Њ؊ ؊  h h0 P  ` ,@$+PK!82.2.0/x86_64-linux/psych.sonuȯELF>,@X}@8 @pbpb ll l ` hmhm hm 00888$$PbPbPb StdPbPbPb PtdHYHYHYQtdRtdll l ppGNUj:krDe3tC^ BL0H ^fix BE"aj |SE6 ZqXH8 x<ub4  XH-FwvU2jW  qSC^J!d2C, Eu`F"#UU R%r  0V P>Z8t @t 8Xt  CN BtPt ,r Ht h(t 80t __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizerb_check_typeddatacPsychParserrb_const_get_atrb_class_new_instancerb_intern2__stack_chk_failyaml_parser_deleteruby_xfreerb_funcallrb_funcallv_publicrb_string_value_ptrmemcpyrb_utf8_encindexrb_default_internal_encodingrb_iv_getrb_scan_argsyaml_parser_initializerb_respond_torb_to_encoding_indexrb_usascii_encindexrb_enc_find_indexrb_ascii8bit_encindexyaml_parser_set_encodingyaml_parser_set_inputrb_cIOrb_obj_is_kind_ofrb_string_valuerb_enc_get_indexrb_utf8_encodingrb_str_export_to_encyaml_parser_set_input_stringyaml_parser_parserb_str_new_cstrrb_enc_associate_indexrb_protectyaml_event_deleterb_jump_tagrb_str_newrb_ary_newrb_ary_new_from_argsrb_ary_pushrb_str_new_staticrb_usascii_str_new_cstrePsychSyntaxErrorrb_exc_raiseruby_xmallocrb_data_typed_object_allocInit_psych_parsermPsychrb_cObjectrb_define_class_underrb_define_alloc_funcrb_define_constrb_requirerb_const_getrb_define_methodrb_internrb_attr_getInit_psych_yaml_treerb_define_modulerb_define_module_undercPsychVisitorsYamlTreerb_define_private_methodyaml_get_versionrb_ary_new_from_valuesInit_psychrb_define_singleton_methodInit_psych_emitterInit_psych_to_rubyyaml_emitter_deleteyaml_emitter_set_canonicalyaml_emitter_initializeyaml_emitter_set_unicodeyaml_emitter_set_indentyaml_emitter_emitrb_eRuntimeErrorrb_raiseyaml_alias_event_initializerb_check_typeyaml_mapping_end_event_initializeyaml_sequence_end_event_initializeyaml_document_end_event_initializeyaml_stream_end_event_initializerb_fix2intyaml_emitter_set_widthrb_num2intyaml_stream_start_event_initializeyaml_mapping_start_event_initializeyaml_sequence_start_event_initializeyaml_scalar_event_initializeyaml_emitter_set_outputyaml_document_start_event_initializerb_ary_entryruby_xcallocrb_gc_writebarrier_unprotectcPsychEmitterrb_path_to_classrb_obj_allocrb_iv_setcPsychVisitorsToRubylibruby.so.2.2libyaml-0.so.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5GLIBC_2.14GLIBC_2.4/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ui =Iii Tl @-l -l l l Xl  . m Y0m pDo  o  o io )o go bo co jo :o Ko Qo ko Vp  p (p 0p 8p @p Hp Pp Xp  `p  hp  pp xp p p p ^p p p p p p p p p p p p fp `q q q q  q !(q "0q #8q $@q aHq %Pq &Xq '`q (hq *pq +xq ,q -q .q /q 0q 1q 2q 3q 4q 5q 6q 7q 8q 9q ;q <q =r >r ?r @r A r B(r C0r D8r E@r FHr GPr HXr I`r Jhr Lpr Mxr Nr Or Pr Rr Sr Tr Ur Vr Wr Xr Yr Zr [r \r ]HHN HtH5N %N hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?h@hAhBhChDhEhFhGqhHahIQhJAhK1hL!hMhNhOhPhQhRhShThUhVhWqhXahYQhZA%-I D%%I D%I D%I D% I D%I D%H D%H D%H D%H D%H D%H D%H D%H D%H D%H D%H D%H D%H D%H D%H D%H D%}H D%uH D%mH D%eH D%]H D%UH D%MH D%EH D%=H D%5H D%-H D%%H D%H D%H D% H D%H D%G D%G D%G D%G D%G D%G D%G D%G D%G D%G D%G D%G D%G D%G D%G D%G D%}G D%uG D%mG D%eG D%]G D%UG D%MG D%EG D%=G D%5G D%-G D%%G D%G D%G D% G D%G D%F D%F D%F D%F D%F D%F D%F D%F D%F D%F D%F D%F D%F D%F D%F D%F D%}F D%uF D%mF D%eF D%]F DH=YF HRF H9tHB Ht H=)F H5"F H)HHH?HHtHB HtfD=E u+UH=B Ht H=~? dE ]wSH5d? H dH%(HD$1H5E HHtlHEB H8]HcHHHL H $HcHL HL$HcHL HL$KHT$dH3%(u+H [DH=(?HHD tKff.SHH[f.H5uE 11ff.H5eE 11ff.H5D 11ff.H5D 11ff.HOH5D 1H?fHOH5D 1H?rfHOH5D 1H?RfHOH5YD H?@HOH5ID H?@HOH51D H?@HOH5)D H?@UHcHSHHLHH5D dH%(HD$1HH$Hu&Ht$dH34%(uGH[]f.HH $H uHHHHgDHQDAWAVAUATIUSHH(HT$8dH%(H$1D$TD$HH5P&H\$XINLD$`HLH$H6&13 H|$8H5; %IH LH|$X1ɉL$@u H1H5B 8H5A Hl$XH 11HH H}9N 9A H=%u9tH=%`9t1LHl$XSHT$XH5LH> H|$XH0HDD$D$fHHD$XHD$hyH=$H=$H|$hA9 91 A9 H|$hHHT$hHD$hHT$pHT$hLHD$XHD$XH ^HHpLHD$TL|$pHD$H$HA%HD$LL5A |$p 7D$pHcH>@H|$xAHt?[T$Iątu Ht$LMtLLIH$HtF HŋD$t@uH@t$HMtHLHŃ$Hc$L$H=JHH $Ht$H$HHTH$HT$H$H$@HT$H4$H=x[L3|$TbfH|$xAHt?t$Iątu H,t$LMtLLIH$HtFL$HŅtuH2t$HLMtHL|HŃ$Hc$L$H=*HH $Ht$H$HHTH$HT$H$H$fH$H$;DL$HEt.u*Ht"HƒHft$HtMtHLHH|$xHtKDD$HEtu H t$HHL$ MHL$ tHLJHH$AHtbHL$ :|$HL$ IątuHcf.t$LHL$ MHL$ tLLHL$ Iă$Hc$H$HH<$H$HHt6L$$H$H=qHH$HT$HH$Ht$H$H|$xHtHLDT$HEtuH t$HMtHLHH$H$H=6HT$Ht$H$H4$HT$TH=L|$TxH$dH3 %(HD$8H([]A\A]A^A_ÐH$HT$H=Ht$H$HcD$xHDH$@H$|$xH=Ht$H$HEHT$H$sHD$ HD$xHHcPHc01HTHt6SHD$0H$HH$$H=Ht$H$HD$0H$HD$ H$HEHT$H$HT$H4$H=0HT$H4$H=8HHDD$DH$H9BLt$@Dt$L|$HIDH}AHtXIEt,u(Ht HƒI$t$LDMtLLtIH}Ht\nHEt&u"HtHHt$HHT$(MHT$(tHL HL1HH|$ HI9Lt$@L|$H"CHD$0ffDH@HI;@HPHpH58 H|$XB1H58 H|$X115HD$`H=HH7 HƒHEHEƒHEHƒI$HƒI$HƒI$=HƒHEHƒHHEhHD$h- H=HD$`hHD$hHD$hH@H@H @@H@HA@HAf@HHD$`I~8AH$IFHHXIFPHhHtII~AHtIIcFHcHcHl-H\LlH]5 HtMHHIIH<2 ATAWAUHL$ H81H LH#L+H#H=6BH4 T@UHSHIHHHHH[H|. ]6fDUH5SHH-`1 H11 H}HHN1 H5HHH;H5H;H5H;H5xH;H5llH=hH54 HpH}H0 H;H5SHH'bH;1HH57JH#4 HH4 H4 HHd4 H3 H\HE4 H3 H%H&4 H3 HH4 H3 HH3 Hi3 HH3 HJ3 HIH3 H+3 HH3 H 3 HHl3 H2 HHM3 H2 HtqH23 H2 Ht.H3 H[]þ H=HH2 p H=\Hh2 H2 H[]f. H=oH@2 r H=OH(2 ?H=/H2 H=H1 H=uH1  H=HH1 cH=H1 , H=H1  H=oH1 H=OHh1 H=v/HP1 PH=QH81 SHHH|$HT$uHHH2H[ff.SH=H5H H5HH, HHtHH5HbH, H5HHHR[f.fH8dH%(HD$(1HT$ Ht$H|$HcD$Ht$HDHD$HcD$HDHD$HcD$ HDHD$ HL$(dH3 %(uH8ff.HH=H, 1H5HHH?eHfHH51) HcHHDff.HH5) HcHHDff.HH5( x|HHHЃf.SHH[:f.SHH5( l1HH@H[DUHSHHHH߾H߾HHH[H( ]lff.SHWt[H* HSH5>H81DATUSHHĀHt$H5' dH%(HD$x1H|$IHu:1Hl$H#HLxHHT$xdH3%(uCH[]A\@yH|$HHD$HtH|$H]ff.fATH5' USHHpdH%(HD$h1HHIHLHT$hdH3%(u HpH[]A\ff.ATH5& USHHpdH%(HD$h1HbHI'HL\HT$hdH3%(u HpH[]A\{ff.ATUHH5& SHHpdH%(HD$h11HH@IH{HLHT$hdH3%(u HpH[]A\ff.@ATH5% USHHpdH%(HD$h1HrHIHLlHT$hdH3%(u HpH[]A\ff.USHH50% HHHtgHHH[]USHH5$ HHHtHmHH[]SHHHH5+ HߺH1HǨt [fD;[fATUHSHH5;$ HpdH%(HD$h1H߾IrH߃t:UHHHLHHT$hdH3%(uHp[]A\ÐfAWAVAUATIUHSLHHt$H5# H$dH%(HD$x1mIH|$IHtH|$LHD$H<$HtH<$L{H$H߃fE1MAE1H<$t HI1H|$t H|$HLd$LADLLLHHT$xdH3%(u&HĈ[]A\A]A^A_kpff.@AWAVAUATIUHSLHHt$H$dH%(HD$x1dH|$IHt|H|$L_HD$H<$HtVH<$L:H$HH5! H߃IE1MAE1H<$t HUI1H|$t H|$>HLd$LADLELLjHHT$xdH3%(u#HĈ[]A\A]A^A_Dsoff.@AWAVMAUMATUHSHHT$ H$HL$Ht$(H5 dH%(H$1H|$(IH|$(HIH|$ HD$(HtH|$ LHD$ H|$HtH|$LHD$H߃HD$(MAMLAEEA IDD$H|$(1H|$HtH|$HD$HL$H1H|$ t!H|$ HL$HT$jHL$HT$HL|$0SEAVDD$LXLZLHH$dH3%(u.HĨ[]A\A]A^A_Ë@D$N@+ff.@AVAUIH5 ATAHUSHH dH%(HD$1HL$LDHLD$H1tBHT$H5&H~HHL$dH3 %(H []A\A]A^f.H5% H|$11H5d% H|$1I1H|$H5?% 1I1LAIu?HLAt7rH1IH@&/K"fAWIH5 AVAUATUSHHH|$0HL$8dH%(H$1LHD$(I HD$ 1HIE1H|$8A IL|$ HHt$HH\$PHDHL H|$(HMtLH$dH3 %(HD$0H[]A\A]A^A_DIB1LFLI6LAHaHD$HD$L{H߾IH; |HE1XHD$ HHCHD$HD$@HD$HD$PHD$fDHL9HHH 0HD$N4LI HH,LLI yIVHLHT$@eLI PIFHH|$@LHIHD$PoH|$PLHD$@]H|$HD$PH|$HEHEH HCHD$HJEH{I~HC fIF H2fDsIV H|$ H  H5H81hsSH=DH5HH HHHH5HHr H5HHHH;HH5R-H;H^H5H;1HH5 H;HH5H;H0H5H;H%H5H;HH5H;1HrH5vH;H7H5[H;1HH5CH;HH5^(H;1HH5@H;HH5/H;1HiH5"H;HnH5H;1HH5H;HH5H HtKH  H HH H HtiH H Ht.H [DH=H fD H=7[HW Hp  H=$H8 z H=oH  GH$@UHHSH;HH5HH&HH[]ff.ATH=US\H-U H5HHHUHH5IMHUH5HHHH5HH H5~HHH50[L]HH5dA\HHMark@handler11external_encodingUTF-16LEUTF-16BEnewParserANYUTF8UTF16LEUTF16BEpsych/syntax_errorSyntaxErrorparsemarkreadpathemptystart_streamend_streamstart_documentend_documentaliasscalarstart_sequenceend_sequencestart_mappingend_mappingPsych/parser d$ L<$PsychVisitorsVisitorYAMLTreeprivate_iv_getlibyaml_version%stag tuple must be of length 2HandlerEmitterinitializecanonicalcanonical=indentationindentation=line_widthline_width=writePsych/emittermesgClassLoaderToRubybuild_exceptionpath2class;0 (<8PXdxx8X088HTp(Hx4h8(8d8h0$pzRx $(FJ w?:*3$"D \EK0 AF EL(<(P4d@(xLEGQ0F AAK ` FBB B(D0C8J 8A0A(B BBBB RGBS$,:EID TGH80DEHD   AAA C AAK l4EG fAtEjxH@t A NHA %HW8%HWP&HW,hELHl+Ee$dTEID nGH+AM A 0FAA G`  AABE 0XeFHA GB  DABA 0eFHA GB  DABA 0DqFAK GK  DABA 0xeFHA GB  DABA (XIEAN c DAD (|IEAN c DAD GEt G F0$FAD Na  AABB HX,AFBB B(D0D8J 8A0A(B BBBI L0AFBB B(D0D8J 8A0A(B BBBF \0FBE E(A0D8G[ENDe 8A0A(B BBBA @TNFBL G(A0GPj 0A(A BBBK HFLB B(A0A8J 8A0A(B BBBF $0E] F r V   $ 4EGD ^DA(H FHA DUGNU@--l X .YpD^ Vl l o`   p p oPootohm 0!@!P!`!p!!!!!!!!!"" "0"@"P"`"p"""""""""## #0#@#P#`#p#########$$ $0$@$P$`$p$$$$$$$$$%% %0%@%P%`%p%%%%%%%%%&& &0&@&P&`&p&&&&&&&GA$3a1 V GA$3p1067P-VGA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA$3p1067@BUGA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFYP-UGA+GLIBCXX_ASSERTIONSpsych.so-2.2.10-35.el8.x86_64.debugCfE7zXZִF!t/']?Eh=ڊ2NH bj}q`7GFy#D%0O1qk\T?EyS,Vet'PUK0_zICGEH,1 ) .5N>%훿$tݝNRձ"^0~<}ǣrlh@%=[]kWRCeLJ:/^6`filc-PZZd(@aPbc6[_6~'Թq%9axJ ^Oe>c"q;㋒טW`.Rj^wU0±UDq3kN> SV !Ue50 tUjLĪ^V-D`Ê@w.U6|qC60K\c[^~Ǹqkk'nv ޝتl |@=0ayiNOPo.mGA;O NH0;4{/e#X̾Oز8CZy;%]FbXeSQE:*'xK15ln0`3{W(\oqrFzw 1#v;.,HzIiLQ5C<%(7}YGmUco=R[ NM1 \ 5fn1ģ&w^lI$p"ri?ㆻ5O3廲49RjԸ;1ir-&?WLWN/}Ds4v))g=ab+: ^cݿ 5Ԍ/ߒ3aYr Fw) *uHhꄐWNׂ`d4Z508(#SB;e>WĽMD'zJ0Ya_ٟ^H+jD!DbeڡN #Ϥ*Z1 @Wnr~$у{ehg2gLRlB`?xVAAdpZ3Xx vs r/CU7*Ei8xP0@oN:f2m-MEߵ5قeD3 !\oVV:yLXCZrCS.9PD|EQ .]k9BTe#;٩ "'gfPt͠ek<0 Qsf (:-2/gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``d(  0 8ottEoPP@T^Bpph c ! !n&&w,,O*}VV VVWHYHYZZtPbPb l ll ll l hm hm0o ohp pr rhXt`r  w(4w,|+PK!FH!!2.2.0/x86_64-linux/date_core.sonuȯELF>S@h@8 @XX ""h* PP"P"  888$$888 Std888 PtdQtdRtd""GNU›!ᝨCtSv+ @DDBEN#YN|@b/EC2,OqX[,xjד#l2{="?iM mJS$U6'=ZU0C%>{_^UL vT|ko23%#oZK , F"`mmkbx3x#n CA ETF# +f . 2 G^ CT  :x#| @Ay k0P E^ У__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizerb_funcallrb_intern2rb_rational_newrb_check_typeddata__stack_chk_failstrlen__errno_locationdate_strftimeruby_xmallocruby_xfreerb_sys_failrb_id2symrb_hash_arefrb_hash_asetrb_hash_deleterb_fix2intrb_num2intdate__jisx0301date__httpdatedate__rfc2822date__xmlschemadate__rfc3339date__iso8601rb_ary_new_caparb_usascii_str_new_cstrrb_obj_freezerb_ary_pushrb_gc_markrb_rational_denrb_rational_numrb_gc_writebarrier_incrementalrb_gc_writebarrier_generationalrb_scan_argsrb_string_valuerb_enc_getrb_enc_dummy_prb_hash_newdate__strptimerb_enc_copyrb_eArgErrorrb_raiserb_error_frozen_objectdate__parsememchrrb_str_new_staticrb_str_catrb_str_newrb_usascii_str_newrb_num2dblrb_warningrb_usascii_str_new_staticrb_f_sprintfrb_str_appendrb_float_valueroundrb_float_newrb_usascii_encodingrb_enc_sprintfrb_cRationalrb_obj_is_kind_ofrb_cNumericdate_zone_to_diffrb_eTypeErrorruby_xcallocrb_data_typed_object_alloctzsetlocaltime_rclock_gettimerb_int2bigrb_gc_writebarrier_unprotectrb_copy_generic_ivarrb_marshal_loadrb_obj_classrb_obj_classnamerb_num_coerce_cmprb_ary_new_from_argsrb_memhashmodfrb_block_given_prb_yieldrb_frame_this_funcrb_enumeratorize_with_sizeabortrb_out_of_intrb_gc_register_mark_objectrb_sym2idrb_cTimeInit_date_corerb_cObjectrb_define_classrb_mComparablerb_include_modulerb_define_constrb_define_alloc_funcrb_define_singleton_methodrb_define_methodrb_define_private_methodrb_undef_methodrb_cFalseClassrb_cFixnumrb_cNilClassrb_cFloatrb_cTrueClassrb_cSymbol__ctype_b_locrb_str_to_inumrb_reg_nth_matchstrncasecmprb_num2longrb_reg_newstrspnmemcpyrb_cstr_to_inum__ctype_tolower_locrb_str_new_cstrstrchrstrpbrkstrcpyrb_backref_getrb_match_busyrb_str_duprb_backref_setstrncmprb_internrb_uint2bigrb_islowerrb_toupperstrtoulruby_snprintfrb_tolowerrb_isupperrb_str_formatrb_string_value_cstrstrlcpymemmovememsetlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5GLIBC_2.3GLIBC_2.14GLIBC_2.4GLIBC_2.17/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64 ui K ui K)ii Waii lvui K"0T"S " "@"xH"plX"T""ގ"""""" "0"@"P"`"p"ą"Ñ" """"Ʌ""""^"Q "\0"@"UP"`"!p"""""C"p"k"" "" "0"@"P"#`"(p"","0"5"9">"C"G"K"P"T "L0"9@"YP"^`"bp"f"j"n"s"w"{""""" "0"@"P"`"p"""""""ď"ȏ"͏"я"Տ "ڏ0":@"P"ޏ`"p""""""""""W"" ".0":@"AP"P`"[p"d"s"k""""H""""̐ "ِ0"@"БP"`"p"" """$"("1"7"<"F"L "S0"B@"`P"h`"xp"~"""""ۑ""ő"͑"ؑ" "0"@"P" `"p"#"*"3"9"/"?"K"W"d"v" "0"@"H"P"dX"`"h"p"x"""""Ò"""ǒ"˒"ϒ"Ӓ"ג"F"""""" "("0"8"@"lH"P"X"`"h"Ċp"̊x"Պ"\"`"d"h"l"p"t"x"|""""#"*"1"9"C"L"S" " ("0"8"@"H" #(# 0#8#@#H#P#`##h#*p#1x#9#C#L#S#\#`#d#h#l#p#t#x#|###(#0#8#@#H#lP#X#`#h#p#Ċx#̊#Պ#0;#}#p#0#####p###p##U# # #`(#p"x""""""#"D"N"W"^"q"s"u"w"}"# #(#0#8#@#H#P# X# `# h# p# x############### #!##"##$#% #&(#'0#(8#)@#*H#+P#,X#-`#.h#/p#0x#1#2#3#4#5#6#7#8#9#:##;#<#=#>#?#@##A#B#C #E(#F0#G8#H@#IH#JP#KX#L`#Mh#Op#Px#Q#R#S#T#U#V##X#Y#Z#[#\#]##_##`#a#b#c#d #e(#f0#g8#h@#iH#jP#kX#l`#mh#np#ox#p#r###t#u#v#x#y#z#{#|#~###HHѻ"HtH5"%"hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?h@hAhBhChDhEhFhGqhHahIQhJAhK1hL!hMhNhOhPhQhRhShThUhVhWqhXahYQhZAh[1h\!h]h^h_h`hahbhchdhehfhgqhhahiQhjAhk1hl!hmhnhohphqhrhshthuhvhwqhxahyQhzAh{1%M"D%E"D%="D%5"D%-"D%%"D%"D%"D% "D%"D%"D%"D%"D%"D%ݳ"D%ճ"D%ͳ"D%ų"D%"D%"D%"D%"D%"D%"D%"D%"D%}"D%u"D%m"D%e"D%]"D%U"D%M"D%E"D%="D%5"D%-"D%%"D%"D%"D% "D%"D%"D%"D%"D%"D%ݲ"D%ղ"D%Ͳ"D%Ų"D%"D%"D%"D%"D%"D%"D%"D%"D%}"D%u"D%m"D%e"D%]"D%U"D%M"D%E"D%="D%5"D%-"D%%"D%"D%"D% "D%"D%"D%"D%"D%"D%ݱ"D%ձ"D%ͱ"D%ű"D%"D%"D%"D%"D%"D%"D%"D%"D%}"D%u"D%m"D%e"D%]"D%U"D%M"D%E"D%="D%5"D%-"D%%"D%"D%"D% "D%"D%"D%"D%"D%"D%ݰ"D%հ"D%Ͱ"D%Ű"D%"D%"D%"D%"D%"D%"D%"D%"D%}"D%u"DH="H"H9tHޫ"Ht H="H5"H)HHH?HHtH"HtfD=}"u+UH=ҫ"Ht H="dU"]wGHF<HB<HЉ91A0Aw ;w;v1@u1 fD7@u>G, iƒ??k<+G x =QOƒG7fQf%HHH0fDH@uJH5S"SHHtH߹5w1[DH=/HH"5wfDtHGHfH5e"SHHtH11[_H=/H1[HH'"10@t@uH<1HHH9HM@t@uTUHSHHH5"HtHHHߺ[1]@H=#3oHH"HHH9HE@uJH5"SHHtH߹1[EDH=-HHU"VfDSHH5!"HHr"HC[ff.HH5"tHxHD ~%6f55*^5f(fTf(f.v3H,f=5fUH*f(f(fT\fV5f(Yf(fTf.v5H,ffUDd5H*f(fAT\f(fVՁlf-C5*Y ?5\f(Xf(fTf.v5H,ffUD4H*f(f(fAT\fVʃff(*Y4f(fTf.v3H,f=4fUH*f(f(fT\fVXfҸ*XX\ 4f/v\1A,Ðf*f/5&4~-4F4.4f(Xf(\ B4^f(fTf.v5H,ffUD3H*f(f(fAT\fVYf(f(fTf.v5H,ffUD3H*f(f(fAT\fVf(3f(\f(^f(fTf.v8H,ffUD 03H*fD(Df(fETA\fVYf(f(f(fTf.v3H,f=2fUH*f(fT\fVf(\2f/f(r#\2\ 2,,,‰\\ 2f\ 2~-@35X2f(^2f(f(fTf.v3H,f%12fUH*f(fT\f(fV2f(Yf(fTf.v3H,f=1fUH*f(f(fT\fV؃f*X\ff.AWAVAUMATAUSHHHL$L$Lt$4LD$D$dH%(HD$81F H؅DL$LDMfA(LT$L\$LA}LLD9d$4t*1HT$8dH3%(HH[]A\A]A^A_DA9uѸA9*tAHD$0T$,HD$ DtHMMAWHL$0DD$ZYtϋl$,A}LHL$HT$D$D9d$4=HD$90HD$(fAWAAVIAUIATUSH(D$Ld$Hl$dH%(HD$1 ft/HHMAUD$MDZYtθHL$dH3 %(uH([]A\A]A^A_DAUMATIUSH(dH%(HD$1HT$Ht$D$'|$L$xp$I))Љ)ƒ)f)ǍD=*A$1f/AEHD$dH3%(u9H([]A\A]fD%I$щ)))ȍPff.AVAAUMATMUSH dH%(HD$1HT$Ht$D$2D$L$pD)|kJ%I$)))ʍ)f)T1*A$f/AEHD$dH3%(u8H []A\A]A^ù)Ѻ%I$)))ȍPAUIAfD(ATLAULSHH(dH%(HD$1HL$ HT$HT$Ht$A9fA()D$pD)|xJ%I$))))BL"x}Ⱥ$I4 )ƍ))3MHD$dH3%(H([]A\A]@)Ѻ%I$)))ȍP)BL"yѺ$Iȉ)ֺ%I$ȃ)))ȍHcfDAWf(AAVMAUATAUSӃHHLL$L$L$dH%(HD$81HD$(HH$f(MML$DډD4LD$LDL$H$A}f(1D9|$(t)Ht$8dH34%(HH[]A\A]A^A_fDA9.uHD$9@ʍLL$$LD$4L\$D$L$H$D<HL$,)f(LD$0|$4g1D9|$(L$L\$Vl$,AAWfD(AVIAUATAUHSHHHD$HL$,HT$(dH%(HD$81Ht$$DDl$$LT$4LL$0MLfA(ºE}LT$DLL$D$0LL$LT$D9E>D)Ⱥ%I$)MAA%I$DD))D)…ҸDЉHD$8dH3%(HH[]A\A]A^A_fD$LMD"E.D+L$0WѺ$I)щMAW%I$D))))ȍPPff.AWf(MAVIAUATAUSӃHHdH4%(Ht$81H$Ll$(HڅILɉLL$f(DL$CLL$LLL$LA9f(1D9d$(t*Ht$8dH34%(HH[]A\A]A^A_A9.u1A9ǐHL$4LD$$HD$LL$D$L$HL$0L<HT$,)f(|$4+D9d$(L$LL$HD$t 1SDl$,:f.UHIfD(SH(dH%(HD$1HL$ HT$NHT$Ht$A8fA(g+\$]HD$dH3%(uH([]AVIAUATIUHSHHHu 1[]A\A]A^ÐIH}LLdHHuHE8tMI fHH%LLHHEH}lHuH}I9wL;"kDAWAVAUATUSHHH=8"HHHHHH="HRHHHH5ѥ"HhH1%HIƺ1H5"HHH!1q%H!IǺ1UH5>"HHHy1.%HyIź1H5"HH?H1H%I1L{JHž+1H="IH[HLHH=^"H}8HLHH=3"H:HLHH="HHLHH=ݣ"HHHHH="HtuHHHH[]A\A]A^A_H+H1H5"HHAH=_HH"H=F?HH"kH=; HH",H=}HH"H=HHբ"H=HH"cH=HH" H=HH"H=i_HHu">H=I?HH]"H=)HHE"xH=HH5"H@t1H@sHff.H4@HD@HD@H4@H@H$@AUATUHSHL,HI@H;Ht.HHsHLHL9uLWHL[]A\A]fUSHH-"@uMH5."HHtHHHߺ[1]fDH=HH"HH[]fSHHt H{[SHuHt t H[HtHHuH[f.UHSH@u HHu HH[]cuHE`H`uH`H`tHH;fAWf(AVAUATAUHSHHHL$dH%(HD$81Lt$4Ll$0L|$$f(LHD $EfL $HL$LD*E1f/f(}1D;d$$t)H\$8dH3%(HH[]A\A]A^A_fD19\$0DHD$(ALt$4HD$HD$,Ll$0HD$ fAAtaHLf(Dt$LL$(MD L$iZY $t\$(L|$$f(LL $ D;d$$t 1-fD $\$0DAVAUATUHH.SH dH%(HD$1Ld$Ll$MLcLH|$xSH|$H9HD$H0 AL`LpGH`ILHLILH!HH=p"Hg2HH7H=H"IHdHHHItCHt$LnAu IH="HLHHHtCHt$H%@u HH="H}HHH?HL$dH3 %(H H []A\A]A^HL`ILH|$OxH|$;HcHD$L(A uZIHhAlfH=HH"yH=HH"|HhLhHUЃHD$HH%H HUI$ЃHD$6H*H%H I$H= HH"H=HH"'fDH@HFHM"H5VH81GH0"H5iH81ff.@HUHMATUSHHHƒIH9tNH5}"HH5}"LH€t5EtVoʀUoX]o` Ue H[]A\oEoHH؉UM[]A\HH""H5H81UHGSH(dH%(HD$1H\$LD$HHH|$ xwH|$H!]Ht$H|$H=B"HHHHHHu%HL$dH3 %(HH([]Ht$HuFHt=HЃHD$u#HtHt%H HH="Ht\HHH_@HD$DH=HHE" H=HH"Hi8HE"H5NH81?ff.@AWAVIAUIHATUSHdH%(H$1Hl$Ld$0HLd$fHH|$x4H|$HHD$H( DHXHhLt$ LL1HHHN11H*IH9L|$fLHLbHt$LHHH|$H4L9tHt$Ld$Ht$H9v3>Htf;HH9uHLH) Ht$L#Au-It$IUЃHH$dH3 %(LHĨ[]A\A]A^A_@HHXH9HLH)H9[H|$LH8H|$H[H|$IL9*u LHD$+HD$AH5H$%H IE~Hg"H5H81fDH 0H  ATIHUSHdH%(H$1Hl$H\$ HH\$5HH|$L5H|$HH|$HH9tvH$dH3 %(Hu HĐ[]A\ff.@HH= Mff.ff.HH= ff.fHH= ff.ff.HH= ff.f@tH5wHN@H5"SHHtH߹5w1[H=> HHM"ff.H@t9HHx"HA0H9"HiQHDfDH_cntH9}޹*1kff.@t9HHx"HH9"Hiʚ;HDfDHAH9}޹5w*1 ff.UH SH(dH%(HD$1HL$LD$Hl$3*F~H|$f.z_f(fT f. Sw Qf/w;f/Kw1HHDHT$dH3%(uH([]H= 1ff.F AH1V wsxw@Q)1iҐ9HHcHHHHHEɋBTDHE~NA9I1EfDAA@tTDкQ1iҐA)A1DQ)¸kd98SQ)¸kd90UHSHH(dH%(HD$1tGHH'$?H$~nH*%I H=9H$_D1QfIH߾<H1=IH߾<mHt` H=GH$-H1:HHD$8HT$dH3%(H([]D1WJH߾<H1_JH߾<HtQ H=F H$[fH=bf.HX%~ H=VH$ AWAVAUATIUSHH(dH%(HD$1uHt ?H5Ȏ"HH11 H=HHH3H5p"LH=ZIL-~"H\$H$MH5]"HHٺ1`H51"HHHٺ19H"IHNA/LH޺H11LH1HHD$HHQA H=gH@1H߾>HH=mHHH}HE tH}LHL$dH3 %(H([]A\A]A^A_DH=HH݌" H=HH2_DI~H=HH"H=doHHm"CH=EOHHU"H=/IH=" ff.USHHvHdH%(HD$1HbH4$ H$HHH=HcH+H1HT$dH3%(uH[]pg@t:@u\HHHt0t&@ t t=t01 u HuH5"1?Ht+1Hu 1H@Hu@fAUfIATIUSHcH\Hf/FL+HtI$H[]A\A]HcL*H|?1Hٺ+H1}I$H[]A\A]ff.ATIUHSHcH\Ht I$[]A\H*1KqHٺ+H1[]I$A\ff.@UH5l"SHuHH[]fDHHD$#HD$x xxfQOtHhHcH|? HHHuHDHHߺH[+1]GǀQAUfɸATUHSHf/HF@tH?HHH9~rI$+1H\H5݈"IHL1HٺI$HHtVL-hEH[]A\A]HhHxuHHH|HH>HEʍ]H[]A\A]DLHٺ%3IfDH=HH"GHHHHH)HDHKH@H(HdH%(HD$1HT$ Ht$~L$ xntAȺQ)iҐ)уHH|$dH3<%(H(@ȺQ)¸kd9tt/QiҐ)ֺHDDȺQ)¸kd9`fDH(HdH%(HD$1HT$ Ht$nT$ 1H?H?HL$dH3 %(uH(-ff.fATIH5L"UHSHHtgH1Kq3I$HHu2H߹Kq1% H![E]A\fH[E]A\þH=HH"yAWf(IAVMAUMATIUSHH8fT dH%(HD$(1f. 5@-H "HH=-H= "f. {sDf(LLHL$L$LA<$Lf(HL$(dH3 %(H8[]A\A]A^A_fDf(f. zuHD$D$LHT$ŅtHc|$LLH|? I?HusAE?uHt$ LHKfD<D$& "D$HCf.HA$f.AWf(IIAVMAUAATAUSLHHfT H$L$H$H$dH%(HD$81f. 8@pH "HH=-H= "f. @Lf(LHL$H;DUL$DMLL$Lf(!AXZHL$8dH3 %(D4HH[]A\A]A^A_fDf(f. zuLL\$D$LT$HDMUD$LDLL$<^_AątL\$Hc|$,LT$H$LH|?L$LT$L$I;LT$Hu}MunHt$0HLHL$<D$H|$LT$D$H F"L\$lfDL\ff.SHHGdH%(HD$1(T . vHZs{HLD$$ CHD$dH3%(upH[@HoHuJH{@tHx&k"땐1<HtM"lfZCVmff.fAWf(IIAVAUMATMUSHHfT H$L$L$H$dH%(HD$81f. @ H "HH=-H= |"ff.fDf(LLLL$L$ff/TC H؍C _A$1Hc˃HHHHHHiT(H$9A]A.H $AuMf(A<$ff(ff.>8LL\$D$LT$0HLAWD$MLL$B4 AE)EiE)DEDD)k<A)D)D ЉƉC,HHujH{@t8HxNr"fDAAÀQ-@1<Hter";fZC$-荱ff.f€tSHtC [1DC [ff.HH5S"L€ttHcx H|?HٹfHHD$SHD$Hcx H|?HH51S"€ufZ@HstfZ@$HYfHHD$HD$ff.tzUSHHt][ ؉1Ã)Ã+ųHAHljH5- i)É[A1AЉ]A[fH=\ff.@SHSHH uC[HD3[H@ff.fHH5Q"蜰HHAUHvA3*FATUSHhdH%(HD$X1HL$0HHD$PP1LL$PLD$H賮Ld$@H|$HHl$PXZ~Ll$H@VYHVFLwdHL$@HHD$$LPHD$(PHD$,PLL$0LD$,cH HHЃHT$HdH3%(uJHX[]A\A]H=^1肪f@cH*P%蔫@ATIHUHSHH@dH%(HD$81ǪH߃D$谰H蝰HL$(HLHD$,PHD$0PHD$4PD$(LL$8LD$4H tt$ H|$(HT$0HT$0Ht$8dH34%(Hu*H@[]A\Dky@[V蟪ff.@AUILATIUHSHHHdH%(HD$81©LAD$誯HA薯H߃胯D$fTf.AL j"HH=-H= j"f. HT$Ht$(f(LL$HD$ DPHD$$PL$|$ f(LL$(LD$$̼ZYH\$0t$H|$(H,HD$0HL$8dH3 %(mHH[]A\A]L$f. "TNL^HT$ DRHT$,RD$LL$(LD$$4_AX¸{Hc|$$HT$Ht$(H|?H|$(?Ht$ uH\$0HT$LHy@ HAH߃ DL1<O h"H$fLH\$0CD$}f.AWAVAUATIUSHHHH=mc"dH%(HD$81H臫HH茧HHoH=(c"HZHH_IHt-H=b"H1HH6IHH=b"HHH IHtpH=b"H۪HHIHtGH=`b"H貪HH跦Ht!LLLHHZfDH=b"HkHHpIH#H=a"H>HHCIHH=a"H&HHIHLQLD$LAHL$(HLHT$,RHT$0RHT$4RD$(DLL$8LD$4H t(t$ H|$(HT$0eHD$0HJfDH=`"H[HH`IHH=`"H.HH3IHtJH=s`"H:HH Ht$MLLHNH@H=!`"H軨HHHHǹ1-ͤ%H1贤IHtkH=_"HVHH[IHtBH={_"H"-HH2HtMLLHvHHL$8dH3 %(HHH[]A\A]A^A_f.H=ϨHH}_"$H=诨HHU_"1LLD$D$HL$HT$(LL$$LD$ L5t$ H|$(HT$0HD$0HH$@H=i^"H HHHKH=HH-^"H=ϧHH]^"H=诧HH^"MH=菧HH]"H=oHH]"H=dOHH]"'H=]"HpHH IHHHLEf.H=ߦHH]]"PH=)]"H 諥HH谡IHH֩HLE2DH=oHH\"H=OHH\"H=/HH\"YH=HH5\"H=HHU\"H=gϥHH\"H=该HH%\"pH=菥HH["H=oHH["@Kff.DAu1ËG,ASDWDW AAQDODкųEAA%>DF ʉA ѺDE)D)A iA)DDDD)k<)É[ D ЉG,?D?@A€Qdff.DAu1ËG,AS__ QO؉غųAAAD>D  A EE)EiD)ۉA[)k<A)DD)D ЉG, fD ÐÀQhDDAu1ËG,AS__ QO؉غųAAAD>D  A EE)EiD)ۉA[)k<A)DD)D ЉG,?fD?ÐÀQhDAUL-ATUHSHH؃HHH t| L%'O"HI4$HHXH؃HHQHm]gDHuHxN"HH0HDH5W"HH11МL%N"HHI4$ʟHM@uH;sf(oYf/f/f(L$L$,f*Ef.z 1H=4謚wDH踠HI轟AH5V"H+1H1HHIHAtII$QH=1H[]A\A]HHCHvHuiۀQ]H[]A\A]H萞HƒtHHQHwUH[]A\A]LHHU"8@HIHDe4fH=TH=w臟HHuU"HK"H5H81ИSH5<"_DAu[HNj@,A__ QO؉غųAAAD>D  A EE)EiD)ۉA)k<A)DD)D ЉG, [HDÀQjff.fSH5;"_DAu[HNj@,ADWDW AAQDODкųEAAD%F >A DD)iA)DDDD)k<)DD) ЉG,?[HDfA€Qf@SH5:"_DAu[HNj@,A__ QO؉غųAAAD>D  A EE)EiD)ۉA)k<A)DD)D ЉG,[?HDÀQjff.fU0HSHhHH9"HHcHCHdT JHCHCHK HC(H[]f.AWIAVAAUEATI UDSH(L$D$ʛLH8"HHŚAL$IuXLHLcHtFLLL$L$u/I`H`u#I$`H`tLL跖L$LcD$`AfD DsZL$$KLKkH([]A\A]A^A_A$]LL$HT$觙HT$L$;HH.LL$mL$IHC^HHff.ATH57"USlHH-V" ZH7"IHHUID$HHA$HHdT JID$H5;7"ID$ooKHH[]A\DH=U"TH56"HH貕oo[Xoc H@` S,@ P,H[]A\SHHdH%(HD$1ƒu%t1CHL$dH3 %(H[@u_DG(T i. v0Zs{HLD$K$ CHGHuRH{@tHx.CT"f1<誓HtT"|fZCf=ff.fSHHdH%(HD$1ƒu-GHt$dH34%(lH[{ t!{Cx^QDS, iу??k<ʉ)xQ~ Q9KCy]G(T . vXZs{HLD$諛$ C DQ9DS@HHuJH{@tHx&{R"념1<Ht]R"\fZCF}ff.fATH53"US|HudHx11jH=R"E1E1[Y^H53"HI7o HHoSPEL[]A\ÐH11jH=Q"E1E1H5 3"IXZLӑHsLHHp蠯CC$H߉EC(EEC,%EEBeuEL[]A\H#|.H%I$H))‰)D%I$H))))ȃfH|6H%I$))‰)кDH%I$)))к)ȃDHHH51"|HdHHHDHH51"LH|?H%I$)))ʃHEHD%I$))))ȍPDHH51"輏Hd|?H%I$)))ʃHEHD%I$))))ȍPDHH5q0",H|?H%I$)))ʃHEHD%I$))))ȍPDHH5/"蜎HD|?H%I$)))ʃHEHD%I$))))ȍPDHH5Q/" H|?H%I$)))ʃHEHD%I$))))ȍPDHH5."|H$|?H%I$)))ʃHEHD%I$))))ȍPDHH51."H|7H%I$)))ʃHHD%I$))))ȍPHHÐHH5-"\H|7H%I$H)))HcHDfD%I$H))))ȍPHcHDfUSHH8dH%(HD$(1G(T . &vTZHD$BD$HL$ HT$LD$$TD$ Ht$(dH34%(H8[]DHǾHH{@tTHxjJ"DG$(T q. `H{HtfZC$H1<Ht]J"fZC}ff.ff1DSHH0dH%(HD$(1G(T . vSZHD$D$HT$ HL$$Ht$襝D$ HT$(dH3%(H0[HWHH{@tTHxjOI"DG$(T . aH HtfZC$I1<zHtH"fZC ff.fHH5Q*" HHHHDATIUSHHdH%(HD$1ƒu_nHC$ HCHLs9kt#HD$dH3%(H[]A\fDkHC $ HCHL;kuDF(T y.  Zs{HLD$W,$ HCk"HǾ-1׆K% S$ Hǹ1+覆k% f.Hǹ1+wk% HkHCHǾ-16K% SDH~wHuRH{@tHx.sF"fD1<څHtMF"fZCmff.fSHH D$dH%(HD$1ƒuGHCfZT$SHD$dH3%(MH [fH萋u"HCfZd$c$@HC(fG(T . *vhZs{HL$LD$D$CЃ€HC(>fDH跸HuRH{@tHx.D"rfD1<HtD"DfZC.譃ff.fATUSHH H5C"dH%(HD$1H1H1襃H5C"IH1H1膃H螈H5oC"HH1H1_Hw'HT$ LHt$H HAAjC"1ҋL$Ht$ H=C"H5(%"HXZHۃHKHHL$dH3 %(uxH []A\H=臇HHB"H=o_HH}B"H=T?HHeB"ff.ATUHHSHpdH%(HD$h1HL$nT$H\$(HۃH.較Ht$0HH$D$@HT$Ht$ Dd$f.f/wf/ H=21V\$H=^wrH=ffDAWIAVEAUAATMUH0SH(L$D$ZLH""HHU@L$IuXHHkHkHtFHLL$sL$u/I`H`u#HE`H`tHLGL$HkDkKAuOLHLcHt=LLu.I`H`u"I$`H`tLL@LcD$`T$xfDs ZL$K$C($  $ ЋT$p ЋT$h ЉC,$ H(L[]A\A]A^A_fDA$>L踂.HH!L苃IHCPHHEHL$HT$`HT$L$dHHWHL$&L$HHCHH0AWAVAUATUSHH8H5>"dH%(HD$(1H1H1~H5`>"H$H1H1}HH50>"IHD1H1}HH5>"IH1H1}HɂH5="IH1H1}H袂H5="IHo1H1;^}HvH5o="<EH 1H14}H̩H5=="HD$H1H1 }H#H<$HT$ʼHt$ H赳HA1j ¼1UH=`="AWAVAUATD$TPLD$HHt$` H@H5"HHv}~HHHL$(dH3 %(H8[]A\A]A^A_þH=HH<" H=|HH=<" H=U߀HH%<"H=8迀HH <"qH=蟀HH;"*H=HH;"H=o_HH;"H=T?HH;"U{ff.AWAVAUATUSHHT$HL$(HpdH%(H$1`z  $~H|$(z$1Ht$@yHD$@HD$8|Ht$PH|$8]yH]D$dDd$PH\$xDl$\lD$`Dt$XD|$THl$HAyH= ~H=}ff.@USHHdH%(HD$1ƒG;(Tʅo. Cw9H{8H_H{@!H7(9" fDZf(fT ȸf. Hwvf1*f/HL$dH3 %(H[]fC$k(T . wH{蔬H\fZC$yD1f.8"EfD. QZs{HLD$C,$ TЉk(D1<wH7"@fZCf{fDH觫HuRH{@tHx.7"?fD1< wHt}7"fZCvff.fHH5"wHHHfDHH5"lwHTHHHЃAWAVAUATIUSHH5u"HHdH%(HD$81wA I HI$ƒ   H Hƒ HCH HH HsHH sHCHL0ysHH dsHCH8HH߉D$LsHH |7sHC H8HA sHH 8 sHC(HL(rHH rHC0H8ˑH߉D$rHH /rHC8H8sD$EEAu I"LuLLCD$D}EAu I5LmLLD$EfHE(ZT$E U$Hƒt [HL$8dH3 %(LHH[]A\A]A^A_DHHPHHDHL-R4"qHH -qHC H8L-1sHIrqHH ]qHCL8H$"AH0LL|$YvH)3"It3"vAHD$fpHC nfpHC H fDpHC HfDpHC H{fDpHC H6fDpHC H(fDHppHH [pHC HL(LpHH T7pHCHL0(pHH pHC HHD$L+1H 2"q%HI1qH5Y,"IH}1L1qLHD$%HI1qH5 ,"IH1L1yqLHD$ LI衝H5+"IHV1L1BqLHIDyHH|$HT$,Ht$0跪H|$LAH|$ApD$AQAI5wvAQ=L$f.f(fTʰf.Jw Hf/f/ >EE\Ht$0@uHtHuLD$,DuEAuItAEbfLmLL豎fD} Zd$HE(e$Ef.HLEoI$ƒI$|{mHCfkmHCfAL sHHLsI@AELrHHLsI1L<nHH57)"H15wLnH@H=1 m5rt$E LˢHEH|$0迌LHEHD$,fHEZ|$EE}fDH= lH=rHHe("L(T$ HLLHEH\D$fHEZ|$EE}AfH=/rHH'"H=ѥrHH'"cH=1E1kdf.jHC HfDjHC HfDjHC HefDH=qHH'"LHpHHLqIsHHt$pHt$HHHpHLQjHz"H5H81YjHb"H5H81AjH"H5H81)jkH"H5iH81 jff.UHHSH;nHHHHH[]ff.@ATH5 "UHSH D$ClHHn H-pHHS "HI(oA$H59 "ID$HHdT JID$HID$ko oSHXPu HHl$H|$H5 "kD$HHD$H []A\DmHH5 "HHQkoIoc`ok HXh u HucI\$nHaHHmkNHE`H`=H`H`-HH9j@HH%kuHE`H`uH`H`qHHia@ *"ff.@)"ff.@Lff.@$ff.@UHHYSHdH%(HD$1HBhڨ&H^HT$dH3%(ucH[]H<$gf.z.f(fT ըf. Uw Sf/w f/MvH=џ1f]&hfDAVAUATIUH5m "SH#iLHlkHH5@ "HIhLsILpACID$AD$HID$CCAD$(CAD$$%AD$, A$Ll$H|$H5 "hHuBC, i??k<+C =QOC€3HCk HD$H[]A\A]A^ÐILLXhIE`H`I`H`LL$g#jH+H5"HIgo IoSPo[ HXX u HI\$HHLgIE`H`H`H`qHLmfaHC(fDHVfQfDHLgFIE`H`5H`H`%HLeff.H1H=HD$Ht$H׏UHHSH(dH%(HD$1HL$pdD$ 1"HHT$dH3%(uBH([]H|$Ht$ t t$ H=*1D$ :csdUSHH(7 dH%(HD$1@Ck=QC$(T . ZHL$HT$Ht$ EoD$ L$S, C(D$ ȉу? ȉс ЉC,HD$dH3%(H([]ÐC, iƒ??k<Љ)x_Q~ QS3k H{ߗHujH{@t0HxF#"fD€QS3D1<*cHt#"fZC$bff.fSHH dH%(HD$1ƒu)t5GHL$dH3 %(H [ftdC,G(T . ڢvHZ{HT$HL$Ht$ mmD$ T$ CD$ ЉCy땐H臖HuRH{@tHx.""f1<aHt]""dfZCN}aff.fSHH dH%(HD$1ƒu)t5GHL$dH3 %(H [ftdC,G(T . vHZ{HT$HL$Ht$ -lD$ T$ CD$ ЉCyC땐HGHuRH{@tHx.C!"f1<`Ht!"dfZCN=`ff.fUSHH(dH%(HD$1uAHotysLL$LH֕HD$HL$dH3 %( H([]fDtHo…uHD;Hkƒuf.C(T . v@ZsLL${HL$ Mȉht$ s>H{ϓHuJH{@tHx&"띐1<:_Ht"tfZC^^ff.fSH{J-H1^HIu L[DH(eHcKtHL +[L1^fDUHSH~HHxnHMbH9oHiH\EHmH蝒HunH﹁/!^HHߺH[+1]^@HV-H9}Hǹ1*]HEHH[]ATUSHul?tHHHH9Hǹ1*y]-H1`][]HA\bHǁHuDeH+H1]HAtLcL^Ht)H[]A\ÐHXcC-tHHHHLz[HH]+1A\\DH<[]HA\aff.HH5!L]HHATH5s!US,]HHtH$HH9}CH>I-H1 \H=a Hu+H[]A\HHa HttS{AtLcLHuLty[HH]+1A\y[f{, i??k<+{ xPQO{ qHcH|?cH+H1[HEDǀQAWH5!AVAUATIUSHHdH%(HD$81[H5 "HH HD$HD$01L1ZHD$HXH tHXL]L-"IMHHT$ HT$01LH1DZH5"HD$ HGEHD$(HD$011 ZUHD$(сnfZU$T$Du HD$(LhH tLhE1LD$ IhI tIhH6HHDMLD[AVHEAUD$LHIH5XZYH\$8dH3%(HH[]A\A]A^A_ffE1ZML$LfH}Hh_D}>H=]HH%"H=]IH";H=]_]HH"H蘤UfZ]$\$сyHD$(E1~H`M\Wff.fUSHHdH%(HD$1tt=HkHHH脍H$HL$dH3 %(uH[]f tW@HH5!|XHt1*F-HH1wWHH5!I-HH17WHH5A!WHHATUHSHH5!WHIHe"H0YHufH5y"HYHuH "Ht`HH[]A\XH5"HuH=oc[H"HH11}VHLRH[]HA\s^H=ӑ[HH[H]A\H"&XfDAUATUSHH8dH%(HD$(1LgC(T 2. Kw9H{@HOH{@H'0" fDZHD$Ll$ )D$HT$LHt$iLl$ӉHt~HcHDHL$(dH3 %(H8[]A\A]LgC$(T e. ~hLpH0fZC$MfHt,LLljHD$ WD1<TH"@fZCf.Lc*XT@HH5a!UHHAWH5C!AVAUATUHSHTHË2fZCtWIŋ7Lcc Od$HLs:Z3Lc{O|?THcSHTt HHsLMAUM1TZY@uPHtGHUуt9t4HHHD$RHD$uHtHуtHH[]A\A]A^A_AAAtm3HcS4@fZC$:VIŋt@HLcc Od$AAuHHHT$HT$fk3@HPcff.SH54!H@dH%(HD$81RHËtHSHT$teHcSHT$1ҨHT$ tHCH|$ HD$(KRHL$8dH3 %(HD0H@[@uC(T . Zs{HL$LD$ ZHcT$ SHT$1ҨSDHxWHcS=H@HSHT$`HH{HuRH{@tHx."BfD1<zPHt"fZC Pff.fAVAUIATUSHH5"H/SHtFH53!LPH5$!HIPLHHAE…8tHL[]A\A]A^LLHHA$tuLfDEI\$tuHLLmHAt"AtHIL9t41[]A\A]A^DH5A"Ht$1LHOHtA9uȸÐH=sSHH "AVAUIATIH5i"ULSQH5!LH|OH5!LHuOHu H5!LUOH5!LHCOHŋN~DsHCDEZ$ HCHLlD;st#Eƒ6>DmHEDE:$ HEHLlD;mtetELctELmAt A}H5 "H}1LLkMHƒEDcƒED9[]A\A]A^HHHAE…8FHLHLtu HfELctuHfLmLLTH(AAIIM9(DH[]A\A]A^ MLHH!H0&OHH5 "LOHEH&"HM[L]LA\A]A^MfHEt A1L<LKHlHDD%H؉E1E2AHLDSHHLRHfIIM9M9H8?H(H8uH(H5"H1L1JHHt @HH5) "[HǺ]1A\A]A^ZJf.Hǹ1+7Jm% MHǹ1+Jk% H=sNHH"cHǾ-1IK% S|fDHǾ-1IM% UfDIH萕<Ht A"Lf.H訴H螴9@HOED9E%LcH]fDHHHǸH)HHHHIIfDH=fWMHH"H؆4HxHNDCE"1&HIL)HǸHSH=ڀLHH5"PADUHSHHHH5f"JHu H1[]HHH[H]{AWAVAUL-!ATIUHSHHdH%(HD$81LH:HHAAD)LHHA A$ EDAu^AIuIJMAA$ t,#L[JHHfDL(KIIZH!LH0qIHNH51"H( L11D$HH5&!H2 LKq19>%LKqH$1>H5!IH L1=H CLHD$%A1=*H1=H5l!IHE L1=HBLHD$%A1c=5w*H1J=|$ILqHz L{E H}CDcHEhAH<$LqHB HSH$ED$fZcd$H@HEMT$DHRDjjjjjjD$PHt$@ӻH@ f.‰T$*fZC$[ H$y?HAML$DLHQDjjjjjjD$@GH@~fDD{,DK HfZC$H[D$DL$?DHD?AT IQDLHǃ?QRDjjjD$PDL$HL$@ɺH@tH{L1+<;IƋAAAS,DK HfZC$L{D$[T$D $W>HMLAUT$ Hljу?Q ?QRDjjjD$HDL$@H@Jf. A A$ L1+A% e:IDåff*X$f/xf/0z:D,H=Fr>HH!AE9n@pLsHL{2!L`eHA5w-L=$7 $f.@4$\5xAĀQ4$rf.H=o=KqH!HfDL1+$8$\xIDt$K Y$rAfZC$H訄DS EAArA€xuHxH5'!HL11:8D$If.H=p@0q$H|$hHt$\,H|$`Ld$xLwHMH|$xA]eHf*f/d!Hl$xH|$XLsHMH|$xAeHuHl$xH|$PLWyHoMH|$xD$ dHuHl$xH|$HLtH9MH|$xAdHu|Hl$xH|$@MH|$8H$HDHD$k\$H|$xHt$$H|$pL$L6rHHH$A_Hf*f/!H$H|$hLmHBHH$A_HuH$H|$`LsHHH$D$v_Hu^H$H|$XLoHGH$A;_Hu#H$D$fTjH|$PD$GD$LT$Hf.JjAL!HH=-~H=~!ff/H$DLHHD$LPHD$PPHD$HPD$(LL$LLD$HsiH @|$HL$4DDLL$HILH?HxH tHxH[]A\{:ff.AWIAVAUATUSHHH!H|$HH;E1D$$Dt$ 4HHcH9D9JHl HHR!H Q HCJHA HH , HH1E1LkVf.HHcH9uT9~mH HH tI LH4LHHAH; uH{HcH9t  HC DD9$$} D$D$$D$Hg!IDt$H; H{fDK H[ HfD3 HC $Z H=!H LH HC H=!H LH H H=|!H LH H HB!H, HYLH^ tHw~HHǹw1>i Ht(H!H' H wLHHHL[]A\A]A^A_H!HGHIH!HHIH!HHIHj!HJHHHG!HHfHH$!HHKHMMAVHHHڿ1 A^ZH1 H$H!HiHIH!H1HIH!HHIH_!HHHHH!YH=>H!eH=4H!H=4H!H=5yH!H=h6\Hm!MH=6?HX!H=8"HC!H=5H.!xH=3H!@H=3H!H='5H!H=5Hڹ!H=8tHŹ!+H=l4WH!H=J4:H!H=+3H!H=3Hq!KH=\4H\! H=5HG!H=3H2!lH=3H!4H=3oH!H=`2RH!H=H25H޸!H=3Hɸ!TH=3H!H=2H!H=1H!H=1Hu!HH=3H`!H=2jHK!H=5MH6!gH=\20H!!/H=-2H !H=1H!H=0H!H=52Hͷ!OH=1H!H=5H!H=1eH!nH=b1HHy!6H=90+Hd!H=!0HO!H=j1H:!H=0H%!H=0H!H=0H!H=/}H!uH=s/`HѶ!=H=0CH!H=3&H!H=50 H!ZH=0H}!"H=.Hh!H=.HS!H=0H>!zH= 3xH)! H=/[H!H=W/>H!H=/.!H!a0Hm "Hm H=90Hѳ!Hm *H=0H~!H!HHǽLHHHP!HHWLH\HH!HMH=<.1H!0HCE1H$HHHcH9mD9H HH tbH$N4LLHudHtILI1HH1LLHPH tH{uHC H9!11@sHH!HnH3LH8HnHױ!HtXH LHHmH!H.HLH@Hm H=,Hb!HCE1H$HHHcH9D9HHH H$N4LLLHHLI<1HH1MLLHH hH{iH=,HB!H=+H!uHq!HHLHXeHC *HC 7H@!11GqH'H!HH7LH!HHLH@H!11pHH=B.H!H=*Hc!H=*uH!HCE1H$HHHcH9D9HMHH tb,@HH=!HHHHu*H=!HHHHHH<$HLHHCIIGH= !HGHHHH=!HhHHmHuH=!D$HCHL$dH3 %(HHDH [@tdC,C(T . vPZ{HT$HL$Ht$ -D$ T$CD$  ЉCpH@_fDH{?HuJH{@tHx&;!덐1<Ht!dfZCN=ff.fSH5e!H dH%(HD$1+HËu2t>CHL$dH3 %(HHDH [@tdC,C(T 1. JvPZ{HT$HL$Ht$ D$ T$CD$  ЉCpH]fDH{HuJH{@tHx&!덐1<ZHt͂!dfZCNff.fATH53d!USH dH%(HD$1IċA\$Hl-LЮH5!HcIH\HH s!LIIغH81HL$dH3 %(oH []A\fDWAl$,HcHl-$A\$,_f.H=HH]!^AD$(T /. H2ZA|$HT$HL$Ht$ D$ AD$l$D$A $ A$Al$ƒHcHl-AzAD$(T . v{ZA|$HL$HT$Ht$ ND$ AD$\$D$A $ A\$KfDLX[LH[A$ƒ@I|$6HI|$@tBHxX-!YI|$H}I|$@tBHxX!1<jHt!1<:Ht!JfAZD$2fAZD$軾A\$&AW1AVAUATUSH(dH%(HD$1gVH5`!HD$H|$葿ItHxEHA6+1uA>IAA=@A^AAAHcH\EHE~LAAH5m~!McIO|?HHIMLHEo!AUATUH81H5"~!H HHtN11H袽HL$dH3 %(=H([]A\A]A^A_E~,SH=HH}!H=HH}!7AF,@zA^A^  QO؉غųAAȉ%D >A EE)E)A EiD)ӉA)k<A)A E D ЉAăAF,AAA?Od$A~,AA^A^ LQO؉غųAAAE>D  A EE)EiD)ۉ؉)k<) DD) A~,?H|?AAA?Od$ Hl-t|Ã6AF(T . ZA~HL$ HT$Ht$7D$AF\$D$ AA> A^L@VA>AF,AAcAF(T . ZA~HL$ HT$Ht$D$AFD|$D$ AAA E~[LUI~HI~@tlHz!fDI~wHI~@tdHxzoz!CfÀQDÀQD1<躹H~)z!e@1<芹Hty!fAZFfAZF ff.AUIH2ATUSHhdH%(HD$X1HL$(HHD$HP1LL$HLD$@FY^{DH|$@f.f(D$z2fTf.a[f/wf/UH=1=a|$fDg ?AL$H|$(HL$PHHD$,PHD$0PHD$4PD$(LL$8LD$4%H HE1E11jD$LT$0Ht$` LHXZ'HHT$XdH3%(HjHh[]A\A]@\$H|$8Ht$H HǨ苼H|$HHf*f/w!H|$0Ld$H@藶-AH1l$fD%AH1d$fDHL%oHDAH|$0@g讻I @5XAt$Hg!H5+H81}Hg!H5H81`AWAVAUIH[ATUSHdH%(HD$x1HL$8HHD$hPHD$hPHD$hP1LL$hLD$`D$DH &H HcH>\$H|$XHt$$H|$PLd$hLH9H|$hAHf*f/u!Hl$hH|$HLkHH|$hD$eHuHl$hL|$@DAMALHHt:A t4A %dLDtHH}H5o!HL1\%LIĺ1@H5n!HD$hHHǹ11HD$hDLlAH|$hOHuBiHl$h2f.=E1E1D$|$H|$8Ht$h)H|$hIHuHl$ht$HL$(DDLL$0LD$,{|$(HT$4Ht$pLt$,L$(|$0DL$$iT$4Dkf/wf/z"H=1%d$pE1E1D$A\$@THHiHDLǴD$|L$f.M}LH @LHcA /HtOA uDHD$hMLHD$L$f. H5Ap!H1L1dHD$hIăDfDH1+D$(HH=ϴHHj!HD$hH=觴HHmj!XH=D$$,4H=:_HHMo!MQH!a!H5NH81蠭Ha!H5BH81胭AWAVAUIH~ATUSHdH%(HD$x1HD$`HL$0PHD$`PHD$`PHD$`P1LL$`LD$X1D$4H tH HcH>f$H|$XHt$H|$PLd$hLHRH|$hAHf*f/n!Hl$hH|$HLH H|$hAHuHl$hH|$@LHH|$hD$ IHuiHl$hH|$8LYHǨٲAH|$h Hu,Hl$hH|$0$HL$HT$pDLL$,LD$(|$ HL$DDLL$$LD$ mL$Pt$ i|$$DL$T$(Dk[!HHj!H2\H5e`! H=i!H5H%H5_! H=i!H5HH5W_!}H=i!H5qH׭H5^!VH=i!H5EH谭H=ii!3*FH58蘭H=Qi! HH5&耭i!H=,i!H5H]h!H= i!H5H:H=h!H5,WH=h!H4H5H=h!HH5٪H=h!HFH5躪H=h!H'H5蛪H=dh!HxH5}|H=Eh!HH5p]H=&h!HH5^>H=h!H{H59H=g!HH5 H=g!H H52H=g!HH5 ©H=g!HH5裩H=lg!HH5脩H=Mg!HQ$H5eH=.g!H2H5FH=g!HH5b'H=f!HH5LH=f!HH5.H=f!HfH5ʨH=f!HH5諨H=tf!HH5茨H=Uf!HH5mH=6f!HH5NH=f!H H5/H=e!H|H5xH=e!H]H5bH=e!HH5;ҧH=e!HH5%賧H=|e!HH5 蔧H=]e!HH5uH=>e!HH5VH=e!H3H57H=e!HH5H=d!1HGH5ܦH=d!1HGH5}H=d!1HLH5褦H=d!1HtLH5F舦H=qd!1HLH5,lH=Ud!1H|H5PH=9d!1HH5_4H=d!1HH5MH=d!1HH5H=c!1HH5H=c!1HH5?ĥH=c!1HH5j訥H=c!1HNH5茥H=uc!1HH5pH=Yc!1HH5TH==c!1HH5r8H=!c!1HXH5H=c!1HH5H=b!1HH5H=b!1HTH5ȤH=b!1HH5謤H=b!1HH5萤H=yb!1HPH5ytH=]b!1H$H5訣H=Ab!1H H5o茣H=%b!1HH5/pH= b!1HH5TH=a!1HH58H=a!1HHH5H=a!1H,H5H=a!1HpH55H=}a!1HH5ȢH=aa!1H*H5\H=Ea!1H)H5u@H=)a!1H0H5^$H= a!1HDH5LH=`!H%7H5)H=`!1H6H5͢H=`!1H6H5豢H=`!1Hq6H5蕢H=~`!1H56H5yH=b`!Hf:H5誡H=C`!HmH5;H=$`!HȆH57H=`!H|H5sH=_!HڋH5]ޡH=_!1H|H5J¡H=_!1H|H53覡H=_!HSH5臡H=p_!HDH5hH=Q_!HH5IH=2_!HH5*H=_!HH5 H=^!H(H5H=^!HyH5͠H=^!H*yH5u讠H=^!H[xH5[菠H=x^!HNH5pH=Y^!HmMH5$QH=:^!HUH5 2H=^!1HRKH5H=]!1HvH5H=]!1HJBH5ޟH=]!H{H5迟H=]!1HOH5裟H=]!1H3H5s臟H=p]!1HH5kH=T]!1HH5OH=8]!1HH53H=]!1HH5H=]!1HH5H=\!1H6H5yߞH=\!1HϋH5gÞH=\!1HGH5觞H=\!Ht%H5舞H=q\!H0H5o艞H5R\!H=bHzH5jHH!\!TH=\!H1H55H=[!HnH5aH=[!HnH5'H=[!H4iH5؝H[!!ƒ3H9< AHxH5H=R[!H^H5grH=3[!H/H5SH=[!HH5o4H=Z!HH5ZH=Z!HҸH5BH=Z!HH5,לH=Z!HTH5踜H=yZ!HH5虜H=ZZ!HvH5zH=;Z!HH5[H=Z!HH5<H=9+HH= HH=Y!HٺH1&H=H͜H=HɝH=Y!HٺH1H=蟝H臜H=H胝H=DY!HٺH1蚘H=YHAH=9H=H=X!HٺH1TH= HH=HH=X!HٺH1 H=͜H赛H=H豜H=rX!HٺH1ȗH=臜HoH=gHkH=,X!HٺH1肗H=AH)H=!H%H=W!HٺH1<H="HH=HߛH=W!HٺH1 H=赛H蝚H=H虛H=ZW!HٺH1谖H=AW!1H0H5bDH=%W!HH5%H=W!H"H5rH=V!HH5eH=V!HtH5=ȘH=V!HH5M詘HbG!1HiH5H;芘H;1HH5rH;1HVH5ZH=CV!1HzH5^>H='V!1HnH5J"H= V!1HH56H=U!1HVH5 H=U!1HzH5ΗH=U!1[H=H5鱗H#Ht.HH~F!H8 fDHaF!H8H9F!H8HF!H8H)F!H8HYF!H8AWLAVAUATIU1S1HL/MIA ADL9}kVHL (JHȉكEىكE<-t3<.t'H=~HH@!dH=o~HH@!/HxH@HHwH5@!HHH=HL$~HL$HH@!@ZH=|HHOyH02!~@HmH= }HH?!H=}HH?!}H=ݰ_}HH?!UHAWAVIAUIATISHH8DEdH%(HE1u IH5W?!HL11"xIHUIKIHH qL{AAըM|MH0DIAAըDFt+L}H5LyxI4>IIEL A}'tHHf.HcHH 7D{A'tHH8HAGLHU{HUH0fDHD:AGըADFtAOՁIAHH5"LEHUwHULEHHH LCL)HAIHH%H)HHH9tHH$H9ut H)HLLL$LLILw1Ҿ B8HsH==!IHuH=JzHfHVILD H=%!D D|PMcO|?Hu#H=?HMcHMH$!HHMbLLHX`HMH=$!D D D|PMcO|?HuH=qYcHMHn$!HHM2bLLH_HMH=A$!D D D|PMcO|?HuH=bHMH$!HHMaLLH_HMH=#!D D D|PMcO|?HuH=bHMH#!HHMjaLLH,_HMH D H=Z#!D D|PMcO|?HPHMaLLH^HMH CDPItI WIA>-DH="!HH\Hu$H=KaH"!Hf`HLHM^HEHUHUHUHH HLpIHHTADH=i!!ADD|PMcO|?H_LLH]H~CADH=!!ADD|PMcO|?H_LLHj]HuDAH= !AF\PHcH\Hc_HLH%]DHEHEHEIIM -HH5? !H\ HCHٺ1=[1Ҿ LHXHH``H=!HHE^HLH\H]HtFH thH=!LkLsHtn^HLHQ\A}[vHEHEHEHMdH3 %(He[A\A]A^A_]HH=E!LkIHuH=Q%_HH!rfDH@I}HHWH5!HHH=Ñ^HH!fDLpHXITH<HT*AH=!AFD|PMcO|?H]H]LLH [H~AAFH=X!AFD|PMcO|?H^]LLHZHAFH=!AF\PHcH\HTH=9]HH!4@HXHHcH= ]HH!STJHcH\H I H=!HH=!]HH!rfHICH=!CDtPMcOt6H [LLH}YH=[!0HcH\HH=\HH,!HICH=!CDtPMcOt6H #[LLHXCH=j!CDtPMcOt6H ZLLHXH=$!C\PHcH\HH=[HH!@H.I$CH=!CDtPMcOt6H CZLLHXCH=!CDtPMcOt6H ZLLHWCH=[!CDtPMcOt6HzYLLHWH=!0HcH\H H=ZHH!fHvIlCH=!CDtPMcOt6H +YLLHVH=!C\PHcH\HcH= YHHX!CHICH=Y!CDtPMcOt6H XLLHMVCH=!CDtPMcOt6HLXLLHVH=!0HcH\HH=2YHH!pIFHHH%H)HHH9tHH$H9ut H)HLH\$LLHHLkUBD3H߾:SLHtHHID"VH=s!IHZWLLHUXSHDPt+ILUHVH=!HH WHLHTH=^!CDtPMcOt6H=VLLHTCH=!C\PHcH\HH=WHH!11@ HTJHuH=!HcH\HH=:*WHH!{CTPItI [IA>-DH=]!HcLtHULLHyS1f HTJHuH= !HcH\HH=rVHH!E11B;ITPIuItI IA>-DH=i!HcLtHTLLHR1B;ITPIuH=!HcH\H"H=UHH!fCTPItI IA>-DH=!HcLtHT?TLLHRCH=n!CDtPMcOt6HTLLHQCH='!C\PHcH\H7H=ۇTHH!11@4HTrHuItI IA>-DH=R!HcLtHqHM@SLLHQCH=!HMCHDtPMcOt6HMRLLHPCH=!HMCHDtPMcOt6 HMRLLHtPHMH CH=k!C DtPMcOt6HrHMaRLLH#PHMH C H=!C DtPMcOt6HHMRLLHOHMHu>C H=!C \PHcH\HQHLHOH={!HQ1LHhOHEH=!HH=wRHH!H=bORHH!fH=Lj/RHHu!H=)RHH=!H=QHH%!H=gQHHE!H=ĄQHMHHy!@H=QHH!H=w_QHH!7H=W?QHH!H=7QHHe!H=PHMHH!@H=oHMPHMHH!gH=xPHH]!H= PHH!H=oPHH! H=̓OPHH!H=/PHH}!H=PHH!0H=OHH !H=OHH!HH=ǁOHH!H=OHH}!H=oOHHU!@H=͂OOHH!:H11f HTJHuItI pIA>-DH=!HcH\H[MLHHKH=!HH=vNHH!fDMvMvMvMv4H=ŁGNHH![H=7NHMHH!@H= MHMHH!j@H=HMMHMHH!H=MHH !MvMvH= uMHHc!QHAUIATIUSHdH%(HD$x1H吉L6GHDHHuH|$HxH|$(HH\$@HAH|$HHt21Ҿ EH= !HHKHLHmIH|$PH1Ҿ EH= !HHjKHLH,IH|$X1Ҿ KEH= !HHx3KLHHHH|$`Ht21Ҿ EH=O !HH[JHLHHH|$hHt+سH= !HHEJHLHHH\$pHtVH= !H2JHLHOHHIH= !HH_JHLH!HHL$xdH3 %(HĈ[]A\A]f.1Ҿ DH= !HHAIHLHGH\$ HB1Ҿ HCHH nH(H=) !HIHLH]G1Ҿ tCH= !HH\IHLHGH\$HsH tHsH-7HH|$Hu7HsH tHsH€1G1Ҿ BH=U !HH H=|IHH. !H|$81Ҿ BH=!HHpHHLH2FH1Ҿ SBH=!HHX;HHLHEH\$0H1Ҿ HBHH H{xH=Q!H@H= |HHH-! H={HHH-!H=|HHH!H=|HHH!H=z_HHH}!1Ҿ H1AIH HH=!HFLLHDfH=zGHHe!_H=yGHH!hH=yGHH!H=y GHH!H{:H{LI%H=}5GHH!HH=%zGHHM!8H=zFHH=!H=yFHH%!3H=?}FHH !HHHHxcAAUIATIUSHdH%(H$1HfDL>@HDHHuH|$HH|$(HH|$0HH\$HHH|$@1Ҿ >H=!HHDHLHlBH1Ҿ >H=^!HHuDHLH7BH\$81Ҿ HS>HH "H^H=!HH=Lx"EHH!{fD1Ҿ =H=!HHCHLHAH\$ 1Ҿ H=HH H{rH=!HBCHLHHAH|$hH1Ҿ ]=H=!HHECHLHAH|$p1Ҿ &=H=!HHjCLHH@H|$xHt21Ҿ 1Ҿ ;H=!HHuH=uAHH!H$H=tAHH!H=tAHH!bH=uAHH !H=t_AHH H=ks?AHH 1Ҿ H:IH HFH= H?LLH=7H=s@HH H=r@HH6 vH=r@HH H=r h@HH H=vH@HH HH~H{H\$XHufH|$`Hz1Ҿ 8HH H+HH=bv?HH L3IH|$P1Ҿ 8HHH HHo>HLH1?H OH{H=8r?HH FH=r>HH [H]HH=q>Hu 1H=q>HH 9fDAUIATIUSHHdH%(HD$81HLj8HDHHuH|$1Ҿ *7H= HH=HLH:H|$1Ҿ 6H=d HH`HH[]A\A]H=p/=HHm H=;o=HHU \H=L HH;HLH91Ҿ 5H= HH;HLH^9fH=n3f1Ҿ T/H=5 HH<5HLH2uf1Ҿ /H= HH!4HLH2&f1Ҿ .H= HH4HLH~2f1Ҿ .H= HHte4HLHB2DH=kg5HHU EH=[g ?5HH hH=9h5HH {H=h4HH H=f4HH H=f4HH _H=h4HHe {/ff.AUIATIUSHHdH%(HD$81HLZ.HDHHuH|$1Ҿ -H= HH3HLH0H|$1Ҿ ,H= HH`2LHH0H|$HH|$ HH\$(HtMH=- H2HLHA0H1H= HHt:U2HLH0HL$8dH3 %(>HH[]A\A]H=f3HH H=+e2HH \ۚH=| HH1HLH/1Ҿ +H=M HH1HLHN/fH=do2HH H=bdO2HH )H=Kd /2HH HH=e2HH _,ff.AUIATIUSH8dH%(HD$(1HL+HDHHuH|$H\H|$H H|$HH\$ HtMH= HN0HLH.H/H= HHt9$0HLH-HL$(dH3 %(mH8[]A\A]fH=ud0HHE H=b0HH- ]1Ҿ )H= HH/HLHN- f1Ҿ d)H= HHL/HLH-f1Ҿ $)H= HHtE/HLH,qDH= c/HH] GH=b/HHE H=b/HH ?*ff.AUIATUHSHXdH%(HD$H1I@Lf)IHH uH|$Ht0hH= HcH\H .HHH+H|$1Ҿ 'H=E HH)-HHH+H|$H= HcH\H-HHHa+H\$ 1Ҿ H}'IH NHMH= HH-LHH +H|$(1Ҿ )'H=j HH&-HHH*H|$01Ҿ &H=+ HH,HHH*H|$8H-H= H\$@HX,HHHe*H+H= HHJu,HHH7*HL$HdH3 %(HX[]A\A]H=^`?-HH H{H5) HeL1,(HuL+1 (H= IHiH=Mc,HH IfD1Ҿ %H= HHl+HHH.)fH={^O,HHe H=_/,HH= H='^,HH5 H=^+HH H=^+HH H=^+HH H= _+HH H=]o+HHu PK&ff.AUIATIUSHhdH%(HD$X1H@L&%HDHH uHD$Ht%H rH@H,rH|$1Ҿ #Hٺ+H1%H= HH)HLHD'H|$1Ҿ c#H= HHpK)HLH 'H|$ 1Ҿ ,#H=U HH)LHH&H|$(H7H|$@HH\$HHtMH= H(HLH&H"(H= HHts(HLH`&HL$XdH3 %(WHh[]A\A]@HH,HiHBH\xf.H=\/)HH mH=;[)HH #H= HH'HLH%1Ҿ !H= HHA'LHH^%H|$0Ht21Ҿ w!H= HH_'HLH!%H|$8HK1Ҿ 6!H=G HH'HLH$H=[(HH H=Z'HH pH=W^'HH H=['HH ]H=Y'HH H=rY_'HHm H=[Y ?'HH5 H"ff.AUIATUSHH&HI"H=d H$H=bH!H5S H4 IHxHH1!'H= HH.y%HLH;#H#ƒƒ ƒ  ƒk ƒ} ƒ   H=a H $HH HH=- H $HH HHt[H5 H H11 +H1 H= HH3 >$HHH"H= HP $HH HHt[H5` H H11+ +H1 H=# HH/ #HHH|!H= H#HHHH= H k#HHpHHH5 H 1HoHH5W H 1HBHH5" H91HHtHH1+H= HHuLH=V#HH /H﹡1+H= HHW"HHH fH=Q H +"HH0HHt7H5 H 1H3Hf.H= H!HH "H= H!HH"H=q Ht\!HHHHt*H=D Hkf!HHkH LYHH[]A\A]H=cT7"HH H=]"HH HH=]!HH H=]!HH H=S]!HH L- I H={]NLHHLH֝HƒL- I H=+]HLHLH膝6fDH谇bL- Io H=\HLHLH&L- IH=\^HHLL.HHfH=\O HH H=.\HD$* LD$HH ^fDH=SHH uL- I? H=[HLHL^H&HV.L-? IH=q[DHHLLH̛HW1ҾH=nHHH- 0fDL-! IH=ZHLHLHNL- I H=ZHLHLԊH L- I H=oZBHLHLHʚJL-C I H=-ZHLHLH舚H= m H= 5 H5 H H= 1HH H=  H=  H5Q Hj H=q 1HH H aL-1 I'H=CYHLHL&H螙H΃fH5 H1HHH5 H1HHH1+H=~ HHuHHH7fL-) IOH=KXHLHLH覘&HւL- IH=WHLHLHTL- IH=WHLHLHH>4fL- IoH=[W.HLHL>H趗6Hƒ L-Q I?H=VHLHLރHVH膁ƒL- I?H=VnHLHLHvL- IH=YV,HLHLLH贖4HH=PHH H=MHH `H=gPHH H=LHH L- IOH={UNHLHLΥH֕VH4HH= HH HHHDL-) IgH=THLHLVHNH~fH=LHH H='OHH H=LoHH YH=JOHHE )H=J/HHU H=9KHHe H=`IHOL- NH=OeZIHL- )H=?f*IHL- H=o_IHL- dH=K/HH H=KHH- H﹡1+H= HHJH=[MHH *@H=c:IHL- DH=IoHH +'H=?`IHL-H ,1ҾH=J_IHL- fD1ҾH=raIHRL- gfDH=aZIHL- 6H=^*IHL-@ LH=o`IHL-x 'H=_IHL-8 H=]IH_L- H=VGHH H=6GHH #H=^*IHL- lcH=\IHL- 6H=_IHL-` L H=]IH_L- SH=^jIH/L- FH=FHH $H=JHH] 1ҾH="]IHL-K 1ҾH=\IHL- L- H=O LHHLH\H=gNHH 1ҾH=\LIHL- 1ҾH=\"IH L-` iL-< H=PN# LHHLH諎+H=MHH v1Ҿ H=8[IH` L- <1Ҿ H=[qIH6 L- f.ATIUSH<HHQ H5% HHH HLxtHZ HH[]A\fDH5 HH HLxuH5 HH yHLnxuH5{ HH RHLGxpfH=XZHHD$ Ht$H5A $@H=V"HHD$ Ht$H5 -@LH=_VHHD$ Ht$H5 @HH=UHHD$u Ht$H5 @ATIUSH|HH ,H5E HHt,HLH wH HH[]A\fDaH=THHD$ Ht$H5 ff.@ATIUSHHH H5 HHt|H HLzvtH HH[]A\fH5Y Ht{H \HLAvuH5. HH HLvkH=?S* HHD$ Ht$H5 P@AH=R HHD$ Ht$H5 Q@CH=R HHD$} Ht$H5i @ff.ATIUSH| HH ,H5% HHt,HLH uH HH[]A\fDH=P HHD$Ht$H5 ff.@ATIUSH HH H5} HHt|H 5HLzttHHH[]A\fH59 Ht{H ̚HLAtuH5 HH EHLtH=N* HHD$Ht$H5ɿ P@H=N HHD$Ht$H5 Q@H=/M HHD$}Ht$H5I @ff.ATIUSH| HH, H5 HHtHL E1#HAH[D]A\A]fD# 9E1D9AHA![]DA\A]AWHAVAUATUSHHHt$H $LD$dH %(HL$81H1HE1IIf.BD=< tZ~L<%FD=H qWLcWL :DÍCMwP|7HfIC,DB uIL;<$rLB\=t7DLDDD$LVDD$H VHL 9!BD=C8,IK,E1L|$H>Ll$ IMLd$(IIHDH! N$LILHLtIIuH HkHH|$H1HL$8dH3 %(H5HH[]A\A]A^A_Ht$0K<,HbH|$01cI H= H\$0HRNH|$HHH=O HM)H|$H,HfI;C<,%II#Ht$LD$K<,H\UL)-H= HHZf.H|$HHI|1N|5Ld$Hl$ ILLHIcH TLTL 7=IItH0 J,HHK,E1L|$H<Ll$ IILd$(HMI(@IIH N,LILHL&uLl$ DLL|$Ld$(LI͉R)H HcH\HrH=z7eH UIJ|= K<,Ht$0HH= IH\$0HH|$HHHt$LD$K<,H SL)H= HHH=RHH Ht$0K<,HYH|$05I H= H\$0Hxf+H|$HIHFHt$LD$K<,H5L)PH=I HH-H=&RHH" O4,APՁu1<-I\O4,IJ|=THt$0 LHIŃH\$0H= HHH=8?HH] (H= qHIK<, H5 HHWH=o Hٺ1HH3HƿH5 HD$HH߹1H|$HHD$ HHH=U IHTH|$HT$HH=# H-HT$ H|$IHL>Ht$0K<,WHH|$01;IH=+ H\$0HH=2HH mB\=DHDDD$H ODD$LOHL 2M2K,E1Ld$ H uOHD$HLIIHt$HLHHn H L$LHK<,?-, HHt$0(HIH5 H1H|$0H H= HHFH=|1uHHk &Ht$LD$K<,HNL)H=5 HHqH=jN HH QHt$0K<,NH+H|$0 I~H= H\$0HH=1HH aHt$LD$K<,H:L)H= HHH=M[HH Ht$LD$K<, HML)zH= HHWH=PMHH 7K<,?-Z HHt$0&HH\$0IH=~ HuH=/HHZ UHt$0K<,HH|$0IH= H\$0HH=R04HH Ht$0K<,bHH|$01IlH=> H\$0HH=/HH xHt$LD$K<,HKL)H= HHH=KrHH Ht$LD$K<,HKL)H= HHnH=gKHH NHt$LD$K<,HM.L)fDHt$ HL$0H{L)LHHt?ABALcI9K,H;l$ ZD"1H\$xdH3%(HĈ[]A\A]A^A_ÅOApuIT$(Ht$8 LLL$@H=wH9D$LL$@rHcHD$XLhMMLL)H MMfIML$HxHH;D$,Lt$L9t$ LAH+D$IfL9t$ HLH51LLL$@A@8LL$@HID8zHD$H+LhH|$0LL$@HGH?LL$@LcLH?HL1H)HDAكHHHHHo^M<+ HHHHHHHiH99QE9LHD$ L9QL)HcHH9|$( u8D9~3Ht$ D)1LLH0L)HDIIn+MyIܸ-LAHt$ HIo^M<+ HHH)I1HIIHA0v6MiHHLt@M)u @ HLHHIH Ht$ A:Mn1H0LL)HLMtLHL)HH)@Y HO Ht$ A:I^1HHH)mLl$HHL4MMAtEAAEH\$0HCH;PHn HA|$ADHH1L PLc HD$ L9L)HH9HLLHL$( HL$(M$t7u HLM8f.A>WAIM9tA>t܅ApAAT$AtEAAEH\$0HCH;IHt%LLL$@PLL$@HHML$<tApjAAT$PAHD$ u  L9L)HA%ML$IHt$ HL$0HW+L)<ApAAT$ApAT$D$( Ht$ HL$0H L)H\$0HCH;PNAD$(AEH.<0t$H,uA|$dH HDHt$ L)1LHIH\$0HCH;gW Hǹ%1HǨ AND$(AE<0tH(,bHa VH\$0HCH;PAH\$0HCH;P@AHD$ ~ A* L9L)HA ML$IHt$ HL$0HX)L)RH|$0HGH?PpEA…HO̓jEuHD H\$0HD$`HCH;PpHD$hD$(<0NH=+:DHt$`HH\$ H|$8HD$X^L)LHHH92AHD$ u ^ L9L)HA ML$IH|$0HGH?P0AAuOD$(<0H[*Ht$ L)Ht$ HL$0H(L)LHH3AALcI9K,H;l$ I)LHK<M|$( @D@LLIML$H|$0HGH?PHAAAtEAAEH\$0HCH;P HA|$BDHHp+L P6H HH|$0HGH?HH1ƒNAEHID$(<0 H(Ht$ L)1LHt$ HL$0H8&L)PHt$ HL$0H&L)/AT$A LL$HH߈T$@T$@LL$HHDHt$ HL$0HL)H\$0HCH;G5HHID$(H?NAE<0H'H\$0HCH;PPNAD$(AEH<0Ho'A|$HH HDH\$0HCH;PPAP DO…D$(NAEHS<0EH&6A|$IH /HD L E…NHD$ L9L)HcHD$(HH9H|$0AHGH?PhI~.Hǹ5w1A *AIEt:HHAuH LǺ*1IH5 HL1ML$M<LL$@HHt$(LIH%1MLL$@ H\$0HCH;PXAT$A&LL$HH=%T$@6DpQPH|$0HGH?PPL q' IALM@H\$0HCH;PxEA…HO̓EuHD H\$0HD$`HCH;PxHD$hD$(<0H=Ht$ HL$0Hy"L)yH\$0HCH;P`H\$0HCH;U3P@H\$0HCH;P(D$(I1fL9cHD$ LL$HL9LL)HI9<|$(I)˸ HL$@ML@D@LMHL$@LL$H"EEHID$(<0jH#[Ht$ L)HbDL I)HLK<M>\$( DHLQHt$ 1HLL)LHILl$HMMA NAuHcHDHr HD$`HH|$0HGH?HH1_HD$hD$(<0NAuHcHTHD$hD$(HT$`<0WzHa"A P8AH=HH P HADP H\HD$hH=3H\$`Ht$`HaH|$8HD$X2HT$(LMHLL$@L9L)HcHH9|$( UHc@D@LMtbL9\L)HcHH9I|$( UHc@D@LMtpL9L)HcHH9|$( UHc@D@LMt*A XHHHHHHHH)HHH9u!QE9LHD$ L9QQE9LHD$ L9_QtH=LD$@LD$@HH QE)H=siHHo D=Ll$H1MEff.GHHquogetlocalsecondsdivhourminsec_fraction11zoneleftover%FT%T%z%F%Y-%m-%d%Y-%m-%dT%H:%M:%S%:z%a %b %e %H:%M:%S %Y%a, %-d %b %Y %T %z>=invalid start is ignoredM%02d.%%m.%%dT%02d.%%m.%%dS%02d.%%m.%%dH%02d.%%m.%%dto_iT%H:%M:%S.%0*dround**21%c%02d:%02d31ydaymdaymoncwdaycweekcwyearwnum0wnum1fraction of offset is ignoredexpected numericto_rlocaltimesubsecutc_offsetclock_gettimeinvalid offset is ignoredexpected an arrayfloorinvalid day fractioninvalid size%a, %d %b %Y %T GMTto_sinspectajd<=>-@08invalid fractioninvalid date040302commercialcivilordinal-4712-01-01T00:00:00+00:00-4712-01-01utc0607<=DateABBR_MONTHNAMESABBR_DAYNAMESITALYENGLANDJULIANGREGORIANvalid_jd?valid_ordinal?valid_civil?valid_date?valid_commercial?julian_leap?gregorian_leap?newtoday_strptime_parse_iso8601_rfc3339_xmlschema_rfc2822_rfc822_httpdate_jisx0301initialize_copyamjdday_fractionsunday?monday?tuesday?wednesday?thursday?friday?saturday?minutesecondsecond_fractionjulian?gregorian?new_startitalyenglandjuliangregoriannew_offset+next_dayprev_daynextsucc>><<next_monthprev_monthnext_yearprev_yearstepuptodownto===eql?hashstrftimeasctimemarshal_dumpmarshal_loadDateTimenowpublicto_timeto_dateto_datetimeSunMonTueWedThuFriSatSundayMondayTuesdayWednesdayThursdayFridaySaturdayJanFebMarAprMayJunJulAugSepOctNovDecJanuaryFebruaryMarchAprilJuneJulyAugustSeptemberOctoberNovemberDecemberstring should have ASCII compatible encodingformat should have ASCII compatible encodingcannot load complex into simple#<%s: %s ((%sj,%ds,%sn),%+ds,%.0fj)>Mon, 01 Jan -4712 00:00:00 GMTMon, 1 Jan -4712 00:00:00 +0000@pȓ8l̙,\,p(p` L|,;Zx0N<[y1OY@0C??@v@aTR'>@З@@}!A!HA!A("CT"Dx"(F"G"H"H#Jl#8J#K#xN $NL$(Od$hO|$O$hP$HR%hR,%xT%XV%W%^p&_&t't'y(L))X)؃)H *X4***H+8++h,0,Hd,,t--.X<.h..8../D/X///80D0xp0000(X111x12h42h2H22(2x383X3x4X4H5855X55X6D6666,7\7X77X78 X8 8!8!8$,9'l9)9.:54:6t:X7:7:7;7;h8L;8;X9;h=;F<^@<d<l<ho<r<=v|=xy={=4>Ht>>x>?xL??x?(?@@@@@H AHA8AzRx $xFJ w?:*3$"D \JpģW ZNX J `T`PLP L W80xMDG P LCI ` LZNX J `pD$E^X+H^p\wBBB E(D0C8F 8A0A(B BBBF DJVAT,تBEE E(A0A8I`phJpWhA`] 8A0A(B BBBA 8 BED C(FP (A ABBG @ԫBEE D(C0FP 0A(A BBBA 8ZBMG D(GP (A ABBE H@_BIE B(D0C8I 8A0A(B BBBG HBGE B(G0D8G 8A0A(B BBBC HVBIE B(D0C8I 8A0A(B BBBH ($0oALF@T AAA 8PtBEB D(D0V (A BBBB H BBB B(A0A8G@N 8D0A(B BBBD ̵"DO E Iܵ  ص  Ե 4е H̵ \ȵ 4pĵgBBA D(K0I(D ABB0nAAD ` LCK dDA8 EVpCpGpK`sP`sT`sL`s9PeY@W^bfjnsw{       0*0*0*0*@8@8PFXMď`Tȏpb͏pяpՏpڏ~:~ޏжH?p0*@80*W".:AP[@8dsk`THp@W0*ِ̐ Б PF  $ (`s1XM781< F~LSB`h[h`TxP~ppbۑő0*͑ؑPepbp  `T#p*3~9ж/?KWpdvPF~dÒǒ˒ϒӒגFlĊ̊Պ\`dhlptx|#*19CLS ) C ̄""o``  # (8X o0ooo(P"DD D0D@DPD`DpDDDDDDDDDEE E0E@EPE`EpEEEEEEEEEFF F0F@FPF`FpFFFFFFFFFGG G0G@GPG`GpGGGGGGGGGHH H0H@HPH`HpHHHHHHHHHII I0I@IPI`IpIIIIIIIIIJJ J0J@JPJ`JpJJJJJJJJJKK K0K@KPK`KpKKKKK #*19CLS\`dhlptx|lĊ̊Պ0;}p0ppU `GA$3a1Cل GA$3p1067@ToGA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA$3p1067ɄGA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFY@TpGA+GLIBCXX_ASSERTIONSdate_core.so-2.2.10-35.el8.x86_64.debugK-7zXZִF!t/8_ -]?Eh=ڊ2N\ Ҳ4 ]pD%e^Lߜ htޓQ$E*_jhj` /(x֌,-ϓy~Li7܆?h+:6"7_ơ sNͩ1DBPLǩx]]|L:g_pn::0LN$% lnE v Tl72Ծ&TKw4r5 < Vx:|=S8[i`{9ew{N~}G`tUm4Ex6 xǪOHxu[Yb D6Ny z.mHi]1=Hy'géfTptWz 0&! A1 r͵wE<`cE~T<ȡ߲s*Lt{|:zWT]e8u@O`+{ zҨ]2JH򫰧͝SŦ0s|[t:rl'<b a@O-%Q*K.'ra"@ђ6ML'oF7WPKyG/Jq$?1&. \WʜYҩ+nMclîHt)w!YepVD DrSXF%yP!:KOH'{@ڴ\ _SaOGjbBP IA^$ϫqmiw MFIu )\I֯w22}0gP+Gt@sLk[WIE sck7O)DryU扥0)" 4O2!3`l;˓^?'GM ?AOFs@ˁ tZ)]X{>.3qG[mI$E!^[Q mcA;fl.N(aRfGD3#8+&+r0΂zPk 2\|X<N^\T¸tme8Wp@"rk|,j{qhQW mr*RiU}Z+Lb§vǷՅ 5DUQoȲv_;kpm6CVsȾP13Z| jBmB+u9/h~@ho;skƒ!:/+w@:>8qg1H`$Z оY#)@н&|o=fu)M?v)D#ıg_=^!sj &Kh&dkؠ{+ l~ޘքFԁymUybxz2e4fxNh4R:\2)c0K,j0}:mB JPJBq3"' }U0,%PzeY-> ·}]zgB6fuI;=Q':5ZgtwJ^ʦY/IG:Sv3K1ʐ|F`qlE.f“66SH~-QZQFH(Z %?Mlrڬ4( 5h+x(_旸n2BD@6cyM\u(Z*8a3KEgůn5/v+E(eq)΄+Nc#N6hV@qb&m* ڀzԒ7_ы80[\4Gu)s 6QVݹU-IUB8Sg4ːIo"xc*1*\pUzj&uU+4Da9_vKcV0nOG3 `C-:iT JG2GfɦwQ_ ]%vBk:‹h"h;2I۝0O[}m\U+G%>q}55xv _vBp2pR %/FS7,﫜ww9&FLI5aD*d9$sņ-dÖy9h"KTlzmVkk1чjheȴ+`!3k:M!|2Xn<9gFCAb0 ks9% Y3fYh{:W^T_iZ((17O㔁ؙ}@Ɖ]rLSDՄXhɖ $CKM/J:dP r-(J'H[c#oS3Mf^6B;K ŒW+-*#"ӲvUQxl0j5ASӢUr-7*PaE=QR=,Zf42@ULFK+}۴MLqgf9@84jB?*6"ygnJ#+{sPv(kMt|"sLN 'vrS ,jhz&ߦ 2vJQ;9;& G$Y?~ysSL앋>Z>}?f߬"Jq3)lX5v`U꓏B590}>"*YCE6%IRz/2Xp=l]gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.data.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``d(  0``8o"Eo00TX^B(8(8 hCCcCCnKKwSSI1}̄̄ " XX888 "" " 0 P"P p"p##x x#xcx ," p 01PK!kќ0..)2.2.0/x86_64-linux/digest/bubblebabble.sonuȯELF>0 @'@8 @       888$$ Std PtdhhhDDQtdRtd  ``GNUEC3- uspd@ BE\1A|qX U pe, F"ix  | px __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizerb_string_valuerb_str_newrb_eRuntimeErrorrb_raiserb_funcallrb_funcallvInit_bubblebabblerb_requirerb_path2classrb_define_module_functionrb_define_singleton_methodrb_define_methodrb_intern2libruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64_ui               ( 0 8 @ H  P  X  `  h p HHY HtH5b %c hhhhhhhhqhah Qh Ah 1% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E DH=A H: H9tH Ht H= H5  H)HHH?HHtHe HtfD= u+UH=B Ht H= Id ]wAWAVAUATUSH(H|$H|$HD$L A IHhALHHt@1HHD$H\$ HD$H@HD$HD$xMHD$ME1AIHIHpLI)@ILI<6HBD F-AVHƒAVIADA)H88McIIHHHLHH)M9Fl D@@HHIHHRHH);LFDAFHIHHHIHHRHH);FM9 IAExHD$H([]A\A]A^A_fL`HhH*LHH9CH H5H81ffDHHD$GfHLGHwILoHHRHH) H\$ ;IBx3NAAaeff.HH5 11HH zqbA&A L {I QBJ=l,C&QM!6ş6AfРo"ή Tf :k>q?p|jRR9}wk{xϯ|hs\tyam7GKӯ}xJt9X:,bW;X[-Ndsצp(2o턊__f(*SƝt:ݲ||l(KWʥ<_AQ $jr ܆s56(ޕK  [s+ނA ,k~ToQl6,Xb7AIA'o{nVQ{7XԄf](Gf4/َAG?.".)E^dۂ=̊%MUլ"L+2 ;A 4 eKA?BAG҅OiB:Axq{ [$I b6 ){ZHd[Vc9&8r8,xYۇIw-FR,Ce9ˤxb@ @8)@8 @      @@888$$ Std Ptd <<QtdRtd  PPGNUvGiW8lxRcfSe@@ hBE`fJL+Nû|qXFVtLF"?xj _ 2 , `  @ $ p ` U  ` __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeInit_sha2rb_requirerb_path2classrb_define_class_underrb_data_object_allocrb_ivar_setrb_intern2SHA512_InitSHA512_UpdateSHA512_FinishSHA384_InitSHA384_UpdateSHA384_FinishSHA256_InitSHA256_UpdateSHA256_FinishSHA256_FinalSHA512_Finallibruby.so.2.2libcrypto.so.10libssl.so.10libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64 ui [ t [         @  H  P          ( 0 8  @  H  P X HH HtH5 % hhhhhhhhqha%] D%U D%M D%E D%= D%5 D%- D%% D% DH= H H9tH Ht H= H5 H)HHH?HHtHU HtfD= u+UH= Ht H= d} ]wAUH=tATUSHHG HH=`H=[HHH5VHIv11H5 1IHLHLHH5"A11H5 1ILHLHnLHH5 1H5 11HHHH[H]A\A]/H=HHU HHHff.HHHnff.HHHNHHdigestmetadataDigestDigest::BaseSHA256SHA384SHA512;8TT|DdzRx $FJ w?:*3$"Dp<\FIA A(D0 (G DBBL GNU  @0 @pL[kx t   o`     oPooo 0 @ P ` p GA$3a1 GA$3p1067  GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA$3p1067 r GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFY 2 GA+GLIBCXX_ASSERTIONSsha2.so-2.2.10-35.el8.x86_64.debug*h7zXZִF!t/']?Eh=ڊ2N!k& X9nG8hnvO~l,`5??agE>O YbR9xs9X~g`8K.cG#XJ26cg[hM(7,{=^p0Ow_iŷG&b>54O.&+,3=JV_.a KFT+sMĵ~8iS+Zk_l$1g J:ԑ{KhB Kο<){D6P6d'-ۘKaCM_xvg\J `ȮNJר-OQkJߢVQlaZq0ytObz=I zgYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``@( p08o4EoPP@T^B  h c  n w@ @ 2}t t 2 9 <       @   `` ` p ``  |$($h (+PK!a w  !2.2.0/x86_64-linux/digest/sha1.sonuȯELF>P @@8 @ 0 0 0 (8  @@888$$ Std Ptd ,,QtdRtd0 0 0 GNUuG1 :ȅ?pۤ B@ (sSBE|DVqXF"xj_  ,  PX ch U  WX __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeInit_sha1rb_requirerb_path2classrb_define_class_underrb_data_object_allocrb_ivar_setrb_intern2SHA1_InitSHA1_UpdateSHA1_FinishSHA1_Finallibruby.so.2.2libcrypto.so.10libssl.so.10libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64 t Fui h0  8  @ @             ( 0 8 @ H P  HH HtH5 % hhhhhhhhq%= D%5 D%- D%% D% D% D%  D% DH= H H9tHv Ht H= H5 H)HHH?HHtHE HtfD= u+UH= Ht H=^ de ]wUH=SHH=H=HHH5HH5 111HH5 HHtHHH[]H=UHH HHH>HHdigestDigestDigest::BaseSHA1metadata;(DDlzRx $FJ w?:*3$"D`,\EHD Z GAM GNU @ @`#.<Ft  0 8 o``   Xh o(ooo P`pGA$3a1 GA$3p1067 GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA$3p1067 GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realignsha1.so-2.2.10-35.el8.x86_64.debugB7zXZִF!t/7]?Eh=ڊ2Na?Ӈ[!HtM% Nmj= 6NP 6S[<]̓3ˍbsJ~c@ k^#ԜA+Qbh6{X"+ Wjg} H%8ۆkpf /z蛨V8]H˵.^LѺIoM3N}rҞ^ovD7-GBVe?lճ#XI@૆}re4w>#"f}ai(}'f#ѵN: KoӦ|y*:N~ ,~Kn(i2Kᴁ|N`b2.,W8oK_`9j# h`N|&B/oBfE2W{jN琋Fc>ikqן"ԐjTlsq=BbQ}#WR~$~*H\o?֪S09$~pgUiսiyAv;%Eu\bֱgYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``8( 0``8o&Eo((@Thh^BXXhc@@nwP P r} 2 ) ,( (  0 0 8 8 @ @ X  @   XX Xh`X $(LX+PK!5;  #2.2.0/x86_64-linux/digest/rmd160.sonuȯELF>` @@8 @ 0 0 0 (8  @@888$$ Std Ptd ,,QtdRtd0 0 0 GNUb=ClmRW$*HYD ABEb&|qXF"zla  , cX U vh jX  __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeInit_rmd160rb_requirerb_path2classrb_define_class_underrb_data_object_allocrb_ivar_setrb_intern2RIPEMD160_InitRIPEMD160_UpdateRMD160_FinishRIPEMD160_Finallibruby.so.2.2libcrypto.so.10libssl.so.10libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64Y ui {  t  0  8  @ @             ( 0 8 @ H  P  HH HtH5 % hhhhhhhhq%- D%% D% D% D%  D% D% D% DH= H H9tHf Ht H= H5 H)HHH?HHtH5 HtfD=} u+UH= Ht H=N dU ]wUH=SHH=H=HHH5HH5 111HH5 HHtHHH[]H=WHH HHHNHHdigestDigestDigest::BaseRMD160metadata;(DDlzRx $FJ w?:*3$"D`,\EHD Z GAM GNU @ @` &6AOY 0 0 8 o``   p o@ooo `pGA$3a10 GA$3p1067 GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA$3p1067 GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realignrmd160.so-2.2.10-35.el8.x86_64.debuglfȠ7zXZִF!t/7]?Eh=ڊ2N3LL.5r>a0grs$Cɪ+., .L_aӒ3Nf(MDՏv[v[~Rzr,uhvVqN8 p}]H2kߖF1$!Ck@qp:, DsbuWjG'Ԕ7L0R+p:(& *VcRb3R=E梦nN}(1^ 660cG!ֆ qƊ H"V\B0AJA*ITx_P){^ykI #um^L&6SU>z{{Qx šH9pNt,'=ٺloG4Ӿ\9/>Pegk4Kl{|/B䂀nNY…C[ˆCn& mBK`Qm0W#臲mbzAK׷ !CR|A29N'e'x.9Ųr}TQ#,wE&SUX5Ct.㶋%$܎Rcʪn4#g p$x ax٪|)סY 6F/DEiF'Uc)3feDgp/IҐw." r)曚ꇽYܱhrFu.L+(%IP*YŇL¢XHà\gl2(xpPfo G0]LgYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``8( 0``8o&Eo@@@T^Bpph00cPPnw` ` r} 2 + ,8 8  0 0 8 8 @ @ X  @   XX Xh`X $,PX+PK!~7  2.2.0/x86_64-linux/digest/md5.sonuȯELF>P @@8 @ 0 0 0 (8  @@888$$ Std Ptd ,,QtdRtd0 0 0 GNUi 9. %B ABE|_UqX+qZF"wi^  , KX ^h U  RX  __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeInit_md5rb_requirerb_path2classrb_define_class_underrb_data_object_allocrb_ivar_setrb_intern2MD5_InitMD5_UpdateMD5_FinishMD5_Finallibruby.so.2.2libcrypto.so.10libssl.so.10libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64A ui c t 0  8  @ @             ( 0 8 @ H  P  HH HtH5 % hhhhhhhhq%= D%5 D%- D%% D% D% D%  D% DH= H H9tHv Ht H= H5 H)HHH?HHtHE HtfD= u+UH= Ht H=^ de ]wUH=SHH=H=HHH5HH5 111HH5 HHtHHH[]H=THH HHHHHdigestDigestDigest::BaseMD5metadata;(DDlzRx $FJ w?:*3$"D`,\EHD Z GAM GNU @ @\)7Ao  0 8 o``   Xh o(ooo P`pGA$3a1 GA$3p1067 GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA$3p1067 GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realignmd5.so-2.2.10-35.el8.x86_64.debug 7zXZִF!t//]?Eh=ڊ2Na?Ӈs+ݒ&} S7 ֒[i=<"Ѩ+ajP 2.AݒP,.-Z7!UXˤ(A#*|j7w}$Ms< ?CF &~a.?M|-?(q7S`cۛaF08. O\RDX!y6 aSL?\HCҷ˛pnxw!sr?nd9:д8;_4)Zma= Fa\ &y~3qm%hోO9S[x$+QB_hgHTG6ma/SZWk5!>D񎱎{R>׸xdg#%Cx?wޒe@u(T ,Q H;|A&^gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``8( 0``8o&Eo((@Thh^BXXhc@@nwP P r} 2 ( ,( (  0 0 8 8 @ @ X  @   XX Xh`X $(LT+PK!2aa2.2.0/x86_64-linux/dbm.sonuȯELF>@Z@8 @KK LL L (P hMhM hM @@888$$hKhKhK StdhKhKhK PtdBBBLLQtdRtdLL L GNUXȧa^DG [,JH JLMBE|qX U s}V H d.6`II0Yhr{U)S v+: ?k-, &F"g> R @R R  :R__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizerb_check_typeddatadbm_closeruby_xfreerb_raiserb_hash_newdbm_firstkeydbm_fetchrb_tainted_str_newrb_hash_asetdbm_nextkeyrb_ary_newrb_assoc_newrb_ary_pushrb_string_valuerb_check_safe_objrb_str_exportmemcmprb_block_callrb_intern2rb_error_frozendbm_deleterb_hash_delete_ifrb_yieldrb_ary_tmp_newrb_str_duprb_protectrb_gc_writebarrier_unprotectrb_ary_clearrb_freeze_singleton_class__stack_chk_failrb_jump_tagrb_block_given_prb_ary_new_caparb_warnrb_obj_as_stringdbm_storedbm_clearerr__errno_locationrb_sys_failrb_out_of_intrb_check_typerb_eArgErrorrb_data_typed_object_allocrb_frame_this_funcrb_id2symrb_enumeratorize_with_sizerb_scan_argsrb_eIndexErrorrb_get_pathdbm_openrb_fix2intdbm_pagfnorb_fd_fix_cloexecdbm_dirfnoruby_xmallocrb_num2intrb_sys_fail_strrb_ensureInit_dbmrb_cObjectrb_define_classrb_eStandardErrorrb_mEnumerablerb_include_modulerb_define_alloc_funcrb_define_singleton_methodrb_define_methodrb_define_constgdbm_versionrb_str_new_cstrlibruby.so.2.2libgdbm_compat.so.4libgdbm.so.6libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5GLIBC_2.4/opt/alt/openssl/lib64:/opt/alt/ruby22/lib640ui ii zui L ` L  M M M A0M  8M p O O O $O &O 1O 3O =O >O ?O AO BP  P (P 0P 8P @P HP  PP  XP  `P  hP  pP xP P P P P P P P P P P P P P P P P Q  Q !Q "Q # Q %(Q &0Q '8Q (@Q )HQ *PQ +XQ ,`Q -hQ .pQ /xQ 0Q 2Q 4Q 5Q 6Q 7Q 8Q 9Q :Q ;Q <Q @Q BQ CQ DQ EQ FR GR HR IHH)8 HtH5b8 %c8 hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?%]4 D%U4 D%M4 D%E4 D%=4 D%54 D%-4 D%%4 D%4 D%4 D% 4 D%4 D%3 D%3 D%3 D%3 D%3 D%3 D%3 D%3 D%3 D%3 D%3 D%3 D%3 D%3 D%3 D%3 D%}3 D%u3 D%m3 D%e3 D%]3 D%U3 D%M3 D%E3 D%=3 D%53 D%-3 D%%3 D%3 D%3 D% 3 D%3 D%2 D%2 D%2 D%2 D%2 D%2 D%2 D%2 D%2 D%2 D%2 D%2 D%2 D%2 D%2 D%2 D%}2 D%u2 D%m2 D%e2 DH=a2 HZ2 H9tH/ Ht H=12 H5*2 H)HHH?HHtH/ HtfD=1 u+UH=/ Ht H=, d1 ]w1HHff.@HH5, HtHxHHHfDHtSHHHt%H[,@PXH5?1HH=1 DAVH5+ AUATUS(HtL`Mtv5LI:HHHtOHHLzHcHHcHIqLLHL{HHHu[L]A\A]A^?ff.@AWAVAUATUSHHH5/+ HIdHtL`MtvL~HHHtQHHLHcHIIIcLHHLHELHHHuHL[]A\A]A^A_{ff.HH5* Ht0HxHt'H8xuH@Ht1H"fATH53* USlHthHhIHt\HH~[HD]A\fHhHt+1ېHHuHcHDI$[]A\1f.SH5) Ht HxHHtyHC[UDAVH5c) AUATUSHL`MtzqLIHHHtSHHLHcHHcHILHLH[LHHHu[L]A\A]A^UH5( SHHt]HXHtTHHHt5HHEHcHJHHHWHuHH[]#UH54( SHjHtRHXHtIGHH|Ht*HcHHHZHHuHH[]ff.ATUHSHH|$Ht$H|$H|$HHD$ uIHL`H5o' HHtNHxHtELHHu'H1[]A\@HHHcH9uL`@H[]A\ff.fSHHH|$Ht$H|$H|$QHHD$ u$HHHcH9tH1[f.H@HcH9uH5& HHHXHtyHHu1@H9uHHcHt=H:HtHHHt$H t9VuHvHcHiuH[DATUSHHH|$Ht$H|$H|$>HHD$ u!HHHcH9tH[]A\ÐH@HcH9uH5}% HHHhHHHIHu?f.HHH9u HtKHHIHnHLHHt$HcH tH;VuHvH=uIcHH[]A\UHSHHH5) Ht$IHL 11>HH[]@ H=HHe) @uHtHƒtuHH=uff.AWAVAUATUSHHH5# H7HHXHHHBHIHtWHHIcHIIIcLI}HHLILHLL[]A\A]A^A_cH[]A\A]A^A_7HCHHWAWAVAUATIUSHFH5# LIDHHhHHVIHHL-" 6fDLLHHhHt}HIHHtXHLHZHcH_HcLHQHHVHH HtHL{HL[]A\A]A^A_ fAWAVAUATUSHHHH|$1dH%(HD$81HD$4H|H5! H HfL`IMVHILHD$( IHAH+HD$4HD$ KH|$H5l! IHL`MLFIHAHHDLLH!H HIcLHT$HD$HT$Iu2Ht*HtHI}IMt SH|$HcLILHHT$ H=1# HIT$4u!HLHDIE1gHL9~lHHHE HEJH HHrL!LIH HHE uHEL9|$4HL$(H~H)IHHD$HL$8dH3 %(u[HH[]A\A]A^A_HrB}@HE PfLHT$9H=b$ H51f.AVAUATIUSHHt$H|$)H|$H|$uHHD$ HHhH5 LIHLpMHHLqHtDHcHqHHLI@upIEHxHIEHL[]A\A]A^CAtH|$HI[]LA\A]A^@HHHcH9uHh8H=# IEH5<1ff.@AUATIUHSHH|$Ht$H|$H|$-HHD$ HLhH5 LHHxHLH/Ht"HcH/HHH[]A\A]fDHutH|$_HD$uHtHу~0HHHHHHcH9uLh@Hrff.@fAUHcATIIUSHHHE~-AELlH3LH|HHL9uHH[]A\A]ff.U1HSHH=HHHH[]AWIAVAUATUHSHHHHH HI HHkHcH9M$A txMt$MD$IcI9H5{ LEHLxMHLMHAHLiu5HL[]A\A]A^A_IMt$A냐HkHSPLx8tH= H581f1HlLd@ATUHSH8H |HHHHH uEHC HHL HH tAHH3LH*[]A\HCDH{fDH[ H H5P H81ff.fH 1^ff.ATIUS@H5 LHt]HXHHtQHHH%uHHuHEL[]A\H=M H5| 1 f.UHSHH[H5  Ht'IHLB11HH[] H= HH ff.USHHtzH5 HHHxHt~HtEH-h HcH5HHHHtBHxHt9/HuHH[]KHHHE1[11H]fDATUHSH5 H HHXHHHtRL% HH]HcHbH*LHHtEHXHtݐ ~BNBXPjSTpz'mjF>ia(f?},HYϛq~ת1b=i)&WѰk_~+@*G1+A;;.O\k[X_] T!do5E#!z>eT7񦀗^NUU&ԮS}+p(cCKpl$)k{VS;eq+S٥֐C^xH:Se-ЉhBtI\ئ|-g} d5P= *tpPQst1S#k$ܘ 2yjZahZ 4Kf-_^۷p`d΅vi Yb!-b;GK\iYOkw7_Q=9u@lseVo"-JS uRu1%Ɏo$Wvڼ-b8RF߲?7wI'4#%CoP|bi ˮg]]Qu 9ʴmb({'o޾Pt z+3"(v 9e"VkOW?MT!2ti&{hYgsm+m:a;D/bҡ: T_^m{%XԔ.c QT&[抂Z -%ڬZ&6/}D9?Wu? &/gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( P0 8oEoPT^Bhcnw }4@4@ 2H@H@BBLXCXC hKhK L LL LM Mh hM hM@O OXP PR R(@R`RH `T(TXY+PK!]LQC2.2.0/x86_64-linux/sdbm.sonuȯELF> @H{@8 @bb mm m (p mm m  888$$bbb Stdbbb PtdUUUQtdRtdmm m GNU eЏ] 3DA$ DHOBE|Ϲ = %2?ѣnVqX?~G*ŤZx|[!y <3A nU`P6w#m[oj (v}V0:\, U}F"JyI8r \r  +3 @)fPr  *5 +d pMP8r  @+2 p1 `* , '__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizefcntlreadlseeknullitemmemcmpmemcpymemmovesdbm_prep__fxstat__errno_location__stack_chk_failsdbm_openstrlensdbm_closesdbm_firstkeysdbm_nextkeysdbm_hashsdbm_fetchsdbm_deletewritesdbm_storerb_check_typeddataruby_xfreerb_raiserb_hash_newrb_external_str_newrb_hash_asetrb_ary_newrb_assoc_newrb_ary_pushrb_string_valuerb_check_safe_objrb_str_exportrb_out_of_intrb_block_callrb_intern2rb_error_frozenrb_hash_delete_ifrb_yieldrb_str_duprb_protectrb_gc_writebarrier_unprotectrb_jump_tagrb_block_given_prb_ary_new_caparb_warnrb_sys_failrb_check_typerb_eArgErrorrb_scan_argsrb_get_pathrb_num2intruby_xmallocrb_fix2intrb_sys_fail_strrb_data_typed_object_allocrb_ensurerb_frame_this_funcrb_id2symrb_enumeratorize_with_sizerb_eIndexErrorInit_sdbmrb_cObjectrb_define_classrb_eStandardErrorrb_mEnumerablerb_include_modulerb_define_alloc_funcrb_define_singleton_methodrb_define_methodlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5GLIBC_2.14GLIBC_2.4/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64  ui a?mii xui am !m P! m  m @m TPm 3Xm P3o Ho o o !o #o -o 8o 9o :o <o =p  p (p 0p 8p @p Hp  Pp  Xp  `p  hp  pp xp p Op Ip p p p p p p p p p p Pp p p Jq q q q  q  (q "0q #8q $@q %Hq QPq &Xq '`q (hq )pq *xq +q Fq ,q Mq .q /q 0q 1q Gq 2q 3q 4q 5q 6q 7q ;q Nr =r >r ?r @ r A(r B0r CHHW HtH5W %W hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?h@hAhBhC%mS D%eS D%]S D%US D%MS D%ES D%=S D%5S D%-S D%%S D%S D%S D% S D%S D%R D%R D%R D%R D%R D%R D%R D%R D%R D%R D%R D%R D%R D%R D%R D%R D%}R D%uR D%mR D%eR D%]R D%UR D%MR D%ER D%=R D%5R D%-R D%%R D%R D%R D% R D%R D%Q D%Q D%Q D%Q D%Q D%Q D%Q D%Q D%Q D%Q D%Q D%Q D%Q D%Q D%Q D%Q D%}Q D%uQ D%mQ D%eQ D%]Q D%UQ DH=QQ HJQ H9tHN Ht H=!Q H5Q H)HHH?HHtHN HtfD=P u+UH=N Ht H=K dP ]w1vftwHGfHOf9|?~#5D89'D@fD9|A9DHٸ1ff.fS1t ~t 1[߾1[AWHHIAVAUE1ATU1SHHD$1HHE1fDHt$A?HM@HLH?H?H4H=HÁH)IDAHH)skHDAT$HNlhM9oAMI]MIIHMMIIM;@tLA?1H aH8IcH.HH!MoIG I9o8uH[]A\A]A^A_Mg@IH1HHLH 1H)IG@ILJ8HAHx.ALuHxLt Io8w1mHcH&.HH!Cf.UHo@SHHfDD9HcȺH4 ~T5HDMHH)Hu}HC({C HpHs(H9C8tH 1 Hx_Hs({Hs8HH~BHt6C S@C f`HJ HRHtH[]HyJ KHHRH[]ff.@AWAVAUATUSH~}LcHT$IMHl6fAD]HH9tAIT]A)HD9uH|$LLuHD[]A\A]A^A_E1ff.AUATIUHSHL/fE~Bo)Ӆu.IEf\EL,D)Eu9fB\-fEH[]A\A]HcHcDD$ HDD$ fDHcIcLHwDAWAVAUATUSHH/HHA1EEIA9McAJ|{H|$IGB cCL,D)L)LHcLH)H)HHgL$JD+HtkD)DPHfPH9uD#AfD#H[]A\A]A^A_DHD$eDAVIHAUIATAUSHdH%(H$1UHHYH@ H@(HH@@DL1CDL13HHD$01ҹHC8HHHHC1H@HS@HHHHHHH$dH3 %(HujHĠ[]A\A]A^D D{tK;t?H1{ufD nff.AWAVAUATUSHt$ H?HALxHK{HHx)HC8HHC(C H[]\@HD KHPHH[]H~D HPHH[]HtfHHBD HPHHff.t(FHL1fDHHi3WHH9u1ff.fAUATIUSHHuHHHt@HDHzHHouKHC KHHRH[]A\A]fDHtC HHRH[]A\A]@s@t8Lk@DHLt"HHTHD@T>HL)fDHC HR뢐AVHAUIATUSHHouzIDLHHtMLs@DLL{t_Hs8{1H Hx {LHx []A\A]A^ÃKDfDƐ{ff.AWAVAUATLg@USHHhHt$L$PLt$PT$HdH%(H$X1HHD$L HD$8HGHHD$@LLHk HHI$Ht$8L}HFH|$@HHLH)HLH$PfImL|$(H\$0ILIDHD$ fMIOD)N, LHȉHL)HL$T$LHD$(AIET$HL$LIAWL;|$ uIH\$0Hk L}HD${H!L L+Hs81H H{LHHk8H{HILHLI$H)IH)΁H8HLC;MIhIIIHMIIHIHL$I H;@tQ1LLD$ LL$H8;HHHHL$;LD$ LL$H@HH?H4HŁH)LH?H=I H)+HHCI9| HHC1L}H;HHHHK@~ALt$HT )ЍV9HC Hs1ɋ{HPHT$H 1HLqHC Hs8HKH Hx#{LCHxl$L1H$XdH3%(uRHh[]A\A]A^A_fH1H Hx{LHf4@AWAVAUATIUDSH(Hu!HHt_G4Av*5H([]A\A]A^A_fIDIDL$ LL$vHHHD$fDL$ HE@L$HD$At^DU@EfE~jDLDLD$H}@DT$ D$\fD{ADLHDU@L$EѸECT)AV9}Ht$DHL$L$tEDLH}@LHu8}1H Hx}Hu@HfMfD$DL$ LD$MHE@BH`1HtHHH%HXHH59 HtHxHHHfDSHHHtH[!PXH51HH=> DAVH5C9 AUATUSHHtL`MtvLIJHHHtOHHLHcHoHcHIaLLH3LHHHu[L]A\A]A^?ff.@AWAVAUATUSHHH58 HIHtL`MtvLHHHtQHHLbHcHIIIcLHHLHuL]HHHuHL[]A\A]A^A_{ff.HH57 Ht0HxHt'xuH@Ht1H"fATH57 USHt`L`HMtTHc~[HD]A\f.LxHt#1ېLHuHcHD][]A\ø1fSH57 Ht HxHHt)HC[eDAVH56 AUATUSHL`MtzLIHHHtSHHLHcHHcHILHFLHLHHHu[L]A\A]A^UH56 SHHt]HXHtTHHHt5HHHcHJHHOHHuHH[]3UH55 SHHtRHXHtIWHHHt*HcHHHHHuHH[]ff.SHHH|$Ht$H|$H|$H8HD$ HHcH9H54 HHHXHHHuDHLcL99uHuDHHHtDHHtDHHiHt$HHρ tHNHvHHquH[fH1[Hx!Hzf.ATUHSHH|$Ht$H|$xH|$>HHD$ uYHL`HcH9uUH53 HHt:HxHt1LHHHHH[]A\fDL`HPHATUSHHH|$Ht$H|$H|$H8HD$ HHcH9H52 HHHhHHHIHu6}DHHH9u HtGHHIHtIHLH{Ht$HcH tH;VuHvHuIcHH[]A\ÐH[]A\fHx$ff.fUHSHHH56 Ht$IHL' 11>HH[]@ H=HH6 @uHtHƒtuHH=ff.AWAVAUATUSHHH5/1 H7HHXIHH6HIHtkHHIcHIHT$]HT$LIHcJHLHIA$xA$HLL[]A\A]A^A_H[]A\A]A^A_HHH'AWAVAUATIUSHH5/0 LI4HHhHH6IHHL-/ 6fDLLHHhHt}HIHHtXHLHHcHHcLHHHvHH HtHL{HL[]A\A]A^A_fAWAVAUATUSHHXH|$dH%(HD$H1HD$<HnH5. HH|LhIMlALD$,IHAHHD$H<$5DH$ 1ff.ATI1UHH$ SbLHHHtwuH[]A\H[]A\H=& HH[H3]A\ff.ATIUSH5$ L!Ht\HXHHtPHHuH HuEL[]A\H=( H5 1P;ff.UHSHH[H5( Ht'IHL11HH[] H=} HHe( ff.USHHtzH5# HHHxHt~$HtEH-" HcHUH]HHHtBHxHt9HuHH[]HCHHE1[11H]kfDATUHS`H5Q" HYHHXHH[HtRL%" HH-HcHHLHHtEHXHtH5H=" 1HH5H=" 1HH5H=" 1H H5mnH=" 1H.H5\RH=" 1HH5l6H=g" 1HH5-H=K" 1HH5H=/" 1HH5H=" HH5H=! 1HsH5H=! 1HWH5H=! 1H H5oH=! 1H/H5SH=! 1HH57H=h! H4H5jH=I! HeH5RH=*! HH5;H= ! HH5%H= HH5H= HH5}H= HJH5^H= H+H5?H=p 1H_H5#H=T 1HH5HHH????closed SDBM fileeach_pairSDBMsdbm_delete failedsdbm_store failedpair must be [key, value]11key not foundSDBMErroropeninitializecloseclosed?[]fetch[]=storeindexselectvalues_atlengthsizeempty?eacheach_valueeach_keykeysvaluesshiftdeletedelete_ifreject!rejectclearinvertupdatereplacehas_key?include?member?has_value?to_ato_hashsdbmSDBM#index is deprecated; use SDBM#key;9P0 DpdPP0l@ L`l@(hpPp<Xt` 0Xpt  `8lPT l  `` P `  t p 0 `  d p zRx $XPFJ w?:*3$"D@\hspHA_ H THBLB E(A0C8DP 8C0A(B BBBD 0AEG  AAH VAAHdBBB B(A0A8DPl 8D0A(B BBBI 8\BBD D(I@y (A ABBD H BBB B(A0A8DP 8A0A(B BBBF DFJE D(C0G' 0A(A BBBF H,8FBB B(A0A8DP 8D0A(B BBBH x5E[ H L<EAD  AAI V AAH ]AA2T]3LFDG A(D0E (A ABBG ] (A ABBE <TpHHH C(A0z (C BBBA L BBB B(E0A8Jt 8A0A(B BBBJ LFBB B(D0D8D`B 8C0A(B BBBJ 4@ HL:H] K IhlEUpAAM<tFIB A(A0~ (D BBBA HFBB B(A0A8G@ 8D0A(B BBBA ,XNHk E P A 4L~FHA ^ FBK l ABA ;Ep A <FIB A(A0 (D BBBA (d}EHD a DAA ( rEHD V DAA (8 6EG  FC D CI 0d FAD D0x  DAEG @3FAA G0  AABB D  FABC (]EDG f DAE 2f`FBB B(A0A8GP 8G0A(B BBBF D 8F0A(B BBBA tHIH|FBB B(D0A8D@ 8D0A(B BBBA L@FBB B(A0A8G 8A0A(B BBBG T4MFBB A(D0D@ 0D(A BBBF m 0D(A EBBA @BEE A(A0D@ 0D(A BBBF 4bFEG A(G0~(D ABB$ /EFN IGAXD FEB A(A0D@E 0D(A BBBE T 0D(A BBBA , $FAI w FBA 0 FAA N@  AABH  @ uFFM h ABD I ABD NHB,\ FDA \ ABA ( 8eEDG k DAH 4 |EAG } DAA Q GHE 8 FAD  ABE N GIE `, "FBB E(A0A8D@ 8D0A(B BBBK Q 8G0C(D EBBE ( dEKF@P AAH  HGNU!P! m T3P3 '5? ( @Rm m o`x   p `0 ooo(om `p 0@P`p 0@P`p 0@P`p 0@P`pGA$3a1(MR GA$3p1067!=RGA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFY!p3GA+GLIBCXX_ASSERTIONSsdbm.so-2.2.10-35.el8.x86_64.debug;{7zXZִF!t/2]?Eh=ڊ2N$:~Xo/#[oخ_3u$>f; ||Tj]>%8Bb`yVԃxBǼ2Fyu&,[Ҕnyl@'|Q:-e R2JfK~Ϧ c1qSE&uvdRl=,,K>GO F.RBT(=J9aW$jsJ(:h% Om%;T&&ﰣ oƝ`m*ӬB<‚q.Jc?R:5:#VM29R"3tȖ.oGz~K7W(~*4&3x6A8CO5Įج gc h\ y"Tr!bG28辴z-&B+hPˣYo6=gmN)\)aBg(x3(\},# -%I00UIH+b5Hk,-k\ [n9L46Jd&xBqMG[ f49[ݬsZj jjQCjUOukWh[ֿ-x5\JpJѓ2 * mlA:}o cnW00\6(&m6'vB4 QU~2U{൵EhRByA5p[iA$dWoSjh24.m A]0oRAM_”>g)Mt:0+hJrKf-Vy2)׬$ӚʿS9 m܁jwcim>#4tx  +RgYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``d( 0x x 8o((Eo`T00^B`h((cPPPn@w ]1}@R@R `R`R UUVV bb m mm m m mh m m o oXp p8@r 8r@r`8rH t(ttz+PK!"2.2.0/x86_64-linux/continuation.sonuȯELF>@@8 @XX     888$$888 Std888 Ptd$$QtdRtd XXGNU ~4g09HM}gaC  BE|qX4 o , gF"0 8 0 U @__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeInit_continuationrb_warnruby_Init_Continuation_bodylibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ui  0          ( HH HtH5 % hhh% D% D% DH= H H9tHF Ht H=y H5r H)HHH?HHtH HtfD=5 u+UH= Ht H= Yd ]wHH=!1 HHHcallcc is obsolete; use Fiber instead;$x@hzRx $0@FJ w?:*3$"DH0\ HRGNU0   `  o` (  H oooo 0@GA$3a1m GA$3p1067@_GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realigncontinuation.so-2.2.10-35.el8.x86_64.debug:7zXZִF!t/]?Eh=ڊ2N{n I3ǰU d0QD9( Ƈr]a*fAaEOhGyOӏ $jUk'#A/km5WovPt\4F8տm9ShOX}B3?l36uc@]? /M>E`miio9 I[Qo~o:l3.qdGeݔÎSS4YQE>@g 2* `Ro$bnP d)w>[8Y aaٲghX;$LZ)t؇BV;F6 .R [֦yX^m#GuR VHL"V4%詼'dݑ@\w$݃e$({qw0.Ɓcy2R`Mc,uƔfv&MKQ݈Nb&~aokmF<)l(.=;,!ǂeJV*X`vq_!Twc<'pg'A%uFe#yQ{X`XgA8+35M:[ʝ4SRۓǮQ1.6KiZ;d"xh4}D%LpHm_Y^"BlYu೵m4kxoJ@8K|٫[nY`@ ̣8gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 0(8oEo T^BHhc@nPP0w}`` 2pp($t88        00 08`0 (0XD+PK!0``2.2.0/x86_64-linux/zlib.sonuȯELF><@ @8 @    (( ( 00888$$ Std PtdhhhQtdRtd  GNUYe%Ѵ!I玥@ BE|qX)hVV7# NY 'b\f`KQh8U/xdsi~YI (Q>5<E]'"sDmE <k<~zwtG1, 8vVbF"V0o$)  3  '  w __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizerb_check_typeddataruby_xfreerb_gc_markrb_eNoMethodErrorrb_eEOFErrorrb_rescue2rb_errinforb_obj_is_kind_ofrb_funcallrb_check_typerb_str_resizerb_cStringrb_obj_revealrb_block_given_prb_str_new_staticrb_yieldrb_str_newmemmoverb_uint2inumrb_protect__stack_chk_failrb_thread_call_with_gvlruby_xreallocrb_exc_new_cstrrb_exc_raiserb_sys_failrb_sprintfrb_exc_new_strzErrorrb_enc_dummy_prb_str_conv_enc_optsrb_econv_str_convertrb_enc_associateruby_xmalloc2memcpyrb_str_buf_newrb_str_catrb_obj_hiderb_scan_argsrb_fix2intinflateInit2_rb_io_extract_encoding_optionrb_econv_prepare_optsrb_econv_open_optsrb_ensurerb_warningruby_xcallocrb_data_typed_object_alloccrc32rb_default_external_encodingrb_class_new_instancerb_io_closerb_jump_tagtimerb_check_convert_typedeflateInit2_rb_respond_torb_define_singleton_methodrb_call_superrb_attr_getrb_str_inspectrb_str_appendrb_string_valuerb_num2ulongrb_ivar_getadler32rb_hash_asetrb_hash_newrb_ivar_setinflateInit_deflateInit_get_crc_tablerb_ary_new_caparb_ary_pushcrc32_combinerb_num2longrb_uint2bigadler32_combinezlibVersionrb_str_new_cstrstderr__fprintf_chkrb_raiserb_int2inumrb_econv_closerb_str_duprb_time_newinflateSetDictionaryrb_out_of_intinflateSyncPointdeflateSetDictionarydeflateCopyrb_str_resurrectinflateSyncrb_file_open_strrb_eArgErrorrb_str_to_strmemchrrb_Integerrb_num2uintrb_frame_this_funcrb_id2symrb_enumeratorize_with_sizerb_hash_arefrb_thread_call_without_gvlonigenc_get_left_adjust_char_headrb_enc_precise_mbclenrb_warnrb_enumeratorizerb_intern2rb_num2intrb_rsrb_eRuntimeErrormemcmprb_check_string_typerb_ary_newrb_lastline_setrb_enc_mbclenrb_econv_convertrb_econv_check_errorrb_obj_as_stringrb_ascii8bit_encodingrb_enc_getrb_str_conv_encdeflateParamsInit_zlibrb_define_modulerb_eStandardErrorrb_define_class_underrb_define_module_functionrb_define_constrb_cObjectrb_undef_alloc_funcrb_define_methodrb_define_alloc_funcrb_define_attrrb_mEnumerablerb_include_modulerb_io_addstrrb_io_printfrb_io_printrb_io_putsinflateResetinflateEndinflatedeflateResetdeflateEnddeflatelibruby.so.2.2libz.so.1libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.3.4GLIBC_2.14GLIBC_2.2.5GLIBC_2.4ZLIB_1.2.2/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64 Pti 8 D ui O ii [ 'e  < <  @ H >P ZX `=  `> [ P= x P   ( ^ *X ` h p x    ! 9 H J T j k v y       ( 0 8 @ H  P  X  `  h p x              " # $ % & ' ) + ,( -0 .8 /@ 0H 1P 2X 3` 4h 5p 6x 7 8 : ; < = > ? @ A B C D E F G I J K L M N( O0 Q8 R@ SH UP VX W` Xh Yp Zx [ \ ] _ ` a b c d e f g h i l m n o p q r s( t0 u8 w@ zH {P |X }` ~h p x                   HH HtH5 % hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?h@hAhBhChDhEhFhGqhHahIQhJAhK1hL!hMhNhOhPhQhRhShThUhVhWqhXahYQhZAh[1h\!h]h^h_h`hahbhchdhehfhgqhhahiQhjAhk1hl!hmhnhohphqhrhshthuhvhwqhxahyQhzAh{1h|!h}h~% D% D%ݫ D%ի D%ͫ D%ū D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D%ݪ D%ժ D%ͪ D%Ū D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D%ݩ D%թ D%ͩ D%ũ D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D%ݨ D%ը D%ͨ D%Ũ D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% DH= H H9tH. Ht H=ɧ H5§ H)HHH?HHtHm HtfD= u+UH=Z Ht H=~ d] ]wAVAUIHATAUHSHL9~"AHL)LAHL9H~H[L]A\A]A^[H]A\A]A^@G @fDHHHHfDHH5 HHHH5 HHEHÐHH5 HHHHHH5 |HPHtH uH >HHDHcBHHDfH@SHH/H{[%DSHH HHH{H{HH[fHHHʠ HjH&H=LH L1HfDUHSHH HtHH޻$HuHH[]DHH5R 1HHtHǾKHH[]ÐSH5 1H<HH H[ATUSHLgpHkHHsHHk HH0@u*Ht!HUЃHHCHCHC8C@tH= HH=ɟ H=ß vH= hH= ZH= LHH= 6HH=jh1H= HRuhHHH[H)]aHPH9HH)H@HwH[H)]&fDATUSHHHH{tsHCH t3H@(HD HC0H9uCHL9u$[]A\ÐhHH=H~ H5N12H=+~ H5N1H5&~ HGzf.HH5u HHуHuMHxuFtNHxHt4_u0Ht(HуHrHHfDHHD$HD$ff.Ht %H Gt @HHff.fAUATUSHHHt$%Iu HH|$Ht$H HHnID$HtLH HPIT$ H9PHNPAT$(I|$ =ID$IH~1Il$ I|$ H9HOA\$(1H[]A\A]HHID$ HЃH @HD$HH%H HfDH^HnID$H0 uhHAD$(Ml$LH),HHLH[]A\A]fDAT$(It$ I|$f.HpIt$Pnff.AUH53s IATUSHHXHHt^L%u HI4$SHEI4$H?u!HtHЃ4Hs)HH[]A\A]11L%u HAuItIEt%H HfDUH1SHHmHEHEHPH tHPHU8HH9HOډ]@H[]/ff.@HGHt^W@H9uDUHSHHHwHHHCH t0H@HCH9HC8HNs@H[]fD3Hf.USHHnHHHHHcKHH[]ÐH SHwu#HtHу~nHHH5*y H1S u[@HH5x tHH5x 11[fHrATUS~0HH5RBIH;=LHމH[]A\Hs H5HH81ff.PXH5B1HH=x DAUATIUSH*@ujLHHHH t?HPLh1LHtL)HHHHL[]A\A]DHLhVfDAUATIUSH@ujLHJHHH t?HPLh1LHtL)HHrHHL[]A\A]DHLhfDUHSH@u'HHHHHH[]}ff.fSHH?HE111H[ff.PXH5^@HHq H812fATE1USHH dH%(HD$1Hl$~HHx1LL)`HHOHD$HHSH: HIHl$HT$H uaHHpH{HCH uHPHx1L)LHxHL$dH3 %(u=H []A\fDHPHpfDLbtH=8u H5D?1=ff.fUSHHHH5u HǃHǃHHǃuH[]H5t HH1[1]ff.@SHHgH[fHH5!l luHDH0HfDATUSHHHdH%(HD$1HHHH tQHGHkH)H=?~TC@@HHHHS8HD$dH3%(H[]A\fDHHkH)H=?H%IIJt%H@ANHSHkC@H HrHRmHsH?H{HkpD$UHm H{H0RHs@uHHt?HЃ@u(HtHEt%H HfDH=m HT$HCH߾@|$fHf.H{-H#SfD@HH)H5HQAWAVAUATUSHHHdH%(HD$81H|$ HD$L$(HD$,H{D$4u H)H{HSH HBHC H9BHNBHT$S@C(HCLd$ AH$YD`L{pMSH5q LsHH$HH H HLLHzLH=HAŃuEt C@tH HCS(v``Hs H<$NfDHJHHK S@H:C(HC HfuK|$0uqHD$8dH3%(ufHH[]A\A]A^A_HT$H4$GHT$H4$HHs H{HD$HD$HD$HsPD>fSHH_fDtCHD$H HD$HHHD$H ufHt$HH`HCHpugHzHD$HD$HtJHD$H HD$tHxpHD$HpDHPtt HCH[H=n H581茾ff.USHHHuHHtH{uH11[]SHHHtHHH@u)Ht HEƒ HrHEHHH[]IfHH11[]ɾfH[]@UHSHHxqt@HHHGu%H9 #DH9}HHHCtHtH9HOH[]ÁHuHHD$xHD$Hh HH5R7H81fDAUIATUHSHH_H uCHMeIH+HILbHH)HH9$HH[]A\A]fDH[f.ILH޽HcH|HHHOH[H]A\A]DHLHHHHOff.USHHHtMxHHHHuHH[]HHHHH[]H11[]ѼHHvHtH tH@H%HHHfSHuDHоHHu[H[S1HH=;u!H=j Ht%H11H[H[wH=55 HHmj HHtHSATIUHSHdH%(HD$1HLHH31>H<$HtD@u.IHcHx@H H\$dH3%(u#H[]A\fH1Hre HH524H81fDATUSHHt HHH{ut[]A\HCHPH uGHL1DHH9C~>< HctH-[LHH]A\+HPHL@HLHHH{t!HH{utKHCHPH ZHPQfAWAVAUATIUHSHHdH%(HD$81HH@D$$Hc HHD$(HD$(IHHD$(H HD$(tUHxuVHD$(H HD$(H@H$HD$(H HD$(]L D$IA.tHAHT2D$H$L{M9D@HHL{M9+tM~LHoHL$8dH3 %(IHH[]A\A]A^A_@Ll$(LD$0LLH018H|$0HD$(HH"@9HIMHD$(HMLH^H|$~L9|H{DLHHHHHHrHH3fLKI /MIMM9~/PHLKI ILL)IT$tdL{MH $@M91@ @l$>LLLL$L)HgLL$HH>MwM9nT$uHT$(H _HHH9$vL9mH` H5/H81艵fHH uH„ILt$(IFH$fDHxfDLH|$0Ht@IHHILLLL$L)H)LL$HH2HL)IItYH4$LH*tFLMI fMI"H$H9BHBfM9D$|$~|$tM9|uLHIƃLHHHtD$uoHHT@/fDL`D$HH|$(茴Ht(HD$(H|$0|HM6H^ H|$(HH|$0HD$(E11Wmff.fAUAATIUHSHHHH轸HLDHuHH[]A\A]ff.ATAUHSH*u,@H(HHDHuH[]A\@H[]A\ff.AT1IUHSH=o3Ҹ轸u)H=a Ht5HL[H]A\$@LH[]A\?H=v, HHa ff.HHtHHD$耱HD$HfDSHuKHHMH[ATUSHH HWdH%(HD$1HHchHu(H9|*H9k}HHtHSHHtHhHCHH0 tRHxHpHJHHcHtYHH.HHL$dH3 %(H]H []A\HHxHu H@fLMHkHE HHSHL$MD$ HAHt$Hl$HLd$訶HHt$HH)謼HHHHt$HL)HHH耰@HHEƒ~3HEHm< WIHHrfHHHSH胵u-DH耲HHHpHu[H[WHH;HtH[ff.AVAUIH5^V ATIUHSH dH%(HD$1HD$耰HL$LHH(LD$1 H{ pH'足HD$H  HHrHCH H@8TxJPgPx PǃHLk LH@ @@?HCHtH TSHt$HH57] H|$EHL$dH3 %(LH []A\A]A^fH҃ f.HCHSH{H HH)HI蠲Hu5Ht-HуHrDHf.IvLHHH{H MHH)HH Hu0Ht(Hу HrHf.HuL45HHCH H@D0HILLLHH5:[ 11虬1HLHH5$誯DHx11Hf.HYH)HH5Z H{H$H=Z H5$]H=nZ H5+1HHsP荺H=NZ H5+1(H=9Z H5+1H=$Z H5$1)fATIUHSH@tNH t8HH=T HLH HLHHHH[]A\p+fATUSHHu HHHLMt*/I9t HL{HLH-HH t2HSHsHH u5H []>A\Hf.HHsHH tHC[]A\HDGMff.fAUIATAHUHSHdH%(HD$1DHLHH!1'H<$Ht]裫H<$蚯uIHHH5NX IuEHT$dH3%(HuKH[]A\A]1H5:"H HH5W 119ҨfSHHdH%(HD$1@tg1H5!HHHߋ$C0D$H HHL$dH3 %(uH[H<$HtD躩H<$豭u0H裱H\$dH3%(u+H[]A\f.1H5j H:#UHSHHt$HtLH|$谧Ht$Ht uOHHHG uSHHuD1H5H[]fDHVHvHH[]HVHDUHSHHu!HtHЃ-Hs"H"H1HHH[]@uHtHEt%H Hff.AUIATAHUSHH(dH%(HD$1HL$LDHLD$H1@u HuZH|$1Ht諧H|$衫Ht$H2H芯HL$dH3 %(u`H([]A\A]HЃ HrHD$uHyHh%H HXդDSHwHH u$HHH߹H[ۮHVHvff.Sf1H5HHmH[键@AWAVAUIATAUHSHHItLWLOAE1HtH6H.ALs DDk@LV+k@Hku9L=c$1L薢H^DDLk@+k@HktхuH[]A\A]A^A_HsP莲ff.SHHHt$HtMH|$Ht$H t&HVH~MHvH,H[fDHt7Hؐ1H5*H[C(uK(tUSHHHt$Ht$Hu Hu[EHuHH[]fH|$Ht$H HVHvH赳HH[]HЃ Hr@uHzHi%H HY@HESHnHH[]@HHcATUSHIHHt$Ht$HAu HE'HH|$ Ht$H :HHH觲11HH0HH҃MHHуtwH H0iHЃH+@@HH%H HH蘪H[]A\HHxEtHH$ƲH$H[]A\fHVHvUSHHHHtHH[]fD蓟HH[]ATIUHSH dH%(HD$1HL$LHLD$H1H|$@h蓥HcHH|$HuH11 HOfVLd$ItAu%ItI$ƒjI$HHHSu&Ht(DH{uHHtHSHeHH"HHHHItPHu HuL藞HU HHuI|$I$ tI|$覠L@uJHtAHEƒHE&f軝fD1LLHL$dH3 %(HuhH []A\ADH5@HUHuDH@HrVSHG HH5TH81t(It 1LdHEG H5H81ܛH$fUHSHH@umHtdHEƒuV tAH}~JHUH{*HuRHXH{HSH tPHwH~NDHUuDHux;H{HtHHS usHH9tHwHJHCH uEH@(C@HCt HC8C@HH[]3H@fH9W?!ATHUSHHt$lH|$HRHHMH9H|$H蓚H|$HHCH(HD$ HsHhL`HHHHsHSH HH<.H{H HHLC@HktH9HGHS8)ЉC@HH[]A\f.HD$H( MHsHL`HJHHS uHH9N)fH9VHv8DCH[]A\f.H0ATUS~0HH5IH;轛LHމH[]A\TH%D H5VH81蜘ff.USHHdH%(HD$1辿Hu>Ht5Hƒu( tH{~HS HSuDHu8Ht$HD$HHL$dH3 %(uH[]S ff.AUH=pATUSHHHG HH ٕLHH5v H> LHH5h I諕HH!: HH0薔H LH5@ KL1LHH5% 1LH?H5 1LHGH5 ے1LHH5 Ò1LHWH5 諒1LHH5 蓒1LH'H5 {1HHH5 cHHH5 HLHH5 -LHH5r LHsH5b 1LHH5 ߑ1LH#H5 Ǒ1LHKH5译1HHH5 藑1HH۴H5 1LHH5G gLH8H5 L1HH`H5 41LH(H5 1HH0H5 1LHH5s LHMH5] LH5BLH#H5.觐LHhH51茐LH]H5 qLH2H5 VH6 LH5;H6 LH5 H6 LH5 HN6 LH5 HHH5[ HH5@HHqH5,襏1HHH55 荏1HHH5$ uHH&H5 ZHH+H5?1HHSH5 '1HHH51HHH51HHH5ߎ1HHH5ǎ1HHH5w诎1HHH5i藎HHHH5T|HHH5@aHHH5/FHHH5+HHH5HHH5HHH5ڍHHH5迍HߺH5HߺH5HߺH5HߺH5ߏHߺH5ˏHߺ H5v跏Hߺ H5k裏HߺH5^菏HߺH5S{HߺH5IgHߺ H5>SHߺH53?HߺH5*+HߺH5HߺH5HHߺ[H5]A\A]D H=v迎H7 H=蟎HP7 H=H87 H=0_H 7 H=?H7 IH=dH6  H=WH6 H=2ߍH6 H= 迍H6 mHHunknown zlib error %d: %s011.2.11to_hashHash12path04, input=>02zlib(finalizer): %s closed gzip streamstream is not readyfooter is not foundrbheader is already writtenend of file reachedunexpected end of filenegative length %ld giveneach_byte rs modifiedeach_line1:not in gzip formatunknown flags 0x%02xwbZlib@dictionariesStreamEndNeedDictDataErrorStreamErrorMemErrorBufErrorVersionErrorzlib_versionadler32adler32_combinecrc32crc32_combinecrc_table0.6.0ZLIB_VERSIONZStreamavail_outavail_out=avail_intotal_intotal_outdata_typeadlerfinished?stream_end?closed?ended?closeendresetfinishflush_next_inflush_next_outBINARYASCIITEXTDeflatedeflateinitializeinitialize_copy<<flushparamsset_dictionaryInflateinflateadd_dictionarysyncsync_point?NO_COMPRESSIONBEST_SPEEDBEST_COMPRESSIONDEFAULT_COMPRESSIONFILTEREDHUFFMAN_ONLYRLEFIXEDDEFAULT_STRATEGYMAX_WBITSDEF_MEM_LEVELMAX_MEM_LEVELNO_FLUSHSYNC_FLUSHFULL_FLUSHFINISHwritereadreadpartialseek@inputGzipFileinspectNoFooterCRCErrorLengthErrorGzipWriterGzipReaderwrapto_iocrcmtimelevelos_codeorig_namecommentlinenolineno=mtime=orig_name=comment=eofeof?sync=postellopenputcprintfprintputsrewindunusedreadcharreadbyteeach_charbytesungetcungetbytegetsreadlineeachreadlinesOS_CODEOS_MSDOSOS_AMIGAOS_VMSOS_UNIXOS_ATARIOS_OS2OS_MACOSOS_TOPS20OS_WIN32OS_VMCMSOS_ZSYSTEMOS_CPMOS_QDOSOS_RISCOSOS_UNKNOWNgzfilezstreamP^lz9attempt to close uninitialized zstream; ignored.attempt to close unfinished zstream; reset forced.the stream state was inconsistent.the stream was freed prematurely.Zlib::GzipWriter object must be closed explicitly.invalid compressed data -- crc errorinvalid compressed data -- length errorwrong number of arguments (0 for 1)Zlib::GzipReader#bytes is deprecated; use #each_byte insteadZlib::GzipReader#lines is deprecated; use #each_line insteadunsupported compression method %dmulti-part gzip file is not supportedencrypted gzip file is not supporteddeflateParams() returned Z_BUF_ERROR;u}@hX؆8h(H\xx8x0ȊH|X,(Dxdؑ( ؒD hd x ȓ H h, @ T x  Ț (x ؜ H X h( D (l H 8 أT 8t ؤ X ȥ0(HH`hxȦH8Tp(Xȩ(4HLXX4xhX(xȳ(8\8Hdط$HXhDHH4hP((8H(X 88Xhtx$h`hX<hxx(l88hDx8zRx $pFJ w?:*3$"DpxH\lBBH G(D0u (D BBBJ A(D BBB, ( $0 HW8/HfP)H],hNHr F HL `EQ|WEM܁:DO f0EDD h DAF yDAL9Es,p*BAA  ABE 4p HP0LxLAA  ABG h HSSH E A x`2FEI B(D0A8DP 8C0A(B BBBE P 8D0A(B BBBC 8F0A(B BBB0$AH܆PAC A 8h BAD H ABN N ABG  @'BDD  ABG D ABA AB؈AKa D P(EKD0 AAA HAG {Ah0|0 4Eu F t A (BII AB8jBJD I(D0F(A ABB04D@(XLADDPk AAJ  (hAAG@ AAK D<FEG D(FPX\`FXAPM (A ABBH X QFBE K(A0D`YhFpRhH`hHpPhA`_ 0A(A BBBA (|EHD z DAH 0,BAK D@  AABB $QEAG0~DA@<,80Ej$HLEG> AE ,pEMGq AAD (TKFAA AB4xFAD } FBH yDB4FAD } FBH yDB<HHHu C X|XGc F cxfEu F .EL O I( r_GG ^AACt/DU A 4E_ D K !HX4 (H_L ؗHPd HP| HP HP HM HQ HP E F $ MEAD @AA< XHV B X LXHV B t HR /DU A  !HX ęHM ̙HP ԙHM ܙHM HV8 HV0P FDA G0  AABD К:E] F F A 0 FDA G0  AABD , țFDK X ABH ( HYbDG _AB08 |BDA G@  AABA l @AJD 8 (eHJ [DDn HAD, BFA R ABB  H q G  3dNL, FBA A(G@ (A ABBA  (F ABBG 8| xFLA A(D0c (D ABBD $ QAFG |AA0 DvYDG {AAGH $?EAG lDA <QR E j N (`4TFAA l ABE hAAM8lFBD A(D0X (D ABBF 8FBD A(D0X (D ABBF ( CEDD k DAA L8$A^hLAAK0P#BDA G@  AABG 0LqAAG E AAH KFCEX:HZ F Q0(YFAA G0~  AABG L\7BBB B(A0C8G 8A0A(B BBBA بAG  AA HAAG i EAH Z GAN L EAN DFA(HADD0P AAA LHBEA D(D0@ (D ABBG y (A DBBF <BAA G@  AABD $HI<IEr I D\ص%HW A @xFBL D(F0DP 0A(A BBBJ ,XgBDD N ABE 8FAA  AEO ` ABM 8(LFEG D(D@ (A ABBH dEG s AH |ZEA J 0FDF D0m  AABK 48ADD0n AAG V AAH (EDG  DAD 8@ FEG A(GP (A ABBH |BEk H ,EbH0FBB E(G0D8D@ 8F0A(B BBBA (ԿAG @ AG g AH @,HEAG0t DAJ o DAD n DAE @pFAA J0J  AABH j  AABJ 0MEAG _ DAG ODA0FDF D@  AABH (/EDD  FAD @HFDA D0  FABK q  AABK (TFAA l ABE (EAG0 AAD 8PFIA A(D0 (I HBBJ GNU<< >Z`=`>[P=  p +   o`8     oooo ( 0,@,P,`,p,,,,,,,,,-- -0-@-P-`-p---------.. .0.@.P.`.p.........// /0/@/P/`/p/////////00 000@0P0`0p00000000011 101@1P1`1p11111111122 202@2P2`2p22222222233 303@3P3`3p33333333344GA$3a1+ͭ GA$3p1067<GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFY<<=GA+GLIBCXX_ASSERTIONSzlib.so-2.2.10-35.el8.x86_64.debug7zXZִF!t/)? 3]?Eh=ڊ2N61:Q;]t+/AoZ o*)HθwS0[>Gd{=,/Z.x1^1Pʤ\x YlL6ۊ#c7ô ߚo Ii 9au#;c^6ͻMVnky)y \9ЂfIq5}ަM-El^|_J hI,"!xY#yuo=fSq]+5oWn5[ykˆ/n'sLMX海YvlŜƳ{b5,&"`w#>M꿴ZZxA ~rD??Z45cmڢVu6E,\dz-Y|}"Y QrsVx XکV B P,Vr/;ٜ#:); AIybQP,E$j/|qռ9mmSD=lr9 2oPwnt<1m%#^"Æ1C>84e8̘/;m vPZ/^3 /riL2|WGW- uosLRƏW g}Z+f>¬% 3u~ T8cauy%պVd[nzG'ob[(a9|’+ֲ|bNR`|s '.?x?ZK`HgƛCA82.D|GЙ{XX`.*gHɛ71&`C}!8OD Ϩ-}(yַ蛻~N FpxcYʽmZ au|Y I KGYNQ"q몝A.9f'oIM8a*! KCxhCdA4٢m%7J޳ቦo8# gv{/'AUt-C5;gH~|%1{pܫOr$; FQPQް?@@o9:=k2v*;㨘`B1%>ǹܓbbK]rO~"H eBeb(讒xG ?z\;S/Vj@ k}06QЧmrA"[> B2ӯ\)>:?n]81).syv9ڣ IRY2 )\~dQ#263Y锼߅T;;K֔{m&i%I_K:F <#u>LRO^5՝TG-(8UXyĥɖ,py XJ"h/Rwř0'}Y`펮な@D18o@F sUgk,T LF݃8Қʳ f,'/T{(RXR$®,C-$'i<^Ɖfw>tf210~QFz@8?c{؁ ɨzq5.+XHSlGYo@=5[Wf'Ƽyޘ?N꼵O5Dbgp6~744.u)?X쐯 ȨC L|3LCݒYf?k-£ z@@8 @ ""  ""  888$$ Std Ptdmmm  QtdRtd""GNUZAVcusi2a P JPHH1 @%D!GAD(` $"  H@@D " WH C$  `8  #$&'(*+-./0123578:6'HAs!k >3`<3`7u+/Ze/y蘵~KUK % oxvLqzN:|ys>xD(hYijdu B62WR]Ų9T~CEȷ0*F{]FKNwbQ,?.a b-q)[)uzt;ӊk4@k=@ˌhjqXGn`O %o?f$ |4cuUNnHv20tD}p%R%q@mlPi#&p%LV Lif\y׫/VHL2Mc'x毷NL4\ U]" V N " 0,_  ,.yȹ" @  0: 0w  0h < Q5"_ s7  Pr>S"\   h 4" 0  ~p  z @s&  Tl?"'"  pU &N  VM @w)  X % z Љ  r"H  # P~Z"ع"E N"P l* pQ9 \f"  ' v[W  le   '  Ib  ,." Dc ^" i Q Q  #Y t&  r& Pi 7 0Qr * RU Q  n yu }? ps"8 `(9    Q;  0g  pn | |7c  - ? (  $  +E n  r (Y ~# r5 Q PQ5 9j  # P ~7 .U  Py Pй" f __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeaccept4__errno_locationrb_maygvl_fd_fix_cloexecrsock_raise_socket_errorgai_strerrorrb_eSocketrb_raiserb_sys_failrsock_init_sock__fxstatrb_reserved_fd_prb_update_max_fdrb_io_make_open_filerb_io_ascii8bit_binmodersock_do_not_reverse_lookuprb_io_synchronized__stack_chk_failrsock_sendto_blockingsendtorsock_send_blockingrsock_s_recvfromrb_scan_argsrb_fix2intrb_io_taint_checkrb_io_check_closedrb_io_read_pendingrb_tainted_str_newrb_obj_hiderb_thread_io_blocking_regionrb_io_wait_readablerb_obj_revealrb_obj_taintrsock_unixaddrrb_assoc_newrb_num2intrb_str_set_lenrsock_ipaddrrsock_io_socket_addrinforb_eRuntimeErrorrb_bugrb_eIOErrorrsock_s_recvfrom_nonblockrb_io_set_nonblockrb_readwrite_sys_failrsock_detect_cloexecfcntlrsock_socketrb_gcrsock_connectgetsockoptrb_wait_for_single_fdrsock_s_accept_nonblockrb_securerb_obj_allocrsock_s_acceptrsock_getfamilygetsocknamersock_init_socket_initrb_eStandardErrorrb_define_classrsock_init_ipsocketrsock_init_tcpsocketrsock_init_tcpserverrsock_init_sockssocketrsock_init_udpsocketrsock_init_unixsocketrsock_init_unixserverrsock_init_sockoptrsock_init_ancdatarsock_init_addrinforsock_init_sockifaddrrsock_init_socket_constantsrb_cAddrinforb_cSocketrb_cUNIXServerrb_cUNIXSocketrb_cUDPSocketrb_cTCPServerrb_cTCPSocketrb_cIPSocketrb_cBasicSocketrsock_family_to_intrsock_socktype_to_intrsock_ip_level_to_intrsock_so_optname_to_intmemcmprsock_ip_optname_to_intrsock_ipv6_optname_to_intrsock_tcp_optname_to_intrsock_shutdown_how_to_intrsock_scm_optname_to_intrsock_unknown_level_to_intrsock_udp_optname_to_intrb_check_string_typerb_check_safe_objrb_sym_to_srsock_ipproto_to_intrsock_intern_familyst_lookuprsock_intern_family_noprefixrsock_intern_protocol_familyrsock_intern_socktypersock_intern_ipprotorsock_intern_iplevelrsock_intern_so_optnamersock_intern_ip_optnamersock_intern_ipv6_optnamersock_intern_tcp_optnamersock_intern_udp_optnamersock_intern_scm_optnamersock_intern_local_optnamersock_family_argrsock_socktype_argrsock_level_argrsock_optname_argrsock_cmsg_type_argrsock_shutdown_how_argrb_define_module_underrb_define_constst_init_numtablerb_intern2st_insertrsock_bsock_sendrb_string_valuersock_sockaddr_string_valuerb_str_new_frozenrb_io_wait_writablerb_out_of_intgetpeernamersock_fd_socket_addrinforb_str_newrsock_sockopt_newrsock_sys_fail_pathrb_funcallsetsockoptshutdownrb_io_closerb_eArgErrorrsock_init_basicsocketrb_cIOrb_undef_methodrb_define_singleton_methodrb_define_methodrsock_bsock_sendmsgrsock_bsock_sendmsg_nonblockrsock_bsock_recvmsgrsock_bsock_recvmsg_nonblockrb_rescuerb_ary_entryrb_yieldrb_ensurersock_sockaddr_string_value_ptrrsock_unixpath_strrb_eTypeErrorrsock_make_ipaddrrsock_addrinforb_freeaddrinforb_string_value_cstrgetservbyportrb_tainted_str_new_cstrrb_num2longrb_eRangeErrorgetservbynameruby_strtoulgethostbyaddrrb_ary_newrb_str_new_cstrrb_ary_pushrsock_make_hostentrb_str_new_staticrb_str_modify_expandgethostnamestrlenrb_str_resizerb_syserr_failrsock_addrinfo_newgetifaddrsfreeifaddrs__memcpy_chkrsock_unix_sockaddr_lenrb_check_sockaddr_string_typerb_getnameinfostrcmprb_check_array_typerb_gc_writebarrier_unprotectrb_string_value_ptrstrncpyruby_snprintfrb_getaddrinforsock_sock_listenrsock_sock_s_socketpairrb_block_given_prsock_getaddrinforsock_revlookup_flagrsock_syserr_fail_host_portrb_sprintfrb_syserr_fail_strrsock_sys_fail_host_portrsock_syserr_fail_pathrsock_syserr_fail_raddrinforsock_addrinfo_inspect_sockaddrrsock_syserr_fail_sockaddrrsock_sys_fail_sockaddrrsock_sys_fail_raddrinforsock_syserr_fail_raddrinfo_or_sockaddrrsock_sys_fail_raddrinfo_or_sockaddrrsock_sockaddr_string_value_with_addrinfobindrsock_sockaddr_lenrsock_sockaddr_objInit_socketrsock_init_inetsockrb_check_typerb_sym2idrb_id2namersock_freeaddrinforsock_cmsg_cloexec_staterb_funcallvrsock_discard_cmsg_resourcersock_recvmsgrb_str_duprb_obj_freezerb_obj_is_kind_ofrsock_init_unixsockrb_get_pathrb_protectrb_jump_tagrb_ivar_setrb_attr_getrb_id2symrb_str_catfif_indextonameinet_ntoprb_str_cat_cstrrb_str_catrb_to_intrb_obj_classnamerb_str_dumprb_str_appendrb_cSockOptrb_newobj_ofrb_check_to_integerrb_cObjectrb_define_class_underrb_str_buf_newrb_num2uintrb_ary_new_from_valuesrb_time_newrb_time_nano_newlocaltimestrftimerb_thread_call_without_gvlrb_str_tmp_newmemsetmemcpyrb_check_convert_typerb_int2bigrb_hash_arefrb_cStringrb_num2ulongrb_io_fdopenrb_freeze_singleton_classrb_data_typed_object_allocrb_gc_markrb_check_typeddatarb_id2strrb_isprintrb_isspacestrtolrb_ary_storestrspninet_ptonruby_xmallocruby_xcallocruby_xfreerb_cIntegerrb_ary_new_capagethostbynamerb_convert_type__sprintf_chkrb_str_equalrsock_inspect_sockaddrrb_typeddata_is_kind_ofrb_cDatarb_define_alloc_funcrb_cSockIfaddrrb_ull2inumif_nametoindexrb_class_namerb_cFalseClassrb_cNilClassrb_cFixnumrb_cFloatrb_cTrueClassrb_cSymbollibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5GLIBC_2.3GLIBC_2.14GLIBC_2.3.4GLIBC_2.10GLIBC_2.4/opt/alt/ruby22/lib64 ui kIii wti ii ui k"0{"z " "@"jH"`X""om"3"4"3""" "("0"8"@"H"P"X"`"h"'p"*x""""2"""")"T"Ȯ"ZЮ"^خ""3" "q""" "|" "(";0"<8"@"H"1P"X"`",h"p"x" """""!""""ȯ"Я"د"6"""" "("0"8"@"H"P"X"`" h"p"x" " "" " """""Ȱ"а"ذ""""""""" "("0"$8"@"H"P"X" `"!h""p"x""#""""$""%"&"(ȱ")б"'ر"+"+","-"."/"#"0"1 "2("30"48"5@"6H"7P"8X"9`"h"*p":x" "";""<""="(">"?Ȳ"@в"Aز"B"""C"D"E"F""0 "G("H0"I8"J@"/H"KP"8X"L`")h"p"Mx"N"O"P""Q"R"S"9"U"Vȳ"Wг"Xس":"Y"[""\"]"_"`"a "("b0"8"c@"dH"P"X"e`"fh"gp"5x"h"i"j"k"l" ""m"n"ȴ"oд"pش"r"s"-"t"u"v"w"x" "y("z0"{8" @" H"}P"~X"`"h"p"x""""""""""ȵ"е"ص""7""""""" "%("0"8"@"H"P"X"`"h"p"x""""""""." "4ȶ"ж"ض""""""""" "("0"8"@"&H"P"X"`"h"p"x""""""""""ȷ"з"ط"""""""HH1T"HtH5RU"%SU"hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?h@hAhBhChDhEhFhGqhHahIQhJAhK1hL!hMhNhOhPhQhRhShThUhVhWqhXahYQhZAh[1h\!h]h^h_h`hahbhchdhehfhgqhhahiQhjAhk1hl!hmhnhohphqhrhshthuhvhwqhxahyQhzAh{1h|!h}h~hhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!h%mE"D%eE"D%]E"D%UE"D%ME"D%EE"D%=E"D%5E"D%-E"D%%E"D%E"D%E"D% E"D%E"D%D"D%D"D%D"D%D"D%D"D%D"D%D"D%D"D%D"D%D"D%D"D%D"D%D"D%D"D%D"D%D"D%}D"D%uD"D%mD"D%eD"D%]D"D%UD"D%MD"D%ED"D%=D"D%5D"D%-D"D%%D"D%D"D%D"D% D"D%D"D%C"D%C"D%C"D%C"D%C"D%C"D%C"D%C"D%C"D%C"D%C"D%C"D%C"D%C"D%C"D%C"D%}C"D%uC"D%mC"D%eC"D%]C"D%UC"D%MC"D%EC"D%=C"D%5C"D%-C"D%%C"D%C"D%C"D% C"D%C"D%B"D%B"D%B"D%B"D%B"D%B"D%B"D%B"D%B"D%B"D%B"D%B"D%B"D%B"D%B"D%B"D%}B"D%uB"D%mB"D%eB"D%]B"D%UB"D%MB"D%EB"D%=B"D%5B"D%-B"D%%B"D%B"D%B"D% B"D%B"D%A"D%A"D%A"D%A"D%A"D%A"D%A"D%A"D%A"D%A"D%A"D%A"D%A"D%A"D%A"D%A"D%}A"D%uA"D%mA"D%eA"D%]A"D%UA"D%MA"D%EA"D%=A"D%5A"D%-A"D%%A"D%A"D%A"D% A"D%A"D%@"D%@"D%@"D%@"D%@"D%@"D%@"D%@"D%@"D%@"D%@"D%@"D%@"D%@"D%@"D%@"D%}@"D%u@"D%m@"D%e@"D%]@"D%U@"D%M@"D%E@"D%=@"D%5@"D%-@"D%%@"D%@"D%@"D% @"D%@"D%?"D%?"D%?"D%?"D%?"D%?"D%?"D%?"D%?"D%?"D%?"D%?"D%?"D%?"D%?"D%?"D%}?"D%u?"D%m?"D%e?"D%]?"D%U?"D%M?"D%E?"D%=?"D%5?"D%-?"D%%?"D%?"D%?"D% ?"D%?"D%>"D%>"D%>"D%>"D%>"D%>"D%>"D%>"D%>"D%>"D%>"D%>"D%>"D%>"D%>"D%>"D%}>"D%u>"D%m>"D%e>"D%]>"D%U>"D%M>"D%E>"D%=>"D%5>"D%->"D%%>"D%>"D%>"D% >"D%>"D%="D%="D%="D%="D%="D%="D%="D%="D%="D%="D%="D%="D%="D%="D%="D%="DH=="H="H9tH3"Ht H=i="H5b="H)HHH?HHtH4"HtfD=%="u+UH=4"Ht H=0"Yd<"]wULOLGSHHHwoOH u)HH;Ht9kvkH[]fHVHvfDHWHw?HHAVIAUAATE1USHHtD"&<"t.HLDŃuP8&ug;"HLD>ŃtHHtD9#wv[]A\A]A^D#~HtD9#vD#@AHHWHw?)HHfSHt%HH5HHx2"H81fATIUSHdH%(H$1HLD$%=uu-ujbLzLXH@ #H&1"u0H0LH$dH3 %(u>HĠ[]A\fDM H=# H=HwDOLGOH uH?HsHV?HvaHwOH uH?HHV?HvfAWAAVAUATUSHXH|$HL$ LD$(HH\dH%(H$H15H|$(HD$4H|$ @_:H|$LcMHhHHY3EL1D$@Ll$0L55D$0HHD$8H@HHD$HL9HHT$0LLHy,}H{yH tHCHt$HHD$HHT$ HCH9HAEt%At$@I}:HHHH$HdH3 %(H,HX[]A\A]A^A_fDHH9xHHH-Amt$@trU I}HH HffAu~T$@H|$Iu(HHH9D@t5D$4H߾HH."H5H81H=lH=u1H."H5H81fQAWAVAUAATA@USHHH<$HL$ LD$(HHgdH%(H$81D$8H|$(HH|$ @EH<$HcYHhHHeEH1D$HIHID$IwD$ I Lt$0|$DHLL$MDHJ\$ 9\$H3I IWH9LAEt(AWT$H<$L)HLIH$8dH3 %(L-HH[]A\A]A^A_Iw/\$SHH9^LHLUASD$aU LHF@IfD@t2}AA@+8 t.H=af.;AA@H5o1JH+"H5AH81H=ú1ff.@S1t[8H=H1t@AUAATAUSH3"Tu*Ãt>/H[]A\A]Åy7u 8t;ɐÅx~ 3"uDD`Ãt2"df.AUAATAUSHÅxXH[]A\A]cwDDÅyH[]A\A]@AUATUSH8dH%(HD$(1|$Ht$Ht$T$H=Ņx*HL$(dH3 %(H8[]A\A]fIċ tUtsuLl$ Hl$MHD$ 8xd1Ҿ&xRMHD$ x/D$1UF>; 2*A$fD Qfj|эPfAUIATIUHSHH|H4{LLy2Gtgt t H=!0H51fÉ71t4߉1tHHH[]A\A]H=@AWAVAUIATAUHSHH(dH%(HD$1Hl$DHH\$1D$$3$HH=QD?AF_I?PF_I?AF_U?PF_U8?AF_A|?PF_At?AF_I?PF_IufSDu N@HAF_UNSPEH9HPF_UNSPEH9HAF_PACKEH9HPF_PACKEH9HAPPLETALH9uKu1fDHAF_APPLEH9HPF_APPLEH9`TALKSf?IPef?SNf?MA-X#1-@?INET?UNIXn?AX25R?ISDN"1?INET?LOCA`?ROUTE1f?AF_I?PF_IH?AF_S?PF_S?AF_M?PF_M?PF_K?UNSP?PACK*fET1HAF_INET6H9tyHPF_INET6H9tjHAF_LOCALH9tQHH9tHHAF_ROUTEH9tHPF_ROUTEH91fNIPXF1Ð 1fNET1ÐfNA1Tw1D6R1 DC!1DfPX`1X@TALKN'fDfX2x5n1ÐfNE4T*DA41DLfCl3fPX;TjffNIX[DfNAtfAXo-1fAXffX25vfSDqNgfEY.1fEC%1ff.HH w6H 'HcH>HSOCK_SEQH9uPACKu f ETfDf?RA-f?RDuMulfD?DGRAùMuD?STRE,?PACKufETuHSOCK_RAWH9HSOCK_RDMH9n1ÐHSEQPACKEH9QTG1f.HSOCK_DGRH9!fAM1HSOCK_STRH9tQHSOCK_PACH9fKE T 1W1DfEAu Mu1ffAMfHwnH HcH>Df?TCEf?EG f?PU_f?UDf?IDf?ESf?RAuW@DfHIPPROTO_H9uICMPuf V6u1:HIPPROTO_H9=HIPPROTO_H9RHIPPROTO_H9uROUTuf IN~Gtf?IPf?TP:f?AHG31fD?ICMP?IGMP?IPV6?NONE;1?SOCK4?ICMPfV6HSOL_SOCKH9HIPPROTO_H9:HIPPROTO_H9HIPPROTO_H9|fAHp13HIPPROTO_H9]HIPPROTO_H9HIPPROTO_H9gHIPPROTO_H9HIPPROTO_H9HIPPROTO_H9HIPPROTO_H9fRA W1@HIPPROTO_H9HIPPROTO_H9:HIPPROTO_H9HIPPROTO_H9lNONE_1;fDHIPPROTO_H3HFRAGMENTH3wHH )1,?DSTOl?HOPOtd?ROUTfING1+ÐHFRAGMENTH9,1@fET1fPTuSu1ÐfEGB P81ÐfIPfIGMP1f.P@11P1DfTC PځICMP&1f.fETfPTS~1<fDSTOf PTSHOPOf PTS1@)1fTPu1IPV6l1)f.P1 DfPU PڀPr1DfUDp PfڀPM1fIDX PN߀P-12fES@ P6f.HHUH fHSHHHcH>HITY_ENCRH3WHSO_SECURH3H uHYPTION_NH9G> H[]H_ENCRYPTH3WHSECURITYH3H uHION_NETWH9G% DH_ENCRYPTH3WHSECURITYH3H uHION_TRANH9G{fH_AUTHENTH3WHSECURITYH3H u ICAT BfHITY_AUTHH3WHSO_SECURH3H uHENTICATIH9G} fHT_ERR_QUH3WHSO_SELECH3H u fEUw f.HACING_RAH3WHSO_MAX_PH3H u fTE%f.HSO_SNDBUH9 HSO_RCVBUH9 HSO_TIMESH9\ HSO_WIFI_H9 HSO_LOCK_H92HBPF_EXTEH9@HSO_ACCEPH9HSO_GET_FH9r HATTACH_FH9 HDETACH_FH9F f.HSO_REUSEH9HSO_REUSEH9: HSO_DONTRH9 HSO_BROADH9A HSO_KEEPAH9 HSO_OOBINH9 HSO_TIMESH9 HSO_BUSY_H9CHBINDTODEH9HTIMESTAMH9%f.HSO_NO_CHH9 HSO_PRIORH9 HSO_PASSCH9< HSO_PEERCH9M HSO_RCVLOH9 HSO_SNDLOH9 HSO_RCVTIH9K HSO_SNDTIH9 HSO_PEERNH9 HSO_PROTOH9 H5AH H51H^ H5H H5HzX H5H^x H5HBP H5tH&,E,;fHH_FILTERH3GHSO_ATTACH3H 1EfDHSO_PEERSH9HSO_PASSSH9HACCEPTCOH9HGET_FILTH9 f?SNDB$;RCVB;LING;DOMA7 ofD?DEBU;ERRO;NOFC;f?TYPE$?MARKL E$1f.HITY_ENCRH3WHSO_SECURH3H u%HRANSPORTH3WHYPTION_TH3GH +HXTENSIONH3WHSO_BPF_EH3H u SN@HSO_BINDTH9HSO_TIMESH9BHMAX_PACIH9>DHSO_DEBUGH9mHSO_ERRORH9HSO_NOFCSH9HNO_CHECKH9RHPRIORITYH9HPASSCREDH9 HPEERCREDH9{ HRCVLOWATH9 HSNDLOWATH9^ HRCVTIMEOH9| HSNDTIMEOH9 HPEERNAMEH9 HPROTOCOLH9 HRXQ_OVFLH9 HPEEK_OFFH9 *1fDHSO_SNDBUH9HSO_RCVBUH9 HSO_LINGEH9dHSO_DOMAIH9HREUSEADDH9HREUSEPORH9HDONTROUTH9sHBROADCASH9HKEEPALIVH9HOOBINLINH9} H5\H H5ۡH E.fD?SO_T;SO_M;PEER;PASSfDSPOR%TE1{NG_R6f{ AT*{E E/1Z{NSIOFf{ NS:E013f.fYP(Ef.E1fHSO_DETACH3H b1E@Gj11ODEV.f IC"E1yfUF1`fEC_1@F91"fTCON& N1@ADDR^1fDFFOR^f CER1 ffEC K1 DHRR_QUEUEH3OHSELECT_EH3H XE-1J{R1E1f{AR4{K*1f{EC1E"fD{F1E{FFORYf{ CEM1E!ff{IT{ Y1E e@{ILTE{ RwE1<{PORT1ED{TAMPf{ IN{G1E%f{UFD1EETWOfRKE1fORKfONwE1nfION ڀE{S1E+/f{NN[1Ef{SE,{C"1E+1{TAMPf{ NS1E#{ILTE{ RWf{ER1E {OUTE1El{R1E Tf{RE{ D1E0f{RE{ D1E {CAST1E{N*1E'f{ER1Ef{SE{C1E" 1{STATTf{ USH1E)g{ILTE{ R1EBf{IN1E'({LIVE1E  1{RL1E{FILTf{ ER1E,f{WAK{ TA1Ef{WA:{ T01Ey{T1Ea{LINE-1E F191,{TAMP 1E{E1Ef{ME{ O1E1{POLL1E.{T(1Ef{MEN{ OD1EgÀ{E1E K{VICEP1E01#f{AM{ E1E1f{CO{ L1E&{Ey1E {PING1E%E11uE*iE(](1P&1CE!7E +#E)E#fHHH kHcH>DHCAST_LOOH3OHIP_MULTIH3H DHEMBERSHIH3OHIP_ADD_MH3H u P HCK_SOURCH3OHIP_UNBLOH3H u Ef.HLT_MULTIH3OHIP_DEFAUH3H HSOURCE_MH3OHIP_DROP_H3H uHEMBERSHIH9GuPu(1Df?TO]f?TT f?MTgU]1@?IP_T?IP_T ?IP_Mt ?MINT fTL1?OPTI?HDRI?RETO ?RECV( ?PKTI ?RECVP ?RECVq ?PASSfSEC1fHRECVOPTSH9HFREEBINDH9HMSFILTERH9G)1fDHIP_MINTTH9%LfDHIP_OPTIOH9}HIP_HDRINH9JHIP_RETOPH9HIP_RECVTH9 HIP_PKTINH9R HIP_RECVEH9 HIP_RECVTH93 HIP_PASSSH9M HPKTOPTIOH9efNSY1 HIP_RECVOH9HIP_FREEBH9BHIP_MSFILH9HRECVRETOH9 HXFRM_POLH9 HTRANSPARH9 HPMTUDISCH9f_D O1@HMULTICASH9HROUTER_AH9HMTU_DISCH9?HIPSEC_POH9jHBLOCK_SOH9IURCE<1&HIP_PKTOPH9eHMULTICASH9HPMTUDISCH9HPMTUDISCH9_WAN T1@HIP_RECVRH9HIP_XFRM_H9HIP_TRANSH9HIP_PMTUDH9HMULTICASH9tHADD_MEMBH9%HUNBLOCK_H9;SOUR.f CE"1%fHMEMBERSHH3OHIP_DROP_H3H HEMBERSHIH3OHIP_MAX_MH3H fPSHCAST_TTLH3OHIP_MULTIH3H CHISC_DONTH3GHIP_PMTUDH3H 1HIP_MULTIH95HIP_ROUTEH9HIP_MTU_DH9HIP_IPSECH90HIP_BLOCKH9HDROP_MEMH9GHMAX_MEMBH9ERSHf IPS1HMULTICASH3OHDEFAULT_H3H HRCE_MEMBH3OHDROP_SOUH3H XERSHKfIP?f.HMULTICASH3OHDEFAULT_H3H lHCE_MEMBEH3OHADD_SOURH3H RSHIP'1HLT_MULTIH3OHIP_DEFAUH3H HOURCE_MEH3OHIP_ADD_SH3H xHMBERSHIPH9GdfT_TTI L?1!HCAST_LOOH9G`PV1fP1"DfIP$1T_LOWfOPKDHCAST_TTLH9Gf.T_TTL}b@fNSw11fONPSFfPT S1ÐSCASTf _IF1 @ETOP&f TS1fDTION SC@T_IFffOS0MR_AL)f ERT1@fNC<L21fPOLIif CY]1fDfIN D1fHISC_WANTH3GHƸH fCLmLERT1fD1L1DfTLf.OVER1 f._DON  T@fTS 1fPTSDfTUJISCOtf VEhR^UPAREf NT1fDfTE% R1)ÁERSHf IP1#fTL71 ÁLICY1Á_POLf ICYfTTL띁ISC_f DO fPTj S`{fFO1Á_SOUDf RC8E.ffNFHO>fIC  YT_LOf OPsfEN T]fRR 1 ÁBERSf HIPfERRfOS1 fTOSyfECf.HHH 7HcH>DHTICAST_IH3OHIPV6_MULH3H HCAST_HOPH3OHIPV6_UNIH3H HVHOPLIMIH3OHIPV6_RECH3H u TAHDRDSTOPTH3OHIPV6_RTHH3H u SZHDR_TYPE_H3OHIPV6_RTHH3H u 0@HTICAST_HH3OHIPV6_MULH3H tfOPhS^1D?RTHDuRuiD?V6ON?TCLAufSSv9?DSTOL?HOPO?NEXT?PATH?PKTI2fNF&O12DHCHECKSUMH9HDONTFRAGH9HHOPLIMITH941fDHRECVRTHDH9R/fDHIPV6_RTHH9MHJOIN_GROH9ZHRECVTCLAH9efSSY1BfHIPV6_V6OH9HIPV6_TCLH9HLEAVE_GRH9HRECVDSTOH9HRECVHOPOH9HRECVPKTIH9'HRECVPATHH9fMT U1<@HIPV6_RECH9HMULTICASH9HMULTICASH9mT_LO`f OPT1DHIPV6_DSTH9HIPV6_HOPH9HIPV6_NEXH9WHIPV6_PATH9HIPV6_PKTH9HMULTICASH9 HUNICAST_H9'HRECVHOPLH9HRTHDRDSTH9HRTHDR_TYH9PE_0{1@HVE_GROUPH3OHIPV6_LEAH3H BHVDSTOPTSH3GHIPV6_RECH3H  1:HIPV6_CHEH95HIPV6_DONH9BHIPV6_HOPH9LIMI T14HIPV6_JOIH9HIPV6_RECH9VTCLf ASwSmf.HTICAST_LH3OHIPV6_MULH3H :fOO.P$fOU P1ÐFR1DS^1DCKSU M1ÁOPTSn1;f.VRTHf DR18fDfNL Y1ffDR191fPTSZDfLY`f.N_GR.f OU"P1@TFRA G1>fPT,S"16ÐT_HOf PSffAS S1CÐOPTS말fUPRHVHOPOPTSH3GH u15@>1HVPKTINFOH3GH u=11@THOP1 ffHOHP>HVPATHMTUH3wH fPT[ SQ(HMTUG1=fMTU߁IMITe13ÁINFOfPT SOPTS517ÁT_IFfNF OHOPSf.HHwHTCP_THINH9u_DUPuf ACu KHIE_TRANSH3OHTCP_COOKH3H uځACTIufONuɀSu1H_LINEAR_H3OHTCP_THINH3H uHTIMEOUTSH9Gu1?CORK?INFOb 1?MAXS?MD5S(?SYNC?REPA"fIR1?NODE?KEEPh?LINGfER21DHTCP_CORKH9HTCP_INFOH9:HKEEPIDLEH9HQUICKACKH9'HFASTOPENH9c1HTCP_MAXSH9mHTCP_MD5SH9 HTCP_SYNCH9HTCP_REPAH9HCONGESTIH9fON1 @HTCP_NODEH9HTCP_KEEPH9HTCP_LINGH9?HTHIN_DUPH9fAC K1DHKEEPINTVH9-HQUEUE_SEH9HTIMESTAMH99P/1@HTCP_KEEPH9HTCP_QUICH9HTCP_FASTH9/HDEFER_ACH9HWINDOW_CH9HREPAIR_QH9HUSER_TIMH9EOUT1DHTCP_KEEPH9HTCP_QUEUH9HTCP_TIMEH9ISTAM< P2HTCP_CONGH9HREPAIR_OH9PTIOf NS @HR_ACCEPTH3OHTCP_DEFEH3H HOW_CLAMPH3OHTCP_WINDH3H 0 1HRANSACTIH3OHCOOKIE_TH3H ffONZSPHEAR_TIMEH3OHTHIN_LINH3H &OUTSf.HIR_OPTIOH3OHTCP_REPAH3H fNS1ÁCEPT 1Ð1INTV. L$1ÁIDLEn1f.ESTIFf ON:]ffEG1L@fLAY1ffLA YfEGfE_SEa QW1fCN T1ÐfCNTHIR_QUEUEH3OHTCP_REPAH3H uf1QxfIG1fIGf.KACK1 H_TIMEOUTH3wHTCP_USERH3H +ÁOPEN11ÐfNTm1fNTHf.fER 2 1fIR,LAMPeUEUEfHtf~$Ht>H uHSHUT_RDWH9tyHuf?RDtYf?WRu1?SHUTt0?SHUTuf_WuRuԁ?RDWRu1f_RuȀDu1ÐRuHH wRH kHcH>HTIMESTAMH9HCREDENTIH92HWIFI_STAH9f.HSCM_TIMEH9uSTAMu؀ PuDHSCM_TIMEH9uHSCM_CREDH9HSCM_WIFIH9u_STAuf TUuSx)1?RIGH\fTSPHSCM_TIMEH3HSTAMPINGH3wHH !%1HTIMESTAMH9P1f.HSCM_RIGHH9fTS1HTIMESTAMH9PINGofTU| SrDfPN/ S%#1fSTAM~f PNrShENTIif AL]SS1@fAL SHtH uHSOL_SOCKH9t)?SOCKufETu1fETuff.Ht&Hu(HUDP_CORKH9u1?CORKtfAUIATIUSHHdH%(HD$1@ @u HutHHHHםHu t;H]HuHT$HAԃtoD$HL$dH3 %(uVH[]A\A]@HH]uH讧HfH߃ts뢐[H!HLH5nH81fDHwnH [HcH>Df?TCf?EGf?PU/f?UDTf?IDyf?ESf?RAuWxDfHIPPROTO_H9uICMPuf V6uHIPPROTO_H9HIPPROTO_H9BHIPPROTO_H9uROUTuf INuGf?IPf?TP"f?AHW31fD?ICMP$?IGMP?IPV6?NONE;1?ICMPfV61:?DSTOL?HOPO?ROUTfING1+DHFRAGMENTH9,1@HIPPROTO_H9HIPPROTO_H9HIPPROTO_H9?fAH313fHIPPROTO_H9mHIPPROTO_H9JHIPPROTO_H9HIPPROTO_H9HIPPROTO_H94HIPPROTO_H9LHIPPROTO_H9fRA W1@HIPPROTO_H9HIPPROTO_H9HIPPROTO_H9HIPPROTO_H94NONE'1;fDHIPPROTO_H3HFRAGMENTH3wHH 1,fPT S1ffEG P1ÐIGMP11f.fTP1P@11P1D1DSTO>f PT2S(1<@fIPgICMPF1ffTC P}gDfPTSHOPOf PTS1@)1IPV61)f.P1 DfPU PڀP1DfUD PڀP}1fID P߀P]12fES Pf.HHcH=!dH%(HD$1HVH$u1HL$dH3 %(HuHOff.@HHcH=!dH%(HD$1HH$u1HL$dH3 %(HuHff.@HHcH=!dH%(HD$1H薔H$u1HL$dH3 %(HuH菗ff.@HHcH=N!dH%(HD$1H6H$u1HL$dH3 %(HuH/ff.@HHcH=!dH%(HD$1H֓H$u1HL$dH3 %(HuHϖff.@HHcH=~!dH%(HD$1HvH$u1HL$dH3 %(HuHoff.@HHcH=!dH%(HD$1HH$u1HL$dH3 %(HuHff.@HHcH=!dH%(HD$1H趒H$u1HL$dH3 %(HuH试ff.@HHcH=F!dH%(HD$1HVH$u1HL$dH3 %(HuHOff.@HHcH=!dH%(HD$1HH$u1HL$dH3 %(HuHff.@HHcH=v!dH%(HD$1H薑H$u1HL$dH3 %(HuH菔ff.@HHcH=!dH%(HD$1H6H$u1HL$dH3 %(HuH/ff.@HHcH=!dH%(HD$1H֐H$u1HL$dH3 %(HuHϓff.@H5-!HnfH5!HnfHHmuH5S!H{H5!HifHHЃu)w8H vHcH>DuH5!HuwHHHǨtTH3HfDH5a!HZwHHfDH5i!HwmHHfDH5!H9mHHfDH51!HlHHnff.HHЃu)w8H uHcH>DuH5!HlHHHǨtTH3HfDH5a!HlHHfDH5i!HmHHfDH5!HlHHfDH51!HrlHHnff.H5%!HlIfSH$!H5lH;5H;H5@bH! H=!H5!bH;H5bޛH=!H5aƛH;H5Cl貛H=!H5+l蚛H; H5 l膛H=_! H5lnH; H5aZH=3! H5aBH;H5ia.H=!H5QaH;H5`H=!H5`H;H5`֚H=!H5`辚H;H5L`誚H=!H54`蒚H;H5(`~H=W!H5`fH;H5jRH=+!H5j:H;H5j&H=!H5jH;H5_H=!H5_H;H5_ΙH=!H5p_趙H;H5d_袙H={!H5L_芙H;H5@_vH=O!H5(_^H; H5^JH=#! H5^2H; H5^H=! H5~^H; H5^H=! H5^ژH; H5^ƘH=! H5^讘H;H5Oi蚘H=s!H57i肘H;H5,inH=G!H5iVH;-H5]BH=!-H5]*H;-H5]H=!-H5]H;!H5hH=!!H5hҗH;!H5h辗H=!!H5vh覗H;EH5d]蒗H=k!EH5L]zH;EH5@]fH=?!EH5(]NH;[H5\:H=![H5\"H;[H5\H=![H5\H;#H5\H=!#H5\ʖH;#H5\趖H=!#H5\螖H;H5%\芖H=c!H5 \rH;H57g^H=7!H5gFH;H5g2H= !H5fH; H5fH=! H5fH;H5fڕH=!H5f•H;AH5f讕H=!AH5f薕H;H5f肕H=[!H5tfjH;H5kfVH=/!H5Sf>H;H5Kf*H=!H53fH;!H5,fH=!!H5fH;H5 fҔH=!H5e躔H;H5e覔H=!H5e莔H;H5ezH=S!H5ebH; H5eNH='! H5e6H;@H5~e"H=!@H5fe H;H5_eH=!H5GeޓH;H5@eʓH=!H5(e貓H;@H5e螓H=w!@H5e膓H;H5YrH=K!H5YZH;H5dFH=!H5d.H; H5dH=! H5dH;#H5dH=!#H5qd֒H;H5#Y’H=!H5 Y誒H;H5lY薒H=o!H5TY~H;H5MYjH=C!H55YRH; H5X>H=! H5X&H;H5XH=!H5XH;H5XH=!H5hXΑH;#H5`X躑H=!#H5HX袑H;-H5@X莑H=g!-H5(XvH;;H5WbH=;!;H5WJH;gH5W6H=!gH5WH;yH5#X H=!yH5 XH;eH5WސH=!eH5WƐH;YH5W貐H=!YH5W蚐H;H5W膐H=_!H5WnH;uH5dWZH=3!uH5LWBH;SH5W.H=!SH5WH;wH5VH=!wH5VH;WH5W֏H=!WH5V辏H;H5tV誏H=!H5\V蒏H;H5!a~H=W!H5 afH;'H5aRH=+!'H5`:H;H5`&H=!H5`H;H5`HH=!HH5`؎H;H5`ĎH=!H5`謎H;H5`H蓎H=l!HH5i`vH;H5n`H]H=6!HH5G`@H;H5N`H'H=!HH5'` H;H5/`HH=!HH5`ԍH; H5WH=! H5W訍H;H5W蔍H=m!H5}W|H;H5?WhH=A!H5'WPH;H5WCYtH;H52CEtH=!H5C-tH;)H5@tH=!)H5@tH;+H5@sH=Ʋ!+H5@sH;%H5.AsH=!%H5AsH;#H5@sH=n!#H5@}sH;'H5@isH=B!'H5@QsH;!H5b@=sH=!!H5J@%sH;5H5?sH=!5H5?rH;H5J?rH=!H52?rH;}H5,?rH=!}H5?rH;wH5>rH=f!wH5>urH;iH5>arH=:!iH5>IrH;mH5f>5rH=!mH5N>rH;H5G> rH=!H5/>qH;{H5(>qH=!{H5>qH;eH5 >qH=!eH5=qH;uH5T>qH=^!uH5<>mqH;gH5>YqH=2!gH5x>AqH;kH5 >-qH=!kH5=qH;cH5=qH=گ!cH5=pH;qH5d=pH=!qH5L=pH;H5W=pH=!H5?=pH;sH5~<}pH=V!sH5f<epH;oH5=QpH=*!oH5=9pH;H5=%pH=!H5h= pH;yH5<oH=Ү!yH5<oH;H5;oH=!H5;oH;!H5CoH=z!!H5CoH;]H5CuoH=N!]H5C]oH;!H5CIoH="!!H5C1oH;!H5CoH=!!H5CoH;H5zCnH=ʭ!H5bCnH;H5WnH=!H5WnH;;H5=nH=r!;H5x=nH;GH5r=mnH=F!GH5Z=UnH;KH5v=AnH=!KH5^=)nH;H5*=nH=!H5=mH;SH5=mH=¬!SH5<mH;H5PBmH=!H58BmH;H51BmH=j!H5BymH;H5BemH=>!H5AMmH; H5A9mH=! H5A!mH;H5A mH=!H5AlH;H5AlH=!H5AlH;H5AlH=!H5|AlH; H5sAlH=b! H5[AqlH;H5UA]lH=6!H5=AElH;AH53A1lH= !AH5AlH;!H5AlH=ު!!H5@kH;@H5@kH=!@H5@kH;H5@kH=!H5@kH;H5@kH=Z!H5@ikH;H5@UkH=.!H5@=kH;H5x@)kH=!H5`@kd H=0Hѩ!jH=ũ!H@`H=\0jH=!-H`H=|0jH={!"H_H=L;ujH=V!H_H=/PjH=1!H_H=:+jH= !H_ H= 0jH=!Hb_H=b/iH=¨!H=_H=/iH=!H_H=Y/iH=x!H^H=%:riH=S! H^H=.MiH=.!H^ H=/(iH= !1H^b H=/Hߧ!hH=ӧ!HV^H=r.hH=!-H1^H=.hH=!"H ^H=b9hH=d!H]H=-fhH=?!H]H=9AhH=!H] H=6.hH=!Hx]H=x-gH=Ц!HS]H=-gH=!H.]H=o-gH=!H ]H=;8gH=a! H\H=-cgH=gH=!1H\H={-gH=!Hx\H=,fH=Х!-HS\H=,fH=!"H.\H=7fH=!H \H=,fH=a!H[H=+7cfH=fH=!H[H=+fH=!Hu[H=+eH=ͤ!HP[H=+eH=!H+[H=`6eH=! H[H=:+eH=^!HZH=U+`eH=9!1HZ_H=*H!2eH=!HZ H=+ eH=ޣ!HiZH=*dH=!-HDZH=*dH=!"HZH=~5dH=o!HYH=*ydH=J!HYH="5TdH=%!HY H=V*/dH=!HYH=) dH=ۢ!HfYH=)cH=!HAYH=)cH=!HYH=W4cH=l! HXH=0)vcH=G!HX H=M)QcH="!1HX ] H=u)H!#cH=! HXH=U)bH=ǡ!HZXH=3bH=!H5XH=U3bH=}!HX H=(bH=X!HW H=(jbH=3!HW!\ H=)H!9bH=!HWH=])bH=ՠ!+HpW H=(aH=!;HKW H=(aH=!)H&WH=(aH=f!:HWH=(aH=A!1HVH=(^aH=!,HV H=(9aH=!2HVH==(aH=՟!<HpV H=v'`H=!3HKV H=F'`H=!H&V H=g'`H=f!HV H=6'`H=A!HU H='[`H=! HU H=&6`H=!HU H=&`H=Ҟ!HmU H=&_H=!HHU H=&_H=!H#U H=&_H=c!1HU\Y H=U&H9!t_H=-!HTH=&O_H=!+HT H=7&*_H=!;HT H=&_H=!)HaTH=%^H=!:HMH=! HBH=MH=ʋ!HuBH=qLH=!HPB H=!LH=!H+B H=LH=[!HBH=LH=6!HAH= `LH=!HA H=;LH=!HA H=aLH=NJ!HrAH= KH=!HMAE H==Hu!KH=i!)HAH=KH=D!(H@H=:vKH=!'H@H=]QKH=!&H@H=,KH=Չ!%H@H=KH=!Hc@H= JH=!H>@H=JH=f!1H@H=IJH=D!H? H=vJH=!H?H=QJH=!H?H=(,JH=Ո!H? H=qJH=!Hc?H=IH=!H>? H=IH=f! H? H=IH=A! H>H=_sIH=! H> H=NIH=! H> H=[)IH=҇!H>H=IH=!H`>H=wHH=!H;>H=HH=c!H>H=@HH=>!H=H=pHH=!$H=H=KHH=!#H=H=u&HH=φ!"H=H=HH=!!H]=H=GH=! H8= H=GH=`! H= H=GH=;!H< H=mGH=!H<H=HGH=!H< H=#GH=̅!H<H=FH=!HZ<H=FH=!H5< H=FH=]!H< H=FH=8!H;H=jFH=!)H;H=?EFH=!(H;H= FH=Ʉ!'H|; H=sEH=!&HW;H=LEH=!%H2; H=qEH=Z!H ; H=EH=5!H: H=gEH=!1H: H=EEH=!H:H=  EH=Ƀ!H|: H=DH=!HW: H=DH=!H2:H=DH=Z!H :H=DH=5!H9H=gDH=! H9H=BDH=! H9 H= DH=Ƃ! Hy9 H=}CH=! HT9H=CH=|!H/9 H=CH=W!H 9H=$CH=2!H8H=DdCH= !H8H=?CH=!H8H=CH=Á!$Hv8H=YBH=!#HQ8H=fBH=y!"H,8 H= BH=T!!H8 H=BH=/! H7H= aBH= ! H7H=; H=}!4H<4 H= >H=\}!;H4 H= >H=7}!>H3 H= q>H=}!H3 H=h L>H=|!H3H=\ '>H=|!H3H= >H=|!H^3H= =H=~|!H93H=5 =H=Y|!H3H=a =H=4|!H2H= n=H=|!H2H= I=H={!CH2 H=; $=H={!<H2 H=o H30H=,:H=Sy!H0H=:H=.y!H/ H=h:H= y!H/H=C:H=x!H/ H=F:H=x!Hz/H={9H=x!HU/ H=9H=ux!H0/ H=b9H=Px!H /f3H=H#x!~9H=x!H. H=Y9H=w!H.H=49H=w!H.H=d9H=w!Hk.H=q8H=w!HF.H=n8H=^w!H!. H=f8H=9w!H- H={8H=w!H-H=V8H=v!H-H=w18H=v! H- H= 8H=v!Hh-H=]7H=v! HC- H=}7H=[v!H- H=7H=6v! H, H=(x7H=v!H, H=<S7H=u!H, H=J.7H=u!H, H= 7H=u!He, H=6H=}u!H@,H= 6H=Xu! H,H=6H=3u! H+H= u6H=u!H+ H=P6H=t!H+ H=+6H=t!H+ H=6H=t!Hb+ H=5H=zt!H=+H=5H=Ut!H+ H=5H=0t!H* H=r5H= t!H*H=M5H=s!H*H=(5H=s!H* H=15H=s!H_*H=4H=ws!H:* H=4H=Rs! H*H='4H=-s!H) H=o4H=s! H)H= J4H=r!H)H=+%4H=r! H)H=4H=r!H\)H=3H=tr!H7) H=3H=Or!H)H=3H=*r!H(H=Ml3H=r!H(H=TG3H=q! H( H="3H=q! H~(H=2H=q!HY(H=2H=qq!H4(H=2H=Lq!H(j,H=Hq!2H=q!H'H=s]2H=p!H',H=hHp!,2H=p!)H'H=,2H=p!Hc'H='1H=kp!%H>'H=1H=Fp!#H' H=1H=!p!H& H=s1H=o!H& H=N1H=o!)H& H=R)1H=o!H& H=M1H=o!%H`& H=0H=ho!#H;& H=0H=Co!H&H=0H=o!H%L*[Hn!HMe!HEfH1H(e!H @ATIUHS)HXH*C ItC H[]A\C H[]A\fSV)HXH)C [H7H?f.AUATIHM USHHdH%(HD$81H\$Ll$IHkMH#H%H|$L#H|$F%H8HD$ HPHxHT$ HcH9|$(H-d!L(L`L(AD$H<$D$@toB/D$@|$&tgT$HH"xHL$8dH3 %(HHDuIHH[]A\A]fDHHHD$ V"돐H-d!VH=8.C#ff.1HH+-ff.1HH )ff.USH(dH%(H$1D$ Hl$N'HXH'{HT$ H!xMT$ w2{HH$dH3 %(u/H([]f.D$ H=5-@"USH(dH%(H$1D$ Hl$&HXH'{HT$ H*xMT$ w2{HH$dH3 %(u/H([]f.D$ H=s,!SH dH%(HD$1D$ %HXH^&{HL$ LD$2$t-t$|$Ht6H|?&'HT$dH3%(uH [H=+ ff.@USH(dH%(H$1D$ Hl$N%HXH%{HT$ HxEt$ w*Hj*H$dH3 %(u*H([]DD$ H==+H USH(dH%(H$1D$ Hl$$HXH%{HT$ H(xEt$ w*H)H$dH3 %(u*H([]DD$ H={*UHAWAVIAUIATSHdH%(HE1#L`LU$A|$'LljL߉A"EAHH9tHH$H9uHH$LL|$#ILEDA|$LD!x9uL(DDH2#HMdH3 %(u He[A\A]A^A_]It$H=&~ff.AVAUATUHSHH0dH%(HD$(1H5Rh!HQH;11H5.h!HD$HH;11tH5h!HD$HH;11SHD$ $H\"HXH"{%Ht$ljHT$A)!H|$ A@@uyt2H5@ t"H4ttF H|$ HD$ H( gLpHhHcH9t"Hs(Lt$ D$ H!{ALDD!HL$(dH3 %(H0[]A\A]A^H:HLH'D$ Lt$ tfHL$LL$ 1LD$Hc`fDD$ Lt$ ,H="'HHf!H= &HHe!H=p&HHe!HLpHsH=0#ff.UHSH HXHr C t${c H[]HH[]j!f.UHSHHXH {1xC tC H[]HH[] !f.USHHHdH%(HD$1HH<$HtRŃw^HHXHz{t/HT$dH3%(uH[]<H=d %Hi[!H5jH81(UHHSHt;f%HH"HHgHxHH[]@H%Z!SH=H0u%H&Z!H5HHl#H;1HH54 H;HH5 H;H*H5H;1HH5H;1HzH5H;HH5H;HdH5sxH;H)H5c]H;1HaH5VEH;1HH5J-H;1HH5>H;1HH51H;1HQH5'H;HX!H5H;HH5H;HH5H;1HH5#|H;HH5aH;H'W!H5FH;H4X!H5+H;HX!H5H;[HW!H5~@H1H=1 fH55a!SHHtH111[mDH=j!H11HH`![1>ff.SH^H=V!H[HHY@`!AVAAUAATAUSH˅bu8{ŃtL;}{u;^{V[]A\A]A^=Ņt7uM8tHː;Ņu~{~띋;I;e_!uvHDDDŃt2_!;EHH|$Ht$HT$H2H HHf8HuBHcH9Hu HtHʃUHsJHDHRHnvHT!nH5H81fHrlHT$uHtHփtH HHU!H5H81HU!H5H81H f.ftf u#HH RHT!H5H81ff.SHH|$Ht$XHHD$H0 u}HHfHcH9Hu HtHʃ7Hs,{HfH|?dH[fDHpfHT$uHtHփtH HHHST!H5H81H;T!H5xH81f.AUI11ATLIUSHHHHxpHHu,Ht#HЃ(Hs]Hs"HH[]A\A]@Au IuAAuItIEt%H HfDAuItI $΃tH HЃwjAUH"ATUSH(dH%(HD$1Ld$HL$MH\$t_HHu^H|$L-Rt L IfLHteH8HT$dH3%(uHH([]A\A]HXHHHHH H50HNH5Q!H81HQ!LH53H81 ATH"USH dH%(HD$1HHl$IHH2H|$tH"HHV H|$It H HHLHt-@fHL$dH3 %(HDuDH []A\@1Ht$LqHT$:tHP!HLH5H81 @AUH2ATUSH(dH%(HD$1H\$LD$HHAH|$H"H|$H HκHH@H?HH2.H}ILHLHIH]Ht'H;HtHLHH;HuHcuLHt6H]H;Ht'HcuHLHhH;HuHT$dH3%(LH([]A\A]fDHw Hu1H H|$H uHH΃DHwHcH9tH  HN!H5 H81) @SHHߺ HH}[H@ATUS1] HL`#@ 8t$uUHHHLHE tH}HxH}HE tH} HH H[]A\H5* ff.HHHHUSH(dH%(H$1D$ Hl$>HXHsHL$ 1HT$ HHH HHsH$dH3%(u H([]Q USH(dH%(H$1D$ Hl$HXHsHL$ HHL!H8xT$ HHH& HHH$dH3%(u H([] fUSH(dH%(H$1D$ Hl$HXHrHL$ HHHpK!H8T$ HHH HH;H$dH3%(u H([] fHtkHftVv<f tfuw HAE11j)H@fnEDf.USHdH%(HD$1HH$tt, H$HHu?fDHHt-H{HtfuHHHHuH$HgHHT$dH3%(uH[]H= ff.USHHt$H|$H\$dH%(H$1, 1H{ HD$HCfHfD$Hl$HU t}HUHlHuH{l H H߉u'HtHʃBHs7H$dH3 %(uhHĘ[]HHuHT$uHtHփtH HHI!lH5H81AWAVAUATUSHH $HHE1dH%(H$x1HL$LD$0HD$ HD$(HD$8HD$0HD$FH|$0HH|$MHHHHD$ oHPHHpLD$pL H3I ^HHcH9pLL$p L$pHAUAMLY_ƅH|$8HHHX(HtyL$pH$pfDHsH{HAUAM5XZ'HL LL H[(HuH|$8L LH HH H$xdH3 %(HĈ[]A\A]A^A_fHHp@tAFDHsA+H|$h HHfHD$)D$@)D$P)D$`H iHCHlHKHH\$H :2HCH\$H(HHH\$H HCH\$HHHD$(HH\$H HC(HHD$ HL$@H|$ H$pv HHVƄ$o HL$(H&L$p H1HL%1AD$H1HtHHHL$8HT$@LD$DÅ HD$8HHxpHH'HHH\$H HC H\$H(HHH\$H HCH\$HHHD$(HH\$H mHC HHD$ H1H|$(L$p LHƄ$oHC H@ HC HHC HCA0E1fD$p uHC HOHC H H\$HHH\$H t8H HHD$ H|$8 HC!H5H81LH[ H‰t$ H|$8t$ HË(Ht t$ +H= H B!H5H81H|$8HD HtH DeH= HH|C!H5H81;HA!H5.H81#Hff.UHHSHt;V HlHhH}xH[]fD H= ff.ATUSHH=H dH%(HD$1HLL$LD$H|$u HD$=Ld$H<$?L5H|$A@t? Dfx8H߉ H\$dH3%(uH []A\3H=, ff.AVAUATUHHZSH0dH%(HD$(1HL$LL$LD$H|$u HD$H\$H|$bHAWH|$A@ Lt$ DDLx}\$ HHlj\$$HIHLHH# uHT$(dH3%(HH0[]A\A]A^n@vH=m D3LDDFfHLHH=|H`*f.AWHAVAUATUSHdH%(H$1HD$HHL$PHD$HPHD$HPHD$HP1LL$HLD$@H|$Hf1)D$p)$)$H HtH|$0D$THt D$XH|$8HMH|$@H\H|$HHkH@>!D$Ht$ H|$HT$P1IċD$D$ MdI,$IHubf{L{ L_IHcuHHt6{HcuHHt6jHcu HHt6YHLNHm(HtMuH}T$ %Lm HMtHHH qHC LxhL@LH$dH3 %(}HĘ[]A\A]A^A_@@tRH|$@D$\H@tH5RH;HH5@H-5!H;H57HH;HH5#H;1HH5H;HH5H;HH5dH;HH5IH;HH5.H;H/H5H;HH5H;H9H5H;HH5~H;HH5aH;HH5`H;HH5@qH;HH5#VH;H1[HH5]8SHHHt :HCH{0Ht $HC0{H\HHoL`LfH$\$`HD$@HD$@HHD$HD$PD$dD$tAT$HD$(HHD$D$Ƅ$HD$HHD$ HD$0D$8HD$PHD$X$<$tX$HHtH$dH3 %(u>HĐ[]A\DHpHXH[It$H=NKH7!H5@H81ff.AWAVAUATAUHSHHdH%(H$1u HHuHLl$ 1HD$"I}IEfHfL$ H HSHlsHslI}XH1ҾA,AƅWEDL[HDvODHH L`LoHwID$H$dH3 %(HHĨ[]A\A]A^A_fDHƒ urtHCpDHHsHT$ Ht$Ll$H=D|$D$T$ xaDHJ@H{t HC8GHEH!lH5,H81zHH=DCHH=?D'HH=D|$ g1uDH!SH=H0H!HHH5HpH;1HH5 XH;1HH5"@H;1HH5}(H;HH5} H;HH5H;HH5H;H8H5GH;[HH51SHdH%(H$1\HXHsHT$1HL$ D$ n$H$dH3%(u HĐ[SHdH%(H$1HXHPH!!sHT$HL$ D$ nH8H$dH3%(u HĐ[ ff.SHdH%(H$1lHXHH!HHL$ HT$D$ nH8lH$dH34%(u HĐ[ff.fH=!SH=PH05H!HHH5HH;1HH51H;1H H5H;1HH5H;[H!H5˽|f.fAUIATIHUHSHLD$HHc؉LH\Hc H|$LcH5!HtrHLHl-H5!HHLOl-H5!HtvLLkH5|!H\$Ht:HLOHL[]A\A]ÐH=HHU!nH=ڹHH!H=HH!jH= HH!.SHHH5!dH%(HD$1Ht8HHH$H$HT$dH3%(u-H[f.H=HH=!ff.ATIUHSH+!Ht&LNHH޺[H]1A\DH=HH!HdH%(HD$1HH$H$H uCHHtNHusHHEHt$dH34%(uHHDHHHt.Hu3H@fH8HEfH@HF!H5H81HdH%(HD$1HH$H$H u;HHu>HHH%HHt$dH34%(u:HDHJHu HRHH!H5H81ff.HdH%(HD$1cHH$WH$H u3HHu6HHt$dH34%(HcHDu:HDHJHu HRHH!H5RH81hSH5!SHHt H[H=1/H[HHQ!ff.SHuHc[HD@H[ff.@H u@HHu+HGHHHHH1H5HÐ1DHuHGff.H u@HHu+HGHH1H5VHfD1DHuHGff.AUIATIUSH(dH%(HD$1HHHt@+v@AtbA)ECA A5HҷJcH>HH5UHH1AubfH|$hHfDDH5H1\%AA HOJcH>A HD$hH pLhIgbH@HhD`Dx,Dp0L$:HL$;HL$9HL$H L$HL$4HL$$HL$ HL$EH5P!DH1H5!DDHH5VH1K H5Hb@HHcH>H5H3T$:H5H1mT$;H1H5 WT$9H1H5AH5H=AAVA&AAA =EkcD$CDD$H5ήHAMbHi@BA)1虿D$DD$HH5Hi@BA)1hT$4H1H5wST$$H1H5n>T$ H1H5e)T$HL$HHco )d$oh)l$ op )t$0H@0HD$@迨HL$HHH5=1&iHXH5H1 f%) H5M D< t"HH_H觝H54HH1胠Af)A2I HHIAo>Hl$pHt$P.H Ef)|$PڛHHH5H1Hl$`DH}HHH5nH1OHH5MHH1蜟H蘜H5%HH1tAI HH IIHl$pLd$It$HHD$AFD$ܚHHH5H1|$H胥H HH5tH1ƞIt$HHHH5H1蒞!DH5 Dq@AI IVHE1In2HI9HB H5H1II tM;fIF@H5 D@IcHDH5 D@HIVHfDHH3I HIVHHHLbHl$pH$HL$HHo )D$oH)L$ oP )T$0H@0HD$@xLHHH51p@I uhHH ,IAANH1EFH5蟜H5 H;fDI~IV@I~ MvI~MvI~ MvDH5UHH5H贜H5ɈH蛜H5H肜aT$H5H躛pAUHMATIUHSHdH%(HD$1QHlj襙L߉ƉLAAtK膦H|$D$DHHL$dH3 %(uH[]A\A]f+Ě@AWAVAUAATIUSHHdH%(H$1HD$HHhHw}询HD$@D$HD$8CHD$(I$HD$8~ ID$HD$(MIH|$8IODxD|$Ht$脛EH\$pE1H|$(gD@EDEH|$@t H|$@HHLt$PL|$`覞HHHT$PHD$XHD$HHt9H8 HHH$HcH9#H$H@EE1HLH=AH\$hD$`Dd$dޕH }ܛbHHD$@fHC0))C)C Ht+H8 uwHHHD$pHcH9s|$xHT$8L$HDŽ$H HBHD$PHBHPHxH$HPHxHT$pfHE1Ht$`HH=0H\$hD$`Dd$d͔HtWHT$HHT$`HT$HH@HHDH$dH3 %(H[]A\A]A^A_˔8 DH=vfDID$HD$@JH|$(@̢A}@1E1HD$HHD$pHD$ fHD$pHH HHHHH4HT$H $SHD$HH $HT$H HH1H7HT$pD$HD$H SHHH$fo$ Ht$pH HHHyI[D9d$jHD$H Hy}JHIHH CH51L裔LH$蒔LI肔HD$p\$H4$.L߉AoH|$ AH/H|$HH ^HD$pHOH aHPHHH_@HVHvHB@H@cH5) H1H1脕H5 H$Htd1H1hH5 IHt)1H1MHD$pI~H=y迟HH H=o蟟HH} |H=oHHe @H|$(趓AwH5͑HU`ːHd H5H81#HG H5H81fD1%DfU@SHHnHt9kvkH[]WHw?Nff.AUATUSHH_(HvnHw HHtbIIHL9muHHIt$ HEHHڃHHv%IL$(HH)H9wH)H9w HHHuH[]A\A]ff.@AWAVAUATUSHH $HH $H AHT$PH}L$HHL$hHdH%(H$)1HDŽ$H$P1L$L$虑H|$xA[[Ht@HIHD$H|$pHt@HH|$H|$xD$LH\$LDT$HD$ ؃@EDH|$hD$Lt1H|$pD$ H$D$\t5H= H;OH$H译HD$\H|$PLhLiLH$\$LD$XAHD$H$H$HD$(HD$HD$ H$HD$0H$HD$8H$ HD$@fLt$8Iv&ILL-MwI tMwH|$HT$@v5H$HHt$H$HPH tHPH|$1fE DD$ HHD$(H|$HE,E4H$HD$ H$LH$؃EDŽ$HDŽ$EL$L$H$DL$HEAEHt$01HH=H$$$qHt$ H|$hH|$p#9\$LHZ\$LLt$8D$ IIZLIUfLؐAEHt$01HH=_H$$$贋HC8 |$Xt ZfD$Xf$ MMH|$pHYd@1$HL$Hvb;$vSL$XfufDH|$辐H$iA}藒LגfH|$Hd$HD$HD$ FfD7T$ VfDHILۍAHB LH0$H$L$H|$P~H$Hc$HDH$H$HHD$跘A}I;H$D$ HHH$HHHL|$HHH{H9HBHH)ޖS s|$ HLT$\IH[H9Cu HHH|$LHH$HHكHHvOH$H)H9w?H)H9w7HHHt*HHOH H5PH81fDL|$H$H$H$H$)dH3%(L HĘ)[]A\A]A^A_I!IƒI衋I.H=> hHH6 tHD$%f.@葖D$LH9CٌIH HLHLkL4HHHD$ I9eL9s[[fDD1H5b IHLIRLHI$L9L9l$ EeHT$D*xDYL=Z AtADE$%=NH H8ωDHH5 IHC H=|HH~ #LIRH袈D$LDAHHAIIƒH€IILf H={H H=osדH5|1iH H5|H81хH H5|H81蹅H H5~H81衅茈H H5|H81脅@1DrfHH H5|HH@ H8(HH5\mHH 趎H= 1HH5x蚎H= 1HH5~H= 1H^H5SbbH= 1HH5!bFH= 1HH5l*H={ H7H5{ H=\ HH5w H== 1HH5wЍH=! HMH5yэH= 1H1H5y蕍H= 1HH5,{yH= HH5{zH= 1H H5z>H= HH5z?H=p 1H?H5zH=T 1HH5zH=8 1HGH5zHnjHHH% ff.HHOHWHwH?TtHH8HHDHG HWwDO(LG OPH?誇HHH 1ff.PXH5{HH| H81BfHtSHH?[H{[Qff.@PXH5{HHt H81fSH5 HHt`pHx 蛎u HtHʃHs[DuHtHփtށH H[bfHH5 lHHx"L@ PHL)9rVfx uOII9rsHI9|I9vKAxHt?Axu1II9uH)H鼍@H H5zH81ЀLHH)鑍HU H56H81褀H= L¹lH5^H)H81聀HH5 者HtH1zv fz uHB(H;ff.HH1Ht:t HRHDHHsH1Ht:t HRHDHH3H1Ht:t HRHDHHH1Ht:t HRHDHHH1Ht:t HRHDHHsH1Ht%:uruJuB ȃHHЃHff.@H#H1Ht2uJuzHDHH1Ht<H҃HHfDH1Ht%=HDHHff.@Hs1Ht%=HDHHff.@H31Ht 8HDHHHH1Ht$:uruJuz HDHHH1Ht:uruJu z HHfDSHH5 Ht H1zvfz u B$ȉ[fDHdH%(HD$1Ht$1҅tD$%=HDHL$dH3 %(HuHd@HdH%(HD$1Ht$>1҅tD$%=HDHL$dH3 %(HuH@HdH%(HD$1Ht$1Ʌt2T$%= t>%=t0f1ҸHDHHL$dH3 %(uHfD|~ff.HH5 |Ht|Pv\H ΃fuMft*f uAuY@"HfHDf.tH H5zH81{H H5tH81zH H5zH81zff.HH5Q Ht$H1zvR fHDHnff.HH5 lHtH1zvfz HDH$@HH5 ,HtH1zvfz HDH@HH5 ~HtH1zvfz HDH@HH5A ~Ht H@HyfHH5 |~HtHc@HHDD@HH5 L~HtHc@HHD@HH5 ~HtHc@HHD@HH5 }HtH¸zv B HDHfDAWH5C AVAUATUSHdH%(H$1}HxLh"Hh I1LH)A9F^A~|HHA覂A~H$A~2؃yHHfM>IIFHD$xHH?HD$LT$`H$HAvjMйHA HLT$(|ZYLT$LހHHӀHHXHD$(H$Ht$ HL$Ld$8HD$0HD$HL$ Ll$@HD$HL|$PȅH$dH3%(7HĘ[]A\A]A^A_A^ fDIFM>HD$uwHH~4HD$AFHL9vZ}uTL }uBHI9uL)LAH }HHʀI,fHH H5mpH811vHʹ AVH5oH81vH H5"pH81uH AVH5oH81uxH=`AHU AVH5oH81uAWAVAUATUHSHdH%(H$1H|1ILo?fUH uIHcH>fDH5oH yH$dH3%(H[]A\A]A^A_H5SIHxH5oHzH59qHzDHH5ct1wH5oHxxgH5tHH\xKLMI9{L f{HL9uI9VHE1I9WA|$/tH5nHwLLHwAT$1H5mHwAT$1H5nHvAT$1H5mHvKAT$H5mH1vAT$f҅KA%DH1H5rhvH5rH1DvsH A$H5nHvHH52mvHH5mvHH5 mvHH5lpvH5lH\v&HHE1jHE1DLnwZY6AL$ffHH5l1HJuAAWH5wlH1+ufDH(rH5 mHH1uMA?I8{uDH5hEHuL%elIAV1LHtI9uMfAzuI9uM)6DHHv&I9 H5kHufDSvAT$1HH5kf%tH5QmHIvA|$LzH,LH5qH1sA H5 mHuAT$1HH5pksA tsH5lHuAD$ <<<<H5;kH1YsAD$ A9uA uHA98[H5llH8uA AT$ 1H5jHsA H52lHtH5jHsAD$ HH H9A_E1L5kfDMH5qHIEtCT, H1H5%jIrD9wAD$ 'H5iHsAT$f҅H5wiH1/rf.ڸ PH5viHrH5PHrvAT$H5liHqH: H5(QHCr5H5QiH*r H52QHr H5iHqpH=HXP{H5ThHqHH5=hqH5,hHqOff.@ATIH5@ UHSH dH%(H$1rHHHL$LHyU1oH|$1H{uL$Hl$HsPHH{ AM-rZYukL_vHHTvHHuH$dH3 %(u5H []A\f.@t {knaoH=Vyff.SH5 HHdH%(HD$1hqHtcxvE@ fu8HHڿH$x1HmHL$dH3 %(u#H[H H5eH81knfDSH5t HH dH%(HD$1pHx@ fuwHHt$HD$HH mH|$HD$j1 HrHHcHTyHHL$dH3 %(u#H [H H5dH81 kmff.@AWAVAUATIUHSHHHL$dH%(HD$x1HdHLH5eoLIAmI98 1L9qD$HrD}DuDm EA ЉAtHH5eYoHIlI9HT$\H޿SqD$H jE1ffD$EtvD9qtpHHEjH9uMoL|$(;pH|$HT$(HHX1ۉH\$xdH3%(HĈ[]A\A]A^A_fDEAA9tw0HL$[wHD$o1HT$H@HL$fpf8|$t$\@ fxpBqrDLz(I׉r BHBHB 0HL$vHD$-o1ҹ|$H@fPHT$fHL$t$\@ fxpBqrqlHD$(Ht$01HH=6H\$0Ld$8Hl$@HD$HgÅ}YfDD$HH5TcHE1E1mHIjL9HT$`H޿ oAŅAqfH5bH߈T$lHHD$0jT$H9D$(T$HHT$` nL$D$HgE1LJffD$Et"D9rtHI9uNfDE1EBD9tuϾ0HT$tHD$`mL$A E1ffDHT$L &g@foT$`fHHL$H@fD@PA rqDLy(Iωq AHAHA 40HT$\tHD$lL$fE1A @HT$L ffDfoL$`fHHL$H@fDPHA rqrXhff.fATIUSGHu#9fH{Hk(iHHiHu[L]A\iHs[L]A\iff.H#pHfHHdH%(HD$81D$PH<$H=Yt$HHT$HHL$1LD$ LL$(D$ dHT$8dH3%(uHHgfHE1E1jeZYuHÉH=NqfDH(1HdH%(HD$1Hf4$HD$fH@ |$HHD$dH3%(uH(gATUSHH|$HQH" HIH04nHH|$ahH|$eHl$HE t`HmHtcEt[<<HWfH=JHH߃1ҨuuuaHH[]A\DHEu1HMtA $fDH|$fHމMtA $fDDfDLf HzِUa@H1HH?fDH1[]A\DH=%^H. H= ^HH޿M HHw H5]H816bfDAVAUATUSHL/LgdH%(H$1HGHfH{ HHBkHHgmLk MtLvdH=v~17gILH9mHcsHHt6(msH{AHH mH[(HuH$dH3 %(HH[]A\A]A^LgIHneMmIMcI}HVf.[jILH|lI}Hu*fDLH1Hcff.AUATIUAHSHHHt$dH%(H$81HH\$Ll$0HrHzjLA I{aZYueMu HtHEƒDLl$Au%ItIEƒf.AfDMuHtEfDH|$@t=@HtthH$8dH3 %(HpHH[]A\A]HtuH|$H^H5UHH1ebHtHЃHr;Mu6Ht-HM΃tH HЃDH HЀH{H HSifDlH|$HlH5XH߉1aH1 dH|$Hl9DHD$6fDHgHHMHL$(HH ΃ H ʉHD lH=X1 gHHu tHuLcHDKIu tIuHsc["fD\H=SH1fHfH_fSHdH%(H$1HHH)fH$dH3%(u H[_AVAUAATUHSHHPdH%(H$H1HT$ Ht$@HD$D$ 1H\$IHH|$`H|$b]H\$H H[H^HfLt$ HP HLAbLEt ED$ EHHL$HLaÅt>MtLQ^A| H=EhHkH$HdH3 %(HD$HP[]A\A]A^@HLt$ 1HH@EL_ZL$ 1f|$ t9Ht$ LHD$.cHD$Ht8uELHY H5ZH81Z1]HH H56VH81yZfAVfIAUIATIULSLH@dH%(HD$81)$)D$)D$ HtH%[D$It L\D$HuAHuRL$pHLL]HthHL$8dH3 %(uSH@[]A\A]A^Ht(hD$ HtH߃th$[֐[t\H H5NCH81lYff.AWAVAUATUHSHH5 HdH%(H$16^H=H OH@CH߾YLd$81HHZLHD$8c]H|$8H7 HwHHT$(aHGZLHD$8]H|$8H7 fHHHT$,aHYHD$8H<D$0HYHD$8HpD$4HYIHD$8Ht L}\Lt$8HYIHD$8Ht LU\Ll$8HcY|$(HD$8cH VNHAHXXLcD$4Lcd$0IHHc\$,ODOd$LD$H\Y1LHD$XHLHjLD$ A HHt$L$HHLD@HpLLD$Md]XHZa  eDL$4DT$0AHHD\$,H@LD$HE !H{ LLD\$DT$DL$\D\$DcHDT$DL$LsD[DSDKL+H$dH3 %(H[]A\A]A^A_HHaHwHLZH|$8H7 HHHT$0ZHG H5QH81UfDL0ZD$(u2H|$8H7 HHHT$4VRH H5|QH81ZUf.H\$@1 HD$BH{HCfHLfL$@YHt$8H HVHlmHvH{lAnC[foD$@ H$foL$PfoT$`L$H$$fo\$p)$fo$fo$$$)$)$)$)$)$f$dbDL$4DT$0AnHHD\$,H@HE `@HwHHwHnHHHQ H5SH81SH9 H5OH81SVH H5OH81S.H' lH5KRH81qSHHfdH%(HD$81ID$I@$A@,T$L‰ $A@VHT$8dH3%(uHHUfAWAAVAUATAUHSH8?dH%(H$(1gSHtbHH$ Ll$ ]H\IEtzHLIjADHSZYH=<_H$ DEH sNHLl$ 1`H[IEuHE1E1jLDH4SAXAY[LP[HDHjAIعLIR^_PL[IHLD@L[IH1 HKXHL4$HLd$HDHl$HD$`H$(dH3 %(uH8[]A\A]A^A_*Tf.HGHH9s>~u-H ~uHH9uH9v1H=;SHH)H]Hff.SfPH=w$HRSH[HYfDHH u0HtuYHcH9u[HÐHfDHGHtHW:u&H9vHm H5VPH81,P@nHHOfDAUATUSHHHt$H|$dH%(H$1\TLl$IUH% IUHlsLd$ 1HD$ID$fI|$HfL$IuI|$lUL S=HK shtA$S CCkCHCHH$dH3%(HĘ[]A\A]@I$H{(HHS ItHtH)LH)H념Ld$ HIuI|$HD$ID$fHfD$fA$S Att-fAtft9QHm lH5:H81'NUHS;SH(dH%(HD$1HL$LD$PH|$HtOH: Hk 1H8QZ H[Ht$HHH@HC }u HuHL$dH3 %(HuWH([]DHЃHrHD$uHtHt%H HPAWAVAUIH5 ATAHUHSHxdH%(HD$h1QH? L|$0E1ZHLLHHDHHH@HE HD$PP1LL$PLD$HNH|$HY^HtcMLcH|$@E1HtMNLcH|$HD$HH|$0iRIH1HL|$PMLHD$PPH|$PH7 HwHHT$,U}D$, FLEMH|$`HD$`PHt$`HtHL$hdH3 %(HHx[]A\A]A^A_fDHHd@VYD$LOHD$0H 7HPHpHcH9AԁsH{ 6QD$DcDsDkCHCH+L;LLI+LLHD$XLLAHD$`LLcH|$XO|?t H|$XNH|$`Ol-NHD$XLcd$HD$Od$EuLct$,KD6LT$`MLHD$HA LjHT$LLT$(uIXZLT$Ht$L.OHD$HIAHx HtBRIǨu6Ht.Hƒt!H€IItu L,T@LWLHD$WH|$IWIIDhHpAH{ DLD$uOD$DkLLD$DcCHD$DCL{HS`@+KD$fHHpADWLfDIH|$LHD$H H5xHH81vHaK H H5-DH81THLGH5DHHۋ H811HHGfH(HdH%(HD$1HT$H H<$H=Ht$HQLHT$dH3%(uH(JAWAHP AVAAUEATMUS1HH H<$H8T HUHH@HE wLH4$Hx HD$MLD$HD$PAXIHExEpEhM`H[]A\A]A^A_fDH(H5 dH%(HD$1KHH¸zfz uzDJ(EuqDB,EuhJ0tuYJ4ɃvOH1HHD$ fGB4fL$DBG LJD$ J2R^_Ht$dH34%(uH(IAUHhBATUSHXdH%(HD$H1HL$HHD$HPHD$HPHD$HP1LL$HLD$@GLd$@H\$8HjLL$PLD$HHL$@LHHT$80^L_HHHIEJH]IHDH{ AHt9MIu-Ht%HƒtH€IyItt[HDC KSsH{AU\QZLYHPH[(HuHOLHL$HdH3 %(uHX[]A\A]LLL$OLL$GATIAHUHISHjHY^HHLLAHIz HtLIt>LHARIzEB AJArUPHHXZOHH[]A\@HtHƒtH€IyItuLLL$NLLL$SHH5M HHHHt H@H[{ff.H HֺH#HֺSHӅtH[f.HߺH5i?FH[SHH5 HHtpHHx [OfDS1HH=T-ZEH[H뱐ATH5C IUSHdH%(HD$1GHLHLH=>H1KLHHRDcE{KC A9>{U-St$CHSH5v>H1 EHCHt HH$$AH5BHH1DHHt HH$@H5<>HH1DH5=HSEHHL$dH3 %(H[]A\{uSS_tE1f[HHSH5=H1>DS)E DDDHHAH5AHH1CCCtArH5=HnDfH@H5EAHH1CQSH5<H1tCC@CtAH5<HC/fH8@H5@HH1CA踽BUH5T SHHH/H!AuHDHH[]H落Hff.ATIUSH/HHH5~ H@uHCH[]A\DH8HHI,$CH[]A\ÐSHAHH Hu H[H@[fSH5t~ HL@H߅u [@[¼fATE1UHSHdH%(HD$1D$rD&HLD$DDt;HE1DAjL$HJZYHT$dH3%(uH[]A\H=:KAATUSH@@uSHHH}@ tw t<t uc@H[]A\=DKH[]A\=EL`LgEA|$H[]A\t=@HuH H5,H81?= tt u@`uKH[]A\=DH SH=9H0KHF H5WHH|IH;HH5$QFH;1HH5809FH;1H H5Q9!FH;HRH5&&FH;HH5,9 FH;HH5%EH;HH5|)EH;HH58EH;1HH58EH;1HH58jEH;1HnH57REH;1H&H57:EH;1HH5{8"EH;1HH5m8 EH;1H.H5[8DH;1HH5I8DH;1HnH578DH;1H6H5#8DH;1H~H58DH;1HfH58zDH;1HH57bDH;1HFH57JDH;1HνH572DH;1H6H57DH;1H޼H57DH;1HH57CH;1H>H57CH;1HH57CH;1HH57CH;1HFH57CH;1H޺H57rCH;1HH57ZCH;1H.H57BCH;1HֹH57*CH;1H~H57CH;1H&H57BH;1HNH57BH;1HƷH5w7BH;1H.H5i7BH;1HH5,BH;H;H5'#BH;1H#H5*7gBH;[HWH57KBf.ff.Ht'HH@DHH@H 1ff.fAVAUATUSHdH%(HD$1H@H$1HuIcHDkHuH[H< x>H$1HhIDhD(H萉8HHPHL`D9uHc/=IH[Hw Mt L%{ DI<$HHH DLHCI9uHL$dH3 %(LuH[]A\A]A^D;ff.PXH57HHDy H816fSH5v ;Ht1HXCt H{(HtAH{([AfD[@SH5dv o;Ht1HXCt H{(Ht2AH{([6AfD[D@SH5v ;Ht)HXH{ Ht@H{ [@@[ff.SH5u :Ht)HXH{Ht@H{[@@[ff.HH5qu |:HtH@xHgArfSH5Du O:HtHXH{;t[HD;HDy HSH55H814ff.@HH5t 9HtH@HxH&>ATH5t IUS9HH=n5Hh+7HAfAD IA !I|$;HH:H50H8HuH\9E1H}t+H5j0H7H}>H}Hډ@H} t+ H5T5H7H} >H} Hډ?Et5H}(td H5%5Hk7H}(r>H}(Hډ?Et2H}(t+ H54H27H}(9>H}(Hډ{?HߺH5.7H[]A\IIMHv H8fAHB/NAAApAA@AĀAA AA:AYAA A@uyAuHMLH53H1;5fDHt H8Hiu H8H5O3H1I4H2H53H1I4Hq2c@H52H1I4HI22@H52H1I4H!2@H5/2H1I[4H1AtH52H1I54H1A@XH51H1I4H1AĀhostname too long (%zu)service name too long (%zu)unexpected address familyunexpected protocol familyunexpected socktypeunexpected protocolunknown:%d13unknown address family: %s24empty-sockaddr#<%s: PF_???(%d) TCP UDP SOCK_???(%d) UNKNOWN_PROTOCOL(%d) (%s)getsockopt(SO_TYPE)Addrinfoinspect_sockaddripunixafamilypfamilycanonnameipv4?ipv6?unix?ip?ip_unpackip_addressip_portipv4_private?ipv4_loopback?ipv4_multicast?ipv6_unspecified?ipv6_loopback?ipv6_multicast?ipv6_linklocal?ipv6_sitelocal?ipv6_unique_local?ipv6_v4mapped?ipv6_v4compat?ipv6_mc_nodelocal?ipv6_mc_linklocal?ipv6_mc_sitelocal?ipv6_mc_orglocal?ipv6_mc_global?ipv6_to_ipv4unix_pathto_sockaddrmarshal_dumpmarshal_loadsocket/addrinfotoo short AF_UNIX address: %zu bytes given for minimum %zu bytes.too long AF_UNIX path (%zu bytes given but %zu bytes max)unexpected sockaddr size for IPv4unexpected sockaddr size for IPv6 (%d bytes for %d bytes sockaddr_in)too-short-AF_INET6-sockaddr %d bytes(%d bytes for %d bytes sockaddr_ll)newline at the end of hostnamealready initialized socket addressLinux abstract socket too long0PЋuninitialized ifaddrinvalid interface name: %s,#<%sUP%sBROADCAST%sDEBUG%sLOOPBACK%sPOINTOPOINT%sRUNNING%sNOARP%sPROMISC%sNOTRAILERS%sALLMULTI%sMASTER%sSLAVE%sMULTICAST%sPORTSEL%sAUTOMEDIA%sDYNAMIC%s%#llx netmask= broadcast= dstaddr=Ifaddrflagsnetmaskbroadaddrdstaddrsocket/ifaddr; A00 X p  @   `$ PX l    < x  p @< @   p! @# ) =8KLU`P]t^``0a@bphh00iLihiPjjkpkk0l,lHldPmpmmmno4oHh|@p 4 Ht L@$`PpPp,0P00 8@T0`0T@ L`(@`x@  <\ppP     <p  T` 0(Lppp 0P`@P<X0p@!`!!! P"< #h # % (!(0! )P!)t!*!*!*!P+!,,"0-P"-|"p." /"/"0"@0#0(#1@#1|#2#4#P5$5,$6P$06h$6$6$7$8%84%pH%H%I%@I%J&JT&K&L&0N&PN&N'OX'@P'P'PQ'0S (pTD(pVp(V(0W(PW(W)W )0XD)PX\)X)PY)0Z*Z,*Z\*[*\*]+eH+Pf+ m+0m+@m+pm$,m8,0np,x,x,x-{ - {4-p{T-{p-{-{-|-0|-|-} .}<. ~\.`~|.~.~. .p. /$/ 8dR BED A(G@ (A ABBE 8S&TYQH C A YQH C A 8YQH C A T ZQH C A pdZQH C A ZQH C A ZQH C A 0[QH C A t[QH C A [QH C A [QH C A 4@\QH C A P\QH C A l\\\78 ]K F P H I G U K U K U K U8]K F P H I G U K U K U K U ^4^kEkT@hL4|XNFDD g ABH JABp&EU8bFBK A(Dp (A ABBG   (4EAGv AAK (`TEAGv AAK ED0u AA (TEAGs AAF (EAGs AAF , \EC DEJ A @8 LFBB A(D0G` 0A(A BBBD 0| VEDD l FAH DDA0 VEDD l FAH DDA( @EAN0j AAH ( YEGD v DAE < lLH\ Xp dRLR J c ,EX8 HEE D(A0t (C BBBD  l6H  F  Rw  ED  AG 8< FIG A(D0W (D ABBE 8x FIA A(DP (A ABBA 0 `FHA D@  AABE 8 FIA A(DP6 (A ABBG $ <Eo,@ FFA  ABA p d p( |EAGz AAA ( EAG AAA ( TEAG AAA  vIlM IE`(@ $EAD0 AAA (l HEAG AAD p uFBB B(A0A8G L11G1R1A1~1L1V1A1} 8A0A(B BBBJ ( eEGD r FAG 08,FAA N@  AABH @lFBB A(K0D` 0A(A BBBD `$FIB B(A0A8G^FFFup 8A0A(B BBBE PE,X&FDD Lh>Ed"EDG 5EDI $7EMO(B0F(D &FDD "EDG  XEF (<&FDD  HLEG0u AF lEG0 AE EG0 AK [ ,EAD CO GEAH(FLB B(A0A8D` 8A0A(B BBBG 0tPFKF Gd  AABA H`t A 0,VIG oAAIh 0 FDF G  AABF 0@TFDF G  AABF tL,EN@YHFPRHA@s AA <Eo$  \Lx `pEN0V AA 8mEGZ AA \uEGb AA TuEGb AA L@8XD|FBB B(A0D8DeRUD 8A0A(B BBBH <LhFEE A(A0[ (F BBBG 0FDD L@~  AABA 0dYEAD w FAH DCA0FDD K0c  AABH ( LD"KT(\EKFP AAA 4LTJPs !:lG".xҠ l ;#?XY `$ږs'*NS 25ކ2^T?WL-7BQjQY@QEv$ YOK)*9y=cVK1]_ E=~8`KGw2ULZ%}@'L(x۩~.1w?#M*'sj-+4PKࡻ0b+OcȽjGP8DVQv9E'Y.+!%6{xhKJԵH5H%5#:F)1T q{tS!(o*{)r!Kj&Ug>kYm|@t>i"u j*Ă^w8K9&v '뽊X;ܥZz ڦ~:u;c%tոuЪ|q !:M;+-nkNn7lyHQ_dUŲY@س|YWO R3ZrrI$úpx*CNf27GQbIUZF lxؠ<AkBn᠓xW^ nGW))]vO`?B^tG!, iUs "ު;$:Mf)D-C6 ->5*$ع6gf+7l3l!ș0QMi~64OMؽ9]cg}ݵ]'V ~D #*==?}"ܖ)c\@F+?ycŒAU*H(HmPQU%FeLϽ>V+!j "8>A U2 }<`S KWЉvT"ڛzYTbs>o,DќNG1DK7WPT)91$##A"HAC:c15 '`J2s[Z$G&n5(PCy-i@3D _$ BwWtj LgEQU1ӳv|&Db8GHB^F''F3]ugO$7xuK\IY;;HT XmZx"aKh4At/yYz' | ˃m{JRYI֯Fka6KT+Vp;`bX tP:$IP%\@M` C-VCⲧ ͻ/RjXKY б>% b=p9yt(p(ń6ڊ|WKGޒ>y=d:MqnP7}L+^'YY<.н]Q(]~ÜbA"޲ĔǼkX*㐩ځL^I+Q%ZY<"' ^fas[y18+>aIVd.%A"ĞHz eh:f՝088xT ӴX:R0pi|YA"{~PK#z_O9w^ ^chʓfZ2;Ēvw1dY4\=!U^ 2/&BQ\NN={3x8@쇙bX&J ~ҺWC[\5d_h}BtzR,D B 4+ TtJaDh! N)h&惧X\JHI %ygj:{qڰp ~l=ƒҗA};noUJT{gI}U1l+]xEfؕ)ɗjn Z@;tM-Q dȿ|18&}ɠLtq^>=L&joPp#* !yGVjBi4Qv@$ ~+S I,4/ٴia&qdsZVG22g]?c^̳@ k\iK%fXdLjT gi0ܽXL1$v cK|L;=M"]$ʯ+< U+`CW>T"_;tɚDJknAKu RZӱ#mpU=,.W,R]֫5zG- g&d9~47&CH%s9]}Kyv1gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.data.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``( XX0$$8o88zEoh;h;T;;^BBBhZZcZZnjjwzz$}== ==/mm wwX2 "" "  " """ "b8,"dP 1PK! ?@@2.2.0/x86_64-linux/syslog.sonuȯELF>@(9@8 @0)0) -- -  -- -  888$$))) Std))) Ptd%%%QtdRtd-- - xxGNUA`4o\_Z?bǾn"g(@ @(*BE|.*qXfU =  >}- tOs,[c, F"I $1 1  $1 __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizerb_extend_objectrb_f_sprintf__syslog_chkrb_eRuntimeErrorrb_raiserb_eArgErrorrb_check_typerb_sprintfcloselogruby_xfreerb_fix2intrb_obj_classrb_eTypeErrorrb_str_new_cstrrb_num2intsetlogmaskrb_scan_argsrb_string_valuerb_check_safe_objruby_strdupopenlogrb_block_given_prb_yieldrb_ensurerb_gv_get__stack_chk_failInit_syslogrb_define_modulerb_define_module_underrb_define_module_functionrb_define_singleton_methodrb_define_constrb_define_methodrb_include_modulerb_funcallrb_intern2libruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.4GLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ii ui - 0- - - / / / / / / "/ #/ $0  0 (0 00 80 @0 H0  P0  X0  `0  h0  p0 x0 0 0 0 0 0 0 0 0 0 0 0 0 0 0  0 !0 $1 %1 &1 'HHy! HtH5! %! hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhh% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D%  D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% DH= H H9tH. Ht H=q H5j H)HHH?HHtH  HtfD=- u+UH= Ht H= )d ]w= HHЃff.HSHHH5 )H[@ t Hcv HD t HcR HDf t Hc. HDS~UE t3HHHH tHHH 1[H H5x H81VH H5H H81>ff.SHHiH[@SHHIH[@SHH)H[@SHH H[@SHHH[@SHHH[@SHHH[@SHH1H[SH t4D  D H1 { H H=[HH= 1[ff.HR tNH=J H5     HH H5 H81HATUS~,_H>Lf@t6HLމ_H[]A\HP H5 H81(H5B HH H81ff.fV u @H=I lff.HHt KHHcHDDHHt HHBHHDf[f St@HH@u0lj=` H[fDlj=C H[H H5 H81fUSH(dH%(HD$1  H1LL$HLD$HH H<$<HH<$[H<$H HH|$H H H|$Huvh 5a H= 51i lj4 wBu^HL$dH3 %(HH([]Ha@tJE‰ @tB- QfH= HHHDk[fH=H$FH/ H5cH81ff.ATIUHSHHL[]A\SH=)H5$HHV H=J H5H4 H=0 H5H H= H5H H= H5H H= H^H5H H= HH5H= HH5|H=~ 1H=H5fH=b 1HH5RH=F 1HUH5<H=* 1HYH5(mH= HH5NH= 1HNH52H= 1H"H5H= HH5H= 1HH5H=| 1H[H5H=P H57H=8 H5}H=  H5nH= H5aH= !H5TH= AH5GH= AH5:H= H5+H= H5 wH=p 1H5_H=X H5GH=@ H5/H=( aH5H= !H5H= qH5H= QH5H= H5H= H5H= H5H= H5oH=h !H5rWH=P 1H5e?H=8 AH5X'H=  QH5KH= aH5>H= qH51H= H5$H= HH5H= H5H= HMH5H=b H5YH=j HH5H=+ H5"H=3 HH5sH= H5H= HHH5osyslog not openedtype mismatch: %li givensyslog already open03$0SyslogConstantsOptionFacilityLevelMacrosreopenopen!opened?identoptionsfacilityclosemaskmask=inspectinstanceLOG_PIDLOG_CONSLOG_ODELAYLOG_NDELAYLOG_NOWAITLOG_PERRORLOG_AUTHLOG_AUTHPRIVLOG_CRONLOG_DAEMONLOG_FTPLOG_KERNLOG_LPRLOG_MAILLOG_NEWSLOG_SYSLOGLOG_USERLOG_UUCPLOG_LOCAL0LOG_LOCAL1LOG_LOCAL2LOG_LOCAL3LOG_LOCAL4LOG_LOCAL5LOG_LOCAL6LOG_LOCAL7LOG_EMERGemergLOG_ALERTalertLOG_CRITcritLOG_ERRerrLOG_WARNINGwarningLOG_NOTICEnoticeLOG_INFOinfoLOG_DEBUGdebugLOG_MASKLOG_UPTOincludedinclude<#%li : opened=true, ident="%s", options=%d, facility=%d, mask=%d>wrong number of arguments (%d for 2+)must open syslog before setting log mask;p(@@`Tphp0Lh0Pp`$8PTpzRx $hFJ w?:*3$"DP\pEV   (rA| E EVEV0EVLEVhEVEVEVESbE L MxHW A (`sFAA m ABA @$T9HX P p7HY O gKf G V A (dEAD@ AAA ()FDF OCB E7 L GNU0- Tcs~ H !- - o`  0 H @  o oo o-  0@P`p 0@P`pGA$3a1H! GA$3p1067@!GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFY@UGA+GLIBCXX_ASSERTIONSsyslog.so-2.2.10-35.el8.x86_64.debuguD7zXZִF!t/']?Eh=ڊ2N ̔''aLzu1y7=A*vak. }0,Iπo ,P'\kp+o&hNY!XpcV< plWG Ih_/wSY[a wEe _A»'PT&ҏ;$R]t֥B`p6c%$"Kw lLb˾y9%z)}vD :yo:Q4eGl О~~Ka\a5Pa(-Y $vޛYVlóV#`2#61Nv]*p9wnJA0X }~w 1Od~13]p %"9A9di4.Q_؞'X[#ԝ&UaLl[Q֐rmI i0|kHE BmU:ᑝo /+UI'r@ Tg3(#V,F2O%>eGNRLsP|hYD}nق-WOh4{I)w]ҜcAէQFOWw Ւw]ffYgcp?`.߆Ix\fljf}w:&nӲp=dϨ]?;B[_߈G1`rr&]ݞ |~*՞aol{D+ax*{] ǣ@G6~*0cO.-j%{A6׺H$PUCwG>vIwySK"7E!,^T`j5s=|g`#TOpBH.Iv @@8 @     888$$ Std Ptd   $$QtdRtd XXGNUXD _"I@ BE| qX ` , F"( 0 U  ( __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeInit_fiberruby_Init_Fiber_as_Coroutinelibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ui            HH) HtH52 %3 hh% D% DH= H H9tH Ht H= H5 H)HHH?HHtHu HtfD= u+UH=R Ht H= Yde ]wHHGNU;$@hzRx $h0FJ w?:*3$"Dp \8  }    o`   0 oooo GA$3a1 GA$3p1067GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realignfiber.so-2.2.10-35.el8.x86_64.debugM=7zXZִF!t/ ]?Eh=ڊ2N.̈́=&~i}o0%{)XH!řf[,Hο%j(EswNmpz{ʷضIFfBH>\Vk`F'eӉEno[gä >}LK uƬ<7nl,Y0S%] -]\_f>E EЕa^!ntwf I4ܙlrgT Bj0#LQyiʊ^Ih9ݹc$H}|E_S ӗ&:"CvgrcGppk2d KR,lt~ jt ]]$B:X|[ 7NE+^1Ė3u^Z x&Φ N'>kr#K2ʱ/xR@gchePc[hG6])!Ul\'DDlOacd Z*{*%:)x<$L UˉyNKE6e,F=AnXsgm 1,takdM!L}b L mjz*)EFd|Ts*xXڪDR7 LО \vjpgYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.note.gnu.property.eh_frame_hdr.eh_frame.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 08oEo T^B0hc0n w  }    $HHp       (( (0`( (H$l#PK!@@8 @     888$$ Std Ptd $$QtdRtd XXGNUQoӋ8|0Z  BE|qXϫ  `, F"q0 8 0 U @__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeInit_fcntlrb_define_modulerb_define_constlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ui  0          ( HH HtH5 % hhh% D% D% DH= H H9tHF Ht H=y H5r H)HHH?HHtH HtfD=5 u+UH= Ht H= Id ]wSH=H5HHHߺH5Hߺ H5HߺH5HߺH5Hߺ H5Hߺ H5HߺH5|HߺH5uhHߺH5lTHߺH5`@HߺH5T,HߺH5HHߺH5<HߺH5/HߺH5$HߺH5HߺH5 HߺH5HߺH5HߺH5xHߺH5dH[H5OHHFcntlF_DUPFDF_GETFDF_GETLKF_SETFDF_GETFLF_SETFLF_SETLKF_SETLKWFD_CLOEXECF_RDLCKF_UNLCKF_WRLCKO_CREATO_EXCLO_NOCTTYO_TRUNCO_APPENDO_NONBLOCKO_NDELAYO_RDONLYO_RDWRO_WRONLYO_ACCMODE; <TdD|zRx $@FJ w?:*3$"D0\EGNU0   $   o`   H oooo 0@GA$3a11 GA$3p1067@! GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realignfcntl.so-2.2.10-35.el8.x86_64.debug^7zXZִF!t/]?Eh=ڊ2N{n )I Q{H[5-sGmg֞ `bvRFjKI(*&1*L\nD{A/\_CcLk!]5)Ѳt>ϕm/b,hcΧ/ w-z9|,*?uP8m6B#hAGD04炦q߻z &Mx۞t(rp|!N5z T*f|PPVk͌nweΰsree9)@@8 @** 88%8%3< GG%G%@@888$$*** Std*** PtdlllddQtdRtd88%8%ppGNU͗:sz^W/UnF N B" @D@ (Q 4I$ BbH $ @X a @@ @ !@D@@ H!$` QJ$)@N)"@X0!B @@F₋@ H@ bRHB@P @NOPSUVWY[]_`bdefgijlnopstvwxy{|  "#$%&'+ wP') 0t:li-2kǙpE{1bolS6x)1GX{+pU8\x%!!0JSq9ѭdO_/:'9 [- Iq#I5A A|7)4y]|{+E'm3͍hVN!, ,Y.\*y\X-Կ[6#BEq$BQ!IYܰ)*%P\8ѩ+nD[H) t- I)04pߝ)4~-)+b^I-(7evH|wvDqXU` u$. z^H|T sY`iƵj,KEީoeRO\ժ }Nsc- byl=v|0z ИmXf9Q;e-&uX_SJfEӕ2=v$.ѫ !oA,<3i'7:5#B 5<p5Cq54& Q<c7$3, /z"A!n)XxB);B\Z60/?G?,>*r=p;8^:'x82\ 62DA 8"+** /DX43_?8(T.2:3 &! C-8A.227:;>h:/)N%!%g46z'@7+(Z(w?@179!#393ED9j<6$'V 3#J)C+ P3C]M;&<1:zD4}5 @F"6(&/6Y Eq37 %:2^)s&J#7 #8A11@'ID:;2*<E,8IC(@4s:?4Py1P ,.3;);;>$5<?9- 6$21 #t ;?@8-At=+ 7*m  +r2CK ^,4T"%>h :4q$K0&@&!5!D15Y*z+At(I@Y2d  2f [E(d+2:A E!q"0>h ;C;<]@YC<#-+)* < a9s($ 24=%Kq!/<$;C: 6q'u<<;D9$)5:{6 =A#"+J*)1#5 (#l0!@!:<'1@y [%SB/ a0. L2C<' $P!=b'@\3 /Dq><=: ;c</0m.5' 4 E*C @+tB~#fD3u4V0 %J.-P -+y)/!2B?1'/g8W$T  -0*-#9  1"i-~>C/$6</'5)!:-$2C&$I,.8.a!558=6",7SX2S&'|*&"C&:AW4%8# N1 2u/S- g/0!M5q@8=04,u"'?+@4 !3(-^= 2)@;h1[).",A D(%Q)<)D9;t=m(!;N-;I}9kP3e.*Bc2?8}4 @.3-6=,>5d/!BnB&f; >B.E 8 q%,%(t>{I< 3 s X *UBRD=  .GBi+.E6#u<8)4j;0= ?XA!f(./u};9-i"j) =2 !64<D9+6"S/45HE? N7x: 7%]>?x!D>2+Bc DD11?AZ5h$ $ 1t27};.D T$ s.6h@"X<m/n#e$w,;0= 5$b;, #(A}@: AU;8 <W;n 5^#c'K40)\;@N'5<*nC?8D  p /I `n;S+   u%t%!s%g,8t%y*t% | `   p2s%% b4 pO& PL' p6 Х< ); r%Z @C%Hs%J=0u%\ p|.Pt%  (t%xr% W>(u% оPr%40 0T)t%#3t%h6 `g. 2r%# ' 0r%'3o%% Hs%$s%* t% (r%M8 P`t%;hr%+0r%  0m3t% @R E%r%  r%N f&s%4t%s  s%r%L$  п1 %"@s%`s%[Hr% Pb s%2Xr%$t% r 8s%0Xt%& 0N1t% r%^ r%=4u%K+t%  R(s% 0 hs%Y `Y!r%(s%D0`t%/Ht% +U`>%Hr%>u%& }l  [s%{$s%  && \ n^7 pi* @=@u%Cr%E FQ)s%` r% P1xt%e pUE@l% l; at%9 ` # U4t% XU( `l* @r!+ igr% 8r%) m' *t%)  Ў'xht%+@t% u% 0Sj$:t%}- iB6 $ ss%Xs%" P r%AE Gr%{ h С*t% u%Z8 U8t%^pr%,0t%'?u%L2 j9I  --(t% (s% r%k2t%r% R/CHu%9 P5@ 9%H' : @H' Nl 1`r% bpV R # %O r% `Rs%p  paR" ,q%a  f  0QE@l%  t%' ~s%;3o%EPu%ps% s% s% 0R^0pt%" it%1 a o@, Ps%* r%'s%+ [0s%A$s%q%?8u%K @s%u%{@r%,E G r%}q%xs%E%s%i 7 r% 0I [2t%P @Gf__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeossl_evp_pkey_typerb_check_typeddataEVP_PKEY_typerb_hash_newossl_bn_newrb_str_new_staticrb_hash_asetrb_eRuntimeErrorrb_raiseossl_raiseGetBNPtrBN_copyBN_neweBNErrorBN_clear_freerb_scan_argsrb_string_valueRSA_sizerb_str_newRSA_private_decryptrb_str_set_lenrb_fix2intrb_iv_geteRSAErrorrb_num2intrb_out_of_int__stack_chk_faili2d_RSAPrivateKeyi2d_RSA_PUBKEY__assert_failGetCipherPtrBIO_s_memBIO_newossl_pem_passwd_cbPEM_write_bio_RSAPrivateKeyBIO_freePEM_write_bio_RSA_PUBKEYossl_membio2streOSSLErrorRSA_printRSA_generate_key_exEVP_PKEY_newEVP_PKEY_assignrb_data_typed_object_allocrb_iv_setEVP_PKEY_freeRSAPublicKey_duprb_cFalseClassRSA_freerb_cNilClassrb_cFixnumrb_cFloatrb_cTrueClassrb_cSymbolRSA_newBN_set_bitBN_freerb_block_given_possl_generate_cb_2ossl_generate_cb_stoprb_thread_call_without_gvlrb_jump_tagossl_to_der_if_possibleossl_obj2bioPEM_read_bio_RSAPrivateKeyrb_string_value_ptrrb_num2ulongBIO_ctrlERR_clear_errorPEM_read_bio_RSA_PUBKEYd2i_RSAPrivateKey_biod2i_RSA_PUBKEY_bioPEM_read_bio_RSAPublicKeyd2i_RSAPublicKey_bioRSA_public_encryptRSA_public_decryptRSA_private_encryptossl_rsa_newcRSArb_eTypeErrorInit_ossl_rsaePKeyErrormPKeyrb_define_class_undercPKeyrb_define_singleton_methodrb_define_methodrb_define_aliasrb_define_constEVP_CIPHER_CTX_iv_lengthEVP_CipherInit_exeCipherErrorEVP_CIPHER_CTX_nidEVP_CIPHER_CTX_ctrlEVP_CIPHER_CTX_key_lengthEVP_CIPHER_CTX_block_sizeEVP_CipherFinal_exEVP_CipherUpdaterb_str_resizerb_eRangeErrorrb_eArgErrorGetDigestPtrEVP_CIPHER_CTX_cipherEVP_BytesToKeyOPENSSL_cleanseEVP_md5rb_ary_newOBJ_NAME_do_all_sortedrb_str_new_cstrrb_ary_pushcCipherrb_obj_is_kind_ofEVP_CIPHER_CTX_copyruby_xcallocrb_error_frozen_objectrb_obj_classEVP_CIPHER_CTX_cleanupruby_xfreeEVP_CIPHER_block_sizeEVP_CIPHER_iv_lengthEVP_CIPHER_key_lengthEVP_CIPHER_nidOBJ_nid2snrb_class_pathrb_warn__memcpy_chkEVP_CIPHER_CTX_initEVP_get_cipherbynameEVP_CIPHER_CTX_set_key_lengthEVP_CIPHER_CTX_set_paddingruby_xmalloc2ossl_cipher_newInit_ossl_cipherrb_cObjectmOSSLrb_define_alloc_funcrb_define_module_functionSSL_SESSION_freeossl_ssl_session_typeSSL_SESSION_printPEM_write_bio_SSL_SESSIONi2d_SSL_SESSIONcSSLSocketrb_obj_is_instance_ofPEM_read_bio_SSL_SESSIONossl_ssl_typeSSL_get1_sessionSSL_SESSION_newd2i_SSL_SESSIONASN1_d2i_bioSSL_SESSION_get_idSSL_SESSION_get_timeoutrb_int2bigSSL_SESSION_set_timeoutrb_num2longSSL_SESSION_get_timerb_cTimerb_funcallrb_intern2SSL_SESSION_set_timeSSL_SESSION_cmpmemcmpcSSLSessionInit_ossl_ssl_sessionmSSLOCSP_CERTID_freeGetX509CertPtrOCSP_cert_to_ideOCSPErrorOCSP_BASICRESP_freeOCSP_resp_countOCSP_resp_get0OCSP_single_get0_statusOCSP_CERTID_dupcOCSPCertIdasn1time_to_timeOCSP_SINGLERESP_get_ext_countOCSP_SINGLERESP_get_extossl_x509ext_newOCSP_basic_add1_nonceOCSP_REQUEST_freei2d_OCSP_RESPONSEOCSP_RESPONSE_freed2i_OCSP_RESPONSEi2d_OCSP_REQUESTOCSP_request_onereq_countOCSP_request_onereq_get0OCSP_onereq_get0_idOCSP_request_add1_nonced2i_OCSP_REQUESTasn1integer_to_numOCSP_id_issuer_cmpOCSP_id_cmpOCSP_CERTID_newcOCSPReqOCSP_copy_nonceOCSP_BASICRESP_newOCSP_response_get1_basiccOCSPBasicResOCSP_response_statusOCSP_response_status_strOCSP_RESPONSE_newOCSP_request_add0_idOCSP_check_nonceOCSP_REQUEST_newOCSP_response_createGetX509StorePtrossl_x509_ary2skOCSP_request_verifyX509_freesk_pop_freeERR_peek_errorERR_error_stringOCSP_basic_verifyGetPrivPKeyPtrEVP_sha1OCSP_basic_signsk_new_nullOCSP_request_signrb_Integerrb_protectASN1_TIME_freerb_check_typecX509Extrb_gc_writebarrier_unprotectX509_gmtime_adjOCSP_basic_add1_statusX509_EXTENSION_freeDupX509ExtPtrOCSP_SINGLERESP_add_extInit_ossl_ocsprb_define_module_undermOCSPcOCSPResX509_ATTRIBUTE_freei2d_X509_ATTRIBUTEeX509AttrErrori2d_ASN1_TYPEi2d_ASN1_SETmASN1ossl_asn1_get_asn1typeASN1_TYPE_getASN1_TYPE_freesk_freeeASN1ErrorX509_ATTRIBUTE_get0_objectOBJ_obj2nidi2a_ASN1_OBJECTd2i_X509_ATTRIBUTEX509_ATTRIBUTE_newOBJ_txt2objX509_ATTRIBUTE_set1_objectossl_x509attr_newX509_ATTRIBUTE_dupcX509AttrDupX509AttrPtrInit_ossl_x509attrmX509EC_GROUP_clear_freeEC_POINT_clear_freecEC_GROUPEC_GROUP_get_point_conversion_formcBNrb_obj_allocossl_bn_ctxEC_POINT_point2bneEC_POINTeEC_GROUPEC_POINT_set_to_infinitycEC_POINTEC_POINT_invertEC_POINT_make_affineEC_POINT_is_on_curveEC_POINT_is_at_infinityEC_POINT_dupEC_POINT_bn2pointEC_POINT_newEC_POINT_mulCRYPTO_mallocrb_ary_entryrb_cArrayrb_ary_unshiftEC_POINTs_mulCRYPTO_freeECPKParameters_printPEM_write_bio_ECPKParametersi2d_ECPKParametersASN1_i2d_bioeECErrorEC_GROUP_set_seedEC_GROUP_set_generatorEC_GROUP_cmpEC_POINT_cmprb_sym2idEC_GROUP_new_curve_GFpEC_GROUP_dupPEM_read_bio_ECPKParametersEC_GFp_nist_methodEC_GROUP_newd2i_ECPKParametersrb_string_value_cstrOBJ_sn2nidERR_get_errorEC_GROUP_new_by_curve_nameEC_GROUP_set_asn1_flagEC_GROUP_set_point_conversion_formEC_GFp_simple_methodEC_GFp_mont_methodEC_KEY_printEC_KEY_get0_public_keyEC_KEY_check_keyEC_KEY_get0_private_keyi2d_ECPrivateKey_bioPEM_write_bio_ECPrivateKeyi2d_EC_PUBKEY_bioPEM_write_bio_EC_PUBKEYECDSA_verifyECDSA_sizeECDSA_signECDH_compute_keyEC_KEY_set_public_keyEC_KEY_set_private_keyEC_KEY_set_groupEC_KEY_get0_groupcECEC_KEY_dupPEM_read_bio_ECPrivateKeyEC_KEY_newPEM_read_bio_EC_PUBKEYd2i_ECPrivateKey_biod2i_EC_PUBKEY_bioEC_KEY_new_by_curve_nameEC_KEY_set_asn1_flagEC_KEY_set_conv_formEC_KEY_freeEC_get_builtin_curvesrb_ary_new_caparb_undef_methodEC_GROUP_get_degreeEC_GROUP_get_seed_lenEC_GROUP_get0_seedrb_id2symEC_GROUP_get_asn1_flagEC_GROUP_get_curve_nameEC_GROUP_get_cofactorEC_GROUP_get_orderEC_GROUP_get0_generatorEC_KEY_generate_keyossl_ec_newInit_ossl_ecrb_attrEVP_MD_CTX_destroyEVP_MD_CTX_mdEVP_MD_sizeEVP_DigestFinal_exEVP_DigestInit_exeDigestErrorEVP_MD_CTX_createossl_digest_updateEVP_DigestUpdateEVP_MD_typeEVP_MD_block_sizecDigestEVP_MD_CTX_copyEVP_get_digestbynameASN1_OBJECT_freeossl_digest_newInit_ossl_digestrb_requirerb_path2classrb_define_private_methodInit_ossl_x509Init_ossl_x509certInit_ossl_x509crlInit_ossl_x509extInit_ossl_x509nameInit_ossl_x509reqInit_ossl_x509revokedInit_ossl_x509storeX509_get_default_cert_areaX509_get_default_cert_dirX509_get_default_cert_fileX509_get_default_cert_dir_envX509_get_default_cert_file_envX509_get_default_private_dirX509_STORE_freeX509_STORE_CTX_freeX509_LOOKUP_fileX509_STORE_add_lookupX509_LOOKUP_ctrlrb_check_safe_objeX509StoreErrorX509_LOOKUP_hash_dirX509_STORE_CTX_set_timecX509StoreDupX509CertPtrX509_STORE_CTX_initX509_STORE_CTX_set_flagsossl_x509crl_newX509_STORE_CTX_get_current_certossl_x509_newX509_STORE_CTX_get_error_depthX509_STORE_CTX_get_errorX509_verify_cert_error_stringX509_STORE_CTX_set_errorX509_STORE_CTX_get_chainsk_numsk_valuedOSSLstderrfwrite__fprintf_chkcX509StoreContextrb_block_procossl_store_ctx_ex_verify_cb_idxX509_STORE_CTX_set_ex_dataX509_verify_certX509_STORE_CTX_newGetX509CRLPtrX509_STORE_add_crlX509_STORE_add_certX509_STORE_set_default_pathsX509_STORE_set_flagsossl_store_ex_verify_cb_idxCRYPTO_set_ex_dataossl_verify_cbX509_STORE_newX509_STORE_CTX_set_purposeX509_STORE_CTX_set_trustX509_STORE_set_purposeX509_STORE_set_trustossl_x509store_newDupX509StorePtrCRYPTO_add_lockossl_x509stctx_newossl_x509stctx_clear_ptrX509_REQ_freeX509_REQ_add1_attreX509ReqErrorX509_REQ_printi2d_X509_REQPEM_write_bio_X509_REQcX509ReqX509_REQ_dupPEM_read_bio_X509_REQd2i_X509_REQ_bioX509_REQ_newX509_REQ_get_attr_countX509_REQ_get_attrGetPKeyPtrX509_REQ_verifyX509_REQ_signX509_REQ_set_pubkeyX509_REQ_get_pubkeyossl_pkey_newGetX509NamePtrX509_REQ_set_subject_nameossl_x509name_newX509_REQ_set_versionASN1_INTEGER_getossl_x509req_newGetX509ReqPtrDupX509ReqPtrrb_attr_getOBJ_txt2nidOBJ_nid2lncASN1EndOfContentrb_funcallv_publiccASN1SetcASN1SequencecASN1GeneralizedTimecASN1UTCTimecASN1ObjectIdcASN1NullcASN1BMPStringcASN1UniversalStringcASN1GeneralStringcASN1ISO64StringcASN1GraphicStringcASN1IA5StringcASN1VideotexStringcASN1T61StringcASN1PrintableStringcASN1NumericStringcASN1UTF8StringcASN1OctetStringcASN1BitStringcASN1EnumeratedcASN1IntegercASN1Booleanrb_ary_eachrb_block_callrb_str_appendsscanfrb_funcallvrb_warningASN1_INTEGER_to_BNOBJ_obj2txtOBJ_createASN1_object_sizeASN1_put_objectmemcpyrb_ivar_setrb_class_superclassrb_hash_lookupASN1_get_objectcASN1DatacASN1Constructiverb_yieldd2i_ASN1_TIMEd2i_ASN1_ENUMERATEDASN1_ENUMERATED_freed2i_ASN1_OBJECTd2i_ASN1_NULLASN1_NULL_freed2i_ASN1_BIT_STRINGASN1_BIT_STRING_freed2i_ASN1_INTEGERASN1_INTEGER_freed2i_ASN1_BOOLEANrb_str_new_frozenASN1_put_eoccASN1Primitivetime_to_time_tasn1str_to_strnum_to_asn1integerBN_to_ASN1_INTEGERASN1_GENERALIZEDTIME_setASN1_TYPE_setASN1_BIT_STRING_newASN1_BIT_STRING_setASN1_STRING_newASN1_STRING_setASN1_STRING_freeASN1_NULL_newossl_to_derASN1_UTCTIME_setossl_buf2strInit_ossl_asn1rb_ary_storerb_mEnumerablerb_include_modulerb_global_variableHMAC_CTX_cleanupHMAC_CTX_copyHMAC_FinaleHMACErrorstring2hexHMAC_CTX_initHMAC_UpdateHMAC_InitcHMACInit_ossl_hmacX509_CRL_freeX509_CRL_add_exteX509CRLErrorX509_CRL_printPEM_write_bio_X509_CRLi2d_X509_CRL_biocX509RevX509_REVOKED_freeDupX509RevokedPtrX509_CRL_add0_revokedX509_CRL_sortcX509CRLX509_CRL_dupPEM_read_bio_X509_CRLd2i_X509_CRL_bioX509_CRL_newX509_CRL_get_ext_countX509_CRL_get_extX509_CRL_verifyX509_CRL_signossl_x509revoked_newX509_time_adjX509_CRL_set_issuer_nameX509_CRL_set_versionDupX509CRLPtrEVP_DigestInitEVP_VerifyFinalEVP_MD_CTX_cleanupid_private_qEVP_PKEY_sizeEVP_SignFinalrb_eNotImpErrorossl_generate_cbossl_dh_newossl_dsa_newd2i_PrivateKey_bioPEM_read_bio_PrivateKeyd2i_PUBKEY_bioPEM_read_bio_PUBKEYossl_pkey_new_from_filefopenfilenorb_fd_fix_cloexecPEM_read_PrivateKeyfclose__errno_locationstrerrorDupPKeyPtrDupPrivPKeyPtrInit_ossl_pkeyInit_ossl_dsaInit_ossl_dhNETSCAPE_SPKI_freeeSPKIErrorNETSCAPE_SPKI_printi2d_NETSCAPE_SPKIeX509CertErrorNETSCAPE_SPKI_b64_decoded2i_NETSCAPE_SPKINETSCAPE_SPKI_verifyNETSCAPE_SPKI_signNETSCAPE_SPKI_set_pubkeyNETSCAPE_SPKI_get_pubkeyNETSCAPE_SPKI_b64_encodestrlenNETSCAPE_SPKI_newInit_ossl_ns_spkimNetscapecSPKIX509_NAME_freei2d_X509_NAMEeX509NameErrorX509_NAME_entry_countrb_ary_new_from_argsX509_NAME_get_entryi2t_ASN1_OBJECTOBJ_ln2nidX509_NAME_print_exX509_NAME_onelineX509_NAME_add_entry_by_txtcX509Namerb_const_getrb_check_array_typed2i_X509_NAMEX509_NAME_newX509_NAME_cmpX509_NAME_hashrb_uint2bigX509_NAME_hash_oldX509_NAME_duprb_mComparablerb_hash_set_ifnoneGetConfigPtrcConfigNCONF_newNCONF_load_bioNCONF_freeeConfigErrorInit_ossl_configCONF_get1_default_config_filei2d_PKCS12ePKCS12ErrorPKCS12_freed2i_PKCS12_bioPKCS12_parseossl_x509_sk2aryPKCS12_newPKCS12_createcPKCS12Init_ossl_pkcs12PKCS7_RECIP_INFO_freePKCS7_SIGNER_INFO_freei2d_PKCS7ePKCS7ErrorPKCS7_freeossl_protect_x509_ary2skPKCS7_verifyERR_reason_error_stringPKCS7_dataInitBIO_writeBIO_readPKCS7_dataFinalPKCS7_content_newd2i_PKCS7_RECIP_INFOi2d_PKCS7_RECIP_INFOASN1_dupcPKCS7RecipientPKCS7_RECIP_INFO_newPKCS7_get_signer_infod2i_PKCS7_SIGNER_INFOi2d_PKCS7_SIGNER_INFOcPKCS7SignerPKCS7_SIGNER_INFO_newPEM_read_bio_PKCS7d2i_PKCS7_biocPKCS7PKCS7_dupPKCS7_RECIP_INFO_setPKCS7_get_signed_attributePKCS7_SIGNER_INFO_setPEM_write_bio_PKCS7ossl_x509crl_sk2arysk_popPKCS7_add_crlPKCS7_add_certificatePKCS7_add_recipient_infoPKCS7_add_signerOBJ_nid2objPKCS7_add_signed_attributePKCS7_set_cipherPKCS7_ctrlstrcmprb_sym2strPKCS7_set_typePKCS7_newSMIME_read_PKCS7PKCS7_decryptPKCS7_encryptEVP_rc2_40_cbcPKCS7_signSMIME_write_PKCS7Init_ossl_pkcs7eDSAErrori2d_DSAPrivateKeyi2d_DSA_PUBKEYPEM_write_bio_DSAPrivateKeyPEM_write_bio_DSA_PUBKEYDSA_printDSA_generate_parameters_exd2i_DSAPublicKeyi2d_DSAPublicKeyDSA_freeDSA_newRAND_bytesDSA_generate_keyPEM_read_bio_DSAPrivateKeyPEM_read_bio_DSA_PUBKEYd2i_DSAPrivateKey_biod2i_DSA_PUBKEY_bioPEM_ASN1_read_biocDSAPKCS5_PBKDF2_HMAC_SHA1ePKCS5PKCS5_PBKDF2_HMACInit_ossl_pkcs5mPKCS5i2d_X509_EXTENSIONeX509ExtErrorX509_EXTENSION_get_objectASN1_OCTET_STRING_newX509_EXTENSION_set_dataASN1_OCTET_STRING_freed2i_X509_EXTENSIONX509V3_EXT_nconf_nidX509V3_EXT_printASN1_STRING_printX509_EXTENSION_get_criticalX509_EXTENSION_set_criticalX509_EXTENSION_set_objectX509V3_set_nconfX509V3_set_ctxX509_EXTENSION_newX509_EXTENSION_dupGetX509ExtPtrcX509ExtFactoryRAND_statusrb_num2dblRAND_addRAND_seedeRandomErrorRAND_egdRAND_pseudo_bytesRAND_write_fileRAND_load_fileRAND_egd_bytesInit_ossl_randmRandomDH_sizeeDHErrori2d_DHparamsPEM_write_bio_DHparamsDHparams_printDH_generate_parameters_exDHparams_dupDH_freeDH_generate_keyDH_checkDH_newPEM_read_bio_DHparamsd2i_DHparamsBN_bin2bncDHOSSL_DEFAULT_DH_512OSSL_DEFAULT_DH_1024ENGINE_freeENGINE_get_cmd_defnsENGINE_ctrl_cmd_stringeEngineErrorENGINE_load_public_keyENGINE_load_private_keyENGINE_get_firstENGINE_up_refENGINE_get_nextENGINE_cleanupENGINE_load_opensslENGINE_load_builtin_enginesENGINE_by_idENGINE_initENGINE_ctrlENGINE_get_nameENGINE_get_idrb_sprintfENGINE_set_defaultENGINE_get_digestENGINE_get_cipherENGINE_finishENGINE_newInit_ossl_enginecEngineX509_add_exti2d_X509cX509CertX509_dupPEM_read_bio_X509d2i_X509_bioX509_newX509_get_ext_countX509_get_extX509_check_private_keyX509_verifyX509_signX509_set_pubkeyX509_get_pubkeyX509_set_issuer_nameX509_get_issuer_nameX509_set_subject_nameX509_get_subject_nameX509_get_serialNumberX509_set_versionX509_printPEM_write_bio_X509ossl_x509_new_from_filePEM_read_X509ossl_call_verify_cb_procossl_get_errorsERR_peek_last_errorrb_vsprintfrb_str_cat_cstrrb_exc_new_strrb_str_catrb_nativethread_lock_initializerb_nativethread_lock_destroyrb_nativethread_lock_lockrb_nativethread_lock_unlockrb_nativethread_selfCRYPTO_THREADID_set_pointerCRYPTO_mem_ctrlossl_x509_ary2sk0ossl_x509name_sk2aryPEM_def_callbackrb_set_errinfoX509_STORE_CTX_get_ex_dataCRYPTO_get_ex_dataossl_s_to_derrb_respond_torb_exc_raisesk_pushFIPS_modeFIPS_mode_setossl_exc_newInit_opensslSSL_library_initOPENSSL_add_all_algorithms_noconfERR_load_crypto_stringsSSL_load_error_stringsrb_define_moduleSSLeay_versionrb_eStandardErrorX509_STORE_CTX_get_ex_new_indexCRYPTO_get_ex_new_indexCRYPTO_num_locksCRYPTO_THREADID_set_callbackCRYPTO_set_locking_callbackCRYPTO_set_dynlock_create_callbackCRYPTO_set_dynlock_lock_callbackCRYPTO_set_dynlock_destroy_callbackInit_ossl_bnInit_ossl_sslrb_eNoMemErrorX509_REVOKED_add_exteX509RevErrorX509_REVOKED_newX509_REVOKED_get_ext_countX509_REVOKED_get_extd2i_X509_REVOKEDi2d_X509_REVOKEDrb_StringBN_dec2bnBN_hex2bnBN_mpi2bnrb_absint_sizerb_integer_packrb_free_tmp_bufferBN_set_negativerb_alloc_tmp_bufferBN_bn2hexrb_cstr_to_inumBN_num_bitsBN_cmpruby_xmallocBN_bn2binrb_memhashBN_is_bit_setBN_clear_bitBN_mask_bitsBN_lshiftBN_rshiftBN_pseudo_randBN_randBN_is_prime_fasttestBN_is_primeBN_bn2decBN_bn2mpirb_assoc_newBN_sqrBN_dupBN_mod_inverseBN_generate_primeBN_pseudo_rand_rangeBN_rand_rangeBN_ucmpBN_gcdBN_mod_expBN_expBN_mod_sqrBN_mod_mulBN_mod_subBN_mod_addBN_divBN_mulBN_subBN_addBN_CTX_newSSL_freeSSL_get0_next_proto_negotiatedSSL_get_client_CA_listSSL_get_verify_resultSSL_stateossl_ssl_ex_ptr_idxSSL_get_ex_dataeSSLErrorossl_ssl_ex_store_pSSL_CTX_get_ex_dataSSL_CTX_freeSSL_pendingSSL_state_stringrb_ruby_verbose_ptrSSL_state_string_longSSL_CIPHER_get_nameSSL_CIPHER_get_versionSSL_CIPHER_get_bitsSSL_get_current_cipherSSL_get_versionSSL_get_peer_cert_chainSSL_get_peer_certificateSSL_get_certificateSSL_shutdownSSL_clearSSL_CTX_flush_sessionsSSL_CTX_ctrlSSL_get_servernameID_callback_stateossl_ssl_ex_client_cert_cb_idxSSL_get_ex_data_X509_STORE_CTX_idxossl_ssl_ex_vcb_idxossl_ssl_ex_tmp_dh_callback_idxSSL_CTX_set_cipher_listSSL_CTX_set_ssl_versionrb_id2nameruby_snprintfSSL_ctrlSSL_newrb_io_taint_checkrb_io_check_closedrb_io_check_readablerb_io_check_writableSSL_set_fdSSL_set_ex_dataSSL_set_info_callbackSSL_set_sessionSSL_writeSSL_get_errorrb_io_wait_writablerb_io_wait_readablerb_sys_failrb_hash_arefrb_ivar_getSSL_acceptSSL_connectSSL_CTX_remove_sessionSSLv23_methodSSL_CTX_newrb_str_modifySSL_readrb_thread_wait_fdrb_eof_errorSSL_CTX_add_sessionSSL_CTX_set_tmp_dh_callbackSSL_CTX_set_ex_dataSSL_CTX_set_cert_storeSSL_CTX_use_certificateSSL_CTX_use_PrivateKeySSL_CTX_check_private_keySSL_CTX_add_client_CASSL_CTX_set_verifySSL_CTX_set_timeoutSSL_CTX_set_verify_depthrb_eachrb_iterateSSL_CTX_set_next_protos_advertised_cbrb_obj_freezeSSL_CTX_set_session_id_contextSSL_CTX_callback_ctrlSSL_CTX_load_verify_locationsSSL_CTX_sess_set_remove_cbSSL_CTX_sess_set_new_cbSSL_CTX_sess_set_get_cbSSL_CTX_set_next_proto_select_cbSSL_CTX_set_client_cert_cbcSSLContextrb_call_superSSL_set_SSL_CTXSSL_get_ex_new_indexrb_mWaitReadablerb_mWaitWritablerb_internTLSv1_methodTLSv1_server_methodTLSv1_client_methodTLSv1_2_methodTLSv1_2_server_methodTLSv1_2_client_methodTLSv1_1_methodTLSv1_1_server_methodTLSv1_1_client_methodSSLv2_methodSSLv2_server_methodSSLv2_client_methodSSLv3_methodSSLv3_server_methodSSLv3_client_methodSSLv23_server_methodSSLv23_client_methodBIO_new_mem_bufrb_cloexec_duprb_update_max_fdfdopenBIO_new_fpossl_membio2str0ossl_protect_obj2bioossl_protect_membio2strlibruby.so.2.2libssl.so.10libcrypto.so.10libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.3.4GLIBC_2.4GLIBC_2.14GLIBC_2.2.5OPENSSL_1.0.2OPENSSL_1.0.1_EC/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64   EPti Eii EEui EE ui EhE Лw hEuE"+j F3F t uE8%p8%08%8%8%#K8%8% 9%M09%9%Q9%9%#Q9% @:%:QP:%:%PQ:%;%R;%@`;%jXp;% ;%{X;%  <%[0<%@Q<%b<%`^<%c<%P^@=%cP=%@s=%Wl=%>%7m>%`>%mp>%>%n>%P ?%o0?%?%p?%p ?%8s?%0@@%QsP@%@@%ks@%pA%vA%V`A%vpA%TA%OyA%P B%ez0B%B%}B%B%B%0B%@C%PC%C%C%`D%aD%dHD%WD%x D%(D%0D%8D%@D%gHD%aPD%ɂXD%`D%hD%5pD%ExD%D%^D%ND%;D%D%eD%gD%gD%gD%gD%gE%gE%g E%g0E%g@E%gPE% h`E%hpE%"hE%/hE%>hE%MhE%VhE%ZhE%hhE%xhE%hF%hF%h F%h0F%h@F%hPF%h`F%hpF%hF%hF%"F%F%·F%<F%ۇF%G%.G% G%0G% @G%PG%$`G%pG%1G%>G%KG%RG%`D%M%D%M%D%pM%D%N%D% O% D%pJ%E%{N%{HE%K%hE%@L%E%%O%%E%XL%E%L%E%K%E%xJ%E%c L%cF%0N%F%O%(F% xO% 8F%K%HF%K%XF%HL%hF% O% F%N%F%"F%F%nF%F%F%G%VG%,(G%X8G%HG%XG%hG%xG%G%MG%G%G%`J%J%J%J% J%(J%0J%$8J%@J%'HJ%PJ%XJ%`J%hJ%J%YJ%J%oJ%eJ%J%dJ%oJ% J%zJ%J%J%J%J%J%J%OK%K%K%K%' K%(K%+0K%8K%@K%HK%&PK%$XK%s`K%(hK%|pK%xK%K%SK%NK%K%K%'K%(K%#K%K%K%K%YK%L%_L%L%L%V(L%0L%8L%UPL%`L%hL%)pL%qxL%L%L%L%L%L%L%L%\L%L%L%L%L%L%L%L%M%M%M%xM% M%(M%0M%8M%h@M%}HM%PM%XM%`M% hM%xM%M%M% M%M%mM%~M%M%/M%M%M%fM%5M%6M%M%>N%EN%FN%Q N%u(N%j8N%@N%lHN%PN%eXN%`N%QhN%pN%xN%N%N%N%N%N%N%N%N%N%yN%N%N%N%N%O%O%O%O% O%(O%0O%T8O%W@O%HO%PO% XO%a`O%hO%pO%O%O%kO%O%!O%!O%(O%O%O%IO%rO%O%P% P%(P%0P%]8P%@P%HP%PP%XP%`P% hP%pP%pxP% P% P% P% P%P%P%P%P%P%P%P%P%P%P%P%P%Q%Q%Q%Q% Q%(Q% 0Q%!8Q%"@Q%#HQ%%PQ%&XQ%'`Q%(hQ%pQ%)xQ%*Q%+Q%,Q%-Q%.Q%/Q%0Q%1Q%2Q%[Q%3Q%4Q%Q%5Q%6Q%7Q%8R%9R%:R%;R%< R%=(R%>0R%?8R%@@R%AHR%BPR%CXR%D`R%EhR%FpR%GxR%HR%IR%JR%KR%LR%MR%NR%OR%PR%QR%RR%SR%TR%UR%VR%WR%^S%ZS%[S%\S%] S%^(S%_0S%`8S%a@S%bHS%cPS%dXS%f`S%ghS%hpS%ixS%jS%kS%lS%mS%pS%qS%rS%sS%tS%uS%vS%wS%xS%yS%{S%|S%}T%~T%T%T% T%(T%0T%8T%@T%HT%PT%XT%`T%hT%pT%xT%T%T%T%T%T%T%T%T%T%T%T%T%T%T%T%T%U%U%U%U% U%(U%0U%8U%@U%HU%PU%XU%`U%hU%pU%xU%U%U%U%U%U%U%U%U%OU%U%U%U%U%U%U%U%V%V%V%V% V%(V%0V%8V%@V%HV%PV%iXV%`V%hV%pV%xV%V%V%V%V%V%V%V%V%V%V%V%V%V%V%V%bV%W%W%W%W% W%(W%0W%8W%@W%HW%PW%XW%`W%hW%pW%xW%W%W%W%W%W%tW%W%W%W%W%W%W%W%W%W%W%X%X%X%X% X%(X%0X%8X%@X%HX%PX%XX%`X%hX%pX% xX% X% X% X% X%X%X%X%X%X%X%X%X%X%X%X%X%Y%NY%Y%Y% Y%(Y%0Y%8Y%@Y% HY%!PY%"XY%#`Y%$hY%%pY%xY%&Y%)Y%*Y%+Y%-Y%.Y%/Y%0Y%1Y%2Y%3Y%4Y%5Y%6Y%7Y%8Y%Z%9Z%:Z%Z%; Z%<(Z%=0Z%>8Z%?@Z%@HZ%APZ%XZ%B`Z%ChZ%DpZ%ExZ%FZ%lZ%GZ%HZ%IZ%JZ%KZ%LZ%MZ%NZ%OZ%PZ%QZ%RZ%SZ%TZ%U[%V[%W[%X[%Y [%Z([%[0[%\8[%]@[%^H[%_P[%`X[%a`[%bh[%cp[%dx[%[%e[%f[%g[%h[%i[%j[%k[%l[%[%m[%n[%o[%p[%q[%r[%s\%t\%u\%v\%w \%x(\%y0\%z8\%@\%{H\%|P\%}X\%~`\%h\%p\%x\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%]%]%]%]% ]%(]%0]%8]%@]%PH]%P]%X]%`]%h]%p]%x]%]%]%]%]%]%]%]%]%]%]%]%]%]%]%]%]%^%^%^%^% ^%(^%0^%8^%@^%H^%P^%X^%`^%h^%p^%x^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%_%_%_%_% _%(_%0_%8_%@_%H_%P_%X_%`_%h_%p_%x_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%g_%_%`%`%`%`% `%(`%0`%8`%@`%H`%P`%X`%``%h`%p`%x`%`%`%`%`%`%`%`%`%`%`% `% `% `% `%`%`%a%a%a%a% a%(a%0a%8a%@a%Ha%Pa%Xa%`a%ha%pa%xa%a% a%!a%#a%$a%%a%&a%a%'a%(a%)a%*a%a%+a%,a%-a%b%.b%b%0b%1 b%2(b%30b%48b%5@b%7Hb%8Pb%9Xb%:`b%;hb%<pb%=xb%?b%@b%Ab%Bb%Cb%Db%Fb%Gb%Hb%Ib%Jb%Kb%Lb%Mb%Nb%Ob%Pc%Qc%Rc%Sc% c%T(c%U0c%W8c%X@c%YHc%ZPc%Xc%[`c%\hc%]pc%^xc%_c%ac%bc%c%cc%c%dc%ec%fc%gc%hc%ic%jc%kc%mc%nc%od%pd%qd%rd%s d%t(d%u0d%*8d%v@d%wHd%xPd%yXd%z`d%{hd%|pd%}xd%~d%d%d%d%d%nd%d%d%d%d%d%d%d%d%,d%d%e%e%e%e% e%(e%0e%8e%@e%He%Pe%Xe%`e%he%pe%xe%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%f%f%f%f% f%(f%0f%8f%@f%Hf%Pf%Xf%`f%hf%pf%xf%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%g%g%g%g% g%(g%0g%8g%@g%Hg%Pg%Xg%`g%hg%pg%xg%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%h%h%h%h% h%(h%0h%8h%@h%Hh%Ph%Xh%`h%Zhh%ph%xh%h%h%h%h%h%h%h%h%h%h%h%h% h% h% h%h% i%i%i%i% i%v(i%0i%8i%@i%Hi%Pi%Xi%`i%hi%pi%Rxi%i%i%i%i%i%i%i% i%i%"i%#i%$i%%i%&i%'i%)i%*j%+j%j%,j%- j%.(j%/0j%08j%1@j%2Hj%3Pj%4Xj%5`j%6hj%7pj%8xj%9j%zj%:j%;j%<j%=j%>j%?j%@j%Aj%Bj%Cj%Dj%Ej%Fj%Gj%Hk%k%Jk%Kk%L k%XHH9$HtH5$%$hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?h@hAhBhChDhEhFhGqhHahIQhJAhK1hL!hMhNhOhPhQhRhShThUhVhWqhXahYQhZAh[1h\!h]h^h_h`hahbhchdhehfhgqhhahiQhjAhk1hl!hmhnhohphqhrhshthuhvhwqhxahyQhzAh{1h|!h}h~hhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?h@hAhBhChDhEhFhGqhHahIQhJAhK1hL!hMhNhOhPhQhRhShThUhVhWqhXahYQhZAh[1h\!h]h^h_h`hahbhchdhehfhgqhhahiQhjAhk1hl!hmhnhohphqhrhshthuhvhwqhxahyQhzAh{1h|!h}h~hhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?h@hAhBhChDhEhFhGqhHahIQhJAhK1hL!hMhNhOhPhQhRhShThUhVhWqhXahYQhZAh[1h\!h]h^h_h`hahbhchdhehfhgqhhahiQhjAhk1hl!hmhnhohphqhrhshthuhvhwqhxahyQhzAh{1h|!h}h~hhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?h@hAhBhChDhEhFhGqhHahIQhJAhK1hL!hMhNhOhPhQhRhShThUhVhWqhXahYQhZAh[1h\!h]h^h_h`ha%m#D%e#D%]#D%U#D%M#D%E#D%=#D%5#D%-#D%%#D%#D%#D% #D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%}#D%u#D%m#D%e#D%]#D%U#D%M#D%E#D%=#D%5#D%-#D%%#D%#D%#D% #D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%}#D%u#D%m#D%e#D%]#D%U#D%M#D%E#D%=#D%5#D%-#D%%#D%#D%#D% #D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%}#D%u#D%m#D%e#D%]#D%U#D%M#D%E#D%=#D%5#D%-#D%%#D%#D%#D% #D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%}#D%u#D%m#D%e#D%]#D%U#D%M#D%E#D%=#D%5#D%-#D%%#D%#D%#D% #D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%}#D%u#D%m#D%e#D%]#D%U#D%M#D%E#D%=#D%5#D%-#D%%#D%#D%#D% #D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%}#D%u#D%m#D%e#D%]#D%U#D%M#D%E#D%=#D%5#D%-#D%%#D%#D%#D% #D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%}#D%u#D%m#D%e#D%]#D%U#D%M#D%E#D%=#D%5#D%-#D%%#D%#D%#D% #D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%}#D%u#D%m#D%e#D%]#D%U#D%M#D%E#D%=#D%5#D%-#D%%#D%#D%#D% #D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%}#D%u#D%m#D%e#D%]#D%U#D%M#D%E#D%=#D%5#D%-#D%%#D%#D%#D% #D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%}#D%u#D%m#D%e#D%]#D%U#D%M#D%E#D%=#D%5#D%-#D%%#D%#D%#D% #D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%}#D%u#D%m#D%e#D%]#D%U#D%M#D%E#D%=#D%5#D%-#D%%#D%#D%#D% #D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%}#D%u#D%m#D%e#D%]#D%U#D%M#D%E#D%=#D%5#D%-#D%%#D%#D%#D% #D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%}#D%u#D%m#D%e#D%]#D%U#D%M#D%E#D%=#D%5#D%-#D%%#D%#D%#D% #D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%}#D%u#D%m#D%e#D%]#D%U#D%M#D%E#D%=#D%5#D%-#D%%#D%#D%#D% #D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%}#D%u#D%m#D%e#D%]#D%U#D%M#D%E#D%=#D%5#D%-#D%%#D%#D%#D% #D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%}#D%u#D%m#D%e#D%]#D%U#D%M#D%E#D%=#D%5#D%-#D%%#D%#D%#D% #D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%}#D%u#D%m#D%e#D%]#D%U#D%M#D%E#D%=#D%5#D%-#D%%#D%#D%#D% #D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%}#D%u#D%m#D%e#D%]#D%U#D%M#D%E#D%=#D%5#D%-#D%%#D%#D%#D% #D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%}#D%u#D%m#D%e#D%]#D%U#D%M#D%E#D%=#D%5#D%-#D%%#D%#D%#D% #D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%}#D%u#D%m#D%e#D%]#D%U#D%M#D%E#D%=#D%5#D%-#D%%#D%#D%#D% #D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%}#D%u#D%m#D%e#D%]#D%U#D%M#D%E#D%=#D%5#D%-#D%%#D%#D%#D% #D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%}#D%u#D%m#D%e#D%]#D%U#D%M#D%E#D%=#D%5#D%-#D%%#D%#D%#D% #D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%}#D%u#D%m#D%e#D%]#D%U#D%M#D%E#D%=#D%5#D%-#D%%#D%#D%#D% #D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%}#D%u#D%m#D%e#D%]#D%U#D%M#D%E#D%=#D%5#D%-#D%%#D%#D%#D% #D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%}#D%u#D%m#D%e#D%]#D%U#D%M#D%E#D%=#D%5#D%-#D%%#D%#D%#D% #D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%}#D%u#D%m#D%e#D%]#D%U#D%M#D%E#D%=#D%5#D%-#D%%#D%#D%#D% #D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%#D%}#D%u#D%m#D%e#DH=y#Hr#H9tHF#Ht H=I#H5B#H)HHH?HHtH#HtfD=#u+UH=#Ht H=N#d#]wATH5#US,H8HHHC Hx H=IGLHH9HC Hx(H=tILHH HC Hx0}H=ILHHHC Hx8NH=ILHHHC Hx@H=_ILHH}HC HxHH=2I\LHHNHC HxPH=I-LHHHC HxXH=ާHHHHH[]A\HA#H5zH81H)#H5{H81ATUSHHH5#5HHHtkHKLe HI|$XHtHt1HH[]A\@HD$Ht$ID$XHE HxXHuHX#1H81@H@ HxXHE H@XHH[]A\HL#H5H81 ff.ATUSHHH5ʪ#UHHHtkHkLe HI|$PHtHt1HH[]A\@HD$Ht$ID$PHE HxPHuHx#1H81 @H@ HxPHE H@PHH[]A\Hl#H5H81+ff.ATUSHHH5#uHHHtkHLe HI|$HHt%Ht1HH[]A\@HD$Ht$ID$HHE HxHHuH#1H81,@H@ HxHHE H@HHH[]A\H#H5ŤH81Kff.ATUSHHH5 #HHHtkHLe HI|$@HtEHt1HH[]A\@HD$Ht$ID$@HE Hx@HuH#1H81L@H@ Hx@HE H@@HH[]A\H#H5H81kff.ATUSHHH5*#HHHtkHLe HI|$8HteHt1HH[]A\@HD$Ht$ID$8HE Hx8HuHا#1H81l@H@ Hx8HE H@8HH[]A\H̪#H5H81ff.ATUSHHH5J#HHHtkHLe HI|$0HtHt1HH[]A\@HD$6Ht$ID$0HE Hx0HuH#1H81@H@ Hx0;HE H@0HH[]A\H#H5%H81ff.ATUSHHH5j#HHHtkH Le HI|$(HtHt1HH[]A\@HD$VHt$ID$(HE Hx(HuH#1H81@H@ Hx([HE H@(HH[]A\H #H5EH81ff.ATUSHHH5#HHHtkH+Le HI|$ HtHt1HH[]A\@HD$vHt$ID$ HE Hx HuH8#1H81@H@ Hx {HE H@ HH[]A\H,#H5eH81ff.AUIATIUHSH(H5#dH%(HD$1H8H{HC Hx THx8Hx@Ld$1LD$LLH(LYH{ 1pHcHK IHPH tHPHD$H8 t[HpHxHcH9AHcLLHL$dH3 %(H([]A\A]f.HHpH|$@tMP8fH5%LHHP#H5 H81߾H%#H5˞H81贾H=#H5H81蜾H%#H5^H81菾Hء#1H81lwATUSHH5#dH%(HD$1H8HH} H8tH@t L%á#L%#1AHcH1HH@H uaH$HH} AԅxlHH4$ tSHCHSH)H9HHHL$dH3 %(H[]A\HCf.HHSH#1H81@Hɤ#H5H81(H#H5H81pH rH57H=@ff.AUIATAHUSH(H5#dH%(HD$1}Hn8HsHl$DHL$LIHϜ1`H|$HE1H|$IUH}HHt=Hs H~8tJH~@tCHL X#1LATE1HFZYu,H(HQ#1H81DHxtHHL$dH3 %(H([]A\A]DH Ld$I<$H% t=I|$HcH9~vHu2IfE1E1 DHMd$H#H5H81~H#H5H81H"#H5cH81@USHH5#Htt8H;uMHHHt%Hs H1Ht H[]H՝#1H81iH#H5DH81QHڡ#H5H81fSHHOHWwH?EC 1[ff.AUIATIU1SH9Ht=LHHqt=H#HL{1H5ΙHHHH[]A\A]fHHH[]A\A]f.USHHH5#'H8HH} rHtJ؃H H{Ht7HHt*H[]HuHt1HuH#H8HH#1H81襸DHA#H8@HI#H8H9#H8uH#H8eH#H8UHڟ#H5,H819HŸ#H5H81UHSHH5L#HtS8Hxu\HC Hx8tHx@tH[]DH5HqH1HtH[]H8#H5qH81H #H5rH81ff.@PXH57HH#H81fHH5# Ht!H@ HxXHt HHHH5A#Ht!H@ HxPHt HHaHH5#Ht!H@ HxHHt HQH!HH5#LHt!H@ Hx@Ht HHHH5# Ht!H@ Hx8Ht HHHH5A#Ht!H@ Hx0Ht HHaHH5#Ht!H@ Hx(Ht HQH!HH5#LHt!H@ Hx Ht HHAVAAUATUHSH`dH%(HD$X1IIMr1Huff@tPHsLuLLE1HT$XdH3%(L2H`[]A\A]A^DH\$D$ HD$HL$H#|$D$H\$HD$ Ll$0Ld$8Dt$@HL$HHA#H= Ht$0HmD$PLuuL|$ 5@H!#HL$D$D$H\$HD$ Ll$0Ld$8Dt$@HL$HLLDLD$PtxMtLfMAVIAUAHATIUSH H5#dH%(HD$1HeH\$HHL$1IH~LD H|$HD$@tCHtHHHމHHu]H,#1H81E1HHHD$1Hڗ#L1HI*HHLHھHrHL$dH3 %(LhH []A\A]A^f.HfDHhH|$IXHH|$H 11ҾLOz111L HHB11ҾLJ1LHH11ҾL1LHH11ҾLdz111LHH11ҾL藳±1LLH=HH]#H5QH81H Hc#H5H81"fUSHHH(dH%(HD$1HL$LD$xH|$Ht @tWHHH|$@tY葷HHHtYHHDHtIH\$dH3%(uTH([]H|$H@uHHHuHHG#1H81ۯfDAUIATUHSH(H5#dH%(HD$1nH^8H 3HC Hx  Ld$1LD$LLHCLH{ Y1pHcH[]HpfHH H5H=hsH#H5H81KHd#1H818AVAUATUHHRSH dH%(HD$1H\$Ll$HMHiHD$H HLpHZH5q#H腵IH'HqHcHHH|$H1茲HD$AHpH ugHT$LLwH|$Hct$H tMHGH9[HD$HL$dH3 %(H []A\A]A^DHpf.HLpHXLHH|$H諢HD$:HɄ#1H81蝟HƂ#HH5H81肟H #H54H81jH#H5H81RH ;H5WH=3>ff.AWAVAUATIH~U1SHdH%(H$1H\$Ll$HHD$0MHP1LL$0趵YH^HD$@H}uKHmP AXH#1H81ۜH_#H5~H81辜Hׁ#H5XH81覜fDS趵H5HHH[f.SHHHH1[AUATUSHHHHƒHH9tSH5l#HȰIHtPL-~#HIu}HtpH5l#H虰HtDHLiuvHH[]A\A]fDIHC HpH #H52}H81hHI]H5HH+#HH81>HW#1H81+ff.HtSHnH[%Dff.@PX1HH#H81ךSH5k#H茯Ht!E1111AH萬uH[H#H5H|H81~fPXH5'|HH#H81RfHH5k# HtH_HHHHDfDHH5j#̮HtHHǞHHHDffDHH5j#茮HtHߪHgHHHD&fDHH5Qj#LHt0H1wIHHЃ<HHfATUHSH Ht$H|$dH%(HD$1蒫HD$LA uaIL`LÃH5i#H购Htg1HT$ALHt6HL$dH3 %(HD$u>H []A\L`HXfDH}#H5z|H81x~ff.HH5!i#Ht#HoH藞HHԮff.@AWAVAUAATIHSxUSHdH%(HD$x1Hl$H\$IH轮EL=HeH={HHH1HH5_h#LWIHH|$fo|)D$ HL$L9A IHAHL$Hl$ RLH$VjEHAHH\$8SHL$Ht$0XIZH11EL٨ H\$xdH3%(L HĈ[]A\A]A^A_H(Ht$H tcH~~lHvo)L$ fH5Ig#LAIHt~E11gHyHcAH9HI@t Hf)D$ H tHVHvH|$ @HHHt}#H5wH81ӕHz#1H81˳ƕfD1DfATUSHH`Ht$H|$dH%(HD$X1貸H5+f#HI H記HC HHLAHfE11AHL$HH)D$)D$ )D$0)D$@զu9HT$XdH3%(Hu!H`[]A\HM|#H5-wH81謔跲Hy#1H81蔔H|#LH5yH81yfATIHUSHt:腛H5e#LHt-HuH[]A\+"H{#H5uH81f.ATIHUSHt:H5d#L蔨Ht-HuH[]A\諪H{#H5DuH81zf.AUATAUSHHuHdH%(HD$1H*HH5c#HHHIHMcLDHHHۚLHȤHHHHL$dH3 %(uH[]A\A]H<$@t詙A?{A1H|w#H5uH81KHy#H5sH813HLw#H5vH81&fDUSHHH-t#Hu蓷Ht"H5b#H详Ht8HH[]HHm@H5uHHx#HH81袑H+y#H5TsH81芑f.Hmt#ATIH9b#U1SH8H軔HE HH,E111ALHuH[]A\H0v#1H81@HUx#SH5(tHHt#H8۠Hu#Hs#H5]sHHH踠Hu#H;H5gH_H;H@H5,s脲H;1HH5$s,H;HH5pQH;1HuH5r9H;HH5qH;H_H5pH;HH5rH;HH5ͱH;1HH5r赱H;1HIH5蝱H;H^H5肱H;H3H5BrgH;H(H52rLH;HH5!r1H;1HH5rH;HH5rH;1H"H5qH;HH5q˰H;1HH5q賰H;1HWH5q蛰H;[HH5qf.D7USHH5s#dH%(HD$1 HtrH=HeHHHH莻td1HsHhH$HxH0HH HHT$dH3%(uH[]HLu#H5rH81諍趫HΛH=#H5s1艍H=#H5r1t@USHH5/r#dH%(HD$1HtrHMHuHHHHtd1HsHxH$HxH0HHHHT$dH3%(uH[]H\t#H5rH81軌ƪHޚH=#H5,r1虌H=#H5 r1脌@USHH5?q#dH%(HD$1*H1HHHc1BHH@H tHCHHH$迦H t7HCH4$HSH)H94HHHL$dH3 %(u8H[]ÐHH4$HSH qH5\qH=k蠜諩H=#H5-q1膋Hs#H5pH81nff.ATUSH Hn#HHHH0Hu8H踾111HIWHHtWL7Hk H[]A\H5m#H蹟HtHܜHHuH=5#H5p1迊11ҾLBH=#o#1LH5_p#zLH诘HoHl#H5@pH81^H=#H5o1IfHo#1ff.PXH5WoHHq#H81fHH5n#dH%(HD$1D$褞Ht.Ht$Hrt$HƛHT$dH3%(u H|觧HH5Qn#LHt3HOH@HxHDHfDHH鴞ff.@ATUHSHH5m#Ht6It!HHL;[H]A\_HЙHfDSH5m#菝HH^HtaH@HxZH\H5#Ht!Hjk#Hٺ[H81OH='HH#[ÐH訝Hff.ATUHSHH5l#֜HIHj#HH0蘑Hu#t>HHLЯ[H]A\@H5#Ht$H11舞HuH舘HH=imOHHՋ#Hn#H5lH81[ff.9uWD;VDtHHHHAUATUSHHH-k#HЛHtJL-n#HIIu腬HtGHH襛HtLHHH[]A\A]H:n#H5kH81虆HIm H5NjHH\m#HH81off.@Hm#SH5VlHHi#H8;H\k#H5n#H5lHHHH;H5Ho#“H;HH5fH;HH5O̧H;1HH5I货H;HH5k虧H;1HH5H聧H;HBH5-fH;1HZH5 NH;1HH5 f6H;1HH5eH;1[HH5eDHATUSHHkH dH%(HD$1HLL$LD$蘛u$HT$dH3%(HH []A\@H<$װH|$HʰH|$IHtDHLH艣HHt@H5U#HHt?H5Hk x@HH1KHHzk#1H81Hwk#H5jH81փfDAWH5U#AVAUATUSHxdH%(HD$h1bHD$H蟜H|$HD$8D$HD$`1HD$HD$XHD$ HD$PHD$(HD$LHD$09l$H|$觘HHtLD$HL$ HHD$`HT$(Ht$0HD$XHD$P訖AąxH;yIHZ؛HAT#LIHlf#H8\LH1IcLHt6!Hct$LLHt6H|$PHtHLH|$XHtHLѯH|$`HtݨHL貯-HIrAŅ~2E1DHA衬HYLHnE9uLL[H|$8LN9l$HL$hdH3 %(HD$8u'Hx[]A\A]A^A_H i#H5gH81hsHh#1H81PUSHHcHdH%(HD$1HHH<$tzH蒓H5R#HӕHH4$H t>H~HcωH9HvH`tQHL$dH3 %(HuQH[]fHHH5R#HaHt)1H Hg#1H81hsHg#H5fH81KVfD7UH5tR#SHdH%(HD$1ڔH1HHdHcH1HH@H uQHHH$2~[HH4$ tBHCHSH)H9jHʒHHL$dH3 %(unH[]HCf.HHSHf#1H81PHf#H5eH818H i'H5eH=h_$@gUSHHaH(dH%(HD$1HHH<$Hu'HL$dH3 %(HH([]fHC HD$HH$H$H uJHHHD$Ht$H|$諘HT$HS HuHe#H5gH815~DHPHT$HP,ff.UH5P#SHdH%(HD$1躒H1HH蔜HcH1яHH@H uQHHH$b~[HH4$ tBHCHSH)H9jH誐HHL$dH3 %(unH[]HCf.HHSHd#1H810}Hd#H5cH81}H qgH5ycH=H]@AVH5O#AUATUS訑HHHAą~mؕ1L5?N#I@HH覭H>HtKHHG`#LH81LHA9u[L]A\A]A^DA[]LA\A]A^Hc#1H81+|Hc#H5bH81|USHH^HdH%(HD$1HHђH<$tzHRH5{N#H蓐HH4$H t>H~HcωH9HvHЯtQHL$dH3 %(HuQH[]fHHH5 N#H!Ht)1H}Hb#1H81({3Hb#H5aH81 {{fDUSHH]H(dH%(HD$1HHH<$Hu'HL$dH3 %(HH([]fHC HD$HH$H$H uJHHHD$Ht$H|$軗HT$HS HuHa#H5cH815zDHPHT$HP,ff.HH5K#̎Ht HxH銬Hsa#H5`H81yfSH]#H@H5]HH`#HH81yfUSHH5 K#HWHtIHH@]#HH0 HtGH5J#H)HtHH HH[]H`#H5f_H81!yHIfUSHH5J#HǍHtIHH\#HH0}HtGH5aJ#H虍HtHHYHH[]H2`#H5^H81xHfPX1HH_#H81gxSHäHtHHI#H[}fDATUSHH5J#HtFL%]#HHI4$螝Ht[H5J#H躌Ht/HHz[]HA\HDHW_#H5^H81wH?_#H5(^H81wHI,$H5S[HHa^#HH81tw@SHSHtHHDI#H[ }fDPXH5]HH^#H81"wfHH5aI#܋Ht9H?}Ht"HH[#HH#H8H|DHfHH5I#|HtHHHHDNff.HH5H##HIHL%O#H|$ I4$訑HH|$ H5=#辀HHLMMUL$(HƋT$<בIHD$ XZMHI H5R#E1HCIG HD$d@HL9sHlHH lHD$JMH; H5GMH; H5MM̋H;H5VM踋H;H5]M褋H;H5QM萋H; H5FM|H;H59MhH;!H5-MTH;AH5"M@H;H5M,H;H5MH;H5MH;H5LH;H5EM܊H;H5LȊH;H5L贊H;H5L蠊H;H5L茊H;H5LxH;[]H5LA\`wUH56#SHdH%(HD$1JxH1HHT~vHc1fuHH@H uNHHH$'~IH4$HCH u2H)HGvHHT$dH3%(u-H[]DHCfHCHJ#1H81bH[J#H5XMH81bf.ATH55#USHdH%(HD$1XwHHxHH@L%]I#E1E11Lx1HcNtHH@H tHCH}HE1E1LH$DuH5c#Hl$HtaHH1OuH5b#Hl$Ht^HH1,uHL$(dH3 %(HH8[]A\A]f.H=HߋHH}b#H=H迋HHUb#H|$6kHHD$IpHD$H tDHPHT$ HPHt$ H|$lHT$HS HBHE#1H81{]HHHD$ q{HD#H5GH81I]fSHHtHH40#H[bHE#1H81]ATIUSHH|$Ht$21HHxHHt-H5/#LqHtAHH>iHD$H[]A\þHwHHuHD#1H81x\HD#H5FH81`\HHt+^Ht(HHC#HH/#H8Ha@HD#1H81\ff.USHHH-C#Hu胁Ht(H5.#HpHtQHҍHt1H[]HHm*H5k?HHyB#HH81[HC#1H81y[HC#H5EH81a[SH|@#H55FHVB#HH;;kH4C#H;H5!FHHB#HkHB#H5HHhH;HH5;|H;HH5E|H;1HH5E|H;H2H5|E|H;1HH5wX~|H;1[HH5:;e|DSGHu H?HtoH[[ff.SGHu H?HtzH[+ff.AUH5[EATUSHHoH5L-#HHnHL MHMA#HH3JHH5j-#HbnHHHH^AH;#H8uHHXsH<#LHHLDxHt&HH[]A\A]H>#H5IH81YH>#H5DH81XH>#H5wDH81XH>#H5IH81XHH?H5<HH?#HH81XHZ>#H5DH81XfAUH5CATUSHHnH5+#HH!mHt_L ML-?#HIu}HH5+#HlHtkH8HtKL萁u&HH[]A\A]H=#H5HH81WH>#H5CH81WH=#H5:CH81WHv=#H5WHH81WHI]H5B;HHP>#HH81cWH=#H5BH81KWff.AUH5BATUSHHlH5*#HHkHtiL ML->#HIu|HH5*#HkHtuH8HtUH9#LHvu&HH[]A\A]H\<#H55GH81VH=#H5OBH81sVHD<#H5AH81[VH,<#H5 GH81CVHI]跆H59HH=#HH81VH;#H5zAH81VAUH5[AATUSHHkH5L)#HHjHtiL ML-Q=#HIuM{HH5m)#HejHtuH8HtUHI8#LH6Xu&HH[]A\A]H;#H5EH81KUHd<#H5AH813UH;#H5@H81UH:#H5EH81UHI]wH58HH;#HH81TH:#H5:@H81TATH5@USHYjH5(#HHgiHHHL%<#HI4$zHH5/(#H'iH}H8Ht]H7#HHtYtu[]A\Ð[1]A\H2;#H5@H81TH9#H5DH81SH9#H5f?H81SH9#H5DH81SHI$-H5n7HH|:#HH81SHH9#H5>H81wSATH5>USH iH5&#HHhHHHL%:#HI4$xHH5&#HgHtyH8HtYHWtu[]A\[1]A\H9#H5>H81RHr8#H5KCH81RHr8#H5>H81RHZ8#H5;CH81qRHI$H5&6HH49#HH81GRH8#H5=H81/Rff.@H99#AVAUIATUSH8HcnH5l%#HHfL59#HII6|wHtOH5%#HfHH0HtpL/SI$HtGHHH5=tn[H]A\A]A^HI.H5>5HHL8#HH81_QH7#H5u=H81GQH7#H5<H81/QH7#H5AH81QAVAUIH5n$#ATUHSHH dH%(HD$1eH8IHL$1LLD$H0g#L-.8#H|$Iu(vHH\$IuHvH{H5.$#H&eHL(M H2#H|$H0uHdH|$jH2#LHH 1cQHHI$HH5J;HlHHL$dH3 %(H []A\A]A^fDL-6#H|$Iu;uHH|$H5:1eL57#HHI6 uHH5,##H$dHL0MIuH|$tHH|$H5"#cHH8HLzPDL-6#H|$Iu{tH<H\$IuHatHH5"#HycHtUH8Hte7{H1#H5?H81zNH1#H5:H81bNH4#1H81ONH 4#H5?H817NH4#H59H81NH3#H5B:H81NH5#H5a?H81MkImH^~HHH4#H51H81MH|$FH[Hg3#H59H81MHO3#H5h>H81~MI.H}HI]H|$}HH3#H5=H81CMH2#H58H81+Mff.AWAVAUAHATIH5l8USHHXdH%(HD$H1bH5O #HHD$(aHH(HL5N4#H|$(I6IrHDH|$(H5d #_aHHHD$HH3#H8hHt$(IHAH5#LaHXHHD$H_DHL$0LL$8LLD$@HT1bH|$0D$AHZ.#H0qIHtrH|$0e1HA~ H|$@eHHt$H|$IHHq.#LaL HL$HdH3 %(LpHX[]A\A]A^A_fH|$0qwHD$0H( MH<H57>\IHt)E1H|$0L|H eKDIL9uH.-#H|$@H0pHH|$@HzHD$@H H<H5?7[HHt=L%#@H|$@L{LHH_HHJDIL9u1҃|$eH-#HMIH0H|$Ht$ lZLYkHkxHXLHhH|$8cHH/#H5s:H81IH/#H5*5H81IH/#H5.5H81IkH kHE/#H55H81tIHE/#H5&:H81\IH|$(IyHH5 -HH0#H811ILjH0#H55H81q_gff.SHYLHHO#[HNfDSH)LHH#[HfNfDUH5d#SHZ]HtH\!#H50H81>\H?&#H500H81>Ho$#H5+H81>H!#H5p0H81n>H|$HnHH5"HH-%#H81C>H #H5/H81+>H##H5)H81>H##H5.H81=H##LH5+H81=H##LH5*H81=DUSHH5!#zRHtV8Hh=Hk HrHYHHtTH1HdH߅t#H[]fH$#H5H81SbKH#H5*H81=H#H5)H81=H#H5l*H81HHc8H[]A\DHxH#H5S!H815H#H5l&H815HH7fH5xHH#HH815H2#H5#H815H #H5"H81i5H#H5+H81KH#H5#H8195fATUSHH5^#IH8H_=Hm HHtXL%#HI4$uZHH55#HIHH0HH0<uH[]A\1H<vH#H5\"H81i4H#H5!H81Q4H#H5H81JH#H5!H81!4H#H5H81 4H#H5$H813HI,$edH5HH#HH813UHSHH5#wHH8H^=H{ HAHHtOH57#Ht#11H7JHt=HHH[] H=`HH7#H[]H#H5%H812H#H5f H812Hm#H57 H812HU#H5H81I@ATUHH5#SiGH8H]=H[ HHu1H7w(H[]A\ÐHHLHHI7u&MtH#H5" H812fuH[]A\H#H5H81KHH#H5UH811H\#H5&H811ff.AWAVAUATIUHSHH5#\FH8H[=Lk M[L5#LI6VHH5#LFHL8MH5HFHHtEI6HVH H5#HEH5HH@MH5&HMLLvFu*HL[]A\A]A^A_H#H5QH81FH#H5H81_0H0#H5H81G0H#H5 H81/0IL`HHH#H5H810H#H5pH81/Hw#H5AH81/I.HK`HfDAUATUHSHH5#sDH8HZ=Lc MH5HEHHtHH[]A\A]fLRIHtL-#I}KIuHHTHHH5#CHHH5L @KHHH5HKHH[]A\A]Hf#H57H81.H>#H5H81.H&#H5_H81DHIm^H5:HHH#HH81[.ff.AWIAVAUATUSHH8H5q#|$ HdH%(HD$(1BH!L` HM)Ll$ Lt$|$ 1LMH7LDL|$IH#LH0VSHH~#H|$H09SH%H5#H|$OBIH8W=(I|$ HUAIML꾘HV|H5HIIt'H51#Hl$HHH1CHL$(dH3 %(HDH8[]A\A]A^A_DHI#H|$H0DRHH|$!`H|$ It LOIH#L1L'3IHL:L꾘HUH5HI?f?IH=YHH}0#?L|$IfD11ҾL7.b,L1LH#TIHG11ҾL.,,1LrSIH11ҾL-,1LVLI{9ML:`HI?AMEDXIHHǾ.L2Ht#H5 H813AHl #H5H81*HT #1H81*LTH9 #H5H81*HH #H5H81k*H<#H|$HZH5HH&#HH819*H#H5H81!*H #LH5pH81*H #LH5<H81)ff.U11HAWAVAUATSH(dH%(HE1C2LcIL9HHHHHH)HH9tHH$H9u%H\$LHH1HL5IE~wEl$IIJ+HEf;RLkI4LI?LHVMt L?HLHqVLLfVH;]uHMdH3 %(LuDHe[A\A]A^A_]H)HL&H(H #H5H81j(uFDSH5 H3HH53HH5L3HH5 [r3fPXH5HH #H81(fHH5"HHtf1IHH;>H#HHHV;u"HH[]H #H5H81#H #H5H81#H #H5dH81#ff.@UH5"SHz8Ht>HHtf1FIHH=HL#HHHAu"HH[]H8 #H5H81O#H #H5H817#H #H5H81#ff.@SH5"H7HtH8Ht):$H[HH#H5H81"PXH5/HHL#H81"fSH5#_7Ht.8HM=u:H{ Ht, 0[HHHЃH #H5H818H #H5H81'"SH5T#6Ht+8HL=ubH{ HtA{:u[Hh #H5H81'8H`#H5H81!HH#H5H81!H #H5H81!ff.@SH5#/6Ht.8HK=u:H{ Ht,k6[HHHЃH#H5H81t7OH#H5bH81 SH5$#5Ht98HPK=uEH{ Ht75HtH[]FD[H*#H5cH816H #H5 H81l ff.UHSHH5#5Ht.8HJ=ueH{ HtD#(u"HH[]H#H5H81\6H#H5H81H}#H5N H81HU#H5 H81@ATUSHtSH?J=H_#H#HH85%1H5HHAH;1HH51>H;HH5A >H;1HH5]->H;HH5 u>H;1HH5;-]>H;HH5 B>H;1HH5 *>H;1H~H5 >H;1HH5 =H;1HH5 =H;HH5z =H;HhH5n =H;HH5a =H;HbH58v=H;H)H5).H;1HH5H=H;1H|H50=H}H5U(H}HH5=H}H$H5 HH*/ff.@HH5!"(HtH&HWHHHDfDHH5"|(HtH&H*HHHDfDAUATUSHHHtzHƒtmuhHH9tRH5l"H(IHtQL--"HIu8HtdH5="H'Ht%HLt.HH[]A\A]HHd"H5H81H"1H81HI]$CH5eHHs"HH81fDUSHH|$@u HuBHc"H37HH|$H5n" 'HH8%H[]ÐuH|$ GHHQEHu1H"-HHE;H(EHH$'H$HuHL"HH5H81H1"H5rH81H|$HBHH5AHHO"H81eDATUSHHH dH%(HD$1Hl$HL$I(H|$4H|$ItH#H54"H%Htd1LHDu:Ht$Hu"HT$dH3%(HuLH []A\fDHP-HH"H5H81H"H5]H81{.fDUHSHHd"H84H5}"HH%Ht1HH@Du"HH[]H"H5H81 H*"H5HH81SH=<4H=^#H5HH"H8H"H"H59HHHH"H;H5fH>H;HH5c1H;HH5H1H;1HH501H;H&"H51H;HH5_"H;HPH5H;1HH5{0H;1HH5q0H;1[HWH50f.H"SH5 H8H~"H>l>w@.x,c-H;H5O4H;H54H;H5,4H; H54H; H54H; H5{4H;H5g4H;H5S4H;H5?4H;H5 +4H;H5 4H;H54H;H5T3H;H5h3H;H5|3H;!H53H;#H53H;%H53H;'H5w3H;)H5c3H;+H5O3H;-H5p;3H;/H5v'3H;1H5u3H;3H5r2H;5H5y2H;7H5{2H;9H5|2H;;H5|2H;=H52H;?H5$2H;AH5ws2H;eH5$_2H; H5jK2H;H5g72H;H5h#2H;H5g2H;H5f1H; H5h1H; H5g1H; H5i1H;H5f1H;H5^1H;H5^1H;H5Wo1H;H5T[1H; H5QG1H; H5I31H; H5G1H;H5C 1F*H H;H5:H04H H;H5-H0()H H;H5H0H H;H5H0 H H;H5Hp0!Hc H;H5[HP0gSHHHt H5h"8H{HtU-H[ff.SHHH5&H[@ATIUS1HHt$Hu\H5"LHH>HHi HteE1HھH<;uHHL[]A\H|$.H|$H\$H uHyDH[kH"1H81lH"H5H81T@ATIUS1HHt$Hu\H5"LHH42HH HteE1HھH\:uHHL[]A\H|$NH|$H\$H uHyDH[kH"1H81H"H5H81t@PXH5HH"H81RfATIHUHS2t6HHH5"LHt)HH1#H[]A\HH~ff.AVAUATUSHHH dH%(HD$1HLL$LD$H5-"HeHFL%"H<$HI4$,HH<$H5Q",IH"H|$E1Ht"IH|$E1HtGILLLHu{H<$H5Ht HHH<$H5H5HH"HT$H5H"HHL$dH3 %(H []A\A]A^H5|"L4H"1H81qH<$I$5HH5"HH0"H81FH"H5H81.H"H5H81!#ATUHSHt-IIH5"HHt LHH[]A\HINff.HH51"lHt!HHt HfHHH5",HtHHHSff.HH5"HtH7HHHDff.HH5q"HtH%HHHDNff.HH51"lHtH?%Hc)HH+fDUSHH5"H'Ht3HHuRH8HH[]fDS f.AUH5"ATUSHHH%HHt}H)AąxNHcIEt+1@H[HLH80A9uHL[]A\A]DH"H8t+H[]A\A]@HA[L]A\A]@H9" H=H 6H H=6H;A1H H -tHp"H5H81ff.@ATUHHSH0dH%(HD$(1LD$ HL${LL$ LD$H5#HH"HH818Hp##0H5HHH5J#H1H1HIH5"HHH@H5HHHH5HHLHL$(dH3 %(H0[]A\@H5cHAI@H=+G.HH#GH={LD$L $.LD$L $HH[#9fUH5"HSHHtAHH5HHHH#"0#H HHH[]Lff.PX1HH"H81SHs3HtHH"H[+fDUSHHH 5H54"HH HtHHu"HH[]H"H5H81Mff.fUSHHH;+H5"HHHtHH2u"HH[]H3"H51H81ff.fHH5a"<HtHu"HH"H5H818PXH5HH"H81fATUHSHt-IIH5"HHt LH/H[]A\HIff.UHSHH5"HdHt1HxxH|"Hڋ0*!HHH57HHH[])fSH54"HH HtuH"H@xH߾HP(dHߺH5$HߺH5HߺH5HߺH5XH[f.SH/HtHH"H[KfDATIHUSHt2H5"L$Ht HH[]A\DCf.ATIHUSHt25H5"LHt HeH[]A\DZf.ATIHUSHt2H5"LdHt HH[]A\D:f.ATIHUSHt2uH5,"LHt HH[]A\D#f.HtH"HH"H8PHf"H5dH81DUSHHH-"HuC HtH5"H_Ht1H[]HHm*H58HHF"HH81YH"H5H81AUSHHH-,"HuHtDHH5"HHtWAa HH D'HH[]HHmN*H5HH"HH81H9"H57H81HtH"HH"H8.PH"H5H81UDUSHHH-"HuHtHC HH[]HHm)H5HH"HH81fATH "H55UH-"SHH}H"H}H5L%"HI$H"H5"HHHE11ɺHv#H5"HH;E11ɺT#H5"HTH;E11ɺ2#H5["H H;E11ɺ#H;H5VH;HH5H;H'H5:H;HH50H;HH5H;H&H5 zH;HH5[_H;HH5DH;HH5)H;1HH5H;HH5H;HH5H;H H5tI$H}H5xH5HH"HHPH߹HH5u1HHIH5]1HHAH5E1HHIH5Z-H߹HH51HHVH5&1HHH5H1HfH5H1HH5H߹HH5H߹HH5|H߹HMH5aH[]HH5@A\BfH="HHm"HDH=A"HH-" H= "HH "H="HH"JAWIAVAUATU1SHHLsH ZHH9}\H "HL HH LH tG1HsHH$HxH0hHH}HHT$dH3%(u:H[]H[H"1H81H"H54H81 ff.UH54"SHdH%(HD$1H1HH$HcH1HH@H uQHHH$ ~[HH4$ tBHCHSH)H9jHHHL$dH3 %(unH[]HCf.HHSH"1H81H"H5,H81H H5'H=( @UH5"SHdH%(HD$1zHH$H HHt^HHtG1HsHH$HxH0hHH}HHT$dH3%(u:H[]H[H"1H81H"H54H81 ff.AUATUSHHHHƒtzuuHH9t_H5"HpIHt^L-"HIu%HtqH5"HAHt2HHHt:LHk HH[]A\A]H*H"H5VH81"H"1H81HI]H5HH"HH81DATUSHH dH%(HD$1HB HL$HEHD$1u!HT$dH3%(HH []A\ÐH|$Ld$HHD$ 11LHHbHT$HS HtHlf.11ҾHLHHIHD$HC +MQHc"1H81 f.PX1HH9"H81SH3HtHH"H[KfDUHH5"SH7Ht$HHHHLt"HH[]H"H5ZH81&QAUH5c"ATUSHHHI ŅxLHcIŅt)1L HLHX9uHL[]A\A]fDH"H8tH[]A\A]@Hq" H=IH H H=H;A1H wHCH"H5>H81 f.UHH5A"SHHt-HH HH,x+HHH[]H>"H5H81AUIH5п"ATIUSHH=Ht6LHLI LHHt&HH[]A\A]H"H5NH81EDUHH5Q"SHHt$HH HH<t"HH[]HW"H5H81HH5"lHtHHt$HHnH"H5H81fUHH5"SHHt$HH'HHt"HH[]H"H5:H811HH5A"HtHHx Ht!H H["H5H81DUHSHHx-HH5"_Ht6HHt"HH[]H"H5H81YH"H5pH81fKH;H"L(HH="OH|$hHt$hL1D$`LHHH="HT$`HHI|$`|D1LuIcH$H;,"Hl@H|$hHt$hL1D$`HHH="HT$`HLHI1|$`t@H|$hHt$hL1\HH1HAŅHD]H%I-DH|$hHt$h1LHHA1fDH|$hHt$hL1LHHHHHc0H{HȃHEHL$HIHL$fH|$hHt$hL1D$`DHH9H=A"HT$`HHI|$`=H|$hHt$h1LM1IAI?1H=E1ILH IDHcl$fDH߽AAT$DD$H|$ DH|$CI u;HHcH9H|$E1DHY"HIVf.H9"HHH)"HH"HH"HoH"H_H"HH˝"HH"HH]"HHHH :H5H=H""H5H81詸H "H5ӺH81葸H"H5H81yfHtHHHH4@Hc7H@SHtHHHHt[H"H5mH81H"1H81AUATUSHHdH%(HD$1jH5"H߉i/H IHcH>f.Lȹ1HIH0L-"\H5#UHHfLHeHHL$dH3 %(H[]A\A]II\IH5MIEHHuH'"H54H81讶fDL1NL-"I4H59"H9HL$$1H IHH4$H HHLID$L-ƙ"HH HID$fHL$$tIHH4$H HHL@L-"Y@I|IHtgL-š"2DHH(IHt>H HHsL蘷1H.IHH"1H81LL-"IH~HcljH9HvDH{HcljH9HsDH~HcljH9ukHvtfHǨu!HcظL$$HHH@裻HҚ"H5ȱH81YdL1ARH"H5ĶH81*H"H5tH81fAWAVAUATUSHHH5̺"dH%(HD$1HǨHEHA*HA1HIRdH5\LcHHH$EEupHLD  @+LOH4$H)I9HcH9HHL$dH3 %(H[]A\A]A^A_1LILE¾?LLtx@HLMQH AH5YH=&yH聲|LtHŘ"H5H81Lff.AWAVAUATUSHHǸ"H H"H"HH"H"HH"Hj"HaH"HK"H*Hø"H,"H H"H "H Hm"H"H HN"HϷ"HN H'"H"H H"H"H H"Hr"H Hҷ"H"H5=1L-Í"L%H8DH"HƘ"H5HHHH2"H;H5HH1lH;HH5SQH;HH5Į6H;H5HI H;EMeIA$<[t&HT-LLLHHH;HHuH`"H5`HL%Z"H5#"I$H6 E1HH5"H I<$E1H5ĵ"H I<$E1uH5"H] I<$E1OI<$HH5я3I<$1HH5I$H;H5|H-"H5"HEH AHǹH}H5CH}H4H5FH}1HH5dI$H;H5 |He"L5"HH2I H5q"H I>A8I>HH5I>1HH5ڎI>1HIH5HUH;H5wڽH "H;HH5ZHuHUH;H5G袽H "H;H!H5*H=HUH;H5jH S"H;HH5HHUH;H52L="H;HH5ȫIHUH;H5H ۔"H;HYH5HHUH;H5¼H "H;HH5sH]HUH;H5c芼H #"H;H)H5FH%HUH;H59RH "H;HH5HHUH;H5H "H;HH5HHUH;H5H "H;HaH5ƪH}HUH;H5誻H "H;HH5HEHUH;H5rH ;"H;H1H5oH HUH;H5b:H "H;HH5EHHUH;H56H S"H;HH5HHUH;H5 ʺH "H;HiH5HeHUH;H5蒺H C"H;HH5ǩH-HUH;H5ZH ӌ"H;H9H5HHUH;H5"L-;"H;HH5aIEHUH;H5SH "H;HH56HHUH;H5#豹H 2"H;HpH5HLIH;H5zH 3"H;HH5ߨHIH;H5ΨCL5"H;H=H5II$H;H5 H-"H;HH5xHEI}HH5eɬI}1HH5UI}1HsH5?I}1HH5~I}HH5ǻI}H5 H谻H5Y"HI?E1+H}1HH5HuHH"%H"H="H0 HS"H=w"H0I7H=`"ۧH" H=H"H0H " H=-"H0襧Iu H="萧HI"H="H0uH"H="H0ZH"!H=ǭ"H0?I6#H="+H"%H="H0Hq"'H=}"H0HF")H=b"H0ڦHӊ"+H=G"H0迦HȌ"-H=,"H0褦H="/H="H0艦Hڍ"1H="H0nH"3H=۬"H0SH"5H="H08HY"7H="H0H"9H="H0H"=H=o"H0HH=\"[]A\A]A^A_MD H=GWH "] H=7HHm"H=DHHM"H=$HH5"HE @H=HH" H=ݢHH"5H=HHݪ"H=_HHŪ"I$@ H=7H":H=_H" H=4Hx"H= H`"H=HH"^H=H0"'H=wH"H=WH"H=N7H" H="HЩ"KH=H"f.SHH[f.ATIUHHSH0dH%(H$(1HH~H<$չH5貳HEHt5LHH˫HsH$(dH3%(u9H0[]A\HLHm"H8tH"H5H817BH#" H=H H<$)H;H1H;A1H ĥHzfH(H5aw"dH%(HD$1lHtbHHT$Ht$H|$t$1HT$耢L$H|$ 9uHD$H|$4 HL$dH3 %(uH(H"H5*H81(Hl"H5 H81ff.AVAUIATUSH0H $H|$HT$dH%(HD$(1:H2H $LA HD$IHiAHM HxHcAH9HXLHHE1HT$$MHHRD>ZY1ɋt$HT$ H9\$49u`H|$ H\$(dH3%(u^H0[]A\A]A^HD$LaHiH YHHXAA\ΟH"H5ޣH81覟豽AVAUIATUSH H $H|$HT$dH%(HD$1HH $LA HD$IHiAHM HxHcAH9HXLHE1HHT$MHHRDZYt$HH\$dH3%(uBH []A\A]A^HD$LaHiH yHHXAA|螞虼fU HSHԡHH t"HHHHԼHH[]f.PXH5*HH"H81fH(H5s"dH%(HD$1輲Ht5HHT$ Ht$t$ H|$HL$dH3 %(u H(}踻SHHH|$Ht$H5.s"HFHt6Ht$H tHVHvHHH[HHfDSH5r"HHt111H9H[ff.@AUATUSHHuHtvHƒtiudHH9tNH5`r"HxIHtML-с"HIu-HtMH51r"HIHt!HL)HH[]A\A]HCH܃"H5HH81;HI]H5HH"HH81ATIUSHHH|$Ht$oH5q"H谰Ht]LH`Ht$H t3H~HcωH9u2HvHH֭HH[]A\f.HH莛IfSH"H5H^"HH;KH}"H;H5HH"H(HY"H5HHϨH;H`H5QH;HH53ٞH;HH5\{込H;HH5K}裼H;1HgH5K}苼H;HH5UpH;HFH5躭H;1H>H5BH;1HvH5*H;HuH5xtH;[H^H5z]f.AWIAVAUATU1SHHLsHZHH9~\H}"HL "HH  LHff.HH5a`"HtHHx HRfHH51`"HtHHxHǰ"fUHH5`"SH跞Ht$HHǡHHt"HH[]HGq"H5HH81覉qHH5_"\HtHHxHwfATIUSHt=HHHx\H5[_"LHt0HHӓtH[]A\HHHp"H5H81Hgl"H5FH81ވff.HH5^"茝Ht3HH8H@Hx HDHHHff.@USHHH-k"HuHtH5W^"HHt1H[]HHm觸H5kHHn"HH81 Ho"H5H81USHHH-4k"HusHtAHH5]"菜HHtTHxAEH LHH[]HHmH5BkHHPn"HH81cHn"H5H81Kff.HHt+螎Ht(HHwj"H(]"H8Ȟ@#Hrj"1H81ff.SHk"H5Hm"HH;軖H,j"H;H5HHn"H蘖Hi"H5zHH?H;H0H5gdH;HH5hIH;1HmH501H;HH5H;1HH5H;1HRH5mH;HH5˧H;1HH5賧H;HH5蘧H;1H,H5y耧H;HH5jeH;1HH5lMH;HH5D2H;HH52H;HHH5rH;HH5rH;1HH5eɦH;1HH5ze豦H;HkeH5keH;1HH5=e胦H;1H'H5kH;H|H5PH;[HH5r4@駆USHHXH5Lh"HT$H $dH%(HD$H1辘HH|$HXHPHH\$SHHXH4$H t\HVHvHHt$H u_HHHHIH߉该u+1HL$HdH3 %(unHX[]fHHu@HVHcH9uHvHf"1H81 HHj"H5bH81KfDAT1UHSHH`HT$1dH%(HD$X1He"H01脙HOH5f"H[IHHHl$ HHH|$ݔHt$H HVHvH茮Lԍ1pHc7HHpH tHpLHHT$裤HA8EtYHt$ uGHH9THHHL$XdH3 %(uXH`[]A\HH\HCHse"1H81臁H 2H5H=-hsHh"H5%aH81諗Hc"H5H813He"SHH0ɊHuH[Hd"H5H81SH3Ht+He"HH茆1H5`HH蘝H[Hd"1H81蠀ATUSjHc1HHTIeHcLHTP[L]A\@AUATUSHHZdH%(HD$1 u(S1HL$dH3 %(utH[]A\A]AыIc1HHTI̘HcվLHT跘H=a"HT$L#D$tC1C|襝DG@SHtgH?t'~tt0=u2H[pu$H[bfH[駢H[WHc"H5H81Hb"H5H81~AUH_ATUSH(dH%(HD$1Ld$HL$M評H|$?1HH"HHt2HŒHzHT$dH3%(H([]A\A]11ҾHǀE1~H|$t L菡IHuc"L1H(HHu11ҾH~1HPHHZ11ҾHS~~H|$t LIHc"1HLHH܋HH,`"H5%H81}薛fDUSHH|$H|$H|$蝍H|$H u_HH5΄HHt`HȗHab"11HEHHHtHH[]fDHH`"1H81|B}8諄H5HH`"H81|USHHH-da"Hu3HtH5`"HOHt1H[]HHmH5(`HH6c"HH81I|Hc"H5 \H81葒U11SHHH(_"H01Hu3H-`"HHu蕡HtKH5)`"H豐HtH[]H^^"H5H81{HFc"H5[H81HHmH5Z_HHhb"HH81{{ff.USHHH-$`"HuHtAH5_"HHHtTHxA H wHH[]HHm聫H5^HHa"HH81zHlb"H5ZH81+ff.U11SHHH]"H01~HuYH-Y_"HHu%HtqH5^"HAHHtBHxA H 詧HH[]H\"H5H81'zHa"H5YH81oHHm胪H5]HH`"HH81yDUH5tSHH]"H8H^"H-`"H5PHHHE蜉Hu]"H}H5*HH`"HxH9^"H}HqH5LHH;H5XH;1HH5Y+H;HO"H6HtfHt$H t4H~HcωH9u3HvHHx趪t$HD$H[HHxH]"1H81wH_"H54~H81wUH5N"SHdH%(HD$1芌HH蹬HHHt^HHހtG1HsHyH$HxH0xHH荅HHT$dH3%(u:H[]HkH\"1H81(wH^"H5a}H81wff.UH5M"SHdH%(HD$1誋H1HHHcH1HH@H uQHHH$~[HH4$ tBHCHSH)H9jH蚉HHL$dH3 %(unH[]HCf.HHSHd\"1H81 vH]"H5Y|H81vH |yH5U|H=8V@USHHdXH(dH%(HD$1Hl$H蟌u#HL$dH3 %(HH([]DHH|$H u2HTHHt,H{ Hk uHf.HD$H t;HPHT$HPHt$1HHuHsZ"1H81tHHHD$SH5K"菉HHH@Hc0~Hx[鮆fDHX"H8t 11[xHqZ" H=InH H H=zרH;A1H zHCnH["H5[zH81 tf.UHH5J"SH跈HtNHHǔHḢtuH[]H1[]HY"1H81sH["H5yH81|sff.PX1HHX"H81WsATUHSHH躟HI迖H5I"HHHtHLHJ{t H[]A\HZ"H57yH81rqUHH5I"SH藇Ht$HH觓HH茙t"HH[]H'Z"H5xH81rHH5AI"}HY"H5xH816rSH5H"Ht+HHHt;H|HcH9u#H߉[鯣HxY"H5(xH81qHqZf.SHHtHHtH"H[[w&fDHU"SH5xH8{HV"HS"H5wHHHRHV"H;H5xHHX"H/HX"H5aHH~H;H'H5QH;1HH5QH;1HH5Q˒H;HQH5QH;1HH5WQ蝒H;1HH5c腒H;HH5_jH;H H5'^OH;H@H5]4H;1HXH5vH;[H|H5vg}UH5G"SHdH%(HD$1蚄H1HH褛HcH1豁HH@H uQHHH$r~[HH4$ tBHCHSH)H9jH节HHL$dH3 %(unH[]HCf.HHSHQ"1H81oHV"H5uH81nH vH5uH=(O@AWH5E"AVAUATUSH(dH%(H$1lHHIؓAƅHcUzHD$E1Ld$TfDLIHEHchHc0HxHl-AHLH1lH|$H诛A9tqLwHHHLtyLtpt襗HmIhDHQ"H8t8辆HD$H$dH3 %(HD$H([]A\A]A^A_H\S" H=4gH ۡH H=At¡H;A1H tH.gϘgHO"1H81lHT"H5sH81lf.ATIHTOUSH dH%(HD$1HL$萃H\$HtlH蔡H輈HHH5C"L1HHH1HHtp茕HT$dH3%(usH []A\H踝HH59C"LрHtH11HPzHH蕂HHD$XHD$yHN"1H81kĉH=S"H5rH81kff.AVAUATIHQUSH dH%(HD$1H\$HLL$IH>HFHI}H|$H5XB"LIHH\$H+ ttH{HcljH9H|$H[@tirHHAAjLL/ZYHL$dH3 %(LH []A\A]A^ÐH|$HH@u腁땐H5q"H,$Hq"Ht1HN"H8*mHHH1HD$H=8qHHEq"HQ"H5pH81iiHL"1H81ifDATIH5@"UHSHH@dH%(HD$81m~HD$H1HL$LD$ LHIbu&HL$8dH3 %(HoH@[]A\fDH|$pHHHT$ Ht6H޿1gH58p"IHtHLA11H赜H5p"HHYM"H8kHHD$ H=dHD$zLL$HHo"fH|$uH|$0HD$0zHD$0H tJHPHT$(HPHt$(H|$HT$HS HHK"1H81)hfHHHD$(fDH=oǕHHo"HlO"H5nH81gff.ATUH1SHHH dH%(HD$1蔘HI脘HH脓1HjHH$YHHD$GHD$Ht4HLHL$dH3 %(utH []A\fDH $H5En"H1}HD$HuH5m"HtHPK"H8iHD$념H=mHHm"讄ff.SHӌHtHH="H[+lHDI"1H81XfATUSHH5r=" {Ht>L%J"HHI4$‹Ht;H5F="HzHt[HH]A\iHM"H5lH81eHI,$VH5IHHL"HH81eHSHx 1҃HTHH@tF@|H@ HVHI"H9t*1HuHtAHuHK"HH¸t1HDHI"H@HI"H@HG"H{HiI"HkH J"H[HH5;"\yHt3HOH?H9wHDHfDHHHK"H5'kH81"H T$IƅAAH|$ dH5]A"H|$(ÊLH5oIH1xLH5cHxHLH5c x|$HL$8dH3 %(HuqH@[]A\A]A^ÐHH~IHt$ H=|?"HAFIŋD$IHt$(H;H=:@"HI$}xH?"H5cH81ZSHSHtHH1"H[`H?"1H81HZAWHbAVAUATUSHdH%(HD$x1H\$0Hl$(HHD$xIHPHD$xPHD$xPLd$xATLl$xAUHD$xPHD$xP1LL$xpH@HD$H|$(t H|HD$E1H|$0t H|IH|$81tzH|$@HD$ՅH|$HHD$HtmH1H|$PE1H|$X H|$`E1HNH|$hE1H\H|$p1HjPALIAUATAVH|$(HL$8HT$0GiH5>"H HH1HjH <"HJ0"HH8o^HT$8H5FHHxuHT$@H5aHduHT$HH5 aHPuHHL$xdH3 %(HĈ[]A\A]A^A_L{HdŅLLh{HdAƅLM{H5`HH|:"H81Wf@tJ_H|$hE1AH@tJ^H|$pA1H@t^nAUnkfD{nAGnuH<"1H81KWff.H>"SH5_HH+;"H8gH<<"HU:"H5_HHHfHA<"H;H5=HHZH;H5IdH5%^"HH;E11ɺ袁H5]"HH;E11ɺ老H5]"HttH;E11ɺbH;HH56GxH;1[HH57.xfDH=6HHu]"TH=^迃HH=]"l H=\^蟃HH%]".iwhUH5D."SHdH%(HD$1JjH1HHjHcH1agHH@H uQHHH$j~[HH4$ tBHCHSH)H9jH:hHHL$dH3 %(unH[]HCf.HHSHL;"1H81THI<"H5]H81TH aWH5]H=4er@\AWAVAUATE1USHH:HHdH%(HD$81HL$D$HHD$8P1LL$8LD$0 kH|$@ZYHHD$(H9H聇H|$IHOHt$%TIŋD$H|$ ,eH5e,"HHD$xhIHp览HoHH(HT$ELILLqLAaEuH~Ht HiHH5SMHpSHh|H5+\HHoH58"LWAHEHL$8dH3 %(HH[]A\A]A^A_fH5[HahHD$(HH|$E1HE1@tYAeDsiASL`H5<8"L褁H8"1H811R4"H5VH81Mff.fSH5D&"_bHVHxHzteH{lt?H{^H{LtgH{>[fDH=T"Htl[yfDH=T"HuH=WVz[HHxT"yH=QT"HuH=BVzHH1T"H= V ozHHT"tH= T"HdH=U ?zHHS"DH=S"H4H=dUzHHS"H3"H5UH81LATUSHH dH%(HD$1HB HL$Hu.HD$1bu!HT$dH3%(HH []A\ÐH|$Ld$YHHD$$11LHHuHtEHD$HHC YHߺH5wT8hH5rEH$hn11ҾHMKLHWZHuH:YH|$ SH-"HC H5rTH81Jhff.AUATUSHHHHƒtwurHH9t\H58#"HP_IHt[L-!-"HIupHtnH5 #"H!_Ht/HDiHt:HC LSRHH[]A\A]H PH1"H5SH81JH~0"1H81IHI]fzH5-HH0"HH81IPXH5YSHH<1"H81IfHH5!"\^Ht HxHiDHH5Q!",^HtH@HxH{HH5!"]HtH@HxH{H0"H5RH81Hff.HH5 "]HtH@H8HifPX1HH1/"H81HUSHHHtH5t "HHI]HtHH]t"HH[]H/"H5QH81CH~ff.SHzHtHH "H[MFfDHH5A "\Ht44HWHt:8tHfDHxHsnHHHPbE0HXHD$-McLKAtot?H\$dH3%(Hu'H([]A\A]A^A_H%"H5FH81=\,ff.SH[HtHHt"H[{CfDATHUSHdH%(HD$1qHH$HHvCHHKHtuH<$AHtfIH"H"HH8BLH5FFHHZH5;7HYHHL$dH3 %(uH[]A\,ZAVAUATU1SHH#H dH%(HD$1HLL$LD$SH<$iH|$IhH|$IHunH5'"H?QIHnqHXHHt_LAHLLcH߅t?~eHT$dH3%(uZH []A\A]A^Ð@t 5C냐 SvJHh""1H81;He#"H5DH81;Yff.@AUH?"ATUSH8dH%(HD$(1HL$D$HHD$(P1LL$(LD$ SRH|$(ZYHQIH|$ 1HH|$nH|$Ht$Hm;IċD$LLHlHHHIH"HH"H8@HT$H5CHHWH5 "L jHHT$(dH3%(uDH8[]A\A]D@t"A=fDeIkQ_XzHH53 "LiH "1H81(:HPH|$^AVH5DAUATUS1H@dH%(HD$81HD$0HL$D$ PHD$0P1LL$0LD$(PZYH|$fH|$I$fH|$0IHH|$ mH|$(HHHt$ 9IċD$ AHLLLiaHHH"H"H8>HT$ H55BHHUH5*3HUH$GH5"LEhHHL$8dH3 %(u>H@[]A\A]A^D@t?fDE1COVHFH5p"LgH"1H81e8HF|$ 4]@HH5" MHtH@H8H'YH"H5AH818ff.@AUH@ATU1SH(dH%(HD$1HLL$LD$NH|$HH|$H<$HQ"H39]HQH<$H55"PLIHdE1H|$plHSHHLLHlXL\EHt`HT$dH3%(H([]A\A]D@tj%>H|$H<$;H5?LH<$HD$!fHxjt2H|$H.jI1fDM@11ɾLc@HEHDLDH"1H81?6H<$HfHH5HH"H816 TH"H5>H815E1ATH"H5x?L%5"USH8I$EH"Hi"H5?HHHEH"H;H5?HH9H;HpH5?d9H;HEH5!#I9H;H5H.9H5<"HH;E11ɺ `H5<"HH;E1_H;H5BH;HH5eVH;HH5@VH;HH5>VH;1HH51oVH;HPH5>TVH;1HH5>$VH;HH5> VH;HH5u>UH;1HH5h>UH;HGH5U>UH;1HH5K>UH;HH5;>UH;HyH50>mUH;1HH5&>UUH;HH5-:UH;HkH5=UH;1H3H5=UH;HH5=TH;H=H56FH;HWH5o TH;HH5TH;1HH5QTH;HBH5BEH;1HH5/ZTI$H;H59=GBH-`"H;H5.=HHEXH}H5?H}HzH5SH}1HH5SH}HH5!.EH}1HH5SH}1HH5<SI$H;H5<AH-"H5KHHE/?H}HH5SSH}1HVH5g:SH}1HH5U!SH}1HtH5&<SH;H5<WH;H5IWH; H5F|WH;H59hWH;!H5TWH;AH5@WH;H5;,WH;H5;WH;H5;WH;[]H5;A\V@H=G9]HH7" H=+*]HH7"ATH5#"USDH8HIZt{]HHC Hx[UH=I3LHH/HC Hx ,UH=lI3LHH/HC Hx(TH=4Ii3LHH[/HC Hx0TH=;I:3LHH,/HC Hx8TH=p;H 3HHH.H[]A\HN"H5H81 EH6"H5;H81.DATUSHHH5"ECHHHtkH[HLe HI|$8Ht_Ht1HH[]A\@HD$aHt$ID$8HE Hx8HuHh"1H81-@H@ Hx8GHE H@8HH[]A\H\"H5 H81Dff.ATUSHHH5"eBHHHtkH{GLe HI|$0Ht_Ht1HH[]A\@HD$`Ht$ID$0HE Hx0HuH"1H81-@H@ Hx0FHE H@0HH[]A\H|"H5 H81;Cff.ATUSHHH5"AHHHtkHFLe HI|$(Ht5^Ht1HH[]A\@HD$_Ht$ID$(HE Hx(HuH"1H81<,@H@ Hx(EHE H@(HH[]A\H"H5 H81[Bff.ATUSHHH5"@HHHtkHELe HI|$ HtU]Ht1HH[]A\@HD$_Ht$ID$ HE Hx HuH"1H81\+@H@ Hx EHE H@ HH[]A\H"H5 H81{Aff.ATUSHHH5:"?HHHtkHDLe HI|$Htu\Ht1HH[]A\@HD$&^Ht$ID$HE HxHuH"1H81|*@H@ Hx+DHE H@HH[]A\H"H5 H81@ff.SHHt$H5["H$>H8HTtH|$lHE H[]A\3ATIUSHH5!Ht)HLH5H%H HEH[]A\ATIUSHH5!VHt)HLH5zHL%H4HEH[]A\ATIUSHH5K!Ht)HLH5?H$Ht4HEH[]A\CSHH H0dH%(HD$(1HL$HHD$(P1LL$(LD$ Ht$XZHtHXHt$HtHHt$HtHHt$ HtH/HT$(dH3%(HuH0[a%UHH5S8H=HtJHE1E11H11HHH! H5HH#HH[]Hg!H5H81fDSHc HtHH!H[[ H!1H81HHt+NHt(HHW!H!H8H @H!1H81.ff.USHHH-!Hu+HtH5g!HHt1H[]HHmW6H5HH!HH81HB!H52H81USHHH-!Hu#+Ht(H5!H?HtQHBHt1H[]HHm5H5 HH!HH81,Hu!1H81H!H5H81ATH!H54UH-!SHH}H !H}H5L%!HI$H!H5THHYH;H5(H~&H5g "H>H;E11ɺ\/H5= "HH;E11ɺ:/H5 "HZH;E11ɺ/H5 "HH;E11ɺ.H5 "HH;E11ɺ.H;HuH5&%H;H H5%H;HH5%H;H4H5h%H;HH5M%H;H~H52%I$H}H5H!H5PHHH;H&H5$H;HH5$H;H`H5$H;HH5Y$H;1H}H5$H;1HH5bi$H;1HH5Q$H;1[H]H5 A\5$DH=@/HH "H=/HH " H=/HH "H=/HH "H=o/HH} "DH1HHHЃfUHSHHH|$Ht$H1H|$H7 u!HHY HH[]HGHcЉH9uH1 HH[]Hff.@HH|$Ht$IH|$H7 u!HH HD$HHGHcЉH9uH HD$HHff.@PX1HH!H81GHH|$Ht$H|$_H|$H u!H#tHf.HDUHSHt>1HcHHxH tHx$tHH[]@"fHH|$Ht$H|$H|$H u!Hx!tHfHDHH|$Ht$H|$?H|$H u!HHtHHeDSHHHt$tZH|$H|$H|$H u!HV,t+H[Hf.[fUHSHt>Y1Hc-HHxH tHx!tHH[]@fH!SH5 H8H!H!H5 HHH H#!H;H5oHH=H;HH5 "H;H3H5 H;HH5 H;HH5{ H;H"H5m H;HH5_ H;H H5H H;1[H#H59 gATH5!US\H8H&+*HHC Hx "H={IwLHHiHC Hx!H=IHLHH:HC Hx !H=vILHH HC Hx(~!H=OHHHHH[]A\H-!H5fH81H!H5 H81t@ATUSHHH5!%HHHtkH;Le HI|$(Ht,Ht1HH[]A\@HD$.Ht$ID$(HE Hx(HuHH!1H81@H@ Hx(HE H@(HH[]A\HHL-!HLHLjHH?H HHuHH[]A\A]ÐHHfSHHdH%(HD$1HH%H<$t~HH<$HGH uMH5TH€t:HH=`1HL$dH3 %(u0H[fDHGf@ ff.@UHSHH\$Ht$HHHH|$H ucH:HHtlHH!HHHuDHtBLQ!H11ҾHH[]ÐHf.HH7!1H81PXH5HHH Ht*H_H[]H9!HH54H81XHA!H5H81UHSHH|$Ht$HHHtHHt*HH[]H!HH5H81H!H5)H81HH5!HtH_t"HHZ!H5H81T@SH3HtHHd!H[K&fDH!SH5HHk!H8[H|!H!H5HHH8H!H;H5wHH;HH5H;1HxH5H;1HH5H;H5H5tHƒ8H>< FHxH5H;1HjH5^H;1HH51FH;1H:H5.H;HH5H;HH5UH;HH5H;HH5H;HH5H;HxH5H;1HH5rtH;1HH5\H;H5KH;H5BH; H59H;H5/H;H5'H;H5"H;H5H;[H5kH&Ht6HHf!H8 fDHA!H8fH!H8H!H8H!H8H!H8AWIAVAUATU1SHHLsHZHH9~\Hռ!HL bHH MLHff.USHH|$H|$H|$MH|$H uoHH5~/HHtpHx111HHHHt0H !HH١!H8aH[]f.HH!1H81w8KH5!HH!H81PUSHHH-!HuHtH5W!HHt1H[]HHmH5ȪHH֭!HH81Hr!H5H81USHHH-!HuSHtAHH5Ԡ!oHHtTHxAzH {HH[]HHmH5"HH0!HH81CH̭!H5H81+ff.SH! H=H H H=H;A}1H HY@H٠! H=H XH H=?H;A}1H ]HLAUATUSHHt}HAąxNHc6IEt+1@HH3LHA9uHL[]A\A]DH!!H8H[]A\A]H!AH8uHΟ! H=H MH H=4H;A~1H RHAY@Hi! H=AH H H=FH;A~1H H;ATIH=USHcHHdH%(HD$1HT$D$BHHtHxH uH;1HH5M&H;HH5= H;[HH5-f.DfDHwSH H !H|$H3dH%(HD$1HD$HH|$@tW@uaHHHtt@ t t:t5HD$HL$dH3 %(H [fDHtDH|$HD$fDH}@RUAD 1IH=LmH=zLmH@HHEHH%H)HHH9tHH$H9ut H)HLL|$IH}AE1LLH5V}!HA+HEHLHDLH2EfDH}蒮kDHEHpH tHpH}j@DAHUH t,HzHcωH9utHzHRHC@HHz΃HzHcωH9u9HzHLoIbHۈ!H5H81:EH!DH5 H81Hs!H5H81bMPX1HHA!H81נSHCHtHH{!H[kfDPXH5YHH!H81肠fHH5a{!HHHtHHtH1[]f.H[]ff.@UHSHHHH!H0Hu H1[]HH5y!HHt4H5x!HʲHtHHzuH[]5H^!H5H81轝ff.fAUH5x!ATUSHfHtZHHXILcLHHIA9u+LLLHgHHD[]A\A]LJH!1H81UHHSHt;&H5w!H赱Ht)HHHH[]˳fATIH5w!USHfHt?LAHu%萳HftH[]A\f.苣bHۃ!H5H81:f.ATIH5w!USHHt?LAHu%HFtH[]A\f. H[!H5H81躛f.ATIH5v!USHfHt?LAHu%萲HvtH[]A\f.苢bHۂ!H5H81:f.UHHSHt;FH5u!HկHt.HH#tHH[]DH[!H5H81躚f.UHHSHt;ơH5}u!HUHt.HHtHH[]DkbHہ!H5H81:f.AVIHAUATUSH dH%(HD$1HLL$LD$H|$E1H|$A@H<$A@ut述(HHDDH t{HHnt!L6H\$dH3%(utH []A\A]A^fE1E1H<$@tk;AfDH|$E1@tGHզH^}!1H81ff.fAVIHAUATUSH dH%(HD$1HLL$LD$蔯H|$E1H|$A@衟H<$A@utoHHDDHff.AUATUSHHH>H5j!HͤIHlIHLHtN؃H H{HLHzj![]A\A]?HuHt)HuH-v!H8[8@Hs!H8@Hs!H8@Hq!H8yHs!H8iHYt!H8YL蹜HBs!1H81֎H_v!H5H81辎ff.HHt+讕Ht(HHp!Hxi!H8H<@Hr!1H81^ff.HHtHHu!H5[H81!AUATUSHHHH5h!HIŢHIdHHHp!LLHHHtBum؃tsHt} H{HHHrh![]A\A]7HuHtHuH%t!H8Hq!H8@Hq!H8@Ho!H8@Hq!H8Hir!H8qHɚHRq!1H81Hot!H5H81Όff.AWAVAUIH oATUSH8dH%(HD$(1HL$HHD$(P1LL$(LD$ dH|$^AX@荓H|$E1H|$AHE1E1贿HHHLDE1jMH蜥ZYHtlHf!HL賑HT$(dH3%(ueH8[]A\A]A^A_@ۢi@軥H|$ E1IHm补I`HaHo!1H81~艩fATUHHS]IվHt(LHH2tHHH!f![]A\3HHto!1H81ATUHHSIeHt(LHHҟtHHHe![]A\xH{Ho!1H81蘊USHHH{H5de!HH9HtHHHH[]HDfDUSHHH+H5e!HHHtHH虰HH[]HDVfDAUATUSHHHףH5d!HI蕞HI4HHHil!LLHH`tCun؃ttHt~ H{HHHCd![]A\A]HuHtHuHo!H8Hm!H8@Hm!H8@Hk!H8@Hm!H8H9n!H8pH虖H"m!1H81趈H?p!H5jH81螈ff.AVAUATUHSHHvHIkH5Tc!HI)H IȻHHHj!LLLHLat<uo؃tuHt H{[HHb!]A\A]A^雍HuHtHuHn!H8HQl!H8@HYl!H8@HIj!H8@H)l!H8Hl!H8oH)Hk!1H81FHn!H5H81.ff.AUATUSHHHH5a!HIśHIdHHHi!LLHHPtCun؃ttHt~ H{HHHsa![]A\A]8HuHtHuH%m!H8Hj!H8@Hj!H8@Hh!H8@Hj!H8Hik!H8pHɓHRj!1H81Hom!H5H81΅ff.AUATUSHHH觟H5`!HIeHIHHH9h!LLHH萎tCun؃ttHt~ H{HHH`![]A\A]؊HuHtHuHk!H8Hi!H8@Hi!H8@Hg!H8@Hii!H8H j!H8pHiHh!1H81膄Hl!H5:H81nff.AVAUATUHSHHFHI;H5$_!HIH I蘷HHHf!LLLHLQt<uo؃tuHt H{[HH^!]A\A]A^kHuHtHuH]j!H8H!h!H8@H)h!H8@Hf!H8@Hg!H8Hh!H8oHHg!1H81Hj!H5ʘH81ff.AVAUATUHSHH֜HI˜H5]!HI艗H I(HHH]e!LLLHLѶt<uo؃tuHt H{[HH7]!]A\A]A^HuHtHuHh!H8Hf!H8@Hf!H8@Hd!H8@Hf!H8H)g!H8oH艏Hf!1H81要H/i!H5ZH81莁ff.AVAUATUHSHHfHI[H5D\!HIH I踴HHHc!LLLHLAt<uo؃tuHt H{[HH[!]A\A]A^鋆HuHtHuH}g!H8HAe!H8@HIe!H8@H9c!H8@He!H8He!H8oHHd!1H816Hg!H5H81ff.AUATUSHHHH5Z!HI赔HITHHHb!1LLHL.tAul؃trHt| H{HHHaZ![]A\A]&fDHuHtHuHf!H8Hc!H8@Hc!H8@Ha!H8@Hc!H8HYd!H8rH蹌HBc!1H81~H_f!H5H81~ff.AVAUATUSHH虘H5Y!HIWH=IIHHH0Ha!LLHLL辔tq؃2Hp H{LHX!贃Iĉ؃#HI uzH-c!H8rHuGHHH{LHX!QIHHu%HHd!H8H{LHRX!IH{HH!HH81mWH>!H5<H81UWDATUHSHHdH%(HD$1H?;!D$H8Hf=!H04|HHtqH>!H8MsAH oIH'I\$ bHHHJLH?HT$HH=}HD$dH3%(uoH[]A\fL%aH HHcljH9tVHHHWHƉi~&uAE%E}A|$=^u,HcHDH[]A\A]A^A_Du ^Ku`H1!H5dH81JH~KHvZEEA|$_1nHiS!HtLH=j1vnHl$LH5a`H޺HH1aH[]A\A]A^A_fDH=cwHHR!H=S!Ht3vH=R!HuH=c wHHR!H=]c wHHR!IEpSHH|cH dH%(HD$1HL$LD$HD$U`H|$1HtH51S!|1HHt$Hߺ2H\$dH3%(uH ['g11AWAAVAUIATUHSHH.!H$H0qxH5+!H]H9H5:`HHW^H/uLpLwH1AHAH&.!H0pHE DHx}tcuHHŋH<$clt[H߉D$ nHHL$ H$IDH.!H5iH81GEA~ZFfEA~\&fHxnDEH$IHQ.!H5*iH81G1H=gkH[]A\A]A^A_fDHHǨt wN lK^ff.@SHH5)!H[H`SHH5)!H1H`[f.SHH5,!H[Hn`SHsH5,!H1HB`[jf.ATUSHH5!![L%J.!HHI4$kHt5H5*!HZHtKHHoN[]A\HEHI,$mvH5)HH,!HH81EHX-!H5+H81EUSHHH5M!!HdZHHIb1ҾHHWWHt HH[]H!,!1H81UEDUHSH_HRHt/!H1HVHHH[H !]JH+!H5^H81Df.AWAVAUIATUSH(dH%(HD$1Ld$HHD$TLL$MH^E1}[H|$HQH<$@tTKH|$LcuTL1hVHD$udHD$HL$dH3 %(H([]A\A]A^A_+[H|$LctLVH|$lVH|$LFtH5&!LXH5][LHzYHRpL`LrHuL-gHt$H HHH_H߉AxDIcDL>MH}#1E1,ZH|$HH5M!E1vHAf;sEHxEjfDH~HcljH9CHvCDE:A|$UEA|$WH|$IcUHD$HHуIHfDHK!H1H=b"fLt$Ld$LH,$H5YWMMHHH1XDHhcA|$\ HyJ!Htd1H=beLd$H,$LH5 Y.WMHHH1FX H=^oHHJ! H=+[nHHI!|H'!H5[H81AHH=I!Ht3mH=I!HuH=[Z nHHI!H=LZ lnHHrI!^@Qf1dEf1uDATUSHH5! UL%:(!HHI4$eHt5H5$!HTHtKHHK[]A\HEHI,$]pH5#HH&!HH81?HH'!H5$H81?AUATUSH(dH%(HD$1@PHH@Hƒ/&H5! TH5XHHTH_H5HrHa%!HH0CH5XHTHD$Ht)HJPHHkH$!H0CH5XHZTHD$Ht&H5F!HIL11H9rH5M8HE1THD$Ht HjIH5`,HSHD$HtKH_IMt;Ht6LH=uLHqHT@H5KXHSIHD$HIAHHƒgHL9L?I$Ld$L c>I|$J !HLHHD$bH|$ pHT$H5RHWHH5HcH!H8VH5RSHwPHHeH5UHTPHD$Ht6H|$MHt$H 6HHHKeH5RHPHH5RHOH5H5pRHOHH5-UHOHD$Ht(HH~5tVH!H(HfDH5H!m@HLHj:;H=$T]*H5)HbH!H8NL%Q! H=)3I $mI $!H=[mI<$1A@H QH3d@H5HaH!H8L%! H=2I $GmI $H=[-mI<$1A<H 3QH29dG@H5)Hq;Hr!H8L%A! H=2I $lI $H=ZZlI<$1A8H PH 2c@HH5HgH!H8 L%! H=1I $4lI $H=RlI<$1A'H PH1&cH5YHWM@HVHcH9Hv3N@C>i@8I|$ fHGHqH=2dHH?!HD$,HGH1ɺ HlH'L%q! H=I0I $jI $ H=BXjI<$1A#H NH;0aF@H ! H=/H jH $H=XojH;AG1H {NH/|aSHk!H5PH815HS!H5OH815H;!H5WH81j5Hr5H!H5OH81J5H!H5qOH8125fUSHHWH(dH%(HD$1HL$LD$KH|$H-!HuZHH|$ `HT$H5CLHQHT$H5LHQ1H5*LHnQH|$H5MHPQ11WIHHL$dH3 %(H([]fH5=!Ht$H-!11H}KHHD$+H=+MaHHH5:!HyH}E1[H5:!H3H}E1[H5v:!H H}E1[H5H:!H H}E1q[H5:!Ha H}E1K[H59!H H}E1%[H59!H H}E1ZH59!H H}E1ZH5b9!HI H}E1ZH549!H H}E1ZH59!H H}E1gZH58!Hw H}E1AZH58!H1 H}E1ZH5|8!H H}E1YH5N8!H H}E1YH5 8!H_ H}E1YH57!H H}E1YH57!H H}E1]YH57!H H}E17YH5h7!HG H}E1YH5:7!H H}E1XH5 7!HH}E1H !XH}HuHH5^ILAH}HWIH5LI@H}HH5 mOH}HH5!IQOH}1HH58OH}HH5HOH}1HoH5HOH}H5HSH}H5HSH}H5HtSH}H5H_SH}H5HJSH}H5O5SH}H5O SH}H5H SH}HH5H?NH}HH5H#NH}1HVH5H NH}HH5HMH}1HH5HMH}HH5HMH}1HH5zHMH}HH5rHMZ7H=JI fDH;HEH4XLHXL9uL|VH}LH5&HQII<$H5H;H!H5(HH8H=BqEH;E11ɺHUH=CBPEH;E11ɺHUH=C/EH;E1HUH=%B EH;E1HƺsUH;HAH5lG=H;HH5 BLH;1HH5D*LH;1H^H5'GLH;1HH5CKH;1HH5GKH;HsH5CKH;HHH5F9H;HH5TCKH;HH5Ff9H;1H H5F^KH;1HH5'#FKH;1H H5F.KH;1H2H5FKH;1HʻH5AJH;1HbH59JH;1HH5DJH;1HH52FJH;1HH5"FJH;H_H5FJH;1HǷH5FkJH;1H_H5BSJH;1HH5E;JI<$H5ENI<$H5ENI<$H5ENI<$ H5ENI<$H5ENI<$H5EmNI<$H5MKXNI<$H5`KCNI<$AH5E.NI<$H5ENI<$H5ENI<$H5EMI<$H5EMI<$H5KMI<$H5EHMI<$H5JMI<$H5EMI<$ H5ElMI<$H5EWMI<$H5{EBMI<$H5E-MI<$H5EMI<$H5xEMI<$H5oELI<$ H5fELI<$H5_ELI<$H5XELI<$H5PELI<$H5MELI<$H5IEpLI<$@H5EE[LI<$H5IFLH=.!H>aRHZ/!H[]A\A]A^A_H=@'SH(/!H=D SHHM.! H==RHH5.!- H=?RHH.!H=K<RHH-! H=?RHH-!SH=<_RHH-! H=<?RHH-!H=<RHH-!H=C?QHH-!;H=i=QHHm-!H=9=QHHU-!H==QHH=-!i H==QHH%-!#H=m>_QHH -!H=??QHH,! H=>QHH,!Q H==PHH,! H==PHH,!H==PHH,!H=\=PHH},!9 H==PHHe,!H=_PHHM,!H=P?PHH5,!gUSHH|$@uHt  tXH|$4H|$H7 t.HGHcЉH9H9Ht|H[]HHkNHXHPH@{?SÅxYRH55)=HHt5HPHuHrHHPKEY wasn't initialized!THIS IS NOT A RSA!qdmp1dmq1iqmpincomplete RSAprivateprivate key needed11ossl_pkey_rsa.cnewlen <= len02Neither PUB key nor PRIV keyNot a RSA key!RSAErrorgenerateinitializepublic?private?to_textexportto_pemto_sto_derpublic_encryptpublic_decryptprivate_encryptprivate_decryptq=dmp1=dmq1=iqmp=paramsPKCS1_PADDINGSSLV23_PADDINGNO_PADDINGPKCS1_OAEP_PADDINGOpenSSL requires passwords to be at least four characters longossl_rsa_to_derCipher not inititalized!iv length too shortunable to set GCM tagkey length too shortossl_cipher.cout_len <= RSTRING_LEN(str)data must not be emptyout_len < RSTRING_LEN(str)13Cipher already inititalized!01CipherErrorinitialize_copyciphersresetpkcs5_keyivgenfinalauth_data=auth_tag=auth_tagauthenticated?key_len=key_leniv=iv_lenblock_sizepadding=OpenSSL/Cipherauthentication tag not supported by this cipherdata too big to make output buffer: %ld bytessalt must be an 8-octet stringwrong argument (%li )! (Expected kind of %li )couldn't set additional authenticated dataarguments for %li #encrypt and %li #decrypt were deprecated; use %li #pkcs5_keyivgen to derive key and IVunsupported cipher algorithm (%s)retrieving the authentication tag failedossl_cipher_updateossl_cipher_finalOpenSSL for RubySSL Session wasn't initialized.SSL Session already initializedBIO_s_mem()SSL_SESSION_print()i2d_SSL_SESSIONossl_ssl_session.cno session availableunknown typeto_iSessionErrortime=OpenSSL/SSL/Sessionossl_ssl_session_to_der21Cert ID wasn't initialized!Response wasn't initialized!ossl_ocsp.cRequest wasn't initialized!22OCSPOCSPErrorRequestadd_noncecheck_nonceadd_certidcreatestatus_stringbasicBasicResponsecopy_nonceadd_statusCertificateIdcmp_issuerserialRESPONSE_STATUS_INTERNALERRORREVOKED_STATUS_NOSTATUSRESPONSE_STATUS_SIGREQUIREDRESPONSE_STATUS_SUCCESSFULRESPONSE_STATUS_TRYLATERREVOKED_STATUS_CACOMPROMISEREVOKED_STATUS_KEYCOMPROMISEREVOKED_STATUS_REMOVEFROMCRLREVOKED_STATUS_SUPERSEDEDRESPONSE_STATUS_UNAUTHORIZEDREVOKED_STATUS_UNSPECIFIEDNOCERTSNOINTERNNOSIGSNOCHAINNOVERIFYNOEXPLICITNOCASIGNNODELEGATEDNOCHECKSTRUSTOTHERNOTIMEV_CERTSTATUS_GOODV_CERTSTATUS_REVOKEDV_CERTSTATUS_UNKNOWNV_RESPID_NAMEV_RESPID_KEYOpenSSL/OCSP/CERTIDOpenSSL/OCSP/BASICRESPOpenSSL/OCSP/RESPONSEOpenSSL/OCSP/REQUESTcannot load DER encoded responsecannot load DER encoded requestRESPONSE_STATUS_MALFORMEDREQUESTREVOKED_STATUS_AFFILIATIONCHANGEDREVOKED_STATUS_CERTIFICATEHOLDREVOKED_STATUS_CESSATIONOFOPERATIONossl_ocspreq_to_derossl_ocspres_to_derATTR wasn't initialized!ossl_x509attr.cdecodecould not get ASN1_TYPEoid=value=AttributeErrorAttributeoidOpenSSL/X509/ATTRIBUTEcouldn't set SEQUENCE for attribute value.ossl_x509attr_get_value@groupEC_POINT is not initializedEC_GROUP is not initializedEC_POINT_point2bnEC_POINT_set_to_infinityEC_POINT_invertEC_POINT_make_affineEC_POINT_is_on_curveEC_POINT_is_at_infinityEC_POINT_dupEC_POINT already initializedunknown type for 2nd argwrong number of argumentsMultiplication failedossl_pkey_ec.cArgument2 must be an arrayBIO_new(BIO_s_mem())EC_GROUP_set_seedEC_GROUP_set_generatorEC_GROUP_newEC_GROUP_dupunknown curve name (%s)unable to create curve (%s)EC_GROUP_new_by_GF*THIS IS NOT A EC PKEY!EC_KEY is not initializedEC_KEY_printoutlen=%dECDSA_verifyPrivate EC key needed!ECDSA_signECDH_compute_keyEC_KEY_set_public_keyEC_KEY_set_private_key@keyEC_KEY_set_groupEC_KEY already initializedunknown curve name (%s) unable to create curve (%s) EVP_PKEY_assign_EC_KEYgroup=EC_get_builtin_curvescloneEC_GROUP_get_cofactorEC_GROUP_get_orderEC_KEY_check_keyEC_KEY_generate_keyNot a EC key!ECErrorECGroupPointGFpGF2mGFp_simpleGFp_montGFp_nistGF2m_simpleuncompressedhybridNAMED_CURVEprivate_key=public_key=private_key?public_key?dh_compute_keydsa_sign_asn1dsa_verify_asn1eql?curve_nameasn1_flagasn1_flag=point_conversion_formpoint_conversion_form=seed=degreeinfinity?on_curve?make_affine!invert!set_to_infinity!to_bnOpenSSL/ec_pointOpenSSL/ec_groupmissing ossl_ec_point structuremissing ossl_ec_group structurewrong argument type: must be OpenSSL::PKey::EC::Point or OpenSSL::Pkey::EC::Group1st argument must be OpenSSL::PKey::EC::Groupmissing group (internal error)EC_GROUP is already initializedunknown symbol, must be :GFp_simple, :GFp_mont, :GFp_nist or :GF2m_simpleunknown symbol, must be :GFp or :GF2munknown argument, must be :GFp or :GF2mcan't export - no public key setcan't export - EC_KEY_check_key failedEC_KEY_get0_get0_group (has public_key but no group???form must be :compressed, :uncompressed, or :hybridunsupported point conversion form: %d, this module should be updatedDigest initialization failed.EVP_MD_CTX_create() failedDigest::ClassDigestError<<finishdigest_lengthblock_lengthOpenSSL/DigestDigest CTX wasn't initialized!Unsupported digest algorithm (%s).V_OKV_ERR_UNABLE_TO_GET_CRLV_ERR_CERT_SIGNATURE_FAILUREV_ERR_CRL_SIGNATURE_FAILUREV_ERR_CERT_NOT_YET_VALIDV_ERR_CERT_HAS_EXPIREDV_ERR_CRL_NOT_YET_VALIDV_ERR_CRL_HAS_EXPIREDV_ERR_OUT_OF_MEMV_ERR_CERT_CHAIN_TOO_LONGV_ERR_CERT_REVOKEDV_ERR_INVALID_CAV_ERR_PATH_LENGTH_EXCEEDEDV_ERR_INVALID_PURPOSEV_ERR_CERT_UNTRUSTEDV_ERR_CERT_REJECTEDV_ERR_SUBJECT_ISSUER_MISMATCHV_ERR_AKID_SKID_MISMATCHV_ERR_KEYUSAGE_NO_CERTSIGNV_FLAG_CRL_CHECKV_FLAG_CRL_CHECK_ALLPURPOSE_SSL_CLIENTPURPOSE_SSL_SERVERPURPOSE_NS_SSL_SERVERPURPOSE_SMIME_SIGNPURPOSE_SMIME_ENCRYPTPURPOSE_CRL_SIGNPURPOSE_ANYPURPOSE_OCSP_HELPERTRUST_COMPATTRUST_SSL_CLIENTTRUST_SSL_SERVERTRUST_EMAILTRUST_OBJECT_SIGNTRUST_OCSP_SIGNTRUST_OCSP_REQUESTDEFAULT_CERT_AREADEFAULT_CERT_DIRDEFAULT_CERT_FILEDEFAULT_CERT_DIR_ENVDEFAULT_CERT_FILE_ENVDEFAULT_PRIVATE_DIRV_ERR_UNABLE_TO_GET_ISSUER_CERTV_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATUREV_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATUREV_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEYV_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELDV_ERR_ERROR_IN_CERT_NOT_AFTER_FIELDV_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELDV_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELDV_ERR_DEPTH_ZERO_SELF_SIGNED_CERTV_ERR_SELF_SIGNED_CERT_IN_CHAINV_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLYV_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATUREV_ERR_AKID_ISSUER_SERIAL_MISMATCHV_ERR_APPLICATION_VERIFICATION@timeSTORE wasn't initialized!STORE_CTX is out of scope!@verify_callback@certOSSL_DEBUG: certs in chain < 0???ossl_x509store.c [%s:%d] @error@error_string@chainSTORE_CTX wasn't initialized!StoreErrorStoreverify_callback=flags=purpose=trust=add_pathadd_fileset_default_pathsadd_certadd_crlStoreContexterror=error_depthcurrent_certcurrent_crlOpenSSL/X509/STORE_CTXOpenSSL/X509/STOREReq wasn't initialized!ossl_x509req.ccount < 0???version must be >= 0!RequestErrorsubjectsubject=signature_algorithmattributesattributes=add_attributeOpenSSL/X509/REQossl_x509req_to_derinvalid tag classeach%2d%2d%2d%2d%2d%2dZbad UTCTIME format: "%s"%4d%2d%2d%2d%2d%2dZbad GENERALIZEDTIME formatunknown time formatutcASN1_INTEGER is NULL!invalid OBJECT IDinvalid tag defaulttag number not specifiedossl_asn1.cmust specify tag numberinvalid tagging methodvalue is too shortinvalid non-infinite taginvalid constructed encodingnil expectedunsupported ASN.1 typeASN1_TYPE alloc failurecannot alloc bufferreallen <= lenEOCUNIVERSALCONTEXT_SPECIFICAPPLICATIONPRIVATEIMPLICIT@value@tag@tagging@tag_class@infinite_length@unused_bitsASN1ASN1Errortraversedecode_allUNIVERSAL_TAG_NAMEASN1DataPrimitiveinfinite_length=ConstructiveBooleanIntegerEnumeratedBitStringOctetStringUTF8StringNumericStringPrintableStringT61StringVideotexStringIA5StringGraphicStringISO64StringGeneralStringUniversalStringBMPStringNullObjectIdUTCTimeGeneralizedTimeSequenceSetEndOfContentregistersnlnshort_namelong_nameBOOLEANINTEGERBIT_STRINGOCTET_STRINGNULLOBJECTOBJECT_DESCRIPTOREXTERNALREALENUMERATEDEMBEDDED_PDVUTF8STRINGRELATIVE_OID[UNIVERSAL 14][UNIVERSAL 15]SEQUENCESETNUMERICSTRINGPRINTABLESTRINGT61STRINGVIDEOTEXSTRINGIA5STRINGUTCTIMEGENERALIZEDTIMEGRAPHICSTRINGISO64STRINGGENERALSTRINGUNIVERSALSTRINGCHARACTER_STRINGBMPSTRINGtag number for Universal too largeuniversal tag for %li not foundInfinite length for primitive valueType mismatch. Bytes read: %ld Bytes available: %ldType mismatch. Total bytes read: %ld Bytes available: %ld Offset: %ldConstructive value must be an ArrayConstructive shall only be used with infinite lengthCan't convert nil into IntegerCan't convert nil into Boolean:99 9H:88H:H:H:88H:H:H:H:H:H:H:H:H:H:H:H:77{HEDFdFFhashhash_oldcountryNameserialNumberdnQualifierDCdomainComponentemailAddressRFC2253ONELINEMULTILINEOpenSSL/X509/NAMEossl_x509name_to_derwrong config formaterror in line %dConfigErrorConfigDEFAULT_CONFIG_FILEPKCS12 wasn't initialized.ossl_pkcs12.cPKCS12_parse@certificate@ca_certs46Unknown PBE algorithm %sPKCS12ErrorOpenSSL/PKCS12ossl_pkcs12_to_derPKCS7 wasn't initialized.ossl_pkcs7.c@dataNegative number of recipient!Negative number of signers!signedencryptedenvelopedsignedAndEnvelopedCould not parse the PKCS7PKCS7ri wasn't initialized.PKCS7si wasn't initialized.Could not add recipient.Could not add signer.must specify a booleanunknown type "%s"32PKCS7Errorread_smimewrite_smimetype=detached=detacheddetached?cipher=add_signersignersadd_recipientrecipientsadd_certificatecertificates=certificatescrls=crlsadd_dataSignerInfoSignersigned_timeRecipientInfoenc_keyTEXTDETACHEDBINARYNOATTRNOSMIMECAPOpenSSL/PKCS7/RECIP_INFOOpenSSL/PKCS7/SIGNER_INFOOpenSSL/PKCS7OpenSSL::PKCS7#get_signer_info == NULL!signeddatasignedAndEnvelopedenvelopedencrypteddigestossl_pkcs7_to_derTHIS IS NOT A DSA!pub_keypriv_keyincomplete DSAPrivate DSA key needed!ossl_pkey_dsa.cDSA PUBLIC KEYNot a DSA key!DSAErrorsyssignsysverifypub_key=priv_key=ossl_dsa_to_derPKCS5_PBKDF2_HMAC_SHA1PKCS5_PBKDF2_HMACPKCS5PKCS5Errorpbkdf2_hmacpbkdf2_hmac_sha1EXT wasn't initialized!ossl_x509ext.cmalloc errorcritical=critical,unknown OID `%s'@config%s = %s@crl@subject_request@subject_certificate@issuer_certificate04CTX wasn't allocated!ExtensionErrorExtensionFactoryissuer_certificate=subject_certificate=subject_request=crl=config=create_extExtensioncritical?OpenSSL/X509/EXTENSIONOpenSSL/X509/EXTENSION/Factoryossl_x509ext_to_derRandomRandomErrorrandom_addload_random_filewrite_random_filerandom_bytespseudo_bytesegdegd_bytesstatus?THIS IS NOT A DH!incomplete DHossl_pkey_dh.cFailed to generate keyNot a DH key!DHErrorparams_ok?generate_key!ossl_dh_to_derENGINE wasn't initialized.NUMERICNO_INPUTopenssl#<%li id="%s" name="%s">no such digest `%s'no such cipher `%s'EngineErrorloadcleanupenginesby_idcipherload_private_keyload_public_keyset_defaultctrl_cmdcmdsMETHOD_RSAMETHOD_DSAMETHOD_DHMETHOD_RANDMETHOD_CIPHERSMETHOD_DIGESTSMETHOD_ALLMETHOD_NONEOpenSSL/Engineno such builtin loader for `%s'#<%li : subject=%+li , issuer=%+li , serial=%+li , not_before=%+li , not_after=%+li >CERT wasn't initialized!ossl_x509cert.cCheck private key:%sCertificateErrorCertificateserial=not_beforenot_before=not_afternot_after=OpenSSL/X509ossl_x509_to_dercall(null)error on stack: %sossl.cOSSL_DEBUG: IS NOW ON! OSSL_DEBUG: IS NOW OFF! empty sk!items in sk < -1???Turning on FIPS mode failedTurning off FIPS mode failedOpenSSL1.1.0OpenSSL 1.0.2u 20 Dec 2019OPENSSL_VERSIONOPENSSL_LIBRARY_VERSIONOPENSSL_VERSION_NUMBEROPENSSL_FIPSfips_mode=OpenSSLErrorossl_store_ex_verify_cb_idxX509_STORE_get_ex_new_indexdebugdebug=errorspassword must be longer than 4 bytespassword must be shorter then %d bytesStoreContext initialization failureexception in verify_callback is ignoredobject in array not of class ##type##ossl_store_ctx_ex_verify_cb_idxX509_STORE_CTX_get_ex_new_indexCRYPTO_num_locks() is too big: %d0123456789abcdefREV wasn't initialized!ossl_x509revoked.cRevokedErrorRevokedOpenSSL/X509/REVBN wasn't initialized!bignum too longinvalid radix %dDon't know how to coerceCannot init BN_CTXBNErrornum_bytesnum_bits+-/%mod_addmod_submod_mulmod_sqr**mod_expgcducmp===zero?one?odd?pseudo_randpseudo_rand_rangegenerate_primeprime?set_bit!clear_bit!bit_set?mask_bits!>>lshift!rshift!to_intmod_inverseprime_fasttest?OpenSSL/BNCannot convert into OpenSSL::BNusing default DH parameters.@context@renegotiation_cb@ioclosed?@sync_close@_protocolsarg must be Time or nilcache_numconnect_goodconnect_renegotiateaccept_goodaccept_renegotiatecache_hitscb_hitscache_missescache_fulltimeouts@tmp_dh@session_remove_cb@session_new_cb@session_get_cb@x509@npn_select_cbSSL_CTX is not initialized.ossl_ssl.cSSL_CTX_set_cipher_listunknown SSL method `%s'.SSL_CTX_set_ssl_version@%sSSL_session_reused@hostnameSSL_newSSL_set_tlsext_host_name@client_cert_cb@tmp_dh_callbackSSL_set_sessionwrite would blockread would blockwait_writablewait_readableSSL_writesyswriteSSL_acceptSSL_connectSSL_CTX_new11:SSL_readsysread@cert_store@extra_chain_certSSL_CTX_use_certificateSSL_CTX_use_PrivateKeySSL_CTX_check_private_key@client_caSSL_CTX_add_client_CA@ca_file@ca_pathcan't set verify locations@verify_mode@timeout@verify_depth@options@npn_protocolsSSL NPN select callback added@session_id_context@servername_cb@callback_stateossl_ssl_ex_vcb_idxossl_ssl_ex_store_possl_ssl_ex_ptr_idxSSLErrorWaitReadableSSLErrorWaitWritableSSLContextssl_timeoutssl_timeout=ssl_version=ciphers=setupSESSION_CACHE_OFFSESSION_CACHE_CLIENTSESSION_CACHE_SERVERSESSION_CACHE_BOTHSESSION_CACHE_NO_AUTO_CLEARSESSION_CACHE_NO_INTERNALsession_addsession_removesession_cache_modesession_cache_mode=session_cache_sizesession_cache_size=session_cache_statsflush_sessionsMETHODSSSLSocketto_ioconnect_nonblockaccept_nonblocksysread_nonblocksyswrite_nonblocksysclosepeer_certpeer_cert_chainpendingsession_reused?session=verify_resultnpn_protocolVERIFY_NONEVERIFY_PEERVERIFY_FAIL_IF_NO_PEER_CERTVERIFY_CLIENT_ONCEOP_MICROSOFT_SESS_ID_BUGOP_NETSCAPE_CHALLENGE_BUGOP_MICROSOFT_BIG_SSLV3_BUFFEROP_MSIE_SSLV2_RSA_PADDINGOP_SSLEAY_080_CLIENT_DH_BUGOP_TLS_D5_BUGOP_TLS_BLOCK_PADDING_BUGOP_ALLOP_SINGLE_ECDH_USEOP_SINGLE_DH_USEOP_EPHEMERAL_RSAOP_CIPHER_SERVER_PREFERENCEOP_TLS_ROLLBACK_BUGOP_NO_SSLv2OP_NO_SSLv3OP_NO_TLSv1OP_NO_TLSv1_1OP_NO_TLSv1_2OP_NO_TICKETOP_NO_COMPRESSIONOP_PKCS1_CHECK_1OP_PKCS1_CHECK_2OP_NETSCAPE_CA_DN_BUGexceptionOpenSSL/SSLOpenSSL/SSL/CTXTLSv1_serverTLSv1_clientTLSv1_2_serverTLSv1_2_clientTLSv1_1_serverTLSv1_1_clientSSLv2_serverSSLv2_clientSSLv3_serverSSLv3_clientSSLv23SSLv23_serverSSLv23_clientSSL session is not started yet.SSL object could not be retrievedSelected protocol name must have length 1..255SSL SESSION get callback enteredSSL SESSION remove callback enteredSSL SESSION new callback enteredAdvertised protocol must have length 1..255%s SYSCALL returned=%d errno=%d state=%s%s returned=%d errno=%d state=%sSSL NPN advertise callback addedSSL_CTX_set_session_id_contextSSL SESSION get callback addedSSL SESSION new callback addedSSL SESSION remove callback addedSSL TLSEXT servername callback addedservername_cb must return an OpenSSL::SSL::SSLContext object or nilossl_ssl_ex_client_cert_cb_idxossl_ssl_ex_tmp_dh_callback_idxSESSION_CACHE_NO_INTERNAL_LOOKUPSESSION_CACHE_NO_INTERNAL_STOREOP_NETSCAPE_REUSE_CIPHER_CHANGE_BUGOP_SSLREF2_REUSE_CERT_TYPE_BUGOP_DONT_INSERT_EMPTY_FRAGMENTSOP_NO_SESSION_RESUMPTION_ON_RENEGOTIATIONOP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG ;` |40td@D$ $H| T!! "Xd#$4$t$$$84%Xt%x%%4&(*`+t-4/T1@1\d2|$6D6d6T7T8$ D9P T:| d< >0!?L!4?h!d@!@!@!A!4A"tA0"AL"Ah"DB"$C"tC"E0#ED#EX#G#G#H#tI $JL$J|$M$$M$N$O%$P4%DQd%dQx%Q%Q%TR%R%dS &4TP&dTd&$U&V&V&V&W'W,'4Z|'D['T['t\'\'t]((^T(t_(`(ta(a)a0)tb\)c)$c)Tc)d)Dd *dd(*dH*ed*De*te*f*f*f+g@+h|+i+dk,lh,q,w,w-x4-{h-{-|-D~ .~(.$\.x.$.$.T..8/Dt//Ć/(0dd0t0d0H1d111T1d1t2T$2p22T2ĝ@3l3D3d3ԡ34$4ĤP4T4ħ4Ԩ4ԩ$5īp545 6$<6dX6t6Գ6T647Ե87Td777ķ7t7ĸ808dL8h88$8Ի8ļ9D9X99d9994 :(:D:`::$::(;D;d;x;4;T;4;<44<`<t<<<T =(=D=`=t==d >L>h>$>>>T>t?@?4l???d?@$,@X@l@D@@4@A4AHAAAABDBBBBBdChCCtCC$DDD`DTDDDD$ETP> Pt?\P@PAPAPC QD8QtEdQTFQTHQ4IRDJDRTKxRtKRKRKR4LRTMHSMtSDNSNSO,TPXT$QTTQTQTQTRUR0USPUS|UDTUTUTWUdWUX$VTZ\VZxVZV4[V[V\W\@W^|W^WT_W`X`,XaXXbXbXcXdXeYf@YgdYhY4hYhYiZTi0ZiLZihZkZkZlZn[oH[q[s[t\4u\uL\vd\v|\Tw\w\$x\x]{4]T}`]}]]]^D,^D^ą^ԅ^^(_<___D<``t``đ(aDa`aD|aaĒaaTab8btbbDbdbbĕcDDchcc$cccd0d`dddĚd$dte eleԝeeԟftHf4fff$gTgԭgg htdhThh4h,iķtitiiDj@jDxjdjjj$jdk4kttkkTklt l>ԉT??,T@X@TABC8DdEGċHI TK\L4MdMЌN PtPP̍DQQ$R`dTU܎$WXXZt[؏\d_T`b̐dcc8i\ipijj̑$kk$DlDldDmmВDnnTolo$p̓4qq4qHrt$sts̔tyyz<{p{4|Е|}8t~h0dXD4ܗD$t0TlD$ܙTxtdĔ4P$lԕ4ț@$T4hTԜħ<$4ԝԺzRx $06FJ w?:*3$"D 6,\PFHA  ABA @FAA G0E  DABE U  DABA @FAA G0E  DABE U  DABA @HFAA G0E  DABE U  DABA @XFAA G0E  DABE U  DABA @FAA G0E  DABE U  DABA @FAA G0E  DABE U  DABA @$FAA G0E  DABE U  DABA @hTFAA G0E  DABE U  DABA 8FED F(DP (A ABBK 0tFAA D0  AABH D FEG A(DPXN`LXAPP (A ABBF (dEAD N AAE \"E\HpBED C(D0K (D ABBJ L(D ABB(OEAG } AAD 4$EDD v FAF ^ AAA \PAAKxT?Hb F I A t?Hb F I A ?Hb F I A ?Hb F I A ?Hb F I A ?Hb F I A 8?Hb F I A X4?Hb F I A @xTBEB A(D0D 0A(A BBBF @ FEH D(A0DP! 0A(A BBBK (\ EFN@| AAI 8, FEA F(DP (A ABBH 8hFEA F(DP (A ABBH 8(FED F(DP (A ABBK  _Hf A PEJ A E<P(dEAG0~ AAC 0\FAD D0  AABG ((EAG0 AAB (EHD0 AAH @FBB A(K0DP 0A(A BBBF l`zFBB B(K0C8GaLMDSPC\ 8A0A(B BBBK &E` EZ8 %FBA A(G0 (D ABBG D !JL` AAF| WEt A  AAK :He H  <:He H  `:He H  NH@ A 0$ FAD D@  AABI X d AHl H Xt ZBBB E(K0A8GUPDy 8A0A(B BBBH  "  "0 "FAA G  AABA (, #vFGA v ABI (X #vFGA v ABI 8 ($ZFBG A(N@ (A ABBH ( L%EAG m DAE , %|MKC J ABA  &L]< p( (P l(EAD0 AAA (| 0)EAD0 AAA ( )EAD0 AAB , *FAA Y ABD  + +AAK4 +iH V A P <,QHq G G E (p |,ZFAD k DBL ,ER Q f B , <-FAD F DBI  --8-FBA A(G0T (A DBBA @|.[L<\/p/ 0/ FAA N@A  AABE 0 L0pFIB B(A0A8D 8A0A(B BBBA (2 EAN0 AAC H3 (\3EHD0 AAA 4 (4EAN@@ AAJ (D5EHD0 AAA L86FIB A(A0} (D BBBF G (A EBBA (D6 EAN0 AAC (p7EAN@@ AAJ p8>HY E 8.A(8EAN M DAA (9EAN M DAA (t9AAFDx9*E[ E ,`9FAA O ADF :*E[ E 0:AAK4:WHv J I A t:2H] H ::He H  :*E[ E (<:FKD } ABA ,h4;FAA O ADF ;*E[ E (;FDJ s KEI 8<gFBB B(A0K8FpYxFRxAp 8A0A(B BBBC TL?gFBB B(A0K8FpYxFRxAp 8A0A(B BBBC \d@FEB B(D0D8D 8A0A(B BBBB JYA(hD0MHA FIJ (JEHD0 AAF 0K6FHA D0  AABH ,MFDA _ ABC 48DNEHD E DAE K ADE 8pNFLG A(G` (A ABBK 0P8E[ E 0TPFDA D0L  AABA PRHg I (QEAG z AAA DxQEdXR%E[lR%E[8RwFIA A(G0 (D ABBA 8S5FIA A(G0q (D ABBA 8T?FIA A(G0{ (D ABBA 8PU?FIA A(G0{ (D ABBA 8VIFHA  FBB A CBA 8WAFHA y FBH A CBA <X IBE A(A0{ (D BBBA @DYFBL A(D0IP/ 0A(A BBBG \t]FBB H(K0A8G~ 8A0A(B BBBC /BPD4a*E]Ha*E]( \aEHD  AAE (LaBAJ { ABE xtbpb lbED f DE H(cVFBE E(A0D8N@ 8D0A(B BBBA ,Ax}AAK}OHb H 40<}yEHD n DDI D FAA Dh}FGD M ABG N ABG N ABA $~HS E K E K E (~vEAN m DAJ ~OHb H  bHi O I A (@lEHD B DAA (lEHD B DAA tOEe H AAKyEq N E{ A  yEq N $ Ey J F A (H tEDD y DAA ,t FAA P ABE < FIA A(D0 (A ABBK  ( EAN0 AAF ($!XuEKD k DAA P!=E[ E l!ЌAAK !ԌjEG D DD ! AHl H !T:He H !x:He H 8"FBA A(G0 (D ABBA (<"`EAD0R AAB 0h"TFAA N@  AABG ("EDD | DAA "dUE="L#x #t4Ej4#EV0P#FDA F0\  DABD 0#HFDA F0\  DABD #AAK(#bFGD t ABH @$<FBB A(A0NP* 0A(A BBBA (D$șRFAD q ABA p$?Ha G I A $2H] H $@2H] H $d2H] H $:He H (%VEAN h DAG \,%AFIA A(D0l (D ABBF Q (A ABBI D (G DBBE 0%ЛFAK DP  AABE (%PEw A (4>HLFAH rDB8`>lFBA A(D@x (A ABBD > ,>Ef E I G D L D E 8>LjFIA A(DPi (A ABBD (?EAD0} AAG (H?$EAG m AAA (t?xEEG G AAA (? EAG P DAA (?EEG j DAA (?D :EHD  AAJ $@X 8@T EG [ AH (\@ EHD0 AAA (@ EHD0 AAA (@ EAN@| AAF @l Eh K R F 4AEKD m FAH D CAA  8A0A(B BBBA 0B4FKA D@  AABD LBFBB K(A0DPXN`LXAPc 0A(A BBBB 08CFKF G`_  AABG 0lC"FAF J@  AABG C8E[ E ,CBAA D GBE C-HdDtVD`dHq G G E FVA  FII ,NhD[FHA  ABA @NEFAA G0E  DABE U  DABA @8O4FFAA G0E  DABE U  DABA @|OFFAA G0E  DABE U  DABA @OlGFAA G0E  DABE U  DABA @PHFAA G0E  DABE U  DABA HPH%ED  AD (lPIEDD@ AAD 0P4KsFAA D0  AABE DPLFEG A(DPXN`LXAPh (A ABBI (QHNEAD N AAE $@QN2EYC LCAHhQNBED C(D0K (D ABBJ L(D ABB(Q(O_EAG  AAF 4Q\PEDD o FAE ^ AAA RPAAK4RP?Hb F I A TRP?Hb F I A tRQ?Hb F I A R(Q?Hb F I A RHQ?Hb F I A <RhQBEA A(G (A ABBG @SRgFEH D(A0DP 0A(A BBBA (XS$UoEGD m AAA ShUiEe O SUEJ A SLVE}DSXCFHA A(D@HDPFHA@I (D ABBC L$TYSFHB A(D0D@HDPFHA@I 0D(A BBBD tTZL[TH[ (TD[EHD0 AAA 4T8\EHD E DAE K ADE  U\ 0 U\FAA J0  AABD 8TU] FLA F(G` (A ABBK 8U_&FBK A(DPK (A ABBG 4UaEHD y DAI P DAE V(bAAK V,b7Hc G EKD _ DAA |n0*HX E nDbHx H (nEAG H AAA n1En@ o<$o8 8o4?AD0 AG ,\oPxEC JIG F oAAFo*E[ E oAAKoAHs A oMH` H T D p -H\ D (8p4oEHD { DAA dpx2H] H p>Hf K 4paEKD m CAK D FAA 4pEDJ X CAA ~ FAA 8 q`FIA A(D0X (F ABBA (HqĴ^EGD t DAG (tqvFKA p ABK (qLvFKA p ABK (qvFKA p ABK (qvEGD u DAF ($rHvEGD u DAF @PrCFLB A(A0DP 0A(A BBBJ @rCFLB A(A0DP 0A(A BBBJ (rEKF@ AAF (sEKF0l AAD 00s,FAA N0  AABF (dsEDG M GAK ,s7FHA j KBJ 8srFBA A(J0 (K ABBL 8srFBA A(J0 (K ABBL 8t4RHg I Ttx/HN A 8ptRFBA A(J0 (K ABBL dtGFBB L(A0A8DpYxFWxBpHxKNxApk 8A0A(B BBBE (uhFAG r ABE (@uhFAG r ABE (lu JEAJ k CAF (uDJEAJ k CAF 8uhRFBA A(J0 (K ABBM <vbFBB A(D0 (K BBBH 8@vRFBA A(J0 (K ABBM 8|vRFBA A(J0 (K ABBM <vbFBB A(D0 (K BBBH <v4bFBB A(D0 (K BBBH <8wdbFBB A(D0 (K BBBH 8xwRFBA A(J0 (K ABBK <wFBB A(A0^ (D EGDJ 8wRFBA A(J0 (K ABBM 80x,BFBA A(J0u (K ABBG 8lx@BFBA A(J0u (K ABBG ,xTFAA ^ ABA xE^ X x0 y,DEm F H0y\H0T D LyHH] K WlyFH] K U4y0ECG S AAD V LCK yAE` K LyFH] K U<z(EAD v DAK k DAH WDA(DzAID0 DAA pzHH] K WzLHH] K WXz|FBA A(D0k (D ABBF D (G DBBE V(D ABB< {{EAD x DAI I DAB UDAL{ NHe K U8l{P FBA A(G0 (F ABBB ({$cENG m CAE {h({t EAN0 AAH (|XMEAN f DAA (@||MEAN f DAA ,l|FHA  ABF |pLHu C G|LHu C G0|FCA G0  AABK (}EDQ@z AAA 0<}EFG w LCH dFA0p}\EFG L LCK dFA0}EFG L LCK dFA,}TFHA  ABA H~]FHL E(A0A8J` 8A0A(B BBBD LT~FIA A(D0\ (D ABBF D (A ABBE (~x|MDD aCB$~SECG xFA<~FAA G0m  CABF N FAB@8FEE A(D0F@ 0A(A BBBK 0|PIFAD G0  AABC 0lyFAD G0  AABA 8FBA D(D@ (A ABBE 8 |FHA A(D@ (A ABBH H\`FLI I(H0D8D 8A0A(B BBBA $~Hv B F J U A 8Ѐ<BBA A(G@~ (A ABBG 8 FAD _ ABC W ABA 0HFDA G0  AABE |@#AAMT#AAM`h`BEE E(A0A8FP 8A0A(B BBBF  8A0A(B BBBG dEN0o AA < HPBEB E(A0D8DP 8A0A(B BBBG `)ESt&E\Ԃ)ES&E\, FAA O AJE (<0[EAQ k DAA (hdfEDD m GHE HpBBB E(A0C8D` 8A0A(B BBBH  ,FAA O AJE 88Dn FBA A(DP (A ABBB (tx nEAN@ AAJ 8 FFA  ABC x ABE L܄ @FBB B(A0A8D@ 8A0A(B BBBD (,EAD0\ AAH XtQH C A t(fEAG0L AAA GNUp08%#KMQ#Q :QPQR@jX {X [@Qb`^cP^c@sWl7mmnPopp 8s0Qs@kspvVvTOyPez}0`adHWxgaɂ5E^N;egggggggggg hh"h/h>hMhVhZhhhxhhhhhhhhhhh"·<ۇ. $1>KR`YEhEuEEEEEE&F P1 G8%8%o`8n SF P%0Q h" ooooG%1111111122 202@2P2`2p22222222233 303@3P3`3p33333333344 404@4P4`4p44444444455 505@5P5`5p55555555566 606@6P6`6p66666666677 707@7P7`7p77777777788 808@8P8`8p88888888899 909@9P9`9p999999999:: :0:@:P:`:p:::::::::;; ;0;@;P;`;p;;;;;;;;;<< <0<@<P<`<p<<<<<<<<<== =0=@=P=`=p=========>> >0>@>P>`>p>>>>>>>>>?? ?0?@?P?`?p?????????@@ @0@@@P@`@p@@@@@@@@@AA A0A@APA`ApAAAAAAAAABB B0B@BPB`BpBBBBBBBBBCC C0C@CPC`CpCCCCCCCCCDD D0D@DPD`DpDDDDDDDDDEE E0E@EPE`EpEEEEEEEEEFF F0F@FPF`FpFFFFFFFFFGG G0G@GPG`GpGGGGGGGGGHH H0H@HPH`HpHHHHHHHHHII I0I@IPI`IpIIIIIIIIIJJ J0J@JPJ`JpJJJJJJJJJKK K0K@KPK`KpKKKKKKKKKLL L0L@LPL`LpLLLLLLLLLMM M0M@MPM`MpMMMMMMMMMNN N0N@NPN`NpNNNNNNNNNOO O0O@OPO`OpOOOOOOOOOPP P0P@PPP`PpPPPPPPPPPQQ Q0Q@QPQ`QpQQQQQQQQQRR R0R@RPR`RpRRRRRRRRRSS S0S@SPS`SpSSSSSSSSSTT T0T@TPT`TpTTTTTTTTTUU U0U@UPU`UpUUUUUUUUUVV V0V@VPV`VpVVVVVVVVVWW W0W@WPW`WpWWWWWWWWWXX X0X@XPX`XpXXXXXXXXXYY Y0Y@YPY`YpYYYYYYYYYZZ Z0Z@ZPZ`ZpZZZZZZZZZ[[ [0[@[P[`[p[[[[[[[[[\\ \0\@\P\`\p\\\\\\\\\]] ]0]@]P]`]p]]]]]]]]]^^ ^0^@^P^`^p^^^^^^^^^__ _0_@_P_`_p_________`` `0`@`P```p`````````aa a0a@aPa`apaaaaaaaaabb b0b@bPb`bpbbbbbbbbbcc c0c@cPc`cpcccccccccdd d0d@dPd`dpdddddddddee e0e@ePe`epeeeeeeeeeff f0f@fPf`fpfffffffffgg g0g@gPg`gpggg%9\T%֟LLSt @׺p(a`LI_`=ө^d`&u1WLe1o}vO{)hW@T@5%WQwq?O`.| qc'DȓHLmzJMRJ1DGJȋGA$3a1P1G GA$3p1067EGA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA$3p1067GGA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFYFGA+GLIBCXX_ASSERTIONSopenssl.so-2.2.10-35.el8.x86_64.debug&7zXZִF!t/'!]?Eh=ڊ2NrU >5f-M)WWEj:oMKbV]_GU}T/cQ3s) :Ê,d2ls+!q"cʷ4u?Y!Kca_B/<.5<' z*R"Oن7Rf[1whU =T?Ϋ xON00C͘U̐%w `69 p֖ v<_&;\GxLM8_BMY||K:K]a{c ben%Β|4*Kdua˱۾'>IʌOh(ꓮָ|Q`ej;2o\PѺ'n3\[Z9nF_i WTi QdE[LïBWүD?ޓǸm'B%IlZH` ~oi>MƓ fx)EUX]!y m(DpD ʳ%Kk_-4gWU. Jtߵ8)e-Ȍ`Ij=]~1Kb6&,|+C473jχ1@nFZvgWm*TaAMv@ly|9\{9ǖ-]m]tOu3ۍ$OQ3c|7Mb-z2,;с ~Idꕵe]^xOE^m$ؿG\I6y)E,_4qohTKtE##NbWʊ?mqKSfjs0a\1ɳ%x 9IK!l{P% P'N_||zZND{MS-hfғU)nki$v6-ozy<V-?/4yP'v]= @7kLhiO<@mi* \n̠c$-mt-E6}i(,=" ;$ r= vdh2@CQ~Y~L _?su])o֧E;;ۧ؟ [ aqk&uȘbGQ(wr5~X'%,O(= \hqn8UF@Lҩ WE Œ>^Hpv& 滗 }%+A$k߆݄-AC&M_ϪԝJj;0:wA2Qdl+CG=lr Rj@rP~cjdP bٰ(-0W:ٯeV~{ "v !lvx. poI(,ͅE RꦒȔpH7b0kБC$\IA@?*ru.: odoMwkyPYn0!*雈uhe _IԷ B>3̈msw 23붞+ޯPUF癀cZ'*'N*f'+= Uq'lHlc@ڹu&vjì؞!NsQ_32SϷin(|2K;=6tc.pٚZ_;K jESbCK$Y4] M/'U ؏y] UwqxWÓP&/^ [E#[h7TJK͙KK-Բ(e4&Hhu^~F1 qoEg^8ޗ5LL8ӷ&~ fV{~\ӯO$?sO#i{Mr0ҽXw6 !fYonM/"!`Y^wPBE͹ S}Q_6^Y^V `kȌĴ?#q73б(C>a3 L%v9X4~OOWs' qGhكuEAbQ XPфpT}}I{Uj]43Lc84iHp /ErIČϡH" J6! GQ>< bPqF"vbڸibI`4ĂmhYZ^M؆rͨW,b;GˆkE;صLH7!eZQ{ 4-"/'᡽n B%zg>39Ѿ5>8볰Cd!"^HJy>@F݅(衽\ aճ7OZ|cPkCHDS =XЮ!cՌ? $WPNm]H3*İ7<ƲtUhm`srJLԩRNF@XwqcD֕ͻ9+M-B,hH%ߺœ߾x_6=10dQ Ca)jӝ}~ d+Z݇/f]{PM3ƀ6KC>ő=-n 'I$6RÖ-Tq qBvo7N :4ht.!ލZ8n82iu3A ᧑j51,hKRҐH,:qMfݩ "i( yT?,h%hD[a 2t/c(uMiz/E:DžBR%i>w=Yc(&B'4cdbT`[s]Am@AjL0df^fSē w;6 R_8{PfFmU_>Gq{o.JaiHy|Mgz*LF .Cp:~n] 7=pjVK2b=ѻ(2-@~1sȝxޣ䕧o0HNk )u; JOxa\Ώ gWZEl)Gp0OPrx4rS*<\H¯kadSc0I̓uTģP4g LޘP,+z-Sf+;%%/LnQcS#C9h^\ 2Qă=vr<hÝZ}+pGUZx`@Y,]M\4p >e@!Qp8T~:~Ķ6 :\Omca{@Myn;U.…X)"&8,璣])b(l٣4c ϑ$sXR3U1vXX 2Qü*g ݛ3qo:z1WF.*Mtgsp[jB3j?GDfֺBA(O6XRyNml(D#2|8c-jg_7k\*mtN5s_s? 毅PKp}%:aѫq#v0X: 웢& ,\b)"(!|{J%oeo?σ|U Y| kq[`TRu2=wV&aU%\:_;s ? uz( Tj|ɹ;uYL1-GXajâsPo/Pj H1ns3֦x '*0>. R%uhv<ݲ"5j49;"H>M=}_MNwuSҤ.1qLUq7[pCveJӋҥHRpॕYnsMGBFM``~ݙsr8q;+lЄ$rA pr6~rrzkZCfҠ 3;]TlI/@;{"/Ȏ=!2N֕=Ǯl絺O^XU gѐ`I0l?M |;I pW&H3la :@ ŅFT/@*2)# U1TFjuхK^,^K1GQ`r'Lb Y{xܺKE9{"47/TԒB'rtH'\f?!5ҳ, tK0N_ z mVTNjri':r*~Wgm5JvMIVMOñ8ʙoY "pghwuuX]4䄤u)&O@& Ibۤ_j6ƐG`,[gwlkyFK2v]G-J!u!e1G%B$&v'~bwUGWi}rU5MSjMh'_ڕ rۨ ~fE>y~a5Q`W6Ml4bBʷ }u.z'u~ǻf ZA m 75A Da/c$B e#B=ĖZK"%dVAKC馛IY;|-mk)B&ZhxaL#>А*eBiLvEV,Mb\,s"Cma6(_Pi oAYIJP4i1u 5fxCNi|TbYE"]ts4,)*g>@Nث2D2^S E:*lX*e 9oz(8>Ev(k ܝ5/B;??7!^iX kR.T|pn iw TAN@c%EN O`dcyRN#dLvS:O;=\ yع P9)C]Lv#N+q޸`6糶FĖ]w@,Nn5n[*,w_&nɈY иLSG!)#ȬF}vhv:_ u"R=ٯ&2$C)V\`cja)WI'Zb9iL}?Bgj޵pXA֙.(x>΅D )^oDbkďz&h8K9~qV顎h2w.NksZRT$AU8SkLkkg*l}Ȫ[FyaL 6+mcXg5 ~g$uf$.s58i2{^J=I҅僇snp)9zju3e>{6!sB/beJ0g8y2/gp,GÃAg0|B2vYn,sx}~-Z,cGJg3F,4ٓhƤ*I+UUrlC!~Cr=J+Xlq x5x[zVV 6«Gb̔>O |yJE`@KI覔E8atp:A  h %ViPXLNDiqvVpx)'VIkQ`f$DkfN~ = 纛 kj6"U*l%AS$ ;C-g<^tX\Ly\NLjCIW{Y8;-I+^1Ș5C:o㩣 m/ގfȮ嵥?Ӏ+8a QPD5jZFQ@+8TpvV7MDo-j۫ekAPs>D@RMS^~*zUc5nwuEd>qe?6>¢>m6FԊرc} D\>6y$'S ͮ~|ߨ0;lƭ'B@tiE\ݮO<\,?GR^X9X%GTMB¡d!v*3Pwq"_ɔҘ~n"* 3b, pk˦&ќ^rڕ&bܷ>Zpl+ƫ,]q/M<ʶ^'c!e Z uP~eĽ!. oIR{D&JH,ny$ѐlDK(#Rϰ$/.\-IMGA_Kmk$x^~dW"@;ԣKS컗XU)?Ab*uO68r)C;*xq_IpAci#/J! y%hVS@n-ZF#0R5.t,nqT -B2k#G4 91#S|:Qų zsX=q| *ɹePP|o GzhpyʥU䉿 ɹe: UM.A/P<=@)rTD~5ЙߠkS?ŃP;EqkK`_:Fz&ud@vŷ8òtˎp?9lDO z)&W}UHNkG[ ŇoyƲzg쑛@bs띩JWZKO{F)l)ģLî=c[GzlC(gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.data.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``(  8d08n8nSF8oZEoTh"^B 0QhP1P1cp1p106ngg 6w}GG GGD lldФФȅ** 8%88%88%8  G%G@J%JP%P(@k%@k @l%@l Pue@l\p,"p!h1PK!cxx2.2.0/x86_64-linux/pathname.sonuȯELF>@8{@8 @(a(a `m`m `m  xmxm xm  888$$aaa Stdaaa PtdHRHRHRQtdRtd`m`m `m GNU-ۂK`LkVL8@ 8:BE|qXGqw{bM t)U"V pn:)_E, @zF" Q4kpq s pq  `E __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizerb_class_new_instancerb_cFilerb_funcallrb_intern2rb_cDir__stack_chk_failrb_yieldrb_scan_argsrb_block_given_prb_block_callrb_funcallvrb_convert_typerb_ary_storerb_check_funcallrb_string_valuememchrrb_obj_duprb_ivar_setrb_eArgErrorrb_raiserb_ivar_getrb_eTypeErrorrb_mErrnorb_const_get_atrb_rescue2rb_mFileTestrb_obj_classrb_cIOrb_check_array_typerb_ary_entryrb_ary_new_from_argsrb_enc_getruby_enc_find_extnamerb_str_subseqrb_str_appendrb_obj_classnamerb_sprintfrb_str_hashrb_call_superrb_obj_untaintrb_obj_taintrb_str_freezerb_obj_is_kind_ofrb_str_equalInit_pathnamerb_cObjectrb_define_classrb_define_methodrb_f_notimplementrb_define_singleton_methodrb_undef_methodrb_define_global_functionlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5GLIBC_2.4/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64{ui ii `m hm Ppm pm o o o o o o o o o ,o -o .o 0o 6p  p (p 0p 8p  @p  Hp  Pp  Xp  `p hp pp xp p p p p p p p p p p p  p !p "p #p $p %q &q 'q (q ) q *(q +0q /8q 0@q 1Hq 2Pq 3Xq 4`q 5hq 7HHi] HtH5] %] hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*A%Z D%Z D%Z D%Z D%Z D%Z D%Z D%Z D%Z D%Z D%Z D%Z D%}Z D%uZ D%mZ D%eZ D%]Z D%UZ D%MZ D%EZ D%=Z D%5Z D%-Z D%%Z D%Z D%Z D% Z D%Z D%Y D%Y D%Y D%Y D%Y D%Y D%Y D%Y D%Y D%Y D%Y D%Y D%Y D%Y D%Y DH=Y HY H9tHW Ht H=YY H5RY H)HHH?HHtHW HtfD=Y u+UH=W Ht H=T dX ]wHHA[ Ht$Ht$-HH5Z SHHtH W Hٺ[H81fH=6HHZ H5Z SHHtHV Hٺ[H81bfH=16/HHMZ SHHH5Y dH%(HD$1Ht@HAV 1H81HHڿH$1HL$dH3 %(u&H[H=5HHY fDHHH|$Ht$HIH@f.AUATIHH5USH8dH%(HD$(1H\$LCHt\H5X HHEU MHLVH8HHL$(dH3 %(HH8[]A\A]fH5X HHT Hى1Ll$H85H 4H4H*HIDHH9uHEHLLHD$HHHHHD$LHE uH;].HE H=4HHW @H=3HHW ff.UHSHHdH%(HD$1u HH5W 11H HH4HEH$H$H HSH{1HHwH5xW HHH$1@u+Ht"HUЃdHsYfHL$dH3 %(HukH[]fDHH{qHЃ!H$FfDH$uHtHt%H HU]HR H5n2H81DHH5V uHtuHHR H5B2H81ff.fUHSHH5V HtGHR H8HH}HIE1HH[1HH=,]6fDH=1HHU S&H5oU HHtHQ Hٺ[H81]DH=1'HH-U ff.SH5T HHtHQ Hٺ[H81DH=&1HHT ff.SfH5oT HHtHP Hٺ[H81DH=0gHH-T ff.SH5T HHtHXP Hٺ[H81=DH={0HHS ff.SH5S HHtHO Hٺ[H81D H=!0HH]S ff.SFH57S HHtHO Hٺ[H81}DH=/GHHR ff.SH5R HHtH8O Hٺ[H81DH=t/HHR ff.SH5gR HHtHN Hٺ[H81DH=/HH%R ff.S&H5Q HHtHxN Hٺ[H81]DH=.'HHQ ff.SH5Q HHtHN Hٺ[H81DH=g.HHUQ ff.SfH5/Q HHtHM Hٺ[H81DH=.gHHP ff.SH5P HHtHXM Hٺ[H81=DH=-HHP ff.SH5_P HHtHL Hٺ[H81DH=f-HHP ff.SFH5O HHtHL Hٺ[H81}D H= -GHHO ff.SH5O HHtH8L Hٺ[H81DH=,HHMO ff.SH5'O HHtHK Hٺ[H81DH=V,HHN ff.S&H5N HHtHxK Hٺ[H81]DH=+'HH}N ff.SH5WN HHtHK Hٺ[H81DH=+HHN ff.SfH5M HHtHJ Hٺ[H81D H=J+gHHM ff.SH5M HHtHXJ Hٺ[H81=D H=*HHEM ff.SH5M HHtHI Hٺ[H81DH=*HHL ff.SFH5L HHtHI Hٺ[H81}DH=F*GHHuL ff.SH5OL HHtH8I Hٺ[H81D H=)HH L ff.SH5K HHtHH Hٺ[H81DH=)HHK ff.S&H5K HHtHxH Hٺ[H81]D H=L)'HH=K ff.SH5J HHtHXH Hٺ[H81DH=(HHJ ff.UHSHH[H5tJ IHt,HG IHٺH8H1[]f.H=(HD$JLL$HHJ fUHSHH5I HHt'HpG IHٺH8H1[] DH=(HHI ff.SHHoH5xI IHt HG HٺH8H1[fH=)HD$jLD$HH+I fSH5I HHtHF Hٺ[H81=DH=M'HHH ff.SH5H HHtH8F Hٺ[H81DH=&HH]H ff.UHSH>H5/H HHt'HE IHٺH8H1[]mDH=&7HHG ff.SHHH5G IHt HaE HٺH8H1[fH=V'HD$LD$HHSG fSfH5/G HHtHD Hٺ[H81DH=%gHHF ff.UHSHHH5F IHt,HD IHٺH8H1[]*f.H=H%HD$LL$HHSF fUHSHH{H5$F IHt,H D IHٺH8H1[]f.H=$HD$jLL$HHE fSHHH5E IHt HC HٺH8H1[2fH=_$HD$LD$HHSE fSHHH5(E IHt H!C HٺH8H1[fH=#HD$LD$HHD fS&H5D HHtHB Hٺ[H81]DH=#'HHuD ff.SH5OD HHtHXB Hٺ[H81DH=4#HH D ff.SfH5C HHtHA Hٺ[H81DH="gHHC ff.USHHdH%(HD$1H5D HH$HtSH|A HH81"HH$HHFHL$dH3 %(u+H[]H=0"HHC fDUSHHdH%(HD$1>H5'C HHtOH@ HH81vHH$HHHL$dH3 %(u'H[]H=!HHB ff.SHH dH%(HD$1HHD$RH5C IHt;H? HL$L;H8HT$dH3%(u2H [DH= HD$bLL$HHsC Lff.HdH%(HD$1H54C H$Ht3H\? E1E1HH8HT$dH3%(u#HÐH= HHB ff.ATIUHSH dH%(HD$1GHL$LHH 1\uHH5iB HtlH> HٺH81cH\$dH3%(H []A\fDH5B LD$Ht?HX> HٺH81@H=tHHA tH=TLD$LD$HHA @ATIUHSHH0dH%(HD$(14HL$ LHD$H1GusH5\@ Hl$HH= HH81EHD$HHt$HfH\$(dH3%(H0[]A\fH5? LD$ Hl$HtJH+= HH81HD$f. H=*HH? B H= LD$jLD$HHc? T@ATIUHSHH0dH%(HD$(1HL$ LHD$H1usH5> Hl$HHO< HH81HD$HXHt$HH\$(dH3%(H0[]A\fH5q> LD$ Hl$HtJH; HH81HD$f.H=?HH%> BH=LD$LD$HH= @ATIUHSH0dH%(HD$(1HL$LHLD$ H1~H5'= LL$ Hl$Ht@H: IHH81H\$(dH3%(H0[]A\H=LL$BLL$HH< 뙐H5< Hl$HtH: IHH81#념H=HHm< ff.ATUSHHKH dH%(HD$1HL$HLd$SH5; HHtTH9 MHH81HHD$Ht$HH\$dH3%(u&H []A\þ H=HH; ff.ATUSHH{H dH%(HD$1HL$HLd$H5: HHtTH9 MHH81HHD$Ht$HH\$dH3%(u&H []A\þH=OHH=: >ff.AUATUSHHdH%(HD$1HIH5; HHH58 Hٺ1IH81H HHsHDfDHH9}LHEHLLH$HHHHH$HE uH;]} HE DHL$dH3 %(Hu-H[]A\A]fH=HH ; $ ff.ATIUHSH0dH%(HD$(1HHKLKH$LCH1LjtCH5D9 Ht_H6 E1E1HىH8HL$(dH3 %(urH0[]A\@H58 Htff.ATIUHSH0dH%(HD$(1HLHKH$LKLC1HH57 hHt2H 5 HىH8nHL$(dH3 %(u+H0[]A\DH=rHH6 ~ff.ATIUHSH0dH%(HD$(1HLHKH$LKLC1HH5J6 hHt2HK4 HىH8HL$(dH3 %(u+H0[]A\DH=HH5 ff.ATIUHSH0dH%(HD$(1HDLHKH$LKLC1H6QH55 hHt2H3 HىH8HL$(dH3 %(u+H0[]A\D H=HH-5 ff.ATIUSHH dH%(HD$1HLHMH$LEH1H54 XHt6H2 HH82HL$dH3 %(u/H []A\fH=EOHHe4 >ff.ATIUHSH0dH%(HD$(1HLHKH$LKLC1HH53 hHt2H 2 HىH8nHL$(dH3 %(u+H0[]A\DH=HH3 ~ff.ATIUHSH0dH%(HD$(1HHKLKH$LCH1LtCH53 Ht_H@1 E1E1HىH8HL$(dH3 %(urH0[]A\@H52 HtH59 "H=K- 1HrH5! H=/- 1H6H5 H=- 1HH5 H=, 1HH5 H=, HH5a H=, HH5 tH=, H1H5 UH=~, HBH5 6H=_, HH5L H=@, HH5 H=!, HH5 H=, HH5v H=+ HH5Q H=+ H(H5/ |H=+ HIH5 ]H=+ 1HmH5AH' 1H=a+ H5d %H=N+ 1HH5F H=2+ 1HYH5$H=+ HH5H=* H;H5H=* HH5H=* HH5qH=* H.H5RH={* HH5|3H=\* 1HCH5:H=@* HH5JH=!* HH5H=* 1HH5H=) HH5H=) 1HnH5H=) 1HH5|fH=) HcH5GH=p) HH55(H=Q) H5H5 H=2) HvH5aH=) 1HZH5H=( 1H~H5H=( HH5H=( 1HH5IwH=( 1HH5P[H=( 1HKH5+?H=h( 1HH5#H=L( 1HSH5H=0( 1HH5H=( 1H[H5H=' 1HH5fH=' 1HcH5DH=' 1HH5"{H=' 1HkH5_H=' 1HH5CH=l' 1HsH5'H=P' 1HH5 H=4' 1H{H5oH=' 1HH5KH=& 1HH5'H=& 1HH5H=& 1HH5H=& 1HH5cH=& 1HH5GH=p& 1HH5u+H=T& 1HH5SH=8& 1HH5(H=& 1HH5H=& HDH5H=% 1HXH5uH=% 1Hto_pathPathnameinitializefreezeuntaint===eql?<=>hashto_sinspectsub_exteach_linebirthtimefnmatch?make_linkmake_symlinkpwdopendireach_entrydelete=~;T(X <(X|X,X8tXx88TpXx84PlXx80\X(4Px|h8 ( D p X   D Hx x H  HP X  XT  $ P x ( X0hzRx $XFJ w?:*3$"D\H(H _t`MLX L MLX L EG W AD 4,H cL8HFBK A(D`x (A ABBJ (8kEDG0 AAG dCDf A ($}EDD j MQK xUEd O UEd O UEd O DUEd O UEd O 8UEd O TUEd O pTUEd O UEd O UEd O  UEd O dUEd O UEd O UEd O 40UEd O PtUEd O lUEd O UEd O @UEd O UEd O UEd O  UEd O PUEd O 0UEd O LUEd O hUEd O (`wEDG0m CAO (eEDD m CAJ gEG j CG DUEd O UEd O (8eEDD m CAJ dgEG j CG \UEd O (wEDG0m CAO (wEDG0m CAO HgEG j CG gEG j CG DUEd O `$UEd O |hUEd O (EAG0q AAH (0EAG0m AAD EG0e AF @H V B 00 FDF D@q  AABG 0dLFDF GP  AABJ 0LFDF GP  AABJ 0"FDF DP  AABH 0FAA N@  AABA 04`FAA N@  AABA 8h%FBA A(G@ (A ABBC 0 FDF DP  AABE 0FDA I@n  AABJ 0 XFDF DPr  AABF 0@ FDF DPr  AABF 0t pFDF DPr  AABF 0 FDA I@n  AABJ 0 FDF DPr  AABF 0  FDF DP  AABE 0D FDF G0r  AABC (x EAG@ AAF 0 vFAD DP  AABC $ 7EAG TNC HI HQ0 &E`L (&E`h <&E`4 P.EDJ  DAI DEA0 HTEDJ U CAD WGA t H O GNUPpm 9HXcq{ H O`m hm o`8  p @  o oo oxm  0@P`p 0@P`p GA$3a1HO GA$3p1067}OGA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFYGA+GLIBCXX_ASSERTIONSpathname.so-2.2.10-35.el8.x86_64.debug87zXZִF!t/]?Eh=ڊ2Nz("yBSDk:2^&חFǙΰ{c]=pù"`ǻ#U>e|֓KᶈCt2 B7-!ee R7fpBՐhrSYxwzYn/<ĖNO`&E0nRwĕmaa^tmaC1Uj=r,?5 ym6!1QˠWAZ 8"h Fk5G?wK Ɵ Q6dђՆ]}\JljshR$^o#·_p)Ac0},eϾH>`My:o)֙i"5MdQfO)_sOXU|:?w]ӬW ^Rmi $YݙNBT3q-)+Ffm?' _}%(>lb0n n8 Ff^v"ubC$ԽX۫tA-le~:+:v芯3Y^ؼAr2ڮP=k]ӯD#c cP ֙ , B7]aQ5Hb=JJ"c6m,{y <=0۳] 'ߡoHUc*sef(:2H{Kx#A!gaLį T4 SQдc@<*<8A]#?7*Za"1ffOvߊ?6\e`zOF;T.]kJszT!_i|60I,OvX]qSI9ƺ]վHtz<k4uȄW鈖~0KW% \[Ljw ٘'/&Ȧ⸼Ts6@i+vEw1t}wX#SO(ҡ,'n$$jǤp wMz4rW{ޡs W ]q,ĵhޡ]w݈ppB؄ESP߰2[)"y SS<"%5ٌl@=Ry}~_`~j;˜Dֲ̅l^Q-CcP.'@>uCc!xb,4`cw]@YJ5®ae+}W;s$!la{#?x 3o(gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 0888o  xEo 0T ^B@@hHHcppn00w7}OO 2OOHRHRTT aa `m `mhm hmpm pmxm xm o ohp pppq pqs`pqH s,s$z+PK!j<PP2.2.0/x86_64-linux/stringio.sonuȯELF>`&@|@8 @ii ll l  HmHm Hm  888$$iii Stdiii PtdH\H\H\DDQtdRtdll l 00GNUXI@=OT\@ A\_1BE|qXz4bQ w8Q3SD'Unj%dn^> ,3"X|bCE(W:a, qF"b3 @Pmr r r __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizerb_scan_argsrb_io_write__stack_chk_failrb_funcallvrb_intern2rb_eof_errorruby_xfreerb_gc_markrb_default_external_encodingrb_enc_str_new_staticrb_string_value_cstrrb_io_modestr_fmoderb_string_valuerb_str_resizerb_fix2intrb_io_oflags_fmode__errno_locationrb_sys_failrb_check_typeddatarb_call_superruby_xmallocrb_class_new_instancerb_block_given_prb_yieldrb_ensurerb_data_typed_object_allocrb_io_taint_checkrb_eIOErrorrb_raiserb_to_encodingrb_enc_associaterb_enc_getrb_enc_from_encodingrb_num2longrb_ascii8bit_encodingrb_int2bigrb_notimplementrb_convert_typememsetrb_obj_as_stringrb_str_buf_appendrb_str_conv_encmemmoverb_str_modifyrb_enc_str_buf_catrb_num2intrb_str_newrb_str_substrmemcpyrb_check_safe_objrb_enc_mbclenrb_enc_str_newrb_enc_codelenrb_str_updaterb_str_concatrb_uint2bigrb_str_new_staticrb_eArgErrorrb_enc_copyrb_hash_arefmemchrrb_rsrb_check_string_typememcmponigenc_get_right_adjust_char_headrb_ary_newrb_ary_pushrb_lastline_setrb_frame_this_funcrb_id2symrb_enumeratorize_with_sizerb_enc_codepoint_lenrb_warnrb_enumeratorizeInit_stringiorb_cDatarb_define_classrb_mEnumerablerb_include_modulerb_define_alloc_funcrb_define_singleton_methodrb_define_methodrb_cIOrb_define_module_underrb_io_addstrrb_io_printrb_io_printfrb_io_putslibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.14GLIBC_2.2.5GLIBC_2.4/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64@ui ii ui l 'l &l l m Xm P)m 0)m  'ho po  xo  o  o o o o -o 4o 5o ;o Po Qo So Uo Vp  p (p 0p 8p @p Hp Pp Xp  `p  hp pp xp p p p p p p p p p p p p p  p !p "p #q $q %q &q ' q ((q )0q *8q +@q ,Hq .Pq /Xq 0`q 1hq 2pq 3xq 5q 6q 7q 8q 9q :q <q =q >q ?q @q Aq Bq Cq Dq Eq Fr Gr Hr Ir J r K(r L0r M8r N@r OHr RPr TXr V`r Whr Xpr Yxr Zr [HH1S HtH5rS %sS hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?h@hAhBhChDhEhFhGqhHahIQhJAhK1hL!hM%N D%N D%}N D%uN D%mN D%eN D%]N D%UN D%MN D%EN D%=N D%5N D%-N D%%N D%N D%N D% N D%N D%M D%M D%M D%M D%M D%M D%M D%M D%M D%M D%M D%M D%M D%M D%M D%M D%}M D%uM D%mM D%eM D%]M D%UM D%MM D%EM D%=M D%5M D%-M D%%M D%M D%M D% M D%M D%L D%L D%L D%L D%L D%L D%L D%L D%L D%L D%L D%L D%L D%L D%L D%L D%}L D%uL D%mL D%eL D%]L D%UL D%ML D%EL D%=L D%5L D%-L D%%L DH=!L HL H9tHH Ht H=K H5K H)HHH?HHtHI HtfD=K u+UH=H Ht H=E dK ]w1HHff.@fDSE1HH^0HdH%(HD$1H"H4$HVHT$dH3%(uH[Kff.ATIH5K USHHtLH7Ht&[]A\@H=1'HHJ fDATIH5J USHHtLHHt&[]A\@H=p/HH]J vfDH5=J SHHt11HHt'[H=0oHHI ff.H5I SHHt11H Ht'[H=0HHI ff.GG~fDHtH?/AVAUATUHSHHD.H dH%(HD$1Lt$Ll$MLAătytMHD$SHHHCHCH UHD$dH3%(QH []A\A]A^fD1H=-HjC@H|$@LqHI&CA<$wAELSHD$t.HH΃E1HPLHD$uBHt:H΃t-HHҁHHɹDDDc IAC1 ff.AUIH5A ATAHUSHH HHt211HHLDHH[]A\A]f. VHHH@H@HHEHk SHu H[DH=yC HH[HfDH@ 1ff.HH5@ HHtHH/C H5,+H81FfDAUIATAHUSHH(dH%(HD$1DHLL$H(LD$L1H*H<$Ht3^HHsHHT$dH3%(uH([]A\A]D{@HHfH1Hff.SHH[ff.HHfHH@H@HfHcHfSHCH[ff.SH#HtHC @H[SHHtHC @H[SHHtHC @H[HHHff.SHsH`H[HSH8HHff.@AUAHATUHSHHdH%(HD$1HI1IHd(D1HHHEHE @H<$Ht0@tbHHtgHukI$H HBH@HI\$HL$dH3 %(}H[]A\A]fDHHuI\$HtH='@HhH*HmHE? H5^'H81\Wb1eDUSHHHtHHHEHH[]fHHEHH[]f.USHH^HVHt HS BuHH[]fH}HDHH[]f.HHxH@HxHD?HfDHHHxH@HxHD?HfDHUHSHHt$yHHncH|$PHD$uHu"SHCHCHH[]DH΃tсH҃PXHHfATH h%Hj%USHH jH9t`HHH53: HIHtH{ GG~zLc Ht.H%HHHE%H HAD$H[]A\DHtɉƒ~E@uHtHUсH ƒHELc HuDHkff.@SHHt HS Bt[H< H5K$H81f.AUATIUSHH(AtqMIH] uRHMxcLHL9}"LH}H)HE tH}H1HL[]A\A]fDH]f.LXI~H=#|ff.@uHtHƒtuHH: H5j#H81fAWAVAUIATUSH(Ht$dH%(HD$1HYH|$I@u HNIHD$H}H|$III9t M95HD$H HXHH}H}H HE@HEHt$M9M9@HEuHHt@HʃAu)It IUփtH HfDHD$HD$HD$H]H@H HDHL$dH3 %(JH([]A\A]A^A_fH@DH|$LHxHD$fDHUH9H$H}H$L'A LgH4H$L9H$L9~"HEL)HxH L1Ht$H usH}HH usHH}HHEDHG-IH4H$AL9bHt$H tH}HvH tHDH HLH|HE0H$Hʃ~HT$HHփH Hf.H(HvpHm@HIm@HxxBfUHSHHdH%(HD$1H8uHt t[HuCH|$D$HHHHL$dH3 %(u1H[]fDf1HHSHHt HS Bt[H36 H5H81Jf.HHHxH uDHHHֺH9}HWHPH9HҁHHHf.H;y}HIff.@H3HHHH u$HH9HLHHBf.AWAVAUATUSH8Ht$dH%(HD$(1H|$HHLxH@lALt$'D$'Ld$H}H4$HH4$L9~]H HSL)HHH$H H{H$tH{J4?LE11H tH[fDI)LH uHHLLL}Ld$HD$HL$(dH3 %(upH8[]A\A]A^A_DLd$LH|$yHD$H0 tLpHpHtI@HLpHff.@ATUS3H8HH H{H1 uVHH9}:HH,9HHHH;LcLc[LHH]A\[]A\fDHQH9}HqH,>Hf.AVAUATUSH0Ht$dH%(HD$(1vH|$H8IH|$@I}H\$H HމIHAT$0LLHHcHD$I}I]H/ HLwH9L1 HILHLsHLH9rI}HGH tHGI)1HL$I}HMuHL$(dH3 %(H0[]A\A]A^H|$FH|$,I}H|$HIH9%H9H|$LHIHD$HoH9|LwfDHswIEHHIUHxH tHxH1~Ht$I}ImfDI{SHsHtHS BtH%H[H0 H5yH81SH#HtHS BtH%H[HP0 H5QH81gSHHtHS BtH%H[H0 H5H81USHH~HtHHHxHEHH[]DH1ff.H#HHt>H8 uHHD?HfDHxH?H9vH,H-/ H5H81D@ATIUHSH~H uFHHH{L)H9HNH~[L]HA\jf.[1]1A\HKHL)H9HNH~H{H[]LA\'ATUHSHHdH%(HD$1H$IătFt"HK. H5bH81PHEH$HtHH<$HUH$Hth*HHOIt$M$H$kI IHH9RH1H@I<$HIIA HWIt$H9H)1HMHH˃H)HH9HOHxI4$H 7HH<$It$H  HHI4$H<$LH$HIL$ HHIT$HL$dH3 %(H[]A\HIt$HH9!1HHH$fDHt:IIA MIXfDHPgLH$@H<$HH$fDHHvH @HHfD1H+ H57H81ATE1I1UH{HSHdH%(HD$1IH$H<$Hu6LHHtKHL$dH3 %(u6H[]A\f.H5. !HuLHOAWAVAUATIHUSHHdH%(H$81Hl$ LD$(H^1I<$It$H/ :HoH9AH_HHH~ L,I9LD$ IzIIA 7HIMteII)IM9It$I<$LI$H HH)ID$Il$fDHH9; tHH9t#x HxmH H)mHuI<$HH)HGH tHGHH)"I$H lHRgHH_H9H$8dH3 %(HH[]A\A]A^A_fDMhH( HHT$ B@H|$ uhHD$(HtMeHDH|$ Ht-@uHt t?H4HD$ 1fHHD$(HuIN4+L9'I@Lt$IHD$DHt$LLLL$L$L$LL$IHD$K.H9MtIp@HIt$I<$H)tHLHHH9f.Mu;IA0LHHHXHhII)IH(M@f.HhMM@HD$0H$0DL(HH9uMIt'LLDHrHD0HuM9MfMLLF LL)L)LG:tHHD08u3HBH9uHjLH,I[I?fNL0M9|:HD$ t0HHD11IQHl$II)HfAVAUATIUHSHT_IŅ~SHcMtI>HtBrHu7I>@tUHHu&H|% H5H81HLHLHpHu[L]A\A]A^)H@UHSHHHH,HHHH[]AUATIUHSHHb~YHcMlI}HtGzHuHHH=\ H[]HM A\fH= HH% HH10:gets02uninitialized stream11:11closed streaminvalid whenceto_strioStringIOnot opened for writingnegative lengthnot modifiable stringnot opened for readingnot openednegative length %ld giveneach_codepointeach_chareach_byteeach_lineinitializeinitialize_copyreopenstring=linenolineno=binmodecloseclose_readclose_writeclosed?closed_read?closed_write?eofeof?fcntlflushfsyncpospos=rewindseeksync=telleachbytescharscodepointsungetcungetbytereadlinesputcisattytty?pidfilenosizetruncateexternal_encodinginternal_encodingset_encodinggeneric_readablereadcharreadbytereadlinesysreadreadpartialread_nonblockgeneric_writable<<printprintfputssyswritewrite_nonblockexceptionclosing non-duplex IO for writingclosing non-duplex IO for readingwrong number of arguments (%d for 0)invalid limit: 0 for readlinesinvalid limit: 0 for each_lineStringIO#codepoints is deprecated; use #each_codepoint insteadStringIO#chars is deprecated; use #each_char insteadStringIO#bytes is deprecated; use #each_byte insteadStringIO#lines is deprecated; use #each_line instead;DGH`8h(D`|(($D(Xht(Hh,D`(|Xh<pX(H,X\xXh(@h\x8 ` | H h D x h< d  H0 P t  < zRx $FJ w?:*3$"D\0p< 8UEQ x AA (tZFKC \ ABE (ZFKC \ ABE RL[ I  RL[ I 8dLp@`|BBB A(D0NPx 0A(A BBBG 88FLG A(G0k (D ABBK :EU F N:D] A 80FEG A(GPj (A ABBF lPHNXHK`ELdHNl'H^HNEL0Ej80EjT0EjpHLEW!HQ8kFHA D(G@ (A ABBG 0$FEAG [ DAC PDA0,@VEAG d DAJ PDA`l9Ha G D9Ha G D(EDD0S AAF EAD,FOA y ABF 6A\ A 84FBD A(D0_ (D ABBG p>fHFBB E(A0A8D`n 8A0A(B BBBC (LEDG0w AAG 6A\ A qHM K 4hFHp H HPFBB B(A0A8Dp 8A0A(B BBBF 8FAA T JBH A FBG @dFBB A(A0D`' 0A(A BBBA @IEk A 8tIEk A TIEk A (pTEAG ` DAF lHi G W E @`BDD n DEO A CDH ^AE0 FAD I0  AABD 04FIK F0Q  AABK LhBBB B(K0A8I 8A0A(B BBBG <FBB D(D0 (D BBBA $$9EDI aDAL <FBD F(G0 (D ABBH Q (L DBBE 8p FBD A(D@P (A ABBI mEv E D L  $A^ >Em F D 0mEv E D L 00 |EAG g DAG DDA d mEv E D L 4 $FFD q DBI I ABL 4 |pFDF n ABO \AB, mMHA - AIC GNU'&l XP)0) ' h Wl l o`  4 p P( ooooHm  0@P`p 0@P`p 0@P`p  0 @ P ` p !! !0!@!P!`!p!GA$3a1hW GA$3p1067 'WGA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFY '1'GA+GLIBCXX_ASSERTIONSstringio.so-2.2.10-35.el8.x86_64.debugyE K7zXZִF!t/]?Eh=ڊ2No T]ܹE2B^kS8Jt+ZouV#E-u 2ڊƕWS`[Tq1:4szs=trJ ?dYwoP2*RӪG1<\W|LbߞM4xf%qF!ByrtC6W/Iy!# L:OCjf,`Jn@r)ՏeX_I4;(xݹw,2flX?eXG/L-.yA<ȸu LCsy, 9_D%~:ZU8H;ݮ퐳결~(EUK k;0/}QXcBB-n"ISu JN+^(ׁ6|rNswvD#ǸK_ Ch>7_aV{2*6|GԂp=IWSXV:5Jھui@`Z~DH0&oVv ȶoi[Dq"埖?3fsŵ奸^2Opd;GP~{}ZX`H?!5|`Wu&hF_ 1Y.dFޮ=2b'Kǣdm %+~pvE5MN%]շ}[ 'cFƩOr4^|AkUs,IpMJRԲ8'yOaխ6N/0Ui:ØhA~<4$w="H+SJBda|moyMY8^ǥ{;ǛT;ln8{'~JIAEqvX$Ln!bb#{[Ay+VXR%Ϫ,ʟǴrSRzHxߋ+"#.;(N hRH(HA{4q۠Ee6UZPq3GV@Y&5jl.<MO<#Y9ヘu?̅7qBhoW.V PZۡ0 GG8 L_^Q!“\hy'dE`@@j@8 @UU ]] ]  ]] ]  888$$UUU StdUUU PtdOOO$$QtdRtd]] ] GNU;m*E6ݚ6nJD0JLBE|UqXU+7f 9@y]Jr^T.gi[ !6MHwr#n, *F"[j b }hb e /-q b __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeendgrentsetgrentrb_ary_newrb_locale_str_new_cstrrb_ary_pushrb_tainted_str_new_cstrrb_struct_newrb_yieldgetgrentendpwentsetpwentrb_filesystem_str_new_cstrrb_sys_failgetpwentruby_xcallocsched_getaffinityruby_xfree__sched_cpucount__stack_chk_failrb_fix2int__errno_locationconfstrrb_alloc_tmp_bufferrb_num2intrb_str_new_cstrrb_bugunamerb_hash_newrb_id2symrb_hash_asetrb_intern2rb_filesystem_str_newrb_string_valuerb_check_safe_objgetgrnamrb_eArgErrorrb_raiserb_scan_argsgetgidgetgrgidrb_num2uintgetpwnamgetuidgetpwuidgetloginrb_locale_encodingstrlenrb_external_str_new_with_encgetenvrb_ensurerb_eRuntimeErrorrb_frame_this_funcrb_enumeratorize_with_sizerb_block_given_psysconfrb_int2bigrb_io_taint_checkrb_io_check_closedfpathconfInit_etcrb_define_modulerb_define_constrb_define_module_functionrb_cIOrb_define_methodrb_struct_define_underrb_cStructrb_mEnumerablerb_extend_objectrb_define_singleton_methodlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5GLIBC_2.3.4GLIBC_2.4GLIBC_2.6/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64- ui `ti ii ii ui ]  ] ] ] _ _ #_ $_ /_ ;_ ?_ A_ B_ C`  ` (` 0` 8` @` H` P`  X`  ``  h`  p`  x` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` a a  a !a " a %(a &0a '8a (@a )Ha *Pa +Xa ,`a -ha .pa 0xa 1a 2a 3a 4a 5a 6a 7a 8a 9a :a <a =a >a @a Ca Da Eb Fb Gb Hb IHHH HtH5H %H hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?h@%D D%D D%D D%D D%D D%D D%D D%D D%}D D%uD D%mD D%eD D%]D D%UD D%MD D%ED D%=D D%5D D%-D D%%D D%D D%D D% D D%D D%C D%C D%C D%C D%C D%C D%C D%C D%C D%C D%C D%C D%C D%C D%C D%C D%}C D%uC D%mC D%eC D%]C D%UC D%MC D%EC D%=C D%5C D%-C D%%C D%C D%C D% C D%C D%B D%B D%B D%B D%B D%B D%B D%B D%B DH=B HB H9tH>@ Ht H=B H5B H)HHH?HHtH%@ HtfD=EB u+UH=@ Ht H== dB ]wH#B Hff.@HHfH3HfAVAUATIUSpI\$HH;HtHHHH;HuI|$L-A\$HH\IDI<$IHID_IHLH=GA [H1]A\A]A^]ff.fHsHHH{HuHff.HSHtHHfHfDH#@ Hff.@HHfHCHfAWAVAUATUSHHHH(H-|HHD_H{ IHHDLH{IHHDH{DkHD$DcHOl-HDOd$2H;H$HHDHMLjH=? H1AWAVLL$(HT$ H8[]A\A]A^A_H=nfHCHHPkHuHff.HCHtHHfHfDH=0UHAWAVAUA ATA@SH(dH%(HE1QfH޿IHHH1ADžLEEAIcH?HHHwHCHHHHHH)HH9tHH$H9u%uyLD$1HILLLEH1rLEA\LHAEN@HudH34%(DuIHe[A\A]A^A_]H)HLyfALH5AUHHAVAUATSHdH%(HE1 AbLPDLIHH=H=wkH@HHHCHHDž@HH%H)HHH9tHH$H9ut H)HLLl$IfH@HQIAHLD H9rNHHuiHHt,H@Hx5HHD[]Ð;EuH[]DHH[]*H=ff.ATUHHStUHHhH" }IHt,H@Hx5[HD]A\A$u[]A\fD[H]A\tH=XATH=HUS/H59HHHߺ1H51Hߺ3H5(HߺH5*HߺH5!HߺIH5HߺKH5mHߺMH5YHߺOH5 EHߺH5 1HߺH5HߺQH5 Hߺ5H5HߺUH5HߺiH5HߺyH5HߺWH5HߺH5HߺH5}HߺH5iHߺH5UHߺ7H5AHߺ9H5-Hߺ H5Hߺ H5Hߺ H5HߺH5HߺH5HߺH5HߺH5HߺH5HߺH5yHߺ!H5eHߺ#H5QHߺ%H5=Hߺ'H5)Hߺ)H5Hߺ+H5HߺH5HߺH5HߺH5Hߺ3H5HߺH5Hߺ7H5HߺH5yuHߺ+H5raHߺ-H5lMHߺ;H5q9Hߺ?H5f%Hߺ5H5[HߺAH5UHߺH5THߺH5OHߺH5NHߺH5SHߺH5XHߺH5VHߺH5YqHߺH5\]HߺH5fIHߺH5k5HߺH5u!HߺH5 HߺCH5HߺH5HߺIH5HߺH5yHߺkH5oHߺmH5dHߺH5fHߺoH5jmHߺqH5gYHߺH5`EHߺH5^1HߺH5[HߺKH5_ Hߺ;H5cHߺH5ZHߺH5XHߺH5WHߺH5THߺaH5SHߺcH5Q}HߺeH5PiHߺgH5MUHߺ_H5LAHߺaH5D-HߺH5;HߺcH56HߺeH50HߺiH5*HߺQH5%HߺSH5Hߺ_H5HߺUH5HߺWH5yHߺYH5eHߺgH5QHߺH5=Hߺ]H5)Hߺ=H5Hߺ=H5HߺH5 HߺH5HߺH5HߺH5HߺYH5Hߺ?H5HߺAH5uHߺCH5aHߺEH5MHߺ H59Hߺ[H5%HߺGH5HߺH5Hߺ H5HߺH5HߺH5HߺH5HߺH5HߺH5HߺH5qHߺH5]HߺH5IHߺH55HߺH5!HߺH5 HߺH5HߺH5HߺH5HߺH5HߺH5KHߺH5HߺH5HߺH5,mHߺH56YHߺH5 EHߺH5,1HߺH5HߺH5 HߺH5 Hߺ H5HߺH5HߺH5HߺH5HߺH5HߺH5}HߺH5iHߺH5UHߺH5AHߺH5 -HߺH5HߺH5HߺH5HߺH5HߺH5HߺH5HߺH5}HߺH5}HߺH5yHߺH5eHߺH5wQHߺH5p=HߺH5i)Hߺ H5aHߺ H5YHߺ)H5QHߺ%H5KHߺH5IHߺH5KHߺ!H5LHߺ#H5MHߺ'H5KuHߺ H5FaHߺH5FMHߺH5>9HߺH56%HߺH5.HߺH5%1HHH55H߹HfH5H߹HH51HHsH51HH;H51HHH51HHKH5H߹HH5H߹H%H5i1HHH5|Q1HHEH5j91HH H5[!1HHH5L 1HHH5=1HHH501HHH5H߹HH5H߹H'H5H HhH5]H81HH=H5 QH jL Z PH L HPH H PH#H5y 1zL%S H H5` HH" I<$H-V H=" HuH=" 1HH52 rHH1jL L H wHH5 I<$ZH5 YHHP" HuH=@" H=4" [1]HH5 A\HH/etc/passwd/etcconfstrunamesysnamenodenamereleaseversionmachinecan't find group for %li 01can't find group for %dcan't find user for %li can't find user for %dUSERparallel group iterationparallel passwd iterationsysconf(_SC_NPROCESSORS_ONLN)sysconffpathconfEtcSC_AIO_LISTIO_MAXSC_AIO_MAXSC_AIO_PRIO_DELTA_MAXSC_ARG_MAXSC_ATEXIT_MAXSC_BC_BASE_MAXSC_BC_DIM_MAXSC_BC_SCALE_MAXSC_BC_STRING_MAXSC_CHILD_MAXSC_CLK_TCKSC_COLL_WEIGHTS_MAXSC_DELAYTIMER_MAXSC_EXPR_NEST_MAXSC_HOST_NAME_MAXSC_IOV_MAXSC_LINE_MAXSC_LOGIN_NAME_MAXSC_NGROUPS_MAXSC_GETGR_R_SIZE_MAXSC_GETPW_R_SIZE_MAXSC_MQ_OPEN_MAXSC_MQ_PRIO_MAXSC_OPEN_MAXSC_ADVISORY_INFOSC_BARRIERSSC_ASYNCHRONOUS_IOSC_CLOCK_SELECTIONSC_CPUTIMESC_FSYNCSC_IPV6SC_JOB_CONTROLSC_MAPPED_FILESSC_MEMLOCKSC_MEMLOCK_RANGESC_MEMORY_PROTECTIONSC_MESSAGE_PASSINGSC_MONOTONIC_CLOCKSC_PRIORITIZED_IOSC_PRIORITY_SCHEDULINGSC_RAW_SOCKETSSC_READER_WRITER_LOCKSSC_REALTIME_SIGNALSSC_REGEXPSC_SAVED_IDSSC_SEMAPHORESSC_SHARED_MEMORY_OBJECTSSC_SHELLSC_SPAWNSC_SPIN_LOCKSSC_SPORADIC_SERVERSC_SS_REPL_MAXSC_SYNCHRONIZED_IOSC_THREAD_ATTR_STACKADDRSC_THREAD_ATTR_STACKSIZESC_THREAD_CPUTIMESC_THREAD_PRIO_INHERITSC_THREAD_PRIO_PROTECTSC_THREAD_PRIORITY_SCHEDULINGSC_THREAD_PROCESS_SHAREDSC_THREAD_ROBUST_PRIO_INHERITSC_THREAD_ROBUST_PRIO_PROTECTSC_THREAD_SAFE_FUNCTIONSSC_THREAD_SPORADIC_SERVERSC_THREADSSC_TIMEOUTSSC_TIMERSSC_TRACESC_TRACE_EVENT_FILTERSC_TRACE_EVENT_NAME_MAXSC_TRACE_INHERITSC_TRACE_LOGSC_TRACE_NAME_MAXSC_TRACE_SYS_MAXSC_TRACE_USER_EVENT_MAXSC_TYPED_MEMORY_OBJECTSSC_VERSIONSC_V7_ILP32_OFF32SC_V7_ILP32_OFFBIGSC_V7_LP64_OFF64SC_V7_LPBIG_OFFBIGSC_V6_ILP32_OFF32SC_V6_ILP32_OFFBIGSC_V6_LP64_OFF64SC_V6_LPBIG_OFFBIGSC_2_C_BINDSC_2_C_DEVSC_2_CHAR_TERMSC_2_FORT_DEVSC_2_FORT_RUNSC_2_LOCALEDEFSC_2_PBSSC_2_PBS_ACCOUNTINGSC_2_PBS_CHECKPOINTSC_2_PBS_LOCATESC_2_PBS_MESSAGESC_2_PBS_TRACKSC_2_SW_DEVSC_2_UPESC_2_VERSIONSC_PAGE_SIZESC_PAGESIZESC_THREAD_KEYS_MAXSC_THREAD_STACK_MINSC_THREAD_THREADS_MAXSC_RE_DUP_MAXSC_RTSIG_MAXSC_SEM_NSEMS_MAXSC_SEM_VALUE_MAXSC_SIGQUEUE_MAXSC_STREAM_MAXSC_SYMLOOP_MAXSC_TIMER_MAXSC_TTY_NAME_MAXSC_TZNAME_MAXSC_XOPEN_CRYPTSC_XOPEN_ENH_I18NSC_XOPEN_REALTIMESC_XOPEN_REALTIME_THREADSSC_XOPEN_SHMSC_XOPEN_STREAMSSC_XOPEN_UNIXSC_XOPEN_VERSIONSC_PHYS_PAGESSC_AVPHYS_PAGESSC_NPROCESSORS_CONFSC_NPROCESSORS_ONLNCS_PATHCS_POSIX_V7_ILP32_OFF32_LIBSCS_POSIX_V7_ILP32_OFFBIG_LIBSCS_POSIX_V7_LP64_OFF64_CFLAGSCS_POSIX_V7_LP64_OFF64_LIBSCS_POSIX_V7_LPBIG_OFFBIG_LIBSCS_V7_ENVCS_POSIX_V6_ILP32_OFF32_LIBSCS_POSIX_V6_ILP32_OFFBIG_LIBSCS_POSIX_V6_LP64_OFF64_CFLAGSCS_POSIX_V6_LP64_OFF64_LIBSCS_POSIX_V6_LPBIG_OFFBIG_LIBSCS_V6_ENVCS_GNU_LIBC_VERSIONCS_GNU_LIBPTHREAD_VERSIONPC_FILESIZEBITSPC_LINK_MAXPC_MAX_CANONPC_MAX_INPUTPC_NAME_MAXPC_PATH_MAXPC_PIPE_BUFPC_2_SYMLINKSPC_ALLOC_SIZE_MINPC_REC_INCR_XFER_SIZEPC_REC_MAX_XFER_SIZEPC_REC_MIN_XFER_SIZEPC_REC_XFER_ALIGNPC_SYMLINK_MAXPC_CHOWN_RESTRICTEDPC_NO_TRUNCPC_VDISABLEPC_ASYNC_IOPC_PRIO_IOPC_SYNC_IOgetlogingetpwuidgetpwnamsetpwentendpwentgetpwentgetgrgidgetgrnamgroupsetgrentendgrentgetgrentsysconfdirsystmpdirnprocessorsPasswdshellgecoseachmemGrouprequired buffer size for confstr() changed dynamically.SC_THREAD_DESTRUCTOR_ITERATIONSCS_POSIX_V7_ILP32_OFF32_CFLAGSCS_POSIX_V7_ILP32_OFF32_LDFLAGSCS_POSIX_V7_ILP32_OFFBIG_CFLAGSCS_POSIX_V7_ILP32_OFFBIG_LDFLAGSCS_POSIX_V7_LP64_OFF64_LDFLAGSCS_POSIX_V7_LPBIG_OFFBIG_CFLAGSCS_POSIX_V7_LPBIG_OFFBIG_LDFLAGSCS_POSIX_V7_WIDTH_RESTRICTED_ENVSCS_POSIX_V6_ILP32_OFF32_CFLAGSCS_POSIX_V6_ILP32_OFF32_LDFLAGSCS_POSIX_V6_ILP32_OFFBIG_CFLAGSCS_POSIX_V6_ILP32_OFFBIG_LDFLAGSCS_POSIX_V6_LP64_OFF64_LDFLAGSCS_POSIX_V6_LPBIG_OFFBIG_CFLAGSCS_POSIX_V6_LPBIG_OFFBIG_LDFLAGSCS_POSIX_V6_WIDTH_RESTRICTED_ENVS;$#@h<HThlh(xX(4XhH0P8xzRx $` FJ w?:*3$"DX\!HXt(HN0HN88BBB D(A0w(F BBB4Hk*HQ G I!HX0HNHHNT`BBB B(A0A8DPXH`NhBpS8A0A(B BBBAP4Hk*HQ G I,AC FHK+ H (4yEF N" E 4`lFAA G?  AABF TrH L D sH A G EK L AC sH A G EK L AC 04X`EAD a JAJ XFAhDl|$A^&EU F DDl )EU F D0?HZ N N P?HZ N N$,ppHP H s E G E @TEDD z FAB [ FAF D DAE DFAJ K FBD Y FBG A DBE D|-FHA  (H0R8O@` Q(G0m(H gCPGNU ] -=HV`  @@] ] o`   `   o`ooo] @P`p 0@P`p 0@P`p 0@P`p 0@GA$3a1M@ GA$3p1067 =@GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFY A GA+GLIBCXX_ASSERTIONSetc.so-2.2.10-35.el8.x86_64.debugPK7zXZִF!t/A]?Eh=ڊ2NZ6H\k'5ܹE2B^kHt88ɂT[3%rd6'!kv2Xe:n)[JU3ק}{vFր2TrkQ$!,_߉U۴؄\~@q"be!$12 Vlhly!uU1QyܙX+{UJD=ݤukzQZD~=Iޱȡ, `2w.cZso& .bc0`b kF3 F&aFC{@şyM{2`:wؙvY֧2@~ π 59 FxicPٵWOoNvVk\$]̓ϟ09VG(r$24dD`@jm3& >_UM+⪓[M,9%;P`7b]BQ-P%;<( JңRड3*nEu_), 6`;"JSavH<6RG|':CJymw@A^@8j97A|CDp2iFq@>"U#:ɡzIQGLC)Ww[42`*%2${0:(ˈ8<6;aœHX5x,a^NNs4>M*a>P ,Lr~Nv8EZ.T`c^V)F2JߎG,` d[JK $zg6{T"V1Fx'00^Qz_+1;NCB-3]Çٕ =\F5cP;WaQR&0b"gs|>h312#5jnwJ`'OOLHBW-?=tv9PʇSz!; ék3 ԥ(93LvJYLV7@(@8 @tt || |  || | PP888$$ttt Stdttt Ptdiii  QtdRtd|| | xxGNU\;OmƇ@ |CEqX}BWw&)n{!B IwR ?gE^2 q&y ~a, z0F"z]0m@k jU}; CRQdb2M.(;l[m!r:hQW[     \__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizerl_pointrl_editing_modehistory_basehistory_lengthclear_historyrb_attr_getrb_funcallrb_intern2rl_filename_quote_charactersrb_locale_str_new_cstrrl_completer_quote_charactersrl_basic_quote_charactersrl_completer_word_break_charactersrl_basic_word_break_charactersrl_line_bufferrl_completion_append_characterrl_attempted_completion_overrb_Arraymallocrb_locale_encodingrb_enc_from_encodingrb_gc_writebarrier_unprotectrb_obj_as_stringrb_string_value_cstrrb_enc_checkstrcpyrb_enc_codepoint_lenrb_tolowerstrncpystrduprb_memerror__stack_chk_failrb_string_value_ptrrl_username_completion_functionrl_completion_matchesrb_ary_newrb_ary_pushfreerb_ary_shiftrl_filename_completion_functionremove_historyrb_string_valuerb_check_safe_objrb_enc_getrb_str_conv_encadd_historyrb_fix2intreplace_history_entryrb_num2intrb_eIndexErrorrb_raiserb_str_new_staticrl_special_prefixesrb_ivar_getrb_str_new_frozenrb_cStringrb_obj_revealrb_obj_hiderb_ivar_setrl_redisplayrb_setup_fake_strrb_freeze_singleton_classrl_delete_textrb_str_subposrb_str_strlenrb_range_beg_lenrb_num2longrb_error_arityrb_out_of_intrb_eArgErrorrl_insert_textfcloserl_instreamrl_outstreamruby_xrealloc2ruby_xmalloc2rb_locale_str_newrl_emacs_editing_moderl_vi_editing_moderl_get_screen_sizefilenorb_thread_call_without_gvl2rb_wait_for_single_fd__errno_locationrb_sys_failrb_thread_check_intsstdinrb_bugrb_block_given_prb_yieldhistory_getrb_frame_this_funcrb_id2symrb_enumeratorize_with_sizerb_respond_torb_io_taint_checkrb_io_check_initializedrb_eIOErrorrl_initializerl_refresh_linerb_scan_argsrb_protectrb_str_new_sharedrb_str_set_lenrb_str_catrb_str_locktmprb_str_unlocktmp__ctype_b_locrb_str_tmp_newrl_free_line_staterl_cleanup_after_signalrb_jump_tagreadrb_check_typerb_io_check_closedrb_cloexec_dupfdopenrl_set_screen_sizeInit_readlinerl_readline_namerl_getc_functionusing_historyrb_define_modulerb_define_module_functionrb_define_singleton_methodrb_cObjectrb_obj_allocrb_mEnumerablerb_extend_objectrb_define_constrl_library_versionrb_str_new_cstrrl_attempted_completion_functionrl_pre_input_hookrl_catch_signalsrl_clear_signalsrb_gc_register_addresslibruby.so.2.2libreadline.so.7libncurses.so.6libtinfo.so.6libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5GLIBC_2.4GLIBC_2.3/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64O  ui   ii  ii  ui  | `8|  8| | ~ ~        ( 0 8 @ $H )P 1X 6` 8h :p =x ? B Q U W X Y [ a q y {       ( 0 8 @  H  P  X  ` h p x           Ȁ !Ѐ "؀ # % & ' ( * + , - .( /0 08 2@ 3H 4P 5X 7` 8h 9p ;x < > @ A C D E F G Hȁ IЁ J؁ K L M N O P R S T V( Z0 \8 ]@ ^H _P `X b` ch dp ex f g h i j k l m n oȂ pЂ r؂ s t u v w x z | } ~( 0 8 @ H P X ` h p x  HHAU HtH5"V %#V hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?h@hAhBhChDhEhFhGqhHahIQhJAhK1hL!hMhNhOhPhQhRhShThUhVhWqhXahYQhZAh[1h\!h]h^h_h`hahbhchdhehfhgqhhahiQhjAhk1hl!hm%=O D%5O D%-O D%%O D%O D%O D% O D%O D%N D%N D%N D%N D%N D%N D%N D%N D%N D%N D%N D%N D%N D%N D%N D%N D%}N D%uN D%mN D%eN D%]N D%UN D%MN D%EN D%=N D%5N D%-N D%%N D%N D%N D% N D%N D%M D%M D%M D%M D%M D%M D%M D%M D%M D%M D%M D%M D%M D%M D%M D%M D%}M D%uM D%mM D%eM D%]M D%UM D%MM D%EM D%=M D%5M D%-M D%%M D%M D%M D% M D%M D%L D%L D%L D%L D%L D%L D%L D%L D%L D%L D%L D%L D%L D%L D%L D%L D%}L D%uL D%mL D%eL D%]L D%UL D%ML D%EL D%=L D%5L D%-L D%%L D%L D%L D% L D%L D%K D%K D%K D%K D%K D%K DH=K HK H9tH~G Ht H=K H5K H)HHH?HHtHEG HtfD=]K u+UH=*G Ht H=VD d5K ]wH=G HcHDff.HF 8Hff.H}F 8HEHF 8fHF HcHDff.HE 8Hff.SHH[ff.H5J H=K fH5J H=J fH5J H=J fH5J H=J SHtH5J HHt1H11[H=+HHI HD H8Ht f.HE H8Ht Xf.H-E H8Ht (f.HD H8Ht f.H=D H8Ht f.HD H8Ht f.AWAVAUATUHSHH5!I H="I dH%(HD$x1HH HHC H5H H=H HC HHD$ H5H HHHH1'HŨu HSHL HA LeMJHHD$HD$XHN1HIIHD$pHD$HEHD$M%L|$(Ll$X~@HD$H; HH0H[fDUHSHHHt$HtUH|$;H|$H|$HH|$HHHHD$"HHD$UHT$H5? H=:? HD$Ht2H tH@HN: HHH[]ÐHf.H): HHH[]HH=> H5> &fDSHSH[ff.AVAUATUSH@dH%(HD$81H9 IHHHIH$HD$HT$H|$HH=Iƨu6Ht.Hƒt!H€I~Itu LD@t[H<$Ht$HHcH9-HcH9HL$8dH3 %(LH@[]A\A]A^DIu@HI}H4$@HH|$Hl$HLHH)HH$_DLHl$;I}HHAHHD$H<$H#Iu@t7HH4$fDH4$HmHhHAHXH뿺1rHH7 H5H81ff.fUSHHH|$Ht$H|$:H|$HXH|$HHHD$HxH tHxMHH[]H=; HtI9EA9ME1@WAu!H5LE1f.H9v%tIIYuH9&L)AuH5L9HLL+H5$. LLH5 . LLLLd$H\$H u,HsHT$H='bHH|$UHkHT$H=H3HHufDHHM~fDHLLL)I\E1@HLLL)IHu(D$C EC1HL$dH3 %(u&H[]ÐfE]ff.fATUSHHto HHHhH~}AŃthH5 LHt4H% H* H* HH[]A\kH[]A\^D HH=F D#RH=1 FfDATUSHHto HHHhH}ŃthH5Ht4H$ H) H) HH[]A\;H[]A\D HH= D#H=q fDSHHtH% H[DH% H[DATIUHH׃StJLAtuމ H[]A\@{މH[]A\f.[HHt0Džx0( Ht)H8HG DžyH~# 8yH;$ H5 H81"fHHt(HB# x(9~(H?H# yyH# H5 H81SHHtH5' Ht&Ht7H5( H=4( H[H=$ HH]' Hd# H5 H81;ff.AUATUSHR HH# HHz" HHH<' HkH' H' HDHu' H& H HF' H& HH= H ' HH5 HH.' H="' H^H5bH=' HH5CH=& H H5$H=& 1HH55H=& HH5H=& 1HyH5 H=n& 1HH5kH=R& 1HAH5[H=6& H2H5BvH=& HSH5*WH=% 1HH5;H=% 1H{H5H=% 1HH5H=% 1H#H5H=% 1HH5H=l% HxH5H=M% 1HlH5H=1% H H5qH=% 1HaH5UH=$ HH5 6H=$ 1HH5 H=$ HH5H=$ 1HH5H=$ HH5H=a$ 1H H5H=E$ H!H5H=&$ 1HH5iH= $ 1HH5MH=# HzH5.H=# 1HH5dH=# H?H5XH=# HH5EH=u# 1HH55H=Y# HH5 H=:# 1HH5}H" HmH" Ho" H6H-o H" H}/HH HH0Z1HHH5H߹HcH5H߹HH5H߹H=H5~H߹HbH5f1HHH5S1HHH5?v1HHH5-^1HHrH5F1HHZH5.1HHbH5H߹HH51HHOH5H=! HH5-H}H8H5aHHH=G! HH5H}H-pH4H5HHbH=! HH5WHJL- H H- I}IuH=6IH= LH5(HMHH HHo HHH ;H= /HH= []A\A]fH=H xH=1 H11H5sH>$f H=?H  H=H vH=0H H=H H=H H- (@H 1HHcallinvalid indexHISTORYrb_wait_for_single_fdreadclosed readline inputclosed readline output02dupwfdopenRubycompletion_proccompletion_case_foldpre_input_hookspecial_prefixesReadlinereadlineinput=output=completion_proc=completion_case_fold=line_bufferpointpoint=set_screen_sizeget_screen_sizevi_editing_modevi_editing_mode?emacs_editing_modeemacs_editing_mode?completion_append_character=completion_append_characterbasic_word_break_characters=basic_word_break_charactersbasic_quote_characters=basic_quote_characterscompleter_quote_characters=completer_quote_charactersfilename_quote_characters=filename_quote_charactersrefresh_linepre_input_hook=insert_textdelete_textredisplayspecial_prefixes=orig_promptlast_promptto_s[][]=<<pushpopshifteachlengthempty?delete_atclearFILENAME_COMPLETION_PROCUSERNAME_COMPLETION_PROCEditLine wrapper1aVERSIONreadline_getc: input closed unexpectedly or memory corruptedargument must respond to `call'completer_word_break_characters=completer_word_break_characters;@$$Ldx$4Tt  4HTdxDt,`T<h$4Tx4$0d\Dd$8DttDd \ D   tX t T zRx $FJ w?:*3$"D\HpT`lhdp|EL,@]Si D \&p& &<&X&t&L_FBB B(A0D8G 8A0A(B BBBA 0$FAF D0  DABK 0X,FAF D0  DABK $=AFD lDA&@FBE A(A0D@ 0A(A BBBA $ hmEAG0ZDA(4EDD0 AAF 0`dEAG0\ DAB sDAZLh D a0,EDG0 DAB bDAEL@,#FBB A(C0Dp 0A(A BBBF $pmEAG0ZDAaPrVpaPrV(=EAG0 DAF (=EAG0 DAF ((=EAG0 DAF (T=EAG0 DAF (=EAG0 DAF (WH I A lHUtHU |oED \ DA 80%FEA A(DP (A ABBF l&4FDA U ABE NDLh7ziYܺƏ{YnSz53|Kc @ k@8 @SS \\ \ 8h h]h] h] 00888$$SSS StdSSS Ptd`H`H`HQtdRtd\\ \ GNUG/S aqFN@$NPBE| VqXy) Xl<U7~aG~IsUjft "Qj<!/h] ~ !, IvF"M(b Xb  @L(b __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizerb_check_typeddatagdbm_closeruby_xfreerb_eRuntimeErrorrb_raisegdbm_firstkeyrb_str_newgdbm_fetchrb_string_valuegdbm_nextkeyrb_hash_newrb_hash_asetrb_ary_newrb_assoc_newrb_ary_pushmemcmpgdbm_existsrb_out_of_intrb_error_frozengdbm_syncgdbm_reorganizegdbm_fdescrb_fd_fix_cloexecrb_block_callrb_intern2gdbm_deletegdbm_errno_locationgdbm_strerrorrb_hash_delete_ifrb_yieldrb_ary_tmp_newrb_str_duprb_protectrb_gc_writebarrier_unprotectrb_ary_clearrb_freeze_singleton_classrb_jump_tag__stack_chk_failrb_ary_new_caparb_warngdbm_store__errno_locationrb_sys_failrb_check_typerb_eArgErrorrb_data_typed_object_allocgdbm_setoptrb_fix2intrb_block_given_prb_frame_this_funcrb_id2symrb_enumeratorize_with_sizerb_scan_argsrb_eIndexErrorrb_check_safe_objgdbm_openruby_xmallocrb_sys_fail_strrb_num2intrb_ensureInit_gdbmrb_cObjectrb_define_classrb_eStandardErrorrb_eExceptionrb_mEnumerablerb_include_modulerb_define_alloc_funcrb_define_singleton_methodrb_define_methodrb_define_constgdbm_versionrb_str_new_cstrlibruby.so.2.2libgdbm.so.6libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5GLIBC_2.4/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64 ui ii ui \ !\ P!] ] ] 2H0] "8] !_ _  _ "_ $_ &_ 2_ 4_ 9_ ?_ @_ A_ D_ E`  ` (` 0` 8` @` H` P`  X`  ``  h`  p` x` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` a  a !a #a $ a %(a '0a (8a )@a *Ha +Pa ,Xa -`a .ha /pa 0xa 1a 3a 5a 6a 7a 8a :a ;a <a =a >a Ba Ca Ea Fa Ga Hb Ib Jb Kb L b MHH1G HtH5rG %sG hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?h@hA%MC D%EC D%=C D%5C D%-C D%%C D%C D%C D% C D%C D%B D%B D%B D%B D%B D%B D%B D%B D%B D%B D%B D%B D%B D%B D%B D%B D%}B D%uB D%mB D%eB D%]B D%UB D%MB D%EB D%=B D%5B D%-B D%%B D%B D%B D% B D%B D%A D%A D%A D%A D%A D%A D%A D%A D%A D%A D%A D%A D%A D%A D%A D%A D%}A D%uA D%mA D%eA D%]A D%UA D%MA D%EA DH=AA H:A H9tH> Ht H=A H5 A H)HHH?HHtH> HtfD=@ u+UH=> Ht H=; d@ ]w1HHff.@HH5Q; |HtHxHHHfDHtSHHHteH[@PXH57$HH= H81fSH5: Ht HxHHt HC[DPXH5#1HHH=? >ff.USH5Ht`HHcH"HH@u"HtHEƒHsHH[]DHEHH[]ÐHH59 HtIHxHt@xt)H@HtH61HHfUSHHt`HHcH2HH@u"HtHEƒHsHH[]DHEHH[]ÐSHHH|$Ht$Ht$H uHHHIH[HNHcH9uHvSHH58 HtHxHt H[yt@f.USHH ubHHHHtiHHcHHuHtHƒ~IHHH[]fHFHcȉH9uHvyHHuHH[]fHrATH57 USHt^HhHtUHIHHt2HHeHLHHHHHuL[]A\4@ATUSHH5 7 HI.HtXHhHtOHHHt4DHHHLH/HHdHHuL[]A\ff.AWH56 AVAUATUSHHL`IMHc~HHD[]A\A]A^A_fDLHHtPE1DHLAHIHLHMuIcHDEuH[]A\A]A^A_DE1fATH55 USHtfHhHt]HI.HHt:HHHHZLHHHHHuL[]A\Lff.AWH5#5 AVAUATUSHBH~L`MtuLIHHHtHDHHLHLIHINHLHPHLL2MuHL[]A\A]A^A_fDATH5s4 USHtPHhHtGyHIHHt$HLHHHHuL[]A\"fUSHHH|$Ht$H53 HHHhHHgHHuJHHHIɃA u\H9tXHH1HHHHwHtH|$HIA tHwIA tH9uMu?HHpMtHpMu6HmyH[]fHcWf.Hf.H1[]fUSHHH|$Ht$H52 HH HhHHHHuJHHHIɃA u\H9tXHHHHHH'HtH|$HIA tHwIA tH9uMu?HHpMtHpMuHyHH[]HfHcWf.HH[]ff.ATUHSHH|$Ht$bHt$H uMHLfH531 HYHt@HxHt7LHpHHH[]A\H~HcljH9u Lff.@uHtHƒtuHH=ff.SHH5|0 HHtHxHt !H[gUSHHnH570 H_Ht*HhHt!HHJHH[] ff.UHSHHH54 Ht$IHL11NHH[]@ H= HH4 AWAVAUATUSHHH|$H5j/ HHHhIHHIHHurMLMtHHLHHILI6H߅tMtL}8QH=3 H5$H1AEHD$H[]A\A]A^A_UHSHHH53 Ht'IHL"11HH[] H=HHE3 ff.AVAUATUHSHHt$7H|$ Ht$H HLfH5- HIHtLpMtvLHLt5LHLuWAUHxAUH[]A\A]A^@H[]A\A]A^fDHFHcȉH9uLfhTAE'8H=Q2 H5H1ATUHS0H5, H!HtVL`MtML{HHt2LHHHILH[]A\f.[]A\HHHAVAUATIUS|H5U, LIzHHhHHHHtyL-, 7LL5HtdHhHt[HHHHt9HHHHHH`HtHL=[L]A\A]A^AWAVAUI1ATUSH(dH%(HD$1dLD$IH5J+ LrHLxHMELD$ HHLt$HfDH5* LHHLxMHLuHHu)HtHH{H t ;HLHILHWH=, LHL$uHIHL91Mt$GHHH9~JLLI$ LH4LHI$H uIT$H9|$}T$ ~HuNAD$T$ )‰ULXLHT$dH3%(uLH([]A\A]A^A_fDID$ qHHN@AUHcATIIUSHHaHE~(AELlH3LHaHHvL9uHH[]A\A]U1HSHH=HHHH[]AVIAUATUSHH$Ht$H|$H}HD$H HHhHcH9H$ALA LhL@IcI9H5( LD8HHxHLIHALtY8tg8;H=, H5H1sILhAiHhHP*H$H[]A\A]A^1dH L@ATUHSHH |HHHHH uEHC HHL HH tA|HH3LH[]A\[HCDH{fD;H[ HN) H5H81=ff.fHU& 1ff.PXH%8H=O+ H5H1fDSHH5& HdH%(HD$1HtKHxHtB1HT$HD$t#HL$dH3 %(Hu H[IfSHH5q% HdH%(HD$1HtKHxHtB1HT$HD$6t#HL$dH3 %(Hu H[nfUSHH5$ HdH%(HD$1HtKHhHtBHAHT$HD$t$HL$dH3 %(Hu H[](ATUHSPt|H5E$ HmHHxHt~HHt?L%$ @HLH-HtKHxHtBHHHuH[]A\@Hc[HE1]11HA\AUATIUSHH5{# LHHXHHHHtLL-C# HHEHLLRHtVHXHtMHHHHuHL[]A\A]HHLE1[1]1A\HA]fAUATIUSHH5" LHHhHHHHtWL-c" HHeHH:HLLgHt[HhHtRHHHHuHL[]A\A]D+HHLE1[1]1A\HA]fAUATUSHHG H(dH%(HD$1HL$LD$Ld$HLl$LHHt)t2HT$dH3%(Hu_H([]A\A]fDIt2Lu=HuÅuH# H5 H81tLHmff.fATIUHSMHHtHLH[]A\ÐtHOHf.AVAUATIH* USH dH%(HD$1ILL$LD$LtH|$HCH|$HTLA14H<$+H<$H x=ځHHL^"IHuzH<$H HHL!1ɾIHu=H<$H HL1DIMfDLI|$ HI\$ LLkHL$dH3 %(eH []A\A]A^@H|$H@aLH<$ H<$ڀH uZHLIMY8tO8 t E8 u0H<$Hf.U@ 8H=5# H5gH1@S@HHfDH'AAff.ATI1UHHx S2LHHHtWuH[]A\H[]A\H= HH[HS]A\ff.HH H=^H0H=H" H} H0H=yH! HX H0hH=! H! Hk H0KH=! H5-XH=! HH5(H=! HH5ZH=s! 1HjH5>H=W! 1HH5"H=;! HH5H=! HH5H= H!H5H= HH5H= HH5gH= HH5hH= 1HH52LH=e HH5-H=F 1H}H5H=* 1HaH5H= 1HH5H= 1HH5H= 1HH5H= 1H!H5H= 1HH5iH= 1HH5pMH=f 1HH5Y1H=J 1HH5DH=. HH5+H= 1HFH5H= 1H*H5H= 1HH5H= 1HH5H= 1HFH5jH= HWH5KH=d HH5,H=E 1HH5H=) 1H`H5pH=  HH5VH= H2H5BH= HH5-H= HH5xH= HH5YH=r HH5:H=S HH5H=4 HH5H= HH5H= 1HH5H= 1HH5oH= @H5_H= @H5NH= @H5=H=v @H5-H=^ !H5H=F AH5H=. H5mH H8H= HH5HDHHclosed GDBM file%sGDBMeach_pairpair must be [key, value]11key not found12GDBMErrorGDBMFatalErroropeninitializecloseclosed?[]fetch[]=storeindexselectvalues_atlengthsizeempty?eacheach_valueeach_keykeysvaluesshiftdeletedelete_ifreject!rejectclearinvertupdatereplacereorganizesynccachesize=fastmode=syncmode=include?has_key?member?has_value?to_ato_hashREADERWRITERWRCREATNEWDBFASTSYNCNOLOCKVERSIONgdbmGDBM#index is deprecated; use GDBM#key;40`@`<Xt0`P<0``|p 0(@8pP0p 80d040pP0L t` @< ` `  h 0 X zRx $`0FJ w?:*3$"Dh \0p<:H] K I\)JUpAAKt;Ep A "EAM0AAD O DAF YDA$4gHk E X H I A 0\@AAD O DAF YDA YAG s AD ,Aa E 4AAD [ DAJ h DAC ,P|FHA d ABA ,LFAA s ABA `|FIB B(A0A8D@i 8F0A(B BBBG P 8A0A(B BBBF ,lFHA l ABA HFIB B(A0A8D@~ 8D0A(B BBBA ,\0nFHA V ABA 4pNEAG0 FAJ d CAA 4DEAG0 DAD a DAA 0FAD D0[  DAED 0 2fD89En A (`\UEAG } DAA (]EDG f DAE HFBB B(A0A8GP 8A0A(B BBBA (xeEDG k DAH T0BBB A(D0D@ 0A(A BBBE I 0A(A BBBG 8tFAD S ABO A FBA HI<FBB D(A0 (D BBBA H`\FBB G(A0A8D` 8A0A(B BBBG 4ht]FEG A(G0y(D ABB$/EFN IGA@\FEB A(A0D@ 0A(A BBBH , FAI w FBA <pP|*AAD lEN c AA EN c AA (hEAN0b AAA 8FAD } ABE N GIE LPFBD A(D0 (D ABBA Q (G CDEE LlFBD A(D0 (D ABBF Q (G CDEE 8FBA C(NPY (A ABBG ($FFDD ] ABB @$ HFBB K(F0DPq 0A(A BBBH @h uFFM h ABD I ABD NHB PLH5GNU!P!] 2H"!z h \F\ \ o`H  . ` 08p o oovoh]  0@P`p 0@P`p 0@P`p 0@P`pGA$3a1hiF GA$3p1067!\FGA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFY!!GA+GLIBCXX_ASSERTIONSgdbm.so-2.2.10-35.el8.x86_64.debugHYw97zXZִF!t/]?Eh=ڊ2N$:~Xo/*~uS`Yۄo7_1 H`tɾ44(ŋd=>GW0Yr`nOD$uY}C&$.HQ] 06wzquf pνEDR<{*v2BzdSKl3ZQkHe(o {]^uiof>uY!PPL2Z_pl}V*N@-t"(/y*euG56`4W܄ J)cV] ۽wmp' lT$V,%j=0-B{L[42"iRdP9AY 5)b_m~?7,n[Uq Mtˉu X&jQ QP;ėΊ0u,0-:;+ӛ?&|/%Vݞȯ.qάwN!>_#Xbʸ}Bh8BR,B2R97[5Qwƍ+Lk4=X^8kʨbyxC'P4~$uI 2WN?WD=!jcEXĈ5@[o %^9cg3*)rf(8Zb-5*X oA(r뤲5+ζ@ŞLƭJm"w[`D#v/+wjD/<%W)MN~M{>HpặUiG𰻅* 4uR\6;Tӫ[e"_%(;G7WOnFN-$6" Bޑ)!k5BclqB#5Y}= }yN.bL+e-6EZ@eU5(P=lW4_ +K&gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 0H H .8ovvEo  PTpp^B880hhhc0n w |%}\F\F 2pFpF`H`HJJ SS \ \\ \] ]h h] h]0_ _h` `((b (b0Xb`(bH pd(dXi+PK!=8xx2.2.0/x86_64-linux/ripper.sonuȯELF>@R@8@8 @ ""H ""  888$$ Std PtdQtdRtd""PPGNUUFc7$`bn9"td txy&BE|GsqX h/k V`l0}R>8s:z0EC%L({u` (j UqsOnAPc`ga, ~F"NC7Y QQ"d" @X"Q ]__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizerb_isspacerb_str_freerb_gc_force_recycleruby_global_name_punct_bitsrb_isdigitrb_isalpharuby_xrealloc2rb_enc_codelenrb_enc_str_newrb_enc_dummy_prb_enc_str_coderangerb_usascii_encodingrb_utf8_encodingrb_ascii8bit_encodingrb_enc_associaterb_enc_find_indexrb_enc_from_indexrb_sprintfrb_eArgErrorrb_make_backtracerb_ary_unshiftrb_make_exceptionrb_exc_raise__stack_chk_failrb_enc_getrb_raiserb_id2symrb_node_newnoderuby_xmalloc2ruby_xmallocruby_xfreerb_bugrb_vsprintfrb_funcallrb_intern2stderrfwrite__fprintf_chkfputcrb_check_typeddatarb_gc_markrb_enc_from_encodingmemchrrb_str_subseqrb_io_getsrb_scan_argsrb_string_valuerb_str_new_frozenrb_fix2intrb_enc_str_new_staticrb_freeze_singleton_classrb_num2intruby_xcallocrb_data_typed_object_allocstrncmpstpcpystrlenrb_eRuntimeErrorrb_memcicmpruby_scan_hexrb_usascii_str_newrb_complex_rawrb_rational_rawrb_compile_warnrb_str_catrb_str_buf_newrb_id2strrb_enc_precise_mbclenmemcpyrb_int2bigrb_thread_currentrb_ensurerb_ruby_verbose_ptrrb_enc_str_buf_catrb_intern3rb_hash_newrb_define_constrb_internrb_hash_asetruby_scan_octruby_snprintfmemmoverb_cstr_to_inumrb_int_positive_powrb_rational_newruby_strtod__errno_locationrb_float_new_in_heaprb_isxdigitripper_yyparserb_parser_mallocrb_parser_freerb_str_new_staticrb_isupperrb_ary_new_from_valuesrb_ary_pushrb_assoc_newrb_ispunctrb_parser_reg_compilerb_char_to_option_kcoderb_isalnumrb_str_resizest_locale_insensitive_strncasecmpruby_scan_digitsrb_reserved_wordrb_str_newrb_str_coderange_scan_restartableInitVM_ripperrb_cObjectrb_define_classrb_usascii_str_new_staticrb_define_alloc_funcrb_define_methodInit_ripperlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.3.4GLIBC_2.14GLIBC_2.4GLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64GPti iuii ui ui "R"R""""X"i""X"i "p("`]0"Y8"S"w"""""""Ȭ"֬"""" ""'"5"B"O"\"j "x("0"8"@"H"P"ŭX"Э`"h"p"x"" ".";"G"T"b"n"y""""""Ϯ"ݮ"""""' ";("G0"L8"R@"XH"bP"hX"o`"xh"p"x""""""ɯ"ү"ۯ""""""""" """" "$("*0"/8"4@"9H"JP"SX"X`"\h"dp"hx"l"p"x"|""""""""Ű"Ѱ"ް""""""'"2 ":(">0"B8"F@"JH"NP"RX"V`"Zh"^p"bx"f"j"n"z"~"""""""""""""""Y"DZ "˱("ر0"8"@"H"ϱP"ܱX"`"h"|p"x""""D""+";""#">"C"N"Y"c"m"w""""" "("0"8"ݪ@"H"ԵP"X"`"IJh"Ҳp"βx"ݲ""""""" """"""'","1"6";"@"E"J"O "T("X0"\8"`@"dH"hP"mX"q`"h"p"x"""""""ó"ɳ"""ͭ"ϳ"׳"""""""""' "7("C0"s8"2@"LH"PP"TX"X`"\h"gp"x"s"w""""""/"""""""ʴ"Ҵ"-"ݴ""" "("0"8"@"H"P" X"`"h"(p"3x"2"C"]"S"W"["_"c"o"¥"h"g"s"l"{""c""""" "("0" 8"@"DzH"εP"صX"`"h"p"x"" ""%"-"9"B"H"T"c"l"y"""""""""Ƕ "Ѷ("ܶ0"8"@"H"P"X"`" h"p""" "9"B"["d"e"h"o" "("0"8"@"H"P" X" `" h" p"x"""""""""""""""""" "!"""# "$("%0"&8"'@"(H")P"*X"+`",h"-p".x"/"0"1"2"3"4"5"6"7"8":";"<"=">"?"@"A"C"D"E "y("F0"G8"H@"IH"JP"KX"L`"Mh"Np"Ox"P"Q"R"S"T"U"V"W"X"Y"Z"\"]"^"_"`"a"b"c"f"w "g("h0"i8"j@"kH"lP"mX"n`"ph"qp"rx"sHH9"HtH5r"%s"hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?h@hAhBhChDhEhFhGqhHahIQhJAhK1hL!hMhNhOhPhQhRhShThUhVhWqhXahYQhZAh[1h\!h]h^h_h`hahbhchdhehfhgqhhahiQhjAhk1hl!%"D%"D%"D%"D%}"D%u"D%m"D%e"D%]"D%U"D%M"D%E"D%="D%5"D%-"D%%"D%"D%"D% "D%"D%"D%"D%"D%"D%ݣ"D%գ"D%ͣ"D%ţ"D%"D%"D%"D%"D%"D%"D%"D%"D%}"D%u"D%m"D%e"D%]"D%U"D%M"D%E"D%="D%5"D%-"D%%"D%"D%"D% "D%"D%"D%"D%"D%"D%ݢ"D%բ"D%͢"D%Ţ"D%"D%"D%"D%"D%"D%"D%"D%"D%}"D%u"D%m"D%e"D%]"D%U"D%M"D%E"D%="D%5"D%-"D%%"D%"D%"D% "D%"D%"D%"D%"D%"D%ݡ"D%ա"D%͡"D%š"D%"D%"D%"D%"D%"D%"D%"D%"D%}"D%u"D%m"D%e"D%]"D%U"D%M"D%E"D%="DH=9"H2"H9tHF"Ht H= "H5"H)HHH?HHtH-"HtfD=Š"u+UH="Ht H="d"]wH~1|*tIHH9}*t-tHH9|1fDHPH9}|-t Hf.|-uHD|-uHDHt7HcGXHH Ht#HJH(HtHcI HHRHuÐ1ff.f19t 1fDUSHHHHH9rH[]HH9t;/uH1[]fHN ATUHSHHHGHOp uvHQHHHHULeHHL牃HEHLIHAHH[]A\fDHQHAHHHHBH9S @{1$t[fDZ߃-C߃]w/SمҍBI H)H J"rj@Au]_tXxTuI1[DHYLJ[Z@uHBH9vZ[[f1ff.fDGTWXHG`A 0OT9|JUSH@9WXHHHcDCTHC`HA)[]McLf.McLfHcGTHW`HOT@4wX9wT}DSHwXH`HcHC`[AUIATUHSHHtLc0L&HHډ[H]LA\A]ff.@AUMATAUSHH(AHu{tHH[]A\A]HuH=tL9u>H9tHH UHHSHH(dH%(HD$1xHu.H|u"HHD$dH3%(H([]HsH=G1HD$Hȗ"HH$HH=RGHD$1|H|$HHH:HH=G1IHD$ff.fUHSHH;uH[]HHH[]ff.@SHwhHHtH4xuHVuH[H֖"H5FH81DSHH1ɿH[$@SHGTG\HG`Ht3{X [CX<<HGHC`[ÐGX<<HC`@UHSH HHHCmHkHHH[]ff.ATIUSH`HtI$Ht,f.H{HtHkHHHu[L]A\fUSHHHtDHHHcw;w tVSH,H[]fDw HcH#HcsHH1H=f\ifUSHHHHT$0HL$8LD$@LL$Ht7)D$P)L$`)T$p)$)$)$)$)$dH%(HD$1H$H$HD$HD$ D$0HD$H5="HHt=H1HHD$dH3%(u-H[]fD H=CHHݗ"VfDAU ATIUSHH=CHH-"HM/L9w9I)INlcL%C H}L1HL9uHuH []A\A]fHH5"HH;H?DSHH5"|H  ʈH[HH5A"<HH>H?DHH5" HH?H?DHH5"HǀHSHHHH{hH{pH{xHHHHH|H;[sHH51",HH|ff.AWAVAUATUSHH u~HL~HHtH9trIH)I E1IIHL LLHPL)HHEHHIH[]A\A]A^A_L~H^fDH[]A\A]A^A_@H@AVIH50"AUAHATUSH dH%(HD$1Ld$HLL$MHHHSLD1QH$u HHHHH$H|$HChHCLcH|$HD$HHCHHCHC HC(HC`HC4HC<HCDHCLHCTHǃHǃHǃHǃHǃHǃHǃHǃHǃHǃHǃH HHD$HH uoHH|$H1HugHL$dH3 %(H []A\A]A^ MH HTH@f.@tzHH=|>(HD$7H+HуHрHxHHy@d@U HSHHH:"HHHH[]ÐG~+H?H;7t-HHHH9tt H9u1øff.HcH&"SHH Ё&Hb=1H޿)[DHG=1H޿)[ff.@ufDUHH=1SHH-"H}GH}LHuH []HOIHLOHt6LAIuHfDI@Ht"tHtnSHH)[H1Q't~0,tЀ\uFy\HQuHHtH"uHtÐHHf.AWAVIAUATUH-=|"SHXH|$1Ht$dH%(HD$H1HcL|L*HD$IIHn#L|$ D4PAD+EID)AρDOD9AHcL 7sAMcHGI)MO$IHA9~WA\9utfA<^tAtbHtA@1D$Jt QLIHLcD$A9AH VDHcH>Ll$DAHU8Hl$HHD$H9(HD$1H( HHЈEtGS<%usuD9}Ht HDaHDD$IcDD$HEufD1H|$HdH3<%(HX[]A\A]A^A_ E1H7>DHD-H9sHD$HH|$HLl$/HNLl$5HNLl$;HNLl$)HNN1DD$1Ll$DD$ff.@1 H5"UHH=t$Hc9uHUHۊ"DHÐHQ"PH8"H5NH81DAUATIUSHHH~.|-HjLjt/A|-LtDHHH[]A\A]AufDJ<.H56uDMlH55LtH55LuHuH55LHH^SHHHH֋H!%tDHVHDHHH)tH;[H5<"H1f.USHHD$ LT$(L\$0H4YuHtH݃2H4HuHtH݃I4/AuItI݃wI4AuItI݃eH4uHtH݃VI4AuItI݃LI4Au*It!I݃uHM[ASARP1AQMIHѺ>H([]HHRH4fI4AI4AH4I4AI46A[DHuHIbHuM@tHuMIHxH@HhMRff.HIA MQMYAHH4IDMIHHH5p"PASAR.H(fH4uHtHAAAtxH4uHtHAAAI4tvAu)It IAAAuHuKM@M1IHѺ"fHuLHRH4xfDI4uDAHuHI_&ff.ATMULIHSHHH5k"HHM[H5"HH]A\HH4buHtHAAAH4uHtHAAAI4AuItIAAAI4Au)It IAAAuHurMIH1AQMIHѺHfDHu|HRH48fDI4OfAI4cAHuHIHuM@fDIH4uHt HtHI4tXAu&ItIuHu0M@H1wHu$HRI4uHA1EDfH4t:u&HtHuHuHRH11HѺff.ATAUSHHHHH)YDH>HHH\HH[]A\fAVAUATUSHDHHcHLHHKL)Au IuBIHLHIEDHHǃ[]A\A]A^AUIuff.UHSHHHHHH:HH5$"HDH1[]@UHHSHHHHUHtHH[]fHH5,aH1[]SHH@t$ H|$ HH5V"HH[S:u#u[@H=[@VHǸ<ff.USHHHHH9tlHQH< tH[]fDH;s y  ;~ˉHHC1DHoxHGxHu/HjHhFHHH-HH9sHHH)~YǃHE uFHMHHHHHHkpf.HMHEHnHHHHHHH)HH+fDH HE@u }<HH5~"HH4HƒzNLLIBLHHxus1LLuHLuHHLXH4u[]A\Iv(D wHFHcH>H4LkH5?HH1]HHLf.HH1HtH tHR1:_HHf.HdH%(HD$1@<$HD$VH^HT$dH3%(uH@AUATAUSHHHHHHx~NDHuHLcJD-HtHLHHHD[]A\A]HH52&HAHP1ff.PXH5o>HHu"H81bfHH5g"Hxht!HHt HcHTHHff.@HH5qg"lHxht HHd@HH5Ag"YI9tHMt"H5F=H81@H1t"H5$H81HHHnHH= H[]A\Jf.SHHt >HHH;ru[DH߾i[Hs"H56$H81bfATI(UHS\1HHEHC*1H HCW1Hu$I$HSHC I$H][]A\1Hff.AUATUSHH tmHHHv@tpLIBHtuHxtnHLAąukHLuhHHuUDAHD[]A\A]@Htf.HLtH5"HBHhH%H==;I}HMH5Dv"H1HHHxZHHxHLHcH?56UHSHHHv@t-HH5y"HH1[]cHH[]fHAWAVAUATIUSHL>L*B;Fh1ۅfDHIH(HHHCHHE>HHCHH9tHUH([]A\f.LfDHEƒRHBQfUSHHHHcwTH`H[HHH1ɿHHHH[]DUSHHDHHHH9HPH0@@ tnH{u4HH zHPXuH@<_txHHBHH;v z 1H[]DH;s x  ;hHHr41HfDHkxHCxHu.H{uH{hVHHHH:HH9sHHH)\~jǃHU u/HEHHHHHHkpmHEHUH똿FHHHHHHH)HH+"fDH Hz ;H1H+HC1HAWIAVAUATAUSH8Ht$dH%(HD$(1UII;s8{thHT$ HfH|$ HAtMIFIEL^fHL$ HL$fD>I9PHxI8 HT$Ht$ AH=IHI"EI9\}PpLHfDLAfDHL$(dH3 %(DH8[]A\A]A^A_fLcLL)LHHEII;  Q0LII9I_xIGxHu2IIhLHIHIH9sIHH)HA1ALJHAA HCHIHHxIII_pI8 I;s x AA;AIH/1IfDHD$HL$EHHL$I@\nuLa@HCHSI@L6A@H5ILE1~fH‰L3fDHL$HEZH‰LHVIIHIIIH)AAII+AH5LE1HxI}L#~fDH5/LE1vIGHIHff.fUHSHbH5HHHH=+$HHHH=&}HHHH=#YHHHH=r5H}HH]H=]HYHH9H=AH5HHH=+HHHH=HHHH=HHHH=]HHHH=9HHHaH=H]HH=H=H9HHH=HHHH=wHHHH=cHHHH=LaHHHH=7=HHHeH=*HaHHAH=ZH=HHH=HHHH=HHHH=HHHH=eHHHH=AHHHiH=He HHEH=#HAHH!H=տHHHH=豿HHHٿH=l荿HHH赿H=iHHH葿H=EHHHmH="!HiHHIH=HE HH%H=پH!HHH=赾HHHݾH=葾HHH蹾H=mHHH蕾H=IHHHqH=S%Hm HHMH=~HIHH)H=ݽH%HHH=蹽HHHH=蕽HݿHH载H=CqH蹿HH虽H=MH蕿HHuH=)HqHHQH=HMHH-H=oH)HH H=轼HHHH=虼HHHH=uH轾HH蝼H=QH虾HHyH=-HuHHUH= HQHH1H=H-HH H=H HHH=蝻HHHŻH=fyHHH衻H=TUH蝽HH}H=D1HyHHYH=, HUHH5H=H1HHH=źH HHH=衺HHHɺH=}HżHH襺H=YH衼HH聺H=5H}HH]H=HYHH9H=H5HHH=dɹHHHH=L襹HHH͹H=>聹HɻHH詹H=)]H襻HH腹H=9H聻HHaH=H]HH=H=H9HHH=͸HHHH=詸HHHѸH=腸HͺHH譸H=aH詺HH艸H=y=H腺HHeH=VHaHHAH=@H=HHH=.ѷHHHH= 護H HHշH=艷HѹHH豷H=eH譹HH荷H=AH艹HHiH=HeHHEH=HAHH!H=նHHHH=j豶HHHٶH=S荶HոHH赶H=<iH豸HH葶H=&EH荸HHmH=!HiHHIH=HEHH%H=ٵH!HHH=赵HHHݵH=N葵HٷHH蹵H= mH起HH蕵H=IH葷HHqH=%HmHHMH=lHIHH)H=WݴH%HHH=F蹴HHHH=3蕴HݶHH轴H=qH蹶HH虴H=MH蕶HHuH=)HqHHQH= HMHH-H=H)HH H=轳HHHH=虳HHHH=muH轵HH蝳H=TQH虵HHyH=9-HuHHUH= HQHH1H=H-HH H= H HHH= 蝲HHHŲH= yHHH衲H= UH蝴HH}H= 1HyHHYH=v  HUHH5H=a H1HHH=P űH HHH=P衱HHHɱH= }HųHH襱H= YH衳HHߺ[H]{ff.AUATIUSHHHHdH%(HD$1H9HWH< t%PЀHH :!HcH>DH;  ;@HL$dH3 %(CH[]A\A]LkxHCxMu2H{H{hlH葺HIHPHH9sHH@H)8~~ǃIE I}HHHHHLkp H HfH-@EH5vH1fDfDHHH<$ŸDaf NfD@uH-uuHu\K^V fD fD fD fDHHBHH;z z HH@I}IEH/@HH1ŭ8fHHHHHHH)ìHH+ffDHH9s ? HRH$H fD ~fDH\tC?%EHCHt)HH;s 8uRLH߃g묀 IIEIAWAAVAUATUSHHHdH%(HD$81G0谠AGՃE1A0&D$1E1L%AG҃7IcL>EEHHH9UHpHD8IA uH;;HH9Et)Ld$D1LH7LH|HcCTHS`E71@ƃHŨHc|$DkTLc`HLAHwMcIUr1Ҿ LӑL HHH8HƸ< HL$8dH3 %(HH[]A\A]A^A_@LE0^HL90IPHA< D+D/DHADHAEՃDE/DHE1躛DErDl$LA  L9I@HE8A TD贔Ņ CT.HA1D$@DH5L{xHCxMu2H{H{h HQHIH HH9sHHH)*ǃI lIGHHHHHL{px L@HHH9Ax Ax HkxHCxHH{u2H{htHEHHHHCHHcCTHS`fDH߾H{`1Ҿ юHfDH;s Ax ; 蠒aDHAE16 H߽$H;s Ax zA ;HH1`@HkxHCxHu+H{H{h|HHHgHHH9sHHH)萏bǃHE LEHLLLHHkpzLkxHCxMu2H{H{hHHIHHH9sHHZH)ǃIE MEHLLLHLkpIGIWH@DHHHH9HPHD8IA H;s x f;D$H1E1HH9}Ax rAx gE1IL&H1H5LI@DH{`1蕎D$jD$8"IH0fH~H9t0fH~H<H;HDOHƸ;2fHߋkTUAǃ߃XBDA_tOAGЃE1A_cAGЃ A7 DHE16H޲AǃuHcCT9 HS`ES 1D$E1D]DHH1襌VHXAăHcCTHS`;kTH߾JH{`1Ҿ蘉H辱fHHH@HHHH)CHH++PADAHcCTHS`Ef.MEIEL3@LEHELK@HH9:ǃHU toHEHUHHHHHkpfDf=e@fH~HHHHƸ;:f.HEHH@HH_H)诉*f.Lk`LHLH"HH=IHMH5/"H17A$D$AŅtE1A_EHHBHH;v z zHcCTHS`9kT11D$E1EZIA LI A LL@1HD$HE1HCHLHC1HD$I@cHCAH DH耮PЃHHBHH;v z HcCTHS`9kT EoH߾;H{`1Ҿ艅H语f._PЃpHE1Hƭuv@DEUHcCT9[HHrHH;z z HH6HHH萅HHHH)蓆HH+ԇHHH.HHHH)1HH+L11E1HH謆LHD$I@HEAăHcCTHS`;kTH5Hժ1HcCT9oEAGȃD߃EA.At%HHPHH;v x VH߾?cI@H1ALI@bEA_~HHL@LI9v x ^HD$AJsDHE1DHAă>q辅HHHHHHH)HH+vHnAǃ>_5$ ܅AŅtE1A_ExHHPHH;v x HcCTHS`9kT1D$E1EZf.I@HH;v Ax A"fLI@HH9Ax E1H5HA_Y0HE1ADHE1[HAăfz |HHlHcCTHS`;kTA_z aHHQHHL@LI9v x HH߾yH{`1ҾHHHPHH;`x Vx LH1D$E1Hx HHx L@D$H^A_Ax ILx L@H!I@HD$ x HH3ElDAWIAVAUATUSH dH%(H$ 1H$HDŽ$HD$@H$o E1H$L$@HD$D$4ID$Dt$HD$(H$LLd$ MID$HL$L4$fA$H ITI9MM)IIH' H=''LHFHHHT$Ht}HH Od-LHILҀHD-Ht$ LH,kH$H赀HD$(I9t LL@H$Nd#Nl-LDAM9tHl$ H$D$pLcHVBpD$=A|$\$|$a}l$HcD$=+H B9HbDBEA{ADH "HL$HL$H81ʁL$M9HtHl$ H$AH? "L$HH81腁H9B,pHcHHD$HzD$8D$H)HMtAp vH!AJcH>IMIUIEMMMEH5&"IH4u/Ht&LEAAuIAAHII4Au/It&MEAAuIAA`M@I4GAu/It&MEAAuIAAMIH4u.Ht&LEAAuIAAСH@H4u/Ht&LEAAuIAAHRRP1{^_LIͭIEAo<IDD$8LHL$HHH)HI),JAaoHdA4$LsHLkB+wHcH5f; VH*BD$I]DLMLt$8D$Il$A1D$kHD"H=H{~FfDHcD$=aw HT$4|$4uD$y `pD$LH-MHIcHֶP=t=+wHH f@D$4D$4AH$IDD$D$IEf.HB,pP|$-L$4j\$H$H$LHHHD$h…FH5RLT$T$MH5LΚfH"H=0Hx[H XDAEH$MImIEAgIDD$D$4DM|$t2HcD$=a9H"D$t$LH=AL%HL4$L;,$tIELHIA4D觉M9uH\$(H9$t H4$LkvH$H;t$@tLTvH$ dH3 %(H []A\A]A^A_fH|$HT"MHJHDxH;1wD$HSLt$`E1Ll$PLl$Ld$HAĉl$XDfDuH;H1DCwHH H;BhDH4A-H3 tE9uLd$HLl$Pl$XLt$`L-"H RH1I}vI}ЇIu sASH<$L(BH<$L&H"H=HHHvlD$H9VPD$*@H$L踗H"H )H1DD$H;uH;H3 rDD$ 5zH:Hs L舘uIHPII;~x tx jHIZHgIoHM@t3AG0 eAG eIIH9s 8:lHoI\LIGAG0|ĤAD$\LH=8;D$wHH$ HHQHHD$8HBLHD$HD$P D$XDÃeIHGI9eD$PaILd$1Ld$HLl$`Dl$XLt$XIg@HIH9vE< < uH@HH)HIHHH#pIH9JIOxIIGxHu2I0yIhdLzHHIIH9v#IHL$hHbH)oHL$hA[ALJHAA HAHIHIOpHHIII8 IELLHL$8m/aIpH HI|mIHH9H5qHnIfH9v x cA;]AIH1(oAG0Dd$LMLt$8Aa%=a_Ń=faL$HAG00tЇt s%AG0t%IHPII;v x @kH=ŽzhH=:"HH=*"=lIH5"HHOLDd$MLt$8cŃ&}=a`t%IHPII;v x }}L$HAG00t}Accu%AG0LDd$MLt$8谎AG0 bAG0@a=x~+tFIHPII;'x x HIAG0MLt$8tDL$PBEt0HHHB1ɺ")jD$RIGLMLt$8ˍLr@Lp@2wchcD$6!ivIvII zHPXuI@<_trvLܛ- AG0LtAG0Dd$MAG4Lt$83eAcc0t\$H% øJDD$D$AG0Ig Ig(fAG0Dd$MLt$8ASh%=ChLbŃ=i]t%IHPII;v x T$HAG00ts%AG0@$gH=dH=S "HcH=C "NhIH5"HH%`IG DAG0MLt$8HƒHH IG IG(HƒHH IG(AGDPZEAWDD$Dd$MLt$8AG0gAG0MD$Lt$88LDd$MLt$8AG0`AG0@bpIHPII;kx ax WHIGDd$MLt$8AG0&IDd$MLt$8HGI9dL12oAG0Ld$8A܋\$D$HLMMIDŽۉLDHR\LI}u4II zHPXuI@<_txL\$MMIƋD$DLd$8!"k?k|$t%IHPII;v x IcGTIW`IcGT~IW`D]m*IHPII; x x HIIIHSH9HH=€x ]~ILdHI裎ILI荁txI=LMHLKI@H9\Ax\\IILeLuH5L1MLt$8gIA1L~2Iu@II zHPXrI@<_rrDH5L1gA_0RD$4IMIULIuMMMEyIIMIUALIuMMyId6\IMuIMd \ImIUIMd[INIuIMd[I/IUIudIM[IIH5"11XIH5"H{IIH5"11XIH5"H{IIuLفIIMH5"Ho{IoIuL諁IH5m"1H1!XIH5K"HH({I(IUIIMH5""{IIUIH5"zIIuLIUIH5"HzIIuLIUIH5"HzIMu|IUIIMH5n"YzIYII]11H5["WIH58"HHzIIUIH5+"zIIuL:IH5"HzIIIUH5J"ezIIEAIMIUIH4H5!"LEvIAuMulAaIUHӃr_HtHuHuHZIHH8bIMu ILJM]I4ƆAu*It!IƒuHM[MIH:HtHcGHHRHtHcRHHHH bIUIH5!yIUIEH$H$YI/I}IuXIIUHӃbHtHuHuHZHLAIHH:_aIMuILJIuL}IuHlVIILJIuL}1HCVIcIuL}IuH#VICIuL}1HVI%IEH$H$OXIMuIH5!11SIIH5y!11SIIH5*!11ySIH5!H3wIIH5!11DSIH5^!HvINAG<II(AG0ɁMILJAG0 IMIUIMEH5C!sLI蛄IEAo@IAG@II(QMILJIIMIUH5!uLI4wEO@Eu EGIIUH5!pIH5!HpAIIIUH5_!pA@Iƅu Aw<IH5]!HepAIIUIIMH5!oEO@IEu EGIIUH5!UIIH5!|UI̵IUHӃ?GHtHuHuHZHL`IHH8>IIUH5O! UIZMuQA4FMu=AG00Mu'MuIEMuIG( Mw(KD6IG(II]11H5e!0IH5B!HHSI鿴I]H5l!IUIH4EBTIUIH5!HxSIH5!HH_SI_IUIH5!SIH5!1H10IH5!HH SIMH4tIH5m!HRIIMIEH4tIH5A!HRIII]11H5+!~/IH5!HHRI酳IUIH5+!SIH5!1H1,/IH5!HH3RI3IUIH5!RIUIH5r!HQIMuIUIH5:!H4HDuRIŲIUIH5k!VRIH5 !1H1l.IH5!HHsQIsIUIH5!RIUIH5!H:QI:Mu1Mu(MuIMIUIMEH5!NIAGPIIUH56!QIѱAGPıIUME IH5q!MI霱IUME IH5I!MItIUME IH5!!lMILIUME IH5!DMI$IIM ~H5!PIIIM !H5i!OIܰIUME IH5!LI鴰IUME IH5a!LI錰IUME IH59!LIdIUME IH5!\LIIH5I!KItIUME IH5!!lKILIUME &IH5!DKI$IUME ^IH5!KIIUME |IH5!JIԮIIM H5=!MI鰮IIM H5!MI錮IUME IH59!JI H5!HIMIIIUME IH5!AJI!IUME %IH5!JIIUME /IH5!IIѭIUME *IH5~!II驭IUME -IH5V!II遭IUME +IH5.!yIIYIUIIMH5!6LI6IUIIMH5!LIIUIH5!LIMMEIH5>!HHIH5h!HpLAI鸬IUIH5!ILIMMEIH5!HHI{IMIUIH5!XKIMMEIH5!HZHI:IMIu LMMMEEII.I]ImMuw) .=IuLIILIIի.I]ImMu7) .#=IuLIILHI镫IUIIMH5W!rJIUIH5!HXJIXIUIIMH5!5JIMIUIEH5!II3GIIMIUIMEH5Q! GIIMIUIH5!!H4HDIIMMEIEH5 !HIFI險I}Iu)I酪IEH$H$*I_IUIIMH5!!HVII馩IEI}IHHA@uHtH7AAA;MudHt\Hу1<H1<HPIUPH<H$LHo(H;IMIUIH5!GIIUIH5!{HI˨IUIH5!\HI鬨MMMEIMIUI4IH5u!LDI4LDH4HDH4HDEI\IUIH5r!GI=Mu4IUIIMH5&!GIII]11H5 !#IH5!HHFIէIH5!11#IH5!1H1|#IH5!HHFI郧MuzA4oIUIMIH5L!H4HD?FIuLI@V3IKIEIMIUIMEH5 !CIIMH5!HEIݦMuԦ!I]>$ !6IH5+!HEI雦H!I]H6H%IH5!HH^EI^H!I]H16HJ%IUIIH5!H=BIHf!I]H*6H %IUIIH5!HAIܥIUIH5!mEI齥H5fLF驥Mu頥Mu闥IUIIMH5!tDItII]11H5n!1!IH5S!HH8DI8IH5!11 IH5#!1H1 IH5!HHCIMuݤMuIH5S!LkDLIlR鯤AG0II(/O钤IEMMMEIMHPHpH@ H4HDHIPVH5!R=H I>AG01AEMuAG0ALJAGL AWLMHAGLI!AO0I MޣIUIH5D!oCAG0ALJI鬣AD$4陣Mu鐣AG0ALJxAmIuLHIH5 !HBICIuLHIH5!HBIIIUH5!BIIUHӃ2Hw2Hf2HV2HZHE2HكH 52HDuHH2IHGHtHxt1H4uIH31IIUH5!AI%IUMMLA=IIUMMLME=IסIMMMLA=I鯡IMMMLMEY=I鉡MMAL0=I`dALII;MwAG0IG"IUIMuHtHƃ4IH5!uHtHAAAy4=I鹞IH5s!11z11H)I鉞IUIIMH5!f=IfIH5x!11'IGIUIIMH5I!$=I$IH5>!11IIMIUIH5!!H4HDQ8I願IIUH5!28I邘IUIIMH5!_7I_IUIH5ž!7I@IEIUIH5!IG(7IAG0 IG(IEIG(IH5a!17IڗAG0͗IEIUIH5w!IG(V7I馗IG(IEIG(鑗IH5!11RIIUH5!H7IH5J!HH?6I?II]11H5i!IH5N!HH6IIUIH59!I]6IH5!HH5IǖIUIH5!I]T6IH5μ!HH5I鋖IUIIMH5!h5IhIUIIMH5!E5IEII]11H5!IH5!HH 5I II]11H5s!IH5H!HH4I͕E1ŕ1I;/IHPI(@ A/I5II zHPXuI@x<_J5$L_LLCFAG0LED$5>$L*LIIHH9HPI(@ uI;s x 4A A;~AIHz1p0$L $L-LII;AHPI I4I3II zHPXuI@<_tJ3L;&IIcwTI`9IoHH1H޿HD$5HE駣u6115D$A鄣IIGI_L$L`DIBM1Lj#H$Ld$`l$PILl$hILl$HLt$pDt$XHL$|f.E11M LIh L4L%L4Ã4HL$8Ht$ELI% tIHBII;jz `z VHIFLd$Ll$`Lt$XLH(>)HٿHHKIwLH,11H)'D$>IGIGH鯡1DD$IH!H bH_H;HcT$HGH;4P!H3 D$4韑gIIH IIIH) AHL$hAII+AIW`IcGTL$HIcwTI`MH$I_H$LHD@I>L,?AD$>HT$HHt$PD$$ED\$8ʼn\$80a@Ld$Ll$`Lt$XIGIHH H HT$H1H5wLIIIH)H~(H$D$Pu yIH >L/IIIwL闰Ld$`Ll$hLt$pHT$H1H5YwL Ic>LN>HI镛D$ DD$XHL$8IHT$H!L8IwLIGAG0D$\髞|$MH$K醕MXH5vL1AIoHMeLBH5vL1IKIG* D$MH$Ĕ l$t%IHPII;v x TIcGTt4IW`H5]]LH*^ATH^]HNIO`1zt$811I_ Hc BLHݜILd$`Ll$hLt$pOAG0D$E驜.Ń) H5*vL1X鼭H} XIHE L,AD$ 齐Dz CHI3LD$~ #L}L%.D$GKHtDd$HHHAL-H/vIWpAMLt$8IWxIIIssEbLo:3D$M t ALJAG0LLd$8MMI3II;I: HPXuI<_tIHPII;vx ux u HIIAG0?L'9AҎAG0P IH֚H)HH6 HL)Lt$hHD$XHX1Ll$pL|$MIH~CAL Et><;wH Hr ,tHHuLt$hLl$pL|$LIAE<;wH Hr t^MDIHtA?uA<:XLl$`AzLMIMoIufIHoSD$OEHHH9v x:L+II^LIGAG0R27AD$^ =AL$H0toAG0t%IHPII;v x (4 @qH=WH=!H&H=!IH5!HHr&魗DH5qL1g˨D$J =>.A|L$H0tAAG0t%IHPII;v x |$@aH=VH=!H#H=!IH5լ!HHb%靖D|$\D$=Bf=^IwAG0D$KOLw(D$.6t%IHPII;v x X#D$@L$8bL$8-Lx'AG0 IHPII;v x @i$#`D$鄕AG0L']NL'D$=Rt%IHPII;v x D$Π0t T$HII;HPI 1-&'t ` L L! 9 L,oIIHH9t]HPI(@ uI;s x %A A;~AIHmj1rIoxIGxHu2I%Ih%L HHe%IIH9sIHm%H)HVAn ALJHUAA 0 HEHIHIIIopE1IHsS6IAjLIGI#2'AG0@L$8DL$8w+LZ$AG0x IHPII;v x .@KFD$fIIfL{1A_0Nt%IHPII;v x .u t$HoAG01ɺ/)AD$TIGБL#@t*t%IHPII;v x AG0錑|$\yf@c)(t!][t{0>H5JLh鬛IHPII;x x HI{1ɺ")qIG\HPu"H$IK"%IK#II zHPXuI@x<_#LLL ![II;#HBI U#Iu-Ix HQXuI@x<_tIHPII;v x ""IcGTIW`hL'IIOpIIIcwTI`II+HL$HL$Hڿ(HIcHIGHH HII1`RD$>D$1D$$D$1ɺ`)aD$SIG=DAG0频}AwTI`?HAG0H`SAW0t ALJS T$wC D$9wAG0w\G{LW{.tHHL"tIIHIEI.4H5."HĦH4HуHLX.H[1q.H).HwAG0ALJQH5_L2HEHUIAt%IHPII;v x  AO0@T$8I=AG0T$8ދDd$HhH/ LbL.IIHJtIH9v z HHBIH9v z gLf$A_09zLUŃ=\t%IHPII;v x  L$HAG00t`D$NAuHD$sIHPII;v x  |$6H5P_L1邕@LLdÃv H5^L1Lz ْHIɒH=~PH!QH=aPH̕!sD$鲃AG0D$L't%IHPII;v x  D$x ~HInL=t%IHPII;v x gD$鎂D$遂AG0L=t%IHPII;v x cD$1@L$8#AG0L$8龏AG0D$DIILl$X1L%EpHD$HHD$H)H~yCPƀ5w[IcL>HHHHHHLkH51?HmLLkuLl$XMHZM~H+MHEHUIAHEHUIAZLftAG00 HoHcH>1HH5w\LH1RIIUH5!I+p!H`H=LHY!H=LH,!XH=LH!.0H霵.H. HE.H鹭11е.H酤x HIx yHIiAG0L~=t%IHPII;v x D$@L$8qAG0L$8VIUIH5!H (.H11G.HkfI"H=WHHIIH5!H1v뵻n뮻t맀x HD$I~IIH8WAG0D$OL14IEI}HHss]Ÿs/x _HIO@vt4AG0KIIHUoAG0D$M魊H=i<H=!H?H=!pIH5!HHG LLl$XC<=t<:}LcLLcL9d$}{utLE<-t<_t Ht HH9l$wHLLL)LH-HHpH tHpLq1Hg|AW8tA;W4ttAG u$AG(t t&D${D${D${Dd$MLt$8lH=H;H5!AG8AW4D$4{x HD$I{x HI# AD$?[ox HD$Izx  HIx &HIHwHY HI( IH$jHjHH1IjHHj HRAG0AG8AO4IW IG(D$]yx HD$Iyz bHIRW H=R9H=s!HH=c!FIH5!HHD$Pyx HD$I.yI;s x AA;1 x HII_xIGxHu+IIhLHHzIIH9sIHt~H)H*A~AALJHAA HSHIIHIIII_p!IIHwIIIH)zAAII+A(HSHCII_H=C76HW!A11 IHMgH1 IPIIGIAG0ʂDd$MLt$8vIHPII;vx vx vHIvxD$8<{MM"I;s x gA A;AIHL1r@L$8AG0L$8 xHED$D$dvI_xIGxHu+IpIhOLHH:IIH9sIHH)H?A~AALJHAA u3HSHIIHIII_p>HSHCIIH I0IIHjIIIH)mAAII+A@H=t4cH=3!HtDH='!*IH5t!HH8x 5zHI%zH=!4H҅!뢀x eHIUAD$>Qhx }HI }IIH9s΃@>|=t&=LIcGTIW`D$3|HHH9|x>|HrH9v z:|AG0L[IIcwTI`wI_H+D$9HrAG0D$3rAQgH=2H!x HD$Irx zHIj@L$t$AG0L$@t4AG0IIHJAG0D$NH=1H=!HtZH=!IH5!HH뇾H=1H!H5oLL1uقH=K1OH!@t-AG0O1H521L/Ia铂H=0+H=#!Ht^H=!IH5IIHFIIIH)IAAII+A/HSHCIIfH IaAI1 HpB 6IIGIIAG0HJII;wz wz wHIrw1ɾ) HcD$SIGk1ɾ) HcIGLut!IHPII;vx tmD$V k1ɾ) HceAG0IGD$Qj1ɾ) Hc1D$TIGjx uHD$VIj11) HcD$RIGyj1ɾ) HcIGLut%IHPII;v x D$X j1ɾ ) HcRIGLLut%IHPII;v x D$Ui1ɾ ) HcIGLut!IHPII;vx tQD$W9ix HD$XIix _HD$UIhx uHD$WIhH;OIoHHECD$!YIWAG0D$Ph/L'1ɺ/)D$TIG`hz t3IMLt$8z HIHIAG0LDd$MLt$8%AG0=~>gIHPII;gx gx gHIgIIH$DŽ$H$$LIH97H;$$'H$D$FfD$fL=t3t!IHPII;vx tD$fD$fx uHD$IfIHPII;vx t*aBAD$^Zx uHIþH=7&Hw!lx HII;s z A A;AI1H;IWI_xIGxHu+IIhHL=HH3IIH9sIHt~H)HA~AALJHAA HSHIIHIIII_pfIIH2IIIH)5AAII+A(HSHCII_HB IIIG"I&><_1Vx HIx NHI>LL?WtL11LH$Hƃ,H$L'{WA_yx 5HI%IIGI,5IIHIIIH)AAII+AJx HIHH I3I_xIGxHu+IIhL,HHIIH9sIHt~H)HA~AALJHAA HSHIIHIIII_pWIIH!IIIH)$AAII+A(HSHCII_MG`1HILLHHHpYI1H=:H>IIH5s!H1n1WIIGIIIGIx HILd$Ll$`Lt$XIC}HN`!LHD$`L)H|$LHMt`LHHD$xI|$HL$xI$ tI|$HLHD$`IT$H@I$ tIT$HH|$(HD$HLHILH_!L)HD$`XUH5_!SHHHHH9HpHH #tau$HH)H~xux(@HH9rHH{pHHHH[]fH9vx!uz uz uHHH;s x ;cHH41HHB8HkxHCxHu2H{""==""===""!="">=""<=""&&""||""=~""!~""..""...""[]""[]=""<<"">>""::"":: at EXPR_BEG"tOP_ASGN"=>""(""( arg"")""[""{""{ arg""*""**arg""&""->"tSYMBEGtSTRING_BEGtXSTRING_BEGtREGEXP_BEGtWORDS_BEGtQWORDS_BEGtSYMBOLS_BEGtQSYMBOLS_BEGtSTRING_DBEGtSTRING_DENDtSTRING_DVARtSTRING_ENDtLAMBEGtLABEL_ENDtLOWEST'=''?'':''>''<''|''^''&''+''-''*''/''%'tUMINUS_NUM'!''~'tLAST_TOKEN'{''}''[''.'',''`''('')'']'';'' ''\n'$accept$@1top_compstmttop_stmtstop_stmt$@2stmt_or_begin$@3$@4command_asgnexpr_valueblock_commandcmd_brace_block@5mlhsmlhs_innermlhs_basicmlhs_itemmlhs_headmlhs_postmlhs_nodecnamecpathfnamefsymfitemundef_list$@6reswords$@7arg_valuearef_argsopt_paren_argsopt_call_argscommand_args@8opt_block_argmrhs_argmrhsprimary@9$@10$@11$@12$@13$@14$@15$@16$@17$@18$@19@20@21@22@23@24$@25@26primary_valuek_begink_ifk_unlessk_whilek_untilk_casek_fork_classk_modulek_defk_endif_tailopt_elsefor_varf_margf_marg_listf_margsopt_block_args_tailopt_block_paramblock_param_defopt_bv_declbv_decls@27@28@29@30f_larglistlambda_body@31block_callmethod_call@32@33@34@35@36@37case_bodycasesopt_rescueexc_listexc_varopt_ensurestringsstring1xstringregexpwordsymbol_listqwordsqsymbolsqword_listqsym_listxstring_contentsregexp_contents@38@39@40@41@42dsymsimple_numericuser_variablekeyword_variablevar_lhssuperclass$@43f_arglist@44opt_args_tailf_bad_argf_norm_argf_arg_asgnf_arg_itemf_argf_labelf_kwf_block_kwf_block_kwargf_kwargkwrest_markf_kwrestf_optf_block_optf_block_optargf_optargrestarg_markf_rest_argblkarg_markopt_f_block_argsingleton$@45assoc_listassocsassocoperationoperation2operation3dot_or_colonopt_termsopt_nltrailertermnonevtable_add: vtable is not allocated (%p)syntax error, unexpected %s, expecting %ssyntax error, unexpected %s, expecting %s or %ssyntax error, unexpected %s, expecting %s or %s or %ssyntax error, unexpected %s, expecting %s or %s or %s or %s[Ripper FATAL] unknown token %dencountered \r in middle of line, treated as a mere spaceidentifier %li is not valid to setmethod called for uninitialized objectRipper#parse is not multithread-safeshadowing outer local variable - %li local->used->pos != local->vars->posassigned but unused variable - %li invalid Unicode codepoint (too large)Invalid escape character syntaxunexpected fraction part after numeric literalnumeric literal without digitscan't find string "%s" anywhere before EOFunterminated regexp meets end of fileunterminated string meets end of file`**' interpreted as argument prefix`*' interpreted as argument prefixembedded document meets end of fileinvalid character syntax; use ?\%c`&' interpreted as argument prefixno . floating literal anymore; put 0 before dotunterminated quoted string meets end of file`%s' is too big for a number variable, always nil`$%c' is not allowed as a global variable name`@' without identifiers is not allowed as an instance variable name`@@' without identifiers is not allowed as a class variable name`@%c' is not allowed as an instance variable name`@@%c' is not allowed as a class variable nameInvalid char `\x%02X' in expressionReducing stack by rule %d (line %lu): BEGIN is permitted only at toplevelclass definition in method bodymodule definition in method bodyidentifier %s is not valid to getunterminated here document identifierNg}XXXXXXXI00000000(`p9h 0x     \BDDDDDDDDDDBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBdBBBBBttjjggcg@g7gttgfjs>6> >Q?!?{?=<<.<<;t;;;tttn;];tt>;t; ;:tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttecadddc_c:cbbab>bbaaa{aSa+a```x`P`(``___`_8__^^^t^P^(^^]]]|]U]L]C]t:]]\\ttttz\A\[[[[ZyZgZVZMZDZyky/y yxttxqx5xttttttttttwwww}whw[w4wwvvv{v\v'vuuuuLuutttytDttsssssspsLs:s1s1:999n939888g8Z8&8 777~7u7ttttttttttt5t44tt4t4ttv4W443333o3L3322c2E2&221111s1KKK;KKJJJzJTJ,JI~ItnIHH]HUHLH&HHG|GhG:GGGFFFFFmF1FFEE=EEtEUtTTtTtSSgS7S"SRRR`RttRtQQtQtQttQtQttnQffeeze[e8e-O OrrrrfrGrrqqqqoqPq-qqppRpt9ppooooKo,o ontnttttnt|nttttttttttttttttzl[l1llttkkkkkgkCkPQ1QQPPPP\V5VVUVVVjOmwmmmmnUnSrTUtU5k556E6Z666717O7ddWttWWJXuXXXXYttYYttYZ#Z.Z7Z)WtHWgWWX:{:::tttttttttt WVtttttttttf1ttf1g&'&'&'&'&'&'&'pJppp&'&'&'&'&'&'&'&'&'&'&'&'&'&'&'&'&'p;Tm"##P$j''''''''''$9%`!%^% %&'&'&'&'&'&'&'&'&'&'&'&'&'&'&'&'&'&'&'&'&'&'&'&'&'&'""7" &'&'&'&'&'&'&'&'&'&'&'&'&'&'&'&'&'&'&'&'&'&'&'&'&'&'X pgpgpxgpx)p)pxxgp)pgpHogpgp1onnnnnnnnngpgpgpgpgpgpgpxxxxxxxxxxxxxxxxxxxxxxxxxxxgpxxm)pxxxxxxxxxxxxxxxxxxxxxxxxxxxxxgpччччччч$чччччKчччччччччччччччччߧчччччччl8чччЦ8888888888888888888888888888888888888888{t+ v v v v v v v v v v v v v v v v v v֒%s mixed within %s source  !"#$'-./0123456789;<=>@ABDEX[\^_adefghijkl(*+,-./01S^  !"#$%&'-./0123458DEFGHIJKLOPSTUVabwxyz{|}~(*':X[abcf-.01QRX6X 8/[^Q^PQ^.X-.1679) ,W\]()*+,%&t[atFGHIJKLMNOPQRUVuwxyz{|}~WW]X-.148UX-.1!"#$12348/NWVYY8tZ^WYYXYQ^Y6ABWYW]YY[[[X8,W?mop!p!pC!pp!p?pppp?pF`a458TU458T \W 8W48x2\WOV48TraQ4848RYYYTTYQ484846789:F[abc{~689:;<=>?BCDEHIJKL#"!Ny^Yt,XYYXZYY  ^ \ 4848\34845^,YYZYYQY[Z[a:8t7M^4M7474$679'1;=>@ADFGJLXavY ^^Z\ZY88YY:Y6<HJ?DL=EJ;=%ytXMM Z ^ ^\Y\Yaq77M777&yGJ8W@D=FJ=49X-.1  4:=J==48MX8W 7777n=J==4848 =Z7=7B9bQLdIfjjBI3UEYQ\A7E]^_`e\56XY\ o5{\ 3 AmW56NFWt3 7?L?BD%&9%Q 8WyXYW\]^_|}~ ppF` tqt "$&*f +,xHr6789qr|TDIGG6789;<SRYFklGyZ5m:W%&klWt56W}WDzeI8mWFe?56789:;<DFGIFWQStW]bmtoegZklg4:6789fzWFY~ 46789Ybc tWW?FW{Wi0?iY8WWWmWot!W@A[mWop=N?3?WcV;GtW GS{`YSuCmop[1jDvwI94{g}88`t./p=?pY|ppFG[|`S?UVY`Ht?q86TABWt`uYW|moprmoptYWtY?C tY) Wt Bt t?Pm?o%444F+,4PZv\MmYoUVcTUYXmYop3mopKNtyBtttC|}~)XY(\4 ZYyYaBd yMPqr8TUtXt8 46789:679FABn;<=>[abc]_46789*e{3~7;`[Qa]^_`467894F6789UV[56789:;<6[DFaI()*+,yz{|}~Wegkli 01z56BC"46789:F46789F UV[abc5:{|}~FG{~gal"46789:"F4"6789:=?[GFbcSUV[abc{u|{~DIJKLMNOPQRSTUVWXYZ[\]^_`abc e=?U|4BMPTUX37FGHIJKLMOPQUV]^_`CG37Swxyz{|}~adQ3qr]^_)4]MTUX35:FG6:Bg5:WFGhi5:FgI g%&()*+,5:WF nFGHIJKLOPUVg=? wxyz{|}~U=?|,U=?FGHIJKLMNOPQRUVU|uwxyz{|}~|=?U)4|MTUX)4M4TUXFGHIJKLOPUVMTUXwxyz{|}~4MTUX458DEFGHIJKLOPSTUVabwxyz{|}~  !"#$'-./0123456789;<=>@ABDEX[\^_adefghijkl ,%&()*+,FGHIJKLMNOPQRUVFGHIJKLMNOPQRUVWYZ`uwxyz{|}~nqtuvwxyz{|}~ ,%&()*+,FGHIJKLMNOPQRUVFGHIJKLMNOPQRUVWYZu`wxyz{|}~nqtuvwxyz{|}~ %&()*+,FGHIJKLMNOPQRUVFGHIJKLMNOPQRUVWYZu`wxyz{|}~nqtuvwxyz{|}~ %&()*+,FGHIJKLMNOPQRUVFGHIJKLMNOPQRUVWZ`wxyz{|}~nquvwxyz{|}~ %&()*+,FGHIJKLMNOPQRUVWZ`nquvwxyz{|}~ %&()*+,FGHIJKLMNOPQRUVWYZ`nqtuvwxyz{|}~ %&()*+,FGHIJKLMNOPQRUVWZ`nuwxyz{|}~ %&()*+,FGHIJKLMNOPQRUVWZ`nquvwxyz{|}~ %&()*+,FGHIJKLMNOPQRUVWZ`nuwxyz{|}~ %&()*+,FGHIJKLMNOPQRUVWZ`nuwxyz{|}~ %&()*+,FGHIJKLMNOPQRUVWYntuwxyz{|}~ %&()*+,FGHIJKLMNOPQRUVWYntuwxyz{|}~  !"#$'-./0123456789;<=>@ABDEX[\^_adefghijkl  !"#$'-./0123456789;<=>@ABDEX[\^_adefghijkl  !"#$'-./0123456789;<=>@ABDEX[\^_adefghijkl  !"#$'-./0123456789;<=>@ABDEX[\^_adefghijkl  !"#$'-./0123456789;<=>@ABDEX[\^_adefghijkl  !"#$'-./0123456789;<=>@ABDEX[\^_adefghijkl  !"#$'-./0123456789;<=>@ABDEX[\^_adefghijkl  !"#$'-./0123456789;<=>@ABDEX[\^_adefghijkl  !"#$'-./0123456789;<=>@ABDEX[\^_adefghijkl  !"#$'-./0123456789;<=>@ABDEX[\^_adefghijkl  !"#$'-./0123456789;<=>@ABDEX[\^_adefghijkln  !"#$'.123456789:;<=>@ABDEX[\^_abcdefghijkl  !"#$'.123456789;<=>@ABDEX[\^_defghijkl  !"#$'.123456789;<=>@ABDEX[\^_defghijkl  !"#$'-./0123456789;<=>@ABDEX[\^_adefghijkl  !"#$'-./0123456789;<=>@ABDEX[\^_adefghijkl  !"#$%&'-./0123456789DEFGHIJKLOPSTUVabwxyz{|}~  !"#$%&'-./0123456789DEFGHIJKLOPSTUVabwxyz{|}~  !"#$%&'-./01234568DEFGHIJKLOPSTUVabewxyz{|}~  !"#$%&'-./0123458DEFGHIJKLOPSTUVabewxyz{|}~  !"#$%&'-./0123458DEFGHIJKLOPSTUVabwxyz{|}~  !"#$'.123456789;<=>@ABX[\^_defghijkl  !"#$'.123456789;<=>@ABX[\^_defghijkl  !"#$'-./0123456789;<=>@ABDEX[\^_adefghijkl  !"#$'.123456789:;<=>@ABDEX[\^_abcdefghijkl  !"#$'-.0123456789;<=>@ABDEX[\^_adefghijkl  !"#$'.123456789:;<=>@ABDEX[\^_abcdefghijkl  !"#$'.123456789:;<=>@ABDEX[\^_abdefghijkl  !"#$'.123456789:;<=>@ABDEX[\^_bcdefghijkl  !"#$'.123456789:;<=>@ABDEX[\^_abdefghijkl  !"#$'.123456789:;<=>@ABDEX[\^_bdefghijkl  !"#$'.123456789;<=>@ABDEX[\^_adefghijkl  !"#$'.123456789;<=>@ABDEX[\^_adefghijkl  !"#$'.123456789;<=>@ABDEX[\^_adefghijkl  !"#$'.123456789;<=>@ABDEX[\^_adefghijkl  !"#$'.123456789;<=>@ABDEX[\^_adefghijkl  !"#$'.123456789;<=>@ABDEX[\^_defghijkl  !"#$'.123456789;<=>@ABDEX[\^_defghijkl  !"#$'.123456789;<=>@ABDEX[\^_defghijkl  !"#$'.123456789;<=>@ABX[\^_adefghijkl  !"#$'.123456789;<=>@ABX[\^_adefghijkl  !"#$'.123456789;<=>@ABUX[\^_defghijkl  !"#$'.123456789;<=>@ABX[\^_defghijkl  !"#$'.123456789;<=>@ABX[\^_defghijkl  !"#$'.123456789;<=>@ABX[\^_defghijkl  !"#$'.123456789;<=>@ABX[\^_defghijkl458DEFGHIJKLOPSTUVabwxyz{|}~458DEFGHIJKLOPSTUVabwxyz{|}~458DEFGHIJKLOPSTUVabwxyz{|}~458DEFGHIJKLOPSTUVabwxyz{|}~458DEFGHIJKLOPSTUVabwxyz{|}~458DEFGHIJKLOPSTUVabwxyz{|}~458DEFGHIJKLOPSTUVabwxyz{|}~458DEFGHIJKLOPSTUVabwxyz{|}~458DEFGHIJKLOPSTUVabwxyz{|}~458DEFGHIJKLOPSTUVabwxyz{|}~458DEFGHIJKLOPSTUVabwxyz{|}~458DEFGHIJKLOPSTUVabFGHIJKLMNOPQRUVwxyz{|}~uwxyz{|}~w.H?GG19? 4jxm5fm34f hhhVV[wu M|n19mN-S /=JzVjqN=@%;<zY<d^s~~_`abcB<'?)]GDb+?EuIwef:}>124>|Ouzmffz12VW8 12Vhhhh _12Vu@A' VV4G4;<hh Q\^JBPMVVacVXJ JVt7wabc&Gg7NJm7fV12mV''7N7FMCRNNN GHKL'STVVw ;=@GCEVC 7e2E357IZ1o\z|qrxV[cedha h nLOOO  he VVVW1ST'LL1VLLLVJ(h:  WXLMiAkoL!#$%_`abcLL)nLVps B}Ve VVV{ O !    ./qq)*+,)"0~q Hl7V,$LfVqI#VVxvXLLLLVLLOLLuVVLVVzszJyWXLLLLLLLL7LLL6789:\]^_`abcLLLLq  L)))0)/0z(00qLL,`q,q,LJjpLWXLqLq^_`abcq)))0)000,,q,,/)0,LLLLLLqqLL !"#$%&'()*+LLLLLLLL]_qLqLLbL]_qv{qrrLLLLLLqLqrquuJKLMNOPQSTWXSSvqquLZ[\]^_`abcLSLLwLqLrLLLttqrqqqLb9<>DFrtrrugq<>DFqSuqqururqrSSSqqqqruuuStSSutrtStruttutSJOPSWXtrrZ[\]^_`abcruurttuSSJKLMNOPQRSTUVWXSrurrYZ[\]^_`abcS #ruruuttSSStuurStSrrrrutttuSuuuJKLMNOPSTrWXStrSStSrrrZ[\]^_`abcurrurruuStuSSStuuttStuuSSSS,-.ttttttttt  !"#$%&'()*+,-./0123456789:;<=>?@ABCJKLMNOPQRSTUVWXYZ[\]^_`abcJKLMNOPQRSTUVWXYZ[\]^_`abcJKLMNOPQRSTUVWXYZ[\]^_`abcJKLMNOPQRSTWXZ[\]^_`abcOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY  !"#$%&'()*+,-./0123456789:;<=>?@ABC  !"#$%&'()*+,-./0123456789:;<=>?@ABC  !"#$%&'()*+,-./0123456789:;<=>?@ABC  !"#$%&'()*+,-./0123456789:;<=>?@ ABC  !"#$%&'()*+,-./0123456789:;<=>?@ ABC  !"#$%&'()*+,-./012456789:;<=>?@ABC  !"#$%&'()*+,-./0123456789:;<=>?@ABC  !"#$%&'()*+,-./0123456789:;<=>?@ABC  !"#$%&'()*+,-./0123456789:;<=>?@ABC  !"#$%&'()*+,-./0123456789:;<=>?@ ABC  !"#$%&'()*+,-./0123456789:;<=>?@ ABC  !"#$%&'()*+,-./0145689;<=>?@ AC  !"#$%&'()*+,-./0145689:;<=>?@ ABC 12 !"#$%&'()*+,-./0145689:;<=>?@ ABC  !"#$%&'()*+,-./0123456789:;<=>?@ ABC  !"#$%&'()*+,-./0123456789:;<=>?@ABCyz{|}~%&(yz{|}~yz{|}~9yz{|}~9yz{|}~  !"#$%&'()*+,-./45689:;<=>?@   !"#$%&'()*+,-./45689:;<=>?@    !"#$%&'()*+,-./0123456789:;<=>?@ ABC  !"#$%&'()*+,-./0145689;<=>?@ AC  !"#$%&'()*+,-./0123456789:;<=>?@ ABC  !"#$%&'()*+,-./01456d89;<=>?@ AC  !"#$%&'()*+,-./0145689;<=>?@ AC  !"#$%&'()*+,-./0145689;<=>?@ AC  !"#$%&'()*+,-./01456d89;<=>?@ AC  !"#$%&'()*+,-./0145689;<=>?@ AC  !"#$%&'()*+,-./0145689:;<=>?@ AC  !"#$%&'()*+,-./0145689:;<=>?@ AC  !"#$%&'()*+,-./01456689:;<=>?@ AC  !"#$%&'()*+,-./0145689:;<=>?@ AC  !"#$%&'()*+,-./01456d89:;<=>?@ AC  !"#$%&'()*+,-./0145689:;<=>?@ AC  !"#$%&'()*+,-./0145689:;<=>?@ AC  !"#$%&'()*+,-./0145689:;<=>?@ ABC  !"#$%&'()*+,-./F456G89:;<=>?@   !"#$%&'()*+,-./p3456789:;<=>?@   !"x$%&y()*+,-./z{45689:;<=>?@   !"x$%&y()*+,-./{45689:;<=>?@   !"#$%&'()*+,-./F45689:;<=>?@   !"#$%&'()*+,-./45689:;<=>?@   !"#$%&'()*+,-./45689:;<=>?@456Y5Zh-ik5l-5-5---5JKLMNOPQRSTUVWXYZ[\]^_`abc odKrKVl)>87%@b} &5m>V}4y g#/s'b6m Lc"$ \ 0#0#TVax lS"|#0#i0!G:-$EF ;$$$l%%Z_0#"0#0#0#0#F F8`v GnV$eM[rwG4Vi0$zRFR1|L& W3  97$$$$4$$0 V  0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#A j'!$$ia2JM~$/r70<]'##6M0#0# (Z(0#0#()\c0#- (Z(0#0*>:! x MQRL&((-SX0#0#_dL&fh 4 *vv?? 6p gRn??`!`J))!Qi)'$s4 F c0# 0#FGH Ux$F yF RL&RY'h0#pr!RL�###0##0H"7X7~Xt$i$Y\hhZ0#0#0#0#0#\t0#hoh&erf0#RF 0#F F #F F _t$"?iiF 0#B&hS|oh F F ,'&s rh|:*"]R $)'Fh24Q**X 9@ DEF:;HIiJKMNOPQR|}`/TUgukTlUUWWXYZ[\]^_`=QRt  %& rCab80ADKcdefghi&j*kl(," $"m!nopsPt~*+-.V vy23>o[\]TUVYWXZOPQR*kk ]_^ "vvTi !,/76HLV48;i83  <sutxz|vwy{ Fv  vWGEkDvCklOP*-'ikJkoooUkRS\]d53rstj=2XPMv5ijih  noq  HstSJRhg4}Z' \ vk,kvvk12.k% jI!#(qpq)VcZUv*u01vv:>v"+kNY.- *k`back`bacv`_'v@EnopCvL`a#)Y v`ak`aX+m0 KkoS`bk`a0-,+.6?J@NMI*)/1248=vBvGLkvWQA?v^vvvavc9b<?d&k`anorkk**9~[ vk $[^ulnkjk"7QA%K'Ok2|:;vvE||zO('Bn%&@vvfd>FITkM/ks3C5>vPH29xy$g 67 vADKkvqm &#(D{||'<v|F||k;efm:=tod&wlvvvGr!$||||dkk`aeBNp}|~              !"!#$%&!''''())))*++,,,,-----.......//001123224546666778888888888888889999::;<<==>??@@AABBCCDDEFGGHHIIJJKKLMMNONPPQQRRRRSSSTTTTUUUVVWWXXYZ[[[\\]]^  (06;:OOW_ju}%12:BJRUabefrq #+4<EMV^ijt| )7CLOW_ijklq|}  *6DRZbjrz    & . 6 6 ? I O [ \ ` h r | }     % 4 > ? @ A B C D E F G H Q P l l u y t     $ $ $ / : C E B   # ) / 5 ; A G M S Y c i n o v { ~       # ( - 1 5 9 = A I M Q U Y ] a e i o p v %1?IHYXhqp #$,/@ABLVq #,6?JQ\cry  !"%01<=>?BCDEFIJKLMNOR_iq{| #-9:AJSfm{+,/<GHK\`jtt  W^]/ W^]/--66-6B-6A()*+,0t0YZY4Y8YW8YW4Y1Ytttt%&'XVT`STTWTWT [Y[Yaaaaaaaa[Y-.Z4W48W8X81-.Z4W48W8X8148XW485(*yz{GHIOPwKxLJUV|}~aFbDEST123/0-%. $"'&! # tt,0Y0Y,ZY4Y8YW4YW8YX8Y1YQR|}~F,FDEyz{GwKxLHIJOPUVMN.XuXv^[Q[Q[Y^^QQQQc^aaaa/15\Y\Y[W8X8^_PYY.XY'Y'YdW W 2U\4NV4  \ \ \^:[Ya:a:aaa:a:aaADMAMDML=GJ=GJ==G=G==J==J==GJGJ=GG=JJ=^yyNyyXXX4988q  VTVTVTTWTWUW Z      ^^Z^ ^+(*@fpgph Cipip!!kpkpjpjplplp??!! !?o"'m#$%&n6791e)769ep,,;<=>47689"!#$213-.-.AB\x3\\8Y58\BDMBMDML6=HJ7=HJ=7=H7=H=7=J7=J=7=7HJ7HJ=7H7H=7J7J=76876994:;[Y<=<:>>>>@A@?B?FbC4C;t;tFGFEHE~aI4I{cK4L^/OY^Q[RQRZ:frb48548545W]XX\] #&(*.134:;@DHLOSW[_chjnry  "')-/36:<@BDIMQUY\^`bgkoswz|~   !#%')+-/15;?ELRX^dimquy}  $&'*-0247;@BDHMPRTVXZ\^`bdfglmqrsy}  "$&(*,.02468:<>@CEGIOQTVXZ^`dfkrv|   !"(+06<?@FGMQRWX]`bghnou{}  "$')+-/13579;=?ACEGIKMOQSUV[^bcglortwx  !$&().0359=@EHJLNPRTVXZ\^`acdfilmoqsuwz{~|}vxtwuzyQRDEFGUVLKHIJOPSTMN  !"#$%&'()*+,-./0123456789:;<=>?@ABCWXYZ[\]^_`abcdefghijklmnopqrs !%&*+-/<=>?^|~:,.;` ,p$pppppp-ppppp p pp#pp p'pppp!p&p%ppp+ppp pp p"pp p(pp*ppp)pp1p0p2p.p/ppOFA?CD78 4P;@5H3P=X:`6hKxLx{x}J[]GH()@EVXW<TB IMNR>Y(Z0[8\Q`US9(^0P8]@bHcPdXe`fhgphxij;\܃,LD̒Xl<L,HL̖̗ \8|Tx< $\ܛtL|,\ l, L lLL`L| |T l ̩ < ̬  ,0 |\ l , |< ܲp  l ܵ $ LX < | ̸ | 0 L h < lL̽\  Dlp\4L P|,zRx $ЀFJ w?:*3$"D\}plC0naAD [ FAH YCA,FAD  ABG ,d\] G j F W I fJ(DgWAD nDAQD@c\4`ABEA F(I0W(F DEB8đyBED A(G0X (D ABBD (AGG@X AAA 0ܒ1EDG M AAA DGA4KAq A PAV l lAf I ^ B $lDAID pDA(^FDA HDB(ȓgAAG f AAG ( AAM AAG 4<BGI A(N0V(F ABBtH+HW`8Er+HW+HW)H`̕}Es 0$HW\$HFBB B(A0A8D@t 8A0A(B BBBH T8F0A(B BBB @FLH A(A0DP 0A(A BBBD $@?END eAAXBaKk J \(8XQMK cFAd$xDo E b F FlHHBED D(G0T (A ABBH \(C ABBKLILpBBE B(A0H8F 8A0A(B BBBD l kQ8xFBD A(G0g (D ABBD fAT4pAAD B(B0A8D@WAAH ȢGDu B(B0I4(HIBDJ dNB tzDD WGtT(\WBDA LAB<BBB A(A0 (A BBBH $,LADJ xCA0T8XALG ` AAJ SCAd8AG nA DAR E S E (AAG l CAG $LAAG @AA ̩AT0< ЩGAGG ` AAO DAADp BAA L ABE N ABG  FBA  6Dh D  LD B A 8 BBD A(G0f (D ABBA , `AAKH dAHs A d ,H^ A fHI G D E , FHD  ABA x^Aq F I E , tBID N ABH 8( PBBA A(D0 (D ABBE 0d WADG p CAH IDA\ DKBB B(D0A8D@8A0A(B BBBJA@( ԯAAG } AAH 4$ HAAG p AAE D AAJ (\ ZBAD v ABH  aAj E , HBDA  ABK $ KAAG |DA( 0ACG  AAF H( #BEB B(D0C8Dp 8A0A(B BBBC (t ADD zID8 BBD C(G@ (A ABBH < ,BBB D(C0A (C BBBI ,AC FED{ B LL`BEB B(A0A8G 8A0A(B BBBE ]FEB B(A0A8GqFHA 8A0A(B BBBJ h1VRBP`BBBP^HAFNxHAFN HAHN(hTEHD  AAC (EHD |ID|QHDGNURR"XiXip`]YSwȬ֬ '5BO\jxŭЭ .;GTbnyϮݮ';GLRXbhoxɯүۯ $*/49JSX\dhlpx|ŰѰް'2:>BFJNRVZ^bfjnz~YDZ˱رϱܱ|D+;#>CNYcmwݪԵIJҲβݲ "',16;@EJOTX\`dhmqóɳ"ͭϳ׳'7Cs2LPTX\gsw/ʴҴ-ݴ (32C]SW[_co¥hgsl{c" Dzεص %-9BHTclyǶѶܶ $/=G hD 4""o`  "8 0:8" ooool"DDDDDDEE E0E@EPE`EpEEEEEEEEEFF F0F@FPF`FpFFFFFFFFFGG G0G@GPG`GpGGGGGGGGGHH H0H@HPH`HpHHHHHHHHHII I0I@IPI`IpIIIIIIIIIJJ J0J@JPJ`JpJJJJJJJJJKK K0K@KPK`KGA$3a1hDA GA$3p1067S1GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFYS}SGA+GLIBCXX_ASSERTIONSripper.so-2.2.10-35.el8.x86_64.debugx~7zXZִF!t/]?Eh=ڊ2N!Xg+僣(wAXc3*SLaa61qCK^,f[t%1a7>EwQc =DrB H)rFŐJxHh Tl8ExhR#?+Љޞchhv1*Q ."F 62DQԖqFӲ~$lȻH!q2I\D Kj6.D:N+H2K:E7YOR*v^}7/ugq9΢t0ikْ-VZ*>NYn|6 ZiH!~vŞ!AZDSbCB^mb)l*2-6gS6"XzZSc) ʣq&$IF@`aГerKƕ=@ VC?Xa\ /TFtUԯ^CІh'UER^l7z/FGgGуHՌ%ݙL֞0RI17?VA#*M;0x0JQL`|2W3a hC'Xq1AϒKhUv`됿B3՞NaL\!=jπ!I. 1zD3Z(5= *RAo|%ڞ0v?}oʊ!5xBͽ\!qLe5(N ~Bq--vN@dm`RO ůեjߪ#qa|yEOLVPg\d-(ܟ&w2fJ?WQ'o%Kd\4?*3rnE3qꖷܞX53RnK%q Dz {tIdsvU]iLkMp3T?+  O wNLymYm)DHpxXi#vZO!eר8RށcVt\D9 WYwhG)/ǵ+߱)؁QǠEzaw:-#J2L#K*XV.d}m1%WRXa`:?ul+t L[^Aپ(4|3-M3xMJRt଩=~oK|#O0Xv Hի\֦e/`0h%o}aaj mqȷ;;<+,| Lb\ TIw/GS:wPz;gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``<( p 08oEopT88"^B0:0:8 hhDhDcDDnpKpKw@R@RL}44 ``T!  """ " "H""x bH ,+PK!@@2.2.0/x86_64-linux/thread.sonuȯELF>@@9@8 @,, p-p- p-  -- -  888$$,,, Std,,, Ptd&&&QtdRtdp-p- p- GNU^Ts܅« f(@ @(*BE|qXO+ yh<y2& loNYU_, IF"1 1 1  __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizerb_thread_wakeup_aliverb_ary_clearrb_ary_shiftrb_ary_deleterb_thread_currentrb_thread_sleep_deadly_allow_spurious_wakeuprb_funcallvrb_obj_classrb_eTypeErrorrb_raiserb_uint2bigrb_ary_pushrb_thread_sleep_deadlyrb_ensurerb_num2ulongrb_eThreadErrorrb_error_arity__stack_chk_failrb_scan_argsrb_gc_writebarrier_incrementalrb_gc_writebarrier_generationalrb_num2longrb_eArgErrorrb_ary_tmp_newInit_threadrb_struct_alloc_noinitrb_cObjectrb_cThreadrb_struct_define_without_accessor_underrb_define_methodrb_undef_methodrb_define_aliasrb_providerb_intern2rb_const_defined_atrb_const_setlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5GLIBC_2.4/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ui ii &p- 0x- - - / / / / / / / / #/ $/ %/ &0  0 (0 00 80 @0  H0  P0  X0  `0  h0 p0 x0 0 0 0 0 0 0 0 0 0 0 0 0  0 !0 "0 &0 'HH! HtH52! %3! hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!%] D%U D%M D%E D%= D%5 D%- D%% D% D% D%  D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D%} DH=y Hr H9tH Ht H=I H5B H)HHH?HHtH HtfD= u+UH= Ht H=n Id ]wH`t H(HHHHff.ATLgUHS1HH9},LHY\9DH+wV͡aCud9gz#}Wkp8h"O\x\!@z@|Xƽ1}BS#e~LAzԗb*o"9Hk$?=], ,BDӣg2m<VdMDjBTtcB~vG&s%h0ELe[i* ޖwTV"“i2vexJ:Ql.wJ>8 ID7HaQ(hSv3'ML Rh['lXi`dGXYRn}Pr@_-O~(sMN3l2nnc#S>M8&LZ K>oLeR;>'6S_Zg R-pFiX<aaZVÓo5 Pc0zI$27vV 'vo` G%=_/4W,&k1gD͗:O0 W|Y4gFT4EJX@Ǡ ~cʞzW B|+3E&ݴ. du8@i@8 @VV 0]0] 0] x ]] ]  888$$VVV StdVVV Ptd`R`R`RQtdRtd0]0] 0] GNU2YkO*e%!r09@ 9<BE|ŷ|!qX M2@%gUtx=-b Nq0UA]  `, F"Ia @c  @a __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeruby_xfreerb_gc_mark_mayberb_str_buf_newrb_str_internrb_str_catrb_utf8_encodingrb_enc_associaterb_ary_new_caparb_ary_pushrb_hash_foreachrb_ary_entryrb_funcall__stack_chk_failruby_xrealloc2ruby_xmalloc2rb_check_typeddatarb_scan_argsrb_convert_typerb_id2symrb_hash_arefrb_string_valuerb_enc_getrb_ascii8bit_encodingrb_str_conv_encrb_check_typerb_fix2intrb_str_duprb_eTypeErrorrb_raiserb_eArgErrorruby_xmallocrb_data_typed_object_allocrb_cstr2inumrb_cstr_to_dblrb_float_newmemcpyrb_enc_raiserb_class_new_instancerb_ary_newrb_hash_newrb_hash_asetInit_parserrb_requirerb_define_modulerb_define_module_underrb_cObjectrb_define_class_underrb_path2classrb_define_alloc_funcrb_define_methodrb_const_getrb_enc_findrb_intern2libruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5GLIBC_2.14GLIBC_2.4/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ui ii 0] 08] @] @] `] Hh] p] x] _ _ _ _ _ 1_ 2_ 3`  ` (` 0` 8` @`  H`  P`  X`  ``  h` p` x` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `  ` !a "a #a $a % a &(a '0a (8a )@a *Ha +Pa ,Xa -`a .ha /pa 0xa 3a 4a 5a 6a 7a 8HHL HtH5L %L hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1%I D%I D%I D%I D%I D%I D%}I D%uI D%mI D%eI D%]I D%UI D%MI D%EI D%=I D%5I D%-I D%%I D%I D%I D% I D%I D%H D%H D%H D%H D%H D%H D%H D%H D%H D%H D%H D%H D%H D%H D%H D%H D%}H D%uH D%mH D%eH D%]H D%UH D%MH D%EH D%=H D%5H D%-H D%%H DH=!H HH H9tH6F Ht H=G H5G H)HHH?HHtH F HtfD=G u+UH=E Ht H=.C dG ]wH7HxMOHH4 H @x8OHH H Ȅx$OH HHH ȄҺHHff.HG`H@Hhff.@USHHHo`H}HtQHIHH[];ff.SHH?H{ H{@H{HH{X[ff.AWIAVIAUATUSH1H(HT$dH%(HD$1HT$IL{I9A?"tr1KPtLcXI(S8u9IwHDHL$dH3 %(H([]A\A]A^A_fDC4tI>II@HMMeL9AE<"t4<\uMeL9%AEMH@H5( IH1aH=C<H=> H|$H5> IH1$HCPH=> H|$H5\> IH1HH|$LHC H=;> ^H|$H5> IH1HHC@H== H|$H5= IH1bHHCHH== H|$H5= IH1$HHCXH8C<Hl$HEC, uhHHCHEHCLH+HL$dH3 %(AH([]A\A]A^A_@H|$LIHC({HEHCHEfC(dH5 = 11C0H=@= CPDHC@HHC HCHXC< Lt$I lMnInHLRI*I9y1LHoHHl$fH5a< H=< 11HC H|$LHC@f.H|$LcHHDHCXKH|$L;HCHfH|$L#HCPH|$LHC<H|$LHC8DH|$LHC0HMnHDHǾ[LC(fHA}u?A}u A}A}u&H5B; LHHSA}u9A}uA}tjA}u$H5: LHHDL HxHH]cH5: LHAHDH5: LH"HEH7 H5H81H&7 H5*H81H=: H51pPXH5HH6 H81RfHH5A4 lH8tx<HHHЃff.@HH54 ,H8Ht HvfDAUATUSHH4t&IH559 IH11LkHu1H[]A\A]@1LH58 HH1-HtLLUHhSHHxHHHHH@`1H)hH fHH@H2 H@HHC`H[]AAWAVAUATUSHH9tUIIHHՍAHFH9t~auHFH9t~NfDE1HL[]A\A]A^A_0 wIcE~e4ILf$fI]<-1<0HL`L9t@0 HD$L-HD$HL$LLHHD$HHH}HHL$I<$H5|/ 18HCHXI9t)P,t_ t HHXI9uH5/ Iع1H=0 HNfD (+LLsM9SBD/tK]u.Ht$dH34%(HCH([]A\A]A^A_ FMHXI99@<*tS uIM9A<*t*uLsM9tXC<*t? u@IM9t(A<*t*uL0 LH=d- H51GAWIAVAUIATIUHSH8HW@dH%(HD$(1G(HD$t O,93H11I$I9t;A}{u4I]H9t+AE<"L< t< pII]H9u@1H|$(dH3<%(HH8[]A\A]A^A_, H1?H5+ 1HH1)HDHASfDI]H9AE<*tZIcDL> H떃0 fDHL$HLHD$ HHI@LD$ HL$I<$H5) 1OHSHZH9nB<,t6< t< HHZH9uC< t <1HHH9 B< t~<" HH9uYHH9L<*t*uH=' H5 1DHiHZH9B<*tS0@ wifHHHHHH t w3HHXH9P t/uHXH9t@<*tdfHHjH9%R*t/ HHH9:*u@ H@@,HHHH HpHw!fDH9'ffDHSH9Vs@*t9@/H7HHZH9*R*t/HfHH9:*u@@ |@HkH< H5H81Nff.HH=H=0H5HH/" *H H5HH1H=H! >H=~H! +H=! H5H! H=! HH5QH=! 1HH5@H=! 1HH5*H=k! 1H5HcH5 HNH=G! H5s H! HH=$! H5H H HhH=! lH H H%H H HH H HHh H HH= HA KH HH He HH HF HH H' HvH H H?H H HH H HHR H HH3 H HcH4 Hm H,H HN HH H/ HH H HH H=Hu H=HZ H=H? H=H$ H HH=HH% H=YHh \H=6HP %H=H8 H=H  H=H  H=_H IH=k?H  H=?H  H=H  H=H mH=Hx 6 H=H`  H=`HH H=<_H0 H= ?H c H=H , H=H H=H  H=WHH xH=HH 5HH "\ already initialized instance11to_hashHashopts needs to be like a hashuninitialized instance-Infinity%u: unexpected token at '%s'nesting of %d is too deepjson/commonJSONExtJSON::ParserErrorJSON::NestingErrorinitializeparsesourcequirks_mode?NaNMinusInfinityjson_creatable?json_createcreate_idcreate_additionschrmax_nestingallow_nansymbolize_namesquirks_modeobject_classarray_classmatchmatch_stringkey?deep_const_get[]=[]<<utf-16beutf-16leutf-32beutf-32leJSON/ParserA JSON text must at least contain two octets! p@h0 8 0 6$$$$$$$$$$$$$$$$$$6$u$$$$$$$$$$u$$$$$$$$$$$$$$$$$$$$$$$$$$u$$$$u$$$$$$$$$$$$u$$$$$$$$$$u$$$$$$$u$$$$$u$$$$$$uTTTTTTTTTTTT  ;Pp(PlP4Pl 08PPzRx $0FJ w?:*3$"D \fp4$@5EAG ^DAX5EkH|XBEE B(A0A8I`~ 8A0A(B BBBG ,BDD V ABE HDFBL H(D0A8D` 8A0A(B BBBE TAAKX1H] G |*HX E 8FBA F(D0p (C ABBE $ EID fAAHH Frة!3;zA":tBr^r ,M`L|n*匔n{bKHV i63ٴXQ/La 7bs IC W X\(CR#-e 7.AL⠂83ۉ_dS44?M}<[*A(MFJ4}j %|wm*h@ 6zBӨw;XO߀H J^E|-8<ʁ #FZ@r$B7`#]z4Λ$l;fE1u:rveއfQ1~6q]!fKھ^(nTp܃tm;J,\:.O,9R',ڗP*k3k7 (&xCz_J2 x1i16eSu_D7wqDɅm˙e}2]0 @Ki,N| (ќy\~ N`]q98B (эPkwԁzPm2'qU|L1NmpUSaAeG'B˩.e~#ޓ6,ߣD_+׍ßy#gFuP CizYvrN[OimcYB3wOYE7)U##e"H:R;B=ECM4lC !"Y>XiYf˪#i"$_?g`I#aDvbuZ @@8 @ss || |  H}H} H}  888$$`s`s`s Std`s`s`s Ptd8e8e8e,,QtdRtd|| | 00GNUo v(ШD*_^F@$FHIBE|qXt)Sn PUHs`0~ L"`="4o1[l, wF"$ay  L _؃ S A Qm __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizerb_funcallrb_check_typeddataruby_xfreeruby_xmallocruby_xrealloc2ruby_xmalloc2memcpyrb_str_newrb_utf8_encodingrb_enc_associaterb_check_typerb_str_new_staticrb_hash_arefrb_hash_newrb_obj_classrb_class_namerb_hash_asetrb_str_duprb_str_catrb_str_concatrb_str_internrb_sym2idrb_ivar_setrb_ivar_getrb_ary_entryrb_string_value_cstrrb_iv_getrb_str_substrrb_id2symrb_intern2__stack_chk_failrb_check_convert_typerb_convert_typerb_scan_argsruby_xcallocrb_data_typed_object_allocrb_string_value_ptrrb_path2classrb_raiserb_eArgErrorrb_float_valuerb_cHashrb_cArrayrb_cStringrb_cFixnumrb_cBignumrb_cFloatrb_respond_torb_cFalseClassrb_cTrueClassrb_cNilClassrb_cSymbol__ctype_b_locrb_obj_is_kind_ofrb_const_getInit_generatorrb_requirerb_define_modulerb_define_module_underrb_cObjectrb_define_class_underrb_define_alloc_funcrb_define_singleton_methodrb_define_methodrb_define_aliasrb_cRegexplibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.3GLIBC_2.2.5GLIBC_2.14GLIBC_2.4/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64Bii dui nzii | | | | } b}  !} h p x        & ( * / 0 : ; = E  ( 0 8 @  H  P  X  ` h p x          Ȁ Ѐ  ؀ ! " # $ % ' ) + , -( .0 18 2@ 3H 4P 5X 6` 7h 8p 9x < = > ? @ A B C DHHAi HtH5i %i hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4%=f D%5f D%-f D%%f D%f D%f D% f D%f D%e D%e D%e D%e D%e D%e D%e D%e D%e D%e D%e D%e D%e D%e D%e D%e D%}e D%ue D%me D%ee D%]e D%Ue D%Me D%Ee D%=e D%5e D%-e D%%e D%e D%e D% e D%e D%d D%d D%d D%d D%d D%d D%d D%d D%d D%d D%d D%d D%d DH=d Hd H9tH.b Ht H=id H5bd H)HHH?HHtHUb HtfD=%d u+UH=:b Ht H=._ dc ]wH7Hthv$HtNHu8R1€?v2fHuBHHu H[]DHuHHD$gHD$H[]ff.1H=(fHH5!F Hx@HtHpHHvfDHf.HH5E Hx0HtHp8H6fDHwHH5E |Hx HtHp(HfDH7HH5aE D L`Hh\uE1L-&E1D$fL$H@K<<< P=H5*HcH>fAL5%LL)LLHFMOML9wLL)tK4 HH#HHCHS"HCHD$dH3%(nH([]A\A]A^A_LAL5%L)kK4 HLD$LD$IDAL5$&fDAL5$fDAL5$fD00ALt$fT$fЃfADATD$T$@HL`,1AIHHHAIHHAIHHHAIHHAIHIcH w(H+HH(H=3HBH_H"H\aH5#HMDL9AH D(IfALH9H=v#H5&H1D11 f1f1 fAIHHLx<"tt<\tXH 'f4II9M2f.H="H5 &H1#AL5"fDAL5k"fDHHT$HCHsHT$HC@H5$"HoHBHIcDL>H5!H|/H5!H\H5!H<H5x!HH5^!HHwJHLHHHD$H f(aHD$ff$LHBUH= H5$H1p1@ATIUSH9$HH5B> HH53> H HHoEoHMoP U oX0]0o`@e@ohPmPop`u`oxp}pHHHsH;HsH{HE Hs(H{ HEHs8H{0HE H{@HsHHE0H{PHE@HtHwHHEPH{XHtHwHHEXH{`HtHwHHE`L[]A\H? H5H81ATIUHHSHHE$$11H5GC HD$iEu"D$f(fT $f. $wf.zBHHH[]A\oHHD$HD$H=C EH5 H1`HHD$SHD$H=B HH5H11AVIAUIATIUH-> SH/؃9H? VHCH9EH> H9HHA> H9XHnHHHL> H9H$> H9H= H9H5A HlH5A H11HHqH5HtuH&H= HH9E HL[L]LA\A]A^H= HfH1= HHQ= HH)= HHq= HHL[L]LA\A]A^IuqHL[]A\A]A^YfH5[L]A\A]A^4@[L]A\H5A]A^@H5fHL[]HA\A]A^f.H59@ 1H1]H[L]A\A]A^f.IupHL[]A\A]A^fH5? HL1HHHfAWAVAUIHATUHSHXHB@LzHT$HD$8HBHHt$ HD$@HHRhHD$HAPHxH@H|$HHyxHD$HwH|$0Ht$(HqxHt H9HHEHU[HEH|$8t H|$@}D$01D`QDHH9}RH|$tH|$HLHHT$Ht$ HHIE uIEH9|HD$HT$0H|$8HPxtOH|$@Ll$Mt9HD$0H~/A1 DA9tMtLLHA9uHHEHU]HEHX[]A\A]A^A_H|$(,E1AE9MtHt$LHv@HT$Ht$HH^HT$@Ht$8HGLl$M#WHT$@Ht$8H"lHHD$H== H5HPxHT$HHPx1f.AWAVIAUATUHSHhHB0MnxHL$8HZHD$ HB8Ht$HD$@HHRhH$IFXHHH@HD$0IF`HL$XHHH@HD$(IEHL$PHD$HIFxHt H9qHE1AHEHUH5; H|$8{11HELt$IHI9H|$0t EH|$ t H|$@H<$0LLH5< 1HI17HHD$HD$HT$HHt$H;H|$(H|$8LIHT$Ht$HH I 5IGI98Lt$H|$ MnxMeMfxtLH|$@L4$Mt7M~2AE1 @AE9tHtHLHAE9uH~HEHU}HEHh[]A\A]A^A_fDH|$HE1AE9HtH4$HH_DHT$(Ht$PHFHT$@Ht$ H.VfHT$0Ht$XH"HT$@Ht$ HL4$MIFxH=M: H5HP1IVxff.@ATIUSHHH53 H_HLHH>[H]A\fAUATUSHHH5C3 HIxrI$ ID$I\$H~gHlD+H9sGHfHD+H9t'ADP uH9w HH9t UDP uA[t&A{u}}t H=39 H51D}]uHL[]A\A]@HI\$PUHSHHHH%HtHH[]fDH4 HH0Hu)H=8 HtFDO WAAF$ (;AAG lDA$4@DEAN hFA$\h<EAN `FA$:EAN cAA4FAK K FBK FAB4 FAK K FBK FAB4FAK T FBB FAB4T0FAK T FBB FAB4FAK R FBD DAB@_EK(FAD ABH FIA A(J0 (F ABBE K(Q ABB0XEEJ { NAJ pGAH5FBB E(A0A8D` 8A0A(B BBBH < FBE K(A0 (A BBBG 0FKF G0g  AABA L(*E](h<1BGD `AB8PVBHA  ABF M ABH tK KK0 AD (lADD@Y AAD 04EADG0T AAF ZAAh|6H] K D9H] K D(9H] K DH9H] K Dh9H\ L DHBBB B(D0I8G` 8A0A(B BBBH ,hXFDA 1 ABA 0BDG G0N  GABE BEE D(H0' (D EBBL _ (D EBBL K (A BBBN M (D BBBI A (D GIBI W (A EBBO W (D BBBO K (A BBBN LvBBB H(A0D8D 8A0A(B BBBA L!BBE B(A0D8D# 8A0A(B BBBG (, >BDA lDB8X FBA A(G0 (D ABBE @ EDM N DAG o EAK K IFF EK w AA xEK w AA EK w AA 0D PFKA D0u  AABA 0x FKA D0u  AABA ( (EAQ0n AAA 0 FKA D0x  AABA 0 FKA D0x  AABA (@ d6FDF \CB0l xFDH D0u  AABA ( EKD0 AAA ( Xm EHD  AAH GNU| b !*8B H _| | o`    P(( oooDoH}  0@P`p 0@P`p 0@P`pGA$3a1H _ GA$3p1067^GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFYGA+GLIBCXX_ASSERTIONSgenerator.so-2.2.10-35.el8.x86_64.debug7zXZִF!t/ ]?Eh=ڊ2N.L]@F@N}eqqnclS"YMč7. + t> :&P:rU,nmԀAM"ݠ}!{L86$YU@4"'M|@C"@&Ԣ 1u@򂕧(|ϐGۙ2 R̲?h @wypܠ4n>=eC/C_dإu/:&y;@d>_E1y]wc!C gid㩑=UC 與:J3$PFRf:nK8?EMpS6⤿?M'':ZYy`ޣ(pU~e'Ҝ4_Ba='p|sFtcA{54iq<[}pEOtQ$ "lyl8sbxNvl&'>ѩ^ma9[9qbsJh+lJ*g9qWPĩ  2+8Rewa-3?oWG<񀹤Mb.7 gWg4;&5JQDw-r .M>% gg(@ {,w:l7B@$Wa(S!vRUIS$nk[mlJ c/m7% Uj%@!_kb{֝>KT"tιT.[\xuA?{&xgh!7}rqE2zϗsCCguPu'$ IM;PkK~.wpÍb%yesoz Ѡ@vNaü?ȘF`"HD"~(6 z)o qqP?'sa`2皍x<ۗ&I!8-G% fB-A=G+r~=@ڡ ({?i޼$!37i3:t@24N:.6^S|l$~{d`emL(X+C#$řL}ꜥ\2Y\΢Ti9^^g .r;:LDyCKlƸ/I ˰!xx'fЄA_;&^4W]ZBxICyUnJ||Kgrۆ(u'ïZmC %6h @ 5dMl`ЉvZb +nU>:渍IZ9|hc198?by;yK5`}hPo\ @@8 @     888$$ Std Ptd   $$QtdRtd XXGNUKAgƿ= @! BE|QЪqX  b, F"( 0 U ( __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeInit_complexnucomp_canonicalizationlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ui            HH) HtH52 %3 hh% D% DH= H H9tH Ht H= H5 H)HHH?HHtHu HtfD= u+UH=R Ht H= Yde ]wHHGNU;$@hzRx $h0FJ w?:*3$"Dp \8 z    o`   0 oooo GA$3a1 GA$3p1067GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realigncomplex.so-2.2.10-35.el8.x86_64.debug)XH!řf[,Hο%j(EswNmpz{ʰ)^)ggPY^{70m^³_\,UxktC~ '܇U5O b6*eF-'u2$evAn XJ;xe{%= x_;FM"1#Gw Y8t[i|?-EpeӖ);wJ:2/)q\P @,n2XT H>Ȝ~m4ٜY.AeW~ؚ L@f-$t}D 2?qֹVUYBFb܌;bZmZNz =hkZ j ˠ@6rQ 9٥ܠhS2DkiʃDjNGVφch  @@8 @     888$$ Std Ptd   $$QtdRtd XXGNU jIBk@  BE:P|qX c , F"( U 0 ( __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeInit_rationalnurat_canonicalizationlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ui            HH) HtH52 %3 hh% D% DH= H H9tH Ht H= H5 H)HHH?HHtHu HtfD= u+UH=R Ht H= Yde ]wHHGNU;$@hzRx $h0FJ w?:*3$"Dp \8 z    o`   0 oooo GA$3a1 GA$3p1067GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realignrational.so-2.2.10-35.el8.x86_64.debugCʑ!7zXZִF!t/ ]?Eh=ڊ2N.̈́>/~i}o0%{)XH!řf[,Hο%j(EswNmpz{ʵ*-31Ì^x)ӴHLe,"9A䴽-\svx}юBaOz6Outq״\MuŎ^Sƫn&;8&] ۛNwJYUe0Q9 E!5<2@m6 C"i^!j"uQPL^teeݼU]IR׻;n^0Tz dP'ߌߨQf9.jcx8zQhUTV:O.:6kD<1ʵe[Q|C?9\ v+7a Uߥ/AE]0,Cnf"?-w͘zUHwM:k_k ! k4Ջ3Bޙ4+7qU~R唠3!~0S$dif#˜*O !:j_3/D^" bkmg\b{KygagՈŨ)q kdy3oϒe/9 #$ υZ z <+[F~w92,LQgYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.note.gnu.property.eh_frame_hdr.eh_frame.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 08oEo T^B0hc0n w  }    $HHp       (( (0`( ,L(t#PK!v*d@@2.2.0/x86_64-linux/pty.sonuȯELF>@x9@8 @,, x-x- x-  -- - 00888$$+++ Std+++ Ptd)))llQtdRtdx-x- x- GNUzO)Myal27jN/F@  FHIBE|qXuU$ P~l-1c %nUE exnGy7snT CT, F"a:. 2 (2 2 : p'__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizerb_ivar_getrb_intern2rb_ary_entryrb_io_closesigemptysetposix_openptrb_fd_fix_cloexecsigactiongrantptunlockptptsnamerb_cloexec_openrb_update_max_fdstrlcpychmod__stack_chk_failrb_eRuntimeErrorrb_raiserb_scan_argsrb_fix2intrb_waitpidrb_last_status_getrb_num2intkillrb_sprintfrb_exc_new_strrb_iv_setrb_exc_raiserb_detach_processsetsidioctldup2getuidseteuidrb_exec_async_signal_saferb_gcrb_cIOrb_obj_allocrb_io_make_open_filerb_obj_freezerb_cFilerb_str_new_cstrrb_assoc_newrb_block_given_prb_yieldrb_ensurerb_execarg_newrb_execarg_getrb_execarg_fixuprb_fork_async_signal_saferb_io_modestr_fmoderb_cloexec_duprb_ary_new_caparb_ary_store__errno_locationrb_sys_failgetenvrb_jump_taggetpwuidInit_ptyrb_define_modulerb_define_module_functionrb_define_singleton_methodrb_define_class_underrb_define_methodlibruby.so.2.2libutil.so.1libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5GLIBC_2.4/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64 ui !ii -ui !x- P- - - / / !/ "/ */ 6/ ;/ =/ D0  0 (0 00 80 @0 H0 P0  X0  `0  h0  p0  x0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1  1 #1 $ 1 %(1 &01 '81 (@1 )H1 +P1 ,X1 -`1 .h1 /p1 0x1 11 21 31 41 51 71 81 91 :1 <1 =1 >1 ?1 @1 A1 B1 C2 EHH HtH52 %3 hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=%M D%E D%= D%5 D%- D%% D% D% D%  D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D%  D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D%} D%u D%m D%e DH=a HZ H9tH Ht H=1 H5* H)HHH?HHtH HtfD= u+UH= Ht H=V d ]wH5 SHHt H[H= H[HHq ff.UHS1HHHuHt  t HuH[]fDHPRxHff.AWIAVAAUATEUSHXH4$H|$HT$dH%(H$H1HD$DŽ$,Hl$L$LHs1LttOtrtfHHtWE1ҾHAŃt7H$AHH|$D(1!EuIH$HdH3 %(u,HX[]A\A]A^A_fHd#H< H5H81+ff.SHH dH%(HD$1HL$LD$H|$@tFqHt$pÍ@v6HD$u7HT$dH3%(uH [Kd|$H5 t1]H5HHEHcH=1H= HHHH5H/HSHHdH%(HD$1Ht$~{HL$dH3 %(uH[fDAVAUIATIUHSD7_D1ҾT11ocW;u H}[L]A\A]A^WLLH5N[]A\A]A^AUE1AATIUHSHH"uH[]A\A]HDLHHA[]A\A]f.AUATUSH8dH%(HD$(1Hl$Ht$ HH|$fHW H8'HIHH=H@ +D$C1HBHCH/ H8HIHH@ ;D$ C;HLLHCHu(HT$(dH3%(Hu3H8[]A\A]f.H= HHH\H]ff.fAWAVAUATUSHH-j Ht$H}dH%(H$1H}ILILIHt$D$$IHl$`H\$@HHD$PH|$PHD$X1Ht$ HH|$D$H|$$HA Hl$HH5D$@D$ D$pD$DHD$pIHD${|$ D$HT$D$H\$0T$0@ gq5,/?V`y#r#BcY5[Eul/q ~g7dw;;-5 p[ \܃QOt}+IJi6KfL/+bZJ8v.r~ċ oOpK7(?Y"^RT>o17r~ITL Ԑ/1oD|cn~Z fxPѐ~;g4Ϊ>+I[2 PCRjkt_qQlk9B|P 9IVdn77m%;{=7ŗ=`dZ'^_ EXq <&OufFM"8{,/ F'@*_Kr'5t<ݩ,$TbK6>dWB|) WBuq_Ș0:ӢlEomQB`[ֆl㹂]bBIܕNơB~ؗ%|0 2fPd@&0W+P]ڵOs6yEws0ĵA| oGHQϠ)*{:_g;gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 0 d8o EoPT^Bhcnw }@(@( 2M(M())lp)p)|++ x- x-- -- -- -0/ /@0 02 2 (2`2H P4(x4L8+PK!F}J..%2.2.0/x86_64-linux/enc/iso_8859_16.sonuȯELF> @h'@8 @   (0    888$$ Std PtdDDQtdRtd  GNUe8Xך$B @BE|qXg #U Ff, F"Y8 l@ `8  0 __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeonigenc_get_case_fold_codes_by_str_with_maponigenc_apply_all_case_fold_with_mapInit_iso_8859_16rb_enc_registeronigenc_single_byte_mbc_enc_lenonigenc_is_mbc_newline_0x0aonigenc_single_byte_mbc_to_codeonigenc_single_byte_code_to_mbclenonigenc_single_byte_code_to_mbconigenc_minimum_property_name_to_ctypeonigenc_not_support_get_ctype_code_rangeonigenc_single_byte_left_adjust_char_headonigenc_always_true_is_allowed_reverse_matchlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64Oui q @      H ` x       P @  X ` h p              (  0 HH HtH5 % hhhh% D% D% D% DH= H H9tH6 Ht H=q H5j H)HHH?HHtH HtfD=- u+UH= Ht H= Yd ]w1wHyxff.fHIIѺQH5)H@IIѿ)H5ff.H?@abcdefghijklmnopqrstuvwxyz[\]^_`abcdefghijklmnopqrstuvwxyz{|}~;D `ppPzRx $PFJ w?:*3$"D@\#p,HL W"BPGNU@  `  P  ,7EO} H   o`   `  ohoo:o  0 @ GA$3a1 U GA$3p1067P G GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFYP s GA+GLIBCXX_ASSERTIONSiso_8859_16.so-2.2.10-35.el8.x86_64.debugH+7zXZִF!t/H]?Eh=ڊ2N. x'' AA":jL-MkF(H4@q{h'EoTU`n╜Seuk>˻1vB6!#88r:լtUa+ ~KE *%l3gw8%rpw 4t5.v]g(ɫ91^tK&CC+~Z|6*< ЂD=X'Z/i2!j_U$}W5H(e"| 9[c pe!lߑ:geS"Vb({O˜ _G8c;ԵK 3snlBhgYg+󥥲W4& _䇪謁Γ0Jm)v41V@[QTNt ;-!*Ca9t(b"}79Riqy-q,CFu< j1^)ugZY,P @0'@8 @xx        888$$XXX StdXXX Ptd ,,QtdRtd  GNU JE:\;Xe@ !BE|qX5,\ e u{0R, F"n( 0 u( U @ __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeInit_iso_8859_6rb_enc_registeronigenc_single_byte_mbc_enc_lenonigenc_is_mbc_newline_0x0aonigenc_single_byte_mbc_to_codeonigenc_single_byte_code_to_mbclenonigenc_single_byte_code_to_mbconigenc_ascii_mbc_case_foldonigenc_ascii_apply_all_case_foldonigenc_ascii_get_case_fold_codes_by_stronigenc_minimum_property_name_to_ctypeonigenc_not_support_get_ctype_code_rangeonigenc_single_byte_left_adjust_char_headonigenc_always_true_is_allowed_reverse_matchlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64dui        H    @  X ` h p  x                HH HtH5 % hh% D% DH= H H9tHv Ht H= H5 H)HHH?HHtHE HtfD=] u+UH=" Ht H=> Yd5 ]w1wHyxff.fH5 H=.HHISO-8859-6@@@@@@@@@ B BBBB@@@@@@@@@@@@@@@@@@BAAAAAAAAAAAAAAAxxxxxxxxxxAAAAAAA||||||ttttttttttttttttttttAAAAQAxxxxxxppppppppppppppppppppAAAA@000000000000000000000000000000000000000000000;,`HppzRx $0FJ w?:*3$"D \#pGNU   "1ALZd X   o`   0  oooho  GA$3a1 e GA$3p1067 W GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFY 3 GA+GLIBCXX_ASSERTIONSiso_8859_6.so-2.2.10-35.el8.x86_64.debug&s7zXZִF!t/? ]?Eh=ڊ2NaÑ^ַ\{h9G:5:u֚*AˏL3Ie]MJ]32U70EVuN$17LS8TBNa`#'`)@-\G GL9H.,W+'r@8vR} yHTk/oQJ20}?@2)/%(j2$6X[ iHo7{B9 m>ZR7Ov$M\>@B>Qu%XΕ*qp=PL!,+z8"Q FFYs0 bSaKGWq B_[1l\YO~}<87h͚ mϘn4l}y1&;NESK1*8Oބ߅rim/1C=5_<[pG ť,Q DŽhO 0cGEC;eٴ'^af{#l$ cytS ;K&%ĩ}iaީW֕}ӸK( FI_ݜ-4<(UBܗ@':azb6bOl4bĔѡoB41 ٗ& '7TL_/}qCYa&3}YPEJ¿wLfҝ"ސaFlBgYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 08ohh,Eo T^B 0h c 0n0 0 wP P }X X    , XX           (( ( 0 `( H p"0"`&+PK!C'.. 2.2.0/x86_64-linux/enc/euc_kr.sonuȯELF> @'@8 @   @H    888$$ Std Ptd\\QtdRtd  GNUN'dA?yhrdr)Q{?T񧊖 ܈쓺5]֕ gGp,fǿUA Tu\ ׁE%^hn[@h'H!U@5DaA;SiϊˆLS*)7M z݆bh6zj8#Cy?,&m=>Cb  uÃ{ҳ OXrAMHt|u3zYC8!sCiMnL3'm_H}'kPf4ˆT;?@5&wU=5EAK6utj#6=q{tXO^m&6otP@[Q>Ah څΞo(eq&Ukb=Ҹr @h'@8 @   (0    888$$ Std PtdDDQtdRtd  GNUH+l'0c+@ BE|XqX U Aa, F"T8 g@  [8 __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeonigenc_get_case_fold_codes_by_str_with_maponigenc_apply_all_case_fold_with_mapInit_koi8_urb_enc_registeronigenc_single_byte_mbc_enc_lenonigenc_is_mbc_newline_0x0aonigenc_single_byte_mbc_to_codeonigenc_single_byte_code_to_mbclenonigenc_single_byte_code_to_mbconigenc_minimum_property_name_to_ctypeonigenc_not_support_get_ctype_code_rangeonigenc_single_byte_left_adjust_char_headonigenc_always_true_is_allowed_reverse_matchlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64Jui l @      H @ x P       @  X ` h p              (  0 HH HtH5 % hhhh% D% D% D% DH= H H9tH6 Ht H=q H5j H)HHH?HHtH HtfD=- u+UH= Ht H= Yd ]wHHBHff.@1wH xff.fHII1QH5%|HIIѿ%1H5fqH55 H=.IHHKOI8-U@@@@@@@@@ B BBBB@@@@@@@@@@@@@@@@@@BAAAAAAAAAAAAAAAxxxxxxxxxxAAAAAAA||||||ttttttttttttttttttttAAAAQAxxxxxxppppppppppppppppppppAAAA@00000444440000000000000000000000000000000044444444444444444444444444444444  !"#$%&'()*+,-./0123456789:;<=>?@abcdefghijklmnopqrstuvwxyz[\]^_`abcdefghijklmnopqrstuvwxyz{|}~;D``@`zRx $PFJ w?:*3$"D @\!p$#@)HI WT`GNU@  @ P '2@Jx    o`   `x  o`oo6o  0 @ GA$3a1 % GA$3p1067P  GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFYP q GA+GLIBCXX_ASSERTIONSkoi8_u.so-2.2.10-35.el8.x86_64.debug\7zXZִF!t/O]?Eh=ڊ2N. '' AA":yw`UXN~s*dЂAvmGÐ<$ gЪxM@Z{n@Yvy[C]M*՗K$ܑ2Gۮh 8$J-K!3_ G7 oKi`DWf5 xh3sdwrPi%֨'ɒ&Sapp&6uMb!y xM&4l!Zv#\>#譳WV,4>4rnܒ2N/CRmn/ (rz-|yZX!*deHh04O ͡_Ev)=E/c+vV=v28<,[}5T>dfV!qFq5ߔbD.Rsf{jRGE<}ݿj70S nD WXpVlAHEB^KL}AI}0f=u ikDZgYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 08o66*Eo`` T^Bx x `h c PnP P @w }  @ @ ` D           88 8 @ `8 H ","<&+PK!Y߭.."2.2.0/x86_64-linux/enc/utf_32be.sonuȯELF> @'@8 @((   HP    888$$ Std Ptd ddQtdRtd  GNU: :m|@/Rb@ BE'᩻|qX  hB, $F"U8  ` @ 8 __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeonigenc_unicode_get_case_fold_codes_by_stronigenc_unicode_mbc_case_foldOnigEncAsciiToLowerCaseTableInit_utf_32berb_enc_registeronigenc_unicode_apply_all_case_foldonigenc_unicode_property_name_to_ctypeonigenc_unicode_is_code_ctypeonigenc_utf16_32_get_ctype_code_rangeonigenc_always_false_is_allowed_reverse_matchlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ui    P     (  8  @  H  P  X @ h    ` p x              (  0  HH HtH5 % hhhh%m D%e D%] D%U DH=Q HJ H9tH Ht H=! H5 H)HHH?HHtH HtfD= u+UH=z Ht H= Id ]wWWWff.ffDϸ>fHH9vHH)HH?H>HʃH)H)fDLIHHHALǀxxxu xu8tIHHD+1AfHH @AHHW1H9v t f.uu1?ff.H9rWH)H~^GGG( 1Dff.Fff.H5 H=9HHUTF-32BE;d @P`$8PL`zRx $8PFJ w?:*3$"D`@\H#pd `\*x]5thGNU P   @  0 x   o`H 3  ` ooo|o  ` p GA$3a10 GA$3p1067 w GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realignGA+GLIBCXX_ASSERTIONS GA*FORTIFYutf_32be.so-2.2.10-35.el8.x86_64.debug7zXZִF!t/]?Eh=ڊ2N! eoة!3;zA"$]ԣaFUdjZ`w'CM58%yߜD;9ٝ,-ao˾Nmo/il9==`*=;gQ43z&и{*qe"ZÌ-+( Dz }JM* mXn+ڴj=K&i[C#]?4:a.,`HM_bnNCcA8JQ.>G]b_"8s3|)kwI9Pz:Cd?-PqkF@jdvSW_RXv;~iEV^/{F|hWW)7#S׬ADK<>Ϛl@@:$cY3$X;g$j&zTr@u)J tB๎7H%" Eo񅅍Bn9aZz,}RH~%]LZO'O3DžɼROU¯int=WsFxFyLK&v-R(cE;OYU/SXڈN,e^2; _{g4zd,'=M9B#A\/ =Hmd>q˸Et&`fv] )|`\us9_Dfywae2w||nqA좠G'(5vC?uR }SKpTY'FmF1ǹlΖ[iY8w;A[w?EќG!UA*m,ja>Rv*h\8M_>QcTjN^ E6n|HgYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 0HH38o||$Eo T^B`h0 0 cP P Pn @w }x x 2  d         ( 88 8 @ `8 H ","x&+PK!-b..$2.2.0/x86_64-linux/enc/iso_8859_2.sonuȯELF> @h'@8 @   (0    888$$ Std PtdDDQtdRtd  GNUJ D"Zjk@ BE|0,\qX "U Ee, F"X8 k@  0 _8 __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeonigenc_get_case_fold_codes_by_str_with_maponigenc_apply_all_case_fold_with_mapInit_iso_8859_2rb_enc_registeronigenc_single_byte_mbc_enc_lenonigenc_is_mbc_newline_0x0aonigenc_single_byte_mbc_to_codeonigenc_single_byte_code_to_mbclenonigenc_single_byte_code_to_mbconigenc_minimum_property_name_to_ctypeonigenc_not_support_get_ctype_code_rangeonigenc_single_byte_left_adjust_char_headonigenc_always_true_is_allowed_reverse_matchlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64Nui p @      H ` x       P @  X ` h p              (  0 HH HtH5 % hhhh% D% D% D% DH= H H9tH6 Ht H=q H5j H)HHH?HHtH HtfD=- u+UH= Ht H= Yd ]w1wHYxff.fHIIѺQH5(H@IIѿ(H5ff.H?@abcdefghijklmnopqrstuvwxyz[\]^_`abcdefghijklmnopqrstuvwxyz{|}~;D@` pzRx $PFJ w?:*3$"D@\#p,HL W"4BpGNU@  `  P  +6DN| H   o`   `  ohoo:o  0 @ GA$3a1 U GA$3p1067P G GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFYP s GA+GLIBCXX_ASSERTIONSiso_8859_2.so-2.2.10-35.el8.x86_64.debugg5b47zXZִF!t/J]?Eh=ڊ2N. x'' AA":~O+o[O'EW3iܖ0 XG*"nP+RMKxdÑY)\b>5Jbe ^ȟ6/sJx p /}f4HXRKlj!蘀&)5xQ?Uk fb.3OW^# {f'x0pt3QW\6.{)g ䷿(oODS-vhT ߗ8 8$(ьpl$N }uW#$"Y+wq2n+`4?تAO3;/̂ei~h/ǐd6~!ú=AV>#ksz crd׀K+ e)l,FƲP,Y5|@4Gq8gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 08o::*Eohh T^B `h c PnP P @w }H H ` ` ` D           88 8 @ `8 H "0"<&+PK!A??2.2.0/x86_64-linux/enc/big5.sonuȯELF> @7@8 @$$ ,, , @H -- -  888$$### Std### Ptd"""||QtdRtd,, , GNUHHHBig5Big5-HKSCSBig5-UAO;|(0<PPpdx`zRx $`FJ w?:*3$"Dp\]pmxm(EAG  DAI (<PGNU` , pP0pP0pP0 N , , o` { 0 0  oxooDo-  0 @ P ` p GA$3a1  GA$3p1067GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFY GA+GLIBCXX_ASSERTIONSbig5.so-2.2.10-35.el8.x86_64.debugŢ7zXZִF!t/]?Eh=ڊ2N &I5bwS&Y*SWڭ*gn ԫf@s{U6ƯҐ=b-v)VsipQm&D&81P,W ,fͳ?̽*#`fs}댠]H,R M$a))nwO!+5حfEFUeg[3a]CQlrlЯ`f̮TU0dwHz8l)kOj-?I[lUwUB#;3q:[^H7$v0-CycRn+^6 f-z_Fc Rv$)*ES@o,2u^DbAGE3_هyAdh!{r<W.UH/RJyaQ|9OkvA@s߀ RpNs`*%X O,39a6u]#DJǨ Y9N|*&bf? t:p7o~'7H ϘuG^FqöXқvv[ q*w¨u!{Ծnb@}D^P$p;Z۟Ѧ! [;5I&X֛0NiqyC2t1фmVF58!c*h4''*mߴ3a Scm[OrqC ӾzV&[ZeTtڿX|3,Hӓg-"'_vޒW<+ 6,ԗc?46$DB4zV ?oNf^/1geuF;RYGN VhPg3^Rn: gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``<( (0{8oDD.Eoxx T^B0 0 h c n pw }   ""|""d## , ,, , , , - - / / 0 0PP0 P0X0`P0H 2(26+PK!gQ.."2.2.0/x86_64-linux/enc/utf_32le.sonuȯELF> @'@8 @((   HP    888$$ Std Ptd ddQtdRtd  GNUXJصkWb- @ BE<)᩻|qX  hB, $F"U8  ` @ 8 __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeonigenc_unicode_get_case_fold_codes_by_stronigenc_unicode_mbc_case_foldOnigEncAsciiToLowerCaseTableInit_utf_32lerb_enc_registeronigenc_unicode_apply_all_case_foldonigenc_unicode_property_name_to_ctypeonigenc_unicode_is_code_ctypeonigenc_utf16_32_get_ctype_code_rangeonigenc_always_false_is_allowed_reverse_matchlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ui    P     (  8  @  H  P  X @ h    ` p x              (  0  HH HtH5 % hhhh%m D%e D%] D%U DH=Q HJ H9tH Ht H=! H5 H)HHH?HHtH HtfD= u+UH=z Ht H= Id ]wGWWff.ffD>@HH9vHH)HH?H>HʃH)H)fDLIHHHALDExxu xuxtIHHD'HI AB1fAHff.HW1H9v? tuu1fH9rWH)H~^WGG( 1Dff.Fff.H5 H=9HHUTF-32LE;d @P`$ 8PL`zRx $8PFJ w?:*3$"D`@\H#pd ` \*xb.thGNU P   @  0 x   o`H 3  ` ooo|o  ` p GA$3a10 GA$3p1067 w GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realignGA+GLIBCXX_ASSERTIONS GA*FORTIFYutf_32le.so-2.2.10-35.el8.x86_64.debug57zXZִF!t/]?Eh=ڊ2N! eoة!3;zA"$]ԣaFUdjZ`w'CM58%yߜD;9ٝ,-ao˾Nmo/il9==`*=;gQ+e Ss-G#eIi$ #4-I~y2ΚS, Ϸ?07ZI8!gݹCOh|pN.?b4vk5odzG폶cK{nK/ђr?ƫc+8*I=!_;~W e]s癡݅o&fc~L.:Bu;Wi@-jul Ɵk{=֋&ퟤA[8c_! ~}i#1Hvq|Txe/i Vo~%NC,T_;cywWй$hn\\h);SU:c]~GV,7^glX=@ %8lyV$bv|Wxpshmv90]NmH;bu61@۽&n:ˏUP=0 !*ěƵʎ a#\&gV~s@1nq a UE9OQKM>NwpyHw?,Yt6V]­n;[-,fWm7401ɝu- 1K,{L;+نn<<>dh@:H^eaD~\$OZۤop~7]\GVF XNvͳz)Tq]QԬ VD_Sw1;%RHgYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 0HH38o||$Eo T^B`h0 0 cP P Pn @w }x x 2  d         ( 88 8 @ `8 H ","x&+PK!..%2.2.0/x86_64-linux/enc/iso_8859_10.sonuȯELF> @h'@8 @   (0    888$$ Std PtdDDQtdRtd  GNUEtFLGB BE|qXa #U Ff, F"Y8 l@ `8  0 __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeonigenc_get_case_fold_codes_by_str_with_maponigenc_apply_all_case_fold_with_mapInit_iso_8859_10rb_enc_registeronigenc_single_byte_mbc_enc_lenonigenc_is_mbc_newline_0x0aonigenc_single_byte_mbc_to_codeonigenc_single_byte_code_to_mbclenonigenc_single_byte_code_to_mbconigenc_minimum_property_name_to_ctypeonigenc_not_support_get_ctype_code_rangeonigenc_single_byte_left_adjust_char_headonigenc_always_true_is_allowed_reverse_matchlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64Oui q @      H ` x       P @  X ` h p              (  0 HH HtH5 % hhhh% D% D% D% DH= H H9tH6 Ht H=q H5j H)HHH?HHtH HtfD=- u+UH= Ht H= Yd ]w1wHyxff.fHIIѺQH5,H@IIѿ,H5ff.H?@abcdefghijklmnopqrstuvwxyz[\]^_`abcdefghijklmnopqrstuvwxyz{|}~;D `ppPzRx $PFJ w?:*3$"D@\#p,HL W"BPGNU@  `  P  ,7EO} H   o`   `  ohoo:o  0 @ GA$3a1 U GA$3p1067P G GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFYP s GA+GLIBCXX_ASSERTIONSiso_8859_10.so-2.2.10-35.el8.x86_64.debug7~i7zXZִF!t/H]?Eh=ڊ2N. x'' AA":jL-MkF(H4@q{h'EoTU`n╜Seuk>˻1vB6!#88r:լtr$QJ*8صqeLFJ3]E7@" ,NTWa\1-xx).= 0u*a͗(%x`}hIۢH&[VBiCuVso/f,KsYȅ 4`ĢKU׆~6YHYT1G $Lag^OߧTH ,L݅BN㧳kU=ZD58rt лL;ީ[RV<w4l.k+`}z-FP>1H1j(Ra*.\%}c/U~(oAT~qK=w=$neȾ;o ̦sgYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 08o::*Eohh T^B `h c PnP P @w }H H ` `  D((           88 8 @ `8 H "0"8&+PK!9"= 2.2.0/x86_64-linux/enc/gb2312.sonuȯELF>p@@8 @00     888$$ Std Ptdttt$$QtdRtd XXGNUl{<1oRP  BE|qX)3l  am , F"0 8 0 U 0'__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeInit_gb2312rb_enc_findrb_enc_registerlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ui             ( HH HtH5 % hhh% D% D% DH= H H9tHV Ht H= H5 H)HHH?HHtH% HtfD=E u+UH= Ht H= Yd ]wHH=&H=!HHHHEUC-KRGB2312; <d|zRx $H@FJ w?:*3$"D`0\8'HWGNU  }  X  o`   H oooo  0GA$3a1e GA$3p10670WGA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realigngb2312.so-2.2.10-35.el8.x86_64.debugL&7zXZִF!t/]?Eh=ڊ2N$`Z~QvZ? /koОxgh$9@,O!>=PpNnt2i䗛CG*4[R(W[Ea,:]m)n&Ih$향c> Ou!@aZ\4{y/O>f@&+BZ\X[B˵ }%z5@<ױʇ+lZY/6P_ 2R  l\ )y@?eps 2 C"_v񅨵Iٷ/ 1^83,~uQo49G946(ex-DU9p}_G27@'aưB;h5]R:!8>0jfi.!~^8;W:i+栅4+yjyrXOfo_::1Wp@&@8 @HH       888$$((( Std((( Ptd$$QtdRtd  XXGNUe:+Ӏ[ Y( @0 BEj|qX ` q, F"$X U 0 z 7` +X __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeInit_encdbrb_encdb_declarerb_encdb_aliasrb_encdb_replicaterb_enc_set_baserb_encdb_dummyrb_enc_set_dummyrb_encdb_set_unicodelibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ui <             ( 0 8 @ H  P  HH HtH5 % hhhhhhhhq% D% D%  D% D% D% D% D% DH= H H9tHV Ht H= H5 H)HHH?HHtH% HtfD=m u+UH= Ht H= YdE ]wHH=z H=y H=s H=p H=i H=h H=e H=_ xH=^ lH=Y `H=T TH=O HH=J $H== H=< H=; H=: H=9 H=8 H=7 H=6 H=5 H=5 H=5 H=5 H=5 H=5 |H=5 pH=0 dH=+ XH=) LH=& @H=# 4H= (H= H= H= H= H5 H= %H5 H= H5 H= H5a H= H5 H= H5; H= vH5 H= H5 H= PH5 H= H5H= *H5 H= H5H= H5 H= H5H=w H5k H=k H5}H=^ H5R H=R H5WH=E H59 H=9 H51H=, lH5 H= H5 H= FH5 H= H5H= H5 H= ]H5H= H5 H= 7H5H= H5 H= H5sH= H5 H= H5MH= H5 H= H5'H= bH5H=x OH5H=q jze85];AٙNk]DQi?{S9PU6T1YAΝ|ռxk9vwld43@c?=E"t_:Uj+` ̾sF#m4Ѩ,RSiS`c#Zw{k, CK+f x0$#kB,Ȕ:tOMpOzD)w7+sO.w>U5Usx$AJ Ʉ Hոss$z]+)cde` ʤ)gʎnTa$`ЎhAPux,~FWZFTd!Wڬߑ+/$Zy=C5H#eaJc -N}kj5Noޗ1bJ[jbZqήC{{ds8{:X']0K MV, 1ci,)'%pi8C#%!mB&#w* rm {g7JX1?$ iHnKBأ'69A@X)6gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 0u8o Eo T^Bxxh88c``nwpp: } 2$x((         XX X ` `X  P"(x"H%+PK!O5.."2.2.0/x86_64-linux/enc/utf_16le.sonuȯELF> @'@8 @hh   HP    888$$HHH StdHHH Ptd ddQtdRtd  GNU!j5l+Z@ HBE|!qX  hB, $F"U8 @  8 __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeonigenc_unicode_get_case_fold_codes_by_stronigenc_unicode_mbc_case_foldOnigEncAsciiToLowerCaseTableInit_utf_16lerb_enc_registeronigenc_unicode_apply_all_case_foldonigenc_unicode_property_name_to_ctypeonigenc_unicode_is_code_ctypeonigenc_utf16_32_get_ctype_code_rangeonigenc_always_false_is_allowed_reverse_matchlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ui    P     (  8  @  H  P  X 0 h   P ` p x              (  0  HH HtH5 % hhhh%m D%e D%] D%U DH=Q HJ H9tH Ht H=! H5 H)HHH?HHtH HtfD= u+UH=z Ht H= Id ]wGȀtDWO %ʁ ff.fff.fLIHHMLAxAxtIHHLD@Hi AHDH)~HWуu&u~$G<Døf.FøfDHW1H9v? t1ff.v$ f~fÐf>HH9v/HH)HH?HʃH)HH)Pt@HHPH9HGH5u H=HHUTF-16LE;d @`$@8L`zRx $PFJ w?:*3$"D @\CpDP\KZ"9,PhGNU P    0  P  0   o`H 3  ` ooo|o  ` p GA$3a10 GA$3p1067 GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realignGA+GLIBCXX_ASSERTIONS GA*FORTIFYutf_16le.so-2.2.10-35.el8.x86_64.debug}7zXZִF!t/]?Eh=ڊ2N! eoة!3;zA"/Kt6'tIVo)h ː/|X;p`a4 2M@DM<].C'vIy4Π݇cln3s;*|^^Ko=ʪ1qapho`dhM DcCY5I<<xp @h'@8 @   @H    888$$ Std PtdDDQtdRtd  GNU\+6^bk^D@ BE|1,\qX  z<\U, F"O0 b8  P V0 __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeonigenc_apply_all_case_fold_with_mapOnigEncISO_8859_1_ToLowerCaseTableInit_iso_8859_1rb_enc_registeronigenc_single_byte_mbc_enc_lenonigenc_is_mbc_newline_0x0aonigenc_single_byte_mbc_to_codeonigenc_single_byte_code_to_mbclenonigenc_single_byte_code_to_mbconigenc_minimum_property_name_to_ctypeonigenc_not_support_get_ctype_code_rangeonigenc_single_byte_left_adjust_char_headonigenc_always_true_is_allowed_reverse_matchlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64Eui g      (  X  `  h 0 x    8 @ H P  p              ( HH HtH5 % hhh% D% D% DH= H H9tH6 Ht H= H5 H)HHH?HHtH  HtfD=E u+UH= Ht H= Yd ]wx@w8HH A>SuHFH9v FstfDP@vP0wH<i ' ^"eUA7HN718ʹ2ik<:^>ق8:Dv+_'ÿo޽9[3\⁊i7wrm BgYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 08o00*Eo`` T^B Hh c @n@ @ 0wp p }h h   D        ( 00 0 8 `0 H x"0"<&+PK!#..$2.2.0/x86_64-linux/enc/iso_8859_9.sonuȯELF> @h'@8 @   (0    888$$ Std PtdDDQtdRtd  GNU?@abcdefghijklmnopqrstuvwxyz[\]^_`abcdefghijklmnopqrstuvwxyz{|}~;D`0`zRx $PFJ w?:*3$"D@@\(#pD,HL WX"tBGNU@  `  P  +6DN| H   o`   `  ohoo:o  0 @ GA$3a1 U GA$3p1067P G GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFYP s GA+GLIBCXX_ASSERTIONSiso_8859_9.so-2.2.10-35.el8.x86_64.debug7t7zXZִF!t/G]?Eh=ڊ2N. x'' AA":uGVO|~ycG+saF݊V3INio3;S+7܋ZO~:<ǰ1f ].ɓiNaGZ2]eze“tZgNDҊ62hV!IS,Y>p T߇?ԑ64ÄDX&+[X'B/kE0%Nۏ*C 0zY }e5Qm,~&XJ{lkkQ;sA Qi5Y=k;:)#y!v`ID9c/mH7Y :q6OӜHӋn8UQ] BkAl xBhrkʧMs>26g}#R1IOɞu15Ovby"p+;N:Lj<=O0vLy)^W%=7F Qn~`lpҞڎ&d İ5o}ԃt[EO2ttn#^gي[ܠ* 0|kR_ /?ze]q8wXLtXܯS\T:i%^~W뀐Vg1+wn 9smRo Ϸ9ʬXS @e vT oX}^1{#i]eO^ g/Z5jztvgYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 08o::*Eohh T^B `h c PnP P @w }H H ` `  D           88 8 @ `8 H "0"8&+PK!n2H?H? 2.2.0/x86_64-linux/enc/euc_jp.sonuȯELF>P @8@8 @ ,, ,  -- -  888$$ Std PtdQtdRtd,, , PPGNU,q?Az$Y J#@(BE|T5 qXU gN^ +, F"P0 X0 B P0 __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeOnigEncodingASCIIonigenc_with_ascii_strnicmponigenc_minimum_property_name_to_ctypeonigenc_apply_all_case_fold_with_mapOnigEncAsciiToLowerCaseTableonigenc_ascii_get_case_fold_codes_by_stronig_is_in_code_rangeOnigEncAsciiCtypeTableInit_euc_jprb_enc_registeronigenc_is_mbc_newline_0x0alibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ui ,  ,  , , , , , , - P- 0 -  (- @@-  H- P-  X- p`- h- p-  x- `-  - - p 8- / / / / /  /  / 0  0 (0 00  80  @0  H0 HH% HtH5% %% hhhhhhh%-% D%%% D%% D%% D% % D%% D%$ DH=$ H$ H9tH^$ Ht H=$ H5$ H)HHH?HHtH=$ HtfD=$ u+UH=$ Ht H= Yd]$ ]wH H xILGL9t`DGHHJx;LGL9tRHOH1< fDDfD@fH) H IIQHA ~/H9v*Hf.I9vHrr)9fILNHtLLNt (LI@8LLM)HL9u DDIpff.@Br<~ Dv7wH2 HH1f.f.AWIAVI)AUA@IATIUHSH6EH D 1D wrL=HcI _x_L5IA1uKEH=a! LHJT LL$|u(LL$C<uAD_H[]A\A]A^A_HLHL[]A\A]A^A_T@IIѿS1H5FAv7w0%=t瀀pEføo@?\v%_Yv_XG0!Cf.G ff.H>xH[ HUHILSHLHxHH;Hc=pt I[]ff.AUIAATLIULSHLHHHLHADωA\v5A?Yv)A/X A9uH1[]A\A]AQA9tGAD$A $AD$H[]A\A]DHILHD[L]A\A]bfA $AD$AT$H[]A\A]fDAQfIHMI9vEA_<]vL9sIA_<]vHLHLI9rMI)IN LDwv2t@1 t9ÃwXHQ HHCH1 xw6%=t"瀀1øf.1H5 H=.HHEUC-JP                "hanlatingreekhiraganakatakanacyrillicѧئAZazڣݎ£ãģţƣǣȣɣʣˣ̣ͣΣϣУѣңӣԣգ֣ףأ٣ڣ¦æĦŦƦǦȦɦʦ˦̦ͦΦϦЦѦҦӦԦզ֦צئѧҧӧԧէ֧קا٧ڧۧܧݧާߧ; P@$8 L p0 @@zRx $FJ w?:*3$"DHp\`pN(aF\FEE I(D0D8DP 8A0A(B BBBH D8J0A(B BBB L4XLH4 \tiJp AD pFHG D(M0Z (C ABBH d (A ABBF D (M DBBG [ (A ABBG [GNU , P0 @  p ` p z 8 , , o``  0   oooxo- p GA$3a18 % GA$3p1067 GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFY GA+GLIBCXX_ASSERTIONSeuc_jp.so-2.2.10-35.el8.x86_64.debugn<7zXZִF!t//]?Eh=ڊ2NaӇsዋ?R+8x·`A=]2uF_bl/-1Oza(\OHUEx_'/97hv0v6Vpņ*Mm}ܿ3rE"Igp`v ;RʭF&`$s;/Ml@0FHF#x*\SX@y_LpZ(Žu̒U:L@b6P7*?]t@jK*`}x~D`<3e|&rBƯ(o٪K="n`WFCaƔmK'o7b76s(w2.MX:4 6tTHtw.S!X쵠)r+Cv;,z uh6=o pZd#B&sz%}(O{>ݜ^`񮟥XEqMFŅ $f kR(a/gH( \Ȫ ~EU1jVjּ|kLի+ה$I5zX^tބ jbw ĥd'7:I(Цm|ztj0X Baqs& J "`F澃Z&n,1M}u`:MYp ԭSu  cI'Jy2K/]xB7bNP;|<ϮP @0'@8 @xx        888$$XXX StdXXX Ptd ,,QtdRtd  GNU֋qI d@ BE|6,\qX e u{0R, F"n( 0 U @ u( __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeInit_iso_8859_8rb_enc_registeronigenc_single_byte_mbc_enc_lenonigenc_is_mbc_newline_0x0aonigenc_single_byte_mbc_to_codeonigenc_single_byte_code_to_mbclenonigenc_single_byte_code_to_mbconigenc_ascii_mbc_case_foldonigenc_ascii_apply_all_case_foldonigenc_ascii_get_case_fold_codes_by_stronigenc_minimum_property_name_to_ctypeonigenc_not_support_get_ctype_code_rangeonigenc_single_byte_left_adjust_char_headonigenc_always_true_is_allowed_reverse_matchlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64dui        H    @  X ` h p  x                HH HtH5 % hh% D% DH= H H9tHv Ht H= H5 H)HHH?HHtHE HtfD=] u+UH=" Ht H=> Yd5 ]w1wHyxff.fH5 H=.HHISO-8859-8@@@@@@@@@ B BBBB@@@@@@@@@@@@@@@@@@BAAAAAAAAAAAAAAAxxxxxxxxxxAAAAAAA||||||ttttttttttttttttttttAAAAQAxxxxxxppppppppppppppppppppAAAA@0000000000000000000000000000;,`HppzRx $0FJ w?:*3$"D \#pGNU   "1ALZd X   o`   0  oooho  GA$3a1 e GA$3p1067 W GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFY 3 GA+GLIBCXX_ASSERTIONSiso_8859_8.so-2.2.10-35.el8.x86_64.debug)N7zXZִF!t/?]?Eh=ڊ2NaÑ^ַ\{h9G:5:u֚*AˏL3Ie]MJ]32U70EVuN$17LS8TBNa`#'`)@-\G GL9fJBj||!K$CxG{`a2~s7S>~+u1Eq:@ BsHfU)(;AŪë23 ,"gّkh&|Ђ mT$b~cp .w $L1le ⶗}`8YyɅ7-\QNѵ H`O0suI@TjmaRNB0Le1hR$}ua2E-dpuR ,}Eh^{&ّPG+ .BI.Tfs_6y[/mH˨ߤ;rÌ}aLn7،td9tTʥO#]Ɵra; bAё3 ?Ve\R獄qPT 1Z uf\^]ZH6~F~u+~}X9 8*sHh&VCʠun7|ګ~1KbƦEKrzX=ۥ&C( @`'@8 @   (0    888$$ Std PtdDDQtdRtd  GNUV i?@abcdefghijklmnopqrstuvwxyz[\]^_`abcdefghijklmnopqrstuvwxyz{|}~;D `pp zRx $PFJ w?:*3$"D@\!p#)HI W GNU@  @ P  +6DN|    o`   `  ohoo:o  0 @ GA$3a1 % GA$3p1067P  GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFYP q GA+GLIBCXX_ASSERTIONSiso_8859_5.so-2.2.10-35.el8.x86_64.debugUP7zXZִF!t/D]?Eh=ڊ2N. x'' AA":6L-MkF(H4@q{h'EoTU`n╜Sd {zI| %h5v(٤g8AmS@ja?6#fk:R~`GMUWk _؈AOʪfzQ*3.$iYcpxsaO^m^el{1EN=Z}xR|Q||KSװ՛߿MMJy2fަȁTqSv$`T?IhujkȨh?q_e9(cRvVrN5,G^!oןJ(++-OGWLjSj}5mu?Z"}!G(;H֏X/35#vαѬ=`sY\RzG4E Ucی3x!X6~I2a .m!iJluNgǦMQHiY3kmfW^ V9Z YO .JhO2}`d@8 Z$L<UV(,lN#Gs-H1*dCKe~cĕmuԹ`?PM^ݏ!2X]>>Wu &]UʶY[t1."ya %=aĨ mb^-%z*6x/If*#2 z$p3mTDK8gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 08o::*Eohh T^B `h c PnP P @w }  @ @  D((           88 8 @ `8 H "0"4&+PK!*7..%2.2.0/x86_64-linux/enc/iso_8859_13.sonuȯELF> @h'@8 @   (0    888$$ Std PtdDDQtdRtd  GNU{ǝC=ۛ ɝ~B BE|bqX #U Ff, F"Y8 l@  0 `8 __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeonigenc_get_case_fold_codes_by_str_with_maponigenc_apply_all_case_fold_with_mapInit_iso_8859_13rb_enc_registeronigenc_single_byte_mbc_enc_lenonigenc_is_mbc_newline_0x0aonigenc_single_byte_mbc_to_codeonigenc_single_byte_code_to_mbclenonigenc_single_byte_code_to_mbconigenc_minimum_property_name_to_ctypeonigenc_not_support_get_ctype_code_rangeonigenc_single_byte_left_adjust_char_headonigenc_always_true_is_allowed_reverse_matchlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64Oui q @      H ` x       P @  X ` h p              (  0 HH HtH5 % hhhh% D% D% D% DH= H H9tH6 Ht H=q H5j H)HHH?HHtH HtfD=- u+UH= Ht H= Yd ]w1wH9xff.fHIIѺQH5!H@IIѿ!H5ff.H?@abcdefghijklmnopqrstuvwxyz[\]^_`abcdefghijklmnopqrstuvwxyz{|}~;D``@zRx $PFJ w?:*3$"D @\#p$,HL W8"TBGNU@  `  P  ,7EO} H   o`   `  ohoo:o  0 @ GA$3a1 U GA$3p1067P G GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFYP s GA+GLIBCXX_ASSERTIONSiso_8859_13.so-2.2.10-35.el8.x86_64.debug7zXZִF!t/H]?Eh=ڊ2N. x'' AA":yXN~s*dЂAvmp$O^q\caFy;f F5\@ar,,^is&zS+]6xSxxq!F팉D'21 p}ovΧ ളMFz;Q\hȟ+.e>sӤUǸ;$p Jt~vkDɹ$M#FX)~Dns#H觌@4u@T@QŚX(Rx-د 2Pv3Tr p՜1Cd\eT,cQ(eGwͣ2s r{wo@Q#|Cy1ugbhP].$"G?żҶE:gu$͇?Zb>~؏14E6nB{1a3Sdq(FWw ]6h흣3X{iUs tCˆ5h՜]*viy\\g3Jl*n~TjjWDd,-{et\O? #*4zN$@Vl(^:5E9lQ=JRN<O(+q)M{M'tMqQ8 y3 ]y6'$C;:"Z'`sOArF7 3(µDeT7 3_NWɤMfgoϝɚsϝa U]i3>[D1)oU]3rgV3)ճwb̦sgYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 08o::*Eohh T^B `h c PnP P @w }H H ` ` @ D           88 8 @ `8 H "0"8&+PK!?C<..$2.2.0/x86_64-linux/enc/emacs_mule.sonuȯELF> @'@8 @   @H    888$$ Std Ptd```\\QtdRtd  GNUp0Rn,רu@ (BEr_e|qX R{ Ur+, F"0  8 0 __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeOnigEncAsciiToLowerCaseTableonigenc_mbclen_approximateOnigEncAsciiCtypeTableInit_emacs_mulerb_enc_registeronigenc_is_mbc_newline_0x0aonigenc_ascii_apply_all_case_foldonigenc_ascii_get_case_fold_codes_by_stronigenc_minimum_property_name_to_ctypeonigenc_not_support_get_ctype_code_rangeonigenc_always_true_is_allowed_reverse_matchlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ui     `     ( @@  H  P  X  x   p 8 `  h  p              ( HHY HtH5 % hhh%M D%E D%= DH=9 H2 H9tH Ht H=  H5 H)HHH?HHtH HtfD= u+UH=r Ht H=~ Yd ]wHH xiLGL9|DGHHJxWLGL9DGHHJxULGL9t|HOH1< DDfD@fH H H LE Ex H! BHSHHLHLI~%H1DELHE HzH9uLHcIL[@UHHSH^HtHH^tHHt (HH@8B9Bt HHGHcHH)H9u H[]fHpUHSHHr9rt HH}E~,H9v'H H9vHJȍJ)9H[]ff.v7x.w%nff.HH9v>w DH9s H8wfwH  xfx,w1Df.H5 H=.HHEmacs-Mule;\ x`P@P<P@dxzRx $@FJ w?:*3$"D0\pl|qJ(EGH g AAC $4bEDG OAA|F'V GNU `  @ p  `   o`` E  H ( oooo  GA$3a1` % GA$3p1067 GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFY GA+GLIBCXX_ASSERTIONSemacs_mule.so-2.2.10-35.el8.x86_64.debugOP7zXZִF!t/s]?Eh=ڊ2N w_>i`7GFy#D$]43b\%Y'G6Yt9W(x>gWc0ָa $dDpNZؠYF/QdGVKza}j Jwۣ= y͇N@komߑP noR0r$f{@FԜTo ŶK30%-jhEԐ}|dN7^Ov*3? }q ƨZG}ָuոnhӡ&nlb3anޜ>ݲ-uGT@F((b0Pa<SÑm}u-.9+ه}Y޶R-##,^wgƪ@SBt\bD aAzefr0-F~fŃ lhx+Pc+/"B5 3dt H,mL.3.Y~6\Տ"e7b`Ⱦ9O-y~fMG,JGB٣\01,7ѺpOh^]# usnzik4orR*9Bh"%QQ^q""qW3) O%n/aKB0(:y}魰dx8ϻӣ/dl>N(u[6n C9@űgYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 0``E8o&Eo T(^B  Hh` ` c @n 0w '} @@ ``\0        0 00 0 8 `0 H x"0"\&+PK!Fk..$2.2.0/x86_64-linux/enc/iso_8859_4.sonuȯELF> @h'@8 @   (0    888$$ Std PtdDDQtdRtd  GNUUIP yV&)@  2,\BE|qX "U Ee, F" 0 X8 k@ _8 __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeonigenc_get_case_fold_codes_by_str_with_maponigenc_apply_all_case_fold_with_mapInit_iso_8859_4rb_enc_registeronigenc_single_byte_mbc_enc_lenonigenc_is_mbc_newline_0x0aonigenc_single_byte_mbc_to_codeonigenc_single_byte_code_to_mbclenonigenc_single_byte_code_to_mbconigenc_minimum_property_name_to_ctypeonigenc_not_support_get_ctype_code_rangeonigenc_single_byte_left_adjust_char_headonigenc_always_true_is_allowed_reverse_matchlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64Nui p @      H ` x       P @  X ` h p              (  0 HH HtH5 % hhhh% D% D% D% DH= H H9tH6 Ht H=q H5j H)HHH?HHtH HtfD=- u+UH= Ht H= Yd ]w1wHYxff.fHIIѺQH5(H@IIѿ(H5ff.H?@abcdefghijklmnopqrstuvwxyz[\]^_`abcdefghijklmnopqrstuvwxyz{|}~;D@` pzRx $PFJ w?:*3$"D@\#p,HL W"4BpGNU@  `  P  +6DN| H   o`   `  ohoo:o  0 @ GA$3a1 U GA$3p1067P G GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFYP s GA+GLIBCXX_ASSERTIONSiso_8859_4.so-2.2.10-35.el8.x86_64.debugQ7zXZִF!t/J]?Eh=ڊ2N. x'' AA":~O+o[O'EW3iܖ0 XG*"nP+RMKxdÑY)\b>5Jbe "[)Ѥ;,DBgѺ xZ$96|U$vsda|'- 5 d+_mQCfIY8 H:M4m~d;^ ͤ)fk)YdP6y|$rG\L|;R4dd|=غN @'@8 @XX   @H    888$$888 Std888 Ptd\\QtdRtd  GNUVGT+KJL+އq: G T|^C9  j}˩/z 7Q$՞FZ < Bw>nhP 42Lfq~oC9! G2w}cywãֲL()4<{DŽy3/r}aZ -{N3)"TzǛ͓s)!PO~Xcl,Y&|ܕ&5ꆿeQ{ZUVgh ZmZ[oL Mo+CF zb ({ܐ"Uן yV=~aZ8Yi|<wmBTgwVb%Oum~3}fӓ􎓥NJ ziWPrϓF ZnFy+ȗ,*;|_bhBzkWsr*H桦9 셩WB: @?7Anq=ΝGoY)ZffWG~Xt x:agYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 0^8o*Eo T88^B0 0 h c n pw }x x   \  88           PP P X `P H "("&+PK!xnp.p.%2.2.0/x86_64-linux/enc/iso_8859_11.sonuȯELF>P @0'@8 @xx        888$$XXX StdXXX Ptd ,,QtdRtd  GNU͡CJw$L[t*B BE|qXa f v|1S, F"o( 0 v( U @ __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeInit_iso_8859_11rb_enc_registeronigenc_single_byte_mbc_enc_lenonigenc_is_mbc_newline_0x0aonigenc_single_byte_mbc_to_codeonigenc_single_byte_code_to_mbclenonigenc_single_byte_code_to_mbconigenc_ascii_mbc_case_foldonigenc_ascii_apply_all_case_foldonigenc_ascii_get_case_fold_codes_by_stronigenc_minimum_property_name_to_ctypeonigenc_not_support_get_ctype_code_rangeonigenc_single_byte_left_adjust_char_headonigenc_always_true_is_allowed_reverse_matchlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64eui        H    @  X ` h p  x                HH HtH5 % hh% D% DH= H H9tHv Ht H= H5 H)HHH?HHtHE HtfD=] u+UH=" Ht H=> Yd5 ]w1wHyxff.fH5 H=.HHISO-8859-11@@@@@@@@@ B BBBB@@@@@@@@@@@@@@@@@@BAAAAAAAAAAAAAAAxxxxxxxxxxAAAAAAA||||||ttttttttttttttttttttAAAAQAxxxxxxppppppppppppppppppppAAAA@000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;,`HppzRx $0FJ w?:*3$"D \#pGNU   #2BM[e X   o`   0  oooho  GA$3a1 e GA$3p1067 W GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFY 3 GA+GLIBCXX_ASSERTIONSiso_8859_11.so-2.2.10-35.el8.x86_64.debug"z7zXZִF!t/?"]?Eh=ڊ2NaÑ^ַ\{h9G:5:u֚*AˏL3Ie]MJ]32U70EVuN$17LS8TBNa`#'`)@-\G GL9^xVEmA;|K{n8hG+}  @'@8 @   @H    888$$xxx Stdxxx Ptd\\QtdRtd  GNU^\ 3+uBcꗤE@ BE|qXV5   oU r'I, F"P !X P  __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeonigenc_mb4_is_code_ctypeonigenc_mbn_mbc_case_foldonigenc_mb4_code_to_mbconigenc_mbn_mbc_to_codeonigenc_mbclen_approximateInit_euc_twrb_enc_registeronigenc_is_mbc_newline_0x0aonigenc_mb4_code_to_mbclenonigenc_ascii_apply_all_case_foldonigenc_ascii_get_case_fold_codes_by_stronigenc_minimum_property_name_to_ctypeonigenc_not_support_get_ctype_code_rangelibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ui &   `    @  H  `  p  x        X h               ( 0 8  @ H HH HtH5 % hhhhhhh% D% D%} D%u D%m D%e D%] DH=Y HR H9tH Ht H=) H5" H)HHH?HHtH HtfD= u+UH= Ht H= Yd ]wHBH xiLGL9|OHHHxXHOH9|OHHHxWHOH9teHOH1< DDDfD@fHøø1?~H׉ff.LIHHHHff.fHHHHff.USHHH9vG_<]v fH9sH_<]vHHA9Au'HHH9rHH)HH0HH[]DHHH:HHH9sff.H5 H=.HHEUC-TW;\ x0\zRx $FJ w?:*3$"Dp\p (EAG P DAF <GNU `    2   o` _  8 @ o ooo   0 @ P ` p GA$3a1 GA$3p1067 GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFY } GA+GLIBCXX_ASSERTIONSeuc_tw.so-2.2.10-35.el8.x86_64.debug'7zXZִF!t/O]?Eh=ڊ2N cP@^Mme3r7NT?L8^!nkdOBҲ)`NR<݌{dw;qbʤx`)0W~ށee1a!Kn U^Jyv˝CH^+)e &O e!G=ra-pίFf$I6:{ &^!?]ߋjsig :E1 07 oȉ9ܜ`F:ưzzFmflq[@-0lEh*b#JzARPxR 3U͆QK+ 11uMR['z !8DSC HZҳ0Y/IL<$@mxS~xFaI ;.FЪT5n 0;k3)~@W[/,H(~?)ZQ\9 \dՀF2;y{Y2:S Ɔv S ^woXɓGqdm nrwv6+, _XΝ+A2jd(U14! @ kL)NgkHAA'kYchl#ѐˉ-Q\HNEVU9*NaL,ziˮ v37"yɕ^D#C8Q-~ 񛧝9S38al/Aŵ}N_Qup9R BMOy"Zbф:wWh[w)ɻwokC=X :8>Qު~x,~,Tۄ,8.TK=+gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 0_8o*Eo   T@@^B8 8 h c n pw }   \``xx           PP P X `P H ","&+PK!8X?X?%2.2.0/x86_64-linux/enc/windows_31j.sonuȯELF>P @8@8 @ ,, ,  -- -  888$$p p p Stdp p p PtdQtdRtd,, , PPGNU0HqIqe @!BEпeL|qXU gSc +, F"P0 B X0 P0 __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeOnigEncodingASCIIonigenc_with_ascii_strnicmponigenc_minimum_property_name_to_ctypeonigenc_apply_all_case_fold_with_mapOnigEncAsciiToLowerCaseTableonigenc_ascii_get_case_fold_codes_by_stronig_is_in_code_rangeOnigEncAsciiCtypeTableInit_windows_31jrb_enc_registeronigenc_is_mbc_newline_0x0alibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ui ,  ,  , , , (, , , - P- 0 -  (- @@- p H- PP-  X- `- 0h- `p- P x- -  - -  8- / / / / /  /  / 0  0 (0 00  80  @0  H0 HH% HtH5% %% hhhhhhh%-% D%%% D%% D%% D% % D%% D%$ DH=$ H$ H9tH^$ Ht H=$ H5$ H)HHH?HHtH=$ HtfD=$ u+UH=$ Ht H= Yd]$ ]wH"H x)LGL9t0OHHЀ<D@fDDfHy LI HЅx$LOL9tHL<9u L9vÐHFHt HHF.@:H)ff.H <v7wH HH1f.f.AWIAVI)AUA@IATIUHSH6EH  1D wrL=;HcI _x_L5HIA1uKEH=! LHJT LL$ u(LL$C<uAD_H[]A\A]A^A_HLHL[]A\A]A^A_@IIѿS1H5wHcHz pEw@HU <8%nøoÍ}v%a|v{ v@G @G!@1ҁND0H>xH HHILIHDmIRLt A HIRL)҈HcIfDATIAIULLSHLHA2HH2IzH9ArHHЀ<0@@tv}vMA|{{9tl[]ACA3A\ACQ9u[]A3ACA\AS1@ƍt6ofDIHD[L]LA\[1]A\fHI 40Q9\1Tk@HH9DH B<t9NL HFA<HL@A<~LH9uDLHHK<x1H9tٙJw38k2M>=7}L,ekuFjQRKzJ+edLuRQ7njA2ѽ2 .%-FO[fRf&=;n+Cr,5gU #u}ZkhTٵ }=៽`Q/םhDO_&6kzUH=ᴊxUIFׇ;W̦e+Tl0TsMjsBPomO_[mx ϻ 1^,OIKMwiޥp3}8|VV/kK3wɜ\eJž%y:Spދb)]`S %[RNb[e݀u inl /M=*Wʔ2^,:2:[Z5ai ᷺d/$%CU""%w+O`W-G&8rIelK@omDN_靃з- DB{6( @h'@8 @   (0    888$$ Std PtdDDQtdRtd  GNUBwW FOŬ3CĎ@ ABE|7,\qX "U Ee, F"X8 k@  _8 __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeonigenc_get_case_fold_codes_by_str_with_maponigenc_apply_all_case_fold_with_mapInit_iso_8859_7rb_enc_registeronigenc_single_byte_mbc_enc_lenonigenc_is_mbc_newline_0x0aonigenc_single_byte_mbc_to_codeonigenc_single_byte_code_to_mbclenonigenc_single_byte_code_to_mbconigenc_minimum_property_name_to_ctypeonigenc_not_support_get_ctype_code_rangeonigenc_single_byte_left_adjust_char_headonigenc_always_true_is_allowed_reverse_matchlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64Nui p @      H @ x P       @  X ` h p              (  0 HH HtH5 % hhhh% D% D% D% DH= H H9tH6 Ht H=q H5j H)HHH?HHtH HtfD=- u+UH= Ht H= Yd ]wHH"Hff.@1wHxff.fHII1QH5"|HIIѿ"1H5fqH55 H=.IHHISO-8859-7@@@@@@@@@ B BBBB@@@@@@@@@@@@@@@@@@BAAAAAAAAAAAAAAAxxxxxxxxxxAAAAAAA||||||ttttttttttttttttttttAAAAQAxxxxxxppppppppppppppppppppAAAA@444444404444444444444444444444444400000000000000000000000000000000000  !"#$%&'()*+,-./0123456789:;<=>?@abcdefghijklmnopqrstuvwxyz[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ܷ߻;D`0`zRx $PFJ w?:*3$"D@@\(!pD#`)HI WtGNU@  @ P  +6DN|    o`   `  ohoo:o  0 @ GA$3a1 % GA$3p1067P  GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFYP q GA+GLIBCXX_ASSERTIONSiso_8859_7.so-2.2.10-35.el8.x86_64.debugW17zXZִF!t/G]?Eh=ڊ2N. x'' AA":t EmD9ݹD3y׹*I1m88ԔwLƌ3;UI@J3>]|]ԜMz`{DHZ(ĬMK ٤b#a#8D*ȈxQNIZ2r]MhVQ?S[_}I|ۗSa+.˰&( N2'#1( oy纑.ԤpUv5}q#(lKjm黕C+houi=]Y _́v/Dpvdt; X)]m]l @ |C]`LMVQsnUEV> (O-SA1<'q%m`O7t%DVSrB#Rktd)eSyJc՚.oȹ3@ӮqvB=50KUWhj(h6*[&jV#һtvgYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 08o::*Eohh T^B `h c PnP P @w }  @ @ @ D           88 8 @ `8 H "0"8&+PK!.. 2.2.0/x86_64-linux/enc/koi8_r.sonuȯELF> @h'@8 @   (0    888$$ Std PtdDDQtdRtd  GNU_k/qQg$IEçG+^@ BEX|qX U Aa, F"T8  g@ [8 __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeonigenc_get_case_fold_codes_by_str_with_maponigenc_apply_all_case_fold_with_mapInit_koi8_rrb_enc_registeronigenc_single_byte_mbc_enc_lenonigenc_is_mbc_newline_0x0aonigenc_single_byte_mbc_to_codeonigenc_single_byte_code_to_mbclenonigenc_single_byte_code_to_mbconigenc_minimum_property_name_to_ctypeonigenc_not_support_get_ctype_code_rangeonigenc_single_byte_left_adjust_char_headonigenc_always_true_is_allowed_reverse_matchlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64Jui l @      H @ x P       @  X ` h p              (  0 HH HtH5 % hhhh% D% D% D% DH= H H9tH6 Ht H=q H5j H)HHH?HHtH HtfD=- u+UH= Ht H= Yd ]wHH"Hff.@1wHxff.fHII1QH5!|HIIѿ!1H5fqH55 H=.IHHKOI8-R@@@@@@@@@ B BBBB@@@@@@@@@@@@@@@@@@BAAAAAAAAAAAAAAAxxxxxxxxxxAAAAAAA||||||ttttttttttttttttttttAAAAQAxxxxxxppppppppppppppppppppAAAA@040000000000000000000000000000000044444444444444444444444444444444  !"#$%&'()*+,-./0123456789:;<=>?@abcdefghijklmnopqrstuvwxyz[\]^_`abcdefghijklmnopqrstuvwxyz{|}~;D`0`zRx $PFJ w?:*3$"D@@\(!pD#`)HI WtGNU@  @ P '2@Jx    o`   `x  o`oo6o  0 @ GA$3a1 % GA$3p1067P  GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFYP q GA+GLIBCXX_ASSERTIONSkoi8_r.so-2.2.10-35.el8.x86_64.debug2aK7zXZִF!t/N]?Eh=ڊ2N. '' AA":t EmD97;M٧xs8 b\d\HfF 4>O150.=_ы3seNB_0N`pI֫0և@NkFX声cEFR&=se[ʂ>la- Mv82ZID1]~Ey9dqC5OHb]HRAC:7mL[J~F NPvv:i,\#[I{[ֳ^\m]J۩IJśNn>wÿuFUuQ$" Tl-޽̸ gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 08o66*Eo`` T^Bx x `h c PnP P @w }  @ @ @ D           88 8 @ `8 H ","<&+PK!$X..2.2.0/x86_64-linux/enc/gbk.sonuȯELF> @'@8 @XX   @H    888$$888 Std888 Ptd\\QtdRtd  GNUȦW/[FíUP BE|͸UqX o Uo$ F, F" P X  ` P __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeonigenc_mb2_is_code_ctypeonigenc_mbn_mbc_case_foldonigenc_mb2_code_to_mbconigenc_mbn_mbc_to_codeonigenc_mbclen_approximateInit_gbkrb_enc_registeronigenc_is_mbc_newline_0x0aonigenc_mb2_code_to_mbclenonigenc_ascii_apply_all_case_foldonigenc_ascii_get_case_fold_codes_by_stronigenc_minimum_property_name_to_ctypeonigenc_not_support_get_ctype_code_rangelibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ui #   `    @  H  `  p p x P  0     X h               ( 0 8  @ H HH HtH5 % hhhhhhh% D% D%} D%u D%m D%e D%] DH=Y HR H9tH Ht H=) H5" H)HHH?HHtH HtfD= u+UH= Ht H= Yd ]wHH x)LGL9t0OHHЀ<D@fDDfHH<H׉nff.LIHH'HHff.fHHHH+ff.USHHH9vkLA<t4FL H^A<oDCLCA<~LH9uHHA9Au+HHH9rHH)HH0HH[]fHHHrHHH9sH먐H5 H=.)HHGBK;\ @xPp0\zRx $FJ w?:*3$"Dp\0]p|(EAG t DAJ <GNU `   p P 0  / x   o` \  0 8 oooo   0 @ P ` p GA$3a1 GA$3p1067 w GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFY GA+GLIBCXX_ASSERTIONSgbk.so-2.2.10-35.el8.x86_64.debug ^7zXZִF!t/?{]?Eh=ڊ2N .wD%6 H``28!waI|#PCQOCг,&M3s>uMyV3T\S uW?j1:/lWݭߩ:!=rOTq'/--l%;-wo6NR^Ee|WWrb4Ndv)W8*8lr}o,}P+QdeTQ ? TKek(XrN+:Wc/-ČCR|wgHg2UZb?MlD6FmiQ #]MaIfE Lg8|aM zDF5 E&\9WgAgT ienV֘čP "Wд@c,۬LYY}@.]c72|z_ݣwN"ܼ6x Eke!r rծ;RK/ݣmsX"- #?q䩒(=WG:sO 蓟 t>p* X2,trV&R4{d7E%JD,tEGx;! }kꑃj|j)ۇ c1`ִl#<\zWWr K9d҇Aɯ-xEƐɿGqXONP @8@8 @ ,, ,  -- -  888$$p p p Stdp p p PtdQtdRtd,, , PPGNUxZ/ÞA#zs@0 %BE|qXU gQa +, F"B P0 X0 P0 __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeOnigEncodingASCIIonigenc_with_ascii_strnicmponigenc_minimum_property_name_to_ctypeonigenc_apply_all_case_fold_with_mapOnigEncAsciiToLowerCaseTableonigenc_ascii_get_case_fold_codes_by_stronig_is_in_code_rangeOnigEncAsciiCtypeTableInit_shift_jisrb_enc_registeronigenc_is_mbc_newline_0x0alibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ui ,  ,  , , , (, , , - P- 0 -  (- @@- p H- PP-  X- `- 0h- `p- P x- -  - -  8- / / / / /  /  / 0  0 (0 00  80  @0  H0 HH% HtH5% %% hhhhhhh%-% D%%% D%% D%% D% % D%% D%$ DH=$ H$ H9tH^$ Ht H=$ H5$ H)HHH?HHtH=$ HtfD=$ u+UH=$ Ht H= Yd]$ ]wH"H x)LGL9t0OHHЀ<D@fDDfHy LI HЅx$LOL9tHL<9u L9vÐHFHt HHF.@:H)ff.H <v7wH HH1f.f.AWIAVI)AUA@IATIUHSH6EH  1D wrL=;HcI _x_L5HIA1uKEH=! LHJT LL$ u(LL$C<uAD_H[]A\A]A^A_HLHL[]A\A]A^A_@IIѿS1H5wHcHz pEw@HU <8%nøoÍ}v%a|v{ v@G @G!@1ҁND0H>xH HHILIHDmIRLt A HIRL)҈HcIfDATIAIULLSHLHA2HH2IzH9ArHHЀ<0@@tv}vMA|{{9tl[]ACA3A\ACQ9u[]A3ACA\AS1@ƍt6ofDIHD[L]LA\[1]A\fHI 40Q9\1Tk@HH9DH B<t9NL HFA<HL@A<~LH9uDLHHK<x1H9t9c Ûwer PMn¾a Vus|D_H]ҢMPfÙBBP=Jysxb*.FOCENN mK/hRk^3EngIJ/Oy ;D+p](ǝ^mٮPMglߣ ‡dQ ƾMɗEUoL SCTpAQ1 s*X %+-k?J-k$9 s9}l%qx8qGIzvsӾ {o{鄝S;ٺ7V|DN>PJ1/!b 嬠lkzې=ݷ[rZ4{m08FHYxouS[#f!8SX5Ͻz6a[7Α(=HTK0\~F/^29'a"t, gdU\ a 6jwǘHLP?ؑw;[ %;6 5P,lŎLO-hCeG[)YjuopLIL.@ @'@8 @   HP    888$$ Std Ptd   ddQtdRtd  GNUP!˗$I{"@ BE4 ੻|qX  hB, $F"U8  @ 8 __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeonigenc_unicode_get_case_fold_codes_by_stronigenc_unicode_mbc_case_foldOnigEncAsciiToLowerCaseTableInit_utf_16berb_enc_registeronigenc_unicode_apply_all_case_foldonigenc_unicode_property_name_to_ctypeonigenc_unicode_is_code_ctypeonigenc_utf16_32_get_ctype_code_rangeonigenc_always_false_is_allowed_reverse_matchlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ui    P     (  8  @  H  P @ X 0 h    ` p x              (  0  HH HtH5 % hhhh%m D%e D%] D%U DH=Q HJ H9tH Ht H=! H5 H)HHH?HHtH HtfD= u+UH=z Ht H= Id ]wOȀtDWO %ʁ ff.fff.fLIHHHMxx8tIHHLHHf @AHЃtH)1HHH9v.HH)HH?HʃH)HH)tDHHPH9HGH55 H=HHUTF-16BE;d @ p$08L`zRx $PFJ w?:*3$"D@\CpOX)M,PhGNU P    @ 0   0   o`H 3  ` ooo|o  ` p GA$3a10  GA$3p1067 GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realignGA+GLIBCXX_ASSERTIONS GA*FORTIFYutf_16be.so-2.2.10-35.el8.x86_64.debug /7zXZִF!t/]?Eh=ڊ2N! eoة!3;zA"8`gdU< }}'YxW72]S]-A>T r[W)FuMT'Ω~|>zb0d߶ $1T+S67+ k6 ?";S^8P]{}!n =Gμ"P3/ZarE |#w`3gUeO8 M|_)`GZ-/1fM,j*p߱[$ZSF<0/שTB ֒n^Qg9c= c r )s#΍HOm0-5[ UeE3CeIXYqgDZ1ZGpجPތS,ƭ4pkTн2!ezpZM`'8;g(JU4SJ3=?!n"]p=h!׭յK۫p2A޺%*y5 uY|4 bC < 9^}R鱩B icǂ) 4͖=,\@!)P k;CϬwT~oGYC8b]VPҩ DR`AjG Ρ܌`xb K䌉CŖox״qy:`~"{)~nǻ&zMPjryדc>@ӗc4&} \"MAx;ob'%qyx⩷_˿dqCp?rlsO9⩯OjKZTK~bIv+k|]߇h8׾ѱgYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 0HH38o||$Eo T^B`h0 0 cP P Pn @w } 2    dx x         ( 88 8 @ `8 H ","x&+PK!KJ..!2.2.0/x86_64-linux/enc/gb18030.sonuȯELF> @'@8 @   8@    888$$ Std Ptd   \\QtdRtd  GNU&v+zgҺK~[@ @(BE|qX9 oU [2, F"H P H  __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeonigenc_mb4_is_code_ctypeonigenc_mbn_mbc_case_foldonigenc_mb4_code_to_mbconigenc_mbclen_approximateInit_gb18030rb_enc_registeronigenc_is_mbc_newline_0x0aonigenc_mb4_code_to_mbclenonigenc_ascii_apply_all_case_foldonigenc_ascii_get_case_fold_codes_by_stronigenc_minimum_property_name_to_ctypeonigenc_not_support_get_ctype_code_rangelibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ui  0      @ @ H ` `p @x      X h               ( 0 8  @ HHI HtH5R %S hhhhhh% D% D% D% D% D% DH= H H9tHF Ht H= H5 H)HHH?HHtH HtfD=M u+UH= Ht H= Yd% ]wHHxiHOH9OHHHxpHOH9t{OHHHx;HOH9tXHOH1< DfDfD@øøff.HH9HH 241@@U@HH93LG241@t@ylHL9uHH98241@@~7@HH9w 241@S@HD@tHH9(DHH9LG241@@~@HH9241@x@@uHH9c241@x@e@tHH9vf.HH9*LG241@@@HH9w%241@@y HI9uH@_HL9f@HH9241@x]@@uMHH9v241@x$@`@uHH9vf.HI9u8fHH9vfDHH9fHH9 241@@@HH9241@@HI9u@@uHH9241@x@@uHH9`241@x@`@tHL9ufDHI904fDHH9f.HL9fDHH9241@x@@uHH9w241@@HD@HH9241@x@@uHH9w241@x @~@tHI9u뗐@PHH9HI9fHI9=TfDHH9A241@@'@HH9241@@HI9u@uHH9241@x@@uHH9w241@x@a@tHI9uMf.HI9(dH2<H׉.ff.LIHHHHff.fUHSHHr9rt HH}E~,H9v'H H9vHJȍJ)9H[]ff.H5e H=iHHGB18030;\ x  @0XzRx $pFJ w?:*3$"DX`\`p$bEDG OAAPGNU0  @ `@     o`x H    oooo   GA$3a1  GA$3p1067@ GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFY@  GA+GLIBCXX_ASSERTIONSgb18030.so-2.2.10-35.el8.x86_64.debugӕct7zXZִF!t/_]?Eh=ڊ2N. u.U𽢶MPPhI,lay;i=eOaft2/)vWh 4έIzS"ZNRtqAeeh 퉟"Ud Oyw|@R YeJ)OO=(r2!+:]P~_M4JAvd:Ƶ IlexVK\'ŽOH}qF trgEjG%#8Ic n /AT`He_)W]`g\rpAvnۡcao "3͵+jzťul)q2C@ш5^zazEBug*Hzh:5ӥr8n`H^Iq*9*Н;3n[ $K;.Ċ#`\k9!$W6  i;;OXʙRm29&-cN= 91L=YvS{N@e 6]d"~هj㰆slv&5[r{ZҘ6#֖n"E=xOCwKoO*NvYlr>`ގ.R _t+NwʦB<ԓb~c)vivE|KA#u4;ixYW"76U~RcpAK6ģNf}LY ׶4@.ufu'k ]1ɱ(>γtxM>@ۮB0ߨ#cqram`#H;c_|Q. O[2hc{7~w&Px@SzN7q櫵gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 0xxH8o(Eo T^B h c pn `w g}     \           HH H P `H H ","&+PK!o..&2.2.0/x86_64-linux/enc/windows_1250.sonuȯELF> @p'@8 @   (0    888$$ Std PtdDDQtdRtd  GNU< &b1:%6? @  BE쪞ٻ|qX $U Gg, F"Z8   m@ a8 __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeonigenc_get_case_fold_codes_by_str_with_maponigenc_apply_all_case_fold_with_mapInit_windows_1250rb_enc_registeronigenc_single_byte_mbc_enc_lenonigenc_is_mbc_newline_0x0aonigenc_single_byte_mbc_to_codeonigenc_single_byte_code_to_mbclenonigenc_single_byte_code_to_mbconigenc_minimum_property_name_to_ctypeonigenc_not_support_get_ctype_code_rangeonigenc_single_byte_left_adjust_char_headonigenc_always_true_is_allowed_reverse_matchlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64Pui r @      H @ x P       @  X ` h p              (  0 HH HtH5 % hhhh% D% D% D% DH= H H9tH6 Ht H=q H5j H)HHH?HHtH HtfD=- u+UH= Ht H= Yd ]wHHBHff.@1wH xff.fHIIѺQH5(yH@IIѿ(H5cnff.H5% H=9HHWindows-1250@@@@@@@@@ B BBBB@@@@@@@@@@@@@@@@@@BAAAAAAAAAAAAAAAxxxxxxxxxxAAAAAAA||||||ttttttttttttttttttttAAAAQAxxxxxxppppppppppppppppppppAAAA@44444000004444000040044444444444444444444444444444400000000000000000000000000000000  !"#$%&'()*+,-./0123456789:;<=>?@abcdefghijklmnopqrstuvwxyz[\]^_`abcdefghijklmnopqrstuvwxyz{|}~;D``@pzRx $PFJ w?:*3$"D @\!p$#@,HL WT"pGNU@  @ P -8FP~ (   o`   `  ohoo<o  0 @ GA$3a1 5 GA$3p1067P ' GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFYP q GA+GLIBCXX_ASSERTIONSwindows_1250.so-2.2.10-35.el8.x86_64.debugkn7zXZִF!t/Q]?Eh=ڊ2N. Z'' AA"u8g^Ǔ+]&Z=%I_|r`B|:X 1tlyy}RL>ODp>˽I!# :oyY~hRn?Ma}P 팞uo/Zg=7I\I0fgC^ փX,Tn򼹨Ac/F 74xǺbܫ,ƥ|?H2Bow4g)A8V|y(=@y["_u֦ʞ.bxjt=L1[t*mo%2=jX,|ğ'+c3 Ag <4([uӣ^ L}b=:`BBDp{%pV21iJ` ׈O~Y7%`v{-ۜ^D?Ym٠'3y{ IsϷIQ˩h $Fc&o]/쑀-DaѦa^!uBnN!mzpӨJpZ^nDAm\R^0 'xf9M2ɚKZ {i}.-P${'>"CuzgH/^ڪ 4. )'9$=a&d\6@o̵b5rĺm_K۔,3߶0pʁ1t 8$ڂ`ݛT iӄIJ ^X>p:XN$gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 08o<<*Eohh T^B `h c PnP P @w }( ( @ @ ` D           88 8 @ `8 H "0"D&+PK! @h'@8 @   (0    888$$ Std PtdDDQtdRtd  GNUxwuq8La2 @ BE|qX3,\ "U Ee, F"X8 k@ _8  0 __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeonigenc_get_case_fold_codes_by_str_with_maponigenc_apply_all_case_fold_with_mapInit_iso_8859_3rb_enc_registeronigenc_single_byte_mbc_enc_lenonigenc_is_mbc_newline_0x0aonigenc_single_byte_mbc_to_codeonigenc_single_byte_code_to_mbclenonigenc_single_byte_code_to_mbconigenc_minimum_property_name_to_ctypeonigenc_not_support_get_ctype_code_rangeonigenc_single_byte_left_adjust_char_headonigenc_always_true_is_allowed_reverse_matchlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64Nui p @      H ` x       P @  X ` h p              (  0 HH HtH5 % hhhh% D% D% D% DH= H H9tH6 Ht H=q H5j H)HHH?HHtH HtfD=- u+UH= Ht H= Yd ]w1wH9xff.fHIIѺQH5#H@IIѿ#H5ff.H?@abcdefghijklmnopqrstuvwxyz[\]^_`abcdefghijklmnopqrstuvwxyz{|}~;D``@zRx $PFJ w?:*3$"D @\#p$,HL W8"TBGNU@  `  P  +6DN| H   o`   `  ohoo:o  0 @ GA$3a1 U GA$3p1067P G GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFYP s GA+GLIBCXX_ASSERTIONSiso_8859_3.so-2.2.10-35.el8.x86_64.debugv7zXZִF!t/I]?Eh=ڊ2N. x'' AA":yXN~s*dЂAvmp$O^q\caFy;f F5\@ar,,^is&zS+]6xSxxjhx!4i Gt9a_I.@V d叺N^˝uyU+w0WR|ປq̹OH}zLr?(SmXI:"Et)<8B-m`.kyY2[_f9FES%v쿷LYi`h S j b^ւ:/?Vcp :ljҼ]&RZG~Z)j S\9WMX͌mqJ.r:n,\/euւ[ dYpRo[P2eʋe@]=rBpއXGPDkl=݋KYl*=C U3f _w[0Wo3i |Aj9SDi:$~QX=|k\XT_T!k|/39(ҹE5xb%IϞq+|0?}8DM}Y&hG0vk"Ss91H3uYivG]]g7׉> [2\(Ry#: ϑ1ď!ye67!W^#G3A}衧qx6mِ0@}+U5V~YzBAWP^g!FZO7bH#HEq[h:g}iu/hgYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 08o::*Eohh T^B `h c PnP P @w }H H ` ` @ D           88 8 @ `8 H "0"<&+PK!..%2.2.0/x86_64-linux/enc/iso_8859_14.sonuȯELF> @h'@8 @   (0    888$$ Std PtdDDQtdRtd  GNUbp|o'D* XB BE|qXe #U Ff, F"Y8 l@ `8  0 __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeonigenc_get_case_fold_codes_by_str_with_maponigenc_apply_all_case_fold_with_mapInit_iso_8859_14rb_enc_registeronigenc_single_byte_mbc_enc_lenonigenc_is_mbc_newline_0x0aonigenc_single_byte_mbc_to_codeonigenc_single_byte_code_to_mbclenonigenc_single_byte_code_to_mbconigenc_minimum_property_name_to_ctypeonigenc_not_support_get_ctype_code_rangeonigenc_single_byte_left_adjust_char_headonigenc_always_true_is_allowed_reverse_matchlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64Oui q @      H ` x       P @  X ` h p              (  0 HH HtH5 % hhhh% D% D% D% DH= H H9tH6 Ht H=q H5j H)HHH?HHtH HtfD=- u+UH= Ht H= Yd ]w1wHyxff.fHIIѺQH5,H@IIѿ,H5ff.H?@abcdefghijklmnopqrstuvwxyz[\]^_`abcdefghijklmnopqrstuvwxyz{|}~;D `ppPzRx $PFJ w?:*3$"D@\#p,HL W"BPGNU@  `  P  ,7EO} H   o`   `  ohoo:o  0 @ GA$3a1 U GA$3p1067P G GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFYP s GA+GLIBCXX_ASSERTIONSiso_8859_14.so-2.2.10-35.el8.x86_64.debug7zXZִF!t/H]?Eh=ڊ2N. x'' AA":jL-MkF(H4@q{h'EoTU`n╜Seuk>˻1vB6!#88r:լt@C^,rulkWz%\&'.ȆS'dNBf VCPF#TA^raZ47MS^,B袘瓚ek0Ĭ7H-IQz,'GF__n+Ջ4 ʠTdhU 9}̦sgYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 08o::*Eohh T^B `h c PnP P @w }H H ` `  D((           88 8 @ `8 H "0"8&+PK!#@..&2.2.0/x86_64-linux/enc/windows_1251.sonuȯELF> @p'@8 @   (0    888$$ Std PtdDDQtdRtd  GNU(Jr՜H)@  BE|qX $U Gg, F"Z8 m@ a8  __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeonigenc_get_case_fold_codes_by_str_with_maponigenc_apply_all_case_fold_with_mapInit_windows_1251rb_enc_registeronigenc_single_byte_mbc_enc_lenonigenc_is_mbc_newline_0x0aonigenc_single_byte_mbc_to_codeonigenc_single_byte_code_to_mbclenonigenc_single_byte_code_to_mbconigenc_minimum_property_name_to_ctypeonigenc_not_support_get_ctype_code_rangeonigenc_single_byte_left_adjust_char_headonigenc_always_true_is_allowed_reverse_matchlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64Pui r @      H @ x P       @  X ` h p              (  0 HH HtH5 % hhhh% D% D% D% DH= H H9tH6 Ht H=q H5j H)HHH?HHtH HtfD=- u+UH= Ht H= Yd ]wHH"Hff.@1wHxff.fHII1QH5!|HIIѿ!1H5fqH55 H=.IHHWindows-1251@@@@@@@@@B BBBB@@@@@@@@@@@@@@@@@@BAAAAAAAAAAAAAAAxxxxxxxxxxAAAAAAA||||||ttttttttttttttttttttAAAAQAxxxxxxppppppppppppppppppppAAAA@44044444000000404444440010004004444444444444444444444444444444400000000000000000000000000000000  !"#$%&'()*+,-./0123456789:;<=>?@abcdefghijklmnopqrstuvwxyz[\]^_`abcdefghijklmnopqrstuvwxyz{|}~;D`0`zRx $PFJ w?:*3$"D@@\(!pD#`)HI WtGNU@  @ P -8FP~    o`   `  ohoo<o  0 @ GA$3a1 % GA$3p1067P  GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFYP q GA+GLIBCXX_ASSERTIONSwindows_1251.so-2.2.10-35.el8.x86_64.debug%X<7zXZִF!t/P]?Eh=ڊ2N. Z'' AA":t EmD9bk$@#v/ c9Q!Z8s'r<4w%#(]Kc2u{aA;qI۾ðKeKωHqkA(ݘp6qIb/~PQ=S[tN+|N<jc԰~; .9\՗bniجsl:(?yn1Idɠ}lE]z0(T]mtFUSp35Q/m7éI5T C6ȂTLf JJՁ٘A۴l͠4*FX. U.V`Rzm'.y-LUu79uHt1δĿKε/(zs^*7x\v:?&[:aYOHkiI;Uqu:*4>>KCvѫΪPqas]2^6ͬMhf(l ?tw>bD ЄU%=^e%s]af~*zvd5z1}Ks>+TnA/:T=5cM͠ӚGa *S{Mד2tML8 2M|[PX4,e8.BW`ܩ૨/ -:679L2@{6Ϣ8$ K:~gSc. ]nJ cahZGjP&gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 08o<<*Eohh T^B `h c PnP P @w }  @ @ @ D           88 8 @ `8 H "0"@&+PK! ..&2.2.0/x86_64-linux/enc/windows_1252.sonuȯELF> @p'@8 @   (0    888$$ Std PtdDDQtdRtd  GNUkJњ\=H_<{L@/@  BE|qX $U Gg, F"Z8 m@ a8   __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeonigenc_get_case_fold_codes_by_str_with_maponigenc_apply_all_case_fold_with_mapInit_windows_1252rb_enc_registeronigenc_single_byte_mbc_enc_lenonigenc_is_mbc_newline_0x0aonigenc_single_byte_mbc_to_codeonigenc_single_byte_code_to_mbclenonigenc_single_byte_code_to_mbconigenc_minimum_property_name_to_ctypeonigenc_not_support_get_ctype_code_rangeonigenc_single_byte_left_adjust_char_headonigenc_always_true_is_allowed_reverse_matchlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64Pui r @      H @ x P       @  X ` h p              (  0 HH HtH5 % hhhh% D% D% D% DH= H H9tH6 Ht H=q H5j H)HHH?HHtH HtfD=- u+UH= Ht H= Yd ]wHH"Hff.@1wHxff.fHIIѺQH5"yH@IIѿ"H5cnff.H5% H=9HHWindows-1252@@@@@@@@@ B BBBB@@@@@@@@@@@@@@@@@@BAAAAAAAAAAAAAAAxxxxxxxxxxAAAAAAA||||||ttttttttttttttttttttAAAAQAxxxxxxppppppppppppppppppppAAAA@444000400044444444444444444444444444444400000000000000000000000000000000  !"#$%&'()*+,-./0123456789:;<=>?@abcdefghijklmnopqrstuvwxyz[\]^_`abcdefghijklmnopqrstuvwxyz{|}~;D`0`zRx $PFJ w?:*3$"D@@\(!pD#`,HL Wt"GNU@  @ P -8FP~ (   o`   `  ohoo<o  0 @ GA$3a1 5 GA$3p1067P ' GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFYP q GA+GLIBCXX_ASSERTIONSwindows_1252.so-2.2.10-35.el8.x86_64.debug;7zXZִF!t/P]?Eh=ڊ2N. Z'' AA":uY)g4T"7]eo7I2GY0l;T^ƒW^wR"̬i(R˓/ Zju<ΊU?:M2T++bm^X1u?{MIWbNi-,qxSc8@FEطP ;!&<и[WC#4q+![ {Yy׮VRS4rIe_%be3Bg}ob>gw] lQUh)*Tu1n#lۖ!x#6g)ݺ?Q[ohw`l@Vqy[ni%5nH'QJH:]<Ji L@/筺D2{V;(d cru UaS'ww5,fT22ROS#p+̻[,=6AN|7<+X}ƃ5ܛ2fxjJCr݆+s|qfW J"Xna`+OP rD(JA v+)ȆJ)ęe|691>"mߗi@nxמon[¥g> fI%u3]3x`-_O_S%g?T<@%;iCRj0B.4 ʜVNJ˂> 5;G}n12wT[0R_g:gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 08o<<*Eohh T^B `h c PnP P @w }( ( @ @ @ D           88 8 @ `8 H "0"@&+PK!x22.2.0/x86_64-linux/enc/trans/emoji_iso2022_kddi.sonuȯELF>@p@8 @ !!  !!  888$$ Std PtdTTQtdRtd!!GNUj3䎰5Ս@! BE|qXWw[ m , F"(!0!(!U <__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeInit_emoji_iso2022_kddirb_register_transcoderlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ui !P ! ! !@!` H!j X! 6h! !` !` !p ! ȫ! Ы! !j !` ! 6! 0!` 8!` H!0 X!` !{ !` ! 6! !` (!{ 8! 6H! !!!!! !HH!HtH5!%!hh%!D%!DH=!Hz!H9tH&!Ht H=Q!H5J!H)HHH?HHtH!HtfD= !u+UH=Ҧ!Ht H=!Yd!]w1fDHtc>Ht;<tA$ABHQfDFvHBH)ȃ@rf<t޸$HQA@fDIȄtA(ABLAfD I@H)ȃA?HDf.?t!<^H9Hff.@>t'?DȀAFȀAf~(Tt%@t8Bt 11f.Bt1Ju1fD1f1?t(FBfHH=Ѡ!lH=%!`H=!TH=M!HDHHstateless-ISO-2022-JP-KDDIUTF8-KDDI $,HPXY`ⅰⅱⅲⅳⅴⅵⅶⅷⅸⅹⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩ¬¦'"㈱№℡∵纊褜鍈銈蓜俉炻昱棈鋹曻彅丨仡仼伀伃伹佖侒侊侚侔俍偀倢俿倞偆偰偂傔僴僘兊兤冝冾凬刕劜劦勀勛匀匇匤卲厓厲叝﨎咜咊咩哿喆坙坥垬埈埇﨏塚增墲t夋奓奛奝奣妤妺孖寀甯寘寬尞岦岺峵崧嵓﨑嵂嵭嶸嶹巐弡弴彧德忞恝悅悊惞惕愠惲愑愷愰憘戓抦揵摠撝擎敎昀昕昻昉昮昞昤晥晗晙晴晳暙暠暲暿曺朎朗杦枻桒柀栁桄棏﨓楨﨔榘槢樰橫橆橳橾櫢櫤毖氿汜沆汯泚洄涇浯涖涬淏淸淲淼渹湜渧渼溿澈澵濵瀅瀇瀨炅炫焏焄煜煆煇凞燁燾犱犾猤猪獷玽珉珖珣珒琇珵琦琪琩琮瑢璉璟甁畯皂皜皞皛皦益睆劯砡硎硤硺礰礼神祥禔福禛竑竧靖竫箞精絈絜綷綠緖繒罇羡羽茁荢荿菇菶葈蒴蕓蕙蕫﨟薰|蘒﨡蠇裵訒訷詹誧誾諟諸諶譓譿賰賴贒赶﨣軏﨤逸遧郞都鄕鄧釚釗釞釭釮釤釥鈆鈐鈊鈺鉀鈼鉎鉙鉑鈹鉧銧鉷鉸鋧鋗鋙鋐﨧鋕鋠鋓錥錡鋻﨨錞鋿錝錂鍰鍗鎤鏆鏞鏸鐱鑅鑈閒隆﨩隝隯霳霻靃靍靏靑靕顗顥飯飼餧館馞驎髙髜魵魲鮏鮱鮻鰀鵰鵫鶴鸙黑N 、。,.・:;?!゛゜´`¨^ ̄_ヽヾゝゞ〃仝々〆〇ー―‐/\~∥|…‥‘’“”()〔〕[]{}〈〉《》「」『』【】+-±×÷=≠<>≦≧∞∴♂♀°′″℃¥$¢£%#&*@§☆★○●◎◇◆□■△▲▽▼※〒→←↑↓〓∈∋⊆⊇⊂⊃∪∩∧∨¬⇒⇔∀∃∠⊥⌒∂∇≡≒≪≫√∽∝∵∫∬ʼn♯♭♪†‡¶◯\D0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz$ ぁあぃいぅうぇえぉおかがきぎくぐけげこごさざしじすずせぜそぞただちぢっつづてでとどなにぬねのはばぱひびぴふぶぷへべぺほぼぽまみむめもゃやゅゆょよらりるれろゎわゐゑをん ( ァアィイゥウェエォオカガキギクグケゲコゴサザシジスズセゼソゾタダチヂッツヅテデトドナニヌネノハバパヒビピフブプヘベペホボポマミムメモャヤュユョヨラリルレロヮワヰヱヲンヴヵヶ^ ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩαβγδεζηθικλμνξοπρστυφχψω АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщъыьэюя ─│┌┐┘└├┬┤┴┼━┃┏┓┛┗┣┳┫┻╋┠┯┨┷┿┝┰┥┸╂C①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩ㍉㌔㌢㍍㌘㌧㌃㌶㍑㍗㌍㌦㌣㌫㍊㌻㎜㎝㎞㎎㎏㏄㎡㍻〝〟№㏍℡㊤㊥㊦㊧㊨㈱㈲㈹㍾㍽㍼≒≡∫∮∑√⊥∠∟⊿∵∩∪eP亜唖娃阿哀愛挨姶逢葵茜穐悪握渥旭葦芦鯵梓圧斡扱宛姐虻飴絢綾鮎或粟袷安庵按暗案闇鞍杏以伊位依偉囲夷委威尉惟意慰易椅為畏異移維緯胃萎衣謂違遺医井亥域育郁磯一壱溢逸稲茨芋鰯允印咽員因姻引飲淫胤蔭院陰隠韻吋右宇烏羽迂雨卯鵜窺丑碓臼渦嘘唄欝蔚鰻姥厩浦瓜閏噂云運雲荏餌叡営嬰影映曳栄永泳洩瑛盈穎頴英衛詠鋭液疫益駅悦謁越閲榎厭円園堰奄宴延怨掩援沿演炎焔煙燕猿縁艶苑薗遠鉛鴛塩於汚甥凹央奥往応,押旺横欧殴王翁襖鴬鴎黄岡沖荻億屋憶臆桶牡乙俺卸恩温穏音下化仮何伽価佳加可嘉夏嫁家寡科暇果架歌河火珂禍禾稼箇花苛茄荷華菓蝦課嘩貨迦過霞蚊俄峨我牙画臥芽蛾賀雅餓駕介会解回塊壊廻快怪悔恢懐戒拐改魁晦械海灰界皆絵芥蟹開階貝凱劾外咳害崖慨概涯碍蓋街該鎧骸浬馨蛙垣柿蛎鈎劃嚇各廓拡撹格核殻獲確穫覚角赫較郭閣隔革学岳楽額顎掛笠樫橿梶鰍潟割喝恰括活渇滑葛褐轄且鰹叶椛樺鞄株兜竃蒲釜鎌噛鴨栢茅萱4粥刈苅瓦乾侃冠寒刊勘勧巻喚堪姦完官寛干幹患感慣憾換敢柑桓棺款歓汗漢澗潅環甘監看竿管簡緩缶翰肝艦莞観諌貫還鑑間閑関陥韓館舘丸含岸巌玩癌眼岩翫贋雁頑顔願企伎危喜器基奇嬉寄岐希幾忌揮机旗既期棋棄機帰毅気汽畿祈季稀紀徽規記貴起軌輝飢騎鬼亀偽儀妓宜戯技擬欺犠疑祇義蟻誼議掬菊鞠吉吃喫桔橘詰砧杵黍却客脚虐逆丘久仇休及吸宮弓急救朽求汲泣灸球究窮笈級糾給旧牛去居巨拒拠挙渠虚許距鋸漁禦魚亨享京<供侠僑兇競共凶協匡卿叫喬境峡強彊怯恐恭挟教橋況狂狭矯胸脅興蕎郷鏡響饗驚仰凝尭暁業局曲極玉桐粁僅勤均巾錦斤欣欽琴禁禽筋緊芹菌衿襟謹近金吟銀九倶句区狗玖矩苦躯駆駈駒具愚虞喰空偶寓遇隅串櫛釧屑屈掘窟沓靴轡窪熊隈粂栗繰桑鍬勲君薫訓群軍郡卦袈祁係傾刑兄啓圭珪型契形径恵慶慧憩掲携敬景桂渓畦稽系経継繋罫茎荊蛍計詣警軽頚鶏芸迎鯨劇戟撃激隙桁傑欠決潔穴結血訣月件倹倦健兼券剣喧圏堅嫌建憲懸拳捲D検権牽犬献研硯絹県肩見謙賢軒遣鍵険顕験鹸元原厳幻弦減源玄現絃舷言諺限乎個古呼固姑孤己庫弧戸故枯湖狐糊袴股胡菰虎誇跨鈷雇顧鼓五互伍午呉吾娯後御悟梧檎瑚碁語誤護醐乞鯉交佼侯候倖光公功効勾厚口向后喉坑垢好孔孝宏工巧巷幸広庚康弘恒慌抗拘控攻昂晃更杭校梗構江洪浩港溝甲皇硬稿糠紅紘絞綱耕考肯肱腔膏航荒行衡講貢購郊酵鉱砿鋼閤降項香高鴻剛劫号合壕拷濠豪轟麹克刻告国穀酷鵠黒獄漉腰甑忽惚骨狛込L此頃今困坤墾婚恨懇昏昆根梱混痕紺艮魂些佐叉唆嵯左差査沙瑳砂詐鎖裟坐座挫債催再最哉塞妻宰彩才採栽歳済災采犀砕砦祭斎細菜裁載際剤在材罪財冴坂阪堺榊肴咲崎埼碕鷺作削咋搾昨朔柵窄策索錯桜鮭笹匙冊刷察拶撮擦札殺薩雑皐鯖捌錆鮫皿晒三傘参山惨撒散桟燦珊産算纂蚕讃賛酸餐斬暫残仕仔伺使刺司史嗣四士始姉姿子屍市師志思指支孜斯施旨枝止死氏獅祉私糸紙紫肢脂至視詞詩試誌諮資賜雌飼歯事似侍児字寺慈持時T!次滋治爾璽痔磁示而耳自蒔辞汐鹿式識鴫竺軸宍雫七叱執失嫉室悉湿漆疾質実蔀篠偲柴芝屡蕊縞舎写射捨赦斜煮社紗者謝車遮蛇邪借勺尺杓灼爵酌釈錫若寂弱惹主取守手朱殊狩珠種腫趣酒首儒受呪寿授樹綬需囚収周"宗就州修愁拾洲秀秋終繍習臭舟蒐衆襲讐蹴輯週酋酬集醜什住充十従戎柔汁渋獣縦重銃叔夙宿淑祝縮粛塾熟出術述俊峻春瞬竣舜駿准循旬楯殉淳準潤盾純巡遵醇順処初所暑曙渚庶緒署書薯藷諸助叙女序徐恕鋤除傷償\$勝匠升召哨商唱嘗奨妾娼宵将小少尚庄床廠彰承抄招掌捷昇昌昭晶松梢樟樵沼消渉湘焼焦照症省硝礁祥称章笑粧紹肖菖蒋蕉衝裳訟証詔詳象賞醤鉦鍾鐘障鞘上丈丞乗冗剰城場壌嬢常情擾条杖浄状畳穣蒸譲醸錠嘱埴飾%拭植殖燭織職色触食蝕辱尻伸信侵唇娠寝審心慎振新晋森榛浸深申疹真神秦紳臣芯薪親診身辛進針震人仁刃塵壬尋甚尽腎訊迅陣靭笥諏須酢図厨逗吹垂帥推水炊睡粋翠衰遂酔錐錘随瑞髄崇嵩数枢趨雛据杉椙菅頗雀裾d'澄摺寸世瀬畝是凄制勢姓征性成政整星晴棲栖正清牲生盛精聖声製西誠誓請逝醒青静斉税脆隻席惜戚斥昔析石積籍績脊責赤跡蹟碩切拙接摂折設窃節説雪絶舌蝉仙先千占宣専尖川戦扇撰栓栴泉浅洗染潜煎煽旋穿箭線(繊羨腺舛船薦詮賎践選遷銭銑閃鮮前善漸然全禅繕膳糎噌塑岨措曾曽楚狙疏疎礎祖租粗素組蘇訴阻遡鼠僧創双叢倉喪壮奏爽宋層匝惣想捜掃挿掻操早曹巣槍槽漕燥争痩相窓糟総綜聡草荘葬蒼藻装走送遭鎗霜騒像増憎l*臓蔵贈造促側則即息捉束測足速俗属賊族続卒袖其揃存孫尊損村遜他多太汰詑唾堕妥惰打柁舵楕陀駄騨体堆対耐岱帯待怠態戴替泰滞胎腿苔袋貸退逮隊黛鯛代台大第醍題鷹滝瀧卓啄宅托択拓沢濯琢託鐸濁諾茸凧蛸只+叩但達辰奪脱巽竪辿棚谷狸鱈樽誰丹単嘆坦担探旦歎淡湛炭短端箪綻耽胆蛋誕鍛団壇弾断暖檀段男談値知地弛恥智池痴稚置致蜘遅馳築畜竹筑蓄逐秩窒茶嫡着中仲宙忠抽昼柱注虫衷註酎鋳駐樗瀦猪苧著貯丁兆凋喋寵t-帖帳庁弔張彫徴懲挑暢朝潮牒町眺聴脹腸蝶調諜超跳銚長頂鳥勅捗直朕沈珍賃鎮陳津墜椎槌追鎚痛通塚栂掴槻佃漬柘辻蔦綴鍔椿潰坪壷嬬紬爪吊釣鶴亭低停偵剃貞呈堤定帝底庭廷弟悌抵挺提梯汀碇禎程締艇訂諦蹄逓.邸鄭釘鼎泥摘擢敵滴的笛適鏑溺哲徹撤轍迭鉄典填天展店添纏甜貼転顛点伝殿澱田電兎吐堵塗妬屠徒斗杜渡登菟賭途都鍍砥砺努度土奴怒倒党冬凍刀唐塔塘套宕島嶋悼投搭東桃梼棟盗淘湯涛灯燈当痘祷等答筒糖統到|0董蕩藤討謄豆踏逃透鐙陶頭騰闘働動同堂導憧撞洞瞳童胴萄道銅峠鴇匿得徳涜特督禿篤毒独読栃橡凸突椴届鳶苫寅酉瀞噸屯惇敦沌豚遁頓呑曇鈍奈那内乍凪薙謎灘捺鍋楢馴縄畷南楠軟難汝二尼弐迩匂賑肉虹廿日乳入2如尿韮任妊忍認濡禰祢寧葱猫熱年念捻撚燃粘乃廼之埜嚢悩濃納能脳膿農覗蚤巴把播覇杷波派琶破婆罵芭馬俳廃拝排敗杯盃牌背肺輩配倍培媒梅楳煤狽買売賠陪這蝿秤矧萩伯剥博拍柏泊白箔粕舶薄迫曝漠爆縛莫駁麦3函箱硲箸肇筈櫨幡肌畑畠八鉢溌発醗髪伐罰抜筏閥鳩噺塙蛤隼伴判半反叛帆搬斑板氾汎版犯班畔繁般藩販範釆煩頒飯挽晩番盤磐蕃蛮匪卑否妃庇彼悲扉批披斐比泌疲皮碑秘緋罷肥被誹費避非飛樋簸備尾微枇毘琵眉美5鼻柊稗匹疋髭彦膝菱肘弼必畢筆逼桧姫媛紐百謬俵彪標氷漂瓢票表評豹廟描病秒苗錨鋲蒜蛭鰭品彬斌浜瀕貧賓頻敏瓶不付埠夫婦富冨布府怖扶敷斧普浮父符腐膚芙譜負賦赴阜附侮撫武舞葡蕪部封楓風葺蕗伏副復幅服6福腹複覆淵弗払沸仏物鮒分吻噴墳憤扮焚奮粉糞紛雰文聞丙併兵塀幣平弊柄並蔽閉陛米頁僻壁癖碧別瞥蔑箆偏変片篇編辺返遍便勉娩弁鞭保舗鋪圃捕歩甫補輔穂募墓慕戊暮母簿菩倣俸包呆報奉宝峰峯崩庖抱捧放方朋8法泡烹砲縫胞芳萌蓬蜂褒訪豊邦鋒飽鳳鵬乏亡傍剖坊妨帽忘忙房暴望某棒冒紡肪膨謀貌貿鉾防吠頬北僕卜墨撲朴牧睦穆釦勃没殆堀幌奔本翻凡盆摩磨魔麻埋妹昧枚毎哩槙幕膜枕鮪柾鱒桝亦俣又抹末沫迄侭繭麿万慢満9漫蔓味未魅巳箕岬密蜜湊蓑稔脈妙粍民眠務夢無牟矛霧鵡椋婿娘冥名命明盟迷銘鳴姪牝滅免棉綿緬面麺摸模茂妄孟毛猛盲網耗蒙儲木黙目杢勿餅尤戻籾貰問悶紋門匁也冶夜爺耶野弥矢厄役約薬訳躍靖柳薮鑓愉愈油癒;諭輸唯佑優勇友宥幽悠憂揖有柚湧涌猶猷由祐裕誘遊邑郵雄融夕予余与誉輿預傭幼妖容庸揚揺擁曜楊様洋溶熔用窯羊耀葉蓉要謡踊遥陽養慾抑欲沃浴翌翼淀羅螺裸来莱頼雷洛絡落酪乱卵嵐欄濫藍蘭覧利吏履李梨理璃<痢裏裡里離陸律率立葎掠略劉流溜琉留硫粒隆竜龍侶慮旅虜了亮僚両凌寮料梁涼猟療瞭稜糧良諒遼量陵領力緑倫厘林淋燐琳臨輪隣鱗麟瑠塁涙累類令伶例冷励嶺怜玲礼苓鈴隷零霊麗齢暦歴列劣烈裂廉恋憐漣煉簾練聯 >蓮連錬呂魯櫓炉賂路露労婁廊弄朗楼榔浪漏牢狼篭老聾蝋郎六麓禄肋録論倭和話歪賄脇惑枠鷲亙亘鰐詫藁蕨椀湾碗腕?弌丐丕个丱丶丼丿乂乖乘亂亅豫亊舒弍于亞亟亠亢亰亳亶从仍仄仆仂仗仞仭仟价伉佚估佛佝佗佇佶侈侏侘佻佩佰侑佯來侖儘俔俟俎俘俛俑俚俐俤俥倚倨倔倪倥倅伜俶倡倩倬俾俯們倆偃假會偕偐偈做偖偬偸傀傚傅傴傲|@僉僊傳僂僖僞僥僭僣僮價僵儉儁儂儖儕儔儚儡儺儷儼儻儿兀兒兌兔兢竸兩兪兮冀冂囘册冉冏冑冓冕冖冤冦冢冩冪冫决冱冲冰况冽凅凉凛几處凩凭凰凵凾刄刋刔刎刧刪刮刳刹剏剄剋剌剞剔剪剴剩剳剿剽劍劔劒剱劈劑辨B辧劬劭劼劵勁勍勗勞勣勦飭勠勳勵勸勹匆匈甸匍匐匏匕匚匣匯匱匳匸區卆卅丗卉卍凖卞卩卮夘卻卷厂厖厠厦厥厮厰厶參簒雙叟曼燮叮叨叭叺吁吽呀听吭吼吮吶吩吝呎咏呵咎呟呱呷呰咒呻咀呶咄咐咆哇咢咸咥咬哄哈咨C咫哂咤咾咼哘哥哦唏唔哽哮哭哺哢唹啀啣啌售啜啅啖啗唸唳啝喙喀咯喊喟啻啾喘喞單啼喃喩喇喨嗚嗅嗟嗄嗜嗤嗔嘔嗷嘖嗾嗽嘛嗹噎噐營嘴嘶嘲嘸噫噤嘯噬噪嚆嚀嚊嚠嚔嚏嚥嚮嚶嚴囂嚼囁囃囀囈囎囑囓囗囮囹圀囿圄圉E圈國圍圓團圖嗇圜圦圷圸坎圻址坏坩埀垈坡坿垉垓垠垳垤垪垰埃埆埔埒埓堊埖埣堋堙堝塲堡塢塋塰毀塒堽塹墅墹墟墫墺壞墻墸墮壅壓壑壗壙壘壥壜壤壟壯壺壹壻壼壽夂夊夐夛梦夥夬夭夲夸夾竒奕奐奎奚奘奢奠奧奬奩F奸妁妝佞侫妣妲姆姨姜妍姙姚娥娟娑娜娉娚婀婬婉娵娶婢婪媚媼媾嫋嫂媽嫣嫗嫦嫩嫖嫺嫻嬌嬋嬖嬲嫐嬪嬶嬾孃孅孀孑孕孚孛孥孩孰孳孵學斈孺宀它宦宸寃寇寉寔寐寤實寢寞寥寫寰寶寳尅將專對尓尠尢尨尸尹屁屆屎屓H屐屏孱屬屮乢屶屹岌岑岔妛岫岻岶岼岷峅岾峇峙峩峽峺峭嶌峪崋崕崗嵜崟崛崑崔崢崚崙崘嵌嵒嵎嵋嵬嵳嵶嶇嶄嶂嶢嶝嶬嶮嶽嶐嶷嶼巉巍巓巒巖巛巫已巵帋帚帙帑帛帶帷幄幃幀幎幗幔幟幢幤幇幵并幺麼广庠廁廂廈廐廏I廖廣廝廚廛廢廡廨廩廬廱廳廰廴廸廾弃弉彝彜弋弑弖弩弭弸彁彈彌彎弯彑彖彗彙彡彭彳彷徃徂彿徊很徑徇從徙徘徠徨徭徼忖忻忤忸忱忝悳忿怡恠怙怐怩怎怱怛怕怫怦怏怺恚恁恪恷恟恊恆恍恣恃恤恂恬恫恙悁悍惧悃悚K悄悛悖悗悒悧悋惡悸惠惓悴忰悽惆悵惘慍愕愆惶惷愀惴惺愃愡惻惱愍愎慇愾愨愧慊愿愼愬愴愽慂慄慳慷慘慙慚慫慴慯慥慱慟慝慓慵憙憖憇憬憔憚憊憑憫憮懌懊應懷懈懃懆憺懋罹懍懦懣懶懺懴懿懽懼懾戀戈戉戍戌戔戛L戞戡截戮戰戲戳扁扎扞扣扛扠扨扼抂抉找抒抓抖拔抃抔拗拑抻拏拿拆擔拈拜拌拊拂拇抛拉挌拮拱挧挂挈拯拵捐挾捍搜捏掖掎掀掫捶掣掏掉掟掵捫捩掾揩揀揆揣揉插揶揄搖搴搆搓搦搶攝搗搨搏摧摯摶摎攪撕撓撥撩撈撼 N據擒擅擇撻擘擂擱擧舉擠擡抬擣擯攬擶擴擲擺攀擽攘攜攅攤攣攫攴攵攷收攸畋效敖敕敍敘敞敝敲數斂斃變斛斟斫斷旃旆旁旄旌旒旛旙无旡旱杲昊昃旻杳昵昶昴昜晏晄晉晁晞晝晤晧晨晟晢晰暃暈暎暉暄暘暝曁暹曉暾暼O曄暸曖曚曠昿曦曩曰曵曷朏朖朞朦朧霸朮朿朶杁朸朷杆杞杠杙杣杤枉杰枩杼杪枌枋枦枡枅枷柯枴柬枳柩枸柤柞柝柢柮枹柎柆柧檜栞框栩桀桍栲桎梳栫桙档桷桿梟梏梭梔條梛梃檮梹桴梵梠梺椏梍桾椁棊椈棘椢椦棡椌棍(Q棔棧棕椶椒椄棗棣椥棹棠棯椨椪椚椣椡棆楹楷楜楸楫楔楾楮椹楴椽楙椰楡楞楝榁楪榲榮槐榿槁槓榾槎寨槊槝榻槃榧樮榑榠榜榕榴槞槨樂樛槿權槹槲槧樅榱樞槭樔槫樊樒櫁樣樓橄樌橲樶橸橇橢橙橦橈樸樢檐檍檠檄檢檣R檗蘗檻櫃櫂檸檳檬櫞櫑櫟檪櫚櫪櫻欅蘖櫺欒欖鬱欟欸欷盜欹飮歇歃歉歐歙歔歛歟歡歸歹歿殀殄殃殍殘殕殞殤殪殫殯殲殱殳殷殼毆毋毓毟毬毫毳毯麾氈氓气氛氤氣汞汕汢汪沂沍沚沁沛汾汨汳沒沐泄泱泓沽泗泅泝沮沱沾0T沺泛泯泙泪洟衍洶洫洽洸洙洵洳洒洌浣涓浤浚浹浙涎涕濤涅淹渕渊涵淇淦涸淆淬淞淌淨淒淅淺淙淤淕淪淮渭湮渮渙湲湟渾渣湫渫湶湍渟湃渺湎渤滿渝游溂溪溘滉溷滓溽溯滄溲滔滕溏溥滂溟潁漑灌滬滸滾漿滲漱滯漲滌U漾漓滷澆潺潸澁澀潯潛濳潭澂潼潘澎澑濂潦澳澣澡澤澹濆澪濟濕濬濔濘濱濮濛瀉瀋濺瀑瀁瀏濾瀛瀚潴瀝瀘瀟瀰瀾瀲灑灣炙炒炯烱炬炸炳炮烟烋烝烙焉烽焜焙煥煕熈煦煢煌煖煬熏燻熄熕熨熬燗熹熾燒燉燔燎燠燬燧燵燼8W燹燿爍爐爛爨爭爬爰爲爻爼爿牀牆牋牘牴牾犂犁犇犒犖犢犧犹犲狃狆狄狎狒狢狠狡狹狷倏猗猊猜猖猝猴猯猩猥猾獎獏默獗獪獨獰獸獵獻獺珈玳珎玻珀珥珮珞璢琅瑯琥珸琲琺瑕琿瑟瑙瑁瑜瑩瑰瑣瑪瑶瑾璋璞璧瓊瓏瓔珱X瓠瓣瓧瓩瓮瓲瓰瓱瓸瓷甄甃甅甌甎甍甕甓甞甦甬甼畄畍畊畉畛畆畚畩畤畧畫畭畸當疆疇畴疊疉疂疔疚疝疥疣痂疳痃疵疽疸疼疱痍痊痒痙痣痞痾痿痼瘁痰痺痲痳瘋瘍瘉瘟瘧瘠瘡瘢瘤瘴瘰瘻癇癈癆癜癘癡癢癨癩癪癧癬癰@Z癲癶癸發皀皃皈皋皎皖皓皙皚皰皴皸皹皺盂盍盖盒盞盡盥盧盪蘯盻眈眇眄眩眤眞眥眦眛眷眸睇睚睨睫睛睥睿睾睹瞎瞋瞑瞠瞞瞰瞶瞹瞿瞼瞽瞻矇矍矗矚矜矣矮矼砌砒礦砠礪硅碎硴碆硼碚碌碣碵碪碯磑磆磋磔碾碼磅磊磬[磧磚磽磴礇礒礑礙礬礫祀祠祗祟祚祕祓祺祿禊禝禧齋禪禮禳禹禺秉秕秧秬秡秣稈稍稘稙稠稟禀稱稻稾稷穃穗穉穡穢穩龝穰穹穽窈窗窕窘窖窩竈窰窶竅竄窿邃竇竊竍竏竕竓站竚竝竡竢竦竭竰笂笏笊笆笳笘笙笞笵笨笶筐H]筺笄筍笋筌筅筵筥筴筧筰筱筬筮箝箘箟箍箜箚箋箒箏筝箙篋篁篌篏箴篆篝篩簑簔篦篥籠簀簇簓篳篷簗簍篶簣簧簪簟簷簫簽籌籃籔籏籀籐籘籟籤籖籥籬籵粃粐粤粭粢粫粡粨粳粲粱粮粹粽糀糅糂糘糒糜糢鬻糯糲糴糶糺紆^紂紜紕紊絅絋紮紲紿紵絆絳絖絎絲絨絮絏絣經綉絛綏絽綛綺綮綣綵緇綽綫總綢綯緜綸綟綰緘緝緤緞緻緲緡縅縊縣縡縒縱縟縉縋縢繆繦縻縵縹繃縷縲縺繧繝繖繞繙繚繹繪繩繼繻纃緕繽辮繿纈纉續纒纐纓纔纖纎纛纜缸缺P`罅罌罍罎罐网罕罔罘罟罠罨罩罧罸羂羆羃羈羇羌羔羞羝羚羣羯羲羹羮羶羸譱翅翆翊翕翔翡翦翩翳翹飜耆耄耋耒耘耙耜耡耨耿耻聊聆聒聘聚聟聢聨聳聲聰聶聹聽聿肄肆肅肛肓肚肭冐肬胛胥胙胝胄胚胖脉胯胱脛脩脣脯腋a隋腆脾腓腑胼腱腮腥腦腴膃膈膊膀膂膠膕膤膣腟膓膩膰膵膾膸膽臀臂膺臉臍臑臙臘臈臚臟臠臧臺臻臾舁舂舅與舊舍舐舖舩舫舸舳艀艙艘艝艚艟艤艢艨艪艫舮艱艷艸艾芍芒芫芟芻芬苡苣苟苒苴苳苺莓范苻苹苞茆苜茉苙Xc茵茴茖茲茱荀茹荐荅茯茫茗茘莅莚莪莟莢莖茣莎莇莊荼莵荳荵莠莉莨菴萓菫菎菽萃菘萋菁菷萇菠菲萍萢萠莽萸蔆菻葭萪萼蕚蒄葷葫蒭葮蒂葩葆萬葯葹萵蓊葢蒹蒿蒟蓙蓍蒻蓚蓐蓁蓆蓖蒡蔡蓿蓴蔗蔘蔬蔟蔕蔔蓼蕀蕣蕘蕈d蕁蘂蕋蕕薀薤薈薑薊薨蕭薔薛藪薇薜蕷蕾薐藉薺藏薹藐藕藝藥藜藹蘊蘓蘋藾藺蘆蘢蘚蘰蘿虍乕虔號虧虱蚓蚣蚩蚪蚋蚌蚶蚯蛄蛆蚰蛉蠣蚫蛔蛞蛩蛬蛟蛛蛯蜒蜆蜈蜀蜃蛻蜑蜉蜍蛹蜊蜴蜿蜷蜻蜥蜩蜚蝠蝟蝸蝌蝎蝴蝗蝨蝮蝙`f蝓蝣蝪蠅螢螟螂螯蟋螽蟀蟐雖螫蟄螳蟇蟆螻蟯蟲蟠蠏蠍蟾蟶蟷蠎蟒蠑蠖蠕蠢蠡蠱蠶蠹蠧蠻衄衂衒衙衞衢衫袁衾袞衵衽袵衲袂袗袒袮袙袢袍袤袰袿袱裃裄裔裘裙裝裹褂裼裴裨裲褄褌褊褓襃褞褥褪褫襁襄褻褶褸襌褝襠襞g襦襤襭襪襯襴襷襾覃覈覊覓覘覡覩覦覬覯覲覺覽覿觀觚觜觝觧觴觸訃訖訐訌訛訝訥訶詁詛詒詆詈詼詭詬詢誅誂誄誨誡誑誥誦誚誣諄諍諂諚諫諳諧諤諱謔諠諢諷諞諛謌謇謚諡謖謐謗謠謳鞫謦謫謾謨譁譌譏譎證譖譛譚譫hi譟譬譯譴譽讀讌讎讒讓讖讙讚谺豁谿豈豌豎豐豕豢豬豸豺貂貉貅貊貍貎貔豼貘戝貭貪貽貲貳貮貶賈賁賤賣賚賽賺賻贄贅贊贇贏贍贐齎贓賍贔贖赧赭赱赳趁趙跂趾趺跏跚跖跌跛跋跪跫跟跣跼踈踉跿踝踞踐踟蹂踵踰踴蹊j蹇蹉蹌蹐蹈蹙蹤蹠踪蹣蹕蹶蹲蹼躁躇躅躄躋躊躓躑躔躙躪躡躬躰軆躱躾軅軈軋軛軣軼軻軫軾輊輅輕輒輙輓輜輟輛輌輦輳輻輹轅轂輾轌轉轆轎轗轜轢轣轤辜辟辣辭辯辷迚迥迢迪迯邇迴逅迹迺逑逕逡逍逞逖逋逧逶逵逹迸pl遏遐遑遒逎遉逾遖遘遞遨遯遶隨遲邂遽邁邀邊邉邏邨邯邱邵郢郤扈郛鄂鄒鄙鄲鄰酊酖酘酣酥酩酳酲醋醉醂醢醫醯醪醵醴醺釀釁釉釋釐釖釟釡釛釼釵釶鈞釿鈔鈬鈕鈑鉞鉗鉅鉉鉤鉈銕鈿鉋鉐銜銖銓銛鉚鋏銹銷鋩錏鋺鍄錮m錙錢錚錣錺錵錻鍜鍠鍼鍮鍖鎰鎬鎭鎔鎹鏖鏗鏨鏥鏘鏃鏝鏐鏈鏤鐚鐔鐓鐃鐇鐐鐶鐫鐵鐡鐺鑁鑒鑄鑛鑠鑢鑞鑪鈩鑰鑵鑷鑽鑚鑼鑾钁鑿閂閇閊閔閖閘閙閠閨閧閭閼閻閹閾闊濶闃闍闌闕闔闖關闡闥闢阡阨阮阯陂陌陏陋陷陜陞xo陝陟陦陲陬隍隘隕隗險隧隱隲隰隴隶隸隹雎雋雉雍襍雜霍雕雹霄霆霈霓霎霑霏霖霙霤霪霰霹霽霾靄靆靈靂靉靜靠靤靦靨勒靫靱靹鞅靼鞁靺鞆鞋鞏鞐鞜鞨鞦鞣鞳鞴韃韆韈韋韜韭齏韲竟韶韵頏頌頸頤頡頷頽顆顏顋顫顯顰p顱顴顳颪颯颱颶飄飃飆飩飫餃餉餒餔餘餡餝餞餤餠餬餮餽餾饂饉饅饐饋饑饒饌饕馗馘馥馭馮馼駟駛駝駘駑駭駮駱駲駻駸騁騏騅駢騙騫騷驅驂驀驃騾驕驍驛驗驟驢驥驤驩驫驪骭骰骼髀髏髑髓體髞髟髢髣髦髯髫髮髴髱髷r髻鬆鬘鬚鬟鬢鬣鬥鬧鬨鬩鬪鬮鬯鬲魄魃魏魍魎魑魘魴鮓鮃鮑鮖鮗鮟鮠鮨鮴鯀鯊鮹鯆鯏鯑鯒鯣鯢鯤鯔鯡鰺鯲鯱鯰鰕鰔鰉鰓鰌鰆鰈鰒鰊鰄鰮鰛鰥鰤鰡鰰鱇鰲鱆鰾鱚鱠鱧鱶鱸鳧鳬鳰鴉鴈鳫鴃鴆鴪鴦鶯鴣鴟鵄鴕鴒鵁鴿鴾鵆鵈t鵝鵞鵤鵑鵐鵙鵲鶉鶇鶫鵯鵺鶚鶤鶩鶲鷄鷁鶻鶸鶺鷆鷏鷂鷙鷓鷸鷦鷭鷯鷽鸚鸛鸞鹵鹹鹽麁麈麋麌麒麕麑麝麥麩麸麪麭靡黌黎黏黐黔黜點黝黠黥黨黯黴黶黷黹黻黼黽鼇鼈皷鼕鼡鼬鼾齊齒齔齣齟齠齡齦齧齬齪齷齲齶龕龜龠u堯槇遙瑤凜熙 w0wx8z{@}~赶﨣軏﨤逸遧郞都鄕鄧釚H釗釞釭釮釤釥鈆鈐鈊鈺鉀鈼鉎鉙鉑鈹鉧銧鉷鉸鋧鋗鋙鋐﨧鋕鋠鋓錥錡鋻﨨錞鋿錝錂鍰鍗鎤鏆鏞鏸鐱鑅鑈閒隆﨩隝隯霳霻靃靍靏靑靕顗顥飯飼餧館馞驎髙髜魵魲鮏鮱鮻鰀鵰鵫鶴鸙黑ⅰⅱⅲⅳⅴⅵⅶⅷⅸⅹ¬¦'"́t|< x H$,4<DL!"T$%\'(d*+l-.t01|35689;<>?t@A|CEFHIKLNO QR(TU0WX8Z[@]^H`aPcdXfg`ijhlmpopxrsuw(wx0z{8}~@ā@`H aԄ   '$ iЅ  ؆/,, QD     Y ,  D    ܈ a     x '  i   @  h / $<Ԉp8`xq     ` 7 l y X  T  p ? Ў  ,XdPLhȎ$<GD ͿТУʺξФХЦðЧШ| ЩǵǷ˳ЪЫ֦  ЬЭλͽЯвгде˴жμзий hо мнлкʩ¾пǤO Ȳȼ âͤ;դʻ եηx ¥¯ɶW`pdl  ¦ ˵ѣ_ ѤѡѢƯѥνѦѩѧѨѪѬѫȡԔѮѯ ѭѲѱѰѳѴͥѶѵѸѷѹ8Ѻ ѼѻѽѾȬϻʼ¶ŵ% ̽g4 οȡܖ ʬȽ\ §˶-ܗ έҢңϫҥҤoTҦ ļͦҧưҨ̳ҩҭҪҫҮүҰұޱ̘ ҲҳҵҷҶҸҹҺһҼҽҾɤƿTҿ Ⱦ´ñ¨5ؙ wp ͧȿáݹ̚ Ʊ̾ʭp Ϥ̣̿= ӣӡӾӥӤXӢ ӦӯӧӨӭӬůӮӫ̜ өӪӴͣӺӹӰ,ӱ ӶӳӷӸӵӻӲEtӽ ӿӼć ԧ0 ò t ʮȸM ǹ D ԡԢԣԤԦԥԨԩԪԫԭԮ ˷ԬԯԳó԰ԴU ԲԵԶԷԹԺԻԸhԱ ԼԽԿԾǸ Ʋ ʽ ȹŶ]h ʯȡ  ͼ¿̴ŷ# åʳաe բǡǥի̯֬գզ˸է ըլխժթɱ ղհ̼ճձկծշո+`մϬ նչպյ̻m ջɲռս տվ  3T ¸¹֣u ͨɷ  ̩ǫ ºƳǢ;D ֢֡Ÿ°֤֥֧֨}ԧ ְֱֳ̨֪֭֮֩֫֯H ֲִֵƽֶַָֹֻ ּֽ־C ֿ΅D ֺ ̦ç ܩ ġĢ˹K X Ȩʾʿǯͩ  ģŹ < ϭספץףקצערשת׭׫׬׮ׯǶװ! ױϮײ׵Сб׶Ĥ׷ʦ׸׹׿ĥ׺ɫS!0 ׻׼׽׾״׳ɧɷĦʕ!Ĭ ΧħŰ!H ɬǦ˺˻حǰ"ح|̔0,ԖTԗLĘLЙhĚhPĜ$l(l<``XܤL<̧@<ԩP4(@Э4 < ["H ©" ءاإأؤآͪئǺجذةخ"4 دثرتبؽظصضعؼ!#ط غشؾؿسػc#4 زθݥ# ͫʰƴ#< Ĩ)$ ١٢٣٤٥٦٧˼k$٨ ٩ʧ٬٪٭٫ٮʱٯٲ$ ٰٷٱٳٴٸٵȴڭٻ$ ôپټٺٶٹٽ1%t ĩs%  ªĽDZ%` Ϋõ% ·ͬ9&8 »{& Ŧ& DzƵűڥ& ڧڣڤڢٿڦڡګڬŧڮکگڨڳڲڱڴڶA'tڵ ڹڷڸڻںڼڰڽھڿ' Ũ'H ʸ( ι²öI(0 ۦ( (0 Ī˽ۢ) ۣۡۤۥۧۨ۩۪۫Q)  ͭ۬Ŀۭϯ˾īۮۯ۰̤۲۴۷۶۳) ۵۸¼ۻ۹«ۺۼ۽ۿ)( ۾* ɢ˿ͮY*( ϛ* ɰ* +| ܲܡܣܧêܫܨܢܬܪa+ ܦ̺ܥܯܱܰܩܭܮܿܤܻܽأ+d ܸܾܷܼܴܵܺܶܳϰܹ+ ϱ',` i, ɸî,, , ݡݬݨݧݦݣ/- ݥݤݪϦݭݩݫȧݮݲݯq-L ݰݳݴݶݸݷݺ- ݽݼݾ÷ݿ- 7.d y. ̱ɹۻ.0 .x ʨޡ?/ ˡޤޢˢťޥޣˁ/d ްޯެƶަީޮޭިޫު/ ή޶޴ޱ޳ϲ޵04 ޺Ͱ޷޲޸޾G0 ޿øʥ޻ź0 ޽޼¬0l ̫ùͯ 1 ȮίŮO1L ũߣ1 ɺϳߢ̡ߡ1  ߯ߪ߳߬Ĭߩߦߥ߮2hߨߧ߭ ߤ߰߱߶ߵ߷ߺߴ߸W2߲ǻ ߹߾߼߿߻Ǩ޹߽߫ə2,,4lX0ضl@(( t\ܿX$D\(p\,dD`t | 2 3 ϧú_3$ ˣ3t ʲ̵3 %4 Ǯg4< dzࢩ4 4 ĭ̶ϴʪ-5H o5 ìϵ5 ǭͱͲ5` 56 Ψw6 6@ ΰ6 =7 7T ɻ7 żͳҴĮ8 ȪαȫɭάE8h ɥ8 Ρ8l  9 ȯɴM9  Ū9 ݹľ9  ̲į: U: Ʒڗ:$ ̷û:t ˤ; βȣ];  ;H ; #< ʹǪɼe<< Ͻʡǩŧ< <  ̭ɣ+=d m= =4 ΩεƸèüѿ= ū3>, ɮȦȵu> ̧ýȢȤ> ϶>d ;? }? ʴ̰γǴ?p ʵ@ ǼɳʶC@X 帅@ ³þ@d  A ˥KAP A ŻA8 B ȳSB B Bl4x@X8L`dxl@4\,$\hP\H0|| Ϸ ÿC ʹİϸ[CP ȥϾȩɪٝC ˦ƹǽC, ̮æǾı!D IJʢcD ɨǿD< ¡D ڪа)E  kE ˧E  Ed 1F sF< ϵF ɩF ƺ˨9GL ΪơǬ{G G ̬˩ϡG\ ̢¢AH Ƣ鲃H Hl ƣI ݱݢII0 κIx I ȺJ ˪̪QJl ϹijJ ͻJ$ K\ YK ާɽޛK µKl ΢͵ΣL ʣ˫aL< L ʤL 'M` ƤˬiM ɾ˫M ǧͶïĴM ĵ͡/N ƥɵqN N Nt ë7O Ʀ˭ЮɿyO ŽǻO$Ϩ ±O £?P@ P Ķ­P ϩķQ ƧGQP Q Q ž RD ͢OR ŲR ҡäéR\ ųSH$4\4DTd(pdTd4Xl8|H<T  ƨƩ®¤ϢɯWS( ͷƻã½ŬS ͸ˮšSt Ϻ͹T Ţ_T T@ ȰT Τţ%U gU ŴȭȩU ƼĸUP ˯-V ϣϿoV Vt V ŭ5W ƪwWP عW W Ĺ=X ȶX$ ƮX Y ƫΦEY δȻY ͺΥʷY0 ̸Ϫ۱ Z MZ( Z ǣZ ĺƬ[L ſU[ [  Ҭݻ˰[D \ ]\ ɟ\4  \x  ƭ#]  e]  ]p  ȱɦ]  ݵ+^  ̥ϥm^T  ʫ^  ^  3_\  íu_  Ļȷ˱з_  ƾ_@  ̹˲;`  }`  `< a Ca ϼa a8 Ťɡ b Kb ζb@l8HlH( D<, p   h   L   T   8   408\bdc, 3cl      uc     c $ 0 c< @ ;dL   ! c"(48D  !"#}d# ($ 4% c@& ƿdD' eX' Cel'  ' e) e),%8&<'P'd''))) f)<Kf))}f) ȅІ$4<t@ \d $))**f*@BBJ$(!~  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^   !"#$%&'()*+,-./012345  !"#$%&'()*+,-./0123456789:;<=>  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRS  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUV  !"#$%&'()*+,-./0  !"#$%&'()*+,-./0123456789:;<=>?@AB    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRS  !"#$%&'()*+,-./0123  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[  !"#$%&'(   !"#$%&'()*+,-./012                    !"#$%&'()*+,-./0123456789:;<=>?@  !"#$%&'()*+,-./012345678  !"#$%&'()*+,-./0123456788889:;<8          !     !"#$    !                                  !"#$   !"#$%&'                         !"#       !"#$%&                                                                                                           !"     !"#$%&   !                                      !"    !"        !                         !                 !"#                                                              !      !                                                                                                                                                                                                           !"                                                                                      !"#$                                                                                                                                                                                                                                                        !"#                                               !"#$  !"#$%&'()                      !"#                                                   !                                                                                                           !"#$%&'()*+,-./0123456789:;<=   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!   !"#$%&'()*+,-./0123456789:;<=>>>    !      ;T jpjkkhlll8mXm(zRx $0j0FJ w?:*3$"D8j \k pjkk!k~l (l<HoGNUP  !` j l 6g J` ` p  j ` 8 6g J` ` 0 ` { ` t* 6g J` { ̄ 6g J ( < !!o` ! !0 oooo!`pGA$3a1(I GA$3p1067` < GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFY` j GA+GLIBCXX_ASSERTIONSemoji_iso2022_kddi.so-2.2.10-35.el8.x86_64.debug=7zXZִF!t//[]?Eh=ڊ2NH=N !C .|su@<f=u:;dA>?z/oaB⍤NB 199e[q+gtid1VkQ+_vZ@6_"k^* ᧛ ܶzE%P"`ŀ)U<6(?`BWm;'&.TUٯvfsҫs$'n3e2Oy**Q?: gj3A_֞`ko`涿_*%LCYv23g6iw()RO03l@V@8 @;; KK"K"  MM"M"  888$$;;; Std;;; Ptd ; ; ;$$QtdRtdKK"K"GNUqأK%7ym} ef@" BE|qXwD"l h , F"(P"0P"(P"U `<__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeInit_japanese_sjisrb_register_transcoderlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ui K"PK" K" K"@K"HK"XK" hK"K"K"K" L"L"L"L" L" M"(M"8M" HM"O"O"O"O"P" P"HHH"HtH5H"%H"hh%H"D%H"DH=H"HzH"H9tH&H"Ht H=QH"H5JH"H)HHH?HHtHG"HtfD= H"u+UH=G"Ht H=B"YdG"]wHH=D" H=D"H=YC"H=B"HHHUTF-8Windows-31JShift_JIS 、。,.・:;?!゛゜´`¨^ ̄_ヽヾゝゞ〃仝々〆〇ー—‐/\〜‖|…‥‘’“”()〔〕[]{}〈〉《》「」『』【】+−±×÷=≠<>≦≧∞∴♂♀°′″℃¥$¢£%#&*@§☆★○●◎◇◆□■△▲▽▼※〒→←↑↓〓 ∈∋⊆⊇⊂⊃∪∩∧∨¬⇒⇔∀∃∠⊥⌒∂∇≡≒≪≫√∽∝∵∫∬ʼn♯♭♪†‡¶◯ 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzぁあぃいぅうぇえぉおかがきぎくぐけげこごさざしじすずせぜそぞただちぢっつづてでとどなにぬねのはばぱひびぴふぶぷへべぺほぼぽまみむめもゃやゅゆょよらりるれろゎわゐゑをん\ァアィイゥウェエォオカガキギクグケゲコゴサザシジスズセゼソゾタダチヂッツヅテデトドナニヌネノハバパヒビピフブプヘベペホボポマミムメモャヤュユョヨラリルレロヮワヰヱヲンヴヵヶ ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩαβγδεζηθικλμνξοπρστυφχψω~АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ абвгдеёжзийклмнопрстуфхцчшщъыьэюя─│┌┐┘└├┬┤┴┼━┃┏┓┛┗┣┳┫┻╋┠┯┨┷┿┝┰┥┸╂= p 亜唖娃阿哀愛挨姶逢葵茜穐悪握渥旭葦芦鯵梓圧斡扱宛姐虻飴絢綾鮎或粟袷安庵按暗案闇鞍杏以伊位依偉囲夷委威尉惟意慰易椅為畏異移維緯胃萎衣謂違遺医井亥域育郁磯一壱溢逸稲茨芋鰯允印咽員因姻引飲淫胤蔭院陰隠韻吋右宇烏羽迂雨卯鵜窺丑碓臼渦嘘唄欝蔚鰻姥厩浦瓜閏噂云運雲荏餌叡営嬰影映曳栄永泳洩瑛盈穎頴英衛詠鋭液疫益駅悦謁越閲榎厭円園堰奄宴延怨掩援沿演炎焔煙燕猿縁艶苑薗遠鉛鴛塩於汚甥凹央奥往応押旺横欧殴王翁襖鴬鴎黄岡沖荻億屋憶臆桶牡乙俺卸恩温穏音下化仮何伽価佳加可嘉夏嫁家寡科暇果架歌河火珂禍禾稼箇花苛茄荷華菓蝦課嘩貨迦過霞蚊俄峨我牙画臥芽蛾賀雅餓駕介会解回塊壊廻快怪悔恢懐戒拐改z 魁晦械海灰界皆絵芥蟹開階貝凱劾外咳害崖慨概涯碍蓋街該鎧骸浬馨蛙垣柿蛎鈎劃嚇各廓拡撹格核殻獲確穫覚角赫較郭閣隔革学岳楽額顎掛笠樫橿梶鰍潟割喝恰括活渇滑葛褐轄且鰹叶椛樺鞄株兜竃蒲釜鎌噛鴨栢茅萱粥刈苅瓦乾侃冠寒刊勘勧巻喚堪姦完官寛干幹患感慣憾換敢柑桓棺款歓汗漢澗潅環甘監看竿管簡緩缶翰肝艦莞観諌貫還鑑間閑関陥韓館舘丸含岸巌玩癌眼岩翫贋雁頑顔願企伎危喜器基奇嬉寄岐希幾忌揮机旗既期棋棄z 機帰毅気汽畿祈季稀紀徽規記貴起軌輝飢騎鬼亀偽儀妓宜戯技擬欺犠疑祇義蟻誼議掬菊鞠吉吃喫桔橘詰砧杵黍却客脚虐逆丘久仇休及吸宮弓急救朽求汲泣灸球究窮笈級糾給旧牛去居巨拒拠挙渠虚許距鋸漁禦魚亨享京供侠僑兇競共凶協匡卿叫喬境峡強彊怯恐恭挟教橋況狂狭矯胸脅興蕎郷鏡響饗驚仰凝尭暁業局曲極玉桐粁僅勤均巾錦斤欣欽琴禁禽筋緊芹菌衿襟謹近金吟銀九倶句区狗玖矩苦躯駆駈駒具愚虞喰空偶寓遇隅串櫛釧屑屈z掘窟沓靴轡窪熊隈粂栗繰桑鍬勲君薫訓群軍郡卦袈祁係傾刑兄啓圭珪型契形径恵慶慧憩掲携敬景桂渓畦稽系経継繋罫茎荊蛍計詣警軽頚鶏芸迎鯨劇戟撃激隙桁傑欠決潔穴結血訣月件倹倦健兼券剣喧圏堅嫌建憲懸拳捲検権牽犬献研硯絹県肩見謙賢軒遣鍵険顕験鹸元原厳幻弦減源玄現絃舷言諺限乎個古呼固姑孤己庫弧戸故枯湖狐糊袴股胡菰虎誇跨鈷雇顧鼓五互伍午呉吾娯後御悟梧檎瑚碁語誤護醐乞鯉交佼侯候倖光公功効勾厚口向z后喉坑垢好孔孝宏工巧巷幸広庚康弘恒慌抗拘控攻昂晃更杭校梗構江洪浩港溝甲皇硬稿糠紅紘絞綱耕考肯肱腔膏航荒行衡講貢購郊酵鉱砿鋼閤降項香高鴻剛劫号合壕拷濠豪轟麹克刻告国穀酷鵠黒獄漉腰甑忽惚骨狛込此頃今困坤墾婚恨懇昏昆根梱混痕紺艮魂些佐叉唆嵯左差査沙瑳砂詐鎖裟坐座挫債催再最哉塞妻宰彩才採栽歳済災采犀砕砦祭斎細菜裁載際剤在材罪財冴坂阪堺榊肴咲崎埼碕鷺作削咋搾昨朔柵窄策索錯桜鮭笹匙冊刷z察拶撮擦札殺薩雑皐鯖捌錆鮫皿晒三傘参山惨撒散桟燦珊産算纂蚕讃賛酸餐斬暫残仕仔伺使刺司史嗣四士始姉姿子屍市師志思指支孜斯施旨枝止死氏獅祉私糸紙紫肢脂至視詞詩試誌諮資賜雌飼歯事似侍児字寺慈持時次滋治爾璽痔磁示而耳自蒔辞汐鹿式識鴫竺軸宍雫七叱執失嫉室悉湿漆疾質実蔀篠偲柴芝屡蕊縞舎写射捨赦斜煮社紗者謝車遮蛇邪借勺尺杓灼爵酌釈錫若寂弱惹主取守手朱殊狩珠種腫趣酒首儒受呪寿授樹綬需囚収周z宗就州修愁拾洲秀秋終繍習臭舟蒐衆襲讐蹴輯週酋酬集醜什住充十従戎柔汁渋獣縦重銃叔夙宿淑祝縮粛塾熟出術述俊峻春瞬竣舜駿准循旬楯殉淳準潤盾純巡遵醇順処初所暑曙渚庶緒署書薯藷諸助叙女序徐恕鋤除傷償勝匠升召哨商唱嘗奨妾娼宵将小少尚庄床廠彰承抄招掌捷昇昌昭晶松梢樟樵沼消渉湘焼焦照症省硝礁祥称章笑粧紹肖菖蒋蕉衝裳訟証詔詳象賞醤鉦鍾鐘障鞘上丈丞乗冗剰城場壌嬢常情擾条杖浄状畳穣蒸譲醸錠嘱埴飾z拭植殖燭織職色触食蝕辱尻伸信侵唇娠寝審心慎振新晋森榛浸深申疹真神秦紳臣芯薪親診身辛進針震人仁刃塵壬尋甚尽腎訊迅陣靭笥諏須酢図厨逗吹垂帥推水炊睡粋翠衰遂酔錐錘随瑞髄崇嵩数枢趨雛据杉椙菅頗雀裾澄摺寸世瀬畝是凄制勢姓征性成政整星晴棲栖正清牲生盛精聖声製西誠誓請逝醒青静斉税脆隻席惜戚斥昔析石積籍績脊責赤跡蹟碩切拙接摂折設窃節説雪絶舌蝉仙先千占宣専尖川戦扇撰栓栴泉浅洗染潜煎煽旋穿箭線z繊羨腺舛船薦詮賎践選遷銭銑閃鮮前善漸然全禅繕膳糎噌塑岨措曾曽楚狙疏疎礎祖租粗素組蘇訴阻遡鼠僧創双叢倉喪壮奏爽宋層匝惣想捜掃挿掻操早曹巣槍槽漕燥争痩相窓糟総綜聡草荘葬蒼藻装走送遭鎗霜騒像増憎臓蔵贈造促側則即息捉束測足速俗属賊族続卒袖其揃存孫尊損村遜他多太汰詑唾堕妥惰打柁舵楕陀駄騨体堆対耐岱帯待怠態戴替泰滞胎腿苔袋貸退逮隊黛鯛代台大第醍題鷹滝瀧卓啄宅托択拓沢濯琢託鐸濁諾茸凧蛸只z!叩但達辰奪脱巽竪辿棚谷狸鱈樽誰丹単嘆坦担探旦歎淡湛炭短端箪綻耽胆蛋誕鍛団壇弾断暖檀段男談値知地弛恥智池痴稚置致蜘遅馳築畜竹筑蓄逐秩窒茶嫡着中仲宙忠抽昼柱注虫衷註酎鋳駐樗瀦猪苧著貯丁兆凋喋寵帖帳庁弔張彫徴懲挑暢朝潮牒町眺聴脹腸蝶調諜超跳銚長頂鳥勅捗直朕沈珍賃鎮陳津墜椎槌追鎚痛通塚栂掴槻佃漬柘辻蔦綴鍔椿潰坪壷嬬紬爪吊釣鶴亭低停偵剃貞呈堤定帝底庭廷弟悌抵挺提梯汀碇禎程締艇訂諦蹄逓z$邸鄭釘鼎泥摘擢敵滴的笛適鏑溺哲徹撤轍迭鉄典填天展店添纏甜貼転顛点伝殿澱田電兎吐堵塗妬屠徒斗杜渡登菟賭途都鍍砥砺努度土奴怒倒党冬凍刀唐塔塘套宕島嶋悼投搭東桃梼棟盗淘湯涛灯燈当痘祷等答筒糖統到董蕩藤討謄豆踏逃透鐙陶頭騰闘働動同堂導憧撞洞瞳童胴萄道銅峠鴇匿得徳涜特督禿篤毒独読栃橡凸突椴届鳶苫寅酉瀞噸屯惇敦沌豚遁頓呑曇鈍奈那内乍凪薙謎灘捺鍋楢馴縄畷南楠軟難汝二尼弐迩匂賑肉虹廿日乳入z'如尿韮任妊忍認濡禰祢寧葱猫熱年念捻撚燃粘乃廼之埜嚢悩濃納能脳膿農覗蚤巴把播覇杷波派琶破婆罵芭馬俳廃拝排敗杯盃牌背肺輩配倍培媒梅楳煤狽買売賠陪這蝿秤矧萩伯剥博拍柏泊白箔粕舶薄迫曝漠爆縛莫駁麦函箱硲箸肇筈櫨幡肌畑畠八鉢溌発醗髪伐罰抜筏閥鳩噺塙蛤隼伴判半反叛帆搬斑板氾汎版犯班畔繁般藩販範釆煩頒飯挽晩番盤磐蕃蛮匪卑否妃庇彼悲扉批披斐比泌疲皮碑秘緋罷肥被誹費避非飛樋簸備尾微枇毘琵眉美z*鼻柊稗匹疋髭彦膝菱肘弼必畢筆逼桧姫媛紐百謬俵彪標氷漂瓢票表評豹廟描病秒苗錨鋲蒜蛭鰭品彬斌浜瀕貧賓頻敏瓶不付埠夫婦富冨布府怖扶敷斧普浮父符腐膚芙譜負賦赴阜附侮撫武舞葡蕪部封楓風葺蕗伏副復幅服福腹複覆淵弗払沸仏物鮒分吻噴墳憤扮焚奮粉糞紛雰文聞丙併兵塀幣平弊柄並蔽閉陛米頁僻壁癖碧別瞥蔑箆偏変片篇編辺返遍便勉娩弁鞭保舗鋪圃捕歩甫補輔穂募墓慕戊暮母簿菩倣俸包呆報奉宝峰峯崩庖抱捧放方朋z-法泡烹砲縫胞芳萌蓬蜂褒訪豊邦鋒飽鳳鵬乏亡傍剖坊妨帽忘忙房暴望某棒冒紡肪膨謀貌貿鉾防吠頬北僕卜墨撲朴牧睦穆釦勃没殆堀幌奔本翻凡盆摩磨魔麻埋妹昧枚毎哩槙幕膜枕鮪柾鱒桝亦俣又抹末沫迄侭繭麿万慢満漫蔓味未魅巳箕岬密蜜湊蓑稔脈妙粍民眠務夢無牟矛霧鵡椋婿娘冥名命明盟迷銘鳴姪牝滅免棉綿緬面麺摸模茂妄孟毛猛盲網耗蒙儲木黙目杢勿餅尤戻籾貰問悶紋門匁也冶夜爺耶野弥矢厄役約薬訳躍靖柳薮鑓愉愈油癒z0諭輸唯佑優勇友宥幽悠憂揖有柚湧涌猶猷由祐裕誘遊邑郵雄融夕予余与誉輿預傭幼妖容庸揚揺擁曜楊様洋溶熔用窯羊耀葉蓉要謡踊遥陽養慾抑欲沃浴翌翼淀羅螺裸来莱頼雷洛絡落酪乱卵嵐欄濫藍蘭覧利吏履李梨理璃痢裏裡里離陸律率立葎掠略劉流溜琉留硫粒隆竜龍侶慮旅虜了亮僚両凌寮料梁涼猟療瞭稜糧良諒遼量陵領力緑倫厘林淋燐琳臨輪隣鱗麟瑠塁涙累類令伶例冷励嶺怜玲礼苓鈴隷零霊麗齢暦歴列劣烈裂廉恋憐漣煉簾練聯z3蓮連錬呂魯櫓炉賂路露労婁廊弄朗楼榔浪漏牢狼篭老聾蝋郎六麓禄肋録論倭和話歪賄脇惑枠鷲亙亘鰐詫藁蕨椀湾碗腕 弌丐丕个丱丶丼丿乂乖乘亂亅豫亊舒弍于亞亟亠亢亰亳亶从仍仄仆仂仗仞仭仟价伉佚估佛佝佗佇佶侈侏侘佻佩佰侑佯來侖儘俔俟俎俘俛俑俚俐俤俥倚倨倔倪倥倅伜俶倡倩倬俾俯們倆偃假會偕偐偈做偖偬偸傀傚傅傴傲96僉僊傳僂僖僞僥僭僣僮價僵儉儁儂儖儕儔儚儡儺儷儼儻儿兀兒兌兔兢竸兩兪兮冀冂囘册冉冏冑冓冕冖冤冦冢冩冪冫决冱冲冰况冽凅凉凛几處凩凭凰凵凾刄刋刔刎刧刪刮刳刹剏剄剋剌剞剔剪剴剩剳剿剽劍劔劒剱劈劑辨辧劬劭劼劵勁勍勗勞勣勦飭勠勳勵勸勹匆匈甸匍匐匏匕匚匣匯匱匳匸區卆卅丗卉卍凖卞卩卮夘卻卷厂厖厠厦厥厮厰厶參簒雙叟曼燮叮叨叭叺吁吽呀听吭吼吮吶吩吝呎咏呵咎呟呱呷呰咒呻咀呶咄咐咆哇咢咸咥咬哄哈咨z 9咫哂咤咾咼哘哥哦唏唔哽哮哭哺哢唹啀啣啌售啜啅啖啗唸唳啝喙喀咯喊喟啻啾喘喞單啼喃喩喇喨嗚嗅嗟嗄嗜嗤嗔嘔嗷嘖嗾嗽嘛嗹噎噐營嘴嘶嘲嘸噫噤嘯噬噪嚆嚀嚊嚠嚔嚏嚥嚮嚶嚴囂嚼囁囃囀囈囎囑囓囗囮囹圀囿圄圉圈國圍圓團圖嗇圜圦圷圸坎圻址坏坩埀垈坡坿垉垓垠垳垤垪垰埃埆埔埒埓堊埖埣堋堙堝塲堡塢塋塰毀塒堽塹墅墹墟墫墺壞墻墸墮壅壓壑壗壙壘壥壜壤壟壯壺壹壻壼壽夂夊夐夛梦夥夬夭夲夸夾竒奕奐奎奚奘奢奠奧奬奩z<奸妁妝佞侫妣妲姆姨姜妍姙姚娥娟娑娜娉娚婀婬婉娵娶婢婪媚媼媾嫋嫂媽嫣嫗嫦嫩嫖嫺嫻嬌嬋嬖嬲嫐嬪嬶嬾孃孅孀孑孕孚孛孥孩孰孳孵學斈孺宀它宦宸寃寇寉寔寐寤實寢寞寥寫寰寶寳尅將專對尓尠尢尨尸尹屁屆屎屓屐屏孱屬屮乢屶屹岌岑岔妛岫岻岶岼岷峅岾峇峙峩峽峺峭嶌峪崋崕崗嵜崟崛崑崔崢崚崙崘嵌嵒嵎嵋嵬嵳嵶嶇嶄嶂嶢嶝嶬嶮嶽嶐嶷嶼巉巍巓巒巖巛巫已巵帋帚帙帑帛帶帷幄幃幀幎幗幔幟幢幤幇幵并幺麼广庠廁廂廈廐廏z?廖廣廝廚廛廢廡廨廩廬廱廳廰廴廸廾弃弉彝彜弋弑弖弩弭弸彁彈彌彎弯彑彖彗彙彡彭彳彷徃徂彿徊很徑徇從徙徘徠徨徭徼忖忻忤忸忱忝悳忿怡恠怙怐怩怎怱怛怕怫怦怏怺恚恁恪恷恟恊恆恍恣恃恤恂恬恫恙悁悍惧悃悚悄悛悖悗悒悧悋惡悸惠惓悴忰悽惆悵惘慍愕愆惶惷愀惴惺愃愡惻惱愍愎慇愾愨愧慊愿愼愬愴愽慂慄慳慷慘慙慚慫慴慯慥慱慟慝慓慵憙憖憇憬憔憚憊憑憫憮懌懊應懷懈懃懆憺懋罹懍懦懣懶懺懴懿懽懼懾戀戈戉戍戌戔戛zB戞戡截戮戰戲戳扁扎扞扣扛扠扨扼抂抉找抒抓抖拔抃抔拗拑抻拏拿拆擔拈拜拌拊拂拇抛拉挌拮拱挧挂挈拯拵捐挾捍搜捏掖掎掀掫捶掣掏掉掟掵捫捩掾揩揀揆揣揉插揶揄搖搴搆搓搦搶攝搗搨搏摧摯摶摎攪撕撓撥撩撈撼據擒擅擇撻擘擂擱擧舉擠擡抬擣擯攬擶擴擲擺攀擽攘攜攅攤攣攫攴攵攷收攸畋效敖敕敍敘敞敝敲數斂斃變斛斟斫斷旃旆旁旄旌旒旛旙无旡旱杲昊昃旻杳昵昶昴昜晏晄晉晁晞晝晤晧晨晟晢晰暃暈暎暉暄暘暝曁暹曉暾暼zE曄暸曖曚曠昿曦曩曰曵曷朏朖朞朦朧霸朮朿朶杁朸朷杆杞杠杙杣杤枉杰枩杼杪枌枋枦枡枅枷柯枴柬枳柩枸柤柞柝柢柮枹柎柆柧檜栞框栩桀桍栲桎梳栫桙档桷桿梟梏梭梔條梛梃檮梹桴梵梠梺椏梍桾椁棊椈棘椢椦棡椌棍棔棧棕椶椒椄棗棣椥棹棠棯椨椪椚椣椡棆楹楷楜楸楫楔楾楮椹楴椽楙椰楡楞楝榁楪榲榮槐榿槁槓榾槎寨槊槝榻槃榧樮榑榠榜榕榴槞槨樂樛槿權槹槲槧樅榱樞槭樔槫樊樒櫁樣樓橄樌橲樶橸橇橢橙橦橈樸樢檐檍檠檄檢檣z H檗蘗檻櫃櫂檸檳檬櫞櫑櫟檪櫚櫪櫻欅蘖櫺欒欖鬱欟欸欷盜欹飮歇歃歉歐歙歔歛歟歡歸歹歿殀殄殃殍殘殕殞殤殪殫殯殲殱殳殷殼毆毋毓毟毬毫毳毯麾氈氓气氛氤氣汞汕汢汪沂沍沚沁沛汾汨汳沒沐泄泱泓沽泗泅泝沮沱沾沺泛泯泙泪洟衍洶洫洽洸洙洵洳洒洌浣涓浤浚浹浙涎涕濤涅淹渕渊涵淇淦涸淆淬淞淌淨淒淅淺淙淤淕淪淮渭湮渮渙湲湟渾渣湫渫湶湍渟湃渺湎渤滿渝游溂溪溘滉溷滓溽溯滄溲滔滕溏溥滂溟潁漑灌滬滸滾漿滲漱滯漲滌zK漾漓滷澆潺潸澁澀潯潛濳潭澂潼潘澎澑濂潦澳澣澡澤澹濆澪濟濕濬濔濘濱濮濛瀉瀋濺瀑瀁瀏濾瀛瀚潴瀝瀘瀟瀰瀾瀲灑灣炙炒炯烱炬炸炳炮烟烋烝烙焉烽焜焙煥煕熈煦煢煌煖煬熏燻熄熕熨熬燗熹熾燒燉燔燎燠燬燧燵燼燹燿爍爐爛爨爭爬爰爲爻爼爿牀牆牋牘牴牾犂犁犇犒犖犢犧犹犲狃狆狄狎狒狢狠狡狹狷倏猗猊猜猖猝猴猯猩猥猾獎獏默獗獪獨獰獸獵獻獺珈玳珎玻珀珥珮珞璢琅瑯琥珸琲琺瑕琿瑟瑙瑁瑜瑩瑰瑣瑪瑶瑾璋璞璧瓊瓏瓔珱zN瓠瓣瓧瓩瓮瓲瓰瓱瓸瓷甄甃甅甌甎甍甕甓甞甦甬甼畄畍畊畉畛畆畚畩畤畧畫畭畸當疆疇畴疊疉疂疔疚疝疥疣痂疳痃疵疽疸疼疱痍痊痒痙痣痞痾痿痼瘁痰痺痲痳瘋瘍瘉瘟瘧瘠瘡瘢瘤瘴瘰瘻癇癈癆癜癘癡癢癨癩癪癧癬癰癲癶癸發皀皃皈皋皎皖皓皙皚皰皴皸皹皺盂盍盖盒盞盡盥盧盪蘯盻眈眇眄眩眤眞眥眦眛眷眸睇睚睨睫睛睥睿睾睹瞎瞋瞑瞠瞞瞰瞶瞹瞿瞼瞽瞻矇矍矗矚矜矣矮矼砌砒礦砠礪硅碎硴碆硼碚碌碣碵碪碯磑磆磋磔碾碼磅磊磬zQ磧磚磽磴礇礒礑礙礬礫祀祠祗祟祚祕祓祺祿禊禝禧齋禪禮禳禹禺秉秕秧秬秡秣稈稍稘稙稠稟禀稱稻稾稷穃穗穉穡穢穩龝穰穹穽窈窗窕窘窖窩竈窰窶竅竄窿邃竇竊竍竏竕竓站竚竝竡竢竦竭竰笂笏笊笆笳笘笙笞笵笨笶筐筺笄筍笋筌筅筵筥筴筧筰筱筬筮箝箘箟箍箜箚箋箒箏筝箙篋篁篌篏箴篆篝篩簑簔篦篥籠簀簇簓篳篷簗簍篶簣簧簪簟簷簫簽籌籃籔籏籀籐籘籟籤籖籥籬籵粃粐粤粭粢粫粡粨粳粲粱粮粹粽糀糅糂糘糒糜糢鬻糯糲糴糶糺紆zS紂紜紕紊絅絋紮紲紿紵絆絳絖絎絲絨絮絏絣經綉絛綏絽綛綺綮綣綵緇綽綫總綢綯緜綸綟綰緘緝緤緞緻緲緡縅縊縣縡縒縱縟縉縋縢繆繦縻縵縹繃縷縲縺繧繝繖繞繙繚繹繪繩繼繻纃緕繽辮繿纈纉續纒纐纓纔纖纎纛纜缸缺罅罌罍罎罐网罕罔罘罟罠罨罩罧罸羂羆羃羈羇羌羔羞羝羚羣羯羲羹羮羶羸譱翅翆翊翕翔翡翦翩翳翹飜耆耄耋耒耘耙耜耡耨耿耻聊聆聒聘聚聟聢聨聳聲聰聶聹聽聿肄肆肅肛肓肚肭冐肬胛胥胙胝胄胚胖脉胯胱脛脩脣脯腋zV隋腆脾腓腑胼腱腮腥腦腴膃膈膊膀膂膠膕膤膣腟膓膩膰膵膾膸膽臀臂膺臉臍臑臙臘臈臚臟臠臧臺臻臾舁舂舅與舊舍舐舖舩舫舸舳艀艙艘艝艚艟艤艢艨艪艫舮艱艷艸艾芍芒芫芟芻芬苡苣苟苒苴苳苺莓范苻苹苞茆苜茉苙茵茴茖茲茱荀茹荐荅茯茫茗茘莅莚莪莟莢莖茣莎莇莊荼莵荳荵莠莉莨菴萓菫菎菽萃菘萋菁菷萇菠菲萍萢萠莽萸蔆菻葭萪萼蕚蒄葷葫蒭葮蒂葩葆萬葯葹萵蓊葢蒹蒿蒟蓙蓍蒻蓚蓐蓁蓆蓖蒡蔡蓿蓴蔗蔘蔬蔟蔕蔔蓼蕀蕣蕘蕈zY蕁蘂蕋蕕薀薤薈薑薊薨蕭薔薛藪薇薜蕷蕾薐藉薺藏薹藐藕藝藥藜藹蘊蘓蘋藾藺蘆蘢蘚蘰蘿虍乕虔號虧虱蚓蚣蚩蚪蚋蚌蚶蚯蛄蛆蚰蛉蠣蚫蛔蛞蛩蛬蛟蛛蛯蜒蜆蜈蜀蜃蛻蜑蜉蜍蛹蜊蜴蜿蜷蜻蜥蜩蜚蝠蝟蝸蝌蝎蝴蝗蝨蝮蝙蝓蝣蝪蠅螢螟螂螯蟋螽蟀蟐雖螫蟄螳蟇蟆螻蟯蟲蟠蠏蠍蟾蟶蟷蠎蟒蠑蠖蠕蠢蠡蠱蠶蠹蠧蠻衄衂衒衙衞衢衫袁衾袞衵衽袵衲袂袗袒袮袙袢袍袤袰袿袱裃裄裔裘裙裝裹褂裼裴裨裲褄褌褊褓襃褞褥褪褫襁襄褻褶褸襌褝襠襞z\襦襤襭襪襯襴襷襾覃覈覊覓覘覡覩覦覬覯覲覺覽覿觀觚觜觝觧觴觸訃訖訐訌訛訝訥訶詁詛詒詆詈詼詭詬詢誅誂誄誨誡誑誥誦誚誣諄諍諂諚諫諳諧諤諱謔諠諢諷諞諛謌謇謚諡謖謐謗謠謳鞫謦謫謾謨譁譌譏譎證譖譛譚譫譟譬譯譴譽讀讌讎讒讓讖讙讚谺豁谿豈豌豎豐豕豢豬豸豺貂貉貅貊貍貎貔豼貘戝貭貪貽貲貳貮貶賈賁賤賣賚賽賺賻贄贅贊贇贏贍贐齎贓賍贔贖赧赭赱赳趁趙跂趾趺跏跚跖跌跛跋跪跫跟跣跼踈踉跿踝踞踐踟蹂踵踰踴蹊z_蹇蹉蹌蹐蹈蹙蹤蹠踪蹣蹕蹶蹲蹼躁躇躅躄躋躊躓躑躔躙躪躡躬躰軆躱躾軅軈軋軛軣軼軻軫軾輊輅輕輒輙輓輜輟輛輌輦輳輻輹轅轂輾轌轉轆轎轗轜轢轣轤辜辟辣辭辯辷迚迥迢迪迯邇迴逅迹迺逑逕逡逍逞逖逋逧逶逵逹迸遏遐遑遒逎遉逾遖遘遞遨遯遶隨遲邂遽邁邀邊邉邏邨邯邱邵郢郤扈郛鄂鄒鄙鄲鄰酊酖酘酣酥酩酳酲醋醉醂醢醫醯醪醵醴醺釀釁釉釋釐釖釟釡釛釼釵釶鈞釿鈔鈬鈕鈑鉞鉗鉅鉉鉤鉈銕鈿鉋鉐銜銖銓銛鉚鋏銹銷鋩錏鋺鍄錮zb錙錢錚錣錺錵錻鍜鍠鍼鍮鍖鎰鎬鎭鎔鎹鏖鏗鏨鏥鏘鏃鏝鏐鏈鏤鐚鐔鐓鐃鐇鐐鐶鐫鐵鐡鐺鑁鑒鑄鑛鑠鑢鑞鑪鈩鑰鑵鑷鑽鑚鑼鑾钁鑿閂閇閊閔閖閘閙閠閨閧閭閼閻閹閾闊濶闃闍闌闕闔闖關闡闥闢阡阨阮阯陂陌陏陋陷陜陞陝陟陦陲陬隍隘隕隗險隧隱隲隰隴隶隸隹雎雋雉雍襍雜霍雕雹霄霆霈霓霎霑霏霖霙霤霪霰霹霽霾靄靆靈靂靉靜靠靤靦靨勒靫靱靹鞅靼鞁靺鞆鞋鞏鞐鞜鞨鞦鞣鞳鞴韃韆韈韋韜韭齏韲竟韶韵頏頌頸頤頡頷頽顆顏顋顫顯顰ze顱顴顳颪颯颱颶飄飃飆飩飫餃餉餒餔餘餡餝餞餤餠餬餮餽餾饂饉饅饐饋饑饒饌饕馗馘馥馭馮馼駟駛駝駘駑駭駮駱駲駻駸騁騏騅駢騙騫騷驅驂驀驃騾驕驍驛驗驟驢驥驤驩驫驪骭骰骼髀髏髑髓體髞髟髢髣髦髯髫髮髴髱髷髻鬆鬘鬚鬟鬢鬣鬥鬧鬨鬩鬪鬮鬯鬲魄魃魏魍魎魑魘魴鮓鮃鮑鮖鮗鮟鮠鮨鮴鯀鯊鮹鯆鯏鯑鯒鯣鯢鯤鯔鯡鰺鯲鯱鯰鰕鰔鰉鰓鰌鰆鰈鰒鰊鰄鰮鰛鰥鰤鰡鰰鱇鰲鱆鰾鱚鱠鱧鱶鱸鳧鳬鳰鴉鴈鳫鴃鴆鴪鴦鶯鴣鴟鵄鴕鴒鵁鴿鴾鵆鵈zh鵝鵞鵤鵑鵐鵙鵲鶉鶇鶫鵯鵺鶚鶤鶩鶲鷄鷁鶻鶸鶺鷆鷏鷂鷙鷓鷸鷦鷭鷯鷽鸚鸛鸞鹵鹹鹽麁麈麋麌麒麕麑麝麥麩麸麪麭靡黌黎黏黐黔黜點黝黠黥黨黯黴黶黷黹黻黼黽鼇鼈皷鼕鼡鼬鼾齊齒齔齣齟齠齡齦齧齬齪齷齲齶龕龜龠堯槇遙瑤凜熙 kThx !$'*-0369<? BEHKM。「」、・ヲァィゥェォャュョッーアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン゙゚PSVY\_behktm|m 、。,.・:;?!゛゜´`¨^ ̄_ヽヾゝゞ〃仝々〆〇ー―‐/\~∥|…‥‘’“”()〔〕[]{}〈〉《》「」『』【】+-±×÷=≠<>≦≧∞∴♂♀°′″℃¥$¢£%#&*@§☆★○●◎◇◆□■△▲▽▼※〒→←↑↓〓 ∈∋⊆⊇⊂⊃∪∩∧∨¬⇒⇔∀∃∠⊥⌒∂∇≡≒≪≫√∽∝∵∫∬ʼn♯♭♪†‡¶◯(o①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩ ㍉㌔㌢㍍㌘㌧㌃㌶㍑㍗㌍㌦㌣㌫㍊㌻㎜㎝㎞㎎㎏㏄㎡㍻〝〟№㏍℡㊤㊥㊦㊧㊨㈱㈲㈹㍾㍽㍼≒≡∫∮∑√⊥∠∟⊿∵∩∪q纊褜鍈銈蓜俉炻昱棈鋹曻彅丨仡仼伀伃伹佖侒侊侚侔俍偀倢俿倞偆偰偂傔僴僘兊兤冝冾凬刕劜劦勀勛匀匇匤卲厓厲叝﨎咜咊咩哿喆坙坥垬埈埇﨏塚增墲夋奓奛奝奣妤妺孖寀甯寘寬尞岦岺峵崧嵓﨑嵂嵭嶸嶹巐弡弴彧德忞恝悅悊惞惕愠惲愑愷愰憘戓抦揵摠撝擎敎昀昕昻昉昮昞昤晥晗晙晴晳暙暠暲暿曺朎朗杦枻桒柀栁桄棏﨓楨﨔榘槢樰橫橆橳橾櫢櫤毖氿汜沆汯泚洄涇浯涖涬淏淸淲淼渹湜渧渼溿澈澵濵瀅瀇瀨炅炫焏焄煜煆煇凞燁燾犱zr犾猤猪獷玽珉珖珣珒琇珵琦琪琩琮瑢璉璟甁畯皂皜皞皛皦益睆劯砡硎硤硺礰礼神祥禔福禛竑竧靖竫箞精絈絜綷綠緖繒罇羡羽茁荢荿菇菶葈蒴蕓蕙蕫﨟薰蘒﨡蠇裵訒訷詹誧誾諟諸諶譓譿賰賴贒赶﨣軏﨤逸遧郞都鄕鄧釚釗釞釭釮釤釥鈆鈐鈊鈺鉀鈼鉎鉙鉑鈹鉧銧鉷鉸鋧鋗鋙鋐﨧鋕鋠鋓錥錡鋻﨨錞鋿錝錂鍰鍗鎤鏆鏞鏸鐱鑅鑈閒隆﨩隝隯霳霻靃靍靏靑靕顗顥飯飼餧館馞驎髙髜魵魲鮏鮱鮻鰀鵰鵫鶴鸙黑 ⅰⅱⅲⅳⅴⅵⅶⅷⅸⅹ¬¦'"uuzxz{z~zȁzĄzzzzzⅰⅱⅲⅳⅴⅵⅶⅷⅸⅹⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩ¬¦'"㈱№℡∵纊褜鍈銈蓜俉炻昱棈鋹曻彅丨仡仼伀伃伹佖侒侊侚侔俍偀倢俿倞偆偰偂傔僴僘兊兤冝冾凬刕劜劦勀勛匀匇匤卲厓厲叝﨎咜咊咩哿喆坙坥垬埈埇﨏塚增墲夋奓奛奝奣妤妺孖寀甯寘寬尞岦岺峵崧嵓﨑嵂嵭嶸嶹巐弡弴彧德忞恝悅悊惞惕愠惲愑愷愰憘戓抦揵摠撝擎敎昀昕昻昉昮昞昤晥晗晙晴晳暙暠暲暿曺朎朗杦枻桒柀栁桄棏﨓楨﨔榘槢樰橫橆橳橾櫢櫤毖氿汜沆汯泚洄涇浯z涖涬淏淸淲淼渹湜渧渼溿澈澵濵瀅瀇瀨炅炫焏焄煜煆煇凞燁燾犱犾猤猪獷玽珉珖珣珒琇珵琦琪琩琮瑢璉璟甁畯皂皜皞皛皦益睆劯砡硎硤硺礰礼神祥禔福禛竑竧靖竫箞精絈絜綷綠緖繒罇羡羽茁荢荿菇菶葈蒴蕓蕙蕫﨟薰蘒﨡蠇裵訒訷詹誧誾諟諸諶譓譿賰賴贒赶﨣軏﨤逸遧郞都鄕鄧釚釗釞釭釮釤釥鈆鈐鈊鈺鉀鈼鉎鉙鉑鈹鉧銧鉷鉸鋧鋗鋙鋐﨧鋕鋠鋓錥錡鋻﨨錞鋿錝錂鍰鍗鎤鏆鏞鏸鐱鑅鑈閒隆﨩隝隯霳霻靃靍靏靑靕顗顥飯飼餧館馞驎髙z髜魵魲鮏鮱鮻鰀鵰鵫鶴鸙黑 4 |qhxr !$'*-0369<? BEHKM。「」、・ヲァィゥェォャュョッーアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン゙゚PSVY\_behktmux{~ܜ  N}L О ~4 v p  $  П F@ABCDEGHIJKLMNOPQRSTUVWXYZ[\]^_`pqrstuwxyz{|}~<  v~ ؠ ,v , ]\aefghdc D $  f   ȡ |  ,@ nl   4, vD l  <ء8d$<dȣ~У@ABV XYZqrstuvwxyzkl`  JKTU@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^D_`abcdefghijklmnopqrstuvwxyz{|}~ E[RSxxplt Os^NuO  TvVRhL T \]jiSl|Ym wedtWC x`Lf AZC]CgT DNt WrMCoUԪtl̪DL q{|l`\| U TPbBXL C@AlDEHFmGIKJ"VMN LQPORSDUTWVXdY Z[[eZ\}]S_`ZaTTb c~fegh`ijknlmyopq~ustrvw xyyz{}}~Mo* nYhl OUn cwJN uEM2d kxCt\ PmTKp\ ~X} QyFofbp@jEi:D hegD@fNiz| Cl aB@]PDC̳iA ENFGLKNMJB4 SOHISBYXOP UR[VWTZQ`eaش\ fPhA^b[c_igridc$ mkpjnlkorwutJ QqsRv}{|~Ե \Xxy dX` dlc}R y\n VBRx ^C_ Wu|Zx gX YhUom n  dmpsb` [OgVv t_zDz@D\ A@DJWdBEWiF(Ժ GonKLIWHPpj0 QORPNPMVWSK kUXwYTԻ }ZQ[_\0  ^]kda`bcefr4 hgildjmn|q opqrEstuyFGvwwxyz{}~ FvG@XqG{Qeh8 0 xQ@JRz Ľ qAKsA \ rWjwR  Zx@!\ s! R! "H H" BHIbJF" sztAX"D yNKcH# LXM{xNfP#( pLf@CDB_FEAGHILJKMNUO# PMQTU|VOoWX^YJe# Z[\]_`abSRc`FVjdeefi$hga mkjlk]ponqrzsOtJX$$ SKEuuYZzwyOxv|$DLx\ܰT<ܲdij,д̵XpP XܹT̺(̻,t(TT@|<  {|v}}$ P~pb% IxY{`% fySz%D % QTdSc|&&X Jeh& &H ^@ABCYDEF[&G HKILJM}NQ.'4Z OVPc}RSWTReZp' cS]d_fba[YUXS`qg@hminAE\' kwlgjUp}' Jqso{~xP6(v |{uzrt@||TyT[wdf}~x(X `Kgh( rg(0 E>)| TQPdBoh) i^FC[) xU*x q~sUhG~F* |klafzV{*@ U|{* VftE +0 WWNAiqN+ gb\A+ @BCjDFGHgXIJ]\+l LKLN]MNO{DQpSVUR, TWZmXY[\aYt^nf`V,h f]cb}ged_kigms, uAt^_Mpoqnvljrh`,` hIxZz}ji-{j y|~KjVO^-8 ~[B- _IX-o A$. k^|Oyf. T|PY.| \l. W~M,/@ k@n/h @wKGFEB/ DCIELHJMQN/L ORSTU~WVY\40 \[]V^`_abc~cdefv0g ihw}cjlBkmnopqsrtiuEkva0\ Bwxyz|{~}0 CXi<1$` ]rD~1h Bv1 @AgDj2H mk^FhD2 lY_Q\CZ2 OUt2d iW[~Y 3 aknQ`L3( XNp3 anM3 HB4T YRAQ@T4 NIRKHkEDM4GFL COPUTVYbSW4dQZ X][^aZG\`_Jdh5||P@, P(tp8(d`X0|t8DT`@\ L\ fbcgemmjilnoqp\5$ rsD5| FutxY{vzy_5 }G~|wB"6 Rd6, 6` FonM6 RzWC*7 ul7X vSq7 ]7 _KT28\ LPQt8 bl8 8` X]:9 i|9 l9$ :| Z@ZABCDFGErIHB: KJLMONQPr[RYSpTcRb\jU: V[YXEW\Z{L^l_]`afcbE: idehgDa`^jklnmuvprt]us; oqaxwyz|{s}~J; ; oS;4 IFcHM< u~mvXR<  ^< r< u=  mZZ=p umCjv{= d= VOqm >4 A@CBb> DbFEGIH>JV _FSPOcLNj_MKI[QR>$h \TSTUWXHYZ[(?G \Hb]d`a`^_j?H bcBdetgfiljmke?D msonnpqrntuv? wy{xzA|Eq~M0@ }vG[^|r@p J}y@ M}@d Z\8A zUzA4 A A HeSl@B@ WfnBI @gC[RBhAfaFGaIHB( IgDJEoMQLUiROPNKGWC TVSpXea[_Zbfj\dY]^HC, ]gchjmilkC nuovrtqwpcDks{~|z`C  }x@qJDUyJD [ZPD D8 rulDT rQA`HE K|XE0t$XP TXtxx,xh,< h\,8 $x0L(sV lk^E EWE ]IbmnxFd _wEE\`F erE]BF8 AtDCorTHIGFJBFN OKLMpUQGPSRcVWVXZ^[Y^&G\ ]d_`acbefgbhLvijPkhGX lmnopqrsCwMtquwvDGx zy|{}~FGT HmcF|.H cppH sH| t`rH 6I( epHxI GI tKI< Nf>J ~uWH@J UJ@@ BCnJPQKD NFHRGKLOEEIFdOVTFK mSUWX[YZM\a`KX Abh]_^PAdcefK gsi|jkl L qrm\naopztwsNL< uvx`ua{^|}~gL IwL XIMD ZVM IaM yM$ OspXqt\Np U^N TND JN A@CBDPEFG$O vHeIJKK`LoMONePQRSTUfO\V pWXYGZ[\O ]vu`_P^LabcKidfO ehig]frmwllkFlbYj,P opn_FsaUvrwtuqNbnP zxkyz_{~|@}Pldy uwTP xc4Q\  ]QvQ  JQ  L^Q  eLvnM\f SKEuuYZzwyOxv|-w?(///D0L012233 4455dij6x6д6̵Xp87|77 08ܹ8499̻,t::H;T;;D<<<X= =p>?d?l? P~pbowx@ IxY{w@ fySzwAD 5xA JewxtB ^@ABCYDEF[xBZ OVPc}RSWTReZx`C `Kgh=yC Ey4D TQPdBohylD i^FC[zD q~sUhG~Ez?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmmmmmmmmmmmnopqrstummmmmmmmvwxyz{|mmmmmmmmmmm}~mmmmmmmmmmm@   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWWWWWWWWXYZ[\]^_`abcdefghijklmnoWWWWWWWWpqrstuvwxyz{|}~WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW@  !"""""""""""""""#$%&'()*+,-./0123456789:;<=>?@ABC"""""""""""""DEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abc""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""@@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~@  !"#$%&'()*+,-./0123444444444444444444444444444444444444444444456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefgh@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRST@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~@   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwx    !"#$%&'(   !"#$%&'()*+,-./012                !"#$%&'()*+,-./0123456789:;<=>?@  !"#$%&'()*+,-./012345678  !"#$%&'()*+,-./0123456788889:;<8         !"#$                                           !"   !"#$%                           !"       !"#$%                                                                                                           !"    !"#                                          !"                                    !                    !"#                                                                                                                                                                                                                                                                   !                                                                                     !                                                                                                                                                                                                                                                           !"#                                               !"#$  !"#$%&'(                                                                                                                                                                                     !"#$%&'()*+,-./0123456789:;<=   !"#$%&'()*+,-./0123456789:;<=  !"#$%&'()*+,-./0123456789:;<=>  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!                           !    !                             !"#$   !"#$%&'                    !"#       !"#$%&                                          !"#$%&   !                         !"        !                                                         !      !                                                                                                                                                  !"                            !"#$                                                                                                   !"#$%&'()        !"#                                           !                                              !  !"#$%&'()*+,-./0123456789:;<=>?  ; D<tdT|zRx $0FJ w?:*3$"D \<HoGNUP K"4 f' fȞ f o f 0 K"K"o`  P"0( ooooM"`pGA$3a10 GA$3p1067`GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realignjapanese_sjis.so-2.2.10-35.el8.x86_64.debugtj7zXZִF!t/]?Eh=ڊ2NH:^ ,\c@X+Lk7prxQfx+#M\j,r 9`g|z 2G~#"ky@&DHmGo⣦&CļA:RFԷ+UX៦5{ؾΧD[4aD <%DJOdx@@8 @ؼؼ ""  ""  888$$ Std Ptd$$QtdRtd""GNUbJZ翧' cNT@ BE|qX x b , F"("0"("U `<__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeInit_chineserb_register_transcoderlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ui "P" " "@"H"X"h""""""""" "("8"H"""""" "HH"HtH5"%"hh%"D%"DH="Hz"H9tH&"Ht H=Q"H5J"H)HHH?HHtH"HtfD= "u+UH="Ht H="Yd"]wHH=" H="H=Y"H="HHHUTF-8GB12345GB2312 、。·ˉˇ¨〃々—~‖…‘’“”〔〕〈〉《》「」『』〖〗【】±×÷∶∧∨∑∏∪∩∈∷√⊥∥∠⌒⊙∫∮≡≌≈∽∝≠≮≯≤≥∞∵∴♂♀°′″℃$¤¢£‰§№☆★○●◎◇◆□■△▲※→←↑↓〓 ⒈⒉⒊⒋⒌⒍⒎⒏⒐⒑⒒⒓⒔⒕⒖⒗⒘⒙⒚⒛⑴⑵⑶⑷⑸⑹⑺⑻⑼⑽⑾⑿⒀⒁⒂⒃⒄⒅⒆⒇①②③④⑤⑥⑦⑧⑨⑩㈠㈡㈢㈣㈤㈥㈦㈧㈨㈩ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ`!"#¥%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} ̄ぁあぃいぅうぇえぉおかがきぎくぐけげこごさざしじすずせぜそぞただちぢっつづてでとどなにぬねのはばぱひびぴふぶぷへべぺほぼぽまみむめもゃやゅゆょよらりるれろゎわゐゑをん 8ァアィイゥウェエォオカガキギクグケゲコゴサザシジスズセゼソゾタダチヂッツヅテデトドナニヌネノハバパヒビピフブプヘベペホボポマミムメモャヤュユョヨラリルレロヮワヰヱヲンヴヵヶ ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ αβγδεζηθικλμνξοπρστυφχψωАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ абвгдеёжзийклмнопрстуфхцчшщъыьэюяāáǎàēéěèīíǐìōóǒòūúǔùǖǘǚǜüê ㄅㄆㄇㄈㄉㄊㄋㄌㄍㄎㄏㄐㄑㄒㄓㄔㄕㄖㄗㄘㄙㄚㄛㄜㄝㄞㄟㄠㄡㄢㄣㄤㄥㄦㄧㄨㄩ@ ─━│┃┄┅┆┇┈┉┊┋┌┍┎┏┐┑┒┓└┕┖┗┘┙┚┛├┝┞┟┠┡┢┣┤┥┦┧┨┩┪┫┬┭┮┯┰┱┲┳┴┵┶┷┸┹┺┻┼┽┾┿╀╁╂╃╄╅╆╇╈╉╊╋  0 啊阿埃挨哎唉哀皑癌蔼矮艾碍爱隘鞍氨安俺按暗岸胺案肮昂盎凹敖熬翱袄傲奥懊澳芭捌扒叭吧笆八疤巴拔跋靶把耙坝霸罢爸白柏百摆佰败拜稗斑班搬扳般颁板版扮拌伴瓣半办绊邦帮梆榜膀绑棒磅蚌镑傍谤苞胞包褒剥@ 薄雹保堡饱宝抱报暴豹鲍爆杯碑悲卑北辈背贝钡倍狈备惫焙被奔苯本笨崩绷甭泵蹦迸逼鼻比鄙笔彼碧蓖蔽毕毙毖币庇痹闭敝弊必辟壁臂避陛鞭边编贬扁便变卞辨辩辫遍标彪膘表鳖憋别瘪彬斌濒滨宾摈兵冰柄丙秉饼炳 病并玻菠播拨钵波博勃搏铂箔伯帛舶脖膊渤泊驳捕卜哺补埠不布步簿部怖擦猜裁材才财睬踩采彩菜蔡餐参蚕残惭惨灿苍舱仓沧藏操糙槽曹草厕策侧册测层蹭插叉茬茶查碴搽察岔差诧拆柴豺搀掺蝉馋谗缠铲产阐颤昌猖H场尝常长偿肠厂敞畅唱倡超抄钞朝嘲潮巢吵炒车扯撤掣彻澈郴臣辰尘晨忱沉陈趁衬撑称城橙成呈乘程惩澄诚承逞骋秤吃痴持匙池迟弛驰耻齿侈尺赤翅斥炽充冲虫崇宠抽酬畴踌稠愁筹仇绸瞅丑臭初出橱厨躇锄雏滁除楚础储矗搐触处揣川穿椽传船喘串疮窗幢床闯创吹炊捶锤垂春椿醇唇淳纯蠢戳绰疵茨磁雌辞慈瓷词此刺赐次聪葱囱匆从丛凑粗醋簇促蹿篡窜摧崔催脆瘁粹淬翠村存寸磋撮搓措挫错搭达答瘩打大呆歹傣戴带殆代贷袋待逮P怠耽担丹单郸掸胆旦氮但惮淡诞弹蛋当挡党荡档刀捣蹈倒岛祷导到稻悼道盗德得的蹬灯登等瞪凳邓堤低滴迪敌笛狄涤翟嫡抵底地蒂第帝弟递缔颠掂滇碘点典靛垫电佃甸店惦奠淀殿碉叼雕凋刁掉吊钓调跌爹碟蝶迭谍叠丁盯叮钉顶鼎锭定订丢东冬董懂动栋侗恫冻洞兜抖斗陡豆逗痘都督毒犊独读堵睹赌杜镀肚度渡妒端短锻段断缎堆兑队对墩吨蹲敦顿囤钝盾遁掇哆多夺垛躲朵跺舵剁惰堕蛾峨鹅俄额讹娥恶厄扼遏鄂饿恩而儿耳尔饵洱二X贰发罚筏伐乏阀法珐藩帆番翻樊矾钒繁凡烦反返范贩犯饭泛坊芳方肪房防妨仿访纺放菲非啡飞肥匪诽吠肺废沸费芬酚吩氛分纷坟焚汾粉奋份忿愤粪丰封枫蜂峰锋风疯烽逢冯缝讽奉凤佛否夫敷肤孵扶拂辐幅氟符伏俘服浮涪福袱弗甫抚辅俯釜斧脯腑府腐赴副覆赋复傅付阜父腹负富讣附妇缚咐噶嘎该改概钙盖溉干甘杆柑竿肝赶感秆敢赣冈刚钢缸肛纲岗港杠篙皋高膏羔糕搞镐稿告哥歌搁戈鸽胳疙割革葛格蛤阁隔铬个各给根跟耕更庚羹`埂耿梗工攻功恭龚供躬公宫弓巩汞拱贡共钩勾沟苟狗垢构购够辜菇咕箍估沽孤姑鼓古蛊骨谷股故顾固雇刮瓜剐寡挂褂乖拐怪棺关官冠观管馆罐惯灌贯光广逛瑰规圭硅归龟闺轨鬼诡癸桂柜跪贵刽辊滚棍锅郭国果裹过哈骸孩海氦亥害骇酣憨邯韩含涵寒函喊罕翰撼捍旱憾悍焊汗汉夯杭航壕嚎豪毫郝好耗号浩呵喝荷菏核禾和何合盒貉阂河涸赫褐鹤贺嘿黑痕很狠恨哼亨横衡恒轰哄烘虹鸿洪宏弘红喉侯猴吼厚候后呼乎忽瑚壶葫胡蝴狐糊湖h弧虎唬护互沪户花哗华猾滑画划化话槐徊怀淮坏欢环桓还缓换患唤痪豢焕涣宦幻荒慌黄磺蝗簧皇凰惶煌晃幌恍谎灰挥辉徽恢蛔回毁悔慧卉惠晦贿秽会烩汇讳诲绘荤昏婚魂浑混豁活伙火获或惑霍货祸击圾基机畸稽积箕肌饥迹激讥鸡姬绩缉吉极棘辑籍集及急疾汲即嫉级挤几脊己蓟技冀季伎祭剂悸济寄寂计记既忌际妓继纪嘉枷夹佳家加荚颊贾甲钾假稼价架驾嫁歼监坚尖笺间煎兼肩艰奸缄茧检柬碱硷拣捡简俭剪减荐槛鉴践贱见键箭件p健舰剑饯渐溅涧建僵姜将浆江疆蒋桨奖讲匠酱降蕉椒礁焦胶交郊浇骄娇嚼搅铰矫侥脚狡角饺缴绞剿教酵轿较叫窖揭接皆秸街阶截劫节桔杰捷睫竭洁结解姐戒藉芥界借介疥诫届巾筋斤金今津襟紧锦仅谨进靳晋禁近烬浸尽劲荆兢茎睛晶鲸京惊精粳经井警景颈静境敬镜径痉靖竟竞净炯窘揪究纠玖韭久灸九酒厩救旧臼舅咎就疚鞠拘狙疽居驹菊局咀矩举沮聚拒据巨具距踞锯俱句惧炬剧捐鹃娟倦眷卷绢撅攫抉掘倔爵觉决诀绝均菌钧军君峻x 俊竣浚郡骏喀咖卡咯开揩楷凯慨刊堪勘坎砍看康慷糠扛抗亢炕考拷烤靠坷苛柯棵磕颗科壳咳可渴克刻客课肯啃垦恳坑吭空恐孔控抠口扣寇枯哭窟苦酷库裤夸垮挎跨胯块筷侩快宽款匡筐狂框矿眶旷况亏盔岿窥葵奎魁傀!馈愧溃坤昆捆困括扩廓阔垃拉喇蜡腊辣啦莱来赖蓝婪栏拦篮阑兰澜谰揽览懒缆烂滥琅榔狼廊郎朗浪捞劳牢老佬姥酪烙涝勒乐雷镭蕾磊累儡垒擂肋类泪棱楞冷厘梨犁黎篱狸离漓理李里鲤礼莉荔吏栗丽厉励砾历利傈例俐#痢立粒沥隶力璃哩俩联莲连镰廉怜涟帘敛脸链恋炼练粮凉梁粱良两辆量晾亮谅撩聊僚疗燎寥辽潦了撂镣廖料列裂烈劣猎琳林磷霖临邻鳞淋凛赁吝拎玲菱零龄铃伶羚凌灵陵岭领另令溜琉榴硫馏留刘瘤流柳六龙聋咙笼窿%隆垄拢陇楼娄搂篓漏陋芦卢颅庐炉掳卤虏鲁麓碌露路赂鹿潞禄录陆戮驴吕铝侣旅履屡缕虑氯律率滤绿峦挛孪滦卵乱掠略抡轮伦仑沦纶论萝螺罗逻锣箩骡裸落洛骆络妈麻玛码蚂马骂嘛吗埋买麦卖迈脉瞒馒蛮满蔓曼慢漫&谩芒茫盲氓忙莽猫茅锚毛矛铆卯茂冒帽貌贸么玫枚梅酶霉煤没眉媒镁每美昧寐妹媚门闷们萌蒙檬盟锰猛梦孟眯醚靡糜迷谜弥米秘觅泌蜜密幂棉眠绵冕免勉娩缅面苗描瞄藐秒渺庙妙蔑灭民抿皿敏悯闽明螟鸣铭名命谬摸 (摹蘑模膜磨摩魔抹末莫墨默沫漠寞陌谋牟某拇牡亩姆母墓暮幕募慕木目睦牧穆拿哪呐钠那娜纳氖乃奶耐奈南男难囊挠脑恼闹淖呢馁内嫩能妮霓倪泥尼拟你匿腻逆溺蔫拈年碾撵捻念娘酿鸟尿捏聂孽啮镊镍涅您柠狞凝宁)拧泞牛扭钮纽脓浓农弄奴努怒女暖虐疟挪懦糯诺哦欧鸥殴藕呕偶沤啪趴爬帕怕琶拍排牌徘湃派攀潘盘磐盼畔判叛乓庞旁耪胖抛咆刨炮袍跑泡呸胚培裴赔陪配佩沛喷盆砰抨烹澎彭蓬棚硼篷膨朋鹏捧碰坯砒霹批披劈琵毗+啤脾疲皮匹痞僻屁譬篇偏片骗飘漂瓢票撇瞥拼频贫品聘乒坪苹萍平凭瓶评屏坡泼颇婆破魄迫粕剖扑铺仆莆葡菩蒲埔朴圃普浦谱曝瀑期欺栖戚妻七凄漆柒沏其棋奇歧畦崎脐齐旗祈祁骑起岂乞企启契砌器气迄弃汽泣讫掐,恰洽牵扦钎铅千迁签仟谦乾黔钱钳前潜遣浅谴堑嵌欠歉枪呛腔羌墙蔷强抢橇锹敲悄桥瞧乔侨巧鞘撬翘峭俏窍切茄且怯窃钦侵亲秦琴勤芹擒禽寝沁青轻氢倾卿清擎晴氰情顷请庆琼穷秋丘邱球求囚酋泅趋区蛆曲躯屈驱渠.取娶龋趣去圈颧权醛泉全痊拳犬券劝缺炔瘸却鹊榷确雀裙群然燃冉染瓤壤攘嚷让饶扰绕惹热壬仁人忍韧任认刃妊纫扔仍日戎茸蓉荣融熔溶容绒冗揉柔肉茹蠕儒孺如辱乳汝入褥软阮蕊瑞锐闰润若弱撒洒萨腮鳃塞赛三叁/伞散桑嗓丧搔骚扫嫂瑟色涩森僧莎砂杀刹沙纱傻啥煞筛晒珊苫杉山删煽衫闪陕擅赡膳善汕扇缮墒伤商赏晌上尚裳梢捎稍烧芍勺韶少哨邵绍奢赊蛇舌舍赦摄射慑涉社设砷申呻伸身深娠绅神沈审婶甚肾慎渗声生甥牲升绳$1省盛剩胜圣师失狮施湿诗尸虱十石拾时什食蚀实识史矢使屎驶始式示士世柿事拭誓逝势是嗜噬适仕侍释饰氏市恃室视试收手首守寿授售受瘦兽蔬枢梳殊抒输叔舒淑疏书赎孰熟薯暑曙署蜀黍鼠属术述树束戍竖墅庶数漱2恕刷耍摔衰甩帅栓拴霜双爽谁水睡税吮瞬顺舜说硕朔烁斯撕嘶思私司丝死肆寺嗣四伺似饲巳松耸怂颂送宋讼诵搜艘擞嗽苏酥俗素速粟僳塑溯宿诉肃酸蒜算虽隋随绥髓碎岁穗遂隧祟孙损笋蓑梭唆缩琐索锁所塌他它她塔,4獭挞蹋踏胎苔抬台泰酞太态汰坍摊贪瘫滩坛檀痰潭谭谈坦毯袒碳探叹炭汤塘搪堂棠膛唐糖倘躺淌趟烫掏涛滔绦萄桃逃淘陶讨套特藤腾疼誊梯剔踢锑提题蹄啼体替嚏惕涕剃屉天添填田甜恬舔腆挑条迢眺跳贴铁帖厅听烃5汀廷停亭庭挺艇通桐酮瞳同铜彤童桶捅筒统痛偷投头透凸秃突图徒途涂屠土吐兔湍团推颓腿蜕褪退吞屯臀拖托脱鸵陀驮驼椭妥拓唾挖哇蛙洼娃瓦袜歪外豌弯湾玩顽丸烷完碗挽晚皖惋宛婉万腕汪王亡枉网往旺望忘妄威47巍微危韦违桅围唯惟为潍维苇萎委伟伪尾纬未蔚味畏胃喂魏位渭谓尉慰卫瘟温蚊文闻纹吻稳紊问嗡翁瓮挝蜗涡窝我斡卧握沃巫呜钨乌污诬屋无芜梧吾吴毋武五捂午舞伍侮坞戊雾晤物勿务悟误昔熙析西硒矽晰嘻吸锡牺8稀息希悉膝夕惜熄烯溪汐犀檄袭席习媳喜铣洗系隙戏细瞎虾匣霞辖暇峡侠狭下厦夏吓掀锨先仙鲜纤咸贤衔舷闲涎弦嫌显险现献县腺馅羡宪陷限线相厢镶香箱襄湘乡翔祥详想响享项巷橡像向象萧硝霄削哮嚣销消宵淆晓<:小孝校肖啸笑效楔些歇蝎鞋协挟携邪斜胁谐写械卸蟹懈泄泻谢屑薪芯锌欣辛新忻心信衅星腥猩惺兴刑型形邢行醒幸杏性姓兄凶胸匈汹雄熊休修羞朽嗅锈秀袖绣墟戌需虚嘘须徐许蓄酗叙旭序畜恤絮婿绪续轩喧宣悬旋玄;选癣眩绚靴薛学穴雪血勋熏循旬询寻驯巡殉汛训讯逊迅压押鸦鸭呀丫芽牙蚜崖衙涯雅哑亚讶焉咽阉烟淹盐严研蜒岩延言颜阎炎沿奄掩眼衍演艳堰燕厌砚雁唁彦焰宴谚验殃央鸯秧杨扬佯疡羊洋阳氧仰痒养样漾邀腰妖瑶D=摇尧遥窑谣姚咬舀药要耀椰噎耶爷野冶也页掖业叶曳腋夜液一壹医揖铱依伊衣颐夷遗移仪胰疑沂宜姨彝椅蚁倚已乙矣以艺抑易邑屹亿役臆逸肄疫亦裔意毅忆义益溢诣议谊译异翼翌绎茵荫因殷音阴姻吟银淫寅饮尹引隐>印英樱婴鹰应缨莹萤营荧蝇迎赢盈影颖硬映哟拥佣臃痈庸雍踊蛹咏泳涌永恿勇用幽优悠忧尤由邮铀犹油游酉有友右佑釉诱又幼迂淤于盂榆虞愚舆余俞逾鱼愉渝渔隅予娱雨与屿禹宇语羽玉域芋郁吁遇喻峪御愈欲狱育誉L@浴寓裕预豫驭鸳渊冤元垣袁原援辕园员圆猿源缘远苑愿怨院曰约越跃钥岳粤月悦阅耘云郧匀陨允运蕴酝晕韵孕匝砸杂栽哉灾宰载再在咱攒暂赞赃脏葬遭糟凿藻枣早澡蚤躁噪造皂灶燥责择则泽贼怎增憎曾赠扎喳渣札轧A铡闸眨栅榨咋乍炸诈摘斋宅窄债寨瞻毡詹粘沾盏斩辗崭展蘸栈占战站湛绽樟章彰漳张掌涨杖丈帐账仗胀瘴障招昭找沼赵照罩兆肇召遮折哲蛰辙者锗蔗这浙珍斟真甄砧臻贞针侦枕疹诊震振镇阵蒸挣睁征狰争怔整拯正政TC帧症郑证芝枝支吱蜘知肢脂汁之织职直植殖执值侄址指止趾只旨纸志挚掷至致置帜峙制智秩稚质炙痔滞治窒中盅忠钟衷终种肿重仲众舟周州洲诌粥轴肘帚咒皱宙昼骤珠株蛛朱猪诸诛逐竹烛煮拄瞩嘱主著柱助蛀贮铸筑D住注祝驻抓爪拽专砖转撰赚篆桩庄装妆撞壮状椎锥追赘坠缀谆准捉拙卓桌琢茁酌啄着灼浊兹咨资姿滋淄孜紫仔籽滓子自渍字鬃棕踪宗综总纵邹走奏揍租足卒族祖诅阻组钻纂嘴醉最罪尊遵昨左佐柞做作坐座 `\F亍丌兀丐廿卅丕亘丞鬲孬噩丨禺丿匕乇夭爻卮氐囟胤馗毓睾鼗丶亟鼐乜乩亓芈孛啬嘏仄厍厝厣厥厮靥赝匚叵匦匮匾赜卦卣刂刈刎刭刳刿剀剌剞剡剜蒯剽劂劁劐劓冂罔亻仃仉仂仨仡仫仞伛仳伢佤仵伥伧伉伫佞佧攸佚佝G佟佗伲伽佶佴侑侉侃侏佾佻侪佼侬侔俦俨俪俅俚俣俜俑俟俸倩偌俳倬倏倮倭俾倜倌倥倨偾偃偕偈偎偬偻傥傧傩傺僖儆僭僬僦僮儇儋仝氽佘佥俎龠汆籴兮巽黉馘冁夔勹匍訇匐凫夙兕亠兖亳衮袤亵脔裒禀嬴蠃羸冫冱冽冼TI凇冖冢冥讠讦讧讪讴讵讷诂诃诋诏诎诒诓诔诖诘诙诜诟诠诤诨诩诮诰诳诶诹诼诿谀谂谄谇谌谏谑谒谔谕谖谙谛谘谝谟谠谡谥谧谪谫谮谯谲谳谵谶卩卺阝阢阡阱阪阽阼陂陉陔陟陧陬陲陴隈隍隗隰邗邛邝邙邬邡邴邳邶邺J邸邰郏郅邾郐郄郇郓郦郢郜郗郛郫郯郾鄄鄢鄞鄣鄱鄯鄹酃酆刍奂劢劬劭劾哿勐勖勰叟燮矍廴凵凼鬯厶弁畚巯坌垩垡塾墼壅壑圩圬圪圳圹圮圯坜圻坂坩垅坫垆坼坻坨坭坶坳垭垤垌垲埏垧垴垓垠埕埘埚埙埒垸埴埯埸埤埝\L堋堍埽埭堀堞堙塄堠塥塬墁墉墚墀馨鼙懿艹艽艿芏芊芨芄芎芑芗芙芫芸芾芰苈苊苣芘芷芮苋苌苁芩芴芡芪芟苄苎芤苡茉苷苤茏茇苜苴苒苘茌苻苓茑茚茆茔茕苠苕茜荑荛荜茈莒茼茴茱莛荞茯荏荇荃荟荀茗荠茭茺茳荦荥M荨茛荩荬荪荭荮莰荸莳莴莠莪莓莜莅荼莶莩荽莸荻莘莞莨莺莼菁萁菥菘堇萘萋菝菽菖萜萸萑萆菔菟萏萃菸菹菪菅菀萦菰菡葜葑葚葙葳蒇蒈葺蒉葸萼葆葩葶蒌蒎萱葭蓁蓍蓐蓦蒽蓓蓊蒿蒺蓠蒡蒹蒴蒗蓥蓣蔌甍蔸蓰蔹蔟蔺dO蕖蔻蓿蓼蕙蕈蕨蕤蕞蕺瞢蕃蕲蕻薤薨薇薏蕹薮薜薅薹薷薰藓藁藜藿蘧蘅蘩蘖蘼廾弈夼奁耷奕奚奘匏尢尥尬尴扌扪抟抻拊拚拗拮挢拶挹捋捃掭揶捱捺掎掴捭掬掊捩掮掼揲揸揠揿揄揞揎摒揆掾摅摁搋搛搠搌搦搡摞撄摭撖P摺撷撸撙撺擀擐擗擤擢攉攥攮弋忒甙弑卟叱叽叩叨叻吒吖吆呋呒呓呔呖呃吡呗呙吣吲咂咔呷呱呤咚咛咄呶呦咝哐咭哂咴哒咧咦哓哔呲咣哕咻咿哌哙哚哜咩咪咤哝哏哞唛哧唠哽唔哳唢唣唏唑唧唪啧喏喵啉啭啁啕唿啐唼lR唷啖啵啶啷唳唰啜喋嗒喃喱喹喈喁喟啾嗖喑啻嗟喽喾喔喙嗪嗷嗉嘟嗑嗫嗬嗔嗦嗝嗄嗯嗥嗲嗳嗌嗍嗨嗵嗤辔嘞嘈嘌嘁嘤嘣嗾嘀嘧嘭噘嘹噗嘬噍噢噙噜噌噔嚆噤噱噫噻噼嚅嚓嚯囔囗囝囡囵囫囹囿圄圊圉圜帏帙帔帑帱帻帼S帷幄幔幛幞幡岌屺岍岐岖岈岘岙岑岚岜岵岢岽岬岫岱岣峁岷峄峒峤峋峥崂崃崧崦崮崤崞崆崛嵘崾崴崽嵬嵛嵯嵝嵫嵋嵊嵩嵴嶂嶙嶝豳嶷巅彳彷徂徇徉後徕徙徜徨徭徵徼衢彡犭犰犴犷犸狃狁狎狍狒狨狯狩狲狴狷猁狳猃狺tU狻猗猓猡猊猞猝猕猢猹猥猬猸猱獐獍獗獠獬獯獾舛夥飧夤夂饣饧饨饩饪饫饬饴饷饽馀馄馇馊馍馐馑馓馔馕庀庑庋庖庥庠庹庵庾庳赓廒廑廛廨廪膺忄忉忖忏怃忮怄忡忤忾怅怆忪忭忸怙怵怦怛怏怍怩怫怊怿怡恸恹恻恺恂V恪恽悖悚悭悝悃悒悌悛惬悻悱惝惘惆惚悴愠愦愕愣惴愀愎愫慊慵憬憔憧憷懔懵忝隳闩闫闱闳闵闶闼闾阃阄阆阈阊阋阌阍阏阒阕阖阗阙阚丬爿戕氵汔汜汊沣沅沐沔沌汨汩汴汶沆沩泐泔沭泷泸泱泗沲泠泖泺泫泮沱泓泯泾|X洹洧洌浃浈洇洄洙洎洫浍洮洵洚浏浒浔洳涑浯涞涠浞涓涔浜浠浼浣渚淇淅淞渎涿淠渑淦淝淙渖涫渌涮渫湮湎湫溲湟溆湓湔渲渥湄滟溱溘滠漭滢溥溧溽溻溷滗溴滏溏滂溟潢潆潇漤漕滹漯漶潋潴漪漉漩澉澍澌潸潲潼潺濑Z濉澧澹澶濂濡濮濞濠濯瀚瀣瀛瀹瀵灏灞宀宄宕宓宥宸甯骞搴寤寮褰寰蹇謇辶迓迕迥迮迤迩迦迳迨逅逄逋逦逑逍逖逡逵逶逭逯遄遑遒遐遨遘遢遛暹遴遽邂邈邃邋彐彗彖彘尻咫屐屙孱屣屦羼弪弩弭艴弼鬻屮妁妃妍妩妪妣[妗姊妫妞妤姒妲妯姗妾娅娆姝娈姣姘姹娌娉娲娴娑娣娓婀婧婊婕娼婢婵胬媪媛婷婺媾嫫媲嫒嫔媸嫠嫣嫱嫖嫦嫘嫜嬉嬗嬖嬲嬷孀尕尜孚孥孳孑孓孢驵驷驸驺驿驽骀骁骅骈骊骐骒骓骖骘骛骜骝骟骠骢骣骥骧纟纡纣纥纨纩]纭纰纾绀绁绂绉绋绌绐绔绗绛绠绡绨绫绮绯绱绲缍绶绺绻绾缁缂缃缇缈缋缌缏缑缒缗缙缜缛缟缡缢缣缤缥缦缧缪缫缬缭缯缰缱缲缳缵幺畿巛甾邕玎玑玮玢玟珏珂珑玷玳珀珉珈珥珙顼琊珩珧珞玺珲琏琪瑛琦琥琨琰琮琬^琛琚瑁瑜瑗瑕瑙瑷瑭瑾璜璎璀璁璇璋璞璨璩璐璧瓒璺韪韫韬杌杓杞杈杩枥枇杪杳枘枧杵枨枞枭枋杷杼柰栉柘栊柩枰栌柙枵柚枳柝栀柃枸柢栎柁柽栲栳桠桡桎桢桄桤梃栝桕桦桁桧桀栾桊桉栩梵梏桴桷梓桫棂楮棼椟椠棹`椤棰椋椁楗棣椐楱椹楠楂楝榄楫榀榘楸椴槌榇榈槎榉楦楣楹榛榧榻榫榭槔榱槁槊槟榕槠榍槿樯槭樗樘橥槲橄樾檠橐橛樵檎橹樽樨橘橼檑檐檩檗檫猷獒殁殂殇殄殒殓殍殚殛殡殪轫轭轱轲轳轵轶轸轷轹轺轼轾辁辂辄辇辋a辍辎辏辘辚軎戋戗戛戟戢戡戥戤戬臧瓯瓴瓿甏甑甓攴旮旯旰昊昙杲昃昕昀炅曷昝昴昱昶昵耆晟晔晁晏晖晡晗晷暄暌暧暝暾曛曜曦曩贲贳贶贻贽赀赅赆赈赉赇赍赕赙觇觊觋觌觎觏觐觑牮犟牝牦牯牾牿犄犋犍犏犒挈挲掰c搿擘耄毪毳毽毵毹氅氇氆氍氕氘氙氚氡氩氤氪氲攵敕敫牍牒牖爰虢刖肟肜肓肼朊肽肱肫肭肴肷胧胨胩胪胛胂胄胙胍胗朐胝胫胱胴胭脍脎胲胼朕脒豚脶脞脬脘脲腈腌腓腴腙腚腱腠腩腼腽腭腧塍媵膈膂膑滕膣膪臌朦臊膻d臁膦欤欷欹歃歆歙飑飒飓飕飙飚殳彀毂觳斐齑斓於旆旄旃旌旎旒旖炀炜炖炝炻烀炷炫炱烨烊焐焓焖焯焱煳煜煨煅煲煊煸煺熘熳熵熨熠燠燔燧燹爝爨灬焘煦熹戾戽扃扈扉礻祀祆祉祛祜祓祚祢祗祠祯祧祺禅禊禚禧禳忑忐 f怼恝恚恧恁恙恣悫愆愍慝憩憝懋懑戆肀聿沓泶淼矶矸砀砉砗砘砑斫砭砜砝砹砺砻砟砼砥砬砣砩硎硭硖硗砦硐硇硌硪碛碓碚碇碜碡碣碲碹碥磔磙磉磬磲礅磴礓礤礞礴龛黹黻黼盱眄眍盹眇眈眚眢眙眭眦眵眸睐睑睇睃睚睨g睢睥睿瞍睽瞀瞌瞑瞟瞠瞰瞵瞽町畀畎畋畈畛畲畹疃罘罡罟詈罨罴罱罹羁罾盍盥蠲钅钆钇钋钊钌钍钏钐钔钗钕钚钛钜钣钤钫钪钭钬钯钰钲钴钶钷钸钹钺钼钽钿铄铈铉铊铋铌铍铎铐铑铒铕铖铗铙铘铛铞铟铠铢铤铥铧铨铪(i铩铫铮铯铳铴铵铷铹铼铽铿锃锂锆锇锉锊锍锎锏锒锓锔锕锖锘锛锝锞锟锢锪锫锩锬锱锲锴锶锷锸锼锾锿镂锵镄镅镆镉镌镎镏镒镓镔镖镗镘镙镛镞镟镝镡镢镤镥镦镧镨镩镪镫镬镯镱镲镳锺矧矬雉秕秭秣秫稆嵇稃稂稞稔j稹稷穑黏馥穰皈皎皓皙皤瓞瓠甬鸠鸢鸨鸩鸪鸫鸬鸲鸱鸶鸸鸷鸹鸺鸾鹁鹂鹄鹆鹇鹈鹉鹋鹌鹎鹑鹕鹗鹚鹛鹜鹞鹣鹦鹧鹨鹩鹪鹫鹬鹱鹭鹳疒疔疖疠疝疬疣疳疴疸痄疱疰痃痂痖痍痣痨痦痤痫痧瘃痱痼痿瘐瘀瘅瘌瘗瘊瘥瘘瘕瘙0l瘛瘼瘢瘠癀瘭瘰瘿瘵癃瘾瘳癍癞癔癜癖癫癯翊竦穸穹窀窆窈窕窦窠窬窨窭窳衤衩衲衽衿袂袢裆袷袼裉裢裎裣裥裱褚裼裨裾裰褡褙褓褛褊褴褫褶襁襦襻疋胥皲皴矜耒耔耖耜耠耢耥耦耧耩耨耱耋耵聃聆聍聒聩聱覃顸颀颃m颉颌颍颏颔颚颛颞颟颡颢颥颦虍虔虬虮虿虺虼虻蚨蚍蚋蚬蚝蚧蚣蚪蚓蚩蚶蛄蚵蛎蚰蚺蚱蚯蛉蛏蚴蛩蛱蛲蛭蛳蛐蜓蛞蛴蛟蛘蛑蜃蜇蛸蜈蜊蜍蜉蜣蜻蜞蜥蜮蜚蜾蝈蜴蜱蜩蜷蜿螂蜢蝽蝾蝻蝠蝰蝌蝮螋蝓蝣蝼蝤蝙蝥螓螯螨蟒8o蟆螈螅螭螗螃螫蟥螬螵螳蟋蟓螽蟑蟀蟊蟛蟪蟠蟮蠖蠓蟾蠊蠛蠡蠹蠼缶罂罄罅舐竺竽笈笃笄笕笊笫笏筇笸笪笙笮笱笠笥笤笳笾笞筘筚筅筵筌筝筠筮筻筢筲筱箐箦箧箸箬箝箨箅箪箜箢箫箴篑篁篌篝篚篥篦篪簌篾篼簏簖簋p簟簪簦簸籁籀臾舁舂舄臬衄舡舢舣舭舯舨舫舸舻舳舴舾艄艉艋艏艚艟艨衾袅袈裘裟襞羝羟羧羯羰羲籼敉粑粝粜粞粢粲粼粽糁糇糌糍糈糅糗糨艮暨羿翎翕翥翡翦翩翮翳糸絷綦綮繇纛麸麴赳趄趔趑趱赧赭豇豉酊酐酎酏酤@r酢酡酰酩酯酽酾酲酴酹醌醅醐醍醑醢醣醪醭醮醯醵醴醺豕鹾趸跫踅蹙蹩趵趿趼趺跄跖跗跚跞跎跏跛跆跬跷跸跣跹跻跤踉跽踔踝踟踬踮踣踯踺蹀踹踵踽踱蹉蹁蹂蹑蹒蹊蹰蹶蹼蹯蹴躅躏躔躐躜躞豸貂貊貅貘貔斛觖觞觚觜s觥觫觯訾謦靓雩雳雯霆霁霈霏霎霪霭霰霾龀龃龅龆龇龈龉龊龌黾鼋鼍隹隼隽雎雒瞿雠銎銮鋈錾鍪鏊鎏鐾鑫鱿鲂鲅鲆鲇鲈稣鲋鲎鲐鲑鲒鲔鲕鲚鲛鲞鲟鲠鲡鲢鲣鲥鲦鲧鲨鲩鲫鲭鲮鲰鲱鲲鲳鲴鲵鲶鲷鲺鲻鲼鲽鳄鳅鳆鳇鳊鳋Hu鳌鳍鳎鳏鳐鳓鳔鳕鳗鳘鳙鳜鳝鳟鳢靼鞅鞑鞒鞔鞯鞫鞣鞲鞴骱骰骷鹘骶骺骼髁髀髅髂髋髌髑魅魃魇魉魈魍魑飨餍餮饕饔髟髡髦髯髫髻髭髹鬈鬏鬓鬟鬣麽麾縻麂麇麈麋麒鏖麝麟黛黜黝黠黟黢黩黧黥黪黯鼢鼬鼯鼹鼷鼽鼾齄v|0 ( 8 @HPX`hp !x#$&() +,./12$45,784:;<=>D@ALCDTFGLIJTLM\OPdRSlUVtXY|[]^`acdfg ij(lm0op8rs@uvHxPx啊阿埃挨哎唉哀皚癌藹矮艾礙愛隘鞍氨安俺按暗岸胺案骯昂盎凹敖熬翱襖傲奥懊澳芭捌扒叭吧笆八疤巴拔跋靶把耙壩霸罷爸白柏百擺佰敗拜稗斑班搬扳般頒板版扮拌伴瓣半辦絆邦幫梆榜膀綁棒磅蚌鎊傍謗苞胞包褒剥y薄雹保堡飽寶抱報暴豹鮑爆杯碑悲卑北輩背貝鋇倍狽備憊焙被奔苯本笨崩綳甭泵蹦迸逼鼻比鄙筆彼碧蓖蔽畢斃毖幣庇痹閉敝弊必辟壁臂避陛鞭邊編貶扁便變卞辨辯辮遍標彪膘表鱉憋别癟彬斌瀕濱賓擯兵冰柄丙秉餅炳,{病并玻菠播撥鉢波博勃搏鉑箔伯帛舶脖膊渤泊駁捕卜哺補埠不布步簿部怖擦猜裁材才財睬踩采彩菜蔡餐參蠶殘慚慘燦蒼艙倉滄藏操糙槽曹草厠策側册測層蹭插叉茬茶查碴搽察岔差詫拆柴豺攙摻蟬饞讒纏鏟産闡顫昌猖|場嘗常長償腸廠敞暢唱倡超抄鈔朝嘲潮巢吵炒車扯撤掣徹澈郴臣辰塵晨忱沉陳趁襯撑稱城橙成呈乘程懲澄誠承逞騁秤吃痴持匙池遲弛馳耻齒侈尺赤翅斥熾充衝蟲崇寵抽酬疇躊稠愁籌仇綢瞅醜臭初出橱厨躇鋤雛滁除楚4~礎儲矗搐觸處揣川穿椽傳船喘串瘡窗幢床闖創吹炊捶錘垂春椿醇唇淳純蠢戳綽疵茨磁雌辭慈瓷詞此刺賜次聰葱囱匆從叢凑粗醋簇促躥篡竄摧崔催脆瘁粹淬翠村存寸磋撮搓措挫錯搭達答瘩打大呆歹傣戴帶殆代貸袋待逮怠耽擔丹單鄲撣膽旦氮但憚淡誕彈蛋當擋黨蕩檔刀搗蹈倒島禱導到稻悼道盗德得的蹬燈登等瞪凳鄧堤低滴迪敵笛狄滌翟嫡抵底地蒂第帝弟遞締顛掂滇碘點典靛墊電佃甸店惦奠澱殿碉叼雕凋刁掉吊釣調跌爹碟蝶迭諜疊<丁盯叮釘頂鼎錠定訂丢東冬董懂動棟侗恫凍洞兜抖鬥陡豆逗痘都督毒犢獨讀堵睹賭杜鍍肚度渡妒端短鍛段斷緞堆兑隊對墩噸蹲敦頓囤鈍盾遁掇哆多奪垛躲朵跺舵剁惰墮蛾峨鵝俄額訛娥惡厄扼遏鄂餓恩而兒耳爾餌洱二貳發罰筏伐乏閥法珐藩帆番翻樊礬釩繁凡煩反返範販犯飯泛坊芳方肪房防妨仿訪紡放菲非啡飛肥匪誹吠肺廢沸費芬酚吩氛分紛墳焚汾粉奮份忿憤糞豐封楓蜂峰鋒風瘋烽逢馮縫諷奉鳳佛否夫敷膚孵扶拂輻幅氟符伏俘服D浮涪福袱弗甫撫輔俯釜斧脯腑府腐赴副覆賦復傅付阜父腹負富訃附婦縛咐噶嘎該改概鈣蓋溉幹甘杆柑竿肝趕感秆敢贛岡剛鋼缸肛綱崗港杠篙皋高膏羔糕搞鎬稿告哥歌擱戈鴿胳疙割革葛格蛤閣隔鉻個各給根跟耕更庚羹ȅ埂耿梗工攻功恭龔供躬公宫弓鞏汞拱貢共鈎勾溝苟狗垢構購够辜菇咕箍估沽孤姑鼓古蠱骨谷股故顧固雇刮瓜剮寡挂褂乖拐怪棺關官冠觀管館罐慣灌貫光廣逛瑰規圭硅歸龜閨軌鬼詭癸桂櫃跪貴劊輥滚棍鍋郭國果裹過哈L骸孩海氦亥害駭酣憨邯韓含涵寒函喊罕翰撼捍旱憾悍焊汗漢夯杭航壕嚎豪毫郝好耗號浩呵喝荷菏核禾和何合盒貉閡河涸赫褐鶴賀嘿黑痕很狠恨哼亨横衡恒轟哄烘虹鴻洪宏弘紅喉侯猴吼厚候後呼乎忽瑚壺葫胡蝴狐糊湖Ј弧虎唬護互滬户花嘩華猾滑畫劃化話槐徊懷淮壞歡環桓還緩換患喚瘓豢煥渙宦幻荒慌黄磺蝗簧皇凰惶煌晃幌恍謊灰揮輝徽恢蛔回毁悔慧卉惠晦賄穢會燴匯諱誨繪葷昏婚魂渾混豁活伙火獲或惑霍貨禍擊圾基機畸稽積箕T肌饑迹激譏鷄姬績緝吉極棘輯籍集及急疾汲即嫉級擠幾脊己薊技冀季伎祭劑悸濟寄寂計記既忌際妓繼紀嘉枷夾佳家加莢頰賈甲鉀假稼價架駕嫁殲監堅尖箋間煎兼肩艱奸緘繭檢柬碱鹼揀撿簡儉剪减薦檻鑒踐賤見鍵箭件؋健艦劍餞漸濺澗建僵姜將漿江疆蔣槳奬講匠醬降蕉椒礁焦膠交郊澆驕嬌嚼攪鉸矯僥脚狡角餃繳絞剿教酵轎較叫窖揭接皆秸街階截劫節桔杰捷睫竭潔結解姐戒藉芥界借介疥誡届巾筋斤金今津襟緊錦僅謹進靳晉禁近燼浸\盡勁荆兢莖睛晶鯨京驚精粳經井警景頸靜境敬鏡徑痙靖竟競凈炯窘揪究糾玖韭久灸九酒厩救舊臼舅咎就疚鞠拘狙疽居駒菊局咀矩舉沮聚拒據巨具距踞鋸俱句懼炬劇捐鵑娟倦眷卷絹撅攫抉掘倔爵覺决訣絶均菌鈞軍君峻俊竣浚郡駿喀咖卡咯開揩楷凱慨刊堪勘坎砍看康慷糠扛抗亢炕考拷烤靠坷苛柯棵磕顆科殻咳可渴克刻客課肯啃墾懇坑吭空恐孔控摳口扣寇枯哭窟苦酷庫褲誇垮挎跨胯塊筷儈快寬款匡筐狂框礦眶曠况虧盔巋窺葵奎魁傀d饋愧潰坤昆捆困括擴廓闊垃拉喇蠟臘辣啦萊來賴藍婪欄攔籃闌蘭瀾讕攬覽懶纜爛濫琅榔狼廊郎朗浪撈勞牢老佬姥酪烙澇勒樂雷鐳蕾磊累儡壘擂肋類泪棱楞冷厘梨犁黎籬狸離灕理李裏鯉禮莉荔吏栗麗厲勵礫歷利傈例俐痢立粒瀝隸力璃哩倆聯蓮連鐮廉憐漣簾斂臉鏈戀煉練糧凉梁粱良兩輛量晾亮諒撩聊僚療燎寥遼潦了撂鐐廖料列裂烈劣獵琳林磷霖臨鄰鱗淋凛賃吝拎玲菱零齡鈴伶羚凌靈陵嶺領另令溜琉榴硫餾留劉瘤流柳六龍聾嚨籠窿l隆壟攏隴樓婁摟簍漏陋蘆盧顱廬爐擄滷虜魯麓碌露路賂鹿潞禄録陸戮驢吕鋁侣旅履屢縷慮氯律率濾緑巒攣孿灤卵亂掠略掄輪倫侖淪綸論蘿螺羅邏鑼籮騾裸落洛駱絡媽麻瑪碼螞馬駡嘛嗎埋買麥賣邁脉瞞饅蠻滿蔓曼慢漫謾芒茫盲氓忙莽猫茅錨毛矛鉚卯茂冒帽貌貿麽玫枚梅酶霉煤没眉媒鎂每美昧寐妹媚門悶們萌蒙檬盟錳猛夢孟眯醚靡糜迷謎彌米秘覓泌蜜密幂棉眠綿冕免勉娩緬面苗描瞄藐秒渺廟妙蔑滅民抿皿敏憫閩明螟鳴銘名命謬摸t摹蘑模膜磨摩魔抹末莫墨默沫漠寞陌謀牟某拇牡畝姆母墓暮幕募慕木目睦牧穆拿哪呐鈉那娜納氖乃奶耐奈南男難囊撓腦惱鬧淖呢餒内嫩能妮霓倪泥尼擬你匿膩逆溺蔫拈年碾攆捻念娘釀鳥尿捏聶孽嚙鑷鎳涅您檸獰凝寧擰濘牛扭鈕紐膿濃農弄奴努怒女暖虐瘧挪懦糯諾哦歐鷗毆藕嘔偶漚啪趴爬帕怕琶拍排牌徘湃派攀潘盤磐盼畔判叛乓龐旁耪胖抛咆刨炮袍跑泡呸胚培裴賠陪配佩沛噴盆砰抨烹澎彭蓬棚硼篷膨朋鵬捧碰坯砒霹批披劈琵毗|啤脾疲皮匹痞僻屁譬篇偏片騙飄漂瓢票撇瞥拼頻貧品聘乒坪蘋萍平憑瓶評屏坡潑頗婆破魄迫粕剖撲鋪僕莆葡菩蒲埔樸圃普浦譜曝瀑期欺棲戚妻七凄漆柒沏其棋奇歧畦崎臍齊旗祈祁騎起豈乞企啓契砌器氣迄棄汽泣訖掐恰洽牽扦釺鉛千遷簽仟謙乾黔錢鉗前潛遣淺譴塹嵌欠歉槍嗆腔羌墻薔强搶橇鍬敲悄橋瞧喬僑巧鞘撬翹峭俏竅切茄且怯竊欽侵親秦琴勤芹擒禽寢沁青輕氫傾卿清擎晴氰情頃請慶瓊窮秋丘邱球求囚酋泅趨區蛆曲軀屈驅渠取娶齲趣去圈顴權醛泉全痊拳犬券勸缺炔瘸却鵲榷確雀裙群然燃冉染瓤壤攘嚷讓饒擾繞惹熱壬仁人忍韌任認刃妊紉扔仍日戎茸蓉榮融熔溶容絨冗揉柔肉茹蠕儒孺如辱乳汝入褥軟阮蕊瑞鋭閏潤若弱撒灑薩腮鰓塞賽三叁傘散桑嗓喪搔騷掃嫂瑟色澀森僧莎砂殺刹沙紗傻啥煞篩曬珊苫杉山删煽衫閃陝擅贍膳善汕扇繕墒傷商賞晌上尚裳梢捎稍燒芍勺韶少哨邵紹奢賒蛇舌捨赦攝射懾涉社設砷申呻伸身深娠紳神沈審嬸甚腎慎滲聲生甥牲升繩省盛剩勝聖師失獅施濕詩尸虱十石拾時什食蝕實識史矢使屎駛始式示士世柿事拭誓逝勢是嗜噬適仕侍釋飾氏市恃室視試收手首守壽授售受瘦獸蔬樞梳殊抒輸叔舒淑疏書贖孰熟薯暑曙署蜀黍鼠屬術述樹束戍竪墅庶數漱恕刷耍摔衰甩帥栓拴霜雙爽誰水睡税吮瞬順舜説碩朔爍斯撕嘶思私司絲死肆寺嗣四伺似飼巳鬆聳慫頌送宋訟誦搜艘擻嗽蘇酥俗素速粟僳塑溯宿訴肅酸蒜算雖隋隨綏髓碎歲穗遂隧祟孫損笋蓑梭唆縮瑣索鎖所塌他它她塔獺撻蹋踏胎苔抬臺泰酞太態汰坍攤貪癱灘壇檀痰潭譚談坦毯袒碳探嘆炭湯塘搪堂棠膛唐糖倘躺淌趟燙掏濤滔縧萄桃逃淘陶討套特藤騰疼謄梯剔踢銻提題蹄啼體替嚏惕涕剃屉天添填田甜恬舔腆挑條迢眺跳貼鐵帖廳聽烴汀廷停亭庭挺艇通桐酮瞳同銅彤童桶捅筒統痛偷投頭透凸秃突圖徒途塗屠土吐兔湍團推頽腿蜕褪退吞屯臀拖托脱鴕陀馱駝橢妥拓唾挖哇蛙窪娃瓦襪歪外豌彎灣玩頑丸烷完碗挽晚皖惋宛婉萬腕汪王亡枉網往旺望忘妄威巍微危韋違桅圍唯惟爲濰維葦萎委偉僞尾緯未蔚味畏胃喂魏位渭謂尉慰衛瘟温蚊文聞紋吻穩紊問嗡翁瓮撾蝸渦窩我斡卧握沃巫嗚鎢烏污誣屋無蕪梧吾吴毋武五捂午舞伍侮塢戊霧晤物勿務悟誤昔熙析西硒矽晰嘻吸錫犧 稀息希悉膝夕惜熄烯溪汐犀檄襲席習媳喜銑洗系隙戲細瞎蝦匣霞轄暇峽俠狹下厦夏嚇掀鍁先仙鮮纖咸賢銜舷閑涎弦嫌顯險現獻縣腺餡羡憲陷限綫相厢鑲香箱襄湘鄉翔祥詳想響享項巷橡像向象蕭硝霄削哮囂銷消宵淆曉小孝校肖嘯笑效楔些歇蝎鞋協挾携邪斜脅諧寫械卸蟹懈泄瀉謝屑薪芯鋅欣辛新忻心信釁星腥猩惺興刑型形邢行醒幸杏性姓兄凶胸匈汹雄熊休修羞朽嗅銹秀袖綉墟戌需虚嘘須徐許蓄酗叙旭序畜恤絮婿緒續軒喧宣懸旋玄(選癬眩絢靴薛學穴雪血勛熏循旬詢尋馴巡殉汛訓訊遜迅壓押鴉鴨呀丫芽牙蚜崖衙涯雅啞亞訝焉咽閹烟淹鹽嚴研蜒岩延言顔閻炎沿奄掩眼衍演艷堰燕厭硯雁唁彦焰宴諺驗殃央鴦秧楊揚佯瘍羊洋陽氧仰癢養樣漾邀腰妖瑶摇堯遥窑謡姚咬舀藥要耀椰噎耶爺野冶也頁掖業葉曳腋夜液一壹醫揖銥依伊衣頤夷遺移儀胰疑沂宜姨彝椅蟻倚已乙矣以藝抑易邑屹億役臆逸肄疫亦裔意毅憶義益溢詣議誼譯异翼翌繹茵蔭因殷音陰姻吟銀淫寅飲尹引隱0印英櫻嬰鷹應纓瑩螢營熒蠅迎贏盈影穎硬映喲擁傭臃癰庸雍踴蛹咏泳涌永恿勇用幽優悠憂尤由郵鈾猶油游酉有友右佑釉誘又幼迂淤于盂榆虞愚輿餘俞逾魚愉渝漁隅予娱雨與嶼禹宇語羽玉域芋鬱吁遇喻峪御愈欲獄育譽浴寓裕預豫馭鴛淵冤元垣袁原援轅園員圓猿源緣遠苑願怨院曰約越躍鑰岳粤月悦閲耘雲鄖匀隕允運藴醖暈韵孕匝砸雜栽哉灾宰載再在咱攢暫贊贜臟葬遭糟鑿藻棗早澡蚤躁噪造皂竈燥責擇則澤賊怎增憎曾贈扎喳渣札軋8鍘閘眨栅榨咋乍炸詐摘齋宅窄債寨瞻氈詹粘沾盞斬輾嶄展蘸棧占戰站湛綻樟章彰漳張掌漲杖丈帳賬仗脹瘴障招昭找沼趙照罩兆肇召遮折哲蟄轍者鍺蔗這浙珍斟真甄砧臻貞針偵枕疹診震振鎮陣蒸掙睜征猙爭怔整拯正政幀癥鄭證芝枝支吱蜘知肢脂汁之織職直植殖執值侄址指止趾衹旨紙志摯擲至致置幟峙制智秩稚質炙痔滯治窒中盅忠鐘衷終種腫重仲衆舟周州洲謅粥軸肘帚咒皺宙晝驟珠株蛛朱猪諸誅逐竹燭煮拄矚囑主著柱助蛀貯鑄築@住注祝駐抓爪拽專磚轉撰賺篆樁莊裝妝撞壯狀椎錐追贅墜綴諄準捉拙卓桌琢茁酌啄着灼濁兹咨資姿滋淄孜紫仔籽滓子自漬字鬃棕踪宗綜總縱鄒走奏揍租足卒族祖詛阻組鑽纂嘴醉最罪尊遵昨左佐柞做作坐座 `Ĵ亍丌兀丐廿卅丕亘丞鬲孬噩丨禺丿匕乇夭爻卮氐囟胤馗毓睾鼗丶亟鼐乜乩亓芈孛嗇嘏仄厙厝厴厥厮靨贋匚叵匭匱匾賾卦卣刂刈刎剄刳劌剴剌剞剡剜蒯剽劂劁劐劓冂罔亻仃仉仂仨仡仫仞傴仳伢佤仵倀傖伉佇佞佧攸佚佝8佟佗伲伽佶佴侑侉侃侏佾佻儕佼儂侔儔儼儷俅俚俣俜俑俟俸倩偌俳倬倏倮倭俾倜倌倥倨僨偃偕偈偎偬僂儻儐儺傺僖儆僭僬僦僮儇儋仝氽佘僉俎龠汆糴兮巽黌馘囅夔勹匍訇匐鳬夙兕亠兖亳衮袤褻臠裒禀嬴蠃羸冫冱冽冼凇冖冢冥訁訐訌訕謳詎訥詁訶詆詔詘詒誆誄詿詰詼詵詬詮諍諢詡誚誥誑誒諏諑諉諛諗諂誶諶諫謔謁諤諭諼諳諦諮諞謨讜謖謚謐謫謭譖譙譎讞譫讖卩卺阝阢阡阱阪阽阼陂陘陔陟隉陬陲陴隈隍隗隰邗邛鄺邙鄔邡邴邳邶鄴@邸邰郟郅邾鄶郄郇鄆酈郢郜郗郛郫郯郾鄄鄢鄞鄣鄱鄯鄹酃酆芻奐勱劬劭劾哿勐勖勰叟燮矍廴凵凼鬯厶弁畚巰坌堊垡塾墼壅壑圩圬圪圳壙圮圯壢圻坂坩壠坫壚坼坻坨坭坶坳埡垤垌塏埏垧堖垓垠埕塒堝塤埒垸埴埯埸埤埝ĺ堋堍埽埭堀堞堙塄堠塥塬墁墉墚墀馨鼙懿艹艽艿芏芊芨芄芎芑薌芙芫蕓芾芰藶苊苣芘芷芮莧萇蓯芩芴芡芪芟苄苧芤苡茉苷苤蘢茇苜苴苒苘茌苻苓蔦茚茆塋煢苠苕茜荑蕘蓽茈莒茼茴茱莛蕎茯荏荇荃薈荀茗薺茭茺茳犖滎H蕁茛藎蕒蓀葒葤莰荸蒔萵莠莪莓莜莅荼薟莩荽蕕荻莘莞莨鶯蒓菁萁菥菘堇萘萋菝菽菖萜萸萑萆菔菟萏萃菸菹菪菅菀縈菰菡葜葑葚葙葳蕆蒈葺蕢葸萼葆葩葶蔞蒎萱葭蓁蓍蓐驀蒽蓓蓊蒿蒺蘺蒡蒹蒴蒗鎣蕷蔌甍蔸蓰蘞蔟藺̽蕖蔻蓿蓼蕙蕈蕨蕤蕞蕺瞢蕃蘄蕻薤薨薇薏蕹藪薜薅薹薷薰蘚藁藜藿蘧蘅蘩蘖蘼廾弈夼奩耷奕奚奘匏尢尥尬尷扌捫摶抻拊拚拗拮撟拶挹捋捃掭揶捱捺掎摑捭掬掊捩掮摜揲揸揠撳揄揞揎摒揆掾攄摁搋搛搠搌搦搡摞攖摭撖P摺擷擼撙攛擀擐擗擤擢攉攥攮弋忒甙弑卟叱嘰叩叨叻吒吖吆呋嘸囈呔嚦呃吡唄咼吣吲咂咔呷呱呤咚嚀咄呶呦噝哐咭哂咴噠咧咦嘵嗶呲咣噦咻咿哌噲哚嚌咩咪咤噥哏哞嘜哧嘮哽唔哳嗩唣唏唑唧唪嘖喏喵啉囀啁啕唿啐唼唷啖啵啶啷唳唰啜喋嗒喃喱喹喈喁喟啾嗖喑啻嗟嘍嚳喔喙嗪嗷嗉嘟嗑囁嗬嗔嗦嗝嗄嗯嗥嗲噯嗌嗍嗨嗵嗤轡嘞嘈嘌嘁嚶嘣嗾嘀嘧嘭噘嘹噗嘬噍噢噙嚕噌噔嚆噤噱噫噻噼嚅嚓嚯囔囗囝囡圇囫囹囿圄圊圉圜幃帙帔帑幬幘幗X帷幄幔幛幞幡岌屺岍岐嶇岈峴岙岑嵐岜岵岢崬岬岫岱岣峁岷嶧峒嶠峋崢嶗崍崧崦崮崤崞崆崛嶸崾崴崽嵬嵛嵯嶁嵫嵋嵊嵩嵴嶂嶙嶝豳嶷巔彳彷徂徇徉后徠徙徜徨徭徵徼衢彡犭犰犴獷獁狃狁狎狍狒狨獪狩猻狴狷猁狳獫狺狻猗猓玀猊猞猝獼猢猹猥猬猸猱獐獍獗獠獬獯獾舛夥飧夤夂飠餳飩餼飪飫飭飴餉餑余餛餷餿饃饈饉饊饌饢庀廡庋庖庥庠庹庵庾庳賡廒廑廛廨廪膺忄忉忖懺憮忮慪忡忤愾悵愴忪忭忸怙怵怦怛怏怍怩怫怊懌怡慟懨惻愷恂`恪惲悖悚慳悝悃悒悌悛愜悻悱惝惘惆惚悴愠憒愕愣惴愀愎愫慊慵憬憔憧憷懔懵忝隳閂閆闈閎閔閌闥閭閫鬮閬閾閶鬩閿閽閼闃闋闔闐闕闞丬爿戕氵汔汜汊灃沅沐沔沌汨汩汴汶沆潙泐泔沭瀧瀘泱泗沲泠泖濼泫泮沱泓泯涇洹洧洌浹湞洇洄洙洎洫澮洮洵洚瀏滸潯洳涑浯淶潿浞涓涔浜浠浼浣渚淇淅淞瀆涿淠澠淦淝淙瀋涫渌涮渫湮湎湫溲湟溆湓湔渲渥湄灧溱溘灄漭瀅溥溧溽溻溷潷溴滏溏滂溟潢瀠瀟漤漕滹漯漶瀲潴漪漉漩澉澍澌潸潲潼潺瀨h濉澧澹澶濂濡濮濞濠濯瀚瀣瀛瀹瀵灝灞宀宄宕宓宥宸甯騫搴寤寮褰寰蹇謇辶迓迕迥迮迤邇迦逕迨逅逄逋邐逑逍逖逡逵逶逭逯遄遑遒遐遨遘遢遛暹遴遽邂邈邃邋彐彗彖彘尻咫屐屙孱屣屨羼弳弩弭艴弼鬻屮妁妃妍嫵嫗妣妗姊嬀妞妤姒妲妯姗妾婭嬈姝孌姣姘姹娌娉媧嫻娑娣娓婀婧婊婕娼婢嬋胬媪媛婷婺媾嫫媲嬡嬪媸嫠嫣嬙嫖嫦嫘嫜嬉嬗嬖嬲嬷孀尕尜孚孥孳孑孓孢駔駟駙騶驛駑駘驍驊駢驪騏騍騅驂騭騖驁騮騸驃驄驏驥驤糹紆紂紇紈纊p紜紕紓紺紲紱縐紼絀紿絝絎絳綆綃綈綾綺緋緔緄綞綬綹綣綰緇緙緗緹緲繢緦緶緱縋緡縉縝縟縞縭縊縑繽縹縵縲繆繅纈繚繒繮繾繰繯纘幺畿巛甾邕玎璣瑋玢玟珏珂瓏玷玳珀珉珈珥珙頊琊珩珧珞璽琿璉琪瑛琦琥琨琰琮琬琛琚瑁瑜瑗瑕瑙璦瑭瑾璜瓔璀璁璇璋璞璨璩璐璧瓚璺韙韞韜杌杓杞杈榪櫪枇杪杳枘梘杵棖樅梟枋杷杼柰櫛柘櫳柩枰櫨柙枵柚枳柝栀柃枸柢櫟柁檉栲栳椏橈桎楨桄榿梃栝桕樺桁檜桀欒桊桉栩梵梏桴桷梓桫欞楮棼櫝槧棹x欏棰椋椁楗棣椐楱椹楠楂楝欖楫榀榘楸椴槌櫬櫚槎櫸楦楣楹榛榧榻榫榭槔榱槁槊檳榕櫧榍槿檣槭樗樘橥槲橄樾檠橐橛樵檎櫓樽樨橘櫞檑檐檩檗檫猷獒殁殂殤殄殞殮殍殫殛殯殪軔軛軲軻轤軹軼軫軤轢軺軾輊輇輅輒輦輞輟輜輳轆轔軎戔戧戛戟戢戡戥戤戩臧甌瓴瓿甏甑甓攴旮旯旰昊曇杲昃昕昀炅曷昝昴昱昶昵耆晟曄晁晏暉晡晗晷暄暌曖暝暾曛曜曦曩賁貰貺貽贄貲賅贐賑賚賕賫賧賻覘覬覡覿覦覯覲覷牮犟牝牦牯牾牿犄犋犍犏犒挈挲掰搿擘耄毪毳毽毿毹氅氌氆氍氕氘氙氚氡氬氤氪氲攵敕敫牘牒牖爰虢刖肟肜肓肼朊肽肱肫肭肴肷朧腖胩臚胛胂胄胙胍胗朐胝脛胱胴胭膾脎胲胼朕脒豚腡脞脬脘脲腈腌腓腴腙腚腱腠腩腼腽腭腧塍媵膈膂臏滕膣膪臌朦臊膻臁膦歟欷欹歃歆歙颮颯颶颼飆飈殳彀轂觳斐齏斕於旆旄旃旌旎旒旖煬煒炖熗炻烀炷炫炱燁烊焐焓燜焯焱煳煜煨煅煲煊煸煺熘熳熵熨熠燠燔燧燹爝爨灬燾煦熹戾戽扃扈扉礻祀祆祉祛祜祓祚禰祗祠禎祧祺禪禊禚禧禳忑忐懟恝恚恧恁恙恣慤愆愍慝憩憝懋懣戇肀聿沓澩淼磯矸碭砉硨砘砑斫砭碸砝砹礪礱砟砼砥砬砣砩硎硭硤磽砦硐硇硌硪磧碓碚碇磣碡碣碲碹碥磔磙磉磬磲礅磴礓礤礞礴龕黹黻黼盱眄瞘盹眇眈眚眢眙眭眦眵眸睞瞼睇睃睚睨 睢睥睿瞍睽瞀瞌瞑瞟瞠瞰瞵瞽町畀畎畋畈畛畲畹疃罘罡罟詈罨羆罱罹羈罾盍盥蠲釒釓釔釙釗釕釷釧釤鍆釵釹鈈鈦鉅鈑鈐鈁鈧鈄鈥鈀鈺鉦鈷鈳鉕鈽鈸鉞鉬鉭鈿鑠鈰鉉鉈鉍鈮鈹鐸銬銠鉺銪鋮鋏鐃鋣鐺銱銦鎧銖鋌銩鏵銓鉿鎩銚錚銫銃鐋銨銣鐒錸鋱鏗鋥鋰鋯鋨銼鋝鋶鐦鐧鋃鋟鋦錒錆鍩錛鍀錁錕錮鍃錇錈錟錙鍥鍇鍶鍔鍤鎪鍰鎄鏤鏘鐨鎇鏌鎘鎸鎿鎦鎰鎵鑌鏢鏜鏝鏍鏞鏃鏇鏑鐔鐝鏷鑥鐓鑭鐠鑹鏹鐙鑊鐲鐿鑔鑣鍾矧矬雉秕秭秣秫稆嵇稃稂稞稔稹稷穡黏馥穰皈皎皓皙皤瓞瓠甬鳩鳶鴇鴆鴣鶇鸕鴝鴟鷥鴯鷙鴰鵂鸞鵓鸝鵠鵒鷳鵜鵡鶓鵪鵯鶉鶘鶚鷀鶥鶩鷂鶼鸚鷓鷚鷯鷦鷲鷸鸌鷺鸛疒疔癤癘疝癧疣疳疴疸痄疱疰痃痂瘂痍痣癆痦痤癇痧瘃痱痼痿瘐瘀癉瘌瘞瘊瘥瘻瘕瘙瘛瘼瘢瘠癀瘭瘰癭瘵癃癮瘳癍癩癔癜癖癲癯翊竦穸穹窀窆窈窕竇窠窬窨窶窳衤衩衲衽衿袂袢襠袷袼裉褳裎襝襇裱褚裼裨裾裰褡褙褓褸褊襤褫褶襁襦襻疋胥皸皴矜耒耔耖耜耠耮耥耦耬耩耨耱耋耵聃聆聹聒聵聱覃頇頎頏頡頜潁頦頷顎顓顳顢顙顥顬顰虍虔虬蟣蠆虺虼虻蚨蚍蚋蜆蚝蚧蚣蚪蚓蚩蚶蛄蚵蠣蚰蚺蚱蚯蛉蟶蚴蛩蛺蟯蛭螄蛐蜓蛞蠐蛟蛘蛑蜃蜇蛸蜈蜊蜍蜉蜣蜻蜞蜥蜮蜚蜾蟈蜴蜱蜩蜷蜿螂蜢蝽蠑蝻蝠蝰蝌蝮螋蝓蝣螻蝤蝙蝥螓螯蟎蟒蟆螈螅螭螗螃螫蟥螬螵螳蟋蟓螽蟑蟀蟊蟛蟪蟠蟮蠖蠓蟾蠊蠛蠡蠹蠼缶罌罄罅舐竺竽笈篤笄筧笊笫笏筇笸笪笙笮笱笠笥笤笳籩笞筘篳筅筵筌箏筠筮筻筢筲筱箐簀篋箸箬箝籜箅簞箜箢簫箴簣篁篌篝篚篥篦篪簌篾篼簏籪簋$簟簪簦簸籟籀臾舁舂舄臬衄舡舢艤舭舯舨舫舸艫舳舴舾艄艉艋艏艚艟艨衾裊袈裘裟襞羝羥羧羯羰羲籼敉粑糲糶粞粢粲粼粽糝糇糌糍糈糅糗糨艮暨羿翎翕翥翡翦翩翮翳糸縶綦綮繇纛麩麴赳趄趔趑趲赧赭豇豉酊酐酎酏酤酢酡酰酩酯釅釃酲酴酹醌醅醐醍醑醢醣醪醭醮醯醵醴醺豕鹺躉跫踅蹙蹩趵趿趼趺蹌跖跗跚躒跎跏跛跆跬蹺蹕跣躚躋跤踉跽踔踝踟躓踮踣躑踺蹀踹踵踽踱蹉蹁蹂躡蹣蹊蹰蹶蹼蹯蹴躅躪躔躐躦躞豸貂貊貅貘貔斛觖觴觚觜,觥觫觶訾謦靚雩靂雯霆霽霈霏霎霪靄霰霾齔齟齙齠齜齦齬齪齷黽黿鼉隹隼隽雎雒瞿讎銎鑾鋈鏨鍪鏊鎏鐾鑫魷魴鮁鮃鮎鱸穌鮒鱟鮐鮭鮚鮪鮞鱭鮫鮝鱘鯁鱺鰱鰹鰣鰷鯀鯊鯇鯽鯖鯪鯫鯡鯤鯧鯝鯢鯰鯛鯴鯔鱝鰈鰐鰍鰒鰉鯿鰠鰲鰭鰨鰥鰩鰳鰾鱈鰻鰵鱅鱖鱔鱒鱧靼鞅韃鞽鞔韉鞫鞣鞲鞴骱骰骷鶻骶骺骼髁髀髏髂髖髕髑魅魃魘魎魈魍魑饗饜餮饕饔髟髡髦髯髫髻髭髹鬈鬏鬢鬟鬣么麾縻麂麇麈麋麒鏖麝麟黛黜黝黠黟黢黷黧黥黲黯鼢鼬鼯鼹鼷鼽鼾齄4襬闆錶彆蔔纔厂冲丑齣噹党淀鼕斗噁髮范丰複干穀颳广閤鬍划迴彙穫飢几傢价荐薑儘据捲剋夸睏蜡腊纍里曆帘瞭鹵囉黴濛懞矇瀰麵衊闢苹凭扑仆朴韆籤縴鞦麯确舍术松囌台颱檯罎涂糰万係繫鹹嚮鬚葯叶郁禦籲愿云髒症隻只緻製种硃筑准 <|0 ( 8 ${|,~4<DȈLЋT؎\dlt| (0808@ĽHPX`hpx $,4h!p " d @ `*0  l   2t t |x*   \ $  <  | "  d   (  @ * T l  < H 2  t     x4t 8L4@:  | L      B (| xX`һ آؤרاҵ˿ةɥحѾؼΪد رô֮էƹؿҲϰǬJH ءبЩؽĶͤʲ Ǫl ɡΰα٣٤  λס٢١Ӷ٦٥٬ٮ٫ʹR ٩ֶ٨٪٧ٰ٭ٯH ٴٸٵٷٹٶٱٲٳٽٺx@d@8@ ٿٻپծֵZp ټƫͣż͵ ɵ( ɮƧ l bأ Ԫȫ Ƚðڢдũڣԩڤұl ׼ڡƾ͹( ۻɾˢȯɲj| ǰʣ Ȱ۽Ŭ۾ۿ ѫļ0 ذϻƥҽr@ ʮǧئЭ׿߲ռ¬±شîӡΣȴж ѹԭȥ\ ˫ȡ߶ߵֻ̨߳ʷҶ˾̾߷ߴ8 ߺͬ߸߹˱֨z|ѽ ߻߼߽߾Ż߿ԱǺζ8 զӽҧƷ ӴŶ@` Ψ  ơɶžХι ϲ ɤHt ˻ ҭجd  ض԰ΧͼP ԲȦʥ`ַ ̮̳׹̹ƺ ¢ԫX ܤܣXܥ ܡܢǵܧܦܩ0  ܨܪܫ ܯܬ ܭĹǽܮī  ʿ׳Ҽ`  Ϧҹ̫زʧͷD  ۼŮū  ױ&8  ķʼίҦh  ¦Ȣ  Ӥ  ýϱ.  ɩp  T  Тѧث|  լʵ6  ԢįկѰx ξСҢʬβƨ ʺмչɽ > Ͽ ո Ƕ8 Fx ΡѲ ˧ʦϣ֡ϯñ Ļƽ  ׯ®ӦͥӹN  ͢إ pŪ ߮ʽ߱ǿ  ¼ͮӰ!< ͽѭ΢V! ߯־æ!( ddt|8Tt0Xxl\XP( x   <  0   |   L t  0p|h4  ̬ ŭ˼Թ! ˡϢǡ"T Ϥ^" ϧΩ"\ Ը" Ľο$#0 f#t иųܲ# Ϸս¾# ǤִɨŤ,$p ץͶ̧ĨѺn$ Ĵ׾£ӵšȭ˩ƴקʰ$ ָֿ̢ЮŲͦ$D ͱ׽4% Ҵ̽°v%8 ҾԮ%§ ɦЯ%0 ҡ̯ˤժĦġߡ<& Ʋ˺ߤײ׫ߢߣߥ~&ߦ ߧߨߪߩ&T ֧߫߬߭' ЧɢD' իбն˹ʩ'L  ּѮʱ'  ӳ (8! ɹL(! Ͼůĺ($" Իҷ(l" ˷ľδĩ)"ɱ ȨɼT),# ö֦ǹ)# ijȾ)<$ դջ˨У*$Φ ͩɣ׮Ͱ\*0% ÷е*% ɭ* & ֲ׵Ҭ"+d& Ш¥d+& եȶ+' +h' ģӣ*,' l,'̴ ϭ,(( Ƿŷ,`( ЪǸֹ2-( ѳֳŹt-( ĸÿعëձ̺-T) صåˮ-)֭͡ ϫѴ̭:.L* ɳûŽĭմ|.* йȪŢע̩Ӿк.p+ ϴǢ/ , dzŨԡB/, ͿӿɬҺ/ - /- Ԩμ0 . տʪJ0. ԴϪ0. ̲00/ Ư©Į1/ ΫDZº̶R1/ 1D0 10LT(lh<0(LD  0!!"d""$##4$$(%%&\&&&`''' (X(x((L))D**h+,|,--.x..(///<0|00 0 21 Z21 ¯Ȳ̿ը282˸ ϩ22 Ȼ 33 ɷúɿb3\3 ϨѬ33 ȼ33 צүسˬ(4$4 ƬţIJĵǣj4p4Ϭ Ȯ״44 ʨ445 èԳ055 ̡r586 õ5l6 ɺ56 86 7 ɪz67 67 ưȿƿ68 ߰˦@7\8 η78 űƣ789 ֢ӸȬʹƦ̵89 ̱ȳH8T: Ѣ8: Ƥ8(; ӯյʢĿäֱ9|; ʡüգѣP9; ˯غ9d< ϹޫƳ˲ͫհ9< ìʸ֪ʯ:,=ɰ שX:= ˶Ӳȷ:> µ̼:p> ĥ;> ʾ`;,? ףƱ;d? »خ;?˽ ͺ&<@ϡ ˰h<@ Ѩ<@ͻ խҤ<(A վͯ.=A Цp=A Ͳɸǩ=dB =B ׭ƪ¨6>@C x>C >C ճ>D Ŵϵ>?lD ?D ?D @E F@E @0E ԼγɴֽŦ@HEϸ֯ Ѥͳά AE׺ ԵӧȱNAF AG ǼȺA$H BH1022 3T3334h44,5506d66777 8T88099L:: ;t;;\<<$==>h>>$?\??@@@ AAA\BB8CCCCdDDDDEx(E@EEFGH|HH Hҫ ˣҮVBI ְƸBJ Ф֫BJвθ ̥ʤطCxK ֬ŧƢ^C L ҸǻCL ĤϥC Mӷ $D`MҨ ˴fDM ͧɫܴܳܵDPN ܹܷܻܺܶâܼ֥ܽ«ܸܾоܿѿDN έԷ̦ɻӢƻ,ETO ïéݢãnEO ӫݡݣݥݤݦݧҩݩݶݱݴEP ݰɯݮݷݯݸݬݹݳݭĪݨݪݫݲݵӨݺݻçE Qݼ ݿݾ4FQ ݽƼήөӪvF R FtR FR ޤޣ?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHI  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTTTTTTTTTTT  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWWWWWWWW  !"#$%&'()*+,-./01  !"""""""""""""""#$%&'()*+,-./0123456789:;<=>?@ABC"""""""""""""  !"#$%&'()*+,-./0123456789:;<=>?@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLM  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZZZZZ  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRS    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTU        !"#$%&'(   !"#$%&'()*+,-./012             !"#$%&'()*+,-./0123456789:;<=>?@       !"#$%&'()*+,-./01234  !"#$%&'()*+,-./01234567888898888  !"#$%&    !"#$%&'()*+,-     !"#$%         ! " #$ %&' ( ) *   !    !"#                                  !"#$    !         !"#$%               !"#$%&'(          !"#$%&'()*  !"#$%&'()*+,      !"#$   !"#$%&'(                                 !                                                        !"#$%&'()                                                    !"     !                           !"      !"#$%&'()*+,         !                                                      !                                                           !        !"#$%   !"#$                                                                                                                          !"                                    !                                                                !"#$%&'()*+,-./0123456789:;<=    !"#$%&'()*+,-./012345 6 7                 !"#$           !"#$%    !"#$%&'                !"#$       !"#$%&   !"#    !"#    !"#$                                                                                        !"#$%&'()*+,-./0123456789:;<=>   !"#$%&'()*+,-./01234567      !"#  !"#$%&'()*+,                     !"#$%&'   !"#$  !"#$%&'()*+,-./0123,456789:;,<=>    !"#$%                  !"#$%&       !"#$%&'()*+,-./0123456789  !"#$%&'()*+,-./0123456789:  !"#$%&'()*+,-./0123456789:;<   !"#$%&'()*+,-./0   !"#$%&'()*                             !"#             !"#$%&'()               !"#$%&'()*+,-.    !"#$%&                  !"#$% &'()* +,- ./01234                !"#$        !                              !                            !"#         !"#$  !"#$%&'         !"                  !"    !"                                                                                !                                                                                      !        !"#                                                                                                                                              !"                                                                                                                                                                                                                                                             !"                                     !"#                  !           !"#         !"                                                                                                                                                     !"                                        !"#  !"#$            !"                                                                                                                                                                              !"#$%&'()*+,-./0123456789:;<; 4K<dKdDL|zRx $J0FJ w?:*3$"DJ \K<HoGNUP "4zyy 0 ""o`  "0( oooo"`pGA$3a10 GA$3p1067`GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realignchinese.so-2.2.10-35.el8.x86_64.debugc37zXZִF!t/]?Eh=ڊ2NH:^ 7,X\*u Kk ԘCP.cKD.였$hyXבD2E?D1j+(֜0%i,Q5B0?>xR+"+U]/`/bQ6'{̡v +Z`]?tFs w56s+qcؽ>- ' L2-<k,Pp0`X̣bO)V|r-36XGF[f~1w}hkSSzo&*g뤷{r+^ݿsYY(U3\-B>>dڽ`%U5ԳBKv(oH]:IXս }̮-K P\F{ZU*A ^̽Ih@V,:7ޯID6'JVƒ(˶˳V8X}|h94jX㰪C= 6]Ҷ(v=wS!W%ZBMa:"yOU&]Ez+x? L5Y3vznN#H !鞛U6i0ԛv[LRsi _RPk=tu7},9S%θblٟ!p*`fc~@iߩKb޷^dzzsvbS`jZ{iGTM-ht ñgYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 08oEo T(^B0h00cPP0n w} [ $@@t "" "  " " "(("(0b(  ,LD+PK!Ʌ..(2.2.0/x86_64-linux/enc/trans/utf8_mac.sonuȯELF>@H'@8 @xx PP$P$ $$  888$$XXX StdXXX Ptd444<<QtdRtdPP$P$GNU/+M\wZfn  BE|·8qX Ut , F"0 $8 $f P $0 $__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalize__stack_chk_failInit_utf8_macrb_register_transcoderlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5GLIBC_2.4/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ui ii P$pX$0`$`$$ $ $8$ $$$$ $ ($ 8$8H$ $$$$ $ $( $HH$HtH5$%$hhh%}$D%u$D%m$DH=i$Hb$H9tH$Ht H=9$H52$H)HHH?HHtH$HtfD=$u+UH=$Ht H=$Yd$]wHG1ÐW1;Wt2fHcʃHDʃ)ʉWDDW;WuÐff.@AWAVAUATUSHDGDOdH%(HD$1HH"E9u IɺAOLIcALHDDAAA)DGFT DGD;GuL@HxIHPHDEDNF DFD9v@4H\$dH3%(H[]A\A]A^A_1E9tBfIcAHD DAAA)DGDLDGDOE9uL^ELL9r fDIAqMcɉwESFAAAF AE)DOI9uDD)ƒ)&E1AAC4D)A+Hc47L%H--LmMt$IGF|A8wC84+s|1KIcAHD DAAA)DGDL1HcWIu DOE9uHmH1H9L^fID)HcE3C4LELAu+9t$B4AAADރD)Hc47t LAHΈL$LHL$uIADT$HL$HG1I@1LcHB4I9wW|@rfD@HH=$@QABCEQFGHJQKLMOQPQRTQUVWYQZ[\hnoqQrsxQч$Q$@QѲQѹ{\QZQQ+m >?A S <fgiQkmV PoQqstQшQ QѢQѩQ4 QQ T4Hl / Q \ḀḁḂḃḄḅḆḇḊḋḌḍḎḏḐḑḒḓḘḙḚḛḞḟḠḡḢḣḤḥḦḧḨḩḪḫḬḭḰḱḲḳḴḵḶḷḺḻḼḽḾḿ pṀṁṂṃṄṅṆṇṈṉṊṋ    ṔṕṖṗṘṙṚṛṞṟṠṡṢṣṪṫṬṭṮṯṰṱṲṳṴṵṶṷ!"$%ṼṽṾṿ | ẀẁẂẃẄẅẆẇẈẉẊẋẌẍẎẏẐẑẒẓẔẕẖẗẘẙ7ẠạẢả8Q:;Q=>Q@AQCDQFGQIJQLMQOPQRSQUẸẹẺẻẼẽVQX QjkQmnQpqQstỈỉỊịỌọỎỏQvwQyzQ|}QрQуQцQщQьQяQђỤụỦủQѕQјQћQўQѡỲỳỴỵỶỷỸỹg ѳQѹQQQQQQQQQQQQ Q   Q| Q%&')Q+-.0Q1346Q89:<Q>@ACQEFQHJKMQNPQSQUWXZQ[]^`QbdegQhijlQmS| рфQэёѕQўѢѦQѯѳѷQQQQQQQιH    QQQQQ !"Q$%Q'()+Q-./124Q567`9:<=?@BQC´Hht | t t @@ HeQgijlQnpqsQuwxzQ|~QцQэTXѡQѨQѯQEQQQQQQ hpQQQ Q QQQQ!#Q&(Q+-Q02Q57Q:<Q?ACFHKMPRUWZ\_adfiknpsuxz}шQэQђQї QќQѡQѦQѫQѰQѵQѺQѿQQQ  QQQQ"$Q')Q,.Q13Q6 8Q;=Q@BQEGQJLQOQQTVX[]`begjloqtvy{~ѝQѢQѧQѬQѱQѶQѻQQQQQ QQQ  !$&Q(*Q-/Q24Q79Q<>QACQFHQKMQPRQUWQZ\Q_aQdfQikmpr uwz|ѲQѷQѼQQQQQQQQQQQQ            " % ' * , / 1 4 6 9 ; Q= ? QB D QG I QL N QQ S QV X Q[ ] Q` b Qe g Qj l Qo q Qt v Qy { Q~ р               Q Q Q Q Q Q Q Q Q Q Q Q  Q  Q         ! # & ( + - 0 2 5 7 : < ? A D F I K N P QR T QW Y Q\ ^ Qa c Qf h Qk m Qp r Qu w Qz | Q с Q ц Q ы Q ѐ Q ѕ               Q Q Q Q Q Q Q Q  Q Q  Q  Q  Q  Q " $ ' ) , . 1 3 6 8 ; = @ B E G J L O Q T V Y [ ^ ` c e Qg i Ql n Qq s Qv x Q{ } Q т Q ч Q ь Q ё Q і Q ћ Q Ѡ Q ѥ Q Ѫ               Q Q Q Q  Q Q  Q  Q  Q  Q! # Q& ( Q+ - Q0 2 Q5 7 9 < > A C F H K M P R U W Z \ _ a d f i k n p s u x z Q| ~ Q у Q ш Q э Q ђ Q ї Q ќ Q ѡ Q Ѧ Q ѫ Q Ѱ Q ѵ Q Ѻ Q ѿ                 Q Q  Q  Q  Q  Q" $ Q' ) Q, . Q1 3 Q6 8 Q; = Q@ B QE G QJ L N Q S V X [ ] ` b e g j l o q t v y { ~    Q ѓ Q ј Q ѝ Q Ѣ Q ѧ Q Ѭ Q ѱ Q Ѷ Q ѻ Q Q Q Q Q            Q Q#%Q(*Q-/Q24Q79Q<>QACQFHQKMQPRQUWQZ\Q_acfhkmpruwz| (QѨQѭQѲQѷQѼQQQQQQQQQ   "%'*,/0Q35Q8:Q=? 4 QBDQGIQLNQQSQVXQ[]Q`bQegQjlQoqQtvx{}QѽQQQQQQQ @! , 8!D"?L"QQQQQQ  Q "%'*,/1469;>@CEHJMORTQVXQ[]Q`bQegQjlQoqQtvQy{Q~рQхQъQ "яQєQљQQQQQQQQQ  QQQQ!Q$&(+ #-0257:<?ADFIKNPSUXZ]_bdgiQkmQprQuwQz|QсQцQыQѐQѕQњQџQѤQѩQѮ $QQQQ Q QQQQ "Q%'Q*,Q/1Q46Q9;=@BEGJLOQTVY[^`ceh %jmortwy|~QтQчQьQёQіQћQѠQѥQѪQѯQѴQѹQѾQ &  Q QQQQ!#Q&(Q+-Q02Q57Q:<Q?AQDFQIKQNPRUWZ\_adfiknpsuxz}QїQќQѡQ 'ѦQѫQѰQѵQѺQѿQQQQQ  Q"$Q')Q,.Q13Q68Q;=Q@B (QEGQJLQOQQTVQY[Q^`Qcegjloqtvy{~QѬQѱQѶQѻQQQQQQQQ )QQ  !$&)+.034Q79Q<>QACQFHQKMQPRQUWQZ\Q_aQdfQikQnpQsuQxz| *QQQQQQQQQQQQQQ   , "%'*,/1469;>@CEHIQLNQQSQVXQ[]Q`bQegQjlQoqQtvQy{Q~рQхQъQ -QQQQQQQQQQQQ  QQ!#&(+-0257:<?ADFIKNPSUXZ .]^QacQfhQkmQprQuwQz|QсQцQыQѐQѕQњQџQQQQQ ,/QQQ Q QQQQ "Q%'Q*,.1368;=@BEGJLOQTVY[^`cehjmorsQvxQ{}QтQчQьQёQі 80QћQѠQѥQѪQѯQѴQQQQ Q QQQQ!#Q&(Q+-Q02Q5 D17Q:<Q?ACFHKMPRUWZ\_adfiknpsuxz}шQэQђQїQќQѡQѦQѫQѰQѵQѺQѿQQQ P2  QQQQ"$Q')Q,.Q13Q68Q;=Q@BQEGQJLQOQQTVX[]`begjloq \3tvy{~ѝQѢQѧQѬQѱQѶQѻQQQQQQQQ   h4!$&Q(*Q-/Q24Q79Q<>QACQFHQKMQPRQUWQZ\Q_aQdfQikmpruwz| t5ѲQѷQѼQQQQQQQQQQQQ   "%'*,/1469;Q=?QBDQGIQL 6NQQSQVXQ[]Q`bQegQjlQoqQtvQy{Q~рQQQQQQQ 7QQQQQQQ  !#&(+-0257:<?ADFIKNPQRTQWYQ\^QacQfhQkmQprQuwQz|QсQцQ 8ыQѐQѕQQQQQQQQQ Q QQQQ "$' 9),.1368;=@BEGJLOQTVY[^`ceQgiQlnQqsQvxQ{}QтQчQьQёQіQћQѠQѥQѪ :QQQQQ Q QQQQ!#Q&(Q+-Q02Q579<>ACFHKMPRUWZ\_ad ;fiknpsuxzQ|~QуQшQэQђQїQќQѡQѦQѫQѰQѵQѺQѿ  <  Q Q  Q  Q  Q  Q" $ Q' ) Q, . Q1 3 Q6 8 Q; = Q@ B QE G QJ L N Q S V X [ ] ` b e g j l o q t v y { ~    Q ѓ Q ј Q ѝ Q =Ѣ Q ѧ Q Ѭ Q ѱ Q Ѷ Q ѻ Q Q Q Q Q         !!!! ! !!!!!!!Q! !Q#!%!Q(!*!Q-!/!Q2!4!Q7!9!Q! >QA!C!QF!H!QK!M!QP!R!QU!W!QZ!\!Q_!a!c!f!h!k!m!p!r!u!w!z!|!!!!!!!!!!!!!!!!!Q!Ѩ!Q!ѭ!Q!Ѳ!Q!ѷ!Q!Ѽ!Q!!Q!!Q!!Q!!Q!!Q!!Q! ?!Q!!Q!!!!!!!!!!!""" " """""""" """%"'"*","/"0"Q3"5"Q8":"Q="?"QB"D"QG"I"QL"N"QQ"S"QV"X"Q["]"Q`"b"Qe"g"Qj"l"Qo"q"Qt"v"x"{" @}"""""""""""""""""""""""""Q"ѽ"Q""Q""Q""Q""Q""Q""Q""Q""Q""Q""Q""Q""Q""#### # ###### B##!###&#(#+#-#0#2#5#7#:#<#?#A#D#E#QH#J#QM#O#QR#T#QW#Y#Q\#^#Qa#c#Qf#h#Qk#m#Qp#r#Qu#w#Qz#|#Q#с#Q#ц#Q#################### C#########Q##Q##Q##Q##Q##Q##Q##Q##Q##Q##Q$$Q$ $Q $$Q$$$$$$$"$$$'$)$,$.$1$3$6$8$;$=$@$B$E$G$J$L$O$Q$T$V$ DY$Z$Q]$_$Qb$d$Qg$i$Ql$n$Qq$s$Qv$x$Q{$}$Q$т$Q$ч$Q$ь$Q$ё$Q$і$Q$ћ$Q$$$$$$$$$$$$$$$$$$$$$$$$$$$$$Q$$Q$$Q$$Q$ (E$Q$$Q$%Q%%Q% %Q %%Q%%Q%%Q%%Q!%#%Q&%(%*%-%/%2%4%7%9%<%>%A%C%F%H%K%M%P%R%U%W%Z%\%_%a%d%f%i%k%n%o%Qr%t%Qw%y%Q|%~%Q%у%Q%ш%Q%э%Q%ђ% 4FQ%ї%Q%ќ%Q%ѡ%Q%Ѧ%Q%ѫ%Q%Ѱ%Q%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Q%%Q%&Q&&Q & &Q&&Q&&Q&&Q&&Q"&$&Q'&)&Q,&.&Q1& @G3&Q6&8&Q;&=&?&B&D&G&I&L&N&Q&S&V&X&[&]&`&b&e&g&j&l&o&q&t&v&y&{&~&&&ф&Q&щ&Q&ю&Q&ѓ&Q&ј&Q&ѝ&Q&Ѣ&Q&ѧ&Q&Ѭ&Q&ѱ&Q&Ѷ&Q&ѻ&Q&&Q&&Q&&&& LH&&&&&&&&&&&&&&&&&&&'''' ' 'Q''Q''Q''Q' 'Q#'%'Q('*'Q-'/'Q2'4'Q7'9'Q<'>'QA'C'QF'H'QK'M'QP'R'T'W'Y'\'^'a'c'f'h'k'm' XIp'r'u'w'z'|''''''''''''љ'Q'ў'Q'ѣ'Q'Ѩ'Q'ѭ'Q'Ѳ'Q'ѷ'Q'Ѽ'Q''Q''Q''Q''Q''Q''Q'''''''''''''''((( ( ( dJ((((((( ("(Q$(&(Q)(+(Q.(0(Q3(5(Q8(:(Q=(?(QB(D(QG(I(QL(N(QQ(S(QV(X(Q[(](Q`(b(Qe(g(i(l(n(q(s(v(x({(}((((((((((((((((((( pK(Ѯ(Q(ѳ(Q(Ѹ(Q(ѽ(Q((Q((Q((Q((Q((Q((Q((Q((Q((Q((Q(((((()))) ) ))))))))!)#)&)()+)-)0)2)5)7)Q9);)Q>)@)QC)E)QH) |LJ)QM)O)QR)T)QW)Y)Q\)^)Qa)c)Qf)h)Qk)m)Qp)r)Qu)w)Qz)|)~)))))))))))))))))))))))))))))Q))Q))Q))Q))Q))Q))Q)) MQ))Q))Q))Q))Q))Q**Q* * *********"*$*'*)*,*.*1*3*6*8*;*=*@*B*E*G*J*L*QN*P*QS*U*QX*Z*Q]*_*Qb*d*Qg*i*Ql*n*Qq*s*Qv*x*Q{*}*Q*т*Q* Nч*Q*ь*Q*ё******************************Q**Q**Q**Q**Q**Q**Q**Q*+Q++Q+ +Q ++Q++Q++Q++ +#+ O%+(+*+-+/+2+4+7+9+<+>+A+C+F+H+K+M+P+R+U+W+Z+\+_+a+Qc+e+Qh+j+Qm+o+Qr+t+Qw+y+Q|+~+Q+у+Q+ш+Q+э+Q+ђ+Q+ї+Q+ќ+Q+ѡ+Q+Ѧ++++++++++++ P++++++++++++++++++Q++Q++Q++Q+,Q,,Q , ,Q,,Q,,Q,,Q,,Q",$,Q',),Q,,.,Q1,3,5,8,:,=,?,B,D,G,I,L,N,Q,S,V,X,[,],`, Qb,e,g,j,l,o,q,t,v,Qx,z,Q},,Q,ф,Q,щ,Q,ю,Q,ѓ,Q,ј,Q,ѝ,Q,Ѣ,Q,ѧ,Q,Ѭ,Q,ѱ,Q,Ѷ,Q,ѻ,,,,,,,,,,,,,,,,,,,,,,,,,,,, R--Q--Q - -Q--Q--Q--Q- -Q#-%-Q(-*-Q--/-Q2-4-Q7-9-Q<->-QA-C-QF-H-J-M-O-R-T-W-Y-\-^-a-c-f-h-k-m-p-r-u-w-z-|-------Q-я-Q-є-Q-љ-Q- Sў-Q-ѣ-Q-Ѩ-Q-ѭ-Q-Ѳ-Q-ѷ-Q-Ѽ-Q--Q--Q--Q---------------------... . ......Q..Q.!.Q$.&.Q).+.Q..0.Q3.5.Q8.:. TQ=.?.QB.D.QG.I.QL.N.QQ.S.QV.X.Q[.]._.b.d.g.i.l.n.q.s.v.x.{.}...............Q.Ѥ.Q.ѩ.Q.Ѯ.Q.ѳ.Q.Ѹ.Q.ѽ.Q..Q..Q..Q..Q..Q. U.Q..Q............//// / ////////!/#/&/(/+/,/Q//1/Q4/6/Q9/;/Q>/@/QC/E/QH/J/QM/O/QR/T/QW/Y/Q\/^/Qa/c/Qf/h/Qk/m/Qp/r/t/w/ Vy/|/~///////////////////////Q/ѹ/Q/Ѿ/Q//Q//Q//Q//Q//Q//Q//Q//Q//Q//Q//Q////000 0 00000 X0000"0$0'0)0,0.010306080;0=0@0A0QD0F0QI0K0QN0P0QS0U0QX0Z0Q]0_0Qb0d0Qg0i0Ql0n0Qq0s0Qv0x0Q{0}0Q0т0Q00000000000000000000 Y000000000Q00Q00Q00Q00Q00Q00Q00Q00Q00Q00Q01Q11Q1 1Q 11111111 1#1%1(1*1-1/121417191<1>1A1C1F1H1K1M1P1R1 ZU1V1QY1[1Q^1`1Qc1e1Qh1j1Qm1o1Qr1t1Qw1y1Q|1~1Q1у1Q1ш1Q1э1Q1ђ1Q1ї1Q11111111111111111111111111111Q11Q11Q11Q1 $[1Q11Q11Q12Q22Q 2 2Q22Q22Q22Q22Q"2$2&2)2+2.202325282:2=2?2B2D2G2I2L2N2Q2S2V2X2[2]2`2b2e2g2j2k2Qn2p2Qs2u2Qx2z2Q}22Q2ф2Q2щ2Q2ю2 0\Q2ѓ2Q2ј2Q2ѝ2Q2Ѣ2Q2ѧ2Q2Ѭ2Q22222222222222222222222222222Q22Q22Q33Q33Q 3 3Q33Q33Q33Q3 3Q#3%3Q(3*3Q-3 <]/3Q2343Q7393;3>3@3C3E3H3J3M3O3R3T3W3Y3\3^3a3c3f3h3k3m3p3r3u3w3z3|33р3Q3х3Q3ъ3Q3я3Q3є3Q3љ3Q3ў3Q3ѣ3Q3Ѩ3Q3ѭ3Q3Ѳ3Q3ѷ3Q3Ѽ3Q33Q3333 H^333333333333333333333444 4Q 4 4Q44Q44Q44Q4!4Q$4&4Q)4+4Q.404Q3454Q84:4Q=4?4QB4D4QG4I4QL4N4P4S4U4X4Z4]4_4b4d4g4i4 T_l4n4q4s4v4x4{4}4444444444ѕ4Q4њ4Q4џ4Q4Ѥ4Q4ѩ4Q4Ѯ4Q4ѳ4Q4Ѹ4Q4ѽ4Q44Q44Q44Q44Q44Q44444444444444445555 `` 5 55555555Q 5"5Q%5'5Q*5,5Q/515Q4565Q95;5Q>5@5QC5E5QH5J5QM5O5QR5T5QW5Y5Q\5^5Qa5c5e5h5j5m5o5r5t5w5y5|5~55555555555555555 la5Ѫ5Q5ѯ5Q5Ѵ5Q5ѹ5Q5Ѿ5Q55Q55Q55Q55Q55Q55Q55Q55Q55Q55555555666 6 666666666"6$6'6)6,6.61636Q5676Q:6<6Q?6A6QD6 xbF6QI6K6QN6P6QS6U6QX6Z6Q]6_6Qb6d6Qg6i6Ql6n6Qq6s6Qv6x6z6}666666666666666666666666666ѿ6Q66Q66Q66Q66Q66Q66Q66 cQ66Q66Q66Q66Q66Q67Q777 7 77777777 7#7%7(7*7-7/727477797<7>7A7C7F7H7QJ7L7QO7Q7QT7V7QY7[7Q^7`7Qc7e7Qh7j7Qm7o7Qr7t7Qw7y7Q|7~7Q7 d#$%&'()*, -.$/00<1H2T3`4l5x6789:;<=>?@ACD E,F8GDHPI\JhKtLMNOPQRSTUVWYZ[(\4]@^L_X`dapb|cde eу7Q7ш7Q7э777777777777777777777777777777Q77Q77Q77Q77Q77Q77Q77Q77Q78Q88Q 8 8Q88Q88Q8888 f!8$8&8)8+8.808385888:8=8?8B8D8G8I8L8N8Q8S8V8X8[8]8Q_8a8Qd8f8Qi8k8Qn8p8Qs8u8Qx8z8Q}88Q8ф8Q8щ8Q8ю8Q8ѓ8Q8ј8Q8ѝ8Q8Ѣ888888888888 g888888888888888888Q88Q88Q88Q88Q99Q99Q 9 9Q99Q99Q99Q9 9Q#9%9Q(9*9Q-9/919496999;9>9@9C9E9H9J9M9O9R9T9W9Y9\9 h^9a9c9f9h9k9m9p9r9Qt9v9Qy9{9Q~9р9Q9х9Q9ъ9Q9я9Q9є9Q9љ9Q9ў9Q9ѣ9Q9Ѩ9Q9ѭ9Q9Ѳ9Q9ѷ9999999999999999999999999999 i99Q::Q::Q : :Q::Q::Q::Q:!:Q$:&:Q):+:Q.:0:Q3:5:Q8:::Q=:?:QB:D:F:I:K:N:P:S:U:X:Z:]:_:b:d:g:i:l:n:q:s:v:x:{:}:::::Q:ы:Q:ѐ:Q:ѕ:Q: jњ:Q:џ:Q:Ѥ:Q:ѩ:Q:Ѯ:Q:ѳ:Q:Ѹ:Q:ѽ:Q::Q::Q::::::::::::::::::::::;;;; ; ;;;;Q;;Q;;Q ;";Q%;';Q*;,;Q/;1;Q4;6; kQ9;;;Q>;@;QC;E;QH;J;QM;O;QR;T;QW;Y;[;^;`;c;e;h;j;m;o;r;t;w;y;|;~;;;;;;;;;;;;;Q;Ѡ;Q;ѥ;Q;Ѫ;Q;ѯ;Q;Ѵ;Q;ѹ;Q;Ѿ;Q;;Q;;Q;;Q;;Q; l;Q;;Q;;;;;;;;;;;;;;<<< < <<<<<<<<<"<$<'<(<Q+<-<Q0<2<Q5<7<Q:<<<Q?<A<QD<F<QI<K<QN<P<QS<U<QX<Z<Q]<_<Qb<d<Qg<i<Ql<n<p<s< mu<x<z<}<<<<<<<<<<<<<<<<<<<<<<Q<ѵ<Q<Ѻ<Q<ѿ<Q<<Q<<Q<<Q<<Q<<Q<<Q<<Q<<Q<<Q<<Q<<<<<==== = === o===== =#=%=(=*=-=/=2=4=7=9=<===Q@=B=QE=G=QJ=L=QO=Q=QT=V=QY=[=Q^=`=Qc=e=Qh=j=Qm=o=Qr=t=Qw=y=Q|=~=Q==================== p=========Q==Q==Q==Q==Q==Q==Q==Q==Q==Q==Q==Q=>Q>>Q > > >>>>>>>>!>$>&>)>+>.>0>3>5>8>:>=>?>B>D>G>I>L>N> qQ>R>QU>W>QZ>\>Q_>a>Qd>f>Qi>k>Qn>p>Qs>u>Qx>z>Q}>>Q>ф>Q>щ>Q>ю>Q>ѓ>Q>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Q>>Q>>Q>>Q> ,r>Q>>Q>>Q>>Q??Q??Q ? ?Q??Q??Q??Q? ?"?%?'?*?,?/?1?4?6?9?;?>?@?C?E?H?J?M?O?R?T?W?Y?\?^?a?c?f?g?Qj?l?Qo?q?Qt?v?Qy?{?Q~?р?Q?х?Q?ъ? 8sQ?я?Q?є?Q?љ?Q?ў?Q?ѣ?Q?Ѩ?Q?????????????????????????????Q??Q??Q??Q@@Q@@Q @ @Q@@Q@@Q@@Q@!@Q$@&@Q)@ Dt+@Q.@0@Q3@5@7@:@<@?@A@D@F@I@K@N@P@S@U@X@Z@]@_@b@d@g@i@l@n@q@s@v@x@{@|@Q@с@Q@ц@Q@ы@Q@ѐ@Q@ѕ@Q@њ@Q@џ@Q@Ѥ@Q@ѩ@Q@Ѯ@Q@ѳ@Q@Ѹ@Q@ѽ@Q@@@@ Pu@@@@@@@@@@@@@@@@@@@@@@AAAQA AQ AAQAAQAAQAAQ A"AQ%A'AQ*A,AQ/A1AQ4A6AQ9A;AQ>A@AQCAEAQHAJALAOAQATAVAYA[A^A`AcAeA \vhAjAmAoArAtAwAyA|A~AAAAAAAAёAQAіAQAћAQAѠAQAѥAQAѪAQAѯAQAѴAQAѹAQAѾAQAAQAAQAAQAAQAAAAAAAAAAAAAAAAAABB hwB B BBBBBBBQBBQ!B#BQ&B(BQ+B-BQ0B2BQ5B7BQ:BE@ECEEEHEJEMEOERETEWEYEQ[E]EQ`EbEQeEgEQjElEQoEqEQtEvEQyE{EQ~EрEQEхEQEъEQEяEQEєEQEљEQEўEEEEEEEEEEEE }EEEEEEEEEEEEEEEEEEQEEQEEQEEQEEQEEQFFQFFQ F FQFFQFFQFFQF!FQ$F&FQ)F+F-F0F2F5F7F:FG@GBGEGGGJGLGOGQGTGVGYG[G^G`GcGeGhGjGmGoGrGtGwGyG|G~GGGQGчGQGьGQGёGQG ԀіGQGћGQGѠGQGѥGQGѪGQGѯGQGѴGQGѹGQGѾGQGGQGGGGGGGGGGGGGGGGGGGGGGGGHHH H HHHQHHQHHQHHQ!H#HQ&H(HQ+H-HQ0H2H Q5H7HQ:HJQAJCJQFJHJQKJMJQPJRJQUJWJQZJ\JQ_JaJQdJfJQiJkJQnJpJQsJuJQxJzJQ}JJJJJJJJJJJJJJJJJJJJ JJJJJJJJJQJJQJJQJJQJJQJJQJJQJJQJJQJJQJJQJJQJJQKKQKK K KKKKKKKK K"K%K'K*K,K/K1K4K6K9K;K>K@KCKEKHKJK MKNKQQKSKQVKXKQ[K]KQ`KbKQeKgKQjKlKQoKqKQtKvKQyK{KQ~KрKQKхKQKъKQKяKQKKKKKKKKKKKKKKKKKKKKKKKKKKKKKQKKQKKQKKQK (KQKKQKKQKKQKKQLLQLLQ L LQLLQLLQLLL!L#L&L(L+L-L0L2L5L7L:LPQAPCPQFPHPQKPMPQPPRPQUPWPQZP\PQ_PaPQdPfPQiPkPQnPpPrPuPwPzP|PPPPPPPPPPPPPPPPPPPPPPPPѷPQPѼPQPPQPPQPPQPPQPPQPP QPPQPPQPPQPPQPPQPPQPPPQQQ Q QQQQQQQQ Q"Q%Q'Q*Q,Q/Q1Q4Q6Q9Q;Q>Q@QQBQDQQGQIQQLQNQQQQSQQVQXQQ[Q]QQ`QbQQeQgQQjQlQQoQqQQtQvQQyQ {QQ~QрQQQхQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQRRQRRQ R RQRRRR RRR!R#R&R(R+R-R0R2R5R7R:RTATCTFTHTKTMTPTRTUTWTZT\T_TaTdTfTiTkTnTpTsTuTxTzT}TTQTуTQTшTQTэTQT ЖђTQTїTQTќTQTѡTQTѦTQTѫTQTѰTQTѵTQTѺTQTѿTQTTTTTTTTTTTTTTTTTTTTTTTTTUUUU U UQUUQUUQUUQUUQ"U$UQ'U)UQ,U.U ܗQ1U3UQ6U8UQ;U=UQ@UBUQEUGUQJULUQOUQUSUVUXU[U]U`UbUeUgUjUlUoUqUtUvUyU{U~UUUUUUUUUUQUјUQUѝUQUѢUQUѧUQUѬUQUѱUQUѶUQUѻUQUUQUUQUUQU UQUUQUUUUUUUUUUUUUUUUUVVVV V VVVVVVVV VQ#V%VQ(V*VQ-V/VQ2V4VQ7V9VQVQAVCVQFVHVQKVMVQPVRVQUVWVQZV\VQ_VaVQdVfVhVkV mVpVrVuVwVzV|VVVVVVVVVVVVVVVVVVVQVѭVQVѲVQVѷVQVѼVQVVQVVQVVQVVQVVQVVQVVQVVQVVQVVVVVVVVVWWW W  WWWWWWWW W"W%W'W*W,W/W1W4W5WQ8W:WQ=W?WQBWDWQGWIWQLWNWQQWSWQVWXWQ[W]WQ`WbWQeWgWQjWlWQoWqWQtWvWQyW{W}WWWWWWWWWWWWWWWWWW WWWWWWWWWQWWQWWQWWQWWQWWQWWQWWQWWQWWQWWQWWQWWQWWQXXXX X XXXXXXXX!X#X&X(X+X-X0X2X5X7X:XZAZCZFZHZKZMZPZRZUZWZZZ\Z_ZaZdZfZiZkZnZpZsZtZQwZyZQ|Z~ZQZуZQZшZQZэZQZђZQZїZQZќZQZѡZQZѦZQZѫZQZѰZQZѵZQZZZZ HZZZZZZZZZZZZZZZZZZZZZZZZZQZ[Q[[Q [ [Q[[Q[[Q[[Q[[Q"[$[Q'[)[Q,[.[Q1[3[Q6[8[Q;[=[Q@[B[D[G[I[L[N[Q[S[V[X[[[][ T`[b[e[g[j[l[o[q[t[v[y[{[~[[[[[щ[Q[ю[Q[ѓ[Q[ј[Q[ѝ[Q[Ѣ[Q[ѧ[Q[Ѭ[Q[ѱ[Q[Ѷ[Q[ѻ[Q[[Q[[Q[[Q[[[[[[[[[[[[[[[[[[[[ `[\\\\ \ \\\Q\\Q\\Q\ \Q#\%\Q(\*\Q-\/\Q2\4\Q7\9\Q<\>\QA\C\QF\H\QK\M\QP\R\QU\W\Y\\\^\a\c\f\h\k\m\p\r\u\w\z\|\\\\\\\\\\\\\ l\ў\Q\ѣ\Q\Ѩ\Q\ѭ\Q\Ѳ\Q\ѷ\Q\Ѽ\Q\\Q\\Q\\Q\\Q\\Q\\Q\\Q\\\\\\\\\\\\\]]] ] ]]]]]]]] ]"]%]']Q)]+]Q.]0]Q3]5]Q8] x:]Q=]?]QB]D]QG]I]QL]N]QQ]S]QV]X]Q[]]]Q`]b]Qe]g]Qj]l]n]q]s]v]x]{]}]]]]]]]]]]]]]]]]]]]]]]ѳ]Q]Ѹ]Q]ѽ]Q]]Q]]Q]]Q]]Q]] Q]]Q]]Q]]Q]]Q]]Q]]Q]]]]^^^^ ^ ^^^^^^^^!^#^&^(^+^-^0^2^5^7^:^<^Q>^@^QC^E^QH^J^QM^O^QR^T^QW^Y^Q\^^^Qa^c^Qf^h^Qk^m^Qp^r^Qu^ w^Qz^|^Q^с^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^Q^^Q^^Q^^Q^^Q^^Q^^Q^^Q^^Q^^Q^^Q^^Q__Q_ _Q ____ ghijklmo pq$r0s`A`C`F`H`K`M`P` R`U`W`Z`\`_`a`d`f`Qh`j`Qm`o`Qr`t`Qw`y`Q|`~`Q`у`Q`ш`Q`э`Q`ђ`Q`ї`Q`ќ`Q`ѡ`Q`Ѧ`Q`ѫ```````````````````````````` ̬``Q``Q``Q`aQaaQ a aQaaQaaQaaQaaQ"a$aQ'a)aQ,a.aQ1a3aQ6a8a:a=a?aBaDaGaIaLaNaQaSaVaXa[a]a`abaeagajalaoaqatavaya{aQ}aaQaфaQaщaQa حюaQaѓaQaјaQaѝaQaѢaQaѧaQaѬaQaѱaQaѶaQaѻaQaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbQ b bQbbQbbQbbQb bQ#b%bQ(b*b Q-b/bQ2b4bQ7b9bQbQAbCbQFbHbQKbMbObRbTbWbYb\b^babcbfbhbkbmbpbrbubwbzb|bbbbbbbbbQbєbQbљbQbўbQbѣbQbѨbQbѭbQbѲbQbѷbQbѼbQbbQbbQb bQbbQbbbbbbbbbbbbbbbbbbbccc c ccccccccQc!cQ$c&cQ)c+cQ.c0cQ3c5cQ8c:cQ=c?cQBcDcQGcIcQLcNcQQcScQVcXcQ[c]cQ`cbcdcgc iclcncqcscvcxc{c}cccccccccccccccccQcѩcQcѮcQcѳcQcѸcQcѽcQccQccQccQccQccQccQccQccQccccccccccddd d d dddddddd!d#d&d(d+d-d0d1dQ4d6dQ9d;dQ>d@dQCdEdQHdJdQMdOdQRdTdQWdYdQ\d^dQadcdQfdhdQkdmdQpdrdQudwdyd|d~dddddddddddddddd dddddddddQdѾdQddQddQddQddQddQddQddQddQddQddQddQddQddeee e eeeeeeeee"e$e'e)e,e.e1e3e6e8e;e=e@eBe EeFeQIeKeQNePeQSeUeQXeZeQ]e_eQbedeQgeieQleneQqeseQvexeQ{e}eQeтeQeчeQeeeeeeeeeeeeeeeeeeeeeeeeeeeeeQeeQeeQeeQe ,eQeeQeeQeeQeeQeeQefQffQf fQ ffQffffff f#f%f(f*f-f/f2f4f7f9ffAfCfFfHfKfMfPfRfUfWfZf[fQ^f`fQcfefQhfjfQmfofQrftfQwfyfQ|f~f 8QfуfQfшfQfэfQfђfQfїfQfќfQfffffffffffffffffffffffffffffQffQffQffQffQffQfgQggQ g gQggQggQggQg DgQ"g$gQ'g)g+g.g0g3g5g8g:g=g?gBgDgGgIgLgNgQgSgVgXg[g]g`gbgegggjglgogpgQsgugQxgzgQ}ggQgфgQgщgQgюgQgѓgQgјgQgѝgQgѢgQgѧgQgѬgQgѱgQgggg PgggggggggggggggggggggggggQggQhhQhhQ h hQhhQhhQhhQh hQ#h%hQ(h*hQ-h/hQ2h4hQ7h9hQh@hChEhHhJhMhOhRhThWhYh \\h^hahchfhhhkhmhphrhuhwhzh|hhhhхhQhъhQhяhQhєhQhљhQhўhQhѣhQhѨhQhѭhQhѲhQhѷhQhѼhQhhQhhQhhhhhhhhhhhhhhhhhhhh hhhhiii i iiQiiQiiQiiQi!iQ$i&iQ)i+iQ.i0iQ3i5iQ8i:iQ=i?iQBiDiQGiIiQLiNiQQiSiUiXiZi]i_ibidigiiiliniqisivixi{i}iiiiiiiiiii tiњiQiџiQiѤiQiѩiQiѮiQiѳiQiѸiQiѽiQiiQiiQiiQiiQiiQiiQiiiiiiiiiiiiiijjjj j jjjjjjjj!j#jQ%j'jQ*j,jQ/j1jQ4j 6jQ9j;jQ>j@jQCjEjQHjJjQMjOjQRjTjQWjYjQ\j^jQajcjQfjhjjjmjojrjtjwjyj|j~jjjjjjjjjjjjjjjjjjjjѯjQjѴjQjѹjQjѾjQjjQjjQjjQjj QjjQjjQjjQjjQjjQjjQjjjjjjkkk k kkkkkkkkk"k$k'k)k,k.k1k3k6k8kQ:klAlClFlHlKlMlQOlQlQTlVlQYl[lQ^l`lQclelQhljlQmlolQrltlQwlylQ|l~lQlуlQlшlQlэlQlђllllllllllll llllllllllllllllllQllQllQllQllQllQllQllQlmQmmQ m mQmmQmmQmmQmm!m$m&m)m+m.m0m3m5m8m:m=m?mBmDmGmImLm NmQmSmVmXm[m]m`mbmQdmfmQimkmQnmpmQsmumQxmzmQ}mmQmфmQmщmQmюmQmѓmQmјmQmѝmQmѢmQmѧmmmmmmmmmmmmmmmmmmmmmmmmmmmm mmQmmQmmQmmQnnQnnQ n nQnnQnnQnnQn nQ#n%nQ(n*nQ-n/nQ2n4n6n9n;n>n@nCnEnHnJnMnOnRnTnWnYn\n^nancnfnhnknmnpnrnunwnQyn{nQ~nрnQnхnQn ъnQnяnQnєnQnљnQnўnQnѣnQnѨnQnѭnQnѲnQnѷnQnѼnnnnnnnnnnnnnnnnnnnnnnnnnnnnooQooQ o oQooQooQooQo!oQ$o&o Q)o+oQ.o0oQ3o5oQ8o:oQ=o?oQBoDoQGoIoKoNoPoSoUoXoZo]o_obodogoiolonoqosovoxo{o}oooooooQoѐoQoѕoQoњoQoџoQoѤoQoѩoQoѮoQoѳoQoѸoQoѽoQooQo oQooQoooooooooooooooooooopppp p ppppppQppQ p"pQ%p'pQ*p,pQ/p1pQ4p6pQ9p;pQ>p@pQCpEpQHpJpQMpOpQRpTpQWpYpQ\p^p`pcp ephpjpmpoprptpwpyp|p~pppppppppppppppQpѥpQpѪpQpѯpQpѴpQpѹpQpѾpQppQppQppQppQppQppQppQppppppppppppq qq q qqqqqqqqq"q$q'q)q,q-qQ0q2qQ5q7qQ:qrQ?rSHQrQRrSrTrVrQWrXrYr[rQ\r]r^r`rP (08@X,`8T@P"f@H P$ FÀÁÂÃĀĂȦÄẢÅǍȀȂẠḀĄ=HhḂḄḆkhĆĈĊČÇhḊĎḌḐḒḎh ÈÉÊẼĒĔĖËẺĚȄȆẸȨĘḘḚ0xhḞ!hǴĜḠĞĠǦĢ$hĤḢḦȞḤḨḪMhÌÍÎĨĪĬİÏỈǏȈȊỊĮḬ| `hhĴxhḰǨḲĶḴhĹĽḶĻḼḺhḾṀṂ hǸŃÑṄŇṆŅṊṈ=$LhTÒÓÔÕŌŎȮÖỎŐǑȌȎƠỌǪqdhṔṖhŔṘŘȐȒṚŖṞhŚŜṠŠṢȘŞ @hHṪŤṬȚŢṰṮXxhÙÚÛŨŪŬÜỦŮŰǓȔȖƯỤṲŲṶṴ.hṼṾah ẀẂŴẆẄẈ8h@ẊẌP\hdỲÝŶỸȲẎŸỶỴthŹẐŻŽẒẔhàáâãāăȧäảåǎȁȃạḁą=,h4ḃḅḇkDTh\ćĉċčçlhḋďḍḑḓḏhèéêẽēĕėëẻěȅȇẹȩęḙḛh ḟ!08h@ǵĝḡğġǧģ$Pphxĥḣḧȟḥḩḫẖhìíîĩīĭïỉǐȉȋịįḭ9hĵǰl$h,ḱǩḳķḵ<Th\ĺľḷļḽḻlhḿṁṃhǹńñṅňṇņṋṉ=hòóôõōŏȯöỏőǒȍȏơọǫqLhTṕṗdphxŕṙřȑȓṛŗṟhśŝṡšṣșşhṫẗťṭțţṱṯy h(ùúûũūŭüủůűǔȕȗưụṳųṷṵ.8hṽṿahẁẃŵẇẅẘẉhẋẍhỳýŷỹȳẏÿỷẙỵ LhTźẑżžẓẕdh῭΅῁ẦẤẪẨhǞ  hǺ ,4h<ǼǢLXh`Ḉ pxhỀẾỄỂhḮ hỒỐỖỔhṌȬṎh Ȫ 08h@Ǿ PXh`ǛǗǕǙphầấẫẩhǟ hǻ hǽǣhḉ ,4h<ềếễểL`hhḯ xhồốỗổhṍȭṏhȫ hǿ  hǜǘǖǚ,@hH$Dh(Hh$Dp$P.XẰẮẴẲhằắẵẳh ḔḖ(h0ḕḗ@LhT8\kdṐṒhṑṓhṤ!hṥ!hṦ!hṧ!(0h8Ṹ HPhXṹ hphxṺhṻhẛ!h @`ỜỚỠỞỢ 8h@ờớỡởợPhhpỪỨỮỬỰhừứữửựhǮhHxǬ  (h0ǭ @HhP8X`Ǡ t|hǡ hḜhḝhȰ hȱ h$ ,4ǯX`hhpxᾺΆᾹᾸἈἉᾼ(ῈΈἘἙ+hῊΉἨἩ+ῌ( (ῚΊῙῘΪἸἹB<\hdῸΌὈὉ+thῬYhῪΎῩῨΫὙ\hῺΏὨὩ+ῼ( ᾴ(4<sDῄ(T\sdὰάᾱᾰἀἁtᾶᾳvὲέἐἑ+hὴήἠἡ+ῆῃvὶίῑῐϊἰἱB0ῖXP`hὸόὀὁ+|h4l,Ll(t|ῤῥhὺύῡῠϋὐὑBῦ<4DLὼώὠὡ+`ῶῳv|tῒῗῢῧῴ( sϓϔ,8h@ X$HPЇxhӐӒhЃ hЀӖЁhӁӜhӞ(0h8ЍӢЙӤH\hdЌ t|hӦhӮЎӰӲhӴhӸhӬ (h0ӑӓ@LhTѓ dlhtѐӗёhӂӝhӟhѝӣйӥh ќ $h,ӧ<DhL @l8\|4T\ӯўӱӳhӵhӹhӭ(0h8їHPhXѶ2hphxѷ2h @`5ӚhӛhӪh ӫ08h@(HjPآأإ~l|ؤYئYۂYۓY (ۀY8@H0PXऩpxऱऴোৌ( 08DLT!\ୋlୈୌ|t!ஔொௌ $08ோHPX`h@pxైೀೊೇೈ $,4ೋDLT\d<ltൊൌ ോ ේොෞ ((08ෝ+HP(X`h@p.xd4ဦJM가개갸걔거게겨계고과괘괴교구궈궤귀규그긔기PX(`hJp까깨꺄꺠꺼께껴꼐꼬꽈꽤꾀꾜꾸꿔꿰뀌뀨끄끠끼P(J나내냐냬너네녀녜노놔놰뇌뇨누눠눼뉘뉴느늬니PX(`hJp다대댜댸더데뎌뎨도돠돼되됴두둬뒈뒤듀드듸디P(J따때땨떄떠떼뗘뗴또똬뙈뙤뚀뚜뚸뛔뛰뜌뜨띄띠PX(`hJp라래랴럐러레려례로롸뢔뢰료루뤄뤠뤼류르릐리P(J마매먀먜머메며몌모뫄뫠뫼묘무뭐뭬뮈뮤므믜미PX(`hJp바배뱌뱨버베벼볘보봐봬뵈뵤부붜붸뷔뷰브븨비P(J빠빼뺘뺴뻐뻬뼈뼤뽀뽜뽸뾔뾰뿌뿨쀄쀠쀼쁘쁴삐PX(`hJp사새샤섀서세셔셰소솨쇄쇠쇼수숴쉐쉬슈스싀시P(J싸쌔쌰썌써쎄쎠쎼쏘쏴쐐쐬쑈쑤쒀쒜쒸쓔쓰씌씨PX(`hJp아애야얘어에여예오와왜외요우워웨위유으의이P(J자재쟈쟤저제져졔조좌좨죄죠주줘줴쥐쥬즈즤지PX(`hJp짜째쨔쨰쩌쩨쪄쪠쪼쫘쫴쬐쬬쭈쭤쮀쮜쮸쯔쯰찌P(J차채챠챼처체쳐쳬초촤쵀최쵸추춰췌취츄츠츼치PX(`hJp카캐캬컈커케켜켸코콰쾌쾨쿄쿠쿼퀘퀴큐크킈키P(J타태탸턔터테텨톄토톼퇘퇴툐투퉈퉤튀튜트틔티PX(`hJp파패퍄퍠퍼페펴폐포퐈퐤푀표푸풔풰퓌퓨프픠피P(J하해햐햬허헤혀혜호화홰회효후훠훼휘휴흐희히PX(`hJpxxxxxxxxxxgḸ hḹ h|Ṝ ,4h<ṝ LTh\Ṩ!lth|ṩ!hDdẬẶhậặhỆh ệ08h@(HPỘlth|ộhἂἄἆᾀvἃἅἇᾁv$ᾂ(8@sHᾃ(X`shᾄ(xsᾅ(sᾆ(sᾇ(sἊἌἎᾈv  ἋἍ4ἏᾉvH@T\ᾊ(pxsᾋ(sᾌ(sᾍ(sᾎ(sᾏ(s ἒἔ0<hDἓἕT`hhἚἜxhἛἝhἢἤἦᾐvἣἥἧᾑv$ᾒ(8@sHᾓ(X`shᾔ(xsᾕ(sᾖ(sᾗ(sἪἬἮᾘv  ἫἭ4ἯᾙvH@T\ᾚ(pxsᾛ(sᾜ(sᾝ(sᾞ(sᾟ(s ἲἴ0ἶD<LTἳἵhἷ|tἺἼἾἻἽἿ0Pp,h(Lp0Pp,h(`ὂὄhὃὅhὊὌhὋὍ(4h<ὒὔLὖ`XhpὓὕὗὛὝὟὢὤὦᾠvὣὥ0ὧᾡvD<PXᾢ(lts|ᾣ(sᾤ(sᾥ(sᾦ(sᾧ( sὪὬ,Ὦᾨv@8LTὫὭhὯᾩv|tᾪ(sᾫ(sᾬ(sᾭ( sᾮ($,s4ᾯ(DLsTᾲ(dlstῂ(sῲ(s D|(d$`<\|ᾷ(8@sH῍῎X῏ldt|P.ῇ(sῷ(s῝῞῟   : $d0, u4 ゔh p x   が     ぎ     ぐ     げ( 0 8 @ H ごX ` h p x ざ     じ     ず     ぜ  ( 0 8 ぞH P X ` h だx     ぢ     づ     で    ( ど8 @ H P X ばぱh t |   びぴ     ぶぷ     べぺ    ( ぼぽ8 D L T \     P     @ p    0 `    0 d l ゞ     ヴ  ガ,4<DLギ\dlt|グゲゴ ザ$,4<ジLT\dlズ|ゼゾダ $, $TDt4<ヂ|ヅデド $,バパ<HPX`ビピp|ブプベペボポ  (0ヷ@HPX`ヸpxヹヺヾ 4h8h(0 tl]t각갂갃간갅갆갇갈갉갊갋갌갍갎갏감갑값갓갔강갖갗갘b같갚갛|J$객갞갟갠갡갢갣갤갥갦갧갨갩갪갫갬갭갮갯갰갱갲갳갴b4갵갶갷|J갹갺갻갼갽갾갿걀걁걂걃걄걅걆걇걈걉걊걋걌걍걎걏걐b걑걒걓|H@X`lJt,|걕걖걗걘걙걚걛걜걝걞걟걠걡걢걣걤걥걦걧걨걩걪걫걬b걭걮걯| ,J4걱걲걳건걵걶걷걸걹걺걻걼걽걾걿검겁겂것겄겅겆겇겈bD겉겊겋|J<겍겎겏겐겑겒겓겔겕겖겗겘겙겚겛겜겝겞겟겠겡겢겣겤b겥겦겧|ld|J격겪겫견겭겮겯결겱겲겳겴겵겶겷겸겹겺겻겼경겾겿곀b곁곂곃| $,8J@HP곅곆곇곈곉곊곋곌곍곎곏곐곑곒곓곔곕곖곗곘곙곚곛곜bd곝곞곟|J곡곢곣곤곥곦곧골곩곪곫곬곭곮곯곰곱곲곳곴공곶곷곸b 곹곺곻|xpJ곽곾곿관괁괂괃괄괅괆괇괈괉괊괋괌괍괎괏괐광괒괓괔b괕괖괗| 08DJLT\괙괚괛괜괝괞괟괠괡괢괣괤괥괦괧괨괩괪괫괬괭괮괯괰bt괱괲괳|J 괵괶괷괸괹괺괻괼괽괾괿굀굁굂굃굄굅굆굇굈굉굊굋굌b굍굎굏|J5굑굒굓굔굕굖굗굘굙굚굛굜굝굞굟굠굡굢굣굤굥굦굧굨b굩굪굫|D<T\hJp국굮굯군굱굲굳굴굵굶굷굸굹굺굻굼굽굾굿궀궁궂궃궄b궅궆궇|Jx T(궉궊궋권궍궎궏궐궑궒궓궔궕궖궗궘궙궚궛궜궝궞궟궠b<궡궢궣|J궥궦궧궨궩궪궫궬궭궮궯궰궱궲궳궴궵궶궷궸궹궺궻궼b궽궾궿|PH`htJ|s귁귂귃귄귅귆귇귈귉귊귋귌귍귎귏귐귑귒귓귔귕귖귗귘b귙귚귛| $0J8귝귞귟균귡귢귣귤귥귦귧귨귩귪귫귬귭귮귯귰귱귲귳귴bH귵귶귷|J극귺귻근귽귾귿글긁긂긃긄긅긆긇금급긊긋긌긍긎긏긐b긑긒긓|\ T l t  J @  긕긖긗긘긙긚긛긜긝긞긟긠긡긢긣긤긥긦긧긨긩긪긫긬b 긭긮긯|!!,!4!@!JH!긱긲긳긴긵긶긷길긹긺긻긼긽긾긿김깁깂깃깄깅깆깇깈bX!깉깊깋|!!!!!J!P!!"깍깎깏깐깑깒깓깔깕깖깗깘깙깚깛깜깝깞깟깠깡깢깣깤b"깥깦깧|"x""""J"깩깪깫깬깭깮깯깰깱깲깳깴깵깶깷깸깹깺깻깼깽깾깿꺀b"꺁꺂꺃|(# #8#@#L#JT#"\#d#꺅꺆꺇꺈꺉꺊꺋꺌꺍꺎꺏꺐꺑꺒꺓꺔꺕꺖꺗꺘꺙꺚꺛꺜bx#꺝꺞꺟|####$J$꺡꺢꺣꺤꺥꺦꺧꺨꺩꺪꺫꺬꺭꺮꺯꺰꺱꺲꺳꺴꺵꺶꺷꺸b $꺹꺺꺻|$$$$$J$꺽꺾꺿껀껁껂껃껄껅껆껇껈껉껊껋껌껍껎껏껐껑껒껓껔b$껕껖껗|4%,%D%L%X%J`%$$h%p%껙껚껛껜껝껞껟껠껡껢껣껤껥껦껧껨껩껪껫껬껭껮껯껰b%껱껲껳|%%& &&J &껵껶껷껸껹껺껻껼껽껾껿꼀꼁꼂꼃꼄꼅꼆꼇꼈꼉꼊꼋꼌b0&꼍꼎꼏|&&&&&J&(&&5&꼑꼒꼓꼔꼕꼖꼗꼘꼙꼚꼛꼜꼝꼞꼟꼠꼡꼢꼣꼤꼥꼦꼧꼨b&꼩꼪꼫|X'P'h'p'|'J'꼭꼮꼯꼰꼱꼲꼳꼴꼵꼶꼷꼸꼹꼺꼻꼼꼽꼾꼿꽀꽁꽂꽃꽄b'꽅꽆꽇|('(($(J,('4(T<(꽉꽊꽋꽌꽍꽎꽏꽐꽑꽒꽓꽔꽕꽖꽗꽘꽙꽚꽛꽜꽝꽞꽟꽠bP(꽡꽢꽣|(((((J(꽥꽦꽧꽨꽩꽪꽫꽬꽭꽮꽯꽰꽱꽲꽳꽴꽵꽶꽷꽸꽹꽺꽻꽼b(꽽꽾꽿|d)\)t)|))J)()s)꾁꾂꾃꾄꾅꾆꾇꾈꾉꾊꾋꾌꾍꾎꾏꾐꾑꾒꾓꾔꾕꾖꾗꾘b)꾙꾚꾛| **0*8*D*JL*꾝꾞꾟꾠꾡꾢꾣꾤꾥꾦꾧꾨꾩꾪꾫꾬꾭꾮꾯꾰꾱꾲꾳꾴b\*꾵꾶꾷|*****J*꾹꾺꾻꾼꾽꾾꾿꿀꿁꿂꿃꿄꿅꿆꿇꿈꿉꿊꿋꿌꿍꿎꿏꿐b+꿑꿒꿓|p+h++++J+T**++꿕꿖꿗꿘꿙꿚꿛꿜꿝꿞꿟꿠꿡꿢꿣꿤꿥꿦꿧꿨꿩꿪꿫꿬b+꿭꿮꿯|0,(,@,H,T,J\,꿱꿲꿳꿴꿵꿶꿷꿸꿹꿺꿻꿼꿽꿾꿿뀀뀁뀂뀃뀄뀅뀆뀇뀈bl,뀉뀊뀋|,,,,,J-d, --\l4  "p#%&H()+ -(-뀍뀎뀏뀐뀑뀒뀓뀔뀕뀖뀗뀘뀙뀚뀛뀜뀝뀞뀟뀠뀡뀢뀣뀤bt-뀥뀦뀧|----.J .뀩뀪뀫뀬뀭뀮뀯뀰뀱뀲뀳뀴뀵뀶뀷뀸뀹뀺뀻뀼뀽뀾뀿끀b.끁끂끃|.....J....끅끆끇끈끉끊끋끌끍끎끏끐끑끒끓끔끕끖끗끘끙끚끛끜b.끝끞끟|D/닅닆닇|t>l>>>>J>>>T>닉닊닋닌닍닎닏닐닑닒닓닔닕닖닗님닙닚닛닜닝닞닟닠b>닡닢닣|0?(?@?H?T?J\?닥닦닧단닩닪닫달닭닮닯닰닱닲닳담답닶닷닸당닺닻닼bl?닽닾닿|?????J@d? @s@댁댂댃댄댅댆댇댈댉댊댋댌댍댎댏댐댑댒댓댔댕댖댗댘b(@댙댚댛|@@@@@J@댝댞댟댠댡댢댣댤댥댦댧댨댩댪댫댬댭댮댯댰댱댲댳댴b@댵댶댷| @0BCDGlHI4KDMN PRSTHVXXY [0]^_\alcd4fDhi kplnoHqXst vwyz\|l~4 pH  쀅쀆쀇쀈쀉쀊쀋쀌쀍쀎쀏쀐쀑쀒쀓쀔쀕쀖쀗쀘쀙쀚쀛쀜b쀝쀞쀟|(J0쀡쀢쀣쀤쀥쀦쀧쀨쀩쀪쀫쀬쀭쀮쀯쀰쀱쀲쀳쀴쀵쀶쀷쀸b@쀹쀺쀻|ĔДJؔ쀽쀾쀿쁀쁁쁂쁃쁄쁅쁆쁇쁈쁉쁊쁋쁌쁍쁎쁏쁐쁑쁒쁓쁔b쁕쁖쁗|TLdlxJ8쁙쁚쁛쁜쁝쁞쁟쁠쁡쁢쁣쁤쁥쁦쁧쁨쁩쁪쁫쁬쁭쁮쁯쁰b쁱쁲쁳| $,8J@쁵쁶쁷쁸쁹쁺쁻쁼쁽쁾쁿삀삁삂삃삄삅삆삇삈삉삊삋삌bP삍삎삏|̖ԖJH5삑삒삓삔삕삖삗삘삙삚삛삜삝삞삟삠삡삢삣삤삥삦삧삨b 삩삪삫|xpJ삭삮삯산삱삲삳살삵삶삷삸삹삺삻삼삽삾삿샀상샂샃샄b샅샆샇| 08DJLTT\색샊샋샌샍샎샏샐샑샒샓샔샕샖샗샘샙샚샛샜생샞샟샠bp샡샢샣|ܘԘJ샥샦샧샨샩샪샫샬샭샮샯샰샱샲샳샴샵샶샷샸샹샺샻샼b샽샾샿||Js섁섂섃섄섅섆섇섈섉섊섋섌섍섎섏섐섑섒섓섔섕섖섗섘bԙ섙섚섛|@8PXdJl석섞섟선섡섢섣설섥섦섧섨섩섪섫섬섭섮섯섰성섲섳섴b|섵섶섷| J섹섺섻센섽섾섿셀셁셂셃셄셅셆셇셈셉셊셋셌셍셎셏셐b$셑셒셓|Jtě̛셕셖셗션셙셚셛셜셝셞셟셠셡셢셣셤셥셦셧셨셩셪셫셬b셭셮셯|PH`htJ|셱셲셳셴셵셶셷셸셹셺셻셼셽셾셿솀솁솂솃솄솅솆솇솈b솉솊솋|J$,4속솎솏손솑솒솓솔솕솖솗솘솙솚솛솜솝솞솟솠송솢솣솤bH솥솦솧|ĝ̝؝J솩솪솫솬솭솮솯솰솱솲솳솴솵솶솷솸솹솺솻솼솽솾솿쇀b쇁쇂쇃|\TltJ쇅쇆쇇쇈쇉쇊쇋쇌쇍쇎쇏쇐쇑쇒쇓쇔쇕쇖쇗쇘쇙쇚쇛쇜b쇝쇞쇟|(0<JD쇡쇢쇣쇤쇥쇦쇧쇨쇩쇪쇫쇬쇭쇮쇯쇰쇱쇲쇳쇴쇵쇶쇷쇸bT쇹쇺쇻|П؟J쇽쇾쇿숀숁숂숃숄숅숆숇숈숉숊숋숌숍숎숏숐숑숒숓숔b숕숖숗|h`xJL숙숚숛순숝숞숟술숡숢숣숤숥숦숧숨숩숪숫숬숭숮숯숰b숱숲숳|( 8@LJT숵숶숷숸숹숺숻숼숽숾숿쉀쉁쉂쉃쉄쉅쉆쉇쉈쉉쉊쉋쉌bd쉍쉎쉏|СȡJ\5 쉑쉒쉓쉔쉕쉖쉗쉘쉙쉚쉛쉜쉝쉞쉟쉠쉡쉢쉣쉤쉥쉦쉧쉨b 쉩쉪쉫|J쉭쉮쉯쉰쉱쉲쉳쉴쉵쉶쉷쉸쉹쉺쉻쉼쉽쉾쉿슀슁슂슃슄bȢ슅슆슇|4,DLXJ`hTp슉슊슋슌슍슎슏슐슑슒슓슔슕슖슗슘슙슚슛슜슝슞슟슠b슡슢슣|J슥슦슧슨슩슪슫슬슭슮슯슰슱슲슳슴습슶슷슸승슺슻슼b,슽슾슿|JĤ$̤sԤ싁싂싃싄싅싆싇싈싉싊싋싌싍싎싏싐싑싒싓싔싕싖싗싘b싙싚싛|TLdlxJ식싞싟신싡싢싣실싥싦싧싨싩싪싫심십싮싯싰싱싲싳싴b싵싶싷|  J(싹싺싻싼싽싾싿쌀쌁쌂쌃쌄쌅쌆쌇쌈쌉쌊쌋쌌쌍쌎쌏쌐b8쌑쌒쌓|ȦJЦ0ئ쌕쌖쌗쌘쌙쌚쌛쌜쌝쌞쌟쌠쌡쌢쌣쌤쌥쌦쌧쌨쌩쌪쌫쌬b쌭쌮쌯|d\t|J쌱쌲쌳쌴쌵쌶쌷쌸쌹쌺쌻쌼쌽쌾쌿썀썁썂썃썄썅썆썇썈b썉썊썋| $0J8@H썍썎썏썐썑썒썓썔썕썖썗썘썙썚썛썜썝썞썟썠썡썢썣썤b\썥썦썧|ȨبJ썩썪썫썬썭썮썯썰썱썲썳썴썵썶썷썸썹썺썻썼썽썾썿쎀b쎁쎂쎃|phJ쎅쎆쎇쎈쎉쎊쎋쎌쎍쎎쎏쎐쎑쎒쎓쎔쎕쎖쎗쎘쎙쎚쎛쎜b쎝쎞쎟|,$<DPJX쎡쎢쎣쎤쎥쎦쎧쎨쎩쎪쎫쎬쎭쎮쎯쎰쎱쎲쎳쎴쎵쎶쎷쎸bh쎹쎺쎻|Ԫ̪J쎽쎾쎿쏀쏁쏂쏃쏄쏅쏆쏇쏈쏉쏊쏋쏌쏍쏎쏏쏐쏑쏒쏓쏔b쏕쏖쏗||tJ`쏙쏚쏛쏜쏝쏞쏟쏠쏡쏢쏣쏤쏥쏦쏧쏨쏩쏪쏫쏬쏭쏮쏯쏰bЫ쏱쏲쏳|<4LT`Jh쏵쏶쏷쏸쏹쏺쏻쏼쏽쏾쏿쐀쐁쐂쐃쐄쐅쐆쐇쐈쐉쐊쐋쐌bx쐍쐎쐏|ܬJp5 쐑쐒쐓쐔쐕쐖쐗쐘쐙쐚쐛쐜쐝쐞쐟쐠쐡쐢쐣쐤쐥쐦쐧쐨b4쐩쐪쐫|ĭJ̭쐭쐮쐯쐰쐱쐲쐳쐴쐵쐶쐷쐸쐹쐺쐻쐼쐽쐾쐿쑀쑁쑂쑃쑄bܭ쑅쑆쑇|H@X`lJtԭ|T쑉쑊쑋쑌쑍쑎쑏쑐쑑쑒쑓쑔쑕쑖쑗쑘쑙쑚쑛쑜쑝쑞쑟쑠b쑡쑢쑣|(J0쑥쑦쑧쑨쑩쑪쑫쑬쑭쑮쑯쑰쑱쑲쑳쑴쑵쑶쑷쑸쑹쑺쑻쑼b@쑽쑾쑿|įЯJد8s쒁쒂쒃쒄쒅쒆쒇쒈쒉쒊쒋쒌쒍쒎쒏쒐쒑쒒쒓쒔쒕쒖쒗쒘b쒙쒚쒛|h`xJ쒝쒞쒟쒠쒡쒢쒣쒤쒥쒦쒧쒨쒩쒪쒫쒬쒭쒮쒯쒰쒱쒲쒳쒴b쒵쒶쒷| (4J<쒹쒺쒻쒼쒽쒾쒿쓀쓁쓂쓃쓄쓅쓆쓇쓈쓉쓊쓋쓌쓍쓎쓏쓐bL쓑쓒쓓|ȱбܱJD쓕쓖쓗쓘쓙쓚쓛쓜쓝쓞쓟쓠쓡쓢쓣쓤쓥쓦쓧쓨쓩쓪쓫쓬b 쓭쓮쓯|xpJ쓱쓲쓳쓴쓵쓶쓷쓸쓹쓺쓻쓼쓽쓾쓿씀씁씂씃씄씅씆씇씈b씉씊씋| 08DJLT\씍씎씏씐씑씒씓씔씕씖씗씘씙씚씛씜씝씞씟씠씡씢씣씤bp씥씦씧|ܳԳJ씩씪씫씬씭씮씯씰씱씲씳씴씵씶씷씸씹씺씻씼씽씾씿앀b앁앂앃||J악앆앇안앉않앋알앍앎앏앐앑앒앓암압앖앗았앙앚앛앜bԴ앝앞앟|@8PXdJl액앢앣앤앥앦앧앨앩앪앫앬앭앮앯앰앱앲앳앴앵앶앷앸b|앹앺앻| J약앾앿얀얁얂얃얄얅얆얇얈얉얊얋얌얍얎얏얐양얒얓얔b$얕얖얗|JtĶ̶얙얚얛얜얝얞얟얠얡얢얣얤얥얦얧얨얩얪얫얬얭얮얯얰b얱얲얳|PH`htJ|억얶얷언얹얺얻얼얽얾얿엀엁엂엃엄업없엇었엉엊엋엌b엍엎엏|J$,54엑엒엓엔엕엖엗엘엙엚엛엜엝엞엟엠엡엢엣엤엥엦엧엨bH엩엪엫|ĸ̸ظJ역엮엯연엱엲엳열엵엶엷엸엹엺엻염엽엾엿였영옂옃옄b옅옆옇|\TltJT옉옊옋옌옍옎옏옐옑옒옓옔옕옖옗옘옙옚옛옜옝옞옟옠b옡옢옣|(0<JD옥옦옧온옩옪옫올옭옮옯옰옱옲옳옴옵옶옷옸옹옺옻옼bT옽옾옿|кغJLs왁왂왃완왅왆왇왈왉왊왋왌왍왎왏왐왑왒왓왔왕왖왗왘b왙왚왛||tJ왝왞왟왠왡왢왣왤왥왦왧왨왩왪왫왬왭왮왯왰왱왲왳왴b왵왶왷|$4<HJP왹왺왻왼왽왾왿욀욁욂욃욄욅욆욇욈욉욊욋욌욍욎욏욐b`욑욒욓|̼ļܼJX욕욖욗욘욙욚욛욜욝욞욟욠욡욢욣욤욥욦욧욨용욪욫욬b 욭욮욯|J욱욲욳운욵욶욷울욹욺욻욼욽욾욿움웁웂웃웄웅웆웇웈bȽ웉웊웋|4,DLXJ`hp웍웎웏원웑웒웓월웕웖웗웘웙웚웛웜웝웞웟웠웡웢웣웤b웥웦웧|J웩웪웫웬웭웮웯웰웱웲웳웴웵웶웷웸웹웺웻웼웽웾웿윀b,윁윂윃|JĿ$̿Կ윅윆윇윈윉윊윋윌윍윎윏윐윑윒윓윔윕윖윗윘윙윚윛윜b윝윞윟|TLdlxJ육윢윣윤윥윦윧율윩윪윫윬윭윮윯윰윱윲윳윴융윶윷윸b윹윺윻|  J(윽윾윿은읁읂읃을읅읆읇읈읉읊읋음읍읎읏읐응읒읓읔b8읕읖읗|J0읙읚읛읜읝읞읟읠읡읢읣읤읥읦읧읨읩읪읫읬읭읮읯읰b읱읲읳|d\t|J익읶읷인읹읺읻일읽읾읿잀잁잂잃임입잆잇있잉잊잋잌b잍잎잏| $0J8@5H작잒잓잔잕잖잗잘잙잚잛잜잝잞잟잠잡잢잣잤장잦잧잨b\잩잪잫|J잭잮잯잰잱잲잳잴잵잶잷잸잹잺잻잼잽잾잿쟀쟁쟂쟃쟄b쟅쟆쟇|phJT쟉쟊쟋쟌쟍쟎쟏쟐쟑쟒쟓쟔쟕쟖쟗쟘쟙쟚쟛쟜쟝쟞쟟쟠b쟡쟢쟣|,$<DPJX쟥쟦쟧쟨쟩쟪쟫쟬쟭쟮쟯쟰쟱쟲쟳쟴쟵쟶쟷쟸쟹쟺쟻쟼bh쟽쟾쟿|J`s적젂젃전젅젆젇절젉젊젋젌젍젎젏점접젒젓젔정젖젗젘b$젙젚젛|J젝젞젟젠젡젢젣젤젥젦젧젨젩젪젫젬젭젮젯젰젱젲젳젴b젵젶젷|80HP\Jd젹젺젻젼젽젾젿졀졁졂졃졄졅졆졇졈졉졊졋졌졍졎졏졐bt졑졒졓|J l졕졖졗졘졙졚졛졜졝졞졟졠졡졢졣졤졥졦졧졨졩졪졫졬b4졭졮졯|J족졲졳존졵졶졷졸졹졺졻졼졽졾졿좀좁좂좃좄종좆좇좈b좉좊좋|H@X`lJt|좍좎좏좐좑좒좓좔좕좖좗좘좙좚좛좜좝좞좟좠좡좢좣좤b좥좦좧|(J0좩좪좫좬좭좮좯좰좱좲좳좴좵좶좷좸좹좺좻좼좽좾좿죀b@죁죂죃|J8죅죆죇죈죉죊죋죌죍죎죏죐죑죒죓죔죕죖죗죘죙죚죛죜b죝죞죟|h`xJ죡죢죣죤죥죦죧죨죩죪죫죬죭죮죯죰죱죲죳죴죵죶죷죸b죹죺죻| (4J<죽죾죿준줁줂줃줄줅줆줇줈줉줊줋줌줍줎줏줐중줒줓줔bL줕줖줗|JD줙줚줛줜줝줞줟줠줡줢줣줤줥줦줧줨줩줪줫줬줭줮줯줰b 줱줲줳|xpJ줵줶줷줸줹줺줻줼줽줾줿쥀쥁쥂쥃쥄쥅쥆쥇쥈쥉쥊쥋쥌b쥍쥎쥏| 08DJLT5\쥑쥒쥓쥔쥕쥖쥗쥘쥙쥚쥛쥜쥝쥞쥟쥠쥡쥢쥣쥤쥥쥦쥧쥨bp쥩쥪쥫|J쥭쥮쥯쥰쥱쥲쥳쥴쥵쥶쥷쥸쥹쥺쥻쥼쥽쥾쥿즀즁즂즃즄b즅즆즇||JT즉즊즋즌즍즎즏즐즑즒즓즔즕즖즗즘즙즚즛즜증즞즟즠b즡즢즣|@8PXdJl즥즦즧즨즩즪즫즬즭즮즯즰즱즲즳즴즵즶즷즸즹즺즻즼b|즽즾즿| Jts$직짂짃진짅짆짇질짉짊짋짌짍짎짏짐집짒짓짔징짖짗짘b8짙짚짛|J짝짞짟짠짡짢짣짤짥짦짧짨짩짪짫짬짭짮짯짰짱짲짳짴b짵짶짷|LD\dpJx짹짺짻짼짽짾짿쨀쨁쨂쨃쨄쨅쨆쨇쨈쨉쨊쨋쨌쨍쨎쨏쨐b쨑쨒쨓| J (0쨕쨖쨗쨘쨙쨚쨛쨜쨝쨞쨟쨠쨡쨢쨣쨤쨥쨦쨧쨨쨩쨪쨫쨬bH쨭쨮쨯|J쨱쨲쨳쨴쨵쨶쨷쨸쨹쨺쨻쨼쨽쨾쨿쩀쩁쩂쩃쩄쩅쩆쩇쩈b쩉쩊쩋|\TltJ쩍쩎쩏쩐쩑쩒쩓쩔쩕쩖쩗쩘쩙쩚쩛쩜쩝쩞쩟쩠쩡쩢쩣쩤b쩥쩦쩧|(0<JD쩩쩪쩫쩬쩭쩮쩯쩰쩱쩲쩳쩴쩵쩶쩷쩸쩹쩺쩻쩼쩽쩾쩿쪀bT쪁쪂쪃|JL쪅쪆쪇쪈쪉쪊쪋쪌쪍쪎쪏쪐쪑쪒쪓쪔쪕쪖쪗쪘쪙쪚쪛쪜b쪝쪞쪟||tJ쪡쪢쪣쪤쪥쪦쪧쪨쪩쪪쪫쪬쪭쪮쪯쪰쪱쪲쪳쪴쪵쪶쪷쪸b쪹쪺쪻|$4<HJP쪽쪾쪿쫀쫁쫂쫃쫄쫅쫆쫇쫈쫉쫊쫋쫌쫍쫎쫏쫐쫑쫒쫓쫔b`쫕쫖쫗|JX쫙쫚쫛쫜쫝쫞쫟쫠쫡쫢쫣쫤쫥쫦쫧쫨쫩쫪쫫쫬쫭쫮쫯쫰b 쫱쫲쫳|J쫵쫶쫷쫸쫹쫺쫻쫼쫽쫾쫿쬀쬁쬂쬃쬄쬅쬆쬇쬈쬉쬊쬋쬌b쬍쬎쬏|4,DLXJ`h5p쬑쬒쬓쬔쬕쬖쬗쬘쬙쬚쬛쬜쬝쬞쬟쬠쬡쬢쬣쬤쬥쬦쬧쬨b쬩쬪쬫|J쬭쬮쬯쬰쬱쬲쬳쬴쬵쬶쬷쬸쬹쬺쬻쬼쬽쬾쬿쭀쭁쭂쭃쭄b,쭅쭆쭇|J$T쭉쭊쭋쭌쭍쭎쭏쭐쭑쭒쭓쭔쭕쭖쭗쭘쭙쭚쭛쭜쭝쭞쭟쭠b쭡쭢쭣|TLdlxJ쭥쭦쭧쭨쭩쭪쭫쭬쭭쭮쭯쭰쭱쭲쭳쭴쭵쭶쭷쭸쭹쭺쭻쭼b쭽쭾쭿|  J(0s8쮁쮂쮃쮄쮅쮆쮇쮈쮉쮊쮋쮌쮍쮎쮏쮐쮑쮒쮓쮔쮕쮖쮗쮘bL쮙쮚쮛|J쮝쮞쮟쮠쮡쮢쮣쮤쮥쮦쮧쮨쮩쮪쮫쮬쮭쮮쮯쮰쮱쮲쮳쮴b쮵쮶쮷|`XpxJ쮹쮺쮻쮼쮽쮾쮿쯀쯁쯂쯃쯄쯅쯆쯇쯈쯉쯊쯋쯌쯍쯎쯏쯐b쯑쯒쯓| ,J4<D쯕쯖쯗쯘쯙쯚쯛쯜쯝쯞쯟쯠쯡쯢쯣쯤쯥쯦쯧쯨쯩쯪쯫쯬b\쯭쯮쯯|J쯱쯲쯳쯴쯵쯶쯷쯸쯹쯺쯻쯼쯽쯾쯿찀찁찂찃찄찅찆찇찈b찉찊찋|phJ찍찎찏찐찑찒찓찔찕찖찗찘찙찚찛찜찝찞찟찠찡찢찣찤b찥찦찧|,$<DPJX착찪찫찬찭찮찯찰찱찲찳찴찵찶찷참찹찺찻찼창찾찿챀bh챁챂챃|J`책챆챇챈챉챊챋챌챍챎챏챐챑챒챓챔챕챖챗챘챙챚챛챜b$챝챞챟|J챡챢챣챤챥챦챧챨챩챪챫챬챭챮챯챰챱챲챳챴챵챶챷챸b챹챺챻|80HP\Jd챽챾챿첀첁첂첃첄첅첆첇첈첉첊첋첌첍첎첏첐첑첒첓첔bt첕첖첗|J l척첚첛천첝첞첟철첡첢첣첤첥첦첧첨첩첪첫첬청첮첯첰b4첱첲첳|J첵첶첷첸첹첺첻첼첽첾첿쳀쳁쳂쳃쳄쳅쳆쳇쳈쳉쳊쳋쳌b쳍쳎쳏|H@X`lJt|5쳑쳒쳓쳔쳕쳖쳗쳘쳙쳚쳛쳜쳝쳞쳟쳠쳡쳢쳣쳤쳥쳦쳧쳨b쳩쳪쳫|(J0쳭쳮쳯쳰쳱쳲쳳쳴쳵쳶쳷쳸쳹쳺쳻쳼쳽쳾쳿촀촁촂촃촄b@촅촆촇|J8T촉촊촋촌촍촎촏촐촑촒촓촔촕촖촗촘촙촚촛촜총촞촟촠b촡촢촣|h`xJ촥촦촧촨촩촪촫촬촭촮촯촰촱촲촳촴촵촶촷촸촹촺촻촼b촽촾촿| (4J<DsL쵁쵂쵃쵄쵅쵆쵇쵈쵉쵊쵋쵌쵍쵎쵏쵐쵑쵒쵓쵔쵕쵖쵗쵘b`쵙쵚쵛|J쵝쵞쵟쵠쵡쵢쵣쵤쵥쵦쵧쵨쵩쵪쵫쵬쵭쵮쵯쵰쵱쵲쵳쵴b쵵쵶쵷|tlJ쵹쵺쵻쵼쵽쵾쵿춀춁춂춃춄춅춆춇춈춉춊춋춌춍춎춏춐b춑춒춓|,4@JHPX축춖춗춘춙춚춛출춝춞춟춠춡춢춣춤춥춦춧춨충춪춫춬bp춭춮춯|J춱춲춳춴춵춶춷춸춹춺춻춼춽춾춿췀췁췂췃췄췅췆췇췈b췉췊췋||J췍췎췏췐췑췒췓췔췕췖췗췘췙췚췛췜췝췞췟췠췡췢췣췤b췥췦췧|@8PXdJl췩췪췫췬췭췮췯췰췱췲췳췴췵췶췷췸췹췺췻췼췽췾췿츀b|츁츂츃| Jt$츅츆츇츈츉츊츋츌츍츎츏츐츑츒츓츔츕츖츗츘츙츚츛츜b8츝츞츟|J측츢츣츤츥츦츧츨츩츪츫츬츭츮츯츰츱츲츳츴층츶츷츸b츹츺츻|LD\dpJx츽츾츿칀칁칂칃칄칅칆칇칈칉칊칋칌칍칎칏칐칑칒칓칔b칕칖칗| J (0칙칚칛친칝칞칟칠칡칢칣칤칥칦칧침칩칪칫칬칭칮칯칰bH칱칲칳|J칵칶칷칸칹칺칻칼칽칾칿캀캁캂캃캄캅캆캇캈캉캊캋캌b캍캎캏|\TltJ5캑캒캓캔캕캖캗캘캙캚캛캜캝캞캟캠캡캢캣캤캥캦캧캨b캩캪캫|(0<JD캭캮캯캰캱캲캳캴캵캶캷캸캹캺캻캼캽캾캿컀컁컂컃컄bT컅컆컇|JLT컉컊컋컌컍컎컏컐컑컒컓컔컕컖컗컘컙컚컛컜컝컞컟컠b컡컢컣||tJ컥컦컧컨컩컪컫컬컭컮컯컰컱컲컳컴컵컶컷컸컹컺컻컼b컽컾컿|$4<HJPXs`켁켂켃켄켅켆켇켈켉켊켋켌켍켎켏켐켑켒켓켔켕켖켗켘bt켙켚켛|J 켝켞켟켠켡켢켣켤켥켦켧켨켩켪켫켬켭켮켯켰켱켲켳켴b켵켶켷|J켹켺켻켼켽켾켿콀콁콂콃콄콅콆콇콈콉콊콋콌콍콎콏콐b콑콒콓|0(@HTJ\dl콕콖콗콘콙콚콛콜콝콞콟콠콡콢콣콤콥콦콧콨콩콪콫콬b콭콮콯|J콱콲콳콴콵콶콷콸콹콺콻콼콽콾콿쾀쾁쾂쾃쾄쾅쾆쾇쾈b,쾉쾊쾋|J$쾍쾎쾏쾐쾑쾒쾓쾔쾕쾖쾗쾘쾙쾚쾛쾜쾝쾞쾟쾠쾡쾢쾣쾤b쾥쾦쾧|TLdlxJ쾩쾪쾫쾬쾭쾮쾯쾰쾱쾲쾳쾴쾵쾶쾷쾸쾹쾺쾻쾼쾽쾾쾿쿀b쿁쿂쿃|  J(08쿅쿆쿇쿈쿉쿊쿋쿌쿍쿎쿏쿐쿑쿒쿓쿔쿕쿖쿗쿘쿙쿚쿛쿜bL쿝쿞쿟|J쿡쿢쿣쿤쿥쿦쿧쿨쿩쿪쿫쿬쿭쿮쿯쿰쿱쿲쿳쿴쿵쿶쿷쿸b쿹쿺쿻|`XpxJ쿽쿾쿿퀀퀁퀂퀃퀄퀅퀆퀇퀈퀉퀊퀋퀌퀍퀎퀏퀐퀑퀒퀓퀔b퀕퀖퀗| ,J4<Dh̙ܛ@|Tȫ,h̴ܶ@|T,h0@|DT,Xh0@l|DT \퀙퀚퀛퀜퀝퀞퀟퀠퀡퀢퀣퀤퀥퀦퀧퀨퀩퀪퀫퀬퀭퀮퀯퀰bh퀱퀲퀳|J퀵퀶퀷퀸퀹퀺퀻퀼퀽퀾퀿큀큁큂큃큄큅큆큇큈큉큊큋큌b큍큎큏||tJ5큑큒큓큔큕큖큗큘큙큚큛큜큝큞큟큠큡큢큣큤큥큦큧큨b큩큪큫|80HP\Jd큭큮큯큰큱큲큳클큵큶큷큸큹큺큻큼큽큾큿킀킁킂킃킄bt킅킆킇|J lT킉킊킋킌킍킎킏킐킑킒킓킔킕킖킗킘킙킚킛킜킝킞킟킠b0킡킢킣|J킥킦킧킨킩킪킫킬킭킮킯킰킱킲킳킴킵킶킷킸킹킺킻킼b킽킾킿|D<T\hJpxs탁탂탃탄탅탆탇탈탉탊탋탌탍탎탏탐탑탒탓탔탕탖탗탘b탙탚탛|$J,택탞탟탠탡탢탣탤탥탦탧탨탩탪탫탬탭탮탯탰탱탲탳탴b<탵탶탷|J탹탺탻탼탽탾탿턀턁턂턃턄턅턆턇턈턉턊턋턌턍턎턏턐b턑턒턓|PH`htJ|4턕턖턗턘턙턚턛턜턝턞턟턠턡턢턣턤턥턦턧턨턩턪턫턬b턭턮턯| (4J<턱턲턳턴턵턶턷털턹턺턻턼턽턾턿텀텁텂텃텄텅텆텇텈bL텉텊텋|JD텍텎텏텐텑텒텓텔텕텖텗텘텙텚텛템텝텞텟텠텡텢텣텤b텥텦텧|tlJ텩텪텫텬텭텮텯텰텱텲텳텴텵텶텷텸텹텺텻텼텽텾텿톀b톁톂톃|,4@JHPX톅톆톇톈톉톊톋톌톍톎톏톐톑톒톓톔톕톖톗톘톙톚톛톜bl톝톞톟|J톡톢톣톤톥톦톧톨톩톪톫톬톭톮톯톰톱톲톳톴통톶톷톸b톹톺톻|xJ톽톾톿퇀퇁퇂퇃퇄퇅퇆퇇퇈퇉퇊퇋퇌퇍퇎퇏퇐퇑퇒퇓퇔b퇕퇖퇗|( 8@LJT \d퇙퇚퇛퇜퇝퇞퇟퇠퇡퇢퇣퇤퇥퇦퇧퇨퇩퇪퇫퇬퇭퇮퇯퇰b|퇱퇲퇳| J퇵퇶퇷퇸퇹퇺퇻퇼퇽퇾퇿툀툁툂툃툄툅툆툇툈툉툊툋툌b$툍툎툏|J5툑툒툓툔툕툖툗툘툙툚툛툜툝툞툟툠툡툢툣툤툥툦툧툨b툩툪툫|LD\dpJx툭툮툯툰툱툲툳툴툵툶툷툸툹툺툻툼툽툾툿퉀퉁퉂퉃퉄b퉅퉆퉇| J (T0퉉퉊퉋퉌퉍퉎퉏퉐퉑퉒퉓퉔퉕퉖퉗퉘퉙퉚퉛퉜퉝퉞퉟퉠bD퉡퉢퉣|J퉥퉦퉧퉨퉩퉪퉫퉬퉭퉮퉯퉰퉱퉲퉳퉴퉵퉶퉷퉸퉹퉺퉻퉼b퉽퉾퉿|X P h p | J  s 튁튂튃튄튅튆튇튈튉튊튋튌튍튎튏튐튑튒튓튔튕튖튗튘b 튙튚튛|  $ , 8 J@ 튝튞튟튠튡튢튣튤튥튦튧튨튩튪튫튬튭튮튯튰튱튲튳튴bP 튵튶튷|     J 특튺튻튼튽튾튿틀틁틂틃틄틅틆틇틈틉틊틋틌틍틎틏틐b 틑틒틓|d \ t |  J H    틕틖틗틘틙틚틛틜틝틞틟틠틡틢틣틤틥틦틧틨틩틪틫틬b 틭틮틯|$  4 < H JP 틱틲틳틴틵틶틷틸틹틺틻틼틽틾틿팀팁팂팃팄팅팆팇팈b` 팉팊팋|     J X   팍팎팏판팑팒팓팔팕팖팗팘팙팚팛팜팝팞팟팠팡팢팣팤b 팥팦팧|     J 팩팪팫팬팭팮팯팰팱팲팳팴팵팶팷팸팹팺팻팼팽팾팿퍀b 퍁퍂퍃|0(@HTJ\ dl퍅퍆퍇퍈퍉퍊퍋퍌퍍퍎퍏퍐퍑퍒퍓퍔퍕퍖퍗퍘퍙퍚퍛퍜b퍝퍞퍟|J퍡퍢퍣퍤퍥퍦퍧퍨퍩퍪퍫퍬퍭퍮퍯퍰퍱퍲퍳퍴퍵퍶퍷퍸b(퍹퍺퍻|J퍽퍾퍿펀펁펂펃펄펅펆펇펈펉펊펋펌펍펎펏펐펑펒펓펔b펕펖펗|<4LT`Jh px펙펚펛펜펝펞펟펠펡펢펣펤펥펦펧펨펩펪펫펬펭펮펯펰b펱펲펳|  J(펵펶펷편펹펺펻펼펽펾펿폀폁폂폃폄폅폆폇폈평폊폋폌b8폍폎폏|J05폑폒폓폔폕폖폗폘폙폚폛폜폝폞폟폠폡폢폣폤폥폦폧폨b폩폪폫|`XpxJ폭폮폯폰폱폲폳폴폵폶폷폸폹폺폻폼폽폾폿퐀퐁퐂퐃퐄b퐅퐆퐇| ,J4<TD퐉퐊퐋퐌퐍퐎퐏퐐퐑퐒퐓퐔퐕퐖퐗퐘퐙퐚퐛퐜퐝퐞퐟퐠bX퐡퐢퐣|J퐥퐦퐧퐨퐩퐪퐫퐬퐭퐮퐯퐰퐱퐲퐳퐴퐵퐶퐷퐸퐹퐺퐻퐼b퐽퐾퐿|ld|Js푁푂푃푄푅푆푇푈푉푊푋푌푍푎푏푐푑푒푓푔푕푖푗푘b푙푚푛|( 8@LJT푝푞푟푠푡푢푣푤푥푦푧푨푩푪푫푬푭푮푯푰푱푲푳푴bd푵푶푷|J푹푺푻푼푽푾푿풀풁풂풃풄풅풆풇품풉풊풋풌풍풎풏풐b 풑풒풓|xpJ\풕풖풗풘풙풚풛풜풝풞풟풠풡풢풣풤풥풦풧풨풩풪풫풬b풭풮풯|80HP\Jd풱풲풳풴풵풶풷풸풹풺풻풼풽풾풿퓀퓁퓂퓃퓄퓅퓆퓇퓈bt퓉퓊퓋|J l퓍퓎퓏퓐퓑퓒퓓퓔퓕퓖퓗퓘퓙퓚퓛퓜퓝퓞퓟퓠퓡퓢퓣퓤b0퓥퓦퓧|J퓩퓪퓫퓬퓭퓮퓯퓰퓱퓲퓳퓴퓵퓶퓷퓸퓹퓺퓻퓼퓽퓾퓿픀b픁픂픃|D<T\hJpx픅픆픇픈픉픊픋플픍픎픏픐픑픒픓픔픕픖픗픘픙픚픛픜b픝픞픟|$J,픡픢픣픤픥픦픧픨픩픪픫픬픭픮픯픰픱픲픳픴픵픶픷픸b<픹픺픻|J픽픾픿핀핁핂핃필핅핆핇핈핉핊핋핌핍핎핏핐핑핒핓핔b핕핖핗|PH`htJ|4학핚핛한핝핞핟할핡핢핣핤핥핦핧함합핪핫핬항핮핯핰b핱핲핳| (4J<핵핶핷핸핹핺핻핼핽핾핿햀햁햂햃햄햅햆햇했행햊햋햌bL햍햎햏|JD5햑햒햓햔햕햖햗햘햙햚햛햜햝햞햟햠햡햢햣햤향햦햧햨b햩햪햫|tlJ햭햮햯햰햱햲햳햴햵햶햷햸햹햺햻햼햽햾햿헀헁헂헃헄b헅헆헇|,4@JHPTX헉헊헋헌헍헎헏헐헑헒헓헔헕헖헗험헙헚헛헜헝헞헟헠bl헡헢헣|J헥헦헧헨헩헪헫헬헭헮헯헰헱헲헳헴헵헶헷헸헹헺헻헼b헽헾헿|xJ s혁혂혃현혅혆혇혈혉혊혋혌혍혎혏혐협혒혓혔형혖혗혘b혙혚혛|< 4 L T ` Jh 혝혞혟혠혡혢혣혤혥혦혧혨혩혪혫혬혭혮혯혰혱혲혳혴bx 혵혶혷|    !J!혹혺혻혼혽혾혿홀홁홂홃홄홅홆홇홈홉홊홋홌홍홎홏홐b !홑홒홓|!!!!!J!p !!!확홖홗환홙홚홛활홝홞홟홠홡홢홣홤홥홦홧홨황홪홫홬b!홭홮홯|L"D"\"d"p"Jx"홱홲홳홴홵홶홷홸홹홺홻홼홽홾홿횀횁횂횃횄횅횆횇횈b"횉횊횋|""# ##J #"(#0#획횎횏횐횑횒횓횔횕횖횗횘횙횚횛횜횝횞횟횠횡횢횣횤bD#횥횦횧|#####J#횩횪횫횬횭횮횯횰횱횲횳횴횵횶횷횸횹횺횻횼횽횾횿훀b#훁훂훃|X$P$h$p$|$J$#$$훅훆훇훈훉훊훋훌훍훎훏훐훑훒훓훔훕훖훗훘훙훚훛훜b$훝훞훟|% %$%,%8%J@%훡훢훣훤훥훦훧훨훩훪훫훬훭훮훯훰훱훲훳훴훵훶훷훸bP%훹훺훻|%%%%%J%훽훾훿휀휁휂휃휄휅휆휇휈휉휊휋휌휍휎휏휐휑휒휓휔b%휕휖휗|d&\&t&|&&J&H%%&&휙휚휛휜휝휞휟휠휡휢휣휤휥휦휧휨휩휪휫휬휭휮휯휰b&휱휲휳|$''4'<'H'JP'휵휶휷휸휹휺휻휼휽휾휿흀흁흂흃흄흅흆흇흈흉흊흋흌b`'흍흎흏|'''''J'X'(5(흑흒흓흔흕흖흗흘흙흚흛흜흝흞흟흠흡흢흣흤흥흦흧흨b(흩흪흫|(((((J(흭흮흯흰흱흲흳흴흵흶흷흸흹흺흻흼흽흾흿힀힁힂힃힄b(힅힆힇|0)()@)H)T)J\)(d)Tl)힉힊힋힌힍힎힏힐힑힒힓힔힕힖힗힘힙힚힛힜힝힞힟힠b)힡힢힣|)))**J* *(*(dt<   xP(d!<#$&(x)0*8*(p\PHl<d(H4d\0\xlPpdh` l-`**  !"#$%&'()*+,-./0123456  !"#$%&'()*+,-./012345678  !"#$%&'()*+,-./0123456  !"#$%&'()*+,ǕǖǗǘǙǚǛǜǞǟǠǡǢǣǬǭǮǯǺǻǼǽǾǿ  !"#$%&'()*+,-ȪȫȬȭȰȱ̈́  ΅ΆΈΉΊΌΎΏΪΫάέήίϊϋόύώϓϔ  ЀЁЃЇЌЍЎЙй ѐёѓїќѝўѶѷ   !"#ӁӂӐӑӒӓӖӗӚӛӜӝӞӟӢӣӤӥӦӧӪӫӬӭӮӯӰӱӲӳӴӵӸӹآأؤإئۀۂۓऩऱऴ क़ख़ग़ज़ड़ढ़फ़य़োৌড়ঢ়য়ਲ਼ਸ਼ਖ਼ਗ਼ਜ਼ਫ਼ୈୋୌଡ଼ଢ଼ஔொோௌైೀೇೈೊೋൊോൌේොෝෞ  གྷཌྷདྷབྷཛྷཀྵཱཱིུྲྀླཱྀྀྒྷྜྷྡྷྦྷྫྷྐྵ     ဦ  !"#$%&'()*+,-./0123456789:;<=>?@ḈḉḔḕḖḗḜḝḮḯḸḹṌṍṎṏṐṑṒṓṜṝṤṥṦṧṨṩṸṹṺṻ  !"#$%&'()*+,-./0123456789:;<ẛẤấẦầẨẩẪẫẬậẮắẰằẲẳẴẵẶặẾế  !"#$%&'()*+,-./0123456789:;;;;;;ỀềỂểỄễỆệỐốỒồỔổỖỗỘộỚớỜờỞởỠỡỢợỨứỪừỬửỮữỰự  !"#$%&'()*+,-./0123456789:;<=ἀἁἂἃἄἅἆἇἈἉἊἋἌἍἎἏἐἑἒἓἔἕἘἙἚἛἜἝἠἡἢἣἤἥἦἧἨἩἪἫἬἭἮἯἰἱἲἳἴἵἶἷἸἹἺἻἼἽἾἿ  !"#$%&'()*+,-./0ὀὁὂὃὄὅὈὉὊὋὌὍὐὑὒὓὔὕὖὗὙὛὝὟὠὡὢὣὤὥὦὧὨὩὪὫὬὭὮὯὰὲὴὶὸὺὼ  !"#$%&'()*+,-./0123456789:;6<6=6ᾀᾁᾂᾃᾄᾅᾆᾇᾈᾉᾊᾋᾌᾍᾎᾏᾐᾑᾒᾓᾔᾕᾖᾗᾘᾙᾚᾛᾜᾝᾞᾟᾠᾡᾢᾣᾤᾥᾦᾧᾨᾩᾪᾫᾬᾭᾮᾯᾰᾱᾲᾳᾴᾶᾷᾸᾹᾺᾼ   !"#$%&'()*+,-./0῁ῂῃῄῆῇῈῊῌ῍῎῏ῐῑῒΐῖῗῘῙῚ῝῞῟ῠῡῢΰῤῥῦῧῨῩῪῬ῭ῲῳῴῶῷῸῺῼ      がぎぐげござじずぜぞだぢづでどばぱびぴぶぷべぺぼぽ     ゔゞガギグゲゴザジズゼゾ   ダヂヅデドバパビピブプベペボポヴヷヸヹヺヾ가각갂갃간갅갆갇갈갉갊갋갌갍갎갏감갑값갓갔강갖갗갘같갚갛개객갞갟갠갡갢갣갤갥갦갧갨갩갪갫갬갭갮갯갰갱갲갳갴갵갶갷갸갹갺갻갼갽갾갿걀걁걂걃걄걅걆걇걈걉걊걋걌걍걎걏걐걑걒걓걔걕걖걗걘걙걚걛걜걝걞걟걠걡걢걣걤걥걦걧걨걩걪걫걬걭걮걯거걱걲걳건걵걶걷걸걹걺걻걼걽걾걿검겁겂것겄겅겆겇겈겉겊겋게겍겎겏겐겑겒겓겔겕겖겗겘겙겚겛겜겝겞겟겠겡겢겣겤겥겦겧겨격겪겫견겭겮겯결겱겲겳겴겵겶겷겸겹겺겻겼경겾겿곀곁곂곃계곅곆곇곈곉곊곋곌곍곎곏곐곑곒곓곔곕곖곗곘곙곚곛곜곝곞곟고곡곢곣곤곥곦곧골곩곪곫곬곭곮곯곰곱곲곳곴공곶곷곸곹곺곻과곽곾곿관괁괂괃괄괅괆괇괈괉괊괋괌괍괎괏괐광괒괓괔괕괖괗괘괙괚괛괜괝괞괟괠괡괢괣괤괥괦괧괨괩괪괫괬괭괮괯괰괱괲괳괴괵괶괷괸괹괺괻괼괽괾괿굀굁굂굃굄굅굆굇굈굉굊굋굌굍굎굏교굑굒굓굔굕굖굗굘굙굚굛굜굝굞굟굠굡굢굣굤굥굦굧굨굩굪굫구국굮굯군굱굲굳굴굵굶굷굸굹굺굻굼굽굾굿궀궁궂궃궄궅궆궇궈궉궊궋권궍궎궏궐궑궒궓궔궕궖궗궘궙궚궛궜궝궞궟궠궡궢궣궤궥궦궧궨궩궪궫궬궭궮궯궰궱궲궳궴궵궶궷궸궹궺궻궼궽궾궿귀귁귂귃귄귅귆귇귈귉귊귋귌귍귎귏귐귑귒귓귔귕귖귗귘귙귚귛규귝귞귟균귡귢귣귤귥귦귧귨귩귪귫귬귭귮귯귰귱귲귳귴귵귶귷그극귺귻근귽귾귿글긁긂긃긄긅긆긇금급긊긋긌긍긎긏긐긑긒긓긔긕긖긗긘긙긚긛긜긝긞긟긠긡긢긣긤긥긦긧긨긩긪긫긬긭긮긯기긱긲긳긴긵긶긷길긹긺긻긼긽긾긿김깁깂깃깄깅깆깇깈깉깊깋까깍깎깏깐깑깒깓깔깕깖깗깘깙깚깛깜깝깞깟깠깡깢깣깤깥깦깧깨깩깪깫깬깭깮깯깰깱깲깳깴깵깶깷깸깹깺깻깼깽깾깿꺀꺁꺂꺃꺄꺅꺆꺇꺈꺉꺊꺋꺌꺍꺎꺏꺐꺑꺒꺓꺔꺕꺖꺗꺘꺙꺚꺛꺜꺝꺞꺟꺠꺡꺢꺣꺤꺥꺦꺧꺨꺩꺪꺫꺬꺭꺮꺯꺰꺱꺲꺳꺴꺵꺶꺷꺸꺹꺺꺻꺼꺽꺾꺿껀껁껂껃껄껅껆껇껈껉껊껋껌껍껎껏껐껑껒껓껔껕껖껗께껙껚껛껜껝껞껟껠껡껢껣껤껥껦껧껨껩껪껫껬껭껮껯껰껱껲껳껴껵껶껷껸껹껺껻껼껽껾껿꼀꼁꼂꼃꼄꼅꼆꼇꼈꼉꼊꼋꼌꼍꼎꼏꼐꼑꼒꼓꼔꼕꼖꼗꼘꼙꼚꼛꼜꼝꼞꼟꼠꼡꼢꼣꼤꼥꼦꼧꼨꼩꼪꼫꼬꼭꼮꼯꼰꼱꼲꼳꼴꼵꼶꼷꼸꼹꼺꼻꼼꼽꼾꼿꽀꽁꽂꽃꽄꽅꽆꽇꽈꽉꽊꽋꽌꽍꽎꽏꽐꽑꽒꽓꽔꽕꽖꽗꽘꽙꽚꽛꽜꽝꽞꽟꽠꽡꽢꽣꽤꽥꽦꽧꽨꽩꽪꽫꽬꽭꽮꽯꽰꽱꽲꽳꽴꽵꽶꽷꽸꽹꽺꽻꽼꽽꽾꽿꾀꾁꾂꾃꾄꾅꾆꾇꾈꾉꾊꾋꾌꾍꾎꾏꾐꾑꾒꾓꾔꾕꾖꾗꾘꾙꾚꾛꾜꾝꾞꾟꾠꾡꾢꾣꾤꾥꾦꾧꾨꾩꾪꾫꾬꾭꾮꾯꾰꾱꾲꾳꾴꾵꾶꾷꾸꾹꾺꾻꾼꾽꾾꾿꿀꿁꿂꿃꿄꿅꿆꿇꿈꿉꿊꿋꿌꿍꿎꿏꿐꿑꿒꿓꿔꿕꿖꿗꿘꿙꿚꿛꿜꿝꿞꿟꿠꿡꿢꿣꿤꿥꿦꿧꿨꿩꿪꿫꿬꿭꿮꿯꿰꿱꿲꿳꿴꿵꿶꿷꿸꿹꿺꿻꿼꿽꿾꿿 뀀뀁뀂뀃뀄뀅뀆뀇뀈뀉뀊뀋뀌뀍뀎뀏뀐뀑뀒뀓뀔뀕뀖뀗뀘뀙뀚뀛뀜뀝뀞뀟뀠뀡뀢뀣뀤뀥뀦뀧뀨뀩뀪뀫뀬뀭뀮뀯뀰뀱뀲뀳뀴뀵뀶뀷뀸뀹뀺뀻뀼뀽뀾뀿끀끁끂끃끄끅끆끇끈끉끊끋끌끍끎끏끐끑끒끓끔끕끖끗끘끙끚끛끜끝끞끟끠끡끢끣끤끥끦끧끨끩끪끫끬끭끮끯끰끱끲끳끴끵끶끷끸끹끺끻끼끽끾끿낀낁낂낃낄낅낆낇낈낉낊낋낌낍낎낏낐낑낒낓낔낕낖낗나낙낚낛난낝낞낟날낡낢낣낤낥낦낧남납낪낫났낭낮낯낰낱낲낳내낵낶낷낸낹낺낻낼낽낾낿냀냁냂냃냄냅냆냇냈냉냊냋냌냍냎냏냐냑냒냓냔냕냖냗냘냙냚냛냜냝냞냟냠냡냢냣냤냥냦냧냨냩냪냫냬냭냮냯냰냱냲냳냴냵냶냷냸냹냺냻냼냽냾냿넀넁넂넃넄넅넆넇너넉넊넋넌넍넎넏널넑넒넓넔넕넖넗넘넙넚넛넜넝넞넟넠넡넢넣네넥넦넧넨넩넪넫넬넭넮넯넰넱넲넳넴넵넶넷넸넹넺넻넼넽넾넿녀녁녂녃년녅녆녇녈녉녊녋녌녍녎녏념녑녒녓녔녕녖녗녘녙녚녛녜녝녞녟녠녡녢녣녤녥녦녧녨녩녪녫녬녭녮녯녰녱녲녳녴녵녶녷노녹녺녻논녽녾녿놀놁놂놃놄놅놆놇놈놉놊놋놌농놎놏놐놑높놓놔놕놖놗놘놙놚놛놜놝놞놟놠놡놢놣놤놥놦놧놨놩놪놫놬놭놮놯놰놱놲놳놴놵놶놷놸놹놺놻놼놽놾놿뇀뇁뇂뇃뇄뇅뇆뇇뇈뇉뇊뇋뇌뇍뇎뇏뇐뇑뇒뇓뇔뇕뇖뇗뇘뇙뇚뇛뇜뇝뇞뇟뇠뇡뇢뇣뇤뇥뇦뇧뇨뇩뇪뇫뇬뇭뇮뇯뇰뇱뇲뇳뇴뇵뇶뇷뇸뇹뇺뇻뇼뇽뇾뇿눀눁눂눃누눅눆눇눈눉눊눋눌눍눎눏눐눑눒눓눔눕눖눗눘눙눚눛눜눝눞눟눠눡눢눣눤눥눦눧눨눩눪눫눬눭눮눯눰눱눲눳눴눵눶눷눸눹눺눻눼눽눾눿뉀뉁뉂뉃뉄뉅뉆뉇뉈뉉뉊뉋뉌뉍뉎뉏뉐뉑뉒뉓뉔뉕뉖뉗뉘뉙뉚뉛뉜뉝뉞뉟뉠뉡뉢뉣뉤뉥뉦뉧뉨뉩뉪뉫뉬뉭뉮뉯뉰뉱뉲뉳뉴뉵뉶뉷뉸뉹뉺뉻뉼뉽뉾뉿늀늁늂늃늄늅늆늇늈늉늊늋늌늍늎늏느늑늒늓는늕늖늗늘늙늚늛늜늝늞늟늠늡늢늣늤능늦늧늨늩늪늫늬늭늮늯늰늱늲늳늴늵늶늷늸늹늺늻늼늽늾늿닀닁닂닃닄닅닆닇니닉닊닋닌닍닎닏닐닑닒닓닔닕닖닗님닙닚닛닜닝닞닟닠닡닢닣다닥닦닧단닩닪닫달닭닮닯닰닱닲닳담답닶닷닸당닺닻닼닽닾닿대댁댂댃댄댅댆댇댈댉댊댋댌댍댎댏댐댑댒댓댔댕댖댗댘댙댚댛댜댝댞댟댠댡댢댣댤댥댦댧댨댩댪댫댬댭댮댯댰댱댲댳댴댵댶댷댸댹댺댻댼댽댾댿덀덁덂덃덄덅덆덇덈덉덊덋덌덍덎덏덐덑덒덓더덕덖덗던덙덚덛덜덝덞덟덠덡덢덣덤덥덦덧덨덩덪덫덬덭덮덯데덱덲덳덴덵덶덷델덹덺덻덼덽덾덿뎀뎁뎂뎃뎄뎅뎆뎇뎈뎉뎊뎋뎌뎍뎎뎏뎐뎑뎒뎓뎔뎕뎖뎗뎘뎙뎚뎛뎜뎝뎞뎟뎠뎡뎢뎣뎤뎥뎦뎧뎨뎩뎪뎫뎬뎭뎮뎯뎰뎱뎲뎳뎴뎵뎶뎷뎸뎹뎺뎻뎼뎽뎾뎿돀돁돂돃도독돆돇돈돉돊돋돌돍돎돏돐돑돒돓돔돕돖돗돘동돚돛돜돝돞돟돠돡돢돣돤돥돦돧돨돩돪돫돬돭돮돯돰돱돲돳돴돵돶돷돸돹돺돻돼돽돾돿됀됁됂됃됄됅됆됇됈됉됊됋됌됍됎됏됐됑됒됓됔됕됖됗되됙됚됛된됝됞됟될됡됢됣됤됥됦됧됨됩됪됫됬됭됮됯됰됱됲됳됴됵됶됷됸됹됺됻됼됽됾됿둀둁둂둃둄둅둆둇둈둉둊둋둌둍둎둏두둑둒둓둔둕둖둗둘둙둚둛둜둝둞둟둠둡둢둣둤둥둦둧둨둩둪둫둬둭둮둯둰둱둲둳둴둵둶둷둸둹둺둻둼둽둾둿뒀뒁뒂뒃뒄뒅뒆뒇뒈뒉뒊뒋뒌뒍뒎뒏뒐뒑뒒뒓뒔뒕뒖뒗뒘뒙뒚뒛뒜뒝뒞뒟뒠뒡뒢뒣뒤뒥뒦뒧뒨뒩뒪뒫뒬뒭뒮뒯뒰뒱뒲뒳뒴뒵뒶뒷뒸뒹뒺뒻뒼뒽뒾뒿듀듁듂듃듄듅듆듇듈듉듊듋듌듍듎듏듐듑듒듓듔듕듖듗듘듙듚듛드득듞듟든듡듢듣들듥듦듧듨듩듪듫듬듭듮듯듰등듲듳듴듵듶듷듸듹듺듻듼듽듾듿딀딁딂딃딄딅딆딇딈딉딊딋딌딍딎딏딐딑딒딓디딕딖딗딘딙딚딛딜딝딞딟딠딡딢딣딤딥딦딧딨딩딪딫딬딭딮딯따딱딲딳딴딵딶딷딸딹딺딻딼딽딾딿땀땁땂땃땄땅땆땇땈땉땊땋때땍땎땏땐땑땒땓땔땕땖땗땘땙땚땛땜땝땞땟땠땡땢땣땤땥땦땧땨땩땪땫땬땭땮땯땰땱땲땳땴땵땶땷땸땹땺땻땼땽땾땿떀떁떂떃떄떅떆떇떈떉떊떋떌떍떎떏떐떑떒떓떔떕떖떗떘떙떚떛떜떝떞떟떠떡떢떣떤떥떦떧떨떩떪떫떬떭떮떯떰떱떲떳떴떵떶떷떸떹떺떻떼떽떾떿뗀뗁뗂뗃뗄뗅뗆뗇뗈뗉뗊뗋뗌뗍뗎뗏뗐뗑뗒뗓뗔뗕뗖뗗뗘뗙뗚뗛뗜뗝뗞뗟뗠뗡뗢뗣뗤뗥뗦뗧뗨뗩뗪뗫뗬뗭뗮뗯뗰뗱뗲뗳뗴뗵뗶뗷뗸뗹뗺뗻뗼뗽뗾뗿똀똁똂똃똄똅똆똇똈똉똊똋똌똍똎똏또똑똒똓똔똕똖똗똘똙똚똛똜똝똞똟똠똡똢똣똤똥똦똧똨똩똪똫똬똭똮똯똰똱똲똳똴똵똶똷똸똹똺똻똼똽똾똿뙀뙁뙂뙃뙄뙅뙆뙇뙈뙉뙊뙋뙌뙍뙎뙏뙐뙑뙒뙓뙔뙕뙖뙗뙘뙙뙚뙛뙜뙝뙞뙟뙠뙡뙢뙣뙤뙥뙦뙧뙨뙩뙪뙫뙬뙭뙮뙯뙰뙱뙲뙳뙴뙵뙶뙷뙸뙹뙺뙻뙼뙽뙾뙿뚀뚁뚂뚃뚄뚅뚆뚇뚈뚉뚊뚋뚌뚍뚎뚏뚐뚑뚒뚓뚔뚕뚖뚗뚘뚙뚚뚛뚜뚝뚞뚟뚠뚡뚢뚣뚤뚥뚦뚧뚨뚩뚪뚫뚬뚭뚮뚯뚰뚱뚲뚳뚴뚵뚶뚷뚸뚹뚺뚻뚼뚽뚾뚿뛀뛁뛂뛃뛄뛅뛆뛇뛈뛉뛊뛋뛌뛍뛎뛏뛐뛑뛒뛓뛔뛕뛖뛗뛘뛙뛚뛛뛜뛝뛞뛟뛠뛡뛢뛣뛤뛥뛦뛧뛨뛩뛪뛫뛬뛭뛮뛯뛰뛱뛲뛳뛴뛵뛶뛷뛸뛹뛺뛻뛼뛽뛾뛿뜀뜁뜂뜃뜄뜅뜆뜇뜈뜉뜊뜋뜌뜍뜎뜏뜐뜑뜒뜓뜔뜕뜖뜗뜘뜙뜚뜛뜜뜝뜞뜟뜠뜡뜢뜣뜤뜥뜦뜧뜨뜩뜪뜫뜬뜭뜮뜯뜰뜱뜲뜳뜴뜵뜶뜷뜸뜹뜺뜻뜼뜽뜾뜿띀띁띂띃띄띅띆띇띈띉띊띋띌띍띎띏띐띑띒띓띔띕띖띗띘띙띚띛띜띝띞띟띠띡띢띣띤띥띦띧띨띩띪띫띬띭띮띯띰띱띲띳띴띵띶띷띸띹띺띻라락띾띿란랁랂랃랄랅랆랇랈랉랊랋람랍랎랏랐랑랒랓랔랕랖랗래랙랚랛랜랝랞랟랠랡랢랣랤랥랦랧램랩랪랫랬랭랮랯랰랱랲랳랴략랶랷랸랹랺랻랼랽랾랿럀럁럂럃럄럅럆럇럈량럊럋럌럍럎럏럐럑럒럓럔럕럖럗럘럙럚럛럜럝럞럟럠럡럢럣럤럥럦럧럨럩럪럫러럭럮럯런럱럲럳럴럵럶럷럸럹럺럻럼럽럾럿렀렁렂렃렄렅렆렇레렉렊렋렌렍렎렏렐렑렒렓렔렕렖렗렘렙렚렛렜렝렞렟렠렡렢렣려력렦렧련렩렪렫렬렭렮렯렰렱렲렳렴렵렶렷렸령렺렻렼렽렾렿례롁롂롃롄롅롆롇롈롉롊롋롌롍롎롏롐롑롒롓롔롕롖롗롘롙롚롛로록롞롟론롡롢롣롤롥롦롧롨롩롪롫롬롭롮롯롰롱롲롳롴롵롶롷롸롹롺롻롼롽롾롿뢀뢁뢂뢃뢄뢅뢆뢇뢈뢉뢊뢋뢌뢍뢎뢏뢐뢑뢒뢓뢔뢕뢖뢗뢘뢙뢚뢛뢜뢝뢞뢟뢠뢡뢢뢣뢤뢥뢦뢧뢨뢩뢪뢫뢬뢭뢮뢯뢰뢱뢲뢳뢴뢵뢶뢷뢸뢹뢺뢻뢼뢽뢾뢿룀룁룂룃룄룅룆룇룈룉룊룋료룍룎룏룐룑룒룓룔룕룖룗룘룙룚룛룜룝룞룟룠룡룢룣룤룥룦룧루룩룪룫룬룭룮룯룰룱룲룳룴룵룶룷룸룹룺룻룼룽룾룿뤀뤁뤂뤃뤄뤅뤆뤇뤈뤉뤊뤋뤌뤍뤎뤏뤐뤑뤒뤓뤔뤕뤖뤗뤘뤙뤚뤛뤜뤝뤞뤟뤠뤡뤢뤣뤤뤥뤦뤧뤨뤩뤪뤫뤬뤭뤮뤯뤰뤱뤲뤳뤴뤵뤶뤷뤸뤹뤺뤻뤼뤽뤾뤿륀륁륂륃륄륅륆륇륈륉륊륋륌륍륎륏륐륑륒륓륔륕륖륗류륙륚륛륜륝륞륟률륡륢륣륤륥륦륧륨륩륪륫륬륭륮륯륰륱륲륳르륵륶륷른륹륺륻를륽륾륿릀릁릂릃름릅릆릇릈릉릊릋릌릍릎릏릐릑릒릓릔릕릖릗릘릙릚릛릜릝릞릟릠릡릢릣릤릥릦릧릨릩릪릫리릭릮릯린릱릲릳릴릵릶릷릸릹릺릻림립릾릿맀링맂맃맄맅맆맇마막맊맋만맍많맏말맑맒맓맔맕맖맗맘맙맚맛맜망맞맟맠맡맢맣매맥맦맧맨맩맪맫맬맭맮맯맰맱맲맳맴맵맶맷맸맹맺맻맼맽맾맿먀먁먂먃먄먅먆먇먈먉먊먋먌먍먎먏먐먑먒먓먔먕먖먗먘먙먚먛먜먝먞먟먠먡먢먣먤먥먦먧먨먩먪먫먬먭먮먯먰먱먲먳먴먵먶먷머먹먺먻먼먽먾먿멀멁멂멃멄멅멆멇멈멉멊멋멌멍멎멏멐멑멒멓메멕멖멗멘멙멚멛멜멝멞멟멠멡멢멣멤멥멦멧멨멩멪멫멬멭멮멯며멱멲멳면멵멶멷멸멹멺멻멼멽멾멿몀몁몂몃몄명몆몇몈몉몊몋몌몍몎몏몐몑몒몓몔몕몖몗몘몙몚몛몜몝몞몟몠몡몢몣몤몥몦몧모목몪몫몬몭몮몯몰몱몲몳몴몵몶몷몸몹몺못몼몽몾몿뫀뫁뫂뫃뫄뫅뫆뫇뫈뫉뫊뫋뫌뫍뫎뫏뫐뫑뫒뫓뫔뫕뫖뫗뫘뫙뫚뫛뫜뫝뫞뫟뫠뫡뫢뫣뫤뫥뫦뫧뫨뫩뫪뫫뫬뫭뫮뫯뫰뫱뫲뫳뫴뫵뫶뫷뫸뫹뫺뫻뫼뫽뫾뫿묀묁묂묃묄묅묆묇묈묉묊묋묌묍묎묏묐묑묒묓묔묕묖묗묘묙묚묛묜묝묞묟묠묡묢묣묤묥묦묧묨묩묪묫묬묭묮묯묰묱묲묳무묵묶묷문묹묺묻물묽묾묿뭀뭁뭂뭃뭄뭅뭆뭇뭈뭉뭊뭋뭌뭍뭎뭏뭐뭑뭒뭓뭔뭕뭖뭗뭘뭙뭚뭛뭜뭝뭞뭟뭠뭡뭢뭣뭤뭥뭦뭧뭨뭩뭪뭫뭬뭭뭮뭯뭰뭱뭲뭳뭴뭵뭶뭷뭸뭹뭺뭻뭼뭽뭾뭿뮀뮁뮂뮃뮄뮅뮆뮇뮈뮉뮊뮋뮌뮍뮎뮏뮐뮑뮒뮓뮔뮕뮖뮗뮘뮙뮚뮛뮜뮝뮞뮟뮠뮡뮢뮣뮤뮥뮦뮧뮨뮩뮪뮫뮬뮭뮮뮯뮰뮱뮲뮳뮴뮵뮶뮷뮸뮹뮺뮻뮼뮽뮾뮿므믁믂믃믄믅믆믇믈믉믊믋믌믍믎믏믐믑믒믓믔믕믖믗믘믙믚믛믜믝믞믟믠믡믢믣믤믥믦믧믨믩믪믫믬믭믮믯믰믱믲믳믴믵믶믷미믹믺믻민믽믾믿밀밁밂밃밄밅밆밇밈밉밊밋밌밍밎및밐밑밒밓바박밖밗반밙밚받발밝밞밟밠밡밢밣밤밥밦밧밨방밪밫밬밭밮밯배백밲밳밴밵밶밷밸밹밺밻밼밽밾밿뱀뱁뱂뱃뱄뱅뱆뱇뱈뱉뱊뱋뱌뱍뱎뱏뱐뱑뱒뱓뱔뱕뱖뱗뱘뱙뱚뱛뱜뱝뱞뱟뱠뱡뱢뱣뱤뱥뱦뱧뱨뱩뱪뱫뱬뱭뱮뱯뱰뱱뱲뱳뱴뱵뱶뱷뱸뱹뱺뱻뱼뱽뱾뱿벀벁벂벃버벅벆벇번벉벊벋벌벍벎벏벐벑벒벓범법벖벗벘벙벚벛벜벝벞벟베벡벢벣벤벥벦벧벨벩벪벫벬벭벮벯벰벱벲벳벴벵벶벷벸벹벺벻벼벽벾벿변볁볂볃별볅볆볇볈볉볊볋볌볍볎볏볐병볒볓볔볕볖볗볘볙볚볛볜볝볞볟볠볡볢볣볤볥볦볧볨볩볪볫볬볭볮볯볰볱볲볳보복볶볷본볹볺볻볼볽볾볿봀봁봂봃봄봅봆봇봈봉봊봋봌봍봎봏봐봑봒봓봔봕봖봗봘봙봚봛봜봝봞봟봠봡봢봣봤봥봦봧봨봩봪봫봬봭봮봯봰봱봲봳봴봵봶봷봸봹봺봻봼봽봾봿뵀뵁뵂뵃뵄뵅뵆뵇뵈뵉뵊뵋뵌뵍뵎뵏뵐뵑뵒뵓뵔뵕뵖뵗뵘뵙뵚뵛뵜뵝뵞뵟뵠뵡뵢뵣뵤뵥뵦뵧뵨뵩뵪뵫뵬뵭뵮뵯뵰뵱뵲뵳뵴뵵뵶뵷뵸뵹뵺뵻뵼뵽뵾뵿부북붂붃분붅붆붇불붉붊붋붌붍붎붏붐붑붒붓붔붕붖붗붘붙붚붛붜붝붞붟붠붡붢붣붤붥붦붧붨붩붪붫붬붭붮붯붰붱붲붳붴붵붶붷붸붹붺붻붼붽붾붿뷀뷁뷂뷃뷄뷅뷆뷇뷈뷉뷊뷋뷌뷍뷎뷏뷐뷑뷒뷓뷔뷕뷖뷗뷘뷙뷚뷛뷜뷝뷞뷟뷠뷡뷢뷣뷤뷥뷦뷧뷨뷩뷪뷫뷬뷭뷮뷯뷰뷱뷲뷳뷴뷵뷶뷷뷸뷹뷺뷻뷼뷽뷾뷿븀븁븂븃븄븅븆븇븈븉븊븋브븍븎븏븐븑븒븓블븕븖븗븘븙븚븛븜븝븞븟븠븡븢븣븤븥븦븧븨븩븪븫븬븭븮븯븰븱븲븳븴븵븶븷븸븹븺븻븼븽븾븿빀빁빂빃비빅빆빇빈빉빊빋빌빍빎빏빐빑빒빓빔빕빖빗빘빙빚빛빜빝빞빟빠빡빢빣빤빥빦빧빨빩빪빫빬빭빮빯빰빱빲빳빴빵빶빷빸빹빺빻빼빽빾빿뺀뺁뺂뺃뺄뺅뺆뺇뺈뺉뺊뺋뺌뺍뺎뺏뺐뺑뺒뺓뺔뺕뺖뺗뺘뺙뺚뺛뺜뺝뺞뺟뺠뺡뺢뺣뺤뺥뺦뺧뺨뺩뺪뺫뺬뺭뺮뺯뺰뺱뺲뺳뺴뺵뺶뺷뺸뺹뺺뺻뺼뺽뺾뺿뻀뻁뻂뻃뻄뻅뻆뻇뻈뻉뻊뻋뻌뻍뻎뻏뻐뻑뻒뻓뻔뻕뻖뻗뻘뻙뻚뻛뻜뻝뻞뻟뻠뻡뻢뻣뻤뻥뻦뻧뻨뻩뻪뻫뻬뻭뻮뻯뻰뻱뻲뻳뻴뻵뻶뻷뻸뻹뻺뻻뻼뻽뻾뻿뼀뼁뼂뼃뼄뼅뼆뼇뼈뼉뼊뼋뼌뼍뼎뼏뼐뼑뼒뼓뼔뼕뼖뼗뼘뼙뼚뼛뼜뼝뼞뼟뼠뼡뼢뼣뼤뼥뼦뼧뼨뼩뼪뼫뼬뼭뼮뼯뼰뼱뼲뼳뼴뼵뼶뼷뼸뼹뼺뼻뼼뼽뼾뼿뽀뽁뽂뽃뽄뽅뽆뽇뽈뽉뽊뽋뽌뽍뽎뽏뽐뽑뽒뽓뽔뽕뽖뽗뽘뽙뽚뽛뽜뽝뽞뽟뽠뽡뽢뽣뽤뽥뽦뽧뽨뽩뽪뽫뽬뽭뽮뽯뽰뽱뽲뽳뽴뽵뽶뽷뽸뽹뽺뽻뽼뽽뽾뽿뾀뾁뾂뾃뾄뾅뾆뾇뾈뾉뾊뾋뾌뾍뾎뾏뾐뾑뾒뾓뾔뾕뾖뾗뾘뾙뾚뾛뾜뾝뾞뾟뾠뾡뾢뾣뾤뾥뾦뾧뾨뾩뾪뾫뾬뾭뾮뾯뾰뾱뾲뾳뾴뾵뾶뾷뾸뾹뾺뾻뾼뾽뾾뾿뿀뿁뿂뿃뿄뿅뿆뿇뿈뿉뿊뿋뿌뿍뿎뿏뿐뿑뿒뿓뿔뿕뿖뿗뿘뿙뿚뿛뿜뿝뿞뿟뿠뿡뿢뿣뿤뿥뿦뿧뿨뿩뿪뿫뿬뿭뿮뿯뿰뿱뿲뿳뿴뿵뿶뿷뿸뿹뿺뿻뿼뿽뿾뿿쀀쀁쀂쀃쀄쀅쀆쀇쀈쀉쀊쀋쀌쀍쀎쀏쀐쀑쀒쀓쀔쀕쀖쀗쀘쀙쀚쀛쀜쀝쀞쀟쀠쀡쀢쀣쀤쀥쀦쀧쀨쀩쀪쀫쀬쀭쀮쀯쀰쀱쀲쀳쀴쀵쀶쀷쀸쀹쀺쀻쀼쀽쀾쀿쁀쁁쁂쁃쁄쁅쁆쁇쁈쁉쁊쁋쁌쁍쁎쁏쁐쁑쁒쁓쁔쁕쁖쁗쁘쁙쁚쁛쁜쁝쁞쁟쁠쁡쁢쁣쁤쁥쁦쁧쁨쁩쁪쁫쁬쁭쁮쁯쁰쁱쁲쁳쁴쁵쁶쁷쁸쁹쁺쁻쁼쁽쁾쁿삀삁삂삃삄삅삆삇삈삉삊삋삌삍삎삏삐삑삒삓삔삕삖삗삘삙삚삛삜삝삞삟삠삡삢삣삤삥삦삧삨삩삪삫사삭삮삯산삱삲삳살삵삶삷삸삹삺삻삼삽삾삿샀상샂샃샄샅샆샇새색샊샋샌샍샎샏샐샑샒샓샔샕샖샗샘샙샚샛샜생샞샟샠샡샢샣샤샥샦샧샨샩샪샫샬샭샮샯샰샱샲샳샴샵샶샷샸샹샺샻샼샽샾샿섀섁섂섃섄섅섆섇섈섉섊섋섌섍섎섏섐섑섒섓섔섕섖섗섘섙섚섛서석섞섟선섡섢섣설섥섦섧섨섩섪섫섬섭섮섯섰성섲섳섴섵섶섷세섹섺섻센섽섾섿셀셁셂셃셄셅셆셇셈셉셊셋셌셍셎셏셐셑셒셓셔셕셖셗션셙셚셛셜셝셞셟셠셡셢셣셤셥셦셧셨셩셪셫셬셭셮셯셰셱셲셳셴셵셶셷셸셹셺셻셼셽셾셿솀솁솂솃솄솅솆솇솈솉솊솋소속솎솏손솑솒솓솔솕솖솗솘솙솚솛솜솝솞솟솠송솢솣솤솥솦솧솨솩솪솫솬솭솮솯솰솱솲솳솴솵솶솷솸솹솺솻솼솽솾솿쇀쇁쇂쇃쇄쇅쇆쇇쇈쇉쇊쇋쇌쇍쇎쇏쇐쇑쇒쇓쇔쇕쇖쇗쇘쇙쇚쇛쇜쇝쇞쇟쇠쇡쇢쇣쇤쇥쇦쇧쇨쇩쇪쇫쇬쇭쇮쇯쇰쇱쇲쇳쇴쇵쇶쇷쇸쇹쇺쇻쇼쇽쇾쇿숀숁숂숃숄숅숆숇숈숉숊숋숌숍숎숏숐숑숒숓숔숕숖숗수숙숚숛순숝숞숟술숡숢숣숤숥숦숧숨숩숪숫숬숭숮숯숰숱숲숳숴숵숶숷숸숹숺숻숼숽숾숿쉀쉁쉂쉃쉄쉅쉆쉇쉈쉉쉊쉋쉌쉍쉎쉏쉐쉑쉒쉓쉔쉕쉖쉗쉘쉙쉚쉛쉜쉝쉞쉟쉠쉡쉢쉣쉤쉥쉦쉧쉨쉩쉪쉫쉬쉭쉮쉯쉰쉱쉲쉳쉴쉵쉶쉷쉸쉹쉺쉻쉼쉽쉾쉿슀슁슂슃슄슅슆슇슈슉슊슋슌슍슎슏슐슑슒슓슔슕슖슗슘슙슚슛슜슝슞슟슠슡슢슣스슥슦슧슨슩슪슫슬슭슮슯슰슱슲슳슴습슶슷슸승슺슻슼슽슾슿싀싁싂싃싄싅싆싇싈싉싊싋싌싍싎싏싐싑싒싓싔싕싖싗싘싙싚싛시식싞싟신싡싢싣실싥싦싧싨싩싪싫심십싮싯싰싱싲싳싴싵싶싷싸싹싺싻싼싽싾싿쌀쌁쌂쌃쌄쌅쌆쌇쌈쌉쌊쌋쌌쌍쌎쌏쌐쌑쌒쌓쌔쌕쌖쌗쌘쌙쌚쌛쌜쌝쌞쌟쌠쌡쌢쌣쌤쌥쌦쌧쌨쌩쌪쌫쌬쌭쌮쌯쌰쌱쌲쌳쌴쌵쌶쌷쌸쌹쌺쌻쌼쌽쌾쌿썀썁썂썃썄썅썆썇썈썉썊썋썌썍썎썏썐썑썒썓썔썕썖썗썘썙썚썛썜썝썞썟썠썡썢썣썤썥썦썧써썩썪썫썬썭썮썯썰썱썲썳썴썵썶썷썸썹썺썻썼썽썾썿쎀쎁쎂쎃쎄쎅쎆쎇쎈쎉쎊쎋쎌쎍쎎쎏쎐쎑쎒쎓쎔쎕쎖쎗쎘쎙쎚쎛쎜쎝쎞쎟쎠쎡쎢쎣쎤쎥쎦쎧쎨쎩쎪쎫쎬쎭쎮쎯쎰쎱쎲쎳쎴쎵쎶쎷쎸쎹쎺쎻쎼쎽쎾쎿쏀쏁쏂쏃쏄쏅쏆쏇쏈쏉쏊쏋쏌쏍쏎쏏쏐쏑쏒쏓쏔쏕쏖쏗쏘쏙쏚쏛쏜쏝쏞쏟쏠쏡쏢쏣쏤쏥쏦쏧쏨쏩쏪쏫쏬쏭쏮쏯쏰쏱쏲쏳쏴쏵쏶쏷쏸쏹쏺쏻쏼쏽쏾쏿쐀쐁쐂쐃쐄쐅쐆쐇쐈쐉쐊쐋쐌쐍쐎쐏쐐쐑쐒쐓쐔쐕쐖쐗쐘쐙쐚쐛쐜쐝쐞쐟쐠쐡쐢쐣쐤쐥쐦쐧쐨쐩쐪쐫쐬쐭쐮쐯쐰쐱쐲쐳쐴쐵쐶쐷쐸쐹쐺쐻쐼쐽쐾쐿쑀쑁쑂쑃쑄쑅쑆쑇쑈쑉쑊쑋쑌쑍쑎쑏쑐쑑쑒쑓쑔쑕쑖쑗쑘쑙쑚쑛쑜쑝쑞쑟쑠쑡쑢쑣쑤쑥쑦쑧쑨쑩쑪쑫쑬쑭쑮쑯쑰쑱쑲쑳쑴쑵쑶쑷쑸쑹쑺쑻쑼쑽쑾쑿쒀쒁쒂쒃쒄쒅쒆쒇쒈쒉쒊쒋쒌쒍쒎쒏쒐쒑쒒쒓쒔쒕쒖쒗쒘쒙쒚쒛쒜쒝쒞쒟쒠쒡쒢쒣쒤쒥쒦쒧쒨쒩쒪쒫쒬쒭쒮쒯쒰쒱쒲쒳쒴쒵쒶쒷쒸쒹쒺쒻쒼쒽쒾쒿쓀쓁쓂쓃쓄쓅쓆쓇쓈쓉쓊쓋쓌쓍쓎쓏쓐쓑쓒쓓쓔쓕쓖쓗쓘쓙쓚쓛쓜쓝쓞쓟쓠쓡쓢쓣쓤쓥쓦쓧쓨쓩쓪쓫쓬쓭쓮쓯쓰쓱쓲쓳쓴쓵쓶쓷쓸쓹쓺쓻쓼쓽쓾쓿씀씁씂씃씄씅씆씇씈씉씊씋씌씍씎씏씐씑씒씓씔씕씖씗씘씙씚씛씜씝씞씟씠씡씢씣씤씥씦씧씨씩씪씫씬씭씮씯씰씱씲씳씴씵씶씷씸씹씺씻씼씽씾씿앀앁앂앃아악앆앇안앉않앋알앍앎앏앐앑앒앓암압앖앗았앙앚앛앜앝앞앟애액앢앣앤앥앦앧앨앩앪앫앬앭앮앯앰앱앲앳앴앵앶앷앸앹앺앻야약앾앿얀얁얂얃얄얅얆얇얈얉얊얋얌얍얎얏얐양얒얓얔얕얖얗얘얙얚얛얜얝얞얟얠얡얢얣얤얥얦얧얨얩얪얫얬얭얮얯얰얱얲얳어억얶얷언얹얺얻얼얽얾얿엀엁엂엃엄업없엇었엉엊엋엌엍엎엏에엑엒엓엔엕엖엗엘엙엚엛엜엝엞엟엠엡엢엣엤엥엦엧엨엩엪엫여역엮엯연엱엲엳열엵엶엷엸엹엺엻염엽엾엿였영옂옃옄옅옆옇예옉옊옋옌옍옎옏옐옑옒옓옔옕옖옗옘옙옚옛옜옝옞옟옠옡옢옣오옥옦옧온옩옪옫올옭옮옯옰옱옲옳옴옵옶옷옸옹옺옻옼옽옾옿와왁왂왃완왅왆왇왈왉왊왋왌왍왎왏왐왑왒왓왔왕왖왗왘왙왚왛왜왝왞왟왠왡왢왣왤왥왦왧왨왩왪왫왬왭왮왯왰왱왲왳왴왵왶왷외왹왺왻왼왽왾왿욀욁욂욃욄욅욆욇욈욉욊욋욌욍욎욏욐욑욒욓요욕욖욗욘욙욚욛욜욝욞욟욠욡욢욣욤욥욦욧욨용욪욫욬욭욮욯우욱욲욳운욵욶욷울욹욺욻욼욽욾욿움웁웂웃웄웅웆웇웈웉웊웋워웍웎웏원웑웒웓월웕웖웗웘웙웚웛웜웝웞웟웠웡웢웣웤웥웦웧웨웩웪웫웬웭웮웯웰웱웲웳웴웵웶웷웸웹웺웻웼웽웾웿윀윁윂윃위윅윆윇윈윉윊윋윌윍윎윏윐윑윒윓윔윕윖윗윘윙윚윛윜윝윞윟유육윢윣윤윥윦윧율윩윪윫윬윭윮윯윰윱윲윳윴융윶윷윸윹윺윻으윽윾윿은읁읂읃을읅읆읇읈읉읊읋음읍읎읏읐응읒읓읔읕읖읗의읙읚읛읜읝읞읟읠읡읢읣읤읥읦읧읨읩읪읫읬읭읮읯읰읱읲읳이익읶읷인읹읺읻일읽읾읿잀잁잂잃임입잆잇있잉잊잋잌잍잎잏자작잒잓잔잕잖잗잘잙잚잛잜잝잞잟잠잡잢잣잤장잦잧잨잩잪잫재잭잮잯잰잱잲잳잴잵잶잷잸잹잺잻잼잽잾잿쟀쟁쟂쟃쟄쟅쟆쟇쟈쟉쟊쟋쟌쟍쟎쟏쟐쟑쟒쟓쟔쟕쟖쟗쟘쟙쟚쟛쟜쟝쟞쟟쟠쟡쟢쟣쟤쟥쟦쟧쟨쟩쟪쟫쟬쟭쟮쟯쟰쟱쟲쟳쟴쟵쟶쟷쟸쟹쟺쟻쟼쟽쟾쟿저적젂젃전젅젆젇절젉젊젋젌젍젎젏점접젒젓젔정젖젗젘젙젚젛제젝젞젟젠젡젢젣젤젥젦젧젨젩젪젫젬젭젮젯젰젱젲젳젴젵젶젷져젹젺젻젼젽젾젿졀졁졂졃졄졅졆졇졈졉졊졋졌졍졎졏졐졑졒졓졔졕졖졗졘졙졚졛졜졝졞졟졠졡졢졣졤졥졦졧졨졩졪졫졬졭졮졯조족졲졳존졵졶졷졸졹졺졻졼졽졾졿좀좁좂좃좄종좆좇좈좉좊좋좌좍좎좏좐좑좒좓좔좕좖좗좘좙좚좛좜좝좞좟좠좡좢좣좤좥좦좧좨좩좪좫좬좭좮좯좰좱좲좳좴좵좶좷좸좹좺좻좼좽좾좿죀죁죂죃죄죅죆죇죈죉죊죋죌죍죎죏죐죑죒죓죔죕죖죗죘죙죚죛죜죝죞죟죠죡죢죣죤죥죦죧죨죩죪죫죬죭죮죯죰죱죲죳죴죵죶죷죸죹죺죻주죽죾죿준줁줂줃줄줅줆줇줈줉줊줋줌줍줎줏줐중줒줓줔줕줖줗줘줙줚줛줜줝줞줟줠줡줢줣줤줥줦줧줨줩줪줫줬줭줮줯줰줱줲줳줴줵줶줷줸줹줺줻줼줽줾줿쥀쥁쥂쥃쥄쥅쥆쥇쥈쥉쥊쥋쥌쥍쥎쥏쥐쥑쥒쥓쥔쥕쥖쥗쥘쥙쥚쥛쥜쥝쥞쥟쥠쥡쥢쥣쥤쥥쥦쥧쥨쥩쥪쥫쥬쥭쥮쥯쥰쥱쥲쥳쥴쥵쥶쥷쥸쥹쥺쥻쥼쥽쥾쥿즀즁즂즃즄즅즆즇즈즉즊즋즌즍즎즏즐즑즒즓즔즕즖즗즘즙즚즛즜증즞즟즠즡즢즣즤즥즦즧즨즩즪즫즬즭즮즯즰즱즲즳즴즵즶즷즸즹즺즻즼즽즾즿지직짂짃진짅짆짇질짉짊짋짌짍짎짏짐집짒짓짔징짖짗짘짙짚짛짜짝짞짟짠짡짢짣짤짥짦짧짨짩짪짫짬짭짮짯짰짱짲짳짴짵짶짷째짹짺짻짼짽짾짿쨀쨁쨂쨃쨄쨅쨆쨇쨈쨉쨊쨋쨌쨍쨎쨏쨐쨑쨒쨓쨔쨕쨖쨗쨘쨙쨚쨛쨜쨝쨞쨟쨠쨡쨢쨣쨤쨥쨦쨧쨨쨩쨪쨫쨬쨭쨮쨯쨰쨱쨲쨳쨴쨵쨶쨷쨸쨹쨺쨻쨼쨽쨾쨿쩀쩁쩂쩃쩄쩅쩆쩇쩈쩉쩊쩋쩌쩍쩎쩏쩐쩑쩒쩓쩔쩕쩖쩗쩘쩙쩚쩛쩜쩝쩞쩟쩠쩡쩢쩣쩤쩥쩦쩧쩨쩩쩪쩫쩬쩭쩮쩯쩰쩱쩲쩳쩴쩵쩶쩷쩸쩹쩺쩻쩼쩽쩾쩿쪀쪁쪂쪃쪄쪅쪆쪇쪈쪉쪊쪋쪌쪍쪎쪏쪐쪑쪒쪓쪔쪕쪖쪗쪘쪙쪚쪛쪜쪝쪞쪟쪠쪡쪢쪣쪤쪥쪦쪧쪨쪩쪪쪫쪬쪭쪮쪯쪰쪱쪲쪳쪴쪵쪶쪷쪸쪹쪺쪻쪼쪽쪾쪿쫀쫁쫂쫃쫄쫅쫆쫇쫈쫉쫊쫋쫌쫍쫎쫏쫐쫑쫒쫓쫔쫕쫖쫗쫘쫙쫚쫛쫜쫝쫞쫟쫠쫡쫢쫣쫤쫥쫦쫧쫨쫩쫪쫫쫬쫭쫮쫯쫰쫱쫲쫳쫴쫵쫶쫷쫸쫹쫺쫻쫼쫽쫾쫿쬀쬁쬂쬃쬄쬅쬆쬇쬈쬉쬊쬋쬌쬍쬎쬏쬐쬑쬒쬓쬔쬕쬖쬗쬘쬙쬚쬛쬜쬝쬞쬟쬠쬡쬢쬣쬤쬥쬦쬧쬨쬩쬪쬫쬬쬭쬮쬯쬰쬱쬲쬳쬴쬵쬶쬷쬸쬹쬺쬻쬼쬽쬾쬿쭀쭁쭂쭃쭄쭅쭆쭇쭈쭉쭊쭋쭌쭍쭎쭏쭐쭑쭒쭓쭔쭕쭖쭗쭘쭙쭚쭛쭜쭝쭞쭟쭠쭡쭢쭣쭤쭥쭦쭧쭨쭩쭪쭫쭬쭭쭮쭯쭰쭱쭲쭳쭴쭵쭶쭷쭸쭹쭺쭻쭼쭽쭾쭿쮀쮁쮂쮃쮄쮅쮆쮇쮈쮉쮊쮋쮌쮍쮎쮏쮐쮑쮒쮓쮔쮕쮖쮗쮘쮙쮚쮛쮜쮝쮞쮟쮠쮡쮢쮣쮤쮥쮦쮧쮨쮩쮪쮫쮬쮭쮮쮯쮰쮱쮲쮳쮴쮵쮶쮷쮸쮹쮺쮻쮼쮽쮾쮿쯀쯁쯂쯃쯄쯅쯆쯇쯈쯉쯊쯋쯌쯍쯎쯏쯐쯑쯒쯓쯔쯕쯖쯗쯘쯙쯚쯛쯜쯝쯞쯟쯠쯡쯢쯣쯤쯥쯦쯧쯨쯩쯪쯫쯬쯭쯮쯯쯰쯱쯲쯳쯴쯵쯶쯷쯸쯹쯺쯻쯼쯽쯾쯿찀찁찂찃찄찅찆찇찈찉찊찋찌찍찎찏찐찑찒찓찔찕찖찗찘찙찚찛찜찝찞찟찠찡찢찣찤찥찦찧차착찪찫찬찭찮찯찰찱찲찳찴찵찶찷참찹찺찻찼창찾찿챀챁챂챃채책챆챇챈챉챊챋챌챍챎챏챐챑챒챓챔챕챖챗챘챙챚챛챜챝챞챟챠챡챢챣챤챥챦챧챨챩챪챫챬챭챮챯챰챱챲챳챴챵챶챷챸챹챺챻챼챽챾챿첀첁첂첃첄첅첆첇첈첉첊첋첌첍첎첏첐첑첒첓첔첕첖첗처척첚첛천첝첞첟철첡첢첣첤첥첦첧첨첩첪첫첬청첮첯첰첱첲첳체첵첶첷첸첹첺첻첼첽첾첿쳀쳁쳂쳃쳄쳅쳆쳇쳈쳉쳊쳋쳌쳍쳎쳏쳐쳑쳒쳓쳔쳕쳖쳗쳘쳙쳚쳛쳜쳝쳞쳟쳠쳡쳢쳣쳤쳥쳦쳧쳨쳩쳪쳫쳬쳭쳮쳯쳰쳱쳲쳳쳴쳵쳶쳷쳸쳹쳺쳻쳼쳽쳾쳿촀촁촂촃촄촅촆촇초촉촊촋촌촍촎촏촐촑촒촓촔촕촖촗촘촙촚촛촜총촞촟촠촡촢촣촤촥촦촧촨촩촪촫촬촭촮촯촰촱촲촳촴촵촶촷촸촹촺촻촼촽촾촿쵀쵁쵂쵃쵄쵅쵆쵇쵈쵉쵊쵋쵌쵍쵎쵏쵐쵑쵒쵓쵔쵕쵖쵗쵘쵙쵚쵛최쵝쵞쵟쵠쵡쵢쵣쵤쵥쵦쵧쵨쵩쵪쵫쵬쵭쵮쵯쵰쵱쵲쵳쵴쵵쵶쵷쵸쵹쵺쵻쵼쵽쵾쵿춀춁춂춃춄춅춆춇춈춉춊춋춌춍춎춏춐춑춒춓추축춖춗춘춙춚춛출춝춞춟춠춡춢춣춤춥춦춧춨충춪춫춬춭춮춯춰춱춲춳춴춵춶춷춸춹춺춻춼춽춾춿췀췁췂췃췄췅췆췇췈췉췊췋췌췍췎췏췐췑췒췓췔췕췖췗췘췙췚췛췜췝췞췟췠췡췢췣췤췥췦췧취췩췪췫췬췭췮췯췰췱췲췳췴췵췶췷췸췹췺췻췼췽췾췿츀츁츂츃츄츅츆츇츈츉츊츋츌츍츎츏츐츑츒츓츔츕츖츗츘츙츚츛츜츝츞츟츠측츢츣츤츥츦츧츨츩츪츫츬츭츮츯츰츱츲츳츴층츶츷츸츹츺츻츼츽츾츿칀칁칂칃칄칅칆칇칈칉칊칋칌칍칎칏칐칑칒칓칔칕칖칗치칙칚칛친칝칞칟칠칡칢칣칤칥칦칧침칩칪칫칬칭칮칯칰칱칲칳카칵칶칷칸칹칺칻칼칽칾칿캀캁캂캃캄캅캆캇캈캉캊캋캌캍캎캏캐캑캒캓캔캕캖캗캘캙캚캛캜캝캞캟캠캡캢캣캤캥캦캧캨캩캪캫캬캭캮캯캰캱캲캳캴캵캶캷캸캹캺캻캼캽캾캿컀컁컂컃컄컅컆컇컈컉컊컋컌컍컎컏컐컑컒컓컔컕컖컗컘컙컚컛컜컝컞컟컠컡컢컣커컥컦컧컨컩컪컫컬컭컮컯컰컱컲컳컴컵컶컷컸컹컺컻컼컽컾컿케켁켂켃켄켅켆켇켈켉켊켋켌켍켎켏켐켑켒켓켔켕켖켗켘켙켚켛켜켝켞켟켠켡켢켣켤켥켦켧켨켩켪켫켬켭켮켯켰켱켲켳켴켵켶켷켸켹켺켻켼켽켾켿콀콁콂콃콄콅콆콇콈콉콊콋콌콍콎콏콐콑콒콓코콕콖콗콘콙콚콛콜콝콞콟콠콡콢콣콤콥콦콧콨콩콪콫콬콭콮콯콰콱콲콳콴콵콶콷콸콹콺콻콼콽콾콿쾀쾁쾂쾃쾄쾅쾆쾇쾈쾉쾊쾋쾌쾍쾎쾏쾐쾑쾒쾓쾔쾕쾖쾗쾘쾙쾚쾛쾜쾝쾞쾟쾠쾡쾢쾣쾤쾥쾦쾧쾨쾩쾪쾫쾬쾭쾮쾯쾰쾱쾲쾳쾴쾵쾶쾷쾸쾹쾺쾻쾼쾽쾾쾿쿀쿁쿂쿃쿄쿅쿆쿇쿈쿉쿊쿋쿌쿍쿎쿏쿐쿑쿒쿓쿔쿕쿖쿗쿘쿙쿚쿛쿜쿝쿞쿟쿠쿡쿢쿣쿤쿥쿦쿧쿨쿩쿪쿫쿬쿭쿮쿯쿰쿱쿲쿳쿴쿵쿶쿷쿸쿹쿺쿻쿼쿽쿾쿿퀀퀁퀂퀃퀄퀅퀆퀇퀈퀉퀊퀋퀌퀍퀎퀏퀐퀑퀒퀓퀔퀕퀖퀗퀘퀙퀚퀛퀜퀝퀞퀟퀠퀡퀢퀣퀤퀥퀦퀧퀨퀩퀪퀫퀬퀭퀮퀯퀰퀱퀲퀳퀴퀵퀶퀷퀸퀹퀺퀻퀼퀽퀾퀿큀큁큂큃큄큅큆큇큈큉큊큋큌큍큎큏큐큑큒큓큔큕큖큗큘큙큚큛큜큝큞큟큠큡큢큣큤큥큦큧큨큩큪큫크큭큮큯큰큱큲큳클큵큶큷큸큹큺큻큼큽큾큿킀킁킂킃킄킅킆킇킈킉킊킋킌킍킎킏킐킑킒킓킔킕킖킗킘킙킚킛킜킝킞킟킠킡킢킣키킥킦킧킨킩킪킫킬킭킮킯킰킱킲킳킴킵킶킷킸킹킺킻킼킽킾킿타탁탂탃탄탅탆탇탈탉탊탋탌탍탎탏탐탑탒탓탔탕탖탗탘탙탚탛태택탞탟탠탡탢탣탤탥탦탧탨탩탪탫탬탭탮탯탰탱탲탳탴탵탶탷탸탹탺탻탼탽탾탿턀턁턂턃턄턅턆턇턈턉턊턋턌턍턎턏턐턑턒턓턔턕턖턗턘턙턚턛턜턝턞턟턠턡턢턣턤턥턦턧턨턩턪턫턬턭턮턯터턱턲턳턴턵턶턷털턹턺턻턼턽턾턿텀텁텂텃텄텅텆텇텈텉텊텋테텍텎텏텐텑텒텓텔텕텖텗텘텙텚텛템텝텞텟텠텡텢텣텤텥텦텧텨텩텪텫텬텭텮텯텰텱텲텳텴텵텶텷텸텹텺텻텼텽텾텿톀톁톂톃톄톅톆톇톈톉톊톋톌톍톎톏톐톑톒톓톔톕톖톗톘톙톚톛톜톝톞톟토톡톢톣톤톥톦톧톨톩톪톫톬톭톮톯톰톱톲톳톴통톶톷톸톹톺톻톼톽톾톿퇀퇁퇂퇃퇄퇅퇆퇇퇈퇉퇊퇋퇌퇍퇎퇏퇐퇑퇒퇓퇔퇕퇖퇗퇘퇙퇚퇛퇜퇝퇞퇟퇠퇡퇢퇣퇤퇥퇦퇧퇨퇩퇪퇫퇬퇭퇮퇯퇰퇱퇲퇳퇴퇵퇶퇷퇸퇹퇺퇻퇼퇽퇾퇿툀툁툂툃툄툅툆툇툈툉툊툋툌툍툎툏툐툑툒툓툔툕툖툗툘툙툚툛툜툝툞툟툠툡툢툣툤툥툦툧툨툩툪툫투툭툮툯툰툱툲툳툴툵툶툷툸툹툺툻툼툽툾툿퉀퉁퉂퉃퉄퉅퉆퉇퉈퉉퉊퉋퉌퉍퉎퉏퉐퉑퉒퉓퉔퉕퉖퉗퉘퉙퉚퉛퉜퉝퉞퉟퉠퉡퉢퉣퉤퉥퉦퉧퉨퉩퉪퉫퉬퉭퉮퉯퉰퉱퉲퉳퉴퉵퉶퉷퉸퉹퉺퉻퉼퉽퉾퉿튀튁튂튃튄튅튆튇튈튉튊튋튌튍튎튏튐튑튒튓튔튕튖튗튘튙튚튛튜튝튞튟튠튡튢튣튤튥튦튧튨튩튪튫튬튭튮튯튰튱튲튳튴튵튶튷트특튺튻튼튽튾튿틀틁틂틃틄틅틆틇틈틉틊틋틌틍틎틏틐틑틒틓틔틕틖틗틘틙틚틛틜틝틞틟틠틡틢틣틤틥틦틧틨틩틪틫틬틭틮틯티틱틲틳틴틵틶틷틸틹틺틻틼틽틾틿팀팁팂팃팄팅팆팇팈팉팊팋파팍팎팏판팑팒팓팔팕팖팗팘팙팚팛팜팝팞팟팠팡팢팣팤팥팦팧패팩팪팫팬팭팮팯팰팱팲팳팴팵팶팷팸팹팺팻팼팽팾팿퍀퍁퍂퍃퍄퍅퍆퍇퍈퍉퍊퍋퍌퍍퍎퍏퍐퍑퍒퍓퍔퍕퍖퍗퍘퍙퍚퍛퍜퍝퍞퍟퍠퍡퍢퍣퍤퍥퍦퍧퍨퍩퍪퍫퍬퍭퍮퍯퍰퍱퍲퍳퍴퍵퍶퍷퍸퍹퍺퍻퍼퍽퍾퍿펀펁펂펃펄펅펆펇펈펉펊펋펌펍펎펏펐펑펒펓펔펕펖펗페펙펚펛펜펝펞펟펠펡펢펣펤펥펦펧펨펩펪펫펬펭펮펯펰펱펲펳펴펵펶펷편펹펺펻펼펽펾펿폀폁폂폃폄폅폆폇폈평폊폋폌폍폎폏폐폑폒폓폔폕폖폗폘폙폚폛폜폝폞폟폠폡폢폣폤폥폦폧폨폩폪폫포폭폮폯폰폱폲폳폴폵폶폷폸폹폺폻폼폽폾폿퐀퐁퐂퐃퐄퐅퐆퐇퐈퐉퐊퐋퐌퐍퐎퐏퐐퐑퐒퐓퐔퐕퐖퐗퐘퐙퐚퐛퐜퐝퐞퐟퐠퐡퐢퐣퐤퐥퐦퐧퐨퐩퐪퐫퐬퐭퐮퐯퐰퐱퐲퐳퐴퐵퐶퐷퐸퐹퐺퐻퐼퐽퐾퐿푀푁푂푃푄푅푆푇푈푉푊푋푌푍푎푏푐푑푒푓푔푕푖푗푘푙푚푛표푝푞푟푠푡푢푣푤푥푦푧푨푩푪푫푬푭푮푯푰푱푲푳푴푵푶푷푸푹푺푻푼푽푾푿풀풁풂풃풄풅풆풇품풉풊풋풌풍풎풏풐풑풒풓풔풕풖풗풘풙풚풛풜풝풞풟풠풡풢풣풤풥풦풧풨풩풪풫풬풭풮풯풰풱풲풳풴풵풶풷풸풹풺풻풼풽풾풿퓀퓁퓂퓃퓄퓅퓆퓇퓈퓉퓊퓋퓌퓍퓎퓏퓐퓑퓒퓓퓔퓕퓖퓗퓘퓙퓚퓛퓜퓝퓞퓟퓠퓡퓢퓣퓤퓥퓦퓧퓨퓩퓪퓫퓬퓭퓮퓯퓰퓱퓲퓳퓴퓵퓶퓷퓸퓹퓺퓻퓼퓽퓾퓿픀픁픂픃프픅픆픇픈픉픊픋플픍픎픏픐픑픒픓픔픕픖픗픘픙픚픛픜픝픞픟픠픡픢픣픤픥픦픧픨픩픪픫픬픭픮픯픰픱픲픳픴픵픶픷픸픹픺픻피픽픾픿핀핁핂핃필핅핆핇핈핉핊핋핌핍핎핏핐핑핒핓핔핕핖핗하학핚핛한핝핞핟할핡핢핣핤핥핦핧함합핪핫핬항핮핯핰핱핲핳해핵핶핷핸핹핺핻핼핽핾핿햀햁햂햃햄햅햆햇했행햊햋햌햍햎햏햐햑햒햓햔햕햖햗햘햙햚햛햜햝햞햟햠햡햢햣햤향햦햧햨햩햪햫햬햭햮햯햰햱햲햳햴햵햶햷햸햹햺햻햼햽햾햿헀헁헂헃헄헅헆헇허헉헊헋헌헍헎헏헐헑헒헓헔헕헖헗험헙헚헛헜헝헞헟헠헡헢헣헤헥헦헧헨헩헪헫헬헭헮헯헰헱헲헳헴헵헶헷헸헹헺헻헼헽헾헿혀혁혂혃현혅혆혇혈혉혊혋혌혍혎혏혐협혒혓혔형혖혗혘혙혚혛혜혝혞혟혠혡혢혣혤혥혦혧혨혩혪혫혬혭혮혯혰혱혲혳혴혵혶혷호혹혺혻혼혽혾혿홀홁홂홃홄홅홆홇홈홉홊홋홌홍홎홏홐홑홒홓화확홖홗환홙홚홛활홝홞홟홠홡홢홣홤홥홦홧홨황홪홫홬홭홮홯홰홱홲홳홴홵홶홷홸홹홺홻홼홽홾홿횀횁횂횃횄횅횆횇횈횉횊횋회획횎횏횐횑횒횓횔횕횖횗횘횙횚횛횜횝횞횟횠횡횢횣횤횥횦횧효횩횪횫횬횭횮횯횰횱횲횳횴횵횶횷횸횹횺횻횼횽횾횿훀훁훂훃후훅훆훇훈훉훊훋훌훍훎훏훐훑훒훓훔훕훖훗훘훙훚훛훜훝훞훟훠훡훢훣훤훥훦훧훨훩훪훫훬훭훮훯훰훱훲훳훴훵훶훷훸훹훺훻훼훽훾훿휀휁휂휃휄휅휆휇휈휉휊휋휌휍휎휏휐휑휒휓휔휕휖휗휘휙휚휛휜휝휞휟휠휡휢휣휤휥휦휧휨휩휪휫휬휭휮휯휰휱휲휳휴휵휶휷휸휹휺휻휼휽휾휿흀흁흂흃흄흅흆흇흈흉흊흋흌흍흎흏흐흑흒흓흔흕흖흗흘흙흚흛흜흝흞흟흠흡흢흣흤흥흦흧흨흩흪흫희흭흮흯흰흱흲흳흴흵흶흷흸흹흺흻흼흽흾흿  !"#$%%%%%%%%%%%%%%%%%%%%%%%%%%%%힀힁힂힃힄힅힆힇히힉힊힋힌힍힎힏힐힑힒힓힔힕힖힗힘힙힚힛힜힝힞힟힠힡힢힣   יִײַשׁשׂשּׁשּׂאַאָאּבּגּדּהּוּזּטּיּךּכּלּמּ נּסּףּפּצּקּרּשּתּוֹבֿכֿפֿ                   !"#$%&'(        A  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHI;8T\|L\zRx $@FJ w?:*3$"D0\pAHlFBB B(A0A8DP 8A0A(B BBBA  $HWGNUp0`$ @8t   8t   ( t P$X$o` 2  $H oooo$`pGA$3a1( GA$3p1067t GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFYGA+GLIBCXX_ASSERTIONSutf8_mac.so-2.2.10-35.el8.x86_64.debug 7zXZִF!t/8]?Eh=ڊ2N^ ܫeвOY)c5 2LJ6K GLK33M6G~*g*e'uz/Ț)c䄂λq|C /-t%YLh*U燩S7&,";#(Q1oj޲b:.=Ɓs#S|u`ɅWBLrK`8r=ITwTu$0aCο\$ۡ?-Svآי6H 4qU7W8nv9aO*=HrfkΞL A=p`Q;L\ɶ$La/~C9nˮq¶"sdm霧N+TY Z?^xU^=5ܬt6}ſf3wŮ]Z9I~2$ڥ @?e䱉R6A } g77%C^*BuILC\? ÷BPejm@@8 @xx PP!P! !!  888$$XXX StdXXX Ptd$$QtdRtdPP!P!GNU^S"A!@   BE|qX{ j , F"(!0!(!U $__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeInit_emoji_sjis_kddirb_register_transcoderlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ui P!X!``!`!!! !b!  ! (!8!bH! !!!!! !HHa!HtH5b!%c!hh%=!D%5!DH=1!H*!H9tH!Ht H=!H5!H)HHH?HHtH!HtfD=!u+UH=!Ht H=!Yd!]wHH=a! H=!HHHUTF8-KDDISJIS-KDDI 、。,.・:;?!゛゜´`¨^ ̄_ヽヾゝゞ〃仝々〆〇ー―‐/\~∥|…‥‘’“”()〔〕[]{}〈〉《》「」『』【】+-±×÷=≠<>≦≧∞∴♂♀°′″℃¥$¢£%#&*@§☆★○●◎◇◆□■△▲▽▼※〒→←↑↓〓 ∈∋⊆⊇⊂⊃∪∩∧∨¬⇒⇔∀∃∠⊥⌒∂∇≡≒≪≫√∽∝∵∫∬ʼn♯♭♪†‡¶◯ 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzぁあぃいぅうぇえぉおかがきぎくぐけげこごさざしじすずせぜそぞただちぢっつづてでとどなにぬねのはばぱひびぴふぶぷへべぺほぼぽまみむめもゃやゅゆょよらりるれろゎわゐゑをん\ァアィイゥウェエォオカガキギクグケゲコゴサザシジスズセゼソゾタダチヂッツヅテデトドナニヌネノハバパヒビピフブプヘベペホボポマミムメモャヤュユョヨラリルレロヮワヰヱヲンヴヵヶ ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩαβγδεζηθικλμνξοπρστυφχψω~АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ абвгдеёжзийклмнопрстуфхцчшщъыьэюя─│┌┐┘└├┬┤┴┼━┃┏┓┛┗┣┳┫┻╋┠┯┨┷┿┝┰┥┸╂= p①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩ ㍉㌔㌢㍍㌘㌧㌃㌶㍑㍗㌍㌦㌣㌫㍊㌻㎜㎝㎞㎎㎏㏄㎡㍻〝〟№㏍℡㊤㊥㊦㊧㊨㈱㈲㈹㍾㍽㍼≒≡∫∮∑√⊥∠∟⊿∵∩∪ 亜唖娃阿哀愛挨姶逢葵茜穐悪握渥旭葦芦鯵梓圧斡扱宛姐虻飴絢綾鮎或粟袷安庵按暗案闇鞍杏以伊位依偉囲夷委威尉惟意慰易椅為畏異移維緯胃萎衣謂違遺医井亥域育郁磯一壱溢逸稲茨芋鰯允印咽員因姻引飲淫胤蔭z 院陰隠韻吋右宇烏羽迂雨卯鵜窺丑碓臼渦嘘唄欝蔚鰻姥厩浦瓜閏噂云運雲荏餌叡営嬰影映曳栄永泳洩瑛盈穎頴英衛詠鋭液疫益駅悦謁越閲榎厭円園堰奄宴延怨掩援沿演炎焔煙燕猿縁艶苑薗遠鉛鴛塩於汚甥凹央奥往応押旺横欧殴王翁襖鴬鴎黄岡沖荻億屋憶臆桶牡乙俺卸恩温穏音下化仮何伽価佳加可嘉夏嫁家寡科暇果架歌河火珂禍禾稼箇花苛茄荷華菓蝦課嘩貨迦過霞蚊俄峨我牙画臥芽蛾賀雅餓駕介会解回塊壊廻快怪悔恢懐戒拐改9d 魁晦械海灰界皆絵芥蟹開階貝凱劾外咳害崖慨概涯碍蓋街該鎧骸浬馨蛙垣柿蛎鈎劃嚇各廓拡撹格核殻獲確穫覚角赫較郭閣隔革学岳楽額顎掛笠樫橿梶鰍潟割喝恰括活渇滑葛褐轄且鰹叶椛樺鞄株兜竃蒲釜鎌噛鴨栢茅萱粥刈苅瓦乾侃冠寒刊勘勧巻喚堪姦完官寛干幹患感慣憾換敢柑桓棺款歓汗漢澗潅環甘監看竿管簡緩缶翰肝艦莞観諌貫還鑑間閑関陥韓館舘丸含岸巌玩癌眼岩翫贋雁頑顔願企伎危喜器基奇嬉寄岐希幾忌揮机旗既期棋棄9`機帰毅気汽畿祈季稀紀徽規記貴起軌輝飢騎鬼亀偽儀妓宜戯技擬欺犠疑祇義蟻誼議掬菊鞠吉吃喫桔橘詰砧杵黍却客脚虐逆丘久仇休及吸宮弓急救朽求汲泣灸球究窮笈級糾給旧牛去居巨拒拠挙渠虚許距鋸漁禦魚亨享京供侠僑兇競共凶協匡卿叫喬境峡強彊怯恐恭挟教橋況狂狭矯胸脅興蕎郷鏡響饗驚仰凝尭暁業局曲極玉桐粁僅勤均巾錦斤欣欽琴禁禽筋緊芹菌衿襟謹近金吟銀九倶句区狗玖矩苦躯駆駈駒具愚虞喰空偶寓遇隅串櫛釧屑屈9\掘窟沓靴轡窪熊隈粂栗繰桑鍬勲君薫訓群軍郡卦袈祁係傾刑兄啓圭珪型契形径恵慶慧憩掲携敬景桂渓畦稽系経継繋罫茎荊蛍計詣警軽頚鶏芸迎鯨劇戟撃激隙桁傑欠決潔穴結血訣月件倹倦健兼券剣喧圏堅嫌建憲懸拳捲検権牽犬献研硯絹県肩見謙賢軒遣鍵険顕験鹸元原厳幻弦減源玄現絃舷言諺限乎個古呼固姑孤己庫弧戸故枯湖狐糊袴股胡菰虎誇跨鈷雇顧鼓五互伍午呉吾娯後御悟梧檎瑚碁語誤護醐乞鯉交佼侯候倖光公功効勾厚口向9X后喉坑垢好孔孝宏工巧巷幸広庚康弘恒慌抗拘控攻昂晃更杭校梗構江洪浩港溝甲皇硬稿糠紅紘絞綱耕考肯肱腔膏航荒行衡講貢購郊酵鉱砿鋼閤降項香高鴻剛劫号合壕拷濠豪轟麹克刻告国穀酷鵠黒獄漉腰甑忽惚骨狛込此頃今困坤墾婚恨懇昏昆根梱混痕紺艮魂些佐叉唆嵯左差査沙瑳砂詐鎖裟坐座挫債催再最哉塞妻宰彩才採栽歳済災采犀砕砦祭斎細菜裁載際剤在材罪財冴坂阪堺榊肴咲崎埼碕鷺作削咋搾昨朔柵窄策索錯桜鮭笹匙冊刷9T察拶撮擦札殺薩雑皐鯖捌錆鮫皿晒三傘参山惨撒散桟燦珊産算纂蚕讃賛酸餐斬暫残仕仔伺使刺司史嗣四士始姉姿子屍市師志思指支孜斯施旨枝止死氏獅祉私糸紙紫肢脂至視詞詩試誌諮資賜雌飼歯事似侍児字寺慈持時次滋治爾璽痔磁示而耳自蒔辞汐鹿式識鴫竺軸宍雫七叱執失嫉室悉湿漆疾質実蔀篠偲柴芝屡蕊縞舎写射捨赦斜煮社紗者謝車遮蛇邪借勺尺杓灼爵酌釈錫若寂弱惹主取守手朱殊狩珠種腫趣酒首儒受呪寿授樹綬需囚収周9P宗就州修愁拾洲秀秋終繍習臭舟蒐衆襲讐蹴輯週酋酬集醜什住充十従戎柔汁渋獣縦重銃叔夙宿淑祝縮粛塾熟出術述俊峻春瞬竣舜駿准循旬楯殉淳準潤盾純巡遵醇順処初所暑曙渚庶緒署書薯藷諸助叙女序徐恕鋤除傷償勝匠升召哨商唱嘗奨妾娼宵将小少尚庄床廠彰承抄招掌捷昇昌昭晶松梢樟樵沼消渉湘焼焦照症省硝礁祥称章笑粧紹肖菖蒋蕉衝裳訟証詔詳象賞醤鉦鍾鐘障鞘上丈丞乗冗剰城場壌嬢常情擾条杖浄状畳穣蒸譲醸錠嘱埴飾9L拭植殖燭織職色触食蝕辱尻伸信侵唇娠寝審心慎振新晋森榛浸深申疹真神秦紳臣芯薪親診身辛進針震人仁刃塵壬尋甚尽腎訊迅陣靭笥諏須酢図厨逗吹垂帥推水炊睡粋翠衰遂酔錐錘随瑞髄崇嵩数枢趨雛据杉椙菅頗雀裾澄摺寸世瀬畝是凄制勢姓征性成政整星晴棲栖正清牲生盛精聖声製西誠誓請逝醒青静斉税脆隻席惜戚斥昔析石積籍績脊責赤跡蹟碩切拙接摂折設窃節説雪絶舌蝉仙先千占宣専尖川戦扇撰栓栴泉浅洗染潜煎煽旋穿箭線9H 繊羨腺舛船薦詮賎践選遷銭銑閃鮮前善漸然全禅繕膳糎噌塑岨措曾曽楚狙疏疎礎祖租粗素組蘇訴阻遡鼠僧創双叢倉喪壮奏爽宋層匝惣想捜掃挿掻操早曹巣槍槽漕燥争痩相窓糟総綜聡草荘葬蒼藻装走送遭鎗霜騒像増憎臓蔵贈造促側則即息捉束測足速俗属賊族続卒袖其揃存孫尊損村遜他多太汰詑唾堕妥惰打柁舵楕陀駄騨体堆対耐岱帯待怠態戴替泰滞胎腿苔袋貸退逮隊黛鯛代台大第醍題鷹滝瀧卓啄宅托択拓沢濯琢託鐸濁諾茸凧蛸只9D#叩但達辰奪脱巽竪辿棚谷狸鱈樽誰丹単嘆坦担探旦歎淡湛炭短端箪綻耽胆蛋誕鍛団壇弾断暖檀段男談値知地弛恥智池痴稚置致蜘遅馳築畜竹筑蓄逐秩窒茶嫡着中仲宙忠抽昼柱注虫衷註酎鋳駐樗瀦猪苧著貯丁兆凋喋寵帖帳庁弔張彫徴懲挑暢朝潮牒町眺聴脹腸蝶調諜超跳銚長頂鳥勅捗直朕沈珍賃鎮陳津墜椎槌追鎚痛通塚栂掴槻佃漬柘辻蔦綴鍔椿潰坪壷嬬紬爪吊釣鶴亭低停偵剃貞呈堤定帝底庭廷弟悌抵挺提梯汀碇禎程締艇訂諦蹄逓9@&邸鄭釘鼎泥摘擢敵滴的笛適鏑溺哲徹撤轍迭鉄典填天展店添纏甜貼転顛点伝殿澱田電兎吐堵塗妬屠徒斗杜渡登菟賭途都鍍砥砺努度土奴怒倒党冬凍刀唐塔塘套宕島嶋悼投搭東桃梼棟盗淘湯涛灯燈当痘祷等答筒糖統到董蕩藤討謄豆踏逃透鐙陶頭騰闘働動同堂導憧撞洞瞳童胴萄道銅峠鴇匿得徳涜特督禿篤毒独読栃橡凸突椴届鳶苫寅酉瀞噸屯惇敦沌豚遁頓呑曇鈍奈那内乍凪薙謎灘捺鍋楢馴縄畷南楠軟難汝二尼弐迩匂賑肉虹廿日乳入9<)如尿韮任妊忍認濡禰祢寧葱猫熱年念捻撚燃粘乃廼之埜嚢悩濃納能脳膿農覗蚤巴把播覇杷波派琶破婆罵芭馬俳廃拝排敗杯盃牌背肺輩配倍培媒梅楳煤狽買売賠陪這蝿秤矧萩伯剥博拍柏泊白箔粕舶薄迫曝漠爆縛莫駁麦函箱硲箸肇筈櫨幡肌畑畠八鉢溌発醗髪伐罰抜筏閥鳩噺塙蛤隼伴判半反叛帆搬斑板氾汎版犯班畔繁般藩販範釆煩頒飯挽晩番盤磐蕃蛮匪卑否妃庇彼悲扉批披斐比泌疲皮碑秘緋罷肥被誹費避非飛樋簸備尾微枇毘琵眉美98,鼻柊稗匹疋髭彦膝菱肘弼必畢筆逼桧姫媛紐百謬俵彪標氷漂瓢票表評豹廟描病秒苗錨鋲蒜蛭鰭品彬斌浜瀕貧賓頻敏瓶不付埠夫婦富冨布府怖扶敷斧普浮父符腐膚芙譜負賦赴阜附侮撫武舞葡蕪部封楓風葺蕗伏副復幅服福腹複覆淵弗払沸仏物鮒分吻噴墳憤扮焚奮粉糞紛雰文聞丙併兵塀幣平弊柄並蔽閉陛米頁僻壁癖碧別瞥蔑箆偏変片篇編辺返遍便勉娩弁鞭保舗鋪圃捕歩甫補輔穂募墓慕戊暮母簿菩倣俸包呆報奉宝峰峯崩庖抱捧放方朋94/法泡烹砲縫胞芳萌蓬蜂褒訪豊邦鋒飽鳳鵬乏亡傍剖坊妨帽忘忙房暴望某棒冒紡肪膨謀貌貿鉾防吠頬北僕卜墨撲朴牧睦穆釦勃没殆堀幌奔本翻凡盆摩磨魔麻埋妹昧枚毎哩槙幕膜枕鮪柾鱒桝亦俣又抹末沫迄侭繭麿万慢満漫蔓味未魅巳箕岬密蜜湊蓑稔脈妙粍民眠務夢無牟矛霧鵡椋婿娘冥名命明盟迷銘鳴姪牝滅免棉綿緬面麺摸模茂妄孟毛猛盲網耗蒙儲木黙目杢勿餅尤戻籾貰問悶紋門匁也冶夜爺耶野弥矢厄役約薬訳躍靖柳薮鑓愉愈油癒902諭輸唯佑優勇友宥幽悠憂揖有柚湧涌猶猷由祐裕誘遊邑郵雄融夕予余与誉輿預傭幼妖容庸揚揺擁曜楊様洋溶熔用窯羊耀葉蓉要謡踊遥陽養慾抑欲沃浴翌翼淀羅螺裸来莱頼雷洛絡落酪乱卵嵐欄濫藍蘭覧利吏履李梨理璃痢裏裡里離陸律率立葎掠略劉流溜琉留硫粒隆竜龍侶慮旅虜了亮僚両凌寮料梁涼猟療瞭稜糧良諒遼量陵領力緑倫厘林淋燐琳臨輪隣鱗麟瑠塁涙累類令伶例冷励嶺怜玲礼苓鈴隷零霊麗齢暦歴列劣烈裂廉恋憐漣煉簾練聯9,5蓮連錬呂魯櫓炉賂路露労婁廊弄朗楼榔浪漏牢狼篭老聾蝋郎六麓禄肋録論倭和話歪賄脇惑枠鷲亙亘鰐詫藁蕨椀湾碗腕 弌丐丕个丱丶丼丿乂乖乘亂亅豫亊舒弍于亞亟亠亢亰亳亶从仍仄仆仂仗仞仭仟价伉佚估佛佝佗佇佶侈侏侘佻佩佰侑佯來侖儘俔俟俎俘俛俑俚俐俤俥倚倨倔倪倥倅伜俶倡倩倬俾俯們倆偃假會偕偐偈做偖偬偸傀傚傅傴傲(8僉僊傳僂僖僞僥僭僣僮價僵儉儁儂儖儕儔儚儡儺儷儼儻儿兀兒兌兔兢竸兩兪兮冀冂囘册冉冏冑冓冕冖冤冦冢冩冪冫决冱冲冰况冽凅凉凛几處凩凭凰凵凾刄刋刔刎刧刪刮刳刹剏剄剋剌剞剔剪剴剩剳剿剽劍劔劒剱劈劑辨辧劬劭劼劵勁勍勗勞勣勦飭勠勳勵勸勹匆匈甸匍匐匏匕匚匣匯匱匳匸區卆卅丗卉卍凖卞卩卮夘卻卷厂厖厠厦厥厮厰厶參簒雙叟曼燮叮叨叭叺吁吽呀听吭吼吮吶吩吝呎咏呵咎呟呱呷呰咒呻咀呶咄咐咆哇咢咸咥咬哄哈咨9|:咫哂咤咾咼哘哥哦唏唔哽哮哭哺哢唹啀啣啌售啜啅啖啗唸唳啝喙喀咯喊喟啻啾喘喞單啼喃喩喇喨嗚嗅嗟嗄嗜嗤嗔嘔嗷嘖嗾嗽嘛嗹噎噐營嘴嘶嘲嘸噫噤嘯噬噪嚆嚀嚊嚠嚔嚏嚥嚮嚶嚴囂嚼囁囃囀囈囎囑囓囗囮囹圀囿圄圉圈國圍圓團圖嗇圜圦圷圸坎圻址坏坩埀垈坡坿垉垓垠垳垤垪垰埃埆埔埒埓堊埖埣堋堙堝塲堡塢塋塰毀塒堽塹墅墹墟墫墺壞墻墸墮壅壓壑壗壙壘壥壜壤壟壯壺壹壻壼壽夂夊夐夛梦夥夬夭夲夸夾竒奕奐奎奚奘奢奠奧奬奩9x=奸妁妝佞侫妣妲姆姨姜妍姙姚娥娟娑娜娉娚婀婬婉娵娶婢婪媚媼媾嫋嫂媽嫣嫗嫦嫩嫖嫺嫻嬌嬋嬖嬲嫐嬪嬶嬾孃孅孀孑孕孚孛孥孩孰孳孵學斈孺宀它宦宸寃寇寉寔寐寤實寢寞寥寫寰寶寳尅將專對尓尠尢尨尸尹屁屆屎屓屐屏孱屬屮乢屶屹岌岑岔妛岫岻岶岼岷峅岾峇峙峩峽峺峭嶌峪崋崕崗嵜崟崛崑崔崢崚崙崘嵌嵒嵎嵋嵬嵳嵶嶇嶄嶂嶢嶝嶬嶮嶽嶐嶷嶼巉巍巓巒巖巛巫已巵帋帚帙帑帛帶帷幄幃幀幎幗幔幟幢幤幇幵并幺麼广庠廁廂廈廐廏9t@廖廣廝廚廛廢廡廨廩廬廱廳廰廴廸廾弃弉彝彜弋弑弖弩弭弸彁彈彌彎弯彑彖彗彙彡彭彳彷徃徂彿徊很徑徇從徙徘徠徨徭徼忖忻忤忸忱忝悳忿怡恠怙怐怩怎怱怛怕怫怦怏怺恚恁恪恷恟恊恆恍恣恃恤恂恬恫恙悁悍惧悃悚悄悛悖悗悒悧悋惡悸惠惓悴忰悽惆悵惘慍愕愆惶惷愀惴惺愃愡惻惱愍愎慇愾愨愧慊愿愼愬愴愽慂慄慳慷慘慙慚慫慴慯慥慱慟慝慓慵憙憖憇憬憔憚憊憑憫憮懌懊應懷懈懃懆憺懋罹懍懦懣懶懺懴懿懽懼懾戀戈戉戍戌戔戛9pC戞戡截戮戰戲戳扁扎扞扣扛扠扨扼抂抉找抒抓抖拔抃抔拗拑抻拏拿拆擔拈拜拌拊拂拇抛拉挌拮拱挧挂挈拯拵捐挾捍搜捏掖掎掀掫捶掣掏掉掟掵捫捩掾揩揀揆揣揉插揶揄搖搴搆搓搦搶攝搗搨搏摧摯摶摎攪撕撓撥撩撈撼據擒擅擇撻擘擂擱擧舉擠擡抬擣擯攬擶擴擲擺攀擽攘攜攅攤攣攫攴攵攷收攸畋效敖敕敍敘敞敝敲數斂斃變斛斟斫斷旃旆旁旄旌旒旛旙无旡旱杲昊昃旻杳昵昶昴昜晏晄晉晁晞晝晤晧晨晟晢晰暃暈暎暉暄暘暝曁暹曉暾暼9lF曄暸曖曚曠昿曦曩曰曵曷朏朖朞朦朧霸朮朿朶杁朸朷杆杞杠杙杣杤枉杰枩杼杪枌枋枦枡枅枷柯枴柬枳柩枸柤柞柝柢柮枹柎柆柧檜栞框栩桀桍栲桎梳栫桙档桷桿梟梏梭梔條梛梃檮梹桴梵梠梺椏梍桾椁棊椈棘椢椦棡椌棍棔棧棕椶椒椄棗棣椥棹棠棯椨椪椚椣椡棆楹楷楜楸楫楔楾楮椹楴椽楙椰楡楞楝榁楪榲榮槐榿槁槓榾槎寨槊槝榻槃榧樮榑榠榜榕榴槞槨樂樛槿權槹槲槧樅榱樞槭樔槫樊樒櫁樣樓橄樌橲樶橸橇橢橙橦橈樸樢檐檍檠檄檢檣9hI檗蘗檻櫃櫂檸檳檬櫞櫑櫟檪櫚櫪櫻欅蘖櫺欒欖鬱欟欸欷盜欹飮歇歃歉歐歙歔歛歟歡歸歹歿殀殄殃殍殘殕殞殤殪殫殯殲殱殳殷殼毆毋毓毟毬毫毳毯麾氈氓气氛氤氣汞汕汢汪沂沍沚沁沛汾汨汳沒沐泄泱泓沽泗泅泝沮沱沾沺泛泯泙泪洟衍洶洫洽洸洙洵洳洒洌浣涓浤浚浹浙涎涕濤涅淹渕渊涵淇淦涸淆淬淞淌淨淒淅淺淙淤淕淪淮渭湮渮渙湲湟渾渣湫渫湶湍渟湃渺湎渤滿渝游溂溪溘滉溷滓溽溯滄溲滔滕溏溥滂溟潁漑灌滬滸滾漿滲漱滯漲滌9dL漾漓滷澆潺潸澁澀潯潛濳潭澂潼潘澎澑濂潦澳澣澡澤澹濆澪濟濕濬濔濘濱濮濛瀉瀋濺瀑瀁瀏濾瀛瀚潴瀝瀘瀟瀰瀾瀲灑灣炙炒炯烱炬炸炳炮烟烋烝烙焉烽焜焙煥煕熈煦煢煌煖煬熏燻熄熕熨熬燗熹熾燒燉燔燎燠燬燧燵燼燹燿爍爐爛爨爭爬爰爲爻爼爿牀牆牋牘牴牾犂犁犇犒犖犢犧犹犲狃狆狄狎狒狢狠狡狹狷倏猗猊猜猖猝猴猯猩猥猾獎獏默獗獪獨獰獸獵獻獺珈玳珎玻珀珥珮珞璢琅瑯琥珸琲琺瑕琿瑟瑙瑁瑜瑩瑰瑣瑪瑶瑾璋璞璧瓊瓏瓔珱9`O瓠瓣瓧瓩瓮瓲瓰瓱瓸瓷甄甃甅甌甎甍甕甓甞甦甬甼畄畍畊畉畛畆畚畩畤畧畫畭畸當疆疇畴疊疉疂疔疚疝疥疣痂疳痃疵疽疸疼疱痍痊痒痙痣痞痾痿痼瘁痰痺痲痳瘋瘍瘉瘟瘧瘠瘡瘢瘤瘴瘰瘻癇癈癆癜癘癡癢癨癩癪癧癬癰癲癶癸發皀皃皈皋皎皖皓皙皚皰皴皸皹皺盂盍盖盒盞盡盥盧盪蘯盻眈眇眄眩眤眞眥眦眛眷眸睇睚睨睫睛睥睿睾睹瞎瞋瞑瞠瞞瞰瞶瞹瞿瞼瞽瞻矇矍矗矚矜矣矮矼砌砒礦砠礪硅碎硴碆硼碚碌碣碵碪碯磑磆磋磔碾碼磅磊磬9\R磧磚磽磴礇礒礑礙礬礫祀祠祗祟祚祕祓祺祿禊禝禧齋禪禮禳禹禺秉秕秧秬秡秣稈稍稘稙稠稟禀稱稻稾稷穃穗穉穡穢穩龝穰穹穽窈窗窕窘窖窩竈窰窶竅竄窿邃竇竊竍竏竕竓站竚竝竡竢竦竭竰笂笏笊笆笳笘笙笞笵笨笶筐筺笄筍笋筌筅筵筥筴筧筰筱筬筮箝箘箟箍箜箚箋箒箏筝箙篋篁篌篏箴篆篝篩簑簔篦篥籠簀簇簓篳篷簗簍篶簣簧簪簟簷簫簽籌籃籔籏籀籐籘籟籤籖籥籬籵粃粐粤粭粢粫粡粨粳粲粱粮粹粽糀糅糂糘糒糜糢鬻糯糲糴糶糺紆9XU紂紜紕紊絅絋紮紲紿紵絆絳絖絎絲絨絮絏絣經綉絛綏絽綛綺綮綣綵緇綽綫總綢綯緜綸綟綰緘緝緤緞緻緲緡縅縊縣縡縒縱縟縉縋縢繆繦縻縵縹繃縷縲縺繧繝繖繞繙繚繹繪繩繼繻纃緕繽辮繿纈纉續纒纐纓纔纖纎纛纜缸缺罅罌罍罎罐网罕罔罘罟罠罨罩罧罸羂羆羃羈羇羌羔羞羝羚羣羯羲羹羮羶羸譱翅翆翊翕翔翡翦翩翳翹飜耆耄耋耒耘耙耜耡耨耿耻聊聆聒聘聚聟聢聨聳聲聰聶聹聽聿肄肆肅肛肓肚肭冐肬胛胥胙胝胄胚胖脉胯胱脛脩脣脯腋9TX隋腆脾腓腑胼腱腮腥腦腴膃膈膊膀膂膠膕膤膣腟膓膩膰膵膾膸膽臀臂膺臉臍臑臙臘臈臚臟臠臧臺臻臾舁舂舅與舊舍舐舖舩舫舸舳艀艙艘艝艚艟艤艢艨艪艫舮艱艷艸艾芍芒芫芟芻芬苡苣苟苒苴苳苺莓范苻苹苞茆苜茉苙茵茴茖茲茱荀茹荐荅茯茫茗茘莅莚莪莟莢莖茣莎莇莊荼莵荳荵莠莉莨菴萓菫菎菽萃菘萋菁菷萇菠菲萍萢萠莽萸蔆菻葭萪萼蕚蒄葷葫蒭葮蒂葩葆萬葯葹萵蓊葢蒹蒿蒟蓙蓍蒻蓚蓐蓁蓆蓖蒡蔡蓿蓴蔗蔘蔬蔟蔕蔔蓼蕀蕣蕘蕈9P[蕁蘂蕋蕕薀薤薈薑薊薨蕭薔薛藪薇薜蕷蕾薐藉薺藏薹藐藕藝藥藜藹蘊蘓蘋藾藺蘆蘢蘚蘰蘿虍乕虔號虧虱蚓蚣蚩蚪蚋蚌蚶蚯蛄蛆蚰蛉蠣蚫蛔蛞蛩蛬蛟蛛蛯蜒蜆蜈蜀蜃蛻蜑蜉蜍蛹蜊蜴蜿蜷蜻蜥蜩蜚蝠蝟蝸蝌蝎蝴蝗蝨蝮蝙蝓蝣蝪蠅螢螟螂螯蟋螽蟀蟐雖螫蟄螳蟇蟆螻蟯蟲蟠蠏蠍蟾蟶蟷蠎蟒蠑蠖蠕蠢蠡蠱蠶蠹蠧蠻衄衂衒衙衞衢衫袁衾袞衵衽袵衲袂袗袒袮袙袢袍袤袰袿袱裃裄裔裘裙裝裹褂裼裴裨裲褄褌褊褓襃褞褥褪褫襁襄褻褶褸襌褝襠襞9L^襦襤襭襪襯襴襷襾覃覈覊覓覘覡覩覦覬覯覲覺覽覿觀觚觜觝觧觴觸訃訖訐訌訛訝訥訶詁詛詒詆詈詼詭詬詢誅誂誄誨誡誑誥誦誚誣諄諍諂諚諫諳諧諤諱謔諠諢諷諞諛謌謇謚諡謖謐謗謠謳鞫謦謫謾謨譁譌譏譎證譖譛譚譫譟譬譯譴譽讀讌讎讒讓讖讙讚谺豁谿豈豌豎豐豕豢豬豸豺貂貉貅貊貍貎貔豼貘戝貭貪貽貲貳貮貶賈賁賤賣賚賽賺賻贄贅贊贇贏贍贐齎贓賍贔贖赧赭赱赳趁趙跂趾趺跏跚跖跌跛跋跪跫跟跣跼踈踉跿踝踞踐踟蹂踵踰踴蹊9Ha蹇蹉蹌蹐蹈蹙蹤蹠踪蹣蹕蹶蹲蹼躁躇躅躄躋躊躓躑躔躙躪躡躬躰軆躱躾軅軈軋軛軣軼軻軫軾輊輅輕輒輙輓輜輟輛輌輦輳輻輹轅轂輾轌轉轆轎轗轜轢轣轤辜辟辣辭辯辷迚迥迢迪迯邇迴逅迹迺逑逕逡逍逞逖逋逧逶逵逹迸遏遐遑遒逎遉逾遖遘遞遨遯遶隨遲邂遽邁邀邊邉邏邨邯邱邵郢郤扈郛鄂鄒鄙鄲鄰酊酖酘酣酥酩酳酲醋醉醂醢醫醯醪醵醴醺釀釁釉釋釐釖釟釡釛釼釵釶鈞釿鈔鈬鈕鈑鉞鉗鉅鉉鉤鉈銕鈿鉋鉐銜銖銓銛鉚鋏銹銷鋩錏鋺鍄錮9Dd錙錢錚錣錺錵錻鍜鍠鍼鍮鍖鎰鎬鎭鎔鎹鏖鏗鏨鏥鏘鏃鏝鏐鏈鏤鐚鐔鐓鐃鐇鐐鐶鐫鐵鐡鐺鑁鑒鑄鑛鑠鑢鑞鑪鈩鑰鑵鑷鑽鑚鑼鑾钁鑿閂閇閊閔閖閘閙閠閨閧閭閼閻閹閾闊濶闃闍闌闕闔闖關闡闥闢阡阨阮阯陂陌陏陋陷陜陞陝陟陦陲陬隍隘隕隗險隧隱隲隰隴隶隸隹雎雋雉雍襍雜霍雕雹霄霆霈霓霎霑霏霖霙霤霪霰霹霽霾靄靆靈靂靉靜靠靤靦靨勒靫靱靹鞅靼鞁靺鞆鞋鞏鞐鞜鞨鞦鞣鞳鞴韃韆韈韋韜韭齏韲竟韶韵頏頌頸頤頡頷頽顆顏顋顫顯顰9@g顱顴顳颪颯颱颶飄飃飆飩飫餃餉餒餔餘餡餝餞餤餠餬餮餽餾饂饉饅饐饋饑饒饌饕馗馘馥馭馮馼駟駛駝駘駑駭駮駱駲駻駸騁騏騅駢騙騫騷驅驂驀驃騾驕驍驛驗驟驢驥驤驩驫驪骭骰骼髀髏髑髓體髞髟髢髣髦髯髫髮髴髱髷髻鬆鬘鬚鬟鬢鬣鬥鬧鬨鬩鬪鬮鬯鬲魄魃魏魍魎魑魘魴鮓鮃鮑鮖鮗鮟鮠鮨鮴鯀鯊鮹鯆鯏鯑鯒鯣鯢鯤鯔鯡鰺鯲鯱鯰鰕鰔鰉鰓鰌鰆鰈鰒鰊鰄鰮鰛鰥鰤鰡鰰鱇鰲鱆鰾鱚鱠鱧鱶鱸鳧鳬鳰鴉鴈鳫鴃鴆鴪鴦鶯鴣鴟鵄鴕鴒鵁鴿鴾鵆鵈9 mZk>` \umCjv{> ]^d_> VOqm1?4 A@CBs? DbFEGIH`?JV _FSPOcLNj_MKI[QR?(h \TSdfTUWXHYZ[9@G \Hb]d`a`^_{@H bcBdetgfiljmke@P msonnpqrntuv@ wy{xzA|Eq~MAA  }gvhGj[^|A| J}yA M}B| Zk\IB zUBP B C HeSlQC\ WfnCI @gC[RBhAfaFGaIHCD IgDJmEoMQLUniROPNKGWD TVSpXepa[_Zbfj\odY]^YDP ]qgchjmilkD nuovrtqwpcDks{~|z`D< }x@qJrDUyJE [@ZaE$ Ep srulE rtQA`H'F K|iFpX d,D$8lLPxdX, HttHT<H4hhsV lk^F EWF< ]Ibmnx/G _wEE\qG erE]BGx AtDCorTHIGFJBGN OKLMpUQGPSRcVWVXZ^[Y^7H(\ ]d_`acbefgbhLvijPkyH lmnopqrsCwMtquwvDH x zy|{}~FH HmcF|?I cpIP vsI t`rwxJ( GJt yepHzJ GJ8 {tK K Nf|OK ~uWDH@KH UK@ B}C~nJPQLD NFHRGKLOEEIFdOVTWLX mSUWX[YZM\a`L Abh]_^PAdcefL gsi|jklMd qrm\naopztws_M uvx`ua{^|}~gM IwMX XI%N ZgN IaNH yN OspXqt\-O UoOX TO JAO( A@CBDPEFG5P| vHeIJKK`LoMONePQRSTUwPV pWXYGZ[\PL ]vu`_P^LabcKidfP ehig]frmwllkFlbYj=Q  opn_FsaUvrwtuqNbQx  zxkyz_{~|@}Q dy uwTR  xcER  ]QR`  JR  L^ S  eLvnM\fMS Gd Go^qwS  S,  qNTp  zUT  HHT  xHT< @DABCJEGIFLRKMU| NQPOSRUTVWYXgZ[]^]U _\`aORb]cfedygU0 rihqkmjlpnPorySsAutx`U wv{zyQ|}~D#V hCJ_HeVH Iv}RqV4p H l0@P\P@P tD|p  |  X     $ h   4t(@ trATiNV xV^BkyKJI+W WM@mW` xYSsXsW AW Uz|Vy_3X, XuX dBjtX bnX Szg;Y eCLK}Y< NseI|Y K@BACdB^EDFZ BtKbGHLJICZ` OZMNLPZ VYXLQRUWZTSZ ^_`]\[dbcae [< fhgsiljkmopqtruwK[ v[ [ xMyzJ[{|}~t}{\ S\ hj\ ~@wAz\ G@KuB] YWGJ_d[] kIP] rvxC] f!^ BCc^ {azjop^8 z{^@BA^ CDEF)_  HGIHQJKZOk_0 LM{a`NOPRSUQTVWXY_ Z\[^a]_`b_ cde]nfgyh1`  wmljkiwnopqsrxs`d tvRuxyz`} |~{`  [9a\  E{a  TSa  @Da@! LNAb! I~b! khVbH" Lc" PIc" c,# DCEL@ABQJFKc# HG{LMNIOSTRd# QWPUVYX[\]hZ^Qd($ _`adt$ bcdd$ efghki[jlmnpqoe$ sotuvwxzy{|}~Ye$% Cl@e% Ve% sf,&X$x4X4 0(|\ T x  8!!!@"""$### $l$$$%%%$&H&afP&f@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~X'd(@ABCp)DEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~|*+@ABCDEFG,HIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~-.@ABCDEFGHIJK/LMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~01@ABCDEFGHIJKLMNO2PQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~34@ABCDEFGHIJKLMNOPQRS6TUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ 78@ABCDEFGHIJKLMNOPQRSTUVW$9XYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~0:<;@ABCDEFGHIJKLMNOPQRSTUVWXYZ[H<\]^_`abcdefghijklmnopqrstuvwxyz{|}~T=`>@ABCDEFGHIJKLMNOPQR@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_l?`abcdefghijklmnopqrstuvwxyz{|}~x@A@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcBdefghijklmnopqrstuvwxyz{|}~CD fESTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~$F0G@ABCd?p@|ABCDEF(G4H@ILJJKLMN O,P8Q?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmmmmmmmmmmmnopqrstummmmmmmmvwxyz{|mmmmmmmmmmm}~mmmmmmmmmmm@   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWWWWWWWWXYZ[\]^_`abcdefghijklmnoWWWWWWWWpqrstuvwxyz{|}~WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW@  !"""""""""""""""#$%&'()*+,-./0123456789:;<=>?@ABC"""""""""""""DEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abc""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""@@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRST@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~@  !"#$%&'()*+,-./0123444444444444444444444444444444444444444444456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~@   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwx  !"#$%&'(   !"#$%&'()*+,-./012                    !"#$%&'()*+,-./0123456789:;<=>?@  !"#$%&'()*+,-./012345678  !"#$%&'()*+,-./0123456788889:;<8          !     !"#$    !                                  !"#$   !"#$%&'                         !"#       !"#$%&                                                                                                           !"     !"#$%&   !                                      !"    !"        !                         !                 !"#                                                              !      !                                                                                                                                                                                                           !"                                                                                      !"#$                                                                                                                                                                                                                                                        !"#                                               !"#$  !"#$%&'()                      !"#                                                   !                                                                                                           !"#$%&'()*+,-./0123456789:;<=    !"#$%&'()*+,-./0123456789:;<=>>>   !"#$%&'()*+,  !  !"#$%&'()*+,-./0123456789:;<=>?  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!   ;$8@9h9zRx $80FJ w?:*3$"D8 \p9$HWGNU``! \Zbk V bk V x P!X!o`  !0Hh oooo !GA$3a1x GA$3p1067GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realignemoji_sjis_kddi.so-2.2.10-35.el8.x86_64.debugi17zXZִF!t/ ]?Eh=ڊ2N GⳲlFKMCN=W){by0$:4%ʉ((%%.6"j9eWQcK3ZaẈ,PJ7B-csZH·w0ڭ4?(: &gZf{j9zZgz8J'(fIgu+vLX5'G/[*‘i-.@ZYTe5hN75꼠-mοݍՆ8M"B4Td1L6vU茓gk6 ]'RH u>葍5_z-jwnHX7 jjC+nAٰUiAWʐaU1b ՓW;/ 5xt5rnHr "UC!uo9tsW?p`K7V5sM`:Jw%\*L,˥@gU0RaR;NM@OH铧 Q'X\|VtfD#j NG,U~5g`U{1 뭴lxf_ojjbze@t}^H9;a>9)7rQ;O?$sgYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 08oEo Th^BHH0hxxc0n w}  $tXX P!PX!X`!`` ! ! !((!(0a(  4T@+PK!ܭ$2.2.0/x86_64-linux/enc/trans/big5.sonuȯELF> @@8 @hh PP(P( ((  888$$HHH StdHHH Ptd$$QtdRtdPP(P(GNUE,F/L @  BE|qX1 V _ , F"((0(((U __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeInit_big5rb_register_transcoderlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ui P( X(P `(`((@ (F (`( (F ((@ 8(`H( (@ (O (`( `(O h(@ x(`( (@ (U (`(( (U (@ (`( @(@ H(` X(`h( (` (@ (`( (@ (f (`( (f ((@ 8(`H( ((((( (HHq(HtH5r(%s(hh%M(D%E(DH=A(H:(H9tH(Ht H=(H5 (H)HHH?HHtH(HtfD=(u+UH=(Ht H=(Yd(]wHH=q( H=(H=(H=m(H=(H=(H=i(H=(H=(H=e(HHHUTF-8Big5-UAOCP951Big5-HKSCSCP950Big5  ,、。.‧;:?!︰…‥﹐﹑﹒·﹔﹕﹖﹗|–︱—︳╴︴﹏()︵︶{}︷︸〔〕︹︺【】︻︼《》︽︾〈〉︿﹀「」﹁﹂『』﹃﹄﹙﹚﹛﹜﹝﹞‘’“”〝〞‵′#&*※§〃○●△▲◎☆★◇◆□■▽▼㊣℅¯ ̄_ˍ﹉﹊﹍﹎﹋﹌﹟﹠﹡+-×÷±√<>=≦≧≠∞≒≡﹢﹣﹤﹥﹦~∩∪⊥∠∟⊿㏒㏑∫∮∵∴♀♂⊕⊙↑↓←→↖↗↙↘∥∣/\∕﹨$¥〒¢£%@℃℉﹩﹪﹫㏕㎜㎝㎞㏎㎡㎎㎏㏄°兙兛兞兝兡兣嗧瓩糎▁▂▃▄▅▆▇█▏▎▍▌▋▊▉┼┴┬┤├▔─│▕┌┐└┘╭╮╰╯═╞╪╡◢◣◥◤╱╲╳0123456789ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩ〡〢〣〤〥〦〧〨〩十卄卅ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩαβγδεζηθικλμνξοπρστυφχψωㄅㄆㄇㄈㄉㄊㄋㄌㄍㄎㄏㄐㄑㄒㄓㄔㄕㄖㄗㄘㄙㄚㄛㄜㄝㄞㄟㄠㄡㄢㄣㄤㄥㄦㄧㄨㄩ˙ˉˊˇˋ €一乙丁七乃九了二人儿入八几刀刁力匕十卜又三下丈上丫丸凡久么也乞于亡兀刃勺千叉口土士夕大女子孑孓寸小尢尸山川工己已巳巾干廾弋弓才丑丐不中丰丹之尹予云井互五亢仁什仃仆仇仍今介仄元允內六兮公冗凶分切刈勻勾勿化匹午升卅卞厄友及反壬天夫太夭孔少尤尺屯巴幻廿弔引心戈戶手扎支文斗斤方日曰月木欠止歹毋比毛氏水火爪父爻片牙牛犬王丙世丕且丘主乍乏乎以付仔仕他仗代令仙仞充兄冉冊冬凹出凸刊加功包匆北匝仟半卉卡占卯卮去可古右召叮叩叨叼司叵叫另只史叱台句叭叻四囚外央失奴奶孕它尼巨巧左市布平幼弁弘弗必戊打扔扒扑斥旦朮本未末札正母民氐永汁汀氾犯玄玉瓜瓦甘生用甩田由甲申疋白皮皿目矛矢石示禾穴立丞丟乒乓乩亙交亦亥仿伉伙伊伕伍伐休伏仲件任仰仳份企伋光兇兆先全 共再冰列刑划刎刖劣匈匡匠印危吉吏同吊吐吁吋各向名合吃后吆吒因回囝圳地在圭圬圯圩夙多夷夸妄奸妃好她如妁字存宇守宅安寺尖屹州帆并年式弛忙忖戎戌戍成扣扛托收早旨旬旭曲曳有朽朴朱朵次此死氖汝汗汙江池汐汕污汛汍汎灰牟牝百竹米糸缶羊羽老考而耒耳聿肉肋肌臣自至臼舌舛舟艮色艾虫血行衣西阡串亨位住佇佗佞伴佛何估佐佑伽伺伸佃佔似但佣 作你伯低伶余佝佈佚兌克免兵冶冷別判利刪刨劫助努劬匣即卵吝吭吞吾否呎吧呆呃吳呈呂君吩告吹吻吸吮吵吶吠吼呀吱含吟听囪困囤囫坊坑址坍均坎圾坐坏圻壯夾妝妒妨妞妣妙妖妍妤妓妊妥孝孜孚孛完宋宏尬局屁尿尾岐岑岔岌巫希序庇床廷弄弟彤形彷役忘忌志忍忱快忸忪戒我抄抗抖技扶抉扭把扼找批扳抒扯折扮投抓抑抆改攻攸旱更束李杏材村杜杖杞杉杆杠杓杗步每求汞沙沁沈沉沅沛汪決沐汰沌汨沖沒汽沃汲汾汴沆汶沍沔沘沂灶灼災灸牢牡牠狄狂玖甬甫男甸皂盯矣私秀禿究系罕肖肓肝肘肛肚育良芒芋芍見角言谷豆豕貝赤走足身車辛辰迂迆迅迄巡邑邢邪邦那酉釆里防阮阱阪阬並乖乳事些亞享京佯依侍佳使佬供例來侃佰併侈佩佻侖佾侏侑佺兔兒兕兩具其典冽函刻券刷刺到刮制剁劾劻卒協卓卑卦卷卸卹取叔受味呵咖呸咕咀呻呷咄咒咆呼咐呱呶和咚呢周咋命咎固垃坷坪坩坡坦坤坼夜奉奇奈奄奔妾妻委妹妮姑姆姐姍始姓姊妯妳姒姅孟孤季宗定官宜宙宛尚屈居屆岷岡岸岩岫岱岳帘帚帖帕帛帑幸庚店府底庖延弦弧弩往征彿彼忝忠忽念忿怏怔怯怵怖怪怕怡性怩怫怛或戕房戾所承拉拌拄抿拂抹拒招披拓拔拋拈抨抽押拐拙拇拍抵拚抱拘拖拗拆抬拎放斧於旺昔易昌昆昂明昀昏昕昊昇服朋杭枋枕東果杳杷枇枝林杯杰板枉松析杵枚枓杼杪杲欣武歧歿氓氛泣注泳沱泌泥河沽沾沼波沫法泓沸泄油況沮泗泅泱沿治泡泛泊沬泯泜泖泠炕炎炒炊炙爬爭爸版牧物狀狎狙狗狐玩玨玟玫玥甽疝疙疚的盂盲直知矽社祀祁秉秈空穹竺糾罔羌羋者肺肥肢肱股肫肩肴肪肯臥臾舍芳芝芙芭芽芟芹花芬芥芯芸芣芰芾芷虎虱初表軋迎返近邵邸邱邶采金長門阜陀阿阻附陂隹雨青非亟亭亮信侵侯便俠俑俏保促侶俘俟俊俗侮俐俄係俚俎俞侷兗冒冑冠剎剃削前剌剋則勇勉勃勁匍南卻厚叛咬哀咨哎哉咸咦咳哇哂咽咪品哄哈咯咫咱咻咩咧咿囿垂型垠垣垢城垮垓奕契奏奎奐姜姘姿姣姨娃姥姪姚姦威姻孩宣宦室客宥封屎屏屍屋峙峒巷帝帥帟幽庠度建弈弭彥很待徊律徇後徉怒思怠急怎怨恍恰恨恢恆恃恬恫恪恤扁拜挖按拼拭持拮拽指拱拷拯括拾拴挑挂政故斫施既春昭映昧是星昨昱昤曷柿染柱柔某柬架枯柵柩柯柄柑枴柚查枸柏柞柳枰柙柢柝柒歪殃殆段毒毗氟泉洋洲洪流津洌洱洞洗活洽派洶洛泵洹洧洸洩洮洵洎洫炫為炳炬炯炭炸炮炤爰牲牯牴狩狠狡玷珊玻玲珍珀玳甚甭畏界畎畋疫疤疥疢疣癸皆皇皈盈盆盃盅省盹相眉看盾盼眇矜砂研砌砍祆祉祈祇禹禺科秒秋穿突竿竽籽紂紅紀紉紇約紆缸美羿耄耐耍耑耶胖胥胚胃胄背胡胛胎胞胤胝致舢苧范茅苣苛苦茄若茂茉苒苗英茁苜苔苑苞苓苟苯茆虐虹虻虺衍衫要觔計訂訃貞負赴赳趴軍軌述迦迢迪迥迭迫迤迨郊郎郁郃酋酊重閂限陋陌降面革韋韭音頁風飛食首香乘亳倌倍倣俯倦倥俸倩倖倆值借倚倒們俺倀倔倨俱倡個候倘俳修倭倪俾倫倉兼冤冥冢凍凌准凋剖剜剔剛剝匪卿原厝叟哨唐唁唷哼哥哲唆哺唔哩哭員唉哮哪哦唧唇哽唏圃圄埂埔埋埃堉夏套奘奚娑娘娜娟娛娓姬娠娣娩娥娌娉孫屘宰害家宴宮宵容宸射屑展屐峭峽峻峪峨峰島崁峴差席師庫庭座弱徒徑徐恙恣恥恐恕恭恩息悄悟悚悍悔悌悅悖扇拳挈拿捎挾振捕捂捆捏捉挺捐挽挪挫挨捍捌效敉料旁旅時晉晏晃晒晌晅晁書朔朕朗校核案框桓根桂桔栩梳栗桌桑栽柴桐桀格桃株桅栓栘桁殊殉殷氣氧氨氦氤泰浪涕消涇浦浸海浙涓浬涉浮浚浴浩涌涊浹涅浥涔烊烘烤烙烈烏爹特狼狹狽狸狷玆班琉珮珠珪珞畔畝畜畚留疾病症疲疳疽疼疹痂疸皋皰益盍盎眩真眠眨矩砰砧砸砝破砷砥砭砠砟砲祕祐祠祟祖神祝祗祚秤秣秧租秦秩秘窄窈站笆笑粉紡紗紋紊素索純紐紕級紜納紙紛缺罟羔翅翁耆耘耕耙耗耽耿胱脂胰脅胭胴脆胸胳脈能脊胼胯臭臬舀舐航舫舨般芻茫荒荔荊茸荐草茵茴荏茲茹茶茗荀茱茨荃"虔蚊蚪蚓蚤蚩蚌蚣蚜衰衷袁袂衽衹記訐討訌訕訊託訓訖訏訑豈豺豹財貢起躬軒軔軏辱送逆迷退迺迴逃追逅迸邕郡郝郢酒配酌釘針釗釜釙閃院陣陡陛陝除陘陞隻飢馬骨高鬥鬲鬼乾偺偽停假偃偌做偉健偶偎偕偵側偷偏倏偯偭兜冕凰剪副勒務勘動匐匏匙匿區匾參曼商啪啦啄啞啡啃啊唱啖問啕唯啤唸售啜唬啣唳啁啗圈國圉域堅堊堆埠埤基堂堵執培夠奢娶婁婉婦婪婀$娼婢婚婆婊孰寇寅寄寂宿密尉專將屠屜屝崇崆崎崛崖崢崑崩崔崙崤崧崗巢常帶帳帷康庸庶庵庾張強彗彬彩彫得徙從徘御徠徜恿患悉悠您惋悴惦悽情悻悵惜悼惘惕惆惟悸惚惇戚戛扈掠控捲掖探接捷捧掘措捱掩掉掃掛捫推掄授掙採掬排掏掀捻捩捨捺敝敖救教敗啟敏敘敕敔斜斛斬族旋旌旎晝晚晤晨晦晞曹勗望梁梯梢梓梵桿桶梱梧梗械梃棄梭梆梅梔條梨梟梡梂欲殺'毫毬氫涎涼淳淙液淡淌淤添淺清淇淋涯淑涮淞淹涸混淵淅淒渚涵淚淫淘淪深淮淨淆淄涪淬涿淦烹焉焊烽烯爽牽犁猜猛猖猓猙率琅琊球理現琍瓠瓶瓷甜產略畦畢異疏痔痕疵痊痍皎盔盒盛眷眾眼眶眸眺硫硃硎祥票祭移窒窕笠笨笛第符笙笞笮粒粗粕絆絃統紮紹紼絀細紳組累終紲紱缽羞羚翌翎習耜聊聆脯脖脣脫脩脰脤舂舵舷舶船莎莞莘荸莢莖莽莫莒莊莓莉莠荷荻荼)莆莧處彪蛇蛀蚶蛄蚵蛆蛋蚱蚯蛉術袞袈被袒袖袍袋覓規訪訝訣訥許設訟訛訢豉豚販責貫貨貪貧赧赦趾趺軛軟這逍通逗連速逝逐逕逞造透逢逖逛途部郭都酗野釵釦釣釧釭釩閉陪陵陳陸陰陴陶陷陬雀雪雩章竟頂頃魚鳥鹵鹿麥麻傢傍傅備傑傀傖傘傚最凱割剴創剩勞勝勛博厥啻喀喧啼喊喝喘喂喜喪喔喇喋喃喳單喟唾喲喚喻喬喱啾喉喫喙圍堯堪場堤堰報堡堝堠壹壺奠,婷媚婿媒媛媧孳孱寒富寓寐尊尋就嵌嵐崴嵇巽幅帽幀幃幾廊廁廂廄弼彭復循徨惑惡悲悶惠愜愣惺愕惰惻惴慨惱愎惶愉愀愒戟扉掣掌描揀揩揉揆揍插揣提握揖揭揮捶援揪換摒揚揹敞敦敢散斑斐斯普晰晴晶景暑智晾晷曾替期朝棺棕棠棘棗椅棟棵森棧棹棒棲棣棋棍植椒椎棉棚楮棻款欺欽殘殖殼毯氮氯氬港游湔渡渲湧湊渠渥渣減湛湘渤湖湮渭渦湯渴湍渺測湃渝渾滋.溉渙湎湣湄湲湩湟焙焚焦焰無然煮焜牌犄犀猶猥猴猩琺琪琳琢琥琵琶琴琯琛琦琨甥甦畫番痢痛痣痙痘痞痠登發皖皓皴盜睏短硝硬硯稍稈程稅稀窘窗窖童竣等策筆筐筒答筍筋筏筑粟粥絞結絨絕紫絮絲絡給絢絰絳善翔翕耋聒肅腕腔腋腑腎脹腆脾腌腓腴舒舜菩萃菸萍菠菅萋菁華菱菴著萊菰萌菌菽菲菊萸萎萄菜萇菔菟虛蛟蛙蛭蛔蛛蛤蛐蛞街裁裂袱覃視註詠評詞証詁1詔詛詐詆訴診訶詖象貂貯貼貳貽賁費賀貴買貶貿貸越超趁跎距跋跚跑跌跛跆軻軸軼辜逮逵週逸進逶鄂郵鄉郾酣酥量鈔鈕鈣鈉鈞鈍鈐鈇鈑閔閏開閑間閒閎隊階隋陽隅隆隍陲隄雁雅雄集雇雯雲韌項順須飧飪飯飩飲飭馮馭黃黍黑亂傭債傲傳僅傾催傷傻傯僇剿剷剽募勦勤勢勣匯嗟嗨嗓嗦嗎嗜嗇嗑嗣嗤嗯嗚嗡嗅嗆嗥嗉園圓塞塑塘塗塚塔填塌塭塊塢塒塋奧嫁嫉嫌媾媽媼3媳嫂媲嵩嵯幌幹廉廈弒彙徬微愚意慈感想愛惹愁愈慎慌慄慍愾愴愧愍愆愷戡戢搓搾搞搪搭搽搬搏搜搔損搶搖搗搆敬斟新暗暉暇暈暖暄暘暍會榔業楚楷楠楔極椰概楊楨楫楞楓楹榆楝楣楛歇歲毀殿毓毽溢溯滓溶滂源溝滇滅溥溘溼溺溫滑準溜滄滔溪溧溴煎煙煩煤煉照煜煬煦煌煥煞煆煨煖爺牒猷獅猿猾瑯瑚瑕瑟瑞瑁琿瑙瑛瑜當畸瘀痰瘁痲痱痺痿痴痳盞盟睛睫睦睞督6睹睪睬睜睥睨睢矮碎碰碗碘碌碉硼碑碓硿祺祿禁萬禽稜稚稠稔稟稞窟窠筷節筠筮筧粱粳粵經絹綑綁綏絛置罩罪署義羨群聖聘肆肄腱腰腸腥腮腳腫腹腺腦舅艇蒂葷落萱葵葦葫葉葬葛萼萵葡董葩葭葆虞虜號蛹蜓蜈蜇蜀蛾蛻蜂蜃蜆蜊衙裟裔裙補裘裝裡裊裕裒覜解詫該詳試詩詰誇詼詣誠話誅詭詢詮詬詹詻訾詨豢貊貉賊資賈賄貲賃賂賅跡跟跨路跳跺跪跤跦躲較載軾輊8辟農運遊道遂達逼違遐遇遏過遍遑逾遁鄒鄗酬酪酩釉鈷鉗鈸鈽鉀鈾鉛鉋鉤鉑鈴鉉鉍鉅鈹鈿鉚閘隘隔隕雍雋雉雊雷電雹零靖靴靶預頑頓頊頒頌飼飴飽飾馳馱馴髡鳩麂鼎鼓鼠僧僮僥僖僭僚僕像僑僱僎僩兢凳劃劂匱厭嗾嘀嘛嘗嗽嘔嘆嘉嘍嘎嗷嘖嘟嘈嘐嗶團圖塵塾境墓墊塹墅塽壽夥夢夤奪奩嫡嫦嫩嫗嫖嫘嫣孵寞寧寡寥實寨寢寤察對屢嶄嶇幛幣幕幗幔廓廖弊彆彰徹慇;愿態慷慢慣慟慚慘慵截撇摘摔撤摸摟摺摑摧搴摭摻敲斡旗旖暢暨暝榜榨榕槁榮槓構榛榷榻榫榴槐槍榭槌榦槃榣歉歌氳漳演滾漓滴漩漾漠漬漏漂漢滿滯漆漱漸漲漣漕漫漯澈漪滬漁滲滌滷熔熙煽熊熄熒爾犒犖獄獐瑤瑣瑪瑰瑭甄疑瘧瘍瘋瘉瘓盡監瞄睽睿睡磁碟碧碳碩碣禎福禍種稱窪窩竭端管箕箋筵算箝箔箏箸箇箄粹粽精綻綰綜綽綾綠緊綴網綱綺綢綿綵綸維緒緇綬=罰翠翡翟聞聚肇腐膀膏膈膊腿膂臧臺與舔舞艋蓉蒿蓆蓄蒙蒞蒲蒜蓋蒸蓀蓓蒐蒼蓑蓊蜿蜜蜻蜢蜥蜴蜘蝕蜷蜩裳褂裴裹裸製裨褚裯誦誌語誣認誡誓誤說誥誨誘誑誚誧豪貍貌賓賑賒赫趙趕跼輔輒輕輓辣遠遘遜遣遙遞遢遝遛鄙鄘鄞酵酸酷酴鉸銀銅銘銖鉻銓銜銨鉼銑閡閨閩閣閥閤隙障際雌雒需靼鞅韶頗領颯颱餃餅餌餉駁骯骰髦魁魂鳴鳶鳳麼鼻齊億儀僻僵價儂儈儉儅凜@劇劈劉劍劊勰厲嘮嘻嘹嘲嘿嘴嘩噓噎噗噴嘶嘯嘰墀墟增墳墜墮墩墦奭嬉嫻嬋嫵嬌嬈寮寬審寫層履嶝嶔幢幟幡廢廚廟廝廣廠彈影德徵慶慧慮慝慕憂慼慰慫慾憧憐憫憎憬憚憤憔憮戮摩摯摹撞撲撈撐撰撥撓撕撩撒撮播撫撚撬撙撢撳敵敷數暮暫暴暱樣樟槨樁樞標槽模樓樊槳樂樅槭樑歐歎殤毅毆漿潼澄潑潦潔澆潭潛潸潮澎潺潰潤澗潘滕潯潠潟熟熬熱熨牖犛獎獗瑩璋璃B瑾璀畿瘠瘩瘟瘤瘦瘡瘢皚皺盤瞎瞇瞌瞑瞋磋磅確磊碾磕碼磐稿稼穀稽稷稻窯窮箭箱範箴篆篇篁箠篌糊締練緯緻緘緬緝編緣線緞緩綞緙緲緹罵罷羯翩耦膛膜膝膠膚膘蔗蔽蔚蓮蔬蔭蔓蔑蔣蔡蔔蓬蔥蓿蔆螂蝴蝶蝠蝦蝸蝨蝙蝗蝌蝓衛衝褐複褒褓褕褊誼諒談諄誕請諸課諉諂調誰論諍誶誹諛豌豎豬賠賞賦賤賬賭賢賣賜質賡赭趟趣踫踐踝踢踏踩踟踡踞躺輝輛輟輩輦輪輜輞E輥適遮遨遭遷鄰鄭鄧鄱醇醉醋醃鋅銻銷鋪銬鋤鋁銳銼鋒鋇鋰銲閭閱霄霆震霉靠鞍鞋鞏頡頫頜颳養餓餒餘駝駐駟駛駑駕駒駙骷髮髯鬧魅魄魷魯鴆鴉鴃麩麾黎墨齒儒儘儔儐儕冀冪凝劑劓勳噙噫噹噩噤噸噪器噥噱噯噬噢噶壁墾壇壅奮嬝嬴學寰導彊憲憑憩憊懍憶憾懊懈戰擅擁擋撻撼據擄擇擂操撿擒擔撾整曆曉暹曄曇暸樽樸樺橙橫橘樹橄橢橡橋橇樵機橈歙歷氅濂澱澡G濃澤濁澧澳激澹澶澦澠澴熾燉燐燒燈燕熹燎燙燜燃燄獨璜璣璘璟璞瓢甌甍瘴瘸瘺盧盥瞠瞞瞟瞥磨磚磬磧禦積穎穆穌穋窺篙簑築篤篛篡篩篦糕糖縊縑縈縛縣縞縝縉縐罹羲翰翱翮耨膳膩膨臻興艘艙蕊蕙蕈蕨蕩蕃蕉蕭蕪蕞螃螟螞螢融衡褪褲褥褫褡親覦諦諺諫諱謀諜諧諮諾謁謂諷諭諳諶諼豫豭貓賴蹄踱踴蹂踹踵輻輯輸輳辨辦遵遴選遲遼遺鄴醒錠錶鋸錳錯錢鋼錫錄錚J錐錦錡錕錮錙閻隧隨險雕霎霑霖霍霓霏靛靜靦鞘頰頸頻頷頭頹頤餐館餞餛餡餚駭駢駱骸骼髻髭鬨鮑鴕鴣鴦鴨鴒鴛默黔龍龜優償儡儲勵嚎嚀嚐嚅嚇嚏壕壓壑壎嬰嬪嬤孺尷屨嶼嶺嶽嶸幫彌徽應懂懇懦懋戲戴擎擊擘擠擰擦擬擱擢擭斂斃曙曖檀檔檄檢檜櫛檣橾檗檐檠歜殮毚氈濘濱濟濠濛濤濫濯澀濬濡濩濕濮濰燧營燮燦燥燭燬燴燠爵牆獰獲璩環璦璨癆療癌盪瞳瞪瞰瞬L瞧瞭矯磷磺磴磯礁禧禪穗窿簇簍篾篷簌篠糠糜糞糢糟糙糝縮績繆縷縲繃縫總縱繅繁縴縹繈縵縿縯罄翳翼聱聲聰聯聳臆臃膺臂臀膿膽臉膾臨舉艱薪薄蕾薜薑薔薯薛薇薨薊虧蟀蟑螳蟒蟆螫螻螺蟈蟋褻褶襄褸褽覬謎謗謙講謊謠謝謄謐豁谿豳賺賽購賸賻趨蹉蹋蹈蹊轄輾轂轅輿避遽還邁邂邀鄹醣醞醜鍍鎂錨鍵鍊鍥鍋錘鍾鍬鍛鍰鍚鍔闊闋闌闈闆隱隸雖霜霞鞠韓顆颶餵騁O駿鮮鮫鮪鮭鴻鴿麋黏點黜黝黛鼾齋叢嚕嚮壙壘嬸彝懣戳擴擲擾攆擺擻擷斷曜朦檳檬櫃檻檸櫂檮檯歟歸殯瀉瀋濾瀆濺瀑瀏燻燼燾燸獷獵璧璿甕癖癘癒瞽瞿瞻瞼礎禮穡穢穠竄竅簫簧簪簞簣簡糧織繕繞繚繡繒繙罈翹翻職聶臍臏舊藏薩藍藐藉薰薺薹薦蟯蟬蟲蟠覆覲觴謨謹謬謫豐贅蹙蹣蹦蹤蹟蹕軀轉轍邇邃邈醫醬釐鎔鎊鎖鎢鎳鎮鎬鎰鎘鎚鎗闔闖闐闕離雜雙雛雞霤鞣鞦Q鞭韹額顏題顎顓颺餾餿餽餮馥騎髁鬃鬆魏魎魍鯊鯉鯽鯈鯀鵑鵝鵠黠鼕鼬儳嚥壞壟壢寵龐廬懲懷懶懵攀攏曠曝櫥櫝櫚櫓瀛瀟瀨瀚瀝瀕瀘爆爍牘犢獸獺璽瓊瓣疇疆癟癡矇礙禱穫穩簾簿簸簽簷籀繫繭繹繩繪羅繳羶羹羸臘藩藝藪藕藤藥藷蟻蠅蠍蟹蟾襠襟襖襞譁譜識證譚譎譏譆譙贈贊蹼蹲躇蹶蹬蹺蹴轔轎辭邊邋醱醮鏡鏑鏟鏃鏈鏜鏝鏖鏢鏍鏘鏤鏗鏨關隴難霪霧靡韜韻類T願顛颼饅饉騖騙鬍鯨鯧鯖鯛鶉鵡鵲鵪鵬麒麗麓麴勸嚨嚷嚶嚴嚼壤孀孃孽寶巉懸懺攘攔攙曦朧櫬瀾瀰瀲爐獻瓏癢癥礦礪礬礫竇競籌籃籍糯糰辮繽繼纂罌耀臚艦藻藹蘑藺蘆蘋蘇蘊蠔蠕襤覺觸議譬警譯譟譫贏贍躉躁躅躂醴釋鐘鐃鏽闡霰飄饒饑馨騫騰騷騵鰓鰍鹹麵黨鼯齟齣齡儷儸囁囀囂夔屬巍懼懾攝攜斕曩櫻欄櫺殲灌爛犧瓖瓔癩矓籐纏續羼蘗蘭蘚蠣蠢蠡蠟襪襬覽譴V護譽贓躊躍躋轟辯醺鐮鐳鐵鐺鐸鐲鐫闢霸霹露響顧顥饗驅驃驀騾髏魔魑鰭鰥鶯鶴鷂鶸麝黯鼙齜齦齧儼儻囈囊囉孿巔巒彎懿攤權歡灑灘玀瓤疊癮癬禳籠籟聾聽臟襲襯觼讀贖贗躑躓轡酈鑄鑑鑒霽霾韃韁顫饕驕驍髒鬚鱉鰱鰾鰻鷓鷗鼴齬齪龔囌巖戀攣攫攪曬欐瓚竊籤籣籥纓纖纔臢蘸蘿蠱變邐邏鑣鑠鑤靨顯饜驚驛驗髓體髑鱔鱗鱖鷥麟黴囑壩攬灞癱癲矗罐羈蠶蠹衢讓讒Y讖艷贛釀鑪靂靈靄韆顰驟鬢魘鱟鷹鷺鹼鹽鼇齷齲廳欖灣籬籮蠻觀躡釁鑲鑰顱饞髖鬣黌灤矚讚鑷韉驢驥纜讜躪釅鑽鑾鑼鱷鱸黷豔鑿鸚爨驪鬱鸛鸞籲[^`乂乜凵匚厂万丌乇亍囗兀屮彳丏冇与丮亓仂仉仈冘勼卬厹圠夃夬尐巿旡殳毌气爿丱丼仨仜仩仡仝仚刌匜卌圢圣夗夯宁宄尒尻屴屳帄庀庂忉戉扐氕氶汃氿氻犮犰玊禸肊阞伎优伬仵伔仱伀价伈伝伂伅伢伓伄仴伒冱刓刉刐劦匢匟卍厊吇囡囟圮圪圴夼妀奼妅奻奾奷奿孖尕尥屼屺屻屾巟幵庄异弚彴忕忔忏扜扞扤扡扦扢扙扠扚扥旯旮朾朹朸朻机朿朼朳氘汆汒汜汏汊汔汋c汌灱牞犴犵玎甪癿穵网艸艼芀艽艿虍襾邙邗邘邛邔阢阤阠阣佖伻佢佉体佤伾佧佒佟佁佘伭伳伿佡冏冹刜刞刡劭劮匉卣卲厎厏吰吷吪呔呅吙吜吥吘吽呏呁吨吤呇囮囧囥坁坅坌坉坋坒夆奀妦妘妠妗妎妢妐妏妧妡宎宒尨尪岍岏岈岋岉岒岊岆岓岕巠帊帎庋庉庌庈庍弅弝彸彶忒忑忐忭忨忮忳忡忤忣忺忯忷忻怀忴戺抃抌抎抏抔抇扱扻扺扰抁抈扷扽扲扴攷旰旴旳旲旵杅杇e杙杕杌杈杝杍杚杋毐氙氚汸汧汫沄沋沏汱汯汩沚汭沇沕沜汦汳汥汻沎灴灺牣犿犽狃狆狁犺狅玕玗玓玔玒町甹疔疕皁礽耴肕肙肐肒肜芐芏芅芎芑芓芊芃芄豸迉辿邟邡邥邞邧邠阰阨阯阭丳侘佼侅佽侀侇佶佴侉侄佷佌侗佪侚佹侁佸侐侜侔侞侒侂侕佫佮冞冼冾刵刲刳剆刱劼匊匋匼厒厔咇呿咁咑咂咈呫呺呾呥呬呴呦咍呯呡呠咘呣呧呤囷囹坯坲坭坫坱坰坶垀坵坻坳坴坢h坨坽夌奅妵妺姏姎妲姌姁妶妼姃姖妱妽姀姈妴姇孢孥宓宕屄屇岮岤岠岵岯岨岬岟岣岭岢岪岧岝岥岶岰岦帗帔帙弨弢弣弤彔徂彾彽忞忥怭怦怙怲怋怴怊怗怳怚怞怬怢怍怐怮怓怑怌怉怜戔戽抭抴拑抾抪抶拊抮抳抯抻抩抰抸攽斨斻昉旼昄昒昈旻昃昋昍昅旽昑昐曶朊枅杬枎枒杶杻枘枆构杴枍枌杺枟枑枙枃杽极杸杹枔欥殀歾毞氝沓泬泫泮泙沶泔沭泧沷泐泂沺泃泆泭泲j泒泝沴沊沝沀泞泀洰泍泇沰泹泏泩泑炔炘炅炓炆炄炑炖炂炚炃牪狖狋狘狉狜狒狔狚狌狑玤玡玭玦玢玠玬玝瓝瓨甿畀甾疌疘皯盳盱盰盵矸矼矹矻矺矷祂礿秅穸穻竻籵糽耵肏肮肣肸肵肭舠芠苀芫芚芘芛芵芧芮芼芞芺芴芨芡芩苂芤苃芶芢虰虯虭虮豖迒迋迓迍迖迕迗邲邴邯邳邰阹阽阼阺陃俍俅俓侲俉俋俁俔俜俙侻侳俛俇俖侺俀侹俬剄剉勀勂匽卼厗厖厙厘咺咡咭咥哏m哃茍咷咮哖咶哅哆咠呰咼咢咾呲哞咰垵垞垟垤垌垗垝垛垔垘垏垙垥垚垕壴复奓姡姞姮娀姱姝姺姽姼姶姤姲姷姛姩姳姵姠姾姴姭宨屌峐峘峌峗峋峛峞峚峉峇峊峖峓峔峏峈峆峎峟峸巹帡帢帣帠帤庰庤庢庛庣庥弇弮彖徆怷怹恔恲恞恅恓恇恉恛恌恀恂恟怤恄恘恦恮扂扃拏挍挋拵挎挃拫拹挏挌拸拶挀挓挔拺挕拻拰敁敃斪斿昶昡昲昵昜昦昢昳昫昺昝昴昹昮朏朐柁柲柈枺o柜枻柸柘柀枷柅柫柤柟枵柍枳柷柶柮柣柂枹柎柧柰枲柼柆柭柌枮柦柛柺柉柊柃柪柋欨殂殄殶毖毘毠氠氡洨洴洭洟洼洿洒洊泚洳洄洙洺洚洑洀洝浂洁洘洷洃洏浀洇洠洬洈洢洉洐炷炟炾炱炰炡炴炵炩牁牉牊牬牰牳牮狊狤狨狫狟狪狦狣玅珌珂珈珅玹玶玵玴珫玿珇玾珃珆玸珋瓬瓮甮畇畈疧疪癹盄眈眃眄眅眊盷盻盺矧矨砆砑砒砅砐砏砎砉砃砓祊祌祋祅祄秕种秏秖秎窀r穾竑笀笁籺籸籹籿粀粁紃紈紁罘羑羍羾耇耎耏耔耷胘胇胠胑胈胂胐胅胣胙胜胊胕胉胏胗胦胍臿舡芔苙苾苹茇苨茀苕茺苫苖苴苬苡苲苵茌苻苶苰苪苤苠苺苳苭虷虴虼虳衁衎衧衪衩觓訄訇赲迣迡迮迠郱邽邿郕郅邾郇郋郈釔釓陔陏陑陓陊陎倞倅倇倓倢倰倛俵俴倳倷倬俶俷倗倜倠倧倵倯倱倎党冔冓凊凄凅凈凎剡剚剒剞剟剕剢勍匎厞唦哢唗唒哧哳哤唚哿唄唈哫唑唅哱t唊哻哷哸哠唎唃唋圁圂埌堲埕埒垺埆垽垼垸垶垿埇埐垹埁夎奊娙娖娭娮娕娏娗娊娞娳孬宧宭宬尃屖屔峬峿峮峱峷崀峹帩帨庨庮庪庬弳弰彧恝恚恧恁悢悈悀悒悁悝悃悕悛悗悇悜悎戙扆拲挐捖挬捄捅挶捃揤挹捋捊挼挩捁挴捘捔捙挭捇挳捚捑挸捗捀捈敊敆旆旃旄旂晊晟晇晑朒朓栟栚桉栲栳栻桋桏栖栱栜栵栫栭栯桎桄栴栝栒栔栦栨栮桍栺栥栠欬欯欭欱欴歭肂殈毦毤w毨毣毢毧氥浺浣浤浶洍浡涒浘浢浭浯涑涍淯浿涆浞浧浠涗浰浼浟涂涘洯浨涋浾涀涄洖涃浻浽浵涐烜烓烑烝烋缹烢烗烒烞烠烔烍烅烆烇烚烎烡牂牸牷牶猀狺狴狾狶狳狻猁珓珙珥珖玼珧珣珩珜珒珛珔珝珚珗珘珨瓞瓟瓴瓵甡畛畟疰痁疻痄痀疿疶疺皊盉眝眛眐眓眒眣眑眕眙眚眢眧砣砬砢砵砯砨砮砫砡砩砳砪砱祔祛祏祜祓祒祑秫秬秠秮秭秪秜秞秝窆窉窅窋窌窊窇竘笐y笄笓笅笏笈笊笎笉笒粄粑粊粌粈粍粅紞紝紑紎紘紖紓紟紒紏紌罜罡罞罠罝罛羖羒翃翂翀耖耾耹胺胲胹胵脁胻脀舁舯舥茳茭荄茙荑茥荖茿荁茦茜茢荂荎茛茪茈茼荍茖茤茠茷茯茩荇荅荌荓茞茬荋茧荈虓虒蚢蚨蚖蚍蚑蚞蚇蚗蚆蚋蚚蚅蚥蚙蚡蚧蚕蚘蚎蚝蚐蚔衃衄衭衵衶衲袀衱衿衯袃衾衴衼訒豇豗豻貤貣赶赸趵趷趶軑軓迾迵适迿迻逄迼迶郖郠郙郚郣郟郥郘郛郗郜郤酐|酎酏釕釢釚陜陟隼飣髟鬯乿偰偪偡偞偠偓偋偝偲偈偍偁偛偊偢倕偅偟偩偫偣偤偆偀偮偳偗偑凐剫剭剬剮勖勓匭厜啵啶唼啍啐唴唪啑啢唶唵唰啒啅唌唲啥啎唹啈唭唻啀啋圊圇埻堔埢埶埜埴堀埭埽堈埸堋埳埏堇埮埣埲埥埬埡堎埼堐埧堁堌埱埩埰堍堄奜婠婘婕婧婞娸娵婭婐婟婥婬婓婤婗婃婝婒婄婛婈媎娾婍娹婌婰婩婇婑婖婂婜孲孮寁寀屙崞崋崝崚崠崌崨崍崦崥崏~崰崒崣崟崮帾帴庱庴庹庲庳弶弸徛徖徟悊悐悆悾悰悺惓惔惏惤惙惝惈悱惛悷惊悿惃惍惀挲捥掊掂捽掽掞掭掝掗掫掎捯掇掐据掯捵掜捭掮捼掤挻掟捸掅掁掑掍捰敓旍晥晡晛晙晜晢朘桹梇梐梜桭桮梮梫楖桯梣梬梩桵桴梲梏桷梒桼桫桲梪梀桱桾梛梖梋梠梉梤桸桻梑梌梊桽欶欳欷欸殑殏殍殎殌氪淀涫涴涳湴涬淩淢涷淶淔渀淈淠淟淖涾淥淜淝淛淴淊涽淭淰涺淕淂淏淉淐淲淓淽淗淍淣涻烺焍烷焗烴焌烰焄烳焐烼烿焆焓焀烸烶焋焂焎牾牻牼牿猝猗猇猑猘猊猈狿猏猞玈珶珸珵琄琁珽琇琀珺珼珿琌琋珴琈畤畣痎痒痏痋痌痑痐皏皉盓眹眯眭眱眲眴眳眽眥眻眵硈硒硉硍硊硌砦硅硐祤祧祩祪祣祫祡离秺秸秶秷窏窔窐笵筇笴笥笰笢笤笳笘笪笝笱笫笭笯笲笸笚笣粔粘粖粣紵紽紸紶紺絅紬紩絁絇紾紿絊紻紨罣羕羜羝羛翊翋翍翐翑翇翏翉耟耞耛聇聃聈脘脥脙脛脭脟脬脞脡脕脧脝脢舑舸舳舺舴舲艴莐莣莨莍荺荳莤荴莏莁莕莙荵莔莩荽莃莌莝莛莪莋荾莥莯莈莗莰荿莦莇莮荶莚虙虖蚿蚷蛂蛁蛅蚺蚰蛈蚹蚳蚸蛌蚴蚻蚼蛃蚽蚾衒袉袕袨袢袪袚袑袡袟袘袧袙袛袗袤袬袌袓袎覂觖觙觕訰訧訬訞谹谻豜豝豽貥赽赻赹趼跂趹趿跁軘軞軝軜軗軠軡逤逋逑逜逌逡郯郪郰郴郲郳郔郫郬郩酖酘酚酓酕釬釴釱釳釸釤釹釪釫釷釨釮镺閆閈陼陭陫陱陯隿靪頄飥馗傛傕傔傞傋傣傃傌傎傝偨傜傒傂傇兟凔匒匑厤厧喑喨喥喭啷噅喢喓喈喏喵喁喣喒喤啽喌喦啿喕喡喎圌堩堷堙堞堧堣堨埵塈堥堜堛堳堿堶堮堹堸堭堬堻奡媯媔媟婺媢媞婸媦婼媥媬媕媮娷媄媊媗媃媋媩婻婽媌媜媏媓媝寪寍寋寔寑寊寎尌尰崷嵃嵫嵁嵋崿崵嵑嵎嵕崳崺嵒崽崱嵙嵂崹嵉崸崼崲崶嵀嵅幄幁彘徦徥徫惉悹惌惢惎惄愔惲愊愖愅惵愓惸惼惾惁愃愘愝愐惿愄愋扊掔掱掰揎揥揨揯揃撝揳揊揠揶揕揲揵摡揟掾揝揜揄揘揓揂揇揌揋揈揰揗揙攲敧敪敤敜敨敥斌斝斞斮旐旒晼晬晻暀晱晹晪晲朁椌棓椄棜椪棬棪棱椏棖棷棫棤棶椓椐棳棡椇棌椈楰梴椑棯棆椔棸棐棽棼棨椋椊椗棎棈棝棞棦棴棑椆棔棩椕椥棇欹欻欿欼殔殗殙殕殽毰毲毳氰淼湆湇渟湉溈渼渽湅湢渫渿湁湝湳渜渳湋湀湑渻渃渮湞湨湜湡渱渨湠湱湫渹渢渰湓湥渧湸湤湷湕湹湒湦渵渶湚焠焞焯烻焮焱焣焥焢焲焟焨焺焛牋牚犈犉犆犅犋猒猋猰猢猱猳猧猲猭猦猣猵猌琮琬琰琫琖琚琡琭琱琤琣琝琩琠琲瓻甯畯畬痧痚痡痦痝痟痤痗皕皒盚睆睇睄睍睅睊睎睋睌矞矬硠硤硥硜硭硱硪确硰硩硨硞硢祴祳祲祰稂稊稃稌稄窙竦竤筊笻筄筈筌筎筀筘筅粢粞粨粡絘絯絣絓絖絧絪絏絭絜絫絒絔絩絑絟絎缾缿罥罦羢羠羡翗聑聏聐胾胔腃腊腒腏腇脽腍脺臦臮臷臸臹舄舼舽舿艵茻菏菹萣菀菨萒菧菤菼菶萐菆菈菫菣莿萁菝菥菘菿菡菋菎菖菵菉萉萏菞萑萆菂菳菕菺菇菑菪萓菃菬菮菄菻菗菢萛菛菾蛘蛢蛦蛓蛣蛚蛪蛝蛫蛜蛬蛩蛗蛨蛑衈衖衕袺裗袹袸裀袾袶袼袷袽袲褁裉覕覘覗觝觚觛詎詍訹詙詀詗詘詄詅詒詈詑詊詌詏豟貁貀貺貾貰貹貵趄趀趉跘跓跍跇跖跜跏跕跙跈跗跅軯軷軺軹軦軮軥軵軧軨軶軫軱軬軴軩逭逴逯鄆鄬鄄郿郼鄈郹郻鄁鄀鄇鄅鄃酡酤酟酢酠鈁鈊鈥鈃鈚鈦鈏鈌鈀鈒釿釽鈆鈄鈧鈂鈜鈤鈙鈗鈅鈖镻閍閌閐隇陾隈隉隃隀雂雈雃雱雰靬靰靮頇颩飫鳦黹亃亄亶傽傿僆傮僄僊傴僈僂傰僁傺傱僋僉傶傸凗剺剸剻剼嗃嗛嗌嗐嗋嗊嗝嗀嗔嗄嗩喿嗒喍嗏嗕嗢嗖嗈嗲嗍嗙嗂圔塓塨塤塏塍塉塯塕塎塝塙塥塛堽塣塱壼嫇嫄嫋媺媸媱媵媰媿嫈媻嫆媷嫀嫊媴媶嫍媹媐寖寘寙尟尳嵱嵣嵊嵥嵲嵬嵞嵨嵧嵢巰幏幎幊幍幋廅廌廆廋廇彀徯徭惷慉慊愫慅愶愲愮慆愯慏愩慀戠酨戣戥戤揅揱揫搐搒搉搠搤搳摃搟搕搘搹搷搢搣搌搦搰搨摁搵搯搊搚摀搥搧搋揧搛搮搡搎敯斒旓暆暌暕暐暋暊暙暔晸朠楦楟椸楎楢楱椿楅楪椹楂楗楙楺楈楉椵楬椳椽楥棰楸椴楩楀楯楄楶楘楁楴楌椻楋椷楜楏楑椲楒椯楻椼歆歅歃歂歈歁殛嗀毻毼毹毷毸溛滖滈溏滀溟溓溔溠溱溹滆滒溽滁溞滉溷溰滍溦滏溲溾滃滜滘溙溒溎溍溤溡溿溳滐滊溗溮溣煇煔煒煣煠煁煝煢煲煸煪煡煂煘煃煋煰煟煐煓煄煍煚牏犍犌犑犐犎猼獂猻猺獀獊獉瑄瑊瑋瑒瑑瑗瑀瑏瑐瑎瑂瑆瑍瑔瓡瓿瓾瓽甝畹畷榃痯瘏瘃痷痾痼痹痸瘐痻痶痭痵痽皙皵盝睕睟睠睒睖睚睩睧睔睙睭矠碇碚碔碏碄碕碅碆碡碃硹碙碀碖硻祼禂祽祹稑稘稙稒稗稕稢稓稛稐窣窢窞竫筦筤筭筴筩筲筥筳筱筰筡筸筶筣粲粴粯綈綆綀綍絿綅絺綎絻綃絼綌綔綄絽綒罭罫罧罨罬羦羥羧翛翜耡腤腠腷腜腩腛腢腲朡腞腶腧腯腄腡舝艉艄艀艂艅蓱萿葖葶葹蒏蒍葥葑葀蒆葧萰葍葽葚葙葴葳葝蔇葞萷萺萴葺葃葸萲葅萩菙葋萯葂萭葟葰萹葎葌葒葯蓅蒎萻葇萶萳葨葾葄萫葠葔葮葐蜋蜄蛷蜌蛺蛖蛵蝍蛸蜎蜉蜁蛶蜍蜅裖裋裍裎裞裛裚裌裐覅覛觟觥觤觡觠觢觜触詶誆詿詡訿詷誂誄詵誃誁詴詺谼豋豊豥豤豦貆貄貅賌赨赩趑趌趎趏趍趓趔趐趒跰跠跬跱跮跐跩跣跢跧跲跫跴輆軿輁輀輅輇輈輂輋遒逿遄遉逽鄐鄍鄏鄑鄖鄔鄋鄎酮酯鉈鉒鈰鈺鉦鈳鉥鉞銃鈮鉊鉆鉭鉬鉏鉠鉧鉯鈶鉡鉰鈱鉔鉣鉐鉲鉎鉓鉌鉖鈲閟閜閞閛隒隓隑隗雎雺雽雸雵靳靷靸靲頏頍頎颬飶飹馯馲馰馵骭骫魛鳪鳭鳧麀黽僦僔僗僨僳僛僪僝僤僓僬僰僯僣僠凘劀劁勩勫匰厬嘧嘕嘌嘒嗼嘏嘜嘁嘓嘂嗺嘝嘄嗿嗹墉塼墐墘墆墁塿塴墋塺墇墑墎塶墂墈塻墔墏壾奫嫜嫮嫥嫕嫪嫚嫭嫫嫳嫢嫠嫛嫬嫞嫝嫙嫨嫟孷寠寣屣嶂嶀嵽嶆嵺嶁嵷嶊嶉嶈嵾嵼嶍嵹嵿幘幙幓廘廑廗廎廜廕廙廒廔彄彃彯徶愬愨慁慞慱慳慒慓慲慬憀慴慔慺慛慥愻慪慡慖戩戧戫搫摍摛摝摴摶摲摳摽摵摦撦摎撂摞摜摋摓摠摐摿搿摬摫摙摥摷敳斠暡暠暟朅朄朢榱榶槉榠槎榖榰榬榼榑榙榎榧榍榩榾榯榿槄榽榤槔榹槊榚槏榳榓榪榡榞槙榗榐槂榵榥槆歊歍歋殞殟殠毃毄毾滎滵滱漃漥滸漷滻漮漉潎漙漚漧漘漻漒滭漊漶潳滹滮漭潀漰漼漵滫漇漎潃漅滽滶漹漜滼漺漟漍漞漈漡熇熐熉熀熅熂熏煻熆熁熗牄牓犗犕犓獃獍獑獌瑢瑳瑱瑵瑲瑧瑮甀甂甃畽疐瘖瘈瘌瘕瘑瘊瘔皸瞁睼瞅瞂睮瞀睯睾瞃碲碪碴碭碨硾碫碞碥碠碬碢碤禘禊禋禖禕禔禓禗禈禒禐稫穊稰稯稨稦窨窫窬竮箈箜箊箑箐箖箍箌箛箎箅箘劄箙箤箂粻粿粼粺綧綷緂綣綪緁緀緅綝緎緄緆緋緌綯綹綖綼綟綦綮綩綡緉罳翢翣翥翞耤聝聜膉膆膃膇膍膌膋舕蒗蒤蒡蒟蒺蓎蓂蒬蒮蒫蒹蒴蓁蓍蒪蒚蒱蓐蒝蒧蒻蒢蒔蓇蓌蒛蒩蒯蒨蓖蒘蒶蓏蒠蓗蓔蓒蓛蒰蒑虡蜳蜣蜨蝫蝀蜮蜞蜡蜙蜛蝃蜬蝁蜾蝆蜠蜲蜪蜭蜼蜒蜺蜱蜵蝂蜦蜧蜸蜤蜚蜰蜑裷裧裱裲裺裾裮裼裶裻裰裬裫覝覡覟覞觩觫觨誫誙誋誒誏誖谽豨豩賕賏賗趖踉踂跿踍跽踊踃踇踆踅跾踀踄輐輑輎輍鄣鄜鄠鄢鄟鄝鄚鄤鄡鄛酺酲酹酳銥銤鉶銛鉺銠銔銪銍銦銚銫鉹銗鉿銣鋮銎銂銕銢鉽銈銡銊銆銌銙銧鉾銇銩銝銋鈭隞隡雿靘靽靺靾鞃鞀鞂靻鞄鞁靿韎韍頖颭颮餂餀餇馝馜駃馹馻馺駂馽駇骱髣髧鬾鬿魠魡魟鳱鳲鳵麧僿儃儰僸儆儇僶僾儋儌僽儊劋劌勱勯噈噂噌嘵噁噊噉噆噘噚噀嘳嘽嘬嘾嘸嘪嘺圚墫墝墱墠墣墯墬墥墡壿嫿嫴嫽嫷嫶嬃嫸嬂嫹嬁嬇嬅嬏屧嶙嶗嶟嶒嶢嶓嶕嶠嶜嶡嶚嶞幩幝幠幜緳廛廞廡彉徲憋憃慹憱憰憢憉憛憓憯憭憟憒憪憡憍慦憳戭摮摰撖撠撅撗撜撏撋撊撌撣撟摨撱撘敶敺敹敻斲斳暵暰暩暲暷暪暯樀樆樗槥槸樕槱槤樠槿槬槢樛樝槾樧槲槮樔槷槧橀樈槦槻樍槼槫樉樄樘樥樏槶樦樇槴樖歑殥殣殢殦氁氀毿氂潁漦潾澇濆澒澍澉澌潢潏澅潚澖潶潬澂潕潲潒潐潗澔澓潝漀潡潫潽潧澐潓澋潩潿澕潣潷潪潻熲熯熛熰熠熚熩熵熝熥熞熤熡熪熜熧熳犘犚獘獒獞獟獠獝獛獡獚獙獢璇璉璊璆璁瑽璅璈瑼瑹甈甇畾瘥瘞瘙瘝瘜瘣瘚瘨瘛皜皝皞皛瞍瞏瞉瞈磍碻磏磌磑磎磔磈磃磄磉禚禡禠禜禢禛歶稹窲窴窳箷篋箾箬篎箯箹篊箵糅糈糌糋緷緛緪緧緗緡縃緺緦緶緱緰緮緟罶羬羰羭翭翫翪翬翦翨聤聧膣膟膞膕膢膙膗舖艏艓艒艐艎艑蔤蔻蔏蔀蔩蔎蔉蔍蔟蔊蔧蔜蓻蔫蓺蔈蔌蓴蔪蓲蔕蓷蓫蓳蓼蔒蓪蓩蔖蓾蔨蔝蔮蔂蓽蔞蓶蔱蔦蓧蓨蓰蓯蓹蔘蔠蔰蔋蔙蔯虢蝖蝣蝤蝷蟡蝳蝘蝔蝛蝒蝡蝚蝑蝞蝭蝪蝐蝎蝟蝝蝯蝬蝺蝮蝜蝥蝏蝻蝵蝢蝧蝩衚褅褌褔褋褗褘褙褆褖褑褎褉覢覤覣觭觰觬諏諆誸諓諑諔諕誻諗誾諀諅諘諃誺誽諙谾豍貏賥賟賙賨賚賝賧趠趜趡趛踠踣踥踤踮踕踛踖踑踙踦踧踔踒踘踓踜踗踚輬輤輘輚輠輣輖輗遳遰遯遧遫鄯鄫鄩鄪鄲鄦鄮醅醆醊醁醂醄醀鋐鋃鋄鋀鋙銶鋏鋱鋟鋘鋩鋗鋝鋌鋯鋂鋨鋊鋈鋎鋦鋍鋕鋉鋠鋞鋧鋑鋓銵鋡鋆銴镼閬閫閮閰隤隢雓霅霈霂靚鞊鞎鞈韐韏頞頝頦頩頨頠頛頧颲餈飺餑餔餖餗餕駜駍駏駓駔駎駉駖駘駋駗駌骳髬髫髳髲髱魆魃魧魴魱魦魶魵魰魨魤魬鳼鳺鳽鳿鳷鴇鴀鳹鳻鴈鴅鴄麃黓鼏鼐儜儓儗儚儑凞匴叡噰噠噮噳噦噣噭噲噞噷圜圛壈墽壉墿墺壂墼壆嬗嬙嬛嬡嬔嬓嬐嬖嬨嬚嬠嬞寯嶬嶱嶩嶧嶵嶰嶮嶪嶨嶲嶭嶯嶴幧幨幦幯廩廧廦廨廥彋徼憝憨憖懅憴懆懁懌憺憿憸憌擗擖擐擏擉撽撉擃擛擳擙攳敿敼斢曈暾曀曊曋曏暽暻暺曌朣樴橦橉橧樲橨樾橝橭橶橛橑樨橚樻樿橁橪橤橐橏橔橯橩橠樼橞橖橕橍橎橆歕歔歖殧殪殫毈毇氄氃氆澭濋澣濇澼濎濈潞濄澽澞濊澨瀄澥澮澺澬澪濏澿澸澢濉澫濍澯澲澰燅燂熿熸燖燀燁燋燔燊燇燏熽燘熼燆燚燛犝犞獩獦獧獬獥獫獪瑿璚璠璔璒璕璡甋疀瘯瘭瘱瘽瘳瘼瘵瘲瘰皻盦瞚瞝瞡瞜瞛瞢瞣瞕瞙瞗磝磩磥磪磞磣磛磡磢磭磟磠禤穄穈穇窶窸窵窱窷篞篣篧篝篕篥篚篨篹篔篪篢篜篫篘篟糒糔糗糐糑縒縡縗縌縟縠縓縎縜縕縚縢縋縏縖縍縔縥縤罃罻罼罺羱翯耪耩聬膱膦膮膹膵膫膰膬膴膲膷膧臲艕艖艗蕖蕅蕫蕍蕓蕡蕘蕀蕆蕤蕁蕢蕄蕑蕇蕣蔾蕛蕱蕎蕮蕵蕕蕧蕠薌蕦蕝蕔蕥蕬虣虥虤螛螏螗螓螒螈螁螖螘蝹螇螣螅螐螑螝螄螔螜螚螉褞褦褰褭褮褧褱褢褩褣褯褬褟觱諠諢諲諴諵諝謔諤諟諰諈諞諡諨諿諯諻貑貒貐賵賮賱賰賳赬赮趥趧踳踾踸蹀蹅踶踼踽蹁踰踿躽輶輮輵輲輹輷輴遶遹遻邆郺鄳鄵鄶醓醐醑醍醏錧錞錈錟錆錏鍺錸錼錛錣錒錁鍆錭錎錍鋋錝鋺錥錓鋹鋷錴錂錤鋿錩錹錵錪錔錌錋鋾錉錀鋻錖閼闍閾閹閺閶閿閵閽隩雔霋霒霐鞙鞗鞔韰韸頵頯頲餤餟餧餩馞駮駬駥駤駰駣駪駩駧骹骿骴骻髶髺髹髷鬳鮀鮅鮇魼魾魻鮂鮓鮒鮐魺鮕魽鮈鴥鴗鴠鴞鴔鴩鴝鴘鴢鴐鴙鴟麈麆麇麮麭黕黖黺鼒鼽儦儥儢儤儠儩勴嚓嚌嚍嚆嚄嚃噾嚂噿嚁壖壔壏壒嬭嬥嬲嬣嬬嬧嬦嬯嬮孻寱寲嶷幬幪徾徻懃憵憼懧懠懥懤懨懞擯擩擣擫擤擨斁斀斶旚曒檍檖檁檥檉檟檛檡檞檇檓檎檕檃檨檤檑橿檦檚檅檌檒歛殭氉濌澩濴濔濣濜濭濧濦濞濲濝濢濨燡燱燨燲燤燰燢獳獮獯璗璲璫璐璪璭璱璥璯甐甑甒甏疄癃癈癉癇皤盩瞵瞫瞲瞷瞶瞴瞱瞨矰磳磽礂磻磼磲礅磹磾礄禫禨穜穛穖穘穔穚窾竀竁簅簏篲簀篿篻簎篴簋篳簂簉簃簁篸篽簆篰篱簐簊糨縭縼繂縳顈縸縪繉繀繇縩繌縰縻縶繄縺罅罿罾罽翴翲耬膻臄臌臊臅臇膼臩艛艚艜薃薀薏薧薕薠薋薣蕻薤薚薞蕷蕼薉薡蕺蕸蕗薎薖薆薍薙薝薁薢薂薈薅蕹蕶薘薐薟虨螾螪螭蟅螰螬螹螵螼螮蟉蟃蟂蟌螷螯蟄蟊螴螶螿螸螽蟞螲褵褳褼褾襁襒褷襂覭覯覮觲觳謞謘謖謑謅謋謢謏謒謕謇謍謈謆謜謓謚豏豰豲豱豯貕貔賹赯蹎蹍蹓蹐蹌蹇轃轀邅遾鄸醚醢醛醙醟醡醝醠鎡鎃鎯鍤鍖鍇鍼鍘鍜鍶鍉鍐鍑鍠鍭鎏鍌鍪鍹鍗鍕鍒鍏鍱鍷鍻鍡鍞鍣鍧鎀鍎鍙闇闀闉闃闅閷隮隰隬霠霟霘霝霙鞚鞡鞜鞞鞝韕韔韱顁顄顊顉顅顃餥餫餬餪餳餲餯餭餱餰馘馣馡騂駺駴駷駹駸駶駻駽駾駼騃骾髾髽鬁髼魈鮚鮨鮞鮛鮦鮡鮥鮤鮆鮢鮠鮯鴳鵁鵧鴶鴮鴯鴱鴸鴰鵅鵂鵃鴾鴷鵀鴽翵鴭麊麉麍麰黈黚黻黿鼤鼣鼢齔龠儱儭儮嚘嚜嚗嚚嚝嚙奰嬼屩屪巀幭幮懘懟懭懮懱懪懰懫懖懩擿攄擽擸攁攃擼斔旛曚曛曘櫅檹檽櫡櫆檺檶檷櫇檴檭歞毉氋瀇瀌瀍瀁瀅瀔瀎濿瀀濻瀦濼濷瀊爁燿燹爃燽獶璸瓀璵瓁璾璶璻瓂甔甓癜癤癙癐癓癗癚皦皽盬矂瞺磿礌礓礔礉礐礒礑禭禬穟簜簩簙簠簟簭簝簦簨簢簥簰繜繐繖繣繘繢繟繑繠繗繓羵羳翷翸聵臑臒臐艟艞薴藆藀藃藂薳薵薽藇藄薿藋藎藈藅薱薶藒蘤薸薷薾虩蟧蟦蟢蟛蟫蟪蟥蟟蟳蟤蟔蟜蟓蟭蟘蟣螤蟗蟙蠁蟴蟨蟝襓襋襏襌襆襐襑襉謪謧謣謳謰謵譇謯謼謾謱謥謷謦謶謮謤謻謽謺豂豵貙貘貗賾贄贂贀蹜蹢蹠蹗蹖蹞蹥蹧蹛蹚蹡蹝蹩蹔轆轇轈轋鄨鄺鄻鄾醨醥醧醯醪鎵鎌鎒鎷鎛鎝鎉鎧鎎鎪鎞鎦鎕鎈鎙鎟鎍鎱鎑鎲鎤鎨鎴鎣鎥闒闓闑隳雗雚巂雟雘雝霣霢霥鞬鞮鞨鞫鞤鞪鞢鞥韗韙韖韘韺顐顑顒颸饁餼餺騏騋騉騍騄騑騊騅騇騆髀髜鬈鬄鬅鬩鬵魊魌魋鯇鯆鯃鮿鯁鮵鮸鯓鮶鯄鮹鮽鵜鵓鵏鵊鵛鵋鵙鵖鵌鵗鵒鵔鵟鵘鵚麎麌黟鼁鼀鼖鼥鼫鼪鼩鼨齌齕儴儵劖勷厴嚫嚭嚦嚧嚪嚬壚壝壛夒嬽嬾嬿巃幰徿懻攇攐攍攉攌攎斄旞旝曞櫧櫠櫌櫑櫙櫋櫟櫜櫐櫫櫏櫍櫞歠殰氌瀙瀧瀠瀖瀫瀡瀢瀣瀩瀗瀤瀜瀪爌爊爇爂爅犥犦犤犣犡瓋瓅璷瓃甖癠矉矊矄矱礝礛礡礜礗礞禰穧穨簳簼簹簬簻糬糪繶繵繸繰繷繯繺繲繴繨罋罊羃羆羷翽翾聸臗臕艤艡艣藫藱藭藙藡藨藚藗藬藲藸藘藟藣藜藑藰藦藯藞藢蠀蟺蠃蟶蟷蠉蠌蠋蠆蟼蠈蟿蠊蠂襢襚襛襗襡襜襘襝襙覈覷覶觶譐譈譊譀譓譖譔譋譕譑譂譒譗豃豷豶貚贆贇贉趬趪趭趫蹭蹸蹳蹪蹯蹻軂轒轑轏轐轓辴酀鄿醰醭鏞鏇鏏鏂鏚鏐鏹鏬鏌鏙鎩鏦鏊鏔鏮鏣鏕鏄鏎鏀鏒鏧镽闚闛雡霩霫霬霨霦鞳鞷鞶韝韞韟顜顙顝顗颿颽颻颾饈饇饃馦馧騚騕騥騝騤騛騢騠騧騣騞騜騔髂鬋鬊鬎鬌鬷鯪鯫鯠鯞鯤鯦鯢鯰鯔鯗鯬鯜鯙鯥鯕鯡鯚鵷鶁鶊鶄鶈鵱鶀鵸鶆鶋鶌鵽鵫鵴鵵鵰鵩鶅鵳鵻鶂鵯鵹鵿鶇鵨麔麑黀黼鼭齀齁齍齖齗齘匷嚲嚵嚳壣孅巆巇廮廯忀忁懹攗攖攕攓旟曨曣曤櫳櫰櫪櫨櫹櫱櫮櫯瀼瀵瀯瀷瀴瀱灂瀸瀿瀺瀹灀瀻瀳灁爓爔犨獽獼璺皫皪皾盭矌矎矏矍矲礥礣礧礨礤礩禲穮穬穭竷籉籈籊籇籅糮繻繾纁纀羺翿聹臛臙舋艨艩蘢藿蘁藾蘛蘀藶蘄蘉蘅蘌藽蠙蠐蠑蠗蠓蠖襣襦覹觷譠譪譝譨譣譥譧譭趮躆躈躄轙轖轗轕轘轚邍酃酁醷醵醲醳鐋鐓鏻鐠鐏鐔鏾鐕鐐鐨鐙鐍鏵鐀鏷鐇鐎鐖鐒鏺鐉鏸鐊鏿鏼鐌鏶鐑鐆闞闠闟霮霯鞹鞻韽韾顠顢顣顟飁飂饐饎饙饌饋饓騲騴騱騬騪騶騩騮騸騭髇髊髆鬐鬒鬑鰋鰈鯷鰅鰒鯸鱀鰇鰎鰆鰗鰔鰉鶟鶙鶤鶝鶒鶘鶐鶛鶠鶔鶜鶪鶗鶡鶚鶢鶨鶞鶣鶿鶩鶖鶦鶧麙麛麚黥黤黧黦鼰鼮齛齠齞齝齙龑儺儹劘劗囃嚽嚾孈孇巋巏廱懽攛欂櫼欃櫸欀灃灄灊灈灉灅灆爝爚爙獾甗癪矐礭礱礯籔籓糲纊纇纈纋纆纍罍羻耰臝蘘蘪蘦蘟蘣蘜蘙蘧蘮蘡蘠蘩蘞蘥蠩蠝蠛蠠蠤蠜蠫衊襭襩襮襫觺譹譸譅譺譻贐贔趯躎躌轞轛轝酆酄酅醹鐿鐻鐶鐩鐽鐼鐰鐹鐪鐷鐬鑀鐱闥闤闣霵霺鞿韡顤飉飆飀饘饖騹騽驆驄驂驁騺騿髍鬕鬗鬘鬖鬺魒鰫鰝鰜鰬鰣鰨鰩鰤鰡鶷鶶鶼鷁鷇鷊鷏鶾鷅鷃鶻鶵鷎鶹鶺鶬鷈鶱鶭鷌鶳鷍鶲鹺麜黫黮黭鼛鼘鼚鼱齎齥齤龒亹囆囅囋奱孋孌巕巑廲攡攠攦攢欋欈欉氍灕灖灗灒爞爟犩獿瓘瓕瓙瓗癭皭礵禴穰穱籗籜籙籛籚糴糱纑罏羇臞艫蘴蘵蘳蘬蘲蘶蠬蠨蠦蠪蠥襱覿覾觻譾讄讂讆讅譿贕躕躔躚躒躐躖躗轠轢酇鑌鑐鑊鑋鑏鑇鑅鑈鑉鑆霿韣顪顩飋饔饛驎驓驔驌驏驈驊驉驒驐髐鬙鬫鬻魖魕鱆鱈鰿鱄鰹鰳鱁鰼鰷鰴鰲鰽鰶鷛鷒鷞鷚鷋鷐鷜鷑鷟鷩鷙鷘鷖鷵鷕鷝麶黰鼵鼳鼲齂齫龕龢儽劙壨壧奲孍巘蠯彏戁戃戄攩攥斖曫欑欒欏毊灛灚爢玂玁玃癰矔籧籦纕艬蘺虀蘹蘼蘱蘻蘾蠰蠲蠮蠳襶襴襳觾讌讎讋讈豅贙躘轤轣醼鑢鑕鑝鑗鑞韄韅頀驖驙鬞鬟鬠鱒鱘鱐鱊鱍鱋鱕鱙鱌鱎鷻鷷鷯鷣鷫鷸鷤鷶鷡鷮鷦鷲鷰鷢鷬鷴鷳鷨鷭黂黐黲黳鼆鼜鼸鼷鼶齃齏齱齰齮齯囓囍孎屭攭曭曮欓灟灡灝灠爣瓛瓥矕礸禷禶籪纗羉艭虃蠸蠷蠵衋讔讕躞躟躠躝醾醽釂鑫鑨鑩雥靆靃靇韇韥驞髕魙鱣鱧鱦鱢鱞鱠鸂鷾鸇鸃鸆鸅鸀鸁鸉鷿鷽鸄麠鼞齆齴齵齶囔攮斸欘欙欗欚灢爦犪矘矙礹籩籫糶纚纘纛纙臠臡虆虇虈襹襺襼襻觿讘讙躥躤躣鑮鑭鑯鑱鑳靉顲饟鱨鱮鱭鸋鸍鸐鸏鸒鸑麡黵鼉齇齸齻齺齹圞灦籯蠼趲躦釃鑴鑸鑶鑵驠鱴鱳鱱鱵鸔鸓黶鼊龤灨灥糷虪蠾蠽蠿讞貜躩軉靋顳顴飌饡馫驤驦驧鬤鸕鸗齈戇欞爧虌躨钂钀钁驩驨鬮鸙爩虋讟钃鱹麷癵驫鱺鸝灩灪麤齾齉龘碁銹裏墻恒粧嫺╔╦╗╠╬╣╚╩╝╒╤╕╞╪╡╘╧╛╓╥╖╟╫╢╙╨╜║═╭╮╰╯▓ "$'),.1368;=@BEGJLOQTVY[^`cehjmortwy|~C XPD 8  X DEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijLkl mnopqrs,P`` VXLKEx 4 JKv    A<P ~ w xz{|}utsrq ~ZD bcdefghiponmlkjvy (  \ LtPH Tl@BC qrmnuvyzijEef tuvwxyz{|}~ T T  UVPQRT  WSO 4LP,P X@B CEVTWUFOMBA@CXPc˱YDd\ | @D[G\EGFAAE^]K  ܱܲFGH_QE`FGܳH xR TSJKLMIPjfiQahNOHegɰɺɮɲ" ɱɵ ɹɶɳɫɻɸɯɬɴɷɭfBgD[`hd  dG]˽Cb^ZeEH@FcAi\_a˿˹˸˼˳˵ X˶˻˴˷˺ ˾˲VJIQ]K 8YPX T[NWMURZO\SLH* PpP0l  [ cW \bUYRVgQfXSO]PNZ`a[^M_dLTe  ^W_UXY]SRQ\ZTVܷܴܽܺܿܵ2 H ܾܼܸܻܹܶt  vwux_lkI a SRJIK^YZ\[`]^JK@L  NTUAj`_UaVBɼMNk:< ha@LZBYWX|MN bɾZkFɿDEɽGClmnPOSQR8 chdgfebikjlABZ @ABDCO\[HUVTWopBlk ijnmCDEyUcV ]^IqmcbP_Cl`KJXoEQ dcbmnRedrWgfLMsYZo\ DtuppdeFFXhJ SeqOfjytonuslzmixwvkrq{pt SYU[XNQTPWZORV\~{g|[]upʥ}_aʤhxtv\mvsdnowljkqʡ^rʣfc zbʦei`ʢyOPIKMLEADIRC FHQMSJGB@NHKxt}rCOyEBwJ|LRs~{@FGzv uDND@BCAC@ FB@GԡEDAwԧ|Ԣv{zԥԨsԩ ~ԦԪtԤux}yԣqrjuxq nv{ofsmyzlrthwgipZ0 _UQKTNP SILJOHMRGMGDGSTJBLRFIHHCEKA kONP@EBACD@QF p{}~ z|P`VQAY@XWZb$ monI}|_^]yʩʨwzʧxT HIEFԬԫ|IHGkgYnobfdcea`h}ʪ ʫʭ{ʮʬ~|ʯY[Z@XWV\A( UTZX^UY[]WVQRS\PSRWNQPTj XGJOUIJԺVMHLԱԯԽԿԴԼԾԹԲئ԰ԷԭԵ0Գ ԻԶKԸԮءتةآؤبأإ}زرخKثح~ذدسج ا]c_fW\0U[d Z`eV^bhXagYYKWVMRNQ\[JPZOLXMOJLrX NPIKSRabcB[h_iS  ZʰB`YLi~pgh]j[qijʱ aC_`^ZabMNOشj]klon8@qpmk ʶʹʸʵʳʴʻʷʲʺgoOHpSDKfEdLPczQJ MriTRnlIkGFjhqmeNogcsblpVvdfmqurknhjite \b[`PU_\aQ[TRcSWXZY]^d@ CDBA@ػظؽB@ GCضADغطعؾؼEؿصB@CD@FAA BEnzpvkyx|utm{orwqlsUaXWZ\_VT ][Y_^c^`b`WVUXQRZS\[TYT\\ ]ClmnrssUutV]eEGF}^pH  rsvtuwʼʽWXvxzw{yfwhgc_`bdafeJ I HGKFIKHJHIJ~fged]d_oxl  igNMLLMp\ty|KqʾʿNLru,  Y~Z}xjhkij^PQOhiaKswvzP  hb]ec\ilg`fad[_k^j  ΫΤΪΣΥ}{άΩyΧΨΦ|z΢~Ρέonlknposqpήrmlm0 qr SRTXAZV^[UCWB\]YD@Q  ROOPSVNPUTCRDMQX egkhcbljjmdikfaf`e^hdic_gjb, rDE`rqt{_utWvwxίSy] x|nmoγΰαβδtsvubFac`UEV WTZ\E[YXqompnlmklnnz~}FX`$y zθηιζκyuwwxxvεGJKHgfdeIh Z[\]_aHGY`^psrtqtuossqprofFGU{ λ|I}qrspμzzyiLjM]&pb uvtstνkJU{mCnl^vLwvhu ξ}|{OorpNuqPtsa_`KdLcwxwu@HI {xy|x@40Tlx8(h`(P8| T  d $  | (  $ht$., ̢̯~̮̩̪̭̬̣|̨̥̰̦{̧z̫}̡̤οp8ѡ ~}|~vѤѦ ѨSѬѣxQѮRѥѩѫѪѭѧyѢwzU^d|e`V~TbeI c]a{dYbWX[_\fcZ}ko@QmDqeFSilGHN6`sT JOC^UrAP]pNMtEjBKMRgLPh\phlnk[j_Z@x(q XimOfgAWYVo}GF|ECDzn{HyBz ~y~xxv}w|{z~ |y{}VgjihaJbAt>d |̱ѯur`atvuIW̲ ѰvQ~} ̷̴̸̶̳̺̼̻̾̿̽  ̵̹A@ѱCBF TE ѲDѾѴfѷѺ}ѽ  ѿѸѵѶѼѻ ѳgyurզwա{j գiբ shxեqtդRoxnl~w|pmzvTSkd !x!z jYgw}kn|\ml~Uyi_phqfec]ѹVݷW{yXox`[a^N!@" p|ݱݶݪlݻiz{bkݤnoݥݲݸjdݣ}ݺݨݩ~ݴݫݵݭehfݹݰݬݡSݯmݧݦgc!#ݳݮ ݢQLKObRTNPU!# JZM"$ YX^\]ZV"P%k [BEFDGlCNdMLKceurF"& GէvuxswtqݼV"&H yݽz{rWH|s_I#' ը}~ݾYXJIO^J^#L( @PMSKNQLOR#) լիխժծթ٧٢٥٨٦٣١#)٤ yݿvwu{xtz\Z[$$p* `nKmQRfPTf$$+٩ |BAկzag$+ CGBE@AA@FDWCMNFXHSIVQO$, JPDRUELTGK[\iVLbJ[EeRA,%T-DQa`FX _`cZKSfYamVXCjc]@lgIkPHd\T^bGZYO_UWh]NMB^WUn%- %. մյչվսհ%l/ ձղճպռշջնտ4&0 ٽ٫ٳ٭ٻٶٰٵٯٱٺٷٴv&0 ٬ټپ٪ٲٹٸٮ&1 ո~ٿ&02 JH^FX}_B]GUd][@ZoQamI^KYgDkaMCWh`eSfEPLN<'3 `_nObTcljAVibR\~'3 'p4 E((5 AHIDJ@GCFBchibfeD(5 gdQNWVTOrPqSpXRMoLVUUhYZTXSW(6 vVYd(47 pceqdKjYwBZ[nk\ )7 eofpfghLlZ_qgL)8 ij`CHrhsijBAC@@AAB@k)\9 M[]a~IJ^tklDBrɡɤɣ):Dɢ @E[YLQSLMUROQVZXZKM\TW*:EG^UNJYVHICOP[]PN S\WR]FTKXDjzqKbeBmovhfguT*;GpnsJ uycIMO@lk}rux|AF~wi_d`N{taL*l<|ϡ ϤwϧϪϬtv{Iϥϭ{sd~Ϣxz}}pϨϫzmxϩo^H|wvnϣyqr*4=Ϧy~ LCU[WJMFGJV_E@NBOYDhHHEfZgaS+>b \ecITAG`FQCiPKKX]eRPG[UGDg\+> dXcNOIE@QYBD^F\SHFJhb_]faR`AEWVTLKC+d? MAZIMDJCUVH+X@ DBSKQWAGEBCOLT@FGFEPNR",A @a`F_IJh^CRHKcjbWiULYeTMPZdd,AGQ[NESgVlXfOD ]\}nwmqsu,BS}o u~||vtzwxz~pyx{tsr{y,>\?P@@AxB4CDDElF.tF pmnsrx_ey\vsgwt^abcf]udh`]j`kh_\^bedg[ic-Gfia xyWelA^_b_`a2.\H XZURTVSPWQYϯϳ϶ϲϱϴϵϮϰt.I wxyPLnv{QlrkuqMOzjmst|pNmNPLXJWiH[RlS.IV ZOTjkYMI[QUKHIeOYbXL`^_Jc\ZK]aMd.LJ pwyޡkzޢ}m~lxޣq|ovrnuN{st:/J gdpjlfnmkqhocebriJQUSKI|/KLMHUVGVQOLPN RRMNOPKTSWXT\b`^a]_wtuv/LL lmzkji{ljkyRnb0M Ϸ}ϸϹfPޤ|gBedc`[ϺϽϻϼҢҡ~S]^o\_B0MRp QkjhilަޥީިާstYZr}qpnolɥɦCDfba0|Negcfgd _Ͼ]deab\^c`ϿҨҥҧXWUҤҩTVҦg04OңҪ bfenyhcmtsadurq`ipwTvsVuoqtrUxSޭެު1Oޮ ޫްޯvu~}{zwxy|_\]W[a`^decyx~ámnmJ1PzYvjɧ Eljkhhimkgjfilhү1lQ ҴҫҶҮҹҺҬҸҵҳҷ_]ұҭҰһҲ^Z\xmklstp{u1,Rro ynwzqy[xwv|~ڡ`ڧکڢZڦڥ[abڨX}{ڣz_|ڤڪY^\]W2R޷޻ ޱ޼޲޳޽޺޸޹޵޴޾޶@bR2SA ifegfZcX\[dhYmzjhknlgBEu@oFâD{2LTACGv tãsnnҼҽ}޿]ä{o`Ҿҿ~ګ2 U i^_ropqIH|wcdFjiڬklnmrp3Uq `dcba{zfeڮڭBZ3Vj sæå|sopthinlkje3 Wm fg֢֡|~֤֣}ڶkjڰhڳlڴmڱgiڵڲگ3W ECHIFGDlksmro`qabpn 4X twuvM¡N}O~LPJçxèoKp~}noGb4HY qm֦o֥ڸqڷpJxQqpuprKtRr4Y qrs֧ڹsLducySsnxwvy4Z uvְwtֱֲ֪֭֮֩֫֬֨֯(5T[ ڼھںڻڿڽtCFDEAB@j5 \ NQOMP}~vzywfgex{|h@{A|z~}U¤¥¢£5\ T{éyztwuvfoxuGB|x͡z|~}{5] |ֹzy}~{06D^ ֳִֵֶַָֺֻvwxNQr6^ MLHOPJKITXV6_ SURYWjlikFECDV6<` GZW¦[]\XYê~}z}yq{|~rtsrͣ87`͢ ּֽ־ֿRSz7a TACB@mHI_^§ëšɨVr7tbqp ͤ78c} |z{yAZX@W\[YIHDGF^_[]Z@8c\ pErqnoJ`ª¨©íìHsͥͦ@8|d ~D]^CBJKLa`sK8(e «¬uAEMvͧ9eBC @BDGEFCHAH9`f aPSGLFcJHbONKMIR_Q9g ]XNPUTWRQSY[VOi\bce9g`h dfgvjtxQyw{zON:Xh LPMucag°ed²j±kh®ib¯­flòðñîïP:ió xwyţŢXYm~ͨEFDG:iHI IOMKLNJVdTeUfa^`_:j ka|}WSXTVRU³z{A@tͩ;$kLJKZSYRXVUTQPW X;k lh]_ae[;lYj `d\XWbZ^kifgcrjxtxeubwfvpcqs;tmhgd limynokpyurvltswqnzrm{o<t CBDFGEtuEDpomnq|¿¾ťŤp>lu wvFɩͫvwwtvyu{zxxͭͰͬ|ͯͮ>u [GH]WZcaIgLd\YIbDeV_FK`OMXJ^NEfjlkinH>vom NEGHPLJMQFOKIQO6?dw JߡNKPMGLwu{sߢxr{}v~|~yxy}|tzLx?wH MJKIADC@Btxzw?xv usry}~þĤEŦCDRN{SPTUVOh?lyp WP|RQEߣRͱiQrqWTVSUXYZ>@.?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefgh.@ijklmnopqrstuvwxyz{|}~.A@ABCDEFGHIJK.BLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~.C.D@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmn.Eopqrstuvwxyz{|}~.F@ABCDEFGHIJKLMNOPQ.GRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~.H.J@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrst. Kuvwxyz{|}~.L@ABCDEFGHIJKLMNOPQRSTUVW.$MXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~.0N.?@ABCDEFGHIKLM(N4O@PLQXRdSpT|UVWXYZ[\]^_a bc$d0eQ?@A撍蹾CQDEFHQIJKM䟴QNO骲㩧P㿭㔆RQSTU鵮頕䏙W撴哣QXYZ㧻\Q]^_擪aQb蹨cdf䠋Qg㿺塳hikQlmn啹䂻䎺䪴pQq膪飵r捹㧾s跀嚡摼㹃uQvwxzQ{㦒㨆|㕸}噒Qт㒼氽QчQь羓Qё㗻Qі㾓QћQѠ㿹Q搲ktQQ㨘QQ閪哌苄喹 鰦骶Q煀腭胬尜脴㞗卟醶Q㗝㘉Q嚯QQ婔Q垜Q    Q㜃QQ墙剨㘚箲孨䠀䬬鼧䧧鰟鮍Q嗻㗲嚉丨夂靑!乛亻㔾尣彑忄㣺扌攵歺氵氺灬爫丬犭Q"罒礻糹罓#㓁$耂肀&Q'卝衤见(讠贝钅镸长门)韦页风飞饣+鱼鸟黄歯龜丷Q,阝户钢ņ倻淾]龦㷉袏_灷峵䬠Q`㕙a愢b辧釶熑朙玺dQe㲋f䬐磤琂冮g䀉橣i䈣蘏Qj稪kl靕灍匤n鏴盙Qo龧矝亣俰傼丯众龨吴綋墒壐p庒庙忂q斋s椙橃Qt泿 爀u玌㻛v嬕璹讃xQy窓篬糃繬苸薗龩袐龪躹龫迏蕟駠鈡龬z{䁱䊢娚顨杫䉶圽藖}芿Q~䲁嵻р龭龮宖龯曧繛湗秊㶈䓃Q䎚䔶峕х諹屸㴒嵸龲煗䕘Q䱷㥸㑊ъ諌侴Q妿腬顖弻pDя Q䄂䚻㼇龳є䃸㟖䛷䅼Q䕭㣔љ䕡䔛䶉䱻䵶䗪㿈㙡䓞䒽䇭崾嵈嵖㷼㠏嶤嶹㠠㠸幂庽弥徃㤈㤔㤿㥍惗愽峥㦉憷憹懏㦸戬抐拥挘㧸嚱㨃揢揻搇摚㩋擀崕嘡龟㪗斆㪽旿晓㫲暒㬢朖㭂枤栀㭘桊梄㭲㭱㭻椉楃牜楤榟榅㮼槖㯝橥橴橱檂㯬檙㯲檫檵櫔櫶殁毁毪汵沪㳋洂洆洦涁㳯涤涱渕渘温溆Q溻滢滚齿滨滩漤漴㵆澁澾㵪㵵熷岙㶊瀬㶑灐灔灯灿炉ў䏁㗱垾焾㙎榢Q孴穉穥穽窻窰竂竃燑Q䇊竚竝竪䇯咲笋筕笩箢筯莜Q篐萡箒 㶭蒒篺簵Q籄粃粦晽糉糇糦籴糳糵繧䔝絝Q璍綉綫焵綳緤㴓緵緥Q繮纒䌫鑬縧罀罁罇礶駡羗Q羣䕜䔃Q翺耈耝耯耻耼聡Q䦉朥肧Q脇脚墰汿擧Q舘橓  䑺舩Q  俹蓢荢QQ芪椛䇛r0蕋苐茚IQJ㛁KL艻苢茘NQOPQS㶿茝嗬莅䔋QT莬 菓㑾U橗蕚㒖VX葘QY葱㷓䓤檧葊Z祘[]Q^蓞莑䒠蒓蓤_䉀`䕃蔴嫲b䔧蕳䔖枿蘖Qcd藁e蘂gQhi䕪蘨㙈j号l虾蝱Qm蟮n螱蟚蠏噡虬桖䘏衅衆oqQr衞袜䙛袴袵揁装睷s覇覊覧覼t觧vQw誜瞓釾誐x竩y{䜓Q|煼謌謟}~謿譌譍誩讐讛誯Q䘕衏貛у㜥Q賖ш贒贃賛灜贑Q㻐ct趩ѼQ㭼竧躭躶軃鋔輙輭Q辥錃辳䤪Q廸迹Q㦀逷Q遡邨Q郄邮 酧㫰醩釄粬鈎沟鉁鉢QQ錬鍫炏嫃Q䥥鉄Q鍳鑛躼閅閦鐦閠濶䊹Q䧟氜陻隖䅬隣懚隶磵隽双䦡QQ霱虂霶䨏䔽䖅灵孁霛Q靗孊靟鐥僐鞉鞟鞱鞾韀韒韠Q韮琜韵 䫑頴頳顋顦㬎Q 㵑  2v飊颷飈飇䫿Q喰飡飦飬鍸餹䭲Q駵騌騻騐驘㛄髠髢Q髴䰎鬔鬭倴鬴㣃魐魀Q婅鮎 鰂鯿鰌"鷔Q#$%'Q()鵾鶃*鸎梈鷄,Q-./1鴹Q23麐麕麞麢䴴麪麯4黁㭠㧥㴝伲㞾6鼂鼈䮖鐤Q7鼗 鼹嚟嚊齅馸8韲葿齢齩竜龎爖䮾9;煷Q<=>玞@QA禟BC鍩鏳E鋬鎁鏋QFG爗㻫睲穃烐HJ煾QK炣LM㻇OQPQ㜢RT㛡QUVW㜣Y坛QZ[\xQ蔃ѐ 葕QѕQ䓴њ柹㜳㰕㷧塬Q栐䁗џQ哋嚞Ѥ嚒Q鏆ѩ鎜仸儫㠙亼Q佋侊Ѯ婨Q㦙ѳ㐵伩Q諚Ѹ亘働儍侢伃Q佂倮偬傁俌俥偘僼湶ѽ浲Q冨凃䓝Q赺剙劤Q勡䙺熌Q槑㻞璙琔瑖玘䮎叐㖄爏Q喴响圝鉝雴鍦埝垍坿㘾壋媙Q娬妸銏婾嫏娒Q㛵洅瑃娡xy媁Q鏠璌焅䥲鐈鎽㞠尞岞幞幈Q廍孏Q㜁㛝㛓脪Q弌弎Q婫孄蘔衠恾Q忛㺸Q懀憙憘恵Q 摱Q  㨩 Q挷撶挱揑Q护搻敫楲㯴Q唍Q曎 !㫠䆐#Q$%&(Q)磮*+-㑤Q./0暎2晫䮓昰Q34晣57昞Q8㣑9:㮙<Q=瓐㮖枏>梶栞㯄檾㡣?A樳橒櫉欅QB攑梘橌㯗橺歗CD鎠鋲FQG`銉xz鑧涥漋Q{ |㶏渄}娽渊塇洤硂焻Q烱牐犇犔т兹Q瑺чQ㼆㺱ьQ悧㻳瓌琼鎇琷䒟䕑疃㽣ё㽘畕癳Q㬙瑨і㫻㷍Q㻿ћ釺圲鍂Q僟Ѡ睸眎眏睻Q㩞ѥ琸璛㺿Q䃈Ѫ錇砞碍碈磒珐祙Q䄎蒖禥樭ѯ稺秴䅮䄲鈵秱QѴQ㖗啫㕰㚪ѹ竢婙Q娍Ѿ磰娪竾䇹籝籭䈑Q糍Q粎籼粮檲緜縇緓罎"}綗Q䉪柖Q埄翝笧Q笌駦虅驣樜Q㧢騟蒀Q䓪脷䐂胆脉腂飃艢艥Q葓蘐媆䅿嬫Q嫤蚠蠭Q娂衮佅袇袿裦襥襍襔Q㺭蒣䛵䛏㟲訽訜Q彍鈫旔焩烄鵭貟賩妚矃姰䍮㛔踪躧Q輰轊䋴汘澻䢛潹溋鯩㚵 邻 啱䤆醻鐄Q 䁢 鐧  蓥訫閙閧閗閖Q 瑅㻂  㻧Q 随   㻌Q   琒瑫㻼靁 \桇䨝F G 鍨I QJ K L 銺嬑譩䤼珹N 鞛靱餸QO 巁P Q 頟S 鋶QT 釥䓀U V X 飜QY 㼀鈪䤥萔餻饍Z 㷽馛䭯馪驜[ ] 檏騡嫾騯Q^ 䮐_ 馼䮽䮗鍽塲` 堢b Qc 硄d e 棅㵽鑘㤧慐g Qh 愇鱏鱓鱻鰵鰐魿鯏i 鮟j l 鴡䲮Qm 鸘䲰鴌n o q Qr 鶥蒽s t v 藼䔳Qw x y 萠藮{ Q| } 秢~  䤭Q 㵢鏛銾鍈 碹鉷鑍俤㑀遤у 砽硔碶硋 Q 㚚佲濚濙瀞吔ш 垻壳垊鴖埗焴㒯 燫Q э  Y愌嫎娋䊼Q 㜬䭻 鎻鎸ђ  葲Q ї  Q 妔 ќ 綨 Q ѡ  鋥珢㻩璴Q 㻡Ѧ 櫘珳珻㻖 Q ѫ  Q 瑈Ѱ 炥 銄珦鍟Q 錱 ѵ 鎆 Q 䤵 煫Ѻ  嚤Q ѿ 唂秄 緾Q 䔮鐁㜊 Q 妰  媡㛢Q 㚰鉟婹 鍴㳍 䪖㦊僴㵩㵌Q 煵䋻 渏 䓫浗 灧沯㳖Q 渂漌㵯 畑㚼㓈䚀㻚䡱姄鉮䤾轁 Q 堒埈㛖 烾  Q 梹楧 Q  Q 樚 Q 萾䓟䓎T  Q 漗 茽 菭 Q 妉媂 婡婱 Q 㜭姯 㛇熎鎐暚!婮娫!樫Q!!!!焝Q! !侰 !峂 !Q !!樌!!炦焳Q!㶥泟!!繥姫崯㷳彜!Q!綤萦咅!!!坾Q!!㿥! !瀃Q!!嵰玏糓"!#!俈翧狍猐%!猸猹Q&!獁獈㺩'!遬燵(!珡臶㻊県㻑沢国琙琞琟㻢㻰㻴㻺瓓㼎㽓畂畭畲疍㽼痈痜㿀癍㿗癴㿜発*!熈嘣覀塩䀝睃䀹条䁅㗛瞘䁪䁯属瞾矋売砘点砜䂨砹硇硑硦葈Q+!礳栃礲䄃䄉禑禙辻稆込䅧窑䆲窼艹䇄竏竛䇏両筢筬筻簒簛䉠䉺类粜䊌粸䊔糭输烀,!総緔緐緽羮羴犟䎗耠耥笹耮耱联㷌垴炠肷胩䏭脌猪脎脒畠脔䐁㬹腖腙腚䐓堺腼膄䐥膓䐭膥埯臁臤艔䒏芦艶苊苘苿䒰荗险榊萅烵葤惣蒈䔄蒾蓡蓸蔐蔸蕒䔻蕯蕰藠䕷虲蚒蚲蛯际螋䘆䘗袮裿褤襇覑-!訩訸誔誴豑賔賲贜䞘塟跃䟭仮踺嗘坔蹱嗵躰䠷軎転軤軭軲辷迁迊迌逳駄䢭飠鈓䤞鈨鉘鉫銱銮銿T鋣鋫鋳鋴鋽鍃鎄鎭䥅䥑麿鐗匁鐝鐭鐾䥪鑔鑹锭関䦧间阳䧥枠䨤靀䨵鞲韂噔䫤惨颹䬙飱塄餎餙冴餜餷饂饝饢䭰駅䮝騼鬏窃魩鮁鯝鯱鯴䱭鰠㝯/!鵉鰺黾噐鶓鶽鷀鷼银辶鹻麬麱麽黆铜黢黱黸竈齄Q0!1!2!椚铃妬4!塀铁㞹Q5!6!7!9!块煳Q:!;!!Q?!咞@!A!C!QD!E!惧F!噺H!QI!J!K!M!QN!楕鰯螥O!P!R!QS!T!U!尠W!帋QX!Y!Z!朞\!Q]!^!㙇_!a!Qb!c!卤蒭d!f!Qg!讁h!i!k!Ql!乸炻m!n!Q!!Ѣ!!Q!!拃ѧ!!熘桕Q!槩㛈!Ѭ!!Q!!ѱ!苽!Q!!覥Ѷ!辠!鞸Q!顇骽! ѻ!!Q!!!!Q!!!!Q!!!!徱晈暿Q!!!!Q!!!墵朎椘!Q!!!!Q!!䣐䪸!!Q!!!!Q!!!凒!妟Q!㮾!!!垈Q!㦛!!!㝢Q!譞!!!Q!爉!!奥!Q!"軚"劏圿煱"Q"""喼"Q " "㑳 " "Q"䜘"""Q""偦㓻""䝼Q""""Q"垡煑""遖!"Q""譢#"$"T嵛QV" W"X"諪Z"Q["\"]"䯀_"Q`"a"鑥b"憕娧d"嚹Qe"f"乪g"陖涏i"㘘襷Qj"k"l"n"Qo"筂p"q"s"Qt"穅u"騦v"㙟x"Qy"禃z"{"崬}"Q~"䛐"画补р"墶㜜"Q""㱔х""銁Q""錰ъ""氹钟Q""蠧裵я""Q"溸"є"㦤㚹䔿暶"Q"襃"љ"囖䃟"㦡Q""ў"熭荦"Q"䲷"ѣ""Q""Ѩ""筃祾Q"澵"樃ѭ"厢"鎿栶靝Q""Ѳ""Q""嶅ѷ""圕頣Q"嶫"斾槕叒Ѽ""㰑朶Q""""Q"""Q""""㗊Q""䣺揦"砈鉕#䏲Q#䏟###姸Q# # # #Q #㷷 ##运犏嚋#Q####Q####Q####纟Q #!#䲤镇"#熢$#䶑递Q%#䶜&#达嗁辺'#边)#䔉繿潖檱仪㓤Q*#+#㜺躀,#.#Q/#0#1#3#㷫Q4#5#6#8#亚Q9#:#嚿;#踎孭=#Q>#揞?#@#攰嘭B#吚QC#㷆D#䱽嘢嘞罉E#奵G#蝰东QH#I#J#脗鵞贘瘻鱅癎瞹鍅吲腈苷嘥脲萘肽嗪祢噃吖L#㗎嘅嗱曱QM#㘭甴嗰喺咗啲N#O#廐Q#QR#S##麫絚嗞Q#抝靭咔賍燶酶揼掹揾啩#鱲ш#冚㓟#冧呍唞唓癦踭Q#疱肶蠄螆裇膶萜#䓬猄э#宐茋#噻Q##ђ##Q##酰ї#鈈#Q##ќ#牦#䝎Q##ѡ#䃺鱝攟#䣳Q##Ѧ## Q##ѫ##熣纎鵐业丄㕷嬍沲卧㚬㧜卽㚥Q#墚#舭呋垪Ѱ##㩒Q#獴#䴉鯭ѵ##䱛Q##Ѻ#葜#Q##ѿ#挮紥#Q#㨪逈勌㹴㙺䗩#癀嫰#硺#墧䂿噼鮋嵴癔Q#麅䳡㟻愙##噝#垧Q##刴#㖭鵼S籖鬹埞Q$屓擓$$$蚭Q$$$ $ 凾Q $嶎霃 $麁遌笟鬂峑箣扨挵髿篏鬪籾籂粆鰕篼鬉鰛 $齚啳寃俽麘俲剠㸆勑坧偖妷帒韈鶫轜呩鞴饀鞺匬愰椬叚鰊鴂䰻陁榀傦畆$駚剳酙隁酜酑Q$捿$櫊嘑醎畺抅$獏籰$Q$$盖鮝个$莾衂届槀坺刟巵从氱$伹咜哚劚趂㗾㗳歒酼龥鮗頮颴骺麨麄煺笔毺蠘罸嘠Q$蹷齓跔蹏鸜踁抂$踨蹵竓$稾磘泪詧瘇@QM$鼦泎蟖痃N$硓O$贌狢獱謭猂瓱賫Q$蘯徺袠䒷 QR$S$詾T$惽癧髗鵄鍮鮏蟵賷猬霡鮰㗖犲䰇籑饊V$慙䰄麖慽坟慯抦戹㩜懢厪QW$捤栂㗒嵗X$迚Y$僙[$礆匲阸Q\$䁥矾糂]$糚稭聦聣絍甅瓲覔舚朌聢^$聛瓰脃眤覉`$畓Qa$螩蟎臈螌詉貭譃眫瓸蓚㘵榲趦覩涹蟁b$瓧㷛煶悤憜㳑恷罱c$惩䭾删㰘e$Qf$g$h$j$Qk$l$m$o$峁Qp$q$r$t$Qu$v$䕢嬟w$齐麦y$tL ,、。.•;:?!︰…‥﹐、﹒·﹔﹕﹖﹗|–︱—︳ ︴﹏()︵︶{}︷︸〔〕︹︺【】︻︼《》︽︾〈〉︿﹀「」﹁﹂『』﹃﹄﹙﹚﹛﹜﹝﹞‘’“”〝〞‵′#&*※§〃○●△▲◎☆★◇◆□■▽▼㊣℅‾_﹉﹊﹍﹎﹋﹌﹟﹠﹡+-×÷±√<>=≦≧≠∞≒≡﹢﹣﹤﹥﹦∼∩∪⊥∠∟⊿㏒㏑∫∮∵∴♀♂♁☉↑↓←→↖↗↙↘∥∣ /\$¥〒¢£%@℃℉﹩﹪﹫㏕㎜㎝㎞㏎㎡㎎㎏㏄°兙兛兞兝兡兣嗧瓩糎▁▂▃▄▅▆▇█▏▎▍▌▋▊▉┼┴┬┤├▔─│▕┌┐└┘╭╮╰╯═╞╪╡◢◣◥◤╱╲╳0123456789ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩ〡〢〣〤〥〦〧〨〩卄ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩαβγδεζηθικλμνξοπρστυφχψωㄅㄆㄇㄈㄉㄊㄋㄌㄍㄎㄏㄐㄑㄒㄓㄔㄕㄖㄗㄘㄙㄚㄛㄜㄝㄞㄟㄠㄡㄢㄣㄤㄥㄦㄧㄨㄩ˙ˉˊˇˋ k讖艷贛釀鑪靂靈靄韆顰驟鬢魘鱟鷹鷺鹼鹽鼇齷齲廳欖灣籬籮蠻觀躡釁鑲鑰顱饞髖鬣黌灤矚讚鑷韉驢驥纜讜躪釅鑽鑾鑼鱷鱸黷豔鑿鸚爨驪鬱鸛鸞籲①②③④⑤⑥⑦⑧⑨⑩⑴⑵⑶⑷⑸⑹⑺⑻⑼⑽ⅰⅱⅲⅳⅴⅵⅶⅷⅸⅹ丶丿亅亠冂冖冫勹匸卩厶夊宀巛⼳广 彐彡攴疒辵¨ˆヽヾゝゞ々〆〇ー[]✽ぁあぃいぅうぇえぉおかがきぎくぐけげこごさざしじ,すずせぜそぞただちぢっつづてでとどなにぬねのはばぱひびぴふぶぷへべぺほぼぽまみむめもゃやゅゆょよらりるれろゎわゐゑをんァアィイゥウェエォオカガキギクグケゲコゴサザシジスズセゼソゾタダチヂッツヅテデトドナニヌネノハバパヒビピフブプヘベペホボポマミムメモャヤュユョヨラリルレロヮワヰヱヲンヴヵヶАБВГДЕЁЖЗИЙКtЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщъыьэюя⇧↸↹㇏k%乚l%刂䒑龰冈龱n% ¬¦'"㈱№℡゛゜⺀⺄⺆⺇⺈⺊⺌⺍⺕⺜⺝⺥⺧⺪⺬⺮⺶⺼⺾⻆⻊⻌⻍⻏⻖⻗⻞⻣ʃɐɛɔɵœøŋʊɪ纘纛纙臠臡虆虇虈襹襺襼襻觿讘讙躥躤躣鑮鑭鑯鑱鑳靉顲饟鱨鱮鱭鸋鸍鸐鸏鸒鸑麡黵鼉齇齸齻齺齹圞灦籯蠼趲躦釃鑴鑸鑶鑵驠鱴鱳鱱鱵鸔鸓黶鼊龤灨灥糷虪蠾蠽蠿讞貜躩軉靋顳顴飌饡馫驤驦驧鬤鸕鸗齈戇欞爧虌躨钂钀钁驩驨鬮鸙爩虋讟钃鱹麷癵驫鱺鸝灩灪麤齾齉龘碁銹裏墻恒粧嫺╔╦╗╠╬╣╚╩╝╒╤╕ ╘╧╛╓╥╖╟╫╢╙╨╜║■%鋛%Q%蕌䊵珯况㙉%%鍄%苮Q%砼杄拟%%%Q%%侫%倈%Q%%%% Q%徤%%滛%儁㑺儎顬㝃萖Q%%兠%兪%Q%%%%Q%%宂蝽%%冲冸鴴凉减凑㳜凓Q%决凢卂凭菍椾%彻刋刦刼劵剗劔効勅簕蕂勠蘍%%啉滙Q%&&匳&泋Q&栛珕恊㺪㣌&燝䒢卭却&卾&Q &矦厓 &厠厫厮玧 &㽙玜叁叅汉义埾叙㪫 &叠Q&&叶&吓灹唫晗浛呭&Q&啝咏咤䞦&&㶴&~0H&I&啇䳭启琗喆喩 K&QL&䕒M&暳N&嘷曍P&暤暭噍噏磱囱鞇叾圀囯园QQ&㘣R&坆S&汮炋坂㚱U&埦QV&堃W&X&堦Z&塜墪㕡壠壜Q[&壻寿坃\&]&鏓㖡够梦㛃湙_&娤啓Q`&蔅姉a&b&d&Qe&姙f&g&i&浱Qj&k&姹l&媫婣㛦n&㜈媖瑥嫓Qo&p&㶅q&㜲s&広勐孶斈孼Qt&䀄䡝u&寕慠v&x&Qy&寳宝䴐尅z&尓珎尔{&}&屉䣝岅峩峯嶋Q~&&崐崘嵆р&岺巗苼㠭&Q&&芇㠶㯂帮檊幺х&&厦亷厨Q&帉廴&a廹廻㢠廼栾鐛弍&Q&㫞䢮&强Ѿ&& Q&彣鞽&彲鍀&徧嶶㵟&Q&&&釖&Q&怱暅&㥣㷇㘹垐&祱㹀悞悳&Q&&璤僡媠慤萤慂&&憁凴Q&憇宪&&懓&Q&懐㤲&&怣慜攞掋&担Q&拕&捬&㨗搸揸&Q&澊&頔&&擡擥鑻㩦携㩗敍漖Q&&斅敭敟&斵&䬷旑䃘Q&无旣忟&昘&&晄Q&&晋&晧&晳Q&&&&Q&矅&馤朂&'㬫槺Q'杧杢''柗䓩栢湐鈼栁'Q'桝+8'槡樋:'楳棃Q;'椁椀㴲㨁<'㮀枬楡='䋼椶榘㮡?'荣傐槹Q@'A'橅B'檝㯳枱櫈D'㰍欝QE'惞欵歴F'溵G'I'QJ'㝀吡K'毡L'毜氷N'QO'P'汚舦汹Q'䓅S'QT'U'V'X'㛥㳫QY'鮃Z'['羏样]'Q^'_'涖浜湼漄`'b'Qc'蔳d'凇 萮e'g'瑓Qh'秌湏媑i'濸㜍澝j'滺l'Qm'䕕鏰潄潜㵎潴n'㴻澟o'濓q'Qr's't'v'Qw'凟x'y'{'Q|'灋灾炧炁烌烕烖烟䄄㷨熴熖}'焫煅媈煊岜~'煏鍢'焬Q''у'熺'炽爎"鑂爕夑鑃爤鍁'爮牀ѷ'梽牕牗㹕'栍漽犂 猫Q''䣭Ѽ'猨献珏玪'Q'珉瑉'''昣㛅Q'''珷琕椃'琹Q'㻗'瑠'瑇珤瑶莹瑬㜰瑴鏱樬璂䥓'Q'''孆'Q'瓈'甎甞''寗Q'鎅畍畊畧畮'㼄'疎瑝疞疴瘂瘬癑癏癯癶'皐臯㟸Q''皡皥皷盌'葢'Q''眞眦着撯'睘'瞯Q'''矴'Q'棊碯磇磓隥礮'磗礴碱'辸袄'Q''禆褀椂禀'禝'礼禩渪Q'㺨秆'秔 lħ<(pXؽTLLLDx "$'),.1368;=@BEGJLOQTVY[lehjmortwy|~( |dl XP`YW ][fa_jhomsqwu{y&Vg Zl\nph ^tx Xir`vz|}~@ k.x p  @ABCDEFGHIJKLMNOPQRSTUVWXYZ\]^_`abcdefghijklmnopqrstu [6 cxe (P 8@ JK>X ƵƶƷƸƹƺƻƼƽƾ| wx¤ v F( ơƢƣƤƥƦƧƨƩƪƫƬƭƮƯưƱƲƳƴ@ ZD bcdefghiponmlkjvyʥD   N   ҦTPt  8 <TlL`h@BC qrmnuvyzijEefV @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdef.Xghijklmnopqrstuvwxyz {|}~ǡǢǣǤǥǦǧǨǩǪǫǬǭǮǯǰDZDzdzǴǵǶǷǸǹǺǻdǼǽǾǿ ڧP@ABCDFIJMOPQRTUy H ^ w hY ]$ Sf n< KpT z, F~hhn j\^pf HEo\0 e4\ E}XdVM[Yv WESxQl k{, `K<L K~l digh z BD fR mnoȭ  pd ( ` ttxLD  ZH}}x  JGQЮ  xk  T  Io~  y{دD  Dh L KS\  ]  aR  "  Vd$  8  Id  Y*  IrkPl  eDncSyj]ci  pD j M2X  dot|  fna]~i b cG  ur:8  |\  Zmp P\H@P,P 4L(T$Dd < p     < `      0 \    < P t   0 T h    ]B MW Ƶ J~ D@J, FNsX Hζ| KUN_Y `Rt UDV Y[ECַ P( ZD \ g޸p vQs@O  zdb  ~npS^\ z]dbdL( T|Uzjd vpKTQD CG XY0 Br$ H ]E` yL8 Lz MzW  Rg@  Ľ, JD VIH` dU|M HI}PG̾ U XP AZ\  \Կ@ `E` XcIX| knOF uypxJ  oj_A`O NUyW0 Ys` IC& [h XF Vx{@B CEVTWUFOMBA@COXPrc˱ƿYDdF. @D[G\EGFA{AE^]WKpܱܲF GH_Q~E`oFGܳHk@R TSJKLMIPjfiQahNOHegɰɺɮɲgɱɵɹɶ ɳɫɻɸɯsɬNɴɷOxɭfBgD[`h6 dG]n˽Cb^ZeEH@FcAi\_a˿˹˸˼˳˵x˶˻˴˷˺o ˾˲PWVJfIQ]KxYPX T[NWMURZO\SLHpnl8$Pt <Th\@Xx$<X|8PXt(X8p0>  Y[c@cW \bUYRVgQsfXSO]PNZ`a[^M_dLTe^W _UXYV]SRQ\ZTVܷܽܺܿqܴܵ ܾܼܸܻܹܶrFgi vwuhx_lkIh a SRJIKQ^YZ\[`o]^JqK@RLZD! NȢTUAj`_URSaUV[Bɼ}hGMN~k " ha@LZTzBYWXON"MN}b ɾZkFɿDEɽGClmnPOSQR|# chdgfeboikjl@$ABZ @ABDCO\[UHVUVTWop %lk ijqnmCDEyUcVV% L]^IqmcbP_Cl`KJXh}oEW&Qd cbmXnRaedrWgfLMsYZo@' DtuppdezFFXh( SeYZqOfjytonuslzmixwvkrq{pY^( SYU[XNQTPWZORV\~{g|[]upmʥ}_aʤhxtv\mDvsdunowljkqʡ^|)rʣfc zbʦeiV`ʢyOPyIKMLEADIRl*C FHQMSJGGB@NHKxt}rCOZyEBwJ|L$0+s~{@FGzv ]QuDNDy@BCACf , FB@GԡEDXWAAwԧ|Ԣv{zԥԨs,ԩ ~BԦԪtԤux}yԣNjqrjux-q Fnv{oFfsmyzlrthwgGiHpS,|.~C _RUQKTn\/NP SILJOHMRGMGDGSTJBLROFIHHCEKP0A kTOUN_P@EBACD@QFj,1{}~ bz|`P^`VQl~AY@XWTZ4 2 monI}|_^][yʩʨwz\ʧ[xWTev2ZHIEF Ԭԫ|IHGkgYnobfdcea`3}ʪdv ʫ`ʭ{ʮʬ~|ʯsY[Zr@XWV\AT4 UTZgX^UY[]W}VQRS\oPSRWNQPAT<5 XGJJOUIJԺVMHLԱBԯԽԿgԴԼԾԹԲئ԰ԷԭԵ~5ԳiԻԶKԸ Ԯءتةآ}ؤبlأإ}زرخKثح~ذدسج6 eNاnT{]c_fW\7U[d Z`eV^bhXawgYYKWVMRNQ\[oJPZOLX}~MOJLD\8 NPIKxSRrabqcB[h\_tiS49 Z]ʰ^B`YLBi~pgh]h{j[q_`ij9ʱ aC_`^ZabMNOشj]klon :qpmk LʶʹʸRʵʳʴʻʷʲʺgoOHpSDKtfEdLPcLl;QJ MriTRnlIkGFjhqmeNogcsblpwVvdTfmqurknUhjitH<e~ \bB[`PU_\aQ[TRcSWXZQY\]^d@L@=kCD xBOAqe[P@ػظؽB> @MrGCضADغطsعoؾؼEؿصB@CD@FT>AA BEArnzpvkyx|utwm{orwqlxsUaXWZ\_VrT? ][Y_^c^`b`WKVUXQRZS\[TYuT@\ ]gCTlmnrssUutVa]eEGFH}^pArysv tuwʼgʽWXvxzw{ybcfw}hgc_`bdasfeJ\lBIkHGKF IKHJHIJm~fged]d_oxu8C igNMLLMp\ty|]LKqʾʿNLruD Y~Z}xjhDkij^PQOhiaKswvz"D dhMb]ec\ilg`fad[_k^jdE hΫΤΪΣΥ}{άΩyXΧΨΦ|z΢~ΡέsonlknposHqpήrmtlm\Fqr SRTXAZV^[UCWB\]YuDx@Q` G RaOOPb@SVNPUTCRDMQ*G Qegkhcbljjmdikfeaf`e^hdic_gjbXflHTr DE`rqt{_utWvwxίSy]I x|unmoγΰαβδtsvubFac`UE@JViWT OZ\E[YXqoNmpnlmklnnz~}FX2Jy zez{θηιζκyuwwxxvεGJKHgfdeIjhtK Z[\]_aHGY`^SpsrtqtuossqprofFGUY@AC{L λ|aFbI}qrskpμzzyiLjML]|Mb uvtstνkJzUQ{mCnl^vTLwv:4Nul ξ}|{OorpNuqPtsaWa_`KdLcpwxwQu@|OHI| {nxyO` ?@AdB0CDDETFGGHI8JJKLtM,NNOP.P ̢̯~̮̩̪̭̬̣|̨̥̰̦{̧z̫a}̡̤οfQѡ ~}|~zkvBhRѤѦ ѨSѬѣxQѮRѥѩѫѪѭѧkyѢwhzU^dm|e`V~Tb(SeI c]a{dYbWXq[_\dfcZ}ako@QmDqeFSilG[HNSsT JOC^UrAP@]pNMtEjBKMRgLPMh\phln~k[j_rZ@Tqv XimOfgAWYVo}GnF|ECDtzn{tHyBzqJUy~y |~xPxyxv}w|{zuv~Vt| y{}wyVgjihaJbAtlW |̱ѯur`atvuIyWv̲`R SSTUVdW4XXYZt[(\\]^_d`0abbcdXe(fgghiXjk llm\n@oppqrsTt@uuvwHxyzz{|}D~ ̀|XT(. pmnsrx_ey\vsgwt^abcf]udh`]j`kh_\^bedg[icfia gxyWelA^_Gb_`a XZURTcVSPWQYϯpϳpo϶ϲϱϴϵϮlϰ܉^ wxyPLnv{QlrkuqMOzjmst|pNmNTPLXJWiH[RlSFV ZOFTjkYMI[QUKHIeOcYbXL`^_Jc\ZK]apMdQCtZpwyޡk zޢ}m~lxޣq|ovrnu~N{st0 WQIgdpjlfnvmkqhocebriJQUSKI LMHUVGVQOLPN RRMSNOPKTSWXT\b`^a]_IwtuvNl mzkji{ljkAD_yGRnbHϷ} ϸϹfPޤUKL|gBedc`x[ϺϽϻϼҢҡ~S]^o\_RpQ QkjVhilަޥީaިާWstYZfr}qpnolɥɦiCDfbaegcfgd _Ͼ]deab\^c`IϿҨҥҧXWUҤҩTVҦgVdңҪL ebfenyhcmtsadurq`ipwTvsXVuSeuYoqtrUxSޭެު,ޮޫ ްޯvu~}{zwxy|_\]W[a`^deJcyx~ámnmzYvjɧ Eljkhhimkgjfi[lhSү ^ZҴҫҶҮҹҺҬҸҵҳҷ_]\ұtҭsҰһҲ^Z\FdxmkhlNsetp{u^roZynwzqy[xwv| i~Eڡ`ڧکڢZڦڥ[abڨX}{ڣz_|ڤڪY^\]mlWk޷޻ޱ޼sn_޲޳޽޺޸޹޵޴޾޶ qxzwyu]@bA| DifegfZcXy\[dhYqmzjhknlg^BEu@oFâD{$ACGv tãsjnnҼҽ}޿]ä{o`MҾҿ~ګf i^_ropqIH|wcdFjiڬmklnm{rpTq `vdcbax{zfeڮڭB8j qsæå|sopt\hinlkje,mDf g֢֡|~֤֣}ڶkjڰhڳlڴmڱgiڵڲگn ECHIFGDlksmro`qabpn twuvM¡N}O~LPJçxèoKpY\~}wnoGl qm֦o֥ڸqڷpJxQqpuprKtRr4H qrs֧kڹsLducySsnxwvyv uvְwtֱֲ֪֭֮֩֫֬֨֯ȟ ڼھںڻڿڽtCFDEAB@O NQOMP}~vzywfgex{|h@{A|z~}U¤¥¢£<l T{éyztwuvfnoxuGB|x͡z|~}{~P L|ֹzy}~{O$ PֳִֵֶַָֺֻFvwxNQ MLHOPJKITXVD SURYWjYlikFVECDVx GZW¦[]\XYê~}z}yq{|~rtsrͣ`͢ hּֽ־ֿiRS ,Tr ACAB@BmHI_^§ëšɨVrL qp ͤ} |Dz{yAZX@W\[YIHcDGF^_[]Z\ jpIErqnoJ`ª¨©LíìHsͥͦM@| sG~D]^CBJKLa`PsOIKT@QR«¬ uLAVMWGXEMvͧBC @BDGE\SFCHAVO^jЬ d]aPPSGLFcJQHbbONKMIR_QR ]XNPUTWRQhSY[VOiaY\bce\d`h dfgvj]ftxQyw{zOndN LPMuScTag°ed²j±kh®ib¯­flpòðñîïó axrwyk@ţŢXYm~{ͨEFDW_G"HI sIObMKLNJXurVdTeUfZa^`_d yxka|}WSXTVRUz³\z{A|@}tͩTLJKZSYRXVUTQPW ( Blh]_ae[*Yj `d\XWvbZ^kifgcgrBjxtxe}ubUwfvpcqslhgd limynok`bapyurvltswqnzrm{ocе ~_Yia]dg\e`Zhc^b[f nt¹w´µovqº·m¶su¸rpv÷øôõúö~}2ġ B@BAlpnopt qrs tuo  j»ĢCIuM`[_]^\@ijnohkgm@pz|}:T ùDONbaBCAsmlnrqd~yexûýüP|<edc DopN~CAB{|}kz{¼½l$ԉl(\$ؓxL0d@dHpX$t8 Ȭ\ L ȵ|L4. ģQ ARS@BTfA@hqiklsͪCUhg CBDFGEmtuEDpomnq|¿¾ťŤB wvFɩͫvwwtvyu{zxxͭͰͬ|ͯ]qͮ [GH]eWZcaIgLd\YIbDeV_FK`OMXJ^NEfr\jlkinH\om ftvwyNEGHPLJMQFO\KI_cQO4 gJߡNKPMGL|}~wu{sߢxr{}v~[|~yxy}|tzLJH MJKIADC@Batxzwvusry }~þĤEŦCDRN{SPTUVOhp WP|RQEߣRͱiQrwqWTVSUXYZߦ ߧߥߨߤSJFIKHGklĥF}}X[AJJvHKMNR`L ˢˣ{ˡ|zy}~~jͶ͵ͷͼͲ͹Ϳʹͺ;͸ͽͻ<ͳ RwAb\daqt]kV`ceТwIUСYWRo~svХMf}^xФuy|mУ{Tl p_ZSXTgnӥ[ hzAӨJvBӣ}QӲӪ~өx|ӵӭӤӳtӬsӫr\ӦFz{ӡuӯ ӮӶӴӰӧӢwӱyUx^`ey]houZ biS@wrnj\aYofcsdzlckZ_pvA[gmVxqtvlx`}۪ۧhۣiwst] ۤXۡu۬pۯnzrۭkdocaۥjۨH۩~vf^ۢ۫e۰qD m|xyg{bۦelۮbg_u~Uߵ߿ߪ @߲ f߶߱nE߫`߹߸߼߾߰ߴbL߻ߺ߬߭߷b_ ߳߯߮`mqX[YZ]aU^ WVTc\b_mrstgfbvuߩ_c]pawZXdniO mB߽[RU{\SQNe`hx|WkoTyLrVjP^Yl}zqwMI(@CEAG@DL FUOF\JTQDHBVSPWMK{NS@ERDAjMOQIPBRJGU vHTKLVCN~ ÿħĩĦ ĪĬĭīapĨh~JPKIGHL0t VEFGOhӸӷ@B|{~XZYWЩЧЦikjШr\ ӿAFӼӽCӻHӾyӹGDӺEBILץKר׫HF~שקפ׬׭ׯװ}(Eעס׮GףIDצM Jתۿ۴۽۱۶ۺ۸۲۵۳۾ۼ۷۹ۻ kdz8 akg_e`o\hi_^lb]cn[mjfY]Zag\pj_kfm^`nXlzdch[ bieCoa^ ĮįBEACDQON@PFM|ZnxЪ GlЫױNj|ЬЮЭmIJNM@lKL PײUTE׸R׳S׿׻׽׷׾O׺R׹׵׼״׶QD `tBAv@nprqs o up|wyqux{stzrvrqwst uxvİIKHJŨRŧ]HIKJPHn WVCFEDXy{zıTS[ yЯoCA@BDIGH}|}IJLUũLx qrабpTRQXPYVSWUO_Y^`Z[X]\DFEI( CB@GAHPMEJQXGP OKNLFLx{NM}OKy|z~wJ |~E ~KtA O@BCķĵLĸĴĶij@NMPQAV[XhŪXWZY CB@A@MNgmzL { DDZaTSvbHVUWQRFEˤ\[I YZXGst]^hfcgedJLQSRUOKMT`PN [HTSUNd HIJHĺĹRBS\ūŬEB ji\]вvu_&X WV_b`ae^fcdV@LNKMTowlkhh `[^Yl]\_Zhonpmrikgjqs[aY4bX]c`_^ W\ZAC@EBFDZ JEA@CBDROSQPT\.ļľ ĽĻCEVDUaŭ`Ů^]bcF_\QPOpn`HIp UJyxcabmnCAEFLHJBIKDGb@acuwv{ xtyz|gfdeMNILJKLH@GMFGHI XYWVZXxYWFdůeHG|}~6h ]d@ZPO|GdAT[CE}˦x ˥`жд|г~{}еzjgn[ilT,X4p<8 lT Hpd<p l`D`,` T.\hekmf pzvy~w|roq}uxty{sMeOgiNfjbhGO~h PEJCBUMLKIN}DFHeRCASDBQPOE>0 UoRSQT˪˧ˬ˨˩˫hlимй jлнпокqprзlVWTnS\ [\ZfŰut@As_a]`o^pnsUTSqsuJtra^_M`[\J K]LOPNpR_Q^Ŀc]HIFC]qqo VqB^xvzDywIC[B@CPAmlljbqeovnysuc iwuhxzkrswutfrvtsdgpcaWYeZ\fL[w db^c`MXg]x_xz 4r@~ |y{wv}RZUgPJOVN eTqcdNXtysowuhb}W~Kx mkfAn{jz@S[v|rlQApYiBCYDDA CQ B@@CEEBADv UEEK tE_Lz Fyl`Y Tc[XeU_aWfX]bjgk^Zhj\GdfiSVIHJV s cqdalhrbetympid`CokugnzjBf@  DHACKEMafOhNIdjNJK`gMeL_cbO^ i @CűmplnoijgkhŲųQKMLNJNCDSRT_U^VruthsRrpqw  ^ x   S  tDxv$  {EF}zy|{~{hTP[\MKIJFFNHLf  GnlmwxEGFPmlkV  ɪXVYWˮ˰˯˭W t@ YEF~|}IHKJG}, ܣ ܢ|~ܡjkiGHOIoAGLn ܤܦܥnoml PJptqusyBܨܧsprq  R]^_`QNKPSLROMfwvx~}z{|HISknQRoŴŵq X[EG FWCftQRDaSMܩFܫܪQuv48 XcbdVUTTPA@}{~|y@z]z\J|KRpvŷ^ŶOPHvi CBqrWDXALMTQNܬ z|wx{ytgWe[fYZU[YXVZW EJFI^HGDBECF@AQNOPrVUtsŸjI`X< ܭhBbGB~H uRSi tDCsAu`IHOJܮKd~}  if\kjlga_i^]`\K^]_NLMRKQTSPOjRMfJHIX {k CDlXWgUTYvŹwWvVwlaYmD4  PUj`WVLlw  onqsrtpmocfdcUihgbbaedZR^[]\Y_b`a@T  XcSMUEF]qm`^]cas\Z[_bx~Tqy[ < Z}|Y{Xz }~{Żx|yzźRVSmJvjWkzL, jlWuejmf_dkN fde\żb]I[\hvw^nqpoghfe\< gWOPeGrgih`ŽTUVKcxi^aJ{rdAizy iSRQh^]Lt|{}xvwTsuy trum`|j{z~jmltosqpnkCBDAugX WUTJKvIHwxloVpT omsqkvjqrnuctgz`V_ſ~p žZ\_[`YW]X^MZ\[yPxwzst\ }~okplmnz{~|vy}EFw^ }HYZ[MxOPsNzX{L }{|x~zwywabd"8c sindgkreosjcmlqphbfNOad, ]^}`_ba|{x|}( PQTG QSpRmecATJ*t dHurqLJKI\fvwd}uܰl xRe~]gyA^|{zM}fN~ ihijTSgjih setCmtȡȣH2 t ( |dD, plxP0x@  P ,  L 4 $4LPP0$ x(.0 bd< ICH]^ADGFHI@P FGDXPH XP||: qu| vH | NKzHGB  ES,  rH  Gd  }J  {  _T y t  uR  I|c`m!b kj8! TsX! BveZx! l! n! u ! @bd! v{b! mB\" D" {(h" j" " P4" Ҧ" " Fc0" r# # f,# Sb@# 8X# zp# # @b# r@ # ^\ # C $ |!@$ _YkH!d$ DJ!$ dMWCD!$ T"$ P"% ceo~C",% fpu"d% ]H@v#% wdgX#% KSJ#% _#(& X$@& a}`$l&$ @ P\ x     !0!P!p!!!!!!"<"`"x"""""""#$#8#P#h#####$8$\$$$$%$%\%%%% &8&d&&$& Byz$|' ~D|q&%' Nh%'c InZ{|%' %(( Ar.&D( p&`( r&x( s&( _6'( x'( '( |EnVK'( >() (,) @(H) Nhl)h) jtF)) A)) ))  *) N*) ** *$* +8* GaZV+T* GfU+* C+* dND,* iK|^, + U,l+t lc,+ `Xv$-+ JIxf- , UVQDUc-4, kQ-p,W xP,., Ln., @., Aa., 4/, |v/- B/(- C/<- yD<0P- {n~0l- y^0- S1- D1- t1- EG1. PH 2. [/0. L2D. L2\.''' (<(X(p(((((( )$)@)`)))))P))*0*L****+d+++,,,h,,,,,,- -4-H-d------.(.<.T.h.2p. Ki3\/ T3x/ s3/ Y// 3/ */ B4/ P"0 N&0 _\4(0  @0 NOP4T0 P4p0 s"50 Xd50 ^Yu50 "0 pq50 wm*61 ]l601 A6H1 k6`1 }MQ27|1 1 hmt71 g1 71 lR71 p 2 :8,2 |8D2 SU8\2 V9x2 B92 WY92 []92 O:2 {BJ:2 PP:3 `EF:,3 b{`c;L3 iGR;t3 |ef;3 rz;3 hwg<3 Y3 Z<4 i<4 Q<44 _ =L4 jb=`4 k=t4Pp/////// 0 080L0h000000 1(1@1X1t1111112$2<2T2p2222223$3D3l3333334,4D4X4l44=4 lҦl5 Nmg(>5 j>5 T35 >5 F 5 >6 0? 6 wr?H6 Z?t6 TQ?6 8@6 nz@6 pb=6 o@{@7 Y@47 @_@AL7 h7 vA|7 GtA7 B7 FOIuHB7\ QyKB7 X_B8 |CC08 MPCT8 [zXCl8 B98 C8 D8 8 XD8  9 iRD 9 T3<9 nT3P9 T d9 ||gDx9 NtE9 `E9 {SXy{E9 E: bH&F0: KhFd: @^_JpF: g: cHF: ~.G: CHpG;x5555556@6l66666P6,7D7`7t777778(8L8d8888889949H9\9p9999:(:\::::: ;<;GD; JKG< 6H@< ZxHT< YHx< [H< F>I< m|aI< `RI= OJ0= nmdSxFJD= ]ZPJl= bOJ= R K= kNK= kK= QqK> LjL8> aVLT> DLp> ibL> UM> w^M> P"> M> M? 6H? }"0? fY$ND? XfN`? Dt? TN? tXD? tN?~ }oaRXh,O?I MIqnO@ nCYf}oFm|e~XwOX@ mFF[gO@ bkNg4PA `u{j^vPPA ~h[]VbOPA _eLPA [fNB ,B m@B 0>L>h>>>>>P>>?(?jQ HGjQ R qJ(R E0AdBDTF<GI8JJKLtMNOP. F̵̹Q{A@ѱCBu qլիխժծթ٧٢٥٨٦٣١v P`nKmQRfPTp PCGBE@AA@FDWCMNFXHSIVQO;, JPDRUELTGKYM[\i^VLbJ[EeRA}}Bl X^{ DBSKQ~WAGEBCOLT@FGFEPNR`R SSTUVdW4XXYZ(\\]^_d`0abbcdXe(fhg$i llm\n@oppqrTt@uuvwHxyzz{|}D~ ̀d|XT(.lfia gxyWelA^_Gb_`aCxZpwyޡk zޢ}m~lxޣq|ovrnu~N{st`l mzkji{ljkADyGRnbǘL ^ZҴҫҶҮҹҺҬҸҵҳҷ_]\ұtҭsҰһҲ^Z\FdxmkhlNsetp{u ޷޻ޱ޼sn_޲޳ ޽޺޸޹޵޴޾޶qzwyu]@bKA| DifegfZcX\[dhYqmzjhknlg^BEu@oFâD{ACGv tãsjnnҼҽ}޿]ä{o`MҾҿ~ګϙqp ͤ} |Dz{yAZX@W\[YIHcDGF^_[]ZS`\ jpIErqnoJ`ª¨©LíìHsͥͦM@ QR«¬ uLAVMWGXEMvͧך ]XNPUTWRQhSY[VOiaY\bce`h dfgvj]ftxQyw{zOndN[DYj `d\XWvbZ^kifgcrBjxtxe}ubUwfvpcqsXl(D\$ؓ0d@dHpX$X \<L |L4. gJߡNKPMGL|}~wu{sߢxr{}v~[|~yxy}|tzLߛ_ ߳߯߮`mqX[YZ]aU!O mB߽[RU{\SQNe`hx|WkoTyLrVjP^Yl}zqwMIcMOQIPBRJGU HTKLVCN~ ĪĬĭīapĨh~JPKIGHLtKL PײUTE׸R׳S׿׻׽׷׾O׺R׹׵׼״׶Q)X |~Ek0ŪXWZY CB@A@MNgmzT,X4p<8 llP Hpd<(p  `D`,` T. PEJCBUMLKIN}DFHeRCASDBQPOEjbqeovnysuc iwuhxzkrswutfrvtsdgpcaWYeZ\f1| DHACKEMafOhNIdjNJK`gMeL_cbO^s` R]^_`QNKPSLROMfwvx~}z{|HISnQRoŴŵqD[EG FWCftQRDaSMܩFܫܪQuv  EJFI^HGDBECF@AQNOPrVUtsŸjI`X9 set{(t|dDX <plxPx P ,  L 4 $4LPP0$ xZyt`iùrO_TdZ}PİþYT NrlcĪS|OLSw. ICH]^ADGFHI@s. P~\htȈԉ(4@LXdp|P@Xܟ|gԺ8Pp4$XhP pp,D}丗丢丬乕乢亊亰仫仭仼伜侊俿偂偐偸僘僞僴儖兊兑兤兪内冐冝冦冨冩凇凖凛凬凼刋刔刕删别刹剏剱劐劒劔劜劯劵勐匀匇匤卆卟厓厰叝吣呐呑咊咝咣咴哐唣唿啌啓啝啬喞喩嗬嗵嘣噐噼嚊嚔嚠嚯囘圀坙坥坿垅垉垡垬垴埀埈埓埯塄塬墒墚墲墸壥壻夂夋夐夘夛璌璍璙璛璤璴璹瓈瓌瓐瓓畂畕畮疍疞痜瘬癏癑癳癴皥盙眎眏睘睲睷睸睺睻瞘瞯瞾矃矅矋矝矦矴砞砽硂硄硋硑d唖壷頴葛焔艶襖鴬鴎躯恢晦蛎撹鎌噛潅諌煉巌蝉騨箪贋饗尭繋頚倦捲鹸砿麹麺賎讃蒋醤穣撰巽庖聡楕竪瀦梼祷涜迩祢嚢蝿剥禄溌醗箆頬桝侭薮篭蝋倶植殖慎具真値置直槙惣拶呟鞄噌僅嘘虞夲奛奝奣奬妛姗姫娚媪嫐嫱嬶寉寳尓尜尞屓岙岜岺岻峁峵峺崕崘崾嵓嵜嵭嵳嵴嶌嶐嶹巐巓幇幤廏廐廪廰弉弌弑弡弴彁彅彑彜彦徃忰恊恠悋悦惞愑愠愡愼愽憘憷懴戓戝戞户幺氐収伫低吴囱壮夹妆尬决冲灾见角贝车亚来仑两协届冈底抵东争状籼纠卧轧邸长门侠侣兖则劲却奂帅柢汹为纣红纪纫纥约纡胝苎计订讣贞负军轨闩韦页风飞俩们伥个伦仓冻刚剥员娱孙峡岛岘师库径挟时晋书泾浃乌狭狈亩砥秪纺纱纹纯纽纰级纭纳纸纷胁脉刍记讦讨讧讪讯训讫岂财贡轩轫钉针钊钋闪阵陕陉饥马骨伪伟侦侧务动区参哑问衔国坚垩执够娄妇专将d屉峥岗带帐张强从徕凄怅扫挂扪抡挣败启斛斩昼勖弃条枭杀氢凉浅渊泪沦净牵狰现产毕异众绊统绍绋绌细绅组终绁绂钵习荚茎莒庄苋处术衮觅规访讶诀讷许设讼讹贩责贯货贪贫轭软这连迳钗钓钏钒闭陈陆阴顶顷鱼鸟卤麦备伧伞凯剀创劳勋丧单哟唤乔围尧场报埚壶娲寻岚帧帏厕厩恶闷惬恻恼拣挥换扬枣栋栈钦残壳氯氩涌凑湮涡汤测浑涣无犹苏画痉发盗砚秆窗笔笋绞结绒绝丝络给绚绖绛肃肾胀华莱苌虚视评词证诂诏诅诈诋诉诊诃贮贴贰贻贲费贺贵买贬贸贷轲轴轶进邮乡钞钮钙钠钧钝钤钣闵闰开闲间闳队阶阳韧项顺须饪饭饨饮饬冯驭乱债传仅倾伤偬铲势积汇吗呜呛园圆涂块坞埘茔奥妈爱忾怆恺损抢捣构晖晕旸会业极杨桢枫岁沟灭湿滑沧烦炼炀焕爷狮猾珲当盏睐睁雎碌节笕粤经绢绑绥绦义羡圣肠脚肿脑荤苇叶莴虞d虏号蜈蚬补装诧该详试诗诘诙诣诚话诛诡询诠诟贼资贾贿赀赁赂赅较载轼轾农运达违过邹钴钳钹钸钾铀铅钩铂铃铉铋钜铍钿铆闸陨隽电预顽顿顼颁颂饲饴饱饰驰驮驯鸠侥侨匮厌尝呕叹喽啧哔团图尘垫堑寿梦夺奁妪实寝对屡崭岖币帼彻态惯恸惭惨搂掴掺畅荣枪滚渍汉满滞渐涨涟沪渔渗涤荧尔荦狱琐玛疟疡疯痪尽监硕祯祸种称洼窝笺筝绽绾综绰绫绿紧缀纲绮绸绵纶维绪缁绶罚闻莅盖荪苍蚀诵语诬认诫误说诰诲诱诳诮宾赈赊赵赶辅辄轻远逊递铰银铜铭铢铬铨铵铣阂闺闽阁阀际颇领飒饺饼饵饷驳肮骰鸣鸢凤齐亿仪价侬侩俭剧刘剑刽厉唠嘴哗嘘喷啸叽墟坟坠堕娴婵妩娇娆宽审写层嶔帜废厨庙厮广弹庆虑忧怂悯惮愤怃挚扑捞拨挠抚掸揿敌数暂昵样桩枢标楼桨乐枞欧殇殴浆泼洁浇溃润涧浔热奖莹疮皑皱盘确码窑穷缔练纬d缄缅缉编缘线缎缓缍缂缈缇骂罢胶肤莲荫蒋虾蜗卫谊谅谈谆诞请诸课诿谄调谁论诤谇诽谀竖赔赏赋贱账赌贤卖赐质赓践辉辆辍辈辇轮辎辋辊适迁邻郑邓锌锑销铺铐锄铝锐锉锋钡锂闾阅巩颉颌养饿馁驼驻驷驶驽驾驹驸骷闹鱿鲁鸩鸦麸齿俦傧侪幂剂吨哝嗳垦坛奋袅学导宪凭惫懔忆战拥挡挞据掳择捡担挝历晓晔昙桦横树椭桥机桡淀浓泽浊沣澦渑炽烧灯烫焖独玑瓯 瘘卢瞒砖碛积颖稣窥笃筛缢缣萦缚县缟缜缙绉腻兴舱荡萧芜蚂萤裤亲觎谛谚谏讳谋谍谐谘诺谒谓讽谕谙谌谖赖辐辑输辏办选迟辽遗邺锭锯锰错钱钢锡录铮锥锦锟锢锱阎随险静腼颊颈频颔头颓颐馆饯馄馅骇骈骆骸骼鲍鸵鸪鸯鸭鸳龙龟优偿储励咛吓压埙婴嫔嬷尴屦屿嵘帮弥应恳戏击挤拧拟搁敛毙暧档检桧栉樯殓毡泞滨济涛滥涩潍营灿烛烩墙狞获环瑷痨疗矫磺矶d 篓粪镆糁缩绩缪缕缧绷缝总纵缫纤缥繦缦声聪联耸脓胆脸脍临举艰蔷蓟亏蝼蝈亵褛觊谜谤谦讲谎谣谢誊谧赚赛购赙趋辖辗毂辕舆还迈酝镀镁锚键锲锅锤锺锹锻锾锷阔阕阑闱隐隶虽韩颗飓骋骏鲜鲛鲔鲑鸿鸽点斋丛噜圹垒婶懑扩掷扰撵摆擞撷断槟柜槛柠欤归殡泻渖滤渎溅浏烬焘犷猎瓮疠睑础礼穑秽窜窍箫簧箪篑简粮织缮绕缭绣缯翘职聂脐膑旧萨蓝荠蛲蝉觐觞谟谨谬谪赘蹒迹跸躯转辙迩医酱镑锁钨镍镇镐镒镉阖闯阗阙杂双雏鸡额颜题颚颛馏馊馈骑髁鲨鲤鲫鲧鹃鹅鹄垄坜宠庞庐惩怀懒拢旷橱椟榈橹潇濑沥濒泸烁牍犊兽獭玺琼畴瘪碍祷稳签茧绎绳绘罗缴膻艺薮药蚁蝇裆袄谱识谭谲讥谯赠赞跷辚轿辞边镜镝镞链镗镘镖镙锵镂铿錾关陇难雾韬韵类颠飕馒馑骛骗鲸鲳鲭鲷鹑鹉鹊鹌鹏丽麴劝咙嘤严宝悬忏拦搀胧榇澜潋炉珑矿d砺矾砾窦竞筹篮辫缤继罂胪舰蔼蔺芦苹蕴蚝褴觉触议译谵赢赡趸释钟铙锈阐飘饶饥骞腾骚鳃鳅党龃龄俪嗫啭嚣属惧慑摄携斓樱栏棂歼烂牺镶璎癞缠续兰藓蛎览谴护誉赃踌跃跻轰辩镰镭铁铛铎镯镌响顾颢飨驱骠蓦骡髅鳍鳏莺鹤鹞龇龈啮俨傥呓孪巅峦弯摊权欢滩猡叠瘾癣笼籁聋脏袭衬读赎赝踯踬辔郦铸鉴霁鞑繮颤骄骁鳖鲢鳔鳗鹧鸥鼹龉龊龚恋挛搅瓒窃缨臢萝蛊变逦逻镳铄靥显餍惊驿验髓髑鳝鳞鳜鸶嘱坝揽瘫癫羁蚕让谗谶艳赣酿雳灵霭颦骤鬓魇鲎鹰鹭硷盐鳌龌龋厅榄湾篱箩蛮观蹑衅钥颅馋髋黉滦瞩镊鞯驴骥缆谠躏酽钻銮锣鳄鲈黩凿鹦骊鹳鸾钺仂虍殒垧坻戋俣刭厍呙卺纨茇钇钆呗弪祓纾郏钌剐匦囵垭娅岽崃涞渌烃眦绀绐胫钎钐钕钍闫妫嵛恽桠枨沩浈畲砗绗菝觇讵诎诒贶贳轺轵轸逯郓鄄钫钬钛钯钭钪闶陧顸饫黹伛偻d佥唢垲巯徭炜茕狲玮绨绠绡羟荭蛱诓诖诩诔诜趑辂辁邬铊铈钰钲钶锍铌钽钼颃颀凫黾偾唛嵝帻悫悭怄戬戗抟抠掼桤杩荥浒沤炝皲砀绻绲绯绺莳觋诶赇铱铒铑铕铟铫铯铪铷铖铥飑刿劢哓呒崂峤庑愦挢椠毵颍涝潢涠滗琏璁瘗缃缗缌缏缑荜蒌茑苁诹诼谂赕郸锒铗铽锓锊铤锆锇锔阆阃靓颏饽驵骀鲂鸨哒哕哙嫒峄怿殚浍烨猃狯碜窭縗缛蒇荨蒉荞莸芗蛳诨谑谔谝郐锩锬锖锗铼锛锕锞钔阏阈阉阊阌阍鸲鸱哜帱恹摈泶猕甓瘅痫硗箦筚糨缡耧荟莶蛰裢觏谡诌谥跄锸锴铡锶阒饧鲒鲕鸸鸹鸺龀怼摅撸泺疖缋聩荩蟥虮讴谩赜贽辘邝镓铠锼镏蓥韪饩骐骒骓阋鲩鲠鹈鹁鹆厣呖垆槠栎氇泷潆祢缲缳罴舣蛏虿裣觑觯谮镛镟镪镆铩韫颡馐髂鲵鲶鲻鲱鹎鸫黼喾撄栊枥栌缱聍茏苈蕲蛴蝾铴镦镨镡镣镄镫铧镤铹阚颟馔驺骝骟骘鹗鹚鹜龆龅傩岿痈撺d榉滠砻粝纩缬蔹赆镱闼飙骢骖骜鲥鳎鳐鹣鹘鹾冁娈灕攒瘿箨籴舻觌跹跞轹镔镬骣骅鳕鲣鲦鹨鸷龛栾椤蓠雠轳鳟鲟鹩鹬鹪鹫鹇灏簖谰髌笾粜缵脔蹿镧鲚趱躜酾谳颞颧骧鸬戆阄鲡鹂禸拔跋珐宫拐毁减禄吕潜袜郧兹戸抛挧掻揞揺撑擀擡擶攅攵敎敫斈旙昞昻昿晄晗晩晳暃暼暿曁曵曺曻朎朖朷杤杦枦枧枩査柽栀栁栅栞桊桒桕桙梍梹棏傈锨鲗椢椦Üü椶楡苅苊苘茘茚茣荆荛荢荬荮莜莟莵莼菷萪葈葜葢蒄蒈蓜蓣蔸蕚薗薫藁蘓蘖∋蜕蝰蝽螋螨蟇蟐蠇蠎蠧袮∈袵袿裥裵褜褝襷觧訷説諚譛譱谫谺豼貎貮贒赉赍赱踈踺蹰躙躰躱軅軆軎軣輌轱轷辧迯逎逹遥邉郞鄕釖釛釞釡釥釶釼鈩鈬'鉙鉷鋭錺爫冂冖丷八儿朩氺厂疒肀衤丆⺗勹匕‡㐄凵屮囗亠冫⺀槇╎◘◙♂▶◄↕‼¶∀↨↔⌂\ 亜悪圧囲医壱逸隠栄営駅謁円縁応欧殴桜奥穏仮価画灰会悔海絵壊懐拡殻覚学楽喝渇巻陥勧寛漢関歓観気帰戯犠虐旧急拠挙虚峡挟狭郷響暁勤謹区駆勲径茎恵掲渓経蛍軽継鶏撃県倹剣険圏検権顕験厳呉娯誤広港鉱号国黒穀砕済斎歳剤雑参桟惨賛残歯児辞湿実写舎捨釈寿収衆従渋獣縦粛処将称渉焼奨条状乗浄剰畳縄壌嬢譲醸触嘱寝尽図粋酔穂随髄枢数据"瀬声斉静窃摂絶専浅戦践銭潜遷選繊禅疎壮争荘捜挿巣窓装僧層総騒増憎蔵贈臓属続堕対帯滞滝択沢濯単嘆団断弾遅昼鋳庁徴聴懲塚逓鉄点転伝電灯当党盗稲闘徳毒独読届難弐悩脳拝廃売梅博薄麦縛発髪抜浜敏敷侮払仏辺変歩舗簿包宝抱泡胞砲豊飽墨毎満脈黙訳薬躍与誉摇様謡曜来頼乱覧竜隆旅両猟緑涙塁礼励戻霊齢暦歴恋練錬炉労楼録湾弥亀曽姉宍嶋\%樫椛喰粂込榊咲鴫雫椙揃駄凧栂辻働峠栃凪匂硲畑畠噺鋲塀柾俣杢籾匁俤俥凩叺哘囎圦圷圸垈垳垪垰埖塰墹壗屶岼峅岾嵶弖怺掵杁杣枡梺椥椨橺椣椡楾榁槝樮橲欟毟渕熕瓧瓲瓰瓱瓸甅畩癪硴竍竏竕竓竡竰笂簓簗粐粭糀糘綛縅繧纃纐膤艝萢蓙蘰蚫蛯袰裃裄褄躾軈轌辷迚逧遖錵錻鎹閊閖靹鞆鞐颪鮖鮗鮴鯏鯑鯒鯲鯱鰰鱇鱚鳰鵆鵤鶫乄呏挘鮱鱩鵇鵥鰯麿冴呪枠鮎'邨冲㘭担勅枱响恒叁烱堃啟鈎着琼煊滙叠献裏碍羣綫踪鑛捬徧尅耻峯㦸煑賍韮塲婣罸嵗慯榘綉粮綳澁嫺墻牕癎輭銹鵞麯罇鷄贘决虬咤厦刦朶両却廹効咏廸妬怱牀脗瘻弍晋暨慤捏烟洤粧糉叙敍坂珏胆㕑欵碁双猫猪珉畊姹燄甎緜駡覩濶㩗擪㯭没湼畧塩刄憇携臯况凑汹够迹飱攷脉袴㨪躭羗騐紥櫈册刧脚厠厢汚氷舘喆廻凉碱鉢卭凃葱覇靭讐隣廼隷兎鰐昰xX*鉕砈鍅鉳鍩釟釚硔硦碈碶磇磒磗Å⇋磤磮磰磱磵礲礳礶祘〓祙祱祾禃禆禇禑禙禟禥秢秱秴稪稺穅穥窼竂竉竛竩竾笌笧笩筂筃筕筯箲槞槹酶腚苷呋脲肽萘酞酰醌腈䐶腙肟啉吡哚吲喹咔硒硅硌蒽萜苄葻謭坋坅蟎噠嗪噻肼碸樌哌篐篬篺簕簛簵籄籭粎粸糃糦糭糳糵糹糼綋綗綤綨緍緐緓緥緽樒樢樰樶橥橳橸橼檩檪,⓪①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳鍄鎭鏆鏥鐚鐡鐾鑁鑓鑚钚钷铘铞铳锃锎锏锘锝锪锫锿镅镎镢镥镩镲閇閙閠閲陦隝隯隲霳霻靍靏靑靕靤靫靱鞒鞲韲頽顔颥飃飚飮餝餠饣馀馇馍馓馕馼駈駲骶髙髞鬏魉魲鮃鮟鮻鯣鯵鰀鰄鰛ⒶⒷⒸⒹⒺⒻⒼⒽⒾⒿⓀⓁⓂⓃⓄⓅⓆⓇⓈⓉⓊⓋⓌⓍⓎⓏⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ®™T/鱶➊➋➌➍➎➏➐➑➒➓鲅鲆鲇鲋鲐鲞鲮鲰鲲鲴鲺鲼鲽鳆鳇鳊鳋鳓鳘鳙鳢鳫鳬鴪鵈鵐鵺鷆鹋鹕鹛鹱麪麽黄黢黪鼈鼋鼍鼡齄齑龝﨎﨏﨑﨓﨔礼﨟蘒﨡﨣﨤﨧﨨﨩丄丯亁亇亣亷亼仸伨伩伷佂佅佋佲侢侰侽俈俌俰俲俹倃倈倴倻偘偦傁傐傼僐僟僡僼儍儫兠冮冸凒凢刅刴刼剙剨剹劤勌匧卂卝卽卾叅叐叒叾呭咅咓咞咹哣哯唍唘唥唨唫啇啹喐喴嗁嗗嗘嗻侴嘡∃噒☻1噝⑴⑵⑶⑷⑸⑹⑺⑻⑼⑽⑾⑿⒀⒁⒂⒃⒄⒅⒆⒇噡嚉嚋嚞嚡嚱嚹嚿囖囯圕圝圲圽圿坃⇔坾垊垍垐垜垻垾埄埞埾堒堢塇塜塟塳墧墪墰墵墶壋壐壠夅夑妉妔妚妟妰妸姄姯姰姸娂娋娍娒娡娤娧娪娫娬娽婅婔婙婡婨婫婮婱婹婾媁媂媆媈媑媙媠媡媫嫃嫎嫏嫓嫤嫰嫾嬍嬑嬕嬟嬫孁孄孆孊孏孨孴孶孼宂宐⒜⒝⒞⒟⒠⒡⒢⒣⒤⒥⒦⒧⒨⒩⒪⒫⒬⒭⒮⒯⒰⒱⒲⒳⒴⒵㈲㈱檫T4宖⒈⒉⒊⒋⒌⒍⒎⒏⒐⒑⒒⒓⒔⒕⒖⒗⒘⒙⒚⒛寕寗尣岅岞峂崐崬崯嵈嵖嵰嵻嶅嶤嶫嶶巁巗帉幈庒庽弎彲徱忂忛忟怣恾惗愇愌愙愢慐慠憁憕憹懀懏懓懚抐挱⊃挷捹掋揁揢揦揻揾搇搲搸搻摚摱摼撍撯撴撶擝擥攊攑攟敟敭斆斵斾旑旔旣旿昘昣晣晫晽暅暒暚暤暭暳暶曍曎朂朌朙杄杫枏枤枿柖柗⊂栍栐栛栶桇桖梄梈梽棃棅椂椃椉椘楃楆楤楧楲榅榟榢槑槕槖騡騦騯櫁6妿槡樃樚樜樬樭樳橃橅橌橓橗橣橴檂檊檏檙檧檱檵檾櫉櫔櫘櫶歗歺毜氜氱汘汮汵汿沯泋泟泿洂洅洆洦浗浛浱涁涏涥涱淾渂渄渏渘渪湐湙溚溵溸滛滺漄漋漌漖漗漴漽潖潹澊澝澟澻澾濓濙濸瀃灋灍灐灔灜灧灷灹炋炏炠炣炥炦炧烄烌烐烖ɪɛæʌɑɔʊɝəɚɜɡṃṉŊḻɵðʃʒʧʤãɯɸʇÇœɒgˋˏabdefhijklmnoprstuvwzT9烵㈠㈡㈢㈣㈤㈥㈦㈧㈨㈩烾焅焝焩焫焬焳焵焻焾煀煏煫煵煷煼煾熌熎熑熖熢熣熭熴熷熺燑燝燫爀爉爎爏爖爗爤媤爮⊆牗牜犔猄猐獁獴玌玏玘玜玞玧玪珕珡珢珤珦珯珳⊇珹珻琂琑琒琔琕琗琙琜琞琟琷琸琹瑃瑅瑇瑈瑉瑓瑖瑥瑫瑬瑴瑺璂厂广丨幺冖宀卩⺇匃☒艹䒑⺌⺊丶匚⺕└乚辶廴冈亅丿乛厶车纟讠贝鸟门钅阝扌氵亻忄灬⺮口櫢騻騼驘驜驣;☎→←↑↓⇨⇦⇧⇩☞☜☛☟〖〗○✕✓囻☽夝晍爥✩✡☺☹屸♬♪嫑宷峼✉✂峕杮瑡璝罓薓❏嵸弻━┃骲髠鬔鬴鬹魀魐魿☼綕☁霴☂✈℻℡曧湗煗秊№腬諹顖☠♤♠♧♣♢♦♡♥櫤℞㏂㏘㎡㎥☑鮁鮋鮍鯝鯩鯭鯴鰟鰠鰦鱓鱝鱻鴌鴖↲欅9T>賩賲贃贑贜赺趩跀踁踎蹆蹨蹱蹾躀躶躹躼軃軤軭軲輰轁轊辥辳辸迊迏逈逳逷遤遬醩醶釄釺鈈鈓鈡鈨鈫鈵鈼鉁鉘鉝鉟鉫鉮銁銄銉銏銱銺銿鋔鋛鋣鋥鋫鋬鋴鋶鋽錃錇錰錱鍀鍂鍃鍟鍢鍦鍨鍳鍴鍸鍽鎁鎄鎆鎇鎐鎜鎠鎸鎻鎽鎿鏋鏓鏛鏠鏰鏱鏳鏴鐁鐄鐈鐗鐛鐝鐤鐥鐦鐭鑂鑃鑍鑔鑘鑥鑧鑬鑹鑻镸閅閦閪陖陻隥雴霛霶靀靁靗鞇鞉鞛鞱鞽韀韂韒韠頔頕頣頳顨颷颹飇飊飠飡飬飵@鴡鴴鴹鵉鵎鵭∷鵮鵼鶃鶓鶥∬鶽殁殱鱏麐鷀☯☰☷☳☴☵☲☶☱鷉鷔鷼鸊鸌鸎鸘鹻麅麢麬麱黁黆黇黱黸鼧餎餙餜餷饝饢馛馤馪馸駠駦駵騟緾縇繛繥繬缷罀罁罉罒羏羓羴翝翧翺耂耈耮耯耼肧脌脪脴腂腖膄膥臤艔艥艻芇芿苢苮苸苼苿茋茝茽荗莑莬菍菭萅萔萖萡萮萾葊葓葕葘葤葲葿蒀蒒蒓蒖蒣蒾蓞蓡蓢蓤蓸蔃蔅蔐蔳‐蕂蕌蕒蕟蕯蕰蕳藖藠藮藼蘍蘏蘔蘨虂虅虲DC袜孭脷餸啲啫㗎啱喺嗱㗒嗰嘅嘢嘭噃嘞嚒糍吚吓咗曱甴呍嚤嚟擓挮揸攞乸毪氲氽汢沲淸温湶溂溆溻滟滢漑漤潴澑澵濳濵炻烀焏∂煕煳煺刣㑑迌ÀÈÌÒÙÁÍÓÚāēīōūǖÄËÏÖÜÆÇÑÃÕáéíóúǘäëïöüæçñãõǎěǐǒǔǚÅÉ熈ØÐỲÞߪ¡àèìòùǜå熘燗øðỳþÿº¿âêîôû燵ÂÊÎÔÛ¸¤ƒEwxyzΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩαβγδεζηθικλμνξοπρστυφχψωㄅㄆㄇㄈㄉㄊㄋㄌㄍㄎㄏㄐㄑㄒㄓㄔㄕㄖㄗㄘㄙㄚㄛㄜㄝㄞㄟㄠㄡㄢㄣㄤㄥㄦㄧㄨㄩ˙ˉˊˇˋ␀␁␂␃␄␅␆␇␈␉␊␋␌␍␎␏␐␑␒␓␔␕␖␗␘␙␚␛␜␝␞␟␡€DH讖艷贛釀鑪靂靈靄韆顰驟鬢魘鱟鷹鷺鹼鹽鼇齷齲廳欖灣籬籮蠻觀躡釁鑲鑰顱饞髖鬣黌灤矚讚鑷韉驢驥纜讜躪釅鑽鑾鑼鱷鱸黷豔鑿鸚爨驪鬱鸛鸞籲①②③④⑤⑥⑦⑧⑨⑩⑴⑵⑶⑷⑸⑹⑺⑻⑼⑽ⅰⅱⅲⅳⅴⅵⅶⅷⅸⅹ丶丿亅亠冂冖冫勹匸卩厶夊宀巛幺广廴彐彡攴无疒癶辵隶¨ˆヽヾゝゞ〃仝々〆〇ー[]✽ぁあぃいぅうぇえぉおかがきぎくぐけげこごさざしじJЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщъыьэюя⇧↸↹㇏乚刂䒑龰冈龱゛゜ゔヷヸヹヺ・。「」、・ヲァィゥェォャュョッーアイウエ¬¦'"㈱№℡オカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン゙゚DM爲爼牦犂犏犟犭犱犸犾狍狛猤猯猸猹玽珎珱瑶璢甁甙産甼畄畉畍畭疂疃疉疬痖痩癀癍癔癨皀皃皐皷皹眍眞睃砘砜砹砼硇硖硺碵碹磆磙礇礰礴礻禀禝秃秡稆税穃穐竃竒竢竧竸笶筢筬筺筻箚箞箟箢箧篶簒簔籏籖籘粫糺絈絋絷緔緕緖緤繍繝繿纉纎纒绔绱缒缰罱羂羮翆耠耢耥耱聟聨肬O肷冚吖吔㓟䱽拃哋喼肶冧唓舦唞嗞掹梘唂啩疴揼麄鈪裇悞嘥煅嫲劏噏瞓螆踭膶㗾燶蠄鎅癦鱲拎麖䦉糓軚麫擧芪杧浲礆秄罎蟮莾蘯覥䘏飈饀饍騌髗麘鼦伃伹伲侫偖倮傦僙儎僭儁凴刟剠剗劚勑勠勡凓凟畆凾匲匬匳厫厪龎呩咜叚櫊啳㗖嘑噍噔㗳坆坺坧堺埦埝塀堦壜妷姙尠峑峩嵆嶎巵帋帒帮幞DR彍穽寃窻徤徺徼恷悤悳惽愰憜慙慽慜捿懢烕戹扨抅抂抦拕捤挵撐㩜晈晧朞栃枬柹梶椬椁椀棊楳榀椾榲槀榊槺槩檲橒檝欝歒毺㳑泎湏涹潄濚炁秌焴㷌煶爕牐犇猬犲狢猂獈猨獏獱斅瑝瑨甞畓畺皡盌眤眫䁥硓磓磘鵾碯慂禩鰺秔稭稾穉竝竚痃瘇瘂癧癯嘠詧鼗笟箒箣篏篼籂籑籝籰籾粆粃粬糇糂糚絍絚緵縧繮麕剳耝聢聣聦聛肦脃麁臈T辠臶舚蝱螩螌麞蟁鸜蟖蟵蠏蠘蠭衂衅鰵衮袪袠抝襃襍煲衞苽䒷苐莅鴂齩萠蓚蒭䓻蕋蘂蘐揑覉覊覔鱅覼詾詉謌譃讁譌貭賫賷贌趂趦跔踨蹏蹷蹵躧輙轜鵄郄酑酜酙酧酼醎醻麨遖遌釾鉢銾鍫鍮鎺鐧閗閧阸隃隖隁隽霃霡霱靟鞟鞴鞸鞺鞾韈麿頟頮龥顇顋顦顬颴齚飜飦饂餹餻齓饊齅䭾駚竈骺骽鼂鬪鬭髢鬂髿䰇鬉䰄䰻鮏鮝鮰鰌鰕鰊鯿鰮胨胩胬脎DW氹乪陁売祢栢脇埗䓪搵蔴䃟椚鰂疱菓煱樋橺髴瞹攰涖嘷朥樫絝遡亘粦笹奵㛇灿溋靝鋐坔㻙憙瑠焿礮媖鍈暎俽鍁㙔嵵瀞敻炍廍悧窰彣珷瑨疴魩½⅓⅔¼¾⅕⅖⅗⅘⅙⅚蚒蚠蚭蚲螥螱⅛⅜⅝⅞蟚衏衠袇袏袐裦裿褀褤襇襔襥覀覑訜訩訫訸訽⌒誐誔誜誩誯誴諪謟‰謿譍譞譢譩讛豑貛貟賔賖脒脱脶腟腭腽膓膪膸臁舩舭舮舾艢艪芈Y\\\ \ \\\T "T%'P*,L/1L46L9;L>@l Gig[NMLLMp\ty|KqWʾʿJYNLru\ Y~Z}@Wxjhkij^PQpO[iaswvpdz½8 XBhYb]ec\ilg`fad[_k^jqs ZrΫΤΪΣΥ}{άΩyΧΨqΦ|z΢~ΡέPAonlkn]posqpήrmilmFqr SRT[XAZV^[UCWB\]Y\D]@Q R^OOP_egSVNPUTCRD`MQ~tzaʾ̦ beghcbljjmdikfcaf`ed^hdic_gjbe fr DE`Srqgt{_WutCWvwxίfiy]N xl|hDnmoγΰαβδCtsvugoPbFac`hUE\VWT iZ\E[YXqompnlmklnnz~}F@Xҿ<yuzx rjYjθqηιζκyuwwxxvεGJKHgfdeIkh$ Z[\]_aHGY`^psrtqtuossqprofFGU{V{fV λ|lI}uEqrspμzzyiLjMF{]qb uvtAstνkJU{mCnl^vmLwvuξ }|{HOorpNuqPtsGZa_`KDLcnwvxwHu@ЮHIo {pNxqy^wxyxzX{@|(} ~܀t<܉|h<̓pX(؜ĝĞdT0ĦT4Ȯ.tkJ ̢̯~̮̩̪̭̬̣|̨̥̰̦rt{̧z̫}̡̤οvKtѡ G~}|J~KQsvѤѦ ѨSѬѣxQѮRѥYѩѫѪѭѧdyѢwLzAijU^dM|e`V~Tb$leI c]H{dYbWXt[_\fcZ}qsko@QmDqeFSilGNHNfXsT JOC^uUrAPv]pNMtEjBKwMRgLPxh\phlnOk[j_Z@Pq XimOfgAWYoyr}GRFT|EzCDzn{fHyBzS0{~y ~x_|xtQv}w|{z}~$~| y{}]uVVxjihaJbAt, |̱mѯur`atvuIIlpWX̲n ѰvQ~}YMKԹ[Z WjnoN\̷̴̳̺̼̻̾̿Z̸̶̽ F̵̹]u^vA@ѱCB4L ѲDvOѾѴ^f_ѷѺ}ѽVvѿѸѵѶѼѻ ѳU^gYyrզ]wա{jUգiբ shxեqtդRoxnl~w|pmzvTSwWpkdzjJgw}kn|\ml~Uyli _phqfec]ѹVݷW{yXox`[a^_]S<t p|ݱݶݪlݻiz{bkݤnoݥݲݸjdݣ}ݺݨݩ~ݴݫݵݭehfݹݰݬݡSݯmݧݦtgc~xݳݮEݢsuR QLKObRTNPUd JZMhvMH ]YX^\]ZD0k [BEFDGlCWNdMLKce`u[rF GէvuxswtqݼVHB yݽuRz{rWSH|s_I  ը}~ݾYXJIO^JwL @PMSKNQLORTF bYլիխժծթKc٧٢٥٨٦٣١٤}yݿvwu{z xtz\Zl nKmQRfPXTT\٩| BAկdz^ag{|0YxYC GBE@AA@FDW\ySrWCrMNFXHSIVQO  JPDRUELTGKzfX[\iEVLbJ[EeRADQa`FX _`cZKSfYamVXCjc]lgImPHd\T^bGZYO_UWh]NMBg^WZU\MQH wEj Q|qմյչվսհձ ղXճպռշջնտh{o" xlٽ٫ٳ٭ٻٶٰٵٯٱٺٷٴdkj٬ټپ٪ٲٹٸ IOAyk|}ٮio lո~ٿmbnnz@E JH^FX}_B]gGUd][@ZoQamI^KYgDkaMCqWh`eSfEPLN*r`_nO bTcljAVibR}Au~tlBT CD@EFvGt HIJwKLMxN{~EtOAH PIQDJ@RGxCFSBchiTvbUfeV2\ gdWQNWVTOrXYPqSpXRMoLVUUhYZTXSZWtP vVyYd pceqdzl[KjYwBZ[nk\y\Neof pfghLlZO_qg_:uij`CH ehsi]jBAC@b@AAB@{k|M [A]a~nIJ^^tklZDB_crɡ@ɤdɣDɢ @`Ee[YLQSLMUaROQVZXbZKnM\TWcEG^UNJYVHICOP[]PN S\WR]FTKXDku~_jzqdKbfeBmovhfguBtGpnsJ uyecI}MO@lk}rux|Af~i_d`N^{taTLwgl|hϤwijϧϪϬtv{Iϥϭ{s d~Ϣxz}}pϨϫzkmxϩo^H|wvnϣyrhhϦy~\ tlLCmU[WJMFGJV_E@NBOYnDhHZHEfZgaS`boecITAG`QCpiPKK\X] qqeRPrG[UGDgP dXcNOIE@QYBD^F\SHFJhb_]faR`AEWVgTLKCsJL tuMd]vwAZIMDhxJCUVHH DB~ySKQzWAGEBCOLT@FGFEiPNRoD jk@jxa`F_IJh^{CRHKcjbWiULYe|T}MlPZd(GQ[NESgVlXfOD]P~\imAn {}nwmqsuRS}ou~| o|vtzwxzjppyx{tsr{y  P|vDNMYKOFRT^W[`UILqH_aV\ kJ EAZB@XrQP]GI@ACOBDFEDJsGFEB@ ANC}QSYWZRVU[TlXtPuqoZ|dPH(ظ̹xlp\@(xdT(llTHld`XHD@< . pmnsrx_ey\vsgwt^abcfn]udh`@]j`kh_\^bedg[icfia vxVyWelWA^__b_`aMXZURT VSPWQYEvϯϳ϶ϲϱϴϵϮvϰwzwxyP Lnv{QlrkuWqMOzjmst|pNmNIPL@XJWiH[RlKS V ZOLTjkYMI[xQUDKHIeOMYbXL`^_JcNOP\ZK]aQRMdSTvbUpwyޡfk ROzޢV}_m~lzxޣq|ovrnuWN{Ss{XYt|Z[h \]^_gdpjlfn`amkqhobcebrcidJQeUSKI\LMHUGVQOLPN RRMfNOPKTSWXTg\b`^ha]_pwtuv(Hil mzkjji{klljkmnoZyqdRenbj,Ϸ} ϸϹfPޤns|gtBedc`f[ϺϽϻϼaҢҡ~S{]^o\_ Rpg QkjhilަޥީhިާustYZiqr}qpnoljɥɦkCD]lfbmaegcfgd _Ͼ]dneab\^co`ϿbGҨҥҧXWUҤҩTVҦg0ңҪv bfenyhwcmtUsadurq`ipwpTvsVuRqoqtrUxSrsޭެުrޮxޫ ްޯvu~}{zwxy|_\]W[a`^decyyx~ámnmzYvjɧz E{ljkhhi|}m~kgjfilhHcүt uҴҫҶҮҹҺҬҸҵҳҷ_]ұҭҰһҲ^Z\vxmklstp{u8roynwzqy[xwv| ~ڡ`ڧکڢZڦڥ[abڨX}{ڣz_|ڤڪY^\]Wz޷޻ޱ޼޲޳ ޽޺޸޹޵޴޾޶usw@bA }ifegfZcXt\[dhxYmzjhknlgBEu@oFâD{ACGv tãsnnҼҽ}޿]ä{o`Ҿҿ~ګ@|y i^_ropqVH|wz{cdFjiڬYzklnm|rpTq }~U`dcbaV{zfeڮڭBDj sæå|sQopxtQhi\nlkjemf g֢֡|~֤֣}ڶkjڰhڳlڴmڱgiڵڲگXH W@ECHIFGDTlksmro`qabpnX twuvoM¡N}O~LPJ~çxèoKpvU~}noGqm ֦o֥ڸqڷpJxQqpupwrKtRr qrsi֧IڹsLducySsnxwvyP vְwtֱֲ֪֭֮֩֫֬֨֯M ڼھںڻڿڽtCFDEAB@\ NQOMPBk}~vzywfgex{|h@|{A|z~}ZU¤¥¢£8  T{éyztwuvfoxuGB|x͡z|~}{AX$ x AC|ֹzy}~{@BB_  ֳֵֶַֻKYvLwxThNQ  MMHOPJKDINTXV  SOURYPWQjTlikUFVWEXCV`  GZW¦[]\XYê~}z}yq{|~rtswYZ[rͣ͢ \^sּֽ־ֿ_pR`SlTawPbcA CdB@efgmHI_^§ëšVr&Xqp ͤhijhL} |z{yAZX@W\[YGIHkDGF^l_[]Z mpErqnoSJ`ª¨©gníìHsͥͦB@ X~D]^CBHCJKLa`sDoK.p«¬ uqAgrDsmEMvͧtpBCI@B DGEAuFCHA@vwdz xyz[JaPSGLFcJHb{ONKMIR_QEp ]XzNPUTWRQSY[VOi\ZYqVbc|e6L`h dfgvj@txQyw{zFpONx$ LPMuwcag°ed²j±khib¯­flòðñî óx wyţŢXYm~ZͨEFD^]GHICIO MKLNJ{CcAVdTeUfa^`_>C kTa~|}WSXTVRU³\z{A@tͩLJKZSYRXVUTQPW  l`[Fh]_ae[Yj `d\XWhbZ^kifgcrdjxtxeubwfVvpjcqsFthgd limynok\pyurvltswqnzr{o~h M~_Yia]dg\e`ZhX c^b[fOZ nt¹w´µovqº·m¶su¸rpP÷øôõúö~} L!ġ B@BAl_vqpNtuDrsLAENL"qronmpShkljDCJHIKGEBiJK IIEC{zB@EI|y<#DI@AKJB yHFGGCDRNQJP]KLHOQHDFME|o@$Jj t»ĢCIuuMF`[_]^\M@ijnohkg@pz|}d<% VùDONbaLBAUsmlnrq~yxûýüPV8&edc Dop~CAB{|}kz{¼½l,'`T@$tL<|T0      dPD|hDl`P D!D"4#8$4%0&$'(.(ģQ ARS@BTfA@q^sͪCUUh\g() CBDFGETtuEDkzSpomnqw|¿¾ťŤ* LwvFɩͫvwwtvyu{zxxͭOͰ{|ͯM@ͮM^*N[GH]WWZca IgLd\YIbDeV_FK`wXJ^NEfKjlNkinH+om HYV}NEGHPLJMQFOKIBXQO, JߡNKPMGLwu{sߢxr{}v~|~yxy}|tzTeL$-H MJKIADC@Bntxzwfp.vusry }~bþĤEŦCDRN{SPBTUVOhX/p WwP|RQECߣRͱiQrSqLVWTVSU[XYZ@0ߦ ߧߥߨߤSJFIKHGĥF}\}[X[EAJKMN,81L ˢˣ{ˡ|zy}~~jͶ͵ͷYͼͲO͹Ϳʹͺ;͸ͽͻn$2ͳ@ AyQKx_b\daqt]BkV`ceТwUСYWRo~svХf}^xФuy|PУ{]l3p_ZSXTgӥ[ zAvFӨCvDӣ}ӲӪ~Eөx|ӭӤӳtӬsӫr\Ӧz4{ӡuӯFӮӶӴӰӧӢwӱ yTuG_WHs{JQIMJ^`ey]hou45 biH@wrnj\aYwfcsdzlKkLZ_pvA[gmxqtPP}M`Nlv5`}۪ۧhۣiwst] ۤRۡu۬pۯzrۭkdocaۥjۨ۩~vfO^ۢ۫e۰q6 m|xyg{bۦۮc_[MXPUߵ߿ߪ7߲ Q߶߱߫߹߸CR߼߾S߰ߴ߻ߺ߬߭߷<8 T߳Ue߯߮`X[YfZ]aU~9^ WVTc\b_eV^lWstgfbvuߩ_c]pawZXdni:O m߽[RU{\SQNe`hx|WkoTyLrVjP^Yl}zqL`]XFNMMI;@CEAGhL FUOFYJTQDHBVSPWMKQNS@ERDAD<MOQIPBRJGU vHZTKLVCN~[~=\ ÿħĩĦ>j ĪĬĭīkĨ]^JKIGHL ? EFG@rӸӷ@B|{R~XZYWx}ЩЧЦikjШSL|@LZ ӿAFӼӽCWӻHRӾӹGDӺEBCLץKר׫HF~שקפ׬׭ׯװ}\AEעס׮GףIDצMJתLۿ ۴۽۱۶ۺ۸۲۵۳۾ۼ۷۹ۻraNHBB `Tjeghmilfd4C aTkaEd`buTD akgle`ocG\hi_^lb]cn[mjfdFY]Zag\pj_kfm^`nXlEIdch[ebie fLo|MFrghN ĮįOBEACDQOiN@PFMPZnFЪQu GlЫױN[DЬЮЭm|IJNM\GKL PײUT׸R׳S׿׻׽׷׾O׺V׹׵׼״׶QjlmHEc Sb\ntBAv@nporqsIo ucpqp|wyqux{stzrvrSqwst"J uxXYvFİIKHJŨRŧrHIKJPHKn mnWVo`CFEDy{zmıqTSdtL[Ns ~}STd~\^cOЯoCA@BUsIGH}|}IJLUũLDM qrабpTRQXPYVSWUO_Y^`Z[X]\DFtEI0N CsB@GAHPMEJQrGPN OKNLFlLx{NM}OKy|zwJu*O Qv~PK t~lQAu Ow@BCwķĵĸĴĶijx@NMPQAV[RŪvXcWZY CB@A@MNgmyz{PXVhb~bj|SVW^TY Z\][eUXWORIPJKLNPSOZTSQRMcGHFQQONXRTVUWSM[\ge]^2dTfa`_WYdX VcmdiaehiknYfl`_edkjffgm@ByAxXZzRPthU DDZaSvbHVUWQRFEˤ\[{lVI YZX|Gst]^hfcgedy}JLQSRUOKMT@WPN [`bTSU@zA{:4X BHIaJW|ĺĹRC~BS\ūŬvEBDP|}nPlqhp_akc`fjidebUWX|$YYZ[V\GZ[jmip rhoCqnoZY\ji\]вvu\]_E$ZX} WVr_b`aeTfcdV~FLNKMTow[lk[Gg` ^Yl]\_Z^honpmrikgjqssF][aYB[bHX]c`_^W\ ZIAC@EBFDWm\ JtDEA@CBKDROSLQPTM~]Nļľ ĽĻCEVUaŭ`Ů^]bcF_\QPOpn`IOPQ^ URyxcabmn}SCAEFLHJTBIUKDGb@acuJ_wv{ xtyz|gfdeMNIJKLH@GpV`WFGHXIXYWVZXYWFdůeHG QaHyknlm_`_^`a VU]_^uxwt|{vzspqrvstId@AYG|GdAZ[[NDwc˦b ~ey˥\]bxnadvжд|г~{r}еzjgnEilR|c **+,-h.P/800123 4456789:;<=>?t@TA@B,CDEEFGHIJKlLRcuf^_ indgkreosjcmlqphbfNOa` a]b^c`_ba|{dx|J}\~}NMPhpqr kmlughRiQgqstrgfj^ePQSt^fG QQS|ReHcgkhsi`alF4jtm klzdHurqLJKI\nofmvwd}und4 xRpe~qr]gyso^|{zM(}tfN~uhij bTSgjih  s jklkseitvȡȣN`fLg,hi jkklmnopqrsttudvdwXxTy8z${||}~|`D<(Ĉ`8|X,l,, P.@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abc  GHIKOPQTY`ab@ hqtuwy{ @EVĠF JPp  @DK\dHi x^t FG NUXYeiklprs  Sb $( fH e P"  =Ȣ EFܢGH  , nT   Z 4ԣ v _`abcjmnopxy$| d < ST~ CG4 }L  p d8Px@l  @ԢḶ\,Dh|D z|ȤȥȦȧȨȩȪȫȬȭȮȯȰ0 | Jwxyz{|}~  ICH]^ADGFHI@P ABaUbȹȺȻȼȽȾȿL X \ FGD PtHXPT  ^____$`Ph```$Xhainv )xep,(@T H@@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_________________________________`_____________________________  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[  !"#$%&'(                !"#$%&       !"#$%&  !"      !   !"#$%&'()   !"#$%  !"#$%&'()*+,-./012345      !" #$% &   !"#$%&'()*    !"#$%&'()*+,-  !"#$%&'()*+,-./    !"#$%&'()*   !"#$%&'()*+,-.  !"#$%&'()*+,-./0   !"#$%&'()           !"#$%   !"#$%&'()  !   !"#$%&  !"#$%    !"#$%&      !"  !"#$%&'()*+,-./0     !"#$%&'(   !"#$%&'()*+,-       ! "#$% &   !"#$%&'(   !"#$%  !"#$%&'()*+,-  !"#$%&'()*+,-./0  !"#$%&'()*      !"#$%&'()*        !"#$% &'(   !"#   !"#$%  !"#$       !"#$%&'()  !"#$%&'()*+,-./0   !"#$%&'(   !"#$%&'()*   !"#$%&'      !"#$%&'()*   !"#$%&'()*+  !"#$%&'()*+,-./0123    !   !"#$%&'()*+,-   !"#$%&'()*+,  !"#$%&'()*+,-./0    !"#$%&'()*    !"#$%&'()*    !"#$%&'  !"#$%&'()*+,-  !"#$%  !"#$%&'()*+  !"#$%&'(   !"#$%    !"#$%&'()*+,-    !"#$    !"#$%&'()*+     !"#$%&   !"#$   !"#$%&'()*+,-./0    !"#$%&'()*   !"#$%&'()*+,-./0    !"#$%    !"#$%&'(   !"#$%&'()*+,-   !"#$%&'()  !"#$%&'()*+,-./0123456789:;<=>?@  !"#$%&'()*+,     !"#$%&' ( )   !"#$%&'()*+,  !"#$%&'()*+,-./   !"#$%&'()  !"#$%&'()*+,-./01   !"#$%&'()*+,  !"#$%&'()*+    !"#$%&'()*+   !"#$%&'()*+,-./0    !"#$%&'()*  !"#$%&'()*+,-.  !"#$%  !"#$%&'()*+,-   !"#$%&'()*+,-./  !"#$%&'()*+,-./012   !"#$%&'()*+,-./   !"#$%&'()*+,    !"#$%&'()*+   !"#$%&'()*+,-.  !"#$%&'()*+,-./    !"#$%&'()*   !"#$%&'()*+,  !"#$%&'()*  !"#$%&'()*+,-     !"#$%&'()   !"#$%&'()*     !"#$%&'()    !"#$%&'()*+,-.  !"#$%&'()*+,   !"#$%&  !"#$%&'()*+,-./0123456   !   !"#$   !"#$%&'()*+,   !"#$%&'()*+,-./0123  !"   !"#$%&'()*+,-./012  !"#$%&'()*+,-.  !"#$%&'    !"#$%&'()*+   !"#$%&'   !"#$%&'()*+,-    !"#$%&   !"#$%&'()*  !"#$%&'()*   !"#$%&'()*+,-  !"#$%&'()*+,-   !"#$%&'()*+,-./  !"#$%&'()*+,-  !"#$%&'()*+,-./    ! "#$ %&'()*+,- . /   !"#$%&'()*+,-./0123456  !"#$%  !"#$%&'(  !"#$%&'()*+,-./0123456789:   !"#$%&'   !"#$%&'()*+,-.   !"#$%&'()*+,  !"#$%&'()*+,   !"#$%&'()*+,-./01234   !"#$%&'()*+,-   !"#$%&'()*+,-./01  !"#$%&'()*+,-./0  !"#$%&'()*+,-./01234    !"#$%&'()*  !"#   !"#$%&    !"   !"#$%&'()*    !"#$%&'()*+       !" #$% &'( ) *+ ,-./0    !"#$%&    !"#$%&'()*+,-   !"#$%&'()*+   !"#$%&'()*+,-    !"#$%&'(   !"#$%&'()*+,-./0        ! "#$%&'() *+ ,-   !"#$%&'()*+  !"#$%&'()*  !"#$%&'()*    !"#$%&'()*+,-   !"#$%&'(   !"#$%&'()*+,-./      !"#$%  !"#$%&'()*+,-./0123   !"#$%&'()*+,-.    !"#$%&'    !"#$%&    !"#$%&'()*+,-   !"#$%&'()*+    !"#$%&'()   !"#$%&'()*+,-./01   !"#$%&'()*+  !"#$%&'(     !     !"#$%&'()*+,  !"#$%&'()*+,-  !"#$%&'(  !"#$%&'()*+,-./0   !"#$%&'()*+,-.    !"#   !"#$%&'(    !"#$%&'(   !"#$%&'()*+,      !"#$%&'()*  !"#$%&'  !"#$    !"#$%&'()*+,-  !"#$%&'()*+,-    !"#$%&'    !"#$%&   !"#$%  !"#$$$$$%&$'($)*+,-.$/0$12345678       ! "#$%&'( )*+,- .   !"#$%&'()*+,-./   !"#$%&'()*+  !"#$%&'()*+,-./01234     !" # $% &'()*+,-./012        !"#$%&'()*+,-.   !"#$%&'()*+,-./01  !"#$%&'()*+,-./01234  !"#$%&'()*+         !"#$%&   !"#$%&'()*+,-./      !"#$%&'()*   !"#$%&'()*+,-./    !"#$%&'()*+,-./01  !"#$%&'()*+,-  !"#$%&'()*+,-  !"#$%&'()*+,-./012    !"#$%&'(        !"#$%&'()*+, -  !"  !"#$%&'()*  !"#$%&'()*+,-./0123456789  !"#$%&'   !"#$%&'()*+,-./01   !"#$%&'()  !"#$%&'()*+,-  !"#$%&'()*+,-./   !"#$%&'()*+,-./01  !"#$%&'()*+,-./0123456    !"#$%&'()*+,-./0123    !"#$%&'()*+,-.    !"#$%&'()*+    !"#$%&'()*+,-./      !"#$% &'()*+, -   !"#$%&'()*+,-./01234  !"#$%&'()*+,-./0123    !"#$%&'()*+,-./01   !"#$%&'()*+,-./01  !"#$%&'()*+,-./012345   !"#$%&'()*   !"#$%&'()   !"#$%&'()*+,-.    !"#$%&'()*+,-./01  !"#$%&'()*+,-./    !"#$%   !"#$%&   !"#$%&'(  !"#$%&'()*+,-./    !"#$%&'()*     !"#$%&'()*+,-./01234    !"#$%&'()*+,-./0123456   !"#$%&'()*+,-./0     !"#$%&'()*+,-./0    !"#$%&'()*+,-./012345      !"#$%&'()*+,-./0       !"#$%&'()*+,-  !"#$%&'()*+,-./01    !"#$%&'()*+,-./0123  !"#$%&'()*+,-./0  !"#$%&'()   !"#$%&'()*+   !"#$%&'()*+,-./012    !"    !"#$%&'(   !"#$%&'()*+  !"#$%&'()*+,-./0       !"#$%&'( ) *+,   !"#$%&'()*+,-.    !" #$%&'()*+,-./0123 4567 89  !"#$%&'()*+,-     !"#$%&'()*+, - ./ 012    !"#$%&'()*+,-.        !"#$% &'()* +,-  !"#$%&'()*+  !"#$%&'()*+,-./  !"#$%&'()*+,-./0  !"#$%&'()*+,-./0  !"#$%&'()*   !"#$%&'()*+,  !"#$%&'()*+,-.  !"#$%&'()*   !"#$%&'()*+  !"#$%&'()*+,       !"#$%&'()*   !"#$%&'()*  !"#$%&'()*+,-./012    !"#$%&'()*+,-./      !"#$%&   !"#$%&'(  !"#$%&'(       ! " # $% & ' ()* +    !"#$%&'(            !"#$%&'()*+,-        !"#$%&'()*+,-./0   !"#$%&'()*+,-./01   !"#$%     !"#$%&'   !"#$%&'()*+,  !"#$%&'()*+    !   !"#    !"#$   !"#$%&      !"#$%&'(    !"#$%&'()*+,  !"#$%&'()*+,-./012345  !"#$%&'()*+,-./01234567       !"#$%&'(   !"#$%&'()*+,-    !"#$%&'()*+,-  !"#$%&'()*+,-./0123      !"#$%&'()*+,-./0123456789:;<=     !"#$%&  !"#$%&'()*+,-./0123456789:;          !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~                !  !"#$%&'()*+,-./01222222222222222   !"#$%&'()*+,-./0123456789:;<=>?  !"#$%&'()*+,-./01(23456789:;<=>?  !  !   !"##$%&'(###############)*##+,#-  @  !"#$%&'()*+,-./0123456789:'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''𧉧𧲱𧳅𤊿𣘗𧍒𦺋𧃒𪍑𧱬𦬣𥩔𡩣𣸆𣽡𨮹𧯯𡵞𩺰𩥅@  !"#$#%&'()*+,-./0123456789:;<=>?@#A#BCDEF####################################################################################𠄌𠃑𠃍𠃋𡿨𠃊𠄎@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~𪎩𡅅𧜵𠧧𩷶𧀎𪄳𨑬𡷊𠗐𢫦@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~𧶄𠱂𠴕𥄫𢳆𠍁𤶸𩓥𨂾𢰸𨅝𦧲𤷪𠵼𠾴𠳕𡃴𠺖𠰋𠽤𢲩𨉖𤓓𠵆𩩍𨃩𤺧𢳂𩗴𥋇𩟔𧣈𢵄𦂥𢵌𢯊𡁷𡁯𦛚𦜖𧦠𥁒𠱃𢆡𨭌𠜱𠆩𢶍𤗈𠓼𦂗𠽌𠶖𢩦𡂝𠶜𢝵𪘁𠸉𢫏𢳉𡃈𣧂𨊛𥹉𢃇𠼱𢲲𩜠𤸻𧕴𢺋𢈈𪙛𨳍𠹺𠰴𦠜𡃏𢠃𢤹𥇣𠺌𠾍𠺪𠼰𠵇𡅏𠹌𠺫𠮩𠵈𡃀𡄽𢚖𠾭@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~𣏴𧘹𢯎𠵾𠵿𢱑𢱕𠺘𡃇𠼮𪘲𦭐𨳒𨶙𨳊𩻃𧝞𢷮𦕲𨂽𠻺𠸏𠹷𠻻𤷫𠳖𢞵𡃉𠸐𠹸𡁸𡅈𨈇𡑕𠹹𤹐𢶤𡀝𡀞𡃵𡃶𠸑𧚔𨋍𠾵𠹻𥅾𠾶𡆀𥋘𪊽𤧚𡠺𤅷𨉼𥜽𥭴𣄽𡯁屮𠂆𤣩𦉪𦍋𦘒𦥑𧢲𨸏𩠐𠂇@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdEEEefghEijklmnopqrstuvwxyz{|}~E𩱳𤅎𥇍𥴰𨨲𣊁𪄇𡦀𨜏𪊺𠩯𩥇𨫪𢁾𨧣𡶶𢜒𣏹𣱣𤔅𤨓𥲤𥚕𨶹𡐿𤥻𧄍𦵴𦬕𦾾𣉖𢞖𣬚𣕑𤃬𡸣𠆤𦱁𠈹𩣺𠮟𢇁𨥭𩁹𪆵𦱆𨚲𧏿𥒚𤬏𨧀𣽁𠌥𠻘@  !"#$%&'()*+,-./*0123456789:;<=*>?@ABCDEFG*HIJKLMNO*PQRSTUVWXYZ[\]^_`abcdefg*hi*jklmnopqrstuvwxyz{|}~𣻗𦻓𥟠𨯩𥣡𩓙𥦬𦒍𥰁𥌎𥳾𥮴𦱿𥴠𥱥𥳁𤢂𤕸𦹄𦻖𤁗𦀩𡟹𨍭𦄡𦅚𦋐𦍑𡙡𠁨𣝦𨌺𦒉𪂇𦳃𢜔𦘦𣷣𦛨𨩈𢛶𦒘𤾸𡒊𡡞𤩥𤪕𠬍𦩒𣵾𡓽𦬊𤦧𣔰𡝳𣷸芳@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~𠸖𡞴𣅽𣕚𣺋𦶣𦬅𦮗𣗎𦶥𦻔𦹂𢻯𥯤𣲵𦮖𦹷𦹃𥲑𥳀𦺙𨘥𨘻𧂈𡖂𧃍䕫𡢢𧎚𪃸𢰧𧗠𣶹𧗤𧜏𨨥𧤤𧪽𧩙𧬺𣾏𧬸𥐰𥕥𤩺𡛟𧵔𧶏貫𧵓𧶘𧶽𡤐𤳉@  !"#$%&'()*+,-./0123456789:.;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxy.z{|}~.𨀂𡀔𤦊𨆼𧄌𨍥𨐒𪊟𠩐𨧞𨔽𣶻𣉢𪀔𨚼𨔁𢌥𦻗𨔼𧪾𨕬𨘋𨜓𨛦𨤳𡺉𥖹𨫆𣲛𨬌𥗛𠴱𨫡𨯫𨫢𨫥𨯬𨰹𨯿𢙺𨛘𡉼𣸮𦻕𨫠𦲸𠉴𦐐𩂯𩃥𤫑𡤕𣌊𤫩𩇕𩇫𣂷𣂼𥑬𩐳𩐝𧥺𧅵𠘰𤅜𥜆𦴧𡛓𤨩𩡗𩤅𥜥𩂱𩯕𩬅𨘀𦦨𣁽𩴾𡡣𤉋𩹨𩾷𪆒𪆫𪃡𪄣𪇟𪄴𢅛𪆓𪈠𡤻𪈳𪂹𪊴𤍤𨰫𦶢𩂋𤥵𤦻𤧸𤍈𤩑𨯚𡣺𨥾𨸶𨩄𨥬𤒹𤑳𤏸𡟯𡢾𣖙𡢅𥐯𡟸𡛻𡠹𡝴𡣑𥽋𡛀𤨥𡏾𡊨@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~𡏆𡒶𣚦𤦔𧅥𣸱𥕜𣻻𧁒𣛮𩦝𦼦𡤢𣜿𤃡𤂋𤄏𦰡𦚱𠿟𠮨𠸍𨬓𤐶𠑥𠍿𥙑𠆫𠏋𠌊𠐔𠋀𨺳𠉵𠈌𤨎𣺊𣖕𣸹𣺿𡢄𣺉𠗠𠒣𠒒𠒑𨪜𠜎𠡳𤎌𠰠𤦬𡃤𠸝𤪼𤂍𤃉𠍅𠯆𨩆𡛺𡝯𡜐𥥆𡧳𡡡𤊕𥺃𨯗𠐓𡌃𨧻𡦖𡥼𣫮𡤃𡤄𡢠𡛾𨩇𡶺𣑲𨦨𡤧𡞫𡜻𧗽𢡠𢘫𢖯𢖾𩂈𦽳𠀾𠁆𢘛𢲛𢴇𤛔𩅍𤙥𢭪𢬢𣑐𩣪𢹸𪑛𤧣𢵧𢲡𣂎𣊭𤦉𣊫𣋠𡣙𩐿𣊉𣆳𥖄𨬢𥖏𡛼𥕛𥐥𣄃𡠪𣈴𣈏𣆂𤋉𦴤𧡰𡷫𣋒𣋡𥡲𣠺𣞼𣞢𣏾𤘪𣟕𤒇𡤒𣿀𣲚𨯪𨫋@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~𨀞𨧜𤧬𣽿𤀼𤌚𤉶𤞏𤜥𤪤𠗫𣻸𣙟𤩊𤤗𥿡𤫟𨰣𣼵𦷪𤳙𤴆𪗆𨫌𤦫𤦎𤩎𤧅𤣳𨫣𡡤𥈡𥇧𣈲𤚗𣞁𤣰𤪺𤫇𤪖𦆮𥖁𧝁𥛣𣻺𡛦𠵌𤦌𠊙𣶺𡝮𠇔𠰍𢛵𥪯𥪜𠉛𥯆𥮳𥺼𥺦𤧹𡞰𦉡𦅜𧭈𥺂𦭵𠤖𠁎𣗏𦐒𦏸𤥢𠠬𥫩𥵃𥸎𣐿𤧷𦖭𦖠𧄧𦳑𦞴𦩂𦩑𦶧𧈛𡡀𡢡𡣘蜨𣶏𧐢𥚃𧞅𧞄𨯵𨯙𨮜𨧹𩑈𤊄𡡅𧷜𤰉𢌡𡟚𤤯𨩋𨫼𨰝𨰻𨴴𤣿𤩂𤏪𣈥𨻧𨹦𨹥𤧭𤩸𣿮𩂰@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~𩂓𥟟𨦉𨰦𨬯𦎾𤈛𠼦𨯅𤪲𩓚𩗗𨭐𤩧𨭤𨩅𧬆𨭥𥣈𩣱𩥈𡌂𤦸𡓨𢜟𣶸𢞁𢥫𩸭𪇵𪃾𤄄𪆴𪃭𪃳𩤯𦸒𦿟𦮂𦶤𦺄𦷰𦸀𣟗𦁤𣖜𣙀𤧞𠊿𥕝𡝗𣇉𤥁𤆵𤆬𦱀𤾗𡞵𨩉𤒈𨧼𡣖𠼝𦳀𡐓𤋺𢰦𤏁𣶷𦝁𦅛𦂤𤦹𤦋𨧺𨭣𡢟𤪳𤨾𤪔𡟙𤩦𠎧𡐤𤧥𤤖𤥶𠓾𨫎𨨖𨯧𥗕𨪂𤥃𠳿𠘚𠯫𠲸𡟺𡛂𤩐𡡒𨫀𤦭𡢿𡢃𧒄𣵛𨪁𡡢𠪴𡎜𨈘𩃤𧹏𣿭𣸭𠏵𨰜𦯀𡑒𤍢𤩱𢿣𡊰𢎽𡎘𣓥𧯴𣛟𨪃𣟖𣏺𤲟𣚭𦲷𦴦𦵑𦲂𦿞𧄉𡜺𦲀𧁓𡟛𡞳𡤅𤇼𡜼𤊥𤊓𣻹𧜶𤑛𤋊𤉙𨧡𦴨𤓎𧹍𤎽𤉖𡌄𤏩勇𤩏𤩝𡟟𣫺𣌀𠈔𠣕𠘙𡾞𪊶𩅛𨩙𩐠𧫴𥛶𧬘𤣲𤽜𥔵𠳏𧥧𡯂𠂔𠊷𠎠𠓗𠗕𠘕𠙶𡚺𠫂𠫍𠮿吆𠯋𠯻𠰻𠱓𠱥𠱼𠲍𠲵𠳝𠳭𠵯𠶲𠷈𠸄𠸎𠻗𠾐𠼭𠹳𠾼𡁜𡁏𡁶𡁻𡂈𡂖𡂿𡃓𡄯𡄻𡋣𡍵𡌶𡕷𡘙𡟃𡟇𡠭𡥪@  !"#$%&'()*+,-./0123456"7"89":;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`a"bcdefghijklmnopqrstuvwx"yz{|}~""𡨭𡩅𡰪𡱰𡲬𡻈𡻕𡼕𢁅𢉼𢏗𢏺𢜪𢡱𢥏𢥧𢦓𢫕𢫨𢬎𢬿𢱌𢲈𢲷𥯨𢴈𢴒𢶷𢶕𢹂𢽴𢿌𣀳𣁦𣌟𣏞𧩹𣕧𣗳𤦺𣘚𣜖𠍆𣪧𧙗𥿢𣸑𣺹𧗾𢂚𤄙𨪚𤋮𤌍𤀻𤌴𤎖𤩅𠗊𠘑𡺨𣳿𤐄𤓖𤙴𤜯𨗨𩧉𢇃𨭎𤠒𤣻𤨕𤫀𠱸𤺥𤾆𠝹𥀬𥊙𥐙𣽊𤪧𥑆𥑮𦭒𥔿𧘲𥕞𥕢𥕦𥟇𤤿𥡝𣏌𥤃𨥈𥪮𥮉𥰆𡶐𦄂𧰒𦆲𤾚𦐂𦑊@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~𦯷𦒄𡤜𤧶𦒈𣿯𦔒𦖿𦚵𢜛𥟡晉𤔡𦛼𤤴𦲽𦞙𦡮𦐑𦡞𦣇𩃀𠨑𦤦𦤹𦧺𦨭𦑩𠀡𦨴𦭛𣔙𦮝𦲤𦶮𢖍𧁋𧇍𧊀𧊅𢅺𧊋𧋦𤧐𧑐𠻸𢤦𨑳𡞱𤨪𡠠𩲭𩢤𧟌𧡘𡘊𣜯𨃨𡏅𧧝𩆨𧂯𨦫𧧽𧨊𧬋𧵦𤅺𨀉𪋟𨌘𦸇𨅯𨀣𦦵𡏭𣈯𨁈𨰰𨂃𨥉𤦈𤪥𣾁𨂐𨃴𨄮𡾡𨅏@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~𨆉𨆯𨈚𨌆𨌯𨎊𨑨𨚪𨥖𨦸𨧧𨧨𨭆𨯔𨰉𨿅𩃬𩄐𩄼𩅞𤫊𩓧𩗩𩖰𩖸𩜲𩣑𩥉𩥪𩧃𩨨𩬎𩵚𩶛𩻸𩼣𪊓𪋿𪗋𠲜𢒰𤪓𨬬𧢝𡟵𨀤𨭬𨮙𧨾𦚯𧙕𣲷𥘵𥥖𥺁𦉘𠹭𣺈𤲞𡟶𡡻𥱊𥌑𩶘𥻘𣵀𠿪𠵉𣚺𠺝𨋢𠱁𠲖𥅈𠹶𢱢@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJHKLMNOPQRSTUVWXYZ[\]^_`aHbcdefghijklmnopqrstuvwxyz{|}~HHH𠺢𡁵𢭃𢺳𠶧𦢊𡃁𤜆𦢓𢛴𧴯𤆣𧵳𦻐𧊶𡇙𣳼𪚩𠺬𠻹𡲢𤿂𧿹𠿫𢶠𤟠𩵼𠿬𠸊𧖣𠿭𦁈𡆇𤘘𤭮𥪕𠥹𢑥𩺬𣳾𩼰𤾩𩖞𩿞𣶶𧊲𦞳𣜠𣻷𣸬𠒎𠺶𧼮𪐴𣃚𤏲𡊩𤥣𩸆𧂮@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~𡝬𩓐𦌵𧅤𠴨𦴢𤫢𠵱𡼏𡷑𤤾𡝭𨺗𦴣𠏼𥰡𣳽𤤙𠳔𠇲𪙊𨍽𤩷@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~𨩚𪊲咢𤪻𡠻𦸅𢔛𦅙𣏵𨯂𨸹𡵆𠼻𥼚𧒆𦟌𦻑𤀑𨬭𣳇𥻗𧙖𥔱𡥄𡋾𩤃𦷜𧂭𦆭𨨏𣙷𠃮𦡆𤼎𦍌𦉫@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_______________________________________________________________@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqnrnsntuvwxynnz{|}~@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghiDDDjklmnopqrs𠃌𠂊𧘇@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~@  !"#$%& '()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ [\]^_`a bcdefghijklmnop qrstuvwxyz{|}~𠕇𠗟𣿅𤥂𨧤𡧛𣳈𤤳𨦪𠊠𦮳𡌅𢓭𦴩𧪄𣘀𤪱𢔓𠍾𠎀𠍇𠐟𤦤𠒇𣎴𠯿𢃼𠋥𢔰𠖎𣈳𡦃𠖳𣲙𤪦𣜭𦬓𨫞𣾀𠥔𣿬𠯢𡜦𡛨𨚫𡖖𡘓𨪛𥝲𠮏𣿫𢶣𠱷𦭓𠵴𡜍𠻝𠵍@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUV WXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ 𨦼𢚘𡣗𤀺𤐵𡂴𣊊𨭦𡉏𤆥𦱾𡐖𡑔𤍣𤯵𡈼𪅐𤉸𡘾𡚒𠵎𦲁𦴪𡟜𡟻𡞲𦶦𡠨𡛕𦹅𤦩𦾡𢕔𡤑𡚸𧨎𠈄𡨴𥧌𠖥𡭄𡲥𦬨𡷹𡸷𡺤𤤁𢁉𢅳𤒼𠳓𡝱𨒂@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~𠇁弢𡌺𦢈𢏐𢑱𦹮𨨶𥉐𡽪𧃸𢙨𠊞𨨩𡡷𢞴𤦂𤦏𧩓慈𦻒𠙖𣾷𢡟𨮝𩥝𢦀𢣁𠄘𡝰𢸍𤧟𡎎𡟼𢸶𤂌𥜝𤨨𤨣𣁾𤥀𡠩𣐀𣇷𣇸𣆤𣆥𠹵𥇦𡸽𣈱𨗴𣇈𥌓𢣷𤎜𤨡𣟂𤇍𩃭𣏦𦶠@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVVWXVYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~V𣑯𨫟𣗍𣘼𨩊𠏉𣙙𢄪𣜃𩆜𠤣𢟍𣫛𠎵𡥘𣭚𣻼𢒋𤣱𦭑𣶼𣶽𤆤𤤌𤤀𣳉𠴲𣇹𢒑𦴥𦶡𦷫𤥿𤂅𦹲𦽴𨬡𣸯𣾂𣁋𣸰𡒗𤀽𩅰𤅄𤂑𤅕𤀹𣿰𣾴𤄿𤅖𤅗𤅀𦇝𤉷𤍥𤋁𤑚𤨧𤨢𨯨@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~𥘅𤥴𣁄𤠣𨠫𨠄𠰺𦨮𤇢𡛧𤨤𤦷𤦍𤧻𤨦𠗃𢢭𨺲𤪌𤅟𤩹𨮏𨰃𡢞𡦈𨻙𡩋𨺬𤾂𤴓𦏵𦤑𦤎𦾟𥂝𥅽𡸜𥈠𣊬𨥤𨥨𡛁𡍶𤨒𥗠𧘌𨬫𦂃𢘜𥡗𧬹𧄦𩄍  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz        !"#$%&'()*+,-./012                      !"#$%&'()*+,-./012345678  !"#$%&'()*+,-./01234567888889:;8                                        !"#$%&'()*+,-./0123456789:;                      !"#$%&'()*+,-./       ! " #$%& ' () *+,- .   !"#$%&'()*+,-.   !"#$%&'()*+,-   !"#$%&'()*+,-./0123456789        !" #$%&'( )*+ , -  !"#$%&'()*+,-./012  !"#$%&'()*+,-./01234567*89:;<=>?  !"#$%&'()*+,-./012  !"#$%&'()*+,-./0123   !"#$%&'()*+,-./   !"#$%&'()*+,-./012345  !"#$%&'()*+,-./01234   !"#$%&'()*+,-.    !"#$%&'()*+,  !"#$%&'()*+  !"#$%&'()*+,-.  !"#$%&'()*+,-./0  !"#$%&'()*   !"#$%&'()*+,-  !"#$%&'()*+,-   !"#$%&'()*+,-./01   !"#$%   !"#$%&'()*+,-./0  !"#$%&'()*+,-./0123456789   !"#$%&'()*+,-.   !"#$%&'()*+,-./0123456789      !"# $%& '( )*+, -  !"#$%&'()*+,-./012   !"#$%&'()*+,-./  !"#$%&'()*+,-./012345  !"#$%&'()*+!,!!-./0!!123!456789:   !"#$%&'()*+,-./01234   !"#$%&'()*+,-./012345        !" #$%&'( )*+,-./ 0 1234  !"#$%&'()*  !"#$%&'()*+  !"#$%&'()*+,-./    !"#$%&'()*+,   !"#$%&'()*+,-./01  !"#$%&'()*+,-./0123456   !"#$%&'()*+,-./01   !"#$%&'()*+,-./0123   !"#$%&'()*+,-./   !"#$%&'()*   !"#$%&'()*+,   !"#$%&'()*+,-./01234  !"#$%&'()*+,-./0123456789:;    !"#$%&'()*+,-   !"#$%&'()*+,- ./ 012345678   !"#$%&'()*+,-./01234567  !"#$%&'()*+,-./0123456789   !"#$%&'()*+,-./   !"#$%&'()*+,-./012345    !"#$%&'()*+,-./0     !"#$%&'( )*+,-. /0 1 2 3  !"#$%&'()*+,  !"#$%&'()*+,-./0   !"#$%&'()*+,-.   !"#$%&'()*+,-.  !"#$%&'()*+,-./0123  !"#$%&'()*+,-   !"#$%&'()*+,-./012     !"#$%&'()*     !"#$%&'(  !"#$%&'()*+,-./012345  !"#$%&'()*+,-./  !"#$%&'()*+,-./01234567  !"#$%&'()*+  !"#$%&'()*+,-./0  !"#$%&'()*+,-./012   !"#$%&'()*+,-  !"#$%&'()*+,-./      !"#$%&'( ) * + ,-   !"#$%&'()*+,-./0  !"#$%&'()*+,-./0123456  !"#$%&'()*+,-./  !"#$%&'()*+,-./0123456789   !"#$%&'()*+,-./01234  !"#$%&'()*+,-./01    !"#$%&'()*+,-.  !"#$%&'()*+,-./012      !"#$% &'() *+ ,-./0  !"#$%&'()*+,-./01234  !"#$%&'()*  !"#$%&'()*+,-./01  !"#$%&'()*+,-./01  !"#$%&'()*+,-./0123456789:;   !"#$%&'()*+,-./01234   !"#$%&'()*+,-./   !"#$%&'()*+,-./0   !"#$%&'()*+,-./012345   !"#$%&'()*+,-./0123456     !"#$%&'()*+,-.      ! "#$ %&' () *+,-. /0123  !"#$%&'()*+,-./  !"#$%&'()*+,-./01  !"#$%&'()*+,-./012345  !"#$%&'()*+,-./0123  !"#$%&'()*+,-  !"#$%&'()*+,-./0123456  !"#$%&'()*+,-./012   !"#$%&'()*+,-  !"#$%&'()*+,-./0123456789:   !"#$%&'()*+,-.  !"#$%&'()*  !"#$%&'()*+,-./0123  !"#$%&'()*+,-./0123456  !"#$%&'()*+,-.  !"#$%&'()*+,-./0123456789:    !"#$%&'()*+,-./012345  !"#$%&'()*+,-./  !"#$%&'()*+,-./012345   !"#$%&'()*+,-./012   !"#$%&'()*+,-./012345678   !"#$%&'()*+,   !"#$%&'()*+,-  !"#$%&'()*+,-./   !"#$%&'()*+,-.  !"#$%&'()*+,-./012   !"#$%&'()*+,-./0123456  !"#$%&'()*+,-./01234  !"#$%&'()*+,-./01234   !"# $ %&'()*+,-./01 2 3 4  !"#$%&'()*+,-./0123456789:;   !"#$%&'()*+  !"#$%&'()*+,-./  !"#$%&'()*+,-./0123456789:;   !"#$%&'()*+,-./   !"#$%&'()*+,-./01234    !"#$%&'()*+,-./012  !"#$%&'()*+,-./01234  !"#$%&'()*+,-./0123456789:;<  !"#$%&'()*+,-./012  !"#$%&'()*+,-./012345678  !"#$%&'()*+,-./012345  !"#$%&'()*+,-./01234567  !"#$%&'()*+,-./012345678    !"#$%&'()*+,-./0  !"#$%&'()*+,-./0   !"#$%&'()*+,    !"#$%&'()*+ , -./0 1234 56789     !"#$%&'()*+,-./01234567     !"#$ %&'( )*+ ,-. /0 12345   !"#$%&'()*+,-./01   !"#$%&'()*+,-./0123   !"#$%&'()*+,-./012  !"#$%&'()*+,-./   !"#$%&'()*+,-./012   !"#$%&'()*+,-./012345  !"#$%&'()*+,-./012345  !"#$%&'()*+,-./0123456789:  !"#$%&'()*+,-./012345678  !"#$%&'()*+,-./0123456789:;<  !"#$%&'()*+,-./0123456   !"#$%&'()*+,-./012  !"#$%&'()*+,-./0123456   !"#$%&'()*+,-  !"#$%&'()*+,   !"#$%&'()*+,-./0123456   !"#$%&'()*+,-./012  !"#$%&'()*+,-./01234   !"#$%&'()*    !"#$%&'()*+,-./0   !"#$%&'()*+,-./012  !"#$%&'()*+,-./01   !"#$%&'()*+,-./0123456  !"#$%&'()*+,-./012  !"#$%&'()*+,-./  !"#$%&'()*   !"#$%&'()*+,-./0123  !"#$%&'()*+,-./01234567   !"#$%&'()*+,-./0  !"#$%&'()*+,-./012345   !"#$%&'()*+,-./012345678  !"#$%&'()*+,   !"#$%&'()*+,-./  !"#$%&'()*+,-.  !"#$%&'()*+,-./012   !"#$%&'()*+,   !"#$%&'()*+,-./01  !"#$%&'()*+,-.  !"#$%&'()   !"#$%&'()*+,-./0123  !"#$%&'()*+,-./01    !"#$%&'()*+,-./012   !"#$%&'()*+,-.   !"#$%&'()*+,-./012  !"#$$%$$&'$()$*+,-./$01$23456789      !"#$ %&'()*+ ,-./0 1   !"#$%&'()*+,-./01234567  !"#$%&'()*+,-./0123456  !"#$%&'()*+,-./0123456   !"#$%&'()* +,-./012345678    !"#$%&'()*+,-./01234567  !"#$%&'()*+,-./01234567  !"#$%&'()*+,-./01234567    !" #$% & '()* +,-./ 0 12345     !"#$%&   !"#$%&'()*+,-   !"#$%&'()*+,-./0123    !"#$%&'()*+,-  !"#$%&'()*+,-./012  !"#$%&'()*+,-./01234      !"#$%& '()* +,- ./01234 56  !"#$%&'()*+,-./0123  !"#$%&'()*+,-./01234  !"#$%&'()*+,-./0123456  !"#$%&'()*+,-./01234      !"# $ %&'()*+,-./01 2  !"#$%&'  !"#$%&'()*+,-./0  !"#$%&'()*+,-./0123456789:;<  !"#$%&'()*+,-./012  !"#$%&'()*+,-./0123456789:;<  !"#$%&'()*+,-./0123  !"#$%&'()*+,-./01234  !"#$%&'()*+,-./0123456  !"#$%&'()*+,-./0123456789:  !"#$%&'()*+,-./012345678    !"# $%&'()*+,-. /012345678  !"#$%&'()*+,-./01234567   !"#$%&'()*+,-./0   !"#$%&'()*+,-./0123      !"#$% & '()*+,- .   !"#$%&'()*+,-./0123456   !"#$%&'()*+,-./01234567  !"#$%&'()*+,-./01234567  !"#$%&'()*+,-./0123456789:   !"#$%&'()*+,-./0123   !"#$%&'()*+,-./01234  !"#$%&'()*+,-./0123    !"#$%&'()*+,-./0123   !"#$%&'()*+,-./012345   !"#$%&'()*+,-./   !"#$%&'()   !"#$%&'()*+,-   !"#$%&'()*+,-./012   !"#$%&'()*+,-./0   !"#$%&'()*+,-./012345678   !"#$%&'()*+,-./0123456789:  !"#$%&'()*+,-./0123456     !"#$%&'()*+,-./01    !"#$%&'()*+,-./012345678     !"#$%&'()*+,-./012345678     !"#$%&'()*+,-./0   !"#$%&'()*+,-./01234  !"#$%&'()* +, -. /012 345 6789  !"#$%&'()*+,-./01234567  !"#$%&'()*+,-./0   !"#$%&'()*+,-./012   !"#$%&'()*+,-./012345  !"#$% &' (     !"#$%&'()*+,-./    !"#$%&'()*+,-./  !"#$%&'()*+,-./0123456       ! "#$%&'()* + , -./    !"#$%&'()*+,-./  !"#$%&'()*+,-./012345   !"#$%&'()*+,-./01 234567       !"#$%&'() * +,-./012 345      !"#$ %& '( )*+,-./0123 4567  !"#$%&'()*+,-./012345  !"#$%&'()*+,-./012345678  !"#$%&'()*+,-./0123456789:;   !"#$%&'()*+,-./012345  !"#$%&'()*+,-./0123456789:;<   !"#$%&'()* +,-./01234 56 7 8 9  !"#$%&'()*+,-./01234567  !"#$%&'()*+,-./01234567  !"#$%&'()*+,-./0123456   !"#$%&'()*+,-./012345         !"#$%&'()*+,-./   !"#$%&'()*+,-./01  !"#$%&'()*+,-./0123    !"#$%&'()*+,-./012345   !"#$%&'()*+,-./0   !"#$%&'()*+,-./0123    !" #$ %&'( )* +,-. /01   ! "#$% & '()* +,-. /01 2   !"#$%&'()*+,-./    !"#$%&'()     !"#$%&'()*+,-./01234      !"  !"#$%&'()*+,-./01234567  !"#$%&'()*+,-./0123456789   !"#$%&'()    !"#$%&'()*+,  !"#$%&'()*+,-./01234   !"#$%&'()*+,-./    !"#$%&'()*+    !"#$%&'()*   !"#$%&'()*+,-./0  !"#$%&'()*+,-     !"#$%&'()*+,-.   !"#$%&'()*+,-./012345  !"#$%&'()*+,-./0123456789:  !"#$%&'()*+,-./0123456789:;<     !"#$%&'()*+,-./0123456789:   !"#$%&'()*+,-./012345    !"#$%&'()*+,-./0123  !"#$%&'()*+,-./0123456789:;     !"#$%&'()*+,-./0123456789:;<=>?               !"#$%&'()*+,-./012345678                     !"#$%&'()*+,-./012345678    !"#$%&'()*+,-./012345       !"#$%&'()*+,-./012                       !"#$%&'()*+,-./0123456789:   !"#$%&'()*+,-./01234       !"#$%&'()*+,-./0123456789   !"#$%&'()*+,-./012345                !"#$%&'()*+,-./    !"#$%&'(         !"""#$%&'()*)      !"             !"#$%&'()*+,-./0123456789:;<                  !" #$ %&' ()* + ,  !"#$%&'()*+,-./012345*6*789:;<=>   !"#$%&'()*+,-./    !"#$%&'()*+,-  !"#$%&'()    !"#$%&'()*+  !"#$%&'()*+,-./012345   !"#$%&'()*+,-./012   !"#$%&'()   !"#$%&'()*+,-./0123   !"#$%&'()*+,-./0123456  !"#$%&'()*+,-./012345678    !"#$%&'()*+,-./    !"#$%&' ()*+,- ./ 0 1 2  !"#$%&'()*+,-./   !"#$%&'()*+,  !"#$%&'()*+,  !"#$%&'()*  !"#$%&'()*+,-./0123   !"#$%&'()*+,-./0123  !"#$%&'()*+,  !"#$%&'()*+,-./01  !"#$%&'()*+,  !"#$%&'()*+,-./01234   !"#$%&'()*+,-./0123  !"#$%&'()*+,-./01234567     !"#$%&'()* + ,-./ 0123 45678    !"#$%&'()*+,-./0  !"#$%&'()*+,-./0123456789   !"#$ %&'()*+,-./01234 56 789:  !"#$%&'()*+,-./012345    !"#$%&'()*+,-./01  !"#$%&'()*   !"#$%&'()*+,-  !"#$%&'()*+,-   !"#$%&'()*+  !"#$%&'(   !"#$%&'()*+,-./012   !"#$%&'()*+,-./0123456  !"#$%&'()*+,-./01  !"#$%&'()*+,-./012  !"#$%&'()*+,-./012345  !"#$%&'()*+,-./01234567  !"#$%&'()*+,-./0123456   !"#$%&'()*+,-./0123     !"#$%&'()*+,-./0123456     !"#$%&'()*+,-./012345       !"# $% &' ()*+,-./012 3456  !"#$%&'()*+,-./0123456    !"#$%&'()*+,-./01234    !"#$%&'()*+,-./  !"#$%&'()*+,-.     !"#$%&'()*+,-./0123456789:;<=>?3   @  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[[\]^_`abcdefghijklmnopqrstuvwxyz{|}~@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijkllmnopqrstuvwxyz{|}~@   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~    !"#$%&'()*+,-./0123456789:;<=>?              !         !"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!  !"#$%&'()*+,,,,,,,,,,,,,,,,,,,,,       !"#$%&'               !"#  !"#$%&'()*+,-./0123456789      !"#$%&'()*+,-./0123456789:  !"#$%&'(  !"#$%&'()*+,-./0123456       ! "#$%&'( )*+,-./01 234 5   !"#$%&'()*+,-./012345678   !"#$%&'()*+,-./0123456789:      !"#$%&'()*+, -./012 345 6 7  !"#$%&'()*+,-./0123456789     !"#$%&'()*+,-./01234567  !"#$%&'()*+,-./0123456789   !"#$%&'()*+,-./0123   !"#$%&'()*+,-./01234567  !"#$%&'()*+,-./012345  !"#$%&'()*+,-./01234567    !"#$%&'()*+,-./01234567  !"#$%&'()*+,-./0123456  !"#$%&'()*+,-./0123456789:;<  !"#$%&'()*+,-./0123456789:  !"#$%&'()*+,-./012345   !"#$%&'()*+,-./0   !"#$%&'()*+,-./01234     !" #$ % &'()*+,-./0 123456789   !"#$%&'()*+,-./   !"#$%&'()*+,-./012345  !"#$%&'()*+,-./0123456789:;   !"#$%&'()*+,-./0123456789:   !"#$%&'()*+,-./0123456789:;<=   !"#$%&'()*+ ,-. /01 23 4567 8  !"#$%&'()*+,-./01234567  !"#$%&'()*+,-./012345  !"#$%&'()*+,-./0123456789:  !"#$%&'()*+,-!!./012!345!6789:;<   !"#$%&'()*+,-./01234567   !"#$%&'()*+,-./01234567     !"#$%& '()*+, -./0123 4 5678  !"#$%&'()*+,-./012  !"#$%&'()*+,-./0123  !"#$%&'()*+,-./0123456  !"#$%&'()*+,-./012345678    !"#$%&'()*+,-./01234567  !"#$%&'()*+,-./01234567  !"#$%&'()*+,-./0123   !"#$%&'()*+,-./0123456   !"#$%&'()*+,-./01234567  !"#$%&'()*+,-./01   !"#$%&'()*+,-./012345     !"#$%&'() *+,-./0123456789:;  !"#$%&'()*+,-./0123456789:;<  !"#$%&'()*+,-./0123456   !"#$%&'()*+,- ./ 0123456789:;   !"#$%&'()*+,-./012345678  !"#$%&'()*+,-./0123456789:;<=   !"#$%&'()*+,-./012   !"#$%&'()*+,-./01234567   !"#$%&'()*+,-./0123456     !"#$%&'()* +,-./0 12 34567 89  !"#$%&'()*+,-./01234  !"#$%&'()*+,-./012345   !"#$%&'()*+,-./0123456789   !"#$%&'()*+,-./012345  !"#$%&'()*+,-./0123456  !"#$%&'()*+,-./012345  !"#$%&'()*+,-./01234    !"#$%&'()*+,-./012   !"#$%&'()*+,-./012345   !"#$%&'()*+,-./01234567  !"#$%&'()*+,-./0123456  !"#$%&'()*+,-./0123456789:;  !"#$%&'()*+,-./012345678  !"#$%&'()*+,-./0123456  !"#$%&'()*+,-./01234567    !"#$%&'()*+,-./012  !"#$%&'()*+,-./012345678       !"#$%&'()* +, -./01234567  !"#$%&'()*+,-./012345678  !"#$%&'()*+,-./0123456789:;  !"#$%&'()*+,-./012345  !"#$%&'()*+,-./0123456789:  !"#$%&'()*+,-./012345  !"#$%&'()*+,-./0123456789:  !"#$%&'()*+,-./012345678   ! "#$ %&'()*+,-. /012 34 56789  !"#$%&'()*+,-./0123456789:;<  !"#$%&'()*+,-./012345678  !"#$%&'()*+,-./01234567  !"#$%&'()*+,-./0123456789:  !"#$%&'()*+,-./0123456789:;<=>  !"#$%&'()*+,-./012345678     !" #$%&'()*+,-./012345 6   !"#$%&'()*+,-./01234567   !"#$%&'()*+,-./01234567   !"#$%&'()*+,-./012345678   !"#$%&'()*+,-./012     ! "#$%&'()*+ ,- ./012 34567  !"#$%&'()*+,-./01234  !"#$%&'()*+,-./0123456  !"#$%&'()*+,-./012345678  !"#$%&'()*+,-./0123456789  !"#$%&'()*+,-./012  !"#$%&'()*+,-./0123456789      !"#$%&'()*+,-./0123456789:;<  !"#$%&'()*+,-./012345678  !"#$%&'()*+,-./0123456789:;<=  !"#$%&'()*+,-./012345678  !"#$%&'()*+,-./01234567  !"#$%&'()*+,-./0123456  !"#$%&'()*+,-./0123456789  !"#$%&'()*+,-./012345678  !"#$%&'()*+,-./0123456789:;<=     !"#$%&'()*+,-./01234 5 6789:  !"#$%&'()*+,-./0123456  !"#$%&'()*+,-./0123456789:;<=   !"#$%&'()*+,-./01234567   !"#$%&'()*+,-./0123456789:  !"#$%&'()*+,-./   !"#$%&'()*+,-./01  !"#$%&'()*+,-./0123  !"#$%&'()*+,-./01234567  !"#$%&'()*+,-./012345678     !"#$%&'()* +,-./012345678 9:;  !"#$%&'()*+,-./01234567  !"#$%&'()*+,-./0123456789:;   !"# $ %&'()*+,-./01 23456789:;<     !"#$%& '()*+,- ./0123456789  !"#$%&'()*+,-./0123456789:;<  !"#$%&'()*+,-./0123456789:;<  !"#$%&'()*+,-./0123456789:;<   !"#$%&'()*+,-./0123456  !"#$%&'()*+,-./01234567  !"#$%&'$()$*+,-.$/0$123456789:;<  !"#$%&'()*+,-./0123456789:;<=   !"#$%&'()*+,-./01234567  !"#$%&'()*+,-./0123456789:  !"#$%&'()*+,-./0123456789  !"#$%&'()*+,-./0123456789   !"#$%&'()*+,-./01234  !"# $ %&'( )*+ ,-. /0123456789:;  !"#$%&'()*+,-./0123   !"#$%&'()*+, - ./01 2345 6789:     !"#$%&'()*+,-./012345678    !"#$% &'() *+, -./ 01 23456   !"#$%&'()*+,-./012345  !"#$%&'()*+,-./0123456  !"#$%&'()*+,-./0123456789:  !"#$%&'()*+,-./0123456789   !"#$%&'()*+,-./0123456789   !"#$%&'()*+,-./01234567  !"#$%&'()*+,-./0123456789:;  !"#$%&'()*+,-./0123456789:;<  !"#$%&'()*+,-./0123456789:   !"#$% &'()*+,-./0123456 78 9:;<  !"#$%&'()*+,-./012345678    !"#$%&'()*+,-./0123   !"#$%&'()*+,-./0123456789  !"#$%&'()*+,-./0123  !"#$%&'()*+,-./0123456  !"#$%&'()*+,-./0123456789:;<  !"#$%&'()*+,-./0123456789  !"#$%&'()*+,-./012345678   !"#$%&'()*+,-./0   !"#$%&'()*+,-./012345  !"#$%&'()*+,-./0123  !"#$%&'()*+,-./01234   !"#$%&'()*+,-./012345678  !"#$%&'()*+,-./012345   !"#$%&'()*+,-./0123456789  !"#$%&'()*+,-./01   !"#$%&'()*+,-./0123456  !"#$%&'()*+,-./0123456789    !"#$%&'()*+,-./012  !"#$%&'()*+,-./012345678   ! "#$%&'()*+, -./01 234567 89:  !"#$%&'()*+,-./0  !"#$%&'()*+,-./01  !"#$%&'()*+,-./0123  !"#$%&'()*+,-./012345678   !"#$%&'()*+,-./0123  !"#$%&'()*+,-./012345678  !"#$%&'()*+,-./01234  !"#$%&'()*+,-./0123   !"#$%&'()*+,-./01234567  !"#$%&'()*+,-./012345   !"#$%&'()*+,-./012345  !"#$%&'()*+,-./01234567  !"#$%&'()*+,-./0123456  !"#$$%$&'($)*$+,-./0$12$3456789:     ! "#$%&' ()*+,-. /01 23456 7   !"#$%&'()*+,-./0123456789:  !"#$%&'()*+,-./0123456789  !"#$%&'()*+,-./0123456789:  !"#$%&'()*+,-./0123456789:;<=  !"#$%&'()*+,-./0123456789  !"#$%&'()*+,%-./012345678%9:;<=>    !"#$%&'()*+,-./0123456789 :;<  !"#$%&'()*+,-./0123456789:;<  !"#$%&'()*+,-./0123456789:  !"#$%&'()*+,-./0123456789    !"#$%&' ( )*+, -./0123 45678   !"#$%&'()*+,-./   !"#$%&'()*+,-./01234    !"#$%&'()* +,-./012 3456789    !"#$%&'()*+,-./0123456  !"#$%&'()*+,-./0123456  !"#$%&'()*+,-./01234567      !"#$%&' ()*+ ,-. /012345 67  !"#$%&'()*+,-./0123456789:;  !"#$%&'()*+,-./012345678   !"#$%&'()*+,-./0123456789:   !"#$%&'()*+,-./0123456789:;<      !"#$%&'() * +,-./01234567 8  !"#$%&'()*+,-./0123456789:  !"#$%&'()*+,-./0123456789:;  !"#$%&'()*+,-./0123456789:;<=  !"#$%&'()*+,-./012345678  !"#$%&'()*+,-./0123456789:;<=  !"#$%&'()*+,-./01234567  !"#$%&'()*+,-./0123456789:;  !"#$%&'()*+,-./0123456789:  !"#$%&'()*+,-./0123456789:;<  !"#$%&'()*+,-./0123456789:;    !"#$ %&'()*+,-./ 0123456789  !"#$%&'()*+,-./012345678  !"#$%&'()*+,-./012345   !"#$%&'()*+,-./012345678  !"#$%&'()*+,-./012345678  !"#$%&'()*+,-./0123456   !"#$%&'()*+,-./0123456789:;<=   !"#$%&'()*+,-./012345678  !"#$%&'()*+,-./0123456789  !"#$%&'()*+,-./0123456789:;<   !"#$%&'()*+,-./012345   !"#$%&'()*+,-./0123456     !"#$%& '( )*+,-./0123456789:   !"#$%&'()*+,-./012345678   !"#$%&'()*+,-./01  !"#$%&'()*+,-./012345678   !"#$%&'()*+,-./  !"#$%&'()*+,-./01234   !"#$%&'()*+,-./0123456789:;  !"#$%&'()*+,-./0123456789    !"#$%&'()*+,-./01234567  !"#$%&'()*+,-./0123456789:;<=>   !"#$%&'()*+,-./01234567 89:;<=>  !"#$%&'()*+,-./012   !"#$%&'()*+,-./0123456789:    !"#$%&'()*+,-./0123456789  !"#$%&'()*+,-./0123456789:;<=  !"#$%&'()*+,-./012345678  !"#$%&'()*+,-./0123   !"# $%&'()* +,-./012 3456789:;  !"#$%&'()*+,-./012 3456 789 :;<=  !"#$%&'()*+,-./0123456789:;  !"#$%&'()*+,-./0123456  !"#$%&'()*+,-./01234567  !"#$%&'()*+,-./0123456  !"#$%&'()*&+,-./0123456789:;<=>?   !"#$%&'()*+,-./012345678  !"#$%&'()*+,-./0123456789:;  !"#$%&'()*+,-./01234567  !"#$%&'()*+,-./012345678       !"# $ % &'()*+,-. /012 345   !"#$%&'()*+,-./012345678   !"# $%&'()*+,-./01234 5678 9:  !"#$%&'()*+,-./0123456789:;    !" #$%&'()*+,-./0123456789:   !"#$%&'()*+,-./0123456789:;       !"#$%&'() *+,-./01234 5678  !"#$%&'()*+,-./0123456789  !"#$%&'()*+,-./0123456789  !"#$%&'()*+,-./0123456789:;<   !"#$%&'()*+,-./0123456789   !"#$%&'()* +,-./01234 56789 : ;  !"#$%&'()*+,-./012345678  !"#$%&'()*+,-./012345678  !"#$%&'()*+,-./0123456789  !"#$%&'()*+,-./0123456789:;<=  !"#$%&'()*+,-./0123456789:  !"#$%&'()*+,-./0123456789:;<   !"#$%&'()*+,-./0123456  !"#$%&'()*+,-./012345678   !"#$%&'()*+,-./012345  !"#$%&'()*+,-./0123456  !"#$%&'()*+,-./0123456789   !"#$%&'()*+,-./012345678  !"#$%&'()*+,-./0123456789     !"#$%&'()*+,-./0123 4567 89:     !"#$%&'()*+,-./01234567    !"#$ % &'()*+ ,-./ 012345 678    !"# $%&'() *+,- ./ 0123 456   !" #$%& '()*+, -./0 123 456   !"#$%&'()*+,-./0123456789:;      !"#$%& '()* +,-. /012345678  !"#$%&'()*+,-./012    !"#$%&'()*+,-./01234567  !"#$%&'()*+,-./012345    !"#$%&'()*+,-./0123   !"#$%&'()*+,-./0123456789:  !"#$%&'()*+,-./0123456789:;<   !"#$%&'()*+,-./0123456789:;    !"#$%&'()*+,-./01234   !"#$%&'()*+,-./0123  !"#$%&'()*+,-./012345  !"#$%&'()*+,-./012    !"#$%&'()*+,-./    !"#$%&'()*+,-./  !"#$%&'()*+,-./01234  !"#$%&'()*+,-./012   !"#$%&'()*+,-./  !"#$%&'()*+,-./     !"#$%&'()*+,-./012  !"#$%&'()*+,-./0123456789:;  !"#$%&'()*+,-./0123456789:;  !"#$%&'!()!*+,-./!0123456789:;<=   !"# $% &'()*+ , -./ 012345 678  !"#$%&'()*+,-  !"#$%&'()*+,-./0123456789:;<=   !"#$%&'()*+,-./0123456789:   !"#$%&'()*+,-./0123456  !"#$%&'()*+,-)./012)3456789:));<    !"#$%%%%%%%%%%%%%%%%%%%%%%%%%%%%                             !"#       !"#$%&'()*+,-./0123456789:;<=>  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!    ; G<HdH|zRx $G0FJ w?:*3$"DG \pHHwGNU P `(@ F ̪`K  F @ D^`K  @ O \`K  O @ l`K  @ U e`K  U @ X`K  @ ` `K  ` @ 3`K  @ f h`K  f @ `K  v h $ P(X(o`  (08 h oooo+( GA$3a1h 1 GA$3p1067 $ GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realignbig5.so-2.2.10-35.el8.x86_64.debug7zXZִF!t/]?Eh=ڊ2NpI Q{H ;P{Vڐ&a]kao!Gw m0bu`c f]i%yſ q[P P]e}eSlUia ,%&U/G7s`%sUXSv_9UyZ :M0XBdu)`boQYmvG[F$-+3 7qP)dVˁ&+奠;rp+^#ueID_AISN \˥\ӔAJ?3<+aO +YZ&t9|R %]Ф-I,D icppi`FEG8vK@eCh&'(7L=r"ŪWq1Dz2!6,>pԔ$V"=ShN>7k \_f.5DW.?$(\oȱq s29BU1V,.ZK>_BP5+𛖍' _=p-52K*Eao[{xy+a)h=b&`93-=g^z+8^ oF }}s:v j6(wS6UO>0,H8p/%Шt6ܗfH"br% ̈KsVk[f@&)XSASuyq \ jƶΡ!&Zt%`ͪ.0aӑ:nd$ {=E\gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 08oEo Th^B8 8 0hh h c 0n w D}$ $ @ @ k $tHH P(PX(X`(`` ( ( (((((0h(  (HP+PK!2@@8 @00 PP!P! !!  888$$ Std Ptdttt$$QtdRtdPP!P!GNU6ۄ}_/O ]&U1@   BE|{-qX n , F"(!0!U $(!__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeInit_emoji_sjis_softbankrb_register_transcoderlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ui P!X!``!`!!!! S!  !(!8! SH! !!!!! !HHa!HtH5b!%c!hh%=!D%5!DH=1!H*!H9tH!Ht H=!H5!H)HHH?HHtH!HtfD=!u+UH=!Ht H=!Yd!]wHH=a! H=!HHHUTF8-SoftBankSJIS-SoftBank 、。,.・:;?!゛゜´`¨^ ̄_ヽヾゝゞ〃仝々〆〇ー―‐/\~∥|…‥‘’“”()〔〕[]{}〈〉《》「」『』【】+-±×÷=≠<>≦≧∞∴♂♀°′″℃¥$¢£%#&*@§☆★○●◎◇◆□■△▲▽▼※〒→←↑↓〓 ∈∋⊆⊇⊂⊃∪∩∧∨¬⇒⇔∀∃∠⊥⌒∂∇≡≒≪≫√∽∝∵∫∬ʼn♯♭♪†‡¶◯ 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzぁあぃいぅうぇえぉおかがきぎくぐけげこごさざしじすずせぜそぞただちぢっつづてでとどなにぬねのはばぱひびぴふぶぷへべぺほぼぽまみむめもゃやゅゆょよらりるれろゎわゐゑをん\ァアィイゥウェエォオカガキギクグケゲコゴサザシジスズセゼソゾタダチヂッツヅテデトドナニヌネノハバパヒビピフブプヘベペホボポマミムメモャヤュユョヨラリルレロヮワヰヱヲンヴヵヶ ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩαβγδεζηθικλμνξοπρστυφχψω~АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ абвгдеёжзийклмнопрстуфхцчшщъыьэюя─│┌┐┘└├┬┤┴┼━┃┏┓┛┗┣┳┫┻╋┠┯┨┷┿┝┰┥┸╂= p①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩ ㍉㌔㌢㍍㌘㌧㌃㌶㍑㍗㌍㌦㌣㌫㍊㌻㎜㎝㎞㎎㎏㏄㎡㍻〝〟№㏍℡㊤㊥㊦㊧㊨㈱㈲㈹㍾㍽㍼≒≡∫∮∑√⊥∠∟⊿∵∩∪ 亜唖娃阿哀愛挨姶逢葵茜穐悪握渥旭葦芦鯵梓圧斡扱宛姐虻飴絢綾鮎或粟袷安庵按暗案闇鞍杏以伊位依偉囲夷委威尉惟意慰易椅為畏異移維緯胃萎衣謂違遺医井亥域育郁磯一壱溢逸稲茨芋鰯允印咽員因姻引飲淫胤蔭z 院陰隠韻吋右宇烏羽迂雨卯鵜窺丑碓臼渦嘘唄欝蔚鰻姥厩浦瓜閏噂云運雲荏餌叡営嬰影映曳栄永泳洩瑛盈穎頴英衛詠鋭液疫益駅悦謁越閲榎厭円園堰奄宴延怨掩援沿演炎焔煙燕猿縁艶苑薗遠鉛鴛塩於汚甥凹央奥往応押旺横欧殴王翁襖鴬鴎黄岡沖荻億屋憶臆桶牡乙俺卸恩温穏音下化仮何伽価佳加可嘉夏嫁家寡科暇果架歌河火珂禍禾稼箇花苛茄荷華菓蝦課嘩貨迦過霞蚊俄峨我牙画臥芽蛾賀雅餓駕介会解回塊壊廻快怪悔恢懐戒拐改9d 魁晦械海灰界皆絵芥蟹開階貝凱劾外咳害崖慨概涯碍蓋街該鎧骸浬馨蛙垣柿蛎鈎劃嚇各廓拡撹格核殻獲確穫覚角赫較郭閣隔革学岳楽額顎掛笠樫橿梶鰍潟割喝恰括活渇滑葛褐轄且鰹叶椛樺鞄株兜竃蒲釜鎌噛鴨栢茅萱粥刈苅瓦乾侃冠寒刊勘勧巻喚堪姦完官寛干幹患感慣憾換敢柑桓棺款歓汗漢澗潅環甘監看竿管簡緩缶翰肝艦莞観諌貫還鑑間閑関陥韓館舘丸含岸巌玩癌眼岩翫贋雁頑顔願企伎危喜器基奇嬉寄岐希幾忌揮机旗既期棋棄9`機帰毅気汽畿祈季稀紀徽規記貴起軌輝飢騎鬼亀偽儀妓宜戯技擬欺犠疑祇義蟻誼議掬菊鞠吉吃喫桔橘詰砧杵黍却客脚虐逆丘久仇休及吸宮弓急救朽求汲泣灸球究窮笈級糾給旧牛去居巨拒拠挙渠虚許距鋸漁禦魚亨享京供侠僑兇競共凶協匡卿叫喬境峡強彊怯恐恭挟教橋況狂狭矯胸脅興蕎郷鏡響饗驚仰凝尭暁業局曲極玉桐粁僅勤均巾錦斤欣欽琴禁禽筋緊芹菌衿襟謹近金吟銀九倶句区狗玖矩苦躯駆駈駒具愚虞喰空偶寓遇隅串櫛釧屑屈9\掘窟沓靴轡窪熊隈粂栗繰桑鍬勲君薫訓群軍郡卦袈祁係傾刑兄啓圭珪型契形径恵慶慧憩掲携敬景桂渓畦稽系経継繋罫茎荊蛍計詣警軽頚鶏芸迎鯨劇戟撃激隙桁傑欠決潔穴結血訣月件倹倦健兼券剣喧圏堅嫌建憲懸拳捲検権牽犬献研硯絹県肩見謙賢軒遣鍵険顕験鹸元原厳幻弦減源玄現絃舷言諺限乎個古呼固姑孤己庫弧戸故枯湖狐糊袴股胡菰虎誇跨鈷雇顧鼓五互伍午呉吾娯後御悟梧檎瑚碁語誤護醐乞鯉交佼侯候倖光公功効勾厚口向9X后喉坑垢好孔孝宏工巧巷幸広庚康弘恒慌抗拘控攻昂晃更杭校梗構江洪浩港溝甲皇硬稿糠紅紘絞綱耕考肯肱腔膏航荒行衡講貢購郊酵鉱砿鋼閤降項香高鴻剛劫号合壕拷濠豪轟麹克刻告国穀酷鵠黒獄漉腰甑忽惚骨狛込此頃今困坤墾婚恨懇昏昆根梱混痕紺艮魂些佐叉唆嵯左差査沙瑳砂詐鎖裟坐座挫債催再最哉塞妻宰彩才採栽歳済災采犀砕砦祭斎細菜裁載際剤在材罪財冴坂阪堺榊肴咲崎埼碕鷺作削咋搾昨朔柵窄策索錯桜鮭笹匙冊刷9T察拶撮擦札殺薩雑皐鯖捌錆鮫皿晒三傘参山惨撒散桟燦珊産算纂蚕讃賛酸餐斬暫残仕仔伺使刺司史嗣四士始姉姿子屍市師志思指支孜斯施旨枝止死氏獅祉私糸紙紫肢脂至視詞詩試誌諮資賜雌飼歯事似侍児字寺慈持時次滋治爾璽痔磁示而耳自蒔辞汐鹿式識鴫竺軸宍雫七叱執失嫉室悉湿漆疾質実蔀篠偲柴芝屡蕊縞舎写射捨赦斜煮社紗者謝車遮蛇邪借勺尺杓灼爵酌釈錫若寂弱惹主取守手朱殊狩珠種腫趣酒首儒受呪寿授樹綬需囚収周9P宗就州修愁拾洲秀秋終繍習臭舟蒐衆襲讐蹴輯週酋酬集醜什住充十従戎柔汁渋獣縦重銃叔夙宿淑祝縮粛塾熟出術述俊峻春瞬竣舜駿准循旬楯殉淳準潤盾純巡遵醇順処初所暑曙渚庶緒署書薯藷諸助叙女序徐恕鋤除傷償勝匠升召哨商唱嘗奨妾娼宵将小少尚庄床廠彰承抄招掌捷昇昌昭晶松梢樟樵沼消渉湘焼焦照症省硝礁祥称章笑粧紹肖菖蒋蕉衝裳訟証詔詳象賞醤鉦鍾鐘障鞘上丈丞乗冗剰城場壌嬢常情擾条杖浄状畳穣蒸譲醸錠嘱埴飾9L拭植殖燭織職色触食蝕辱尻伸信侵唇娠寝審心慎振新晋森榛浸深申疹真神秦紳臣芯薪親診身辛進針震人仁刃塵壬尋甚尽腎訊迅陣靭笥諏須酢図厨逗吹垂帥推水炊睡粋翠衰遂酔錐錘随瑞髄崇嵩数枢趨雛据杉椙菅頗雀裾澄摺寸世瀬畝是凄制勢姓征性成政整星晴棲栖正清牲生盛精聖声製西誠誓請逝醒青静斉税脆隻席惜戚斥昔析石積籍績脊責赤跡蹟碩切拙接摂折設窃節説雪絶舌蝉仙先千占宣専尖川戦扇撰栓栴泉浅洗染潜煎煽旋穿箭線9H 繊羨腺舛船薦詮賎践選遷銭銑閃鮮前善漸然全禅繕膳糎噌塑岨措曾曽楚狙疏疎礎祖租粗素組蘇訴阻遡鼠僧創双叢倉喪壮奏爽宋層匝惣想捜掃挿掻操早曹巣槍槽漕燥争痩相窓糟総綜聡草荘葬蒼藻装走送遭鎗霜騒像増憎臓蔵贈造促側則即息捉束測足速俗属賊族続卒袖其揃存孫尊損村遜他多太汰詑唾堕妥惰打柁舵楕陀駄騨体堆対耐岱帯待怠態戴替泰滞胎腿苔袋貸退逮隊黛鯛代台大第醍題鷹滝瀧卓啄宅托択拓沢濯琢託鐸濁諾茸凧蛸只9D#叩但達辰奪脱巽竪辿棚谷狸鱈樽誰丹単嘆坦担探旦歎淡湛炭短端箪綻耽胆蛋誕鍛団壇弾断暖檀段男談値知地弛恥智池痴稚置致蜘遅馳築畜竹筑蓄逐秩窒茶嫡着中仲宙忠抽昼柱注虫衷註酎鋳駐樗瀦猪苧著貯丁兆凋喋寵帖帳庁弔張彫徴懲挑暢朝潮牒町眺聴脹腸蝶調諜超跳銚長頂鳥勅捗直朕沈珍賃鎮陳津墜椎槌追鎚痛通塚栂掴槻佃漬柘辻蔦綴鍔椿潰坪壷嬬紬爪吊釣鶴亭低停偵剃貞呈堤定帝底庭廷弟悌抵挺提梯汀碇禎程締艇訂諦蹄逓9@&邸鄭釘鼎泥摘擢敵滴的笛適鏑溺哲徹撤轍迭鉄典填天展店添纏甜貼転顛点伝殿澱田電兎吐堵塗妬屠徒斗杜渡登菟賭途都鍍砥砺努度土奴怒倒党冬凍刀唐塔塘套宕島嶋悼投搭東桃梼棟盗淘湯涛灯燈当痘祷等答筒糖統到董蕩藤討謄豆踏逃透鐙陶頭騰闘働動同堂導憧撞洞瞳童胴萄道銅峠鴇匿得徳涜特督禿篤毒独読栃橡凸突椴届鳶苫寅酉瀞噸屯惇敦沌豚遁頓呑曇鈍奈那内乍凪薙謎灘捺鍋楢馴縄畷南楠軟難汝二尼弐迩匂賑肉虹廿日乳入9<)如尿韮任妊忍認濡禰祢寧葱猫熱年念捻撚燃粘乃廼之埜嚢悩濃納能脳膿農覗蚤巴把播覇杷波派琶破婆罵芭馬俳廃拝排敗杯盃牌背肺輩配倍培媒梅楳煤狽買売賠陪這蝿秤矧萩伯剥博拍柏泊白箔粕舶薄迫曝漠爆縛莫駁麦函箱硲箸肇筈櫨幡肌畑畠八鉢溌発醗髪伐罰抜筏閥鳩噺塙蛤隼伴判半反叛帆搬斑板氾汎版犯班畔繁般藩販範釆煩頒飯挽晩番盤磐蕃蛮匪卑否妃庇彼悲扉批披斐比泌疲皮碑秘緋罷肥被誹費避非飛樋簸備尾微枇毘琵眉美98,鼻柊稗匹疋髭彦膝菱肘弼必畢筆逼桧姫媛紐百謬俵彪標氷漂瓢票表評豹廟描病秒苗錨鋲蒜蛭鰭品彬斌浜瀕貧賓頻敏瓶不付埠夫婦富冨布府怖扶敷斧普浮父符腐膚芙譜負賦赴阜附侮撫武舞葡蕪部封楓風葺蕗伏副復幅服福腹複覆淵弗払沸仏物鮒分吻噴墳憤扮焚奮粉糞紛雰文聞丙併兵塀幣平弊柄並蔽閉陛米頁僻壁癖碧別瞥蔑箆偏変片篇編辺返遍便勉娩弁鞭保舗鋪圃捕歩甫補輔穂募墓慕戊暮母簿菩倣俸包呆報奉宝峰峯崩庖抱捧放方朋94/法泡烹砲縫胞芳萌蓬蜂褒訪豊邦鋒飽鳳鵬乏亡傍剖坊妨帽忘忙房暴望某棒冒紡肪膨謀貌貿鉾防吠頬北僕卜墨撲朴牧睦穆釦勃没殆堀幌奔本翻凡盆摩磨魔麻埋妹昧枚毎哩槙幕膜枕鮪柾鱒桝亦俣又抹末沫迄侭繭麿万慢満漫蔓味未魅巳箕岬密蜜湊蓑稔脈妙粍民眠務夢無牟矛霧鵡椋婿娘冥名命明盟迷銘鳴姪牝滅免棉綿緬面麺摸模茂妄孟毛猛盲網耗蒙儲木黙目杢勿餅尤戻籾貰問悶紋門匁也冶夜爺耶野弥矢厄役約薬訳躍靖柳薮鑓愉愈油癒902諭輸唯佑優勇友宥幽悠憂揖有柚湧涌猶猷由祐裕誘遊邑郵雄融夕予余与誉輿預傭幼妖容庸揚揺擁曜楊様洋溶熔用窯羊耀葉蓉要謡踊遥陽養慾抑欲沃浴翌翼淀羅螺裸来莱頼雷洛絡落酪乱卵嵐欄濫藍蘭覧利吏履李梨理璃痢裏裡里離陸律率立葎掠略劉流溜琉留硫粒隆竜龍侶慮旅虜了亮僚両凌寮料梁涼猟療瞭稜糧良諒遼量陵領力緑倫厘林淋燐琳臨輪隣鱗麟瑠塁涙累類令伶例冷励嶺怜玲礼苓鈴隷零霊麗齢暦歴列劣烈裂廉恋憐漣煉簾練聯9,5蓮連錬呂魯櫓炉賂路露労婁廊弄朗楼榔浪漏牢狼篭老聾蝋郎六麓禄肋録論倭和話歪賄脇惑枠鷲亙亘鰐詫藁蕨椀湾碗腕 弌丐丕个丱丶丼丿乂乖乘亂亅豫亊舒弍于亞亟亠亢亰亳亶从仍仄仆仂仗仞仭仟价伉佚估佛佝佗佇佶侈侏侘佻佩佰侑佯來侖儘俔俟俎俘俛俑俚俐俤俥倚倨倔倪倥倅伜俶倡倩倬俾俯們倆偃假會偕偐偈做偖偬偸傀傚傅傴傲(8僉僊傳僂僖僞僥僭僣僮價僵儉儁儂儖儕儔儚儡儺儷儼儻儿兀兒兌兔兢竸兩兪兮冀冂囘册冉冏冑冓冕冖冤冦冢冩冪冫决冱冲冰况冽凅凉凛几處凩凭凰凵凾刄刋刔刎刧刪刮刳刹剏剄剋剌剞剔剪剴剩剳剿剽劍劔劒剱劈劑辨辧劬劭劼劵勁勍勗勞勣勦飭勠勳勵勸勹匆匈甸匍匐匏匕匚匣匯匱匳匸區卆卅丗卉卍凖卞卩卮夘卻卷厂厖厠厦厥厮厰厶參簒雙叟曼燮叮叨叭叺吁吽呀听吭吼吮吶吩吝呎咏呵咎呟呱呷呰咒呻咀呶咄咐咆哇咢咸咥咬哄哈咨9|:咫哂咤咾咼哘哥哦唏唔哽哮哭哺哢唹啀啣啌售啜啅啖啗唸唳啝喙喀咯喊喟啻啾喘喞單啼喃喩喇喨嗚嗅嗟嗄嗜嗤嗔嘔嗷嘖嗾嗽嘛嗹噎噐營嘴嘶嘲嘸噫噤嘯噬噪嚆嚀嚊嚠嚔嚏嚥嚮嚶嚴囂嚼囁囃囀囈囎囑囓囗囮囹圀囿圄圉圈國圍圓團圖嗇圜圦圷圸坎圻址坏坩埀垈坡坿垉垓垠垳垤垪垰埃埆埔埒埓堊埖埣堋堙堝塲堡塢塋塰毀塒堽塹墅墹墟墫墺壞墻墸墮壅壓壑壗壙壘壥壜壤壟壯壺壹壻壼壽夂夊夐夛梦夥夬夭夲夸夾竒奕奐奎奚奘奢奠奧奬奩9x=奸妁妝佞侫妣妲姆姨姜妍姙姚娥娟娑娜娉娚婀婬婉娵娶婢婪媚媼媾嫋嫂媽嫣嫗嫦嫩嫖嫺嫻嬌嬋嬖嬲嫐嬪嬶嬾孃孅孀孑孕孚孛孥孩孰孳孵學斈孺宀它宦宸寃寇寉寔寐寤實寢寞寥寫寰寶寳尅將專對尓尠尢尨尸尹屁屆屎屓屐屏孱屬屮乢屶屹岌岑岔妛岫岻岶岼岷峅岾峇峙峩峽峺峭嶌峪崋崕崗嵜崟崛崑崔崢崚崙崘嵌嵒嵎嵋嵬嵳嵶嶇嶄嶂嶢嶝嶬嶮嶽嶐嶷嶼巉巍巓巒巖巛巫已巵帋帚帙帑帛帶帷幄幃幀幎幗幔幟幢幤幇幵并幺麼广庠廁廂廈廐廏9t@廖廣廝廚廛廢廡廨廩廬廱廳廰廴廸廾弃弉彝彜弋弑弖弩弭弸彁彈彌彎弯彑彖彗彙彡彭彳彷徃徂彿徊很徑徇從徙徘徠徨徭徼忖忻忤忸忱忝悳忿怡恠怙怐怩怎怱怛怕怫怦怏怺恚恁恪恷恟恊恆恍恣恃恤恂恬恫恙悁悍惧悃悚悄悛悖悗悒悧悋惡悸惠惓悴忰悽惆悵惘慍愕愆惶惷愀惴惺愃愡惻惱愍愎慇愾愨愧慊愿愼愬愴愽慂慄慳慷慘慙慚慫慴慯慥慱慟慝慓慵憙憖憇憬憔憚憊憑憫憮懌懊應懷懈懃懆憺懋罹懍懦懣懶懺懴懿懽懼懾戀戈戉戍戌戔戛9pC戞戡截戮戰戲戳扁扎扞扣扛扠扨扼抂抉找抒抓抖拔抃抔拗拑抻拏拿拆擔拈拜拌拊拂拇抛拉挌拮拱挧挂挈拯拵捐挾捍搜捏掖掎掀掫捶掣掏掉掟掵捫捩掾揩揀揆揣揉插揶揄搖搴搆搓搦搶攝搗搨搏摧摯摶摎攪撕撓撥撩撈撼據擒擅擇撻擘擂擱擧舉擠擡抬擣擯攬擶擴擲擺攀擽攘攜攅攤攣攫攴攵攷收攸畋效敖敕敍敘敞敝敲數斂斃變斛斟斫斷旃旆旁旄旌旒旛旙无旡旱杲昊昃旻杳昵昶昴昜晏晄晉晁晞晝晤晧晨晟晢晰暃暈暎暉暄暘暝曁暹曉暾暼9lF曄暸曖曚曠昿曦曩曰曵曷朏朖朞朦朧霸朮朿朶杁朸朷杆杞杠杙杣杤枉杰枩杼杪枌枋枦枡枅枷柯枴柬枳柩枸柤柞柝柢柮枹柎柆柧檜栞框栩桀桍栲桎梳栫桙档桷桿梟梏梭梔條梛梃檮梹桴梵梠梺椏梍桾椁棊椈棘椢椦棡椌棍棔棧棕椶椒椄棗棣椥棹棠棯椨椪椚椣椡棆楹楷楜楸楫楔楾楮椹楴椽楙椰楡楞楝榁楪榲榮槐榿槁槓榾槎寨槊槝榻槃榧樮榑榠榜榕榴槞槨樂樛槿權槹槲槧樅榱樞槭樔槫樊樒櫁樣樓橄樌橲樶橸橇橢橙橦橈樸樢檐檍檠檄檢檣9hI檗蘗檻櫃櫂檸檳檬櫞櫑櫟檪櫚櫪櫻欅蘖櫺欒欖鬱欟欸欷盜欹飮歇歃歉歐歙歔歛歟歡歸歹歿殀殄殃殍殘殕殞殤殪殫殯殲殱殳殷殼毆毋毓毟毬毫毳毯麾氈氓气氛氤氣汞汕汢汪沂沍沚沁沛汾汨汳沒沐泄泱泓沽泗泅泝沮沱沾沺泛泯泙泪洟衍洶洫洽洸洙洵洳洒洌浣涓浤浚浹浙涎涕濤涅淹渕渊涵淇淦涸淆淬淞淌淨淒淅淺淙淤淕淪淮渭湮渮渙湲湟渾渣湫渫湶湍渟湃渺湎渤滿渝游溂溪溘滉溷滓溽溯滄溲滔滕溏溥滂溟潁漑灌滬滸滾漿滲漱滯漲滌9dL漾漓滷澆潺潸澁澀潯潛濳潭澂潼潘澎澑濂潦澳澣澡澤澹濆澪濟濕濬濔濘濱濮濛瀉瀋濺瀑瀁瀏濾瀛瀚潴瀝瀘瀟瀰瀾瀲灑灣炙炒炯烱炬炸炳炮烟烋烝烙焉烽焜焙煥煕熈煦煢煌煖煬熏燻熄熕熨熬燗熹熾燒燉燔燎燠燬燧燵燼燹燿爍爐爛爨爭爬爰爲爻爼爿牀牆牋牘牴牾犂犁犇犒犖犢犧犹犲狃狆狄狎狒狢狠狡狹狷倏猗猊猜猖猝猴猯猩猥猾獎獏默獗獪獨獰獸獵獻獺珈玳珎玻珀珥珮珞璢琅瑯琥珸琲琺瑕琿瑟瑙瑁瑜瑩瑰瑣瑪瑶瑾璋璞璧瓊瓏瓔珱9`O瓠瓣瓧瓩瓮瓲瓰瓱瓸瓷甄甃甅甌甎甍甕甓甞甦甬甼畄畍畊畉畛畆畚畩畤畧畫畭畸當疆疇畴疊疉疂疔疚疝疥疣痂疳痃疵疽疸疼疱痍痊痒痙痣痞痾痿痼瘁痰痺痲痳瘋瘍瘉瘟瘧瘠瘡瘢瘤瘴瘰瘻癇癈癆癜癘癡癢癨癩癪癧癬癰癲癶癸發皀皃皈皋皎皖皓皙皚皰皴皸皹皺盂盍盖盒盞盡盥盧盪蘯盻眈眇眄眩眤眞眥眦眛眷眸睇睚睨睫睛睥睿睾睹瞎瞋瞑瞠瞞瞰瞶瞹瞿瞼瞽瞻矇矍矗矚矜矣矮矼砌砒礦砠礪硅碎硴碆硼碚碌碣碵碪碯磑磆磋磔碾碼磅磊磬9\R磧磚磽磴礇礒礑礙礬礫祀祠祗祟祚祕祓祺祿禊禝禧齋禪禮禳禹禺秉秕秧秬秡秣稈稍稘稙稠稟禀稱稻稾稷穃穗穉穡穢穩龝穰穹穽窈窗窕窘窖窩竈窰窶竅竄窿邃竇竊竍竏竕竓站竚竝竡竢竦竭竰笂笏笊笆笳笘笙笞笵笨笶筐筺笄筍笋筌筅筵筥筴筧筰筱筬筮箝箘箟箍箜箚箋箒箏筝箙篋篁篌篏箴篆篝篩簑簔篦篥籠簀簇簓篳篷簗簍篶簣簧簪簟簷簫簽籌籃籔籏籀籐籘籟籤籖籥籬籵粃粐粤粭粢粫粡粨粳粲粱粮粹粽糀糅糂糘糒糜糢鬻糯糲糴糶糺紆9XU紂紜紕紊絅絋紮紲紿紵絆絳絖絎絲絨絮絏絣經綉絛綏絽綛綺綮綣綵緇綽綫總綢綯緜綸綟綰緘緝緤緞緻緲緡縅縊縣縡縒縱縟縉縋縢繆繦縻縵縹繃縷縲縺繧繝繖繞繙繚繹繪繩繼繻纃緕繽辮繿纈纉續纒纐纓纔纖纎纛纜缸缺罅罌罍罎罐网罕罔罘罟罠罨罩罧罸羂羆羃羈羇羌羔羞羝羚羣羯羲羹羮羶羸譱翅翆翊翕翔翡翦翩翳翹飜耆耄耋耒耘耙耜耡耨耿耻聊聆聒聘聚聟聢聨聳聲聰聶聹聽聿肄肆肅肛肓肚肭冐肬胛胥胙胝胄胚胖脉胯胱脛脩脣脯腋9TX隋腆脾腓腑胼腱腮腥腦腴膃膈膊膀膂膠膕膤膣腟膓膩膰膵膾膸膽臀臂膺臉臍臑臙臘臈臚臟臠臧臺臻臾舁舂舅與舊舍舐舖舩舫舸舳艀艙艘艝艚艟艤艢艨艪艫舮艱艷艸艾芍芒芫芟芻芬苡苣苟苒苴苳苺莓范苻苹苞茆苜茉苙茵茴茖茲茱荀茹荐荅茯茫茗茘莅莚莪莟莢莖茣莎莇莊荼莵荳荵莠莉莨菴萓菫菎菽萃菘萋菁菷萇菠菲萍萢萠莽萸蔆菻葭萪萼蕚蒄葷葫蒭葮蒂葩葆萬葯葹萵蓊葢蒹蒿蒟蓙蓍蒻蓚蓐蓁蓆蓖蒡蔡蓿蓴蔗蔘蔬蔟蔕蔔蓼蕀蕣蕘蕈9P[蕁蘂蕋蕕薀薤薈薑薊薨蕭薔薛藪薇薜蕷蕾薐藉薺藏薹藐藕藝藥藜藹蘊蘓蘋藾藺蘆蘢蘚蘰蘿虍乕虔號虧虱蚓蚣蚩蚪蚋蚌蚶蚯蛄蛆蚰蛉蠣蚫蛔蛞蛩蛬蛟蛛蛯蜒蜆蜈蜀蜃蛻蜑蜉蜍蛹蜊蜴蜿蜷蜻蜥蜩蜚蝠蝟蝸蝌蝎蝴蝗蝨蝮蝙蝓蝣蝪蠅螢螟螂螯蟋螽蟀蟐雖螫蟄螳蟇蟆螻蟯蟲蟠蠏蠍蟾蟶蟷蠎蟒蠑蠖蠕蠢蠡蠱蠶蠹蠧蠻衄衂衒衙衞衢衫袁衾袞衵衽袵衲袂袗袒袮袙袢袍袤袰袿袱裃裄裔裘裙裝裹褂裼裴裨裲褄褌褊褓襃褞褥褪褫襁襄褻褶褸襌褝襠襞9L^襦襤襭襪襯襴襷襾覃覈覊覓覘覡覩覦覬覯覲覺覽覿觀觚觜觝觧觴觸訃訖訐訌訛訝訥訶詁詛詒詆詈詼詭詬詢誅誂誄誨誡誑誥誦誚誣諄諍諂諚諫諳諧諤諱謔諠諢諷諞諛謌謇謚諡謖謐謗謠謳鞫謦謫謾謨譁譌譏譎證譖譛譚譫譟譬譯譴譽讀讌讎讒讓讖讙讚谺豁谿豈豌豎豐豕豢豬豸豺貂貉貅貊貍貎貔豼貘戝貭貪貽貲貳貮貶賈賁賤賣賚賽賺賻贄贅贊贇贏贍贐齎贓賍贔贖赧赭赱赳趁趙跂趾趺跏跚跖跌跛跋跪跫跟跣跼踈踉跿踝踞踐踟蹂踵踰踴蹊9Ha蹇蹉蹌蹐蹈蹙蹤蹠踪蹣蹕蹶蹲蹼躁躇躅躄躋躊躓躑躔躙躪躡躬躰軆躱躾軅軈軋軛軣軼軻軫軾輊輅輕輒輙輓輜輟輛輌輦輳輻輹轅轂輾轌轉轆轎轗轜轢轣轤辜辟辣辭辯辷迚迥迢迪迯邇迴逅迹迺逑逕逡逍逞逖逋逧逶逵逹迸遏遐遑遒逎遉逾遖遘遞遨遯遶隨遲邂遽邁邀邊邉邏邨邯邱邵郢郤扈郛鄂鄒鄙鄲鄰酊酖酘酣酥酩酳酲醋醉醂醢醫醯醪醵醴醺釀釁釉釋釐釖釟釡釛釼釵釶鈞釿鈔鈬鈕鈑鉞鉗鉅鉉鉤鉈銕鈿鉋鉐銜銖銓銛鉚鋏銹銷鋩錏鋺鍄錮9Dd錙錢錚錣錺錵錻鍜鍠鍼鍮鍖鎰鎬鎭鎔鎹鏖鏗鏨鏥鏘鏃鏝鏐鏈鏤鐚鐔鐓鐃鐇鐐鐶鐫鐵鐡鐺鑁鑒鑄鑛鑠鑢鑞鑪鈩鑰鑵鑷鑽鑚鑼鑾钁鑿閂閇閊閔閖閘閙閠閨閧閭閼閻閹閾闊濶闃闍闌闕闔闖關闡闥闢阡阨阮阯陂陌陏陋陷陜陞陝陟陦陲陬隍隘隕隗險隧隱隲隰隴隶隸隹雎雋雉雍襍雜霍雕雹霄霆霈霓霎霑霏霖霙霤霪霰霹霽霾靄靆靈靂靉靜靠靤靦靨勒靫靱靹鞅靼鞁靺鞆鞋鞏鞐鞜鞨鞦鞣鞳鞴韃韆韈韋韜韭齏韲竟韶韵頏頌頸頤頡頷頽顆顏顋顫顯顰9@g顱顴顳颪颯颱颶飄飃飆飩飫餃餉餒餔餘餡餝餞餤餠餬餮餽餾饂饉饅饐饋饑饒饌饕馗馘馥馭馮馼駟駛駝駘駑駭駮駱駲駻駸騁騏騅駢騙騫騷驅驂驀驃騾驕驍驛驗驟驢驥驤驩驫驪骭骰骼髀髏髑髓體髞髟髢髣髦髯髫髮髴髱髷髻鬆鬘鬚鬟鬢鬣鬥鬧鬨鬩鬪鬮鬯鬲魄魃魏魍魎魑魘魴鮓鮃鮑鮖鮗鮟鮠鮨鮴鯀鯊鮹鯆鯏鯑鯒鯣鯢鯤鯔鯡鰺鯲鯱鯰鰕鰔鰉鰓鰌鰆鰈鰒鰊鰄鰮鰛鰥鰤鰡鰰鱇鰲鱆鰾鱚鱠鱧鱶鱸鳧鳬鳰鴉鴈鳫鴃鴆鴪鴦鶯鴣鴟鵄鴕鴒鵁鴿鴾鵆鵈9 mZk>` \umCjv{> ]^d_> VOqm1?4 A@CBs? DbFEGIH`?JV _FSPOcLNj_MKI[QR?(h \TSdfTUWXHYZ[9@G \Hb]d`a`^_{@H bcBdetgfiljmke@P msonnpqrntuv@ wy{xzA|Eq~MAA  }gvhGj[^|A| J}yA M}B| Zk\IB zUBP B C HeSlQC\ WfnCI @gC[RBhAfaFGaIHCD IgDJmEoMQLUniROPNKGWD TVSpXepa[_Zbfj\odY]^YDP ]qgchjmilkD nuovrtqwpcDks{~|z`D< }x@qJrDUyJE [@ZaE$ Ep srulE rtQA`H'F K|iFpX d,D$8lLPxdX, HttHT<H4hhsV lk^F EWF< ]Ibmnx/G _wEE\qG erE]BGx AtDCorTHIGFJBGN OKLMpUQGPSRcVWVXZ^[Y^7H(\ ]d_`acbefgbhLvijPkyH lmnopqrsCwMtquwvDH x zy|{}~FH HmcF|?I cpIP vsI t`rwxJ( GJt yepHzJ GJ8 {tK K Nf|OK ~uWDH@KH UK@ B}C~nJPQLD NFHRGKLOEEIFdOVTWLX mSUWX[YZM\a`L Abh]_^PAdcefL gsi|jklMd qrm\naopztws_M uvx`ua{^|}~gM IwMX XI%N ZgN IaNH yN OspXqt\-O UoOX TO JAO( A@CBDPEFG5P| vHeIJKK`LoMONePQRSTUwPV pWXYGZ[\PL ]vu`_P^LabcKidfP ehig]frmwllkFlbYj=Q  opn_FsaUvrwtuqNbQx  zxkyz_{~|@}Q dy uwTR  xcER  ]QR`  JR  L^ S  eLvnM\fMS Gd Go^qwS  S,  qNTp  zUT  HHT  xHT< @DABCJEGIFLRKMU| NQPOSRUTVWYXgZ[]^]U _\`aORb]cfedygU0 rihqkmjlpnPorySsAutx`U wv{zyQ|}~D#V hCJ_HeVH Iv}RqV4p H l0@P\P@P tD|p  |  X     $ h   4t(@ trATiNV xV^BkyKJI+W WM@mW` xYSsXsW AW Uz|Vy_3X, XuX dBjtX bnX Szg;Y eCLK}Y< NseI|Y K@BACdB^EDFZ BtKbGHLJICZ` OZMNLPZ VYXLQRUWZTSZ ^_`]\[dbcae [< fhgsiljkmopqtruwK[ v[ [ xMyzJ[{|}~t}{\ S\ hj\ ~@wAz\ G@KuB] YWGJ_d[] kIP] rvxC] f!^ BCc^ {azjop^8 z{^@BA^ CDEF)_  HGIHQJKZOk_0 LM{a`NOPRSUQTVWXY_ Z\[^a]_`b_ cde]nfgyh1`  wmljkiwnopqsrxs`d tvRuxyz`} |~{`  [9a\  E{a  TSa  @Da@! LNAb! I~b! khVbH" Lc" PIc" c,# DCEL@ABQJFKc# HG{LMNIOSTRd# QWPUVYX[\]hZ^Qd($ _`adt$ bcdd$ efghki[jlmnpqoe$ sotuvwxzy{|}~Ye$% Cl@e% Ve% sf,&X$x4X4 0(|\ T x  8!!!@"""$### $l$$$%%%$&H&afP&f@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~X'd(@ABCp)DEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~|*ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~+@ABCDEFG,HIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~-./ghijklmnopqrstuvwxyz{|}~01@ABCDEFGHIJKLMNO2P34@ABCDEFGHIJKLMNOPQRS6TUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ 7ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~8@ABCDEFGHIJKLMNOPQRSTUVW$9XYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~0:<;[H<\]^_`abcdefghijklmnopqrstuvwxyz{|}~T=`>@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_l?`abcdefghijklmnopqrstuvwxyz{|}~x@A@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcBdefghijklmnopqrstuvwxyz{|}~CD fE\(h)t*+,-./012345789(:4;@<L=X>d?p@|ABCDEFg$F IgF gF s~BYabceilugF Iij{C|D^OPQRSTUVWXFGH`abcdefghijklmnopqrstuvwxym_nOQdGMobp` hpH QhxI PhJFF\GhHpIJ(Jh0J(i\Jw \JIi\J (ؠ`,l H'P'FTJdJlJtJ[i|J@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmmmmmmmmmmmnopqrstummmmmmmmvwxyz{|mmmmmmmmmmm}~mmmmmmmmmmm@   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWWWWWWWWXYZ[\]^_`abcdefghijklmnoWWWWWWWWpqrstuvwxyz{|}~WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW@  !"""""""""""""""#$%&'()*+,-./0123456789:;<=>?@ABC"""""""""""""DEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abc""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""@@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRST@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~@  !"#$%&'()*+,-./0123444444444444444444444444444444444444444444456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~@   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwx  !"#$%&'(   !"#$%&'()*+,-./012                    !"#$%&'()*+,-./0123456789:;<=>?@  !"#$%&'()*+,-./012345678  !"#$%&'()*+,-./0123456788889:;<8          !     !"#$    !                                  !"#$   !"#$%&'                         !"#       !"#$%&                                                                                                           !"     !"#$%&   !                                      !"    !"        !                         !                 !"#                                                              !      !                                                                                                                                                                                                           !"                                                                                      !"#$                                                                                                                                                                                                                                                        !"#                                               !"#$  !"#$%&'()                      !"#                                                   !                                                                                                           !"#$%&'()*+,-./0123456789:;<=    !  !"#$%&'()*+,-./0123456789:;<=>?  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!  ; ,I<\Id>'2.2.0/x86_64-linux/enc/trans/transdb.sonuȯELF> @6@8 @pp -- -  -- -  888$$PPP StdPPP Ptd$$QtdRtd-- - XXGNUayU-:98\K@  BE|1nqX b , F"(0 00 U X(0 __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeInit_transdbrb_declare_transcoderlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ui - - - - / / / / 0  0 HH)* HtH52* %3* hh% * D%* DH=* H) H9tH) Ht H=) H5) H)HHH?HHtHu) HtfD=) u+UH=R) Ht H=' Yde) ]wHHVH5TH=SH<H5@H=3H"H5 H=$HH5H=HH5H=HH5H=|HH5H=bHH5H=HHH5H=.HlH5H=cHH5PH=|HhH56H=iHNH5OH=H4H5<H=H1H50H=3HH5,H=xHH5H=^HH5H=DHH5H=*HH5fH=HH5H=H{H5zH=HaH5H=oHGH5PH=H-H5,H=HH5(H=tH#H5H=(ZH H5H=@HH5H=&HH5H= HH5H=HH5H=HH5\H=HH5H=;HH5>H=HH5H=pHH5H=6VHH5H=H=AH#H5.H=lH H5 H=RHH5H=8HH5H=HH5H=HH5H=HH5H=HH5H=}HH5jH=HH5 H=IHwH5 H=vhH]H5 H=4NHCH5 H=K4H)H5H=i HH5H=O HH5H=5 HH5H= HH5 H=HH5 H=HH5|H= ~HH5H= dHH5H= JH|H5 H=u0HbH5iH=e HHH5R H=HHBH58 H=@H(H5-H= HH5 H=H H5H= H H5 H= zH H5 H= `H H5 H= FH H5 H={ ,Hr H5h H= HX H5 H=G H> H54 H=q H$ H5^ H= H H5 H=H H H55 H= H H5 H= vH H5 H= \H H5 H= BH H5 H=w (Hn H5d H= HT H5 H=C H: H50 H= H H5 H= H H5 H={ H H5h H= H H5 H=S rH H5@ H= XH H5 H=+ >H H5 H=s $Hj H5` H= HP H5 H=? H6 H5, H= H H5 H= H H5H= H H5 H=H H5H= nH H5x H=TH H5H=c :H H5P H=o Hf H5\H=< HL H5) H=;H2 H5(H= H H5 H=H H5H= H H5 H=H H5H= jH H5 H=PH H5H= 6H| H5 H=kHb H5XH=y HH H5f H=7H. H5$H=R H H5? H=HH5H=+ HH5 H=HH5H= fHH5 H=LHH5H= 2HxH5 H=gH^H5TH= HDH5 H=3H*H5 H=w HH5d H=HH5H=J HH57 H=|HH5H= bHH5 H=HHH5H=.HtH5H=cHZH5PH=H@H5H=/H&H5H=H H5H=HH5H=iHH5VH=xHH5H=<^HH5)H=DHH5H=*HpH5H=_HVH5LH=H<H5H=+H"H5H=HH5H=HH5H=HH5H=tHH5H=gZHH5TH=@HH5|H=>&HlH5+H=[ HRH5HH=H8H5H='HH5H=HH5H=HH5H=HH5H=pHH5H=VHH5H=H4H5+H=#HH5H=HH5H=HH5H=HH5H=lHH5H=RHH5H=8HH5H=mH|H5ZH=wHtH5@H=pHZH5]H=H@H5 H=EH&H52H=H H5H=HH5H=hHH5H=NHH5H=4HH5pH=HH5VH=HpH5H=5HVH5HH=HHbig5UTF-8Big5CP950Big5-HKSCSCP951Big5-UAOchineseGB2312GB12345emojiUTF8-KDDIUTF8-DoCoMoUTF8-SoftBankemoji_iso2022_kddistateless-ISO-2022-JP-KDDIemoji_sjis_docomoUTF8-DOCOMOSJIS-DOCOMOemoji_sjis_kddiSJIS-KDDIemoji_sjis_softbankSJIS-SoftBankamp_escapexml_text_escapexml_attr_content_escapexml_attr_quotegb18030GB18030gbkGBKiso2022stateless-ISO-2022-JPEUC-JPcp51932CP50220CP50221CP51932japaneseShift_JISjapanese_euceucJP-msEUC-JIS-2004japanese_sjisWindows-31JkoreanEUC-KRCP949single_byteUS-ASCIIASCII-8BITISO-8859-1ISO-8859-2ISO-8859-3ISO-8859-4ISO-8859-5ISO-8859-6ISO-8859-7ISO-8859-8ISO-8859-9ISO-8859-10ISO-8859-11ISO-8859-13ISO-8859-14ISO-8859-15ISO-8859-16WINDOWS-874WINDOWS-1250WINDOWS-1251WINDOWS-1252WINDOWS-1253WINDOWS-1254WINDOWS-1255WINDOWS-1256WINDOWS-1257IBM437IBM775IBM737IBM852IBM855IBM857IBM860IBM861IBM862IBM863IBM865IBM866IBM869MACCROATIANMACCYRILLICMACGREEKMACICELANDMACROMANMACROMANIAMACTURKISHMACUKRAINEKOI8-UKOI8-RTIS-620CP850CP852CP855utf8_macUTF8-MACutf_16_32UTF-16BEUTF-16LEUTF-32BEUTF-32LEUTF-16UTF-32; <Ld,|zRx $0FJ w?:*3$"D \XHDGNU- x  8- - o`  0 0 oooo- GA$3a1E GA$3p10678GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realigntransdb.so-2.2.10-35.el8.x86_64.debugn)7zXZִF!t/]?Eh=ڊ2N.̈́%GwJbЖ(ݽbP B %d5ևGekYAC2_yWQ&}څ Q$9;Q%i@HSg\xYW6ضЪd*N2wwA6ctX_b^D-1eY[1Mt[BlpJ(;B?mlRBk;=:,颯 ۩1IМ{@1mكQ؃{ fIth(8xf!;Rp Aw܁H׋!ϛz,@9KQJoݺŊ+I8l ݮA7Apq.mLᱭF9r$HKOU,Y >8ڂ>)2.2.0/x86_64-linux/enc/trans/utf_16_32.sonuȯELF>P @7@8 @h!h! && &  -- -  888$$H!H!H! StdH!H!H! PtdQtdRtd&& & GNU~ri7g|#@  BE|qX d , F"(0 00 (0 U P__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeInit_utf_16_32rb_register_transcoderlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ui &  &  &  & @& H& X& h& @& &  & &  & ' @0' X' ' ' ' ' @' ' P'   (  (( 8( H( @p( ( P(  ( ( ( ( @8)  `) h) x) ) @) 0* * * (* @x* @* * * * @+ P@+ H+ &X+ h+ @+ @+ &+ + , @X, 0, , /, , @,   - /(- 8- H- @-  / / / / 0  0 HH# HtH5$ %$ hh%# D%# DH=# H# H9tHv# Ht H=# H5# H)HHH?HHtHE# HtfD=]# u+UH="# Ht H=> Yd5# ]wu-Vym ЃF?ȀAD<ƒtFV< ЃȀAF?ȀAV  Ѓ0V ЃȀAFV0 V ЃȀAF?ȀAV Ѓ@~<@ ؈F~@< ˆQF܈AFF ЈAf.AÐF? ЈAfD@ FVǍB Aff.@Fu,ym Ѓ?ȀAfD<ƒtFF< ЃȀA?ȀA@  Ѓ0 ЃȀAV0 V ЃȀAF?ȀAff.Ѓ@~<@ ؈AF~@< ˆF܈AFF ЈAf.AÐAF? ЈfD@ QFVǍB ff.@FutFu,V ЃF?ȀA<FV< ЃȀAF?ȀA@FV0 ЃȀAFV< ЃȀAF?ȀAV7x1fAAɃƒtHV ЈAFV ЈAFF? ЈAfAF ЈAFVǍB AgDAAF? ЈAff.FutFu, Ѓ?ȀAf<F< ЃȀA?ȀAfDFV0 ЃȀAF< ЃȀA?ȀAD7Ax1fAɃƒtHV ЈAFV ЈAFF? ЈAF ЈAFVǍB hfDAAF? Јff.@1fD<t <t1fDff.<tutI<u8~u.VJvuF(<HHHuL~u~u܀~u Ð>uVJvuFfDu~u~u~u <t <t1fDff.<t]t1<u%VJ(w H HfDftCu߀~u J(wH%H~u Ð?t"fHfA HfD?tfHHfHH= H= H=i H= H= H=e H= H=  xH=a lH= `H= TH=] HDHHUTF-8UTF-32UTF-16UTF-32LEUTF-32BEUTF-16LEUTF-16BE(0 <D LD \Td2lt|24   (G4<G<<L\G\\4DLTdlt|;( ( 84HH8\(pHHH$zRx $80FJ w?:*3$"D@ \ph d%$8<%LX`*t'HGNU & @j  @j,@jP  @jP @j @j0@j@@jP&@j@&4@j0/@j /@j { & & o`  0 0  ooooE-  GA$3a1  GA$3p1067 GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFY GA+GLIBCXX_ASSERTIONSutf_16_32.so-2.2.10-35.el8.x86_64.debug=no7zXZִF!t/]?Eh=ڊ2Na \Ӈ!L4ff^ * яQ%o#QF:_XklHw }9-IInM)ϝ˙])>GpGp7N F/pd{u5ׄ:v_YR WS6Iڎ{@vkOCՎvUۀҢbO AJ@M_K;qE97$Ȥ`܏ $!x(-8𷐧6l&Lݰ쭭aF=Ei-m:-\Aɝ^ki)?\-OA$oHE+H$vSJpnɰ֧-fGtٽe~ݤڭ[J)ܫc\CZDmZlAZTXNV.WPWՁIH  -!\vmʖQ513;5_7^2p $(%MPM^yơjQ5c2}to J(BZ~(Ibfi. !n,$gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 08oEo T^B 0h c 0n0 0 wP P }  H!H! & && & & & - - / / 0 0((0 (000`(0H p2,2t6+PK!12.2.0/x86_64-linux/enc/trans/emoji_sjis_docomo.sonuȯELF>@@8 @00 PP!P! !!  888$$ Std Ptdttt$$QtdRtdPP!P!GNUq#rɭ 22-@! BE|K>qX l , F"(!0!U $(!__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeInit_emoji_sjis_docomorb_register_transcoderlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ui P!X!``!`!!! ! S!  ! (!8! SH! !!!!! !HHa!HtH5b!%c!hh%=!D%5!DH=1!H*!H9tH!Ht H=!H5!H)HHH?HHtH!HtfD=!u+UH=!Ht H=!Yd!]wHH=a! H=!HHHUTF8-DOCOMOSJIS-DOCOMO 、。,.・:;?!゛゜´`¨^ ̄_ヽヾゝゞ〃仝々〆〇ー―‐/\~∥|…‥‘’“”()〔〕[]{}〈〉《》「」『』【】+-±×÷=≠<>≦≧∞∴♂♀°′″℃¥$¢£%#&*@§☆★○●◎◇◆□■△▲▽▼※〒→←↑↓〓 ∈∋⊆⊇⊂⊃∪∩∧∨¬⇒⇔∀∃∠⊥⌒∂∇≡≒≪≫√∽∝∵∫∬ʼn♯♭♪†‡¶◯ 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzぁあぃいぅうぇえぉおかがきぎくぐけげこごさざしじすずせぜそぞただちぢっつづてでとどなにぬねのはばぱひびぴふぶぷへべぺほぼぽまみむめもゃやゅゆょよらりるれろゎわゐゑをん\ァアィイゥウェエォオカガキギクグケゲコゴサザシジスズセゼソゾタダチヂッツヅテデトドナニヌネノハバパヒビピフブプヘベペホボポマミムメモャヤュユョヨラリルレロヮワヰヱヲンヴヵヶ ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩαβγδεζηθικλμνξοπρστυφχψω~АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ абвгдеёжзийклмнопрстуфхцчшщъыьэюя─│┌┐┘└├┬┤┴┼━┃┏┓┛┗┣┳┫┻╋┠┯┨┷┿┝┰┥┸╂= p①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩ ㍉㌔㌢㍍㌘㌧㌃㌶㍑㍗㌍㌦㌣㌫㍊㌻㎜㎝㎞㎎㎏㏄㎡㍻〝〟№㏍℡㊤㊥㊦㊧㊨㈱㈲㈹㍾㍽㍼≒≡∫∮∑√⊥∠∟⊿∵∩∪ 亜唖娃阿哀愛挨姶逢葵茜穐悪握渥旭葦芦鯵梓圧斡扱宛姐虻飴絢綾鮎或粟袷安庵按暗案闇鞍杏以伊位依偉囲夷委威尉惟意慰易椅為畏異移維緯胃萎衣謂違遺医井亥域育郁磯一壱溢逸稲茨芋鰯允印咽員因姻引飲淫胤蔭z 院陰隠韻吋右宇烏羽迂雨卯鵜窺丑碓臼渦嘘唄欝蔚鰻姥厩浦瓜閏噂云運雲荏餌叡営嬰影映曳栄永泳洩瑛盈穎頴英衛詠鋭液疫益駅悦謁越閲榎厭円園堰奄宴延怨掩援沿演炎焔煙燕猿縁艶苑薗遠鉛鴛塩於汚甥凹央奥往応押旺横欧殴王翁襖鴬鴎黄岡沖荻億屋憶臆桶牡乙俺卸恩温穏音下化仮何伽価佳加可嘉夏嫁家寡科暇果架歌河火珂禍禾稼箇花苛茄荷華菓蝦課嘩貨迦過霞蚊俄峨我牙画臥芽蛾賀雅餓駕介会解回塊壊廻快怪悔恢懐戒拐改9d 魁晦械海灰界皆絵芥蟹開階貝凱劾外咳害崖慨概涯碍蓋街該鎧骸浬馨蛙垣柿蛎鈎劃嚇各廓拡撹格核殻獲確穫覚角赫較郭閣隔革学岳楽額顎掛笠樫橿梶鰍潟割喝恰括活渇滑葛褐轄且鰹叶椛樺鞄株兜竃蒲釜鎌噛鴨栢茅萱粥刈苅瓦乾侃冠寒刊勘勧巻喚堪姦完官寛干幹患感慣憾換敢柑桓棺款歓汗漢澗潅環甘監看竿管簡緩缶翰肝艦莞観諌貫還鑑間閑関陥韓館舘丸含岸巌玩癌眼岩翫贋雁頑顔願企伎危喜器基奇嬉寄岐希幾忌揮机旗既期棋棄9`機帰毅気汽畿祈季稀紀徽規記貴起軌輝飢騎鬼亀偽儀妓宜戯技擬欺犠疑祇義蟻誼議掬菊鞠吉吃喫桔橘詰砧杵黍却客脚虐逆丘久仇休及吸宮弓急救朽求汲泣灸球究窮笈級糾給旧牛去居巨拒拠挙渠虚許距鋸漁禦魚亨享京供侠僑兇競共凶協匡卿叫喬境峡強彊怯恐恭挟教橋況狂狭矯胸脅興蕎郷鏡響饗驚仰凝尭暁業局曲極玉桐粁僅勤均巾錦斤欣欽琴禁禽筋緊芹菌衿襟謹近金吟銀九倶句区狗玖矩苦躯駆駈駒具愚虞喰空偶寓遇隅串櫛釧屑屈9\掘窟沓靴轡窪熊隈粂栗繰桑鍬勲君薫訓群軍郡卦袈祁係傾刑兄啓圭珪型契形径恵慶慧憩掲携敬景桂渓畦稽系経継繋罫茎荊蛍計詣警軽頚鶏芸迎鯨劇戟撃激隙桁傑欠決潔穴結血訣月件倹倦健兼券剣喧圏堅嫌建憲懸拳捲検権牽犬献研硯絹県肩見謙賢軒遣鍵険顕験鹸元原厳幻弦減源玄現絃舷言諺限乎個古呼固姑孤己庫弧戸故枯湖狐糊袴股胡菰虎誇跨鈷雇顧鼓五互伍午呉吾娯後御悟梧檎瑚碁語誤護醐乞鯉交佼侯候倖光公功効勾厚口向9X后喉坑垢好孔孝宏工巧巷幸広庚康弘恒慌抗拘控攻昂晃更杭校梗構江洪浩港溝甲皇硬稿糠紅紘絞綱耕考肯肱腔膏航荒行衡講貢購郊酵鉱砿鋼閤降項香高鴻剛劫号合壕拷濠豪轟麹克刻告国穀酷鵠黒獄漉腰甑忽惚骨狛込此頃今困坤墾婚恨懇昏昆根梱混痕紺艮魂些佐叉唆嵯左差査沙瑳砂詐鎖裟坐座挫債催再最哉塞妻宰彩才採栽歳済災采犀砕砦祭斎細菜裁載際剤在材罪財冴坂阪堺榊肴咲崎埼碕鷺作削咋搾昨朔柵窄策索錯桜鮭笹匙冊刷9T察拶撮擦札殺薩雑皐鯖捌錆鮫皿晒三傘参山惨撒散桟燦珊産算纂蚕讃賛酸餐斬暫残仕仔伺使刺司史嗣四士始姉姿子屍市師志思指支孜斯施旨枝止死氏獅祉私糸紙紫肢脂至視詞詩試誌諮資賜雌飼歯事似侍児字寺慈持時次滋治爾璽痔磁示而耳自蒔辞汐鹿式識鴫竺軸宍雫七叱執失嫉室悉湿漆疾質実蔀篠偲柴芝屡蕊縞舎写射捨赦斜煮社紗者謝車遮蛇邪借勺尺杓灼爵酌釈錫若寂弱惹主取守手朱殊狩珠種腫趣酒首儒受呪寿授樹綬需囚収周9P宗就州修愁拾洲秀秋終繍習臭舟蒐衆襲讐蹴輯週酋酬集醜什住充十従戎柔汁渋獣縦重銃叔夙宿淑祝縮粛塾熟出術述俊峻春瞬竣舜駿准循旬楯殉淳準潤盾純巡遵醇順処初所暑曙渚庶緒署書薯藷諸助叙女序徐恕鋤除傷償勝匠升召哨商唱嘗奨妾娼宵将小少尚庄床廠彰承抄招掌捷昇昌昭晶松梢樟樵沼消渉湘焼焦照症省硝礁祥称章笑粧紹肖菖蒋蕉衝裳訟証詔詳象賞醤鉦鍾鐘障鞘上丈丞乗冗剰城場壌嬢常情擾条杖浄状畳穣蒸譲醸錠嘱埴飾9L拭植殖燭織職色触食蝕辱尻伸信侵唇娠寝審心慎振新晋森榛浸深申疹真神秦紳臣芯薪親診身辛進針震人仁刃塵壬尋甚尽腎訊迅陣靭笥諏須酢図厨逗吹垂帥推水炊睡粋翠衰遂酔錐錘随瑞髄崇嵩数枢趨雛据杉椙菅頗雀裾澄摺寸世瀬畝是凄制勢姓征性成政整星晴棲栖正清牲生盛精聖声製西誠誓請逝醒青静斉税脆隻席惜戚斥昔析石積籍績脊責赤跡蹟碩切拙接摂折設窃節説雪絶舌蝉仙先千占宣専尖川戦扇撰栓栴泉浅洗染潜煎煽旋穿箭線9H 繊羨腺舛船薦詮賎践選遷銭銑閃鮮前善漸然全禅繕膳糎噌塑岨措曾曽楚狙疏疎礎祖租粗素組蘇訴阻遡鼠僧創双叢倉喪壮奏爽宋層匝惣想捜掃挿掻操早曹巣槍槽漕燥争痩相窓糟総綜聡草荘葬蒼藻装走送遭鎗霜騒像増憎臓蔵贈造促側則即息捉束測足速俗属賊族続卒袖其揃存孫尊損村遜他多太汰詑唾堕妥惰打柁舵楕陀駄騨体堆対耐岱帯待怠態戴替泰滞胎腿苔袋貸退逮隊黛鯛代台大第醍題鷹滝瀧卓啄宅托択拓沢濯琢託鐸濁諾茸凧蛸只9D#叩但達辰奪脱巽竪辿棚谷狸鱈樽誰丹単嘆坦担探旦歎淡湛炭短端箪綻耽胆蛋誕鍛団壇弾断暖檀段男談値知地弛恥智池痴稚置致蜘遅馳築畜竹筑蓄逐秩窒茶嫡着中仲宙忠抽昼柱注虫衷註酎鋳駐樗瀦猪苧著貯丁兆凋喋寵帖帳庁弔張彫徴懲挑暢朝潮牒町眺聴脹腸蝶調諜超跳銚長頂鳥勅捗直朕沈珍賃鎮陳津墜椎槌追鎚痛通塚栂掴槻佃漬柘辻蔦綴鍔椿潰坪壷嬬紬爪吊釣鶴亭低停偵剃貞呈堤定帝底庭廷弟悌抵挺提梯汀碇禎程締艇訂諦蹄逓9@&邸鄭釘鼎泥摘擢敵滴的笛適鏑溺哲徹撤轍迭鉄典填天展店添纏甜貼転顛点伝殿澱田電兎吐堵塗妬屠徒斗杜渡登菟賭途都鍍砥砺努度土奴怒倒党冬凍刀唐塔塘套宕島嶋悼投搭東桃梼棟盗淘湯涛灯燈当痘祷等答筒糖統到董蕩藤討謄豆踏逃透鐙陶頭騰闘働動同堂導憧撞洞瞳童胴萄道銅峠鴇匿得徳涜特督禿篤毒独読栃橡凸突椴届鳶苫寅酉瀞噸屯惇敦沌豚遁頓呑曇鈍奈那内乍凪薙謎灘捺鍋楢馴縄畷南楠軟難汝二尼弐迩匂賑肉虹廿日乳入9<)如尿韮任妊忍認濡禰祢寧葱猫熱年念捻撚燃粘乃廼之埜嚢悩濃納能脳膿農覗蚤巴把播覇杷波派琶破婆罵芭馬俳廃拝排敗杯盃牌背肺輩配倍培媒梅楳煤狽買売賠陪這蝿秤矧萩伯剥博拍柏泊白箔粕舶薄迫曝漠爆縛莫駁麦函箱硲箸肇筈櫨幡肌畑畠八鉢溌発醗髪伐罰抜筏閥鳩噺塙蛤隼伴判半反叛帆搬斑板氾汎版犯班畔繁般藩販範釆煩頒飯挽晩番盤磐蕃蛮匪卑否妃庇彼悲扉批披斐比泌疲皮碑秘緋罷肥被誹費避非飛樋簸備尾微枇毘琵眉美98,鼻柊稗匹疋髭彦膝菱肘弼必畢筆逼桧姫媛紐百謬俵彪標氷漂瓢票表評豹廟描病秒苗錨鋲蒜蛭鰭品彬斌浜瀕貧賓頻敏瓶不付埠夫婦富冨布府怖扶敷斧普浮父符腐膚芙譜負賦赴阜附侮撫武舞葡蕪部封楓風葺蕗伏副復幅服福腹複覆淵弗払沸仏物鮒分吻噴墳憤扮焚奮粉糞紛雰文聞丙併兵塀幣平弊柄並蔽閉陛米頁僻壁癖碧別瞥蔑箆偏変片篇編辺返遍便勉娩弁鞭保舗鋪圃捕歩甫補輔穂募墓慕戊暮母簿菩倣俸包呆報奉宝峰峯崩庖抱捧放方朋94/法泡烹砲縫胞芳萌蓬蜂褒訪豊邦鋒飽鳳鵬乏亡傍剖坊妨帽忘忙房暴望某棒冒紡肪膨謀貌貿鉾防吠頬北僕卜墨撲朴牧睦穆釦勃没殆堀幌奔本翻凡盆摩磨魔麻埋妹昧枚毎哩槙幕膜枕鮪柾鱒桝亦俣又抹末沫迄侭繭麿万慢満漫蔓味未魅巳箕岬密蜜湊蓑稔脈妙粍民眠務夢無牟矛霧鵡椋婿娘冥名命明盟迷銘鳴姪牝滅免棉綿緬面麺摸模茂妄孟毛猛盲網耗蒙儲木黙目杢勿餅尤戻籾貰問悶紋門匁也冶夜爺耶野弥矢厄役約薬訳躍靖柳薮鑓愉愈油癒902諭輸唯佑優勇友宥幽悠憂揖有柚湧涌猶猷由祐裕誘遊邑郵雄融夕予余与誉輿預傭幼妖容庸揚揺擁曜楊様洋溶熔用窯羊耀葉蓉要謡踊遥陽養慾抑欲沃浴翌翼淀羅螺裸来莱頼雷洛絡落酪乱卵嵐欄濫藍蘭覧利吏履李梨理璃痢裏裡里離陸律率立葎掠略劉流溜琉留硫粒隆竜龍侶慮旅虜了亮僚両凌寮料梁涼猟療瞭稜糧良諒遼量陵領力緑倫厘林淋燐琳臨輪隣鱗麟瑠塁涙累類令伶例冷励嶺怜玲礼苓鈴隷零霊麗齢暦歴列劣烈裂廉恋憐漣煉簾練聯9,5蓮連錬呂魯櫓炉賂路露労婁廊弄朗楼榔浪漏牢狼篭老聾蝋郎六麓禄肋録論倭和話歪賄脇惑枠鷲亙亘鰐詫藁蕨椀湾碗腕 弌丐丕个丱丶丼丿乂乖乘亂亅豫亊舒弍于亞亟亠亢亰亳亶从仍仄仆仂仗仞仭仟价伉佚估佛佝佗佇佶侈侏侘佻佩佰侑佯來侖儘俔俟俎俘俛俑俚俐俤俥倚倨倔倪倥倅伜俶倡倩倬俾俯們倆偃假會偕偐偈做偖偬偸傀傚傅傴傲(8僉僊傳僂僖僞僥僭僣僮價僵儉儁儂儖儕儔儚儡儺儷儼儻儿兀兒兌兔兢竸兩兪兮冀冂囘册冉冏冑冓冕冖冤冦冢冩冪冫决冱冲冰况冽凅凉凛几處凩凭凰凵凾刄刋刔刎刧刪刮刳刹剏剄剋剌剞剔剪剴剩剳剿剽劍劔劒剱劈劑辨辧劬劭劼劵勁勍勗勞勣勦飭勠勳勵勸勹匆匈甸匍匐匏匕匚匣匯匱匳匸區卆卅丗卉卍凖卞卩卮夘卻卷厂厖厠厦厥厮厰厶參簒雙叟曼燮叮叨叭叺吁吽呀听吭吼吮吶吩吝呎咏呵咎呟呱呷呰咒呻咀呶咄咐咆哇咢咸咥咬哄哈咨9|:咫哂咤咾咼哘哥哦唏唔哽哮哭哺哢唹啀啣啌售啜啅啖啗唸唳啝喙喀咯喊喟啻啾喘喞單啼喃喩喇喨嗚嗅嗟嗄嗜嗤嗔嘔嗷嘖嗾嗽嘛嗹噎噐營嘴嘶嘲嘸噫噤嘯噬噪嚆嚀嚊嚠嚔嚏嚥嚮嚶嚴囂嚼囁囃囀囈囎囑囓囗囮囹圀囿圄圉圈國圍圓團圖嗇圜圦圷圸坎圻址坏坩埀垈坡坿垉垓垠垳垤垪垰埃埆埔埒埓堊埖埣堋堙堝塲堡塢塋塰毀塒堽塹墅墹墟墫墺壞墻墸墮壅壓壑壗壙壘壥壜壤壟壯壺壹壻壼壽夂夊夐夛梦夥夬夭夲夸夾竒奕奐奎奚奘奢奠奧奬奩9x=奸妁妝佞侫妣妲姆姨姜妍姙姚娥娟娑娜娉娚婀婬婉娵娶婢婪媚媼媾嫋嫂媽嫣嫗嫦嫩嫖嫺嫻嬌嬋嬖嬲嫐嬪嬶嬾孃孅孀孑孕孚孛孥孩孰孳孵學斈孺宀它宦宸寃寇寉寔寐寤實寢寞寥寫寰寶寳尅將專對尓尠尢尨尸尹屁屆屎屓屐屏孱屬屮乢屶屹岌岑岔妛岫岻岶岼岷峅岾峇峙峩峽峺峭嶌峪崋崕崗嵜崟崛崑崔崢崚崙崘嵌嵒嵎嵋嵬嵳嵶嶇嶄嶂嶢嶝嶬嶮嶽嶐嶷嶼巉巍巓巒巖巛巫已巵帋帚帙帑帛帶帷幄幃幀幎幗幔幟幢幤幇幵并幺麼广庠廁廂廈廐廏9t@廖廣廝廚廛廢廡廨廩廬廱廳廰廴廸廾弃弉彝彜弋弑弖弩弭弸彁彈彌彎弯彑彖彗彙彡彭彳彷徃徂彿徊很徑徇從徙徘徠徨徭徼忖忻忤忸忱忝悳忿怡恠怙怐怩怎怱怛怕怫怦怏怺恚恁恪恷恟恊恆恍恣恃恤恂恬恫恙悁悍惧悃悚悄悛悖悗悒悧悋惡悸惠惓悴忰悽惆悵惘慍愕愆惶惷愀惴惺愃愡惻惱愍愎慇愾愨愧慊愿愼愬愴愽慂慄慳慷慘慙慚慫慴慯慥慱慟慝慓慵憙憖憇憬憔憚憊憑憫憮懌懊應懷懈懃懆憺懋罹懍懦懣懶懺懴懿懽懼懾戀戈戉戍戌戔戛9pC戞戡截戮戰戲戳扁扎扞扣扛扠扨扼抂抉找抒抓抖拔抃抔拗拑抻拏拿拆擔拈拜拌拊拂拇抛拉挌拮拱挧挂挈拯拵捐挾捍搜捏掖掎掀掫捶掣掏掉掟掵捫捩掾揩揀揆揣揉插揶揄搖搴搆搓搦搶攝搗搨搏摧摯摶摎攪撕撓撥撩撈撼據擒擅擇撻擘擂擱擧舉擠擡抬擣擯攬擶擴擲擺攀擽攘攜攅攤攣攫攴攵攷收攸畋效敖敕敍敘敞敝敲數斂斃變斛斟斫斷旃旆旁旄旌旒旛旙无旡旱杲昊昃旻杳昵昶昴昜晏晄晉晁晞晝晤晧晨晟晢晰暃暈暎暉暄暘暝曁暹曉暾暼9lF曄暸曖曚曠昿曦曩曰曵曷朏朖朞朦朧霸朮朿朶杁朸朷杆杞杠杙杣杤枉杰枩杼杪枌枋枦枡枅枷柯枴柬枳柩枸柤柞柝柢柮枹柎柆柧檜栞框栩桀桍栲桎梳栫桙档桷桿梟梏梭梔條梛梃檮梹桴梵梠梺椏梍桾椁棊椈棘椢椦棡椌棍棔棧棕椶椒椄棗棣椥棹棠棯椨椪椚椣椡棆楹楷楜楸楫楔楾楮椹楴椽楙椰楡楞楝榁楪榲榮槐榿槁槓榾槎寨槊槝榻槃榧樮榑榠榜榕榴槞槨樂樛槿權槹槲槧樅榱樞槭樔槫樊樒櫁樣樓橄樌橲樶橸橇橢橙橦橈樸樢檐檍檠檄檢檣9hI檗蘗檻櫃櫂檸檳檬櫞櫑櫟檪櫚櫪櫻欅蘖櫺欒欖鬱欟欸欷盜欹飮歇歃歉歐歙歔歛歟歡歸歹歿殀殄殃殍殘殕殞殤殪殫殯殲殱殳殷殼毆毋毓毟毬毫毳毯麾氈氓气氛氤氣汞汕汢汪沂沍沚沁沛汾汨汳沒沐泄泱泓沽泗泅泝沮沱沾沺泛泯泙泪洟衍洶洫洽洸洙洵洳洒洌浣涓浤浚浹浙涎涕濤涅淹渕渊涵淇淦涸淆淬淞淌淨淒淅淺淙淤淕淪淮渭湮渮渙湲湟渾渣湫渫湶湍渟湃渺湎渤滿渝游溂溪溘滉溷滓溽溯滄溲滔滕溏溥滂溟潁漑灌滬滸滾漿滲漱滯漲滌9dL漾漓滷澆潺潸澁澀潯潛濳潭澂潼潘澎澑濂潦澳澣澡澤澹濆澪濟濕濬濔濘濱濮濛瀉瀋濺瀑瀁瀏濾瀛瀚潴瀝瀘瀟瀰瀾瀲灑灣炙炒炯烱炬炸炳炮烟烋烝烙焉烽焜焙煥煕熈煦煢煌煖煬熏燻熄熕熨熬燗熹熾燒燉燔燎燠燬燧燵燼燹燿爍爐爛爨爭爬爰爲爻爼爿牀牆牋牘牴牾犂犁犇犒犖犢犧犹犲狃狆狄狎狒狢狠狡狹狷倏猗猊猜猖猝猴猯猩猥猾獎獏默獗獪獨獰獸獵獻獺珈玳珎玻珀珥珮珞璢琅瑯琥珸琲琺瑕琿瑟瑙瑁瑜瑩瑰瑣瑪瑶瑾璋璞璧瓊瓏瓔珱9`O瓠瓣瓧瓩瓮瓲瓰瓱瓸瓷甄甃甅甌甎甍甕甓甞甦甬甼畄畍畊畉畛畆畚畩畤畧畫畭畸當疆疇畴疊疉疂疔疚疝疥疣痂疳痃疵疽疸疼疱痍痊痒痙痣痞痾痿痼瘁痰痺痲痳瘋瘍瘉瘟瘧瘠瘡瘢瘤瘴瘰瘻癇癈癆癜癘癡癢癨癩癪癧癬癰癲癶癸發皀皃皈皋皎皖皓皙皚皰皴皸皹皺盂盍盖盒盞盡盥盧盪蘯盻眈眇眄眩眤眞眥眦眛眷眸睇睚睨睫睛睥睿睾睹瞎瞋瞑瞠瞞瞰瞶瞹瞿瞼瞽瞻矇矍矗矚矜矣矮矼砌砒礦砠礪硅碎硴碆硼碚碌碣碵碪碯磑磆磋磔碾碼磅磊磬9\R磧磚磽磴礇礒礑礙礬礫祀祠祗祟祚祕祓祺祿禊禝禧齋禪禮禳禹禺秉秕秧秬秡秣稈稍稘稙稠稟禀稱稻稾稷穃穗穉穡穢穩龝穰穹穽窈窗窕窘窖窩竈窰窶竅竄窿邃竇竊竍竏竕竓站竚竝竡竢竦竭竰笂笏笊笆笳笘笙笞笵笨笶筐筺笄筍笋筌筅筵筥筴筧筰筱筬筮箝箘箟箍箜箚箋箒箏筝箙篋篁篌篏箴篆篝篩簑簔篦篥籠簀簇簓篳篷簗簍篶簣簧簪簟簷簫簽籌籃籔籏籀籐籘籟籤籖籥籬籵粃粐粤粭粢粫粡粨粳粲粱粮粹粽糀糅糂糘糒糜糢鬻糯糲糴糶糺紆9XU紂紜紕紊絅絋紮紲紿紵絆絳絖絎絲絨絮絏絣經綉絛綏絽綛綺綮綣綵緇綽綫總綢綯緜綸綟綰緘緝緤緞緻緲緡縅縊縣縡縒縱縟縉縋縢繆繦縻縵縹繃縷縲縺繧繝繖繞繙繚繹繪繩繼繻纃緕繽辮繿纈纉續纒纐纓纔纖纎纛纜缸缺罅罌罍罎罐网罕罔罘罟罠罨罩罧罸羂羆羃羈羇羌羔羞羝羚羣羯羲羹羮羶羸譱翅翆翊翕翔翡翦翩翳翹飜耆耄耋耒耘耙耜耡耨耿耻聊聆聒聘聚聟聢聨聳聲聰聶聹聽聿肄肆肅肛肓肚肭冐肬胛胥胙胝胄胚胖脉胯胱脛脩脣脯腋9TX隋腆脾腓腑胼腱腮腥腦腴膃膈膊膀膂膠膕膤膣腟膓膩膰膵膾膸膽臀臂膺臉臍臑臙臘臈臚臟臠臧臺臻臾舁舂舅與舊舍舐舖舩舫舸舳艀艙艘艝艚艟艤艢艨艪艫舮艱艷艸艾芍芒芫芟芻芬苡苣苟苒苴苳苺莓范苻苹苞茆苜茉苙茵茴茖茲茱荀茹荐荅茯茫茗茘莅莚莪莟莢莖茣莎莇莊荼莵荳荵莠莉莨菴萓菫菎菽萃菘萋菁菷萇菠菲萍萢萠莽萸蔆菻葭萪萼蕚蒄葷葫蒭葮蒂葩葆萬葯葹萵蓊葢蒹蒿蒟蓙蓍蒻蓚蓐蓁蓆蓖蒡蔡蓿蓴蔗蔘蔬蔟蔕蔔蓼蕀蕣蕘蕈9P[蕁蘂蕋蕕薀薤薈薑薊薨蕭薔薛藪薇薜蕷蕾薐藉薺藏薹藐藕藝藥藜藹蘊蘓蘋藾藺蘆蘢蘚蘰蘿虍乕虔號虧虱蚓蚣蚩蚪蚋蚌蚶蚯蛄蛆蚰蛉蠣蚫蛔蛞蛩蛬蛟蛛蛯蜒蜆蜈蜀蜃蛻蜑蜉蜍蛹蜊蜴蜿蜷蜻蜥蜩蜚蝠蝟蝸蝌蝎蝴蝗蝨蝮蝙蝓蝣蝪蠅螢螟螂螯蟋螽蟀蟐雖螫蟄螳蟇蟆螻蟯蟲蟠蠏蠍蟾蟶蟷蠎蟒蠑蠖蠕蠢蠡蠱蠶蠹蠧蠻衄衂衒衙衞衢衫袁衾袞衵衽袵衲袂袗袒袮袙袢袍袤袰袿袱裃裄裔裘裙裝裹褂裼裴裨裲褄褌褊褓襃褞褥褪褫襁襄褻褶褸襌褝襠襞9L^襦襤襭襪襯襴襷襾覃覈覊覓覘覡覩覦覬覯覲覺覽覿觀觚觜觝觧觴觸訃訖訐訌訛訝訥訶詁詛詒詆詈詼詭詬詢誅誂誄誨誡誑誥誦誚誣諄諍諂諚諫諳諧諤諱謔諠諢諷諞諛謌謇謚諡謖謐謗謠謳鞫謦謫謾謨譁譌譏譎證譖譛譚譫譟譬譯譴譽讀讌讎讒讓讖讙讚谺豁谿豈豌豎豐豕豢豬豸豺貂貉貅貊貍貎貔豼貘戝貭貪貽貲貳貮貶賈賁賤賣賚賽賺賻贄贅贊贇贏贍贐齎贓賍贔贖赧赭赱赳趁趙跂趾趺跏跚跖跌跛跋跪跫跟跣跼踈踉跿踝踞踐踟蹂踵踰踴蹊9Ha蹇蹉蹌蹐蹈蹙蹤蹠踪蹣蹕蹶蹲蹼躁躇躅躄躋躊躓躑躔躙躪躡躬躰軆躱躾軅軈軋軛軣軼軻軫軾輊輅輕輒輙輓輜輟輛輌輦輳輻輹轅轂輾轌轉轆轎轗轜轢轣轤辜辟辣辭辯辷迚迥迢迪迯邇迴逅迹迺逑逕逡逍逞逖逋逧逶逵逹迸遏遐遑遒逎遉逾遖遘遞遨遯遶隨遲邂遽邁邀邊邉邏邨邯邱邵郢郤扈郛鄂鄒鄙鄲鄰酊酖酘酣酥酩酳酲醋醉醂醢醫醯醪醵醴醺釀釁釉釋釐釖釟釡釛釼釵釶鈞釿鈔鈬鈕鈑鉞鉗鉅鉉鉤鉈銕鈿鉋鉐銜銖銓銛鉚鋏銹銷鋩錏鋺鍄錮9Dd錙錢錚錣錺錵錻鍜鍠鍼鍮鍖鎰鎬鎭鎔鎹鏖鏗鏨鏥鏘鏃鏝鏐鏈鏤鐚鐔鐓鐃鐇鐐鐶鐫鐵鐡鐺鑁鑒鑄鑛鑠鑢鑞鑪鈩鑰鑵鑷鑽鑚鑼鑾钁鑿閂閇閊閔閖閘閙閠閨閧閭閼閻閹閾闊濶闃闍闌闕闔闖關闡闥闢阡阨阮阯陂陌陏陋陷陜陞陝陟陦陲陬隍隘隕隗險隧隱隲隰隴隶隸隹雎雋雉雍襍雜霍雕雹霄霆霈霓霎霑霏霖霙霤霪霰霹霽霾靄靆靈靂靉靜靠靤靦靨勒靫靱靹鞅靼鞁靺鞆鞋鞏鞐鞜鞨鞦鞣鞳鞴韃韆韈韋韜韭齏韲竟韶韵頏頌頸頤頡頷頽顆顏顋顫顯顰9@g顱顴顳颪颯颱颶飄飃飆飩飫餃餉餒餔餘餡餝餞餤餠餬餮餽餾饂饉饅饐饋饑饒饌饕馗馘馥馭馮馼駟駛駝駘駑駭駮駱駲駻駸騁騏騅駢騙騫騷驅驂驀驃騾驕驍驛驗驟驢驥驤驩驫驪骭骰骼髀髏髑髓體髞髟髢髣髦髯髫髮髴髱髷髻鬆鬘鬚鬟鬢鬣鬥鬧鬨鬩鬪鬮鬯鬲魄魃魏魍魎魑魘魴鮓鮃鮑鮖鮗鮟鮠鮨鮴鯀鯊鮹鯆鯏鯑鯒鯣鯢鯤鯔鯡鰺鯲鯱鯰鰕鰔鰉鰓鰌鰆鰈鰒鰊鰄鰮鰛鰥鰤鰡鰰鱇鰲鱆鰾鱚鱠鱧鱶鱸鳧鳬鳰鴉鴈鳫鴃鴆鴪鴦鶯鴣鴟鵄鴕鴒鵁鴿鴾鵆鵈9 mZk>` \umCjv{> ]^d_> VOqm1?4 A@CBs? DbFEGIH`?JV _FSPOcLNj_MKI[QR?(h \TSdfTUWXHYZ[9@G \Hb]d`a`^_{@H bcBdetgfiljmke@P msonnpqrntuv@ wy{xzA|Eq~MAA  }gvhGj[^|A| J}yA M}B| Zk\IB zUBP B C HeSlQC\ WfnCI @gC[RBhAfaFGaIHCD IgDJmEoMQLUniROPNKGWD TVSpXepa[_Zbfj\odY]^YDP ]qgchjmilkD nuovrtqwpcDks{~|z`D< }x@qJrDUyJE [@ZaE$ Ep srulE rtQA`H'F K|iFpX d,D$8lLPxdX, HttHT<H4hhsV lk^F EWF< ]Ibmnx/G _wEE\qG erE]BGx AtDCorTHIGFJBGN OKLMpUQGPSRcVWVXZ^[Y^7H(\ ]d_`acbefgbhLvijPkyH lmnopqrsCwMtquwvDH x zy|{}~FH HmcF|?I cpIP vsI t`rwxJ( GJt yepHzJ GJ8 {tK K Nf|OK ~uWDH@KH UK@ B}C~nJPQLD NFHRGKLOEEIFdOVTWLX mSUWX[YZM\a`L Abh]_^PAdcefL gsi|jklMd qrm\naopztws_M uvx`ua{^|}~gM IwMX XI%N ZgN IaNH yN OspXqt\-O UoOX TO JAO( A@CBDPEFG5P| vHeIJKK`LoMONePQRSTUwPV pWXYGZ[\PL ]vu`_P^LabcKidfP ehig]frmwllkFlbYj=Q  opn_FsaUvrwtuqNbQx  zxkyz_{~|@}Q dy uwTR  xcER  ]QR`  JR  L^ S  eLvnM\fMS Gd Go^qwS  S,  qNTp  zUT  HHT  xHT< @DABCJEGIFLRKMU| NQPOSRUTVWYXgZ[]^]U _\`aORb]cfedygU0 rihqkmjlpnPorySsAutx`U wv{zyQ|}~D#V hCJ_HeVH Iv}RqV4p H l0@P\P@P tD|p  |  X     $ h   4t(@ trATiNV xV^BkyKJI+W WM@mW` xYSsXsW AW Uz|Vy_3X, XuX dBjtX bnX Szg;Y eCLK}Y< NseI|Y K@BACdB^EDFZ BtKbGHLJICZ` OZMNLPZ VYXLQRUWZTSZ ^_`]\[dbcae [< fhgsiljkmopqtruwK[ v[ [ xMyzJ[{|}~t}{\ S\ hj\ ~@wAz\ G@KuB] YWGJ_d[] kIP] rvxC] f!^ BCc^ {azjop^8 z{^@BA^ CDEF)_  HGIHQJKZOk_0 LM{a`NOPRSUQTVWXY_ Z\[^a]_`b_ cde]nfgyh1`  wmljkiwnopqsrxs`d tvRuxyz`} |~{`  [9a\  E{a  TSa  @Da@! LNAb! I~b! khVbH" Lc" PIc" c,# DCEL@ABQJFKc# HG{LMNIOSTRd# QWPUVYX[\]hZ^Qd($ _`adt$ bcdd$ efghki[jlmnpqoe$ sotuvwxzy{|}~Ye$% Cl@e% Ve% sf,&X$x4X4 0(|\ T x  8!!!@"""$### $l$$$%%%$&H&afP&f@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~X'd(@ABCp)DEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~|*+@ABCDEFG,HIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~-.@ABCDEFGHIJK/LMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~01@ABCDEFGHIJKLMNO2PQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~34@ABCDEFGHIJKLMNOPQRS6TUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ 78@ABCDEFGHIJKLMNOPQRSTUVW$9XYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~0:<;@ABCDEFGHIJKLMNOPQRSTUVWXYZ[H<\]^_`abcdefghijklmnopqrstuvwxyz{|}~T=`>@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_l?`abcdefghijklmnopqrstuvwxyz{|}~x@A@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcBdefghijklmnopqrstuvwxyz{|}~CD fE\(h)t*+,-./012345789(:4;@<L=X>d?p@|ABCDEFg$F IgF gF s~BYabceilugF Iij{C|D^OPQRSTUVWXFGH`abcdefghijklmnopqrstuvwxym_nOQdGMobp` hpH QhxI PhJFF\GhHpIJ(Jh0J(i\Jw \JIi\J (ؠ`,l H'P'FTJdJlJtJ[i|J@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmmmmmmmmmmmnopqrstummmmmmmmvwxyz{|mmmmmmmmmmm}~mmmmmmmmmmm@   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWWWWWWWWXYZ[\]^_`abcdefghijklmnoWWWWWWWWpqrstuvwxyz{|}~WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW@  !"""""""""""""""#$%&'()*+,-./0123456789:;<=>?@ABC"""""""""""""DEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abc""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""@@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRST@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~@  !"#$%&'()*+,-./0123444444444444444444444444444444444444444444456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~@   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwx  !"#$%&'(   !"#$%&'()*+,-./012                    !"#$%&'()*+,-./0123456789:;<=>?@  !"#$%&'()*+,-./012345678  !"#$%&'()*+,-./0123456788889:;<8          !     !"#$    !                                  !"#$   !"#$%&'                         !"#       !"#$%&                                                                                                           !"     !"#$%&   !                                      !"    !"        !                         !                 !"#                                                              !      !                                                                                                                                                                                                           !"                                                                                      !"#$                                                                                                                                                                                                                                                        !"#                                               !"#$  !"#$%&'()                      !"#                                                   !                                                                                                           !"#$%&'()*+,-./0123456789:;<=    !  !"#$%&'()*+,-./0123456789:;<=>?  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!  ; ,I<\IdҲ2v^E@WOuzʭ8)'ő1 6kj+wRcTm8 tZq';F4rԥjkxVR۴6"‘lQ̨Y(9Y|ofs>ROO(bq rktgHV q''Y$g}LaBgΤ 6糪7n= !yQbz.ElQ«T7v' *[yُ|VK?U _W@}+H!6TP2 D7Y%MEV´N6V]Vf1_ʕoF@~FvK2elcIR#4d@a~oIU:((tOkݧd 2>}we*7#{Flz{; ϥSQ)lgKWVT*rxGX0;>f>34f`*ߑ0cc}-P}½Ui 꼀:ֱ3}ZsHK%6pǾ=H,C\f {) h7Epg?qس|-@ض@8 @`` PkPk!Pk!DD !!  888$$h`h`h` Stdh`h`h` Ptd___$$QtdRtdPkPk!Pk!DDGNUI&zx 4U rL`  BE|qXMe f , F"(!0!(!U .__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeInit_single_byterb_register_transcoderlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ui Pk!.Xk!P.`k!`k!k!3k!3k!k!5 l!3(l!38l!Hl!5l!3l!3l!l!5`m!3hm!3xm!m!5n!3n!3n!(n!5n!3n!3n!n!5@o!3Ho!3Xo!ho!5o!3o!3o!p!5p!3p!3p!p!5 q!3(q!38q!Hq!5q!3q!3q!q!5`r!3hr!3xr!r!5s!3s!3s!(s!5s!3s!3s!s!5@t!3Ht!3Xt!ht!5t!3t!3t!u!5u!3u!4u!u!5 v!4(v!38v!Hv!5v!3v!4v!v!5`w!4hw!3xw!w!5x!3x!4x!(x!5x!4x!3x!x!5@y!3Hy!#4Xy!hy!5y!#4y!3y!z!5z!3z!,4z!z!5 {!,4({!38{!H{!5{!3{!84{!{!5`|!84h|!3x|!|!5}!3}!D4}!(}!5}!D4}!3}!}!5@~!3H~!K4X~!h~!5~!K4~!3~!!5!3!R4!!5 !R4(!38!H!5!3Ȁ!Y4؀!!5`!Y4h!3x!!5!3!`4!(!5!`4!3!Ȃ!5@!3H!g4X!h!5!g4!3!!5!3!n4!!5 !n4(!38!H!5!3ȅ!u4؅!!5`!u4h!3x!!5!3!|4!(!5!|4!3!ȇ!5@!3H!4X!h!5!4!3!!5!3!4!!5 !4(!38!H!5!3Ȋ!4؊!!5`!4h!3x!!5!3!4!(!5!4!3!Ȍ!5@!3H!4X!h!5!4!3!!5!3!4!!5 !4(!38!H!5!3ȏ!4؏!!5`!4h!3x!!5!3!4!(!5!4!3!ȑ!5@!3H!4X!h!5!4!3!!5!3!4!!5 !4(!38!H!5!3Ȕ!4ؔ!!5`!4h!3x!!5!3!4!(!5!4!3!Ȗ!5@!3H!5X!h!5!5!3!!5!3!5!!5 !5(!38!H!5!3ș!5ؙ!!5`!5h!3x!!5!3!+5!(!5!+5!3!ț!5@!3H!75X!h!5!75!3!!5!3!C5!!5 !C5(!38!H!5!3Ȟ!O5؞!!5`!O5h!3x!!5!3![5!(!5![5!3!Ƞ!5@!3H!f5X!h!5!f5!3!!5!3!q5!!5 !q5(!38!H!5!3ȣ!|5أ!!5`!|5h!3x!!5!3!5!(!5!5!3!ȥ!5@!3H!5X!h!5!5!3!!5!3!5!!5 !5(!38!H!5!3Ȩ!5ب!!5`!5h!3x!!5!3!5!(!5!5!3!Ȫ!5@!3H!5X!h!5!5!3!!5!3!5!!5 !5(!38!H!5!!!!! !HHi!HtH5r!%s!hh%M!D%E!DH=A!H:!H9tH!Ht H=!H5 !H)HHH?HHtH!HtfD=́!u+UH=!Ht H=!H==!H=E=!H= $> %? V%? %8@ %X@h@;p@>??0@P@(0@8HPX&@€ …‘’“”•–— กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮฯะัาำิีึืฺุู฿เแโใไๅๆ็่้๊๋์ํ๎๏๐๑๒๓๔๕๖๗๘๙๚๛'@ (`B W(tB #BBBBlB.0B8HPX(B€ ‚„…†‡‰Š‹ŚŤŽŹ‘’“”•–—™š›śťžź ˇ˘Ł¤Ą¦§¨©Ş«¬­®Ż°±˛ł´µ¶·¸ąş»Ľ˝ľżŔÁÂĂÄĹĆÇČÉĘËĚÍÎĎĐŃŇÓÔŐÖ×ŘŮÚŰÜÝŢßŕáâăäĺćçčéęëěíîďđńňóôőö÷řůúűüýţ˙)C *E XE FE HF *lF +FFBFX+FPE4E@FdF(0F8HPX+FЂЃ‚ѓ„…†‡€‰Љ‹ЊЌЋЏђ‘’“”•–— ™љ›њќћџ ЎўЈ¤Ґ¦§Ё©Є«¬­®Ї°±Ііґµ¶·ё№є»јЅѕїАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюяE,G ,8I  I  J ,K #,K -@KF8KPKX+XK|IJ K$K(0lK8HPXW-tK€ ‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿN.K P/M "@N /lN /N8NdNxNN(0F8HPX0N€ ‚ƒ„…†‡‰‹‘’“”•–—™› ΅Ά£¤¥¦§¨©«¬­®―°±²³΄µ¶·ΈΉΊ»Ό½ΎΏΐΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩΪΫάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύώ 1N 2P  Q Q2QDRBFX+LRQxNQ\(0`R8HPX2hR€ ‚ƒ„…†‡ˆ‰Š‹Œ‘’“”•–—˜™š›œŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏĞÑÒÓÔÕÖרÙÚÛÜİŞßàáâãäåæçèéêëìíîïğñòóôõö÷øùúûüışÿ3R 4T8Nl%%TxNN(0F8HPX4T€ ‚ƒ„…†‡ˆ‰‹‘’“”•–—˜™› ¡¢£₪¥¦§¨©×«¬­®¯°±²³´µ¶·¸¹÷»¼½¾¿ְֱֲֳִֵֶַָֹֻּֽ־ֿ׀ׁׂ׃װױײ׳״אבגדהוזחטיךכלםמןנסעףפץצקרשת‎‏5U 6V  7HW K7W 74X 7XXXFX+X 8X S8 YY\Y8dY@W!xNNW,X(0X8tYHPX8|Y€پ‚ƒ„…†‡ˆ‰ٹ‹Œچژڈگ‘’“”•–—ک™ڑ›œ‌‍ں ،¢£¤¥¦§¨©ھ«¬­®¯°±²³´µ¶·¸¹؛»¼½¾؟ہءآأؤإئابةتثجحخدذرزسشصض×طظعغـفقكàلâمنهوçèéêëىيîïًٌٍَôُِ÷ّùْûü‎‏ےEY 9[ :T\ R:\:,K \ :D] ;] Z;] ;]D^BFX+L^L\\\xN\<]]]](0`^8HPX;h^€ ‚„…†‡‰‹¨ˇ¸‘’“”•–—™›¯˛ ¢£¤¦§Ø©Ŗ«¬­®Æ°±²³´µ¶·ø¹ŗ»¼½¾æĄĮĀĆÄÅĘĒČÉŹĖĢĶĪĻŠŃŅÓŌÕÖ×ŲŁŚŪÜŻŽßąįāćäåęēčéźėģķīļšńņóōõö÷ųłśūüżž˙<^ =`  aa4223,a(0F8HPX+4aÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñѪº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ Exa >c [>c /xd >d >d !?d c?d ?e ?$e )@De k@`e @e @ fdde?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~  !"#$%&'()*+,-./0123456789:;<=>?@   !"""#""$%""""&""'"""(""")"""""""         !   !"#$%&'()*+,-.&/0123456789:;<=&>?@A&BCDEFGHIJKLM&NOPQRSTUVWXYZ[\]^_&`abcdefghijk&lmnopqrstuvwxyz  !""#$""%&""""'""(")*+,"-.""""/""  !"#$%&'()*+,-./0     !"""#""$%""""&"'(""")"""*"""""""    !"#$%&       !""""""#"""""$""""""""""""""""""  !"#$%&'()*+,-./0123456789:;<=>?     !"""#"""""""$%"""""""""""""&"""'"()*+,-./0123456789:;<=>?@A"""""BCDEFGHIJKLMNOPQRST"""""""""""""  !"""#""""""""$""""""""""""""""""     !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQR/STUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~/  !""#""$%&'"()*""+,-."""/"""0"1""  !"#$%&'()*+,-./0123456789      !"#$%&'()*+,-./0123456789:;<=>?""""""""""""""""""""""""""""""""@ABCDEFGHIJKLMNOPQRSTUVWXYZ[""\]"  !"#$%&'()*"+,-./0123456789":;<="     !"#$%&'()*+,-./0123456789:;    !""""""#"""""$""%""""""&""""""""   !"#$%&'()*+,-.       !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxy\\\\  !"""""""""""""""""""""""""""""""  !"#$%&'()*+,-./0123456789:;<    !"#$%"&'"(")*+,"-./0"123"4"5678"            !""#"""$"%"""&'"""""""("""""""""  !"#$%&'()*+,-./0123456789:;    !"#$%&%'%()*+,-./012%345%678%%%9    !""""""#"$"%"&""'("""")*"""+""""  !"#$%&'()*+,-./          !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ab    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|              !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|  !     !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnop         !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz     !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghij      !"#$%                       !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstu        !"#$                  !"#$%&'()*+,-./012345         !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefgVhijklmnopqVrstuvwxyz{|}~       !"#$%&'          !"#$%&'(                !"#$%&  !"#$%&'()*+,-./012345   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwx        !"#$%&'()*+,-./0123456789                      !"#$%&'()*+,-./0123456789:            !"#$%&'()*+,-./0123456789:    !"#$%&'()*+,-./0123456  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuqvwxyz{|}~           !"#$%&'()*+,-./012345      !"#$%&'()*+,-./012      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX   ; <d|zRx $0FJ w?:*3$"D \PHGNU.P.`k!33xd5?133ud5?133sd5?133hqd5?133d5?133d5?133d5?133d5?133,d5?133d5?133 d5?133d5?133d5?133d5?133d5?133d5?134d5?143 d5?134d5?1430d5?134$d5?143Xd5?13#4Ld5?1#43d5?13,4d5?1,43ěd5?1384d5?1843xd5?13D4ld5?1D43hd5?13K4|d5?1K43d5?13R4d5?1R43pd5?13Y4dd5?1Y43d5?13`4܅d5?1`43d5?13g4܂d5?1g43d5?13n4d5?1n43~d5?13u4|d5?1u43zd5?13|4xd5?1|43ud5?134sd5?143hqd5?134\od5?143\md5?134Pkd5?143hd5?134fd5?143|cd5?134pad5?143`d5?134^d5?143[d5?134Yd5?143Vd5?134Ud5?143Td5?134Rd5?143Pd5?134Nd5?143Md5?134Kd5?1430Id5?134$Gd5?143Dd5?135Bd5?153XBd5?135@d5?153 >d5?135<d5?153:d5?13+5t8d5?1+535d5?13753d5?17530d5?13C5.d5?1C53,d5?13O5*d5?1O53'd5?13[5%d5?1[53t$d5?13f5h"d5?1f53h d5?13q5d5?1q53<d5?13|58d5?1|53d5?135(d5?153d5?135d5?153d5?135 d5?153| d5?135 d5?153d5?135d5?153d5?135d5?153d5?135d5?153d5?1} p- 3Pk!Xk!o`  !0@-h( oooo!--GA$3a1p-3 GA$3p1067.3GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realignsingle_byte.so-2.2.10-35.el8.x86_64.debugu\7zXZִF!t/]?Eh=ڊ2N!4v!͕d8|2XT zCB迌9YSژMf /|>ZA5as͘ E2xTq _m0sonuw_3j\5@ˌ8GO7tR,8! 6ᢅ|jBMnB<6cSagcܥ p&1/ڍPٟCk^t2R/riHGTx0xoO.:]{[jz!YS,,5AS q+T;%jDFRUvQ pPƋg9v>T_U9: >0A*5OTIf1RXF_5)>! `&OK0Αْrӳ,/S{W\hcIpH E'\?\Km%#;&cߖv1 v%j` fZ4G6J8 @@8 @      888$$ Std PtdPPP$$QtdRtd  GNUFw=-gLτpEʥQ BE|qX  ` , F"( 0 ( U ` __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeInit_emojirb_register_transcoderlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ui  P    @  H & X jh `  4 j `  > j ` & (  8 jH ` & ȸ 4 ظ j ` ` & h > x j ` 4    j( ` 4 & jȺ ` @ 4 H > X jh ` >  j ` > & j ` > ( 4 8 jH `      HH HtH5 % hh% D% DH= Hz H9tH& Ht H=Q H5J H)HHH?HHtH HtfD= u+UH=Ҵ Ht H= Yd ]wHH= H= H=Y H= H= H=U H= H= H=Q H= H= H=M HHHUTF-8UTF8-SoftBankUTF8-KDDIUTF8-DoCoMoBd0 H  L L t@D ( [PPP (HX`hp   X 'Q)\ P  (4X`h<☀☁l☔⛄⚡ ♈♉♊♋♌♍♎♏♐♑♒♓⚾⛳⚽Ⓜ✈⛽☕✂↗ ☎♥♠♦♣✌↘↖♿⛵↙✒0 ✉↩mQnoprQstuwQxy❤⤴♨r8 ⤵ ❢⁉‼〰✏⌚©™㊙♻®⚠↔↕  - |0   ( X`h  o@  Ѽ    <  ~      D  2l   @ S     H 2  [    Ѽ  !  c ` x   d8@ X   ` )  k D<  (XX`h   < ( q x H 7 y`   ? ' $ X ` Gl  ' A&8> &t> &>'>I'@= '><<<<=$=8=L=T===>0>l>>>>>>'> (D? Q(\?T?l?(t?(@=)@= Y)? )?)@= *?a*@= *@ *d@ '+@ 2i+ A +pA +A /,B q,B ,B,C 7-0C y-HC -C-D?????@ @\@@AhAAB|BBC(C@CCD$D?.,D D.D|< 2G'G E E8EhEEEEEE,FFFF4G`GGGGG'G2@=Q(HH@HXH(`H(xH)H2H 3H F3H3(I 3@I 4I N4J4K 4L 5L V5M5N 5xO,4P 6HPt^6lP 6LQ-QHHHH? I8IIJKLLMNpO,P@PdPDQQQ?.Q 4R.2T'URRRRR S S  !"#$%&!!!!!!'!()!!!*!!!!!!+!!!!!  !"#$%&'()*+,-.   !"#$%&'()*+ ,-./0123 4 56789    !"#$%&'()*+,-./0123456789:;<     ! " # $% &    !"#$%&    !"#$%&'()*         #⃣1⃣2⃣3⃣4⃣5⃣6⃣7⃣8⃣9⃣0⃣      !"#$%&'()*+,-./0123456   !"""#   !""#        !"#$%&'()*+                       !"#$%&'()*+,-,./01234   !"#$%&'()*)+,-     !"#$%%%           !"#$%&'''      !"#$%&'()*+,-./01234 56789:;  !"#$%&'()*+,-./01234  !"#$%&'()*+,-.-.---.//01      !"#$%&'()  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!  !"#$%&'()*+,-./0123456789:;<=>?@  !"#$%&'()*+,-./0123456789:;*<***  !"#$%&'()     !"#$%&'()*+,-./0123456789:;<=>?  !"#$%&'()*+,-./0.............111      !"#$%&'()*+,-./01232456789  !"#$%&'()*+,-./01234356789   !"#$%&'()*+,-./01234555             !"#$%&'()*+,---  🇯🇵    🇺🇸   🇪🇸🇷🇺🇫🇷 🇩🇪🇮🇹🇺🇰🇨🇳🇰🇷          !"#$%&      !!!!!!!!!!!!"# $%%& ' ()*+,-               !   !              ! " # $        !"############$%&'(()*+,-./012   !"#$%&''()*+ ,-./0123456 789:;<   !"#$%&'()*+,-./0123456789:    !"#$%&'(()*+,-./01234/56789:;<=>   !"#$%&'()*+,-./0123456789:;<=>?    ! "#$%&'()*+,-./01234        !                                                                 !   !"#$%&'()*+,-./0123456789:   !"#$%&'()*+,-./012    !"#$%&#'()*   !"#$#$%&'()*+,-./01234567  !"#$%&'()*+,-./01**2345678  !"##$%&'()*+,,*,-./01,23,4567,,,   !"##$#%&'()*+,   !!!!!"#$%&'()*+,-./012345!                       !"""#$     !" #$%& ' $ ()       !"#  !"#$%&'()*+,-./0123  !"##$%&'()*))((+,-.//0           !!!!!   "#$%%%&'(!    ;$c@0chdzRx $b0FJ w?:*3$"Db \cHGNUP  & ]j<`  4 Rj<`  > Dj<` & d<j<` & 4 9j<` & > 1j<` 4 -j<` 4 & 'j<` 4 > 4j<` > 8 j<` > & dj<` > 4 j<` w (   o`   0 ( oooo3 ` p GA$3a1( GA$3p1067` GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realignemoji.so-2.2.10-35.el8.x86_64.debug*4Q7zXZִF!t/]?Eh=ڊ2NHC. )I Q{Hb&9~vTf2QeґY $^*b>Djm'=N JYCy(-*B2$r$yrJ;[1t oആ:vB0S,"hy@T:r5),#װH!::i6a7'* !5,­׌$Sっ0?bTk[cH.E*^|H0]5`%}foTlJS^QT*7X6-v.L*9T$`N<0vHyC.3.:]>:ӏJf"?MD8=nQ&[n)F٦XSO-m2xɎ=1N{RdppB4PތM.K{0[vZR 5E3<`lGp6t!o6jE/Ћ]ANpwƃK (?l%Wn*plRe\=n%[o˭Y,=2ꈅ̣ ص!#rx-lx:)}Oa+?k>5%wT;ɽfWd61xGM{{gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 08oEo T(^B 0h( ( cP P 0n w \}  0 PP$xxt        (( (0`(  (HH+PK!QK#2.2.0/x86_64-linux/enc/trans/gbk.sonuȯELF>@@8 @ PP"P" ""  888$$ Std Ptd$$QtdRtdPP"P"GNUg#{:FpbU P  BE|͸UqX ^ , F"("0"U $("__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeInit_gbkrb_register_transcoderlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ui P"X"P`"`""""" "("8"H"""""" "HHq"HtH5r"%s"hh%M"D%E"DH=A"H:"H9tH"Ht H="H5 "H)HHH?HHtH"HtfD="u+UH="Ht H="Yd"]wHH=q" H="HHHUTF-8GBK丂丄丅丆丏丒丗丟丠両丣並丩丮丯丱丳丵丷丼乀乁乂乄乆乊乑乕乗乚乛乢乣乤乥乧乨乪乫乬乭乮乯乲乴乵乶乷乸乹乺乻乼乽乿亀亁亂亃亄亅亇亊亐亖亗亙亜亝亞亣亪亯亰亱亴亶亷亸亹亼亽亾仈仌仏仐仒仚仛仜仠仢仦仧仩仭仮仯仱仴仸仹仺仼仾伀伂伃伄伅伆伇伈伋伌伒伓伔伕伖伜伝伡伣伨伩伬伭伮伱伳伵伷伹伻伾伿佀佁佂佄佅佇佈佉佊佋佌佒佔佖佡佢佦佨佪佫佭佮佱佲併佷佸佹佺佽侀侁侂侅來侇侊侌侎侐侒侓侕侖侘侙侚侜侞侟価侢侤侫侭侰侱侲侳侴侶侷侸侹侺侻侼侽侾俀俁係俆俇俈俉俋俌俍俒俓俔俕俖俙俛俠俢俤俥俧俫俬俰俲俴俵俶俷俹俻俼俽俿倀倁倂倃倄倅倆倇倈倉倊個倎倐們倓倕倖倗倛倝倞倠倢倣値倧倫倯倰倱倲倳倴倵倶倷倸倹倻倽倿偀偁偂偄偅偆偉偊偋偍偐偑偒偓偔偖偗偘偙偛偝偞偟偠偡偢偣偤偦偧偨偩偪偫偭偮偯偰偱偲偳側偵偸偹偺偼偽傁傂傃傄傆傇傉傊傋傌傎傏傐傑傒傓傔傕傖傗傘備傚傛傜傝傞傟傠傡傢傤傦傪傫傭傮傯傰傱傳傴債傶傷傸傹傼傽傾傿僀僁僂僃僄僅僆僇僈僉僊僋僌働僎僐僑僒僓僔僕僗僘僙僛僜僝僞僟僠僡僢僣僤僥僨僩僪僫僯僰僱僲僴僶僷僸價僺僼僽僾僿儀儁儂儃億儅儈儉儊儌儍儎儏儐儑儓儔儕儖儗儘儙儚儛儜儝儞償儠儢儣儤儥儦儧儨儩優儫儬儭儮儯儰儱儲儳儴儵儶儷儸儹儺儻儼儽儾兂兇兊兌兎兏児兒兓兗兘兙兛兝兞兟兠兡兣兤兦內兩兪兯兲兺兾兿冃冄円冇冊冋冎冏冐冑冓冔冘冚冝冞冟冡冣冦冧冨冩冪冭冮冴冸冹冺冾冿凁凂凃凅凈凊凍凎凐凒凓凔凕凖凗凘凙凚凜凞凟凢凣凥処凧凨凩凪凬凮凱凲凴凷凾刄刅刉刋刌刏刐刓刔刕刜刞刟刡刢刣別刦刧刪刬刯刱刲刴刵刼刾剄剅剆則剈剉剋剎剏剒剓剕剗剘剙剚剛剝剟剠剢剣剤剦剨剫剬剭剮剰剱剳剴創剶剷剸剹剺剻剼剾劀劃劄劅劆劇劉劊劋劌劍劎劏劑劒劔劕劖劗劘劙劚劜劤劥劦劧劮劯劰労劵劶劷劸効劺劻劼劽勀勁勂勄勅勆勈勊勌勍勎勏勑勓勔動勗務勚勛勜勝勞勠勡勢勣勥勦勧勨勩勪勫勬勭勮勯勱勲勳勴勵勶勷勸勻勼勽匁匂匃匄匇匉匊匋匌匎 匑匒匓匔匘匛匜匞匟匢匤匥匧匨匩匫匬匭匯匰匱匲匳匴匵匶匷匸匼匽區卂卄卆卋卌卍卐協単卙卛卝卥卨卪卬卭卲卶卹卻卼卽卾厀厁厃厇厈厊厎厏厐厑厒厓厔厖厗厙厛厜厞厠厡厤厧厪厫厬厭厯厰厱厲厳厴厵厷厸厹厺厼厽厾叀參叄叅叆叇収叏叐叒叓叕叚叜叝叞叡叢叧叴叺叾叿吀吂吅吇吋吔吘吙吚吜吢吤吥吪吰吳吶吷吺吽吿呁呂呄呅呇呉呌呍呎呏呑呚呝呞呟呠呡呣呥呧呩呪呫呬呭呮呯呰呴呹呺呾呿咁咃咅咇咈咉咊咍咑咓咗咘咜咞咟咠咡 咢咥咮咰咲咵咶咷咹咺咼咾哃哅哊哋哖哘哛哠員哢哣哤哫哬哯哰哱哴哵哶哷哸哹哻哾唀唂唃唄唅唈唊唋唌唍唎唒唓唕唖唗唘唙唚唜唝唞唟唡唥唦唨唩唫唭唲唴唵唶唸唹唺唻唽啀啂啅啇啈啋啌啍啎問啑啒啓啔啗啘啙啚啛啝啞啟啠啢啣啨啩啫啯啰啱啲啳啴啹啺啽啿喅喆喌喍喎喐喒喓喕喖喗喚喛喞喠喡喢喣喤喥喦喨喩喪喫喬喭單喯喰喲喴営喸喺喼喿嗀嗁嗂嗃嗆嗇嗈嗊嗋嗎嗏嗐嗕嗗嗘嗙嗚嗛嗞嗠嗢嗧嗩嗭嗮嗰嗱嗴嗶嗸嗹嗺嗻嗼嗿嘂嘃嘄嘅嘆嘇嘊嘋嘍嘐嘑嘒嘓嘔嘕嘖嘗嘙嘚嘜嘝嘠嘡嘢嘥嘦嘨嘩嘪嘫嘮嘯嘰嘳嘵嘷嘸嘺嘼嘽嘾噀噁噂噃噄噅噆噇噈噉噊噋噏噐噑噒噓噕噖噚噛噝噞噟噠噡噣噥噦噧噭噮噯噰噲噳噴噵噷噸噹噺噽噾噿嚀嚁嚂嚃嚄嚇嚈嚉嚊嚋嚌嚍嚐嚑嚒嚔嚕嚖嚗嚘嚙嚚嚛嚜嚝嚞嚟嚠嚡嚢嚤嚥嚦嚧嚨嚩嚪嚫嚬嚭嚮嚰嚱嚲嚳嚴嚵嚶嚸嚹嚺嚻嚽嚾嚿囀囁囂囃囄囅囆囇囈囉囋囌囍囎囏囐囑囒囓囕囖囘囙囜団囥囦囧囨囩囪囬囮囯囲図囶囷囸囻囼圀圁圂圅圇國圌圍圎圏圐圑園圓圔圕圖圗團圙圚圛圝圞圠圡圢圤圥圦圧圫圱圲圴圵圶圷圸圼圽圿坁坃坄坅坆坈坉坋坒坓坔坕坖坘坙坢坣坥坧坬坮坰坱坲坴坵坸坹坺坽坾坿垀垁垇垈垉垊垍垎垏垐垑垔垕垖垗垘垙垚垜垝垞垟垥垨垪垬垯垰垱垳垵垶垷垹垺垻垼垽垾垿埀埁埄埅埆埇埈埉埊埌埍埐埑埓埖埗埛埜埞埡埢埣埥埦埧埨埩埪埫埬埮埰埱埲埳埵埶執埻埼埾埿堁堃堄堅堈堉堊堌堎堏堐堒堓堔堖堗堘堚堛堜堝堟堢堣堥堦堧堨堩堫堬堭堮堯報堲堳場堶堷堸堹堺堻堼堽堾堿塀塁塂塃塅塆塇塈塉塊塋塎塏塐塒塓塕塖塗塙塚塛塜塝塟塠塡塢塣塤塦塧塨塩塪塭塮塯塰塱塲塳塴塵塶塷塸塹塺塻塼塽塿墂墄墆墇墈墊墋墌墍墎墏墐墑墔墕墖増墘墛墜墝墠墡墢墣墤墥墦墧墪墫墬墭墮墯墰墱墲墳墴墵墶墷墸墹墺墻墽墾墿壀壂壃壄壆壇壈壉壊壋壌壍壎壏壐壒壓壔壖壗壘壙壚壛壜壝壞壟壠壡壢壣壥壦壧壨壩壪壭壯壱売壴壵壷壸壺壻壼壽壾壿夀夁夃夅夆夈変夊夋夌夎夐夑夒夓夗夘夛夝夞夠夡夢夣夦夨夬夰夲夳夵夶夻 夽夾夿奀奃奅奆奊奌奍奐奒奓奙奛奜奝奞奟奡奣奤奦奧奨奩奪奫奬奭奮奯奰奱奲奵奷奺奻奼奾奿妀妅妉妋妌妎妏妐妑妔妕妘妚妛妜妝妟妠妡妢妦妧妬妭妰妱妳妴妵妶妷妸妺妼妽妿姀姁姂姃姄姅姇姈姉姌姍姎姏姕姖姙姛姞姟姠姡姢姤姦姧姩姪姫姭姮姯姰姱姲姳姴姵姶姷姸姺姼姽姾娀娂娊娋娍娎娏娐娒娔娕娖娗娙娚娛娝娞娡娢娤娦娧娨娪娫娬娭娮娯娰娳娵娷娸娹娺娻娽娾娿婁婂婃婄婅婇婈婋婌婍婎婏婐婑婒婓婔婖婗婘婙婛婜婝婞婟婠$婡婣婤婥婦婨婩婫婬婭婮婯婰婱婲婳婸婹婻婼婽婾媀媁媂媃媄媅媆媇媈媉媊媋媌媍媎媏媐媑媓媔媕媖媗媘媙媜媝媞媟媠媡媢媣媤媥媦媧媨媩媫媬媭媮媯媰媱媴媶媷媹媺媻媼媽媿嫀嫃嫄嫅嫆嫇嫈嫊嫋嫍嫎嫏嫐嫑嫓嫕嫗嫙嫚嫛嫝嫞嫟嫢嫤嫥嫧嫨嫪嫬嫭嫮嫯嫰嫲嫳嫴嫵嫶嫷嫸嫹嫺嫻嫼嫽嫾嫿嬀嬁嬂嬃嬄嬅嬆嬇嬈嬊嬋嬌嬍嬎嬏嬐嬑嬒嬓嬔嬕嬘嬙嬚嬛嬜嬝嬞嬟嬠嬡嬢嬣嬤嬥嬦嬧嬨嬩嬪嬫嬬嬭嬮嬯嬰嬱嬳嬵嬶嬸嬹嬺嬻嬼嬽嬾嬿孁孂孃孄孅孆孇(孈孉孊孋孌孍孎孏孒孖孞孠孡孧孨孫孭孮孯孲孴孶孷學孹孻孼孾孿宂宆宊宍宎宐宑宒宔宖実宧宨宩宬宭宮宯宱宲宷宺宻宼寀寁寃寈寉寊寋寍寎寏寑寔寕寖寗寘寙寚寛寜寠寢寣實寧審寪寫寬寭寯寱寲寳寴寵寶寷寽対尀専尃尅將專尋尌對導尐尒尓尗尙尛尞尟尠尡尣尦尨尩尪尫尭尮尯尰尲尳尵尶尷屃屄屆屇屌屍屒屓屔屖屗屘屚屛屜屝屟屢層屧屨屩屪屫屬屭屰屲屳屴屵屶屷屸屻屼屽屾岀岃岄岅岆岇岉岊岋岎岏岒岓岕岝岞岟岠岡岤岥岦岧岨,!岪岮岯岰岲岴岶岹岺岻岼岾峀峂峃峅峆峇峈峉峊峌峍峎峏峐峑峓峔峕峖峗峘峚峛峜峝峞峟峠峢峣峧峩峫峬峮峯峱峲峳峴峵島峷峸峹峺峼峽峾峿崀崁崄崅崈崉崊崋崌崍崏崐崑崒崓崕崗崘崙崚崜崝崟崠崡崢崣崥崨崪崫崬崯崰崱崲崳崵崶崷崸崹崺崻崼崿嵀嵁嵂嵃嵄嵅嵆嵈嵉嵍嵎嵏嵐嵑嵒嵓嵔嵕嵖嵗嵙嵚嵜嵞嵟嵠嵡嵢嵣嵤嵥嵦嵧嵨嵪嵭嵮嵰嵱嵲嵳嵵嵶嵷嵸嵹嵺嵻嵼嵽嵾嵿嶀嶁嶃嶄嶅嶆嶇嶈嶉嶊嶋嶌嶍嶎嶏嶐嶑嶒嶓嶔嶕嶖嶗嶘嶚嶛嶜嶞嶟嶠0$嶡嶢嶣嶤嶥嶦嶧嶨嶩嶪嶫嶬嶭嶮嶯嶰嶱嶲嶳嶴嶵嶶嶸嶹嶺嶻嶼嶽嶾嶿巀巁巂巃巄巆巇巈巉巊巋巌巎巏巐巑巒巓巔巕巖巗巘巙巚巜巟巠巣巤巪巬巭巰巵巶巸巹巺巻巼巿帀帄帇帉帊帋帍帎帒帓帗帞帟帠帡帢帣帤帥帨帩帪師帬帯帰帲帳帴帵帶帹帺帾帿幀幁幃幆幇幈幉幊幋幍幎幏幐幑幒幓幖幗幘幙幚幜幝幟幠幣幤幥幦幧幨幩幪幫幬幭幮幯幰幱幵幷幹幾庁庂広庅庈庉庌庍庎庒庘庛庝庡庢庣庤庨庩庪庫庬庮庯庰庱庲庴庺庻庼庽庿廀廁廂廃廄廅4'廆廇廈廋廌廍廎廏廐廔廕廗廘廙廚廜廝廞廟廠廡廢廣廤廥廦廧廩廫廬廭廮廯廰廱廲廳廵廸廹廻廼廽弅弆弇弉弌弍弎弐弒弔弖弙弚弜弝弞弡弢弣弤弨弫弬弮弰弲弳弴張弶強弸弻弽弾弿彁彂彃彄彅彆彇彈彉彊彋彌彍彎彏彑彔彙彚彛彜彞彟彠彣彥彧彨彫彮彯彲彴彵彶彸彺彽彾彿徃徆徍徎徏徑従徔徖徚徛徝從徟徠徢徣徤徥徦徧復徫徬徯徰徱徲徳徴徶徸徹徺徻徾徿忀忁忂忇忈忊忋忎忓忔忕忚忛応忞忟忢忣忥忦忨忩忬忯忰忲忳忴忶忷忹忺忼怇8*怈怉怋怌怐怑怓怗怘怚怞怟怢怣怤怬怭怮怰怱怲怳怴怶怷怸怹怺怽怾恀恄恅恆恇恈恉恊恌恎恏恑恓恔恖恗恘恛恜恞恟恠恡恥恦恮恱恲恴恵恷恾悀悁悂悅悆悇悈悊悋悎悏悐悑悓悕悗悘悙悜悞悡悢悤悥悧悩悪悮悰悳悵悶悷悹悺悽悾悿惀惁惂惃惄惇惈惉惌惍惎惏惐惒惓惔惖惗惙惛惞惡惢惣惤惥惪惱惲惵惷惸惻惼惽惾惿愂愃愄愅愇愊愋愌愐愑愒愓愔愖愗愘愙愛愜愝愞愡愢愥愨愩愪愬愭愮愯愰愱愲愳愴愵愶愷愸愹愺愻愼愽愾慀慁慂慃慄慅慆<-慇慉態慍慏慐慒慓慔慖慗慘慙慚慛慜慞慟慠慡慣慤慥慦慩慪慫慬慭慮慯慱慲慳慴慶慸慹慺慻慼慽慾慿憀憁憂憃憄憅憆憇憈憉憊憌憍憏憐憑憒憓憕憖憗憘憙憚憛憜憞憟憠憡憢憣憤憥憦憪憫憭憮憯憰憱憲憳憴憵憶憸憹憺憻憼憽憿懀懁懃懄懅懆懇應懌懍懎懏懐懓懕懖懗懘懙懚懛懜懝懞懟懠懡懢懣懤懥懧懨懩懪懫懬懭懮懯懰懱懲懳懴懶懷懸懹懺懻懼懽懾戀戁戂戃戄戅戇戉戓戔戙戜戝戞戠戣戦戧戨戩戫戭戯戰戱戲戵戶戸戹戺戻戼扂扄扅扆扊@0扏扐払扖扗扙扚扜扝扞扟扠扡扢扤扥扨扱扲扴扵扷扸扺扻扽抁抂抃抅抆抇抈抋抌抍抎抏抐抔抙抜抝択抣抦抧抩抪抭抮抯抰抲抳抴抶抷抸抺抾拀拁拃拋拏拑拕拝拞拠拡拤拪拫拰拲拵拸拹拺拻挀挃挄挅挆挊挋挌挍挏挐挒挓挔挕挗挘挙挜挦挧挩挬挭挮挰挱挳挴挵挶挷挸挻挼挾挿捀捁捄捇捈捊捑捒捓捔捖捗捘捙捚捛捜捝捠捤捥捦捨捪捫捬捯捰捲捳捴捵捸捹捼捽捾捿掁掃掄掅掆掋掍掑掓掔掕掗掙掚掛掜掝掞掟採掤掦掫掯掱掲掵掶掹掻掽掿揀D3揁揂揃揅揇揈揊揋揌揑揓揔揕揗揘揙揚換揜揝揟揢揤揥揦揧揨揫揬揮揯揰揱揳揵揷揹揺揻揼揾搃搄搆搇搈搉搊損搎搑搒搕搖搗搘搙搚搝搟搢搣搤搥搧搨搩搫搮搯搰搱搲搳搵搶搷搸搹搻搼搾摀摂摃摉摋摌摍摎摏摐摑摓摕摖摗摙摚摛摜摝摟摠摡摢摣摤摥摦摨摪摫摬摮摯摰摱摲摳摴摵摶摷摻摼摽摾摿撀撁撃撆撈撉撊撋撌撍撎撏撐撓撔撗撘撚撛撜撝撟撠撡撢撣撥撦撧撨撪撫撯撱撲撳撴撶撹撻撽撾撿擁擃擄擆擇擈擉擊擋擌擏擑擓擔擕擖擙據H6擛擜擝擟擠擡擣擥擧擨擩擪擫擬擭擮擯擰擱擲擳擴擵擶擷擸擹擺擻擼擽擾擿攁攂攃攄攅攆攇攈攊攋攌攍攎攏攐攑攓攔攕攖攗攙攚攛攜攝攞攟攠攡攢攣攤攦攧攨攩攪攬攭攰攱攲攳攷攺攼攽敀敁敂敃敄敆敇敊敋敍敎敐敒敓敔敗敘敚敜敟敠敡敤敥敧敨敩敪敭敮敯敱敳敵敶數敹敺敻敼敽敾敿斀斁斂斃斄斅斆斈斉斊斍斎斏斒斔斕斖斘斚斝斞斠斢斣斦斨斪斬斮斱斲斳斴斵斶斷斸斺斻斾斿旀旂旇旈旉旊旍旐旑旓旔旕旘旙旚旛旜旝旞旟旡旣旤旪旫L9旲旳旴旵旸旹旻旼旽旾旿昁昄昅昇昈昉昋昍昐昑昒昖昗昘昚昛昜昞昡昢昣昤昦昩昪昫昬昮昰昲昳昷昸昹昺昻昽昿晀時晄晅晆晇晈晉晊晍晎晐晑晘晙晛晜晝晞晠晢晣晥晧晩晪晫晬晭晱晲晳晵晸晹晻晼晽晿暀暁暃暅暆暈暉暊暋暍暎暏暐暒暓暔暕暘暙暚暛暜暞暟暠暡暢暣暤暥暦暩暪暫暬暭暯暰暱暲暳暵暶暷暸暺暻暼暽暿曀曁曂曃曄曅曆曇曈曉曊曋曌曍曎曏曐曑曒曓曔曕曖曗曘曚曞曟曠曡曢曣曤曥曧曨曪曫曬曭曮曯曱曵曶書曺曻曽朁朂會P<朄朅朆朇朌朎朏朑朒朓朖朘朙朚朜朞朠朡朢朣朤朥朧朩朮朰朲朳朶朷朸朹朻朼朾朿杁杄杅杇杊杋杍杒杔杕杗杘杙杚杛杝杢杣杤杦杧杫杬杮東杴杶杸杹杺杻杽枀枂枃枅枆枈枊枌枍枎枏枑枒枓枔枖枙枛枟枠枡枤枦枩枬枮枱枲枴枹枺枻枼枽枾枿柀柂柅柆柇柈柉柊柋柌柍柎柕柖柗柛柟柡柣柤柦柧柨柪柫柭柮柲柵柶柷柸柹柺査柼柾栁栂栃栄栆栍栐栒栔栕栘栙栚栛栜栞栟栠栢栣栤栥栦栧栨栫栬栭栮栯栰栱栴栵栶栺栻栿桇桋桍桏桒桖桗桘桙桚桛T?桜桝桞桟桪桬桭桮桯桰桱桲桳桵桸桹桺桻桼桽桾桿梀梂梄梇梈梉梊梋梌梍梎梐梑梒梔梕梖梘梙梚梛梜條梞梟梠梡梣梤梥梩梪梫梬梮梱梲梴梶梷梸梹梺梻梼梽梾梿棁棃棄棅棆棇棈棊棌棎棏棐棑棓棔棖棗棙棛棜棝棞棟棡棢棤棥棦棧棨棩棪棫棬棭棯棲棳棴棶棷棸棻棽棾棿椀椂椃椄椆椇椈椉椊椌椏椑椓椔椕椖椗椘椙椚椛検椝椞椡椢椣椥椦椧椨椩椪椫椬椮椯椱椲椳椵椶椷椸椺椻椼椾楀楁楃楄楅楆楇楈楉楊楋楌楍楎楏楐楑楒楓楕楖楘楙楛楜楟XB楡楢楤楥楧楨楩楪楬業楯楰楲楳楴極楶楺楻楽楾楿榁榃榅榊榋榌榎榏榐榑榒榓榖榗榙榚榝榞榟榠榡榢榣榤榥榦榩榪榬榮榯榰榲榳榵榶榸榹榺榼榽榾榿槀槂槃槄槅槆槇槈槉構槍槏槑槒槓槕槖槗様槙槚槜槝槞槡槢槣槤槥槦槧槨槩槪槫槬槮槯槰槱槳槴槵槶槷槸槹槺槻槼槾樀樁樂樃樄樅樆樇樈樉樋樌樍樎樏樐樑樒樓樔樕樖標樚樛樜樝樞樠樢樣樤樥樦樧権樫樬樭樮樰樲樳樴樶樷樸樹樺樻樼樿橀橁橂橃橅橆橈橉橊橋橌橍橎橏橑橒橓橔橕橖橗橚\E橜橝橞機橠橢橣橤橦橧橨橩橪橫橬橭橮橯橰橲橳橴橵橶橷橸橺橻橽橾橿檁檂檃檅檆檇檈檉檊檋檌檍檏檒檓檔檕檖檘檙檚檛檜檝檞檟檡檢檣檤檥檦檧檨檪檭檮檯檰檱檲檳檴檵檶檷檸檹檺檻檼檽檾檿櫀櫁櫂櫃櫄櫅櫆櫇櫈櫉櫊櫋櫌櫍櫎櫏櫐櫑櫒櫓櫔櫕櫖櫗櫘櫙櫚櫛櫜櫝櫞櫟櫠櫡櫢櫣櫤櫥櫦櫧櫨櫩櫪櫫櫬櫭櫮櫯櫰櫱櫲櫳櫴櫵櫶櫷櫸櫹櫺櫻櫼櫽櫾櫿欀欁欂欃欄欅欆欇欈欉權欋欌欍欎欏欐欑欒欓欔欕欖欗欘欙欚欛欜欝欞欟欥欦欨欩欪欫欬欭欮`H欯欰欱欳欴欵欶欸欻欼欽欿歀歁歂歄歅歈歊歋歍歎歏歐歑歒歓歔歕歖歗歘歚歛歜歝歞歟歠歡歨歩歫歬歭歮歯歰歱歲歳歴歵歶歷歸歺歽歾歿殀殅殈殌殎殏殐殑殔殕殗殘殙殜殝殞殟殠殢殣殤殥殦殧殨殩殫殬殭殮殯殰殱殲殶殸殹殺殻殼殽殾毀毃毄毆毇毈毉毊毌毎毐毑毘毚毜毝毞毟毠毢毣毤毥毦毧毨毩毬毭毮毰毱毲毴毶毷毸毺毻毼毾毿氀氁氂氃氄氈氉氊氋氌氎氒気氜氝氞氠氣氥氫氬氭氱氳氶氷氹氺氻氼氾氿汃汄汅汈汋汌汍汎汏汑汒汓汖汘dK汙汚汢汣汥汦汧汫汬汭汮汯汱汳汵汷汸決汻汼汿沀沄沇沊沋沍沎沑沒沕沖沗沘沚沜沝沞沠沢沨沬沯沰沴沵沶沷沺泀況泂泃泆泇泈泋泍泎泏泑泒泘泙泚泜泝泟泤泦泧泩泬泭泲泴泹泿洀洂洃洅洆洈洉洊洍洏洐洑洓洔洕洖洘洜洝洟洠洡洢洣洤洦洨洩洬洭洯洰洴洶洷洸洺洿浀浂浄浉浌浐浕浖浗浘浛浝浟浡浢浤浥浧浨浫浬浭浰浱浲浳浵浶浹浺浻浽浾浿涀涁涃涄涆涇涊涋涍涏涐涒涖涗涘涙涚涜涢涥涬涭涰涱涳涴涶涷涹涺涻涼涽涾淁淂淃淈淉淊hN淍淎淏淐淒淓淔淕淗淚淛淜淟淢淣淥淧淨淩淪淭淯淰淲淴淵淶淸淺淽淾淿渀渁渂渃渄渆渇済渉渋渏渒渓渕渘渙減渜渞渟渢渦渧渨渪測渮渰渱渳渵渶渷渹渻渼渽渾渿湀湁湂湅湆湇湈湉湊湋湌湏湐湑湒湕湗湙湚湜湝湞湠湡湢湣湤湥湦湧湨湩湪湬湭湯湰湱湲湳湴湵湶湷湸湹湺湻湼湽満溁溂溄溇溈溊溋溌溍溎溑溒溓溔溕準溗溙溚溛溝溞溠溡溣溤溦溨溩溫溬溭溮溰溳溵溸溹溼溾溿滀滃滄滅滆滈滉滊滌滍滎滐滒滖滘滙滛滜滝滣滧滪滫滬滭滮滯lQ滰滱滲滳滵滶滷滸滺滻滼滽滾滿漀漁漃漄漅漇漈漊漋漌漍漎漐漑漒漖漗漘漙漚漛漜漝漞漟漡漢漣漥漦漧漨漬漮漰漲漴漵漷漸漹漺漻漼漽漿潀潁潂潃潄潅潈潉潊潌潎潏潐潑潒潓潔潕潖潗潙潚潛潝潟潠潡潣潤潥潧潨潩潪潫潬潯潰潱潳潵潶潷潹潻潽潾潿澀澁澂澃澅澆澇澊澋澏澐澑澒澓澔澕澖澗澘澙澚澛澝澞澟澠澢澣澤澥澦澨澩澪澫澬澭澮澯澰澱澲澴澵澷澸澺澻澼澽澾澿濁濃濄濅濆濇濈濊濋濌濍濎濏濐濓濔濕濖濗濘濙濚濛濜濝濟濢濣濤濥pT濦濧濨濩濪濫濬濭濰濱濲濳濴濵濶濷濸濹濺濻濼濽濾濿瀀瀁瀂瀃瀄瀅瀆瀇瀈瀉瀊瀋瀌瀍瀎瀏瀐瀒瀓瀔瀕瀖瀗瀘瀙瀜瀝瀞瀟瀠瀡瀢瀤瀥瀦瀧瀨瀩瀪瀫瀬瀭瀮瀯瀰瀱瀲瀳瀴瀶瀷瀸瀺瀻瀼瀽瀾瀿灀灁灂灃灄灅灆灇灈灉灊灋灍灎灐灑灒灓灔灕灖灗灘灙灚灛灜灝灟灠灡灢灣灤灥灦灧灨灩灪灮灱灲灳灴灷灹灺灻災炁炂炃炄炆炇炈炋炌炍炏炐炑炓炗炘炚炛炞炟炠炡炢炣炤炥炦炧炨炩炪炰炲炴炵炶為炾炿烄烅烆烇烉烋烌烍烎烏烐烑烒烓烔烕烖烗烚tW烜烝烞烠烡烢烣烥烪烮烰烱烲烳烴烵烶烸烺烻烼烾烿焀焁焂焃焄焅焆焇焈焋焌焍焎焏焑焒焔焗焛焜焝焞焟焠無焢焣焤焥焧焨焩焪焫焬焭焮焲焳焴焵焷焸焹焺焻焼焽焾焿煀煁煂煃煄煆煇煈煉煋煍煏煐煑煒煓煔煕煖煗煘煙煚煛煝煟煠煡煢煣煥煩煪煫煬煭煯煰煱煴煵煶煷煹煻煼煾煿熀熁熂熃熅熆熇熈熉熋熌熍熎熐熑熒熓熕熖熗熚熛熜熝熞熡熢熣熤熥熦熧熩熪熫熭熮熯熰熱熲熴熶熷熸熺熻熼熽熾熿燀燁燂燄燅燆燇燈燉燊燋燌燍燏燐燑燒燓xZ燖燗燘燙燚燛燜燝燞營燡燢燣燤燦燨燩燪燫燬燭燯燰燱燲燳燴燵燶燷燸燺燻燼燽燾燿爀爁爂爃爄爅爇爈爉爊爋爌爍爎爏爐爑爒爓爔爕爖爗爘爙爚爛爜爞爟爠爡爢爣爤爥爦爧爩爫爭爮爯爲爳爴爺爼爾牀牁牂牃牄牅牆牉牊牋牎牏牐牑牓牔牕牗牘牚牜牞牠牣牤牥牨牪牫牬牭牰牱牳牴牶牷牸牻牼牽犂犃犅犆犇犈犉犌犎犐犑犓犔犕犖犗犘犙犚犛犜犝犞犠犡犢犣犤犥犦犧犨犩犪犫犮犱犲犳犵犺犻犼犽犾犿狀狅狆狇狉狊狋狌狏狑狓狔狕狖狘狚狛|]  、。·ˉˇ¨〃々—~‖…‘’“”〔〕〈〉《》「」『』〖〗【】±×÷∶∧∨∑∏∪∩∈∷√⊥∥∠⌒⊙∫∮≡≌≈∽∝≠≮≯≤≥∞∵∴♂♀°′″℃$¤¢£‰§№☆★○●◎◇◆□■△▲※→←↑↓〓` ⅰⅱⅲⅳⅴⅵⅶⅷⅸⅹ⒈⒉⒊⒋⒌⒍⒎⒏⒐⒑⒒⒓⒔⒕⒖⒗⒘⒙⒚⒛⑴⑵⑶⑷⑸⑹⑺⑻⑼⑽⑾⑿⒀⒁⒂⒃⒄⒅⒆⒇①②③④⑤⑥⑦⑧⑨⑩㈠㈡㈢㈣㈤㈥㈦㈧㈨㈩ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫb !"#¥%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} ̄`c ぁあぃいぅうぇえぉおかがきぎくぐけげこごさざしじすずせぜそぞただちぢっつづてでとどなにぬねのはばぱひびぴふぶぷへべぺほぼぽまみむめもゃやゅゆょよらりるれろゎわゐゑをんCd ァアィイゥウェエォオカガキギクグケゲコゴサザシジスズセゼソゾタダチヂッツヅテデトドナニヌネノハバパヒビピフブプヘベペホボポマミムメモャヤュユョヨラリルレロヮワヰヱヲンヴヵヶDf ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩαβγδεζηθικλμνξοπρστυφχψω︵︶︹︺︿﹀︽︾﹁﹂﹃﹄︻︼︷︸︱︳︴g АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщъыьэюяhˊˋ˙–―‥‵℅℉↖↗↘↙∕∟∣≒≦≧⊿═║╒╓╔╕╖╗╘╙╚╛╜╝╞╟╠╡╢╣╤╥╦╧╨╩╪╫╬╭╮╯╰╱╲╳▁▂▃▄▅▆▇█▉▊▋▌▍▎▏▓▔▕▼▽◢◣◤◥☉⊕〒〝〞 āáǎàēéěèīíǐìōóǒòūúǔùǖǘǚǜüêɑńňɡㄅㄆㄇㄈㄉㄊㄋㄌㄍㄎㄏㄐㄑㄒㄓㄔㄕㄖㄗㄘㄙㄚㄛㄜㄝㄞㄟㄠㄡㄢㄣㄤㄥㄦㄧㄨㄩGi〡〢〣〤〥〦〧〨〩㊣㎎㎏㎜㎝㎞㎡㏄㏎㏑㏒㏕︰¬¦ ℡㈱‐ー゛゜ヽヾ〆ゝゞ﹉﹊﹋﹌﹍﹎﹏﹐﹑﹒﹔﹕﹖﹗﹙﹚﹛﹜﹝﹞﹟﹠﹡﹢﹣﹤﹥﹦﹨﹩﹪﹫〇─━│┃┄┅┆┇┈┉┊┋┌┍┎┏┐┑┒┓└┕┖┗┘┙┚┛├┝┞┟┠┡┢┣┤┥┦┧┨┩┪┫┬┭┮┯┰┱┲┳┴┵┶┷┸┹┺┻┼┽┾┿╀╁╂╃╄╅╆╇╈╉╊╋Pl狜狝狟狢狣狤狥狦狧狪狫狵狶狹狽狾狿猀猂猄猅猆猇猈猉猋猌猍猏猐猑猒猔猘猙猚猟猠猣猤猦猧猨猭猯猰猲猳猵猶猺猻猼猽獀獁獂獃獄獅獆獇獈獉獊獋獌獎獏獑獓獔獕獖獘獙獚獛獜獝獞獟獡獢獣獤獥獦獧獨獩獪獫獮獰獱 n獲獳獴獵獶獷獸獹獺獻獼獽獿玀玁玂玃玅玆玈玊玌玍玏玐玒玓玔玕玗玘玙玚玜玝玞玠玡玣玤玥玦玧玨玪玬玭玱玴玵玶玸玹玼玽玾玿珁珃珄珅珆珇珋珌珎珒珓珔珕珖珗珘珚珛珜珝珟珡珢珣珤珦珨珪珫珬珮珯珰珱珳珴珵珶珷 0p珸珹珺珻珼珽現珿琀琁琂琄琇琈琋琌琍琎琑琒琓琔琕琖琗琘琙琜琝琞琟琠琡琣琤琧琩琫琭琯琱琲琷琸琹琺琻琽琾琿瑀瑂瑃瑄瑅瑆瑇瑈瑉瑊瑋瑌瑍瑎瑏瑐瑑瑒瑓瑔瑖瑘瑝瑠瑡瑢瑣瑤瑥瑦瑧瑨瑩瑪瑫瑬瑮瑯瑱瑲瑳瑴瑵瑸瑹瑺 q瑻瑼瑽瑿璂璄璅璆璈璉璊璌璍璏璑璒璓璔璕璖璗璘璙璚璛璝璟璠璡璢璣璤璥璦璪璫璬璭璮璯環璱璲璳璴璵璶璷璸璹璻璼璽璾璿瓀瓁瓂瓃瓄瓅瓆瓇瓈瓉瓊瓋瓌瓍瓎瓏瓐瓑瓓瓔瓕瓖瓗瓘瓙瓚瓛瓝瓟瓡瓥瓧瓨瓩瓪瓫瓬瓭瓰瓱瓲 Ps瓳瓵瓸瓹瓺瓻瓼瓽瓾甀甁甂甃甅甆甇甈甉甊甋甌甎甐甒甔甕甖甗甛甝甞甠甡產産甤甦甧甪甮甴甶甹甼甽甿畁畂畃畄畆畇畉畊畍畐畑畒畓畕畖畗畘畝畞畟畠畡畢畣畤畧畨畩畫畬畭畮畯異畱畳畵當畷畺畻畼畽畾疀疁疂疄疅疇 t疈疉疊疌疍疎疐疓疕疘疛疜疞疢疦疧疨疩疪疭疶疷疺疻疿痀痁痆痋痌痎痏痐痑痓痗痙痚痜痝痟痠痡痥痩痬痭痮痯痲痳痵痶痷痸痺痻痽痾瘂瘄瘆瘇瘈瘉瘋瘍瘎瘏瘑瘒瘓瘔瘖瘚瘜瘝瘞瘡瘣瘧瘨瘬瘮瘯瘱瘲瘶瘷瘹瘺瘻瘽癁療癄 pv癅癆癇癈癉癊癋癎癏癐癑癒癓癕癗癘癙癚癛癝癟癠癡癢癤癥癦癧癨癩癪癬癭癮癰癱癲癳癴癵癶癷癹発發癿皀皁皃皅皉皊皌皍皏皐皒皔皕皗皘皚皛皜皝皞皟皠皡皢皣皥皦皧皨皩皪皫皬皭皯皰皳皵皶皷皸皹皺皻皼皽皾盀盁盃啊阿埃挨哎唉哀皑癌蔼矮艾碍爱隘鞍氨安俺按暗岸胺案肮昂盎凹敖熬翱袄傲奥懊澳芭捌扒叭吧笆八疤巴拔跋靶把耙坝霸罢爸白柏百摆佰败拜稗斑班搬扳般颁板版扮拌伴瓣半办绊邦帮梆榜膀绑棒磅蚌镑傍谤苞胞包褒剥x盄盇盉盋盌盓盕盙盚盜盝盞盠盡盢監盤盦盧盨盩盪盫盬盭盰盳盵盶盷盺盻盽盿眀眂眃眅眆眊県眎眏眐眑眒眓眔眕眖眗眘眛眜眝眞眡眣眤眥眧眪眫眬眮眰眱眲眳眴眹眻眽眾眿睂睄睅睆睈睉睊睋睌睍睎睏睒睓睔睕睖睗睘睙睜薄雹保堡饱宝抱报暴豹鲍爆杯碑悲卑北辈背贝钡倍狈备惫焙被奔苯本笨崩绷甭泵蹦迸逼鼻比鄙笔彼碧蓖蔽毕毙毖币庇痹闭敝弊必辟壁臂避陛鞭边编贬扁便变卞辨辩辫遍标彪膘表鳖憋别瘪彬斌濒滨宾摈兵冰柄丙秉饼炳{睝睞睟睠睤睧睩睪睭睮睯睰睱睲睳睴睵睶睷睸睺睻睼瞁瞂瞃瞆瞇瞈瞉瞊瞋瞏瞐瞓瞔瞕瞖瞗瞘瞙瞚瞛瞜瞝瞞瞡瞣瞤瞦瞨瞫瞭瞮瞯瞱瞲瞴瞶瞷瞸瞹瞺瞼瞾矀矁矂矃矄矅矆矇矈矉矊矋矌矎矏矐矑矒矓矔矕矖矘矙矚矝矞矟矠矡矤病并玻菠播拨钵波博勃搏铂箔伯帛舶脖膊渤泊驳捕卜哺补埠不布步簿部怖擦猜裁材才财睬踩采彩菜蔡餐参蚕残惭惨灿苍舱仓沧藏操糙槽曹草厕策侧册测层蹭插叉茬茶查碴搽察岔差诧拆柴豺搀掺蝉馋谗缠铲产阐颤昌猖~矦矨矪矯矰矱矲矴矵矷矹矺矻矼砃砄砅砆砇砈砊砋砎砏砐砓砕砙砛砞砠砡砢砤砨砪砫砮砯砱砲砳砵砶砽砿硁硂硃硄硆硈硉硊硋硍硏硑硓硔硘硙硚硛硜硞硟硠硡硢硣硤硥硦硧硨硩硯硰硱硲硳硴硵硶硸硹硺硻硽硾硿碀碁碂碃场尝常长偿肠厂敞畅唱倡超抄钞朝嘲潮巢吵炒车扯撤掣彻澈郴臣辰尘晨忱沉陈趁衬撑称城橙成呈乘程惩澄诚承逞骋秤吃痴持匙池迟弛驰耻齿侈尺赤翅斥炽充冲虫崇宠抽酬畴踌稠愁筹仇绸瞅丑臭初出橱厨躇锄雏滁除楚 碄碅碆碈碊碋碏碐碒碔碕碖碙碝碞碠碢碤碦碨碩碪碫碬碭碮碯碵碶碷碸確碻碼碽碿磀磂磃磄磆磇磈磌磍磎磏磑磒磓磖磗磘磚磛磜磝磞磟磠磡磢磣磤磥磦磧磩磪磫磭磮磯磰磱磳磵磶磸磹磻磼磽磾磿礀礂礃礄礆礇礈礉礊礋礌础储矗搐触处揣川穿椽传船喘串疮窗幢床闯创吹炊捶锤垂春椿醇唇淳纯蠢戳绰疵茨磁雌辞慈瓷词此刺赐次聪葱囱匆从丛凑粗醋簇促蹿篡窜摧崔催脆瘁粹淬翠村存寸磋撮搓措挫错搭达答瘩打大呆歹傣戴带殆代贷袋待逮礍礎礏礐礑礒礔礕礖礗礘礙礚礛礜礝礟礠礡礢礣礥礦礧礨礩礪礫礬礭礮礯礰礱礲礳礵礶礷礸礹礽礿祂祃祄祅祇祊祋祌祍祎祏祐祑祒祔祕祘祙祡祣祤祦祩祪祫祬祮祰祱祲祳祴祵祶祹祻祼祽祾祿禂禃禆禇禈禉禋禌禍禎禐禑禒怠耽担丹单郸掸胆旦氮但惮淡诞弹蛋当挡党荡档刀捣蹈倒岛祷导到稻悼道盗德得的蹬灯登等瞪凳邓堤低滴迪敌笛狄涤翟嫡抵底地蒂第帝弟递缔颠掂滇碘点典靛垫电佃甸店惦奠淀殿碉叼雕凋刁掉吊钓调跌爹碟蝶迭谍叠禓禔禕禖禗禘禙禛禜禝禞禟禠禡禢禣禤禥禦禨禩禪禫禬禭禮禯禰禱禲禴禵禶禷禸禼禿秂秄秅秇秈秊秌秎秏秐秓秔秖秗秙秚秛秜秝秞秠秡秢秥秨秪秬秮秱秲秳秴秵秶秷秹秺秼秾秿稁稄稅稇稈稉稊稌稏稐稑稒稓稕稖稘稙稛稜丁盯叮钉顶鼎锭定订丢东冬董懂动栋侗恫冻洞兜抖斗陡豆逗痘都督毒犊独读堵睹赌杜镀肚度渡妒端短锻段断缎堆兑队对墩吨蹲敦顿囤钝盾遁掇哆多夺垛躲朵跺舵剁惰堕蛾峨鹅俄额讹娥恶厄扼遏鄂饿恩而儿耳尔饵洱二稝稟稡稢稤稥稦稧稨稩稪稫稬稭種稯稰稱稲稴稵稶稸稺稾穀穁穂穃穄穅穇穈穉穊穋穌積穎穏穐穒穓穔穕穖穘穙穚穛穜穝穞穟穠穡穢穣穤穥穦穧穨穩穪穫穬穭穮穯穱穲穳穵穻穼穽穾窂窅窇窉窊窋窌窎窏窐窓窔窙窚窛窞窡窢贰发罚筏伐乏阀法珐藩帆番翻樊矾钒繁凡烦反返范贩犯饭泛坊芳方肪房防妨仿访纺放菲非啡飞肥匪诽吠肺废沸费芬酚吩氛分纷坟焚汾粉奋份忿愤粪丰封枫蜂峰锋风疯烽逢冯缝讽奉凤佛否夫敷肤孵扶拂辐幅氟符伏俘服窣窤窧窩窪窫窮窯窰窱窲窴窵窶窷窸窹窺窻窼窽窾竀竁竂竃竄竅竆竇竈竉竊竌竍竎竏竐竑竒竓竔竕竗竘竚竛竜竝竡竢竤竧竨竩竪竫竬竮竰竱竲竳竴竵競竷竸竻竼竾笀笁笂笅笇笉笌笍笎笐笒笓笖笗笘笚笜笝笟笡笢笣笧笩笭浮涪福袱弗甫抚辅俯釜斧脯腑府腐赴副覆赋复傅付阜父腹负富讣附妇缚咐噶嘎该改概钙盖溉干甘杆柑竿肝赶感秆敢赣冈刚钢缸肛纲岗港杠篙皋高膏羔糕搞镐稿告哥歌搁戈鸽胳疙割革葛格蛤阁隔铬个各给根跟耕更庚羹 笯笰笲笴笵笶笷笹笻笽笿筀筁筂筃筄筆筈筊筍筎筓筕筗筙筜筞筟筡筣筤筥筦筧筨筩筪筫筬筭筯筰筳筴筶筸筺筼筽筿箁箂箃箄箆箇箈箉箊箋箌箎箏箑箒箓箖箘箙箚箛箞箟箠箣箤箥箮箯箰箲箳箵箶箷箹箺箻箼箽箾箿節篂篃範埂耿梗工攻功恭龚供躬公宫弓巩汞拱贡共钩勾沟苟狗垢构购够辜菇咕箍估沽孤姑鼓古蛊骨谷股故顾固雇刮瓜剐寡挂褂乖拐怪棺关官冠观管馆罐惯灌贯光广逛瑰规圭硅归龟闺轨鬼诡癸桂柜跪贵刽辊滚棍锅郭国果裹过哈$篅篈築篊篋篍篎篏篐篒篔篕篖篗篘篛篜篞篟篠篢篣篤篧篨篩篫篬篭篯篰篲篳篴篵篶篸篹篺篻篽篿簀簁簂簃簄簅簆簈簉簊簍簎簐簑簒簓簔簕簗簘簙簚簛簜簝簞簠簡簢簣簤簥簨簩簫簬簭簮簯簰簱簲簳簴簵簶簷簹簺簻簼簽簾籂骸孩海氦亥害骇酣憨邯韩含涵寒函喊罕翰撼捍旱憾悍焊汗汉夯杭航壕嚎豪毫郝好耗号浩呵喝荷菏核禾和何合盒貉阂河涸赫褐鹤贺嘿黑痕很狠恨哼亨横衡恒轰哄烘虹鸿洪宏弘红喉侯猴吼厚候后呼乎忽瑚壶葫胡蝴狐糊湖(籃籄籅籆籇籈籉籊籋籌籎籏籐籑籒籓籔籕籖籗籘籙籚籛籜籝籞籟籠籡籢籣籤籥籦籧籨籩籪籫籬籭籮籯籰籱籲籵籶籷籸籹籺籾籿粀粁粂粃粄粅粆粇粈粊粋粌粍粎粏粐粓粔粖粙粚粛粠粡粣粦粧粨粩粫粬粭粯粰粴粵粶粷粸粺粻弧虎唬护互沪户花哗华猾滑画划化话槐徊怀淮坏欢环桓还缓换患唤痪豢焕涣宦幻荒慌黄磺蝗簧皇凰惶煌晃幌恍谎灰挥辉徽恢蛔回毁悔慧卉惠晦贿秽会烩汇讳诲绘荤昏婚魂浑混豁活伙火获或惑霍货祸击圾基机畸稽积箕,粿糀糂糃糄糆糉糋糎糏糐糑糒糓糔糘糚糛糝糞糡糢糣糤糥糦糧糩糪糫糬糭糮糰糱糲糳糴糵糶糷糹糺糼糽糾糿紀紁紂紃約紅紆紇紈紉紋紌納紎紏紐紑紒紓純紕紖紗紘紙級紛紜紝紞紟紡紣紤紥紦紨紩紪紬紭紮細紱紲紳紴紵紶肌饥迹激讥鸡姬绩缉吉极棘辑籍集及急疾汲即嫉级挤几脊己蓟技冀季伎祭剂悸济寄寂计记既忌际妓继纪嘉枷夹佳家加荚颊贾甲钾假稼价架驾嫁歼监坚尖笺间煎兼肩艰奸缄茧检柬碱硷拣捡简俭剪减荐槛鉴践贱见键箭件0紷紸紹紺紻紼紽紾紿絀絁終絃組絅絆絇絈絉絊絋経絍絎絏結絑絒絓絔絕絖絗絘絙絚絛絜絝絞絟絠絡絢絣絤絥給絧絨絩絪絫絬絭絯絰統絲絳絴絵絶絸絹絺絻絼絽絾絿綀綁綂綃綄綅綆綇綈綉綊綋綌綍綎綏綐綑綒經綔綕綖綗綘健舰剑饯渐溅涧建僵姜将浆江疆蒋桨奖讲匠酱降蕉椒礁焦胶交郊浇骄娇嚼搅铰矫侥脚狡角饺缴绞剿教酵轿较叫窖揭接皆秸街阶截劫节桔杰捷睫竭洁结解姐戒藉芥界借介疥诫届巾筋斤金今津襟紧锦仅谨进靳晋禁近烬浸4継続綛綜綝綞綟綠綡綢綣綤綥綧綨綩綪綫綬維綯綰綱網綳綴綵綶綷綸綹綺綻綼綽綾綿緀緁緂緃緄緅緆緇緈緉緊緋緌緍緎総緐緑緒緓緔緕緖緗緘緙線緛緜緝緞緟締緡緢緣緤緥緦緧編緩緪緫緬緭緮緯緰緱緲緳練緵緶緷緸緹緺尽劲荆兢茎睛晶鲸京惊精粳经井警景颈静境敬镜径痉靖竟竞净炯窘揪究纠玖韭久灸九酒厩救旧臼舅咎就疚鞠拘狙疽居驹菊局咀矩举沮聚拒据巨具距踞锯俱句惧炬剧捐鹃娟倦眷卷绢撅攫抉掘倔爵觉决诀绝均菌钧军君峻8緻緼緽緾緿縀縁縂縃縄縅縆縇縈縉縊縋縌縍縎縏縐縑縒縓縔縕縖縗縘縙縚縛縜縝縞縟縠縡縢縣縤縥縦縧縨縩縪縫縬縭縮縯縰縱縲縳縴縵縶縷縸縹縺縼總績縿繀繂繃繄繅繆繈繉繊繋繌繍繎繏繐繑繒繓織繕繖繗繘繙繚繛繜繝俊竣浚郡骏喀咖卡咯开揩楷凯慨刊堪勘坎砍看康慷糠扛抗亢炕考拷烤靠坷苛柯棵磕颗科壳咳可渴克刻客课肯啃垦恳坑吭空恐孔控抠口扣寇枯哭窟苦酷库裤夸垮挎跨胯块筷侩快宽款匡筐狂框矿眶旷况亏盔岿窥葵奎魁傀<繞繟繠繡繢繣繤繥繦繧繨繩繪繫繬繭繮繯繰繱繲繳繴繵繶繷繸繹繺繻繼繽繾繿纀纁纃纄纅纆纇纈纉纊纋續纍纎纏纐纑纒纓纔纕纖纗纘纙纚纜纝纞纮纴纻纼绖绤绬绹缊缐缞缷缹缻缼缽缾缿罀罁罃罆罇罈罉罊罋罌罍罎罏罒罓馈愧溃坤昆捆困括扩廓阔垃拉喇蜡腊辣啦莱来赖蓝婪栏拦篮阑兰澜谰揽览懒缆烂滥琅榔狼廊郎朗浪捞劳牢老佬姥酪烙涝勒乐雷镭蕾磊累儡垒擂肋类泪棱楞冷厘梨犁黎篱狸离漓理李里鲤礼莉荔吏栗丽厉励砾历利傈例俐@罖罙罛罜罝罞罠罣罤罥罦罧罫罬罭罯罰罳罵罶罷罸罺罻罼罽罿羀羂羃羄羅羆羇羈羉羋羍羏羐羑羒羓羕羖羗羘羙羛羜羠羢羣羥羦羨義羪羫羬羭羮羱羳羴羵羶羷羺羻羾翀翂翃翄翆翇翈翉翋翍翏翐翑習翓翖翗翙翚翛翜翝翞翢翣痢立粒沥隶力璃哩俩联莲连镰廉怜涟帘敛脸链恋炼练粮凉梁粱良两辆量晾亮谅撩聊僚疗燎寥辽潦了撂镣廖料列裂烈劣猎琳林磷霖临邻鳞淋凛赁吝拎玲菱零龄铃伶羚凌灵陵岭领另令溜琉榴硫馏留刘瘤流柳六龙聋咙笼窿D翤翧翨翪翫翬翭翯翲翴翵翶翷翸翹翺翽翾翿耂耇耈耉耊耎耏耑耓耚耛耝耞耟耡耣耤耫耬耭耮耯耰耲耴耹耺耼耾聀聁聄聅聇聈聉聎聏聐聑聓聕聖聗聙聛聜聝聞聟聠聡聢聣聤聥聦聧聨聫聬聭聮聯聰聲聳聴聵聶職聸聹聺聻聼聽隆垄拢陇楼娄搂篓漏陋芦卢颅庐炉掳卤虏鲁麓碌露路赂鹿潞禄录陆戮驴吕铝侣旅履屡缕虑氯律率滤绿峦挛孪滦卵乱掠略抡轮伦仑沦纶论萝螺罗逻锣箩骡裸落洛骆络妈麻玛码蚂马骂嘛吗埋买麦卖迈脉瞒馒蛮满蔓曼慢漫H聾肁肂肅肈肊肍肎肏肐肑肒肔肕肗肙肞肣肦肧肨肬肰肳肵肶肸肹肻胅胇胈胉胊胋胏胐胑胒胓胔胕胘胟胠胢胣胦胮胵胷胹胻胾胿脀脁脃脄脅脇脈脋脌脕脗脙脛脜脝脟脠脡脢脣脤脥脦脧脨脩脪脫脭脮脰脳脴脵脷脹脺脻脼脽脿谩芒茫盲氓忙莽猫茅锚毛矛铆卯茂冒帽貌贸么玫枚梅酶霉煤没眉媒镁每美昧寐妹媚门闷们萌蒙檬盟锰猛梦孟眯醚靡糜迷谜弥米秘觅泌蜜密幂棉眠绵冕免勉娩缅面苗描瞄藐秒渺庙妙蔑灭民抿皿敏悯闽明螟鸣铭名命谬摸L腀腁腂腃腄腅腇腉腍腎腏腒腖腗腘腛腜腝腞腟腡腢腣腤腦腨腪腫腬腯腲腳腵腶腷腸膁膃膄膅膆膇膉膋膌膍膎膐膒膓膔膕膖膗膙膚膞膟膠膡膢膤膥膧膩膫膬膭膮膯膰膱膲膴膵膶膷膸膹膼膽膾膿臄臅臇臈臉臋臍臎臏臐臑臒臓摹蘑模膜磨摩魔抹末莫墨默沫漠寞陌谋牟某拇牡亩姆母墓暮幕募慕木目睦牧穆拿哪呐钠那娜纳氖乃奶耐奈南男难囊挠脑恼闹淖呢馁内嫩能妮霓倪泥尼拟你匿腻逆溺蔫拈年碾撵捻念娘酿鸟尿捏聂孽啮镊镍涅您柠狞凝宁P臔臕臖臗臘臙臚臛臜臝臞臟臠臡臢臤臥臦臨臩臫臮臯臰臱臲臵臶臷臸臹臺臽臿舃與興舉舊舋舎舏舑舓舕舖舗舘舙舚舝舠舤舥舦舧舩舮舲舺舼舽舿艀艁艂艃艅艆艈艊艌艍艎艐艑艒艓艔艕艖艗艙艛艜艝艞艠艡艢艣艤艥艦艧艩拧泞牛扭钮纽脓浓农弄奴努怒女暖虐疟挪懦糯诺哦欧鸥殴藕呕偶沤啪趴爬帕怕琶拍排牌徘湃派攀潘盘磐盼畔判叛乓庞旁耪胖抛咆刨炮袍跑泡呸胚培裴赔陪配佩沛喷盆砰抨烹澎彭蓬棚硼篷膨朋鹏捧碰坯砒霹批披劈琵毗T艪艫艬艭艱艵艶艷艸艻艼芀芁芃芅芆芇芉芌芐芓芔芕芖芚芛芞芠芢芣芧芲芵芶芺芻芼芿苀苂苃苅苆苉苐苖苙苚苝苢苧苨苩苪苬苭苮苰苲苳苵苶苸苺苼苽苾苿茀茊茋茍茐茒茓茖茘茙茝茞茟茠茡茢茣茤茥茦茩茪茮茰茲茷茻茽啤脾疲皮匹痞僻屁譬篇偏片骗飘漂瓢票撇瞥拼频贫品聘乒坪苹萍平凭瓶评屏坡泼颇婆破魄迫粕剖扑铺仆莆葡菩蒲埔朴圃普浦谱曝瀑期欺栖戚妻七凄漆柒沏其棋奇歧畦崎脐齐旗祈祁骑起岂乞企启契砌器气迄弃汽泣讫掐X茾茿荁荂荄荅荈荊荋荌荍荎荓荕荖荗荘荙荝荢荰荱荲荳荴荵荶荹荺荾荿莀莁莂莃莄莇莈莊莋莌莍莏莐莑莔莕莖莗莙莚莝莟莡莢莣莤莥莦莧莬莭莮莯莵莻莾莿菂菃菄菆菈菉菋菍菎菐菑菒菓菕菗菙菚菛菞菢菣菤菦菧菨菫菬菭恰洽牵扦钎铅千迁签仟谦乾黔钱钳前潜遣浅谴堑嵌欠歉枪呛腔羌墙蔷强抢橇锹敲悄桥瞧乔侨巧鞘撬翘峭俏窍切茄且怯窃钦侵亲秦琴勤芹擒禽寝沁青轻氢倾卿清擎晴氰情顷请庆琼穷秋丘邱球求囚酋泅趋区蛆曲躯屈驱渠\菮華菳菴菵菶菷菺菻菼菾菿萀萂萅萇萈萉萊萐萒萓萔萕萖萗萙萚萛萞萟萠萡萢萣萩萪萫萬萭萮萯萰萲萳萴萵萶萷萹萺萻萾萿葀葁葂葃葄葅葇葈葉葊葋葌葍葎葏葐葒葓葔葕葖葘葝葞葟葠葢葤葥葦葧葨葪葮葯葰葲葴葷葹葻葼取娶龋趣去圈颧权醛泉全痊拳犬券劝缺炔瘸却鹊榷确雀裙群然燃冉染瓤壤攘嚷让饶扰绕惹热壬仁人忍韧任认刃妊纫扔仍日戎茸蓉荣融熔溶容绒冗揉柔肉茹蠕儒孺如辱乳汝入褥软阮蕊瑞锐闰润若弱撒洒萨腮鳃塞赛三叁`葽葾葿蒀蒁蒃蒄蒅蒆蒊蒍蒏蒐蒑蒒蒓蒔蒕蒖蒘蒚蒛蒝蒞蒟蒠蒢蒣蒤蒥蒦蒧蒨蒩蒪蒫蒬蒭蒮蒰蒱蒳蒵蒶蒷蒻蒼蒾蓀蓂蓃蓅蓆蓇蓈蓋蓌蓎蓏蓒蓔蓕蓗蓘蓙蓚蓛蓜蓞蓡蓢蓤蓧蓨蓩蓪蓫蓭蓮蓯蓱蓲蓳蓴蓵蓶蓷蓸蓹蓺蓻蓽蓾蔀蔁蔂伞散桑嗓丧搔骚扫嫂瑟色涩森僧莎砂杀刹沙纱傻啥煞筛晒珊苫杉山删煽衫闪陕擅赡膳善汕扇缮墒伤商赏晌上尚裳梢捎稍烧芍勺韶少哨邵绍奢赊蛇舌舍赦摄射慑涉社设砷申呻伸身深娠绅神沈审婶甚肾慎渗声生甥牲升绳d蔃蔄蔅蔆蔇蔈蔉蔊蔋蔍蔎蔏蔐蔒蔔蔕蔖蔘蔙蔛蔜蔝蔞蔠蔢蔣蔤蔥蔦蔧蔨蔩蔪蔭蔮蔯蔰蔱蔲蔳蔴蔵蔶蔾蔿蕀蕁蕂蕄蕅蕆蕇蕋蕌蕍蕎蕏蕐蕑蕒蕓蕔蕕蕗蕘蕚蕛蕜蕝蕟蕠蕡蕢蕣蕥蕦蕧蕩蕪蕫蕬蕭蕮蕯蕰蕱蕳蕵蕶蕷蕸蕼蕽蕿薀薁省盛剩胜圣师失狮施湿诗尸虱十石拾时什食蚀实识史矢使屎驶始式示士世柿事拭誓逝势是嗜噬适仕侍释饰氏市恃室视试收手首守寿授售受瘦兽蔬枢梳殊抒输叔舒淑疏书赎孰熟薯暑曙署蜀黍鼠属术述树束戍竖墅庶数漱h薂薃薆薈薉薊薋薌薍薎薐薑薒薓薔薕薖薗薘薙薚薝薞薟薠薡薢薣薥薦薧薩薫薬薭薱薲薳薴薵薶薸薺薻薼薽薾薿藀藂藃藄藅藆藇藈藊藋藌藍藎藑藒藔藖藗藘藙藚藛藝藞藟藠藡藢藣藥藦藧藨藪藫藬藭藮藯藰藱藲藳藴藵藶藷藸恕刷耍摔衰甩帅栓拴霜双爽谁水睡税吮瞬顺舜说硕朔烁斯撕嘶思私司丝死肆寺嗣四伺似饲巳松耸怂颂送宋讼诵搜艘擞嗽苏酥俗素速粟僳塑溯宿诉肃酸蒜算虽隋随绥髓碎岁穗遂隧祟孙损笋蓑梭唆缩琐索锁所塌他它她塔l藹藺藼藽藾蘀蘁蘂蘃蘄蘆蘇蘈蘉蘊蘋蘌蘍蘎蘏蘐蘒蘓蘔蘕蘗蘘蘙蘚蘛蘜蘝蘞蘟蘠蘡蘢蘣蘤蘥蘦蘨蘪蘫蘬蘭蘮蘯蘰蘱蘲蘳蘴蘵蘶蘷蘹蘺蘻蘽蘾蘿虀虁虂虃虄虅虆虇虈虉虊虋虌虒虓處虖虗虘虙虛虜虝號虠虡虣虤虥虦虧虨虩虪獭挞蹋踏胎苔抬台泰酞太态汰坍摊贪瘫滩坛檀痰潭谭谈坦毯袒碳探叹炭汤塘搪堂棠膛唐糖倘躺淌趟烫掏涛滔绦萄桃逃淘陶讨套特藤腾疼誊梯剔踢锑提题蹄啼体替嚏惕涕剃屉天添填田甜恬舔腆挑条迢眺跳贴铁帖厅听烃p虭虯虰虲虳虴虵虶虷虸蚃蚄蚅蚆蚇蚈蚉蚎蚏蚐蚑蚒蚔蚖蚗蚘蚙蚚蚛蚞蚟蚠蚡蚢蚥蚦蚫蚭蚮蚲蚳蚷蚸蚹蚻蚼蚽蚾蚿蛁蛂蛃蛅蛈蛌蛍蛒蛓蛕蛖蛗蛚蛜蛝蛠蛡蛢蛣蛥蛦蛧蛨蛪蛫蛬蛯蛵蛶蛷蛺蛻蛼蛽蛿蜁蜄蜅蜆蜋蜌蜎蜏蜐蜑蜔蜖汀廷停亭庭挺艇通桐酮瞳同铜彤童桶捅筒统痛偷投头透凸秃突图徒途涂屠土吐兔湍团推颓腿蜕褪退吞屯臀拖托脱鸵陀驮驼椭妥拓唾挖哇蛙洼娃瓦袜歪外豌弯湾玩顽丸烷完碗挽晚皖惋宛婉万腕汪王亡枉网往旺望忘妄威t蜙蜛蜝蜟蜠蜤蜦蜧蜨蜪蜫蜬蜭蜯蜰蜲蜳蜵蜶蜸蜹蜺蜼蜽蝀蝁蝂蝃蝄蝅蝆蝊蝋蝍蝏蝐蝑蝒蝔蝕蝖蝘蝚蝛蝜蝝蝞蝟蝡蝢蝦蝧蝨蝩蝪蝫蝬蝭蝯蝱蝲蝳蝵蝷蝸蝹蝺蝿螀螁螄螆螇螉螊螌螎螏螐螑螒螔螕螖螘螙螚螛螜螝螞螠螡螢螣螤巍微危韦违桅围唯惟为潍维苇萎委伟伪尾纬未蔚味畏胃喂魏位渭谓尉慰卫瘟温蚊文闻纹吻稳紊问嗡翁瓮挝蜗涡窝我斡卧握沃巫呜钨乌污诬屋无芜梧吾吴毋武五捂午舞伍侮坞戊雾晤物勿务悟误昔熙析西硒矽晰嘻吸锡牺x螥螦螧螩螪螮螰螱螲螴螶螷螸螹螻螼螾螿蟁蟂蟃蟄蟅蟇蟈蟉蟌蟍蟎蟏蟐蟔蟕蟖蟗蟘蟙蟚蟜蟝蟞蟟蟡蟢蟣蟤蟦蟧蟨蟩蟫蟬蟭蟯蟰蟱蟲蟳蟴蟵蟶蟷蟸蟺蟻蟼蟽蟿蠀蠁蠂蠄蠅蠆蠇蠈蠉蠋蠌蠍蠎蠏蠐蠑蠒蠔蠗蠘蠙蠚蠜蠝蠞蠟蠠蠣稀息希悉膝夕惜熄烯溪汐犀檄袭席习媳喜铣洗系隙戏细瞎虾匣霞辖暇峡侠狭下厦夏吓掀锨先仙鲜纤咸贤衔舷闲涎弦嫌显险现献县腺馅羡宪陷限线相厢镶香箱襄湘乡翔祥详想响享项巷橡像向象萧硝霄削哮嚣销消宵淆晓|蠤蠥蠦蠧蠨蠩蠪蠫蠬蠭蠮蠯蠰蠱蠳蠴蠵蠶蠷蠸蠺蠻蠽蠾蠿衁衂衃衆衇衈衉衊衋衎衏衐衑衒術衕衖衘衚衛衜衝衞衟衠衦衧衪衭衯衱衳衴衵衶衸衹衺衻衼袀袃袆袇袉袊袌袎袏袐袑袓袔袕袗袘袙袚袛袝袞袟袠袡袣袥袦袧袨袩袪小孝校肖啸笑效楔些歇蝎鞋协挟携邪斜胁谐写械卸蟹懈泄泻谢屑薪芯锌欣辛新忻心信衅星腥猩惺兴刑型形邢行醒幸杏性姓兄凶胸匈汹雄熊休修羞朽嗅锈秀袖绣墟戌需虚嘘须徐许蓄酗叙旭序畜恤絮婿绪续轩喧宣悬旋玄袬袮袯袰袲袳袴袵袶袸袹袺袻袽袾袿裀裃裄裇裈裊裋裌裍裏裐裑裓裖裗裚裛補裝裞裠裡裦裧裩裪裫裬裭裮裯裲裵裶裷裺裻製裿褀褁褃褄褅褆複褈褉褋褌褍褎褏褑褔褕褖褗褘褜褝褞褟褠褢褣褤褦褧褨褩褬褭褮褯褱褲褳褵褷选癣眩绚靴薛学穴雪血勋熏循旬询寻驯巡殉汛训讯逊迅压押鸦鸭呀丫芽牙蚜崖衙涯雅哑亚讶焉咽阉烟淹盐严研蜒岩延言颜阎炎沿奄掩眼衍演艳堰燕厌砚雁唁彦焰宴谚验殃央鸯秧杨扬佯疡羊洋阳氧仰痒养样漾邀腰妖瑶褸褹褺褻褼褽褾褿襀襂襃襅襆襇襈襉襊襋襌襍襎襏襐襑襒襓襔襕襖襗襘襙襚襛襜襝襠襡襢襣襤襥襧襨襩襪襫襬襭襮襯襰襱襲襳襴襵襶襷襸襹襺襼襽襾覀覂覄覅覇覈覉覊見覌覍覎規覐覑覒覓覔覕視覗覘覙覚覛覜覝覞覟覠覡摇尧遥窑谣姚咬舀药要耀椰噎耶爷野冶也页掖业叶曳腋夜液一壹医揖铱依伊衣颐夷遗移仪胰疑沂宜姨彝椅蚁倚已乙矣以艺抑易邑屹亿役臆逸肄疫亦裔意毅忆义益溢诣议谊译异翼翌绎茵荫因殷音阴姻吟银淫寅饮尹引隐覢覣覤覥覦覧覨覩親覫覬覭覮覯覰覱覲観覴覵覶覷覸覹覺覻覼覽覾覿觀觃觍觓觔觕觗觘觙觛觝觟觠觡觢觤觧觨觩觪觬觭觮觰觱觲觴觵觶觷觸觹觺觻觼觽觾觿訁訂訃訄訅訆計訉訊訋訌訍討訏訐訑訒訓訔訕訖託記訙訚訛訜訝印英樱婴鹰应缨莹萤营荧蝇迎赢盈影颖硬映哟拥佣臃痈庸雍踊蛹咏泳涌永恿勇用幽优悠忧尤由邮铀犹油游酉有友右佑釉诱又幼迂淤于盂榆虞愚舆余俞逾鱼愉渝渔隅予娱雨与屿禹宇语羽玉域芋郁吁遇喻峪御愈欲狱育誉訞訟訠訡訢訣訤訥訦訧訨訩訪訫訬設訮訯訰許訲訳訴訵訶訷訸訹診註証訽訿詀詁詂詃詄詅詆詇詉詊詋詌詍詎詏詐詑詒詓詔評詖詗詘詙詚詛詜詝詞詟詠詡詢詣詤詥試詧詨詩詪詫詬詭詮詯詰話該詳詴詵詶詷詸詺詻詼詽詾詿誀浴寓裕预豫驭鸳渊冤元垣袁原援辕园员圆猿源缘远苑愿怨院曰约越跃钥岳粤月悦阅耘云郧匀陨允运蕴酝晕韵孕匝砸杂栽哉灾宰载再在咱攒暂赞赃脏葬遭糟凿藻枣早澡蚤躁噪造皂灶燥责择则泽贼怎增憎曾赠扎喳渣札轧誁誂誃誄誅誆誇誈誋誌認誎誏誐誑誒誔誕誖誗誘誙誚誛誜誝語誟誠誡誢誣誤誥誦誧誨誩說誫説読誮誯誰誱課誳誴誵誶誷誸誹誺誻誼誽誾調諀諁諂諃諄諅諆談諈諉諊請諌諍諎諏諐諑諒諓諔諕論諗諘諙諚諛諜諝諞諟諠諡諢諣铡闸眨栅榨咋乍炸诈摘斋宅窄债寨瞻毡詹粘沾盏斩辗崭展蘸栈占战站湛绽樟章彰漳张掌涨杖丈帐账仗胀瘴障招昭找沼赵照罩兆肇召遮折哲蛰辙者锗蔗这浙珍斟真甄砧臻贞针侦枕疹诊震振镇阵蒸挣睁征狰争怔整拯正政諤諥諦諧諨諩諪諫諬諭諮諯諰諱諲諳諴諵諶諷諸諹諺諻諼諽諾諿謀謁謂謃謄謅謆謈謉謊謋謌謍謎謏謐謑謒謓謔謕謖謗謘謙謚講謜謝謞謟謠謡謢謣謤謥謧謨謩謪謫謬謭謮謯謰謱謲謳謴謵謶謷謸謹謺謻謼謽謾謿譀譁譂譃譄譅帧症郑证芝枝支吱蜘知肢脂汁之织职直植殖执值侄址指止趾只旨纸志挚掷至致置帜峙制智秩稚质炙痔滞治窒中盅忠钟衷终种肿重仲众舟周州洲诌粥轴肘帚咒皱宙昼骤珠株蛛朱猪诸诛逐竹烛煮拄瞩嘱主著柱助蛀贮铸筑譆譇譈證譊譋譌譍譎譏譐譑譒譓譔譕譖譗識譙譚譛譜譝譞譟譠譡譢譣譤譥譧譨譩譪譫譭譮譯議譱譲譳譴譵譶護譸譹譺譻譼譽譾譿讀讁讂讃讄讅讆讇讈讉變讋讌讍讎讏讐讑讒讓讔讕讖讗讘讙讚讛讜讝讞讟讬讱讻诇诐诪谉谞住注祝驻抓爪拽专砖转撰赚篆桩庄装妆撞壮状椎锥追赘坠缀谆准捉拙卓桌琢茁酌啄着灼浊兹咨资姿滋淄孜紫仔籽滓子自渍字鬃棕踪宗综总纵邹走奏揍租足卒族祖诅阻组钻纂嘴醉最罪尊遵昨左佐柞做作坐座 谸谹谺谻谼谽谾谿豀豂豃豄豅豈豊豋豍豎豏豐豑豒豓豔豖豗豘豙豛豜豝豞豟豠豣豤豥豦豧豨豩豬豭豮豯豰豱豲豴豵豶豷豻豼豽豾豿貀貁貃貄貆貇貈貋貍貎貏貐貑貒貓貕貖貗貙貚貛貜貝貞貟負財貢貣貤貥貦貧貨販貪貫責貭亍丌兀丐廿卅丕亘丞鬲孬噩丨禺丿匕乇夭爻卮氐囟胤馗毓睾鼗丶亟鼐乜乩亓芈孛啬嘏仄厍厝厣厥厮靥赝匚叵匦匮匾赜卦卣刂刈刎刭刳刿剀剌剞剡剜蒯剽劂劁劐劓冂罔亻仃仉仂仨仡仫仞伛仳伢佤仵伥伧伉伫佞佧攸佚佝貮貯貰貱貲貳貴貵貶買貸貹貺費貼貽貾貿賀賁賂賃賄賅賆資賈賉賊賋賌賍賎賏賐賑賒賓賔賕賖賗賘賙賚賛賜賝賞賟賠賡賢賣賤賥賦賧賨賩質賫賬賭賮賯賰賱賲賳賴賵賶賷賸賹賺賻購賽賾賿贀贁贂贃贄贅贆贇贈贉贊贋贌贍佟佗伲伽佶佴侑侉侃侏佾佻侪佼侬侔俦俨俪俅俚俣俜俑俟俸倩偌俳倬倏倮倭俾倜倌倥倨偾偃偕偈偎偬偻傥傧傩傺僖儆僭僬僦僮儇儋仝氽佘佥俎龠汆籴兮巽黉馘冁夔勹匍訇匐凫夙兕亠兖亳衮袤亵脔裒禀嬴蠃羸冫冱冽冼贎贏贐贑贒贓贔贕贖贗贘贙贚贛贜贠赑赒赗赟赥赨赩赪赬赮赯赱赲赸赹赺赻赼赽赾赿趀趂趃趆趇趈趉趌趍趎趏趐趒趓趕趖趗趘趙趚趛趜趝趞趠趡趢趤趥趦趧趨趩趪趫趬趭趮趯趰趲趶趷趹趻趽跀跁跂跅跇跈跉跊跍跐跒跓跔凇冖冢冥讠讦讧讪讴讵讷诂诃诋诏诎诒诓诔诖诘诙诜诟诠诤诨诩诮诰诳诶诹诼诿谀谂谄谇谌谏谑谒谔谕谖谙谛谘谝谟谠谡谥谧谪谫谮谯谲谳谵谶卩卺阝阢阡阱阪阽阼陂陉陔陟陧陬陲陴隈隍隗隰邗邛邝邙邬邡邴邳邶邺跕跘跙跜跠跡跢跥跦跧跩跭跮跰跱跲跴跶跼跾跿踀踁踂踃踄踆踇踈踋踍踎踐踑踒踓踕踖踗踘踙踚踛踜踠踡踤踥踦踧踨踫踭踰踲踳踴踶踷踸踻踼踾踿蹃蹅蹆蹌蹍蹎蹏蹐蹓蹔蹕蹖蹗蹘蹚蹛蹜蹝蹞蹟蹠蹡蹢蹣蹤蹥蹧蹨蹪蹫蹮蹱邸邰郏郅邾郐郄郇郓郦郢郜郗郛郫郯郾鄄鄢鄞鄣鄱鄯鄹酃酆刍奂劢劬劭劾哿勐勖勰叟燮矍廴凵凼鬯厶弁畚巯坌垩垡塾墼壅壑圩圬圪圳圹圮圯坜圻坂坩垅坫垆坼坻坨坭坶坳垭垤垌垲埏垧垴垓垠埕埘埚埙埒垸埴埯埸埤埝蹳蹵蹷蹸蹹蹺蹻蹽蹾躀躂躃躄躆躈躉躊躋躌躍躎躑躒躓躕躖躗躘躙躚躛躝躟躠躡躢躣躤躥躦躧躨躩躪躭躮躰躱躳躴躵躶躷躸躹躻躼躽躾躿軀軁軂軃軄軅軆軇軈軉車軋軌軍軏軐軑軒軓軔軕軖軗軘軙軚軛軜軝軞軟軠軡転軣軤堋堍埽埭堀堞堙塄堠塥塬墁墉墚墀馨鼙懿艹艽艿芏芊芨芄芎芑芗芙芫芸芾芰苈苊苣芘芷芮苋苌苁芩芴芡芪芟苄苎芤苡茉苷苤茏茇苜苴苒苘茌苻苓茑茚茆茔茕苠苕茜荑荛荜茈莒茼茴茱莛荞茯荏荇荃荟荀茗荠茭茺茳荦荥軥軦軧軨軩軪軫軬軭軮軯軰軱軲軳軴軵軶軷軸軹軺軻軼軽軾軿輀輁輂較輄輅輆輇輈載輊輋輌輍輎輏輐輑輒輓輔輕輖輗輘輙輚輛輜輝輞輟輠輡輢輣輤輥輦輧輨輩輪輫輬輭輮輯輰輱輲輳輴輵輶輷輸輹輺輻輼輽輾輿轀轁轂轃轄荨茛荩荬荪荭荮莰荸莳莴莠莪莓莜莅荼莶莩荽莸荻莘莞莨莺莼菁萁菥菘堇萘萋菝菽菖萜萸萑萆菔菟萏萃菸菹菪菅菀萦菰菡葜葑葚葙葳蒇蒈葺蒉葸萼葆葩葶蒌蒎萱葭蓁蓍蓐蓦蒽蓓蓊蒿蒺蓠蒡蒹蒴蒗蓥蓣蔌甍蔸蓰蔹蔟蔺轅轆轇轈轉轊轋轌轍轎轏轐轑轒轓轔轕轖轗轘轙轚轛轜轝轞轟轠轡轢轣轤轥轪辀辌辒辝辠辡辢辤辥辦辧辪辬辭辮辯農辳辴辵辷辸辺辻込辿迀迃迆迉迊迋迌迍迏迒迖迗迚迠迡迣迧迬迯迱迲迴迵迶迺迻迼迾迿逇逈逌逎逓逕逘蕖蔻蓿蓼蕙蕈蕨蕤蕞蕺瞢蕃蕲蕻薤薨薇薏蕹薮薜薅薹薷薰藓藁藜藿蘧蘅蘩蘖蘼廾弈夼奁耷奕奚奘匏尢尥尬尴扌扪抟抻拊拚拗拮挢拶挹捋捃掭揶捱捺掎掴捭掬掊捩掮掼揲揸揠揿揄揞揎摒揆掾摅摁搋搛搠搌搦搡摞撄摭撖這逜連逤逥逧逨逩逪逫逬逰週進逳逴逷逹逺逽逿遀遃遅遆遈遉遊運遌過達違遖遙遚遜遝遞遟遠遡遤遦遧適遪遫遬遯遰遱遲遳遶遷選遹遺遻遼遾邁還邅邆邇邉邊邌邍邎邏邐邒邔邖邘邚邜邞邟邠邤邥邧邨邩邫邭邲邷邼邽邿郀摺撷撸撙撺擀擐擗擤擢攉攥攮弋忒甙弑卟叱叽叩叨叻吒吖吆呋呒呓呔呖呃吡呗呙吣吲咂咔呷呱呤咚咛咄呶呦咝哐咭哂咴哒咧咦哓哔呲咣哕咻咿哌哙哚哜咩咪咤哝哏哞唛哧唠哽唔哳唢唣唏唑唧唪啧喏喵啉啭啁啕唿啐唼郂郃郆郈郉郋郌郍郒郔郕郖郘郙郚郞郟郠郣郤郥郩郪郬郮郰郱郲郳郵郶郷郹郺郻郼郿鄀鄁鄃鄅鄆鄇鄈鄉鄊鄋鄌鄍鄎鄏鄐鄑鄒鄓鄔鄕鄖鄗鄘鄚鄛鄜鄝鄟鄠鄡鄤鄥鄦鄧鄨鄩鄪鄫鄬鄭鄮鄰鄲鄳鄴鄵鄶鄷鄸鄺鄻鄼鄽鄾鄿酀酁酂酄唷啖啵啶啷唳唰啜喋嗒喃喱喹喈喁喟啾嗖喑啻嗟喽喾喔喙嗪嗷嗉嘟嗑嗫嗬嗔嗦嗝嗄嗯嗥嗲嗳嗌嗍嗨嗵嗤辔嘞嘈嘌嘁嘤嘣嗾嘀嘧嘭噘嘹噗嘬噍噢噙噜噌噔嚆噤噱噫噻噼嚅嚓嚯囔囗囝囡囵囫囹囿圄圊圉圜帏帙帔帑帱帻帼酅酇酈酑酓酔酕酖酘酙酛酜酟酠酦酧酨酫酭酳酺酻酼醀醁醂醃醄醆醈醊醎醏醓醔醕醖醗醘醙醜醝醞醟醠醡醤醥醦醧醨醩醫醬醰醱醲醳醶醷醸醹醻醼醽醾醿釀釁釂釃釄釅釆釈釋釐釒釓釔釕釖釗釘釙釚釛針釞釟釠釡釢釣釤釥帷幄幔幛幞幡岌屺岍岐岖岈岘岙岑岚岜岵岢岽岬岫岱岣峁岷峄峒峤峋峥崂崃崧崦崮崤崞崆崛嵘崾崴崽嵬嵛嵯嵝嵫嵋嵊嵩嵴嶂嶙嶝豳嶷巅彳彷徂徇徉後徕徙徜徨徭徵徼衢彡犭犰犴犷犸狃狁狎狍狒狨狯狩狲狴狷猁狳猃狺 釦釧釨釩釪釫釬釭釮釯釰釱釲釳釴釵釶釷釸釹釺釻釼釽釾釿鈀鈁鈂鈃鈄鈅鈆鈇鈈鈉鈊鈋鈌鈍鈎鈏鈐鈑鈒鈓鈔鈕鈖鈗鈘鈙鈚鈛鈜鈝鈞鈟鈠鈡鈢鈣鈤鈥鈦鈧鈨鈩鈪鈫鈬鈭鈮鈯鈰鈱鈲鈳鈴鈵鈶鈷鈸鈹鈺鈻鈼鈽鈾鈿鉀鉁鉂鉃鉄鉅狻猗猓猡猊猞猝猕猢猹猥猬猸猱獐獍獗獠獬獯獾舛夥飧夤夂饣饧饨饩饪饫饬饴饷饽馀馄馇馊馍馐馑馓馔馕庀庑庋庖庥庠庹庵庾庳赓廒廑廛廨廪膺忄忉忖忏怃忮怄忡忤忾怅怆忪忭忸怙怵怦怛怏怍怩怫怊怿怡恸恹恻恺恂鉆鉇鉈鉉鉊鉋鉌鉍鉎鉏鉐鉑鉒鉓鉔鉕鉖鉗鉘鉙鉚鉛鉜鉝鉞鉟鉠鉡鉢鉣鉤鉥鉦鉧鉨鉩鉪鉫鉬鉭鉮鉯鉰鉱鉲鉳鉵鉶鉷鉸鉹鉺鉻鉼鉽鉾鉿銀銁銂銃銄銅銆銇銈銉銊銋銌銍銏銐銑銒銓銔銕銖銗銘銙銚銛銜銝銞銟銠銡銢銣銤銥銦銧恪恽悖悚悭悝悃悒悌悛惬悻悱惝惘惆惚悴愠愦愕愣惴愀愎愫慊慵憬憔憧憷懔懵忝隳闩闫闱闳闵闶闼闾阃阄阆阈阊阋阌阍阏阒阕阖阗阙阚丬爿戕氵汔汜汊沣沅沐沔沌汨汩汴汶沆沩泐泔沭泷泸泱泗沲泠泖泺泫泮沱泓泯泾銨銩銪銫銬銭銯銰銱銲銳銴銵銶銷銸銹銺銻銼銽銾銿鋀鋁鋂鋃鋄鋅鋆鋇鋉鋊鋋鋌鋍鋎鋏鋐鋑鋒鋓鋔鋕鋖鋗鋘鋙鋚鋛鋜鋝鋞鋟鋠鋡鋢鋣鋤鋥鋦鋧鋨鋩鋪鋫鋬鋭鋮鋯鋰鋱鋲鋳鋴鋵鋶鋷鋸鋹鋺鋻鋼鋽鋾鋿錀錁錂錃錄錅錆錇錈錉洹洧洌浃浈洇洄洙洎洫浍洮洵洚浏浒浔洳涑浯涞涠浞涓涔浜浠浼浣渚淇淅淞渎涿淠渑淦淝淙渖涫渌涮渫湮湎湫溲湟溆湓湔渲渥湄滟溱溘滠漭滢溥溧溽溻溷滗溴滏溏滂溟潢潆潇漤漕滹漯漶潋潴漪漉漩澉澍澌潸潲潼潺濑錊錋錌錍錎錏錐錑錒錓錔錕錖錗錘錙錚錛錜錝錞錟錠錡錢錣錤錥錦錧錨錩錪錫錬錭錮錯錰錱録錳錴錵錶錷錸錹錺錻錼錽錿鍀鍁鍂鍃鍄鍅鍆鍇鍈鍉鍊鍋鍌鍍鍎鍏鍐鍑鍒鍓鍔鍕鍖鍗鍘鍙鍚鍛鍜鍝鍞鍟鍠鍡鍢鍣鍤鍥鍦鍧鍨鍩鍫濉澧澹澶濂濡濮濞濠濯瀚瀣瀛瀹瀵灏灞宀宄宕宓宥宸甯骞搴寤寮褰寰蹇謇辶迓迕迥迮迤迩迦迳迨逅逄逋逦逑逍逖逡逵逶逭逯遄遑遒遐遨遘遢遛暹遴遽邂邈邃邋彐彗彖彘尻咫屐屙孱屣屦羼弪弩弭艴弼鬻屮妁妃妍妩妪妣鍬鍭鍮鍯鍰鍱鍲鍳鍴鍵鍶鍷鍸鍹鍺鍻鍼鍽鍾鍿鎀鎁鎂鎃鎄鎅鎆鎇鎈鎉鎊鎋鎌鎍鎎鎐鎑鎒鎓鎔鎕鎖鎗鎘鎙鎚鎛鎜鎝鎞鎟鎠鎡鎢鎣鎤鎥鎦鎧鎨鎩鎪鎫鎬鎭鎮鎯鎰鎱鎲鎳鎴鎵鎶鎷鎸鎹鎺鎻鎼鎽鎾鎿鏀鏁鏂鏃鏄鏅鏆鏇鏈鏉鏋鏌鏍妗姊妫妞妤姒妲妯姗妾娅娆姝娈姣姘姹娌娉娲娴娑娣娓婀婧婊婕娼婢婵胬媪媛婷婺媾嫫媲嫒嫔媸嫠嫣嫱嫖嫦嫘嫜嬉嬗嬖嬲嬷孀尕尜孚孥孳孑孓孢驵驷驸驺驿驽骀骁骅骈骊骐骒骓骖骘骛骜骝骟骠骢骣骥骧纟纡纣纥纨纩鏎鏏鏐鏑鏒鏓鏔鏕鏗鏘鏙鏚鏛鏜鏝鏞鏟鏠鏡鏢鏣鏤鏥鏦鏧鏨鏩鏪鏫鏬鏭鏮鏯鏰鏱鏲鏳鏴鏵鏶鏷鏸鏹鏺鏻鏼鏽鏾鏿鐀鐁鐂鐃鐄鐅鐆鐇鐈鐉鐊鐋鐌鐍鐎鐏鐐鐑鐒鐓鐔鐕鐖鐗鐘鐙鐚鐛鐜鐝鐞鐟鐠鐡鐢鐣鐤鐥鐦鐧鐨鐩鐪鐫鐬鐭鐮纭纰纾绀绁绂绉绋绌绐绔绗绛绠绡绨绫绮绯绱绲缍绶绺绻绾缁缂缃缇缈缋缌缏缑缒缗缙缜缛缟缡缢缣缤缥缦缧缪缫缬缭缯缰缱缲缳缵幺畿巛甾邕玎玑玮玢玟珏珂珑玷玳珀珉珈珥珙顼琊珩珧珞玺珲琏琪瑛琦琥琨琰琮琬鐯鐰鐱鐲鐳鐴鐵鐶鐷鐸鐹鐺鐻鐼鐽鐿鑀鑁鑂鑃鑄鑅鑆鑇鑈鑉鑊鑋鑌鑍鑎鑏鑐鑑鑒鑓鑔鑕鑖鑗鑘鑙鑚鑛鑜鑝鑞鑟鑠鑡鑢鑣鑤鑥鑦鑧鑨鑩鑪鑬鑭鑮鑯鑰鑱鑲鑳鑴鑵鑶鑷鑸鑹鑺鑻鑼鑽鑾鑿钀钁钂钃钄钑钖钘铇铏铓铔铚铦铻锜锠琛琚瑁瑜瑗瑕瑙瑷瑭瑾璜璎璀璁璇璋璞璨璩璐璧瓒璺韪韫韬杌杓杞杈杩枥枇杪杳枘枧杵枨枞枭枋杷杼柰栉柘栊柩枰栌柙枵柚枳柝栀柃枸柢栎柁柽栲栳桠桡桎桢桄桤梃栝桕桦桁桧桀栾桊桉栩梵梏桴桷梓桫棂楮棼椟椠棹 锧锳锽镃镈镋镕镚镠镮镴镵長镸镹镺镻镼镽镾門閁閂閃閄閅閆閇閈閉閊開閌閍閎閏閐閑閒間閔閕閖閗閘閙閚閛閜閝閞閟閠閡関閣閤閥閦閧閨閩閪閫閬閭閮閯閰閱閲閳閴閵閶閷閸閹閺閻閼閽閾閿闀闁闂闃闄闅闆闇闈闉闊闋椤棰椋椁楗棣椐楱椹楠楂楝榄楫榀榘楸椴槌榇榈槎榉楦楣楹榛榧榻榫榭槔榱槁槊槟榕槠榍槿樯槭樗樘橥槲橄樾檠橐橛樵檎橹樽樨橘橼檑檐檩檗檫猷獒殁殂殇殄殒殓殍殚殛殡殪轫轭轱轲轳轵轶轸轷轹轺轼轾辁辂辄辇辋#闌闍闎闏闐闑闒闓闔闕闖闗闘闙闚闛關闝闞闟闠闡闢闣闤闥闦闧闬闿阇阓阘阛阞阠阣阤阥阦阧阨阩阫阬阭阯阰阷阸阹阺阾陁陃陊陎陏陑陒陓陖陗陘陙陚陜陝陞陠陣陥陦陫陭陮陯陰陱陳陸陹険陻陼陽陾陿隀隁隂隃隄隇隉隊辍辎辏辘辚軎戋戗戛戟戢戡戥戤戬臧瓯瓴瓿甏甑甓攴旮旯旰昊昙杲昃昕昀炅曷昝昴昱昶昵耆晟晔晁晏晖晡晗晷暄暌暧暝暾曛曜曦曩贲贳贶贻贽赀赅赆赈赉赇赍赕赙觇觊觋觌觎觏觐觑牮犟牝牦牯牾牿犄犋犍犏犒挈挲掰&隌階隑隒隓隕隖隚際隝隞隟隠隡隢隣隤隥隦隨隩險隫隬隭隮隯隱隲隴隵隷隸隺隻隿雂雃雈雊雋雐雑雓雔雖雗雘雙雚雛雜雝雞雟雡離難雤雥雦雧雫雬雭雮雰雱雲雴雵雸雺電雼雽雿霂霃霅霊霋霌霐霑霒霔霕霗霘霙霚霛霝霟霠搿擘耄毪毳毽毵毹氅氇氆氍氕氘氙氚氡氩氤氪氲攵敕敫牍牒牖爰虢刖肟肜肓肼朊肽肱肫肭肴肷胧胨胩胪胛胂胄胙胍胗朐胝胫胱胴胭脍脎胲胼朕脒豚脶脞脬脘脲腈腌腓腴腙腚腱腠腩腼腽腭腧塍媵膈膂膑滕膣膪臌朦臊膻)霡霢霣霤霥霦霧霨霩霫霬霮霯霱霳霴霵霶霷霺霻霼霽霿靀靁靂靃靄靅靆靇靈靉靊靋靌靍靎靏靐靑靔靕靗靘靚靜靝靟靣靤靦靧靨靪靫靬靭靮靯靰靱靲靵靷靸靹靺靻靽靾靿鞀鞁鞂鞃鞄鞆鞇鞈鞉鞊鞌鞎鞏鞐鞓鞕鞖鞗鞙鞚鞛鞜鞝臁膦欤欷欹歃歆歙飑飒飓飕飙飚殳彀毂觳斐齑斓於旆旄旃旌旎旒旖炀炜炖炝炻烀炷炫炱烨烊焐焓焖焯焱煳煜煨煅煲煊煸煺熘熳熵熨熠燠燔燧燹爝爨灬焘煦熹戾戽扃扈扉礻祀祆祉祛祜祓祚祢祗祠祯祧祺禅禊禚禧禳忑忐,鞞鞟鞡鞢鞤鞥鞦鞧鞨鞩鞪鞬鞮鞰鞱鞳鞵鞶鞷鞸鞹鞺鞻鞼鞽鞾鞿韀韁韂韃韄韅韆韇韈韉韊韋韌韍韎韏韐韑韒韓韔韕韖韗韘韙韚韛韜韝韞韟韠韡韢韣韤韥韨韮韯韰韱韲韴韷韸韹韺韻韼韽韾響頀頁頂頃頄項順頇須頉頊頋頌頍頎怼恝恚恧恁恙恣悫愆愍慝憩憝懋懑戆肀聿沓泶淼矶矸砀砉砗砘砑斫砭砜砝砹砺砻砟砼砥砬砣砩硎硭硖硗砦硐硇硌硪碛碓碚碇碜碡碣碲碹碥磔磙磉磬磲礅磴礓礤礞礴龛黹黻黼盱眄眍盹眇眈眚眢眙眭眦眵眸睐睑睇睃睚睨/頏預頑頒頓頔頕頖頗領頙頚頛頜頝頞頟頠頡頢頣頤頥頦頧頨頩頪頫頬頭頮頯頰頱頲頳頴頵頶頷頸頹頺頻頼頽頾頿顀顁顂顃顄顅顆顇顈顉顊顋題額顎顏顐顑顒顓顔顕顖顗願顙顚顛顜顝類顟顠顡顢顣顤顥顦顧顨顩顪顫顬顭顮睢睥睿瞍睽瞀瞌瞑瞟瞠瞰瞵瞽町畀畎畋畈畛畲畹疃罘罡罟詈罨罴罱罹羁罾盍盥蠲钅钆钇钋钊钌钍钏钐钔钗钕钚钛钜钣钤钫钪钭钬钯钰钲钴钶钷钸钹钺钼钽钿铄铈铉铊铋铌铍铎铐铑铒铕铖铗铙铘铛铞铟铠铢铤铥铧铨铪2顯顰顱顲顳顴颋颎颒颕颙颣風颩颪颫颬颭颮颯颰颱颲颳颴颵颶颷颸颹颺颻颼颽颾颿飀飁飂飃飄飅飆飇飈飉飊飋飌飍飏飐飔飖飗飛飜飝飠飡飢飣飤飥飦飩飪飫飬飭飮飯飰飱飲飳飴飵飶飷飸飹飺飻飼飽飾飿餀餁餂餃餄餅餆餇铩铫铮铯铳铴铵铷铹铼铽铿锃锂锆锇锉锊锍锎锏锒锓锔锕锖锘锛锝锞锟锢锪锫锩锬锱锲锴锶锷锸锼锾锿镂锵镄镅镆镉镌镎镏镒镓镔镖镗镘镙镛镞镟镝镡镢镤镥镦镧镨镩镪镫镬镯镱镲镳锺矧矬雉秕秭秣秫稆嵇稃稂稞稔5餈餉養餋餌餎餏餑餒餓餔餕餖餗餘餙餚餛餜餝餞餟餠餡餢餣餤餥餦餧館餩餪餫餬餭餯餰餱餲餳餴餵餶餷餸餹餺餻餼餽餾餿饀饁饂饃饄饅饆饇饈饉饊饋饌饍饎饏饐饑饒饓饖饗饘饙饚饛饜饝饞饟饠饡饢饤饦饳饸饹饻饾馂馃馉稹稷穑黏馥穰皈皎皓皙皤瓞瓠甬鸠鸢鸨鸩鸪鸫鸬鸲鸱鸶鸸鸷鸹鸺鸾鹁鹂鹄鹆鹇鹈鹉鹋鹌鹎鹑鹕鹗鹚鹛鹜鹞鹣鹦鹧鹨鹩鹪鹫鹬鹱鹭鹳疒疔疖疠疝疬疣疳疴疸痄疱疰痃痂痖痍痣痨痦痤痫痧瘃痱痼痿瘐瘀瘅瘌瘗瘊瘥瘘瘕瘙8馌馎馚馛馜馝馞馟馠馡馢馣馤馦馧馩馪馫馬馭馮馯馰馱馲馳馴馵馶馷馸馹馺馻馼馽馾馿駀駁駂駃駄駅駆駇駈駉駊駋駌駍駎駏駐駑駒駓駔駕駖駗駘駙駚駛駜駝駞駟駠駡駢駣駤駥駦駧駨駩駪駫駬駭駮駯駰駱駲駳駴駵駶駷駸駹瘛瘼瘢瘠癀瘭瘰瘿瘵癃瘾瘳癍癞癔癜癖癫癯翊竦穸穹窀窆窈窕窦窠窬窨窭窳衤衩衲衽衿袂袢裆袷袼裉裢裎裣裥裱褚裼裨裾裰褡褙褓褛褊褴褫褶襁襦襻疋胥皲皴矜耒耔耖耜耠耢耥耦耧耩耨耱耋耵聃聆聍聒聩聱覃顸颀颃;駺駻駼駽駾駿騀騁騂騃騄騅騆騇騈騉騊騋騌騍騎騏騐騑騒験騔騕騖騗騘騙騚騛騜騝騞騟騠騡騢騣騤騥騦騧騨騩騪騫騬騭騮騯騰騱騲騳騴騵騶騷騸騹騺騻騼騽騾騿驀驁驂驃驄驅驆驇驈驉驊驋驌驍驎驏驐驑驒驓驔驕驖驗驘驙颉颌颍颏颔颚颛颞颟颡颢颥颦虍虔虬虮虿虺虼虻蚨蚍蚋蚬蚝蚧蚣蚪蚓蚩蚶蛄蚵蛎蚰蚺蚱蚯蛉蛏蚴蛩蛱蛲蛭蛳蛐蜓蛞蛴蛟蛘蛑蜃蜇蛸蜈蜊蜍蜉蜣蜻蜞蜥蜮蜚蜾蝈蜴蜱蜩蜷蜿螂蜢蝽蝾蝻蝠蝰蝌蝮螋蝓蝣蝼蝤蝙蝥螓螯螨蟒>驚驛驜驝驞驟驠驡驢驣驤驥驦驧驨驩驪驫驲骃骉骍骎骔骕骙骦骩骪骫骬骭骮骯骲骳骴骵骹骻骽骾骿髃髄髆髇髈髉髊髍髎髏髐髒體髕髖髗髙髚髛髜髝髞髠髢髣髤髥髧髨髩髪髬髮髰髱髲髳髴髵髶髷髸髺髼髽髾髿鬀鬁鬂鬄鬅鬆蟆螈螅螭螗螃螫蟥螬螵螳蟋蟓螽蟑蟀蟊蟛蟪蟠蟮蠖蠓蟾蠊蠛蠡蠹蠼缶罂罄罅舐竺竽笈笃笄笕笊笫笏筇笸笪笙笮笱笠笥笤笳笾笞筘筚筅筵筌筝筠筮筻筢筲筱箐箦箧箸箬箝箨箅箪箜箢箫箴篑篁篌篝篚篥篦篪簌篾篼簏簖簋A鬇鬉鬊鬋鬌鬍鬎鬐鬑鬒鬔鬕鬖鬗鬘鬙鬚鬛鬜鬝鬞鬠鬡鬢鬤鬥鬦鬧鬨鬩鬪鬫鬬鬭鬮鬰鬱鬳鬴鬵鬶鬷鬸鬹鬺鬽鬾鬿魀魆魊魋魌魎魐魒魓魕魖魗魘魙魚魛魜魝魞魟魠魡魢魣魤魥魦魧魨魩魪魫魬魭魮魯魰魱魲魳魴魵魶魷魸魹魺魻簟簪簦簸籁籀臾舁舂舄臬衄舡舢舣舭舯舨舫舸舻舳舴舾艄艉艋艏艚艟艨衾袅袈裘裟襞羝羟羧羯羰羲籼敉粑粝粜粞粢粲粼粽糁糇糌糍糈糅糗糨艮暨羿翎翕翥翡翦翩翮翳糸絷綦綮繇纛麸麴赳趄趔趑趱赧赭豇豉酊酐酎酏酤E魼魽魾魿鮀鮁鮂鮃鮄鮅鮆鮇鮈鮉鮊鮋鮌鮍鮎鮏鮐鮑鮒鮓鮔鮕鮖鮗鮘鮙鮚鮛鮜鮝鮞鮟鮠鮡鮢鮣鮤鮥鮦鮧鮨鮩鮪鮫鮬鮭鮮鮯鮰鮱鮲鮳鮴鮵鮶鮷鮸鮹鮺鮻鮼鮽鮾鮿鯀鯁鯂鯃鯄鯅鯆鯇鯈鯉鯊鯋鯌鯍鯎鯏鯐鯑鯒鯓鯔鯕鯖鯗鯘鯙鯚鯛酢酡酰酩酯酽酾酲酴酹醌醅醐醍醑醢醣醪醭醮醯醵醴醺豕鹾趸跫踅蹙蹩趵趿趼趺跄跖跗跚跞跎跏跛跆跬跷跸跣跹跻跤踉跽踔踝踟踬踮踣踯踺蹀踹踵踽踱蹉蹁蹂蹑蹒蹊蹰蹶蹼蹯蹴躅躏躔躐躜躞豸貂貊貅貘貔斛觖觞觚觜H鯜鯝鯞鯟鯠鯡鯢鯣鯤鯥鯦鯧鯨鯩鯪鯫鯬鯭鯮鯯鯰鯱鯲鯳鯴鯵鯶鯷鯸鯹鯺鯻鯼鯽鯾鯿鰀鰁鰂鰃鰄鰅鰆鰇鰈鰉鰊鰋鰌鰍鰎鰏鰐鰑鰒鰓鰔鰕鰖鰗鰘鰙鰚鰛鰜鰝鰞鰟鰠鰡鰢鰣鰤鰥鰦鰧鰨鰩鰪鰫鰬鰭鰮鰯鰰鰱鰲鰳鰴鰵鰶鰷鰸鰹鰺鰻觥觫觯訾謦靓雩雳雯霆霁霈霏霎霪霭霰霾龀龃龅龆龇龈龉龊龌黾鼋鼍隹隼隽雎雒瞿雠銎銮鋈錾鍪鏊鎏鐾鑫鱿鲂鲅鲆鲇鲈稣鲋鲎鲐鲑鲒鲔鲕鲚鲛鲞鲟鲠鲡鲢鲣鲥鲦鲧鲨鲩鲫鲭鲮鲰鲱鲲鲳鲴鲵鲶鲷鲺鲻鲼鲽鳄鳅鳆鳇鳊鳋K鰼鰽鰾鰿鱀鱁鱂鱃鱄鱅鱆鱇鱈鱉鱊鱋鱌鱍鱎鱏鱐鱑鱒鱓鱔鱕鱖鱗鱘鱙鱚鱛鱜鱝鱞鱟鱠鱡鱢鱣鱤鱥鱦鱧鱨鱩鱪鱫鱬鱭鱮鱯鱰鱱鱲鱳鱴鱵鱶鱷鱸鱹鱺鱻鱽鱾鲀鲃鲄鲉鲊鲌鲏鲓鲖鲗鲘鲙鲝鲪鲬鲯鲹鲾鲿鳀鳁鳂鳈鳉鳑鳒鳚鳛鳠鳡鳌鳍鳎鳏鳐鳓鳔鳕鳗鳘鳙鳜鳝鳟鳢靼鞅鞑鞒鞔鞯鞫鞣鞲鞴骱骰骷鹘骶骺骼髁髀髅髂髋髌髑魅魃魇魉魈魍魑飨餍餮饕饔髟髡髦髯髫髻髭髹鬈鬏鬓鬟鬣麽麾縻麂麇麈麋麒鏖麝麟黛黜黝黠黟黢黩黧黥黪黯鼢鼬鼯鼹鼷鼽鼾齄 N鳣鳤鳥鳦鳧鳨鳩鳪鳫鳬鳭鳮鳯鳰鳱鳲鳳鳴鳵鳶鳷鳸鳹鳺鳻鳼鳽鳾鳿鴀鴁鴂鴃鴄鴅鴆鴇鴈鴉鴊鴋鴌鴍鴎鴏鴐鴑鴒鴓鴔鴕鴖鴗鴘鴙鴚鴛鴜鴝鴞鴟鴠鴡鴢鴣鴤鴥鴦鴧鴨鴩鴪鴫鴬鴭鴮鴯鴰鴱鴲鴳鴴鴵鴶鴷鴸鴹鴺鴻鴼鴽鴾鴿鵀鵁鵂 Q鵃鵄鵅鵆鵇鵈鵉鵊鵋鵌鵍鵎鵏鵐鵑鵒鵓鵔鵕鵖鵗鵘鵙鵚鵛鵜鵝鵞鵟鵠鵡鵢鵣鵤鵥鵦鵧鵨鵩鵪鵫鵬鵭鵮鵯鵰鵱鵲鵳鵴鵵鵶鵷鵸鵹鵺鵻鵼鵽鵾鵿鶀鶁鶂鶃鶄鶅鶆鶇鶈鶉鶊鶋鶌鶍鶎鶏鶐鶑鶒鶓鶔鶕鶖鶗鶘鶙鶚鶛鶜鶝鶞鶟鶠鶡鶢 R鶣鶤鶥鶦鶧鶨鶩鶪鶫鶬鶭鶮鶯鶰鶱鶲鶳鶴鶵鶶鶷鶸鶹鶺鶻鶼鶽鶾鶿鷀鷁鷂鷃鷄鷅鷆鷇鷈鷉鷊鷋鷌鷍鷎鷏鷐鷑鷒鷓鷔鷕鷖鷗鷘鷙鷚鷛鷜鷝鷞鷟鷠鷡鷢鷣鷤鷥鷦鷧鷨鷩鷪鷫鷬鷭鷮鷯鷰鷱鷲鷳鷴鷵鷶鷷鷸鷹鷺鷻鷼鷽鷾鷿鸀鸁鸂 0T鸃鸄鸅鸆鸇鸈鸉鸊鸋鸌鸍鸎鸏鸐鸑鸒鸓鸔鸕鸖鸗鸘鸙鸚鸛鸜鸝鸞鸤鸧鸮鸰鸴鸻鸼鹀鹍鹐鹒鹓鹔鹖鹙鹝鹟鹠鹡鹢鹥鹮鹯鹲鹴鹵鹶鹷鹸鹹鹺鹻鹼鹽麀麁麃麄麅麆麉麊麌麍麎麏麐麑麔麕麖麗麘麙麚麛麜麞麠麡麢麣麤麥麧麨麩麪 U麫麬麭麮麯麰麱麲麳麵麶麷麹麺麼麿黀黁黂黃黅黆黇黈黊黋黌黐黒黓黕黖黗黙黚點黡黣黤黦黨黫黬黭黮黰黱黲黳黴黵黶黷黸黺黽黿鼀鼁鼂鼃鼄鼅鼆鼇鼈鼉鼊鼌鼏鼑鼒鼔鼕鼖鼘鼚鼛鼜鼝鼞鼟鼡鼣鼤鼥鼦鼧鼨鼩鼪鼫鼭鼮鼰鼱 PW鼲鼳鼴鼵鼶鼸鼺鼼鼿齀齁齂齃齅齆齇齈齉齊齋齌齍齎齏齒齓齔齕齖齗齘齙齚齛齜齝齞齟齠齡齢齣齤齥齦齧齨齩齪齫齬齭齮齯齰齱齲齳齴齵齶齷齸齹齺齻齼齽齾龁龂龍龎龏龐龑龒龓龔龕龖龗龘龜龝龞龡龢龣龤龥郎凉秊裏隣 X兀嗀﨎﨏﨑﨓﨔礼﨟蘒﨡﨣﨤﨧﨨﨩 KpZ€   $!($,'0*4-80<3@6D9H<L?PBTEXH\K`NdQhTlWpZt]x`bXcdADGKNQR(TUHWXhZZ Z  \ O \  <]  \]  |] W ]  ] @AB ]  ] _ ^  ^  _]% ` ` \CDEFG `  h` GHY |`  ` IJKLOa MNO8a PQRa Sa Wa b xbb TUVWXYZ[\]^_`abcdefghijklmnopqrstuvw_d xyz{|}~d De %xe ge``]t``a0aaaabpbbcd>ҫSTUVWˣXYZ[\]^_`abcdefghijkҮlmno?pqrstuvְwxyz{|}~Ƹ€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ @@ABCDEFGHIJKLMФNOP֫QRSTUVWXYZ[\Aвθ]^_`ab̥cdefghijʤklmnطopqrstuvBwx֬yz{|}~ÀŧÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßƢàC@ABCDEFGҸHIJKǻLMNOPQRSTUVWXYZ[\]^_`abcDdefghijklmnopqrstuvwĤϥxyz{|}~ĀāĂ㥹ĆćĈĉĊċČčĎďĐđĒēEӷĔĕĖėĘęĚěĜĝĞğĠ@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`aGҨbcdefghijklmnopq˴rstuvwxyz{|}~HŀŁłŃńŅͧņŇňʼnŊŋŌōŎŏŐőŒœŔŕŖŗŘřŚśŜŝŞşŠ@ABCDɫEFGHܳIJܴܵIKLMܹNOPQܷRܺܶSܻâTUVWܼܽXY֥Z[\]«^ܸܾо_`aܿbcdѿe(JfghijέklԷ̦mnopqrstuɻvwxyӢz{|}~ƻƀƁƂƃƄ4KƅïéƆƇƈƉƊƋƌƍƎݢƏƐƑƒƓƔƕƖƗƘƙƚãƛƜƝƞƟƠ@A@LBCDEFGHIJKLMNOPQRSӫݡݣݥݤݦݧҩTUVWXYZݩ[\ݶݱݴ]^LM_`abcݰdefghiɯjklݮmnopݷqrݯsݸtݬuvwxyz{ݹݳݭĪ|}~ǀݨݪݫǁݲݵӨݺǂݻçǃDŽXNݼDždžLJLjljNJNjnjǍǎǏǐǑǒǓݿǔǕǖǗǘǙǚݾǛǜǝǞǟǠ@ABCDEFGHIJKdOLݽMNOPQRƼήSTUVWXYZ[\]^_`abөӪcdefghijklmnopqrstupPvwxyz{|}~ȀȁȂȃȄȅȆȇȈȉȊȋȌȍȎȏȐȑȒȓȔȕȖȗȘșȚțȜȝȞȟȠ@AB|QCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnoRpqrstuvwxyz{|}~ɀɁɂɃɄɅɆɇɈɉɊɋɌɍɎɏɐɑɒɓɔɕɖɗɘəɚɛޤɜɝޣSɞɟɠ@ABCDEFGHIJKLMNOPQRεSTUVWXYZ[\]^_`abcdefghijǾޢklTmnoެpqrsަtuvwxyz{|}~ޡʀʁޥʂʃʄʅީʆʇʈʉʊިʋʌʍާʎʏʐʑʒʓʔʕʖޭʗʘʙʚʛ޳ުޮʜʝʞUʟʠ@A޶BޱCDEFGHI޲JKLMNOPQRSTѦ޵UVWXYZ[ޯ\]^ް_н`ab޴޹cdefgh޸i޷jklmnoVp޻qrstuvwxyz{|}~޺ˀźˁ˂˃˄˅ˆ޼ˇˈˉˊˋˌˍˎˏːˑ˒˓˔˕˖˗˘˙˚˛˜˝˞˟ˠ@ABCD޽WEFGHI޿JKLMNOPQRSTĢUVWXYZ[\]^_`abcdefgh޾ijklmnopqrstuvwպxyz{|}X~̀́̂̃̄̅̆̇̈̉̊̋²Ư̖̗̘̙̜̝̞̟̠̋̌̍̎̏̐̑̒̓̔̕̚@ABʭCDEFGHIϺYʴJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopZqrstuvwxyz{|}~͇͈͉͍͎̀́͂̓̈́͆͊͋͌ͅ͏Ӽ͓͔͐͑͒[͕͖͙͚͗͛֩͘͜͟͝͞͠@ABCDEFGHIJKLMNOPQRSTUVW]XYZ[\]^Ӭ_`aЫbcdefghijklmnopqrstuvwxyz{|}~΀΁΂΃΄ ^΅Ά·ΈΉΊ΋Ό΍ΎΏΐΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠ@ABCDEFGHIJKLMNOPQ_RSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~зπρςστ$`υφχψωϊϋόύώϏϐϑϒϓϔϕϖϗϘϙϚϛϜϝϞϟϠ@ABCDEFGHIJKLMNOPQRSTUVWX0aѪYZ[\]^_`abcdefghijklmnopqrstuv˥wxyz{|}~ЀЁ?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_@   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRS@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRST@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVW@  !"#$%&'()*+,-./0123456789:;<=>?@ABCD@  !"#$%&'()*+,-./0123456789:;<=>?@ABC@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVVVVVVVVVVVWXYZ[\]^_`abcdefghijklmnopqVrsVtVVVVuvwxyz{|}~VVVVVVVVVVVVVVVVVVVVV@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~@   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~       !"#$%&'(   !"#$%&'()*+,-./012                 !"#$%&'()*+,-./0123456789:;<=>?@  !"#$%&'()*+,-./01         !"#  !"#$%&'()*+,-./012345678  !"#$%&'()*+,-./01234567888889:;8  !"#$%&      !"#$%&''''''''''''''''''''''''''      !"#$%&      ;$@hzRx $80FJ w?:*3$"D@ \$HWGNUP`"p\pu h P"X"o`  "08h oooo "GA$3a1h GA$3p1067GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realigngbk.so-2.2.10-35.el8.x86_64.debug7zXZִF!t/]?Eh=ڊ2NpI Q{H ;qµ2 oy406j_jGby}s8}g⻑u,$.|ʔRCWˌp3S)VVj\ c5!ʮ%sS0F Ƣ/eS*7(Ldq(?!i-i Y;Y/yug8mTЪoBWA5~o,>b=x J"w p ,Xֆ#WueLց(Vk/*_y_ wЕ Y1Nhzɉ!bڽ0HliC+,|$Xj+{o|&;2o;s#ugYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 08oEo Th^B880hhhc0n w} 0 $88t P"PX"X`"`` " " "(("(0b(  (HD+PK!2 '2.2.0/x86_64-linux/enc/trans/gb18030.sonuȯELF>@@H@8 @ PP"P" ""  888$$ȪȪȪ StdȪȪȪ PtdDDQtdRtdPP"P"GNUUm8m\@jI@ @( BE|qX9 b , F"("0"("U ` $__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeInit_gb18030rb_register_transcoderlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ui P"X"`"`"" " "@" "p" " (" 8"@H" ""0 """"" "HH "HtH5"%"hh%"D%"DH="Hڨ"H9tH"Ht H="H5"H)HHH?HHtHU"HtfD=m"u+UH=2"Ht H="YdE"]wV-0ii81V{PF ?ʀQƒ?Ȁ?AʀQÐFAA  % Fv?  AAA)DЃ0AAk~)׺ih@yA)lj0@ypHVtQBVk~ЍFP)- Aƒ?Ȁ?A@ʀAP)]f.VH  V? tgn:̉r2)0AH k~J)ƉApA)0AH ffAHH="H="HHHUTF-8GB18030€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“4”•–—˜™š›œhžŸ ¡¢£¥¦©ª«¬­®¯²³´µ¶¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊË8ÌÍÎÏÐÑÒÓÔÕlÖØÙÚÛÜÝÞßâãäåæçëîïðñôõöøûýþÿĀĂ㥹ĆćĈĉĊċČ<čĎďĐđĒĔĕĖėpĘęĚĜĝĞğĠġĢģĤĥĦħĨĩĪĬĭĮįİıIJijĴĵĶķ ĸĹĺĻļĽľĿŀŁ@łŃŅņŇʼnŊŋŌŎtŏŐőŒœŔŕŖŗŘřŚśŜŝŞşŠšŢţŤťŦŧŨũŪŬŭŮůŰűŲųŴŵŶŷDŸŹźŻżŽžſƀƁxƂƃƄƅƆƇƈƉƊƋƌƍƎƏƐƑƒƓƔƕƖƗƘƙƚƛƜƝƞƟƠơƢƣƤƥƦƧƨƩHƪƫƬƭƮƯưƱƲƳ|ƴƵƶƷƸƹƺƻƼƽƾƿǀǁǂǃDŽDždžLJLjljNJNjnjǍǏǑǓǕǗǙǛǝǞǟǠǡǢǣLǤǥǦǧǨǩǪǫǬǭǮǯǰDZDzdzǴǵǶǷǸǺǻǼǽǾǿȀȁȂȃȄȅȆȇȈȉȊȋȌȍȎȏȐȑȒȓȔȕȖPȗȘșȚțȜȝȞȟȠȡȢȣȤȥȦȧȨȩȪȫȬȭȮȯȰȱȲȳȴȵȶȷȸȹȺȻȼȽȾ ȿɀɁɂɃɄɅɆɇɈTɉɊɋɌɍɎɏɐɒɓɔɕɖɗɘəɚɛɜɝɞɟɠɢɣɤɥɦɧɨɩɪɫɬɭɮɯɰɱɲ$ ɳɴɵɶɷɸɹɺɻɼX ɽɾɿʀʁʂʃʄʅʆ ʇʈʉʊʋʌʍʎʏʐ ʑʒʓʔʕʖʗʘʙʚ ʛʜʝʞʟʠʡʢʣʤ( ʥʦʧʨʩʪʫʬʭʮ\ ʯʰʱʲʳʴʵʶʷʸ ʹʺʻʼʽʾʿˀˁ˂ ˃˄˅ˆˈˌˍˎˏː ˑ˒˓˔˕˖˗˘˚˛, ˜˝˞˟ˠˡˢˣˤ˥` ˦˧˨˩˪˫ˬ˭ˮ˯ ˰˱˲˳˴˵˶˷˸˹ ˺˻˼˽˾˿̀́̂̃ ̄̅̆̇̈̉̊̋̌̍0 ̖̗̎̏̐̑̒̓̔̕d ̡̛̘̙̜̝̞̟̠̚ ̢̧̨̣̤̥̦̩̪̫ ̴̵̬̭̮̯̰̱̲̳ ̶̷̸̹̺̻̼̽̾̿4 ͇͈͉̀́͂̓̈́͆ͅh ͍͎͊͋͌͏͓͐͑͒ ͔͕͖͙͚͗͛͘͜͝ ͣͤͥͦͧͨͩͪͫͬͭͮͯ͟͢͞͠͡Ͱͱ8Ͳͳʹ͵Ͷͷ͸͹ͺͻlͼͽ;Ϳ΀΁΂΃΄΅Ά·ΈΉΊ΋Ό΍ΎΏΐ΢ΪΫάέήίΰςϊϋόύώϏϐϑϒϓ<ϔϕϖϗϘϙϚϛϜϝpϞϟϠϡϢϣϤϥϦϧϨϩϪϫϬϭϮϯϰϱϲϳϴϵ϶ϷϸϹϺϻ ϼϽϾϿЀЂЃЄЅІ@ЇЈЉЊЋЌЍЎЏѐtђѓєѕіїјљњћќѝўџѠѡѢѣѤѥѦѧѨѩѪѫѬѭѮѯѰѱѲѳѴѵѶѷѸѹDѺѻѼѽѾѿҀҁ҂҃x҄҅҆҇҈҉ҊҋҌҍҎҏҐґҒғҔҕҖҗҘҙҚқҜҝҞҟҠҡҢңҤҥҦҧҨҩҪҫHҬҭҮүҰұҲҳҴҵ|ҶҷҸҹҺһҼҽҾҿӀӁӂӃӄӅӆӇӈӉӊӋӌӍӎӏӐӑӒӓӔӕӖӗӘәӚӛӜӝLӞӟӠӡӢӣӤӥӦӧӨөӪӫӬӭӮӯӰӱӲӳӴӵӶӷӸӹӺӻӼӽӾӿԀԁԂԃԄԅԆԇԈԉԊԋԌԍԎԏPԐԑԒԓԔԕԖԗԘԙԚԛԜԝԞԟԠԡԢԣԤԥԦԧԨԩԪԫԬԭԮԯ԰ԱԲԳԴԵԶԷ ԸԹԺԻԼԽԾԿՀՁTՂՃՄՅՆՇՈՉՊՋՌՍՎՏՐՑՒՓՔՕՖ՗՘ՙ՚՛՜՝՞՟ՠաբգդեզէըթ$ժիլխծկհձղճXմյնշոչպջռսվտրցւփքօֆևֈ։֊֋֌֍֎֏֐֑֖֛֚֒֓֔֕֗֘֙(֢֣֤֥֜֝֞֟֠֡\ְֱֲֳִֵֶַָֹֺֻּֽ֦֧֪֭֮֨֩֫֬֯־ֿ׀ׁׂ׃ׅׄ׆ׇ׈׉׊׋׌׍,׎׏אבגדהוזח`טיךכלםמןנסעףפץצקרשת׫׬׭׮ׯװױײ׳״׵׶׷׸׹׺׻׼׽׾׿0؀؁؂؃؄؅؆؇؈؉d,`0d4h8l<p @tDxH|L P T $ X ( \ , ` 0d4h8l<p @tDxH|LP T$X(\ ؊؋،؍؎؏ؘؙؚؐؑؒؓؔؕؖؗ؛؜؝؞؟ؠءآأؤإئابةتثجحخدذر8زسشصضطظعغػlؼؽؾؿـفقكلمنهوىيًٌٍَُِّْٕٖٜٟٓٔٗ٘ٙٚٛٝٞ٠١٢٣<٤٥٦٧٨٩٪٫٬٭pٮٯٰٱٲٳٴٵٶٷٸٹٺٻټٽپٿڀځڂڃڄڅچڇڈډڊڋ ڌڍڎڏڐڑڒړڔڕ@ږڗژڙښڛڜڝڞڟtڠڡڢڣڤڥڦڧڨکڪګڬڭڮگڰڱڲڳڴڵڶڷڸڹںڻڼڽھڿۀہۂۃۄۅۆۇDۈۉۊۋیۍێۏېۑxےۓ۔ەۖۗۘۙۚۛۜ۝۞ۣ۟۠ۡۢۤۥۦۧۨ۩۪ۭ۫۬ۮۯ ۰۱۲۳۴۵۶۷۸۹H ۺۻۼ۽۾ۿ܀܁܂܃| ܄܅܆܇܈܉܊܋܌܍ ܎܏ܐܑܒܓܔܕܖܗ ܘܙܚܛܜܝܞܟܠܡ!ܢܣܤܥܦܧܨܩܪܫL!ܬܭܮܯܱܴܰܲܳܵ!ܷܸܹܻܼܾܶܺܽܿ!݂݄݆݈݀݁݃݅݇݉!݊݋݌ݍݎݏݐݑݒݓ"ݔݕݖݗݘݙݚݛݜݝP"ݞݟݠݡݢݣݤݥݦݧ"ݨݩݪݫݬݭݮݯݰݱ"ݲݳݴݵݶݷݸݹݺݻ"ݼݽݾݿހށނރބޅ #ކއވމފދތލގޏT#ސޑޒޓޔޕޖޗޘޙ#ޚޛޜޝޞޟޠޡޢޣ#ޤޥަާިީުޫެޭ#ޮޯްޱ޲޳޴޵޶޷$$޸޹޺޻޼޽޾޿߀߁X$߂߃߄߅߆߇߈߉ߊߋ$ߌߍߎߏߐߑߒߓߔߕ$ߖߗߘߙߚߛߜߝߞߟ$ߠߡߢߣߤߥߦߧߨߩ(%ߪ߲߫߬߭߮߯߰߱߳\%ߴߵ߶߷߸߹ߺ߻߼߽%߾߿%%0d4h8l<p @ t !D!x!!!"H"|"""#L####$P$$$$ %T%%%%%%%$&&& '('8'L'\'t''~'~'~r'h'hd`'`'`_ (^]\[ (WVUPO<(OKJ\(JIHt(HG(GEA((A?4(?(?>=@(=<(<)<;L);,);:X<):P)%&' '0'D'T'l''''''''((4(T(l((((((())$)4)H)X)d`):0)0**$*8*H*`*t**~*~}{*{*{wL*w*wut*t+tsr +r8+X)) **0*@*X*l*|*******++0+@+H+rq+qpom+@++++ml+l+lkji  ,hfe@(,ed@,dT,dXTA,d,A?6,6,658,޻D,`,`,`VUP,U-UT$-T8-TRH-RO\-Np-NM-MLJI\-I-H-HGX-G-+, ,8,L,\,x,,,,,,, --0-@-T-h-x-------h-&&)++`.54,*&   ߐېՐѐϐΐ̐Ð{zyolkjigedb`^\[ZYXWVUTSh.GFL0F,0FE<0EDXP0Dd0DCt0C0CBX0B0-$040H0\0l000000B@0@1@?X1?(1>81>=H1=\1=<4l1<1<;1;100 1 101@1T1d1x111191;:X1:2:929(298828L211 2 202D2T2\2876E26265L25254242432333232,3214<30P30/`3/.t3.3T222222233$343H3X3l333Q3.-3-3-,4,+)'4'84'&%H4%`4%#Lp4#4#"4"4"X4444334404@4X4h4|444444445L5`5oiXp5oi54X5h5|55]55$501|23D555~}yxwvsponmlkjihgdcba_\YXWVUSRPONMLKIHEDCBA@=<;95oiZ6YYL6YiYfY 6eYdY7dYbY`Y $7`Y_YX<7^YP7^Y\Y`7\Yt7[Y75667747H7X7l7|77 77$7577zyxwurqpomnlkhdba`_\[ZYXWSQJGDCA?>;:87642-*'&%#" F 7[YZY48ZY8ZYYYL8YY8YYXY9XY9XYWY,9WYVY@9VYT9VYRYQYOYNY d9NYKYIYFY# 9FY9788899$989L9\9|999/ 9FYDY2Y92Y(Y$YYY :Y(:YX48:XL:XX\:Xp: :9: :0:D:T:h:x:: ::$:9::_^][ZYXVUSMHEDB@:98754210*)$#! ; ::&#!   ޏ܏ۏڏُ؏֏ЏϏΏʏɏǏÏ~}usrqpolhedcba_\[XUT ;:{qpnjdb`_]\[YXUTSRONMIHGFDCA@>=;:9541-+*%     =:1/.,+*(&%#!    >:%$#"  ߎގ܎ێَ؎֎ӎҎЎώΎ͎̎ɎȎǎƎĎÎŽ?:ߎގݎ܎ڎَ؎׎֎ՎԎӎҎюЎ͎ˎʎɎǎƎÎP@:ݎڎَ؎֎ԎӎҎώЎ̎ʎɎȎǎƎŎÎ!A:֎ՎԎӎώΎ͎̎ʎɎȎǎƎŎÎŽB:ݎێڎ؎׎֎ՎԎҎώ̎ʎɎȎǎutplkjigfdba_^\[YWVOM;87610e@E:qolkjihged]\ZYXWVTSQOMLKJHGFEC?><;:864321/,*$#"!  6FLGTG$\GdG/.+*'&#!   ߍލ܍ڍ؍׍֍ՍԍҍЍ̍ƍčÍlGdGݍ܍ۍڍٍ؍֍ԍӍҍэЍύ΍ōHdGߍ׍֍ՍԍӍЍύ͍ʍƍčwvtsrpomkjdca^]\ZYWUTSONKJIHGED@=<:8765TIdGvutsonmljigfedcba]\ZXVTSQRPNMLKJIDCBA@?>=<9865310/.-*)(&%$#"!zJdG\[ZYXWVUTSQNLKIHFEDCA@?=;:8765431/.-,*)(&%$#"  KKdGECBA?>=<:765320/.-*)('&$#    LdG3/.-+*)('&%!   ߌ݌׌ԌьЌόΌ͌̌ɌnjƌČÌMdGیьЌό͌̌ˌɌȌnjƌŌŒOdG֌ՌԌӌҌьΌ͌̌ˌʌƌŌÌŒOdGیڌٌ،׌֌ՌԌӌьЌό͌Ȍnj`PdGߌތ܌یڌٌ،ҌьЌό͌̌ˌʌɌȌŌČ1QdGތ׌֌ӌҌьЌόΌ̌ɌnjŌČŒ~{zyxvurqplkjfda][ZYXWVTRQONMLJIHGDC><64321/+RdGjihfdba`^]\[ZYWVURPOMLKIFEDCBA@?=;987654310.-+*)('&%$#!  SdGGFEDCBA>=<9876543210/.-,+)('&%$#! TdGQONLKJIHGDB@?>;:876320+*)&#u!UdG[ZYURQPONLKJHEDAB@?>=<;:7643210/.-+)('&%$#"F"VdGa`_^]\[ZYXVQPONLJIHGFEDB@?=<;954210/.,*)%! #VdGqr·ˉˇ¨D~±×÷/jpco°¤§#%KM;=_ba#WdG(< Hp.nx$XdG%YdGQRWy[&@YdGq,'`YdGΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ+αβγδεζηθικλμνξοπρστυφχψωCOTV'YdG12АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщъыьэюя:(ZdGˊˋ˙'&96/&#xnāáǎàēéěèīíǐìōóǒòūúǔùǖǘǚǜüêɑńňǹɡ)[dGzxv kjm/ oCp[]V   Bp*\dG[ZXVMKHGFEDC@<:95432/-.,+*)'&(A+H]dGŕĕÕ•:),]dG?><:8653210/.*)('#! ),`^dG~*-^dGDCA@?>=<;876530+*(&%$#"  +.(_dG}zxvutsponmlkhgeda^]\YXWTS+V/_dGߗޗݗܗۗڗٗח֗՗ԗNZx׶sι޹Te%txw g^ Ŏ3TqlҺWаQw>mwjQRbEfZv]pE?~aLi'ayb̂'0`dGsqpoihedcb`^][ZYXWTSRPNMLJKIEDCA@?=;xz+v(s5V!ގ {Ů_ŌŢUp~FȱCҙypİ 1Tyy(x~54ڧxK|s[}^/z@-*xvB0bdGژט՘ԘҘј͘˘ȘƘĘØ˜Ӛ#ߜ{F޽{vq9vXRKѸOvҫkoR~Xw1<ۯK'զک@0Ln -P!o1bwׄϑ{JzOxߝ1ddGQPOKJIHBA?=<9865410.-,&%$#"! ^|b|A[p }u:dzuF>  5)ЏNƱ/q{9O+͗fyj۰AH>wȽ؛̮obwUrMs4*r״?#un׃ėm dϿ}Gi|#{2{2fdGXÚ´!dj sF|s#8}.s,¤ɓ{ wɝ^t\V׻ÿ6CȖ R7m*ёל 2ή}(ùsJɴjhoǂk3hdG*)('&#"    x\հbGْs\åLJm܌UPJIKg;zd#7PNCv/vѤ܃{&9Nƒ6{UA!c|2J$&]}bZ#R|<4jdG~}|{&|uqA>PN~jڞQ,ˡAo`}$/ә֜¼x~Ҹ#\iQ|5՝N>(˼v H|-ºrenn{޸~{çi 5tldG  h@LNʨС9gĤ؅C|֨h w~ˑ`~^|Ɖ'ppSIֵ-ع/َҀ}03Ɩ'sGw,_ҩ̚5|ndG}|{yxwutsrqnmj* rńtS V39#_'y7p.'BՊ:$6N|ś(PggC+4:sJ{HD߲ٴxKs}WݖZ<6TpdGߛכ֛՛ԛӛֿZa1x6H8 Δפ , )Ux}|DwǴȎuԮ\812N~[lBx{|n b!V--7XrdGrponmkjigfedcba`^]\ZYXU}0#u~<xӼS^!YhF(Mͬ܇=TI"I8p?ǂajzzKm/xkezRʹA[6No~#*Q8xtdGݜܜqKn gSdҪiʍد]\؉PˣT?ipzĠh:͸xzzYBk=koڟ(zг~|1ӷނŌuz`"9\vdGxwvtsqnmljihgfedcba 4۪||!˱X88ӕ34RJvlݴ|/ܛU*qBVZ~þa5ohݛ#4oi{1ŅG9 xdG3iI,]E?R:_dm1ɆϣܨECjOFC2ܷ%Eԡv%O~c]j֮ ɹ8<BĮĞƆ(Ə}q"}:ydG[T9B(׻՝@8 P'?P)Yѡӡ˸@"̄uC_knٶŚ5+& RN#xf_1w~ma_Q#:.%KX;{dG<=;:@ >,=}[6ΠTѬV@ݚʵŴ% w"Ǒ"VyR}z(0o %7aF.Ϻj9'&8_1L}uf<}dGٟ؟ןɟğupcKJIHFDr7W7ο ۻ]CFVЙDʻâC֯)«XecŞ[_.}ׇbRBK\|$D5]'ЯުC`նe>kki%7=~dGߟޟݟ۟؟ן՟ԟӟҟџПϟΟ̟͟ɟȟǟƟğŸΤMŏ4Nra0D/9 q&[<Aa-'6צ &WDkl5]Jޫ4~[ɩXZ6>dGSQPOMLJHDA@?98760/.*)('%$ T ̤VADZ) {m1S.^nBۋV[m5:ޱġ\SX*f+_*~/8WW%FaxcyD$\]ߛʱ>dGysrqpnmljkcba`_^][ZYXootǵȩތ6krc)9M"t)!ԋƋ'g.hԑ[   Cע{\KL՜z׵*+=P̓vȕ}?dGڠ٠ؠנ֠ՠԠѠРϠΠ͠ˠǠƠŠĠy4Ju˃[JںK]_ȫQQsl M}o PԌmOL֡&‹zaג$m$.ihɄokIt{@ĆdGcba`^\ZYVSQPONLJGFB?876543210/.?.L.2W ܝ]=K*q&|jɬrv, 3I#EpsB'9Uw kA߼=ݫxGkLAȈdG͡ʡǡš¡~}|srpomligdcb^[Z4[c^4ڨS\ ͋ů@"W^GAiX4vzԔ+kqɏ?eޠ^gҵKewyѣ Upf۸,uIeBĊdGۡ١֡ԡӡҡСϡ̡͡ˡǡȡá(\%5ؐ[ޕ"|%ІZLFewafV^'~|qH7Wj)9ĢH&U]\׷jj]n7(c*CշBdGIFDCB@?:98610/-,+'&%$! c\ع:ٰn nr7b@ם |+ұELҵݎ">vmD>?Pƞc\.m}uؑD[ܹǢ.4C0dGz6Iu4B0hpHPT^ǤjC9LΑdZ 9ix/}uy՞'|@ُr˥sT!g9"aIuҲ/عͲD$dG43210/.-+$# 1ym"˜k3dˏ+Ͱ1c<{.(T6U%8GIX5%OHH˦ PzrD5T uʉm=ĹaEdGCbG,tfqEz0X|<2LBAÙ: ҝqh2% T`=C^QN R`=ݮ=êݵ̬p{2FdG>=<;:9876510/.-+{OΩɧCx4X\}}O+@J¾  S`!#ع5*ĦǚV%wVSI%ƕA_O Kz˵|ը 0n2GdGʤɤȤX>cWP3ȖA1Wˬе5z1"4Wfn+@›Uo]P) ;n^4aUKOLaLeppGdG    )XpgUݩ~k:_.beFL04Ӗַ&+)dJs(q:0uH3}GJS]oӗ{HdG~}|{zywvt*R# yG ǘ"3.˺=w% q՗:cVL1)]߶6cA*} {9lĩMj>.vIdG    <y$VKZTUl 5b  xZN9c${6Q{׭XI8љE>ߗgS,!Z~nJOG)qGJdG~|{wvtrponmljgfecba`6q(8+aģ9!P%t^ $  ˥0@(bLv*ţT^}zxG_tr^K|dGQr5 y1 sVooٞJ5dyśV*e¶ϯ/?&gEpR<>WY Q+1<2פ} 3,eKxdG~}|{z(i', v|;\֡C޺6=J%*9>  }yۥR CMvЯ~^YWd+^*_ _*3OBlL$dG$ũ10k^"PkѢݯpO *,סXOgpњrORC!Rwȱll:><`xâboĥO`?MdGrQاI k0ݼ[ySܸ[ٸJ1i*KVedHc:<ѳ=ھæZ=O,3mg~\NtdGSRqҾɣڨoncZߵ[Dp)nNŲLDֺ) 4+Tk 2dAI+D; פ|'CH2ŧ-OdGש̩ĩyI=  s5I޹<"" WPkcknw|AtF}iKzv˚:ֶf ' &`[|sIMOdG ZXo6:|ga|o=ʵ3}ZN%1_O1"^gneiwu{)\XZLJ\! P8dG9Bh^&) $(g@|kytWI {o6dkD\ڭF5{F6ضn9GB79QdG)&ܪ۪٪ת֪ժԪӪЪϪΪͪ˪ɪȪƪĪêڬ׬٬֬լԬҬЬͬʬƬŬìn^}yts`\S;URQVDP>@;qRldGb`^[YXUTSRMLKIHGFCA?><;:8754/-,+*(&˨֨ިͨڨبǨʨ|vmkq  k{(LyoTU`bvrjn5?X3@4VJ8BSdGīë«[<6" &1.-$,#! ط'%·շȷݷڷƷӷQLķTdGRS0~1/2( ",.з޷ݷͷ ۷q}uw^KZLpdON&'-H17U նTdG٬άɬB^CU6;'`2*!1(޶׶}|jfi{^*'e]J%m/Rt0# "+o_UdG    ܬج׬~vJga`tb;*HO](@&_/ 18^9VdGusrqmlkhfcba`_^\[ZYWVUTSaC%jn*01x{s}Twkrc[N3 WWܹdG߭ݭܭ׭ѭέ̭ͭ˭ȭŭíaUF@><%  hXjW]~bK52] `]SONLDA?40)#~530.$'(X|dGQRz~h}wltVZQI><.ȧOLEC><975310F6=3%+} yxzXL TG:YľdGԾ:. h>!ӫҫ̫ͫ˫ƫū|7VLIRwml];: A JZܾ:_rXTvUuoW< PR7QWx\jD :10#(OAvebdywz$[<:-,lqXJ)&}oֳγٳճͳ~j{rzc[WRXQ7t,xoneJR[:˰ʰyxpJh^SAC  wm`tba`\_]ZXWRQONLKJIHQPONL\:ihXTAIG+8< (-! j1]\:ȱzw}Y?EH(3#$ Ůf`VmM1OG#H!6Kyz\|}5xv[._^l:߱ұͱ̱˱tE.gA`F :&0u$%IM8   '1_(yo>TxUAC+XTKRFA9yxutsrpomj0_:kgUNC?=;:8760-+*$!   ϹzzB3amtndoPD=#.yI|njdcb`E`p:~{zyxwYzxYDc_\R%  }lr|j{6dk]MG&*:`0:     vdcZXFϱα˱gZ5! Rj_WS5(1lt"}tjfWK@#%a :\<@4[D;E(* sUmv|_/82F.- Dtb:()64kfY]aO93*VNQiJ?C<5963540.1-'!#    EcX:ȴ~|{zxwut" d`:/.-,+*)_bI̯- y{}yxzvtsrqpnkjhgca]b?>=48*%"+- dt:}]x{\pn`k^dWGRK>;5/*)   UQI?>< q]N)(o{tre:=>  XR;:*0/1!$  "  `gkx|r_DL#f@:ݶ׶Ƕ¶zxts|wv]uh\giK6&3C9H;(Zg:0/.-,+*)'"yotc[]_zysqlhgdZVN931^ G{4)+*'   . j<5J.3ueVZ;+hH:68*2- ,([3\Mpkft`WSXLsjciW\Vh:[\]vJ|zxk*('&ܽ/W4ZGECB@?>:876542,*i:ݸܸڸѸ͸ȸ̸ʸɸǸƸĸ+# \z}y{wt޼tvߺպٺ˺źºYUSM DC̶öj:TUdtok:uok:uok:4/-'&#   Jv@l:|zyxwutsqpnmlkjihgfvmX:gbbbaawm:+b*b)b&b bbb-2t-'(-&8&E&--"?#"{"!"!--2--(TO-53t|0xn<068;=>?@AB4CtD8EFDGHLIJKLMOOP QRSTU VVWXY8YXYxYZ[\@]]X^^ __`|bdxfhjlltnLpPrptTvxyx{ }~x|(||tpإl0d|صԹtD4 Tdh(PXl8@|P4<oD 0@P`p 0@P`p 0@P`p 0@P`p 0@P`p 0@P`ppL 0@P`p 0@P`p 0@P`p 0@P`p 0@P`ppX 0@P`p 0@P`p 0@P`p 0@P`p 0@P`p 0@P`ppd 0@P`p 0@P`p 0@P`p 0@P`p 0@P`p 0@P`ppp 0@P`p 0@P`p 0@P`p 0@P`p 0@P`p 0@P`pp| 0@P`p 0@P`p 0@P`p 0@P`p 0@P`p 0@P`pp 0@P`p 0@P`p 0@P`p 0@P`p 0@P`p 0@P`pp 0@P`p 0@P`p 0@P`p 0@P`p 0@P`p 0@P`p p0@P`p 0@P`p 0@P`p 0@P`p 0@P`p 0@P`p 0@P`pp 0@@AP`p 0@P`pB 0@P`p 0@P`p 0@P`p 0@Pp`p 0@P`p 0@P`p 0@P`p 0@P`p 0@P`p 0@P`p€p 0@P`pÀÐ 0@P`pĀĐ 0@P`pŀŐ 0@P`pƀƐ 0@P`pǀǐ 0@P`pȀȐ 0p@P`pɀɐ 0@P`pʀʐ 0@P`pˀpː 0@P`p̀̐ 0@P`p̀͐ 0@P`p΀ΐ 0@P`pπϐ 0@P`pЀА 0p@P`pрѐ 0@P`pҀpҐ 0@P`pӀӐ 0@P`pԀԐ 0@P`pՀՐ 0@P`pր֐ 0@Pp`p׀א 0@P`p؀ؐ 0@P`pـِ 0@P`pڀڐ 0@P`pۀې 0@P`p܀ܐ 0@P`p݀ݐp  0@P`pހސ 0@P`p߀ߐ 0@P`p 0@P`p 0@P`p 0@P`p 0p@P`p 0@P`p 0@P`p 0@P`p 0@P`p 0@P`p 0@P`pp$ 0@P`p 0@P`p 0@P`p 0@P`p 0@P`p 0@P`pp0 0@P`p 0@P`p 0@P`p 0@P`p 0@P`p 0@P`p 0@Pp<`p 0@P`p 0@P`p 0@P`p 0@P`p 0@P`p 0@P`ppH 0@P`p!1AQaq!1AQaq!1AQaq!1AQaq!1AQaq!1pTAQaq!1AQaq!1AQaq!1AQaq!1AQaq!1AQaq!1AQaqp`!1AQaq!1AQaq!1AQaq!1AQaq!1AQaq!1AQaqpl!1AQaq!1AQaq!1AQaq!1AQaq!1AQaq!1AQaq!1AQpxaq!1AQaq!1AQaq!1AQaq!1AQaq!1AQaq!1AQaqp!1AQaq!1AQaq!1AQaq!1AQaq!1AQaq!1AQaq!1pAQaq!1AQaq!1AQaq!1AQaq!1AQaq!1AQaq!1AQaqp!1AQaq!1AQaq!1AQaq!1AQaq!1AQaq!1AQaqpp% qpC'&~+qp('.mq<pL'96/~q\~r(hqhb_ad`3rp'`_^]/\[&W#VUPOKJurJIHGpjEoAc?rx?>/=<rp,);:;spP):p0H}sH s0p*pPt`MK=;Ct|%#~}{wtwuttsr up8+r-q-po--m-l-kj-i-h-feKu@e-dupT,dXu,4LTp (@HXt08vTVxAn?6B5SvT5WvW޻v[]w`[wp,`V Uw$p-UTwLp8-TRON!xlNMzLxJvIcxp-I(H'Gxp-G&Fxp,0FE&E8&D)ypd0D?#Cky<C"ByTp0B""@{"?ytp(1?!>1zp81>!=szp\1=<yp1<;zp1<D\d ,4Ldlz ;:9{p2:9{{p(2928{pL2876{ 65A|, p2549{L p24(32|l p,32T1O0| 0/} /.I} p3.5-,+} +)'&%#} p4#"{X "~p p4|Q~ p4y p`554,*&u|s}bgg~   u acZQN}^vjujpZ_JG}zNyXm%~ <Wg.i C_, %H$ߐFLې1J/Ր9 ѐ5ϐ6ΐ̐ !( Ð YT z~vh^@\evIy{zpyB{~9zoJolksj[ixbgU)e&d(b$1`)^M\i[6ZY XWVUTS=0936  %~}yxwvsponmlka $ < D \ d        H P h         L 8|8@kljihgdcba_\YkXpWVV|UySgRtSPkON>M3LWK=5IIH@'xuE'DkCbBJA @=*<;9zizyxwurqpo`omnlkZh^dwbwa`x_f\P[PZ9Y}X:WW6kSC8Q\Nze_cFJtaXG/4\\DLCC+ALC?>C?;:X81764G23@B*:-8$*97'q&%#" _^][ZYXVUSMHEDB@:Ͽ98754210bnp*)Tv$#Z!wIk{wuw19s\C70ZXkLJ  E*G'H% >y޽Xÿ&#! cyd[XSU Vc GoFR~JS>AiDednL=6()87Sm5^\?xenke%L1@DN"6ޏG܏ۏ ڏُh؏4֏ЏϏΏʏɏǏÏҺÄȽxznusttyg~l}a]`bPuVssmr]qpkoO_:lIHhgoveGNd;c@bIa8_5%'\I[* XZ(UT/8&17!  ޹ -{ ιqpnjdb`_]˅l\[YXUTSRONnMpnpIjHaGF 4DCwA}@N>=C;:^94HC5K4O1%$-0_+**O%.9%[ ^  "J?9'3    ӆ4!1/.,+*(&%#u! |!V{x}sw:xrTk B c W|" [T(ONM3"  ׻ۇD#%$#y"^#nh{X[]y  ~OympPX7JvoGrnj@b`_l$. TU9XBV>J( ?"@25.34ߎ8ގ0%ގֿ׶܎ێَ؎֎ӎҎ ѸЎώΎ͎̎ɎȎ%ǎƎ¼ĎÎŽ˼z}%t&[`<z6Lg&&"'m/ O>#\'ߎގݎ܎ڎَ؎׎֎Վ'ՎԎӎҎюЎ͎ˎʎɎǎùƎxÎ|mz-0(|q}_jRwifrT2.Mh{=o(o\npݎ".Wڎ>َe؎//֎^ԎLӎҎR)ώЎJ̎&ʎɎȎǎƎ)ƎŎÎ `*ºyxc5*pvh^֎SՎJԎDӎ'AuCώΎnw+͎"̎!ʎɎ Ȏ6ǎ ƎŎ+ŎÎŽ@,=,zzrvw_i<gtRUm8ݎ0\ێ6ڎrt؎`׎w֎cՎoԎ,)tҎp&ώ^G ̎:UʎRɎȎǎ:8DL&?I"O%)*>'/-,  ӼҸ.ع޸þ|rk[kE$/^utpcibl[kjiW[gfVdUbCaW%_d/^`f\[YWPV : OM 51ɍ0~}zyxwvu 41uvt״rqponmljigfdM1dc~a`h_j^]b\]XZWYX82XKW5V2Uю2 ´dzа2ȱ}{zyvsmɴqkyihabfkcU\3cbU`z_F]]@\>[<FYNAmV#UQTX?R>P[ 4FN"M]CK=IZ6FF 93JAKZ? >,'+;%I876=10ُ40qoοlkjihgedX5]\İZYXWVʹTSQqOMLKJm|HG]5gFEUC^?g>c<A;v:Xx8}w6J64`3]2Y15F/6pmS,)o*OKN5L$S#""D!#&A?O40)#47   %# Ʊֵ#7pXL(Pp`d,x ,!!t""<##d$(%%l&&T''((()X**x++8,,,-.//0,110222T344P556,778p8/.+*'&#x!\e9[az}C D@ < k;4m.>|1*(VryzxP9x:7! =JIG=ߍލ܍<;܍ڍ׻؍׍ ֍ՍԍҍЍ۰̍Ůۯƍč͸Í+<rpm<whp_Ek=F>6$=[`!ݍ܍ۍڍ=ڍٍ؍֍ԍӍҍэ3=Ѝύٴ΍ɹōӷzgwuD>x{oqlvoTo5Dߍ7^4z.p>L׍f֍wՍxԍnӍKH?3Ѝ ύ_>͍<H ʍ:ƍ3č*0+9G#*?,'հ!ۻ ʻ;|@̮ǴϺ{wsvtsrcpo}hAomcWkkjq^|dXceaPK^]t\mfZeY8]W]iUB=TUSNIbRO1NJ5eK*JIQH*G E%D((8@/'0=E<%:817#6+5B5v u"ts o nmlji˸gܷfedcbaCC߲]\ZXήVTSQRPN}MlLKYHDJIQD\CBGAI@?m>4=<}9ǕD9A8oa6"5+[3_10 / .-2*).(&%$ hE#"!\[ZYҫXKFWVUT~SvoQzxNLaK~pFI|HV{F{EDnCY^Aj@N?pA=g6;i:D?87H6~5s4ϖF443^1E/.--,V *=))(B4&%$ #"  G )  ݴٶ ECBS4HA?>=<г:765320/.-*)(H('&y$t#^mpnoadoN^8j(PD9חIRD. = T  .#.DJ ک[J3߼/.-+*)('&%u! (Kh\|mjf{k`i` Vs F}MOF5cBGHKB]ߘK!,1e6]O6#V!5:/%!Lߌ-݌ں׌Ԍ ьЌόΌ͌̌ʵɌnjƌctMČÌڧնy NXgkPI\~یyzIW|}?<ьЌxό1v͌N͌0̌\ˌ)aɌȌ[njƌ'Ō05Œ=%%5)pO#. !˱ ŴԮkOtsugdsP`KEF|A֌MՌIԌ:ӌҌ.ь,08Ό ͌Q&̌:ˌ ʌM$%ƌ1Ō)'ÌŒL   41QدզsRyiRqyxfoیڌ_ٌ}،T׌U֌R+Ռ Ԍ>ӌCAьЌ(ό+͌9PS͌pS͌vȌnjdc{SZXZfFN^Ouwns<ZTX^jT!O<RKFA93ߌ&tTތ܌یڌٌ،ҌьǵЌόͬ͌¾̌ˌʌɌȌATȌŌČ׵۸ҩuszqUXchRiYތP|HEoq׌S֌wӌ4Ҍ8ьmЌlόXΌuŠŝXV̌U?JɌV]nja/ŌRČKLŒIB 7*';:#A  W(ع ʨ֨ ŢIWܹ֮~{zĮyrxvvuuçroq_p\lXlkXje]mTftdUlWaL]@[ZPYRXQWgVTXT*<R$Q#}O7N͞tYN4MkLjTJ*I:HGKD*C. &>&<D6 43214Z$/.+j ihfdåba`^]\¤[ZYWQZW׷VURPOعMLKշIFEDCBA@?[?|=nx;987[6j5\4W3^"՟\\10D.6-O+:*J)A(<'1&0%$%# !( #$\2Ҫ ޱ֯GѤFEYl]EDҵCBAЯ>=<ʱ987Ĺ6543 ^3421U0j/L.S-,[+@:)(v'y&z%w$ݠ^$A#)e!dbU>$_۪$QOa_p:4;;<===<>>?t@`ABBC@DD`EEhFF|G,HHIOK a5;3:#8@76!3)201 #+ *B)!&#'a2[ZѬYĤUعҵRQPONi,bNLKJHEDAB|bA@?x>=j<P;M:te_7|6WR4S3291,c10I/.>-5S+D1)(( '&%"$/c$#"a`_^]\qd\[ZsYXtVyoQoPfOpdN\LqcJ_I\H^G?FEJDKcBQ@}?y|=<%;V{9nd#]5j4,d2c1b0`/I.5,3*0). %7e%'&$! #פ[ZܨXVˡ˺MK«HyeHGFEDCߝ@<z~:}9tw54t32lh/dkf-.ZV,+Q*I)>+'<&ŕ.ĕlgĕqÕ:•_aIG"F<84+&-(1ߜ?g! С ?dh?>ު<ޫ:ݵ8}653210/.*)åh)Y(HE'?#B!3 l(#xi$ GiůұַDCɝA@j@ھ?>=<;Ҳ8˵76Ͳ5t3ry0+*(ki&%˦jf$[#a"] Y_rkOfy99nz3T hk*NP/?>=&K+8 4G<+*0-+%", OkӚҾٰ ڞе}zˣxv؛uҙtslלponmlkh}g{exdɩa}^p]n\kYrX]Wd`ӧm\T^STWRKG6>;nCQR@nb7E:Jߗޗݗ ܗOۗڗٗ+)ח(֗+Wn՗ԗsq޺poݼihedcbȫ`^]߶[ɬZ՝Y@oYXWTSRPNMLrqJKIEDCۨp|A@?=B;ژE6Qט4Q՘ԘjRҘAј3p͘\d˘"Ș\ƘĘØ˜C_$qÚȩͰQPOϣ֜KJIHqBA?ݫ=<9865410.-,&%@rX$#"|!s vXm_~=U@ok%rF] R8KA2/R.-=4-$gxs' צĠ t*)('&{#"t ={@J};u t -tnq .jf WK@+'ou* ֺ͗ԡ¶ڟu~}|{ėb_zvsI -+ @n5R!5Dw/1H *)9 427+7L   6wwΤܸӡѡٸәś4x}|{ݮyxwutsrq̚nmjx|vLWwvTuhig]jm\"=tyi])K`CHC2ߛ69/;3Gכ*֛՛&ԛ,zԛ(ӛr޹ڨpon̤mkjigfâedcbazaȖ`^]\ytZoYcXv@{][UX[d\GKE{I4+6+)*2'2-ݜ ܜx{x w v t*sqnmlΠjihgfɮd|fe̬dĞcba |~jM,}<5H}<ѯl}<=}<g;:ٟU}ٟ`؟JןQPAON Lɟ ğ}"ߵ՝ˬܛɓֶġٰ\~ݛעupƖcϑvêKJnILItHsFDS~Vߟ@ޟQݟNj۟Jd|؟LןCu՟?ԟ<ӟ9ҟ]ҟ5џ_П'ϟ)ΟD͟D̟ 8ɟ1ȟ ǟƟğ9<Ÿ,*  SQPOŎMLJ aa$bb$ccdhddxeefdgg\hhpii8jj`kklxm8nn8oopqq8rrpstttuuv=<;:987y6}5Sp56XKZWm1R0/v.R-r;ʤ:ɤ3Ȥe01/^3*+Ea0$a!"1<    ׸82*܌Ȓَ[t\  T  h|x~|krg,`D_PLD߹#~}|!L|{zyƞwvtzxca_x { q v x~VUK|QLO{,IT?9>"<331hE E;F ũ~ם|{wvt՞rpon)HnȎmljgfecba`k^q]oX o#1 #~}|{1Ę˥{ڭz]sXi0lI(S9ęSRv{ܙR@4"%I2( ,-ש '!.ڨ̩ا ڬ ٬׬ĩ֬լ˜Ԭ ҬʍLJЬģͬՊʬƬŬۥìҝƉǑAפׄţyŷ|Əoȕwj[}TM1]s(ož`ji?c\WԜI)æ&ĥŌ}ŧhr0m}_out}VWIngwZCgssafu3VPpܪͿ̝ܪ9۪e٪*cתZ֪Vժ#Ԫ;Ӫ'ЪϪΪͪ˪ɪȪ#ƪĪêb`^[YXUTSRMLQ$LKI׃HGFCA?><;:87ԟ54ogO/-\,U+M*Pn(tp&\īëk«fRh``iWXSML9C(ϹRYdRSSF{y5x_ukudts]RrF٬pCo/m!Bbjά _ɬH1< 154.(ޕ ,-$֡"؅؉Ѣŏ ٳֳճ܃ԔγͳԑaԄ<l0Ċ0܌$$h0l$D@PPxԙX̜(ĝ̟`\xp›Ùǚגפƒâǂ     ~de{zrF5jlccs[ThrWXRQ>/AUVRQP$?~D7@>ܬ;جި׬'׬*uڨ֨sبrq˨ͨɣmlkʨǨ܇hfסcba`_^\iԦ\[Z~YWV|UvTTmSk}nkpgC86<h߭2_ݭuܭ3-*:׭,O9a`(ѭ hЧέͭ,̭[˭Cȭ6ŭ.í/~ٞńQqQRhR{|/7y-,ԩ,-W˰˰4ʰ? ˰ʰi h$hiHZh6Z534Z01.$-5}+ {+'&K(#! {&G0{ؐތȱȖۋǘ   Ɇś{ɏ8|љҀؑƕ}zwӗ}ƆqŅ}t~y|{zPx߱awbұu4tͱc̱| ˱̱OP̱kԋӫΑҫgyӖ|ͫ՗̫˫ƋԌƫūUdǂNzC?=;~:8760-Zxԭ+*p|nTq{$V[_! dyyN~O{}XcpytslV]Y` Q\NeWSx*=; WL"{#{}ׇܽxߗ~ނ{‹zyxw|zx{wk|J Y P | `~ Vh{^}}(Qw+#w)& (x_ݎŮ̄њُ(H()ȴ5&|j{l0gjaDQ|%\tZvAr]4 B  *+%A0H|6{Oxg}ϱα͋˱|ˏȧ޼</.w-,,-vt+O*4)LC|,U+vLE~{ECExv>n{-<O9LN~75bw3[1]08DAo4==>Ĵ>ݶx0]9bw׶9vBb<aR` P_V\5ش]cǶ1ZW~X¶W>wT RUQO NLK8J;IH}}w8 {ߺٺպ˚0˺/ź.º-,+*o)|'l'~}zz"{ywbtJ=̶$[8[\L^GEd)ECBs@?>:%8C7ݸ6ܸ5ڸ4Ѹ2͸͸.,ȸ*̸ʸsɸǸƸĸTTU XUMl 4Ʉ||̓/-'&}{k#yzxxvzt~svrbqp n k j\hgcjzab,]31(YUSMDCD3.%Uz̯zІ˃|zyxwutsqp0pqunmxlkjʉi̶högfpĺZUrL*(W'&XxDBx6oi]xp5`̦xȧ`t̩@`x0H\̭Dدt @T4,д0dĶ0D\xPdx (DpĻp̻Ļpؼؼ(p(:):)))p()~*E8~* +L +p` ++p+dt dtpdtuMuuupнuJvJvvvpvwUw0x,0xp@0xqPqrd|QQRRо112<Znxyq]$q+COTV:TYmopYMiY2tfYeYdYbY`Y_Y#_Y2t^Y3t\Y[Yep7  0DXh|Ƚؽ$8H\tȾܾL| [YgbZYmqZYbYYYYbXY+XYaWYaVYmVY+bRY*bQY)bOY&bNY bKYbIYbFYp9FY DYl2Y (Y $Y YY3p(:YuDXxpL:XkjX\d08pLG|p;pmP\ht(4@LXdp|L9`мt09   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~0909  !"#$%&'()*+,-./012344444444444444444444444444444444444444444444444444444444444444444444444444409090909090909090909090909090909  090909 0909090909090909 0  !!!!!!"##########$$$$$$$%&'(()***+,---.////0001233455567889:::;<===>?@AAAAAAABBCCCCCDDEFGGHHHIJKLMNOOOOOPPQQQQQQRSTUUVWXXYYZZ[\\\\]^^^___`abcddeefffghhii  0909 09 0  !!!"##$%%%&'((((((((((()*++++,,,---./////0000122222222333333444444444555667777889999:::::::::::::::::::::;<==>>>>>???????@0909 0   !!""##$$$$%%&'((()*+++++,,-...//0001234456666660909 09 0  !!""#$$###$%%&&&'())))**++++++++++,-.....///////00111111123333444555555555566677789::::;<<<=>>>>>>????@@@@@@@@@@@AAAAAAAABBBCCCCDEEEEF0  !""#####""$%%&''()****+++++++,,,,---./////000112344455678999:;<=>???@ABBCDEFFGHIJJKKLMNNNNOPQQQQQRSTUUUUUUUUVWWXXYZ[\\\\]^_``abbbb0  !"###$$$$%&'())*****++++,,,,,----..//0111111223455666788999::;<<<<<<<=========>?@ABCDDDDDEEEFFGGGHIIIIIJKLMNOOPPQRSSSSSTUUUU0  !!!!!!!!!!!!!"""""""""##$$%&''''''())**+++,,---./00000000  !"###$%%%&&&&&&&&&'''''''(())*++,,-...////////01111222334456667778999:::;;;<<<<=>>?????@@@@@AAAABBBBBBBB0  !!"""""#$$$$%%&''(((()*+,--../0  !!!!!!!"""####$$%&'''''())***++++++++++++,---./00111123333444556678889999999:;<<<<<===>>>>>??@@@@@@@@@@AAAABBBBBB0  !!""""""""#######0  !""##$$$$$%&&&&&&&''())*++,,,,-../01222234555566667788899::;;<<<===>>>>?@ABBBBBBBCDDDDDDDEEEEFGGGGGHHHIIJJKLLLLLMMMMM0  !!!!!!!!""""""""##$$$$$$$$$$$%%&'''''''''''())****+++++++++++++,,,,,,,,,,,,,,,,,,,,,,---...0  !!!!!!!!!!!!!!!"#$%&&&'(()))*+,-..../////000001222233333330  !!!"#$$%&&'((()*+++,-.../00122333344444456677777789999:::::;;<<=>>>???@@AABBCCDEEFFFGGHHIJ0  !"###$%&&''())*+,---..////////000111112223345677777899:;;<<<<<====>???@@@@@AAAABBBBCCDEEEFFFFFFFFFFFFFFFFFFFGGGGGGG0  !"""#$%%%%&'(((())*****+,,,-0  !!"##$%&''''())))****++,,,,---.//01112233333344555567789999::::::::;<<<=>>>??@@@@AABBBBCDDDDEFGHHHIJJJJJJJKLMNOPPQQRSTUU0  !""#$$$$$$$%&&&'''''(((((((()***++++++++++,,,,,,,-./////////00112222333334444556777789:;;;<==>>>>>>>?@AAAABB0  !!!"""#$$$%&''())*+,-.////////001112333345566677777777899::0  !!!!!"""#$$%%%&&&'(())))****++++,,,,,---------...../////0000111122222222222222222222222222344444444556666667889::;<<<0  !"""""#$%%&&'())))****+,-.../01234456666666678888888888999:;<==>>>??@@ABBBBBBBBCDDDDEFGHIIJJJJJKKKLLLLLLLMMMMMMMNNNOOPQRSTUVVVVVV0  !!!!"""#####$%&''''''''''''((())))))))**+++,,,,---.//0000000000000000011223340  !!!!!!!!!!"##########$$$$$$$$$$$$%%%%%%&''''''())))*+++,,,,,,,-----..////////000000010 0  !"#####$$$$$$$$%%%&&&'((()))*******+++++,-.///0123334566777788999:;;;;;<<<=>0  !! "#$$%&&'()**++,,---.///000012233333345566778999:;;<=>?@AAAABCDEEFFGGHHHIIIIJJKKKLLLLLMMNNOOPQQRSSSSSTUVWWXXYYZZ[[[[[[\\\]]]0   !!!!!!!!""""""""####$%&&'''((((((((((())***************+++,--.....///////0001122334556666789::;<<<====>>>???@ABCCDDDEFGGGGGG0  !!!""#############$$$$%%%%%&&&&&&&&&&&''(())))))*++++++,,,,,,,-----------.////0  0  !!!!""""###$$$$$%%%%%%%&&&''''''()))*********++++++++++,,,,,0  !!!!!"#$$%%%%%%%%%%%%&&&&&&&&&&&&'((()*******+++,,,,-.////0110  !"#$%&'()*+,,--./012344567889:;<=>?@ABCDEFGHIIJK0 0000  !"#$%&'()*+,-./012345555555667788779999::;;<<=>==?????????0  !"#$%%%%%%%%%%%%%%%&'()*+,-./0123456789:;<=>?@ABCDEFGGGGGGGGGGGGG0  !"#$%&'()*+,-./0123456789:;<====>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>?????????????????????0  !!!!!!!!!!!!!!!0 0  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!0 0 0  !!!!!"""##$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%0  !! !"""####$%&&&'())*++,,--.../00122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222220  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_P`abcdefghijklmnopqrstuvw0  !"""########$$$$$$$$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdFefghijjklmnopqrstuvwxyz{|}~0  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwx0  !!!""!!!!!!!!!!!!########$$$$%%%%%%%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~0  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefgh5ijklmnopqrstuvwxyz{0  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuv0  !!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~0  !"#$%&'()*+,-./0123456789:;<=>?@ABCDE6FGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijk7lmnopqrs0  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~0  !!!"""###$$%%%&&&&&&&&'''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~0  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuv0  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmn0  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqr0  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`0  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ab0  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abc0  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqr0  !!!!!!""#$%&'()*+,-./0123456789:;<:=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\2]^_`abcdefghijklmnopqrstuvwxyz{|}~0  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~0  !!!""#$%&'((()))))))))))))**+,,,-...../0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstu1vwxyz{|}~0  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~0  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[?\;]^_`abcdefghijklmnopqrstuvwxyz{|0  !!""##$$$$$%%&'(()**++++++++++,,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~0  !"###$%%%&&&'''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~0  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz0  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^^_`abcdefghijklmnopqrstuvrwxyz0  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrs0  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopq0  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmn0  !!""""#$%&'()*+,-./01234*56789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~0  !!!!!!!"""""#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{p|}~0  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvw0  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{0  !"#$%&'()*+,-./0123456789:;<=>?@A)BCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|0  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefgh0   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijkl0  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ab0  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ab0  !"#$$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`0  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefffff0   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMMNOPQRSTUVWXY3Z[\]^_`abcdecfghijklm0   !"#$%&'()*+,-./01232456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ0  !"##$%%&''()*+++,--.//011234567889:;<=>>???@A>ABBBCDEEFFGGHHIJKLMNOPQRSTUVWXYZ[\]^_`abcdedf0  !!""#$%&'()*+,*-./*0-123456789:;<=>??@ABCDEFGHIJKLMNOPQRSTUVWXYZ[WW\]^_`_abcdefghijklmnopqrstuvwxyz{0  !"#$%&'()*+,-./012345(67889:;+.<=>?@AB@CD8E9FDG=HIJHHK2ALMMGNOPQRSTUVWLX5YZ[\LY0  !"#$%&!'()*+,," -./012345667859:;<=>?1@ABCDBEFGHIJKLHMNOPQRST0  !"#$%&'()*+,-&./0123456789:;<=>?@ABCBDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~0  !"""##$$$%&'())**+,,-,./0123456789:;<=>?@ABCDDDEFGHDIJKLMNOPPQNELRSTUVWPXXYZ[\]^[[_``abcdeVfghijjklmnopqrstuvwx0  !"#$%&'()*++,-./012332'45*677889:;<=>?@A=:*BCDEFBGHIFJKLMNOPPQRSTUVWXYZ[\]^_`abcdee0  !"#$%&'()((*+(,-./01(23.4567889:;<=>?@ABCDEFEGHIJDKLMNOPQRSTUVWXYZ[\]^_`abccdefghijklmnopoq0  !"#$%&'(()))*+,-./0123456789:;<=>?@ABCDEEFGHIJKLMNOKPQRSSTUV0  !"#$%&'()*+,,-.//0122223455566789:;<=>?@ABCCDEFGHIJKKLMJNOPQRSTQU0   !"#!$%&'()*+,-./01--234567879:;<=>?@ABCDEEFGHIJKLMNOPQRSTUVW0  !"#$%&'()(*(+,-./01233.4566789:;<=>?@ABCDEFGHIJKLMNOPQRSTMUVWXXY0  !"#$%&'()*(*%+,-./0123456789::;<=>>?@ABCCDEFFFGGHHIJKLMNOO0  !!!!!"#$%&'()*+,-.-/012.345637489:;<=>=?@A0  !"#$$$%&'()*+,-./012345-6789:;<=>?@=ABCDEFGHHIIJKLKMNOPQRHSTUVWMXYZ[\]^__`0   !""#$%&'()*+,-./01234567889:;<=>?@AB6CDEFGHAHIJKKLKMMNOOPQRSTTTUUVTUUVWXXYZ[0  !"#$%&'(')*+,-./012344456789:;<=>?>@ABCDEFGHIJKLMNOOPQRRSTUVWWXXYZ[\]^^^____`abcdeefghijklm0  !""#$%&'(')*+,-.///0123456789:;<=>?@ABCDEFDGHHHHIJKLMNOLPQRSTTUVWTXYZ[\]^_`abbcdeffghijklmnopqrst0  !"""#$$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJDKLMNOPQRSTUVWXYZ[\]]^_`abbcdefghijklmnopq0   !"#$%&''()*''+++,-./,0123345-6789:;:<=>?<@ABCDEDFGHIJKLLMNOPNNQRSTUVWXXYZ[\0   !"#$%%%&'((&&)*+,,,--././..0122222334566666667778889:9;;;<==>>?0  !!!"##$%&&'((()**+$+++,-..///000012202233333333345556789:;<=>?@AB0  !"#$""%&&'(((())*+,-.../011111112324567897::;<=>?@ABCDEFDGHIJKLMNOPQRSTL0   !"#$%&'()*+,-.,/01/23414567879:;:<=>?@ABCDEFGHIJJJKLMNOPQRSTUVWXY0  !"#$%&''()*+,- ./0(102/3456789:;<=;>?@AABCD9E?FGHIJKLMNO0  !"#$%&'()*+,-./0123456789:;<<=>?@AABCDEFGHIJKLMNJOPQRGSTQUVWRXYZ[[\]^_S_`^a]bcdefgghijkilm0  !""#$%&'()*+,-./01233456789:;<==>?@@ABCD%E2FGHIJKLMNOPQRSTUVWXYZ[\]^_`aab0   !"##$%&&' ())$*)#+*,-./0/1234567118829:;<9=>?@ABCDEFGHIJKL0   !"#$%&'()*+,----./0111223344444455555677888888889999::::;;0  !"#$%&'%()*+*,,-./.0123456789:;<=>=?@ABCDEEFGHHIJKLMNNNONOPQORSTUVWXYYZ00 0  0 0      !"## $%#&'() *+,-./0122334567889:::;<=======>8??????????????????????????????????????????????????????????????????????????????????????????????  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~  !"#$%&'()*+,-./0123456789:;<=>?@    !""            !"#$%&'()*++,-./0123456789:;  !""#$$$$$$%&'())))))))))*+  !"#$%&'((()*+,----.///0  !"#$$%&'()***+,-./01233345678  !"#$%&'()*+,-.//  !""#$$%&''()*+,,,,-)./0  !"!#$%&&&&&'((((((((()  !"#$%&&&&'()***+,  !"#$  !"#$      !"#$%&'()*+,-./01233  !!"#$%&'()*+++,-.//  !!"#$%&'()*+,-.  !"#$%&'(()**+,-./01234  !!!!!!!!!!"#$     !"#$$%&  !"#$%&'()**+,-./0123456788889   !"""""""#$$$$%&&&'  !"#$%&'()*+,-./0123455  !"##$%&'()*+,-./01234456789:;<  !"#$$%&'((  !"#$%&'()*+++,--./012  !"##$%&&&'())))))*+,-./  !!!"####$%&'  !!"#$%&  !"#$%&'())*   !"#$%%%%%&"'  !"#$$$%     !"#  !  ! "#$%&&&'(()*+++,-...  !"#$$$%&&&&&&&  !"##$%%       !"#$%%&''()*+,-...  !"#$%&'''())  !!"#$$%&&&&&&'()**+,     !!!!!"""        !"#$%&&&&'(()**  !"#$%%%&'(((()**+,-./01222345  !""#  !""""#$$%&&&'()*+,-.  !"""""""#$%%%%&  !"#$$$$%&'       !"  !!"#####$%&&''())    !!!!!"#####$%&'()*++++,-   !""#$%&'((((((()*+,---  !"#$%&'''  !"######$%&''''()**  !"#$$%&&&'(()**+,-./  !"#$$$%&&&&&'((((()*++,  !"##$%%&'(()*+,-.  !"#$%&'()))*++,-...  !"#$%%&'(((((      !"#$$$$%&''()))))*+,  !"#$$%&&'(()**+,-.  !"""#$$$%&'()*+  !"#$%&''()*+,-./012344445678  !""#$$$$$$%&''())  !""""#$%%&'((((  !"#$%&''()**+,-./0123  !"#$%%%%&'(  !""#$%   !"###     !"#$$%&&&&&&&&  !"#$$$$$$$$%&&'())  !""""#$%%&'''''  !"#$$%&%'''''()*+  !"#$%%&'''()    !"#$$%&''''())*++  !""#$%&'()*+,-,,,,)./0  !"#$%&'(()*+,-.///////  !"#$%%%%%%%%&'(  !""#$%&  !"########$%&'((((((((   !"""    !!!"##!!          !!!"###$%%  !"#$%&'())*++++,--  !"#$%&''()))*+,  !"#$%&'(()&*++++,-./0123  !!" #$%&'()**+,-./01  !"#$$$%&'()*+   !"###$%&&&&'(()*+++,---  !"##$%&&'(()**+,,,,,,-  !"#$$$%&'()*+++   !"##$%&$$'&()))))   !"##$%&'((  !!!!"####$%%%%%%  !        !"#$%&&  !!!"##       !"""#$%%%&&   !"#$%&&'()*+,---  !!"##$%&''''()   !""#$%%%%    !"""""#$$$     !"#$%&'())*+    !"#$%&''())*+,,-./0  !" ####$%&&'(((()**+,,-   !""#$$!%&''()))*+,-    !"#$%&&&'())*+,-  !"#$%%%    !"   !"""#$$%&'''()*+   !"####$%%%%&'    !"#####   !"#$$$$$$$%&&'()**  !"#$   !"#####$%%%%%%%%%%%&   !"#$%%&'$(((()*+,-./0  !!"#$%&'())*+   !"     !    !!"#$  !"#$%&'()*++,--./01234556789   !"#$%&'(((((  !""""#$    !!!!!!!"#$$$  !""""""#$%&'()*++,-./0   !"#$%&'()*+),,-.."/0123  !"#$%&'()*+,-.//  !"#####$%  !""""#$%&&'(    !"#$%&'()**)+  !   !"#$%&'()*++,-.///012   !"""#$%&&'(()*+*,----    !"#$%&'()*+,-..    !!!!!!!"#$$%&''  !"#$%&'((  !"#####$$%%%&''                   !!!!!   !!"#$$$%&&&&'(  !""#$$%&&%'''())*+    !""     !!!"#$  !!!  !""#$#%    !"""""""     !"#$$%&'()*+,-./0123456789:  !"#$$%&''()**+,,-........    !"#$  !"#$%&&&'()**+,,-./0122222222    !"#$%%&'%(&))  !"       !!"#$$$$%&''''())*+++,-.  !"#$%&'()**+,,,-./000122  !"###$%%%%%%$&'((((())*+,,-./01  !!!!!!!"#$  !"#$%&'()(*+,-.//01    !!!!"###$%%%%&'(   !"#$%&$'()*+,-...//0     ! "#$%&'''''())*+  !"###$%&'()**+,  !!"#$%&''() ***+,-./00  !   !!"#$%&'(((()*+,-  !"#$$$$$%&'()*++++++++  !"  !""""#$  !!!!"#      !""#$$$$$$$$$$$$$$$$$$$$$$$$      !"""""""#$%%%%&'()'*+,,,         !!!!!!!!!!"#   !"          !"##############################       !"#$%&'()***+,-.///0;D8]`h]H^^x__`zRx $\0FJ w?:*3$"D\ \]op]^v__$HWGNU`" x@v pp D@v p0 y  P"X"o`  "0 oooo"GA$3a1 GA$3p1067 GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFYoGA+GLIBCXX_ASSERTIONSgb18030.so-2.2.10-35.el8.x86_64.debugό,7zXZִF!t/>]?Eh=ڊ2N nmE]ҧ6Ӱ96 dn9vW4.6|)0,Xsbi~шMQٰJkuf7p*@fHܾ)gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 08oEo T^B0hc0n   w@@D}   DȪȪ P"PX"X`"`` " " "(("(0b(H p,+PK!-3p.p.(2.2.0/x86_64-linux/enc/trans/japanese.sonuȯELF>@0'@8 @ PP P     888$$ Std Ptd 44QtdRtdPP P GNU@7VP8(@ BE||qX c , F"( 0 U $( __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeInit_japaneserb_register_transcoderlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ui P X ` `        0  ( 8  H         HH9 HtH5B %C hh% D% DH= H  H9tH Ht H= H5 H)HHH?HHtH HtfD= u+UH=b Ht H= Ydu ]w~t@A0޺pAFkp~O@q@9HtNV=pOƍrax@9@qf.r`~ލrxDAfHH=q "6NC`bNi\4TdlסC;qʣ˄|UW4wx"f&_CvJ e6}U|U3*z% 9U PaOAU=C呯q㈏msSyg9ۈKI-qݶqXH%/1,X! ~b٘s7&CPDԏ!`rƛǼXf;B`"b1 f^,:B@TD40>l!հ`fGMߠ2\æybCpyoxU롑MiD@e7ސ[Tp!%MRZ$uo#eK©B%-7 2ox[5&tmt#Rx @7@8 @(( (( (  -- -  888$$ Std PtdQtdRtd(( ( ppGNUX~Exx3HLB  BE _|qX b , F"(0 U l00 (0 __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeInit_iso2022rb_register_transcoderlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ui (  (  ( ( ( ( ( ( )  )  8) @) H)  P) `) h) x) ) )  )  ) )  )  )  * * * (* P*  X*  h* @x* * * * * *  *  + @+ @+ H+ X+ h+ +  + + + , X,  , , , , ,  ,  ,  -  -  -   - (- 8- H- p-  x-  - p- / / / / 0  0 HH)$ HtH52$ %3$ hh% $ D%$ DH=$ H# H9tH# Ht H=# H5# H)HHH?HHtHu# HtfD=# u+UH=R# Ht H= Yde# ]w1fDHtk>t><tZAB$LAfFAVI@H)ȃAPfD<t$LAA@fDIIȄtA(ABLAfD I@H)ȃAff.?HDf.FFAfAFAfDDHtbtpIL-[ILL)fD_L 4ACDHLȀItA$ABLIfDD@EMQHtsAADF7P_>IIs}@t$ABBIfARHIHfABL[H)@>u^t<vAJAhAAL[H)@GL[H)@wÃAAL[H)1tHt(@BHfPH)GHTHHcH€tA$FBHNfDHAf릐?t!<^H9Hff.@>t'?DȀAFȀAf~(Tt%@t8Bt 11f.Bt1Ju1fD1f1?t(FBf<t5}<tI<u!?HHfDfP߀v]PиDvPB<v>-t9Jи@Dv܃yH9H_wluhȀAfD1f.~(TuItJt1Bu81fD@t+Bu)1ȀFȀA1fHH=q LH= @H= 4H=m (H= H= H= H=] HHH!#!V!W!"!&%r%!%#%%%'%)%c%e%g%C!<%"%$%&%(%*%+%-%/%1%3%5%7%9%;%=%?%A%D%F%H%J%K%L%M%N%O%R%U%X%[%^%_%`%a%b%d%f%h%i%j%k%l%m%o%s!+!,CP51932CP50220CP50221cp51932EUC-JPstateless-ISO-2022-JP $,HPXY`XYt  H  H@BBJ$(!~BJ; $8 L` @` zRx $@0FJ w?:*3$"DH \ p 0hIH\ L  H p H G K Ko!0~Dh XtllH_GNU (  E   E   E @E @E E lE  8E py ( ( o`  0 0  ooooC- GA$3a1  GA$3p1067 GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFY GA+GLIBCXX_ASSERTIONSiso2022.so-2.2.10-35.el8.x86_64.debug#Ȱ7zXZִF!t/]?Eh=ڊ2N.gDq *P+nVH!Րe]b:l0y_t?!@;&EQ4xL[R)&gwcn`6`JJZ/MU#P^ɂ|FjUh'GˇpRY>`haz~(|ּy һG i2(SӉ}úqli~ AG% We#މl1@V8H^;a1_E=y5TDeMꨰ(oW2q 2WFr.8V3T%\ ?|瑰xa:_4Bfh9o GeP§"!0/h p\rcz$^W`yp|bgEY p~/b'<bw`ھ:(>6`>^ccp LdK)˷E޸iy4f\d8ݭ&jV^ v28 ]ypwnU)96ցY)61c_wm)[G__d=X;cl W/TZ# ½q@ X?ZMnz+uf[m{zM^G~7ոz ! S_E2&n&ʉ QA+MT}  pAZb.X=U";wNǁ0)F%Lp{Tyw7{CK>enPNX(<ɭC<R Cdj aǪK'0w֏y#x]A:vhs>6CN[jQHE'>%LO c!hgYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 08oEo T^B 0h c 0n w }      pp ( (( (( (  - - / / 0 0((0 (000`(0H p2,26+PK!D"#~~,2.2.0/x86_64-linux/enc/trans/japanese_euc.sonuȯELF> @v@8 @papa hh%h% mm%m%  888$$PaPaPa StdPaPaPa Ptd```$$QtdRtdhh%h%ppGNUHZ Z@ BE|Z'qX g , F"(p%0p%U l(p%__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeInit_japanese_eucrb_register_transcoderlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ui h% h% h%h%h%` h%f h%h% `i%` hi%s xi%i% j%` j%{ j%(j% j%` j% j%j% @k%f Hk%` Xk%hk% k%s k%` k%l% l%{ l%` l%l% m% (m%` 8m%Hm% o%o%o%o%p% p%HH)g%HtH52g%%3g%hh% g%D%g%DH=g%Hf%H9tHf%Ht H=f%H5f%H)HHH?HHtHuf%HtfD=f%u+UH=Rf%Ht H=^%Ydef%]wHH=1c% H=b%H=a%H=-a%H=`%H=_%H=)_%H=}^%HHHUTF-8EUC-JIS-2004CP51932eucJP-msEUC-JP。「」、・ヲァィゥェォャュョッーアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン゙゚  `  ˘ˇ¸˙˝¯˛˚~΄΅¡¦¿ºª©®™¤№ ΆΈΉΊΪΌΎΫΏάέήίϊΐόςύϋΰώ  ЂЃЄЅІЇЈЉЊЋЌЎЏђѓєѕіїјљњћќўџÆĐ ĦIJŁĿŊØŒŦÞæđðħıijĸłŀʼnŋøœßŧþ\ÁÀÄÂĂǍĀĄÅÃĆĈČÇĊĎÉÈËÊĚĖĒĘ ĜĞĢĠĤÍÌÏÎǏİĪĮĨĴĶĹĽĻŃŇŅÑÓÒÖÔǑŐŌÕŔŘŖŚŜŠŞŤŢÚÙÜÛŬǓŰŪŲŮŨǗǛǙǕŴÝŸŶŹŽŻ@áàäâăǎāąåãćĉčçċďéèëêěėēęǵĝğ ġĥíìïîǐīįĩĵķĺľļńňņñóòöôǒőōõŕřŗśŝšşťţúùüûŭǔűūųůũǘǜǚǖŵýÿŷźžż@丂丄丅丌丒丟丣两丨丫丮丯丰丵乀乁乄乇乑乚乜乣乨乩乴乵乹乿亍亖亗亝亯亹仃仐仚仛仠仡仢仨仯仱仳仵份仾仿伀伂伃伈伋伌伒伕伖众伙伮伱你伳伵伷伹伻伾佀佂佈佉佋佌佒佔佖佘佟佣佪佬佮佱佷佸佹佺佽佾侁侂侄侅侉侊侌侎侐侒侓侔侗侙侚侞侟侲侷侹侻侼侽侾俀俁俅俆俈俉俋俌俍俏俒俜俠俢俰俲俼俽俿倀倁倄倇倊倌倎倐倓倗倘倛倜倝倞倢倧倮倰倲倳倵偀偁偂偅偆偊偌偎偑偒偓偗偙偟偠偢偣偦偧偪偭偰偱倻傁傃傄傆傊傎傏傐(傒傓傔傖傛傜傞傟傠傡傢傪傯傰傹傺傽僀僃僄僇僌僎僐僓僔僘僜僝僟僢僤僦僨僩僯僱僶僺僾儃儆儇儈儋儌儍儎僲儐儗儙儛儜儝儞儣儧儨儬儭儯儱儳儴儵儸儹兂兊兏兓兕兗兘兟兤兦兾冃冄冋冎冘冝冡冣冭冸冺冼冾冿凂凈减凑凒凓凕凘凞凢凥凮凲凳凴凷刁刂刅划刓刕刖刘刢刨刱刲刵刼剅剉剕剗剘剚剜剟剠剡剦剮剷剸剹劀劂劅劊劌劓劕劖劗劘劚劜劤劥劦劧劯劰劶劷劸劺劻劽勀勄勆勈勌勏勑勔勖勛勜勡勥勨勩勪勬勰勱勴勶勷匀匃匊匋0 匌匑匓匘匛匜匞匟匥匧匨匩匫匬匭匰匲匵匼匽匾卂卌卋卙卛卡卣卥卬卭卲卹卾厃厇厈厎厓厔厙厝厡厤厪厫厯厲厴厵厷厸厺厽叀叅叏叒叓叕叚叝叞叠另叧叵吂吓吚吡吧吨吪启吱吴吵呃呄呇呍呏呞呢呤呦呧呩呫呭呮呴呿 咁咃咅咈咉咍咑咕咖咜咟咡咦咧咩咪咭咮咱咷咹咺咻咿哆哊响哎哠哪哬哯哶哼哾哿唀唁唅唈唉唌唍唎唕唪唫唲唵唶唻唼唽啁啇啉啊啍啐啑啘啚啛啞啠啡啤啦啿喁喂喆喈喎喏喑喒喓喔喗喣喤喭喲喿嗁嗃嗆嗉嗋嗌嗎嗑嗒8 嗓嗗嗘嗛嗞嗢嗩嗶嗿嘅嘈嘊嘍嘎嘏嘐嘑嘒嘙嘬嘰嘳嘵嘷嘹嘻嘼嘽嘿噀噁噃噄噆噉噋噍噏噔噞噠噡噢噣噦噩噭噯噱噲噵嚄嚅嚈嚋嚌嚕嚙嚚嚝嚞嚟嚦嚧嚨嚩嚫嚬嚭嚱嚳嚷嚾囅囉囊囋囏囐囌囍囙囜囝囟囡囤囥囦囧囨囱囫园囶囷圁圂圇圊圌圑圕圚圛圝圠圢圣圤圥圩圪圬圮圯圳圴圽圾圿坅坆坌坍坒坢坥坧坨坫坭坮坯坰坱坳坴坵坷坹坺坻坼坾垁垃垌垔垗垙垚垜垝垞垟垡垕垧垨垩垬垸垽埇埈埌埏埕埝埞埤埦埧埩埭埰埵埶埸埽埾埿堃堄堈堉埡@堌堍堛堞堟堠堦堧堭堲堹堿塉塌塍塏塐塕塟塡塤塧塨塸塼塿墀墁墇墈墉墊墌墍墏墐墔墖墝墠墡墢墦墩墱墲壄墼壂壈壍壎壐壒壔壖壚壝壡壢壩壳夅夆夋夌夒夓夔虁夝夡夣夤夨夯夰夳夵夶夿奃奆奒奓奙奛奝奞奟奡奣奫奭奯奲奵奶她奻奼妋妌妎妒妕妗妟妤妧妭妮妯妰妳妷妺妼姁姃姄姈姊姍姒姝姞姟姣姤姧姮姯姱姲姴姷娀娄娌娍娎娒娓娞娣娤娧娨娪娭娰婄婅婇婈婌婐婕婞婣婥婧婭婷婺婻婾媋媐媓媖媙媜媞媟媠媢媧媬媱媲媳媵媸媺媻媿H嫄嫆嫈嫏嫚嫜嫠嫥嫪嫮嫵嫶嫽嬀嬁嬈嬗嬴嬙嬛嬝嬡嬥嬭嬸孁孋孌孒孖孞孨孮孯孼孽孾孿宁宄宆宊宎宐宑宓宔宖宨宩宬宭宯宱宲宷宺宼寀寁寍寏寖寗寘寙寚寠寯寱寴寽尌尗尞尟尣尦尩尫尬尮尰尲尵尶屙屚屜屢屣屧屨屩屭屰屴屵屺屻屼屽岇岈岊岏岒岝岟岠岢岣岦岪岲岴岵岺峉峋峒峝峗峮峱峲峴崁崆崍崒崫崣崤崦崧崱崴崹崽崿嵂嵃嵆嵈嵕嵑嵙嵊嵟嵠嵡嵢嵤嵪嵭嵰嵹嵺嵾嵿嶁嶃嶈嶊嶒嶓嶔嶕嶙嶛嶟嶠嶧嶫嶰嶴嶸嶹巃巇巋巐巎巘巙巠巤P巩巸巹帀帇帍帒帔帕帘帟帠帮帨帲帵帾幋幐幉幑幖幘幛幜幞幨幪幫幬幭幮幰庀庋庎庢庤庥庨庪庬庱庳庽庾庿廆廌廋廎廑廒廔廕廜廞廥廫异弆弇弈弎弙弜弝弡弢弣弤弨弫弬弮弰弴弶弻弽弿彀彄彅彇彍彐彔彘彛彠彣彤彧彯彲彴彵彸彺彽彾徉徍徏徖徜徝徢徧徫徤徬徯徰徱徸忄忇忈忉忋忐忑忒忓忔忞忡忢忨忩忪忬忭忮忯忲忳忶忺忼怇怊怍怓怔怗怘怚怟怤怭怳怵恀恇恈恉恌恑恔恖恗恝恡恧恱恾恿悂悆悈悊悎悑悓悕悘悝悞悢悤悥您悰悱悷X悻悾惂惄惈惉惊惋惎惏惔惕惙惛惝惞惢惥惲惵惸惼惽愂愇愊愌愐愑愒愓愔愖愗愙愜愞愢愪愫愰愱愵愶愷愹慁慅慆慉慞慠慬慲慸慻慼慿憀憁憃憄憋憍憒憓憗憘憜憝憟憠憥憨憪憭憸憹憼懀懁懂懎懏懕懜懝懞懟懡懢懧懩懥懬懭懯戁戃戄戇戓戕戜戠戢戣戧戩戫戹戽扂扃扄扆扌扐扑扒扔扖扚扜扤扭扯扳扺扽抍抎抏抐抦抨抳抶抷抺抾抿拄拎拕拖拚拪拲拴拼拽挃挄挊挋挍挐挓挖挘挩挪挭挵挶挹挼捁捂捃捄捆捊捋捎捒捓捔捘捛捥捦捬捭捱捴捵`捸捼捽捿掂掄掇掊掐掔掕掙掚掞掤掦掭掮掯掽揁揅揈揎揑揓揔揕揜揠揥揪揬揲揳揵揸揹搉搊搐搒搔搘搞搠搢搤搥搩搪搯搰搵搽搿摋摏摑摒摓摔摚摛摜摝摟摠摡摣摭摳摴摻摽撅撇撏撐撑撘撙撛撝撟撡撣撦撨撬撳撽撾撿擄擉擊擋擌擎擐擑擕擗擤擥擩擪擭擰擵擷擻擿攁攄攈攉攊攏攓攔攖攙攛攞攟攢攦攩攮攱攺攼攽敃敇敉敐敒敔敟敠敧敫敺敽斁斅斊斒斕斘斝斠斣斦斮斲斳斴斿旂旈旉旎旐旔旖旘旟旰旲旴旵旹旾旿昀昄昈昉昍昑昒昕昖昝h昞昡昢昣昤昦昩昪昫昬昮昰昱昳昹昷晀晅晆晊晌晑晎晗晘晙晛晜晠晡曻晪晫晬晾晳晵晿晷晸晹晻暀晼暋暌暍暐暒暙暚暛暜暟暠暤暭暱暲暵暻暿曀曂曃曈曌曎曏曔曛曟曨曫曬曮曺朅朇朎朓朙朜朠朢朳朾杅杇杈杌杔杕杝 杦杬杮杴杶杻极构枎枏枑枓枖枘枙枛枰枱枲枵枻枼枽柹柀柂柃柅柈柉柒柗柙柜柡柦柰柲柶柷桒栔栙栝栟栨栧栬栭栯栰栱栳栻栿桄桅桊桌桕桗桘桛桫桮桯桰桱桲桵桹桺桻桼梂梄梆梈梖梘梚梜梡梣梥梩梪梮梲梻棅棈棌棏p"棐棑棓棖棙棜棝棥棨棪棫棬棭棰棱棵棶棻棼棽椆椉椊椐椑椓椖椗椱椳椵椸椻楂楅楉楎楗楛楣楤楥楦楨楩楬楰楱楲楺楻楿榀榍榒榖榘榡榥榦榨榫榭榯榷榸榺榼槅槈槑槖槗槢槥槮槯槱槳槵槾樀樁樃樏樑樕樚樝樠樤樨樰樲#樴樷樻樾樿橅橆橉橊橎橐橑橒橕橖橛橤橧橪橱橳橾檁檃檆檇檉檋檑檛檝檞檟檥檫檯檰檱檴檽檾檿櫆櫉櫈櫌櫐櫔櫕櫖櫜櫝櫤櫧櫬櫰櫱櫲櫼櫽欂欃欆欇欉欏欐欑欗欛欞欤欨欫欬欯欵欶欻欿歆歊歍歒歖歘歝歠歧歫歮歰歵歽x%歾殂殅殗殛殟殠殢殣殨殩殬殭殮殰殸殹殽殾毃毄毉毌毖毚毡毣毦毧毮毱毷毹毿氂氄氅氉氍氎氐氒氙氟氦氧氨氬氮氳氵氶氺氻氿汊汋汍汏汒汔汙汛汜汫汭汯汴汶汸汹汻沅沆沇沉沔沕沗沘沜沟沰沲沴泂泆泍泏泐泑泒泔泖&泚泜泠泧泩泫泬泮泲泴洄洇洊洎洏洑洓洚洦洧洨汧洮洯洱洹洼洿浗浞浟浡浥浧浯浰浼涂涇涑涒涔涖涗涘涪涬涴涷涹涽涿淄淈淊淎淏淖淛淝淟淠淢淥淩淯淰淴淶淼渀渄渞渢渧渲渶渹渻渼湄湅湈湉湋湏湑湒湓湔湗湜湝湞(湢湣湨湳湻湽溍溓溙溠溧溭溮溱溳溻溿滀滁滃滇滈滊滍滎滏滫滭滮滹滻滽漄漈漊漌漍漖漘漚漛漦漩漪漯漰漳漶漻漼漭潏潑潒潓潗潙潚潝潞潡潢潨潬潽潾澃澇澈澋澌澍澐澒澓澔澖澚澟澠澥澦澧澨澮澯澰澵澶澼濅濇濈濊*濚濞濨濩濰濵濹濼濽瀀瀅瀆瀇瀍瀗瀠瀣瀯瀴瀷瀹瀼灃灄灈灉灊灋灔灕灝灞灎灤灥灬灮灵灶灾炁炅炆炔炕炖炗炘炛炤炫炰炱炴炷烊烑烓烔烕烖烘烜烤烺焃焄焅焆焇焋焌焏焞焠焫焭焯焰焱焸煁煅煆煇煊煋煐煒煗煚煜煞煠+煨煹熀熅熇熌熒熚熛熠熢熯熰熲熳熺熿燀燁燄燋燌燓燖燙燚燜燸燾爀爇爈爉爓爗爚爝爟爤爫爯爴爸爹牁牂牃牅牎牏牐牓牕牖牚牜牞牠牣牨牫牮牯牱牷牸牻牼牿犄犉犍犎犓犛犨犭犮犱犴犾狁狇狉狌狕狖狘狟狥狳狴狺狻 -狾猂猄猅猇猋猍猒猓猘猙猞猢猤猧猨猬猱猲猵猺猻猽獃獍獐獒獖獘獝獞獟獠獦獧獩獫獬獮獯獱獷獹獼玀玁玃玅玆玎玐玓玕玗玘玜玞玟玠玢玥玦玪玫玭玵玷玹玼玽玿珅珆珉珋珌珏珒珓珖珙珝珡珣珦珧珩珴珵珷珹珺珻珽.珿琀琁琄琇琊琑琚琛琤琦琨琩琪琫琬琭琮琯琰琱琹瑀瑃瑄瑆瑇瑋瑍瑑瑒瑗瑝瑢瑦瑧瑨瑫瑭瑮瑱瑲璀璁璅璆璇璉璏璐璑璒璘璙璚璜璟璠璡璣璦璨璩璪璫璮璯璱璲璵璹璻璿瓈瓉瓌瓐瓓瓘瓚瓛瓞瓟瓤瓨瓪瓫瓯瓴瓺瓻瓼瓿甆0甒甖甗甠甡甤甧甩甪甯甶甹甽甾甿畀畃畇畈畎畐畒畗畞畟畡畯畱畹畺畻畼畽畾疁疅疐疒疓疕疙疜疢疤疴疺疿痀痁痄痆痌痎痏痗痜痟痠痡痤痧痬痮痯痱痹瘀瘂瘃瘄瘇瘈瘊瘌瘏瘒瘓瘕瘖瘙瘛瘜瘝瘞瘣瘥瘦瘩瘭瘲瘳瘵瘸瘹1瘺瘼癊癀癁癃癄癅癉癋癕癙癟癤癥癭癮癯癱癴皁皅皌皍皕皛皜皝皟皠皢皣皤皥皦皧皨皪皭皽盁盅盉盋盌盎盔盙盠盦盨盬盰盱盶盹盼眀眆眊眎眒眔眕眗眙眚眜眢眨眭眮眯眴眵眶眹眽眾睂睅睆睊睍睎睏睒睖睗睜睞睟睠睢3睤睧睪睬睰睲睳睴睺睽瞀瞄瞌瞍瞔瞕瞖瞚瞟瞢瞧瞪瞮瞯瞱瞵瞾矃矉矑矒矕矙矞矟矠矤矦矪矬矰矱矴矸矻砅砆砉砍砎砑砝砡砢砣砭砮砰砵砷硃硄硇硈硌硎硒硜硞硠硡硣硤硨硪确硺硾碊碏碔碘碡碝碞碟碤碨碬碭碰碱碲碳4碻碽碿磇磈磉磌磎磒磓磕磖磤磛磟磠磡磦磪磲磳礀磶磷磺磻磿礆礌礐礚礜礞礟礠礥礧礩礭礱礴礵礻礽礿祄祅祆祊祋祏祑祔祘祛祜祧祩祫祲祹祻祼祾禋禌禑禓禔禕禖禘禛禜禡禨禩禫禯禱禴禸离秂秄秇秈秊秏秔秖秚秝秞$6秠秢秥秪秫秭秱秸秼稂稃稇稉稊稌稑稕稛稞稡稧稫稭稯稰稴稵稸稹稺穄穅穇穈穌穕穖穙穜穝穟穠穥穧穪穭穵穸穾窀窂窅窆窊窋窐窑窔窞窠窣窬窳窵窹窻窼竆竉竌竎竑竛竨竩竫竬竱竴竻竽竾笇笔笟笣笧笩笪笫笭笮笯笰7笱笴笽笿筀筁筇筎筕筠筤筦筩筪筭筯筲筳筷箄箉箎箐箑箖箛箞箠箥箬箯箰箲箵箶箺箻箼箽篂篅篈篊篔篖篗篙篚篛篨篪篲篴篵篸篹篺篼篾簁簂簃簄簆簉簋簌簎簏簙簛簠簥簦簨簬簱簳簴簶簹簺籆籊籕籑籒籓籙籚籛籜籝籞,9籡籣籧籩籭籮籰籲籹籼籽粆粇粏粔粞粠粦粰粶粷粺粻粼粿糄糇糈糉糍糏糓糔糕糗糙糚糝糦糩糫糵紃紇紈紉紏紑紒紓紖紝紞紣紦紪紭紱紼紽紾絀絁絇絈絍絑絓絗絙絚絜絝絥絧絪絰絸絺絻絿綁綂綃綅綆綈綋綌綍綑綖綗綝:綞綦綧綪綳綶綷綹緂緃緄緅緆緌緍緎緗緙縀緢緥緦緪緫緭緱緵緶緹緺縈縐縑縕縗縜縝縠縧縨縬縭縯縳縶縿繄繅繇繎繐繒繘繟繡繢繥繫繮繯繳繸繾纁纆纇纊纍纑纕纘纚纝纞缼缻缽缾缿罃罄罇罏罒罓罛罜罝罡罣罤罥罦罭4<罱罽罾罿羀羋羍羏羐羑羖羗羜羡羢羦羪羭羴羼羿翀翃翈翎翏翛翟翣翥翨翬翮翯翲翺翽翾翿耇耈耊耍耎耏耑耓耔耖耝耞耟耠耤耦耬耮耰耴耵耷耹耺耼耾聀聄聠聤聦聭聱聵肁肈肎肜肞肦肧肫肸肹胈胍胏胒胔胕胗胘胠胭胮=胰胲胳胶胹胺胾脃脋脖脗脘脜脞脠脤脧脬脰脵脺脼腅腇腊腌腒腗腠腡腧腨腩腭腯腷膁膐膄膅膆膋膎膖膘膛膞膢膮膲膴膻臋臃臅臊臎臏臕臗臛臝臞臡臤臫臬臰臱臲臵臶臸臹臽臿舀舃舏舓舔舙舚舝舡舢舨舲舴舺艃艄艅艆Q?岠岢岦岧@岭岵A峉CQD崆崐崫崝崠崤崦崱崹嵂㟨嵡嵪㟴嵰E㟽嶈㠀嶒嶔嶗嶙嶰嶲嶴F嶹巑巗巘巠H巤巩㠯帀㠶帒帕㡀帟帮帾幉㡜幖㡡幫幬幭d 幮QI庥庪庬庹庿廆廒廙J廽弈弎弜K弞彇彣彲彾徏徢徤徸忄㣺忇忋忒忓忔忢忮忯忳忼㤗怗怢怤㤚恌恿悊悕您M悰悱悾惈惙惛惮惲惵愐愒愓愙愞愺㥯慁慆慠慼QN憒憓憗憘憥憨憭O懕懝懟懵P戕戣戩扆扌扑扒扡扤扻扭扳 抙抦拕R拽挃挍挐QST挲挵挻挼捁捄捎U捙WQX捬掄掙Y掔掽揷揔揕揜揠揫揬揲搉搞搥搩搯摚摛摝摳摽撇撑撝撟擋擌擕擗Z擤擥擿攄㩮攏攔攖㩳攞攲敄敔敫敺斁斄斅斊斲斵斸斿旂旉旔㫖旲旹旼昄昈昡昪晅晑晎㫪\晗l 晛晣Q]^晪晫晬晭晻暀暐暒暙㬎暭暱暵㬚暿㬜曬㫗朁朅朒_朙aQb杌杍杔杝cdf杴杶Qg枒h荣栐枰枲柃柈柒柙柛柰柷ikQl栘栟栭m栳栻栾桄桅桉桌桕桗㭷桫桮桺桼梂梐梖㭭梘梙梚梜梪梫梴梻棻np﨓棃棅棌棏棖 棙棤棥棬棷椃椇㮇㮈Qq椻㮍楆楩楬楲楺楿榒㮤榖榘榦榰榷榺榼槀槑槖rs樰uQv槣槮槯槳㯍槴槾樑樚樝w樲樳樴樿橆橉橺橎橒橤x橾檃檋㯰檑檟檡z檫檽櫆櫔櫐櫜櫝Q{|櫬櫱櫲櫳櫽}欋欏欐欑欗㰦欯歊歘歬歵歺殁t殛殮Q殽殾毇毈毉毚毦毧毮毱氂氊氎氵氶氺氿汍汛汭沄沉㳃沔沕沗沭泂泐㳒泖泚泜泩泬泭т洀洊洤洦洧汧洯洼浛浞浠浰涀涁涊涍涑涘渗Qч涫涮涴淂洴淈淎淏淐淟淩淶渶渞渢渧㴑渲渼湈湉湋湌湏湑湓湔湗湣㴞溓溧溴溿滃滊滙漵滫滹滻漊漌漘漥漶漼潒潗潚潠潨澘潽澐澖澾澟澥澯㵤澵濈濉濚濞濩Q濼瀀瀇瀊瀣瀹瀺瀼灃灇灋㶚灔灥灩灬灮灶灾炁炆炕炗炻ь炟炱烬烊烑烓烜焃焄焆焇焈焌㷀焯焱煐煊煓煞㷔熖熀熛熠熢熮熯|熳Q燋燓燙燜爇㸅爫爫爴爸爹丬牂牓牗牣牮牯牸牿犎ё犭犮犰犱狁㹠狌㹦㹨狳狺猇猒猘猙㺃猹猬猱猳猽獒㺔獫獬獮獯獱獷玁玅玊玔玘玜玞玥玨玵玷玹玼玿珅珋珡珧珹琓珺琁琤琱琹瑓瑀瑃瑍瑒瑝瑱璁璅璈Q璒璗璙璠璡璥璪璫璹璻璺瓖瓘瓞瓯瓫瓺і甠甤甪㽗甽甾畀畈畎畐畒畬畲畱畺畽畾疁Q疌㽵疢㽷疰疷疿痀痆痏痓痝痟痠痧痬痮痱痹瘃瘘瘇瘏㾮瘓瘛瘜ћ瘥瘨瘼瘳㿉癁Q癉癕㿗癮皕皜皡皠皧皨皯盉Ѡ盨盬眗眚眭眵Q䀹ѥ睘睠睪睲睼睽Q䁘瞚瞟瞢瞤瞩矞矟矤矦矪矬䂓矰矴矻砅砆砉砍砙砡砬硇硤硪Ѫ碊碔碤碝碞碟碻磈磌磎磕磠磡磦磹磺磻磾礐礛礰礥礻祊祘祛䄅祧祲禔禕禖禛禡禩禴离秂秇秌种秖䅈Q䅏稊稑稕稛稞䅣稭稸穇穌穖穙穜穟穠穧穪穵穸窂窊窐窣窬ѯ䆴窹窼窾䆿竌竑竧竨竴Q笇笽笧笪笮笯笱䇦䇳筿筁䇮筕筹筤筦筩筳Ѵ䈇箐箑箛䈎箯箵箼篅篊Q篔篖篚篪篰簃簋簎簏簦籅籊籑籗籞籡籩籮籯籰ѹ粦Q粶粷粿糄Ѿ糈糍糗Q糦糫糵紃紉䋆紒紞紽紾絀絇Q䋖絙絚絪絰䋝絿綆綈綌綗綝綧綪綶綷緀緗緙緦緱緹䌂Q縉縐縗縝縠縧縬繅繳繵繾纆纇䌫纑纘纚䍃缼缻缾罃罄罏㓁罒罡罣罤罭罽罾羐养Q羖羜羭翃翏翣翥翯翲耂耊耈耎耑耖耤耬耰聃聦聱聵聻肙肜肤肧肸胅胕胘胦脍胵胻䏮脵脖脞䏰脤脧脬Q脽䐈腩䐗膁䐜膄膅䐢膘膲臁臃臖臛臤臬臽臿Q舄舙舡舢舲舴舼艆艉艅艋䑶艏䑺艗Q艜艣艹艹艹䒑艽艿芃芊芓芧芨芲芴芺芼苢苨苷茇茈茌荔茛茝茰茼荄荗䒾荿䓔䒳莍莔莕莛莝菉菐菔菝菥菹萏萑萕萗萹葊葏葑葒葙葚葜葥葶葸葼蒁䔍蓜蒗蒦蒾䔈蓎蓏蓓Q蓧蓪蓯蓰蓱蓺蓽蔌蔛蔤蔥蔫蔴蕏蕯䔥䕃蔾蕑蕓蕞蕡蕢蕻蕽蕿薁薆薓薝薟Q薷薼藇藊藘藙藟藡藦藶蘀蘑蘞蘡蘤蘧蘹蘼虀蘒虓虖虯虷虺蚇蚉蚍蚑蚜蚝蚨﨡蚱蚳蛁蛃蛑蛕蛗蛣蛦䖸蜅蜇蜎蜐蜓蜙蜟蜡蜣蜱蜺蜾蝀蝃蝑蝘蝤蝥蝲蝼Q螧螉螋螓螠䗥螾蟁蟎蟵蟟蟣蟥蟦蟪蟫蟭蠁蠃蠋蠓蠨蠮蠲蠼䘏衊衘衟衤Q衩衯袠袼袽袾裀裒裑裓裛裰裱䙁褁Q褷襂襅襉䙥襢覀覉覐覟覰覷觖觘觫䚡觱觳觽觿䚯訑訔訡訵訾詅詍詘誮誐誷誾諗諼Q謊謅謍謜謟謭譃䜌譑譞譶譿讁讋讔讕讜讞谹谽豅豇豏豔 豗豩豭豳Q貓貒貙䝤貛貤賖賕賙賰賱贉贎赬趄趕趦跆跈跙跬踌䟽跽踆Q踔踖踡踢踧䠖踶踹蹋蹔蹢蹬蹭蹯躘躞躮躳躵躶躻 軑軔䡎軹 輀輈輗輫轀轊轘Q 辤辴辶辶 迁迆﨤迊迍迓迕迠迱迵迻适逌逷遃遄遝!Q邅邌邐阝邡䢵邰邶郃郈郜郟郶郲鄀郫郾郿鄄鄆鄘鄜鄞鄷鄹鄺酆酇酗酙酡酤酴酹醅醎醨醮醳醶釃釄釚Q釬釮鈁鈊鈖鈗鈳鉂鉇鉊鉎鉑鉖鉙鉠鉡鉥鉧鉨鉼鉽鉿銉銍銗銙銟銧銫Q銲銿鋀鋆鋎鋐鋗鋙鋥鋧錑(#鋷鋹鋻錂錍錕錝錞錧錩Q !鍇鍑鍗鍚鍫鍱鍳鎡"$鎈鎋鎏鎞鏵Q%&鏱鏁鏇鏜鏢鏧鐉鐏鐖鐗鏻鐲鐴鐻鑅')鑭鑯镸镹閆閌閍Q*閫閴+闈,.阬阳阴Q/阼陁陡0隂1隚3䧧隩隯隳隺隽䧺Q4雘雚雝䨄霔霣䨩霶靁靇靕靗靛$靪56鞖鞚鞞鞢鞱鞲鞾韌韑韔韘韙韡韱頄頍頎頔頖䪼8頣頲頳頥顇顦颫颭颰Q9颷颸颻颼颿飂飇飋飠:飡飣飥飪飰飱飳餈䬻;餖餗=餚餛餜Q>餱餲餳餺餻餼饀饁饆饍饎饜饟饠馣馦馹馽馿駃駉駔駙駞?駰駹駼騊騑騖騚騠0&騱騶驄驌驘䯂骯䯊骷䯒骹@髆髐髒髕䯨髜髠髥髩鬃鬌鬐鬒鬖鬜鬫鬳鬽䰠魋魣魥魫魬魳魶魷鮦鮬鮱BQC鮲鮸鮾鯇鯳鯘鯝鯧鯪鯫鯯鯮D鯺E鯷G鰖鰘鰙鰚鰝鰢鰧鰩鰪QH鰱鰶鰷鱅鱜I鱉鱊J鱔鱘鱛鱝鱟鱩鱪鱫鱭鱮鱰鱲鱵鱺'鳦鳲鴋鴂L鴑鴗鴘QM䳄N鴲䳑鵂鵊鵟鵢O鵩鵫Q鵳鵶鵷鵾鶄鶍鶙鶡鶿鶵鶹鶽鷃鷇鷉鷖鷚鷟鷠鷣鷴䴇鸊鸂鸍鸙鸜鸝鹻QR麀麅麛麨S麽T黟黧黮黿鼂䵷鼃鼗鼙鼯鼷鼺鼽齁齅齆齓齕齘V齝QW齩X齭齰齵Y @8)T\  d  lt| ! #$(&'0)*l*◆□■△▲▽▼※〒→←↑↓〓'"-~〳〴〵〻〼ヿゟ∈∋⊆⊇⊂⊃∪∩⊄⊅⊊⊋∉∅⌅⌆∧∨¬⇒⇔∀∃⊕⊖⊗∥∦⦅⦆〘〙〖〗∠⊥⌒∂∇≡≒≪≫√∽∝∵∫∬≢≃≅≈≶≷↔ʼn♯♭♪†‡¶♮♫♬♩◯+▷▶◁◀↗↘↖↙⇄⇨⇦⇧⇩⤴⤵0123456789⦿◉〽﹆﹅◦•ABCDEFGHIJKLMNOPQRSTUVWXYZ∓ℵℏ㏋ℓ℧abcdefghijklmnopqrstuvwxyz゠–⧺⧻,ぁあぃいぅうぇえぉおかがきぎくぐけげこごさざしじすずせぜそぞただちぢっつづてでとどなにぬねのはばぱひびぴふぶぷへべぺほぼぽまみむめもゃやゅゆょよらりるれろゎわゐゑをんゔゕゖ @ .ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ♤♠♢♦♡♥♧♣αβγδεζηθικλμνξοπρστυφχψως⓵⓶⓷⓸⓹⓺⓻⓼⓽⓾☖☗〠☎☀☁☂☃♨▱ㇰㇱㇲㇳㇴㇵㇶㇷㇸㇹ ㇺㇻㇼㇽㇾㇿ/АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ⎾⎿⏀⏁⏂⏃⏄⏅⏆⏇⏈⏉⏊⏋⏌абвгдеёжзийклмнопрстуфхцчшщъыьэюяヷヸヹヺ⋚⋛⅓⅔⅕✓⌘␣⏎ 1─│┌┐┘└├┬┤┴┼━┃┏┓┛┗┣┳┫┻╋┠┯┨┷┿┝┰┥┸╂㉑㉒㉓㉔㉕㉖㉗㉘㉙㉚㉛㉜㉝㉞㉟㊱㊲㊳㊴㊵㊶㊷㊸㊹㊺㊻㊼㊽㊾㊿ ◐◑◒◓‼⁇⁈⁉ǍǎǐḾḿǸǹǑǒǔǖǘǚǜ2€ ¡¤¦©ª«­®¯²³·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿĀĪŪĒŌāīūēō3Ą˘ŁĽŚŠŞŤŹŽŻą˛łľśˇšşťź˝žżŔĂĹĆČĘĚĎŃŇŐŘŮŰŢŕăĺćčęěďđńňőřůűţ˙ĈĜĤĴŜŬĉĝĥĵŝŭɱʋɾʃʒɬɮɹʈɖɳɽʂʐɻɭɟɲʝʎɡŋɰʁħʕt5ʔɦʘǂɓɗʄɠƓœŒɨʉɘɵəɜɞɐɯʊɤʌɔɑɒʍɥʢʡɕʑɺɧɚ ǽὰάὲέ͡ˈˌːˑ̆‿̋́̄̀̏̌̂˥˦˧˨˩̥̬̹̜̟̠̩̯̈̽˞̴̤̰̼̝̞̘̙̪̺̻̃̚,6❶❷❸❹❺❻❼❽❾❿⓫⓬⓭⓮⓯⓰⓱⓲⓳⓴ⅰⅱⅲⅳⅴⅵⅶⅷⅸⅹⅺⅻⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ㋐㋑㋒㋓㋔㋕㋖㋗㋘㋙㋚㋛㋜㋝㋞㋟㋠㋡㋢㋣㋺㋩㋥㋭㋬ ⁑⁂T8①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪ㍉㌔㌢㍍㌘㌧㌃㌶㍑㍗㌍㌦㌣㌫㍊㌻㎜㎝㎞㎎㎏㏄㎡Ⅻ ㍻〝〟№㏍℡㊤㊥㊦㊧㊨㈱㈲㈹㍾㍽㍼∮∟⊿❖☞9俱㐂丨丯丰亍仡份仿伃伋你佈佉佖佟佪佬佾侊侔侗侮俉俠倁倂倎倘倧倮偀倻偁傔僌僲僐僦僧儆儃儋儞儵兊免兕兗㒵冝凃凊凞凢凮刁㓛刓刕剉剗剡劓勈勉勌勐勖勛勤勰勻匀匇匜卑卡卣卽厓厝厲吒吧呍咜呫呴呿咈咖咡:咩哆哿唎唫唵啐啞喁喆喎喝喭嗎嘆嘈嘎嘻噉噶噦器噯噱噲嚙嚞嚩嚬嚳囉囊圊Q圡圯圳圴坰坷坼垜﨏垸埇埈埏埤埭埵埶埿堉塚塡塤塀塼墉增墨墩壒壎壔壚壠壩夌虁奝奭妋妒妤姃姒姝娓娣婧婭婷婾媄媞媧嫄嬙嬥剝<蓮連錬呂魯櫓炉賂路露労婁廊弄朗楼榔浪漏牢狼篭老聾蝋郎六麓禄肋録論倭和話歪賄脇惑枠鷲亙亘鰐詫藁蕨椀湾碗腕Q孁孖孽宓寘寬尒尞尣尫㞍屢層屮屺岏岟岣岪岺峋峐峒峴㟢崍崧﨑嵆嵇嵓嵊嵭嶁嶠嶤嶧嶸巋吞>堯槇遙瑤凜熙噓巢帔帘幘幞庾廊廋廹开异弇弝弣弴弶弽彀彅彔彘彤彧彽徉徜徧徯徵德忉忞忡忩怍怔怘怳怵恇悔悝悞惋惔惕惝惸愜愫愰愷慨憍憎憼憹懲戢戾扃扖扚扯抅拄拖拼挊挘挹捃捥捼揥揭揵搐搔搢摹摑摠摭擎撾撿?擄擊擐擷擻攢攩敏敧斝既昀昉昕昞昺昢昤昫昰昱昳曻晈晌晙晚晡晥晳晷晸暍暑暠暲暻曆曈㬢曛曨曺朓朗朳杦杇杈杻极枓枘枛枻柹柀柗柼栁桒栝栬栱桛桲桵梅梣梥梲棈棐棨棭棰棱棼椊楉Q椵楂楗楣楤楨榀﨔榥榭槏㮶 A㯃槢槩槪槵槶樏樕樻樾橅橐橖橛橫橳檉檔檝檞檥櫤櫧㰏欄欛欞欬欵歆歖歠步歧歷殂殩殭殺每毖毗毿氅氐氳汙汜沪汴汶沅沆沘沜泻泆泔泠泫泮洄洎洮洱洹洿浘浥海涂涇涉涔涪涬涿淄淖淚淛淝淼渚渴湄湜湞溫溱滁B滇滎漐漚漢漪漯漳潑潙潞潡潢潾澈澌澍澔澠澧澶澼濇濊濹濰濵瀅瀆瀨灊灝灞灎灤灵炅炤炫炷烔烘烤焏焫焞焠焮焰煆煇煑煮煒煜煠煨凞熅熇熒燁熺燄燾爀爕牕牖㸿犍犛犾狀狻Q猧猨猪獐獦獼玕玟玠玢玦玫珉珏珖珙珣珩D琇琊琚琛琢琦琨琪琫琬琮琯琰瑄瑆瑇瑋瑗瑢瑫瑭璆璇璉璘璜璟璣璐璦璨璩璵璿瓈瓉瓚瓿甁甗甯畯畹疒㽲痎痤瘀瘂瘈瘕瘖瘙瘞瘭瘵癃癋癤癥癭癯癱皁皛皝皞皦皪皶盅盌盎盔盦盱盼眊眙眴眶睆睍睎睜睟睢睺瞀瞔瞪矠砭E硃硎硏硑硨确碑碰碭磤磲礀磷礜礮礱礴社祉祅祆祈祐祖祜祝神祥祹禍禎福禘禱禸秈秊秔秞秫秭稃穀稹穝穭突窅窠Q窳窻竎竫竽笒笭笻筇筎筠筭筯筲箞節篗篙簁簱簞簠簳簶䉤籙籭籹粏粔粠粼糕糙糝紇紈紓紝紣紱G絁絈絓絜絺綃綋綠綦緂緌緖緣練縨縈縑縕繁繇繒繡纊纍罇署羑羗羿翎翛翟翬翮翺者耔耦耵耷耼胊胗胠胳脘腊腠腧腨腭膻臊臏臗臭䑓䑛艠艴芎芡芣芤芩芮芷芾芿苆苕苽苾茀茁荢茢茭茺荃荇荑荕荽莆莒莘莧莩莿菀菇菏H菑菡菪萁萆萊著葈葟葰葳蒅蒞蒯蒴蒺蓀蓂蔲蔞蔣蔯蕙蕤﨟薭蕺薌薏薢薰藋藎藭蘒藿蘄蘅蘐Q蘘蘩蘸虗虛虜虢䖝虬虵蚘蚸蛺蛼蛽蜋蝱螇螈螬螭螵䗪蟖蟬蠆蠊蠐蠔蠟袘袪裊裎裵褜褐褘褙褚褧褰褲褹襀覔視觔觥觶訒訕$J訢訷詇詎詝詡詵詹誧諐諟諴諶諸謁謹譆譔譙譩讝豉豨賓賡賴賸賾贈贒贛趯跎跑跗踠踣踽蹰蹻軀䡄軺輞輭輶轔辦辵迤迨迮逈逭逸邈邕邗邙邛邢邳邾郄郅郇郗郝郞郯郴都鄔鄕鄖鄢鄣鄧鄯鄱鄴鄽酈酛醃醞醬醱醼釗釻釤K釥釭釱鈇鈐鈸鈹鈺鈼鉀鉃鉏鉸銈鋂鋋鋌鋓鋠鋿錄錟錡錥鍈鍉鍊鍤鍥鍪鍰鎛鎣鎺鏆鏞鏟鐄鏽鐳鑊鑣鑫鑱鑲閎閟閦閩閬閶閽闋闐闓䦰闚闞陘隄隆隝隤隥雒雞難雩雯霳霻靍靎靏靚靮靳鞕鞮鞺韁韉韞韛韴響頊頞頫頰頻顒顓顖,M顗顙顚類顥顬颺飈飧饘馞騂騃騤騭騮騸驊驎驒骶髁髃髎髖髹鬂鬈鬠䰗鬭魞魹魦魲魵鮄鮊鮏鮞鮧鯁鯎鯥鯸鯽鰀鰣鱁鱏鱐鱓鱣鱥鱷鴝鴞鵃鵇鵒鵣鵰鵼鶊鶖鷀鶬鶼鷗Q鷧鸇鸕鹼麞麤麬麯麴麵黃黑鼐鼹齗龐龔龗龢姸屛幷瘦繫N+e,./j123l56L89:x<=|npqstvwyz |}(08@ĉȞPԏXܒ`hp?T؟\dlt| (08@HPX`AB DEGHJK$MN,P4P Q  R S,S (T  4U [U U V !V cW,U|X|X X  X KY  Y 8Y Y SY Y Y Z [Z Z Z ![X,UXY0YYYYY|ZZZZZ [c([ p[ [ \ )][\]^,Uk^ ͿТУʺξФХЦðЧШ^Щǵ Ƿ˳ЪЫ֦_ ЬЭλͽЯвгде˴жμзий1D`ом нлкʩ¾пǤs` Ȳȼa âͤ;դʻdb եη98c¥ ¯ɶ{c,U_<``a\b0ccdd d ¦Ae ˵ѣtf ѤѡѢƯѥνѦѩѧѨѪѬѫ$gѮѯ ѭѲѱѰѳѴͥѶѵѸѷѹ gѺѼ ѻѽѾȬϻʼ¶ŵI h ̽ li οȡ Djʬ Ƚ!k §˶Q!k έҢңϫҥҤ!hlҦ ļͦҧưҨ̳ҩҭҪҫҮүҰұ!4m ҲҳҵҷҶҸҹҺһҼҽҾɤƿ" nҿ Ⱦ´ñ¨Y"n ֛"o ͧȿá"Tp Ʊ̾ʭ#(q Ϥ̣̿a#q ӣӡӾӥӤ#|rӢ ӦӯӧӨӭӬůӮӫ#Ds өӪӴͣӺӹӰ'$sӱ ӶӳӷӸӵӻӲi$\tӽ ӿӼ$t ԧ$u ò/% v ʮȸq%v ǹ%Tw %w ԡԢԣԤԦԥԨԩԪԫԭ7&xԮ ˷ԬԯԳó԰Դy&y ԲԵԶԷԹԺԻԸ&,zԱ ԼԽԿԾǸ&z Ʋ?'`{ʽ ȹŶ'{ ʯ'| (4} ͼ¿̴ŷG(} åʳա(~ բǡǥի̯֬գզ˸է(| ըլխժթɱ ) ղհ̼ճձկծշոO)մϬ նչպյ̻)H ջɲռս) տվ*8 W* ¸¹֣ƙ*  ͨ*̩̃ ǫ+ ºƳǢ_+ ֢֡Ÿ°֤֥֧֨+D ְֱֳ̨֪֭֮֩֫֯+ ֲִֵƽֶַָֹֻ%, ּֽ־g, ֿ, ֺ,  ̦ç-- ġĢ˹o-H Ȩʾʿǯͩ-ģ Ź- ϭספץףקצערשת׭׫׬׮ׯǶװ5.< ױϮײ׵Сб׶Ĥ׷ʦ׸׹׿ĥ׺ɫw.׻ ׼׽׾״׳ɧɷĦ. ΧħŰ. ɬǦ˺˻حǰ=/|elfgghdi ȮȧȨȩίȪȫȬȭȮȯŮȰȱs>Ȳȳȴ ȵȶȷȸȹȺȻȼȽũߣȾȿ>0 ɺϳߢ̡ߡ>̹ ߯ߪ߳߬Ĭߩߦߥ߮9?tߨߧ߭ ߤ߰߱߶ߵ߷ߺߴ߸{?߲ǻ ߹߾߼߿ɡɢ߻Ǩ޹ɣɤ߽ɥ߫ɦɧɨɩ?l,dԗ,8,Pğ\ȡp ФDH84|PL@X(ĹlDLɪ ɫɬɭɮɯɰɱɲɳɴɵɶ?X ɷɸɹɺɻɼɽɾɿA@ ϧú@d ˣ@ ʲ̵A@ ʡʢIAʣ ʤʥʦʧʨʩʪʫʬʭǮʮʯʰʱA<ʲʳ dzʴʵʶʷʸʹʺʻʼʽAʾ ʿBT ĭ̶ϴʪQB B ìϵˡB( ˢˣˤ˥˦˧˨˩˪˫ˬ˭ˮ˯˰ǭ˱˲˳˴ͱͲ˵˶˷C ˸˹˺˻˼˽˾˿YCt ΨC ̡C̢̣ ̤̥ΰ̴̵̶̧̨̦̩̪̫̬̭̮̯̰̱̲̳D\̷ ̸̹̺̻̼̽̾̿aD D ɻDD ͣ͢͡żͤͥͦͧͨͩͪͳͫҴͬĮͭͮͯ'EͰ ͱͲͳʹ͵ȪͶͷα͸͹ȫͺɭάͻͼͽ;ͿiE ɥϫE ΡE, Ρ΢/FΤΥΦΧΨΩΣΪ ΫάέήίΰαβγδȯɴqFε ŪζηθικλμνξοF` ݹľF ̲į7G ϡϢϣϤϥϦϧϨϩϪyGϫ ϬϭϮϯϰϱϲϳϴϵ϶ϷϸϹƷϺϻG( ϼϽϾϿ̷ûG ˤ?HT βȣH СТУHL ФХЦЧШЩЪЫЬЮЯабЭвгдезийклIж мнопGI ʹǪɼI0 ϽʡǩI ѡѢѣѤѥѦѧѨѩ J ѪѫѬѭѮѯѰ̭ѱɣѲѳѴѵѶѷѸѹѺѻѼѽѾOJ8 ѿJ J ΩεƸèüѿKL ūҡҢңҤWKҥҦ ɮҧȦҨȵҩҪҫҬҭҮүҰұҲҳK ҴҵҶҷҸ̧ҹҺһҼҽýҾҿȢȤKd ϶L _L ӡӢӣӤӥӦӧӨөӪӫL| Ӭӭʴ̰ӮγӯǴӰӱӲӳӴӵӶӷӸӹL, ӺӻӼӽӾӿʵ%M ǼɳʶgM Mh ³ԡԢԣԤԥԦԧԨþM0 ԩԪԫԬԭԮԯ԰ԱԲԴԵԶԷԸԹԺԻԼԽԾ-NԳ Կ˥oN Np ŻN$ 5O ȳաբգդwOե զէըթժիլխծկհձղճմյOն շոչպջռսվտO4ܽ\ܾ84L lT<$X x LD(0D\t$`(h,Ux,Ϸ ÿ=P ʹİϸP ȥϾȩɪP8 ˦֢֣֡ƹ֤֥֦ǽ֧Q ְֱֲֳ̮֪֭֮֨֩֫֬֯æǾִıֵֶEQ| ַָֹֺֻּֽ־ֿIJʢQ ɨǿQ ¡ RP ڪаMR$ סעףפץצקרשת׫׬׭׮Rׯװ ױײ׳״׵׶׷׸׹׺׻׼׽׾׿˧R Sd US  ؾءآSأ ؤإئابةتثجحخدذرزسشصSLض طظعغػؼؽؿɩT ƺ˨]T ΪơǬT  T ̬١٢٣˩ϡ٤٥٦٧٨٪٫٬#U` ٭ٮٯٰٱٲ̢ٳٴٵٶٷٸٹٺٻټ٩ٽپ¢ٿeU ƢקU UX ƣڡ+V$ڢ ڣڤڥڦڧڨکݱݢڪګڬڭڮگڰڱڲڳڴڵmVڶڷ ڸڹںڻڼڽھκڿVP V Ⱥ3W ˪̪ۣۡۢۤۥۦۧۨ۩۪uW4۫ ۭ۬Ϲۮۯ۰۱۲۳۴۵۶ij۷W ۸۹ۺۻۼ۽۾ۿͻW ;X  ܡܢ}Xܣܤܥ ܦܧܨܩާܪܫܬܭܮܯܱܰܲܳɽܴܷܵܶXtܸ µܹܻܼܾܺܽܿY< ΢͵ΣCY ʣ˫Y| ݡݢݣY$ ʤݤݥݦݧݨݩݪݫݬݭݮݯݰݱݲݳ Z ݴݵݶݷݸݹݺݻݼݽݾݿKZ Ƥˬ֍Z ɾZ ǧͶïޡޢޣޤĴ[ ޥަާިީުޫެޭޮĵޯްޱ͡޲޳޴޵޶޷S[h ƥ޸޹޿޺޻޼޽޾ɵ[4 [ \ ë[\ Ʀ˭Юɿ\ ߡߢߣߤߥߦߧߨߩߪ߫Ž\Ϩ߬߭߮±߯ ߲߰߱߳ߴߵ߶߷߸߹ߺ߻߼߽߾߿!] £c]d ʥ] Ķ­]  ϩķ)^  Ƨk^<  ^  ^  ž1_(  ͢s_  Ųᬵ_  ҡäé_ ų9`0tH\DXPH,xl4t`,|,U\  4  x    HPƨ Ʃ®¤Ϣɯ{`\ ͷƻã½Ŭ`8 ͸ˮš` Ϻ͹Aa Ţ҃a\ a Ȱb ΤţIbh b@ Ŵȭb Ƽĸc ˯Qcp ϣϿc0 c d ŭYd( ƪd dd e Ĺae  ȶ泣e@ Ʈe 'f ƫΦif δȻf ͺΥʷf  ̸Ϫ۱/g,! qg! ׳g" ǣgD# ĺƬ7h# ſyh$ ûhX% Ҭݻ˰h% ?i(& i& i\' j' ƭGjx( j) j) ȱɦ k) ݵOk* ̥ϥёkh+ ʫk, l, Wl- íؙlP. Ļȷ˱l. ƾm@/ ̹˲_m/ 췡m0 m1 %n1 gn2 ϼn42 n2 Ťɡ-o3 ooP4 ζo 50 T`8h( \,U8x $!!"<##$P%% &&T''p()|))*`+,,x-H..8//x0111,223H45X5o`55p|X Wph6 ph7 pl8 q8,U`7d88 9_q9Xq4949q49R$S T$U,UUUVVWtXXXh[^dDPTX6`6,9<9D9L9qT9 r9 s: `s`: s: s: &tP; htx;X:,U|::Y0YH;Yp;Y;|ZZZZZ [t; t(< .u< pu< u< u= 6vD= xvl=<\]^,U<<=<=d=|=v=ом нлкʩ¾пǤv=,U_<``|>\b0ccd> ѤѡѢƯѥνѦѩѧѨѪѬѫ>w> οȡwt? ҲҳҵҷҶҸҹҺһҼҽҾɤƿw4@ ӣӡӾӥӤxAԮ ˷ԬԯԳó԰ԴFxA ʯxB̩ ǫx4C ֲִֵƽֶַָֹֻ yD ֿNy|D ΧħŰy Eelfgl?hdiFLNTY``6Dd<9D9L9"l  [ ( ߅Ԅ ! c܅ 0 sPX:,UHY0YH;Yp;Y;|ZZZZZ [t ͿТУʺξФХЦðЧШ ЩǵǷ˳ЪЫ֦) ЬЭλͽЯвгде˴жμзийkо мнлкʩ¾пǤ Ȳȼ âͤ;դʻ1 եηs ¥¯ɶl,Uxd   ¦9 ˵ѣ{ ѤѡѢƯѥνѦѩѧѨѪѬѫXѮѯ ѭѲѱѰѳѴͥѶѵѸѷѹѺ ѼѻѽѾȬϻʼ¶ŵA ̽ οȡŊ` ʬȽ §˶I` έҢңϫҥҤ؏Ҧ ļͦҧưҨ̳ҩҭҪҫҮүҰұ͋P ҲҳҵҷҶҸҹҺһҼҽҾɤƿؐҿ Ⱦ´ñ¨Q\  ͧȿáՌP Ʊ̾ʭ Ϥ̣̿Y| ӣӡӾӥӤܓӢ ӦӯӧӨӭӬůӮӫݍP өӪӴͣӺӹӰӱ ӶӳӷӸӵӻӲaӽ ӿӼD ԧ ò' ʮȸi@ ǹ Ȗ ԡԢԣԤԦԥԨԩԪԫԭ/4Ԯ ˷ԬԯԳó԰Դq ԲԵԶԷԹԺԻԸԱ ԼԽԿԾǸ0 Ʋ7ʽ ȹŶy ʯL  ͼ¿̴ŷ?$ åʳա բǡǥի̯֬գզ˸էÒ( ըլխժթɱ ղհ̼ճձկծշոGմϬ նչպյ̻0 ջɲռս˓h տվ  O؜ ¸¹֣ ͨӔ ̩ǫ$ ºƳǢWȞ ֢֡Ÿ°֤֥֧֨X ְֱֳ̨֪֭֮֩֫֯ە̟ ֲִֵƽֶַָֹֻ( ּֽ־_x ֿȠ ֺ ̦ç%` ġĢ˹gܡ Ȩʾʿǯͩ@ ģŹ ϭספץףקצערשת׭׫׬׮ׯǶװ-  ױϮײ׵Сб׶Ĥ׷ʦ׸׹׿ĥ׺ɫo ׻׼׽׾״׳ɧɷĦH ΧħṲ̋ ɬǦ˺˻حǰ5\PX؎XЏHАTHtԓH<8|,(D ܛ(`М Pğ pXԡ8@ĤT w̦ ©4 ءاإأؤآͪئǺجذةخ دثرتبؽظصضعؼ=@ط غشؾؿسػ زθ0 ͫʰƴ ĨE$ ١٢٣٤٥٦٧˼٨ ٩ʧ٬٪٭٫ٮʱٯٲɛ ٰٷٱٳٴٸٵȴڭٻ  ôپټٺٶٹٽM ĩ ªĽDZќ Ϋõ< ·ͬU » Ŧٝd DzƵűڥ ڧڣڤڢٿڦڡګڬŧڮکگڨڳڲڱڴڶ]ڵ ڹڷڸڻںڼڰڽھڿl Ũ̯ ʸ#8 ι²öe ۦ(  Ī˽ۢ+0 ۣۡۤۥۧۨ۩۪۫m ͭ۬Ŀۭϯ˾īۮۯ۰̤۲۴۷۶۳ ۵۸¼ۻ۹«ۺۼ۽ۿ ۾3< ɢ˿ͮu 0 ɰ ; ܲܡܣܧêܫܨܢܬܪ}x ܦ̺ܥܯܱܰܩܭܮܿܤܻܽ ܸܾܷܼܴܵܺܶܳϰܹh ϱC @ ɸîǣ  , ݡݬݨݧݦݣK ݥݤݪϦݭݩݫȧݮݲݯй ݰݳݴݶݸݷݺϤ ݽݼݾ÷ݿt S ` ̱ɹץ  ʨޡ[h ˡޤޢˢťޥޣ ްޯެƶަީޮޭިޫުߦT ή޶޴ޱ޳ϲ޵! ޺Ͱ޷޲޸޾c ޿øʥ޻źd ޽޼¬ ̫ùͯ)| ȮίŮkп ũߣ0 ɺϳߢ̡ߡ ߯ߪ߳߬Ĭߩߦߥ߮1ߨߧ߭ ߤ߰߱߶ߵ߷ߺߴ߸s@߲ǻ ߹߾߼߿߻Ǩ޹߽߫,8( xܬ4\dį0 (4(p`ܷ8$xȹlX`L\tȿ(8   9p ϧú{ ˣ ʲ̵, Ah Ǯ dzū t ĭ̶ϴʪI 0 ìϵͬ ǭͱͲ Q@ Ψ խ ΰ$ Y|  ɻݮ  żͳҴĮ` Ȫαȫɭάa ɥ Ρ '` ȯɴi Ū ݹľ ̲į/ q` Ʒ ̷û ˤ7H βȣy  , ?x ʹǪɼ Ͻʡǩó(  ̭ɣG P ˴ ΩεƸèüѿ  ūO ɮȦȵ ̧ýȢȤӵ ϶ WD  ʴ̰γǴ۶ ʵt Ǽɳʶ_ h ³þ %h ˥g H Ż - ȳo$  h$`l(x8tXxXX@$p H  x<l``@,UX`Ϸ ÿ5l ʹİϸw ȥϾȩɪ< ˦ƹǽ ̮æǾı= IJʢ` ɨǿ ¡0 ڪаE , ˧ɼ   MT  ѽ  ɩd ƺ˨U ΪơǬ( پ ̬˩ϡ ̢¢]8 Ƣ  ƣ#` ݱݢe κ D Ⱥ+ ˪̪m ϹijL ͻ 3 u, ާɽ| µ ΢͵Σ;P ʣ˫}  ʤp C Ƥˬ ɾ ǧͶïĴ  ĵ͡K ƥɵ   ëS4 Ʀ˭ЮɿP ŽϨ ±@ £[  Ķ­D ϩķ!x Ƨc  l ž) ͢k$ Ų ҡäé ų184X($L\ 0X<D$tH h,,UH8<p d0 ƨƩ®¤Ϣɯs ͷƻã½ŬH ͸ˮš Ϻ͹9P Ţ{  Ȱ( ΤţA  Ŵȭl Ƽĸ ˯I$ ϣϿ  H ŭQ ƪ    ĹY ȶ Ʈ( l ƫΦa δȻ$ ͺΥʷ ̸Ϫ۱'4 i 0 ǣ ĺƬ/ ſqD  Ҭݻ˰ 7 y   ƭ?`   ȱɦ ݵG ̥ϥ ʫ(   O íX Ļȷ˱ ƾ ̹˲W  |    _, ϼP  Ťɡ%4 gl ζ@H xd@x,U d,(<xX| |Pt$H,do  ؂      ,U   8   ,Ūԅ(XX=Ħd`6 <9D9L9  h   $  f  P d , nH   4 v  ,U< ~ x  D  \   L 8 |  T   X l \4 h  " @ dT   *p,UT0tPd;,|ZZ`8Ll T  2 tL   :l | ־  B Ȅ   , JD ʌ` t  R    Z 0 L  ` bx ߤ  ( j   08 rP h  8 z   @ Ȃ  , @\,UD<d=<=d=$<Xl (DXp0H`x$8PHX 4  H  \  p    P  Ȓ      ! X! 4! H! `! `! ! ! &! ! h" " R0" D" .\" pt" " " " 6" x" " # ># 4# H# \# F|# # # Y# ͿТУʺξФХЦðЧШ # ЩǵǷ˳ЪЫ֦N$ ЬЭλͽЯвгде˴жμзий$ом нлкʩ¾пǤ% Ȳȼ\& âͤ;դʻV& եη' ¥¯ɶ(@ T h ,U|      !,!@!X!x!!!!!!"("<"T"l""""""""#,#@#T#t#####$$%T&&|'((( ^t) ¦ * ˵ѣ* ѤѡѢƯѥνѦѩѧѨѪѬѫ$ +Ѯѯ ѭѲѱѰѳѴͥѶѵѸѷѹf+Ѻ ѼѻѽѾȬϻʼ¶ŵ,, ̽, οȡ,- ʬȽn,. §˶. έҢңϫҥҤX/ ҦļͦҧưҨ̳ҩҭҪҫҮүҰұ4/ ҲҳҵҷҶҸҹҺһҼҽҾɤƿv0ҿ Ⱦ´ñ¨(1 1 ͧȿá<D2 Ʊ̾ʭ~2 Ϥ̣̿3 ӣӡӾӥӤ4Ӣ ӦӯӧӨӭӬůӮӫD4 өӪӴͣӺӹӰ45ӱ ӶӳӷӸӵӻӲ5ӽ ӿӼ 6 ԧL6 òĎ6 ʮȸh7 ǹ7 TT8 ԡԢԣԤԦԥԨԩԪԫԭ8Ԯ ˷ԬԯԳó԰Դh9 ԲԵԶԷԹԺԻԸ9Ա ԼԽԿԾǸ\@: Ʋ:ʽ ȹŶP; ʯ"; dD< ͼ¿̴ŷ< åʳա= բǡǥի̯֬գզ˸է*$> ըլխժթɱl> ղհ̼ճձկծշո?մϬ նչպյ̻? ջɲռս2? տվt4@ @ ¸¹֣@ ͨ:A ̩ǫ|8B ºƳǢB ֢֡Ÿ°֤֥֧֨C ְֱֳ̨֪֭֮֩֫֯B0D ֲִֵƽֶַָֹֻD ּֽ־E ֿ E ֺJ E ̦ç pF ġĢ˹ G Ȩʾʿǯͩ G ģŹR 0H ϭספץףקצערשת׭׫׬׮ׯǶװ HױϮ ײ׵Сб׶Ĥ׷ʦ׸׹׿ĥ׺ɫ TI׻ ׼׽׾״׳ɧɷĦ J ΧħŰZ J ɬǦ˺˻حǰ lK**++$,,-$..P//0 11<22344,55666`77L88`998::H;;<<<=>>?|??,@@@A0BBC(DDEEEhFGG(HHLIJJdKLL  M © M ءاإأؤآͪئǺجذةخb (N دثرتبؽظصضعؼ Nط غشؾؿسػ `O زθ( O ͫʰƴj P Ĩ Q ١٢٣٤٥٦٧˼ Q٨ ٩ʧ٬٪٭٫ٮʱٯٲ0(R ٰٷٱٳٴٸٵȴڭٻrR ôپټٺٶٹٽHS ĩS ªĽDZ8pT ΫõzT ·ͬxU »U Ŧ@hV DzƵűڥV ڧڣڤڢٿڦڡګڬŧڮکگڨڳڲڱڴڶ0Wڵ ڹڷڸڻںڼڰڽھڿW ŨHTX ʸX ι²öpY ۦY PZ Ī˽ۢ`[ ۣۡۤۥۧۨ۩۪۫[ ͭ۬Ŀۭϯ˾īۮۯ۰̤۲۴۷۶۳\ ۵۸¼ۻ۹«ۺۼ۽ۿX$] ۾] ɢ˿ͮd^ _ ɰ`_ 8` ܲܡܣܧêܫܨܢܬܪ` ܦ̺ܥܯܱܰܩܭܮܿܤܻܽ&a ܸܾܷܼܴܵܺܶܳϰܹh,b ϱb Xc ɸî.d pd ݡݬݨݧݦݣ e ݥݤݪϦݭݩݫȧݮݲݯe ݰݳݴݶݸݷݺ6f ݽݼݾ÷ݿxf 4g g ̱ɹ>Lh h ʨޡ9Ϩ ±9< £9ܮ :, Ķ­F:h ϩķ: Ƨ:(  ; N; ž; ͢; Ų< ҡäéV<ܲ ų<Hdt`,ędx  (ĠH̡DDԣT4@Lħ4Ĩ$T|,U4Ԯ$` xԲ@ܳƨ Ʃ®¤Ϣɯ< ͷƻã½Ŭ= ͸ˮš^=X Ϻ͹= Ţ=l $> Ȱf>l Τţ> > Ŵȭ,? Ƽĸn? ˯? ϣϿ? 4@ v@ ŭ@ ƪ@\ Z  ͚ Z, D 𳖂X Zl bN   [   F[ [ ZM(,U$<Pdx  4[<  \ M 򡖂 N\ PT p  \ \0 \D ]X bNl V] ] ] &W ^ 4   ^^  ^< X ؂l ^,U(<Pdx4Pdx$_ f_  S$ S8 L R`p` R| 6Y  jO ب_ _ jO PT $ ,`8 P Ėd Ux jO n`  `0,UDXlt0H\p` @RT 4ah va a N a ?@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@           !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVW  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUV  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^  !"#$%&'()*+,-./0123456789:;<=>?@ABCDDDDDDDDDDDDDDDDDDDDDDDDDDD  !"#$%&'()*+,-./0123456789:;<=>?@ABCDE  !"#$%&'()*+,-./0123456   !"#$%&'()*+,-./0123456789:;<=>?  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTTTTTTTTTTT  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWWWWWWWW  !"#$%&'()*+,-./01  !"""""""""""""""#$%&'()*+,-./0123456789:;<=>?@ABC"""""""""""""  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!  !"#$%&'()*+,-./01234444444444444444444444444444444444444444444  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQ    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQ  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRST  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOOPQRSTUVWXYZ[\]  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQ RSTU 𠂉𠂢𠂤𠆢𠈓𠌫𠎁𠍱𠏹𠑊𠔉𠗖𠘨𠝏𠠇𠠺𠢹𠥼𠦝𠫓𠬝𠵅𠷡𠺕𠹭𠹤𠽟𡈁𡉕𡉻𡉴𡋤𡋗𡋽𡌶𡍄𡏄𡑭𡗗𦰩𡙇𡜆𡝂𡧃𡱖𡴭𡵅𡵸𡵢𡶡𡶜𡶒𡶷𡷠𡸳𡼞𡽶𡿺𢅻𢌞𢎭𢛳𢡛𢢫𢦏𢪸𢭏𢭐𢭆𢰝𢮦𢰤𢷡𣇃𣇵𣆶𣍲𣏓𣏒𣏐𣏤𣏕𣏚𣏟𣑊𣑑𣑋𣑥𣓤𣕚𣖔𣘹𣙇𣘸𣘺𣜜𣜌𣝤𣟿𣟧𣠤𣠽𣪘𣱿𣴀𣵀𣷺𣷹𣷓𣽾𤂖𤄃𤇆𤇾𤎼𤘩𤚥𤢖𤩍𤭖𤭯𤰖𤴔𤸎𤸷𤹪𤺋𥁊𥁕𥄢𥆩𥇥𥇍𥈞𥉌𥐮𥓙𥖧𥞩𥞴𥧔𥫤𥫣𥫱𥮲𥱋𥱤𥸮𥹖𥹥𥹢𥻘𥻂𥻨𥼣𥽜𥿠𥿔𦀌𥿻𦀗𦁠𦃭𦉰𦊆𦍌𣴎𦐂𦙾𦚰𦜝𦣝𦣪𦥑𦥯𦧝𦨞𦩘𦪌𦪷𦱳𦳝𦹥𦾔𦿸𦿶𦿷𧄍𧄹𧏛𧏚𧏾𧐐𧑉𧘕𧘔𧘱𧚓𧜎𧜣𧝒𧦅𧪄𧮳𧮾𧯇𧲸𧶠𧸐𧾷𨂊𨂻𨊂𨋳𨐌𨑕𨕫𨗈𨗉𨛗𨛺𨥉𨥆𨥫𨦇𨦈𨦺𨦻𨨞𨨩𨩱𨩃𨪙𨫍𨫤𨫝𨯁𨯯𨴐𨵱𨷻𨸟𨸶𨺉𨻫𨼲𨿸𩊠𩊱𩒐𩗏𩙿𩛰𩜙𩝐𩣆𩩲𩷛𩸽𩸕𩺊𩹉𩻄𩻩𩻛𩿎𪀯𪀚𪃹𪂂𢈘𪎌𪐷𪗱𪘂𪘚𪚲    !"#$%&'()*+,-./0123456789:;<=>????????@ABCDEFGHIJKLMNOPQRSTU??  !"#$%&'$$$$$$$$()*+,-./0123456789:;<$$=>?@ABCDEFGHIJKLMNOPQRST  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTTTTTTTTTUV  !"#$%&'()*+,-./0123456788888889:;<=>?@ABCDEFGHI888J8888KL888MN𠀋𡈽𡌛𡑮𡢽𠮟𡚴𡸴𣇄𣗄𣜿𣝣𣳾𤟱𥒎𥔎𥝱𥧄𥶡𦫿𦹀𧃴𧚄𨉷𨏍𪆐  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`a     !"#$%&'()*+,-./0123456789:;<=>?@  !"#$%&'()*+,-./0123456789:;<  !"#$%&'()*+,-./0123456789:;<=>   !"#$%&'()*+,-./0123456789   !"#$%&'()*+,-./0123456789:;<=>?                !"#$%&'()*+,-./012345678  !"#$%&'()*+,-./0123456788889:;<8  !"#$%&'()*+,-.    !"   !"#$%&'()*   !"#$%&'()*+,-.  !"#$%&'  !"#$%&'()*+,-./012  !"#$%&'()*+,-  !"#$%&'()*+,-.   !"#$%&'()*+,-./012    !"#$%&'()*  !"#$%&'()   !"#$%&'()*+,   !"#$%&'()*+,-./0  !"#$%&'()*+,-  !"#$%&'()*+,-./0123    !"#$%&'()*+,        !" #$%&'()*     !"#$%&'()*    !"#$%&'()*+,-./0    !"#$%&'()*+,-./0123   !"#$%&'()*+,-./01234  !"#$%&'()*+,-./    !"#$%&  !"#$%&'()*+,-./012  !"#$%&'()*   !"#$%   !"#$%&'()*+,-./              !"#$%&'(       !"#  !"#$    !"#$  !"#$%&'()*+,-./  !"#$%&'()*+,-./0  !"#$%&'       !"#$%&'  !"#$   !"#    !"#$%   !"#$%&'()*+,-   !"#$%&'()*+,-  !"#$%&'()*+,-./    !"#$%    !"#$%&                     !"#$%&'(  !"#$%&'()*+,-./0123456      !"# $ %&'( )*+, - . /01  !"#$%&'()*+,-.  !"#$%&'()*     !"             !"     !"#$%&'    !"#$     !"#$%&'()*+,-   !"#   !"#$%&'()*+,-.  !"#$%&'()*+,-./0123456   !"#$%&'()*+,-./01  !"#$%&'()*+,-./   !"#$%&'()*+,-.  !"#$  !"#$%&'()*+,  !"#$%&'()*+,-./01    !"#$%&'()*+,-   !"#$%&'()*+,-.  !"#$%&'()*+,-    !"#$%&'()*  !"#$%&'()    !"#$%&'()*+,-   !"#$%&'()*  !"#$%&   !"#$%&'()*+,-   !"  !"#$%&'()*+    !"#$%&'()*+,-   !"#$%   !"       !"#$%&   !"#$%&'()*+,-     !"#$%&'()*   !"#     !"#$%&'()*+    !"#$%&'()*   !"#$%&'()*+,-./012   !"#$%&'()*+,-./012   !"#$%&'()     !"#$%&'()   !"#$%&'()*   !"#$%&'()*+,-   !"#$%&'()   !"#$%&'()*+,-.    !    !"#$%&'()*+,     !"#$%&'()*+   !"#$%&'()*+,-./  !"#$%&'()*    !"#$%&'()*+,-.    !"#   !"#$%    !"#$%&'()*+,-       !"#$%      !"#$%&'    !"#$%&'()    !"#$%&'()*+,-     !"#    !"#$%&'(     !"#$%&'()   !"#$%&'()*    !"#$%&        !"#$%&'()*+,-.     !"#$%&'   !"#$%     !"#$     !"#$%&'  !   !"#$%&'(     !"#$                                !"#     !"    !"#$%&'()*+,-./          !"#$   !"#$%&'()    !"#$      !"#$%  !"#$%&'(    !"#     !"#$%&'   !"#$%&'    !"#$%&   !"#$%&'()*+,-.  !"#$%&'()*+,-./01234   !"#$%&         !"#$%&' () * +,  !"#$%&'()*+,  !"#$%&'()*+,   !"#$%&'()*  !"#$%&'()*+    !"#$%&'()*    !"#$%&'    !"   !"#          !"#$%&'(    !"#$%&'    !   !"#$%&'()*    !"#$%&'(    !"#$%&'   !"#$%&'()*+,   !"#$%&'()*    !"#$%&  !"#$%&'()*+,-./0     !"#$%&  !"#$%&'   !"#$%&'()*  !"#$%&'(   !"#$%&'()*+  !"#$%&'()     !"#$%&'()*+    !"#$%&'(   !"#$%&'()*+,-./0123       ! " # $%&' () *+,- . /    !"#$%&'()*+,-./0  !"#$%&'()*+,    !"#$%&'()*+     !"#$%&'()*     !"#$%&'()*+  !"#$%&'()*     !"#$%   !"#$%&'()*+,-./01       !"#$    !"#$%&'     !"#    !"#$%&'()   !"#$%&'()*+,-./012   !"#$%&'()*+,-     !"#$%&'(    !"#$%&'()*+,-./012    !"#$%&'       !"#$%&'()* +,       !"#$%&'   !"#$      !"#$%&'()*+,-.    !  !"#$   !"#$%&   !"#$%&'()*+   !"#$%&'()*+,-./0    !"    !"#  !"#$%&     !"     !"#$%&'(   !"#$%&'()*+,     !    !"#$%     !"#$%&  !"#$%&'()  !"#$%&'()*+,-./  !  !"#$%&'()   !"#$%&'     !"#$%&'()*+     !"#$%&'()*        !"#$%&'()*+,-./    !"#$%&'()*+,-./01    !"#$%&'()*+,-./0   !"#$%&'()*+,-./0    !"#$%   !"#$%&'()    !"#$%&'()*+    !"#$%&'()*+,-./       ! " #$ %& ' ( )* +,-./0              !"#$%&'()    !"  !"#$%&'()    !"#$%&'   !"#$     !"#$%&'()*+,-./01           !"#$%&'()*+   !"#$%&'()*+,-./01234  !"#$%&'()*+,-./01234  !"#$%&'()      !"#     !"#$%   !"#$%&'    !"#$%&'()*+,-.   !"#$%&'()*+,-./0123    !"#$%&'()*+,   !"#$%&'()*+,-./0    !"#$%&'   !"#$%&'()*+,-    !"#$%&'()   !"#$%&'(     !"#$  !"#$%   !"#$    !"#$%  !"#$%&'()*+,-.            !"#$%&'()*+   !"#$%&'()*+,-./01  !"#$%&'(   !"#$%&     !"#$%&'()*+,-.    !"#$%&'()  !"#$%&'()*   !"#$%&'()*+,-./   !"#         !"#$%&'()*+,-       !"#$%&'(  !      !"#$%&'()*+,-./   !"#$%&'()*+,-./   !"#$%&'   !"#$%&'()*+,-  !"#$%&'()   !"#$%&'()*+,-./01   !"#$%&'(       !"#$     !"#$%&    !"#    !"#$%       !"#$%&'()*+,-    !"#$%&'()*  !"#$%&'    !"#$%&'()*+,    !"#$%&'()*+,-./0123456789:;<=   !"#$%&'()*+,-./0123456789:;<=  !"#$%&'()*+,-./0123456789:;<=>  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!                            !"#$%&'()*+,-./   !"#$%&'()*+,-    !"#$%&'()*+,-   !"#$%&'()*+,-./0123456  !"#$%&'()*+,-./0  !"#$%&'(    !"#$%&      !"# $% &'() *+,- . / 012      !  !"#$%&'()*+,-./0  !"#$%&'()*+,-./012   !"#$%&'()*+,-./   !"#$   !"#$%&'()*+,-./0123   !"#$%&'()*+,-./0123    !"       !    !"#$%&'()*+,-./0      !     !"#$%&'()*+,-./       ! " #$ % & '()* + ,    !"  !"#$%&'()*+,-./01    !"#$%&'()*+,-./01  !"#$%&'()*+,-     !"#$%&'()*+,-./01   !"#$%&'()*   !"#$%&'()*       ! " #$ %& ' () *+ ,-./01         !"#$    !"#$%&  !"#$%&'()*+,-./   !"#$%&'    !"#$%&'()*+,-./0      !"#$%&'()*+,-./0   !"#$%&'(   !"#$%&'()*+    !  !"#$%&'()*+,-./0123456789:;<=>?    !"#$%&'(   !"#$%&'()*+,-./012     !     !"#$    !                                 !"#$   !"#$%&'                         !"#       !"#$%&                                                                                                           !"     !"#$%&   !                                      !"    !"        !                         !                 !"#                                                              !      !                                                                                                                                                                                                           !"                                                                                      !"#$                                                                                                                                                                                                                                                        !"#                                               !"#$  !"#$%&'()                      !"#                                                   !                                                                                                                     ! "#    !"#$%&'()*+,        !"#$                             !"#$%&'()*+,-./         !"#$  !"#$%&'()*+,-./0123456789:;<=      !"#$%&'()*+,-./01234   !"#$%&'()*      !"#$%&'()    !"#$%&'()     !"#$%&'()*      !"#$   !"#$%&'()*+,-./01  !"#$%&'(             !"#$%&'(   !"#$%&'()*+,    !"#     !"    !"#   !   !"#$%&'    !"#    !"#$%&'()     !"#$%&'()*  !"#$       !"#$%&                                             !"#              !"#$%&'()    !"#    !"#                             !"#$    !"#$%&'      !"#$%&'()*   !"#$%&'  !"#$                 !"#      !"#$%&        !"#$%&'(  !"#$%&'()*+,     !"#$%&'  !"#$%&'()*    !"#$           !"#$%   !"#   !   !"#$%         !"#   !"#$%     !"#$%&'(             !                   !"#$%&        !"#$%         !"#$%&'    !"#$%&'()*+,   !"      !"#$%&   !"#$%&'()*      !"#$%&'(     !"#$%&   !"#$%&'()   !"#$%&'()  !"    !"#$%&'     !"#$%&'   !"#$%&'                    !"#$%    !"#             !"#$%&'    !"#$%     !"#          !"#$%&'()*    !"#$%                       !"                                                                 !"     !"#          !"#$%&  !"#$%&'()*+,-.       !"#$%&'      !"#    !"#$%      !"#$    !"#$                                           !"#$       !"#$%&'()      !"#$%&                !"#$%    !   !"#$%&'()*+,            ! "# $% & '    !"#$%&'(   !    !"#$    !    !"#             !"#$%                         !"#$%    !"#$%&   !"#      !"#$%             !" #       !"      !"#$              !    !"#$               !   !                      !"         !     !"#$   !"     !     !"#               !"#$%&'(     !"#$%                                       !"#$  !"#$%&'()   !"#$%&'()*+    !                    !"#$%&'     !"#                            !"#$%&'(         !   !"#$%&'()*   !"#$       !"#$%          !"#$%&'        !                  !"#                 !"#$    !"#$%&'(   !"#$          !"              !"#               !  !"#$%&'()*+,,,,,,,,,,,,,,,,,,,,,                                          !; <Ld,|zRx $ا0FJ w?:*3$"D \lH_GNU h%` f i @` s ` i @` { i @` 9i @f ` Qi @s ` Li @{ ` i @ ` i @~  L h%h%o`  p%0 oooo#m%GA$3a1Y GA$3p1067 L GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realignjapanese_euc.so-2.2.10-35.el8.x86_64.debug7zXZִF!t/]?Eh=ڊ2N.wGDHVJ+,ڈR7KK|rf4)f (]9 !:v(|h,^`WsFi,-K`b 6[{FxYbuG aO "ވ ƕsNJڤI0GSl%ڙ,џ!b)h=:rv 5x@45L`MϟY4p콇C,BgYsUnȓ9a@Svhƞ9nx6x׈(?7f㤠E_펉#ei3UW\(Ɇ/7$~\aZ 4=+0TL(q`n_7~%eӛ!S`BqR XgWR6krsu=^,&drP tUx9snט{YDmx+#VmB]c')%-Ω|q]=?Jv슧4A0'\P5i)\ή29G~>mmLjiC'P)ȅUe̝dLi2xꬺhp&0ÞIL)5oϞAهr'/ʼ]hҊ[ϑQG:;҇iR$M;SO"){ %o~wyxΨAYR5fw$m)+jXZ^F9;"du)31HG|s\W;gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 08oEo T^B0hc0n w ,}L L ` ` QV ``$``tPaPa h%hh%hh%h  m%m o%o p%p((p%(p0pe(p  r0PrTu+PK!..&2.2.0/x86_64-linux/enc/trans/escape.sonuȯELF>@@'@8 @pp        888$$PPP StdPPP Ptd```<<QtdRtd  GNUst\¥)%P5>c>B  BE|qX -  a , F"( 0 ( U 0 <__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeInit_escaperb_register_transcoderlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ui   p    @  H  X @ h            @        @     (  8 @ H        HHI HtH5R %S hh%- D%% DH=! H H9tH Ht H= H5 H)HHH?HHtH HtfD= u+UH=r Ht H= Yd ]w1fD?uHA"ff.?u "H"ff.@HH= H=5 H= H= HtHHxml_attr_quotexml_attr_content_escapexml_text_escapeamp_escape@@у@у(D&<>";<PX`pzRx $0FJ w?:*3$"D \ p$!<HoGNUp  H@   <@   @   @  x  l   o`   0` oooo GA$3a1y GA$3p1067l GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFYGA+GLIBCXX_ASSERTIONSescape.so-2.2.10-35.el8.x86_64.debug&i$7zXZִF!t/4]?Eh=ڊ2NsU-ٕ%\bvBizjKKv `Β#V='&nb@:L΋WBTb!Phɑ8<?>I.0a=RV3/΋ :F8eԛy*@H6kP!2dYs? XOIUg XD+ qKWԞ%;AwQ\1g][K Ntk|L[Ix#^ג_n>9&LUrol@rc!Busѽ5&8m\+hf>K'\hTѪLI]#j|}\wDKތ,!pԚλJ6awLZ*zSfe^隄sT8ffʄȂ2!H}rC{`Dpt.c[ ̥6 zX?'v{~[}?XI~g@zܥY*T5D}L wS ̊%b &x6Մނm;o7F1Db(-0F3ܶ| oS֫mz G&aZZy(Y%LdD,I"z|9fV=t]c3le&~3qړFQI"u3$[ߒ ?< ±gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 08oEo T^B``0hc0n wl}l l   ``<PP           (( ( 0 `( H p","t&+PK!ꕢ&2.2.0/x86_64-linux/enc/trans/korean.sonuȯELF>@@8 @`` ##  ##  888$$@@@ Std@@@ Ptd$$QtdRtd##GNU*ٓX  ӥФ г۩ӻϦ@ ϧ F ̱˨ X   ӦפN L үХҳҿ ۪  ٵʹ˩VX  Ҧش  ץ  ڬ ! ʪ^@! ޮp! ݡ͵ݢ! ίʫ$" ϨݣҼجһΰf" ۫Ͷڭ# ܳצߣ# ˪ˢھֹ,# n $ ˫X$ ڮչ$ ϩֺ4$ صv$ ٶP% ۬حҴܴ% ݤͷˬ<& ֯ϪΩ~\& ܧ˭& ˮگضӧޯۭ' ڰD|' ҷ'`|(l L@p8PD P !8!h!!!"#|##$P$$$$H%%%T&& 't''((b0( ֻ̥<) οҸ |) ڿL) @* * ٷطα˯* ޻̨ӼTX+ ϫ+ нۮ, ݦ h, ̼\ , ҹϬ͸ - ظ |- Һ"!- d!- Ц̩ߺ!H. !. ؤٸٹ*". ߮ҵӵl". ̪ӽպ"@/ ջ͹ۯ"/ ͺϭߤͻݧ2#/ ְްݨӨ۰t#T0 ۱ײө#0 ۲٥ܵܶ#,1 ع:$1 ʬ٦ͼٺ|$ 2 Ӿغ$2 ѡѢڱ%2 ߴѣB%`3 ۳ͽʭʮϮ%3 ܷٻϯʯҰ׳%4 ̫&|4 J&4 ڲ&5 ѥܸѤо͡ߵԡβ&\5 ٧'5 ڳпR'5 ۴״'L6 ;ϰΪЧ'|6 קټ(6 йѦZ(7Ӫ ̬ޱ(<7 Ԣ(x7 ձղռѧγ )7 ʰϱb)7 ֱ޲ӫ߯)<8 ϲٽԸپϳ)8 Ѩ޼(*8ϴ ߥ˰ڡ̽ѩj* 9 ѪکͿ*p9 *9 ֬զ0+L: ׵޳ݩr+: +: ѫԣרӿ+8; ߶Ԥڴ8,; ڵӬz,< ׶ϵ٨ݪ͢,p< ۵ԥػ,< שخؼ@-= ̾-P= ߻Ӷ-=ֲ̭ Ԧս޴.=t))8***P+++`,,,t---@....8///L00$112|22X334t444T555D6t66647p77748889h99D:::0;;<h<<<H===H>bP> Թ׷޵ճH.\? δؽ϶.? ܹ.? ֭է/P@ P/@ ֡߰/@ /A ԧ0`A մݫX0A Ժ޶ٿڪ̲0B Ի̳0`B Ϸ1B `1B Լִӷ1C ϸѬ޷ּ1TC ʱߦըШ&2C Ϲ׸ѭѮεh2D ׹إ2D ѯ֢Ѱ2D ζ.3\E ̴ܺߧˣp3E дͣ׺ѱ˱Ѳ3F ˲ߨӸ3hF ʲܻئ64F ׻תx4G ͤۡ4LG ٩4G Ԩ>5G ڶ54H Խԩ5tH ٪ؾܭ̡Ϻ6H ϻӭF6H 6$I Щ׼6TI ѳܡا 7I ۶ͥبѴN7I 7Jѵ ѶѷѸ70J ԪԾ8J ܼҶΡV8J ԫʳͦ8$K ϼ8K Ъ9K ЫءܽӮ^9L آݬֽ9xL е9L ѹߩη$:M Կf:DM ӯֳݭ:|M վڷ:M أ,;M ˳ͧЬn;,NѺ ڢڣҡ۷׫;\N ̿թ˴̵Ͻ;N ˵ѻ4<Q ֿD>`Q??H@@@AXAABXBBBCLCC DDDTEEE`FF GDGGG,HlHHHILIxIII(JJJK|KKLpLLLR ޽ڤ֤> S ѿ̷۸ ?XS ˤL?S ޡ?T ݯݰ˷?LT۹ ̮ݱد@T ޢϿT@T ˸ۺ@@Uݲ @U ݳ߷ۻAU ʴ\APV ʵ٫AV AV ݴذ"B$W ιж΢ޣdB`W ԬؿժBW ЭBW ߪۼ*C,X ٬֥lCdX ١߸׭CX CX ڹ˹߱2D0Y ΫtDtY ܢյաDY DY ڥ۽:E0Z ӱ|EXZ ޤEZ FZ ٭բBFZ F[ FD[ ʶ߹ҤGp[ ٱʷӲJG[ ֮ޥգG \ ׮G\\ ˺H\ ̸Ю̯ԭRH\κ H ] ݵͪ۾ʸH0] I] ΣͫΤަZI] I\^ ںۿ˻׽I^ ާ̹ J$_ ܨbJl_ ͬJ_ J_ ݶ޸λި(K_ ʹ޹ݷԮݸjKd` K` ЯݹKa ݺ0L0a ۢʺΥԯrL`a La ԰La 8Mb ʻzM0b ֦ܾMlb Mb ոܩܪ@Nc ʼ̦ڻN@cSPSSSDTTT8UUUHVVVWXWWW$X\XXX(YlYYY(ZPZZZZ [<[h[[\T\\\](]]]T^^_d____\```(aXaaaa(bdbbc8ccbcԱ Բ֧аNd ΦԳӹ̺סO e رܫդHOe ݻάԴOf ީӳODf ٮլ߫Ppf ۣPPf ݼPf ̢߼зPTg˥ ۤQg ٯXQg ˼Qh Q,h ֨ΧԵӴRxh `Rh ׯRh R i &S4i hS\iڦ ˦бSpi μܣSi ݽ.Ti ݾװ˽ԶpT$j ̰ͭTj ڧTj ߬ܤ6Ulk ުڼxUk Uk ԷU(l ޺>VXl Ψ׾Vl ߽Vl ޫWm ܿνFW\m Wm ةWm ʽݿխ Xn ޾NXDn Xxn Xn ۥYn עСVYn ۦتYo YPo Zto ^Zo ˾ܮZo ٰZo $[p ̻f[(p [Pp ͮ[lp ն,\p n\p ث\p ̣ڽ\q ܯެ4]@q v]hq ף]qee fw wĎ w x FxD x x  yl Ny y` y z Vzp z̒ z< { ^{ {\ { $| f|, |h | ¡¢£¤¥¦§¨©ª«¬­®¯°±²,}ԕ³ ´µ¶·¸¹º»n}P ¼½¾¿} } 4~ v~  ~H ~ < áâã~ äåæçèéêëìíîïðñò óôõö÷øùúûüýþÿh D  Ȁ$  T L ę ġĢģĤĥĦħĨĩĪīĬĭĮЁ įİıIJijĴĵĶķĸĹĺĻļĽP ľĿT ؚ ؂, l \(P xЋ$lȌ`,H<dX hĒ4T$`̕H|ؖ@|`ؘLHК$děb̛ ؜ šŢţŤťŦŧŨũŪūŬŭŮ  ůŰűŲųŴŵŶŷ"TŸŹ źŻżŽžſd   *` l  ơƢƣ ƤƥƦƧƨƩƪƫƬƭƮƯưƱ2Ʋ ƳƴƵƶƷƸƹƺƻƼƽƾƿth  $ :D | ǡǢǣ ǤǥǦǧǨǩǪǫǬǭǮ ǯǰDZDzdzǴǵB@ ǶǷǸǹǺǻǼǽǾǿp ƈ ܡ J8 d ȡȢȣȤȥΉȦ ȧȨȩȪȫȬȭȮȯȰȱȲȳȴȵ ȶȷȸȹȺȻȼȽȾȿRX  ֊ 8 ZLX`<8hԡ0\P0Ĥ̤έТиҢңҧҨҩҪҫҭҲҾbXեիծָܥݥ߳bdbpb|  bȩ Ԫ `\ht̪XB\\<DT\ h4)T?RdrxМPȫЫȌث 、。·‥…¨〃­―∥\∼‘’“”〔〕〈〉《》「」『』【】±×÷≠≤≥∞∴°′″℃Å¢£¥♂♀∠⊥⌒∂∇≡≒§※☆★○●◎◇◆□■△▲▽▼→←↑↓↔〓≪≫√∽∝∵∫∬∈∋⊆⊇⊂⊃∪∩∧∨¬X⇒⇔∀∃´~ˇ˘˝˚˙¸˛¡¿ː∮∑∏¤℉‰◁◀▷▶♤♠♡♥♧♣⊙◈▣◐◑▒▤▥▨▧▦▩♨☏☎☜☞¶†‡↕↗↙↖↘♭♩♪♬㉿㈜№㏇™㏂㏘℡€® ܭ!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[₩]^_`abcdefghijklmnopqrstuvwxyz{|} ̄ㄱㄲㄳㄴㄵㄶㄷㄸㄹㄺㄻㄼㄽㄾㄿㅀㅁㅂㅃㅄㅅㅆㅇㅈㅉㅊㅋㅌㅍㅎㅏㅐㅑㅒㅓㅔㅕㅖㅗㅘㅙㅚㅛㅜㅝㅞㅟㅠㅡㅢㅣㅤㅥㅦㅧㅨㅩㅪㅫㅬㅭㅮㅯㅰㅱㅲㅳㅴㅵㅶㅷㅸㅹㅺㅻㅼㅽㅾㅿㆀㆁㆂㆃㆄㆅㆆㆇㆈㆉㆊㆋㆌㆍㆎⅰⅱⅲⅳⅴⅵⅶⅷⅸⅹ ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩαβγδεζηθικλμνξοπρστυφχψω─│┌┐┘└├┬┤┴┼━┃┏┓┛┗┣┳┫┻╋┠┯┨┷┿┝┰┥┸╂┒┑┚┙┖┕┎┍┞┟┡┢┦┧┩┪┭┮┱┲┵┶┹┺┽┾╀╁╃╄╅╆╇╈╉╊ ߎ0㎕㎖㎗ℓ㎘㏄㎣㎤㎥㎦㎙㎚㎛㎜㎝㎞㎟㎠㎡㎢㏊㎍㎎㎏㏏㎈㎉㏈㎧㎨㎰㎱㎲㎳㎴㎵㎶㎷㎸㎹㎀㎁㎂㎃㎄㎺㎻㎼㎽㎾㎿㎐㎑㎒㎓㎔Ω㏀㏁㎊㎋㎌㏖㏅㎭㎮㎯㏛㎩㎪㎫㎬㏝㏐㏓㏃㏉㏜㏆ ?PÆÐªĦ IJĿŁØŒºÞŦŊ㉠㉡㉢㉣㉤㉥㉦㉧㉨㉩㉪㉫㉬㉭㉮㉯㉰㉱㉲㉳㉴㉵㉶㉷㉸㉹㉺㉻ⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮½⅓⅔¼¾⅛⅜⅝⅞æđðħıijĸŀłøœßþŧŋʼn㈀㈁㈂㈃㈄㈅㈆㈇㈈㈉㈊㈋㈌㈍㈎㈏㈐㈑㈒㈓㈔㈕㈖㈗㈘㈙㈚㈛⒜⒝⒞⒟⒠⒡⒢⒣⒤⒥⒦⒧⒨⒩⒪⒫⒬⒭⒮⒯⒰⒱⒲⒳⒴⒵⑴⑵⑶⑷⑸⑹⑺⑻⑼⑽⑾⑿⒀⒁⒂¹²³⁴ⁿ₁₂₃₄ぁあぃいぅうぇえぉおかがきぎくぐけげこごさざしじすずせぜそぞただちぢっつづてでとどなにぬねのはばぱひびぴふぶぷへべぺほぼぽまみむめもゃやゅゆょよらりるれろゎわゐゑをん ァアィイゥウェエォオカガキギクグケゲコゴサザシジスズセゼソゾタダチヂッツヅテデトドナニヌネノハバパヒビピフブプヘベペホボポマミムメモャヤュユョヨラリルレロヮワヰヱヲンヴヵヶ _АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ абвгдеёжзийклмнопрстуфхцчшщъыьэюя`가각간갇갈갉갊감갑값갓갔강갖갗같갚갛개객갠갤갬갭갯갰갱갸갹갼걀걋걍걔걘걜거걱건걷걸걺검겁것겄겅겆겉겊겋게겐겔겜겝겟겠겡겨격겪견겯결겸겹겻겼경곁계곈곌곕곗고곡곤곧골곪곬곯곰곱곳공곶과곽관괄괆괌괍괏광괘괜괠괩괬괭괴괵괸괼굄굅굇굉교굔굘굡굣구국군굳굴굵굶굻굼굽굿궁궂궈궉권궐궜궝궤궷귀귁귄귈귐귑귓규균귤그극근귿글긁금급긋긍긔기긱긴긷길긺김깁깃깅깆깊까깍깎깐깔깖깜깝깟깠깡깥깨깩깬깰깸깹깻깼깽꺄꺅꺌꺼꺽꺾껀껄껌껍껏껐껑께껙껜껨껫껭껴껸껼꼇꼈꼍꼐꼬꼭꼰꼲꼴꼼꼽꼿꽁꽂꽃꽈꽉꽐꽜꽝꽤꽥꽹꾀꾄꾈꾐꾑꾕꾜꾸꾹꾼꿀꿇꿈꿉꿋꿍꿎꿔꿜꿨꿩꿰꿱꿴꿸뀀뀁뀄뀌뀐뀔뀜뀝뀨끄끅끈끊끌끎끓끔끕끗끙끝끼끽낀낄낌낍낏낑나낙낚난낟날낡낢남납낫났낭낮낯낱낳내낵낸낼냄냅냇냈냉냐냑냔냘냠냥너넉넋넌널넒넓넘넙넛넜넝넣네넥넨넬넴넵넷넸넹녀녁년녈념녑녔녕녘녜녠노녹논놀놂놈놉놋농높놓놔놘놜놨뇌뇐뇔뇜뇝 뇟뇨뇩뇬뇰뇹뇻뇽누눅눈눋눌눔눕눗눙눠눴눼뉘뉜뉠뉨뉩뉴뉵뉼늄늅늉느늑는늘늙늚늠늡늣능늦늪늬늰늴니닉닌닐닒님닙닛닝닢다닥닦단닫달닭닮닯닳담답닷닸당닺닻닿대댁댄댈댐댑댓댔댕댜더덕덖던덛덜덞덟덤덥덧덩덫덮데덱덴델뎀뎁뎃뎄뎅뎌뎐뎔뎠뎡뎨뎬도독돈돋돌돎돐돔돕돗동돛돝돠돤돨돼됐되된될됨됩됫됴두둑둔둘둠둡둣둥둬뒀뒈뒝뒤뒨뒬뒵뒷뒹듀듄듈듐듕드득든듣들듦듬듭듯등듸디딕딘딛딜딤딥딧딨딩딪따딱딴딸땀땁땃땄땅땋때땍땐땔땜땝땟땠땡떠떡떤떨떪떫떰떱떳떴떵떻떼떽뗀뗄뗌뗍뗏뗐뗑뗘뗬또똑똔똘똥똬똴뙈뙤뙨뚜뚝뚠뚤뚫뚬뚱뛔뛰뛴뛸뜀뜁뜅뜨뜩뜬뜯뜰뜸뜹뜻띄띈띌띔띕띠띤띨띰띱띳띵라락란랄람랍랏랐랑랒랖랗래랙랜랠램랩랫랬랭랴략랸럇량러럭런럴럼럽럿렀렁렇레렉렌렐렘렙렛렝려력련렬렴렵렷렸령례롄롑롓로록론롤롬롭롯롱롸롼뢍뢨뢰뢴뢸룀룁룃룅료룐룔룝룟룡루룩룬룰룸룹룻룽뤄뤘뤠뤼뤽륀륄륌륏륑류륙륜률륨륩륫륭르륵른를름릅릇릉릊릍릎리릭린릴림립릿링마막만많맏말맑맒맘맙맛망맞맡맣매맥맨맬맴맵맷맸맹맺먀먁먈먕머먹먼멀멂멈멉멋멍멎멓메멕멘멜멤멥멧멨멩며멱면멸몃몄명몇몌모목몫몬몰몲몸몹못몽뫄뫈뫘뫙뫼묀묄묍묏묑묘묜묠묩묫무묵묶문묻물묽묾뭄뭅뭇뭉뭍뭏뭐뭔뭘뭡뭣뭬뮈뮌뮐뮤뮨뮬뮴뮷므믄믈믐믓미믹민믿밀밂밈밉밋밌밍및밑바박밖밗반받발밝밞밟밤밥밧방밭배백밴밸뱀뱁뱃뱄뱅뱉뱌뱍뱐뱝버벅번벋벌벎범법벗$벙벚베벡벤벧벨벰벱벳벴벵벼벽변별볍볏볐병볕볘볜보복볶본볼봄봅봇봉봐봔봤봬뵀뵈뵉뵌뵐뵘뵙뵤뵨부북분붇불붉붊붐붑붓붕붙붚붜붤붰붸뷔뷕뷘뷜뷩뷰뷴뷸븀븃븅브븍븐블븜븝븟비빅빈빌빎빔빕빗빙빚빛빠빡빤빨빪빰빱빳빴빵빻빼빽뺀뺄뺌뺍뺏뺐뺑뺘뺙뺨뻐뻑뻔뻗뻘뻠뻣뻤뻥뻬뼁뼈뼉뼘뼙뼛뼜뼝뽀뽁뽄뽈뽐뽑뽕뾔뾰뿅뿌뿍뿐뿔뿜뿟뿡쀼쁑쁘쁜쁠쁨쁩삐삑삔삘삠삡삣삥사삭삯산삳살삵삶삼삽삿샀상샅새색샌샐샘샙샛샜생샤,샥샨샬샴샵샷샹섀섄섈섐섕서석섞섟선섣설섦섧섬섭섯섰성섶세섹센셀셈셉셋셌셍셔셕션셜셤셥셧셨셩셰셴셸솅소속솎손솔솖솜솝솟송솥솨솩솬솰솽쇄쇈쇌쇔쇗쇘쇠쇤쇨쇰쇱쇳쇼쇽숀숄숌숍숏숑수숙순숟술숨숩숫숭숯숱숲숴쉈쉐쉑쉔쉘쉠쉥쉬쉭쉰쉴쉼쉽쉿슁슈슉슐슘슛슝스슥슨슬슭슴습슷승시식신싣실싫심십싯싱싶싸싹싻싼쌀쌈쌉쌌쌍쌓쌔쌕쌘쌜쌤쌥쌨쌩썅써썩썬썰썲썸썹썼썽쎄쎈쎌쏀쏘쏙쏜쏟쏠쏢쏨쏩쏭쏴쏵쏸쐈쐐쐤쐬쐰4쐴쐼쐽쑈쑤쑥쑨쑬쑴쑵쑹쒀쒔쒜쒸쒼쓩쓰쓱쓴쓸쓺쓿씀씁씌씐씔씜씨씩씬씰씸씹씻씽아악안앉않알앍앎앓암압앗았앙앝앞애액앤앨앰앱앳앴앵야약얀얄얇얌얍얏양얕얗얘얜얠얩어억언얹얻얼얽얾엄업없엇었엉엊엌엎에엑엔엘엠엡엣엥여역엮연열엶엷염엽엾엿였영옅옆옇예옌옐옘옙옛옜오옥온올옭옮옰옳옴옵옷옹옻와왁완왈왐왑왓왔왕왜왝왠왬왯왱외왹왼욀욈욉욋욍요욕욘욜욤욥욧용우욱운울욹욺움웁웃웅워웍원월웜웝웠웡웨<웩웬웰웸웹웽위윅윈윌윔윕윗윙유육윤율윰윱윳융윷으윽은을읊음읍읏응읒읓읔읕읖읗의읜읠읨읫이익인일읽읾잃임입잇있잉잊잎자작잔잖잗잘잚잠잡잣잤장잦재잭잰잴잼잽잿쟀쟁쟈쟉쟌쟎쟐쟘쟝쟤쟨쟬저적전절젊점접젓정젖제젝젠젤젬젭젯젱져젼졀졈졉졌졍졔조족존졸졺좀좁좃종좆좇좋좌좍좔좝좟좡좨좼좽죄죈죌죔죕죗죙죠죡죤죵주죽준줄줅줆줌줍줏중줘줬줴쥐쥑쥔쥘쥠쥡쥣쥬쥰쥴쥼즈즉즌즐즘즙즛증지직진짇질짊짐집짓D징짖짙짚짜짝짠짢짤짧짬짭짯짰짱째짹짼쨀쨈쨉쨋쨌쨍쨔쨘쨩쩌쩍쩐쩔쩜쩝쩟쩠쩡쩨쩽쪄쪘쪼쪽쫀쫄쫌쫍쫏쫑쫓쫘쫙쫠쫬쫴쬈쬐쬔쬘쬠쬡쭁쭈쭉쭌쭐쭘쭙쭝쭤쭸쭹쮜쮸쯔쯤쯧쯩찌찍찐찔찜찝찡찢찧차착찬찮찰참찹찻찼창찾채책챈챌챔챕챗챘챙챠챤챦챨챰챵처척천철첨첩첫첬청체첵첸첼쳄쳅쳇쳉쳐쳔쳤쳬쳰촁초촉촌촐촘촙촛총촤촨촬촹최쵠쵤쵬쵭쵯쵱쵸춈추축춘출춤춥춧충춰췄췌췐취췬췰췸췹췻췽츄츈츌츔츙츠측츤츨츰츱츳층L치칙친칟칠칡침칩칫칭카칵칸칼캄캅캇캉캐캑캔캘캠캡캣캤캥캬캭컁커컥컨컫컬컴컵컷컸컹케켁켄켈켐켑켓켕켜켠켤켬켭켯켰켱켸코콕콘콜콤콥콧콩콰콱콴콸쾀쾅쾌쾡쾨쾰쿄쿠쿡쿤쿨쿰쿱쿳쿵쿼퀀퀄퀑퀘퀭퀴퀵퀸퀼큄큅큇큉큐큔큘큠크큭큰클큼큽킁키킥킨킬킴킵킷킹타탁탄탈탉탐탑탓탔탕태택탠탤탬탭탯탰탱탸턍터턱턴털턺텀텁텃텄텅테텍텐텔템텝텟텡텨텬텼톄톈토톡톤톨톰톱톳통톺톼퇀퇘퇴퇸툇툉툐투툭툰툴툼툽툿퉁퉈퉜T퉤튀튁튄튈튐튑튕튜튠튤튬튱트특튼튿틀틂틈틉틋틔틘틜틤틥티틱틴틸팀팁팃팅파팍팎판팔팖팜팝팟팠팡팥패팩팬팰팸팹팻팼팽퍄퍅퍼퍽펀펄펌펍펏펐펑페펙펜펠펨펩펫펭펴편펼폄폅폈평폐폘폡폣포폭폰폴폼폽폿퐁퐈퐝푀푄표푠푤푭푯푸푹푼푿풀풂품풉풋풍풔풩퓌퓐퓔퓜퓟퓨퓬퓰퓸퓻퓽프픈플픔픕픗피픽핀필핌핍핏핑하학한할핥함합핫항해핵핸핼햄햅햇했행햐향허헉헌헐헒험헙헛헝헤헥헨헬헴헵헷헹혀혁현혈혐협혓혔형혜혠\혤혭호혹혼홀홅홈홉홋홍홑화확환활홧황홰홱홴횃횅회획횐횔횝횟횡효횬횰횹횻후훅훈훌훑훔훗훙훠훤훨훰훵훼훽휀휄휑휘휙휜휠휨휩휫휭휴휵휸휼흄흇흉흐흑흔흖흗흘흙흠흡흣흥흩희흰흴흼흽힁히힉힌힐힘힙힛힝伽佳假價加可呵哥嘉嫁家暇架枷柯歌珂痂稼苛茄街袈訶賈跏軻迦駕刻却各恪慤殼珏脚覺角閣侃刊墾奸姦干幹懇揀杆柬桿澗癎看磵稈竿簡肝艮艱諫間乫喝曷渴碣竭葛褐蝎鞨勘坎堪嵌感憾戡敢柑橄減甘疳監瞰紺邯鑑鑒龕d匣岬甲胛鉀閘剛堈姜岡崗康强彊慷江畺疆糠絳綱羌腔舡薑襁講鋼降鱇介价個凱塏愷愾慨改槪漑疥皆盖箇芥蓋豈鎧開喀客坑更粳羹醵倨去居巨拒据據擧渠炬祛距踞車遽鉅鋸乾件健巾建愆楗腱虔蹇鍵騫乞傑杰桀儉劍劒檢瞼鈐黔劫怯迲偈憩揭擊格檄激膈覡隔堅牽犬甄絹繭肩見譴遣鵑抉決潔結缺訣兼慊箝謙鉗鎌京俓倞傾儆勁勍卿坰境庚徑慶憬擎敬景暻更梗涇炅烱璟璥瓊痙硬磬竟競絅經耕耿脛莖警輕逕鏡頃頸驚鯨係啓堺契季屆悸戒桂械l棨溪界癸磎稽系繫繼計誡谿階鷄古叩告呱固姑孤尻庫拷攷故敲暠枯槁沽痼皐睾稿羔考股膏苦苽菰藁蠱袴誥賈辜錮雇顧高鼓哭斛曲梏穀谷鵠困坤崑昆梱棍滾琨袞鯤汨滑骨供公共功孔工恐恭拱控攻珙空蚣貢鞏串寡戈果瓜科菓誇課跨過鍋顆廓槨藿郭串冠官寬慣棺款灌琯瓘管罐菅觀貫關館刮恝括适侊光匡壙廣曠洸炚狂珖筐胱鑛卦掛罫乖傀塊壞怪愧拐槐魁宏紘肱轟交僑咬喬嬌嶠巧攪敎校橋狡皎矯絞翹膠蕎蛟較轎郊餃驕鮫丘久九仇俱具勾t區口句咎嘔坵垢寇嶇廐懼拘救枸柩構歐毆毬求溝灸狗玖球瞿矩究絿耉臼舅舊苟衢謳購軀逑邱鉤銶駒驅鳩鷗龜國局菊鞠鞫麴君窘群裙軍郡堀屈掘窟宮弓穹窮芎躬倦券勸卷圈拳捲權淃眷厥獗蕨蹶闕机櫃潰詭軌饋句晷歸貴鬼龜叫圭奎揆槻珪硅窺竅糾葵規赳逵閨勻均畇筠菌鈞龜橘克剋劇戟棘極隙僅劤勤懃斤根槿瑾筋芹菫覲謹近饉契今妗擒昑檎琴禁禽芩衾衿襟金錦伋及急扱汲級給亘兢矜肯企伎其冀嗜器圻基埼夔奇妓寄岐崎己幾忌技旗旣|朞期杞棋棄機欺氣汽沂淇玘琦琪璂璣畸畿碁磯祁祇祈祺箕紀綺羈耆耭肌記譏豈起錡錤飢饑騎騏驥麒緊佶吉拮桔金喫儺喇奈娜懦懶拏拿癩羅蘿螺裸邏那樂洛烙珞落諾酪駱亂卵暖欄煖爛蘭難鸞捏捺南嵐枏楠湳濫男藍襤拉納臘蠟衲囊娘廊朗浪狼郎乃來內奈柰耐冷女年撚秊念恬拈捻寧寗努勞奴弩怒擄櫓爐瑙盧老蘆虜路露駑魯鷺碌祿綠菉錄鹿論壟弄濃籠聾膿農惱牢磊腦賂雷尿壘屢樓淚漏累縷陋嫩訥杻紐勒肋凜凌稜綾能菱陵尼泥匿溺多茶丹亶但單團壇彖斷旦檀段湍短端簞緞蛋袒鄲鍛撻澾獺疸達啖坍憺擔曇淡湛潭澹痰聃膽蕁覃談譚錟沓畓答踏遝唐堂塘幢戇撞棠當糖螳黨代垈坮大對岱帶待戴擡玳臺袋貸隊黛宅德悳倒刀到圖堵塗導屠島嶋度徒悼挑掉搗桃棹櫂淘渡滔濤燾盜睹禱稻萄覩賭跳蹈逃途道都鍍陶韜毒瀆牘犢獨督禿篤纛讀墩惇敦旽暾沌焞燉豚頓乭突仝冬凍動同憧東桐棟洞潼疼瞳童胴董銅兜斗杜枓痘竇荳讀豆逗頭屯臀芚遁遯鈍得嶝橙燈登等藤謄鄧騰喇懶拏癩羅蘿螺裸邏樂洛烙珞絡落諾酪駱丹亂卵欄欒瀾爛蘭鸞剌辣嵐擥攬欖濫籃纜藍襤覽拉臘蠟廊朗浪狼琅瑯螂郞來崍徠萊冷掠略亮倆兩凉梁樑粮粱糧良諒輛量侶儷勵呂廬慮戾旅櫚濾礪藜蠣閭驢驪麗黎力曆歷瀝礫轢靂憐戀攣漣煉璉練聯蓮輦連鍊冽列劣洌烈裂廉斂殮濂簾獵令伶囹寧岺嶺怜玲笭羚翎聆逞鈴零靈領齡例澧禮醴隷勞怒撈擄櫓潞瀘爐盧老蘆虜路輅露魯鷺鹵碌祿綠菉錄鹿麓論壟弄朧瀧瓏籠聾儡瀨牢磊賂賚賴雷了僚寮廖料燎療瞭聊蓼遼鬧龍壘婁屢樓淚漏瘻累縷蔞褸鏤陋劉旒柳榴流溜瀏琉瑠留瘤硫謬類六戮陸侖倫崙淪綸輪律慄栗率隆勒肋凜凌楞稜綾菱陵俚利厘吏唎履悧李梨浬犁狸理璃異痢籬罹羸莉裏裡里釐離鯉吝潾燐璘藺躪隣鱗麟林淋琳臨霖砬立笠粒摩瑪痲碼磨馬魔麻寞幕漠膜莫邈万卍娩巒彎慢挽晩曼滿漫灣瞞萬蔓蠻輓饅鰻唜抹末沫茉襪靺亡妄忘忙望網罔芒茫莽輞邙埋妹媒寐昧枚梅每煤罵買賣邁魅脈貊陌驀麥孟氓猛盲盟萌冪覓免冕勉棉沔眄眠綿緬面麵滅蔑冥名命明暝椧溟皿瞑茗蓂螟酩銘鳴袂侮冒募姆帽慕摸摹暮某模母毛牟牡瑁眸矛耗芼茅謀謨貌木沐牧目睦穆鶩歿沒夢朦蒙卯墓妙廟描昴杳渺猫竗苗錨務巫憮懋戊拇撫无楙武毋無珷畝繆舞茂蕪誣貿霧鵡墨默們刎吻問文 汶紊紋聞蚊門雯勿沕物味媚尾嵋彌微未梶楣渼湄眉米美薇謎迷靡黴岷悶愍憫敏旻旼民泯玟珉緡閔密蜜謐剝博拍搏撲朴樸泊珀璞箔粕縛膊舶薄迫雹駁伴半反叛拌搬攀斑槃泮潘班畔瘢盤盼磐磻礬絆般蟠返頒飯勃拔撥渤潑發跋醱鉢髮魃倣傍坊妨尨幇彷房放方旁昉枋榜滂磅紡肪膀舫芳蒡蚌訪謗邦防龐倍俳北培徘拜排杯湃焙盃背胚裴裵褙賠輩配陪伯佰帛柏栢白百魄幡樊煩燔番磻繁蕃藩飜伐筏罰閥凡帆梵氾汎泛犯範范法琺僻劈壁擘檗璧癖(碧蘗闢霹便卞弁變辨辯邊別瞥鱉鼈丙倂兵屛幷昞昺柄棅炳甁病秉竝輧餠騈保堡報寶普步洑湺潽珤甫菩補褓譜輔伏僕匐卜宓復服福腹茯蔔複覆輹輻馥鰒本乶俸奉封峯峰捧棒烽熢琫縫蓬蜂逢鋒鳳不付俯傅剖副否咐埠夫婦孚孵富府復扶敷斧浮溥父符簿缶腐腑膚艀芙莩訃負賦賻赴趺部釜阜附駙鳧北分吩噴墳奔奮忿憤扮昐汾焚盆粉糞紛芬賁雰不佛弗彿拂崩朋棚硼繃鵬丕備匕匪卑妃婢庇悲憊扉批斐枇榧比毖毗毘沸泌琵痺砒碑秕秘粃緋翡肥0脾臂菲蜚裨誹譬費鄙非飛鼻嚬嬪彬斌檳殯浜濱瀕牝玭貧賓頻憑氷聘騁乍事些仕伺似使俟僿史司唆嗣四士奢娑寫寺射巳師徙思捨斜斯柶査梭死沙泗渣瀉獅砂社祀祠私篩紗絲肆舍莎蓑蛇裟詐詞謝賜赦辭邪飼駟麝削數朔索傘刪山散汕珊産疝算蒜酸霰乷撒殺煞薩三參杉森渗芟蔘衫揷澁鈒颯上傷像償商喪嘗孀尙峠常床庠廂想桑橡湘爽牀狀相祥箱翔裳觴詳象賞霜塞璽賽嗇塞穡索色牲生甥省笙墅壻嶼序庶徐恕抒捿敍暑曙書栖棲犀瑞筮絮緖署8胥舒薯西誓逝鋤黍鼠夕奭席惜昔晳析汐淅潟石碩蓆釋錫仙僊先善嬋宣扇敾旋渲煽琁瑄璇璿癬禪線繕羨腺膳船蘚蟬詵跣選銑鐥饍鮮卨屑楔泄洩渫舌薛褻設說雪齧剡暹殲纖蟾贍閃陝攝涉燮葉城姓宬性惺成星晟猩珹盛省筬聖聲腥誠醒世勢歲洗稅笹細說貰召嘯塑宵小少巢所掃搔昭梳沼消溯瀟炤燒甦疏疎瘙笑篠簫素紹蔬蕭蘇訴逍遡邵銷韶騷俗屬束涑粟續謖贖速孫巽損蓀遜飡率宋悚松淞訟誦送頌刷殺灑碎鎖衰釗修受嗽囚垂壽嫂守岫峀帥愁@戍手授搜收數樹殊水洙漱燧狩獸琇璲瘦睡秀穗竪粹綏綬繡羞脩茱蒐蓚藪袖誰讐輸遂邃酬銖銹隋隧隨雖需須首髓鬚叔塾夙孰宿淑潚熟琡璹肅菽巡徇循恂旬栒楯橓殉洵淳珣盾瞬筍純脣舜荀蓴蕣詢諄醇錞順馴戌術述鉥崇崧嵩瑟膝蝨濕拾習褶襲丞乘僧勝升承昇繩蠅陞侍匙嘶始媤尸屎屍市弑恃施是時枾柴猜矢示翅蒔蓍視試詩諡豕豺埴寔式息拭植殖湜熄篒蝕識軾食飾伸侁信呻娠宸愼新晨燼申神紳腎臣莘薪藎蜃訊身辛辰迅失室實悉審尋心沁H沈深瀋甚芯諶什十拾雙氏亞俄兒啞娥峨我牙芽莪蛾衙訝阿雅餓鴉鵝堊岳嶽幄惡愕握樂渥鄂鍔顎鰐齷安岸按晏案眼雁鞍顔鮟斡謁軋閼唵岩巖庵暗癌菴闇壓押狎鴨仰央怏昻殃秧鴦厓哀埃崖愛曖涯碍艾隘靄厄扼掖液縊腋額 櫻罌鶯鸚也倻冶夜惹揶椰爺耶若野弱掠略約若葯蒻藥躍亮佯兩凉壤孃恙揚攘敭暘梁楊樣洋瀁煬痒瘍禳穰糧羊良襄諒讓釀陽量養圄御於漁瘀禦語馭魚齬億憶抑檍臆偃堰彦焉言諺孼蘖俺儼嚴奄掩淹嶪業円予余勵呂女如廬P 旅歟汝濾璵礖礪與艅茹輿轝閭餘驪麗黎亦力域役易曆歷疫繹譯轢逆驛嚥堧姸娟宴年延憐戀捐挻撚椽沇沿涎涓淵演漣烟然煙煉燃燕璉硏硯秊筵緣練縯聯衍軟輦蓮連鉛鍊鳶列劣咽悅涅烈熱裂說閱厭廉念捻染殮炎焰琰艶苒 簾閻髥鹽曄獵燁葉令囹塋寧嶺嶸影怜映暎楹榮永泳渶潁濚瀛瀯煐營獰玲瑛瑩瓔盈穎纓羚聆英詠迎鈴鍈零霙靈領乂倪例刈叡曳汭濊猊睿穢芮藝蘂禮裔詣譽豫醴銳隸霓預五伍俉傲午吾吳嗚塢墺奧娛寤悟惡懊敖旿晤梧汚澳X烏熬獒筽蜈誤鰲鼇屋沃獄玉鈺溫瑥瘟穩縕蘊兀壅擁瓮甕癰翁邕雍饔渦瓦窩窪臥蛙蝸訛婉完宛梡椀浣玩琓琬碗緩翫脘腕莞豌阮頑曰往旺枉汪王倭娃歪矮外嵬巍猥畏了僚僥凹堯夭妖姚寥寮尿嶢拗搖撓擾料曜樂橈燎燿瑤療窈窯繇繞耀腰蓼蟯要謠遙遼邀饒慾欲浴縟褥辱俑傭冗勇埇墉容庸慂榕涌湧溶熔瑢用甬聳茸蓉踊鎔鏞龍于佑偶優又友右宇寓尤愚憂旴牛玗瑀盂祐禑禹紆羽芋藕虞迂遇郵釪隅雨雩勖彧旭昱栯煜稶郁頊云暈橒殞澐熉耘芸蕓`運隕雲韻蔚鬱亐熊雄元原員圓園垣媛嫄寃怨愿援沅洹湲源爰猿瑗苑袁轅遠阮院願鴛月越鉞位偉僞危圍委威尉慰暐渭爲瑋緯胃萎葦蔿蝟衛褘謂違韋魏乳侑儒兪劉唯喩孺宥幼幽庾悠惟愈愉揄攸有杻柔柚柳楡楢油洧流游溜濡猶猷琉瑜由留癒硫紐維臾萸裕誘諛諭踰蹂遊逾遺酉釉鍮類六堉戮毓肉育陸倫允奫尹崙淪潤玧胤贇輪鈗閏律慄栗率聿戎瀜絨融隆垠恩慇殷誾銀隱乙吟淫蔭陰音飮揖泣邑凝應膺鷹依倚儀宜意懿擬椅毅疑矣義艤薏蟻衣誼h議醫二以伊利吏夷姨履已弛彛怡易李梨泥爾珥理異痍痢移罹而耳肄苡荑裏裡貽貳邇里離飴餌匿溺瀷益翊翌翼謚人仁刃印吝咽因姻寅引忍湮燐璘絪茵藺蚓認隣靭靷鱗麟一佚佾壹日溢逸鎰馹任壬妊姙恁林淋稔臨荏賃入卄立笠粒仍剩孕芿仔刺咨姉姿子字孜恣慈滋炙煮玆瓷疵磁紫者自茨蔗藉諮資雌作勺嚼斫昨灼炸爵綽芍酌雀鵲孱棧殘潺盞岑暫潛箴簪蠶雜丈仗匠場墻壯奬將帳庄張掌暲杖樟檣欌漿牆狀獐璋章粧腸臟臧莊葬蔣薔藏裝贓醬長p障再哉在宰才材栽梓渽滓災縡裁財載齋齎爭箏諍錚佇低儲咀姐底抵杵楮樗沮渚狙猪疽箸紵苧菹著藷詛貯躇這邸雎齟勣吊嫡寂摘敵滴狄炙的積笛籍績翟荻謫賊赤跡蹟迪迹適鏑佃佺傳全典前剪塡塼奠專展廛悛戰栓殿氈澱煎琠田甸畑癲筌箋箭篆纏詮輾轉鈿銓錢鐫電顚顫餞切截折浙癤竊節絶占岾店漸点粘霑鮎點接摺蝶丁井亭停偵呈姃定幀庭廷征情挺政整旌晶晸柾楨檉正汀淀淨渟湞瀞炡玎珽町睛碇禎程穽精綎艇訂諪貞鄭酊釘鉦鋌錠霆靖x靜頂鼎制劑啼堤帝弟悌提梯濟祭第臍薺製諸蹄醍除際霽題齊俎兆凋助嘲弔彫措操早晁曺曹朝條棗槽漕潮照燥爪璪眺祖祚租稠窕粗糟組繰肇藻蚤詔調趙躁造遭釣阻雕鳥族簇足鏃存尊卒拙猝倧宗從悰慫棕淙琮種終綜縱腫踪踵鍾鐘佐坐左座挫罪主住侏做姝胄呪周嗾奏宙州廚晝朱柱株注洲湊澍炷珠疇籌紂紬綢舟蛛註誅走躊輳週酎酒鑄駐竹粥俊儁准埈寯峻晙樽浚準濬焌畯竣蠢逡遵雋駿茁中仲衆重卽櫛楫汁葺增憎曾拯烝甑症繒蒸證贈之只咫地址志持指摯支旨智枝枳止池沚漬知砥祉祗紙肢脂至芝芷蜘誌識贄趾遲直稙稷織職唇嗔塵振搢晉晋桭榛殄津溱珍瑨璡畛疹盡眞瞋秦縉縝臻蔯袗診賑軫辰進鎭陣陳震侄叱姪嫉帙桎瓆疾秩窒膣蛭質跌迭斟朕什執潗緝輯鏶集徵懲澄且侘借叉嗟嵯差次此磋箚茶蹉車遮捉搾着窄錯鑿齪撰澯燦璨瓚竄簒纂粲纘讚贊鑽餐饌刹察擦札紮僭參塹慘慙懺斬站讒讖倉倡創唱娼廠彰愴敞昌昶暢槍滄漲猖瘡窓脹艙菖蒼債埰寀寨彩採砦綵菜蔡采釵冊柵策 責凄妻悽處倜刺剔尺慽戚拓擲斥滌瘠脊蹠陟隻仟千喘天川擅泉淺玔穿舛薦賤踐遷釧闡阡韆凸哲喆徹撤澈綴輟轍鐵僉尖沾添甛瞻簽籤詹諂堞妾帖捷牒疊睫諜貼輒廳晴淸聽菁請靑鯖切剃替涕滯締諦逮遞體初剿哨憔抄招梢 "椒楚樵炒焦硝礁礎秒稍肖艸苕草蕉貂超酢醋醮促囑燭矗蜀觸寸忖村邨叢塚寵悤憁摠總聰蔥銃撮催崔最墜抽推椎楸樞湫皺秋芻萩諏趨追鄒酋醜錐錘鎚雛騶鰍丑畜祝竺筑築縮蓄蹙蹴軸逐春椿瑃出朮黜充忠沖蟲衝衷悴膵萃#贅取吹嘴娶就炊翠聚脆臭趣醉驟鷲側仄厠惻測層侈値嗤峙幟恥梔治淄熾痔痴癡稚穉緇緻置致蚩輜雉馳齒則勅飭親七柒漆侵寢枕沈浸琛砧針鍼蟄秤稱快他咤唾墮妥惰打拖朶楕舵陀馱駝倬卓啄坼度托拓擢晫柝濁濯琢琸託%鐸呑嘆坦彈憚歎灘炭綻誕奪脫探眈耽貪塔搭榻宕帑湯糖蕩兌台太怠態殆汰泰笞胎苔跆邰颱宅擇澤撑攄兎吐土討慟桶洞痛筒統通堆槌腿褪退頹偸套妬投透鬪慝特闖坡婆巴把播擺杷波派爬琶破罷芭跛頗判坂板版瓣販辦鈑&阪八叭捌佩唄悖敗沛浿牌狽稗覇貝彭澎烹膨愎便偏扁片篇編翩遍鞭騙貶坪平枰萍評吠嬖幣廢弊斃肺蔽閉陛佈包匍匏咆哺圃布怖抛抱捕暴泡浦疱砲胞脯苞葡蒲袍褒逋鋪飽鮑幅暴曝瀑爆輻俵剽彪慓杓標漂瓢票表豹飇飄驃(品稟楓諷豊風馮彼披疲皮被避陂匹弼必泌珌畢疋筆苾馝乏逼下何厦夏廈昰河瑕荷蝦賀遐霞鰕壑學虐謔鶴寒恨悍旱汗漢澣瀚罕翰閑閒限韓割轄函含咸啣喊檻涵緘艦銜陷鹹合哈盒蛤閤闔陜亢伉姮嫦巷恒抗杭桁沆港缸肛航)行降項亥偕咳垓奚孩害懈楷海瀣蟹解該諧邂駭骸劾核倖幸杏荇行享向嚮珦鄕響餉饗香噓墟虛許憲櫶獻軒歇險驗奕爀赫革俔峴弦懸晛泫炫玄玹現眩睍絃絢縣舷衒見賢鉉顯孑穴血頁嫌俠協夾峽挾浹狹脅脇莢鋏頰亨兄刑型$+形泂滎瀅灐炯熒珩瑩荊螢衡逈邢鎣馨兮彗惠慧暳蕙蹊醯鞋乎互呼壕壺好岵弧戶扈昊晧毫浩淏湖滸澔濠濩灝狐琥瑚瓠皓祜糊縞胡芦葫蒿虎號蝴護豪鎬頀顥惑或酷婚昏混渾琿魂忽惚笏哄弘汞泓洪烘紅虹訌鴻化和嬅樺火畵,禍禾花華話譁貨靴廓擴攫確碻穫丸喚奐宦幻患換歡晥桓渙煥環紈還驩鰥活滑猾豁闊凰幌徨恍惶愰慌晃晄榥況湟滉潢煌璜皇篁簧荒蝗遑隍黃匯回廻徊恢悔懷晦會檜淮澮灰獪繪膾茴蛔誨賄劃獲宖橫鐄哮嚆孝效斅曉梟涍淆,.爻肴酵驍侯候厚后吼喉嗅帿後朽煦珝逅勛勳塤壎焄熏燻薰訓暈薨喧暄煊萱卉喙毁彙徽揮暉煇諱輝麾休携烋畦虧恤譎鷸兇凶匈洶胸黑昕欣炘痕吃屹紇訖欠欽歆吸恰洽翕興僖凞喜噫囍姬嬉希憙憘戱晞曦熙熹熺犧禧稀羲詰/ԭ(HXpx $,4<DLT\dlt| (08@ H  PX`hpx "# %&()+,$./,141ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghb2ijklmnopqrstuvwxyzb3b4b5ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghb6ijklmnopqrstuvwxyzb7b8ABCDb:EFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzb ;b<b$=ABCDEFGHIJKLMNOPQRSTb0>UVWXYZabcdefghijklmnopqrstuvwxyzb4?@@LAXBdC\blCyzbCbDABCDEFGHIJKLMNbEOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzbFbGbHABCDEFGHIJKLMNOPQRSTUVWXYZabcdefgbJhijklmnopqrstuvwxyzbKbLABCDEFGHIJKLMNb(MOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzb4Nb@ObLPABCDEFGHIJKLMNOPQRbXQSTUVWXYZabcdefghijklmnopqrstuvwxyzbdRbpSb|TABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxbUyzbVbWABCDEFGHIJKLMNOPQRSTUVWXbXYZabcdefghijklmnopqrstuvwxyzbYbZb[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzb\b]b^ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzb`b abbABCDEFGHIJKLMNOPQRSTUVWXb$cYZabcdefghijklmnopqrstuvwxyzb0db욨욪욫욬욭욮욯욲욳욵욶욷욻욼욽욾욿웂웄웆웇웈웉웊웋웎웏웑웒웓웕웖웗웘웙웚웛웞웟웢웣웤웥웦웧웪웫웭웮웯웱웲웳웴웵웶웷웺웻웼웾웿윀윁윂윃윆윇윉윊윋윍윎윏윐윑윒윓윖윘윚윛윜윝윞윟윢윣윥윦윧윩윪윫윬윭윮윯윲윴윶윸윹윺윻윾윿읁읂읃읅읆읇읈읉읋읎읐읙읚읛읝읞읟읡읢읣읤읥읦읧읩읪읬읭읮읯읰읱읲읳읶읷읹읺읻읿잀잁잂잆잋잌잍잏잒잓잕잙잛잜잝잞잟잢잧잨잩잪잫잮잯잱잲잳잵잶잷’A잸잹잺잻잾쟂쟃쟄쟅쟆쟇쟊쟋쟍쟏쟑쟒쟓쟔쟕쟖쟗쟙쟚쟛쟜쟞쟟쟠쟡쟢쟣쟥쟦쟧쟩쟪쟫쟭쟮쟯쟰쟱쟲쟳쟴쟵쟶쟷쟸쟹쟺쟻쟼쟽쟾쟿젂젃젅젆젇젉젋젌젍젎젏젒젔젗젘젙젚젛젞젟젡젢젣젥젦젧젨젩젪젫젮젰젲젳젴젵젶젷젹젺젻젽젾젿졁졂졃졄졅졆졇졊졋졎졏졐졑졒졓졕졖졗졘졙졚졛졜졝졞졟졠졡졢졣졤졥졦졧졨졩졪졫졬졭졮졯졲졳졵졶졷졹졻졼졽졾졿좂좄좈좉좊좎좏좐좑좒좓좕좖좗좘좙좚좛좜좞좠좢좣좤’D좥좦좧좩좪좫좬좭좮좯좰좱좲좳좴좵좶좷좸좹좺좻좾좿죀죁죂죃죅죆죇죉죊죋죍죎죏죐죑죒죓죖죘죚죛죜죝죞죟죢죣죥죦죧죨죩죪죫죬죭죮죯죰죱죲죳죴죶죷죸죹죺죻죾죿줁줂줃줇줈줉줊줋줎 、。·‥…¨〃­―∥\∼‘’“”〔〕〈〉《》「」『』【】±×÷≠≤≥∞∴°′″℃Å¢£¥♂♀∠⊥⌒∂∇≡≒§※☆★○●◎◇◆□■△▲▽▼→←↑↓↔〓≪≫√∽∝∵∫∬∈∋⊆⊇⊂⊃∪∩∧∨¬’hG줐줒줓줔줕줖줗줙줚줛줜줝줞줟줠줡줢줣줤줥줦줧줨줩줪줫줭줮줯줰줱줲줳줵줶줷줸줹줺줻줼줽줾줿쥀쥁쥂쥃쥄쥅쥆쥇쥈쥉쥊쥋쥌쥍쥎쥏쥒쥓쥕쥖쥗쥙쥚쥛쥜쥝쥞쥟쥢쥤쥥쥦쥧쥨쥩쥪쥫쥭쥮쥯⇒⇔∀∃´~ˇ˘˝˚˙¸˛¡¿ː∮∑∏¤℉‰◁◀▷▶♤♠♡♥♧♣⊙◈▣◐◑▒▤▥▨▧▦▩♨☏☎☜☞¶†‡↕↗↙↖↘♭♩♪♬㉿㈜№㏇™㏂㏘℡€® AD`G4JLOXRT8WY\t_ bd@ghj`k4nqsvyX|,Ԅ|P$̕tHĦhx(8HнXhx 0@P`p(8HXhx (         !"#$%&'(   !"#$%&'()*+,-./012                !"#$%&'()*+,-./0123456789            !"#$%&'()*+,-./0123456789:;<=>?@  !"#$%&'()*+,-./01234  !"#$%&'()*+,-./01234567888888888      !"#$%&'()*+,-./0123456789:;<=>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     !"#$%&'()*+,-./0123456789:;<                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHHHHHHHHHHHHHHHHHHHHHHH   !"#$%&'()*+,- ./0123456789:;<=>?@ABCDE   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEEEEEEEEEEEEEEEEEEEEEEEEEE  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPPPPPPPPPPPPPPP  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTTTTTTTTTTT  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWWWWWWWW  !"""""""""""""""#$%&'()*+,-./0123456789:;<=>?@ABC"""""""""""""  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[  !"#$%%%%%%%%%%%%%%%%%%%%%%%%%%%%A  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~A  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~A  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_____`abcdefghi_______jklmnopqrstuvwxyz{|}~______________A  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~A  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~A  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZY[\]^_`abYcdefghijklmnopqrstuvwxyz{|}~A  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~A  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~A  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvvvvvvvvvvvvvvvwxyz{|}~vvvvvvvvvvvvvA  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUA  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqA  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_A  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~J; `<`da|zRx $h`0FJ w?:*3$"Dp` \8a<HoGNUP #$    2  P  x 0 ##o`  #0( oooo#`pGA$3a10 GA$3p1067`GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realignkorean.so-2.2.10-35.el8.x86_64.debug2K7zXZִF!t/]?Eh=ڊ2NH:^ 7,X\*u Kkqμr#\R#(^Ap l?{/#uMMY/eQ餀EBm=ɡܯDwOlhji~ږU>^ppDuF{rK2d{3Uc ؜Lݩ|NANKԫidWmd,|-j!mC!2:s~ 2~\n )^Ӕ]?jFzLo^j8:oXւ-ʘ|yxUF)yƨI/)I6Oǂͷ~7WQg~} R߾E۽ġy1FH3nҨQ9Mfi)f ~Vћv)ߚ+)TLK˼Wyj s>cKā*:lDE4[swHǍT7֏=e ͷGr|e@Z<X)6gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 08oEo T(^B0h00cPP0n w}  $ȦȦt@@ ## #  # # #((#(0c(  ,LH+PK! Ϙ..%2.2.0/x86_64-linux/enc/iso_8859_15.sonuȯELF> @h'@8 @   (0    888$$ Std PtdDDQtdRtd  GNUQDƀ @*B  BEd߻|qX #U Ff, F"Y8  0 l@ `8 __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeonigenc_get_case_fold_codes_by_str_with_maponigenc_apply_all_case_fold_with_mapInit_iso_8859_15rb_enc_registeronigenc_single_byte_mbc_enc_lenonigenc_is_mbc_newline_0x0aonigenc_single_byte_mbc_to_codeonigenc_single_byte_code_to_mbclenonigenc_single_byte_code_to_mbconigenc_minimum_property_name_to_ctypeonigenc_not_support_get_ctype_code_rangeonigenc_single_byte_left_adjust_char_headonigenc_always_true_is_allowed_reverse_matchlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64Oui q @      H ` x       P @  X ` h p              (  0 HH HtH5 % hhhh% D% D% D% DH= H H9tH6 Ht H=q H5j H)HHH?HHtH HtfD=- u+UH= Ht H= Yd ]w1wH9xff.fHIIѺQH5"H@IIѿ"H5ff.H?@abcdefghijklmnopqrstuvwxyz[\]^_`abcdefghijklmnopqrstuvwxyz{|}~;D``@zRx $PFJ w?:*3$"D @\#p$,HL W8"TBGNU@  `  P  ,7EO} H   o`   `  ohoo:o  0 @ GA$3a1 U GA$3p1067P G GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFYP s GA+GLIBCXX_ASSERTIONSiso_8859_15.so-2.2.10-35.el8.x86_64.debugKG7zXZִF!t/H]?Eh=ڊ2N. x'' AA":yXN~s*dЂAvmp$O^q\caFy;f F5\@ar,,^is&zS+]6xSxxѿ-49YQ36r0:͆L"|]Xbғy;Q.4ш%kJ&JVDrnEJ:RazVT<%hTUm<ajq ̖`NbFNT%yyN~xtdq>@/qRBeRq_y>PB=ZXlCA:ܿah^ ZzdY@>Rh^VZ䊰JpګQ"K)14rmnsnñHtns8 tf,29V:)Zv)NKh̩*4bHm8ilRPt`klcJm+PdMs#YkN8t9{! u%c” L\K Y{Nc2̯̌ (ÕF GB3Kdo7I6u̔mNi@o d?0/YrO2Qp<4&F.KCLce`R+J,! "8d dJ잓1/Io$%`htJMdB pB{c/ֈIXL6<Xi jw!n~^\zB˲-Bt&Ba  Z@kmQJѕݞin{ʺæc!L $'̦sgYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 08o::*Eohh T^B `h c PnP P @w }H H ` ` @ D           88 8 @ `8 H "0"8&+PK!z%2.2.0/x86_64-linux/rbconfig/sizeof.sonuȯELF>@@8 @p p     888$$P P P StdP P P Ptd $$QtdRtd XXGNU hIgBc9< 7 @  BEh)|qX  m, F"~aH U ` P H __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeInit_sizeofrb_hash_newrb_define_modulerb_define_constrb_str_new_staticrb_hash_asetlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ui  P          ( 0 8 @  HH1 HtH52 %3 hhhhhh% D% D% D% D% D% DH= H H9tH& Ht H=q H5j H)HHH?HHtH HtfD=- u+UH= Ht H= 9d ]wS&H=HHH5HH= HHH=HHH=bHHb H=iAHHAH=R !HH H=:HHH=HHH= HHH=HHH={HH{H=ZHHZH=9HH9 H=Hߺ[HHHRbConfigSIZEOFintshortlong long__int128off_tvoid*floatdoubletime_tclock_tsize_tptrdiff_t;$ @hzRx $pFJ w?:*3$"D `\(EGNUP   <   o` J  p oPoo2o  0GA$3a1I GA$3p1067`9 GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realignsizeof.so-2.2.10-35.el8.x86_64.debugm7zXZִF!t/]?Eh=ڊ2NH:^ 7,X\*u Kk]XPi!d.T6|u[{êI .gTJ. Kjlb}023 i_aMp! DZ`ؚ3Ϲa %7L72Fi`Z}-ȈKMDz{FߩNi{:ai+K7YCz(z}U.Ŗc:2pV~*}|i_/H@3H6&JLvF7+k诏tX.'B)T/! /O,CEZw1+VG[uɐ(O 2 p1ݶb t`6Q/M|ȓgYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( P0J8o22EoPP Tpp^Bhcpn@@`w}< < 2I I f $ xP P        HH HP`H @,l@+PK!*Shh2.2.0/x86_64-linux/objspace.sonuȯELF>`*@(@8 @      888$$ Std PtdЁЁЁQtdRtd  GNUA6w 1]ݸV!LΫ6b@` 8 bfg4~ȺBEtFٻ|qXf-7߬s;$3 t!WNK#cZi9E,/G< o:Ue{9,,Ei _>ELs, VSF"i ( r0  `    ` `U__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizerb_obj_idrb_id2symrb_intern2rb_bugrb_sym2strrb_sprintfrb_hash_newrb_funcallrb_objspace_reachable_objects_from_rootrb_hash_foreach__stack_chk_failrb_ary_newrb_hash_tblst_foreachrb_hash_asetrb_ary_pushrb_str_new_cstrrb_hash_lookuprb_objspace_markable_object_prb_objspace_internal_object_prb_data_typed_object_allocrb_obj_memsize_ofrb_gc_markrb_scan_argsrb_objspace_each_objectsrb_eTypeErrorrb_raiserb_hash_arefrb_fix2intrb_objspace_data_type_namerb_internrb_uint2bigrb_obj_is_kind_ofrb_typeddata_is_kind_ofst_init_numtablerb_objspace_reachable_objects_fromst_insertInit_objspacerb_cObjectrb_const_getrb_define_module_functionrb_define_class_underrb_define_methodInit_object_tracingInit_objspace_dumpst_lookupfwrite__fprintf_chkruby_xfreeruby_xmalloc2st_init_strtablest_clearrb_tracepoint_disablerb_tracepoint_enablerb_tracepoint_newrb_bug_reporter_addst_deleterb_tracearg_from_tracepointrb_tracearg_objectruby_xmallocstrncpyst_add_directst_get_keyrb_tracearg_pathrb_tracearg_linenorb_tracearg_method_idrb_tracearg_defined_classrb_gc_countrb_class_path_cachedrb_num2intrb_yieldrb_ensureobjspace_lookup_allocation_info__vfprintf_chkrb_str_vcatfruby_node_namerb_obj_gc_flagsrb_id2namerb_obj_frozen_prb_enc_str_coderangerb_str_capacityrb_enc_from_indexrb_class2namerb_enc_get_indexrb_io_check_iorb_io_get_write_iorb_io_flushrb_io_taint_checkrb_io_check_closedrb_io_stdio_filestdoutrb_str_new_staticrb_requirerb_assoc_newrb_path2classrb_funcallvrb_eArgErrorlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.4GLIBC_2.2.5GLIBC_2.3.4/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ii ui ti  + *  @ |H 3X 03    ȏ 7Џ 8؏ X Z ]  ( 0 8 @ H P  X  `  h  p x b         Ȑ А ؐ      ! " # $ %( &0 '8 (@ )H *P +X ,` -h .p /x 0 1 2 3 4 d 5 6 9 :ȑ ;Б <ؑ = > ? @ A B C D E F( G0 H8 I@ JH KP LX M` Nh Op Px Q R S T U V W g Y [Ȓ \В ]ؒ ^ _ ` aHHq HtH52q %3q hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?h@hAhBhChDhEhFhGqhHahIQhJAhK1hL!hMhNhOhPhQhRhShThUhVhWqhXahYQhZAh[1%mk D%ek D%]k D%Uk D%Mk D%Ek D%=k D%5k D%-k D%%k D%k D%k D% k D%k D%j D%j D%j D%j D%j D%j D%j D%j D%j D%j D%j D%j D%j D%j D%j D%j D%}j D%uj D%mj D%ej D%]j D%Uj D%Mj D%Ej D%=j D%5j D%-j D%%j D%j D%j D% j D%j D%i D%i D%i D%i D%i D%i D%i D%i D%i D%i D%i D%i D%i D%i D%i D%i D%}i D%ui D%mi D%ei D%]i D%Ui D%Mi D%Ei D%=i D%5i D%-i D%%i D%i D%i D% i D%i D%h D%h D%h D%h D%h D%h D%h D%h D%h D%h D%h D%h D%h D%h DH=h Hh H9tH6e Ht H=ah H5Zh H)HHH?HHtHe HtfD=h u+UH=e Ht H=.b dg ]w5f.HHt AAAuH%HDHH9u1ff.fH HH NHcH>H=j HHH=j HuH=JHSHHj H=j HuH=G#HHyj H=qj HuH=GHHQj d@H=Ij HPH=GHH%j 0H=!j H H=PGHHi H=i HH=GG_HHi H=i HH=G/HH}i H=ai HH=FHH=i pH=ii H`H=F HHEi @H=Ai H0H=KF HHi H=i HH=FoHHh H=h HH=E?HHh H=h HH=EHHh H=h HpH=lEHH}h PH=yh H@H=3EHHUh H=Qh HH=DHH-h H=)h HH=DOHHh H=h HH=DHHg H=g HH=RDHHg `H=g HPH=DHHg 0H=g H H=CHHeg H=ag HH=C_HH=g H=9g HH=pC/HHg H=g HH=9CHHf p1H=C H=CHHe @SH_ ;HHH=C[H10HG H8ff.fSH0dH%(HD$(1rH5{e HD$HH$HtF1H1zHH=HH5QHHHL$(dH3 %(u#H0[þH=CHHe ff.AUIATIUHSHtLHiHH5OHHLH H1[]A\A]ff.HHH׺1HÐHHP1HfAUATUHSHHH9zt~HzHCIH5d IHCHt^1L1"H;L7HH;LL?H7t H9+tH9ku8H[]A\A]DLbfH=AoHHc HXuHHHL[]A\A]@H=9d HH7Z HH=&I1Off.@gH9tWAUIATIUHSHHLH9t!H;tH"H;LIDH9uH1[]A\A]f1ff.fH(H@dH%(HD$1HL$Ht$tMHtHFHtH@H=HD$HT$dH3%(H(fD@uHt tHH[ H5@H81HD$HfHHt$cHt$HHH5!|Ht$R]ff.fH9AWAVL5?AUIATIUHSHHLH9tUHHt uL{MtOLL$HtHPHcHTLLLhH9uH1[]A\A]A^A_fHHIDHHI@1DAWH>AVAUATUSHxdH%(H$h1HL$ Ht$HHXH@HHH9uH=H\$H HCHtH@ 1L=P>I?L%DD@H}tLHi\ IcL>H=\ HIDH}HT?L9wrH|$LHHHjuH$hdH3 %(HD$Hx[]A\A]A^A_H=*\ HSdH}IHT?L9v+HH=[ H1IYH=[ HIIfH=oU H!IIH=ZU HI,H=EU HvIH=0U H9IH=U HIH=U HIH=T HsIH=T HEVI~H=T H9IaH=T HIDH=T HI'H=T HQI H=sT HIH=^T HIH=IT HIH=4T H]nIH=T H QIyH= T H4I\H=S HI?H=S HiI"H=S H,IH=S HIH=YP HIH=S Ht}IHD$uHtHHL H5p1H81 f.+HD$ HHH5HL HHR gH=5 HHO .H= 1 HHR H=0uHH{R H=0 UHHSR wH=0 5HH+R :H=0 HHR H=0 HHQ H=0 HHQ H=u0 HHQ FH=_0HHcQ H=H0 uHH;Q H=30 UHHQ H=0 5HHP RH=0 HHP H=/ HHP H=/ HHsP H=/ HHKP ^H=/ HH#P !H=/uHHO H=/UHHO H=s/ 5HHO jH=^/ HHO -H=I/ HH[O H=4/HH3O H=$/ HH O vH=/ HHN 9H=. uHHN H=. UHHN H=. 5HHkN H=. HHCN EH=. HHN H=. HHM H=.HHM H=v.HHM QH=f. uHH{M H=T. UHHSM H=>. 5HH+M H=). HHM ]H=. HHL H=- HHL H=- HHL H=- HHcL iH=- uHH;L ,H=- UHHL H=- 5HHK H=- HHK uH=o- HHK 8H=Y- HHsK H=C- HHKK H=-- HH#K H=- uHHJ DH=- UHHJ H=, 5HHJ H=, HHJ H=, HH[J PH=, HH3J H=, HH J H=,HHI H=s,uHHI \H=\, UHHI H=F, 5HHkI H=0, HHCI H=, HHI hH=, HHH +H=+HHH H=+ HHH H=+ uHH{H tH=+ UHHSH 7H=+ 5HH+H H=+ HHH H=+ HHG H=l+ HHG CH=Z+ HHG H=E+ HHcG H=1+uHH;G H= +UHHG OH=+ 5HHF H=* HHF H=* HHF H=* HHsF [H=* HHKF H=* HH#F H=* uHHE H=}* UHHE gH=i* 5HHE *H=U* HHE H=A* HH[E H=+* HH3E sH=* HH E 6H=) HHD H=) uHHD H=) UHHD H=)5HHkD BH=) HHCD H=) HHD H=}) HHC H=j) HHC NH=W) HHC H=D) uHH{C H=0) UHHSC H=) 5HH+C ZH=) HHC H=( HHB H=( HHB H=( HHB AVH#AUATUSH dH%(H$1HL$ 8Hl$HHHHH9uHH=FH\$HbHCHtH@[I?1E1f.HH t?H|t'H|IIHT?L9H|$LH=H uH?I9Od$H=XA HH|$LHHD$H$dH3 %(H []A\A]A^fDCHmHD$uHtHHy= H5F"H81H= 'HH@ QLI1HD$HxHH5>H|ff.SH dH%(HD$1HH$HD$~HKH!H=HH<$H?H9wHD?HT$dH3%(uH [f @HHPH?H9wHDHHH@H9AUIATIUHSHH1t"IuHt H3Ht HIELH9t$H3Htt(~wLH9uH1[]A\A]fuHtt1ff.fUHSHH(dH%(HD$1Vu"HL$dH3 %(HuhH([]kH58 HHtH[ lH$CHHH5&HD$H<$HH5I2fATUHSHu []A\@HIuH}LH[]A\^fDH=A HH7 BH}HIUSHH5A HVH-?: H}vHH5#HHxH߹HH5#]H߹HH5#BH߹HH5#'H߹HH5# H߹HH5#1HHH5#HUHH5#1H=H5#HH@ gH=@ 1HH5q#KH=@ 1HH5]#/HHH[]f H=~"OHHE@ HH M@ dH%(HD$1HtHHyH1ɅtH $HT$dH3%(HuHf.HHHt H@0HfHfDHH`HtH@ HHDDHff.HH Ht3Hx8H?H9wHD?HfDH?Hff.HHHtHx(HtHyfHfDHHHtHxHtH9fHfDSHH&H=#H> HtHxHH5%PHٺ$[H=#fDULQ$HHSHM$HHHLNH*$LD1mHK(HH"$H1JHKLC HH$H$HHD1H{0Hu$HH=#H1[]fHHH tHHH#H1fHKH#H1WH1Hff.HH1HfH< HtS0HH< < HCCHCHCH< HC H< [DS1H5]HxHQH{H{ 1H56H{ [fDS6HË~t [DH{H{HCHC[ff.@SHËP~[ÐH{HtH{[fHH1Hپ HCHH{HCF; SH<; t H[[H=1; H[7SH Ht$dH%(HD$1Ht)HT$HHT$Ht)Ht$HHHD$dH3%(u#H [fHHt$1aH|$'`USHH(dH%(HD$1Hl$9HaH{HHHD$tCt"HD$HD$dH3%(uHH([]H{HHt$HD$H{ HpHD$H{ Hp(H|$qf.ATUSH dH%(HD$1HtUIHT$HHPu\I|$LHHHD$_HD$HB Ht$HD$HL$dH3 %(u4H []A\DHD$HHHPlHT$HHDAWE1AVAUATUHSH(dH%(HD$1IHLHLHD$PLIuLIHt$IHt H EHVHvH} IIt AE1H}HT$H*HD$H} Hp(HD$H} Hp(HD$HLAHPHSLxHPLt$HIF Mn0Mf(H}HT$HIF8 HD$dH3%(H([]A\A]A^A_fDI$ƒ(LH H uaHHpH} IDHH0fD@HD$@HPHpfSHH=\/ H[HgWS1HHH5cH1HH5(KH1H/H53H1HH5H1HH5 H߹H4H5H߹H9H5H߹HH5H߹HH5H[H'H5{f.HHT$0HL$8LD$@LL$Ht7)D$P)L$`)T$p)$)$)$)$)$dH%(HD$1H$$HD$HD$ HD$HGD$0Ht+HHHHD$dH3%(uHHHtHH9~0tFSH~8HHtHH51HC8[HH5p1HC8[ff.@AWAVAUATIUHSHHdH%(HD$81AHHHVH}(HF8HOHN0H9^jH#HcH>fH4H5 HH1HH5H>H}8HIHt?HH HP1HH5I}0HiIU8H5H1HHLl$Hߺ(LHHtpH5HL{1aL5f.K|LHH16M9tH5H1 IL9uH5H1H5zH1HD$8dH3%(oHH[]A\A]A^A_fH5wH1DHF0H9tH fH KfHH57H1|HU0HH7HH;=HHcH>@H{HCH5HH1HCHPH5H1f.HC1HtHPH1H5hHHƒ@HS H5HH1yf tHH1H5"HYHH ',t@gHH5H1 LHܾ=0~HЃt 6H%`H=`; H1H5HH tK%`H=`t>HH HH9tHH5HH12fH(=H;HdH5HHP1D؃CH5H@ uHSH5H1yfH}0eHmH56HH1YD@H  @H @H @H @H t@H d@H T@H D@H 4@H $@H @H @H @H @H @H ^@H W@H Q@H w @H p @H t@H q d@H X T@H D@H5H1\f.H5wH1+f.HH5H1|H5~H1_gf.HPH tHPH5dH1)k@H{fHSHSSHfH9HڸH?H)HHH HHD$~D$@H5H1H5H1qHH5H1X6H5^H1BlH5HLk1(1H5HH tLkE1L5^HI9CT=Ѐ EH5+H1DHI tHCfD t; udH5H1sɐ"t\uFH5H1UH5H1?DH5H1'zf<H5H1ZfH5wH1BLH10H5H11H5HHH wHXHS5H5H1wݸff.fH9tWAUIATIUHSHHLH9tH;tHLL\H9uH1[]A\A]f.1ff.fATIUHSHB HH9Htt1H5=HHC H9Htt(LHH1H5Hk C[]A\@LHH51lHk C[]A\ff.@AVAUMATIUHSHHdH%(HD$1HH9( H;( H;( HH$HHH( H_HEHH}HhH^H&I$HL$dH3 %(HH[]A\A]A^fDHy HI$HEH59( HH.f1H=肶HE@H=H=[LILHL-' H$Mt-H=r蹸HLH覷H$DH=9'IH=' H HH5"H81ff.UfHSHhdH%(HD$X1HLD$)D$)D$ H\$)D$0)D$@H$HD$4HT$Ht$ H & H|$LH<$HH#H;-& t4H;-& tHT$XdH3%(uHh[]DH|$ ֶHD$ f.UfH:SHhdH%(HD$X1HL$)D$H\$)D$ )D$0)D$@HD$_H & HT$HsH{LHH=%H D$(u]HH=H;-% t7H;-% tHT$XdH3%(u:Hh[]H|$ HD$ H5H1SHH H52H߹HH5ŶH=% HtiH=$ H% HضH=$ H$ HtuH=$ H$ Ht=訶H11[H$ $@H= OHH$ wH= /HHM$ H=r HH5$ kH=K HH$ 3HHT_NONET_OBJECTT_CLASST_MODULET_FLOATT_STRINGT_REGEXPT_ARRAYT_HASHT_STRUCTT_BIGNUMT_FILET_DATAT_MATCHT_COMPLEXT_RATIONALT_NILT_TRUET_FALSET_SYMBOLT_FIXNUMT_UNDEFT_NODET_ICLASST_ZOMBIEtype2sym: unknown type (%d)#compare_by_identity01non-hash givenunknownNODE_SCOPENODE_BLOCKNODE_IFNODE_CASENODE_WHENNODE_OPT_NNODE_WHILENODE_UNTILNODE_ITERNODE_FORNODE_BREAKNODE_NEXTNODE_REDONODE_RETRYNODE_BEGINNODE_RESCUENODE_RESBODYNODE_ENSURENODE_ANDNODE_ORNODE_MASGNNODE_LASGNNODE_DASGNNODE_DASGN_CURRNODE_GASGNNODE_IASGNNODE_IASGN2NODE_CDECLNODE_CVASGNNODE_CVDECLNODE_OP_ASGN1NODE_OP_ASGN2NODE_OP_ASGN_ANDNODE_OP_ASGN_ORNODE_OP_CDECLNODE_CALLNODE_FCALLNODE_VCALLNODE_SUPERNODE_ZSUPERNODE_ARRAYNODE_ZARRAYNODE_VALUESNODE_HASHNODE_RETURNNODE_YIELDNODE_LVARNODE_DVARNODE_GVARNODE_IVARNODE_CONSTNODE_CVARNODE_NTH_REFNODE_BACK_REFNODE_MATCHNODE_MATCH2NODE_MATCH3NODE_LITNODE_STRNODE_DSTRNODE_XSTRNODE_DXSTRNODE_EVSTRNODE_DREGXNODE_DREGX_ONCENODE_ARGSNODE_ARGS_AUXNODE_OPT_ARGNODE_KW_ARGNODE_POSTARGNODE_ARGSCATNODE_ARGSPUSHNODE_SPLATNODE_TO_ARYNODE_BLOCK_ARGNODE_BLOCK_PASSNODE_DEFNNODE_DEFSNODE_ALIASNODE_VALIASNODE_UNDEFNODE_CLASSNODE_MODULENODE_SCLASSNODE_COLON2NODE_COLON3NODE_CREFNODE_DOT2NODE_DOT3NODE_FLIP2NODE_FLIP3NODE_SELFNODE_NILNODE_TRUENODE_FALSENODE_ERRINFONODE_DEFINEDNODE_POSTEXENODE_ALLOCANODE_BMETHODNODE_MEMONODE_IFUNCNODE_DSYMNODE_ATTRASGNNODE_PRELUDENODE_LAMBDATOTALObjectSpacememsize_ofmemsize_of_allcount_objects_sizecount_nodescount_tdata_objectsreachable_objects_fromreachable_objects_from_rootInternalObjectWrappertypeinspectinternal_object_idĵd4ԴtDT$$d4ԱIJ$$$$$-bE( z]@#uX;pS6kN1fI,~aD' y\?"˿tW:ƾoR5޽jM0ټOۻreachable_object_from_root_i: category should insert at onceObjectSpace::InternalObjectWrapper== object_allocations_reporter: START == object_allocations_reporter: END trace_object_allocations_starttrace_object_allocations_cleartrace_object_allocations_debug_startlivedead-- %p (%s F: %p, C: %sC: %p@%s:%lu (%s)) trace_object_allocationstrace_object_allocations_stopallocation_sourcefileallocation_sourcelineallocation_class_pathallocation_method_idallocation_generation, "references":["%p", "%p"UNKNOWN{}{"address":"%p", "type":"%s", "class":"%p", "frozen":true, "node_type":"%s", "embedded":true, "broken":true, "fstring":true, "shared":true, "bytesize":%ld, "capacity":%ld, "value":\%c\u0000\b\t\f\n\r\u%04d, "encoding":"%s", "size":%ld, "default":"%p", "length":%ld, "name":"%s", "struct":"%s", "value":"%g", "ivars":%ld, "fd":%d], "file":"%s", "line":%lu, "method":"%s", "generation":%zu, "memsize":%zu, "flags":{"%s":true]} tempfile.jsoncreateTempfilewrong output option: %li 1:0:dumpdump_alloutputstdoutstring 0@P`p@@@@@@u0 $$$ltrubyobjrubyheap{"type":"ROOT", "root":"%s", "references":["%p";8ТP(<PlЮ @(`xpгLp(pl  <\P0@` 8T@p p$pX 0 p8 Pd P zRx $FJ w?:*3$"D\ Cp\ XDp L ,0Ea@ LED@u AA 4جTFED D(D0t(C ABB,HVDHNL\FBA D(G0x (A ABBF x (J ABBI  8ܭcKED D(G0v(C ABBC  H0q G P,OBI E(D0D8G@c 8C0A(B BBBC hL|FIB B(A0A8G  8A0A(B BBBA DFIB A(A0G? 0A(A BBBG ED0s AC <`<H` H G@\OED D(G0[ (C ABBJ `(EIG@p AAI 4oFAD M ABE Z ABK ,EAD S DAN 4VD L A P\*HU C Ipl2HU K I RHi G D L I:HZ N I:HZ N IZEI(LENQ  CAC <0HKT8HNl@kQYJEDQE] F h xEY B ] C dIKU H \ AD0W AC (,EAG@` AAA 0XBAA D@~  AABF HFEB B(A0D8D`G 8A0A(B BBBG )ES E$G A @QKd A WILdS BBB B(D0D8D 8A0A(B BBBC 8cKED D(G0n(C ABBK4,FDD Z ABE ]AB@(BBE D(D0G@ 0A(A BBBG (l0ELD AAF (ELD AAI 0E P GNU+* |303`o  Ps  o`x    h o`ooo  0@P`p  0 @ P ` p !! !0!@!P!`!p!!!!!!!!!"" "0"@"P"`"p"""""""""## #0#@#P#`#p#########$$ $0$@$P$`$p$$$GA$3a1]s GA$3p1067 +aGA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA$3p1067aPsGA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFY +bGA+GLIBCXX_ASSERTIONSobjspace.so-2.2.10-35.el8.x86_64.debug'7zXZִF!t/x]?Eh=ڊ2N|7Ut5ܹE2B^k.hzfAaT!''e4^qX bGzC!C"[Pp^8/_d6*;v1eb4 8E1qE$E]yUkC+cnU`]ךۈڼ ќW,cZ=g]H#hray_pዜki)!6By9^8hcB \+*XD6X5h閾mE}i0hy 8wsw.@Pt1 SܞTm8Ne; lllvB gq>x3JJ ~Y Y?A鴿Vxrb4bl)|-rG9D$O UPx ._8 &5ޢT[CxS OFA<(8M@9 )f2l:2+8{,b$= ^r9xG,;_eF- Hc/5=ף]aj?ȜTٚC4*~!D1d*z핉Db`ؐnɲSį]sGa9$p5JӦ`ߙevz #tNבkŀ@J*5앷_M|:k.ZqһTm"ݕ[q58fյ_KK\9IFDt.C]aiЫܛ0Fqb)L1}: =ҫX|,xq&2,mQ)dP-mSSv ֺ7aggmG gu县íCnt=QiH,@C#l7#5+ [$Kݑ'^%@+$1뜠VT N ˬTzanlc5˝U(Dɪȡ尺q[q_I"YdRt@Av\usT4ImhYact(.==) - *gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``@(  0x x 8oEo``@Th^Bhcn$$w`*`*H}PsPs `s`spЁЁ    h   H  ` ,@+PK!s"v..2.2.0/x86_64-linux/io/wait.sonuȯELF> @'@8 @       888$$ Std PtdPPPDDQtdRtd  ``GNU;*9-qB`"BE|qXMV  Ugz, F"|    __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizerb_io_taint_checkrb_io_check_closedrb_io_check_writablerb_scan_argsrb_time_intervalrb_wait_for_single_fdrb_sys_fail__stack_chk_failrb_io_check_readablerb_io_read_pendingioctlInit_waitrb_cIOrb_define_methodlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5GLIBC_2.4/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64rui ii  `             ( 0 8 @ H  P  X  `  h p x HH HtH5 % hhhhhhhhqhah Qh Ah 1h !%- D%% D% D% D%  D% D% D% D% D% D% D% D% DH= H H9tH Ht H= H5 H)HHH?HHtH HtfD=U u+UH= Ht H=n Id- ]wAUIATAHUHSH8dH%(HD$(1HXHHDHL$LHX14H|$1HtHD$HT$HT${Aąx0HGAHEHL$(dH3 %(uH8[]A\A]1hAUIATAHUHSH8dH%(HD$(1HXHHDHL$LH1E1aH|$Ht1Ld$HD$HT$Huf{LxYHj{1HT$T&u9D$HOHL$(dH3 %(u!H8[]A\A]1bff.fSHdH%(HD$1HXHHHuB{HT$Tu D$1҅HL$dH3 %(HuH[@4@SHdH%(HD$1BHXHFHHf~"HHDHL$dH3 %(ubf 3A{o }\#n[)̀퓦\mf䀀v}&U<.dJn-zY/4WUKE_ C-E6 Q*Eo7X[86Ya5pLu4G3  ޣ)!)^P3?X2RW<5<Ȧ 8C -C9ۢ()'V" L]yF%NBC,ě*NJBcwPehm_o1؋H"qɱo+S 60Y_qC>%yӝ#"wM%ʵTքa{P^TXL`fmc vF,`&2ENCz!+0zؖU1κ`rF`Lt+(S}'d:D8qTK4ʌCU,i,B/߇ŘVXs]9K ^('T>5ׄ-ž/@h?gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 08o,Eo0T^B8hc n w ^} 21PPD8       (   ` H "("xh&+PK!PP 2.2.0/x86_64-linux/io/console.sonuȯELF>p@hI@8 @// == = 0 == =  888$$... Std... Ptd|)|)|)QtdRtd== = ppGNU}UYKK1H!@135BE|qX/Do. #%K{ab|U =nW Kll3W, F"as"pA 5A )pA w & (__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizerb_funcallvrb_intern2rb_cIOrb_cFilerb_const_definedrb_cloexec_openrb_update_max_fdrb_class_new_instancerb_io_taint_checkrb_io_check_closedrb_str_new_staticrb_obj_freezerb_const_setrb_const_getrb_const_removerb_id2symrb_check_typerb_io_closerb_sym2idrb_funcallrb_error_arity__stack_chk_failtcflushrb_sys_failtcgetattr__errno_locationtcsetattrcfmakerawrb_scan_argsrb_hash_arefrb_funcallv_publicrb_fix2intrb_num2intioctlrb_assoc_newrb_Arrayrb_gc_writebarrier_unprotectrb_num2uintrb_protectrb_jump_tagrb_yieldInitVM_consolerb_define_methodrb_define_singleton_methodrb_define_module_underInit_consolelibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5GLIBC_2.4/opt/alt/openssl/lib64:/opt/alt/ruby22/lib640ui :ii Fui :=  = = = ? ? ? ? ? +? ,? 0@  @ (@ 0@ 8@ @@ H@ P@  X@  `@  h@  p@  x@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @  @ !A "A #A $A % A &(A 40A '8A (@A )HA *PA ,XA -`A .hA /HH. HtH5/ %/ hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*A%M, D%E, D%=, D%5, D%-, D%%, D%, D%, D% , D%, D%+ D%+ D%+ D%+ D%+ D%+ D%+ D%+ D%+ D%+ D%+ D%+ D%+ D%+ D%+ D%+ D%}+ D%u+ D%m+ D%e+ D%]+ D%U+ D%M+ D%E+ D%=+ D%5+ D%-+ D%%+ D%+ D%+ D% + D%+ D%* DH=* H* H9tH>) Ht H=* H5* H)HHH?HHtH) HtfD=* u+UH=( Ht H=& )d]* ]wH"O {H g ATIH5* USHHtLH[]A\SH=QHH) H5) 11ff.AVAUATUSH dH%(HD$1IH1OH' H9u H' HH5) HH1ҾH=~LcEDOd$HHL$$HD$HHI}LpLH=GHAN LHIFH5( mHHL$dH3 %(L H []A\A]A^H5( HIĨuHuZH5( HH H=k( H9ADH.IH uID$HtxtHAH=( IH9u$LAH5' H'fH(LL1H1I1Mff.fUHSHHXH{18u HH[]1SHPdH%(HD$H1HXH{H;u)D$ HHHЃHT$HdH3%(u HP[1fUSHH  8u&HھuH[]H1[]AUIATUHSHXdH%(HD$H1IHXH[LkuPD$ Iu:D$ LIt.HT$HdH3%(Hu"HX[]A\A]xD$ 1ff.ATUHSHPdH%(HD$H1I)HXH-[Lu@LH"L$ {H $tHT$HdH3%(HuHP[]A\1UHSHH+c HtExCExCH[]AUIATIUSHHXdH%(HD$H11uDHC0oLoKoS HD$0C8H)$H)L$)T$ D$8AHމHT$HdH3%(u HX[]A\A]*f.ATUSHH H dH%(HD$1HL$H|$8H=$ HsH|$HH=# HHNH|$HHI1Hu_Iu!HT$dH3%(H []A\@LHL$*HD$(HǨtqLCH@Hth3HItfDH= HH# =H= HH# f{f1 @AUATUHSHhdH%(HD$X1HT$UHI*HXH.DcH\$HDu8LH;HDtHL$XdH3 %(HuHh[]A\A]1fUHSHHXHH{XHtHXH{u HH[]1fDSHdH%(HD$1BHXHFH{XHt(HXH,{1HTu.t$<$Ht6H|?.HL$dH3 %(u H[1 ff.ATUHSHXHH{XDcHuDuJH[]A\fDsHXHw[tA9t1Dut1eDATIUSHH0dH%(HD$(1 HhH HHHHH HsH; HHHHHD$ P1LL$ LD$H}XXZH]HD$ H<$1HtH|$fD$ 1HtH|$fD$"1HtlH|$fD$$1HtUfD$&HT$ 1TuWHL$(dH3 %(Lu?H0[]A\D{%Hs fHXH[31ff.AWAVAUIATIUHSHH4$dH%(H$1D$bLxLfA_IXAD$ HD$HE1AHhHAtD9uE|$KH$dH3 %(L+HĨ[]A\A]A^A_Ht$ LLD$AA_D$ IXHtDnALxLoA_!A9Ht$\LLGH<$HHT$D$AHIHhH AH}XH }9Ht$\vD$L$ L$ 1f.H<$HHT$E1\HIaHhHeA\D9uIHt$ D4D$L$ Eh#AA_D$ ofDD$ HhH}9sfH5M 1HH5- 1H|SHHdH%(HD$1HLHeH5HHsHL$dH3 %(uH[8SHHdH%(HD$1HH5 HHHHL$dH3 %(uH[SHT HH5kH;H;HH5QH;1HH5>H;1HH5-~H;HH5cH;HH5HH;1HH50H;1H4H5H;1HLH5H;HaH5H;1HyH5H;1HH5H;1HH5H;HH5rH;H5k#HW[H5HWHHq Ht7E #6td33& 6WV+[Sp7KNU:c8pBrK^6V^%  Yua@z:M@cOp(IϾ'+7!t? eNCX4qic ,Qm+8->)NPR_<5@?Ϊ^0Ny=0a^xs7=,hc;ON`z̲ ZXg\CC !Y` I&3w寁!ZWaHN<[xqӕs8!,QRl[VTf[H]e(YUj82E8go厹1uP}do]/}n#mq5U*Kxg[{gO])¶TZ"ovtLmujU5 ؍v)M4ouKbb`+^\1R񽇒ia̦ <}K`=4?N[o[sy:^IB͒ƫ1V#p̒gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``8( 0}8o& & lEo PT ^B hcnwppm}(( 2((|)|)`*`*.. = == == == = ? ?8@ @ppA pAPA`pAH C,CT8H+PK!..!2.2.0/x86_64-linux/io/nonblock.sonuȯELF> @'@8 @       888$$ Std Ptd TTQtdRtd  hhGNU (JX#~vVE@ BE|qX0 U gy, F"[Bh Up Ih  [__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizefcntlrb_sys_failrb_io_taint_checkrb_io_check_closedrb_scan_argsrb_yieldrb_ensure__stack_chk_failrb_io_set_nonblockInit_nonblockrb_cIOrb_define_methodlibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.4GLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib648ii Zui d `               ( 0 8 @  H  P  X ` HH HtH5 % hhhhhhhhqhah Q% D% D% D% D% D% D% D% D% D% DH= H H9tH Ht H= H5z H)HHH?HHtH HtfD== u+UH= Ht H=f Id ]wHW?1t H1H1`tH1ff.@SHXH{[H4H?D%t-u4H1tHt1UDAVIAUAHATAUHSH dH%(HD$1HXHE~)1HL$LDH=E1lHD$Aċ{{DƉD$|$"H= HL$HH|GHT$dH3%(u H []A\A]A^DATIUHS-HXH1ItHH[]A\{8{1҉H[]A\@SH\ 1H;H5PH;H;HmH5<H;[HH5*HH01nonblock?nonblock=nonblock;P TldD`tzRx $FJ w?:*3$"Dh\/H_ A x!DU A +EZK[UT@ FEH G(D0DP 0A(A BBBA 4\FDD f ABI XABH[E~GNU`   .8p 8   o`x   Hp o@ooo p GA$3a18 GA$3p1067p GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFYp GA+GLIBCXX_ASSERTIONSnonblock.so-2.2.10-35.el8.x86_64.debug%P7zXZִF!t/H]?Eh=ڊ2N> .;8'dBs}:Rx@m5ĢN/:SۡC=7VCDdrMy:GjHVm‡rjazȾ StqY*XЫ| È%5+ iͦv7ŐU&2a ?}9{~׿+ #ߊE˾ @!:gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 0xx8o(Eo@@0Tpp^BHHh88c``n  w +} 2  T` ` d       0 hh h p `h H ","d&+PK!4fXPXP!2.2.0/x86_64-linux/racc/cparse.sonuȯELF>@I@8 @:: == = H == =  888$$999 Std999 Ptd555QtdRtd== = GNU٠ <2ou,0A @023BE|qX7/xS  km=H <U3{}, ^,F"eU'` XA A XA  0z__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizerb_gc_markrb_ary_storerb_funcallrb_int2bigrb_ary_subseqrb_catchrb_ivar_getrb_fix2intrb_num2intrb_num2longrb_sym2idrb_eTypeErrorrb_raiserb_check_typeddatarb_check_typerb_ary_entryrb_ary_new_caparb_ivar_setrb_iv_setrb_ary_poprb_ary_newrb_id2namerb_eArgErrorrb_str_new_staticrb_obj_classrb_hash_arefruby_xcallocrb_data_typed_object_alloc__stack_chk_failrb_block_callrb_iter_breakInit_cparserb_intern2rb_cObjectrb_const_definedrb_const_getrb_const_get_atrb_define_private_methodrb_define_constrb_define_class_underrb_undef_alloc_funcrb_undef_methodrb_eRuntimeErrorrb_define_modulelibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5GLIBC_2.4/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ui %ii 1= p= 0 =  = @= 4H= X= ? ? ? ? ?  ? %? &? (@  @ (@ 0@ 8@ @@  H@  P@  X@  `@  h@ p@ x@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ !@ "A #A $A 'A ( A )(A *0A +8A ,@A -HA .PA /HH)/ HtH5R/ %S/ hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'q%, D%, D%, D%, D%, D%, D%, D%, D%, D%, D%}, D%u, D%m, D%e, D%], D%U, D%M, D%E, D%=, D%5, D%-, D%%, D%, D%, D% , D%, D%+ D%+ D%+ D%+ D%+ D%+ D%+ D%+ D%+ D%+ D%+ D%+ D%+ D%+ DH=+ H+ H9tH) Ht H=a+ H5Z+ H)HHH?HHtH) HtfD=+ u+UH=) Ht H=& d* ]wfDSHH?H{H{H{(H{0H{8H{@H{HH{PH{XH{`vH{pmH{xdHXHLH@H4H['ATIHUHSHHH7 HtFHH7 urHwLH{L1LLH5) H@HHxXHT-HH7 t1H[]A\HHwTHw[]A\cHHHx;H u#HGH9HHNH)Hf.Hf.UHSH)HHHHH5H=H{H5( H\t8HHHtH[]f.{H[]@HhfD@ t@uHtuPHL& H5H81AWIAVMAUIATIH5# UHSHHL(L`LxIt L{HC H5' LxHHiHE HUHBH1H`IH0Ls(H?IHLs0HIHLs8HIHLs@HIHLsHHIHLsPHIHjLsXHyIHILs`HXPHHCh H<IH Lsp HIHLsx HHH HHHHE #ǃFH@M@HLHD$fLIuLfDHGUuHD$4H\HHLHD$L]H= H5Q1f.AVAUIATMUSHHIHHHƒ uJHkHuP1HNIEH trH¸uqI$H[]A\A]A^HHHtA>H>H &HHM IH5H81H{„tHHH=I$H[]A\A]A^HHt$Ht$HAt-H>SH HH IH5H81H ZH\H JHL,ff.AUATUSHH(Ht$HT$HHH{@H HGH9HH{8H HH¸H9HIML9=HH~3H?HxHHsHT?H{H5S NHL$LH߽HHH@LH HL6H5 H{17HHH9HHIHtnHthDSEHLH([]A\A]DLH{xHt$HHDEHLH+H{(H HH9 HHHIH{0H HGH9HH)HH1H9f.HxLDHǃE)H{LL$HLD$H5 1wHfDHIUHfDH1f%HIM*HHMt I9|I9L9ulH1^HǃHH([]A\A]ÐHGSHH@HW{HE@H{H5 11\{H-@HHLD$LD$HfHHHuHH{H5 HǃwHvfDHHHHH7 .H.H"HHxHH{@H HH9HHHHI}H{(H HL9~aLaHtS3HIH{0H HL9~)L)HtHH9HH HHwHHHWHG9HHGQHǃHǃ DHHH{1LLH5 H8ILH5t@H{LD$1HHLH5 0H$@HIH{H5 11HL$Hs H{LD$H,DHCHsM~9L9L9H=x LH51tHHL9}LH$&HǃHǃsH= LH51H H5H81{HL$LHfoAUIATIUHSH(dH%(HD$1ZH= H  HH1AHIHHD$‰L1ɺHCHD$HD$HD$HD$HHL$dH3 %(u H([]A\A]ff.AWMAVIAUIATIUHSH(dH%(HD$1pH= H" HH1MLIHHHD$‰L1ɺHCHD$Hs H{1L 1LvAHt5HD$HD$HD$HHL$dH3 %(u3H([]A\A]A^A_H{ H5HH H81^fUHHH5. SH(dH%(HD$1HuZHp HxHHHL$LD$mHT$Ht$H߹Hw9HT$dH3%(uH([]HA H5)H81ff.ATH=USH- HHH}!H}HH=IILHHH߹HH5 HHH5H=4HH5H<H=.HH5HHUH5LHH H= H5JH= H5~7H H=vHH U H=H =H=LHr % H==HR H=2H2 H=-H H= H H=H H=H H=H } H=Hr e[]H\ A\fH=HUH5HIHHHracc_jumpnot symbol[Racc Bug] wrong arg.size %ld@vstack@tstackreturnednext_tokenyielded$token given after EOFextra token after EndOfTokenRaccParser_racc_do_parse_c_racc_yyparse_c1.4.5Racc_Runtime_Core_Version_CRacc_Runtime_Core_Id_CCparseParamsinitializeinitialize_copy@yydebugon_error_reduce_none@racc_error_statusracc_shiftracc_reduceracc_acceptracc_read_tokenracc_next_stateracc_e_popracc/cparsestate stack unexpectedly empty%s() %s %li (must be Array[2])%s() %s wrong size of array (%ld for 2)[Racc Bug] unknown act value %ld%s() is finished before EndOfToken$originalId: cparse.c,v 1.8 2006/07/06 11:39:46 aamine Exp $;HXXTh8x\hDzRx $FJ w?:*3$"Dp\ pE88BGD  AEF e ABH F48AIJ O AAK I AAE =eH(,BEE E(K0D8D@" 8D0A(B BBBE XtFLB B(A0A8D`hTpYhA` 8F0A(B BBBE XdBBE D(A0D@v 0A(A BBBH  0A(A BBBA L,BBA A(GP (A ABBF  (A ABBB 8|FEI I(DP (A ABBA H'FEE J(D0I8D` 8A0A(B BBBA (pEND@v AAA ,0zFMA ( AIJ GNUp0 = 4;  <3= = o`x h @  x P oH oo o=  0@P`p 0@P`p 0GA$3a1I3 GA$3p1067:3GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFYGA+GLIBCXX_ASSERTIONScparse.so-2.2.10-35.el8.x86_64.debug:]7zXZִF!t/]?Eh=ڊ2N~ AKKN>Jq8ol# J9sDt `a4>-KL3IWSX'{gb ը% urE).2^e==lTb5X: J͗ES s/nE0B,b+9'37Q62vzɿ gsqA`^GGa|\70ȹ Z=ҭ1pOBYF+@nK?C- mzCy s{bxh7C #\ .,!PZX '`=F^N {եX9fJEi -F,FQ9gnt ;^cK[_hwOAT .w1ٽzՒL:k_@>^NȪ%޲e@CW%rt~ĢBM>Г0&3~|v!>#p頗"ջZ l^)ڼ"yZ >˰ڿjAԹsb4&D?9OTf}>mXS*#AĀ :*cY:օzB]I,J hX| bbq_;^K. qA^+vVf3B(Y(ظ$e@a2_ E^e)ك=D!Äb=Йk8NB]lS0[v"ƐCʩQC_cN纠yI%"miG[%į+#:E @ayOF{'f;U%UV1rKTͼh S %}:e>ȇ= He^qoL8[/ØjNuX~Жǰ(gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``4( 0xxh8o hEoH H 0Tx x P^B hcn@@wz}<3<3 2P3P35566`99 = == = = =h = = ? ?@@ @XXA XApA`XAH C,CG+PK! PP2.2.0/x86_64-linux/digest.sonuȯELF>@I@8 @.. == = P == =  888$$... Std... Ptd ) ) )  QtdRtd== = GNUT_6#㉠!n{82B 245BE|qXYR  2eUsL X< oGfx^, (F"-`A A `A R "-__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizerb_string_valuerb_usascii_str_newrb_eRuntimeErrorrb_raiserb_funcallvrb_funcallrb_scan_argsrb_obj_clone__stack_chk_failrb_obj_classnamestrlenrb_str_buf_newrb_str_catrb_str_cat_cstrrb_str_buf_appendrb_class_superclassrb_ivar_definedrb_ivar_getrb_check_typerb_obj_classrb_check_typeddatarb_str_newmemcpyrb_error_frozen_objectrb_eTypeErrorruby_xmallocrb_data_typed_object_allocrb_eNotImpErrorrb_obj_allocrb_obj_call_initrb_eArgErrorrb_obj_is_kind_ofrb_check_string_typerb_str_cmpInit_digestrb_define_modulerb_define_module_functionrb_define_module_underrb_define_methodrb_define_private_methodrb_cObjectrb_define_class_underrb_include_modulerb_define_singleton_methodrb_define_alloc_funcrb_intern2libruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.14GLIBC_2.4GLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64zii ui = P=  =  = @= (? ? ? ? ? ? $? *? ,? -@  @ (@ 0@ 8@ @@  H@  P@  X@  `@  h@ p@ x@ @ @ @ @ @ @ @ @ @ @ @ @ @ @  @ !@ "A #A %A &A ' A ((A )0A +8A -@A .HA /PA 0XA 1HHa. HtH5. %. hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(a%+ D%+ D%+ D%+ D%+ D%+ D%+ D%+ D%+ D%+ D%+ D%+ D%+ D%+ D%+ D%+ D%}+ D%u+ D%m+ D%e+ D%]+ D%U+ D%M+ D%E+ D%=+ D%5+ D%-+ D%%+ D%+ D%+ D% + D%+ D%* D%* D%* D%* D%* D%* D%* D%* D%* DH=* H* H9tH( Ht H=* H5* H)HHH?HHtH( HtfD=E* u+UH=( Ht H=% d* ]wHUSHH|$H|$;HD$H unHHh1H4HxH u{Ht:1LMDL΃@A A40LW@4WHH9uH[]DHXHhH?H9vH' H5;H81Hx|HHH5d) H׉HHfDH@H5) 11 ff.H5) 11ff.U11SHHH5( H5( H1H1HH[]off.@U11SHHH5( sH5( H1H1]HH[]USHHHdH%(HD$1H~xH5I( 1H1 H $1H5#( HH5 ( 11HH5 ( 1HH1HHL$dH3 %(u-H[]H-' Hy1HH1H`SVH5' 1HH1`H[ff.SHHH5 HHc% H81fPXH5 Hf.PXH5 Hf.PXH5 Hzf.PXH5 HZf.ATUHS`HIEHxEH5 HHuLHHߺH5d VH11HHHߺH5< +H[]A\PXH5% HH,$ H81rfSHtYH@HxHHt?H5% HHtH5% H HHHC 8u[ÐH# H5 H81H# H5R H81HH[Hc@HHDff.fHSH+Hc@HHDff.fUSHHHHH5| HHU u HH[]f.ATUHSHHH5. HHs1IHHC0HuHE tHuLLS uH[]A\2fATUSHHHt$WH/H5 HI=H|$H Ht$ID$(H uHHHHH[]A\fHVHvfDATUSHH9tz@u|HtsHƒtfuaHHHIH|I9uAHH5 H5 HHvIT$HHH[]A\HH'! H5T H81ff.H9=-# ATUSt:HHxIKHHAT$ u.HHH^ []A\H H5 H81ATUSH dH%(HD$1~nHIԉH|$HHD$vLHUsHD$H|$(HL$H|$1H5=" HL$dH3 %(u!H []A\H; H5EH81jDUSHHHdH%(HD$1HT~pH5! 1H1H $1H5! HH5! 11HpH5! 1HH1ZHL$dH3 %(Hu*H[]H-Y! H1HH1"HHH11dH%(HD$1 HH$H$H u$H >HHL$dH3 %(uH@HcBHDUHSHHH(H5 dH%(HD$1qHH5p 1H1THHD$HD$Ht>H|$RH|$HH|$H t;Ht$HWH uAHH9t>1HL$dH3 %(ucH([]DHHt$HH tHFH9uuH11H11HD$HD$Md@HHi H8H HJ HHr H+ HHS H  HsH4 H H<H H HH=eH RHH5MHH H=  H5:=HH5HH kH= HH5LH= 1H|H5]H= 1H@H5;H=u 1HH5H=Y 1HH5H== HIH5vH= 1H-H5]H= 1H1H5IH= HH5fH= 1HH5JH= HH5+H= 1H[H5H=p 1HH5H=T 1HH5H=8 1HH5H H= H5~H~1HuH5lHH H5 H= H= HH5]H= HH5>H H.Hw H= H5H" H5HHD gH=8 H4H5H= 1HH5H= HyH5H= HZH5$nH= 1HH5"H= 1H2H56H= 1HH54HfDH=&H H=H  H=MH  H=#H H=oHx pH=OH` 9H=s/HH HHdigest string too long01%s does not implement %s()block_lengthresetfinishupdate#<: >Digest initialization failed.different algorithmsno data givenhexdigestdigest_lengthDigesthexencodeInstance<<==inspectnewhexdigest!to_ssizeClassinitializemetadataBaseinitialize_copyIncompatible digest API versionDigest::Base cannot be directly inherited in RubyDigest::Base is an abstract class0123456789abcdef;  P(P@hP| P`$0Lx0`pHd P@DtpHzRx $ FJ w?:*3$"D\(pAAD0 AAF p*HZ $AEEG fDA$=EEG fDA(@EAN0 AAD l%E_'AEAKEAKEAKEAK(FAD ~AB< AAKX$A] B x#HU#HU(FEAG n DAA ,nFAD Z ABA 0(zFAA G0W  DABC ,8tFAA  ABA (hhMAA t ABE 0HFAA D@}  AABA (EAN0 AAA hpH S E (EDJ@ AAF <-H= K GNUP = (!8GWbpz P P'= = o`  @ x @ 8 o oo o=  0@P`p 0@P`pGA$3a1P]' GA$3p1067`M'GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFY`hGA+GLIBCXX_ASSERTIONSdigest.so-2.2.10-35.el8.x86_64.debugO7zXZִF!t/]]?Eh=ڊ2NHfn o?=BMK2e"KI'<__aThR_[<{(oNJȯְ/ $ %{uɡ:uPuiӮ<߶.wfYfV컖<#8,uNv, vC_ϢG@Od='_9%qsE"^|!X6I. *PP2PiL[<&1'LSBbbZ0Tc?4.}Qv$=׊!\{}j)~u?j.!BN&Fl~|$Z*]7Ӧ`o-FoEIu3:Js\%F4K sʥֈWM&g"bYtI\~'̒ ."LW@@= g+1SD0sk2 {k/ W[xZOYSe)(gESh˿[ 14s 2pϬ\RL kf~(zgg0D95 F{ @~襤"xQ.4M_'{BWj9¸J.1Ⱥ7 4^*h2C.``FXêCn^@YzǦ-u&~^iBC4ʧh^m}r$1D Pw0?G~߄ѿx'<N,WE'Jk]^-U.WXK 3~q/"'VDz]w@ !~Ē)`?4n67-O @'@8 @       888$$ Std Ptd<<QtdRtd  ``GNU%i-Nce;9(@ BEq?|qX m{ `4NU#, F"   Q  __gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizerb_ary_duprb_ary_clearrb_ary_freezerb_hash_asetrb_get_coveragesrb_hash_newrb_hash_tblst_foreachrb_hash_freezerb_reset_coveragesrb_eRuntimeErrorrb_raiserb_set_coveragesrb_obj_hideInit_coveragerb_define_modulerb_define_module_functionrb_gc_register_addresslibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6_edata__bss_start_endGLIBC_2.2.5/opt/alt/openssl/lib64:/opt/alt/ruby22/lib64ui              ( 0 8 @ H  P  X  `  h  p x     HH HtH5" %# hhhhhhhhqhah Qh Ah 1h !h hhh%  D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% DH= H H9tH Ht H=a H5Z H)HHH?HHtH HtfD= u+UH=b Ht H= 9d ]wAUIHATIUHSHHHVHHLL0H1[]A\A]USHHHt4HHHH5{HHHH[]Hm H5H81t@H#HuH= H4tYH3HH H= (fDSH=1HH5xHHTH1HH5`Jh#Zd;ڗ.9uŁ/v1 ^`ewǶEd'~(b;x-!E KODH(Ivo~ yxKuN3/bmy(…e\:.PL,Ԡy({bCsTkrdޤ˵ ( "P&^?g]CsCOPY:}'q bol %Lzsuc<       (    ` H","#t&1PK!C%],^,^2.2.0/scanf.rbnu[# scanf for Ruby # #-- # $Release Version: 1.1.2 $ # $Revision: 44961 $ # $Id: scanf.rb 44961 2014-02-15 01:33:03Z ryan $ # $Author: ryan $ #++ # # == Description # # scanf is an implementation of the C function scanf(3), modified as necessary # for Ruby compatibility. # # the methods provided are String#scanf, IO#scanf, and # Kernel#scanf. Kernel#scanf is a wrapper around STDIN.scanf. IO#scanf # can be used on any IO stream, including file handles and sockets. # scanf can be called either with or without a block. # # Scanf scans an input string or stream according to a format, as # described below in Conversions, and returns an array of matches between # the format and the input. The format is defined in a string, and is # similar (though not identical) to the formats used in Kernel#printf and # Kernel#sprintf. # # The format may contain conversion specifiers, which tell scanf # what form (type) each particular matched substring should be converted # to (e.g., decimal integer, floating point number, literal string, # etc.) The matches and conversions take place from left to right, and # the conversions themselves are returned as an array. # # The format string may also contain characters other than those in the # conversion specifiers. White space (blanks, tabs, or newlines) in the # format string matches any amount of white space, including none, in # the input. Everything else matches only itself. # # Scanning stops, and scanf returns, when any input character fails to # match the specifications in the format string, or when input is # exhausted, or when everything in the format string has been # matched. All matches found up to the stopping point are returned in # the return array (or yielded to the block, if a block was given). # # # == Basic usage # # require 'scanf' # # # String#scanf and IO#scanf take a single argument, the format string # array = a_string.scanf("%d%s") # array = an_io.scanf("%d%s") # # # Kernel#scanf reads from STDIN # array = scanf("%d%s") # # == Block usage # # When called with a block, scanf keeps scanning the input, cycling back # to the beginning of the format string, and yields a new array of # conversions to the block every time the format string is matched # (including partial matches, but not including complete failures). The # actual return value of scanf when called with a block is an array # containing the results of all the executions of the block. # # str = "123 abc 456 def 789 ghi" # str.scanf("%d%s") { |num,str| [ num * 2, str.upcase ] } # # => [[246, "ABC"], [912, "DEF"], [1578, "GHI"]] # # == Conversions # # The single argument to scanf is a format string, which generally # includes one or more conversion specifiers. Conversion specifiers # begin with the percent character ('%') and include information about # what scanf should next scan for (string, decimal number, single # character, etc.). # # There may be an optional maximum field width, expressed as a decimal # integer, between the % and the conversion. If no width is given, a # default of `infinity' is used (with the exception of the %c specifier; # see below). Otherwise, given a field width of n for a given # conversion, at most n characters are scanned in processing # that conversion. Before conversion begins, most conversions skip # white space in the input string; this white space is not counted # against the field width. # # The following conversions are available. # # [%] # Matches a literal `%'. That is, `%%' in the format string matches a # single input `%' character. No conversion is done, and the resulting # '%' is not included in the return array. # # [d] # Matches an optionally signed decimal integer. # # [u] # Same as d. # # [i] # Matches an optionally signed integer. The integer is read in base # 16 if it begins with `0x' or `0X', in base 8 if it begins with `0', # and in base 10 other- wise. Only characters that correspond to the # base are recognized. # # [o] # Matches an optionally signed octal integer. # # [x, X] # Matches an optionally signed hexadecimal integer, # # [a, e, f, g, A, E, F, G] # Matches an optionally signed floating-point number. # # [s] # Matches a sequence of non-white-space character. The input string stops at # white space or at the maximum field width, whichever occurs first. # # [c] # Matches a single character, or a sequence of n characters if a # field width of n is specified. The usual skip of leading white # space is suppressed. To skip white space first, use an explicit space in # the format. # # [[] # Matches a nonempty sequence of characters from the specified set # of accepted characters. The usual skip of leading white space is # suppressed. This bracketed sub-expression is interpreted exactly like a # character class in a Ruby regular expression. (In fact, it is placed as-is # in a regular expression.) The matching against the input string ends with # the appearance of a character not in (or, with a circumflex, in) the set, # or when the field width runs out, whichever comes first. # # === Assignment suppression # # To require that a particular match occur, but without including the result # in the return array, place the assignment suppression flag, which is # the star character ('*'), immediately after the leading '%' of a format # specifier (just before the field width, if any). # # == scanf for Ruby compared with scanf in C # # scanf for Ruby is based on the C function scanf(3), but with modifications, # dictated mainly by the underlying differences between the languages. # # === Unimplemented flags and specifiers # # * The only flag implemented in scanf for Ruby is '*' (ignore # upcoming conversion). Many of the flags available in C versions of # scanf(3) have to do with the type of upcoming pointer arguments, and are # meaningless in Ruby. # # * The n specifier (store number of characters consumed so far in # next pointer) is not implemented. # # * The p specifier (match a pointer value) is not implemented. # # === Altered specifiers # # [o, u, x, X] # In scanf for Ruby, all of these specifiers scan for an optionally signed # integer, rather than for an unsigned integer like their C counterparts. # # === Return values # # scanf for Ruby returns an array of successful conversions, whereas # scanf(3) returns the number of conversions successfully # completed. (See below for more details on scanf for Ruby's return # values.) # # == Return values # # Without a block, scanf returns an array containing all the conversions # it has found. If none are found, scanf will return an empty array. An # unsuccessful match is never ignored, but rather always signals the end # of the scanning operation. If the first unsuccessful match takes place # after one or more successful matches have already taken place, the # returned array will contain the results of those successful matches. # # With a block scanf returns a 'map'-like array of transformations from # the block -- that is, an array reflecting what the block did with each # yielded result from the iterative scanf operation. (See "Block # usage", above.) # # == Current limitations and bugs # # When using IO#scanf under Windows, make sure you open your files in # binary mode: # # File.open("filename", "rb") # # so that scanf can keep track of characters correctly. # # Support for character classes is reasonably complete (since it # essentially piggy-backs on Ruby's regular expression handling of # character classes), but users are advised that character class testing # has not been exhaustive, and that they should exercise some caution # in using any of the more complex and/or arcane character class # idioms. # # == License and copyright # # Copyright:: (c) 2002-2003 David Alan Black # License:: Distributed on the same licensing terms as Ruby itself # # == Warranty disclaimer # # This software is provided "as is" and without any express or implied # warranties, including, without limitation, the implied warranties of # merchantability and fitness for a particular purpose. # # == Credits and acknowledgements # # scanf was developed as the major activity of the Austin Ruby Codefest # (Austin, Texas, August 2002). # # Principal author:: David Alan Black (mailto:dblack@superlink.net) # Co-author:: Hal Fulton (mailto:hal9000@hypermetrics.com) # Project contributors:: Nolan Darilek, Jason Johnston # # Thanks to Hal Fulton for hosting the Codefest. # # Thanks to Matz for suggestions about the class design. # # Thanks to Gavin Sinclair for some feedback on the documentation. # # The text for parts of this document, especially the Description and # Conversions sections, above, were adapted from the Linux Programmer's # Manual manpage for scanf(3), dated 1995-11-01. # # == Bugs and bug reports # # scanf for Ruby is based on something of an amalgam of C scanf # implementations and documentation, rather than on a single canonical # description. Suggestions for features and behaviors which appear in # other scanfs, and would be meaningful in Ruby, are welcome, as are # reports of suspicious behaviors and/or bugs. (Please see "Credits and # acknowledgements", above, for email addresses.) module Scanf # :stopdoc: # ==Technical notes # # ===Rationale behind scanf for Ruby # # The impetus for a scanf implementation in Ruby comes chiefly from the fact # that existing pattern matching operations, such as Regexp#match and # String#scan, return all results as strings, which have to be converted to # integers or floats explicitly in cases where what's ultimately wanted are # integer or float values. # # ===Design of scanf for Ruby # # scanf for Ruby is essentially a -to- converter. # # When scanf is called, a FormatString object is generated from the # format string ("%d%s...") argument. The FormatString object breaks the # format string down into atoms ("%d", "%5f", "blah", etc.), and from # each atom it creates a FormatSpecifier object, which it # saves. # # Each FormatSpecifier has a regular expression fragment and a "handler" # associated with it. For example, the regular expression fragment # associated with the format "%d" is "([-+]?\d+)", and the handler # associated with it is a wrapper around String#to_i. scanf itself calls # FormatString#match, passing in the input string. FormatString#match # iterates through its FormatSpecifiers; for each one, it matches the # corresponding regular expression fragment against the string. If # there's a match, it sends the matched string to the handler associated # with the FormatSpecifier. # # Thus, to follow up the "%d" example: if "123" occurs in the input # string when a FormatSpecifier consisting of "%d" is reached, the "123" # will be matched against "([-+]?\d+)", and the matched string will be # rendered into an integer by a call to to_i. # # The rendered match is then saved to an accumulator array, and the # input string is reduced to the post-match substring. Thus the string # is "eaten" from the left as the FormatSpecifiers are applied in # sequence. (This is done to a duplicate string; the original string is # not altered.) # # As soon as a regular expression fragment fails to match the string, or # when the FormatString object runs out of FormatSpecifiers, scanning # stops and results accumulated so far are returned in an array. class FormatSpecifier attr_reader :re_string, :matched_string, :conversion, :matched private def skip; /^\s*%\*/.match(@spec_string); end def extract_float(s) return nil unless s &&! skip if /\A(?[-+]?)0[xX](?\.\h+|\h+(?:\.\h*)?)[pP](?[-+]\d+)/ =~ s f1, f2 = frac.split('.') f = f1.hex if f2 len = f2.length if len > 0 f += f2.hex / (16.0 ** len) end end (sign == ?- ? -1 : 1) * Math.ldexp(f, exp.to_i) elsif /\A([-+]?\d+)\.([eE][-+]\d+)/ =~ s ($1 << $2).to_f else s.to_f end end def extract_decimal(s); s.to_i if s &&! skip; end def extract_hex(s); s.hex if s &&! skip; end def extract_octal(s); s.oct if s &&! skip; end def extract_integer(s); Integer(s) if s &&! skip; end def extract_plain(s); s unless skip; end def nil_proc(s); nil; end public def to_s @spec_string end def count_space? /(?:\A|\S)%\*?\d*c|%\d*\[/.match(@spec_string) end def initialize(str) @spec_string = str h = '[A-Fa-f0-9]' @re_string, @handler = case @spec_string # %[[:...:]] when /%\*?(\[\[:[a-z]+:\]\])/ [ "(#{$1}+)", :extract_plain ] # %5[[:...:]] when /%\*?(\d+)(\[\[:[a-z]+:\]\])/ [ "(#{$2}{1,#{$1}})", :extract_plain ] # %[...] when /%\*?\[([^\]]*)\]/ yes = $1 if /^\^/.match(yes) then no = yes[1..-1] else no = '^' + yes end [ "([#{yes}]+)(?=[#{no}]|\\z)", :extract_plain ] # %5[...] when /%\*?(\d+)\[([^\]]*)\]/ yes = $2 w = $1 [ "([#{yes}]{1,#{w}})", :extract_plain ] # %i when /%\*?i/ [ "([-+]?(?:(?:0[0-7]+)|(?:0[Xx]#{h}+)|(?:[1-9]\\d*)))", :extract_integer ] # %5i when /%\*?(\d+)i/ n = $1.to_i s = "(" if n > 1 then s += "[1-9]\\d{1,#{n-1}}|" end if n > 1 then s += "0[0-7]{1,#{n-1}}|" end if n > 2 then s += "[-+]0[0-7]{1,#{n-2}}|" end if n > 2 then s += "[-+][1-9]\\d{1,#{n-2}}|" end if n > 2 then s += "0[Xx]#{h}{1,#{n-2}}|" end if n > 3 then s += "[-+]0[Xx]#{h}{1,#{n-3}}|" end s += "\\d" s += ")" [ s, :extract_integer ] # %d, %u when /%\*?[du]/ [ '([-+]?\d+)', :extract_decimal ] # %5d, %5u when /%\*?(\d+)[du]/ n = $1.to_i s = "(" if n > 1 then s += "[-+]\\d{1,#{n-1}}|" end s += "\\d{1,#{$1}})" [ s, :extract_decimal ] # %x when /%\*?[Xx]/ [ "([-+]?(?:0[Xx])?#{h}+)", :extract_hex ] # %5x when /%\*?(\d+)[Xx]/ n = $1.to_i s = "(" if n > 3 then s += "[-+]0[Xx]#{h}{1,#{n-3}}|" end if n > 2 then s += "0[Xx]#{h}{1,#{n-2}}|" end if n > 1 then s += "[-+]#{h}{1,#{n-1}}|" end s += "#{h}{1,#{n}}" s += ")" [ s, :extract_hex ] # %o when /%\*?o/ [ '([-+]?[0-7]+)', :extract_octal ] # %5o when /%\*?(\d+)o/ [ "([-+][0-7]{1,#{$1.to_i-1}}|[0-7]{1,#{$1}})", :extract_octal ] # %f when /%\*?[aefgAEFG]/ [ '([-+]?(?:0[xX](?:\.\h+|\h+(?:\.\h*)?)[pP][-+]\d+|\d+(?![\d.])|\d*\.\d*(?:[eE][-+]?\d+)?))', :extract_float ] # %5f when /%\*?(\d+)[aefgAEFG]/ [ '(?=[-+]?(?:0[xX](?:\.\h+|\h+(?:\.\h*)?)[pP][-+]\d+|\d+(?![\d.])|\d*\.\d*(?:[eE][-+]?\d+)?))' + "(\\S{1,#{$1}})", :extract_float ] # %5s when /%\*?(\d+)s/ [ "(\\S{1,#{$1}})", :extract_plain ] # %s when /%\*?s/ [ '(\S+)', :extract_plain ] # %c when /\s%\*?c/ [ "\\s*(.)", :extract_plain ] # %c when /%\*?c/ [ "(.)", :extract_plain ] # %5c (whitespace issues are handled by the count_*_space? methods) when /%\*?(\d+)c/ [ "(.{1,#{$1}})", :extract_plain ] # %% when /%%/ [ '(\s*%)', :nil_proc ] # literal characters else [ "(#{Regexp.escape(@spec_string)})", :nil_proc ] end @re_string = '\A' + @re_string end def to_re Regexp.new(@re_string,Regexp::MULTILINE) end def match(str) @matched = false s = str.dup s.sub!(/\A\s+/,'') unless count_space? res = to_re.match(s) if res @conversion = send(@handler, res[1]) @matched_string = @conversion.to_s @matched = true end res end def letter @spec_string[/%\*?\d*([a-z\[])/, 1] end def width w = @spec_string[/%\*?(\d+)/, 1] w && w.to_i end def mid_match? return false unless @matched cc_no_width = letter == '[' &&! width c_or_cc_width = (letter == 'c' || letter == '[') && width width_left = c_or_cc_width && (matched_string.size < width) return width_left || cc_no_width end end class FormatString attr_reader :string_left, :last_spec_tried, :last_match_tried, :matched_count, :space SPECIFIERS = 'diuXxofFeEgGscaA' REGEX = / # possible space, followed by... (?:\s* # percent sign, followed by... % # another percent sign, or... (?:%| # optional assignment suppression flag \*? # optional maximum field width \d* # named character class, ... (?:\[\[:\w+:\]\]| # traditional character class, or... \[[^\]]*\]| # specifier letter. [#{SPECIFIERS}])))| # or miscellaneous characters [^%\s]+/ix def initialize(str) @specs = [] @i = 1 s = str.to_s return unless /\S/.match(s) @space = true if /\s\z/.match(s) @specs.replace s.scan(REGEX).map {|spec| FormatSpecifier.new(spec) } end def to_s @specs.join('') end def prune(n=matched_count) n.times { @specs.shift } end def spec_count @specs.size end def last_spec @i == spec_count - 1 end def match(str) accum = [] @string_left = str @matched_count = 0 @specs.each_with_index do |spec,i| @i=i @last_spec_tried = spec @last_match_tried = spec.match(@string_left) break unless @last_match_tried @matched_count += 1 accum << spec.conversion @string_left = @last_match_tried.post_match break if @string_left.empty? end return accum.compact end end # :startdoc: end class IO #:stopdoc: # The trick here is doing a match where you grab one *line* # of input at a time. The linebreak may or may not occur # at the boundary where the string matches a format specifier. # And if it does, some rule about whitespace may or may not # be in effect... # # That's why this is much more elaborate than the string # version. # # For each line: # # Match succeeds (non-emptily) # and the last attempted spec/string sub-match succeeded: # # could the last spec keep matching? # yes: save interim results and continue (next line) # # The last attempted spec/string did not match: # # are we on the next-to-last spec in the string? # yes: # is fmt_string.string_left all spaces? # yes: does current spec care about input space? # yes: fatal failure # no: save interim results and continue # no: continue [this state could be analyzed further] # #:startdoc: # Scans the current string until the match is exhausted, # yielding each match as it is encountered in the string. # A block is not necessary though, as the results will simply # be aggregated into the final array. # # "123 456".block_scanf("%d") # # => [123, 456] # # If a block is given, the value from that is returned from # the yield is added to an output array. # # "123 456".block_scanf("%d") do |digit,| # the ',' unpacks the Array # digit + 100 # end # # => [223, 556] # # See Scanf for details on creating a format string. # # You will need to require 'scanf' to use use IO#scanf. def scanf(str,&b) #:yield: current_match return block_scanf(str,&b) if b return [] unless str.size > 0 start_position = pos rescue 0 matched_so_far = 0 source_buffer = "" result_buffer = [] final_result = [] fstr = Scanf::FormatString.new(str) loop do if eof || (tty? &&! fstr.match(source_buffer)) final_result.concat(result_buffer) break end source_buffer << gets current_match = fstr.match(source_buffer) spec = fstr.last_spec_tried if spec.matched if spec.mid_match? result_buffer.replace(current_match) next end elsif (fstr.matched_count == fstr.spec_count - 1) if /\A\s*\z/.match(fstr.string_left) break if spec.count_space? result_buffer.replace(current_match) next end end final_result.concat(current_match) matched_so_far += source_buffer.size source_buffer.replace(fstr.string_left) matched_so_far -= source_buffer.size break if fstr.last_spec fstr.prune end begin seek(start_position + matched_so_far, IO::SEEK_SET) rescue Errno::ESPIPE end soak_up_spaces if fstr.last_spec && fstr.space return final_result end private def soak_up_spaces c = getc ungetc(c) if c until eof ||! c || /\S/.match(c.chr) c = getc end ungetc(c) if (c && /\S/.match(c.chr)) end def block_scanf(str) final = [] # Sub-ideal, since another FS gets created in scanf. # But used here to determine the number of specifiers. fstr = Scanf::FormatString.new(str) last_spec = fstr.last_spec begin current = scanf(str) break if current.empty? final.push(yield(current)) end until eof || fstr.last_spec_tried == last_spec return final end end class String # :section: scanf # # You will need to require 'scanf' to use these methods # Scans the current string. If a block is given, it # functions exactly like block_scanf. # # arr = "123 456".scanf("%d%d") # # => [123, 456] # # require 'pp' # # "this 123 read that 456 other".scanf("%s%d%s") {|m| pp m} # # # ["this", 123, "read"] # # ["that", 456, "other"] # # => [["this", 123, "read"], ["that", 456, "other"]] # # See Scanf for details on creating a format string. # # You will need to require 'scanf' to use String#scanf def scanf(fstr,&b) #:yield: current_match if b block_scanf(fstr,&b) else fs = if fstr.is_a? Scanf::FormatString fstr else Scanf::FormatString.new(fstr) end fs.match(self) end end # Scans the current string until the match is exhausted # yielding each match as it is encountered in the string. # A block is not necessary as the results will simply # be aggregated into the final array. # # "123 456".block_scanf("%d") # # => [123, 456] # # If a block is given, the value from that is returned from # the yield is added to an output array. # # "123 456".block_scanf("%d) do |digit,| # the ',' unpacks the Array # digit + 100 # end # # => [223, 556] # # See Scanf for details on creating a format string. # # You will need to require 'scanf' to use String#block_scanf def block_scanf(fstr) #:yield: current_match fs = Scanf::FormatString.new(fstr) str = self.dup final = [] begin current = str.scanf(fs) final.push(yield(current)) unless current.empty? str = fs.string_left end until current.empty? || str.empty? return final end end module Kernel private # Scans STDIN for data matching +format+. See IO#scanf for details. # # See Scanf for details on creating a format string. # # You will need to require 'scanf' to use Kernel#scanf. def scanf(format, &b) #:doc: STDIN.scanf(format ,&b) end end PK!k?2.2.0/irb/version.rbnu[# # irb/version.rb - irb version definition file # $Release Version: 0.9.6$ # $Revision: 38358 $ # by Keiju ISHITSUKA(keiju@ishitsuka.com) # # -- # # # module IRB # :nodoc: @RELEASE_VERSION = "0.9.6" @LAST_UPDATE_DATE = "09/06/30" end PK! sߦ 2.2.0/irb/output-method.rbnu[# # output-method.rb - output methods used by irb # $Release Version: 0.9.6$ # $Revision: 47120 $ # by Keiju ISHITSUKA(keiju@ruby-lang.org) # # -- # # # require "e2mmap" module IRB # An abstract output class for IO in irb. This is mainly used internally by # IRB::Notifier. You can define your own output method to use with Irb.new, # or Context.new class OutputMethod extend Exception2MessageMapper def_exception :NotImplementedError, "Need to define `%s'" # Open this method to implement your own output method, raises a # NotImplementedError if you don't define #print in your own class. def print(*opts) OutputMethod.Raise NotImplementedError, "print" end # Prints the given +opts+, with a newline delimiter. def printn(*opts) print opts.join(" "), "\n" end # Extends IO#printf to format the given +opts+ for Kernel#sprintf using # #parse_printf_format def printf(format, *opts) if /(%*)%I/ =~ format format, opts = parse_printf_format(format, opts) end print sprintf(format, *opts) end # Returns an array of the given +format+ and +opts+ to be used by # Kernel#sprintf, if there was a successful Regexp match in the given # +format+ from #printf # # % # [#0- +] # (\*|\*[1-9][0-9]*\$|[1-9][0-9]*) # .(\*|\*[1-9][0-9]*\$|[1-9][0-9]*|)? # #(hh|h|l|ll|L|q|j|z|t) # [diouxXeEfgGcsb%] def parse_printf_format(format, opts) return format, opts if $1.size % 2 == 1 end # Calls #print on each element in the given +objs+, followed by a newline # character. def puts(*objs) for obj in objs print(*obj) print "\n" end end # Prints the given +objs+ calling Object#inspect on each. # # See #puts for more detail. def pp(*objs) puts(*objs.collect{|obj| obj.inspect}) end # Prints the given +objs+ calling Object#inspect on each and appending the # given +prefix+. # # See #puts for more detail. def ppx(prefix, *objs) puts(*objs.collect{|obj| prefix+obj.inspect}) end end # A standard output printer class StdioOutputMethod { :PROMPT_I => nil, :PROMPT_N => nil, :PROMPT_S => nil, :PROMPT_C => nil, :RETURN => "%s\n" }, :DEFAULT => { :PROMPT_I => "%N(%m):%03n:%i> ", :PROMPT_N => "%N(%m):%03n:%i> ", :PROMPT_S => "%N(%m):%03n:%i%l ", :PROMPT_C => "%N(%m):%03n:%i* ", :RETURN => "=> %s\n" }, :CLASSIC => { :PROMPT_I => "%N(%m):%03n:%i> ", :PROMPT_N => "%N(%m):%03n:%i> ", :PROMPT_S => "%N(%m):%03n:%i%l ", :PROMPT_C => "%N(%m):%03n:%i* ", :RETURN => "%s\n" }, :SIMPLE => { :PROMPT_I => ">> ", :PROMPT_N => ">> ", :PROMPT_S => nil, :PROMPT_C => "?> ", :RETURN => "=> %s\n" }, :INF_RUBY => { :PROMPT_I => "%N(%m):%03n:%i> ", :PROMPT_N => nil, :PROMPT_S => nil, :PROMPT_C => nil, :RETURN => "%s\n", :AUTO_INDENT => true }, :XMP => { :PROMPT_I => nil, :PROMPT_N => nil, :PROMPT_S => nil, :PROMPT_C => nil, :RETURN => " ==>%s\n" } } @CONF[:PROMPT_MODE] = (STDIN.tty? ? :DEFAULT : :NULL) @CONF[:AUTO_INDENT] = false @CONF[:CONTEXT_MODE] = 3 # use binding in function on TOPLEVEL_BINDING @CONF[:SINGLE_IRB] = false @CONF[:LC_MESSAGES] = Locale.new @CONF[:AT_EXIT] = [] @CONF[:DEBUG_LEVEL] = 0 end def IRB.init_error @CONF[:LC_MESSAGES].load("irb/error.rb") end # option analyzing def IRB.parse_opts load_path = [] while opt = ARGV.shift case opt when "-f" @CONF[:RC] = false when "-m" @CONF[:MATH_MODE] = true when "-d" $DEBUG = true $VERBOSE = true when "-w" $VERBOSE = true when /^-W(.+)?/ opt = $1 || ARGV.shift case opt when "0" $VERBOSE = nil when "1" $VERBOSE = false else $VERBOSE = true end when /^-r(.+)?/ opt = $1 || ARGV.shift @CONF[:LOAD_MODULES].push opt if opt when /^-I(.+)?/ opt = $1 || ARGV.shift load_path.concat(opt.split(File::PATH_SEPARATOR)) if opt when '-U' set_encoding("UTF-8", "UTF-8") when /^-E(.+)?/, /^--encoding(?:=(.+))?/ opt = $1 || ARGV.shift set_encoding(*opt.split(':', 2)) when "--inspect" if /^-/ !~ ARGV.first @CONF[:INSPECT_MODE] = ARGV.shift else @CONF[:INSPECT_MODE] = true end when "--noinspect" @CONF[:INSPECT_MODE] = false when "--readline" @CONF[:USE_READLINE] = true when "--noreadline" @CONF[:USE_READLINE] = false when "--echo" @CONF[:ECHO] = true when "--noecho" @CONF[:ECHO] = false when "--verbose" @CONF[:VERBOSE] = true when "--noverbose" @CONF[:VERBOSE] = false when /^--prompt-mode(?:=(.+))?/, /^--prompt(?:=(.+))?/ opt = $1 || ARGV.shift prompt_mode = opt.upcase.tr("-", "_").intern @CONF[:PROMPT_MODE] = prompt_mode when "--noprompt" @CONF[:PROMPT_MODE] = :NULL when "--inf-ruby-mode" @CONF[:PROMPT_MODE] = :INF_RUBY when "--sample-book-mode", "--simple-prompt" @CONF[:PROMPT_MODE] = :SIMPLE when "--tracer" @CONF[:USE_TRACER] = true when /^--back-trace-limit(?:=(.+))?/ @CONF[:BACK_TRACE_LIMIT] = ($1 || ARGV.shift).to_i when /^--context-mode(?:=(.+))?/ @CONF[:CONTEXT_MODE] = ($1 || ARGV.shift).to_i when "--single-irb" @CONF[:SINGLE_IRB] = true when /^--irb_debug(?:=(.+))?/ @CONF[:DEBUG_LEVEL] = ($1 || ARGV.shift).to_i when "-v", "--version" print IRB.version, "\n" exit 0 when "-h", "--help" require "irb/help" IRB.print_usage exit 0 when "--" if opt = ARGV.shift @CONF[:SCRIPT] = opt $0 = opt end break when /^-/ IRB.fail UnrecognizedSwitch, opt else @CONF[:SCRIPT] = opt $0 = opt break end end load_path.collect! do |path| /\A\.\// =~ path ? path : File.expand_path(path) end $LOAD_PATH.unshift(*load_path) end # running config def IRB.run_config if @CONF[:RC] begin load rc_file rescue LoadError, Errno::ENOENT rescue # StandardError, ScriptError print "load error: #{rc_file}\n" print $!.class, ": ", $!, "\n" for err in $@[0, $@.size - 2] print "\t", err, "\n" end end end end IRBRC_EXT = "rc" def IRB.rc_file(ext = IRBRC_EXT) if !@CONF[:RC_NAME_GENERATOR] rc_file_generators do |rcgen| @CONF[:RC_NAME_GENERATOR] ||= rcgen if File.exist?(rcgen.call(IRBRC_EXT)) @CONF[:RC_NAME_GENERATOR] = rcgen break end end end case rc_file = @CONF[:RC_NAME_GENERATOR].call(ext) when String return rc_file else IRB.fail IllegalRCNameGenerator end end # enumerate possible rc-file base name generators def IRB.rc_file_generators if irbrc = ENV["IRBRC"] yield proc{|rc| rc == "rc" ? irbrc : irbrc+rc} end if home = ENV["HOME"] yield proc{|rc| home+"/.irb#{rc}"} end home = Dir.pwd yield proc{|rc| home+"/.irb#{rc}"} yield proc{|rc| home+"/irb#{rc.sub(/\A_?/, '.')}"} yield proc{|rc| home+"/_irb#{rc}"} yield proc{|rc| home+"/$irb#{rc}"} end # loading modules def IRB.load_modules for m in @CONF[:LOAD_MODULES] begin require m rescue LoadError => err warn err.backtrace[0] << ":#{err.class}: #{err}" end end end DefaultEncodings = Struct.new(:external, :internal) class << IRB private def set_encoding(extern, intern = nil) verbose, $VERBOSE = $VERBOSE, nil Encoding.default_external = extern unless extern.nil? || extern.empty? Encoding.default_internal = intern unless intern.nil? || intern.empty? @CONF[:ENCODINGS] = IRB::DefaultEncodings.new(extern, intern) [$stdin, $stdout, $stderr].each do |io| io.set_encoding(extern, intern) end @CONF[:LC_MESSAGES].instance_variable_set(:@encoding, extern) ensure $VERBOSE = verbose end end end PK!HOO2.2.0/irb/inspector.rbnu[# # irb/inspector.rb - inspect methods # $Release Version: 0.9.6$ # $Revision: 1.19 $ # $Date: 2002/06/11 07:51:31 $ # by Keiju ISHITSUKA(keiju@ruby-lang.org) # # -- # # # module IRB # :nodoc: # Convenience method to create a new Inspector, using the given +inspect+ # proc, and optional +init+ proc and passes them to Inspector.new # # irb(main):001:0> ins = IRB::Inspector(proc{ |v| "omg! #{v}" }) # irb(main):001:0> IRB.CurrentContext.inspect_mode = ins # => omg! # # irb(main):001:0> "what?" #=> omg! what? # def IRB::Inspector(inspect, init = nil) Inspector.new(inspect, init) end # An irb inspector # # In order to create your own custom inspector there are two things you # should be aware of: # # Inspector uses #inspect_value, or +inspect_proc+, for output of return values. # # This also allows for an optional #init+, or +init_proc+, which is called # when the inspector is activated. # # Knowing this, you can create a rudimentary inspector as follows: # # irb(main):001:0> ins = IRB::Inspector.new(proc{ |v| "omg! #{v}" }) # irb(main):001:0> IRB.CurrentContext.inspect_mode = ins # => omg! # # irb(main):001:0> "what?" #=> omg! what? # class Inspector # Default inspectors available to irb, this includes: # # +:pp+:: Using Kernel#pretty_inspect # +:yaml+:: Using YAML.dump # +:marshal+:: Using Marshal.dump INSPECTORS = {} # Determines the inspector to use where +inspector+ is one of the keys passed # during inspector definition. def self.keys_with_inspector(inspector) INSPECTORS.select{|k,v| v == inspector}.collect{|k, v| k} end # Example # # Inspector.def_inspector(key, init_p=nil){|v| v.inspect} # Inspector.def_inspector([key1,..], init_p=nil){|v| v.inspect} # Inspector.def_inspector(key, inspector) # Inspector.def_inspector([key1,...], inspector) def self.def_inspector(key, arg=nil, &block) if block_given? inspector = IRB::Inspector(block, arg) else inspector = arg end case key when Array for k in key def_inspector(k, inspector) end when Symbol INSPECTORS[key] = inspector INSPECTORS[key.to_s] = inspector when String INSPECTORS[key] = inspector INSPECTORS[key.intern] = inspector else INSPECTORS[key] = inspector end end # Creates a new inspector object, using the given +inspect_proc+ when # output return values in irb. def initialize(inspect_proc, init_proc = nil) @init = init_proc @inspect = inspect_proc end # Proc to call when the inspector is activated, good for requiring # dependent libraries. def init @init.call if @init end # Proc to call when the input is evaluated and output in irb. def inspect_value(v) @inspect.call(v) end end Inspector.def_inspector([false, :to_s, :raw]){|v| v.to_s} Inspector.def_inspector([true, :p, :inspect]){|v| begin v.inspect rescue NoMethodError puts "(Object doesn't support #inspect)" end } Inspector.def_inspector([:pp, :pretty_inspect], proc{require "pp"}){|v| v.pretty_inspect.chomp} Inspector.def_inspector([:yaml, :YAML], proc{require "yaml"}){|v| begin YAML.dump(v) rescue puts "(can't dump yaml. use inspect)" v.inspect end } Inspector.def_inspector([:marshal, :Marshal, :MARSHAL, Marshal]){|v| Marshal.dump(v) } end PK!`_X\\2.2.0/irb/ruby-token.rbnu[# # irb/ruby-token.rb - ruby tokens # $Release Version: 0.9.6$ # $Revision: 47298 $ # by Keiju ISHITSUKA(keiju@ruby-lang.org) # # -- # # # # :stopdoc: module RubyToken EXPR_BEG = :EXPR_BEG EXPR_MID = :EXPR_MID EXPR_END = :EXPR_END EXPR_ARG = :EXPR_ARG EXPR_FNAME = :EXPR_FNAME EXPR_DOT = :EXPR_DOT EXPR_CLASS = :EXPR_CLASS class Token def initialize(seek, line_no, char_no) @seek = seek @line_no = line_no @char_no = char_no end attr_reader :seek, :line_no, :char_no end class TkNode < Token def initialize(seek, line_no, char_no) super end attr_reader :node end class TkId < Token def initialize(seek, line_no, char_no, name) super(seek, line_no, char_no) @name = name end attr_reader :name end class TkVal < Token def initialize(seek, line_no, char_no, value = nil) super(seek, line_no, char_no) @value = value end attr_reader :value end class TkOp < Token attr_accessor :name end class TkOPASGN < TkOp def initialize(seek, line_no, char_no, op) super(seek, line_no, char_no) op = TkReading2Token[op][0] unless op.kind_of?(Symbol) @op = op end attr_reader :op end class TkUnknownChar < Token def initialize(seek, line_no, char_no, id) super(seek, line_no, char_no) @name = name end attr_reader :name end class TkError < Token end def Token(token, value = nil) case token when String if (tk = TkReading2Token[token]).nil? IRB.fail TkReading2TokenNoKey, token end tk = Token(tk[0], value) if tk.kind_of?(TkOp) tk.name = token end return tk when Symbol if (tk = TkSymbol2Token[token]).nil? IRB.fail TkSymbol2TokenNoKey, token end return Token(tk[0], value) else if (token.ancestors & [TkId, TkVal, TkOPASGN, TkUnknownChar]).empty? token.new(@prev_seek, @prev_line_no, @prev_char_no) else token.new(@prev_seek, @prev_line_no, @prev_char_no, value) end end end TokenDefinitions = [ [:TkCLASS, TkId, "class", EXPR_CLASS], [:TkMODULE, TkId, "module", EXPR_BEG], [:TkDEF, TkId, "def", EXPR_FNAME], [:TkUNDEF, TkId, "undef", EXPR_FNAME], [:TkBEGIN, TkId, "begin", EXPR_BEG], [:TkRESCUE, TkId, "rescue", EXPR_MID], [:TkENSURE, TkId, "ensure", EXPR_BEG], [:TkEND, TkId, "end", EXPR_END], [:TkIF, TkId, "if", EXPR_BEG, :TkIF_MOD], [:TkUNLESS, TkId, "unless", EXPR_BEG, :TkUNLESS_MOD], [:TkTHEN, TkId, "then", EXPR_BEG], [:TkELSIF, TkId, "elsif", EXPR_BEG], [:TkELSE, TkId, "else", EXPR_BEG], [:TkCASE, TkId, "case", EXPR_BEG], [:TkWHEN, TkId, "when", EXPR_BEG], [:TkWHILE, TkId, "while", EXPR_BEG, :TkWHILE_MOD], [:TkUNTIL, TkId, "until", EXPR_BEG, :TkUNTIL_MOD], [:TkFOR, TkId, "for", EXPR_BEG], [:TkBREAK, TkId, "break", EXPR_END], [:TkNEXT, TkId, "next", EXPR_END], [:TkREDO, TkId, "redo", EXPR_END], [:TkRETRY, TkId, "retry", EXPR_END], [:TkIN, TkId, "in", EXPR_BEG], [:TkDO, TkId, "do", EXPR_BEG], [:TkRETURN, TkId, "return", EXPR_MID], [:TkYIELD, TkId, "yield", EXPR_END], [:TkSUPER, TkId, "super", EXPR_END], [:TkSELF, TkId, "self", EXPR_END], [:TkNIL, TkId, "nil", EXPR_END], [:TkTRUE, TkId, "true", EXPR_END], [:TkFALSE, TkId, "false", EXPR_END], [:TkAND, TkId, "and", EXPR_BEG], [:TkOR, TkId, "or", EXPR_BEG], [:TkNOT, TkId, "not", EXPR_BEG], [:TkIF_MOD, TkId], [:TkUNLESS_MOD, TkId], [:TkWHILE_MOD, TkId], [:TkUNTIL_MOD, TkId], [:TkALIAS, TkId, "alias", EXPR_FNAME], [:TkDEFINED, TkId, "defined?", EXPR_END], [:TklBEGIN, TkId, "BEGIN", EXPR_END], [:TklEND, TkId, "END", EXPR_END], [:Tk__LINE__, TkId, "__LINE__", EXPR_END], [:Tk__FILE__, TkId, "__FILE__", EXPR_END], [:TkIDENTIFIER, TkId], [:TkFID, TkId], [:TkGVAR, TkId], [:TkCVAR, TkId], [:TkIVAR, TkId], [:TkCONSTANT, TkId], [:TkINTEGER, TkVal], [:TkFLOAT, TkVal], [:TkSTRING, TkVal], [:TkXSTRING, TkVal], [:TkREGEXP, TkVal], [:TkSYMBOL, TkVal], [:TkDSTRING, TkNode], [:TkDXSTRING, TkNode], [:TkDREGEXP, TkNode], [:TkNTH_REF, TkNode], [:TkBACK_REF, TkNode], [:TkUPLUS, TkOp, "+@"], [:TkUMINUS, TkOp, "-@"], [:TkPOW, TkOp, "**"], [:TkCMP, TkOp, "<=>"], [:TkEQ, TkOp, "=="], [:TkEQQ, TkOp, "==="], [:TkNEQ, TkOp, "!="], [:TkGEQ, TkOp, ">="], [:TkLEQ, TkOp, "<="], [:TkANDOP, TkOp, "&&"], [:TkOROP, TkOp, "||"], [:TkMATCH, TkOp, "=~"], [:TkNMATCH, TkOp, "!~"], [:TkDOT2, TkOp, ".."], [:TkDOT3, TkOp, "..."], [:TkAREF, TkOp, "[]"], [:TkASET, TkOp, "[]="], [:TkLSHFT, TkOp, "<<"], [:TkRSHFT, TkOp, ">>"], [:TkCOLON2, TkOp], [:TkCOLON3, TkOp], [:TkASSOC, TkOp, "=>"], [:TkQUESTION, TkOp, "?"], #? [:TkCOLON, TkOp, ":"], #: [:TkfLPAREN], # func( # [:TkfLBRACK], # func[ # [:TkfLBRACE], # func{ # [:TkSTAR], # *arg [:TkAMPER], # &arg # [:TkSYMBEG], # :SYMBOL [:TkGT, TkOp, ">"], [:TkLT, TkOp, "<"], [:TkPLUS, TkOp, "+"], [:TkMINUS, TkOp, "-"], [:TkMULT, TkOp, "*"], [:TkDIV, TkOp, "/"], [:TkMOD, TkOp, "%"], [:TkBITOR, TkOp, "|"], [:TkBITXOR, TkOp, "^"], [:TkBITAND, TkOp, "&"], [:TkBITNOT, TkOp, "~"], [:TkNOTOP, TkOp, "!"], [:TkBACKQUOTE, TkOp, "`"], [:TkASSIGN, Token, "="], [:TkDOT, Token, "."], [:TkLPAREN, Token, "("], #(exp) [:TkLBRACK, Token, "["], #[arry] [:TkLBRACE, Token, "{"], #{hash} [:TkRPAREN, Token, ")"], [:TkRBRACK, Token, "]"], [:TkRBRACE, Token, "}"], [:TkCOMMA, Token, ","], [:TkSEMICOLON, Token, ";"], [:TkCOMMENT], [:TkRD_COMMENT], [:TkSPACE], [:TkNL], [:TkEND_OF_SCRIPT], [:TkBACKSLASH, TkUnknownChar, "\\"], [:TkAT, TkUnknownChar, "@"], [:TkDOLLAR, TkUnknownChar, "$"], ] # {reading => token_class} # {reading => [token_class, *opt]} TkReading2Token = {} TkSymbol2Token = {} def RubyToken.def_token(token_n, super_token = Token, reading = nil, *opts) token_n = token_n.id2name if token_n.kind_of?(Symbol) if RubyToken.const_defined?(token_n) IRB.fail AlreadyDefinedToken, token_n end token_c = eval("class #{token_n} < #{super_token}; end; #{token_n}") if reading if TkReading2Token[reading] IRB.fail TkReading2TokenDuplicateError, token_n, reading end if opts.empty? TkReading2Token[reading] = [token_c] else TkReading2Token[reading] = [token_c].concat(opts) end end TkSymbol2Token[token_n.intern] = token_c end for defs in TokenDefinitions def_token(*defs) end end # :startdoc: PK!+  2.2.0/irb/cmd/nop.rbnu[# # nop.rb - # $Release Version: 0.9.6$ # $Revision: 47266 $ # by Keiju ISHITSUKA(keiju@ruby-lang.org) # # -- # # # # :stopdoc: module IRB module ExtendCommand class Nop def self.execute(conf, *opts) command = new(conf) command.execute(*opts) end def initialize(conf) @irb_context = conf end attr_reader :irb_context def irb @irb_context.irb end def execute(*opts) #nop end end end end # :startdoc: PK!2.2.0/irb/cmd/pushws.rbnu[# # change-ws.rb - # $Release Version: 0.9.6$ # $Revision: 47112 $ # by Keiju ISHITSUKA(keiju@ruby-lang.org) # # -- # # # require "irb/cmd/nop.rb" require "irb/ext/workspaces.rb" # :stopdoc: module IRB module ExtendCommand class WorkspacesIRB.conf[:AP_NAME] attr_accessor :ap_name # A copy of the default IRB.conf[:RC] attr_accessor :rc # A copy of the default IRB.conf[:LOAD_MODULES] attr_accessor :load_modules # Can be either name from IRB.conf[:IRB_NAME], or the number of # the current job set by JobManager, such as irb#2 attr_accessor :irb_name # Can be either the #irb_name surrounded by parenthesis, or the # +input_method+ passed to Context.new attr_accessor :irb_path # Whether +Readline+ is enabled or not. # # A copy of the default IRB.conf[:USE_READLINE] # # See #use_readline= for more information. attr_reader :use_readline # A copy of the default IRB.conf[:INSPECT_MODE] attr_reader :inspect_mode # A copy of the default IRB.conf[:PROMPT_MODE] attr_reader :prompt_mode # Standard IRB prompt # # See IRB@Customizing+the+IRB+Prompt for more information. attr_accessor :prompt_i # IRB prompt for continuated strings # # See IRB@Customizing+the+IRB+Prompt for more information. attr_accessor :prompt_s # IRB prompt for continuated statement (e.g. immediately after an +if+) # # See IRB@Customizing+the+IRB+Prompt for more information. attr_accessor :prompt_c # See IRB@Customizing+the+IRB+Prompt for more information. attr_accessor :prompt_n # Can be either the default IRB.conf[:AUTO_INDENT], or the # mode set by #prompt_mode= # # To enable auto-indentation in irb: # # IRB.conf[:AUTO_INDENT] = true # # or # # irb_context.auto_indent_mode = true # # or # # IRB.CurrentContext.auto_indent_mode = true # # See IRB@Configuration for more information. attr_accessor :auto_indent_mode # The format of the return statement, set by #prompt_mode= using the # +:RETURN+ of the +mode+ passed to set the current #prompt_mode. attr_accessor :return_format # Whether ^C (+control-c+) will be ignored or not. # # If set to +false+, ^C will quit irb. # # If set to +true+, # # * during input: cancel input then return to top level. # * during execute: abandon current execution. attr_accessor :ignore_sigint # Whether ^D (+control-d+) will be ignored or not. # # If set to +false+, ^D will quit irb. attr_accessor :ignore_eof # Whether to echo the return value to output or not. # # Uses IRB.conf[:ECHO] if available, or defaults to +true+. # # puts "hello" # # hello # #=> nil # IRB.CurrentContext.echo = false # puts "omg" # # omg attr_accessor :echo # Whether verbose messages are displayed or not. # # A copy of the default IRB.conf[:VERBOSE] attr_accessor :verbose # The debug level of irb # # See #debug_level= for more information. attr_reader :debug_level # The limit of backtrace lines displayed as top +n+ and tail +n+. # # The default value is 16. # # Can also be set using the +--back-trace-limit+ command line option. # # See IRB@Command+line+options for more command line options. attr_accessor :back_trace_limit # Alias for #use_readline alias use_readline? use_readline # Alias for #rc alias rc? rc alias ignore_sigint? ignore_sigint alias ignore_eof? ignore_eof alias echo? echo # Returns whether messages are displayed or not. def verbose? if @verbose.nil? if defined?(ReadlineInputMethod) && @io.kind_of?(ReadlineInputMethod) false elsif !STDIN.tty? or @io.kind_of?(FileInputMethod) true else false end else @verbose end end # Whether #verbose? is +true+, and +input_method+ is either # StdioInputMethod or ReadlineInputMethod, see #io for more information. def prompting? verbose? || (STDIN.tty? && @io.kind_of?(StdioInputMethod) || (defined?(ReadlineInputMethod) && @io.kind_of?(ReadlineInputMethod))) end # The return value of the last statement evaluated. attr_reader :last_value # Sets the return value from the last statement evaluated in this context # to #last_value. def set_last_value(value) @last_value = value @workspace.evaluate self, "_ = IRB.CurrentContext.last_value" end # Sets the +mode+ of the prompt in this context. # # See IRB@Customizing+the+IRB+Prompt for more information. def prompt_mode=(mode) @prompt_mode = mode pconf = IRB.conf[:PROMPT][mode] @prompt_i = pconf[:PROMPT_I] @prompt_s = pconf[:PROMPT_S] @prompt_c = pconf[:PROMPT_C] @prompt_n = pconf[:PROMPT_N] @return_format = pconf[:RETURN] if ai = pconf.include?(:AUTO_INDENT) @auto_indent_mode = ai else @auto_indent_mode = IRB.conf[:AUTO_INDENT] end end # Whether #inspect_mode is set or not, see #inspect_mode= for more detail. def inspect? @inspect_mode.nil? or @inspect_mode end # Whether #io uses a File for the +input_method+ passed when creating the # current context, see ::new def file_input? @io.class == FileInputMethod end # Specifies the inspect mode with +opt+: # # +true+:: display +inspect+ # +false+:: display +to_s+ # +nil+:: inspect mode in non-math mode, # non-inspect mode in math mode # # See IRB::Inspector for more information. # # Can also be set using the +--inspect+ and +--noinspect+ command line # options. # # See IRB@Command+line+options for more command line options. def inspect_mode=(opt) if i = Inspector::INSPECTORS[opt] @inspect_mode = opt @inspect_method = i i.init else case opt when nil if Inspector.keys_with_inspector(Inspector::INSPECTORS[true]).include?(@inspect_mode) self.inspect_mode = false elsif Inspector.keys_with_inspector(Inspector::INSPECTORS[false]).include?(@inspect_mode) self.inspect_mode = true else puts "Can't switch inspect mode." return end when /^\s*\{.*\}\s*$/ begin inspector = eval "proc#{opt}" rescue Exception puts "Can't switch inspect mode(#{opt})." return end self.inspect_mode = inspector when Proc self.inspect_mode = IRB::Inspector(opt) when Inspector prefix = "usr%d" i = 1 while Inspector::INSPECTORS[format(prefix, i)]; i += 1; end @inspect_mode = format(prefix, i) @inspect_method = opt Inspector.def_inspector(format(prefix, i), @inspect_method) else puts "Can't switch inspect mode(#{opt})." return end end print "Switch to#{unless @inspect_mode; ' non';end} inspect mode.\n" if verbose? @inspect_mode end # Obsolete method. # # Can be set using the +--noreadline+ and +--readline+ command line # options. # # See IRB@Command+line+options for more command line options. def use_readline=(opt) print "This method is obsolete." print "Do nothing." end # Sets the debug level of irb # # Can also be set using the +--irb_debug+ command line option. # # See IRB@Command+line+options for more command line options. def debug_level=(value) @debug_level = value RubyLex.debug_level = value end # Whether or not debug mode is enabled, see #debug_level=. def debug? @debug_level > 0 end def evaluate(line, line_no) # :nodoc: @line_no = line_no set_last_value(@workspace.evaluate(self, line, irb_path, line_no)) end def inspect_last_value # :nodoc: @inspect_method.inspect_value(@last_value) end alias __exit__ exit # Exits the current session, see IRB.irb_exit def exit(ret = 0) IRB.irb_exit(@irb, ret) end NOPRINTING_IVARS = ["@last_value"] # :nodoc: NO_INSPECTING_IVARS = ["@irb", "@io"] # :nodoc: IDNAME_IVARS = ["@prompt_mode"] # :nodoc: alias __inspect__ inspect def inspect # :nodoc: array = [] for ivar in instance_variables.sort{|e1, e2| e1 <=> e2} ivar = ivar.to_s name = ivar.sub(/^@(.*)$/, '\1') val = instance_eval(ivar) case ivar when *NOPRINTING_IVARS array.push format("conf.%s=%s", name, "...") when *NO_INSPECTING_IVARS array.push format("conf.%s=%s", name, val.to_s) when *IDNAME_IVARS array.push format("conf.%s=:%s", name, val.id2name) else array.push format("conf.%s=%s", name, val.inspect) end end array.join("\n") end alias __to_s__ to_s alias to_s inspect end end PK!ܼo7 7 2.2.0/irb/ext/save-history.rbnu[# save-history.rb - # $Release Version: 0.9.6$ # $Revision: 47266 $ # by Keiju ISHITSUKA(keiju@ruby-lang.org) # # -- # # # require "readline" module IRB module HistorySavingAbility # :nodoc: end class Context def init_save_history# :nodoc: unless (class<<@io;self;end).include?(HistorySavingAbility) @io.extend(HistorySavingAbility) end end # A copy of the default IRB.conf[:SAVE_HISTORY] def save_history IRB.conf[:SAVE_HISTORY] end # Sets IRB.conf[:SAVE_HISTORY] to the given +val+ and calls # #init_save_history with this context. # # Will store the number of +val+ entries of history in the #history_file # # Add the following to your +.irbrc+ to change the number of history # entries stored to 1000: # # IRB.conf[:SAVE_HISTORY] = 1000 def save_history=(val) IRB.conf[:SAVE_HISTORY] = val if val main_context = IRB.conf[:MAIN_CONTEXT] main_context = self unless main_context main_context.init_save_history end end # A copy of the default IRB.conf[:HISTORY_FILE] def history_file IRB.conf[:HISTORY_FILE] end # Set IRB.conf[:HISTORY_FILE] to the given +hist+. def history_file=(hist) IRB.conf[:HISTORY_FILE] = hist end end module HistorySavingAbility # :nodoc: include Readline def HistorySavingAbility.extended(obj) IRB.conf[:AT_EXIT].push proc{obj.save_history} obj.load_history obj end def load_history if history_file = IRB.conf[:HISTORY_FILE] history_file = File.expand_path(history_file) end history_file = IRB.rc_file("_history") unless history_file if File.exist?(history_file) open(history_file) do |f| f.each {|l| HISTORY << l.chomp} end end end def save_history if num = IRB.conf[:SAVE_HISTORY] and (num = num.to_i) > 0 if history_file = IRB.conf[:HISTORY_FILE] history_file = File.expand_path(history_file) end history_file = IRB.rc_file("_history") unless history_file # Change the permission of a file that already exists[BUG #7694] begin if File.stat(history_file).mode & 066 != 0 File.chmod(0600, history_file) end rescue Errno::ENOENT rescue raise end open(history_file, 'w', 0600 ) do |f| hist = HISTORY.to_a f.puts(hist[-num..-1] || hist) end end end end end PK!2.2.0/irb/ext/multi-irb.rbnu[# # irb/multi-irb.rb - multiple irb module # $Release Version: 0.9.6$ # $Revision: 47266 $ # by Keiju ISHITSUKA(keiju@ruby-lang.org) # # -- # # # IRB.fail CantShiftToMultiIrbMode unless defined?(Thread) require "thread" module IRB class JobManager # Creates a new JobManager object def initialize @jobs = [] @current_job = nil end # The active irb session attr_accessor :current_job # The total number of irb sessions, used to set +irb_name+ of the current # Context. def n_jobs @jobs.size end # Returns the thread for the given +key+ object, see #search for more # information. def thread(key) th, = search(key) th end # Returns the irb session for the given +key+ object, see #search for more # information. def irb(key) _, irb = search(key) irb end # Returns the top level thread. def main_thread @jobs[0][0] end # Returns the top level irb session. def main_irb @jobs[0][1] end # Add the given +irb+ session to the jobs Array. def insert(irb) @jobs.push [Thread.current, irb] end # Changes the current active irb session to the given +key+ in the jobs # Array. # # Raises an IrbAlreadyDead exception if the given +key+ is no longer alive. # # If the given irb session is already active, an IrbSwitchedToCurrentThread # exception is raised. def switch(key) th, irb = search(key) IRB.fail IrbAlreadyDead unless th.alive? IRB.fail IrbSwitchedToCurrentThread if th == Thread.current @current_job = irb th.run Thread.stop @current_job = irb(Thread.current) end # Terminates the irb sessions specified by the given +keys+. # # Raises an IrbAlreadyDead exception if one of the given +keys+ is already # terminated. # # See Thread#exit for more information. def kill(*keys) for key in keys th, _ = search(key) IRB.fail IrbAlreadyDead unless th.alive? th.exit end end # Returns the associated job for the given +key+. # # If given an Integer, it will return the +key+ index for the jobs Array. # # When an instance of Irb is given, it will return the irb session # associated with +key+. # # If given an instance of Thread, it will return the associated thread # +key+ using Object#=== on the jobs Array. # # Otherwise returns the irb session with the same top-level binding as the # given +key+. # # Raises a NoSuchJob exception if no job can be found with the given +key+. def search(key) job = case key when Integer @jobs[key] when Irb @jobs.find{|k, v| v.equal?(key)} when Thread @jobs.assoc(key) else @jobs.find{|k, v| v.context.main.equal?(key)} end IRB.fail NoSuchJob, key if job.nil? job end # Deletes the job at the given +key+. def delete(key) case key when Integer IRB.fail NoSuchJob, key unless @jobs[key] @jobs[key] = nil else catch(:EXISTS) do @jobs.each_index do |i| if @jobs[i] and (@jobs[i][0] == key || @jobs[i][1] == key || @jobs[i][1].context.main.equal?(key)) @jobs[i] = nil throw :EXISTS end end IRB.fail NoSuchJob, key end end until assoc = @jobs.pop; end unless @jobs.empty? @jobs.push assoc end # Outputs a list of jobs, see the irb command +irb_jobs+, or +jobs+. def inspect ary = [] @jobs.each_index do |i| th, irb = @jobs[i] next if th.nil? if th.alive? if th.stop? t_status = "stop" else t_status = "running" end else t_status = "exited" end ary.push format("#%d->%s on %s (%s: %s)", i, irb.context.irb_name, irb.context.main, th, t_status) end ary.join("\n") end end @JobManager = JobManager.new # The current JobManager in the session def IRB.JobManager @JobManager end # The current Context in this session def IRB.CurrentContext IRB.JobManager.irb(Thread.current).context end # Creates a new IRB session, see Irb.new. # # The optional +file+ argument is given to Context.new, along with the # workspace created with the remaining arguments, see WorkSpace.new def IRB.irb(file = nil, *main) workspace = WorkSpace.new(*main) parent_thread = Thread.current Thread.start do begin irb = Irb.new(workspace, file) rescue print "Subirb can't start with context(self): ", workspace.main.inspect, "\n" print "return to main irb\n" Thread.pass Thread.main.wakeup Thread.exit end @CONF[:IRB_RC].call(irb.context) if @CONF[:IRB_RC] @JobManager.insert(irb) @JobManager.current_job = irb begin system_exit = false catch(:IRB_EXIT) do irb.eval_input end rescue SystemExit system_exit = true raise #fail ensure unless system_exit @JobManager.delete(irb) if @JobManager.current_job == irb if parent_thread.alive? @JobManager.current_job = @JobManager.irb(parent_thread) parent_thread.run else @JobManager.current_job = @JobManager.main_irb @JobManager.main_thread.run end end end end end Thread.stop @JobManager.current_job = @JobManager.irb(Thread.current) end @CONF[:SINGLE_IRB_MODE] = false @JobManager.insert(@CONF[:MAIN_CONTEXT].irb) @JobManager.current_job = @CONF[:MAIN_CONTEXT].irb class Irb def signal_handle unless @context.ignore_sigint? print "\nabort!!\n" if @context.verbose? exit end case @signal_status when :IN_INPUT print "^C\n" IRB.JobManager.thread(self).raise RubyLex::TerminateLineInput when :IN_EVAL IRB.irb_abort(self) when :IN_LOAD IRB.irb_abort(self, LoadAbort) when :IN_IRB # ignore else # ignore other cases as well end end end trap("SIGINT") do @JobManager.current_job.signal_handle Thread.stop end end PK!T[2.2.0/irb/ext/change-ws.rbnu[# # irb/ext/cb.rb - # $Release Version: 0.9.6$ # $Revision: 47114 $ # by Keiju ISHITSUKA(keiju@ruby-lang.org) # # -- # # # module IRB # :nodoc: class Context # Inherited from +TOPLEVEL_BINDING+. def home_workspace if defined? @home_workspace @home_workspace else @home_workspace = @workspace end end # Changes the current workspace to given object or binding. # # If the optional argument is omitted, the workspace will be # #home_workspace which is inherited from +TOPLEVEL_BINDING+ or the main # object, IRB.conf[:MAIN_CONTEXT] when irb was initialized. # # See IRB::WorkSpace.new for more information. def change_workspace(*_main) if _main.empty? @workspace = home_workspace return main end @workspace = WorkSpace.new(_main[0]) if !(class<= 0 @contents.find{|no, val| no == idx}[1] else @contents[idx][1] end rescue NameError nil end end def push(no, val) @contents.push [no, val] @contents.shift if @size != 0 && @contents.size > @size end alias real_inspect inspect def inspect if @contents.empty? return real_inspect end unless (last = @contents.pop)[1].equal?(self) @contents.push last last = nil end str = @contents.collect{|no, val| if val.equal?(self) "#{no} ...self-history..." else "#{no} #{val.inspect}" end }.join("\n") if str == "" str = "Empty." end @contents.push last if last str end end end PK!fph׬2.2.0/irb/ext/tracer.rbnu[# # irb/lib/tracer.rb - # $Release Version: 0.9.6$ # $Revision: 47112 $ # by Keiju ISHITSUKA(keiju@ruby-lang.org) # # -- # # # require "tracer" module IRB # initialize tracing function def IRB.initialize_tracer Tracer.verbose = false Tracer.add_filter { |event, file, line, id, binding, *rests| /^#{Regexp.quote(@CONF[:IRB_LIB_PATH])}/ !~ file and File::basename(file) != "irb.rb" } end class Context # Whether Tracer is used when evaluating statements in this context. # # See +lib/tracer.rb+ for more information. attr_reader :use_tracer alias use_tracer? use_tracer # Sets whether or not to use the Tracer library when evaluating statements # in this context. # # See +lib/tracer.rb+ for more information. def use_tracer=(opt) if opt Tracer.set_get_line_procs(@irb_path) { |line_no, *rests| @io.line(line_no) } elsif !opt && @use_tracer Tracer.off end @use_tracer=opt end end class WorkSpace alias __evaluate__ evaluate # Evaluate the context of this workspace and use the Tracer library to # output the exact lines of code are being executed in chronological order. # # See +lib/tracer.rb+ for more information. def evaluate(context, statements, file = nil, line = nil) if context.use_tracer? && file != nil && line != nil Tracer.on begin __evaluate__(context, statements, file, line) ensure Tracer.off end else __evaluate__(context, statements, file || __FILE__, line || __LINE__) end end end IRB.initialize_tracer end PK!|2.2.0/irb/ext/use-loader.rbnu[# # use-loader.rb - # $Release Version: 0.9.6$ # $Revision: 47112 $ # by Keiju ISHITSUKA(keiju@ruby-lang.org) # # -- # # # require "irb/cmd/load" require "irb/ext/loader" class Object alias __original__load__IRB_use_loader__ load alias __original__require__IRB_use_loader__ require end module IRB module ExtendCommandBundle # Loads the given file similarly to Kernel#load, see IrbLoader#irb_load def irb_load(*opts, &b) ExtendCommand::Load.execute(irb_context, *opts, &b) end # Loads the given file similarly to Kernel#require def irb_require(*opts, &b) ExtendCommand::Require.execute(irb_context, *opts, &b) end end class Context IRB.conf[:USE_LOADER] = false # Returns whether +irb+'s own file reader method is used by # +load+/+require+ or not. # # This mode is globally affected (irb-wide). def use_loader IRB.conf[:USE_LOADER] end alias use_loader? use_loader # Sets IRB.conf[:USE_LOADER] # # See #use_loader for more information. def use_loader=(opt) if IRB.conf[:USE_LOADER] != opt IRB.conf[:USE_LOADER] = opt if opt if !$".include?("irb/cmd/load") end (class<<@workspace.main;self;end).instance_eval { alias_method :load, :irb_load alias_method :require, :irb_require } else (class<<@workspace.main;self;end).instance_eval { alias_method :load, :__original__load__IRB_use_loader__ alias_method :require, :__original__require__IRB_use_loader__ } end end print "Switch to load/require#{unless use_loader; ' non';end} trace mode.\n" if verbose? opt end end end PK!L 2.2.0/irb/ext/math-mode.rbnu[# # math-mode.rb - # $Release Version: 0.9.6$ # $Revision: 47112 $ # by Keiju ISHITSUKA(keiju@ruby-lang.org) # # -- # # # require "mathn" module IRB class Context # Returns whether bc mode is enabled. # # See #math_mode= attr_reader :math_mode # Alias for #math_mode alias math? math_mode # Sets bc mode, which loads +lib/mathn.rb+ so fractions or matrix are # available. # # Also available as the +-m+ command line option. # # See IRB@Command+line+options and the unix manpage bc(1) for # more information. def math_mode=(opt) if @math_mode == true && !opt IRB.fail CantReturnToNormalMode return end @math_mode = opt if math_mode main.extend Math print "start math mode\n" if verbose? end end def inspect? @inspect_mode.nil? && !@math_mode or @inspect_mode end end end PK!`2.2.0/irb/ext/workspaces.rbnu[# # push-ws.rb - # $Release Version: 0.9.6$ # $Revision: 47112 $ # by Keiju ISHITSUKA(keiju@ruby-lang.org) # # -- # # # module IRB # :nodoc: class Context # Size of the current WorkSpace stack def irb_level workspace_stack.size end # WorkSpaces in the current stack def workspaces if defined? @workspaces @workspaces else @workspaces = [] end end # Creates a new workspace with the given object or binding, and appends it # onto the current #workspaces stack. # # See IRB::Context#change_workspace and IRB::WorkSpace.new for more # information. def push_workspace(*_main) if _main.empty? if workspaces.empty? print "No other workspace\n" return nil end ws = workspaces.pop workspaces.push @workspace @workspace = ws return workspaces end workspaces.push @workspace @workspace = WorkSpace.new(@workspace.binding, _main[0]) if !(class<IRB.CurrentContext.exit. def irb_exit(ret = 0) irb_context.exit(ret) end # Displays current configuration. # # Modifing the configuration is achieved by sending a message to IRB.conf. def irb_context IRB.CurrentContext end @ALIASES = [ [:context, :irb_context, NO_OVERRIDE], [:conf, :irb_context, NO_OVERRIDE], [:irb_quit, :irb_exit, OVERRIDE_PRIVATE_ONLY], [:exit, :irb_exit, OVERRIDE_PRIVATE_ONLY], [:quit, :irb_exit, OVERRIDE_PRIVATE_ONLY], ] @EXTEND_COMMANDS = [ [:irb_current_working_workspace, :CurrentWorkingWorkspace, "irb/cmd/chws", [:irb_print_working_workspace, OVERRIDE_ALL], [:irb_cwws, OVERRIDE_ALL], [:irb_pwws, OVERRIDE_ALL], [:cwws, NO_OVERRIDE], [:pwws, NO_OVERRIDE], [:irb_current_working_binding, OVERRIDE_ALL], [:irb_print_working_binding, OVERRIDE_ALL], [:irb_cwb, OVERRIDE_ALL], [:irb_pwb, OVERRIDE_ALL], ], [:irb_change_workspace, :ChangeWorkspace, "irb/cmd/chws", [:irb_chws, OVERRIDE_ALL], [:irb_cws, OVERRIDE_ALL], [:chws, NO_OVERRIDE], [:cws, NO_OVERRIDE], [:irb_change_binding, OVERRIDE_ALL], [:irb_cb, OVERRIDE_ALL], [:cb, NO_OVERRIDE]], [:irb_workspaces, :Workspaces, "irb/cmd/pushws", [:workspaces, NO_OVERRIDE], [:irb_bindings, OVERRIDE_ALL], [:bindings, NO_OVERRIDE]], [:irb_push_workspace, :PushWorkspace, "irb/cmd/pushws", [:irb_pushws, OVERRIDE_ALL], [:pushws, NO_OVERRIDE], [:irb_push_binding, OVERRIDE_ALL], [:irb_pushb, OVERRIDE_ALL], [:pushb, NO_OVERRIDE]], [:irb_pop_workspace, :PopWorkspace, "irb/cmd/pushws", [:irb_popws, OVERRIDE_ALL], [:popws, NO_OVERRIDE], [:irb_pop_binding, OVERRIDE_ALL], [:irb_popb, OVERRIDE_ALL], [:popb, NO_OVERRIDE]], [:irb_load, :Load, "irb/cmd/load"], [:irb_require, :Require, "irb/cmd/load"], [:irb_source, :Source, "irb/cmd/load", [:source, NO_OVERRIDE]], [:irb, :IrbCommand, "irb/cmd/subirb"], [:irb_jobs, :Jobs, "irb/cmd/subirb", [:jobs, NO_OVERRIDE]], [:irb_fg, :Foreground, "irb/cmd/subirb", [:fg, NO_OVERRIDE]], [:irb_kill, :Kill, "irb/cmd/subirb", [:kill, OVERRIDE_PRIVATE_ONLY]], [:irb_help, :Help, "irb/cmd/help", [:help, NO_OVERRIDE]], ] # Installs the default irb commands: # # +irb_current_working_workspace+:: Context#main # +irb_change_workspace+:: Context#change_workspace # +irb_workspaces+:: Context#workspaces # +irb_push_workspace+:: Context#push_workspace # +irb_pop_workspace+:: Context#pop_workspace # +irb_load+:: #irb_load # +irb_require+:: #irb_require # +irb_source+:: IrbLoader#source_file # +irb+:: IRB.irb # +irb_jobs+:: JobManager # +irb_fg+:: JobManager#switch # +irb_kill+:: JobManager#kill # +irb_help+:: IRB@Command+line+options def self.install_extend_commands for args in @EXTEND_COMMANDS def_extend_command(*args) end end # Evaluate the given +cmd_name+ on the given +cmd_class+ Class. # # Will also define any given +aliases+ for the method. # # The optional +load_file+ parameter will be required within the method # definition. def self.def_extend_command(cmd_name, cmd_class, load_file = nil, *aliases) case cmd_class when Symbol cmd_class = cmd_class.id2name when String when Class cmd_class = cmd_class.name end if load_file line = __LINE__; eval %[ def #{cmd_name}(*opts, &b) require "#{load_file}" arity = ExtendCommand::#{cmd_class}.instance_method(:execute).arity args = (1..(arity < 0 ? ~arity : arity)).map {|i| "arg" + i.to_s } args << "*opts" if arity < 0 args << "&block" args = args.join(", ") line = __LINE__; eval %[ def #{cmd_name}(\#{args}) ExtendCommand::#{cmd_class}.execute(irb_context, \#{args}) end ], nil, __FILE__, line send :#{cmd_name}, *opts, &b end ], nil, __FILE__, line else line = __LINE__; eval %[ def #{cmd_name}(*opts, &b) ExtendCommand::#{cmd_class}.execute(irb_context, *opts, &b) end ], nil, __FILE__, line end for ali, flag in aliases @ALIASES.push [ali, cmd_name, flag] end end # Installs alias methods for the default irb commands, see # ::install_extend_commands. def install_alias_method(to, from, override = NO_OVERRIDE) to = to.id2name unless to.kind_of?(String) from = from.id2name unless from.kind_of?(String) if override == OVERRIDE_ALL or (override == OVERRIDE_PRIVATE_ONLY) && !respond_to?(to) or (override == NO_OVERRIDE) && !respond_to?(to, true) target = self (class << self; self; end).instance_eval{ if target.respond_to?(to, true) && !target.respond_to?(EXCB.irb_original_method_name(to), true) alias_method(EXCB.irb_original_method_name(to), to) end alias_method to, from } else print "irb: warn: can't alias #{to} from #{from}.\n" end end def self.irb_original_method_name(method_name) # :nodoc: "irb_" + method_name + "_org" end # Installs alias methods for the default irb commands on the given object # using #install_alias_method. def self.extend_object(obj) unless (class << obj; ancestors; end).include?(EXCB) super for ali, com, flg in @ALIASES obj.install_alias_method(ali, com, flg) end end end install_extend_commands end # Extends methods for the Context module module ContextExtender CE = ContextExtender # :nodoc: @EXTEND_COMMANDS = [ [:eval_history=, "irb/ext/history.rb"], [:use_tracer=, "irb/ext/tracer.rb"], [:math_mode=, "irb/ext/math-mode.rb"], [:use_loader=, "irb/ext/use-loader.rb"], [:save_history=, "irb/ext/save-history.rb"], ] # Installs the default context extensions as irb commands: # # Context#eval_history=:: +irb/ext/history.rb+ # Context#use_tracer=:: +irb/ext/tracer.rb+ # Context#math_mode=:: +irb/ext/math-mode.rb+ # Context#use_loader=:: +irb/ext/use-loader.rb+ # Context#save_history=:: +irb/ext/save-history.rb+ def self.install_extend_commands for args in @EXTEND_COMMANDS def_extend_command(*args) end end # Evaluate the given +command+ from the given +load_file+ on the Context # module. # # Will also define any given +aliases+ for the method. def self.def_extend_command(cmd_name, load_file, *aliases) line = __LINE__; Context.module_eval %[ def #{cmd_name}(*opts, &b) Context.module_eval {remove_method(:#{cmd_name})} require "#{load_file}" send :#{cmd_name}, *opts, &b end for ali in aliases alias_method ali, cmd_name end ], __FILE__, line end CE.install_extend_commands end # A convenience module for extending Ruby methods. module MethodExtender # Extends the given +base_method+ with a prefix call to the given # +extend_method+. def def_pre_proc(base_method, extend_method) base_method = base_method.to_s extend_method = extend_method.to_s alias_name = new_alias_name(base_method) module_eval %[ alias_method alias_name, base_method def #{base_method}(*opts) send :#{extend_method}, *opts send :#{alias_name}, *opts end ] end # Extends the given +base_method+ with a postfix call to the given # +extend_method+. def def_post_proc(base_method, extend_method) base_method = base_method.to_s extend_method = extend_method.to_s alias_name = new_alias_name(base_method) module_eval %[ alias_method alias_name, base_method def #{base_method}(*opts) send :#{alias_name}, *opts send :#{extend_method}, *opts end ] end # Returns a unique method name to use as an alias for the given +name+. # # Usually returns #{prefix}#{name}#{postfix}, example: # # new_alias_name('foo') #=> __alias_of__foo__ # def bar; end # new_alias_name('bar') #=> __alias_of__bar__2 def new_alias_name(name, prefix = "__alias_of__", postfix = "__") base_name = "#{prefix}#{name}#{postfix}" all_methods = instance_methods(true) + private_instance_methods(true) same_methods = all_methods.grep(/^#{Regexp.quote(base_name)}[0-9]*$/) return base_name if same_methods.empty? no = same_methods.size while !same_methods.include?(alias_name = base_name + no) no += 1 end alias_name end end end PK!FX]]2.2.0/irb/locale.rbnu[# # irb/locale.rb - internationalization module # $Release Version: 0.9.6$ # $Revision: 47266 $ # by Keiju ISHITSUKA(keiju@ruby-lang.org) # # -- # # # module IRB # :nodoc: class Locale LOCALE_NAME_RE = %r[ (?[[:alpha:]]{2,3}) (?:_ (?[[:alpha:]]{2,3}) )? (?:\. (?[^@]+) )? (?:@ (?.*) )? ]x LOCALE_DIR = "/lc/" @@legacy_encoding_alias_map = {}.freeze def initialize(locale = nil) @lang = @territory = @encoding_name = @modifier = nil @locale = locale || ENV["IRB_LANG"] || ENV["LC_MESSAGES"] || ENV["LC_ALL"] || ENV["LANG"] || "C" if m = LOCALE_NAME_RE.match(@locale) @lang, @territory, @encoding_name, @modifier = m[:language], m[:territory], m[:codeset], m[:modifier] if @encoding_name begin load 'irb/encoding_aliases.rb'; rescue LoadError; end if @encoding = @@legacy_encoding_alias_map[@encoding_name] warn "%s is obsolete. use %s" % ["#{@lang}_#{@territory}.#{@encoding_name}", "#{@lang}_#{@territory}.#{@encoding.name}"] end @encoding = Encoding.find(@encoding_name) rescue nil end end @encoding ||= (Encoding.find('locale') rescue Encoding::ASCII_8BIT) end attr_reader :lang, :territory, :encoding, :modifier def String(mes) mes = super(mes) if @encoding mes.encode(@encoding, undef: :replace) else mes end end def format(*opts) String(super(*opts)) end def gets(*rs) String(super(*rs)) end def readline(*rs) String(super(*rs)) end def print(*opts) ary = opts.collect{|opt| String(opt)} super(*ary) end def printf(*opts) s = format(*opts) print s end def puts(*opts) ary = opts.collect{|opt| String(opt)} super(*ary) end def require(file, priv = nil) rex = Regexp.new("lc/#{Regexp.quote(file)}\.(so|o|sl|rb)?") return false if $".find{|f| f =~ rex} case file when /\.rb$/ begin load(file, priv) $".push file return true rescue LoadError end when /\.(so|o|sl)$/ return super end begin load(f = file + ".rb") $".push f #" return true rescue LoadError return ruby_require(file) end end alias toplevel_load load def load(file, priv=nil) found = find(file) if found return real_load(found, priv) else raise LoadError, "No such file to load -- #{file}" end end def find(file , paths = $:) dir = File.dirname(file) dir = "" if dir == "." base = File.basename(file) if dir.start_with?('/') return each_localized_path(dir, base).find{|full_path| File.readable? full_path} else return search_file(paths, dir, base) end end private def real_load(path, priv) src = MagicFile.open(path){|f| f.read} if priv eval("self", TOPLEVEL_BINDING).extend(Module.new {eval(src, nil, path)}) else eval(src, TOPLEVEL_BINDING, path) end end # @param paths load paths in which IRB find a localized file. # @param dir directory # @param file basename to be localized # # typically, for the parameters and a in paths, it searches # /// def search_file(lib_paths, dir, file) each_localized_path(dir, file) do |lc_path| lib_paths.each do |libpath| full_path = File.join(libpath, lc_path) return full_path if File.readable?(full_path) end redo if defined?(Gem) and Gem.try_activate(lc_path) end nil end def each_localized_path(dir, file) return enum_for(:each_localized_path) unless block_given? each_sublocale do |lc| yield lc.nil? ? File.join(dir, LOCALE_DIR, file) : File.join(dir, LOCALE_DIR, lc, file) end end def each_sublocale if @lang if @territory if @encoding_name yield "#{@lang}_#{@territory}.#{@encoding_name}@#{@modifier}" if @modifier yield "#{@lang}_#{@territory}.#{@encoding_name}" end yield "#{@lang}_#{@territory}@#{@modifier}" if @modifier yield "#{@lang}_#{@territory}" end if @encoding_name yield "#{@lang}.#{@encoding_name}@#{@modifier}" if @modifier yield "#{@lang}.#{@encoding_name}" end yield "#{@lang}@#{@modifier}" if @modifier yield "#{@lang}" end yield nil end end end PK!)-y2.2.0/irb/xmp.rbnu[# # xmp.rb - irb version of gotoken xmp # $Release Version: 0.9$ # $Revision: 47266 $ # by Keiju ISHITSUKA(Nippon Rational Inc.) # # -- # # # require "irb" require "irb/frame" # An example printer for irb. # # It's much like the standard library PrettyPrint, that shows the value of each # expression as it runs. # # In order to use this library, you must first require it: # # require 'irb/xmp' # # Now, you can take advantage of the Object#xmp convenience method. # # xmp < foo = "bar" # #==>"bar" # #=> baz = 42 # #==>42 # # You can also create an XMP object, with an optional binding to print # expressions in the given binding: # # ctx = binding # x = XMP.new ctx # x.puts # #=> today = "a good day" # #==>"a good day" # ctx.eval 'today # is what?' # #=> "a good day" class XMP # Creates a new XMP object. # # The top-level binding or, optional +bind+ parameter will be used when # creating the workspace. See WorkSpace.new for more information. # # This uses the +:XMP+ prompt mode, see IRB@Customizing+the+IRB+Prompt for # full detail. def initialize(bind = nil) IRB.init_config(nil) IRB.conf[:PROMPT_MODE] = :XMP bind = IRB::Frame.top(1) unless bind ws = IRB::WorkSpace.new(bind) @io = StringInputMethod.new @irb = IRB::Irb.new(ws, @io) @irb.context.ignore_sigint = false IRB.conf[:MAIN_CONTEXT] = @irb.context end # Evaluates the given +exps+, for example: # # require 'irb/xmp' # x = XMP.new # # x.puts '{:a => 1, :b => 2, :c => 3}' # #=> {:a => 1, :b => 2, :c => 3} # # ==>{:a=>1, :b=>2, :c=>3} # x.puts 'foo = "bar"' # # => foo = "bar" # # ==>"bar" def puts(exps) @io.puts exps if @irb.context.ignore_sigint begin trap_proc_b = trap("SIGINT"){@irb.signal_handle} catch(:IRB_EXIT) do @irb.eval_input end ensure trap("SIGINT", trap_proc_b) end else catch(:IRB_EXIT) do @irb.eval_input end end end # A custom InputMethod class used by XMP for evaluating string io. class StringInputMethod < IRB::InputMethod # Creates a new StringInputMethod object def initialize super @exps = [] end # Whether there are any expressions left in this printer. def eof? @exps.empty? end # Reads the next expression from this printer. # # See IO#gets for more information. def gets while l = @exps.shift next if /^\s+$/ =~ l l.concat "\n" print @prompt, l break end l end # Concatenates all expressions in this printer, separated by newlines. # # An Encoding::CompatibilityError is raised of the given +exps+'s encoding # doesn't match the previous expression evaluated. def puts(exps) if @encoding and exps.encoding != @encoding enc = Encoding.compatible?(@exps.join("\n"), exps) if enc.nil? raise Encoding::CompatibilityError, "Encoding in which the passed expression is encoded is not compatible to the preceding's one" else @encoding = enc end else @encoding = exps.encoding end @exps.concat exps.split(/\n/) end # Returns the encoding of last expression printed by #puts. attr_reader :encoding end end # A convenience method that's only available when the you require the IRB::XMP standard library. # # Creates a new XMP object, using the given expressions as the +exps+ # parameter, and optional binding as +bind+ or uses the top-level binding. Then # evaluates the given expressions using the +:XMP+ prompt mode. # # For example: # # require 'irb/xmp' # ctx = binding # xmp 'foo = "bar"', ctx # #=> foo = "bar" # #==>"bar" # ctx.eval 'foo' # #=> "bar" # # See XMP.new for more information. def xmp(exps, bind = nil) bind = IRB::Frame.top(1) unless bind xmp = XMP.new(bind) xmp.puts exps xmp end PK!w2.2.0/irb/help.rbnu[# # irb/help.rb - print usage module # $Release Version: 0.9.6$ # $Revision: 47112 $ # by Keiju ISHITSUKA(keiju@ishitsuka.com) # # -- # # # require 'irb/magic-file' module IRB # Outputs the irb help message, see IRB@Command+line+options. def IRB.print_usage lc = IRB.conf[:LC_MESSAGES] path = lc.find("irb/help-message") space_line = false IRB::MagicFile.open(path){|f| f.each_line do |l| if /^\s*$/ =~ l lc.puts l unless space_line space_line = true next end space_line = false l.sub!(/#.*$/, "") next if /^\s*$/ =~ l lc.puts l end } end end PK!<;2.2.0/irb/lc/error.rbnu[# # irb/lc/error.rb - # $Release Version: 0.9.6$ # $Revision: 38600 $ # by Keiju ISHITSUKA(keiju@ruby-lang.org) # # -- # # # require "e2mmap" # :stopdoc: module IRB # exceptions extend Exception2MessageMapper def_exception :UnrecognizedSwitch, "Unrecognized switch: %s" def_exception :NotImplementedError, "Need to define `%s'" def_exception :CantReturnToNormalMode, "Can't return to normal mode." def_exception :IllegalParameter, "Invalid parameter(%s)." def_exception :IrbAlreadyDead, "Irb is already dead." def_exception :IrbSwitchedToCurrentThread, "Switched to current thread." def_exception :NoSuchJob, "No such job(%s)." def_exception :CantShiftToMultiIrbMode, "Can't shift to multi irb mode." def_exception :CantChangeBinding, "Can't change binding to (%s)." def_exception :UndefinedPromptMode, "Undefined prompt mode(%s)." def_exception :IllegalRCGenerator, 'Define illegal RC_NAME_GENERATOR.' end # :startdoc: PK!2.2.0/irb/lc/ja/error.rbnu[# -*- coding: utf-8 -*- # irb/lc/ja/error.rb - # $Release Version: 0.9.6$ # $Revision: 38600 $ # by Keiju ISHITSUKA(keiju@ruby-lang.org) # # -- # # # require "e2mmap" # :stopdoc: module IRB # exceptions extend Exception2MessageMapper def_exception :UnrecognizedSwitch, 'スイッチ(%s)が分りません' def_exception :NotImplementedError, '`%s\'の定義が必要です' def_exception :CantReturnToNormalMode, 'Normalモードに戻れません.' def_exception :IllegalParameter, 'パラメータ(%s)が間違っています.' def_exception :IrbAlreadyDead, 'Irbは既に死んでいます.' def_exception :IrbSwitchedToCurrentThread, 'カレントスレッドに切り替わりました.' def_exception :NoSuchJob, 'そのようなジョブ(%s)はありません.' def_exception :CantShiftToMultiIrbMode, 'multi-irb modeに移れません.' def_exception :CantChangeBinding, 'バインディング(%s)に変更できません.' def_exception :UndefinedPromptMode, 'プロンプトモード(%s)は定義されていません.' def_exception :IllegalRCNameGenerator, 'RC_NAME_GENERATORが正しく定義されていません.' end # :startdoc: # vim:fileencoding=utf-8 PK!a@#2.2.0/irb/lc/ja/encoding_aliases.rbnu[# :stopdoc: module IRB class Locale @@legacy_encoding_alias_map = { 'ujis' => Encoding::EUC_JP, 'euc' => Encoding::EUC_JP }.freeze end end # :startdoc: PK! 2.2.0/irb/lc/ja/help-messagenu[# -*- coding: utf-8 -*- # irb/lc/ja/help-message.rb - # $Release Version: 0.9.6$ # $Revision: 41071 $ # by Keiju ISHITSUKA(keiju@ruby-lang.org) # # -- # # # Usage: irb.rb [options] [programfile] [arguments] -f ~/.irbrc を読み込まない. -m bcモード(分数, 行列の計算ができる) -d $DEBUG をtrueにする(ruby -d と同じ) -r load-module ruby -r と同じ. -I path $LOAD_PATH に path を追加する. -U ruby -U と同じ. -E enc ruby -E と同じ. -w ruby -w と同じ. -W[level=2] ruby -W と同じ. --context-mode n 新しいワークスペースを作成した時に関連する Binding オブジェクトの作成方法を 0 から 3 のいずれかに設定する. --echo 実行結果を表示する(デフォルト). --noecho 実行結果を表示しない. --inspect 結果出力にinspectを用いる(bcモード以外はデフォルト). --noinspect 結果出力にinspectを用いない. --readline readlineライブラリを利用する. --noreadline readlineライブラリを利用しない. --prompt prompt-mode/--prompt-mode prompt-mode プロンプトモードを切替えます. 現在定義されているプ ロンプトモードは, default, simple, xmp, inf-rubyが 用意されています. --inf-ruby-mode emacsのinf-ruby-mode用のプロンプト表示を行なう. 特 に指定がない限り, readlineライブラリは使わなくなる. --sample-book-mode/--simple-prompt 非常にシンプルなプロンプトを用いるモードです. --noprompt プロンプト表示を行なわない. --single-irb irb 中で self を実行して得られるオブジェクトをサ ブ irb と共有する. --tracer コマンド実行時にトレースを行なう. --back-trace-limit n バックトレース表示をバックトレースの頭から n, 後ろ からnだけ行なう. デフォルトは16 --irb_debug n irbのデバッグレベルをnに設定する(非推奨). --verbose 詳細なメッセージを出力する. --noverbose 詳細なメッセージを出力しない(デフォルト). -v, --version irbのバージョンを表示する. -h, --help irb のヘルプを表示する. -- 以降のコマンドライン引数をオプションとして扱わない. # vim:fileencoding=utf-8 PK!sXU2.2.0/irb/lc/help-messagenu[# -*- coding: utf-8 -*- # # irb/lc/help-message.rb - # $Release Version: 0.9.6$ # $Revision: 41028 $ # by Keiju ISHITSUKA(keiju@ruby-lang.org) # # -- # # # Usage: irb.rb [options] [programfile] [arguments] -f Suppress read of ~/.irbrc -m Bc mode (load mathn, fraction or matrix are available) -d Set $DEBUG to true (same as `ruby -d') -r load-module Same as `ruby -r' -I path Specify $LOAD_PATH directory -U Same as `ruby -U` -E enc Same as `ruby -E` -w Same as `ruby -w` -W[level=2] Same as `ruby -W` --context-mode n Set n[0-3] to method to create Binding Object, when new workspace was created --echo Show result(default) --noecho Don't show result --inspect Use `inspect' for output (default except for bc mode) --noinspect Don't use inspect for output --readline Use Readline extension module --noreadline Don't use Readline extension module --prompt prompt-mode/--prompt-mode prompt-mode Switch prompt mode. Pre-defined prompt modes are `default', `simple', `xmp' and `inf-ruby' --inf-ruby-mode Use prompt appropriate for inf-ruby-mode on emacs. Suppresses --readline. --sample-book-mode/--simple-prompt Simple prompt mode --noprompt No prompt mode --single-irb Share self with sub-irb. --tracer Display trace for each execution of commands. --back-trace-limit n Display backtrace top n and tail n. The default value is 16. --irb_debug n Set internal debug level to n (not for popular use) --verbose Show details --noverbose Don't show details -v, --version Print the version of irb -h, --help Print help -- Separate options of irb from the list of command-line args # vim:fileencoding=utf-8 PK!۷jj2.2.0/irb/input-method.rbnu[# # irb/input-method.rb - input methods used irb # $Release Version: 0.9.6$ # $Revision: 47266 $ # by Keiju ISHITSUKA(keiju@ruby-lang.org) # # -- # # # require 'irb/src_encoding' require 'irb/magic-file' module IRB STDIN_FILE_NAME = "(line)" # :nodoc: class InputMethod # Creates a new input method object def initialize(file = STDIN_FILE_NAME) @file_name = file end # The file name of this input method, usually given during initialization. attr_reader :file_name # The irb prompt associated with this input method attr_accessor :prompt # Reads the next line from this input method. # # See IO#gets for more information. def gets IRB.fail NotImplementedError, "gets" end public :gets # Whether this input method is still readable when there is no more data to # read. # # See IO#eof for more information. def readable_after_eof? false end end class StdioInputMethod < InputMethod # Creates a new input method object def initialize super @line_no = 0 @line = [] @stdin = IO.open(STDIN.to_i, :external_encoding => IRB.conf[:LC_MESSAGES].encoding, :internal_encoding => "-") @stdout = IO.open(STDOUT.to_i, 'w', :external_encoding => IRB.conf[:LC_MESSAGES].encoding, :internal_encoding => "-") end # Reads the next line from this input method. # # See IO#gets for more information. def gets print @prompt line = @stdin.gets @line[@line_no += 1] = line end # Whether the end of this input method has been reached, returns +true+ if # there is no more data to read. # # See IO#eof? for more information. def eof? @stdin.eof? end # Whether this input method is still readable when there is no more data to # read. # # See IO#eof for more information. def readable_after_eof? true end # Returns the current line number for #io. # # #line counts the number of times #gets is called. # # See IO#lineno for more information. def line(line_no) @line[line_no] end # The external encoding for standard input. def encoding @stdin.external_encoding end end # Use a File for IO with irb, see InputMethod class FileInputMethod < InputMethod # Creates a new input method object def initialize(file) super @io = IRB::MagicFile.open(file) end # The file name of this input method, usually given during initialization. attr_reader :file_name # Whether the end of this input method has been reached, returns +true+ if # there is no more data to read. # # See IO#eof? for more information. def eof? @io.eof? end # Reads the next line from this input method. # # See IO#gets for more information. def gets print @prompt l = @io.gets l end # The external encoding for standard input. def encoding @io.external_encoding end end begin require "readline" class ReadlineInputMethod < InputMethod include Readline # Creates a new input method object using Readline def initialize super @line_no = 0 @line = [] @eof = false @stdin = IO.open(STDIN.to_i, :external_encoding => IRB.conf[:LC_MESSAGES].encoding, :internal_encoding => "-") @stdout = IO.open(STDOUT.to_i, 'w', :external_encoding => IRB.conf[:LC_MESSAGES].encoding, :internal_encoding => "-") end # Reads the next line from this input method. # # See IO#gets for more information. def gets Readline.input = @stdin Readline.output = @stdout if l = readline(@prompt, false) HISTORY.push(l) if !l.empty? @line[@line_no += 1] = l + "\n" else @eof = true l end end # Whether the end of this input method has been reached, returns +true+ # if there is no more data to read. # # See IO#eof? for more information. def eof? @eof end # Whether this input method is still readable when there is no more data to # read. # # See IO#eof for more information. def readable_after_eof? true end # Returns the current line number for #io. # # #line counts the number of times #gets is called. # # See IO#lineno for more information. def line(line_no) @line[line_no] end # The external encoding for standard input. def encoding @stdin.external_encoding end end rescue LoadError end end PK!$}}2.2.0/irb/magic-file.rbnu[module IRB class << (MagicFile = Object.new) # see parser_magic_comment in parse.y ENCODING_SPEC_RE = %r"coding\s*[=:]\s*([[:alnum:]\-_]+)" def open(path) io = File.open(path, 'rb') line = io.gets line = io.gets if line[0,2] == "#!" encoding = detect_encoding(line) internal_encoding = encoding encoding ||= default_src_encoding io.rewind io.set_encoding(encoding, internal_encoding) if block_given? begin return (yield io) ensure io.close end else return io end end private def detect_encoding(line) return unless line[0] == ?# line = line[1..-1] line = $1 if line[/-\*-\s*(.*?)\s*-*-$/] return nil unless ENCODING_SPEC_RE =~ line encoding = $1 return encoding.sub(/-(?:mac|dos|unix)/i, '') end end end PK!jZ552.2.0/irb/slex.rbnu[# # irb/slex.rb - simple lex analyzer # $Release Version: 0.9.6$ # $Revision: 47266 $ # by Keiju ISHITSUKA(keiju@ruby-lang.org) # # -- # # # require "e2mmap" require "irb/notifier" # :stopdoc: module IRB class SLex extend Exception2MessageMapper def_exception :ErrNodeNothing, "node nothing" def_exception :ErrNodeAlreadyExists, "node already exists" DOUT = Notifier::def_notifier("SLex::") D_WARN = DOUT::def_notifier(1, "Warn: ") D_DEBUG = DOUT::def_notifier(2, "Debug: ") D_DETAIL = DOUT::def_notifier(4, "Detail: ") DOUT.level = Notifier::D_NOMSG def initialize @head = Node.new("") end def def_rule(token, preproc = nil, postproc = nil, &block) D_DETAIL.pp token postproc = block if block_given? create(token, preproc, postproc) end def def_rules(*tokens, &block) if block_given? p = block end for token in tokens def_rule(token, nil, p) end end def preproc(token, proc) node = search(token) node.preproc=proc end #$BMW%A%'%C%/(B? def postproc(token) node = search(token, proc) node.postproc=proc end def search(token) @head.search(token.split(//)) end def create(token, preproc = nil, postproc = nil) @head.create_subnode(token.split(//), preproc, postproc) end def match(token) case token when Array when String return match(token.split(//)) else return @head.match_io(token) end ret = @head.match(token) D_DETAIL.exec_if{D_DETAIL.printf "match end: %s:%s\n", ret, token.inspect} ret end def inspect format("", @head.inspect) end #---------------------------------------------------------------------- # # class Node - # #---------------------------------------------------------------------- class Node # if postproc is nil, this node is an abstract node. # if postproc is non-nil, this node is a real node. def initialize(preproc = nil, postproc = nil) @Tree = {} @preproc = preproc @postproc = postproc end attr_accessor :preproc attr_accessor :postproc def search(chrs, opt = nil) return self if chrs.empty? ch = chrs.shift if node = @Tree[ch] node.search(chrs, opt) else if opt chrs.unshift ch self.create_subnode(chrs) else SLex.fail ErrNodeNothing end end end def create_subnode(chrs, preproc = nil, postproc = nil) if chrs.empty? if @postproc D_DETAIL.pp node SLex.fail ErrNodeAlreadyExists else D_DEBUG.puts "change abstract node to real node." @preproc = preproc @postproc = postproc end return self end ch = chrs.shift if node = @Tree[ch] if chrs.empty? if node.postproc DebugLogger.pp node DebugLogger.pp self DebugLogger.pp ch DebugLogger.pp chrs SLex.fail ErrNodeAlreadyExists else D_WARN.puts "change abstract node to real node" node.preproc = preproc node.postproc = postproc end else node.create_subnode(chrs, preproc, postproc) end else if chrs.empty? node = Node.new(preproc, postproc) else node = Node.new node.create_subnode(chrs, preproc, postproc) end @Tree[ch] = node end node end # # chrs: String # character array # io must have getc()/ungetc(); and ungetc() must be # able to be called arbitrary number of times. # def match(chrs, op = "") D_DETAIL.print "match>: ", chrs, "op:", op, "\n" if chrs.empty? if @preproc.nil? || @preproc.call(op, chrs) DOUT.printf(D_DETAIL, "op1: %s\n", op) @postproc.call(op, chrs) else nil end else ch = chrs.shift if node = @Tree[ch] if ret = node.match(chrs, op+ch) return ret else chrs.unshift ch if @postproc and @preproc.nil? || @preproc.call(op, chrs) DOUT.printf(D_DETAIL, "op2: %s\n", op.inspect) ret = @postproc.call(op, chrs) return ret else return nil end end else chrs.unshift ch if @postproc and @preproc.nil? || @preproc.call(op, chrs) DOUT.printf(D_DETAIL, "op3: %s\n", op) @postproc.call(op, chrs) return "" else return nil end end end end def match_io(io, op = "") if op == "" ch = io.getc if ch == nil return nil end else ch = io.getc_of_rests end if ch.nil? if @preproc.nil? || @preproc.call(op, io) D_DETAIL.printf("op1: %s\n", op) @postproc.call(op, io) else nil end else if node = @Tree[ch] if ret = node.match_io(io, op+ch) ret else io.ungetc ch if @postproc and @preproc.nil? || @preproc.call(op, io) DOUT.exec_if{D_DETAIL.printf "op2: %s\n", op.inspect} @postproc.call(op, io) else nil end end else io.ungetc ch if @postproc and @preproc.nil? || @preproc.call(op, io) D_DETAIL.printf("op3: %s\n", op) @postproc.call(op, io) else nil end end end end end end end # :startdoc: if $0 == __FILE__ case $1 when "1" tr = SLex.new print "0: ", tr.inspect, "\n" tr.def_rule("=") {print "=\n"} print "1: ", tr.inspect, "\n" tr.def_rule("==") {print "==\n"} print "2: ", tr.inspect, "\n" print "case 1:\n" print tr.match("="), "\n" print "case 2:\n" print tr.match("=="), "\n" print "case 3:\n" print tr.match("=>"), "\n" when "2" tr = SLex.new print "0: ", tr.inspect, "\n" tr.def_rule("=") {print "=\n"} print "1: ", tr.inspect, "\n" tr.def_rule("==", proc{false}) {print "==\n"} print "2: ", tr.inspect, "\n" print "case 1:\n" print tr.match("="), "\n" print "case 2:\n" print tr.match("=="), "\n" print "case 3:\n" print tr.match("=>"), "\n" end exit end PK!֊2.2.0/irb/completion.rbnu[# # irb/completor.rb - # $Release Version: 0.9$ # $Revision: 47266 $ # by Keiju ISHITSUKA(keiju@ishitsuka.com) # From Original Idea of shugo@ruby-lang.org # require "readline" module IRB module InputCompletor # :nodoc: # Set of reserved words used by Ruby, you should not use these for # constants or variables ReservedWords = %w[ BEGIN END alias and begin break case class def defined do else elsif end ensure false for if in module next nil not or redo rescue retry return self super then true undef unless until when while yield ] CompletionProc = proc { |input| bind = IRB.conf[:MAIN_CONTEXT].workspace.binding case input when /^((["'`]).*\2)\.([^.]*)$/ # String receiver = $1 message = Regexp.quote($3) candidates = String.instance_methods.collect{|m| m.to_s} select_message(receiver, message, candidates) when /^(\/[^\/]*\/)\.([^.]*)$/ # Regexp receiver = $1 message = Regexp.quote($2) candidates = Regexp.instance_methods.collect{|m| m.to_s} select_message(receiver, message, candidates) when /^([^\]]*\])\.([^.]*)$/ # Array receiver = $1 message = Regexp.quote($2) candidates = Array.instance_methods.collect{|m| m.to_s} select_message(receiver, message, candidates) when /^([^\}]*\})\.([^.]*)$/ # Proc or Hash receiver = $1 message = Regexp.quote($2) candidates = Proc.instance_methods.collect{|m| m.to_s} candidates |= Hash.instance_methods.collect{|m| m.to_s} select_message(receiver, message, candidates) when /^(:[^:.]*)$/ # Symbol if Symbol.respond_to?(:all_symbols) sym = $1 candidates = Symbol.all_symbols.collect{|s| ":" + s.id2name} candidates.grep(/^#{Regexp.quote(sym)}/) else [] end when /^::([A-Z][^:\.\(]*)$/ # Absolute Constant or class methods receiver = $1 candidates = Object.constants.collect{|m| m.to_s} candidates.grep(/^#{receiver}/).collect{|e| "::" + e} when /^([A-Z].*)::([^:.]*)$/ # Constant or class methods receiver = $1 message = Regexp.quote($2) begin candidates = eval("#{receiver}.constants.collect{|m| m.to_s}", bind) candidates |= eval("#{receiver}.methods.collect{|m| m.to_s}", bind) rescue Exception candidates = [] end select_message(receiver, message, candidates, "::") when /^(:[^:.]+)(\.|::)([^.]*)$/ # Symbol receiver = $1 sep = $2 message = Regexp.quote($3) candidates = Symbol.instance_methods.collect{|m| m.to_s} select_message(receiver, message, candidates, sep) when /^(-?(0[dbo])?[0-9_]+(\.[0-9_]+)?([eE]-?[0-9]+)?)(\.|::)([^.]*)$/ # Numeric receiver = $1 sep = $5 message = Regexp.quote($6) begin candidates = eval(receiver, bind).methods.collect{|m| m.to_s} rescue Exception candidates = [] end select_message(receiver, message, candidates, sep) when /^(-?0x[0-9a-fA-F_]+)(\.|::)([^.]*)$/ # Numeric(0xFFFF) receiver = $1 sep = $2 message = Regexp.quote($3) begin candidates = eval(receiver, bind).methods.collect{|m| m.to_s} rescue Exception candidates = [] end select_message(receiver, message, candidates, sep) when /^(\$[^.]*)$/ # global var regmessage = Regexp.new(Regexp.quote($1)) candidates = global_variables.collect{|m| m.to_s}.grep(regmessage) when /^([^."].*)(\.|::)([^.]*)$/ # variable.func or func.func receiver = $1 sep = $2 message = Regexp.quote($3) gv = eval("global_variables", bind).collect{|m| m.to_s} lv = eval("local_variables", bind).collect{|m| m.to_s} iv = eval("instance_variables", bind).collect{|m| m.to_s} cv = eval("self.class.constants", bind).collect{|m| m.to_s} if (gv | lv | iv | cv).include?(receiver) or /^[A-Z]/ =~ receiver && /\./ !~ receiver # foo.func and foo is var. OR # foo::func and foo is var. OR # foo::Const and foo is var. OR # Foo::Bar.func begin candidates = [] rec = eval(receiver, bind) if sep == "::" and rec.kind_of?(Module) candidates = rec.constants.collect{|m| m.to_s} end candidates |= rec.methods.collect{|m| m.to_s} rescue Exception candidates = [] end else # func1.func2 candidates = [] ObjectSpace.each_object(Module){|m| begin name = m.name rescue Exception name = "" end begin next if name != "IRB::Context" and /^(IRB|SLex|RubyLex|RubyToken)/ =~ name rescue Exception next end candidates.concat m.instance_methods(false).collect{|x| x.to_s} } candidates.sort! candidates.uniq! end select_message(receiver, message, candidates, sep) when /^\.([^.]*)$/ # unknown(maybe String) receiver = "" message = Regexp.quote($1) candidates = String.instance_methods(true).collect{|m| m.to_s} select_message(receiver, message, candidates) else candidates = eval("methods | private_methods | local_variables | instance_variables | self.class.constants", bind).collect{|m| m.to_s} (candidates|ReservedWords).grep(/^#{Regexp.quote(input)}/) end } # Set of available operators in Ruby Operators = %w[% & * ** + - / < << <= <=> == === =~ > >= >> [] []= ^ ! != !~] def self.select_message(receiver, message, candidates, sep = ".") candidates.grep(/^#{message}/).collect do |e| case e when /^[a-zA-Z_]/ receiver + sep + e when /^[0-9]/ when *Operators #receiver + " " + e end end end end end if Readline.respond_to?("basic_word_break_characters=") Readline.basic_word_break_characters= " \t\n`><=;|&{(" end Readline.completion_append_character = nil Readline.completion_proc = IRB::InputCompletor::CompletionProc PK!H–2.2.0/irb/notifier.rbnu[# # notifier.rb - output methods used by irb # $Release Version: 0.9.6$ # $Revision: 47112 $ # by Keiju ISHITSUKA(keiju@ruby-lang.org) # # -- # # # require "e2mmap" require "irb/output-method" module IRB # An output formatter used internally by the lexer. module Notifier extend Exception2MessageMapper def_exception :ErrUndefinedNotifier, "undefined notifier level: %d is specified" def_exception :ErrUnrecognizedLevel, "unrecognized notifier level: %s is specified" # Define a new Notifier output source, returning a new CompositeNotifier # with the given +prefix+ and +output_method+. # # The optional +prefix+ will be appended to all objects being inspected # during output, using the given +output_method+ as the output source. If # no +output_method+ is given, StdioOutputMethod will be used, and all # expressions will be sent directly to STDOUT without any additional # formatting. def def_notifier(prefix = "", output_method = StdioOutputMethod.new) CompositeNotifier.new(prefix, output_method) end module_function :def_notifier # An abstract class, or superclass, for CompositeNotifier and # LeveledNotifier to inherit. It provides several wrapper methods for the # OutputMethod object used by the Notifier. class AbstractNotifier # Creates a new Notifier object def initialize(prefix, base_notifier) @prefix = prefix @base_notifier = base_notifier end # The +prefix+ for this Notifier, which is appended to all objects being # inspected during output. attr_reader :prefix # A wrapper method used to determine whether notifications are enabled. # # Defaults to +true+. def notify? true end # See OutputMethod#print for more detail. def print(*opts) @base_notifier.print prefix, *opts if notify? end # See OutputMethod#printn for more detail. def printn(*opts) @base_notifier.printn prefix, *opts if notify? end # See OutputMethod#printf for more detail. def printf(format, *opts) @base_notifier.printf(prefix + format, *opts) if notify? end # See OutputMethod#puts for more detail. def puts(*objs) if notify? @base_notifier.puts(*objs.collect{|obj| prefix + obj.to_s}) end end # Same as #ppx, except it uses the #prefix given during object # initialization. # See OutputMethod#ppx for more detail. def pp(*objs) if notify? @base_notifier.ppx @prefix, *objs end end # Same as #pp, except it concatenates the given +prefix+ with the #prefix # given during object initialization. # # See OutputMethod#ppx for more detail. def ppx(prefix, *objs) if notify? @base_notifier.ppx @prefix+prefix, *objs end end # Execute the given block if notifications are enabled. def exec_if yield(@base_notifier) if notify? end end # A class that can be used to create a group of notifier objects with the # intent of representing a leveled notification system for irb. # # This class will allow you to generate other notifiers, and assign them # the appropriate level for output. # # The Notifier class provides a class-method Notifier.def_notifier to # create a new composite notifier. Using the first composite notifier # object you create, sibling notifiers can be initialized with # #def_notifier. class CompositeNotifier(other) @level <=> other.level end # Whether to output messages to the output method, depending on the level # of this notifier object. def notify? @base_notifier.level >= self end end # NoMsgNotifier is a LeveledNotifier that's used as the default notifier # when creating a new CompositeNotifier. # # This notifier is used as the +zero+ index, or level +0+, for # CompositeNotifier#notifiers, and will not output messages of any sort. class NoMsgNotifierIRB.conf[:__MAIN__] attr_reader :main # Evaluate the given +statements+ within the context of this workspace. def evaluate(context, statements, file = __FILE__, line = __LINE__) eval(statements, @binding, file, line) end # error message manipulator def filter_backtrace(bt) case IRB.conf[:CONTEXT_MODE] when 0 return nil if bt =~ /\(irb_local_binding\)/ when 1 if(bt =~ %r!/tmp/irb-binding! or bt =~ %r!irb/.*\.rb! or bt =~ /irb\.rb/) return nil end when 2 return nil if bt =~ /irb\/.*\.rb/ return nil if bt =~ /irb\.rb/ when 3 return nil if bt =~ /irb\/.*\.rb/ return nil if bt =~ /irb\.rb/ bt = bt.sub(/:\s*in `irb_binding'/, '') end bt end def IRB.delete_caller end end end PK! N.__2.2.0/irb/ruby-lex.rbnu[# # irb/ruby-lex.rb - ruby lexcal analyzer # $Release Version: 0.9.6$ # $Revision: 58086 $ # by Keiju ISHITSUKA(keiju@ruby-lang.org) # # -- # # # require "e2mmap" require "irb/slex" require "irb/ruby-token" # :stopdoc: class RubyLex extend Exception2MessageMapper def_exception(:AlreadyDefinedToken, "Already defined token(%s)") def_exception(:TkReading2TokenNoKey, "key nothing(key='%s')") def_exception(:TkSymbol2TokenNoKey, "key nothing(key='%s')") def_exception(:TkReading2TokenDuplicateError, "key duplicate(token_n='%s', key='%s')") def_exception(:SyntaxError, "%s") def_exception(:TerminateLineInput, "Terminate Line Input") include RubyToken class << self attr_accessor :debug_level def debug? @debug_level > 0 end end @debug_level = 0 def initialize lex_init set_input(STDIN) @seek = 0 @exp_line_no = @line_no = 1 @base_char_no = 0 @char_no = 0 @rests = [] @readed = [] @here_readed = [] @indent = 0 @indent_stack = [] @lex_state = EXPR_BEG @space_seen = false @here_header = false @post_symbeg = false @continue = false @line = "" @skip_space = false @readed_auto_clean_up = false @exception_on_syntax_error = true @prompt = nil end attr_accessor :skip_space attr_accessor :readed_auto_clean_up attr_accessor :exception_on_syntax_error attr_reader :seek attr_reader :char_no attr_reader :line_no attr_reader :indent # io functions def set_input(io, p = nil, &block) @io = io if p.respond_to?(:call) @input = p elsif block_given? @input = block else @input = Proc.new{@io.gets} end end def get_readed if idx = @readed.rindex("\n") @base_char_no = @readed.size - (idx + 1) else @base_char_no += @readed.size end readed = @readed.join("") @readed = [] readed end def getc while @rests.empty? @rests.push nil unless buf_input end c = @rests.shift if @here_header @here_readed.push c else @readed.push c end @seek += 1 if c == "\n" @line_no += 1 @char_no = 0 else @char_no += 1 end c end def gets l = "" while c = getc l.concat(c) break if c == "\n" end return nil if l == "" and c.nil? l end def eof? @io.eof? end def getc_of_rests if @rests.empty? nil else getc end end def ungetc(c = nil) if @here_readed.empty? c2 = @readed.pop else c2 = @here_readed.pop end c = c2 unless c @rests.unshift c #c = @seek -= 1 if c == "\n" @line_no -= 1 if idx = @readed.rindex("\n") @char_no = idx + 1 else @char_no = @base_char_no + @readed.size end else @char_no -= 1 end end def peek_equal?(str) chrs = str.split(//) until @rests.size >= chrs.size return false unless buf_input end @rests[0, chrs.size] == chrs end def peek_match?(regexp) while @rests.empty? return false unless buf_input end regexp =~ @rests.join("") end def peek(i = 0) while @rests.size <= i return nil unless buf_input end @rests[i] end def buf_input prompt line = @input.call return nil unless line @rests.concat line.chars.to_a true end private :buf_input def set_prompt(p = nil, &block) p = block if block_given? if p.respond_to?(:call) @prompt = p else @prompt = Proc.new{print p} end end def prompt if @prompt @prompt.call(@ltype, @indent, @continue, @line_no) end end def initialize_input @ltype = nil @quoted = nil @indent = 0 @indent_stack = [] @lex_state = EXPR_BEG @space_seen = false @here_header = false @continue = false @post_symbeg = false prompt @line = "" @exp_line_no = @line_no end def each_top_level_statement initialize_input catch(:TERM_INPUT) do loop do begin @continue = false prompt unless l = lex throw :TERM_INPUT if @line == '' else @line.concat l if @ltype or @continue or @indent > 0 next end end if @line != "\n" @line.force_encoding(@io.encoding) yield @line, @exp_line_no end break unless l @line = '' @exp_line_no = @line_no @indent = 0 @indent_stack = [] prompt rescue TerminateLineInput initialize_input prompt get_readed end end end end def lex until (((tk = token).kind_of?(TkNL) || tk.kind_of?(TkEND_OF_SCRIPT)) && !@continue or tk.nil?) end line = get_readed if line == "" and tk.kind_of?(TkEND_OF_SCRIPT) || tk.nil? nil else line end end def token @prev_seek = @seek @prev_line_no = @line_no @prev_char_no = @char_no begin begin tk = @OP.match(self) @space_seen = tk.kind_of?(TkSPACE) @lex_state = EXPR_END if @post_symbeg && tk.kind_of?(TkOp) @post_symbeg = tk.kind_of?(TkSYMBEG) rescue SyntaxError raise if @exception_on_syntax_error tk = TkError.new(@seek, @line_no, @char_no) end end while @skip_space and tk.kind_of?(TkSPACE) if @readed_auto_clean_up get_readed end tk end ENINDENT_CLAUSE = [ "case", "class", "def", "do", "for", "if", "module", "unless", "until", "while", "begin" ] DEINDENT_CLAUSE = ["end" ] PERCENT_LTYPE = { "q" => "\'", "Q" => "\"", "x" => "\`", "r" => "/", "w" => "]", "W" => "]", "i" => "]", "I" => "]", "s" => ":" } PERCENT_PAREN = { "{" => "}", "[" => "]", "<" => ">", "(" => ")" } Ltype2Token = { "\'" => TkSTRING, "\"" => TkSTRING, "\`" => TkXSTRING, "/" => TkREGEXP, "]" => TkDSTRING, ":" => TkSYMBOL } DLtype2Token = { "\"" => TkDSTRING, "\`" => TkDXSTRING, "/" => TkDREGEXP, } def lex_init() @OP = IRB::SLex.new @OP.def_rules("\0", "\004", "\032") do |op, io| Token(TkEND_OF_SCRIPT) end @OP.def_rules(" ", "\t", "\f", "\r", "\13") do |op, io| @space_seen = true while getc =~ /[ \t\f\r\13]/; end ungetc Token(TkSPACE) end @OP.def_rule("#") do |op, io| identify_comment end @OP.def_rule("=begin", proc{|op, io| @prev_char_no == 0 && peek(0) =~ /\s/}) do |op, io| @ltype = "=" until getc == "\n"; end until peek_equal?("=end") && peek(4) =~ /\s/ until getc == "\n"; end end gets @ltype = nil Token(TkRD_COMMENT) end @OP.def_rule("\n") do |op, io| print "\\n\n" if RubyLex.debug? case @lex_state when EXPR_BEG, EXPR_FNAME, EXPR_DOT @continue = true else @continue = false @lex_state = EXPR_BEG until (@indent_stack.empty? || [TkLPAREN, TkLBRACK, TkLBRACE, TkfLPAREN, TkfLBRACK, TkfLBRACE].include?(@indent_stack.last)) @indent_stack.pop end end @here_header = false @here_readed = [] Token(TkNL) end @OP.def_rules("*", "**", "=", "==", "===", "=~", "<=>", "<", "<=", ">", ">=", ">>", "!", "!=", "!~") do |op, io| case @lex_state when EXPR_FNAME, EXPR_DOT @lex_state = EXPR_ARG else @lex_state = EXPR_BEG end Token(op) end @OP.def_rules("<<") do |op, io| tk = nil if @lex_state != EXPR_END && @lex_state != EXPR_CLASS && (@lex_state != EXPR_ARG || @space_seen) c = peek(0) if /\S/ =~ c && (/["'`]/ =~ c || /\w/ =~ c || c == "-") tk = identify_here_document end end unless tk tk = Token(op) case @lex_state when EXPR_FNAME, EXPR_DOT @lex_state = EXPR_ARG else @lex_state = EXPR_BEG end end tk end @OP.def_rules("'", '"') do |op, io| identify_string(op) end @OP.def_rules("`") do |op, io| if @lex_state == EXPR_FNAME @lex_state = EXPR_END Token(op) else identify_string(op) end end @OP.def_rules('?') do |op, io| if @lex_state == EXPR_END @lex_state = EXPR_BEG Token(TkQUESTION) else ch = getc if @lex_state == EXPR_ARG && ch =~ /\s/ ungetc @lex_state = EXPR_BEG; Token(TkQUESTION) else if (ch == '\\') read_escape end @lex_state = EXPR_END Token(TkINTEGER) end end end @OP.def_rules("&", "&&", "|", "||") do |op, io| @lex_state = EXPR_BEG Token(op) end @OP.def_rules("+=", "-=", "*=", "**=", "&=", "|=", "^=", "<<=", ">>=", "||=", "&&=") do |op, io| @lex_state = EXPR_BEG op =~ /^(.*)=$/ Token(TkOPASGN, $1) end @OP.def_rule("+@", proc{|op, io| @lex_state == EXPR_FNAME}) do |op, io| @lex_state = EXPR_ARG Token(op) end @OP.def_rule("-@", proc{|op, io| @lex_state == EXPR_FNAME}) do |op, io| @lex_state = EXPR_ARG Token(op) end @OP.def_rules("+", "-") do |op, io| catch(:RET) do if @lex_state == EXPR_ARG if @space_seen and peek(0) =~ /[0-9]/ throw :RET, identify_number else @lex_state = EXPR_BEG end elsif @lex_state != EXPR_END and peek(0) =~ /[0-9]/ throw :RET, identify_number else @lex_state = EXPR_BEG end Token(op) end end @OP.def_rule(".") do |op, io| @lex_state = EXPR_BEG if peek(0) =~ /[0-9]/ ungetc identify_number else # for "obj.if" etc. @lex_state = EXPR_DOT Token(TkDOT) end end @OP.def_rules("..", "...") do |op, io| @lex_state = EXPR_BEG Token(op) end lex_int2 end def lex_int2 @OP.def_rules("]", "}", ")") do |op, io| @lex_state = EXPR_END @indent -= 1 @indent_stack.pop Token(op) end @OP.def_rule(":") do |op, io| if @lex_state == EXPR_END || peek(0) =~ /\s/ @lex_state = EXPR_BEG Token(TkCOLON) else @lex_state = EXPR_FNAME Token(TkSYMBEG) end end @OP.def_rule("::") do |op, io| if @lex_state == EXPR_BEG or @lex_state == EXPR_ARG && @space_seen @lex_state = EXPR_BEG Token(TkCOLON3) else @lex_state = EXPR_DOT Token(TkCOLON2) end end @OP.def_rule("/") do |op, io| if @lex_state == EXPR_BEG || @lex_state == EXPR_MID identify_string(op) elsif peek(0) == '=' getc @lex_state = EXPR_BEG Token(TkOPASGN, "/") #/) elsif @lex_state == EXPR_ARG and @space_seen and peek(0) !~ /\s/ identify_string(op) else @lex_state = EXPR_BEG Token("/") #/) end end @OP.def_rules("^") do |op, io| @lex_state = EXPR_BEG Token("^") end @OP.def_rules(",") do |op, io| @lex_state = EXPR_BEG Token(op) end @OP.def_rules(";") do |op, io| @lex_state = EXPR_BEG until (@indent_stack.empty? || [TkLPAREN, TkLBRACK, TkLBRACE, TkfLPAREN, TkfLBRACK, TkfLBRACE].include?(@indent_stack.last)) @indent_stack.pop end Token(op) end @OP.def_rule("~") do |op, io| @lex_state = EXPR_BEG Token("~") end @OP.def_rule("~@", proc{|op, io| @lex_state == EXPR_FNAME}) do |op, io| @lex_state = EXPR_BEG Token("~") end @OP.def_rule("(") do |op, io| @indent += 1 if @lex_state == EXPR_BEG || @lex_state == EXPR_MID @lex_state = EXPR_BEG tk_c = TkfLPAREN else @lex_state = EXPR_BEG tk_c = TkLPAREN end @indent_stack.push tk_c Token(tk_c) end @OP.def_rule("[]", proc{|op, io| @lex_state == EXPR_FNAME}) do |op, io| @lex_state = EXPR_ARG Token("[]") end @OP.def_rule("[]=", proc{|op, io| @lex_state == EXPR_FNAME}) do |op, io| @lex_state = EXPR_ARG Token("[]=") end @OP.def_rule("[") do |op, io| @indent += 1 if @lex_state == EXPR_FNAME tk_c = TkfLBRACK else if @lex_state == EXPR_BEG || @lex_state == EXPR_MID tk_c = TkLBRACK elsif @lex_state == EXPR_ARG && @space_seen tk_c = TkLBRACK else tk_c = TkfLBRACK end @lex_state = EXPR_BEG end @indent_stack.push tk_c Token(tk_c) end @OP.def_rule("{") do |op, io| @indent += 1 if @lex_state != EXPR_END && @lex_state != EXPR_ARG tk_c = TkLBRACE else tk_c = TkfLBRACE end @lex_state = EXPR_BEG @indent_stack.push tk_c Token(tk_c) end @OP.def_rule('\\') do |op, io| if getc == "\n" @space_seen = true @continue = true Token(TkSPACE) else read_escape Token("\\") end end @OP.def_rule('%') do |op, io| if @lex_state == EXPR_BEG || @lex_state == EXPR_MID identify_quotation elsif peek(0) == '=' getc Token(TkOPASGN, :%) elsif @lex_state == EXPR_ARG and @space_seen and peek(0) !~ /\s/ identify_quotation else @lex_state = EXPR_BEG Token("%") #)) end end @OP.def_rule('$') do |op, io| identify_gvar end @OP.def_rule('@') do |op, io| if peek(0) =~ /[\w@]/ ungetc identify_identifier else Token("@") end end @OP.def_rule("") do |op, io| printf "MATCH: start %s: %s\n", op, io.inspect if RubyLex.debug? if peek(0) =~ /[0-9]/ t = identify_number elsif peek(0) =~ /[^\x00-\/:-@\[-^`{-\x7F]/ t = identify_identifier end printf "MATCH: end %s: %s\n", op, io.inspect if RubyLex.debug? t end p @OP if RubyLex.debug? end def identify_gvar @lex_state = EXPR_END case ch = getc when /[~_*$?!@\/\\;,=:<>".]/ #" Token(TkGVAR, "$" + ch) when "-" Token(TkGVAR, "$-" + getc) when "&", "`", "'", "+" Token(TkBACK_REF, "$"+ch) when /[1-9]/ while getc =~ /[0-9]/; end ungetc Token(TkNTH_REF) when /\w/ ungetc ungetc identify_identifier else ungetc Token("$") end end def identify_identifier token = "" if peek(0) =~ /[$@]/ token.concat(c = getc) if c == "@" and peek(0) == "@" token.concat getc end end while (ch = getc) =~ /[^\x00-\/:-@\[-^`{-\x7F]/ print ":", ch, ":" if RubyLex.debug? token.concat ch end ungetc if (ch == "!" || ch == "?") && token[0,1] =~ /\w/ && peek(0) != "=" token.concat getc end # almost fix token case token when /^\$/ return Token(TkGVAR, token) when /^\@\@/ @lex_state = EXPR_END # p Token(TkCVAR, token) return Token(TkCVAR, token) when /^\@/ @lex_state = EXPR_END return Token(TkIVAR, token) end if @lex_state != EXPR_DOT print token, "\n" if RubyLex.debug? token_c, *trans = TkReading2Token[token] if token_c # reserved word? if (@lex_state != EXPR_BEG && @lex_state != EXPR_FNAME && trans[1]) # modifiers token_c = TkSymbol2Token[trans[1]] @lex_state = trans[0] else if @lex_state != EXPR_FNAME and peek(0) != ':' if ENINDENT_CLAUSE.include?(token) # check for ``class = val'' etc. valid = true case token when "class" valid = false unless peek_match?(/^\s*(<<|\w|::)/) when "def" valid = false if peek_match?(/^\s*(([+\-\/*&\|^]|<<|>>|\|\||\&\&)=|\&\&|\|\|)/) when "do" valid = false if peek_match?(/^\s*([+\-\/*]?=|\*|<|>|\&)/) when *ENINDENT_CLAUSE valid = false if peek_match?(/^\s*([+\-\/*]?=|\*|<|>|\&|\|)/) else # no nothing end if valid if token == "do" if ![TkFOR, TkWHILE, TkUNTIL].include?(@indent_stack.last) @indent += 1 @indent_stack.push token_c end else @indent += 1 @indent_stack.push token_c end end elsif DEINDENT_CLAUSE.include?(token) @indent -= 1 @indent_stack.pop end @lex_state = trans[0] else @lex_state = EXPR_END end end return Token(token_c, token) end end if @lex_state == EXPR_FNAME @lex_state = EXPR_END if peek(0) == '=' token.concat getc end elsif @lex_state == EXPR_BEG || @lex_state == EXPR_DOT @lex_state = EXPR_ARG else @lex_state = EXPR_END end if token[0, 1] =~ /[A-Z]/ return Token(TkCONSTANT, token) elsif token[token.size - 1, 1] =~ /[!?]/ return Token(TkFID, token) else return Token(TkIDENTIFIER, token) end end def identify_here_document ch = getc if ch == "-" ch = getc indent = true end if /['"`]/ =~ ch lt = ch quoted = "" while (c = getc) && c != lt quoted.concat c end else lt = '"' quoted = ch.dup while (c = getc) && c =~ /\w/ quoted.concat c end ungetc end ltback, @ltype = @ltype, lt reserve = [] while ch = getc reserve.push ch if ch == "\\" reserve.push ch = getc elsif ch == "\n" break end end @here_header = false line = "" while ch = getc if ch == "\n" if line == quoted break end line = "" else line.concat ch unless indent && line == "" && /\s/ =~ ch if @ltype != "'" && ch == "#" && peek(0) == "{" identify_string_dvar end end end @here_header = true @here_readed.concat reserve while ch = reserve.pop ungetc ch end @ltype = ltback @lex_state = EXPR_END Token(Ltype2Token[lt]) end def identify_quotation ch = getc if lt = PERCENT_LTYPE[ch] ch = getc elsif ch =~ /\W/ lt = "\"" else RubyLex.fail SyntaxError, "unknown type of %string" end @quoted = ch unless @quoted = PERCENT_PAREN[ch] identify_string(lt, @quoted) end def identify_number @lex_state = EXPR_END if peek(0) == "0" && peek(1) !~ /[.eE]/ getc case peek(0) when /[xX]/ ch = getc match = /[0-9a-fA-F_]/ when /[bB]/ ch = getc match = /[01_]/ when /[oO]/ ch = getc match = /[0-7_]/ when /[dD]/ ch = getc match = /[0-9_]/ when /[0-7]/ match = /[0-7_]/ when /[89]/ RubyLex.fail SyntaxError, "Invalid octal digit" else return Token(TkINTEGER) end len0 = true non_digit = false while ch = getc if match =~ ch if ch == "_" if non_digit RubyLex.fail SyntaxError, "trailing `#{ch}' in number" else non_digit = ch end else non_digit = false len0 = false end else ungetc if len0 RubyLex.fail SyntaxError, "numeric literal without digits" end if non_digit RubyLex.fail SyntaxError, "trailing `#{non_digit}' in number" end break end end return Token(TkINTEGER) end type = TkINTEGER allow_point = true allow_e = true non_digit = false while ch = getc case ch when /[0-9]/ non_digit = false when "_" non_digit = ch when allow_point && "." if non_digit RubyLex.fail SyntaxError, "trailing `#{non_digit}' in number" end type = TkFLOAT if peek(0) !~ /[0-9]/ type = TkINTEGER ungetc break end allow_point = false when allow_e && "e", allow_e && "E" if non_digit RubyLex.fail SyntaxError, "trailing `#{non_digit}' in number" end type = TkFLOAT if peek(0) =~ /[+-]/ getc end allow_e = false allow_point = false non_digit = ch else if non_digit RubyLex.fail SyntaxError, "trailing `#{non_digit}' in number" end ungetc break end end Token(type) end def identify_string(ltype, quoted = ltype) @ltype = ltype @quoted = quoted subtype = nil begin nest = 0 while ch = getc if @quoted == ch and nest == 0 break elsif @ltype != "'" && ch == "#" && peek(0) == "{" identify_string_dvar elsif @ltype != "'" && @ltype != "]" && @ltype != ":" and ch == "#" subtype = true elsif ch == '\\' and @ltype == "'" #' case ch = getc when "\\", "\n", "'" else ungetc end elsif ch == '\\' #' read_escape end if PERCENT_PAREN.values.include?(@quoted) if PERCENT_PAREN[ch] == @quoted nest += 1 elsif ch == @quoted nest -= 1 end end end if @ltype == "/" while /[imxoesun]/ =~ peek(0) getc end end if subtype Token(DLtype2Token[ltype]) else Token(Ltype2Token[ltype]) end ensure @ltype = nil @quoted = nil @lex_state = EXPR_END end end def identify_string_dvar begin getc reserve_continue = @continue reserve_ltype = @ltype reserve_indent = @indent reserve_indent_stack = @indent_stack reserve_state = @lex_state reserve_quoted = @quoted @ltype = nil @quoted = nil @indent = 0 @indent_stack = [] @lex_state = EXPR_BEG loop do @continue = false prompt tk = token if @ltype or @continue or @indent >= 0 next end break if tk.kind_of?(TkRBRACE) end ensure @continue = reserve_continue @ltype = reserve_ltype @indent = reserve_indent @indent_stack = reserve_indent_stack @lex_state = reserve_state @quoted = reserve_quoted end end def identify_comment @ltype = "#" while ch = getc if ch == "\n" @ltype = nil ungetc break end end return Token(TkCOMMENT) end def read_escape case ch = getc when "\n", "\r", "\f" when "\\", "n", "t", "r", "f", "v", "a", "e", "b", "s" #" when /[0-7]/ ungetc ch 3.times do case ch = getc when /[0-7]/ when nil break else ungetc break end end when "x" 2.times do case ch = getc when /[0-9a-fA-F]/ when nil break else ungetc break end end when "M" if (ch = getc) != '-' ungetc else if (ch = getc) == "\\" #" read_escape end end when "C", "c" #, "^" if ch == "C" and (ch = getc) != "-" ungetc elsif (ch = getc) == "\\" #" read_escape end else # other characters end end end # :startdoc: PK!#2.2.0/profile.rbnu[require 'profiler' RubyVM::InstructionSequence.compile_option = { :trace_instruction => true, :specialized_instruction => false } END { Profiler__::print_profile(STDERR) } Profiler__::start_profile PK!DzT\ \ 2.2.0/fiddle/value.rbnu[require 'fiddle' module Fiddle module ValueUtil #:nodoc: all def unsigned_value(val, ty) case ty.abs when TYPE_CHAR [val].pack("c").unpack("C")[0] when TYPE_SHORT [val].pack("s!").unpack("S!")[0] when TYPE_INT [val].pack("i!").unpack("I!")[0] when TYPE_LONG [val].pack("l!").unpack("L!")[0] when TYPE_LONG_LONG [val].pack("q").unpack("Q")[0] else val end end def signed_value(val, ty) case ty.abs when TYPE_CHAR [val].pack("C").unpack("c")[0] when TYPE_SHORT [val].pack("S!").unpack("s!")[0] when TYPE_INT [val].pack("I!").unpack("i!")[0] when TYPE_LONG [val].pack("L!").unpack("l!")[0] when TYPE_LONG_LONG [val].pack("Q").unpack("q")[0] else val end end def wrap_args(args, tys, funcs, &block) result = [] tys ||= [] args.each_with_index{|arg, idx| result.push(wrap_arg(arg, tys[idx], funcs, &block)) } result end def wrap_arg(arg, ty, funcs = [], &block) funcs ||= [] case arg when nil return 0 when Pointer return arg.to_i when IO case ty when TYPE_VOIDP return Pointer[arg].to_i else return arg.to_i end when Function if( block ) arg.bind_at_call(&block) funcs.push(arg) elsif !arg.bound? raise(RuntimeError, "block must be given.") end return arg.to_i when String if( ty.is_a?(Array) ) return arg.unpack('C*') else case SIZEOF_VOIDP when SIZEOF_LONG return [arg].pack("p").unpack("l!")[0] when SIZEOF_LONG_LONG return [arg].pack("p").unpack("q")[0] else raise(RuntimeError, "sizeof(void*)?") end end when Float, Integer return arg when Array if( ty.is_a?(Array) ) # used only by struct case ty[0] when TYPE_VOIDP return arg.collect{|v| Integer(v)} when TYPE_CHAR if( arg.is_a?(String) ) return val.unpack('C*') end end return arg else return arg end else if( arg.respond_to?(:to_ptr) ) return arg.to_ptr.to_i else begin return Integer(arg) rescue raise(ArgumentError, "unknown argument type: #{arg.class}") end end end end end end PK!m2.2.0/fiddle/closure.rbnu[module Fiddle class Closure # the C type of the return of the FFI closure attr_reader :ctype # arguments of the FFI closure attr_reader :args # Extends Fiddle::Closure to allow for building the closure in a block class BlockCaller < Fiddle::Closure # == Description # # Construct a new BlockCaller object. # # * +ctype+ is the C type to be returned # * +args+ are passed the callback # * +abi+ is the abi of the closure # # If there is an error in preparing the +ffi_cif+ or +ffi_prep_closure+, # then a RuntimeError will be raised. # # == Example # # include Fiddle # # cb = Closure::BlockCaller.new(TYPE_INT, [TYPE_INT]) do |one| # one # end # # func = Function.new(cb, [TYPE_INT], TYPE_INT) # def initialize ctype, args, abi = Fiddle::Function::DEFAULT, &block super(ctype, args, abi) @block = block end # Calls the constructed BlockCaller, with +args+ # # For an example see Fiddle::Closure::BlockCaller.new # def call *args @block.call(*args) end end end end PK!UPVYY2.2.0/fiddle/types.rbnu[module Fiddle # Adds Windows type aliases to the including class for use with # Fiddle::Importer. # # The aliases added are: # * ATOM # * BOOL # * BYTE # * DWORD # * DWORD32 # * DWORD64 # * HANDLE # * HDC # * HINSTANCE # * HWND # * LPCSTR # * LPSTR # * PBYTE # * PDWORD # * PHANDLE # * PVOID # * PWORD # * UCHAR # * UINT # * ULONG # * WORD module Win32Types def included(m) # :nodoc: m.module_eval{ typealias "DWORD", "unsigned long" typealias "PDWORD", "unsigned long *" typealias "DWORD32", "unsigned long" typealias "DWORD64", "unsigned long long" typealias "WORD", "unsigned short" typealias "PWORD", "unsigned short *" typealias "BOOL", "int" typealias "ATOM", "int" typealias "BYTE", "unsigned char" typealias "PBYTE", "unsigned char *" typealias "UINT", "unsigned int" typealias "ULONG", "unsigned long" typealias "UCHAR", "unsigned char" typealias "HANDLE", "uintptr_t" typealias "PHANDLE", "void*" typealias "PVOID", "void*" typealias "LPCSTR", "char*" typealias "LPSTR", "char*" typealias "HINSTANCE", "unsigned int" typealias "HDC", "unsigned int" typealias "HWND", "unsigned int" } end module_function :included end # Adds basic type aliases to the including class for use with Fiddle::Importer. # # The aliases added are +uint+ and +u_int+ (unsigned int) and # +ulong+ and +u_long+ (unsigned long) module BasicTypes def included(m) # :nodoc: m.module_eval{ typealias "uint", "unsigned int" typealias "u_int", "unsigned int" typealias "ulong", "unsigned long" typealias "u_long", "unsigned long" } end module_function :included end end PK!2.2.0/fiddle/cparser.rbnu[module Fiddle # A mixin that provides methods for parsing C struct and prototype signatures. # # == Example # require 'fiddle/import' # # include Fiddle::CParser # #=> Object # # parse_ctype('int increment(int)') # #=> ["increment", Fiddle::TYPE_INT, [Fiddle::TYPE_INT]] # module CParser # Parses a C struct's members # # Example: # # include Fiddle::CParser # #=> Object # # parse_struct_signature(['int i', 'char c']) # #=> [[Fiddle::TYPE_INT, Fiddle::TYPE_CHAR], ["i", "c"]] # def parse_struct_signature(signature, tymap=nil) if( signature.is_a?(String) ) signature = signature.split(/\s*,\s*/) end mems = [] tys = [] signature.each{|msig| tks = msig.split(/\s+(\*)?/) ty = tks[0..-2].join(" ") member = tks[-1] case ty when /\[(\d+)\]/ n = $1.to_i ty.gsub!(/\s*\[\d+\]/,"") ty = [ty, n] when /\[\]/ ty.gsub!(/\s*\[\]/, "*") end case member when /\[(\d+)\]/ ty = [ty, $1.to_i] member.gsub!(/\s*\[\d+\]/,"") when /\[\]/ ty = ty + "*" member.gsub!(/\s*\[\]/, "") end mems.push(member) tys.push(parse_ctype(ty,tymap)) } return tys, mems end # Parses a C prototype signature # # If Hash +tymap+ is provided, the return value and the arguments from the # +signature+ are expected to be keys, and the value will be the C type to # be looked up. # # Example: # # include Fiddle::CParser # #=> Object # # parse_signature('double sum(double, double)') # #=> ["sum", Fiddle::TYPE_DOUBLE, [Fiddle::TYPE_DOUBLE, Fiddle::TYPE_DOUBLE]] # def parse_signature(signature, tymap=nil) tymap ||= {} signature = signature.gsub(/\s+/, " ").strip case signature when /^([\w@\*\s]+)\(([\w\*\s\,\[\]]*)\)$/ ret = $1 (args = $2).strip! ret = ret.split(/\s+/) args = args.split(/\s*,\s*/) func = ret.pop if( func =~ /^\*/ ) func.gsub!(/^\*+/,"") ret.push("*") end ret = ret.join(" ") return [func, parse_ctype(ret, tymap), args.collect{|arg| parse_ctype(arg, tymap)}] else raise(RuntimeError,"can't parse the function prototype: #{signature}") end end # Given a String of C type +ty+, returns the corresponding Fiddle constant. # # +ty+ can also accept an Array of C type Strings, and will be returned in # a corresponding Array. # # If Hash +tymap+ is provided, +ty+ is expected to be the key, and the # value will be the C type to be looked up. # # Example: # # include Fiddle::CParser # #=> Object # # parse_ctype('int') # #=> Fiddle::TYPE_INT # # parse_ctype('double') # #=> Fiddle::TYPE_DOUBLE # # parse_ctype('unsigned char') # #=> -Fiddle::TYPE_CHAR # def parse_ctype(ty, tymap=nil) tymap ||= {} case ty when Array return [parse_ctype(ty[0], tymap), ty[1]] when "void" return TYPE_VOID when "char" return TYPE_CHAR when "unsigned char" return -TYPE_CHAR when "short" return TYPE_SHORT when "unsigned short" return -TYPE_SHORT when "int" return TYPE_INT when "unsigned int", 'uint' return -TYPE_INT when "long" return TYPE_LONG when "unsigned long" return -TYPE_LONG when "long long" if( defined?(TYPE_LONG_LONG) ) return TYPE_LONG_LONG else raise(RuntimeError, "unsupported type: #{ty}") end when "unsigned long long" if( defined?(TYPE_LONG_LONG) ) return -TYPE_LONG_LONG else raise(RuntimeError, "unsupported type: #{ty}") end when "float" return TYPE_FLOAT when "double" return TYPE_DOUBLE when "size_t" return TYPE_SIZE_T when "ssize_t" return TYPE_SSIZE_T when "ptrdiff_t" return TYPE_PTRDIFF_T when "intptr_t" return TYPE_INTPTR_T when "uintptr_t" return TYPE_UINTPTR_T when /\*/, /\[\s*\]/ return TYPE_VOIDP else if( tymap[ty] ) return parse_ctype(tymap[ty], tymap) else raise(DLError, "unknown type: #{ty}") end end end end end PK!|Xb"b"2.2.0/fiddle/import.rbnu[require 'fiddle' require 'fiddle/struct' require 'fiddle/cparser' module Fiddle # Used internally by Fiddle::Importer class CompositeHandler # Create a new handler with the open +handlers+ # # Used internally by Fiddle::Importer.dlload def initialize(handlers) @handlers = handlers end # Array of the currently loaded libraries. def handlers() @handlers end # Returns the address as an Integer from any handlers with the function # named +symbol+. # # Raises a DLError if the handle is closed. def sym(symbol) @handlers.each{|handle| if( handle ) begin addr = handle.sym(symbol) return addr rescue DLError end end } return nil end # See Fiddle::CompositeHandler.sym def [](symbol) sym(symbol) end end # A DSL that provides the means to dynamically load libraries and build # modules around them including calling extern functions within the C # library that has been loaded. # # == Example # # require 'fiddle' # require 'fiddle/import' # # module LibSum # extend Fiddle::Importer # dlload './libsum.so' # extern 'double sum(double*, int)' # extern 'double split(double)' # end # module Importer include Fiddle include CParser extend Importer # Creates an array of handlers for the given +libs+, can be an instance of # Fiddle::Handle, Fiddle::Importer, or will create a new instance of # Fiddle::Handle using Fiddle.dlopen # # Raises a DLError if the library cannot be loaded. # # See Fiddle.dlopen def dlload(*libs) handles = libs.collect{|lib| case lib when nil nil when Handle lib when Importer lib.handlers else begin Fiddle.dlopen(lib) rescue DLError raise(DLError, "can't load #{lib}") end end }.flatten() @handler = CompositeHandler.new(handles) @func_map = {} @type_alias = {} end # Sets the type alias for +alias_type+ as +orig_type+ def typealias(alias_type, orig_type) @type_alias[alias_type] = orig_type end # Returns the sizeof +ty+, using Fiddle::Importer.parse_ctype to determine # the C type and the appropriate Fiddle constant. def sizeof(ty) case ty when String ty = parse_ctype(ty, @type_alias).abs() case ty when TYPE_CHAR return SIZEOF_CHAR when TYPE_SHORT return SIZEOF_SHORT when TYPE_INT return SIZEOF_INT when TYPE_LONG return SIZEOF_LONG when TYPE_LONG_LONG return SIZEOF_LONG_LONG when TYPE_FLOAT return SIZEOF_FLOAT when TYPE_DOUBLE return SIZEOF_DOUBLE when TYPE_VOIDP return SIZEOF_VOIDP else raise(DLError, "unknown type: #{ty}") end when Class if( ty.instance_methods().include?(:to_ptr) ) return ty.size() end end return Pointer[ty].size() end def parse_bind_options(opts) h = {} while( opt = opts.shift() ) case opt when :stdcall, :cdecl h[:call_type] = opt when :carried, :temp, :temporal, :bind h[:callback_type] = opt h[:carrier] = opts.shift() else h[opt] = true end end h end private :parse_bind_options # :stopdoc: CALL_TYPE_TO_ABI = Hash.new { |h, k| raise RuntimeError, "unsupported call type: #{k}" }.merge({ :stdcall => (Function::STDCALL rescue Function::DEFAULT), :cdecl => Function::DEFAULT, nil => Function::DEFAULT }).freeze private_constant :CALL_TYPE_TO_ABI # :startdoc: # Creates a global method from the given C +signature+. def extern(signature, *opts) symname, ctype, argtype = parse_signature(signature, @type_alias) opt = parse_bind_options(opts) f = import_function(symname, ctype, argtype, opt[:call_type]) name = symname.gsub(/@.+/,'') @func_map[name] = f # define_method(name){|*args,&block| f.call(*args,&block)} begin /^(.+?):(\d+)/ =~ caller.first file, line = $1, $2.to_i rescue file, line = __FILE__, __LINE__+3 end module_eval(<<-EOS, file, line) def #{name}(*args, &block) @func_map['#{name}'].call(*args,&block) end EOS module_function(name) f end # Creates a global method from the given C +signature+ using the given # +opts+ as bind parameters with the given block. def bind(signature, *opts, &blk) name, ctype, argtype = parse_signature(signature, @type_alias) h = parse_bind_options(opts) case h[:callback_type] when :bind, nil f = bind_function(name, ctype, argtype, h[:call_type], &blk) else raise(RuntimeError, "unknown callback type: #{h[:callback_type]}") end @func_map[name] = f #define_method(name){|*args,&block| f.call(*args,&block)} begin /^(.+?):(\d+)/ =~ caller.first file, line = $1, $2.to_i rescue file, line = __FILE__, __LINE__+3 end module_eval(<<-EOS, file, line) def #{name}(*args,&block) @func_map['#{name}'].call(*args,&block) end EOS module_function(name) f end # Creates a class to wrap the C struct described by +signature+. # # MyStruct = struct ['int i', 'char c'] def struct(signature) tys, mems = parse_struct_signature(signature, @type_alias) Fiddle::CStructBuilder.create(CStruct, tys, mems) end # Creates a class to wrap the C union described by +signature+. # # MyUnion = union ['int i', 'char c'] def union(signature) tys, mems = parse_struct_signature(signature, @type_alias) Fiddle::CStructBuilder.create(CUnion, tys, mems) end # Returns the function mapped to +name+, that was created by either # Fiddle::Importer.extern or Fiddle::Importer.bind def [](name) @func_map[name] end # Creates a class to wrap the C struct with the value +ty+ # # See also Fiddle::Importer.struct def create_value(ty, val=nil) s = struct([ty + " value"]) ptr = s.malloc() if( val ) ptr.value = val end return ptr end alias value create_value # Returns a new instance of the C struct with the value +ty+ at the +addr+ # address. def import_value(ty, addr) s = struct([ty + " value"]) ptr = s.new(addr) return ptr end # The Fiddle::CompositeHandler instance # # Will raise an error if no handlers are open. def handler @handler or raise "call dlload before importing symbols and functions" end # Returns a new Fiddle::Pointer instance at the memory address of the given # +name+ symbol. # # Raises a DLError if the +name+ doesn't exist. # # See Fiddle::CompositeHandler.sym and Fiddle::Handle.sym def import_symbol(name) addr = handler.sym(name) if( !addr ) raise(DLError, "cannot find the symbol: #{name}") end Pointer.new(addr) end # Returns a new Fiddle::Function instance at the memory address of the given # +name+ function. # # Raises a DLError if the +name+ doesn't exist. # # * +argtype+ is an Array of arguments, passed to the +name+ function. # * +ctype+ is the return type of the function # * +call_type+ is the ABI of the function # # See also Fiddle:Function.new # # See Fiddle::CompositeHandler.sym and Fiddle::Handler.sym def import_function(name, ctype, argtype, call_type = nil) addr = handler.sym(name) if( !addr ) raise(DLError, "cannot find the function: #{name}()") end Function.new(addr, argtype, ctype, CALL_TYPE_TO_ABI[call_type], name: name) end # Returns a new closure wrapper for the +name+ function. # # * +ctype+ is the return type of the function # * +argtype+ is an Array of arguments, passed to the callback function # * +call_type+ is the abi of the closure # * +block+ is passed to the callback # # See Fiddle::Closure def bind_function(name, ctype, argtype, call_type = nil, &block) abi = CALL_TYPE_TO_ABI[call_type] closure = Class.new(Fiddle::Closure) { define_method(:call, block) }.new(ctype, argtype, abi) Function.new(closure, argtype, ctype, abi, name: name) end end end PK!У%%2.2.0/fiddle/function.rbnu[module Fiddle class Function # The ABI of the Function. attr_reader :abi # The address of this function attr_reader :ptr # The name of this function attr_reader :name # The integer memory location of this function def to_i ptr.to_i end end end PK!Nں 2.2.0/fiddle/pack.rbnu[require 'fiddle' module Fiddle module PackInfo # :nodoc: all ALIGN_MAP = { TYPE_VOIDP => ALIGN_VOIDP, TYPE_CHAR => ALIGN_CHAR, TYPE_SHORT => ALIGN_SHORT, TYPE_INT => ALIGN_INT, TYPE_LONG => ALIGN_LONG, TYPE_FLOAT => ALIGN_FLOAT, TYPE_DOUBLE => ALIGN_DOUBLE, -TYPE_CHAR => ALIGN_CHAR, -TYPE_SHORT => ALIGN_SHORT, -TYPE_INT => ALIGN_INT, -TYPE_LONG => ALIGN_LONG, } PACK_MAP = { TYPE_VOIDP => ((SIZEOF_VOIDP == SIZEOF_LONG_LONG) ? "q" : "l!"), TYPE_CHAR => "c", TYPE_SHORT => "s!", TYPE_INT => "i!", TYPE_LONG => "l!", TYPE_FLOAT => "f", TYPE_DOUBLE => "d", -TYPE_CHAR => "c", -TYPE_SHORT => "s!", -TYPE_INT => "i!", -TYPE_LONG => "l!", } SIZE_MAP = { TYPE_VOIDP => SIZEOF_VOIDP, TYPE_CHAR => SIZEOF_CHAR, TYPE_SHORT => SIZEOF_SHORT, TYPE_INT => SIZEOF_INT, TYPE_LONG => SIZEOF_LONG, TYPE_FLOAT => SIZEOF_FLOAT, TYPE_DOUBLE => SIZEOF_DOUBLE, -TYPE_CHAR => SIZEOF_CHAR, -TYPE_SHORT => SIZEOF_SHORT, -TYPE_INT => SIZEOF_INT, -TYPE_LONG => SIZEOF_LONG, } if defined?(TYPE_LONG_LONG) ALIGN_MAP[TYPE_LONG_LONG] = ALIGN_MAP[-TYPE_LONG_LONG] = ALIGN_LONG_LONG PACK_MAP[TYPE_LONG_LONG] = PACK_MAP[-TYPE_LONG_LONG] = "q" SIZE_MAP[TYPE_LONG_LONG] = SIZE_MAP[-TYPE_LONG_LONG] = SIZEOF_LONG_LONG end def align(addr, align) d = addr % align if( d == 0 ) addr else addr + (align - d) end end module_function :align end class Packer # :nodoc: all include PackInfo def self.[](*types) new(types) end def initialize(types) parse_types(types) end def size() @size end def pack(ary) case SIZEOF_VOIDP when SIZEOF_LONG ary.pack(@template) when SIZEOF_LONG_LONG ary.pack(@template) else raise(RuntimeError, "sizeof(void*)?") end end def unpack(ary) case SIZEOF_VOIDP when SIZEOF_LONG ary.join().unpack(@template) when SIZEOF_LONG_LONG ary.join().unpack(@template) else raise(RuntimeError, "sizeof(void*)?") end end private def parse_types(types) @template = "" addr = 0 types.each{|t| orig_addr = addr if( t.is_a?(Array) ) addr = align(orig_addr, ALIGN_MAP[TYPE_VOIDP]) else addr = align(orig_addr, ALIGN_MAP[t]) end d = addr - orig_addr if( d > 0 ) @template << "x#{d}" end if( t.is_a?(Array) ) @template << (PACK_MAP[t[0]] * t[1]) addr += (SIZE_MAP[t[0]] * t[1]) else @template << PACK_MAP[t] addr += SIZE_MAP[t] end } addr = align(addr, ALIGN_MAP[TYPE_VOIDP]) @size = addr end end end PK!GGG2.2.0/fiddle/struct.rbnu[require 'fiddle' require 'fiddle/value' require 'fiddle/pack' module Fiddle # C struct shell class CStruct # accessor to Fiddle::CStructEntity def CStruct.entity_class CStructEntity end end # C union shell class CUnion # accessor to Fiddle::CUnionEntity def CUnion.entity_class CUnionEntity end end # Used to construct C classes (CUnion, CStruct, etc) # # Fiddle::Importer#struct and Fiddle::Importer#union wrap this functionality in an # easy-to-use manner. module CStructBuilder # Construct a new class given a C: # * class +klass+ (CUnion, CStruct, or other that provide an # #entity_class) # * +types+ (Fiddle::TYPE_INT, Fiddle::TYPE_SIZE_T, etc., see the C types # constants) # * corresponding +members+ # # Fiddle::Importer#struct and Fiddle::Importer#union wrap this functionality in an # easy-to-use manner. # # Example: # # require 'fiddle/struct' # require 'fiddle/cparser' # # include Fiddle::CParser # # types, members = parse_struct_signature(['int i','char c']) # # MyStruct = Fiddle::CStructBuilder.create(Fiddle::CUnion, types, members) # # obj = MyStruct.allocate # def create(klass, types, members) new_class = Class.new(klass){ define_method(:initialize){|addr| @entity = klass.entity_class.new(addr, types) @entity.assign_names(members) } define_method(:to_ptr){ @entity } define_method(:to_i){ @entity.to_i } members.each{|name| define_method(name){ @entity[name] } define_method(name + "="){|val| @entity[name] = val } } } size = klass.entity_class.size(types) new_class.module_eval(<<-EOS, __FILE__, __LINE__+1) def new_class.size() #{size} end def new_class.malloc() addr = Fiddle.malloc(#{size}) new(addr) end EOS return new_class end module_function :create end # A C struct wrapper class CStructEntity < Fiddle::Pointer include PackInfo include ValueUtil # Allocates a C struct with the +types+ provided. # # When the instance is garbage collected, the C function +func+ is called. def CStructEntity.malloc(types, func = nil) addr = Fiddle.malloc(CStructEntity.size(types)) CStructEntity.new(addr, types, func) end # Returns the offset for the packed sizes for the given +types+. # # Fiddle::CStructEntity.size( # [ Fiddle::TYPE_DOUBLE, # Fiddle::TYPE_INT, # Fiddle::TYPE_CHAR, # Fiddle::TYPE_VOIDP ]) #=> 24 def CStructEntity.size(types) offset = 0 max_align = types.map { |type, count = 1| last_offset = offset align = PackInfo::ALIGN_MAP[type] offset = PackInfo.align(last_offset, align) + (PackInfo::SIZE_MAP[type] * count) align }.max PackInfo.align(offset, max_align) end # Wraps the C pointer +addr+ as a C struct with the given +types+. # # When the instance is garbage collected, the C function +func+ is called. # # See also Fiddle::Pointer.new def initialize(addr, types, func = nil) set_ctypes(types) super(addr, @size, func) end # Set the names of the +members+ in this C struct def assign_names(members) @members = members end # Calculates the offsets and sizes for the given +types+ in the struct. def set_ctypes(types) @ctypes = types @offset = [] offset = 0 max_align = types.map { |type, count = 1| orig_offset = offset align = ALIGN_MAP[type] offset = PackInfo.align(orig_offset, align) @offset << offset offset += (SIZE_MAP[type] * count) align }.max @size = PackInfo.align(offset, max_align) end # Fetch struct member +name+ def [](name) idx = @members.index(name) if( idx.nil? ) raise(ArgumentError, "no such member: #{name}") end ty = @ctypes[idx] if( ty.is_a?(Array) ) r = super(@offset[idx], SIZE_MAP[ty[0]] * ty[1]) else r = super(@offset[idx], SIZE_MAP[ty.abs]) end packer = Packer.new([ty]) val = packer.unpack([r]) case ty when Array case ty[0] when TYPE_VOIDP val = val.collect{|v| Pointer.new(v)} end when TYPE_VOIDP val = Pointer.new(val[0]) else val = val[0] end if( ty.is_a?(Integer) && (ty < 0) ) return unsigned_value(val, ty) elsif( ty.is_a?(Array) && (ty[0] < 0) ) return val.collect{|v| unsigned_value(v,ty[0])} else return val end end # Set struct member +name+, to value +val+ def []=(name, val) idx = @members.index(name) if( idx.nil? ) raise(ArgumentError, "no such member: #{name}") end ty = @ctypes[idx] packer = Packer.new([ty]) val = wrap_arg(val, ty, []) buff = packer.pack([val].flatten()) super(@offset[idx], buff.size, buff) if( ty.is_a?(Integer) && (ty < 0) ) return unsigned_value(val, ty) elsif( ty.is_a?(Array) && (ty[0] < 0) ) return val.collect{|v| unsigned_value(v,ty[0])} else return val end end def to_s() # :nodoc: super(@size) end end # A C union wrapper class CUnionEntity < CStructEntity include PackInfo # Allocates a C union the +types+ provided. # # When the instance is garbage collected, the C function +func+ is called. def CUnionEntity.malloc(types, func=nil) addr = Fiddle.malloc(CUnionEntity.size(types)) CUnionEntity.new(addr, types, func) end # Returns the size needed for the union with the given +types+. # # Fiddle::CUnionEntity.size( # [ Fiddle::TYPE_DOUBLE, # Fiddle::TYPE_INT, # Fiddle::TYPE_CHAR, # Fiddle::TYPE_VOIDP ]) #=> 8 def CUnionEntity.size(types) types.map { |type, count = 1| PackInfo::SIZE_MAP[type] * count }.max end # Calculate the necessary offset and for each union member with the given # +types+ def set_ctypes(types) @ctypes = types @offset = Array.new(types.length, 0) @size = self.class.size types end end end PK!-2.2.0/optparse/version.rbnu[# OptionParser internal utility class << OptionParser def show_version(*pkgs) progname = ARGV.options.program_name result = false show = proc do |klass, cname, version| str = "#{progname}" unless klass == ::Object and cname == :VERSION version = version.join(".") if Array === version str << ": #{klass}" unless klass == Object str << " version #{version}" end [:Release, :RELEASE].find do |rel| if klass.const_defined?(rel) str << " (#{klass.const_get(rel)})" end end puts str result = true end if pkgs.size == 1 and pkgs[0] == "all" self.search_const(::Object, /\AV(?:ERSION|ersion)\z/) do |klass, cname, version| unless cname[1] == ?e and klass.const_defined?(:Version) show.call(klass, cname.intern, version) end end else pkgs.each do |pkg| begin pkg = pkg.split(/::|\//).inject(::Object) {|m, c| m.const_get(c)} v = case when pkg.const_defined?(:Version) pkg.const_get(n = :Version) when pkg.const_defined?(:VERSION) pkg.const_get(n = :VERSION) else n = nil "unknown" end show.call(pkg, n, v) rescue NameError end end end result end def each_const(path, base = ::Object) path.split(/::|\//).inject(base) do |klass, name| raise NameError, path unless Module === klass klass.constants.grep(/#{name}/i) do |c| klass.const_defined?(c) or next klass.const_get(c) end end end def search_const(klass, name) klasses = [klass] while klass = klasses.shift klass.constants.each do |cname| klass.const_defined?(cname) or next const = klass.const_get(cname) yield klass, cname, const if name === cname klasses << const if Module === const and const != ::Object end end end end PK![hzdd2.2.0/optparse/uri.rbnu[# -*- ruby -*- require 'optparse' require 'uri' OptionParser.accept(URI) {|s,| URI.parse(s) if s} PK!Zvvyy2.2.0/optparse/shellwords.rbnu[# -*- ruby -*- require 'shellwords' require 'optparse' OptionParser.accept(Shellwords) {|s,| Shellwords.shellwords(s)} PK!;EE2.2.0/optparse/date.rbnu[require 'optparse' require 'date' OptionParser.accept(DateTime) do |s,| begin DateTime.parse(s) if s rescue ArgumentError raise OptionParser::InvalidArgument, s end end OptionParser.accept(Date) do |s,| begin Date.parse(s) if s rescue ArgumentError raise OptionParser::InvalidArgument, s end end PK!7&2.2.0/optparse/time.rbnu[require 'optparse' require 'time' OptionParser.accept(Time) do |s,| begin (Time.httpdate(s) rescue Time.parse(s)) if s rescue raise OptionParser::InvalidArgument, s end end PK!Ip||2.2.0/optparse/ac.rbnu[require 'optparse' class OptionParser::AC < OptionParser private def _check_ac_args(name, block) unless /\A\w[-\w]*\z/ =~ name raise ArgumentError, name end unless block raise ArgumentError, "no block given", ParseError.filter_backtrace(caller) end end def _ac_arg_enable(prefix, name, help_string, block) _check_ac_args(name, block) sdesc = [] ldesc = ["--#{prefix}-#{name}"] desc = [help_string] q = name.downcase enable = Switch::NoArgument.new(nil, proc {true}, sdesc, ldesc, nil, desc, block) disable = Switch::NoArgument.new(nil, proc {false}, sdesc, ldesc, nil, desc, block) top.append(enable, [], ["enable-" + q], disable, ['disable-' + q]) enable end public def ac_arg_enable(name, help_string, &block) _ac_arg_enable("enable", name, help_string, block) end def ac_arg_disable(name, help_string, &block) _ac_arg_enable("disable", name, help_string, block) end def ac_arg_with(name, help_string, &block) _check_ac_args(name, block) sdesc = [] ldesc = ["--with-#{name}"] desc = [help_string] q = name.downcase with = Switch::PlacedArgument.new(*search(:atype, String), sdesc, ldesc, nil, desc, block) without = Switch::NoArgument.new(nil, proc {}, sdesc, ldesc, nil, desc, block) top.append(with, [], ["with-" + q], without, ['without-' + q]) with end end PK!NywM>M>2.2.0/pathname.rbnu[# # = pathname.rb # # Object-Oriented Pathname Class # # Author:: Tanaka Akira # Documentation:: Author and Gavin Sinclair # # For documentation, see class Pathname. # require 'pathname.so' class Pathname # :stopdoc: if RUBY_VERSION < "1.9" TO_PATH = :to_str else # to_path is implemented so Pathname objects are usable with File.open, etc. TO_PATH = :to_path end SAME_PATHS = if File::FNM_SYSCASE.nonzero? # Avoid #zero? here because #casecmp can return nil. proc {|a, b| a.casecmp(b) == 0} else proc {|a, b| a == b} end if File::ALT_SEPARATOR SEPARATOR_LIST = "#{Regexp.quote File::ALT_SEPARATOR}#{Regexp.quote File::SEPARATOR}" SEPARATOR_PAT = /[#{SEPARATOR_LIST}]/ else SEPARATOR_LIST = "#{Regexp.quote File::SEPARATOR}" SEPARATOR_PAT = /#{Regexp.quote File::SEPARATOR}/ end # :startdoc: # chop_basename(path) -> [pre-basename, basename] or nil def chop_basename(path) # :nodoc: base = File.basename(path) if /\A#{SEPARATOR_PAT}?\z/o =~ base return nil else return path[0, path.rindex(base)], base end end private :chop_basename # split_names(path) -> prefix, [name, ...] def split_names(path) # :nodoc: names = [] while r = chop_basename(path) path, basename = r names.unshift basename end return path, names end private :split_names def prepend_prefix(prefix, relpath) # :nodoc: if relpath.empty? File.dirname(prefix) elsif /#{SEPARATOR_PAT}/o =~ prefix prefix = File.dirname(prefix) prefix = File.join(prefix, "") if File.basename(prefix + 'a') != 'a' prefix + relpath else prefix + relpath end end private :prepend_prefix # Returns clean pathname of +self+ with consecutive slashes and useless dots # removed. The filesystem is not accessed. # # If +consider_symlink+ is +true+, then a more conservative algorithm is used # to avoid breaking symbolic linkages. This may retain more +..+ # entries than absolutely necessary, but without accessing the filesystem, # this can't be avoided. # # See Pathname#realpath. # def cleanpath(consider_symlink=false) if consider_symlink cleanpath_conservative else cleanpath_aggressive end end # # Clean the path simply by resolving and removing excess +.+ and +..+ entries. # Nothing more, nothing less. # def cleanpath_aggressive # :nodoc: path = @path names = [] pre = path while r = chop_basename(pre) pre, base = r case base when '.' when '..' names.unshift base else if names[0] == '..' names.shift else names.unshift base end end end pre.tr!(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR if /#{SEPARATOR_PAT}/o =~ File.basename(pre) names.shift while names[0] == '..' end self.class.new(prepend_prefix(pre, File.join(*names))) end private :cleanpath_aggressive # has_trailing_separator?(path) -> bool def has_trailing_separator?(path) # :nodoc: if r = chop_basename(path) pre, basename = r pre.length + basename.length < path.length else false end end private :has_trailing_separator? # add_trailing_separator(path) -> path def add_trailing_separator(path) # :nodoc: if File.basename(path + 'a') == 'a' path else File.join(path, "") # xxx: Is File.join is appropriate to add separator? end end private :add_trailing_separator def del_trailing_separator(path) # :nodoc: if r = chop_basename(path) pre, basename = r pre + basename elsif /#{SEPARATOR_PAT}+\z/o =~ path $` + File.dirname(path)[/#{SEPARATOR_PAT}*\z/o] else path end end private :del_trailing_separator def cleanpath_conservative # :nodoc: path = @path names = [] pre = path while r = chop_basename(pre) pre, base = r names.unshift base if base != '.' end pre.tr!(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR if /#{SEPARATOR_PAT}/o =~ File.basename(pre) names.shift while names[0] == '..' end if names.empty? self.class.new(File.dirname(pre)) else if names.last != '..' && File.basename(path) == '.' names << '.' end result = prepend_prefix(pre, File.join(*names)) if /\A(?:\.|\.\.)\z/ !~ names.last && has_trailing_separator?(path) self.class.new(add_trailing_separator(result)) else self.class.new(result) end end end private :cleanpath_conservative # Returns the parent directory. # # This is same as self + '..'. def parent self + '..' end # Returns +true+ if +self+ points to a mountpoint. def mountpoint? begin stat1 = self.lstat stat2 = self.parent.lstat stat1.dev == stat2.dev && stat1.ino == stat2.ino || stat1.dev != stat2.dev rescue Errno::ENOENT false end end # # Predicate method for root directories. Returns +true+ if the # pathname consists of consecutive slashes. # # It doesn't access the filesystem. So it may return +false+ for some # pathnames which points to roots such as /usr/... # def root? !!(chop_basename(@path) == nil && /#{SEPARATOR_PAT}/o =~ @path) end # Predicate method for testing whether a path is absolute. # # It returns +true+ if the pathname begins with a slash. # # p = Pathname.new('/im/sure') # p.absolute? # #=> true # # p = Pathname.new('not/so/sure') # p.absolute? # #=> false def absolute? !relative? end # The opposite of Pathname#absolute? # # It returns +false+ if the pathname begins with a slash. # # p = Pathname.new('/im/sure') # p.relative? # #=> false # # p = Pathname.new('not/so/sure') # p.relative? # #=> true def relative? path = @path while r = chop_basename(path) path, = r end path == '' end # # Iterates over each component of the path. # # Pathname.new("/usr/bin/ruby").each_filename {|filename| ... } # # yields "usr", "bin", and "ruby". # # Returns an Enumerator if no block was given. # # enum = Pathname.new("/usr/bin/ruby").each_filename # # ... do stuff ... # enum.each { |e| ... } # # yields "usr", "bin", and "ruby". # def each_filename # :yield: filename return to_enum(__method__) unless block_given? _, names = split_names(@path) names.each {|filename| yield filename } nil end # Iterates over and yields a new Pathname object # for each element in the given path in descending order. # # Pathname.new('/path/to/some/file.rb').descend {|v| p v} # # # # # # # # # # # # Pathname.new('path/to/some/file.rb').descend {|v| p v} # # # # # # # # # # It doesn't access the filesystem. # def descend vs = [] ascend {|v| vs << v } vs.reverse_each {|v| yield v } nil end # Iterates over and yields a new Pathname object # for each element in the given path in ascending order. # # Pathname.new('/path/to/some/file.rb').ascend {|v| p v} # # # # # # # # # # # # Pathname.new('path/to/some/file.rb').ascend {|v| p v} # # # # # # # # # # It doesn't access the filesystem. # def ascend path = @path yield self while r = chop_basename(path) path, = r break if path.empty? yield self.class.new(del_trailing_separator(path)) end end # # Appends a pathname fragment to +self+ to produce a new Pathname object. # # p1 = Pathname.new("/usr") # Pathname:/usr # p2 = p1 + "bin/ruby" # Pathname:/usr/bin/ruby # p3 = p1 + "/etc/passwd" # Pathname:/etc/passwd # # # / is aliased to +. # p4 = p1 / "bin/ruby" # Pathname:/usr/bin/ruby # p5 = p1 / "/etc/passwd" # Pathname:/etc/passwd # # This method doesn't access the file system; it is pure string manipulation. # def +(other) other = Pathname.new(other) unless Pathname === other Pathname.new(plus(@path, other.to_s)) end alias / + def plus(path1, path2) # -> path # :nodoc: prefix2 = path2 index_list2 = [] basename_list2 = [] while r2 = chop_basename(prefix2) prefix2, basename2 = r2 index_list2.unshift prefix2.length basename_list2.unshift basename2 end return path2 if prefix2 != '' prefix1 = path1 while true while !basename_list2.empty? && basename_list2.first == '.' index_list2.shift basename_list2.shift end break unless r1 = chop_basename(prefix1) prefix1, basename1 = r1 next if basename1 == '.' if basename1 == '..' || basename_list2.empty? || basename_list2.first != '..' prefix1 = prefix1 + basename1 break end index_list2.shift basename_list2.shift end r1 = chop_basename(prefix1) if !r1 && /#{SEPARATOR_PAT}/o =~ File.basename(prefix1) while !basename_list2.empty? && basename_list2.first == '..' index_list2.shift basename_list2.shift end end if !basename_list2.empty? suffix2 = path2[index_list2.first..-1] r1 ? File.join(prefix1, suffix2) : prefix1 + suffix2 else r1 ? prefix1 : File.dirname(prefix1) end end private :plus # # Joins the given pathnames onto +self+ to create a new Pathname object. # # path0 = Pathname.new("/usr") # Pathname:/usr # path0 = path0.join("bin/ruby") # Pathname:/usr/bin/ruby # # is the same as # path1 = Pathname.new("/usr") + "bin/ruby" # Pathname:/usr/bin/ruby # path0 == path1 # #=> true # def join(*args) return self if args.empty? result = args.pop result = Pathname.new(result) unless Pathname === result return result if result.absolute? args.reverse_each {|arg| arg = Pathname.new(arg) unless Pathname === arg result = arg + result return result if result.absolute? } self + result end # # Returns the children of the directory (files and subdirectories, not # recursive) as an array of Pathname objects. # # By default, the returned pathnames will have enough information to access # the files. If you set +with_directory+ to +false+, then the returned # pathnames will contain the filename only. # # For example: # pn = Pathname("/usr/lib/ruby/1.8") # pn.children # # -> [ Pathname:/usr/lib/ruby/1.8/English.rb, # Pathname:/usr/lib/ruby/1.8/Env.rb, # Pathname:/usr/lib/ruby/1.8/abbrev.rb, ... ] # pn.children(false) # # -> [ Pathname:English.rb, Pathname:Env.rb, Pathname:abbrev.rb, ... ] # # Note that the results never contain the entries +.+ and +..+ in # the directory because they are not children. # def children(with_directory=true) with_directory = false if @path == '.' result = [] Dir.foreach(@path) {|e| next if e == '.' || e == '..' if with_directory result << self.class.new(File.join(@path, e)) else result << self.class.new(e) end } result end # Iterates over the children of the directory # (files and subdirectories, not recursive). # # It yields Pathname object for each child. # # By default, the yielded pathnames will have enough information to access # the files. # # If you set +with_directory+ to +false+, then the returned pathnames will # contain the filename only. # # Pathname("/usr/local").each_child {|f| p f } # #=> # # # # # # # # # # # # # # # # # # # # # # # # Pathname("/usr/local").each_child(false) {|f| p f } # #=> # # # # # # # # # # # # # # # # # # # # # # # # Note that the results never contain the entries +.+ and +..+ in # the directory because they are not children. # # See Pathname#children # def each_child(with_directory=true, &b) children(with_directory).each(&b) end # # Returns a relative path from the given +base_directory+ to the receiver. # # If +self+ is absolute, then +base_directory+ must be absolute too. # # If +self+ is relative, then +base_directory+ must be relative too. # # This method doesn't access the filesystem. It assumes no symlinks. # # ArgumentError is raised when it cannot find a relative path. # def relative_path_from(base_directory) dest_directory = self.cleanpath.to_s base_directory = base_directory.cleanpath.to_s dest_prefix = dest_directory dest_names = [] while r = chop_basename(dest_prefix) dest_prefix, basename = r dest_names.unshift basename if basename != '.' end base_prefix = base_directory base_names = [] while r = chop_basename(base_prefix) base_prefix, basename = r base_names.unshift basename if basename != '.' end unless SAME_PATHS[dest_prefix, base_prefix] raise ArgumentError, "different prefix: #{dest_prefix.inspect} and #{base_directory.inspect}" end while !dest_names.empty? && !base_names.empty? && SAME_PATHS[dest_names.first, base_names.first] dest_names.shift base_names.shift end if base_names.include? '..' raise ArgumentError, "base_directory has ..: #{base_directory.inspect}" end base_names.fill('..') relpath_names = base_names + dest_names if relpath_names.empty? Pathname.new('.') else Pathname.new(File.join(*relpath_names)) end end end class Pathname # * Find * # # Iterates over the directory tree in a depth first manner, yielding a # Pathname for each file under "this" directory. # # Returns an Enumerator if no block is given. # # Since it is implemented by the standard library module Find, Find.prune can # be used to control the traversal. # # If +self+ is +.+, yielded pathnames begin with a filename in the # current directory, not +./+. # # See Find.find # def find(ignore_error: true) # :yield: pathname return to_enum(__method__, ignore_error: ignore_error) unless block_given? require 'find' if @path == '.' Find.find(@path, ignore_error: ignore_error) {|f| yield self.class.new(f.sub(%r{\A\./}, '')) } else Find.find(@path, ignore_error: ignore_error) {|f| yield self.class.new(f) } end end end class Pathname # * FileUtils * # Creates a full path, including any intermediate directories that don't yet # exist. # # See FileUtils.mkpath and FileUtils.mkdir_p def mkpath require 'fileutils' FileUtils.mkpath(@path) nil end # Recursively deletes a directory, including all directories beneath it. # # See FileUtils.rm_r def rmtree # The name "rmtree" is borrowed from File::Path of Perl. # File::Path provides "mkpath" and "rmtree". require 'fileutils' FileUtils.rm_r(@path) nil end end PK!  2.2.0/ubygems.rbnu[# This file allows for the running of rubygems with a nice # command line look-and-feel: ruby -rubygems foo.rb #-- # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. # All rights reserved. # See LICENSE.txt for permissions. #++ require 'rubygems' PK!8"et2.2.0/fiddle.rbnu[require 'fiddle.so' require 'fiddle/function' require 'fiddle/closure' module Fiddle if WINDOWS # Returns the last win32 +Error+ of the current executing +Thread+ or nil # if none def self.win32_last_error Thread.current[:__FIDDLE_WIN32_LAST_ERROR__] end # Sets the last win32 +Error+ of the current executing +Thread+ to +error+ def self.win32_last_error= error Thread.current[:__FIDDLE_WIN32_LAST_ERROR__] = error end end # Returns the last +Error+ of the current executing +Thread+ or nil if none def self.last_error Thread.current[:__FIDDLE_LAST_ERROR__] end # Sets the last +Error+ of the current executing +Thread+ to +error+ def self.last_error= error Thread.current[:__DL2_LAST_ERROR__] = error Thread.current[:__FIDDLE_LAST_ERROR__] = error end # call-seq: dlopen(library) => Fiddle::Handle # # Creates a new handler that opens +library+, and returns an instance of # Fiddle::Handle. # # If +nil+ is given for the +library+, Fiddle::Handle::DEFAULT is used, which # is the equivalent to RTLD_DEFAULT. See man 3 dlopen for more. # # lib = Fiddle.dlopen(nil) # # The default is dependent on OS, and provide a handle for all libraries # already loaded. For example, in most cases you can use this to access # +libc+ functions, or ruby functions like +rb_str_new+. # # See Fiddle::Handle.new for more. def dlopen library Fiddle::Handle.new library end module_function :dlopen # Add constants for backwards compat RTLD_GLOBAL = Handle::RTLD_GLOBAL # :nodoc: RTLD_LAZY = Handle::RTLD_LAZY # :nodoc: RTLD_NOW = Handle::RTLD_NOW # :nodoc: end PK!mP2.2.0/psych/nodes/mapping.rbnu[module Psych module Nodes ### # This class represents a {YAML Mapping}[http://yaml.org/spec/1.1/#mapping]. # # A Psych::Nodes::Mapping node may have 0 or more children, but must have # an even number of children. Here are the valid children a # Psych::Nodes::Mapping node may have: # # * Psych::Nodes::Sequence # * Psych::Nodes::Mapping # * Psych::Nodes::Scalar # * Psych::Nodes::Alias class Mapping < Psych::Nodes::Node # Any Map Style ANY = 0 # Block Map Style BLOCK = 1 # Flow Map Style FLOW = 2 # The optional anchor for this mapping attr_accessor :anchor # The optional tag for this mapping attr_accessor :tag # Is this an implicit mapping? attr_accessor :implicit # The style of this mapping attr_accessor :style ### # Create a new Psych::Nodes::Mapping object. # # +anchor+ is the anchor associated with the map or +nil+. # +tag+ is the tag associated with the map or +nil+. # +implicit+ is a boolean indicating whether or not the map was implicitly # started. # +style+ is an integer indicating the mapping style. # # == See Also # See also Psych::Handler#start_mapping def initialize anchor = nil, tag = nil, implicit = true, style = BLOCK super() @anchor = anchor @tag = tag @implicit = implicit @style = style end end end end PK!Gp2.2.0/psych/nodes/stream.rbnu[module Psych module Nodes ### # Represents a YAML stream. This is the root node for any YAML parse # tree. This node must have one or more child nodes. The only valid # child node for a Psych::Nodes::Stream node is Psych::Nodes::Document. class Stream < Psych::Nodes::Node # Encodings supported by Psych (and libyaml) # Any encoding ANY = Psych::Parser::ANY # UTF-8 encoding UTF8 = Psych::Parser::UTF8 # UTF-16LE encoding UTF16LE = Psych::Parser::UTF16LE # UTF-16BE encoding UTF16BE = Psych::Parser::UTF16BE # The encoding used for this stream attr_accessor :encoding ### # Create a new Psych::Nodes::Stream node with an +encoding+ that # defaults to Psych::Nodes::Stream::UTF8. # # See also Psych::Handler#start_stream def initialize encoding = UTF8 super() @encoding = encoding end end end end PK!|2.2.0/psych/nodes/document.rbnu[module Psych module Nodes ### # This represents a YAML Document. This node must be a child of # Psych::Nodes::Stream. A Psych::Nodes::Document must have one child, # and that child may be one of the following: # # * Psych::Nodes::Sequence # * Psych::Nodes::Mapping # * Psych::Nodes::Scalar class Document < Psych::Nodes::Node # The version of the YAML document attr_accessor :version # A list of tag directives for this document attr_accessor :tag_directives # Was this document implicitly created? attr_accessor :implicit # Is the end of the document implicit? attr_accessor :implicit_end ### # Create a new Psych::Nodes::Document object. # # +version+ is a list indicating the YAML version. # +tags_directives+ is a list of tag directive declarations # +implicit+ is a flag indicating whether the document will be implicitly # started. # # == Example: # This creates a YAML document object that represents a YAML 1.1 document # with one tag directive, and has an implicit start: # # Psych::Nodes::Document.new( # [1,1], # [["!", "tag:tenderlovemaking.com,2009:"]], # true # ) # # == See Also # See also Psych::Handler#start_document def initialize version = [], tag_directives = [], implicit = false super() @version = version @tag_directives = tag_directives @implicit = implicit @implicit_end = true end ### # Returns the root node. A Document may only have one root node: # http://yaml.org/spec/1.1/#id898031 def root children.first end end end end PK!Ө+GG2.2.0/psych/nodes/scalar.rbnu[module Psych module Nodes ### # This class represents a {YAML Scalar}[http://yaml.org/spec/1.1/#id858081]. # # This node type is a terminal node and should not have any children. class Scalar < Psych::Nodes::Node # Any style scalar, the emitter chooses ANY = 0 # Plain scalar style PLAIN = 1 # Single quoted style SINGLE_QUOTED = 2 # Double quoted style DOUBLE_QUOTED = 3 # Literal style LITERAL = 4 # Folded style FOLDED = 5 # The scalar value attr_accessor :value # The anchor value (if there is one) attr_accessor :anchor # The tag value (if there is one) attr_accessor :tag # Is this a plain scalar? attr_accessor :plain # Is this scalar quoted? attr_accessor :quoted # The style of this scalar attr_accessor :style ### # Create a new Psych::Nodes::Scalar object. # # +value+ is the string value of the scalar # +anchor+ is an associated anchor or nil # +tag+ is an associated tag or nil # +plain+ is a boolean value # +quoted+ is a boolean value # +style+ is an integer idicating the string style # # == See Also # # See also Psych::Handler#scalar def initialize value, anchor = nil, tag = nil, plain = true, quoted = false, style = ANY @value = value @anchor = anchor @tag = tag @plain = plain @quoted = quoted @style = style end end end end PK!vH2.2.0/psych/nodes/alias.rbnu[module Psych module Nodes ### # This class represents a {YAML Alias}[http://yaml.org/spec/1.1/#alias]. # It points to an +anchor+. # # A Psych::Nodes::Alias is a terminal node and may have no children. class Alias < Psych::Nodes::Node # The anchor this alias links to attr_accessor :anchor # Create a new Alias that points to an +anchor+ def initialize anchor @anchor = anchor end end end end PK!G52.2.0/psych/nodes/sequence.rbnu[module Psych module Nodes ### # This class represents a # {YAML sequence}[http://yaml.org/spec/1.1/#sequence/syntax]. # # A YAML sequence is basically a list, and looks like this: # # %YAML 1.1 # --- # - I am # - a Sequence # # A YAML sequence may have an anchor like this: # # %YAML 1.1 # --- # &A [ # "This sequence", # "has an anchor" # ] # # A YAML sequence may also have a tag like this: # # %YAML 1.1 # --- # !!seq [ # "This sequence", # "has a tag" # ] # # This class represents a sequence in a YAML document. A # Psych::Nodes::Sequence node may have 0 or more children. Valid children # for this node are: # # * Psych::Nodes::Sequence # * Psych::Nodes::Mapping # * Psych::Nodes::Scalar # * Psych::Nodes::Alias class Sequence < Psych::Nodes::Node # Any Styles, emitter chooses ANY = 0 # Block style sequence BLOCK = 1 # Flow style sequence FLOW = 2 # The anchor for this sequence (if any) attr_accessor :anchor # The tag name for this sequence (if any) attr_accessor :tag # Is this sequence started implicitly? attr_accessor :implicit # The sequence style used attr_accessor :style ### # Create a new object representing a YAML sequence. # # +anchor+ is the anchor associated with the sequence or nil. # +tag+ is the tag associated with the sequence or nil. # +implicit+ a boolean indicating whether or not the sequence was # implicitly started. # +style+ is an integer indicating the list style. # # See Psych::Handler#start_sequence def initialize anchor = nil, tag = nil, implicit = true, style = BLOCK super() @anchor = anchor @tag = tag @implicit = implicit @style = style end end end end PK! 2.2.0/psych/nodes/node.rbnu[require 'stringio' require 'psych/class_loader' require 'psych/scalar_scanner' module Psych module Nodes ### # The base class for any Node in a YAML parse tree. This class should # never be instantiated. class Node include Enumerable # The children of this node attr_reader :children # An associated tag attr_reader :tag # Create a new Psych::Nodes::Node def initialize @children = [] end ### # Iterate over each node in the tree. Yields each node to +block+ depth # first. def each &block return enum_for :each unless block_given? Visitors::DepthFirst.new(block).accept self end ### # Convert this node to Ruby. # # See also Psych::Visitors::ToRuby def to_ruby Visitors::ToRuby.create.accept(self) end alias :transform :to_ruby ### # Convert this node to YAML. # # See also Psych::Visitors::Emitter def yaml io = nil, options = {} real_io = io || StringIO.new(''.encode('utf-8')) Visitors::Emitter.new(real_io, options).accept self return real_io.string unless io io end alias :to_yaml :yaml end end end PK!=!Y2.2.0/psych/y.rbnu[module Kernel ### # An alias for Psych.dump_stream meant to be used with IRB. def y *objects puts Psych.dump_stream(*objects) end private :y end PK!c/x2.2.0/psych/class_loader.rbnu[require 'psych/omap' require 'psych/set' module Psych class ClassLoader # :nodoc: BIG_DECIMAL = 'BigDecimal' COMPLEX = 'Complex' DATE = 'Date' DATE_TIME = 'DateTime' EXCEPTION = 'Exception' OBJECT = 'Object' PSYCH_OMAP = 'Psych::Omap' PSYCH_SET = 'Psych::Set' RANGE = 'Range' RATIONAL = 'Rational' REGEXP = 'Regexp' STRUCT = 'Struct' SYMBOL = 'Symbol' def initialize @cache = CACHE.dup end def load klassname return nil if !klassname || klassname.empty? find klassname end def symbolize sym symbol sym.to_sym end constants.each do |const| konst = const_get const define_method(const.to_s.downcase) do load konst end end private def find klassname @cache[klassname] ||= resolve(klassname) end def resolve klassname name = klassname retried = false begin path2class(name) rescue ArgumentError, NameError => ex unless retried name = "Struct::#{name}" retried = ex retry end raise retried end end CACHE = Hash[constants.map { |const| val = const_get const begin [val, ::Object.const_get(val)] rescue nil end }.compact] class Restricted < ClassLoader def initialize classes, symbols @classes = classes @symbols = symbols super() end def symbolize sym return super if @symbols.empty? if @symbols.include? sym super else raise DisallowedClass, 'Symbol' end end private def find klassname if @classes.include? klassname super else raise DisallowedClass, klassname end end end end end PK!5l2.2.0/psych/exception.rbnu[module Psych class Exception < RuntimeError end class BadAlias < Exception end class DisallowedClass < Exception def initialize klass_name super "Tried to load unspecified class: #{klass_name}" end end end PK!R II2.2.0/psych/visitors/visitor.rbnu[module Psych module Visitors class Visitor def accept target visit target end private DISPATCH = Hash.new do |hash, klass| hash[klass] = "visit_#{klass.name.gsub('::', '_')}" end def visit target send DISPATCH[target.class], target end end end end PK!",--!2.2.0/psych/visitors/json_tree.rbnu[require 'psych/json/ruby_events' module Psych module Visitors class JSONTree < YAMLTree include Psych::JSON::RubyEvents def self.create options = {} emitter = Psych::JSON::TreeBuilder.new class_loader = ClassLoader.new ss = ScalarScanner.new class_loader new(emitter, ss, options) end def accept target if target.respond_to?(:encode_with) dump_coder target else send(@dispatch_cache[target.class], target) end end end end end PK!&}*2.2.0/psych/visitors/emitter.rbnu[module Psych module Visitors class Emitter < Psych::Visitors::Visitor def initialize io, options = {} opts = [:indentation, :canonical, :line_width].find_all { |opt| options.key?(opt) } if opts.empty? @handler = Psych::Emitter.new io else du = Handler::DumperOptions.new opts.each { |option| du.send :"#{option}=", options[option] } @handler = Psych::Emitter.new io, du end end def visit_Psych_Nodes_Stream o @handler.start_stream o.encoding o.children.each { |c| accept c } @handler.end_stream end def visit_Psych_Nodes_Document o @handler.start_document o.version, o.tag_directives, o.implicit o.children.each { |c| accept c } @handler.end_document o.implicit_end end def visit_Psych_Nodes_Scalar o @handler.scalar o.value, o.anchor, o.tag, o.plain, o.quoted, o.style end def visit_Psych_Nodes_Sequence o @handler.start_sequence o.anchor, o.tag, o.implicit, o.style o.children.each { |c| accept c } @handler.end_sequence end def visit_Psych_Nodes_Mapping o @handler.start_mapping o.anchor, o.tag, o.implicit, o.style o.children.each { |c| accept c } @handler.end_mapping end def visit_Psych_Nodes_Alias o @handler.alias o.anchor end end end end PK!OFTT#2.2.0/psych/visitors/depth_first.rbnu[module Psych module Visitors class DepthFirst < Psych::Visitors::Visitor def initialize block @block = block end private def nary o o.children.each { |x| visit x } @block.call o end alias :visit_Psych_Nodes_Stream :nary alias :visit_Psych_Nodes_Document :nary alias :visit_Psych_Nodes_Sequence :nary alias :visit_Psych_Nodes_Mapping :nary def terminal o @block.call o end alias :visit_Psych_Nodes_Scalar :terminal alias :visit_Psych_Nodes_Alias :terminal end end end PK!Q ??!2.2.0/psych/visitors/yaml_tree.rbnu[require 'psych/tree_builder' require 'psych/scalar_scanner' require 'psych/class_loader' module Psych module Visitors ### # YAMLTree builds a YAML ast given a Ruby object. For example: # # builder = Psych::Visitors::YAMLTree.new # builder << { :foo => 'bar' } # builder.tree # => # true) end end rescue # public_method or source_location might be overridden, # and it's OK to skip it since it's only to emit a warning end end if target.respond_to?(:encode_with) dump_coder target else send(@dispatch_cache[target.class], target) end end def visit_Psych_Omap o seq = @emitter.start_sequence(nil, '!omap', false, Nodes::Sequence::BLOCK) register(o, seq) o.each { |k,v| visit_Hash k => v } @emitter.end_sequence end def visit_Encoding o tag = "!ruby/encoding" @emitter.scalar o.name, nil, tag, false, false, Nodes::Scalar::ANY end def visit_Object o tag = Psych.dump_tags[o.class] unless tag klass = o.class == Object ? nil : o.class.name tag = ['!ruby/object', klass].compact.join(':') end map = @emitter.start_mapping(nil, tag, false, Nodes::Mapping::BLOCK) register(o, map) dump_ivars o @emitter.end_mapping end def visit_Struct o tag = ['!ruby/struct', o.class.name].compact.join(':') register o, @emitter.start_mapping(nil, tag, false, Nodes::Mapping::BLOCK) o.members.each do |member| @emitter.scalar member.to_s, nil, nil, true, false, Nodes::Scalar::ANY accept o[member] end dump_ivars o @emitter.end_mapping end def visit_Exception o tag = ['!ruby/exception', o.class.name].join ':' @emitter.start_mapping nil, tag, false, Nodes::Mapping::BLOCK { 'message' => private_iv_get(o, 'mesg'), 'backtrace' => private_iv_get(o, 'backtrace'), }.each do |k,v| next unless v @emitter.scalar k, nil, nil, true, false, Nodes::Scalar::ANY accept v end dump_ivars o @emitter.end_mapping end def visit_NameError o tag = ['!ruby/exception', o.class.name].join ':' @emitter.start_mapping nil, tag, false, Nodes::Mapping::BLOCK { 'message' => o.message.to_s, 'backtrace' => private_iv_get(o, 'backtrace'), }.each do |k,v| next unless v @emitter.scalar k, nil, nil, true, false, Nodes::Scalar::ANY accept v end dump_ivars o @emitter.end_mapping end def visit_Regexp o register o, @emitter.scalar(o.inspect, nil, '!ruby/regexp', false, false, Nodes::Scalar::ANY) end def visit_DateTime o formatted = if o.offset.zero? o.strftime("%Y-%m-%d %H:%M:%S.%9N Z".freeze) else o.strftime("%Y-%m-%d %H:%M:%S.%9N %:z".freeze) end tag = '!ruby/object:DateTime' register o, @emitter.scalar(formatted, nil, tag, false, false, Nodes::Scalar::ANY) end def visit_Time o formatted = format_time o register o, @emitter.scalar(formatted, nil, nil, true, false, Nodes::Scalar::ANY) end def visit_Rational o register o, @emitter.start_mapping(nil, '!ruby/object:Rational', false, Nodes::Mapping::BLOCK) [ 'denominator', o.denominator.to_s, 'numerator', o.numerator.to_s ].each do |m| @emitter.scalar m, nil, nil, true, false, Nodes::Scalar::ANY end @emitter.end_mapping end def visit_Complex o register o, @emitter.start_mapping(nil, '!ruby/object:Complex', false, Nodes::Mapping::BLOCK) ['real', o.real.to_s, 'image', o.imag.to_s].each do |m| @emitter.scalar m, nil, nil, true, false, Nodes::Scalar::ANY end @emitter.end_mapping end def visit_Integer o @emitter.scalar o.to_s, nil, nil, true, false, Nodes::Scalar::ANY end alias :visit_TrueClass :visit_Integer alias :visit_FalseClass :visit_Integer alias :visit_Date :visit_Integer def visit_Float o if o.nan? @emitter.scalar '.nan', nil, nil, true, false, Nodes::Scalar::ANY elsif o.infinite? @emitter.scalar((o.infinite? > 0 ? '.inf' : '-.inf'), nil, nil, true, false, Nodes::Scalar::ANY) else @emitter.scalar o.to_s, nil, nil, true, false, Nodes::Scalar::ANY end end def visit_BigDecimal o @emitter.scalar o._dump, nil, '!ruby/object:BigDecimal', false, false, Nodes::Scalar::ANY end def visit_String o plain = true quote = true style = Nodes::Scalar::PLAIN tag = nil str = o if binary?(o) str = [o].pack('m').chomp tag = '!binary' # FIXME: change to below when syck is removed #tag = 'tag:yaml.org,2002:binary' style = Nodes::Scalar::LITERAL plain = false quote = false elsif o =~ /\n/ style = Nodes::Scalar::LITERAL elsif o == '<<' style = Nodes::Scalar::SINGLE_QUOTED tag = 'tag:yaml.org,2002:str' plain = false quote = false elsif o =~ /^\W[^"]*$/ style = Nodes::Scalar::DOUBLE_QUOTED else unless String === @ss.tokenize(o) style = Nodes::Scalar::SINGLE_QUOTED end end ivars = find_ivars o if ivars.empty? unless o.class == ::String tag = "!ruby/string:#{o.class}" plain = false quote = false end @emitter.scalar str, nil, tag, plain, quote, style else maptag = '!ruby/string' maptag << ":#{o.class}" unless o.class == ::String register o, @emitter.start_mapping(nil, maptag, false, Nodes::Mapping::BLOCK) @emitter.scalar 'str', nil, nil, true, false, Nodes::Scalar::ANY @emitter.scalar str, nil, tag, plain, quote, style dump_ivars o @emitter.end_mapping end end def visit_Module o raise TypeError, "can't dump anonymous module: #{o}" unless o.name register o, @emitter.scalar(o.name, nil, '!ruby/module', false, false, Nodes::Scalar::SINGLE_QUOTED) end def visit_Class o raise TypeError, "can't dump anonymous class: #{o}" unless o.name register o, @emitter.scalar(o.name, nil, '!ruby/class', false, false, Nodes::Scalar::SINGLE_QUOTED) end def visit_Range o register o, @emitter.start_mapping(nil, '!ruby/range', false, Nodes::Mapping::BLOCK) ['begin', o.begin, 'end', o.end, 'excl', o.exclude_end?].each do |m| accept m end @emitter.end_mapping end def visit_Hash o tag = o.class == ::Hash ? nil : "!ruby/hash:#{o.class}" implicit = !tag register(o, @emitter.start_mapping(nil, tag, implicit, Psych::Nodes::Mapping::BLOCK)) o.each do |k,v| accept k accept v end @emitter.end_mapping end def visit_Psych_Set o register(o, @emitter.start_mapping(nil, '!set', false, Psych::Nodes::Mapping::BLOCK)) o.each do |k,v| accept k accept v end @emitter.end_mapping end def visit_Array o if o.class == ::Array register o, @emitter.start_sequence(nil, nil, true, Nodes::Sequence::BLOCK) o.each { |c| accept c } @emitter.end_sequence else visit_array_subclass o end end def visit_NilClass o @emitter.scalar('', nil, 'tag:yaml.org,2002:null', true, false, Nodes::Scalar::ANY) end def visit_Symbol o if o.empty? @emitter.scalar "", nil, '!ruby/symbol', false, false, Nodes::Scalar::ANY else @emitter.scalar ":#{o}", nil, nil, true, false, Nodes::Scalar::ANY end end def visit_BasicObject o tag = Psych.dump_tags[o.class] tag ||= "!ruby/marshalable:#{o.class.name}" map = @emitter.start_mapping(nil, tag, false, Nodes::Mapping::BLOCK) register(o, map) o.marshal_dump.each(&method(:accept)) @emitter.end_mapping end private # FIXME: Remove the index and count checks in Psych 3.0 NULL = "\x00" BINARY_RANGE = "\x00-\x7F" WS_RANGE = "^ -~\t\r\n" def binary? string (string.encoding == Encoding::ASCII_8BIT && !string.ascii_only?) || string.index(NULL) || string.count(BINARY_RANGE, WS_RANGE).fdiv(string.length) > 0.3 end def visit_array_subclass o tag = "!ruby/array:#{o.class}" if o.instance_variables.empty? node = @emitter.start_sequence(nil, tag, false, Nodes::Sequence::BLOCK) register o, node o.each { |c| accept c } @emitter.end_sequence else node = @emitter.start_mapping(nil, tag, false, Nodes::Sequence::BLOCK) register o, node # Dump the internal list accept 'internal' @emitter.start_sequence(nil, nil, true, Nodes::Sequence::BLOCK) o.each { |c| accept c } @emitter.end_sequence # Dump the ivars accept 'ivars' @emitter.start_mapping(nil, nil, true, Nodes::Sequence::BLOCK) o.instance_variables.each do |ivar| accept ivar accept o.instance_variable_get ivar end @emitter.end_mapping @emitter.end_mapping end end def dump_list o end # '%:z' was no defined until 1.9.3 if RUBY_VERSION < '1.9.3' def format_time time formatted = time.strftime("%Y-%m-%d %H:%M:%S.%9N") if time.utc? formatted += " Z" else zone = time.strftime('%z') formatted += " #{zone[0,3]}:#{zone[3,5]}" end formatted end else def format_time time if time.utc? time.strftime("%Y-%m-%d %H:%M:%S.%9N Z") else time.strftime("%Y-%m-%d %H:%M:%S.%9N %:z") end end end # FIXME: remove this method once "to_yaml_properties" is removed def find_ivars target begin loc = target.method(:to_yaml_properties).source_location.first unless loc.start_with?(Psych::DEPRECATED) || loc.end_with?('rubytypes.rb') if $VERBOSE warn "#{loc}: to_yaml_properties is deprecated, please implement \"encode_with(coder)\"" end return target.to_yaml_properties end rescue # public_method or source_location might be overridden, # and it's OK to skip it since it's only to emit a warning. end target.instance_variables end def register target, yaml_obj @st.register target, yaml_obj yaml_obj end def dump_coder o @coders << o tag = Psych.dump_tags[o.class] unless tag klass = o.class == Object ? nil : o.class.name tag = ['!ruby/object', klass].compact.join(':') end c = Psych::Coder.new(tag) o.encode_with(c) emit_coder c end def emit_coder c case c.type when :scalar @emitter.scalar c.scalar, nil, c.tag, c.tag.nil?, false, Nodes::Scalar::ANY when :seq @emitter.start_sequence nil, c.tag, c.tag.nil?, Nodes::Sequence::BLOCK c.seq.each do |thing| accept thing end @emitter.end_sequence when :map @emitter.start_mapping nil, c.tag, c.implicit, c.style c.map.each do |k,v| accept k accept v end @emitter.end_mapping when :object accept c.object end end def dump_ivars target ivars = find_ivars target ivars.each do |iv| @emitter.scalar("#{iv.to_s.sub(/^@/, '')}", nil, nil, true, false, Nodes::Scalar::ANY) accept target.instance_variable_get(iv) end end end end end PK!rʳ++2.2.0/psych/visitors/to_ruby.rbnu[require 'psych/scalar_scanner' require 'psych/class_loader' require 'psych/exception' unless defined?(Regexp::NOENCODING) Regexp::NOENCODING = 32 end module Psych module Visitors ### # This class walks a YAML AST, converting each node to Ruby class ToRuby < Psych::Visitors::Visitor def self.create class_loader = ClassLoader.new scanner = ScalarScanner.new class_loader new(scanner, class_loader) end attr_reader :class_loader def initialize ss, class_loader super() @st = {} @ss = ss @domain_types = Psych.domain_types @class_loader = class_loader end def accept target result = super return result if @domain_types.empty? || !target.tag key = target.tag.sub(/^[!\/]*/, '').sub(/(,\d+)\//, '\1:') key = "tag:#{key}" unless key =~ /^(tag:|x-private)/ if @domain_types.key? key value, block = @domain_types[key] return block.call value, result end result end def deserialize o if klass = resolve_class(Psych.load_tags[o.tag]) instance = klass.allocate if instance.respond_to?(:init_with) coder = Psych::Coder.new(o.tag) coder.scalar = o.value instance.init_with coder end return instance end return o.value if o.quoted return @ss.tokenize(o.value) unless o.tag case o.tag when '!binary', 'tag:yaml.org,2002:binary' o.value.unpack('m').first when /^!(?:str|ruby\/string)(?::(.*))?/, 'tag:yaml.org,2002:str' klass = resolve_class($1) if klass klass.allocate.replace o.value else o.value end when '!ruby/object:BigDecimal' require 'bigdecimal' class_loader.big_decimal._load o.value when "!ruby/object:DateTime" class_loader.date_time require 'date' @ss.parse_time(o.value).to_datetime when '!ruby/encoding' ::Encoding.find o.value when "!ruby/object:Complex" class_loader.complex Complex(o.value) when "!ruby/object:Rational" class_loader.rational Rational(o.value) when "!ruby/class", "!ruby/module" resolve_class o.value when "tag:yaml.org,2002:float", "!float" Float(@ss.tokenize(o.value)) when "!ruby/regexp" klass = class_loader.regexp o.value =~ /^\/(.*)\/([mixn]*)$/ source = $1 options = 0 lang = nil ($2 || '').split('').each do |option| case option when 'x' then options |= Regexp::EXTENDED when 'i' then options |= Regexp::IGNORECASE when 'm' then options |= Regexp::MULTILINE when 'n' then options |= Regexp::NOENCODING else lang = option end end klass.new(*[source, options, lang].compact) when "!ruby/range" klass = class_loader.range args = o.value.split(/([.]{2,3})/, 2).map { |s| accept Nodes::Scalar.new(s) } args.push(args.delete_at(1) == '...') klass.new(*args) when /^!ruby\/sym(bol)?:?(.*)?$/ class_loader.symbolize o.value else @ss.tokenize o.value end end private :deserialize def visit_Psych_Nodes_Scalar o register o, deserialize(o) end def visit_Psych_Nodes_Sequence o if klass = resolve_class(Psych.load_tags[o.tag]) instance = klass.allocate if instance.respond_to?(:init_with) coder = Psych::Coder.new(o.tag) coder.seq = o.children.map { |c| accept c } instance.init_with coder end return instance end case o.tag when nil register_empty(o) when '!omap', 'tag:yaml.org,2002:omap' map = register(o, Psych::Omap.new) o.children.each { |a| map[accept(a.children.first)] = accept a.children.last } map when /^!(?:seq|ruby\/array):(.*)$/ klass = resolve_class($1) list = register(o, klass.allocate) o.children.each { |c| list.push accept c } list else register_empty(o) end end def visit_Psych_Nodes_Mapping o if Psych.load_tags[o.tag] return revive(resolve_class(Psych.load_tags[o.tag]), o) end return revive_hash(register(o, {}), o) unless o.tag case o.tag when /^!ruby\/struct:?(.*)?$/ klass = resolve_class($1) if $1 if klass s = register(o, klass.allocate) members = {} struct_members = s.members.map { |x| class_loader.symbolize x } o.children.each_slice(2) do |k,v| member = accept(k) value = accept(v) if struct_members.include?(class_loader.symbolize(member)) s.send("#{member}=", value) else members[member.to_s.sub(/^@/, '')] = value end end init_with(s, members, o) else klass = class_loader.struct members = o.children.map { |c| accept c } h = Hash[*members] s = klass.new(*h.map { |k,v| class_loader.symbolize k }).new(*h.map { |k,v| v }) register(o, s) s end when /^!ruby\/object:?(.*)?$/ name = $1 || 'Object' if name == 'Complex' class_loader.complex h = Hash[*o.children.map { |c| accept c }] register o, Complex(h['real'], h['image']) elsif name == 'Rational' class_loader.rational h = Hash[*o.children.map { |c| accept c }] register o, Rational(h['numerator'], h['denominator']) elsif name == 'Hash' revive_hash(register(o, {}), o) else obj = revive((resolve_class(name) || class_loader.object), o) obj end when /^!(?:str|ruby\/string)(?::(.*))?/, 'tag:yaml.org,2002:str' klass = resolve_class($1) members = {} string = nil o.children.each_slice(2) do |k,v| key = accept k value = accept v if key == 'str' if klass string = klass.allocate.replace value else string = value end register(o, string) else members[key] = value end end init_with(string, members.map { |k,v| [k.to_s.sub(/^@/, ''),v] }, o) when /^!ruby\/array:(.*)$/ klass = resolve_class($1) list = register(o, klass.allocate) members = Hash[o.children.map { |c| accept c }.each_slice(2).to_a] list.replace members['internal'] members['ivars'].each do |ivar, v| list.instance_variable_set ivar, v end list when '!ruby/range' klass = class_loader.range h = Hash[*o.children.map { |c| accept c }] register o, klass.new(h['begin'], h['end'], h['excl']) when /^!ruby\/exception:?(.*)?$/ h = Hash[*o.children.map { |c| accept c }] e = build_exception((resolve_class($1) || class_loader.exception), h.delete('message')) init_with(e, h, o) when '!set', 'tag:yaml.org,2002:set' set = class_loader.psych_set.new @st[o.anchor] = set if o.anchor o.children.each_slice(2) do |k,v| set[accept(k)] = accept(v) end set when /^!map:(.*)$/, /^!ruby\/hash:(.*)$/ revive_hash register(o, resolve_class($1).new), o when '!omap', 'tag:yaml.org,2002:omap' map = register(o, class_loader.psych_omap.new) o.children.each_slice(2) do |l,r| map[accept(l)] = accept r end map when /^!ruby\/marshalable:(.*)$/ name = $1 klass = resolve_class(name) obj = register(o, klass.allocate) if obj.respond_to?(:init_with) init_with(obj, revive_hash({}, o), o) elsif obj.respond_to?(:marshal_load) marshal_data = o.children.map(&method(:accept)) obj.marshal_load(marshal_data) obj else raise ArgumentError, "Cannot deserialize #{name}" end else revive_hash(register(o, {}), o) end end def visit_Psych_Nodes_Document o accept o.root end def visit_Psych_Nodes_Stream o o.children.map { |c| accept c } end def visit_Psych_Nodes_Alias o @st.fetch(o.anchor) { raise BadAlias, "Unknown alias: #{o.anchor}" } end private def register node, object @st[node.anchor] = object if node.anchor object end def register_empty object list = register(object, []) object.children.each { |c| list.push accept c } list end def revive_hash hash, o o.children.each_slice(2) { |k,v| key = accept(k) val = accept(v) if key == '<<' && k.tag != "tag:yaml.org,2002:str" case v when Nodes::Alias, Nodes::Mapping begin hash.merge! val rescue TypeError hash[key] = val end when Nodes::Sequence begin h = {} val.reverse_each do |value| h.merge! value end hash.merge! h rescue TypeError hash[key] = val end else hash[key] = val end else hash[key] = val end } hash end def merge_key hash, key, val end def revive klass, node s = register(node, klass.allocate) init_with(s, revive_hash({}, node), node) end def init_with o, h, node c = Psych::Coder.new(node.tag) c.map = h if o.respond_to?(:init_with) o.init_with c elsif o.respond_to?(:yaml_initialize) if $VERBOSE warn "Implementing #{o.class}#yaml_initialize is deprecated, please implement \"init_with(coder)\"" end o.yaml_initialize c.tag, c.map else h.each { |k,v| o.instance_variable_set(:"@#{k}", v) } end o end # Convert +klassname+ to a Class def resolve_class klassname class_loader.load klassname end end class NoAliasRuby < ToRuby def visit_Psych_Nodes_Alias o raise BadAlias, "Unknown alias: #{o.anchor}" end end end end PK!sw@}}2.2.0/psych/stream.rbnu[module Psych ### # Psych::Stream is a streaming YAML emitter. It will not buffer your YAML, # but send it straight to an IO. # # Here is an example use: # # stream = Psych::Stream.new($stdout) # stream.start # stream.push({:foo => 'bar'}) # stream.finish # # YAML will be immediately emitted to $stdout with no buffering. # # Psych::Stream#start will take a block and ensure that Psych::Stream#finish # is called, so you can do this form: # # stream = Psych::Stream.new($stdout) # stream.start do |em| # em.push(:foo => 'bar') # end # class Stream < Psych::Visitors::YAMLTree class Emitter < Psych::Emitter # :nodoc: def end_document implicit_end = !streaming? super end def streaming? true end end include Psych::Streaming extend Psych::Streaming::ClassMethods end end PK!92.2.0/psych/handler.rbnu[module Psych ### # Psych::Handler is an abstract base class that defines the events used # when dealing with Psych::Parser. Clients who want to use Psych::Parser # should implement a class that inherits from Psych::Handler and define # events that they can handle. # # Psych::Handler defines all events that Psych::Parser can possibly send to # event handlers. # # See Psych::Parser for more details class Handler ### # Configuration options for dumping YAML. class DumperOptions attr_accessor :line_width, :indentation, :canonical def initialize @line_width = 0 @indentation = 2 @canonical = false end end # Default dumping options OPTIONS = DumperOptions.new # Events that a Handler should respond to. EVENTS = [ :alias, :empty, :end_document, :end_mapping, :end_sequence, :end_stream, :scalar, :start_document, :start_mapping, :start_sequence, :start_stream ] ### # Called with +encoding+ when the YAML stream starts. This method is # called once per stream. A stream may contain multiple documents. # # See the constants in Psych::Parser for the possible values of +encoding+. def start_stream encoding end ### # Called when the document starts with the declared +version+, # +tag_directives+, if the document is +implicit+. # # +version+ will be an array of integers indicating the YAML version being # dealt with, +tag_directives+ is a list of tuples indicating the prefix # and suffix of each tag, and +implicit+ is a boolean indicating whether # the document is started implicitly. # # === Example # # Given the following YAML: # # %YAML 1.1 # %TAG ! tag:tenderlovemaking.com,2009: # --- !squee # # The parameters for start_document must be this: # # version # => [1, 1] # tag_directives # => [["!", "tag:tenderlovemaking.com,2009:"]] # implicit # => false def start_document version, tag_directives, implicit end ### # Called with the document ends. +implicit+ is a boolean value indicating # whether or not the document has an implicit ending. # # === Example # # Given the following YAML: # # --- # hello world # # +implicit+ will be true. Given this YAML: # # --- # hello world # ... # # +implicit+ will be false. def end_document implicit end ### # Called when an alias is found to +anchor+. +anchor+ will be the name # of the anchor found. # # === Example # # Here we have an example of an array that references itself in YAML: # # --- &ponies # - first element # - *ponies # # &ponies is the achor, *ponies is the alias. In this case, alias is # called with "ponies". def alias anchor end ### # Called when a scalar +value+ is found. The scalar may have an # +anchor+, a +tag+, be implicitly +plain+ or implicitly +quoted+ # # +value+ is the string value of the scalar # +anchor+ is an associated anchor or nil # +tag+ is an associated tag or nil # +plain+ is a boolean value # +quoted+ is a boolean value # +style+ is an integer idicating the string style # # See the constants in Psych::Nodes::Scalar for the possible values of # +style+ # # === Example # # Here is a YAML document that exercises most of the possible ways this # method can be called: # # --- # - !str "foo" # - &anchor fun # - many # lines # - | # many # newlines # # The above YAML document contains a list with four strings. Here are # the parameters sent to this method in the same order: # # # value anchor tag plain quoted style # ["foo", nil, "!str", false, false, 3 ] # ["fun", "anchor", nil, true, false, 1 ] # ["many lines", nil, nil, true, false, 1 ] # ["many\nnewlines\n", nil, nil, false, true, 4 ] # def scalar value, anchor, tag, plain, quoted, style end ### # Called when a sequence is started. # # +anchor+ is the anchor associated with the sequence or nil. # +tag+ is the tag associated with the sequence or nil. # +implicit+ a boolean indicating whether or not the sequence was implicitly # started. # +style+ is an integer indicating the list style. # # See the constants in Psych::Nodes::Sequence for the possible values of # +style+. # # === Example # # Here is a YAML document that exercises most of the possible ways this # method can be called: # # --- # - !!seq [ # a # ] # - &pewpew # - b # # The above YAML document consists of three lists, an outer list that # contains two inner lists. Here is a matrix of the parameters sent # to represent these lists: # # # anchor tag implicit style # [nil, nil, true, 1 ] # [nil, "tag:yaml.org,2002:seq", false, 2 ] # ["pewpew", nil, true, 1 ] def start_sequence anchor, tag, implicit, style end ### # Called when a sequence ends. def end_sequence end ### # Called when a map starts. # # +anchor+ is the anchor associated with the map or +nil+. # +tag+ is the tag associated with the map or +nil+. # +implicit+ is a boolean indicating whether or not the map was implicitly # started. # +style+ is an integer indicating the mapping style. # # See the constants in Psych::Nodes::Mapping for the possible values of # +style+. # # === Example # # Here is a YAML document that exercises most of the possible ways this # method can be called: # # --- # k: !!map { hello: world } # v: &pewpew # hello: world # # The above YAML document consists of three maps, an outer map that contains # two inner maps. Below is a matrix of the parameters sent in order to # represent these three maps: # # # anchor tag implicit style # [nil, nil, true, 1 ] # [nil, "tag:yaml.org,2002:map", false, 2 ] # ["pewpew", nil, true, 1 ] def start_mapping anchor, tag, implicit, style end ### # Called when a map ends def end_mapping end ### # Called when an empty event happens. (Which, as far as I can tell, is # never). def empty end ### # Called when the YAML stream ends def end_stream end ### # Is this handler a streaming handler? def streaming? false end end end PK!,,2.2.0/psych/set.rbnu[module Psych class Set < ::Hash end end PK!Ŝ' 2.2.0/psych/deprecated.rbnu[require 'date' module Psych DEPRECATED = __FILE__ # :nodoc: module DeprecatedMethods # :nodoc: attr_accessor :taguri attr_accessor :to_yaml_style end def self.quick_emit thing, opts = {}, &block # :nodoc: warn "#{caller[0]}: YAML.quick_emit is deprecated" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__)) target = eval 'self', block.binding target.extend DeprecatedMethods metaclass = class << target; self; end metaclass.send(:define_method, :encode_with) do |coder| target.taguri = coder.tag target.to_yaml_style = coder.style block.call coder end target.psych_to_yaml unless opts[:nodump] end # This method is deprecated, use Psych.load_stream instead. def self.load_documents yaml, &block if $VERBOSE warn "#{caller[0]}: load_documents is deprecated, use load_stream" end list = load_stream yaml return list unless block_given? list.each(&block) end def self.detect_implicit thing warn "#{caller[0]}: detect_implicit is deprecated" if $VERBOSE return '' unless String === thing return 'null' if '' == thing ss = ScalarScanner.new(ClassLoader.new) ss.tokenize(thing).class.name.downcase end def self.add_ruby_type type_tag, &block warn "#{caller[0]}: add_ruby_type is deprecated, use add_domain_type" if $VERBOSE domain = 'ruby.yaml.org,2002' key = ['tag', domain, type_tag].join ':' @domain_types[key] = [key, block] end def self.add_private_type type_tag, &block warn "#{caller[0]}: add_private_type is deprecated, use add_domain_type" if $VERBOSE domain = 'x-private' key = [domain, type_tag].join ':' @domain_types[key] = [key, block] end def self.tagurize thing warn "#{caller[0]}: add_private_type is deprecated, use add_domain_type" if $VERBOSE return thing unless String === thing "tag:yaml.org,2002:#{thing}" end def self.read_type_class type, reference warn "#{caller[0]}: read_type_class is deprecated" if $VERBOSE _, _, type, name = type.split ':', 4 reference = name.split('::').inject(reference) do |k,n| k.const_get(n.to_sym) end if name [type, reference] end def self.object_maker klass, hash warn "#{caller[0]}: object_maker is deprecated" if $VERBOSE klass.allocate.tap do |obj| hash.each { |k,v| obj.instance_variable_set(:"@#{k}", v) } end end end class Object undef :to_yaml_properties rescue nil def to_yaml_properties # :nodoc: instance_variables end end PK!_'2.2.0/psych/handlers/document_stream.rbnu[require 'psych/tree_builder' module Psych module Handlers class DocumentStream < Psych::TreeBuilder # :nodoc: def initialize &block super @block = block end def start_document version, tag_directives, implicit n = Nodes::Document.new version, tag_directives, implicit push n end def end_document implicit_end = !streaming? @last.implicit_end = implicit_end @block.call pop end end end end PK!,!WW 2.2.0/psych/handlers/recorder.rbnu[require 'psych/handler' module Psych module Handlers ### # This handler will capture an event and record the event. Recorder events # are available vial Psych::Handlers::Recorder#events. # # For example: # # recorder = Psych::Handlers::Recorder.new # parser = Psych::Parser.new recorder # parser.parse '--- foo' # # recorder.events # => [list of events] # # # Replay the events # # emitter = Psych::Emitter.new $stdout # recorder.events.each do |m, args| # emitter.send m, *args # end class Recorder < Psych::Handler attr_reader :events def initialize @events = [] super end EVENTS.each do |event| define_method event do |*args| @events << [event, args] end end end end end PK!@--2.2.0/psych/omap.rbnu[module Psych class Omap < ::Hash end end PK!ixM M 2.2.0/psych/nodes.rbnu[require 'psych/nodes/node' require 'psych/nodes/stream' require 'psych/nodes/document' require 'psych/nodes/sequence' require 'psych/nodes/scalar' require 'psych/nodes/mapping' require 'psych/nodes/alias' module Psych ### # = Overview # # When using Psych.load to deserialize a YAML document, the document is # translated to an intermediary AST. That intermediary AST is then # translated in to a Ruby object graph. # # In the opposite direction, when using Psych.dump, the Ruby object graph is # translated to an intermediary AST which is then converted to a YAML # document. # # Psych::Nodes contains all of the classes that make up the nodes of a YAML # AST. You can manually build an AST and use one of the visitors (see # Psych::Visitors) to convert that AST to either a YAML document or to a # Ruby object graph. # # Here is an example of building an AST that represents a list with one # scalar: # # # Create our nodes # stream = Psych::Nodes::Stream.new # doc = Psych::Nodes::Document.new # seq = Psych::Nodes::Sequence.new # scalar = Psych::Nodes::Scalar.new('foo') # # # Build up our tree # stream.children << doc # doc.children << seq # seq.children << scalar # # The stream is the root of the tree. We can then convert the tree to YAML: # # stream.to_yaml => "---\n- foo\n" # # Or convert it to Ruby: # # stream.to_ruby => [["foo"]] # # == YAML AST Requirements # # A valid YAML AST *must* have one Psych::Nodes::Stream at the root. A # Psych::Nodes::Stream node must have 1 or more Psych::Nodes::Document nodes # as children. # # Psych::Nodes::Document nodes must have one and *only* one child. That child # may be one of: # # * Psych::Nodes::Sequence # * Psych::Nodes::Mapping # * Psych::Nodes::Scalar # # Psych::Nodes::Sequence and Psych::Nodes::Mapping nodes may have many # children, but Psych::Nodes::Mapping nodes should have an even number of # children. # # All of these are valid children for Psych::Nodes::Sequence and # Psych::Nodes::Mapping nodes: # # * Psych::Nodes::Sequence # * Psych::Nodes::Mapping # * Psych::Nodes::Scalar # * Psych::Nodes::Alias # # Psych::Nodes::Scalar and Psych::Nodes::Alias are both terminal nodes and # should not have any children. module Nodes end end PK!.2.2.0/psych/coder.rbnu[module Psych ### # If an object defines +encode_with+, then an instance of Psych::Coder will # be passed to the method when the object is being serialized. The Coder # automatically assumes a Psych::Nodes::Mapping is being emitted. Other # objects like Sequence and Scalar may be emitted if +seq=+ or +scalar=+ are # called, respectively. class Coder attr_accessor :tag, :style, :implicit, :object attr_reader :type, :seq def initialize tag @map = {} @seq = [] @implicit = false @type = :map @tag = tag @style = Psych::Nodes::Mapping::BLOCK @scalar = nil @object = nil end def scalar *args if args.length > 0 warn "#{caller[0]}: Coder#scalar(a,b,c) is deprecated" if $VERBOSE @tag, @scalar, _ = args @type = :scalar end @scalar end # Emit a map. The coder will be yielded to the block. def map tag = @tag, style = @style @tag = tag @style = style yield self if block_given? @map end # Emit a scalar with +value+ and +tag+ def represent_scalar tag, value self.tag = tag self.scalar = value end # Emit a sequence with +list+ and +tag+ def represent_seq tag, list @tag = tag self.seq = list end # Emit a sequence with +map+ and +tag+ def represent_map tag, map @tag = tag self.map = map end # Emit an arbitrary object +obj+ and +tag+ def represent_object tag, obj @tag = tag @type = :object @object = obj end # Emit a scalar with +value+ def scalar= value @type = :scalar @scalar = value end # Emit a map with +value+ def map= map @type = :map @map = map end def []= k, v @type = :map @map[k] = v end alias :add :[]= def [] k @type = :map @map[k] end # Emit a sequence of +list+ def seq= list @type = :seq @seq = list end end end PK!Q882.2.0/psych/tree_builder.rbnu[require 'psych/handler' module Psych ### # This class works in conjunction with Psych::Parser to build an in-memory # parse tree that represents a YAML document. # # == Example # # parser = Psych::Parser.new Psych::TreeBuilder.new # parser.parse('--- foo') # tree = parser.handler.root # # See Psych::Handler for documentation on the event methods used in this # class. class TreeBuilder < Psych::Handler # Returns the root node for the built tree attr_reader :root # Create a new TreeBuilder instance def initialize @stack = [] @last = nil @root = nil end %w{ Sequence Mapping }.each do |node| class_eval %{ def start_#{node.downcase}(anchor, tag, implicit, style) n = Nodes::#{node}.new(anchor, tag, implicit, style) @last.children << n push n end def end_#{node.downcase} pop end } end ### # Handles start_document events with +version+, +tag_directives+, # and +implicit+ styling. # # See Psych::Handler#start_document def start_document version, tag_directives, implicit n = Nodes::Document.new version, tag_directives, implicit @last.children << n push n end ### # Handles end_document events with +version+, +tag_directives+, # and +implicit+ styling. # # See Psych::Handler#start_document def end_document implicit_end = !streaming? @last.implicit_end = implicit_end pop end def start_stream encoding @root = Nodes::Stream.new(encoding) push @root end def end_stream pop end def scalar value, anchor, tag, plain, quoted, style s = Nodes::Scalar.new(value,anchor,tag,plain,quoted,style) @last.children << s s end def alias anchor @last.children << Nodes::Alias.new(anchor) end private def push value @stack.push value @last = value end def pop x = @stack.pop @last = @stack.last x end end end PK!w2.2.0/psych/core_ext.rbnu[class Object def self.yaml_tag url Psych.add_tag(url, self) end # FIXME: rename this to "to_yaml" when syck is removed ### # call-seq: to_yaml(options = {}) # # Convert an object to YAML. See Psych.dump for more information on the # available +options+. def psych_to_yaml options = {} Psych.dump self, options end remove_method :to_yaml rescue nil alias :to_yaml :psych_to_yaml end class Module def psych_yaml_as url return if caller[0].end_with?('rubytypes.rb') if $VERBOSE warn "#{caller[0]}: yaml_as is deprecated, please use yaml_tag" end Psych.add_tag(url, self) end remove_method :yaml_as rescue nil alias :yaml_as :psych_yaml_as end if defined?(::IRB) require 'psych/y' end PK!K}}2.2.0/psych/streaming.rbnu[module Psych module Streaming module ClassMethods ### # Create a new streaming emitter. Emitter will print to +io+. See # Psych::Stream for an example. def new io emitter = const_get(:Emitter).new(io) class_loader = ClassLoader.new ss = ScalarScanner.new class_loader super(emitter, ss, {}) end end ### # Start streaming using +encoding+ def start encoding = Nodes::Stream::UTF8 super.tap { yield self if block_given? } ensure finish if block_given? end private def register target, obj end end end PK!4#՜++2.2.0/psych/syntax_error.rbnu[require 'psych/exception' module Psych class SyntaxError < Psych::Exception attr_reader :file, :line, :column, :offset, :problem, :context def initialize file, line, col, offset, problem, context err = [problem, context].compact.join ' ' filename = file || '' message = "(%s): %s at line %d column %d" % [filename, err, line, col] @file = file @line = line @column = col @offset = offset @problem = problem @context = context super(message) end end end PK!@E2.2.0/psych/json/yaml_events.rbnu[module Psych module JSON module YAMLEvents # :nodoc: def start_document version, tag_directives, implicit super(version, tag_directives, !streaming?) end def end_document implicit_end = !streaming? super(implicit_end) end def start_mapping anchor, tag, implicit, style super(anchor, nil, true, Nodes::Mapping::FLOW) end def start_sequence anchor, tag, implicit, style super(anchor, nil, true, Nodes::Sequence::FLOW) end def scalar value, anchor, tag, plain, quoted, style if "tag:yaml.org,2002:null" == tag super('null', nil, nil, true, false, Nodes::Scalar::PLAIN) else super end end end end end PK!p6xx2.2.0/psych/json/stream.rbnu[require 'psych/json/ruby_events' require 'psych/json/yaml_events' module Psych module JSON class Stream < Psych::Visitors::JSONTree include Psych::JSON::RubyEvents include Psych::Streaming extend Psych::Streaming::ClassMethods class Emitter < Psych::Stream::Emitter # :nodoc: include Psych::JSON::YAMLEvents end end end end PK!|2.2.0/psych/json/ruby_events.rbnu[module Psych module JSON module RubyEvents # :nodoc: def visit_Time o formatted = format_time o @emitter.scalar formatted, nil, nil, false, true, Nodes::Scalar::DOUBLE_QUOTED end def visit_DateTime o visit_Time o.to_time end def visit_String o @emitter.scalar o.to_s, nil, nil, false, true, Nodes::Scalar::DOUBLE_QUOTED end alias :visit_Symbol :visit_String end end end PK!?OGG 2.2.0/psych/json/tree_builder.rbnu[require 'psych/json/yaml_events' module Psych module JSON ### # Psych::JSON::TreeBuilder is an event based AST builder. Events are sent # to an instance of Psych::JSON::TreeBuilder and a JSON AST is constructed. class TreeBuilder < Psych::TreeBuilder include Psych::JSON::YAMLEvents end end end PK!S? 2.2.0/psych/visitors.rbnu[require 'psych/visitors/visitor' require 'psych/visitors/to_ruby' require 'psych/visitors/emitter' require 'psych/visitors/yaml_tree' require 'psych/visitors/json_tree' require 'psych/visitors/depth_first' PK!HZ2.2.0/psych/scalar_scanner.rbnu[require 'strscan' module Psych ### # Scan scalars for built in types class ScalarScanner # Taken from http://yaml.org/type/timestamp.html TIME = /^-?\d{4}-\d{1,2}-\d{1,2}(?:[Tt]|\s+)\d{1,2}:\d\d:\d\d(?:\.\d*)?(?:\s*(?:Z|[-+]\d{1,2}:?(?:\d\d)?))?$/ # Taken from http://yaml.org/type/float.html FLOAT = /^(?:[-+]?([0-9][0-9_,]*)?\.[0-9]*([eE][-+][0-9]+)?(?# base 10) |[-+]?[0-9][0-9_,]*(:[0-5]?[0-9])+\.[0-9_]*(?# base 60) |[-+]?\.(inf|Inf|INF)(?# infinity) |\.(nan|NaN|NAN)(?# not a number))$/x # Taken from http://yaml.org/type/int.html INTEGER = /^(?:[-+]?0b[0-1_]+ (?# base 2) |[-+]?0[0-7_]+ (?# base 8) |[-+]?(?:0|[1-9][0-9_]*) (?# base 10) |[-+]?0x[0-9a-fA-F_]+ (?# base 16))$/x attr_reader :class_loader # Create a new scanner def initialize class_loader @string_cache = {} @symbol_cache = {} @class_loader = class_loader end # Tokenize +string+ returning the Ruby object def tokenize string return nil if string.empty? return string if @string_cache.key?(string) return @symbol_cache[string] if @symbol_cache.key?(string) case string # Check for a String type, being careful not to get caught by hash keys, hex values, and # special floats (e.g., -.inf). when /^[^\d\.:-]?[A-Za-z_\s!@#\$%\^&\*\(\)\{\}\<\>\|\/\\~;=]+/, /\n/ if string.length > 5 @string_cache[string] = true return string end case string when /^[^ytonf~]/i @string_cache[string] = true string when '~', /^null$/i nil when /^(yes|true|on)$/i true when /^(no|false|off)$/i false else @string_cache[string] = true string end when TIME begin parse_time string rescue ArgumentError string end when /^\d{4}-(?:1[012]|0\d|\d)-(?:[12]\d|3[01]|0\d|\d)$/ require 'date' begin class_loader.date.strptime(string, '%Y-%m-%d') rescue ArgumentError string end when /^\.inf$/i Float::INFINITY when /^-\.inf$/i -Float::INFINITY when /^\.nan$/i Float::NAN when /^:./ if string =~ /^:(["'])(.*)\1/ @symbol_cache[string] = class_loader.symbolize($2.sub(/^:/, '')) else @symbol_cache[string] = class_loader.symbolize(string.sub(/^:/, '')) end when /^[-+]?[0-9][0-9_]*(:[0-5]?[0-9])+$/ i = 0 string.split(':').each_with_index do |n,e| i += (n.to_i * 60 ** (e - 2).abs) end i when /^[-+]?[0-9][0-9_]*(:[0-5]?[0-9])+\.[0-9_]*$/ i = 0 string.split(':').each_with_index do |n,e| i += (n.to_f * 60 ** (e - 2).abs) end i when FLOAT if string =~ /\A[-+]?\.\Z/ @string_cache[string] = true string else Float(string.gsub(/[,_]|\.$/, '')) end else int = parse_int string.gsub(/[,_]/, '') return int if int @string_cache[string] = true string end end ### # Parse and return an int from +string+ def parse_int string return unless INTEGER === string Integer(string) end ### # Parse and return a Time from +string+ def parse_time string klass = class_loader.load 'Time' date, time = *(string.split(/[ tT]/, 2)) (yy, m, dd) = date.match(/^(-?\d{4})-(\d{1,2})-(\d{1,2})/).captures.map { |x| x.to_i } md = time.match(/(\d+:\d+:\d+)(?:\.(\d*))?\s*(Z|[-+]\d+(:\d\d)?)?/) (hh, mm, ss) = md[1].split(':').map { |x| x.to_i } us = (md[2] ? Rational("0.#{md[2]}") : 0) * 1000000 time = klass.utc(yy, m, dd, hh, mm, ss, us) return time if 'Z' == md[3] return klass.at(time.to_i, us) unless md[3] tz = md[3].match(/^([+\-]?\d{1,2})\:?(\d{1,2})?$/)[1..-1].compact.map { |digit| Integer(digit, 10) } offset = tz.first * 3600 if offset < 0 offset -= ((tz[1] || 0) * 60) else offset += ((tz[1] || 0) * 60) end klass.at((time - offset).to_i, us) end end end PK!u2.2.0/psych/parser.rbnu[module Psych ### # YAML event parser class. This class parses a YAML document and calls # events on the handler that is passed to the constructor. The events can # be used for things such as constructing a YAML AST or deserializing YAML # documents. It can even be fed back to Psych::Emitter to emit the same # document that was parsed. # # See Psych::Handler for documentation on the events that Psych::Parser emits. # # Here is an example that prints out ever scalar found in a YAML document: # # # Handler for detecting scalar values # class ScalarHandler < Psych::Handler # def scalar value, anchor, tag, plain, quoted, style # puts value # end # end # # parser = Psych::Parser.new(ScalarHandler.new) # parser.parse(yaml_document) # # Here is an example that feeds the parser back in to Psych::Emitter. The # YAML document is read from STDIN and written back out to STDERR: # # parser = Psych::Parser.new(Psych::Emitter.new($stderr)) # parser.parse($stdin) # # Psych uses Psych::Parser in combination with Psych::TreeBuilder to # construct an AST of the parsed YAML document. class Parser class Mark < Struct.new(:index, :line, :column) end # The handler on which events will be called attr_accessor :handler # Set the encoding for this parser to +encoding+ attr_writer :external_encoding ### # Creates a new Psych::Parser instance with +handler+. YAML events will # be called on +handler+. See Psych::Parser for more details. def initialize handler = Handler.new @handler = handler @external_encoding = ANY end end end PK!à:D:D2.2.0/ipaddr.rbnu[# # ipaddr.rb - A class to manipulate an IP address # # Copyright (c) 2002 Hajimu UMEMOTO . # Copyright (c) 2007, 2009, 2012 Akinori MUSHA . # All rights reserved. # # You can redistribute and/or modify it under the same terms as Ruby. # # $Id: ipaddr.rb 52741 2015-11-24 15:49:21Z nagachika $ # # Contact: # - Akinori MUSHA (current maintainer) # # TODO: # - scope_id support # require 'socket' # IPAddr provides a set of methods to manipulate an IP address. Both IPv4 and # IPv6 are supported. # # == Example # # require 'ipaddr' # # ipaddr1 = IPAddr.new "3ffe:505:2::1" # # p ipaddr1 #=> # # # p ipaddr1.to_s #=> "3ffe:505:2::1" # # ipaddr2 = ipaddr1.mask(48) #=> # # # p ipaddr2.to_s #=> "3ffe:505:2::" # # ipaddr3 = IPAddr.new "192.168.2.0/24" # # p ipaddr3 #=> # class IPAddr # 32 bit mask for IPv4 IN4MASK = 0xffffffff # 128 bit mask for IPv4 IN6MASK = 0xffffffffffffffffffffffffffffffff # Format string for IPv6 IN6FORMAT = (["%.4x"] * 8).join(':') # Regexp _internally_ used for parsing IPv4 address. RE_IPV4ADDRLIKE = %r{ \A (\d+) \. (\d+) \. (\d+) \. (\d+) \z }x # Regexp _internally_ used for parsing IPv6 address. RE_IPV6ADDRLIKE_FULL = %r{ \A (?: (?: [\da-f]{1,4} : ){7} [\da-f]{1,4} | ( (?: [\da-f]{1,4} : ){6} ) (\d+) \. (\d+) \. (\d+) \. (\d+) ) \z }xi # Regexp _internally_ used for parsing IPv6 address. RE_IPV6ADDRLIKE_COMPRESSED = %r{ \A ( (?: (?: [\da-f]{1,4} : )* [\da-f]{1,4} )? ) :: ( (?: ( (?: [\da-f]{1,4} : )* ) (?: [\da-f]{1,4} | (\d+) \. (\d+) \. (\d+) \. (\d+) ) )? ) \z }xi # Generic IPAddr related error. Exceptions raised in this class should # inherit from Error. class Error < ArgumentError; end # Raised when the provided IP address is an invalid address. class InvalidAddressError < Error; end # Raised when the address family is invalid such as an address with an # unsupported family, an address with an inconsistent family, or an address # who's family cannot be determined. class AddressFamilyError < Error; end # Raised when the address is an invalid length. class InvalidPrefixError < InvalidAddressError; end # Returns the address family of this IP address. attr_reader :family # Creates a new ipaddr containing the given network byte ordered # string form of an IP address. def IPAddr::new_ntoh(addr) return IPAddr.new(IPAddr::ntop(addr)) end # Convert a network byte ordered string form of an IP address into # human readable form. def IPAddr::ntop(addr) case addr.size when 4 s = addr.unpack('C4').join('.') when 16 s = IN6FORMAT % addr.unpack('n8') else raise AddressFamilyError, "unsupported address family" end return s end # Returns a new ipaddr built by bitwise AND. def &(other) return self.clone.set(@addr & coerce_other(other).to_i) end # Returns a new ipaddr built by bitwise OR. def |(other) return self.clone.set(@addr | coerce_other(other).to_i) end # Returns a new ipaddr built by bitwise right-shift. def >>(num) return self.clone.set(@addr >> num) end # Returns a new ipaddr built by bitwise left shift. def <<(num) return self.clone.set(addr_mask(@addr << num)) end # Returns a new ipaddr built by bitwise negation. def ~ return self.clone.set(addr_mask(~@addr)) end # Returns true if two ipaddrs are equal. def ==(other) other = coerce_other(other) return @family == other.family && @addr == other.to_i end # Returns a new ipaddr built by masking IP address with the given # prefixlen/netmask. (e.g. 8, 64, "255.255.255.0", etc.) def mask(prefixlen) return self.clone.mask!(prefixlen) end # Returns true if the given ipaddr is in the range. # # e.g.: # require 'ipaddr' # net1 = IPAddr.new("192.168.2.0/24") # net2 = IPAddr.new("192.168.2.100") # net3 = IPAddr.new("192.168.3.0") # p net1.include?(net2) #=> true # p net1.include?(net3) #=> false def include?(other) other = coerce_other(other) if ipv4_mapped? if (@mask_addr >> 32) != 0xffffffffffffffffffffffff return false end mask_addr = (@mask_addr & IN4MASK) addr = (@addr & IN4MASK) family = Socket::AF_INET else mask_addr = @mask_addr addr = @addr family = @family end if other.ipv4_mapped? other_addr = (other.to_i & IN4MASK) other_family = Socket::AF_INET else other_addr = other.to_i other_family = other.family end if family != other_family return false end return ((addr & mask_addr) == (other_addr & mask_addr)) end alias === include? # Returns the integer representation of the ipaddr. def to_i return @addr end # Returns a string containing the IP address representation. def to_s str = to_string return str if ipv4? str.gsub!(/\b0{1,3}([\da-f]+)\b/i, '\1') loop do break if str.sub!(/\A0:0:0:0:0:0:0:0\z/, '::') break if str.sub!(/\b0:0:0:0:0:0:0\b/, ':') break if str.sub!(/\b0:0:0:0:0:0\b/, ':') break if str.sub!(/\b0:0:0:0:0\b/, ':') break if str.sub!(/\b0:0:0:0\b/, ':') break if str.sub!(/\b0:0:0\b/, ':') break if str.sub!(/\b0:0\b/, ':') break end str.sub!(/:{3,}/, '::') if /\A::(ffff:)?([\da-f]{1,4}):([\da-f]{1,4})\z/i =~ str str = sprintf('::%s%d.%d.%d.%d', $1, $2.hex / 256, $2.hex % 256, $3.hex / 256, $3.hex % 256) end str end # Returns a string containing the IP address representation in # canonical form. def to_string return _to_string(@addr) end # Returns a network byte ordered string form of the IP address. def hton case @family when Socket::AF_INET return [@addr].pack('N') when Socket::AF_INET6 return (0..7).map { |i| (@addr >> (112 - 16 * i)) & 0xffff }.pack('n8') else raise AddressFamilyError, "unsupported address family" end end # Returns true if the ipaddr is an IPv4 address. def ipv4? return @family == Socket::AF_INET end # Returns true if the ipaddr is an IPv6 address. def ipv6? return @family == Socket::AF_INET6 end # Returns true if the ipaddr is an IPv4-mapped IPv6 address. def ipv4_mapped? return ipv6? && (@addr >> 32) == 0xffff end # Returns true if the ipaddr is an IPv4-compatible IPv6 address. def ipv4_compat? if !ipv6? || (@addr >> 32) != 0 return false end a = (@addr & IN4MASK) return a != 0 && a != 1 end # Returns a new ipaddr built by converting the native IPv4 address # into an IPv4-mapped IPv6 address. def ipv4_mapped if !ipv4? raise InvalidAddressError, "not an IPv4 address" end return self.clone.set(@addr | 0xffff00000000, Socket::AF_INET6) end # Returns a new ipaddr built by converting the native IPv4 address # into an IPv4-compatible IPv6 address. def ipv4_compat if !ipv4? raise InvalidAddressError, "not an IPv4 address" end return self.clone.set(@addr, Socket::AF_INET6) end # Returns a new ipaddr built by converting the IPv6 address into a # native IPv4 address. If the IP address is not an IPv4-mapped or # IPv4-compatible IPv6 address, returns self. def native if !ipv4_mapped? && !ipv4_compat? return self end return self.clone.set(@addr & IN4MASK, Socket::AF_INET) end # Returns a string for DNS reverse lookup. It returns a string in # RFC3172 form for an IPv6 address. def reverse case @family when Socket::AF_INET return _reverse + ".in-addr.arpa" when Socket::AF_INET6 return ip6_arpa else raise AddressFamilyError, "unsupported address family" end end # Returns a string for DNS reverse lookup compatible with RFC3172. def ip6_arpa if !ipv6? raise InvalidAddressError, "not an IPv6 address" end return _reverse + ".ip6.arpa" end # Returns a string for DNS reverse lookup compatible with RFC1886. def ip6_int if !ipv6? raise InvalidAddressError, "not an IPv6 address" end return _reverse + ".ip6.int" end # Returns the successor to the ipaddr. def succ return self.clone.set(@addr + 1, @family) end # Compares the ipaddr with another. def <=>(other) other = coerce_other(other) return nil if other.family != @family return @addr <=> other.to_i end include Comparable # Checks equality used by Hash. def eql?(other) return self.class == other.class && self.hash == other.hash && self == other end # Returns a hash value used by Hash, Set, and Array classes def hash return ([@addr, @mask_addr].hash << 1) | (ipv4? ? 0 : 1) end # Creates a Range object for the network address. def to_range begin_addr = (@addr & @mask_addr) case @family when Socket::AF_INET end_addr = (@addr | (IN4MASK ^ @mask_addr)) when Socket::AF_INET6 end_addr = (@addr | (IN6MASK ^ @mask_addr)) else raise AddressFamilyError, "unsupported address family" end return clone.set(begin_addr, @family)..clone.set(end_addr, @family) end # Returns a string containing a human-readable representation of the # ipaddr. ("#") def inspect case @family when Socket::AF_INET af = "IPv4" when Socket::AF_INET6 af = "IPv6" else raise AddressFamilyError, "unsupported address family" end return sprintf("#<%s: %s:%s/%s>", self.class.name, af, _to_string(@addr), _to_string(@mask_addr)) end protected # Set +@addr+, the internal stored ip address, to given +addr+. The # parameter +addr+ is validated using the first +family+ member, # which is +Socket::AF_INET+ or +Socket::AF_INET6+. def set(addr, *family) case family[0] ? family[0] : @family when Socket::AF_INET if addr < 0 || addr > IN4MASK raise InvalidAddressError, "invalid address" end when Socket::AF_INET6 if addr < 0 || addr > IN6MASK raise InvalidAddressError, "invalid address" end else raise AddressFamilyError, "unsupported address family" end @addr = addr if family[0] @family = family[0] end return self end # Set current netmask to given mask. def mask!(mask) if mask.kind_of?(String) if mask =~ /\A\d+\z/ prefixlen = mask.to_i else m = IPAddr.new(mask) if m.family != @family raise InvalidPrefixError, "address family is not same" end @mask_addr = m.to_i @addr &= @mask_addr return self end else prefixlen = mask end case @family when Socket::AF_INET if prefixlen < 0 || prefixlen > 32 raise InvalidPrefixError, "invalid length" end masklen = 32 - prefixlen @mask_addr = ((IN4MASK >> masklen) << masklen) when Socket::AF_INET6 if prefixlen < 0 || prefixlen > 128 raise InvalidPrefixError, "invalid length" end masklen = 128 - prefixlen @mask_addr = ((IN6MASK >> masklen) << masklen) else raise AddressFamilyError, "unsupported address family" end @addr = ((@addr >> masklen) << masklen) return self end private # Creates a new ipaddr object either from a human readable IP # address representation in string, or from a packed in_addr value # followed by an address family. # # In the former case, the following are the valid formats that will # be recognized: "address", "address/prefixlen" and "address/mask", # where IPv6 address may be enclosed in square brackets (`[' and # `]'). If a prefixlen or a mask is specified, it returns a masked # IP address. Although the address family is determined # automatically from a specified string, you can specify one # explicitly by the optional second argument. # # Otherwise an IP address is generated from a packed in_addr value # and an address family. # # The IPAddr class defines many methods and operators, and some of # those, such as &, |, include? and ==, accept a string, or a packed # in_addr value instead of an IPAddr object. def initialize(addr = '::', family = Socket::AF_UNSPEC) if !addr.kind_of?(String) case family when Socket::AF_INET, Socket::AF_INET6 set(addr.to_i, family) @mask_addr = (family == Socket::AF_INET) ? IN4MASK : IN6MASK return when Socket::AF_UNSPEC raise AddressFamilyError, "address family must be specified" else raise AddressFamilyError, "unsupported address family: #{family}" end end prefix, prefixlen = addr.split('/') if prefix =~ /\A\[(.*)\]\z/i prefix = $1 family = Socket::AF_INET6 end # It seems AI_NUMERICHOST doesn't do the job. #Socket.getaddrinfo(left, nil, Socket::AF_INET6, Socket::SOCK_STREAM, nil, # Socket::AI_NUMERICHOST) @addr = @family = nil if family == Socket::AF_UNSPEC || family == Socket::AF_INET @addr = in_addr(prefix) if @addr @family = Socket::AF_INET end end if !@addr && (family == Socket::AF_UNSPEC || family == Socket::AF_INET6) @addr = in6_addr(prefix) @family = Socket::AF_INET6 end if family != Socket::AF_UNSPEC && @family != family raise AddressFamilyError, "address family mismatch" end if prefixlen mask!(prefixlen) else @mask_addr = (@family == Socket::AF_INET) ? IN4MASK : IN6MASK end end def coerce_other(other) case other when IPAddr other when String self.class.new(other) else self.class.new(other, @family) end end def in_addr(addr) case addr when Array octets = addr else m = RE_IPV4ADDRLIKE.match(addr) or return nil octets = m.captures end octets.inject(0) { |i, s| (n = s.to_i) < 256 or raise InvalidAddressError, "invalid address" s.match(/\A0./) and raise InvalidAddressError, "zero-filled number in IPv4 address is ambiguous" i << 8 | n } end def in6_addr(left) case left when RE_IPV6ADDRLIKE_FULL if $2 addr = in_addr($~[2,4]) left = $1 + ':' else addr = 0 end right = '' when RE_IPV6ADDRLIKE_COMPRESSED if $4 left.count(':') <= 6 or raise InvalidAddressError, "invalid address" addr = in_addr($~[4,4]) left = $1 right = $3 + '0:0' else left.count(':') <= ($1.empty? || $2.empty? ? 8 : 7) or raise InvalidAddressError, "invalid address" left = $1 right = $2 addr = 0 end else raise InvalidAddressError, "invalid address" end l = left.split(':') r = right.split(':') rest = 8 - l.size - r.size if rest < 0 return nil end (l + Array.new(rest, '0') + r).inject(0) { |i, s| i << 16 | s.hex } | addr end def addr_mask(addr) case @family when Socket::AF_INET return addr & IN4MASK when Socket::AF_INET6 return addr & IN6MASK else raise AddressFamilyError, "unsupported address family" end end def _reverse case @family when Socket::AF_INET return (0..3).map { |i| (@addr >> (8 * i)) & 0xff }.join('.') when Socket::AF_INET6 return ("%.32x" % @addr).reverse!.gsub!(/.(?!$)/, '\&.') else raise AddressFamilyError, "unsupported address family" end end def _to_string(addr) case @family when Socket::AF_INET return (0..3).map { |i| (addr >> (24 - 8 * i)) & 0xff }.join('.') when Socket::AF_INET6 return (("%.32x" % addr).gsub!(/.{4}(?!$)/, '\&:')) else raise AddressFamilyError, "unsupported address family" end end end unless Socket.const_defined? :AF_INET6 class Socket < BasicSocket # IPv6 protocol family AF_INET6 = Object.new end class << IPSocket private def valid_v6?(addr) case addr when IPAddr::RE_IPV6ADDRLIKE_FULL if $2 $~[2,4].all? {|i| i.to_i < 256 } else true end when IPAddr::RE_IPV6ADDRLIKE_COMPRESSED if $4 addr.count(':') <= 6 && $~[4,4].all? {|i| i.to_i < 256} else addr.count(':') <= 7 end else false end end alias getaddress_orig getaddress public # Returns a +String+ based representation of a valid DNS hostname, # IPv4 or IPv6 address. # # IPSocket.getaddress 'localhost' #=> "::1" # IPSocket.getaddress 'broadcasthost' #=> "255.255.255.255" # IPSocket.getaddress 'www.ruby-lang.org' #=> "221.186.184.68" # IPSocket.getaddress 'www.ccc.de' #=> "2a00:1328:e102:ccc0::122" def getaddress(s) if valid_v6?(s) s else getaddress_orig(s) end end end end PK!ϕg/:/:2.2.0/pstore.rbnu[# = PStore -- Transactional File Storage for Ruby Objects # # pstore.rb - # originally by matz # documentation by Kev Jackson and James Edward Gray II # improved by Hongli Lai # # See PStore for documentation. require "digest/md5" # # PStore implements a file based persistence mechanism based on a Hash. User # code can store hierarchies of Ruby objects (values) into the data store file # by name (keys). An object hierarchy may be just a single object. User code # may later read values back from the data store or even update data, as needed. # # The transactional behavior ensures that any changes succeed or fail together. # This can be used to ensure that the data store is not left in a transitory # state, where some values were updated but others were not. # # Behind the scenes, Ruby objects are stored to the data store file with # Marshal. That carries the usual limitations. Proc objects cannot be # marshalled, for example. # # == Usage example: # # require "pstore" # # # a mock wiki object... # class WikiPage # def initialize( page_name, author, contents ) # @page_name = page_name # @revisions = Array.new # # add_revision(author, contents) # end # # attr_reader :page_name # # def add_revision( author, contents ) # @revisions << { :created => Time.now, # :author => author, # :contents => contents } # end # # def wiki_page_references # [@page_name] + @revisions.last[:contents].scan(/\b(?:[A-Z]+[a-z]+){2,}/) # end # # # ... # end # # # create a new page... # home_page = WikiPage.new( "HomePage", "James Edward Gray II", # "A page about the JoysOfDocumentation..." ) # # # then we want to update page data and the index together, or not at all... # wiki = PStore.new("wiki_pages.pstore") # wiki.transaction do # begin transaction; do all of this or none of it # # store page... # wiki[home_page.page_name] = home_page # # ensure that an index has been created... # wiki[:wiki_index] ||= Array.new # # update wiki index... # wiki[:wiki_index].push(*home_page.wiki_page_references) # end # commit changes to wiki data store file # # ### Some time later... ### # # # read wiki data... # wiki.transaction(true) do # begin read-only transaction, no changes allowed # wiki.roots.each do |data_root_name| # p data_root_name # p wiki[data_root_name] # end # end # # == Transaction modes # # By default, file integrity is only ensured as long as the operating system # (and the underlying hardware) doesn't raise any unexpected I/O errors. If an # I/O error occurs while PStore is writing to its file, then the file will # become corrupted. # # You can prevent this by setting pstore.ultra_safe = true. # However, this results in a minor performance loss, and only works on platforms # that support atomic file renames. Please consult the documentation for # +ultra_safe+ for details. # # Needless to say, if you're storing valuable data with PStore, then you should # backup the PStore files from time to time. class PStore RDWR_ACCESS = {mode: IO::RDWR | IO::CREAT | IO::BINARY, encoding: Encoding::ASCII_8BIT}.freeze RD_ACCESS = {mode: IO::RDONLY | IO::BINARY, encoding: Encoding::ASCII_8BIT}.freeze WR_ACCESS = {mode: IO::WRONLY | IO::CREAT | IO::TRUNC | IO::BINARY, encoding: Encoding::ASCII_8BIT}.freeze # The error type thrown by all PStore methods. class Error < StandardError end # Whether PStore should do its best to prevent file corruptions, even when under # unlikely-to-occur error conditions such as out-of-space conditions and other # unusual OS filesystem errors. Setting this flag comes at the price in the form # of a performance loss. # # This flag only has effect on platforms on which file renames are atomic (e.g. # all POSIX platforms: Linux, MacOS X, FreeBSD, etc). The default value is false. attr_accessor :ultra_safe # # To construct a PStore object, pass in the _file_ path where you would like # the data to be stored. # # PStore objects are always reentrant. But if _thread_safe_ is set to true, # then it will become thread-safe at the cost of a minor performance hit. # def initialize(file, thread_safe = false) dir = File::dirname(file) unless File::directory? dir raise PStore::Error, format("directory %s does not exist", dir) end if File::exist? file and not File::readable? file raise PStore::Error, format("file %s not readable", file) end @filename = file @abort = false @ultra_safe = false @thread_safe = thread_safe @lock = Mutex.new end # Raises PStore::Error if the calling code is not in a PStore#transaction. def in_transaction raise PStore::Error, "not in transaction" unless @lock.locked? end # # Raises PStore::Error if the calling code is not in a PStore#transaction or # if the code is in a read-only PStore#transaction. # def in_transaction_wr in_transaction raise PStore::Error, "in read-only transaction" if @rdonly end private :in_transaction, :in_transaction_wr # # Retrieves a value from the PStore file data, by _name_. The hierarchy of # Ruby objects stored under that root _name_ will be returned. # # *WARNING*: This method is only valid in a PStore#transaction. It will # raise PStore::Error if called at any other time. # def [](name) in_transaction @table[name] end # # This method is just like PStore#[], save that you may also provide a # _default_ value for the object. In the event the specified _name_ is not # found in the data store, your _default_ will be returned instead. If you do # not specify a default, PStore::Error will be raised if the object is not # found. # # *WARNING*: This method is only valid in a PStore#transaction. It will # raise PStore::Error if called at any other time. # def fetch(name, default=PStore::Error) in_transaction unless @table.key? name if default == PStore::Error raise PStore::Error, format("undefined root name `%s'", name) else return default end end @table[name] end # # Stores an individual Ruby object or a hierarchy of Ruby objects in the data # store file under the root _name_. Assigning to a _name_ already in the data # store clobbers the old data. # # == Example: # # require "pstore" # # store = PStore.new("data_file.pstore") # store.transaction do # begin transaction # # load some data into the store... # store[:single_object] = "My data..." # store[:obj_heirarchy] = { "Kev Jackson" => ["rational.rb", "pstore.rb"], # "James Gray" => ["erb.rb", "pstore.rb"] } # end # commit changes to data store file # # *WARNING*: This method is only valid in a PStore#transaction and it cannot # be read-only. It will raise PStore::Error if called at any other time. # def []=(name, value) in_transaction_wr @table[name] = value end # # Removes an object hierarchy from the data store, by _name_. # # *WARNING*: This method is only valid in a PStore#transaction and it cannot # be read-only. It will raise PStore::Error if called at any other time. # def delete(name) in_transaction_wr @table.delete name end # # Returns the names of all object hierarchies currently in the store. # # *WARNING*: This method is only valid in a PStore#transaction. It will # raise PStore::Error if called at any other time. # def roots in_transaction @table.keys end # # Returns true if the supplied _name_ is currently in the data store. # # *WARNING*: This method is only valid in a PStore#transaction. It will # raise PStore::Error if called at any other time. # def root?(name) in_transaction @table.key? name end # Returns the path to the data store file. def path @filename end # # Ends the current PStore#transaction, committing any changes to the data # store immediately. # # == Example: # # require "pstore" # # store = PStore.new("data_file.pstore") # store.transaction do # begin transaction # # load some data into the store... # store[:one] = 1 # store[:two] = 2 # # store.commit # end transaction here, committing changes # # store[:three] = 3 # this change is never reached # end # # *WARNING*: This method is only valid in a PStore#transaction. It will # raise PStore::Error if called at any other time. # def commit in_transaction @abort = false throw :pstore_abort_transaction end # # Ends the current PStore#transaction, discarding any changes to the data # store. # # == Example: # # require "pstore" # # store = PStore.new("data_file.pstore") # store.transaction do # begin transaction # store[:one] = 1 # this change is not applied, see below... # store[:two] = 2 # this change is not applied, see below... # # store.abort # end transaction here, discard all changes # # store[:three] = 3 # this change is never reached # end # # *WARNING*: This method is only valid in a PStore#transaction. It will # raise PStore::Error if called at any other time. # def abort in_transaction @abort = true throw :pstore_abort_transaction end # # Opens a new transaction for the data store. Code executed inside a block # passed to this method may read and write data to and from the data store # file. # # At the end of the block, changes are committed to the data store # automatically. You may exit the transaction early with a call to either # PStore#commit or PStore#abort. See those methods for details about how # changes are handled. Raising an uncaught Exception in the block is # equivalent to calling PStore#abort. # # If _read_only_ is set to +true+, you will only be allowed to read from the # data store during the transaction and any attempts to change the data will # raise a PStore::Error. # # Note that PStore does not support nested transactions. # def transaction(read_only = false) # :yields: pstore value = nil if !@thread_safe raise PStore::Error, "nested transaction" unless @lock.try_lock else begin @lock.lock rescue ThreadError raise PStore::Error, "nested transaction" end end begin @rdonly = read_only @abort = false file = open_and_lock_file(@filename, read_only) if file begin @table, checksum, original_data_size = load_data(file, read_only) catch(:pstore_abort_transaction) do value = yield(self) end if !@abort && !read_only save_data(checksum, original_data_size, file) end ensure file.close if !file.closed? end else # This can only occur if read_only == true. @table = {} catch(:pstore_abort_transaction) do value = yield(self) end end ensure @lock.unlock end value end private # Constant for relieving Ruby's garbage collector. EMPTY_STRING = "" EMPTY_MARSHAL_DATA = Marshal.dump({}) EMPTY_MARSHAL_CHECKSUM = Digest::MD5.digest(EMPTY_MARSHAL_DATA) # # Open the specified filename (either in read-only mode or in # read-write mode) and lock it for reading or writing. # # The opened File object will be returned. If _read_only_ is true, # and the file does not exist, then nil will be returned. # # All exceptions are propagated. # def open_and_lock_file(filename, read_only) if read_only begin file = File.new(filename, RD_ACCESS) begin file.flock(File::LOCK_SH) return file rescue file.close raise end rescue Errno::ENOENT return nil end else file = File.new(filename, RDWR_ACCESS) file.flock(File::LOCK_EX) return file end end # Load the given PStore file. # If +read_only+ is true, the unmarshalled Hash will be returned. # If +read_only+ is false, a 3-tuple will be returned: the unmarshalled # Hash, an MD5 checksum of the data, and the size of the data. def load_data(file, read_only) if read_only begin table = load(file) raise Error, "PStore file seems to be corrupted." unless table.is_a?(Hash) rescue EOFError # This seems to be a newly-created file. table = {} end table else data = file.read if data.empty? # This seems to be a newly-created file. table = {} checksum = empty_marshal_checksum size = empty_marshal_data.bytesize else table = load(data) checksum = Digest::MD5.digest(data) size = data.bytesize raise Error, "PStore file seems to be corrupted." unless table.is_a?(Hash) end data.replace(EMPTY_STRING) [table, checksum, size] end end def on_windows? is_windows = RUBY_PLATFORM =~ /mswin|mingw|bccwin|wince/ self.class.__send__(:define_method, :on_windows?) do is_windows end is_windows end def save_data(original_checksum, original_file_size, file) new_data = dump(@table) if new_data.bytesize != original_file_size || Digest::MD5.digest(new_data) != original_checksum if @ultra_safe && !on_windows? # Windows doesn't support atomic file renames. save_data_with_atomic_file_rename_strategy(new_data, file) else save_data_with_fast_strategy(new_data, file) end end new_data.replace(EMPTY_STRING) end def save_data_with_atomic_file_rename_strategy(data, file) temp_filename = "#{@filename}.tmp.#{Process.pid}.#{rand 1000000}" temp_file = File.new(temp_filename, WR_ACCESS) begin temp_file.flock(File::LOCK_EX) temp_file.write(data) temp_file.flush File.rename(temp_filename, @filename) rescue File.unlink(temp_file) rescue nil raise ensure temp_file.close end end def save_data_with_fast_strategy(data, file) file.rewind file.write(data) file.truncate(data.bytesize) end # This method is just a wrapped around Marshal.dump # to allow subclass overriding used in YAML::Store. def dump(table) # :nodoc: Marshal::dump(table) end # This method is just a wrapped around Marshal.load. # to allow subclass overriding used in YAML::Store. def load(content) # :nodoc: Marshal::load(content) end def empty_marshal_data EMPTY_MARSHAL_DATA end def empty_marshal_checksum EMPTY_MARSHAL_CHECKSUM end end PK!B2.2.0/net/telnet.rbnu[# = net/telnet.rb - Simple Telnet Client Library # # Author:: Wakou Aoyama # Documentation:: William Webber and Wakou Aoyama # # This file holds the class Net::Telnet, which provides client-side # telnet functionality. # # For documentation, see Net::Telnet. # require "net/protocol" require "English" module Net # # == Net::Telnet # # Provides telnet client functionality. # # This class also has, through delegation, all the methods of a # socket object (by default, a +TCPSocket+, but can be set by the # +Proxy+ option to new()). This provides methods such as # close() to end the session and sysread() to read # data directly from the host, instead of via the waitfor() # mechanism. Note that if you do use sysread() directly # when in telnet mode, you should probably pass the output through # preprocess() to extract telnet command sequences. # # == Overview # # The telnet protocol allows a client to login remotely to a user # account on a server and execute commands via a shell. The equivalent # is done by creating a Net::Telnet class with the +Host+ option # set to your host, calling #login() with your user and password, # issuing one or more #cmd() calls, and then calling #close() # to end the session. The #waitfor(), #print(), #puts(), and # #write() methods, which #cmd() is implemented on top of, are # only needed if you are doing something more complicated. # # A Net::Telnet object can also be used to connect to non-telnet # services, such as SMTP or HTTP. In this case, you normally # want to provide the +Port+ option to specify the port to # connect to, and set the +Telnetmode+ option to false to prevent # the client from attempting to interpret telnet command sequences. # Generally, #login() will not work with other protocols, and you # have to handle authentication yourself. # # For some protocols, it will be possible to specify the +Prompt+ # option once when you create the Telnet object and use #cmd() calls; # for others, you will have to specify the response sequence to # look for as the Match option to every #cmd() call, or call # #puts() and #waitfor() directly; for yet others, you will have # to use #sysread() instead of #waitfor() and parse server # responses yourself. # # It is worth noting that when you create a new Net::Telnet object, # you can supply a proxy IO channel via the Proxy option. This # can be used to attach the Telnet object to other Telnet objects, # to already open sockets, or to any read-write IO object. This # can be useful, for instance, for setting up a test fixture for # unit testing. # # == Examples # # === Log in and send a command, echoing all output to stdout # # localhost = Net::Telnet::new("Host" => "localhost", # "Timeout" => 10, # "Prompt" => /[$%#>] \z/n) # localhost.login("username", "password") { |c| print c } # localhost.cmd("command") { |c| print c } # localhost.close # # # === Check a POP server to see if you have mail # # pop = Net::Telnet::new("Host" => "your_destination_host_here", # "Port" => 110, # "Telnetmode" => false, # "Prompt" => /^\+OK/n) # pop.cmd("user " + "your_username_here") { |c| print c } # pop.cmd("pass " + "your_password_here") { |c| print c } # pop.cmd("list") { |c| print c } # # == References # # There are a large number of RFCs relevant to the Telnet protocol. # RFCs 854-861 define the base protocol. For a complete listing # of relevant RFCs, see # http://www.omnifarious.org/~hopper/technical/telnet-rfc.html # class Telnet # :stopdoc: IAC = 255.chr # "\377" # "\xff" # interpret as command DONT = 254.chr # "\376" # "\xfe" # you are not to use option DO = 253.chr # "\375" # "\xfd" # please, you use option WONT = 252.chr # "\374" # "\xfc" # I won't use option WILL = 251.chr # "\373" # "\xfb" # I will use option SB = 250.chr # "\372" # "\xfa" # interpret as subnegotiation GA = 249.chr # "\371" # "\xf9" # you may reverse the line EL = 248.chr # "\370" # "\xf8" # erase the current line EC = 247.chr # "\367" # "\xf7" # erase the current character AYT = 246.chr # "\366" # "\xf6" # are you there AO = 245.chr # "\365" # "\xf5" # abort output--but let prog finish IP = 244.chr # "\364" # "\xf4" # interrupt process--permanently BREAK = 243.chr # "\363" # "\xf3" # break DM = 242.chr # "\362" # "\xf2" # data mark--for connect. cleaning NOP = 241.chr # "\361" # "\xf1" # nop SE = 240.chr # "\360" # "\xf0" # end sub negotiation EOR = 239.chr # "\357" # "\xef" # end of record (transparent mode) ABORT = 238.chr # "\356" # "\xee" # Abort process SUSP = 237.chr # "\355" # "\xed" # Suspend process EOF = 236.chr # "\354" # "\xec" # End of file SYNCH = 242.chr # "\362" # "\xf2" # for telfunc calls OPT_BINARY = 0.chr # "\000" # "\x00" # Binary Transmission OPT_ECHO = 1.chr # "\001" # "\x01" # Echo OPT_RCP = 2.chr # "\002" # "\x02" # Reconnection OPT_SGA = 3.chr # "\003" # "\x03" # Suppress Go Ahead OPT_NAMS = 4.chr # "\004" # "\x04" # Approx Message Size Negotiation OPT_STATUS = 5.chr # "\005" # "\x05" # Status OPT_TM = 6.chr # "\006" # "\x06" # Timing Mark OPT_RCTE = 7.chr # "\a" # "\x07" # Remote Controlled Trans and Echo OPT_NAOL = 8.chr # "\010" # "\x08" # Output Line Width OPT_NAOP = 9.chr # "\t" # "\x09" # Output Page Size OPT_NAOCRD = 10.chr # "\n" # "\x0a" # Output Carriage-Return Disposition OPT_NAOHTS = 11.chr # "\v" # "\x0b" # Output Horizontal Tab Stops OPT_NAOHTD = 12.chr # "\f" # "\x0c" # Output Horizontal Tab Disposition OPT_NAOFFD = 13.chr # "\r" # "\x0d" # Output Formfeed Disposition OPT_NAOVTS = 14.chr # "\016" # "\x0e" # Output Vertical Tabstops OPT_NAOVTD = 15.chr # "\017" # "\x0f" # Output Vertical Tab Disposition OPT_NAOLFD = 16.chr # "\020" # "\x10" # Output Linefeed Disposition OPT_XASCII = 17.chr # "\021" # "\x11" # Extended ASCII OPT_LOGOUT = 18.chr # "\022" # "\x12" # Logout OPT_BM = 19.chr # "\023" # "\x13" # Byte Macro OPT_DET = 20.chr # "\024" # "\x14" # Data Entry Terminal OPT_SUPDUP = 21.chr # "\025" # "\x15" # SUPDUP OPT_SUPDUPOUTPUT = 22.chr # "\026" # "\x16" # SUPDUP Output OPT_SNDLOC = 23.chr # "\027" # "\x17" # Send Location OPT_TTYPE = 24.chr # "\030" # "\x18" # Terminal Type OPT_EOR = 25.chr # "\031" # "\x19" # End of Record OPT_TUID = 26.chr # "\032" # "\x1a" # TACACS User Identification OPT_OUTMRK = 27.chr # "\e" # "\x1b" # Output Marking OPT_TTYLOC = 28.chr # "\034" # "\x1c" # Terminal Location Number OPT_3270REGIME = 29.chr # "\035" # "\x1d" # Telnet 3270 Regime OPT_X3PAD = 30.chr # "\036" # "\x1e" # X.3 PAD OPT_NAWS = 31.chr # "\037" # "\x1f" # Negotiate About Window Size OPT_TSPEED = 32.chr # " " # "\x20" # Terminal Speed OPT_LFLOW = 33.chr # "!" # "\x21" # Remote Flow Control OPT_LINEMODE = 34.chr # "\"" # "\x22" # Linemode OPT_XDISPLOC = 35.chr # "#" # "\x23" # X Display Location OPT_OLD_ENVIRON = 36.chr # "$" # "\x24" # Environment Option OPT_AUTHENTICATION = 37.chr # "%" # "\x25" # Authentication Option OPT_ENCRYPT = 38.chr # "&" # "\x26" # Encryption Option OPT_NEW_ENVIRON = 39.chr # "'" # "\x27" # New Environment Option OPT_EXOPL = 255.chr # "\377" # "\xff" # Extended-Options-List NULL = "\000" CR = "\015" LF = "\012" EOL = CR + LF REVISION = '$Id: telnet.rb 47298 2014-08-27 12:10:21Z hsbt $' # :startdoc: # # Creates a new Net::Telnet object. # # Attempts to connect to the host (unless the Proxy option is # provided: see below). If a block is provided, it is yielded # status messages on the attempt to connect to the server, of # the form: # # Trying localhost... # Connected to localhost. # # +options+ is a hash of options. The following example lists # all options and their default values. # # host = Net::Telnet::new( # "Host" => "localhost", # default: "localhost" # "Port" => 23, # default: 23 # "Binmode" => false, # default: false # "Output_log" => "output_log", # default: nil (no output) # "Dump_log" => "dump_log", # default: nil (no output) # "Prompt" => /[$%#>] \z/n, # default: /[$%#>] \z/n # "Telnetmode" => true, # default: true # "Timeout" => 10, # default: 10 # # if ignore timeout then set "Timeout" to false. # "Waittime" => 0, # default: 0 # "Proxy" => proxy # default: nil # # proxy is Net::Telnet or IO object # ) # # The options have the following meanings: # # Host:: the hostname or IP address of the host to connect to, as a String. # Defaults to "localhost". # # Port:: the port to connect to. Defaults to 23. # # Binmode:: if false (the default), newline substitution is performed. # Outgoing LF is # converted to CRLF, and incoming CRLF is converted to LF. If # true, this substitution is not performed. This value can # also be set with the #binmode() method. The # outgoing conversion only applies to the #puts() and #print() # methods, not the #write() method. The precise nature of # the newline conversion is also affected by the telnet options # SGA and BIN. # # Output_log:: the name of the file to write connection status messages # and all received traffic to. In the case of a proper # Telnet session, this will include the client input as # echoed by the host; otherwise, it only includes server # responses. Output is appended verbatim to this file. # By default, no output log is kept. # # Dump_log:: as for Output_log, except that output is written in hexdump # format (16 bytes per line as hex pairs, followed by their # printable equivalent), with connection status messages # preceded by '#', sent traffic preceded by '>', and # received traffic preceded by '<'. By default, not dump log # is kept. # # Prompt:: a regular expression matching the host's command-line prompt # sequence. This is needed by the Telnet class to determine # when the output from a command has finished and the host is # ready to receive a new command. By default, this regular # expression is /[$%#>] \z/n. # # Telnetmode:: a boolean value, true by default. In telnet mode, # traffic received from the host is parsed for special # command sequences, and these sequences are escaped # in outgoing traffic sent using #puts() or #print() # (but not #write()). If you are using the Net::Telnet # object to connect to a non-telnet service (such as # SMTP or POP), this should be set to "false" to prevent # undesired data corruption. This value can also be set # by the #telnetmode() method. # # Timeout:: the number of seconds to wait before timing out both the # initial attempt to connect to host (in this constructor), # which raises a Net::OpenTimeout, and all attempts to read data # from the host, which raises a Net::ReadTimeout (in #waitfor(), # #cmd(), and #login()). The default value is 10 seconds. # You can disable the timeout by setting this value to false. # In this case, the connect attempt will eventually timeout # on the underlying connect(2) socket call with an # Errno::ETIMEDOUT error (but generally only after a few # minutes), but other attempts to read data from the host # will hang indefinitely if no data is forthcoming. # # Waittime:: the amount of time to wait after seeing what looks like a # prompt (that is, received data that matches the Prompt # option regular expression) to see if more data arrives. # If more data does arrive in this time, Net::Telnet assumes # that what it saw was not really a prompt. This is to try to # avoid false matches, but it can also lead to missing real # prompts (if, for instance, a background process writes to # the terminal soon after the prompt is displayed). By # default, set to 0, meaning not to wait for more data. # # Proxy:: a proxy object to used instead of opening a direct connection # to the host. Must be either another Net::Telnet object or # an IO object. If it is another Net::Telnet object, this # instance will use that one's socket for communication. If an # IO object, it is used directly for communication. Any other # kind of object will cause an error to be raised. # def initialize(options) # :yield: mesg @options = options @options["Host"] = "localhost" unless @options.has_key?("Host") @options["Port"] = 23 unless @options.has_key?("Port") @options["Prompt"] = /[$%#>] \z/n unless @options.has_key?("Prompt") @options["Timeout"] = 10 unless @options.has_key?("Timeout") @options["Waittime"] = 0 unless @options.has_key?("Waittime") unless @options.has_key?("Binmode") @options["Binmode"] = false else unless (true == @options["Binmode"] or false == @options["Binmode"]) raise ArgumentError, "Binmode option must be true or false" end end unless @options.has_key?("Telnetmode") @options["Telnetmode"] = true else unless (true == @options["Telnetmode"] or false == @options["Telnetmode"]) raise ArgumentError, "Telnetmode option must be true or false" end end @telnet_option = { "SGA" => false, "BINARY" => false } if @options.has_key?("Output_log") @log = File.open(@options["Output_log"], 'a+') @log.sync = true @log.binmode end if @options.has_key?("Dump_log") @dumplog = File.open(@options["Dump_log"], 'a+') @dumplog.sync = true @dumplog.binmode def @dumplog.log_dump(dir, x) # :nodoc: len = x.length addr = 0 offset = 0 while 0 < len if len < 16 line = x[offset, len] else line = x[offset, 16] end hexvals = line.unpack('H*')[0] hexvals += ' ' * (32 - hexvals.length) hexvals = format("%s %s %s %s " * 4, *hexvals.unpack('a2' * 16)) line = line.gsub(/[\000-\037\177-\377]/n, '.') printf "%s 0x%5.5x: %s%s\n", dir, addr, hexvals, line addr += 16 offset += 16 len -= 16 end print "\n" end end if @options.has_key?("Proxy") if @options["Proxy"].kind_of?(Net::Telnet) @sock = @options["Proxy"].sock elsif @options["Proxy"].kind_of?(IO) @sock = @options["Proxy"] else raise "Error: Proxy must be an instance of Net::Telnet or IO." end else message = "Trying " + @options["Host"] + "...\n" yield(message) if block_given? @log.write(message) if @options.has_key?("Output_log") @dumplog.log_dump('#', message) if @options.has_key?("Dump_log") begin if @options["Timeout"] == false @sock = TCPSocket.open(@options["Host"], @options["Port"]) else Timeout.timeout(@options["Timeout"], Net::OpenTimeout) do @sock = TCPSocket.open(@options["Host"], @options["Port"]) end end rescue Net::OpenTimeout raise Net::OpenTimeout, "timed out while opening a connection to the host" rescue @log.write($ERROR_INFO.to_s + "\n") if @options.has_key?("Output_log") @dumplog.log_dump('#', $ERROR_INFO.to_s + "\n") if @options.has_key?("Dump_log") raise end @sock.sync = true @sock.binmode message = "Connected to " + @options["Host"] + ".\n" yield(message) if block_given? @log.write(message) if @options.has_key?("Output_log") @dumplog.log_dump('#', message) if @options.has_key?("Dump_log") end end # initialize # The socket the Telnet object is using. Note that this object becomes # a delegate of the Telnet object, so normally you invoke its methods # directly on the Telnet object. attr_reader :sock # Set telnet command interpretation on (+mode+ == true) or off # (+mode+ == false), or return the current value (+mode+ not # provided). It should be on for true telnet sessions, off if # using Net::Telnet to connect to a non-telnet service such # as SMTP. def telnetmode(mode = nil) case mode when nil @options["Telnetmode"] when true, false @options["Telnetmode"] = mode else raise ArgumentError, "argument must be true or false, or missing" end end # Turn telnet command interpretation on (true) or off (false). It # should be on for true telnet sessions, off if using Net::Telnet # to connect to a non-telnet service such as SMTP. def telnetmode=(mode) if (true == mode or false == mode) @options["Telnetmode"] = mode else raise ArgumentError, "argument must be true or false" end end # Turn newline conversion on (+mode+ == false) or off (+mode+ == true), # or return the current value (+mode+ is not specified). def binmode(mode = nil) case mode when nil @options["Binmode"] when true, false @options["Binmode"] = mode else raise ArgumentError, "argument must be true or false" end end # Turn newline conversion on (false) or off (true). def binmode=(mode) if (true == mode or false == mode) @options["Binmode"] = mode else raise ArgumentError, "argument must be true or false" end end # Preprocess received data from the host. # # Performs newline conversion and detects telnet command sequences. # Called automatically by #waitfor(). You should only use this # method yourself if you have read input directly using sysread() # or similar, and even then only if in telnet mode. def preprocess(string) # combine CR+NULL into CR string = string.gsub(/#{CR}#{NULL}/no, CR) if @options["Telnetmode"] # combine EOL into "\n" string = string.gsub(/#{EOL}/no, "\n") unless @options["Binmode"] # remove NULL string = string.gsub(/#{NULL}/no, '') unless @options["Binmode"] string.gsub(/#{IAC}( [#{IAC}#{AO}#{AYT}#{DM}#{IP}#{NOP}]| [#{DO}#{DONT}#{WILL}#{WONT}] [#{OPT_BINARY}-#{OPT_NEW_ENVIRON}#{OPT_EXOPL}]| #{SB}[^#{IAC}]*#{IAC}#{SE} )/xno) do if IAC == $1 # handle escaped IAC characters IAC elsif AYT == $1 # respond to "IAC AYT" (are you there) self.write("nobody here but us pigeons" + EOL) '' elsif DO[0] == $1[0] # respond to "IAC DO x" if OPT_BINARY[0] == $1[1] @telnet_option["BINARY"] = true self.write(IAC + WILL + OPT_BINARY) else self.write(IAC + WONT + $1[1..1]) end '' elsif DONT[0] == $1[0] # respond to "IAC DON'T x" with "IAC WON'T x" self.write(IAC + WONT + $1[1..1]) '' elsif WILL[0] == $1[0] # respond to "IAC WILL x" if OPT_BINARY[0] == $1[1] self.write(IAC + DO + OPT_BINARY) elsif OPT_ECHO[0] == $1[1] self.write(IAC + DO + OPT_ECHO) elsif OPT_SGA[0] == $1[1] @telnet_option["SGA"] = true self.write(IAC + DO + OPT_SGA) else self.write(IAC + DONT + $1[1..1]) end '' elsif WONT[0] == $1[0] # respond to "IAC WON'T x" if OPT_ECHO[0] == $1[1] self.write(IAC + DONT + OPT_ECHO) elsif OPT_SGA[0] == $1[1] @telnet_option["SGA"] = false self.write(IAC + DONT + OPT_SGA) else self.write(IAC + DONT + $1[1..1]) end '' else '' end end end # preprocess # Read data from the host until a certain sequence is matched. # # If a block is given, the received data will be yielded as it # is read in (not necessarily all in one go), or nil if EOF # occurs before any data is received. Whether a block is given # or not, all data read will be returned in a single string, or again # nil if EOF occurs before any data is received. Note that # received data includes the matched sequence we were looking for. # # +options+ can be either a regular expression or a hash of options. # If a regular expression, this specifies the data to wait for. # If a hash, this can specify the following options: # # Match:: a regular expression, specifying the data to wait for. # Prompt:: as for Match; used only if Match is not specified. # String:: as for Match, except a string that will be converted # into a regular expression. Used only if Match and # Prompt are not specified. # Timeout:: the number of seconds to wait for data from the host # before raising a Timeout::Error. If set to false, # no timeout will occur. If not specified, the # Timeout option value specified when this instance # was created will be used, or, failing that, the # default value of 10 seconds. # Waittime:: the number of seconds to wait after matching against # the input data to see if more data arrives. If more # data arrives within this time, we will judge ourselves # not to have matched successfully, and will continue # trying to match. If not specified, the Waittime option # value specified when this instance was created will be # used, or, failing that, the default value of 0 seconds, # which means not to wait for more input. # FailEOF:: if true, when the remote end closes the connection then an # EOFError will be raised. Otherwise, defaults to the old # behaviour that the function will return whatever data # has been received already, or nil if nothing was received. # def waitfor(options) # :yield: recvdata time_out = @options["Timeout"] waittime = @options["Waittime"] fail_eof = @options["FailEOF"] if options.kind_of?(Hash) prompt = if options.has_key?("Match") options["Match"] elsif options.has_key?("Prompt") options["Prompt"] elsif options.has_key?("String") Regexp.new( Regexp.quote(options["String"]) ) end time_out = options["Timeout"] if options.has_key?("Timeout") waittime = options["Waittime"] if options.has_key?("Waittime") fail_eof = options["FailEOF"] if options.has_key?("FailEOF") else prompt = options end if time_out == false time_out = nil end line = '' buf = '' rest = '' until(prompt === line and not IO::select([@sock], nil, nil, waittime)) unless IO::select([@sock], nil, nil, time_out) raise Net::ReadTimeout, "timed out while waiting for more data" end begin c = @sock.readpartial(1024 * 1024) @dumplog.log_dump('<', c) if @options.has_key?("Dump_log") if @options["Telnetmode"] c = rest + c if Integer(c.rindex(/#{IAC}#{SE}/no) || 0) < Integer(c.rindex(/#{IAC}#{SB}/no) || 0) buf = preprocess(c[0 ... c.rindex(/#{IAC}#{SB}/no)]) rest = c[c.rindex(/#{IAC}#{SB}/no) .. -1] elsif pt = c.rindex(/#{IAC}[^#{IAC}#{AO}#{AYT}#{DM}#{IP}#{NOP}]?\z/no) || c.rindex(/\r\z/no) buf = preprocess(c[0 ... pt]) rest = c[pt .. -1] else buf = preprocess(c) rest = '' end else # Not Telnetmode. # # We cannot use preprocess() on this data, because that # method makes some Telnetmode-specific assumptions. buf = rest + c rest = '' unless @options["Binmode"] if pt = buf.rindex(/\r\z/no) buf = buf[0 ... pt] rest = buf[pt .. -1] end buf.gsub!(/#{EOL}/no, "\n") end end @log.print(buf) if @options.has_key?("Output_log") line += buf yield buf if block_given? rescue EOFError # End of file reached raise if fail_eof if line == '' line = nil yield nil if block_given? end break end end line end # Write +string+ to the host. # # Does not perform any conversions on +string+. Will log +string+ to the # dumplog, if the Dump_log option is set. def write(string) length = string.length while 0 < length IO::select(nil, [@sock]) @dumplog.log_dump('>', string[-length..-1]) if @options.has_key?("Dump_log") length -= @sock.syswrite(string[-length..-1]) end end # Sends a string to the host. # # This does _not_ automatically append a newline to the string. Embedded # newlines may be converted and telnet command sequences escaped # depending upon the values of telnetmode, binmode, and telnet options # set by the host. def print(string) string = string.gsub(/#{IAC}/no, IAC + IAC) if @options["Telnetmode"] if @options["Binmode"] self.write(string) else if @telnet_option["BINARY"] and @telnet_option["SGA"] # IAC WILL SGA IAC DO BIN send EOL --> CR self.write(string.gsub(/\n/n, CR)) elsif @telnet_option["SGA"] # IAC WILL SGA send EOL --> CR+NULL self.write(string.gsub(/\n/n, CR + NULL)) else # NONE send EOL --> CR+LF self.write(string.gsub(/\n/n, EOL)) end end end # Sends a string to the host. # # Same as #print(), but appends a newline to the string. def puts(string) self.print(string + "\n") end # Send a command to the host. # # More exactly, sends a string to the host, and reads in all received # data until is sees the prompt or other matched sequence. # # If a block is given, the received data will be yielded to it as # it is read in. Whether a block is given or not, the received data # will be return as a string. Note that the received data includes # the prompt and in most cases the host's echo of our command. # # +options+ is either a String, specified the string or command to # send to the host; or it is a hash of options. If a hash, the # following options can be specified: # # String:: the command or other string to send to the host. # Match:: a regular expression, the sequence to look for in # the received data before returning. If not specified, # the Prompt option value specified when this instance # was created will be used, or, failing that, the default # prompt of /[$%#>] \z/n. # Timeout:: the seconds to wait for data from the host before raising # a Timeout error. If not specified, the Timeout option # value specified when this instance was created will be # used, or, failing that, the default value of 10 seconds. # # The command or other string will have the newline sequence appended # to it. def cmd(options) # :yield: recvdata match = @options["Prompt"] time_out = @options["Timeout"] fail_eof = @options["FailEOF"] if options.kind_of?(Hash) string = options["String"] match = options["Match"] if options.has_key?("Match") time_out = options["Timeout"] if options.has_key?("Timeout") fail_eof = options["FailEOF"] if options.has_key?("FailEOF") else string = options end self.puts(string) if block_given? waitfor({"Prompt" => match, "Timeout" => time_out, "FailEOF" => fail_eof}){|c| yield c } else waitfor({"Prompt" => match, "Timeout" => time_out, "FailEOF" => fail_eof}) end end # Login to the host with a given username and password. # # The username and password can either be provided as two string # arguments in that order, or as a hash with keys "Name" and # "Password". # # This method looks for the strings "login" and "Password" from the # host to determine when to send the username and password. If the # login sequence does not follow this pattern (for instance, you # are connecting to a service other than telnet), you will need # to handle login yourself. # # The password can be omitted, either by only # provided one String argument, which will be used as the username, # or by providing a has that has no "Password" key. In this case, # the method will not look for the "Password:" prompt; if it is # sent, it will have to be dealt with by later calls. # # The method returns all data received during the login process from # the host, including the echoed username but not the password (which # the host should not echo). If a block is passed in, this received # data is also yielded to the block as it is received. def login(options, password = nil) # :yield: recvdata login_prompt = /[Ll]ogin[: ]*\z/n password_prompt = /[Pp]ass(?:word|phrase)[: ]*\z/n if options.kind_of?(Hash) username = options["Name"] password = options["Password"] login_prompt = options["LoginPrompt"] if options["LoginPrompt"] password_prompt = options["PasswordPrompt"] if options["PasswordPrompt"] else username = options end if block_given? line = waitfor(login_prompt){|c| yield c } if password line += cmd({"String" => username, "Match" => password_prompt}){|c| yield c } line += cmd(password){|c| yield c } else line += cmd(username){|c| yield c } end else line = waitfor(login_prompt) if password line += cmd({"String" => username, "Match" => password_prompt}) line += cmd(password) else line += cmd(username) end end line end # Closes the connection def close @sock.close end end # class Telnet end # module Net PK!pnɢ ! !2.2.0/net/protocol.rbnu[# # = net/protocol.rb # #-- # Copyright (c) 1999-2004 Yukihiro Matsumoto # Copyright (c) 1999-2004 Minero Aoki # # written and maintained by Minero Aoki # # This program is free software. You can re-distribute and/or # modify this program under the same terms as Ruby itself, # Ruby Distribute License or GNU General Public License. # # $Id: protocol.rb 46060 2014-05-23 12:36:30Z nobu $ #++ # # WARNING: This file is going to remove. # Do not rely on the implementation written in this file. # require 'socket' require 'timeout' module Net # :nodoc: class Protocol #:nodoc: internal use only private def Protocol.protocol_param(name, val) module_eval(<<-End, __FILE__, __LINE__ + 1) def #{name} #{val} end End end end class ProtocolError < StandardError; end class ProtoSyntaxError < ProtocolError; end class ProtoFatalError < ProtocolError; end class ProtoUnknownError < ProtocolError; end class ProtoServerError < ProtocolError; end class ProtoAuthError < ProtocolError; end class ProtoCommandError < ProtocolError; end class ProtoRetriableError < ProtocolError; end ProtocRetryError = ProtoRetriableError ## # OpenTimeout, a subclass of Timeout::Error, is raised if a connection cannot # be created within the open_timeout. class OpenTimeout < Timeout::Error; end ## # ReadTimeout, a subclass of Timeout::Error, is raised if a chunk of the # response cannot be read within the read_timeout. class ReadTimeout < Timeout::Error; end class BufferedIO #:nodoc: internal use only def initialize(io) @io = io @read_timeout = 60 @continue_timeout = nil @debug_output = nil @rbuf = '' end attr_reader :io attr_accessor :read_timeout attr_accessor :continue_timeout attr_accessor :debug_output def inspect "#<#{self.class} io=#{@io}>" end def eof? @io.eof? end def closed? @io.closed? end def close @io.close end # # Read # public def read(len, dest = '', ignore_eof = false) LOG "reading #{len} bytes..." read_bytes = 0 begin while read_bytes + @rbuf.size < len dest << (s = rbuf_consume(@rbuf.size)) read_bytes += s.size rbuf_fill end dest << (s = rbuf_consume(len - read_bytes)) read_bytes += s.size rescue EOFError raise unless ignore_eof end LOG "read #{read_bytes} bytes" dest end def read_all(dest = '') LOG 'reading all...' read_bytes = 0 begin while true dest << (s = rbuf_consume(@rbuf.size)) read_bytes += s.size rbuf_fill end rescue EOFError ; end LOG "read #{read_bytes} bytes" dest end def readuntil(terminator, ignore_eof = false) begin until idx = @rbuf.index(terminator) rbuf_fill end return rbuf_consume(idx + terminator.size) rescue EOFError raise unless ignore_eof return rbuf_consume(@rbuf.size) end end def readline readuntil("\n").chop end private BUFSIZE = 1024 * 16 def rbuf_fill begin @rbuf << @io.read_nonblock(BUFSIZE) rescue IO::WaitReadable if IO.select([@io], nil, nil, @read_timeout) retry else raise Net::ReadTimeout end rescue IO::WaitWritable # OpenSSL::Buffering#read_nonblock may fail with IO::WaitWritable. # http://www.openssl.org/support/faq.html#PROG10 if IO.select(nil, [@io], nil, @read_timeout) retry else raise Net::ReadTimeout end end end def rbuf_consume(len) s = @rbuf.slice!(0, len) @debug_output << %Q[-> #{s.dump}\n] if @debug_output s end # # Write # public def write(str) writing { write0 str } end alias << write def writeline(str) writing { write0 str + "\r\n" } end private def writing @written_bytes = 0 @debug_output << '<- ' if @debug_output yield @debug_output << "\n" if @debug_output bytes = @written_bytes @written_bytes = nil bytes end def write0(str) @debug_output << str.dump if @debug_output len = @io.write(str) @written_bytes += len len end # # Logging # private def LOG_off @save_debug_out = @debug_output @debug_output = nil end def LOG_on @debug_output = @save_debug_out end def LOG(msg) return unless @debug_output @debug_output << msg + "\n" end end class InternetMessageIO < BufferedIO #:nodoc: internal use only def initialize(io) super @wbuf = nil end # # Read # def each_message_chunk LOG 'reading message...' LOG_off() read_bytes = 0 while (line = readuntil("\r\n")) != ".\r\n" read_bytes += line.size yield line.sub(/\A\./, '') end LOG_on() LOG "read message (#{read_bytes} bytes)" end # *library private* (cannot handle 'break') def each_list_item while (str = readuntil("\r\n")) != ".\r\n" yield str.chop end end def write_message_0(src) prev = @written_bytes each_crlf_line(src) do |line| write0 dot_stuff(line) end @written_bytes - prev end # # Write # def write_message(src) LOG "writing message from #{src.class}" LOG_off() len = writing { using_each_crlf_line { write_message_0 src } } LOG_on() LOG "wrote #{len} bytes" len end def write_message_by_block(&block) LOG 'writing message from block' LOG_off() len = writing { using_each_crlf_line { begin block.call(WriteAdapter.new(self, :write_message_0)) rescue LocalJumpError # allow `break' from writer block end } } LOG_on() LOG "wrote #{len} bytes" len end private def dot_stuff(s) s.sub(/\A\./, '..') end def using_each_crlf_line @wbuf = '' yield if not @wbuf.empty? # unterminated last line write0 dot_stuff(@wbuf.chomp) + "\r\n" elsif @written_bytes == 0 # empty src write0 "\r\n" end write0 ".\r\n" @wbuf = nil end def each_crlf_line(src) buffer_filling(@wbuf, src) do while line = @wbuf.slice!(/\A[^\r\n]*(?:\n|\r(?:\n|(?!\z)))/) yield line.chomp("\n") + "\r\n" end end end def buffer_filling(buf, src) case src when String # for speeding up. 0.step(src.size - 1, 1024) do |i| buf << src[i, 1024] yield end when File # for speeding up. while s = src.read(1024) buf << s yield end else # generic reader src.each do |str| buf << str yield if buf.size > 1024 end yield unless buf.empty? end end end # # The writer adapter class # class WriteAdapter def initialize(socket, method) @socket = socket @method_id = method end def inspect "#<#{self.class} socket=#{@socket.inspect}>" end def write(str) @socket.__send__(@method_id, str) end alias print write def <<(str) write str self end def puts(str = '') write str.chomp("\n") + "\n" end def printf(*args) write sprintf(*args) end end class ReadAdapter #:nodoc: internal use only def initialize(block) @block = block end def inspect "#<#{self.class}>" end def <<(str) call_block(str, &@block) if @block end private # This method is needed because @block must be called by yield, # not Proc#call. You can see difference when using `break' in # the block. def call_block(str) yield str end end module NetPrivate #:nodoc: obsolete Socket = ::Net::InternetMessageIO end end # module Net PK!LS+2.2.0/net/https.rbnu[=begin = net/https -- SSL/TLS enhancement for Net::HTTP. This file has been merged with net/http. There is no longer any need to require 'net/https' to use HTTPS. See Net::HTTP for details on how to make HTTPS connections. == Info 'OpenSSL for Ruby 2' project Copyright (C) 2001 GOTOU Yuuzou All rights reserved. == Licence This program is licenced under the same licence as Ruby. (See the file 'LICENCE'.) =end require 'net/http' require 'openssl' PK!5P0j0j2.2.0/net/pop.rbnu[# = net/pop.rb # # Copyright (c) 1999-2007 Yukihiro Matsumoto. # # Copyright (c) 1999-2007 Minero Aoki. # # Written & maintained by Minero Aoki . # # Documented by William Webber and Minero Aoki. # # This program is free software. You can re-distribute and/or # modify this program under the same terms as Ruby itself, # Ruby Distribute License. # # NOTE: You can find Japanese version of this document at: # http://www.ruby-lang.org/ja/man/html/net_pop.html # # $Id: pop.rb 44164 2013-12-13 02:38:55Z a_matsuda $ # # See Net::POP3 for documentation. # require 'net/protocol' require 'digest/md5' require 'timeout' begin require "openssl" rescue LoadError end module Net # Non-authentication POP3 protocol error # (reply code "-ERR", except authentication). class POPError < ProtocolError; end # POP3 authentication error. class POPAuthenticationError < ProtoAuthError; end # Unexpected response from the server. class POPBadResponse < POPError; end # # == What is This Library? # # This library provides functionality for retrieving # email via POP3, the Post Office Protocol version 3. For details # of POP3, see [RFC1939] (http://www.ietf.org/rfc/rfc1939.txt). # # == Examples # # === Retrieving Messages # # This example retrieves messages from the server and deletes them # on the server. # # Messages are written to files named 'inbox/1', 'inbox/2', .... # Replace 'pop.example.com' with your POP3 server address, and # 'YourAccount' and 'YourPassword' with the appropriate account # details. # # require 'net/pop' # # pop = Net::POP3.new('pop.example.com') # pop.start('YourAccount', 'YourPassword') # (1) # if pop.mails.empty? # puts 'No mail.' # else # i = 0 # pop.each_mail do |m| # or "pop.mails.each ..." # (2) # File.open("inbox/#{i}", 'w') do |f| # f.write m.pop # end # m.delete # i += 1 # end # puts "#{pop.mails.size} mails popped." # end # pop.finish # (3) # # 1. Call Net::POP3#start and start POP session. # 2. Access messages by using POP3#each_mail and/or POP3#mails. # 3. Close POP session by calling POP3#finish or use the block form of #start. # # === Shortened Code # # The example above is very verbose. You can shorten the code by using # some utility methods. First, the block form of Net::POP3.start can # be used instead of POP3.new, POP3#start and POP3#finish. # # require 'net/pop' # # Net::POP3.start('pop.example.com', 110, # 'YourAccount', 'YourPassword') do |pop| # if pop.mails.empty? # puts 'No mail.' # else # i = 0 # pop.each_mail do |m| # or "pop.mails.each ..." # File.open("inbox/#{i}", 'w') do |f| # f.write m.pop # end # m.delete # i += 1 # end # puts "#{pop.mails.size} mails popped." # end # end # # POP3#delete_all is an alternative for #each_mail and #delete. # # require 'net/pop' # # Net::POP3.start('pop.example.com', 110, # 'YourAccount', 'YourPassword') do |pop| # if pop.mails.empty? # puts 'No mail.' # else # i = 1 # pop.delete_all do |m| # File.open("inbox/#{i}", 'w') do |f| # f.write m.pop # end # i += 1 # end # end # end # # And here is an even shorter example. # # require 'net/pop' # # i = 0 # Net::POP3.delete_all('pop.example.com', 110, # 'YourAccount', 'YourPassword') do |m| # File.open("inbox/#{i}", 'w') do |f| # f.write m.pop # end # i += 1 # end # # === Memory Space Issues # # All the examples above get each message as one big string. # This example avoids this. # # require 'net/pop' # # i = 1 # Net::POP3.delete_all('pop.example.com', 110, # 'YourAccount', 'YourPassword') do |m| # File.open("inbox/#{i}", 'w') do |f| # m.pop do |chunk| # get a message little by little. # f.write chunk # end # i += 1 # end # end # # === Using APOP # # The net/pop library supports APOP authentication. # To use APOP, use the Net::APOP class instead of the Net::POP3 class. # You can use the utility method, Net::POP3.APOP(). For example: # # require 'net/pop' # # # Use APOP authentication if $isapop == true # pop = Net::POP3.APOP($is_apop).new('apop.example.com', 110) # pop.start(YourAccount', 'YourPassword') do |pop| # # Rest of the code is the same. # end # # === Fetch Only Selected Mail Using 'UIDL' POP Command # # If your POP server provides UIDL functionality, # you can grab only selected mails from the POP server. # e.g. # # def need_pop?( id ) # # determine if we need pop this mail... # end # # Net::POP3.start('pop.example.com', 110, # 'Your account', 'Your password') do |pop| # pop.mails.select { |m| need_pop?(m.unique_id) }.each do |m| # do_something(m.pop) # end # end # # The POPMail#unique_id() method returns the unique-id of the message as a # String. Normally the unique-id is a hash of the message. # class POP3 < Protocol # svn revision of this library Revision = %q$Revision: 44164 $.split[1] # # Class Parameters # # returns the port for POP3 def POP3.default_port default_pop3_port() end # The default port for POP3 connections, port 110 def POP3.default_pop3_port 110 end # The default port for POP3S connections, port 995 def POP3.default_pop3s_port 995 end def POP3.socket_type #:nodoc: obsolete Net::InternetMessageIO end # # Utilities # # Returns the APOP class if +isapop+ is true; otherwise, returns # the POP class. For example: # # # Example 1 # pop = Net::POP3::APOP($is_apop).new(addr, port) # # # Example 2 # Net::POP3::APOP($is_apop).start(addr, port) do |pop| # .... # end # def POP3.APOP(isapop) isapop ? APOP : POP3 end # Starts a POP3 session and iterates over each POPMail object, # yielding it to the +block+. # This method is equivalent to: # # Net::POP3.start(address, port, account, password) do |pop| # pop.each_mail do |m| # yield m # end # end # # This method raises a POPAuthenticationError if authentication fails. # # === Example # # Net::POP3.foreach('pop.example.com', 110, # 'YourAccount', 'YourPassword') do |m| # file.write m.pop # m.delete if $DELETE # end # def POP3.foreach(address, port = nil, account = nil, password = nil, isapop = false, &block) # :yields: message start(address, port, account, password, isapop) {|pop| pop.each_mail(&block) } end # Starts a POP3 session and deletes all messages on the server. # If a block is given, each POPMail object is yielded to it before # being deleted. # # This method raises a POPAuthenticationError if authentication fails. # # === Example # # Net::POP3.delete_all('pop.example.com', 110, # 'YourAccount', 'YourPassword') do |m| # file.write m.pop # end # def POP3.delete_all(address, port = nil, account = nil, password = nil, isapop = false, &block) start(address, port, account, password, isapop) {|pop| pop.delete_all(&block) } end # Opens a POP3 session, attempts authentication, and quits. # # This method raises POPAuthenticationError if authentication fails. # # === Example: normal POP3 # # Net::POP3.auth_only('pop.example.com', 110, # 'YourAccount', 'YourPassword') # # === Example: APOP # # Net::POP3.auth_only('pop.example.com', 110, # 'YourAccount', 'YourPassword', true) # def POP3.auth_only(address, port = nil, account = nil, password = nil, isapop = false) new(address, port, isapop).auth_only account, password end # Starts a pop3 session, attempts authentication, and quits. # This method must not be called while POP3 session is opened. # This method raises POPAuthenticationError if authentication fails. def auth_only(account, password) raise IOError, 'opening previously opened POP session' if started? start(account, password) { ; } end # # SSL # @ssl_params = nil # :call-seq: # Net::POP.enable_ssl(params = {}) # # Enable SSL for all new instances. # +params+ is passed to OpenSSL::SSLContext#set_params. def POP3.enable_ssl(*args) @ssl_params = create_ssl_params(*args) end # Constructs proper parameters from arguments def POP3.create_ssl_params(verify_or_params = {}, certs = nil) begin params = verify_or_params.to_hash rescue NoMethodError params = {} params[:verify_mode] = verify_or_params if certs if File.file?(certs) params[:ca_file] = certs elsif File.directory?(certs) params[:ca_path] = certs end end end return params end # Disable SSL for all new instances. def POP3.disable_ssl @ssl_params = nil end # returns the SSL Parameters # # see also POP3.enable_ssl def POP3.ssl_params return @ssl_params end # returns +true+ if POP3.ssl_params is set def POP3.use_ssl? return !@ssl_params.nil? end # returns whether verify_mode is enable from POP3.ssl_params def POP3.verify return @ssl_params[:verify_mode] end # returns the :ca_file or :ca_path from POP3.ssl_params def POP3.certs return @ssl_params[:ca_file] || @ssl_params[:ca_path] end # # Session management # # Creates a new POP3 object and open the connection. Equivalent to # # Net::POP3.new(address, port, isapop).start(account, password) # # If +block+ is provided, yields the newly-opened POP3 object to it, # and automatically closes it at the end of the session. # # === Example # # Net::POP3.start(addr, port, account, password) do |pop| # pop.each_mail do |m| # file.write m.pop # m.delete # end # end # def POP3.start(address, port = nil, account = nil, password = nil, isapop = false, &block) # :yield: pop new(address, port, isapop).start(account, password, &block) end # Creates a new POP3 object. # # +address+ is the hostname or ip address of your POP3 server. # # The optional +port+ is the port to connect to. # # The optional +isapop+ specifies whether this connection is going # to use APOP authentication; it defaults to +false+. # # This method does *not* open the TCP connection. def initialize(addr, port = nil, isapop = false) @address = addr @ssl_params = POP3.ssl_params @port = port @apop = isapop @command = nil @socket = nil @started = false @open_timeout = 30 @read_timeout = 60 @debug_output = nil @mails = nil @n_mails = nil @n_bytes = nil end # Does this instance use APOP authentication? def apop? @apop end # does this instance use SSL? def use_ssl? return !@ssl_params.nil? end # :call-seq: # Net::POP#enable_ssl(params = {}) # # Enables SSL for this instance. Must be called before the connection is # established to have any effect. # +params[:port]+ is port to establish the SSL connection on; Defaults to 995. # +params+ (except :port) is passed to OpenSSL::SSLContext#set_params. def enable_ssl(verify_or_params = {}, certs = nil, port = nil) begin @ssl_params = verify_or_params.to_hash.dup @port = @ssl_params.delete(:port) || @port rescue NoMethodError @ssl_params = POP3.create_ssl_params(verify_or_params, certs) @port = port || @port end end # Disable SSL for all new instances. def disable_ssl @ssl_params = nil end # Provide human-readable stringification of class state. def inspect "#<#{self.class} #{@address}:#{@port} open=#{@started}>" end # *WARNING*: This method causes a serious security hole. # Use this method only for debugging. # # Set an output stream for debugging. # # === Example # # pop = Net::POP.new(addr, port) # pop.set_debug_output $stderr # pop.start(account, passwd) do |pop| # .... # end # def set_debug_output(arg) @debug_output = arg end # The address to connect to. attr_reader :address # The port number to connect to. def port return @port || (use_ssl? ? POP3.default_pop3s_port : POP3.default_pop3_port) end # Seconds to wait until a connection is opened. # If the POP3 object cannot open a connection within this time, # it raises a Net::OpenTimeout exception. The default value is 30 seconds. attr_accessor :open_timeout # Seconds to wait until reading one block (by one read(1) call). # If the POP3 object cannot complete a read() within this time, # it raises a Net::ReadTimeout exception. The default value is 60 seconds. attr_reader :read_timeout # Set the read timeout. def read_timeout=(sec) @command.socket.read_timeout = sec if @command @read_timeout = sec end # +true+ if the POP3 session has started. def started? @started end alias active? started? #:nodoc: obsolete # Starts a POP3 session. # # When called with block, gives a POP3 object to the block and # closes the session after block call finishes. # # This method raises a POPAuthenticationError if authentication fails. def start(account, password) # :yield: pop raise IOError, 'POP session already started' if @started if block_given? begin do_start account, password return yield(self) ensure do_finish end else do_start account, password return self end end # internal method for Net::POP3.start def do_start(account, password) # :nodoc: s = Timeout.timeout(@open_timeout, Net::OpenTimeout) do TCPSocket.open(@address, port) end if use_ssl? raise 'openssl library not installed' unless defined?(OpenSSL) context = OpenSSL::SSL::SSLContext.new context.set_params(@ssl_params) s = OpenSSL::SSL::SSLSocket.new(s, context) s.sync_close = true s.connect if context.verify_mode != OpenSSL::SSL::VERIFY_NONE s.post_connection_check(@address) end end @socket = InternetMessageIO.new(s) logging "POP session started: #{@address}:#{@port} (#{@apop ? 'APOP' : 'POP'})" @socket.read_timeout = @read_timeout @socket.debug_output = @debug_output on_connect @command = POP3Command.new(@socket) if apop? @command.apop account, password else @command.auth account, password end @started = true ensure # Authentication failed, clean up connection. unless @started s.close if s and not s.closed? @socket = nil @command = nil end end private :do_start # Does nothing def on_connect # :nodoc: end private :on_connect # Finishes a POP3 session and closes TCP connection. def finish raise IOError, 'POP session not yet started' unless started? do_finish end # nil's out the: # - mails # - number counter for mails # - number counter for bytes # - quits the current command, if any def do_finish # :nodoc: @mails = nil @n_mails = nil @n_bytes = nil @command.quit if @command ensure @started = false @command = nil @socket.close if @socket and not @socket.closed? @socket = nil end private :do_finish # Returns the current command. # # Raises IOError if there is no active socket def command # :nodoc: raise IOError, 'POP session not opened yet' \ if not @socket or @socket.closed? @command end private :command # # POP protocol wrapper # # Returns the number of messages on the POP server. def n_mails return @n_mails if @n_mails @n_mails, @n_bytes = command().stat @n_mails end # Returns the total size in bytes of all the messages on the POP server. def n_bytes return @n_bytes if @n_bytes @n_mails, @n_bytes = command().stat @n_bytes end # Returns an array of Net::POPMail objects, representing all the # messages on the server. This array is renewed when the session # restarts; otherwise, it is fetched from the server the first time # this method is called (directly or indirectly) and cached. # # This method raises a POPError if an error occurs. def mails return @mails.dup if @mails if n_mails() == 0 # some popd raises error for LIST on the empty mailbox. @mails = [] return [] end @mails = command().list.map {|num, size| POPMail.new(num, size, self, command()) } @mails.dup end # Yields each message to the passed-in block in turn. # Equivalent to: # # pop3.mails.each do |popmail| # .... # end # # This method raises a POPError if an error occurs. def each_mail(&block) # :yield: message mails().each(&block) end alias each each_mail # Deletes all messages on the server. # # If called with a block, yields each message in turn before deleting it. # # === Example # # n = 1 # pop.delete_all do |m| # File.open("inbox/#{n}") do |f| # f.write m.pop # end # n += 1 # end # # This method raises a POPError if an error occurs. # def delete_all # :yield: message mails().each do |m| yield m if block_given? m.delete unless m.deleted? end end # Resets the session. This clears all "deleted" marks from messages. # # This method raises a POPError if an error occurs. def reset command().rset mails().each do |m| m.instance_eval { @deleted = false } end end def set_all_uids #:nodoc: internal use only (called from POPMail#uidl) uidl = command().uidl @mails.each {|m| m.uid = uidl[m.number] } end # debugging output for +msg+ def logging(msg) @debug_output << msg + "\n" if @debug_output end end # class POP3 # class aliases POP = POP3 # :nodoc: POPSession = POP3 # :nodoc: POP3Session = POP3 # :nodoc: # # This class is equivalent to POP3, except that it uses APOP authentication. # class APOP < POP3 # Always returns true. def apop? true end end # class aliases APOPSession = APOP # # This class represents a message which exists on the POP server. # Instances of this class are created by the POP3 class; they should # not be directly created by the user. # class POPMail def initialize(num, len, pop, cmd) #:nodoc: @number = num @length = len @pop = pop @command = cmd @deleted = false @uid = nil end # The sequence number of the message on the server. attr_reader :number # The length of the message in octets. attr_reader :length alias size length # Provide human-readable stringification of class state. def inspect "#<#{self.class} #{@number}#{@deleted ? ' deleted' : ''}>" end # # This method fetches the message. If called with a block, the # message is yielded to the block one chunk at a time. If called # without a block, the message is returned as a String. The optional # +dest+ argument will be prepended to the returned String; this # argument is essentially obsolete. # # === Example without block # # POP3.start('pop.example.com', 110, # 'YourAccount, 'YourPassword') do |pop| # n = 1 # pop.mails.each do |popmail| # File.open("inbox/#{n}", 'w') do |f| # f.write popmail.pop # end # popmail.delete # n += 1 # end # end # # === Example with block # # POP3.start('pop.example.com', 110, # 'YourAccount, 'YourPassword') do |pop| # n = 1 # pop.mails.each do |popmail| # File.open("inbox/#{n}", 'w') do |f| # popmail.pop do |chunk| #### # f.write chunk # end # end # n += 1 # end # end # # This method raises a POPError if an error occurs. # def pop( dest = '', &block ) # :yield: message_chunk if block_given? @command.retr(@number, &block) nil else @command.retr(@number) do |chunk| dest << chunk end dest end end alias all pop #:nodoc: obsolete alias mail pop #:nodoc: obsolete # Fetches the message header and +lines+ lines of body. # # The optional +dest+ argument is obsolete. # # This method raises a POPError if an error occurs. def top(lines, dest = '') @command.top(@number, lines) do |chunk| dest << chunk end dest end # Fetches the message header. # # The optional +dest+ argument is obsolete. # # This method raises a POPError if an error occurs. def header(dest = '') top(0, dest) end # Marks a message for deletion on the server. Deletion does not # actually occur until the end of the session; deletion may be # cancelled for _all_ marked messages by calling POP3#reset(). # # This method raises a POPError if an error occurs. # # === Example # # POP3.start('pop.example.com', 110, # 'YourAccount, 'YourPassword') do |pop| # n = 1 # pop.mails.each do |popmail| # File.open("inbox/#{n}", 'w') do |f| # f.write popmail.pop # end # popmail.delete #### # n += 1 # end # end # def delete @command.dele @number @deleted = true end alias delete! delete #:nodoc: obsolete # True if the mail has been deleted. def deleted? @deleted end # Returns the unique-id of the message. # Normally the unique-id is a hash string of the message. # # This method raises a POPError if an error occurs. def unique_id return @uid if @uid @pop.set_all_uids @uid end alias uidl unique_id def uid=(uid) #:nodoc: internal use only @uid = uid end end # class POPMail class POP3Command #:nodoc: internal use only def initialize(sock) @socket = sock @error_occurred = false res = check_response(critical { recv_response() }) @apop_stamp = res.slice(/<[!-~]+@[!-~]+>/) end attr_reader :socket def inspect "#<#{self.class} socket=#{@socket}>" end def auth(account, password) check_response_auth(critical { check_response_auth(get_response('USER %s', account)) get_response('PASS %s', password) }) end def apop(account, password) raise POPAuthenticationError, 'not APOP server; cannot login' \ unless @apop_stamp check_response_auth(critical { get_response('APOP %s %s', account, Digest::MD5.hexdigest(@apop_stamp + password)) }) end def list critical { getok 'LIST' list = [] @socket.each_list_item do |line| m = /\A(\d+)[ \t]+(\d+)/.match(line) or raise POPBadResponse, "bad response: #{line}" list.push [m[1].to_i, m[2].to_i] end return list } end def stat res = check_response(critical { get_response('STAT') }) m = /\A\+OK\s+(\d+)\s+(\d+)/.match(res) or raise POPBadResponse, "wrong response format: #{res}" [m[1].to_i, m[2].to_i] end def rset check_response(critical { get_response('RSET') }) end def top(num, lines = 0, &block) critical { getok('TOP %d %d', num, lines) @socket.each_message_chunk(&block) } end def retr(num, &block) critical { getok('RETR %d', num) @socket.each_message_chunk(&block) } end def dele(num) check_response(critical { get_response('DELE %d', num) }) end def uidl(num = nil) if num res = check_response(critical { get_response('UIDL %d', num) }) return res.split(/ /)[1] else critical { getok('UIDL') table = {} @socket.each_list_item do |line| num, uid = line.split table[num.to_i] = uid end return table } end end def quit check_response(critical { get_response('QUIT') }) end private def getok(fmt, *fargs) @socket.writeline sprintf(fmt, *fargs) check_response(recv_response()) end def get_response(fmt, *fargs) @socket.writeline sprintf(fmt, *fargs) recv_response() end def recv_response @socket.readline end def check_response(res) raise POPError, res unless /\A\+OK/i =~ res res end def check_response_auth(res) raise POPAuthenticationError, res unless /\A\+OK/i =~ res res end def critical return '+OK dummy ok response' if @error_occurred begin return yield() rescue Exception @error_occurred = true raise end end end # class POP3Command end # module Net PK!++2.2.0/net/http.rbnu[# # = net/http.rb # # Copyright (c) 1999-2007 Yukihiro Matsumoto # Copyright (c) 1999-2007 Minero Aoki # Copyright (c) 2001 GOTOU Yuuzou # # Written and maintained by Minero Aoki . # HTTPS support added by GOTOU Yuuzou . # # This file is derived from "http-access.rb". # # Documented by Minero Aoki; converted to RDoc by William Webber. # # This program is free software. You can re-distribute and/or # modify this program under the same terms of ruby itself --- # Ruby Distribution License or GNU General Public License. # # See Net::HTTP for an overview and examples. # require 'net/protocol' require 'uri' module Net #:nodoc: autoload :OpenSSL, 'openssl' # :stopdoc: class HTTPBadResponse < StandardError; end class HTTPHeaderSyntaxError < StandardError; end # :startdoc: # == An HTTP client API for Ruby. # # Net::HTTP provides a rich library which can be used to build HTTP # user-agents. For more details about HTTP see # [RFC2616](http://www.ietf.org/rfc/rfc2616.txt) # # Net::HTTP is designed to work closely with URI. URI::HTTP#host, # URI::HTTP#port and URI::HTTP#request_uri are designed to work with # Net::HTTP. # # If you are only performing a few GET requests you should try OpenURI. # # == Simple Examples # # All examples assume you have loaded Net::HTTP with: # # require 'net/http' # # This will also require 'uri' so you don't need to require it separately. # # The Net::HTTP methods in the following section do not persist # connections. They are not recommended if you are performing many HTTP # requests. # # === GET # # Net::HTTP.get('example.com', '/index.html') # => String # # === GET by URI # # uri = URI('http://example.com/index.html?count=10') # Net::HTTP.get(uri) # => String # # === GET with Dynamic Parameters # # uri = URI('http://example.com/index.html') # params = { :limit => 10, :page => 3 } # uri.query = URI.encode_www_form(params) # # res = Net::HTTP.get_response(uri) # puts res.body if res.is_a?(Net::HTTPSuccess) # # === POST # # uri = URI('http://www.example.com/search.cgi') # res = Net::HTTP.post_form(uri, 'q' => 'ruby', 'max' => '50') # puts res.body # # === POST with Multiple Values # # uri = URI('http://www.example.com/search.cgi') # res = Net::HTTP.post_form(uri, 'q' => ['ruby', 'perl'], 'max' => '50') # puts res.body # # == How to use Net::HTTP # # The following example code can be used as the basis of a HTTP user-agent # which can perform a variety of request types using persistent # connections. # # uri = URI('http://example.com/some_path?query=string') # # Net::HTTP.start(uri.host, uri.port) do |http| # request = Net::HTTP::Get.new uri # # response = http.request request # Net::HTTPResponse object # end # # Net::HTTP::start immediately creates a connection to an HTTP server which # is kept open for the duration of the block. The connection will remain # open for multiple requests in the block if the server indicates it # supports persistent connections. # # The request types Net::HTTP supports are listed below in the section "HTTP # Request Classes". # # If you wish to re-use a connection across multiple HTTP requests without # automatically closing it you can use ::new instead of ::start. #request # will automatically open a connection to the server if one is not currently # open. You can manually close the connection with #finish. # # For all the Net::HTTP request objects and shortcut request methods you may # supply either a String for the request path or a URI from which Net::HTTP # will extract the request path. # # === Response Data # # uri = URI('http://example.com/index.html') # res = Net::HTTP.get_response(uri) # # # Headers # res['Set-Cookie'] # => String # res.get_fields('set-cookie') # => Array # res.to_hash['set-cookie'] # => Array # puts "Headers: #{res.to_hash.inspect}" # # # Status # puts res.code # => '200' # puts res.message # => 'OK' # puts res.class.name # => 'HTTPOK' # # # Body # puts res.body if res.response_body_permitted? # # === Following Redirection # # Each Net::HTTPResponse object belongs to a class for its response code. # # For example, all 2XX responses are instances of a Net::HTTPSuccess # subclass, a 3XX response is an instance of a Net::HTTPRedirection # subclass and a 200 response is an instance of the Net::HTTPOK class. For # details of response classes, see the section "HTTP Response Classes" # below. # # Using a case statement you can handle various types of responses properly: # # def fetch(uri_str, limit = 10) # # You should choose a better exception. # raise ArgumentError, 'too many HTTP redirects' if limit == 0 # # response = Net::HTTP.get_response(URI(uri_str)) # # case response # when Net::HTTPSuccess then # response # when Net::HTTPRedirection then # location = response['location'] # warn "redirected to #{location}" # fetch(location, limit - 1) # else # response.value # end # end # # print fetch('http://www.ruby-lang.org') # # === POST # # A POST can be made using the Net::HTTP::Post request class. This example # creates a urlencoded POST body: # # uri = URI('http://www.example.com/todo.cgi') # req = Net::HTTP::Post.new(uri) # req.set_form_data('from' => '2005-01-01', 'to' => '2005-03-31') # # res = Net::HTTP.start(uri.hostname, uri.port) do |http| # http.request(req) # end # # case res # when Net::HTTPSuccess, Net::HTTPRedirection # # OK # else # res.value # end # # At this time Net::HTTP does not support multipart/form-data. To send # multipart/form-data use Net::HTTPRequest#body= and # Net::HTTPRequest#content_type=: # # req = Net::HTTP::Post.new(uri) # req.body = multipart_data # req.content_type = 'multipart/form-data' # # Other requests that can contain a body such as PUT can be created in the # same way using the corresponding request class (Net::HTTP::Put). # # === Setting Headers # # The following example performs a conditional GET using the # If-Modified-Since header. If the files has not been modified since the # time in the header a Not Modified response will be returned. See RFC 2616 # section 9.3 for further details. # # uri = URI('http://example.com/cached_response') # file = File.stat 'cached_response' # # req = Net::HTTP::Get.new(uri) # req['If-Modified-Since'] = file.mtime.rfc2822 # # res = Net::HTTP.start(uri.hostname, uri.port) {|http| # http.request(req) # } # # open 'cached_response', 'w' do |io| # io.write res.body # end if res.is_a?(Net::HTTPSuccess) # # === Basic Authentication # # Basic authentication is performed according to # [RFC2617](http://www.ietf.org/rfc/rfc2617.txt) # # uri = URI('http://example.com/index.html?key=value') # # req = Net::HTTP::Get.new(uri) # req.basic_auth 'user', 'pass' # # res = Net::HTTP.start(uri.hostname, uri.port) {|http| # http.request(req) # } # puts res.body # # === Streaming Response Bodies # # By default Net::HTTP reads an entire response into memory. If you are # handling large files or wish to implement a progress bar you can instead # stream the body directly to an IO. # # uri = URI('http://example.com/large_file') # # Net::HTTP.start(uri.host, uri.port) do |http| # request = Net::HTTP::Get.new uri # # http.request request do |response| # open 'large_file', 'w' do |io| # response.read_body do |chunk| # io.write chunk # end # end # end # end # # === HTTPS # # HTTPS is enabled for an HTTP connection by Net::HTTP#use_ssl=. # # uri = URI('https://secure.example.com/some_path?query=string') # # Net::HTTP.start(uri.host, uri.port, # :use_ssl => uri.scheme == 'https') do |http| # request = Net::HTTP::Get.new uri # # response = http.request request # Net::HTTPResponse object # end # # In previous versions of Ruby you would need to require 'net/https' to use # HTTPS. This is no longer true. # # === Proxies # # Net::HTTP will automatically create a proxy from the +http_proxy+ # environment variable if it is present. To disable use of +http_proxy+, # pass +nil+ for the proxy address. # # You may also create a custom proxy: # # proxy_addr = 'your.proxy.host' # proxy_port = 8080 # # Net::HTTP.new('example.com', nil, proxy_addr, proxy_port).start { |http| # # always proxy via your.proxy.addr:8080 # } # # See Net::HTTP.new for further details and examples such as proxies that # require a username and password. # # === Compression # # Net::HTTP automatically adds Accept-Encoding for compression of response # bodies and automatically decompresses gzip and deflate responses unless a # Range header was sent. # # Compression can be disabled through the Accept-Encoding: identity header. # # == HTTP Request Classes # # Here is the HTTP request class hierarchy. # # * Net::HTTPRequest # * Net::HTTP::Get # * Net::HTTP::Head # * Net::HTTP::Post # * Net::HTTP::Patch # * Net::HTTP::Put # * Net::HTTP::Proppatch # * Net::HTTP::Lock # * Net::HTTP::Unlock # * Net::HTTP::Options # * Net::HTTP::Propfind # * Net::HTTP::Delete # * Net::HTTP::Move # * Net::HTTP::Copy # * Net::HTTP::Mkcol # * Net::HTTP::Trace # # == HTTP Response Classes # # Here is HTTP response class hierarchy. All classes are defined in Net # module and are subclasses of Net::HTTPResponse. # # HTTPUnknownResponse:: For unhandled HTTP extensions # HTTPInformation:: 1xx # HTTPContinue:: 100 # HTTPSwitchProtocol:: 101 # HTTPSuccess:: 2xx # HTTPOK:: 200 # HTTPCreated:: 201 # HTTPAccepted:: 202 # HTTPNonAuthoritativeInformation:: 203 # HTTPNoContent:: 204 # HTTPResetContent:: 205 # HTTPPartialContent:: 206 # HTTPMultiStatus:: 207 # HTTPIMUsed:: 226 # HTTPRedirection:: 3xx # HTTPMultipleChoices:: 300 # HTTPMovedPermanently:: 301 # HTTPFound:: 302 # HTTPSeeOther:: 303 # HTTPNotModified:: 304 # HTTPUseProxy:: 305 # HTTPTemporaryRedirect:: 307 # HTTPClientError:: 4xx # HTTPBadRequest:: 400 # HTTPUnauthorized:: 401 # HTTPPaymentRequired:: 402 # HTTPForbidden:: 403 # HTTPNotFound:: 404 # HTTPMethodNotAllowed:: 405 # HTTPNotAcceptable:: 406 # HTTPProxyAuthenticationRequired:: 407 # HTTPRequestTimeOut:: 408 # HTTPConflict:: 409 # HTTPGone:: 410 # HTTPLengthRequired:: 411 # HTTPPreconditionFailed:: 412 # HTTPRequestEntityTooLarge:: 413 # HTTPRequestURITooLong:: 414 # HTTPUnsupportedMediaType:: 415 # HTTPRequestedRangeNotSatisfiable:: 416 # HTTPExpectationFailed:: 417 # HTTPUnprocessableEntity:: 422 # HTTPLocked:: 423 # HTTPFailedDependency:: 424 # HTTPUpgradeRequired:: 426 # HTTPPreconditionRequired:: 428 # HTTPTooManyRequests:: 429 # HTTPRequestHeaderFieldsTooLarge:: 431 # HTTPServerError:: 5xx # HTTPInternalServerError:: 500 # HTTPNotImplemented:: 501 # HTTPBadGateway:: 502 # HTTPServiceUnavailable:: 503 # HTTPGatewayTimeOut:: 504 # HTTPVersionNotSupported:: 505 # HTTPInsufficientStorage:: 507 # HTTPNetworkAuthenticationRequired:: 511 # # There is also the Net::HTTPBadResponse exception which is raised when # there is a protocol error. # class HTTP < Protocol # :stopdoc: Revision = %q$Revision: 56787 $.split[1] HTTPVersion = '1.1' begin require 'zlib' require 'stringio' #for our purposes (unpacking gzip) lump these together HAVE_ZLIB=true rescue LoadError HAVE_ZLIB=false end # :startdoc: # Turns on net/http 1.2 (Ruby 1.8) features. # Defaults to ON in Ruby 1.8 or later. def HTTP.version_1_2 true end # Returns true if net/http is in version 1.2 mode. # Defaults to true. def HTTP.version_1_2? true end def HTTP.version_1_1? #:nodoc: false end class << HTTP alias is_version_1_1? version_1_1? #:nodoc: alias is_version_1_2? version_1_2? #:nodoc: end # # short cut methods # # # Gets the body text from the target and outputs it to $stdout. The # target can either be specified as # (+uri+), or as (+host+, +path+, +port+ = 80); so: # # Net::HTTP.get_print URI('http://www.example.com/index.html') # # or: # # Net::HTTP.get_print 'www.example.com', '/index.html' # def HTTP.get_print(uri_or_host, path = nil, port = nil) get_response(uri_or_host, path, port) {|res| res.read_body do |chunk| $stdout.print chunk end } nil end # Sends a GET request to the target and returns the HTTP response # as a string. The target can either be specified as # (+uri+), or as (+host+, +path+, +port+ = 80); so: # # print Net::HTTP.get(URI('http://www.example.com/index.html')) # # or: # # print Net::HTTP.get('www.example.com', '/index.html') # def HTTP.get(uri_or_host, path = nil, port = nil) get_response(uri_or_host, path, port).body end # Sends a GET request to the target and returns the HTTP response # as a Net::HTTPResponse object. The target can either be specified as # (+uri+), or as (+host+, +path+, +port+ = 80); so: # # res = Net::HTTP.get_response(URI('http://www.example.com/index.html')) # print res.body # # or: # # res = Net::HTTP.get_response('www.example.com', '/index.html') # print res.body # def HTTP.get_response(uri_or_host, path = nil, port = nil, &block) if path host = uri_or_host new(host, port || HTTP.default_port).start {|http| return http.request_get(path, &block) } else uri = uri_or_host start(uri.hostname, uri.port, :use_ssl => uri.scheme == 'https') {|http| return http.request_get(uri, &block) } end end # Posts HTML form data to the specified URI object. # The form data must be provided as a Hash mapping from String to String. # Example: # # { "cmd" => "search", "q" => "ruby", "max" => "50" } # # This method also does Basic Authentication iff +url+.user exists. # But userinfo for authentication is deprecated (RFC3986). # So this feature will be removed. # # Example: # # require 'net/http' # require 'uri' # # Net::HTTP.post_form URI('http://www.example.com/search.cgi'), # { "q" => "ruby", "max" => "50" } # def HTTP.post_form(url, params) req = Post.new(url) req.form_data = params req.basic_auth url.user, url.password if url.user start(url.hostname, url.port, :use_ssl => url.scheme == 'https' ) {|http| http.request(req) } end # # HTTP session management # # The default port to use for HTTP requests; defaults to 80. def HTTP.default_port http_default_port() end # The default port to use for HTTP requests; defaults to 80. def HTTP.http_default_port 80 end # The default port to use for HTTPS requests; defaults to 443. def HTTP.https_default_port 443 end def HTTP.socket_type #:nodoc: obsolete BufferedIO end # :call-seq: # HTTP.start(address, port, p_addr, p_port, p_user, p_pass, &block) # HTTP.start(address, port=nil, p_addr=nil, p_port=nil, p_user=nil, p_pass=nil, opt, &block) # # Creates a new Net::HTTP object, then additionally opens the TCP # connection and HTTP session. # # Arguments are the following: # _address_ :: hostname or IP address of the server # _port_ :: port of the server # _p_addr_ :: address of proxy # _p_port_ :: port of proxy # _p_user_ :: user of proxy # _p_pass_ :: pass of proxy # _opt_ :: optional hash # # _opt_ sets following values by its accessor. # The keys are ca_file, ca_path, cert, cert_store, ciphers, # close_on_empty_response, key, open_timeout, read_timeout, ssl_timeout, # ssl_version, use_ssl, verify_callback, verify_depth and verify_mode. # If you set :use_ssl as true, you can use https and default value of # verify_mode is set as OpenSSL::SSL::VERIFY_PEER. # # If the optional block is given, the newly # created Net::HTTP object is passed to it and closed when the # block finishes. In this case, the return value of this method # is the return value of the block. If no block is given, the # return value of this method is the newly created Net::HTTP object # itself, and the caller is responsible for closing it upon completion # using the finish() method. def HTTP.start(address, *arg, &block) # :yield: +http+ arg.pop if opt = Hash.try_convert(arg[-1]) port, p_addr, p_port, p_user, p_pass = *arg port = https_default_port if !port && opt && opt[:use_ssl] http = new(address, port, p_addr, p_port, p_user, p_pass) if opt if opt[:use_ssl] opt = {verify_mode: OpenSSL::SSL::VERIFY_PEER}.update(opt) end http.methods.grep(/\A(\w+)=\z/) do |meth| key = $1.to_sym opt.key?(key) or next http.__send__(meth, opt[key]) end end http.start(&block) end class << HTTP alias newobj new # :nodoc: end # Creates a new Net::HTTP object without opening a TCP connection or # HTTP session. # # The +address+ should be a DNS hostname or IP address, the +port+ is the # port the server operates on. If no +port+ is given the default port for # HTTP or HTTPS is used. # # If none of the +p_+ arguments are given, the proxy host and port are # taken from the +http_proxy+ environment variable (or its uppercase # equivalent) if present. If the proxy requires authentication you must # supply it by hand. See URI::Generic#find_proxy for details of proxy # detection from the environment. To disable proxy detection set +p_addr+ # to nil. # # If you are connecting to a custom proxy, +p_addr+ the DNS name or IP # address of the proxy host, +p_port+ the port to use to access the proxy, # and +p_user+ and +p_pass+ the username and password if authorization is # required to use the proxy. # def HTTP.new(address, port = nil, p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil) http = super address, port if proxy_class? then # from Net::HTTP::Proxy() http.proxy_from_env = @proxy_from_env http.proxy_address = @proxy_address http.proxy_port = @proxy_port http.proxy_user = @proxy_user http.proxy_pass = @proxy_pass elsif p_addr == :ENV then http.proxy_from_env = true else http.proxy_address = p_addr http.proxy_port = p_port || default_port http.proxy_user = p_user http.proxy_pass = p_pass end http end # Creates a new Net::HTTP object for the specified server address, # without opening the TCP connection or initializing the HTTP session. # The +address+ should be a DNS hostname or IP address. def initialize(address, port = nil) @address = address @port = (port || HTTP.default_port) @local_host = nil @local_port = nil @curr_http_version = HTTPVersion @keep_alive_timeout = 2 @last_communicated = nil @close_on_empty_response = false @socket = nil @started = false @open_timeout = nil @read_timeout = 60 @continue_timeout = nil @debug_output = nil @proxy_from_env = false @proxy_uri = nil @proxy_address = nil @proxy_port = nil @proxy_user = nil @proxy_pass = nil @use_ssl = false @ssl_context = nil @ssl_session = nil @enable_post_connection_check = true @sspi_enabled = false SSL_IVNAMES.each do |ivname| instance_variable_set ivname, nil end end def inspect "#<#{self.class} #{@address}:#{@port} open=#{started?}>" end # *WARNING* This method opens a serious security hole. # Never use this method in production code. # # Sets an output stream for debugging. # # http = Net::HTTP.new(hostname) # http.set_debug_output $stderr # http.start { .... } # def set_debug_output(output) warn 'Net::HTTP#set_debug_output called after HTTP started' if started? @debug_output = output end # The DNS host name or IP address to connect to. attr_reader :address # The port number to connect to. attr_reader :port # The local host used to establish the connection. attr_accessor :local_host # The local port used to establish the connection. attr_accessor :local_port attr_writer :proxy_from_env attr_writer :proxy_address attr_writer :proxy_port attr_writer :proxy_user attr_writer :proxy_pass # Number of seconds to wait for the connection to open. Any number # may be used, including Floats for fractional seconds. If the HTTP # object cannot open a connection in this many seconds, it raises a # Net::OpenTimeout exception. The default value is +nil+. attr_accessor :open_timeout # Number of seconds to wait for one block to be read (via one read(2) # call). Any number may be used, including Floats for fractional # seconds. If the HTTP object cannot read data in this many seconds, # it raises a Net::ReadTimeout exception. The default value is 60 seconds. attr_reader :read_timeout # Setter for the read_timeout attribute. def read_timeout=(sec) @socket.read_timeout = sec if @socket @read_timeout = sec end # Seconds to wait for 100 Continue response. If the HTTP object does not # receive a response in this many seconds it sends the request body. The # default value is +nil+. attr_reader :continue_timeout # Setter for the continue_timeout attribute. def continue_timeout=(sec) @socket.continue_timeout = sec if @socket @continue_timeout = sec end # Seconds to reuse the connection of the previous request. # If the idle time is less than this Keep-Alive Timeout, # Net::HTTP reuses the TCP/IP socket used by the previous communication. # The default value is 2 seconds. attr_accessor :keep_alive_timeout # Returns true if the HTTP session has been started. def started? @started end alias active? started? #:nodoc: obsolete attr_accessor :close_on_empty_response # Returns true if SSL/TLS is being used with HTTP. def use_ssl? @use_ssl end # Turn on/off SSL. # This flag must be set before starting session. # If you change use_ssl value after session started, # a Net::HTTP object raises IOError. def use_ssl=(flag) flag = flag ? true : false if started? and @use_ssl != flag raise IOError, "use_ssl value changed, but session already started" end @use_ssl = flag end SSL_IVNAMES = [ :@ca_file, :@ca_path, :@cert, :@cert_store, :@ciphers, :@key, :@ssl_timeout, :@ssl_version, :@verify_callback, :@verify_depth, :@verify_mode, ] SSL_ATTRIBUTES = [ :ca_file, :ca_path, :cert, :cert_store, :ciphers, :key, :ssl_timeout, :ssl_version, :verify_callback, :verify_depth, :verify_mode, ] # Sets path of a CA certification file in PEM format. # # The file can contain several CA certificates. attr_accessor :ca_file # Sets path of a CA certification directory containing certifications in # PEM format. attr_accessor :ca_path # Sets an OpenSSL::X509::Certificate object as client certificate. # (This method is appeared in Michal Rokos's OpenSSL extension). attr_accessor :cert # Sets the X509::Store to verify peer certificate. attr_accessor :cert_store # Sets the available ciphers. See OpenSSL::SSL::SSLContext#ciphers= attr_accessor :ciphers # Sets an OpenSSL::PKey::RSA or OpenSSL::PKey::DSA object. # (This method is appeared in Michal Rokos's OpenSSL extension.) attr_accessor :key # Sets the SSL timeout seconds. attr_accessor :ssl_timeout # Sets the SSL version. See OpenSSL::SSL::SSLContext#ssl_version= attr_accessor :ssl_version # Sets the verify callback for the server certification verification. attr_accessor :verify_callback # Sets the maximum depth for the certificate chain verification. attr_accessor :verify_depth # Sets the flags for server the certification verification at beginning of # SSL/TLS session. # # OpenSSL::SSL::VERIFY_NONE or OpenSSL::SSL::VERIFY_PEER are acceptable. attr_accessor :verify_mode # Returns the X.509 certificates the server presented. def peer_cert if not use_ssl? or not @socket return nil end @socket.io.peer_cert end # Opens a TCP connection and HTTP session. # # When this method is called with a block, it passes the Net::HTTP # object to the block, and closes the TCP connection and HTTP session # after the block has been executed. # # When called with a block, it returns the return value of the # block; otherwise, it returns self. # def start # :yield: http raise IOError, 'HTTP session already opened' if @started if block_given? begin do_start return yield(self) ensure do_finish end end do_start self end def do_start connect @started = true end private :do_start def connect if proxy? then conn_address = proxy_address conn_port = proxy_port else conn_address = address conn_port = port end D "opening connection to #{conn_address}:#{conn_port}..." s = Timeout.timeout(@open_timeout, Net::OpenTimeout) { TCPSocket.open(conn_address, conn_port, @local_host, @local_port) } s.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1) D "opened" if use_ssl? ssl_parameters = Hash.new iv_list = instance_variables SSL_IVNAMES.each_with_index do |ivname, i| if iv_list.include?(ivname) and value = instance_variable_get(ivname) ssl_parameters[SSL_ATTRIBUTES[i]] = value if value end end @ssl_context = OpenSSL::SSL::SSLContext.new @ssl_context.set_params(ssl_parameters) D "starting SSL for #{conn_address}:#{conn_port}..." s = OpenSSL::SSL::SSLSocket.new(s, @ssl_context) s.sync_close = true D "SSL established" end @socket = BufferedIO.new(s) @socket.read_timeout = @read_timeout @socket.continue_timeout = @continue_timeout @socket.debug_output = @debug_output if use_ssl? begin if proxy? buf = "CONNECT #{@address}:#{@port} HTTP/#{HTTPVersion}\r\n" buf << "Host: #{@address}:#{@port}\r\n" if proxy_user credential = ["#{proxy_user}:#{proxy_pass}"].pack('m') credential.delete!("\r\n") buf << "Proxy-Authorization: Basic #{credential}\r\n" end buf << "\r\n" @socket.write(buf) HTTPResponse.read_new(@socket).value end # Server Name Indication (SNI) RFC 3546 s.hostname = @address if s.respond_to? :hostname= if @ssl_session and Process.clock_gettime(Process::CLOCK_REALTIME) < @ssl_session.time.to_f + @ssl_session.timeout s.session = @ssl_session if @ssl_session end Timeout.timeout(@open_timeout, Net::OpenTimeout) { s.connect } if @ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE s.post_connection_check(@address) end @ssl_session = s.session rescue => exception D "Conn close because of connect error #{exception}" @socket.close if @socket and not @socket.closed? raise exception end end on_connect end private :connect def on_connect end private :on_connect # Finishes the HTTP session and closes the TCP connection. # Raises IOError if the session has not been started. def finish raise IOError, 'HTTP session not yet started' unless started? do_finish end def do_finish @started = false @socket.close if @socket and not @socket.closed? @socket = nil end private :do_finish # # proxy # public # no proxy @is_proxy_class = false @proxy_from_env = false @proxy_addr = nil @proxy_port = nil @proxy_user = nil @proxy_pass = nil # Creates an HTTP proxy class which behaves like Net::HTTP, but # performs all access via the specified proxy. # # This class is obsolete. You may pass these same parameters directly to # Net::HTTP.new. See Net::HTTP.new for details of the arguments. def HTTP.Proxy(p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil) return self unless p_addr Class.new(self) { @is_proxy_class = true if p_addr == :ENV then @proxy_from_env = true @proxy_address = nil @proxy_port = nil else @proxy_from_env = false @proxy_address = p_addr @proxy_port = p_port || default_port end @proxy_user = p_user @proxy_pass = p_pass } end class << HTTP # returns true if self is a class which was created by HTTP::Proxy. def proxy_class? defined?(@is_proxy_class) ? @is_proxy_class : false end # Address of proxy host. If Net::HTTP does not use a proxy, nil. attr_reader :proxy_address # Port number of proxy host. If Net::HTTP does not use a proxy, nil. attr_reader :proxy_port # User name for accessing proxy. If Net::HTTP does not use a proxy, nil. attr_reader :proxy_user # User password for accessing proxy. If Net::HTTP does not use a proxy, # nil. attr_reader :proxy_pass end # True if requests for this connection will be proxied def proxy? !!if @proxy_from_env then proxy_uri else @proxy_address end end # True if the proxy for this connection is determined from the environment def proxy_from_env? @proxy_from_env end # The proxy URI determined from the environment for this connection. def proxy_uri # :nodoc: @proxy_uri ||= URI::HTTP.new( "http".freeze, nil, address, port, nil, nil, nil, nil, nil ).find_proxy end # The address of the proxy server, if one is configured. def proxy_address if @proxy_from_env then proxy_uri && proxy_uri.hostname else @proxy_address end end # The port of the proxy server, if one is configured. def proxy_port if @proxy_from_env then proxy_uri && proxy_uri.port else @proxy_port end end # The proxy username, if one is configured def proxy_user @proxy_user end # The proxy password, if one is configured def proxy_pass @proxy_pass end alias proxyaddr proxy_address #:nodoc: obsolete alias proxyport proxy_port #:nodoc: obsolete private # without proxy, obsolete def conn_address # :nodoc: address() end def conn_port # :nodoc: port() end def edit_path(path) if proxy? and not use_ssl? then "http://#{addr_port}#{path}" else path end end # # HTTP operations # public # Retrieves data from +path+ on the connected-to host which may be an # absolute path String or a URI to extract the path from. # # +initheader+ must be a Hash like { 'Accept' => '*/*', ... }, # and it defaults to an empty hash. # If +initheader+ doesn't have the key 'accept-encoding', then # a value of "gzip;q=1.0,deflate;q=0.6,identity;q=0.3" is used, # so that gzip compression is used in preference to deflate # compression, which is used in preference to no compression. # Ruby doesn't have libraries to support the compress (Lempel-Ziv) # compression, so that is not supported. The intent of this is # to reduce bandwidth by default. If this routine sets up # compression, then it does the decompression also, removing # the header as well to prevent confusion. Otherwise # it leaves the body as it found it. # # This method returns a Net::HTTPResponse object. # # If called with a block, yields each fragment of the # entity body in turn as a string as it is read from # the socket. Note that in this case, the returned response # object will *not* contain a (meaningful) body. # # +dest+ argument is obsolete. # It still works but you must not use it. # # This method never raises an exception. # # response = http.get('/index.html') # # # using block # File.open('result.txt', 'w') {|f| # http.get('/~foo/') do |str| # f.write str # end # } # def get(path, initheader = nil, dest = nil, &block) # :yield: +body_segment+ res = nil request(Get.new(path, initheader)) {|r| r.read_body dest, &block res = r } res end # Gets only the header from +path+ on the connected-to host. # +header+ is a Hash like { 'Accept' => '*/*', ... }. # # This method returns a Net::HTTPResponse object. # # This method never raises an exception. # # response = nil # Net::HTTP.start('some.www.server', 80) {|http| # response = http.head('/index.html') # } # p response['content-type'] # def head(path, initheader = nil) request(Head.new(path, initheader)) end # Posts +data+ (must be a String) to +path+. +header+ must be a Hash # like { 'Accept' => '*/*', ... }. # # This method returns a Net::HTTPResponse object. # # If called with a block, yields each fragment of the # entity body in turn as a string as it is read from # the socket. Note that in this case, the returned response # object will *not* contain a (meaningful) body. # # +dest+ argument is obsolete. # It still works but you must not use it. # # This method never raises exception. # # response = http.post('/cgi-bin/search.rb', 'query=foo') # # # using block # File.open('result.txt', 'w') {|f| # http.post('/cgi-bin/search.rb', 'query=foo') do |str| # f.write str # end # } # # You should set Content-Type: header field for POST. # If no Content-Type: field given, this method uses # "application/x-www-form-urlencoded" by default. # def post(path, data, initheader = nil, dest = nil, &block) # :yield: +body_segment+ send_entity(path, data, initheader, dest, Post, &block) end # Sends a PATCH request to the +path+ and gets a response, # as an HTTPResponse object. def patch(path, data, initheader = nil, dest = nil, &block) # :yield: +body_segment+ send_entity(path, data, initheader, dest, Patch, &block) end def put(path, data, initheader = nil) #:nodoc: request(Put.new(path, initheader), data) end # Sends a PROPPATCH request to the +path+ and gets a response, # as an HTTPResponse object. def proppatch(path, body, initheader = nil) request(Proppatch.new(path, initheader), body) end # Sends a LOCK request to the +path+ and gets a response, # as an HTTPResponse object. def lock(path, body, initheader = nil) request(Lock.new(path, initheader), body) end # Sends a UNLOCK request to the +path+ and gets a response, # as an HTTPResponse object. def unlock(path, body, initheader = nil) request(Unlock.new(path, initheader), body) end # Sends a OPTIONS request to the +path+ and gets a response, # as an HTTPResponse object. def options(path, initheader = nil) request(Options.new(path, initheader)) end # Sends a PROPFIND request to the +path+ and gets a response, # as an HTTPResponse object. def propfind(path, body = nil, initheader = {'Depth' => '0'}) request(Propfind.new(path, initheader), body) end # Sends a DELETE request to the +path+ and gets a response, # as an HTTPResponse object. def delete(path, initheader = {'Depth' => 'Infinity'}) request(Delete.new(path, initheader)) end # Sends a MOVE request to the +path+ and gets a response, # as an HTTPResponse object. def move(path, initheader = nil) request(Move.new(path, initheader)) end # Sends a COPY request to the +path+ and gets a response, # as an HTTPResponse object. def copy(path, initheader = nil) request(Copy.new(path, initheader)) end # Sends a MKCOL request to the +path+ and gets a response, # as an HTTPResponse object. def mkcol(path, body = nil, initheader = nil) request(Mkcol.new(path, initheader), body) end # Sends a TRACE request to the +path+ and gets a response, # as an HTTPResponse object. def trace(path, initheader = nil) request(Trace.new(path, initheader)) end # Sends a GET request to the +path+. # Returns the response as a Net::HTTPResponse object. # # When called with a block, passes an HTTPResponse object to the block. # The body of the response will not have been read yet; # the block can process it using HTTPResponse#read_body, # if desired. # # Returns the response. # # This method never raises Net::* exceptions. # # response = http.request_get('/index.html') # # The entity body is already read in this case. # p response['content-type'] # puts response.body # # # Using a block # http.request_get('/index.html') {|response| # p response['content-type'] # response.read_body do |str| # read body now # print str # end # } # def request_get(path, initheader = nil, &block) # :yield: +response+ request(Get.new(path, initheader), &block) end # Sends a HEAD request to the +path+ and returns the response # as a Net::HTTPResponse object. # # Returns the response. # # This method never raises Net::* exceptions. # # response = http.request_head('/index.html') # p response['content-type'] # def request_head(path, initheader = nil, &block) request(Head.new(path, initheader), &block) end # Sends a POST request to the +path+. # # Returns the response as a Net::HTTPResponse object. # # When called with a block, the block is passed an HTTPResponse # object. The body of that response will not have been read yet; # the block can process it using HTTPResponse#read_body, if desired. # # Returns the response. # # This method never raises Net::* exceptions. # # # example # response = http.request_post('/cgi-bin/nice.rb', 'datadatadata...') # p response.status # puts response.body # body is already read in this case # # # using block # http.request_post('/cgi-bin/nice.rb', 'datadatadata...') {|response| # p response.status # p response['content-type'] # response.read_body do |str| # read body now # print str # end # } # def request_post(path, data, initheader = nil, &block) # :yield: +response+ request Post.new(path, initheader), data, &block end def request_put(path, data, initheader = nil, &block) #:nodoc: request Put.new(path, initheader), data, &block end alias get2 request_get #:nodoc: obsolete alias head2 request_head #:nodoc: obsolete alias post2 request_post #:nodoc: obsolete alias put2 request_put #:nodoc: obsolete # Sends an HTTP request to the HTTP server. # Also sends a DATA string if +data+ is given. # # Returns a Net::HTTPResponse object. # # This method never raises Net::* exceptions. # # response = http.send_request('GET', '/index.html') # puts response.body # def send_request(name, path, data = nil, header = nil) has_response_body = name != 'HEAD' r = HTTPGenericRequest.new(name,(data ? true : false),has_response_body,path,header) request r, data end # Sends an HTTPRequest object +req+ to the HTTP server. # # If +req+ is a Net::HTTP::Post or Net::HTTP::Put request containing # data, the data is also sent. Providing data for a Net::HTTP::Head or # Net::HTTP::Get request results in an ArgumentError. # # Returns an HTTPResponse object. # # When called with a block, passes an HTTPResponse object to the block. # The body of the response will not have been read yet; # the block can process it using HTTPResponse#read_body, # if desired. # # This method never raises Net::* exceptions. # def request(req, body = nil, &block) # :yield: +response+ unless started? start { req['connection'] ||= 'close' return request(req, body, &block) } end if proxy_user() req.proxy_basic_auth proxy_user(), proxy_pass() unless use_ssl? end req.set_body_internal body res = transport_request(req, &block) if sspi_auth?(res) sspi_auth(req) res = transport_request(req, &block) end res end private # Executes a request which uses a representation # and returns its body. def send_entity(path, data, initheader, dest, type, &block) res = nil request(type.new(path, initheader), data) {|r| r.read_body dest, &block res = r } res end IDEMPOTENT_METHODS_ = %w/GET HEAD PUT DELETE OPTIONS TRACE/ # :nodoc: def transport_request(req) count = 0 begin begin_transport req res = catch(:response) { req.exec @socket, @curr_http_version, edit_path(req.path) begin res = HTTPResponse.read_new(@socket) res.decode_content = req.decode_content end while res.kind_of?(HTTPInformation) res.uri = req.uri res } res.reading_body(@socket, req.response_body_permitted?) { yield res if block_given? } rescue Net::OpenTimeout raise rescue Net::ReadTimeout, IOError, EOFError, Errno::ECONNRESET, Errno::ECONNABORTED, Errno::EPIPE, # avoid a dependency on OpenSSL defined?(OpenSSL::SSL) ? OpenSSL::SSL::SSLError : IOError, Timeout::Error => exception if count == 0 && IDEMPOTENT_METHODS_.include?(req.method) count += 1 @socket.close if @socket and not @socket.closed? D "Conn close because of error #{exception}, and retry" retry end D "Conn close because of error #{exception}" @socket.close if @socket and not @socket.closed? raise end end_transport req, res res rescue => exception D "Conn close because of error #{exception}" @socket.close if @socket and not @socket.closed? raise exception end def begin_transport(req) if @socket.closed? connect elsif @last_communicated && @last_communicated + @keep_alive_timeout < Time.now D 'Conn close because of keep_alive_timeout' @socket.close connect end if not req.response_body_permitted? and @close_on_empty_response req['connection'] ||= 'close' end req.update_uri address, port, use_ssl? req['host'] ||= addr_port() end def end_transport(req, res) @curr_http_version = res.http_version @last_communicated = nil if @socket.closed? D 'Conn socket closed' elsif not res.body and @close_on_empty_response D 'Conn close' @socket.close elsif keep_alive?(req, res) D 'Conn keep-alive' @last_communicated = Time.now else D 'Conn close' @socket.close end end def keep_alive?(req, res) return false if req.connection_close? if @curr_http_version <= '1.0' res.connection_keep_alive? else # HTTP/1.1 or later not res.connection_close? end end def sspi_auth?(res) return false unless @sspi_enabled if res.kind_of?(HTTPProxyAuthenticationRequired) and proxy? and res["Proxy-Authenticate"].include?("Negotiate") begin require 'win32/sspi' true rescue LoadError false end else false end end def sspi_auth(req) n = Win32::SSPI::NegotiateAuth.new req["Proxy-Authorization"] = "Negotiate #{n.get_initial_token}" # Some versions of ISA will close the connection if this isn't present. req["Connection"] = "Keep-Alive" req["Proxy-Connection"] = "Keep-Alive" res = transport_request(req) authphrase = res["Proxy-Authenticate"] or return res req["Proxy-Authorization"] = "Negotiate #{n.complete_authentication(authphrase)}" rescue => err raise HTTPAuthenticationError.new('HTTP authentication failed', err) end # # utils # private def addr_port if use_ssl? address() + (port == HTTP.https_default_port ? '' : ":#{port()}") else address() + (port == HTTP.http_default_port ? '' : ":#{port()}") end end def D(msg) return unless @debug_output @debug_output << msg @debug_output << "\n" end end end require 'net/http/exceptions' require 'net/http/header' require 'net/http/generic_request' require 'net/http/request' require 'net/http/requests' require 'net/http/response' require 'net/http/responses' require 'net/http/proxy_delta' require 'net/http/backward' PK!?2.2.0/net/imap.rbnu[# # = net/imap.rb # # Copyright (C) 2000 Shugo Maeda # # This library is distributed under the terms of the Ruby license. # You can freely distribute/modify this library. # # Documentation: Shugo Maeda, with RDoc conversion and overview by William # Webber. # # See Net::IMAP for documentation. # require "socket" require "monitor" require "digest/md5" require "strscan" begin require "openssl" rescue LoadError end module Net # # Net::IMAP implements Internet Message Access Protocol (IMAP) client # functionality. The protocol is described in [IMAP]. # # == IMAP Overview # # An IMAP client connects to a server, and then authenticates # itself using either #authenticate() or #login(). Having # authenticated itself, there is a range of commands # available to it. Most work with mailboxes, which may be # arranged in an hierarchical namespace, and each of which # contains zero or more messages. How this is implemented on # the server is implementation-dependent; on a UNIX server, it # will frequently be implemented as files in mailbox format # within a hierarchy of directories. # # To work on the messages within a mailbox, the client must # first select that mailbox, using either #select() or (for # read-only access) #examine(). Once the client has successfully # selected a mailbox, they enter _selected_ state, and that # mailbox becomes the _current_ mailbox, on which mail-item # related commands implicitly operate. # # Messages have two sorts of identifiers: message sequence # numbers and UIDs. # # Message sequence numbers number messages within a mailbox # from 1 up to the number of items in the mailbox. If a new # message arrives during a session, it receives a sequence # number equal to the new size of the mailbox. If messages # are expunged from the mailbox, remaining messages have their # sequence numbers "shuffled down" to fill the gaps. # # UIDs, on the other hand, are permanently guaranteed not to # identify another message within the same mailbox, even if # the existing message is deleted. UIDs are required to # be assigned in ascending (but not necessarily sequential) # order within a mailbox; this means that if a non-IMAP client # rearranges the order of mailitems within a mailbox, the # UIDs have to be reassigned. An IMAP client thus cannot # rearrange message orders. # # == Examples of Usage # # === List sender and subject of all recent messages in the default mailbox # # imap = Net::IMAP.new('mail.example.com') # imap.authenticate('LOGIN', 'joe_user', 'joes_password') # imap.examine('INBOX') # imap.search(["RECENT"]).each do |message_id| # envelope = imap.fetch(message_id, "ENVELOPE")[0].attr["ENVELOPE"] # puts "#{envelope.from[0].name}: \t#{envelope.subject}" # end # # === Move all messages from April 2003 from "Mail/sent-mail" to "Mail/sent-apr03" # # imap = Net::IMAP.new('mail.example.com') # imap.authenticate('LOGIN', 'joe_user', 'joes_password') # imap.select('Mail/sent-mail') # if not imap.list('Mail/', 'sent-apr03') # imap.create('Mail/sent-apr03') # end # imap.search(["BEFORE", "30-Apr-2003", "SINCE", "1-Apr-2003"]).each do |message_id| # imap.copy(message_id, "Mail/sent-apr03") # imap.store(message_id, "+FLAGS", [:Deleted]) # end # imap.expunge # # == Thread Safety # # Net::IMAP supports concurrent threads. For example, # # imap = Net::IMAP.new("imap.foo.net", "imap2") # imap.authenticate("cram-md5", "bar", "password") # imap.select("inbox") # fetch_thread = Thread.start { imap.fetch(1..-1, "UID") } # search_result = imap.search(["BODY", "hello"]) # fetch_result = fetch_thread.value # imap.disconnect # # This script invokes the FETCH command and the SEARCH command concurrently. # # == Errors # # An IMAP server can send three different types of responses to indicate # failure: # # NO:: the attempted command could not be successfully completed. For # instance, the username/password used for logging in are incorrect; # the selected mailbox does not exist; etc. # # BAD:: the request from the client does not follow the server's # understanding of the IMAP protocol. This includes attempting # commands from the wrong client state; for instance, attempting # to perform a SEARCH command without having SELECTed a current # mailbox. It can also signal an internal server # failure (such as a disk crash) has occurred. # # BYE:: the server is saying goodbye. This can be part of a normal # logout sequence, and can be used as part of a login sequence # to indicate that the server is (for some reason) unwilling # to accept your connection. As a response to any other command, # it indicates either that the server is shutting down, or that # the server is timing out the client connection due to inactivity. # # These three error response are represented by the errors # Net::IMAP::NoResponseError, Net::IMAP::BadResponseError, and # Net::IMAP::ByeResponseError, all of which are subclasses of # Net::IMAP::ResponseError. Essentially, all methods that involve # sending a request to the server can generate one of these errors. # Only the most pertinent instances have been documented below. # # Because the IMAP class uses Sockets for communication, its methods # are also susceptible to the various errors that can occur when # working with sockets. These are generally represented as # Errno errors. For instance, any method that involves sending a # request to the server and/or receiving a response from it could # raise an Errno::EPIPE error if the network connection unexpectedly # goes down. See the socket(7), ip(7), tcp(7), socket(2), connect(2), # and associated man pages. # # Finally, a Net::IMAP::DataFormatError is thrown if low-level data # is found to be in an incorrect format (for instance, when converting # between UTF-8 and UTF-16), and Net::IMAP::ResponseParseError is # thrown if a server response is non-parseable. # # # == References # # [[IMAP]] # M. Crispin, "INTERNET MESSAGE ACCESS PROTOCOL - VERSION 4rev1", # RFC 2060, December 1996. (Note: since obsoleted by RFC 3501) # # [[LANGUAGE-TAGS]] # Alvestrand, H., "Tags for the Identification of # Languages", RFC 1766, March 1995. # # [[MD5]] # Myers, J., and M. Rose, "The Content-MD5 Header Field", RFC # 1864, October 1995. # # [[MIME-IMB]] # Freed, N., and N. Borenstein, "MIME (Multipurpose Internet # Mail Extensions) Part One: Format of Internet Message Bodies", RFC # 2045, November 1996. # # [[RFC-822]] # Crocker, D., "Standard for the Format of ARPA Internet Text # Messages", STD 11, RFC 822, University of Delaware, August 1982. # # [[RFC-2087]] # Myers, J., "IMAP4 QUOTA extension", RFC 2087, January 1997. # # [[RFC-2086]] # Myers, J., "IMAP4 ACL extension", RFC 2086, January 1997. # # [[RFC-2195]] # Klensin, J., Catoe, R., and Krumviede, P., "IMAP/POP AUTHorize Extension # for Simple Challenge/Response", RFC 2195, September 1997. # # [[SORT-THREAD-EXT]] # Crispin, M., "INTERNET MESSAGE ACCESS PROTOCOL - SORT and THREAD # Extensions", draft-ietf-imapext-sort, May 2003. # # [[OSSL]] # http://www.openssl.org # # [[RSSL]] # http://savannah.gnu.org/projects/rubypki # # [[UTF7]] # Goldsmith, D. and Davis, M., "UTF-7: A Mail-Safe Transformation Format of # Unicode", RFC 2152, May 1997. # class IMAP include MonitorMixin if defined?(OpenSSL::SSL) include OpenSSL include SSL end # Returns an initial greeting response from the server. attr_reader :greeting # Returns recorded untagged responses. For example: # # imap.select("inbox") # p imap.responses["EXISTS"][-1] # #=> 2 # p imap.responses["UIDVALIDITY"][-1] # #=> 968263756 attr_reader :responses # Returns all response handlers. attr_reader :response_handlers # The thread to receive exceptions. attr_accessor :client_thread # Flag indicating a message has been seen. SEEN = :Seen # Flag indicating a message has been answered. ANSWERED = :Answered # Flag indicating a message has been flagged for special or urgent # attention. FLAGGED = :Flagged # Flag indicating a message has been marked for deletion. This # will occur when the mailbox is closed or expunged. DELETED = :Deleted # Flag indicating a message is only a draft or work-in-progress version. DRAFT = :Draft # Flag indicating that the message is "recent," meaning that this # session is the first session in which the client has been notified # of this message. RECENT = :Recent # Flag indicating that a mailbox context name cannot contain # children. NOINFERIORS = :Noinferiors # Flag indicating that a mailbox is not selected. NOSELECT = :Noselect # Flag indicating that a mailbox has been marked "interesting" by # the server; this commonly indicates that the mailbox contains # new messages. MARKED = :Marked # Flag indicating that the mailbox does not contains new messages. UNMARKED = :Unmarked # Returns the debug mode. def self.debug return @@debug end # Sets the debug mode. def self.debug=(val) return @@debug = val end # Returns the max number of flags interned to symbols. def self.max_flag_count return @@max_flag_count end # Sets the max number of flags interned to symbols. def self.max_flag_count=(count) @@max_flag_count = count end # Adds an authenticator for Net::IMAP#authenticate. +auth_type+ # is the type of authentication this authenticator supports # (for instance, "LOGIN"). The +authenticator+ is an object # which defines a process() method to handle authentication with # the server. See Net::IMAP::LoginAuthenticator, # Net::IMAP::CramMD5Authenticator, and Net::IMAP::DigestMD5Authenticator # for examples. # # # If +auth_type+ refers to an existing authenticator, it will be # replaced by the new one. def self.add_authenticator(auth_type, authenticator) @@authenticators[auth_type] = authenticator end # The default port for IMAP connections, port 143 def self.default_port return PORT end # The default port for IMAPS connections, port 993 def self.default_tls_port return SSL_PORT end class << self alias default_imap_port default_port alias default_imaps_port default_tls_port alias default_ssl_port default_tls_port end # Disconnects from the server. def disconnect begin begin # try to call SSL::SSLSocket#io. @sock.io.shutdown rescue NoMethodError # @sock is not an SSL::SSLSocket. @sock.shutdown end rescue Errno::ENOTCONN # ignore `Errno::ENOTCONN: Socket is not connected' on some platforms. rescue Exception => e @receiver_thread.raise(e) end @receiver_thread.join synchronize do unless @sock.closed? @sock.close end end raise e if e end # Returns true if disconnected from the server. def disconnected? return @sock.closed? end # Sends a CAPABILITY command, and returns an array of # capabilities that the server supports. Each capability # is a string. See [IMAP] for a list of possible # capabilities. # # Note that the Net::IMAP class does not modify its # behaviour according to the capabilities of the server; # it is up to the user of the class to ensure that # a certain capability is supported by a server before # using it. def capability synchronize do send_command("CAPABILITY") return @responses.delete("CAPABILITY")[-1] end end # Sends a NOOP command to the server. It does nothing. def noop send_command("NOOP") end # Sends a LOGOUT command to inform the server that the client is # done with the connection. def logout send_command("LOGOUT") end # Sends a STARTTLS command to start TLS session. def starttls(options = {}, verify = true) send_command("STARTTLS") do |resp| if resp.kind_of?(TaggedResponse) && resp.name == "OK" begin # for backward compatibility certs = options.to_str options = create_ssl_params(certs, verify) rescue NoMethodError end start_tls_session(options) end end end # Sends an AUTHENTICATE command to authenticate the client. # The +auth_type+ parameter is a string that represents # the authentication mechanism to be used. Currently Net::IMAP # supports the authentication mechanisms: # # LOGIN:: login using cleartext user and password. # CRAM-MD5:: login with cleartext user and encrypted password # (see [RFC-2195] for a full description). This # mechanism requires that the server have the user's # password stored in clear-text password. # # For both of these mechanisms, there should be two +args+: username # and (cleartext) password. A server may not support one or the other # of these mechanisms; check #capability() for a capability of # the form "AUTH=LOGIN" or "AUTH=CRAM-MD5". # # Authentication is done using the appropriate authenticator object: # see @@authenticators for more information on plugging in your own # authenticator. # # For example: # # imap.authenticate('LOGIN', user, password) # # A Net::IMAP::NoResponseError is raised if authentication fails. def authenticate(auth_type, *args) auth_type = auth_type.upcase unless @@authenticators.has_key?(auth_type) raise ArgumentError, format('unknown auth type - "%s"', auth_type) end authenticator = @@authenticators[auth_type].new(*args) send_command("AUTHENTICATE", auth_type) do |resp| if resp.instance_of?(ContinuationRequest) data = authenticator.process(resp.data.text.unpack("m")[0]) s = [data].pack("m").gsub(/\n/, "") send_string_data(s) put_string(CRLF) end end end # Sends a LOGIN command to identify the client and carries # the plaintext +password+ authenticating this +user+. Note # that, unlike calling #authenticate() with an +auth_type+ # of "LOGIN", #login() does *not* use the login authenticator. # # A Net::IMAP::NoResponseError is raised if authentication fails. def login(user, password) send_command("LOGIN", user, password) end # Sends a SELECT command to select a +mailbox+ so that messages # in the +mailbox+ can be accessed. # # After you have selected a mailbox, you may retrieve the # number of items in that mailbox from @responses["EXISTS"][-1], # and the number of recent messages from @responses["RECENT"][-1]. # Note that these values can change if new messages arrive # during a session; see #add_response_handler() for a way of # detecting this event. # # A Net::IMAP::NoResponseError is raised if the mailbox does not # exist or is for some reason non-selectable. def select(mailbox) synchronize do @responses.clear send_command("SELECT", mailbox) end end # Sends a EXAMINE command to select a +mailbox+ so that messages # in the +mailbox+ can be accessed. Behaves the same as #select(), # except that the selected +mailbox+ is identified as read-only. # # A Net::IMAP::NoResponseError is raised if the mailbox does not # exist or is for some reason non-examinable. def examine(mailbox) synchronize do @responses.clear send_command("EXAMINE", mailbox) end end # Sends a CREATE command to create a new +mailbox+. # # A Net::IMAP::NoResponseError is raised if a mailbox with that name # cannot be created. def create(mailbox) send_command("CREATE", mailbox) end # Sends a DELETE command to remove the +mailbox+. # # A Net::IMAP::NoResponseError is raised if a mailbox with that name # cannot be deleted, either because it does not exist or because the # client does not have permission to delete it. def delete(mailbox) send_command("DELETE", mailbox) end # Sends a RENAME command to change the name of the +mailbox+ to # +newname+. # # A Net::IMAP::NoResponseError is raised if a mailbox with the # name +mailbox+ cannot be renamed to +newname+ for whatever # reason; for instance, because +mailbox+ does not exist, or # because there is already a mailbox with the name +newname+. def rename(mailbox, newname) send_command("RENAME", mailbox, newname) end # Sends a SUBSCRIBE command to add the specified +mailbox+ name to # the server's set of "active" or "subscribed" mailboxes as returned # by #lsub(). # # A Net::IMAP::NoResponseError is raised if +mailbox+ cannot be # subscribed to; for instance, because it does not exist. def subscribe(mailbox) send_command("SUBSCRIBE", mailbox) end # Sends a UNSUBSCRIBE command to remove the specified +mailbox+ name # from the server's set of "active" or "subscribed" mailboxes. # # A Net::IMAP::NoResponseError is raised if +mailbox+ cannot be # unsubscribed from; for instance, because the client is not currently # subscribed to it. def unsubscribe(mailbox) send_command("UNSUBSCRIBE", mailbox) end # Sends a LIST command, and returns a subset of names from # the complete set of all names available to the client. # +refname+ provides a context (for instance, a base directory # in a directory-based mailbox hierarchy). +mailbox+ specifies # a mailbox or (via wildcards) mailboxes under that context. # Two wildcards may be used in +mailbox+: '*', which matches # all characters *including* the hierarchy delimiter (for instance, # '/' on a UNIX-hosted directory-based mailbox hierarchy); and '%', # which matches all characters *except* the hierarchy delimiter. # # If +refname+ is empty, +mailbox+ is used directly to determine # which mailboxes to match. If +mailbox+ is empty, the root # name of +refname+ and the hierarchy delimiter are returned. # # The return value is an array of +Net::IMAP::MailboxList+. For example: # # imap.create("foo/bar") # imap.create("foo/baz") # p imap.list("", "foo/%") # #=> [#, \\ # #, \\ # #] def list(refname, mailbox) synchronize do send_command("LIST", refname, mailbox) return @responses.delete("LIST") end end # Sends a XLIST command, and returns a subset of names from # the complete set of all names available to the client. # +refname+ provides a context (for instance, a base directory # in a directory-based mailbox hierarchy). +mailbox+ specifies # a mailbox or (via wildcards) mailboxes under that context. # Two wildcards may be used in +mailbox+: '*', which matches # all characters *including* the hierarchy delimiter (for instance, # '/' on a UNIX-hosted directory-based mailbox hierarchy); and '%', # which matches all characters *except* the hierarchy delimiter. # # If +refname+ is empty, +mailbox+ is used directly to determine # which mailboxes to match. If +mailbox+ is empty, the root # name of +refname+ and the hierarchy delimiter are returned. # # The XLIST command is like the LIST command except that the flags # returned refer to the function of the folder/mailbox, e.g. :Sent # # The return value is an array of +Net::IMAP::MailboxList+. For example: # # imap.create("foo/bar") # imap.create("foo/baz") # p imap.xlist("", "foo/%") # #=> [#, \\ # #, \\ # #] def xlist(refname, mailbox) synchronize do send_command("XLIST", refname, mailbox) return @responses.delete("XLIST") end end # Sends the GETQUOTAROOT command along with the specified +mailbox+. # This command is generally available to both admin and user. # If this mailbox exists, it returns an array containing objects of type # Net::IMAP::MailboxQuotaRoot and Net::IMAP::MailboxQuota. def getquotaroot(mailbox) synchronize do send_command("GETQUOTAROOT", mailbox) result = [] result.concat(@responses.delete("QUOTAROOT")) result.concat(@responses.delete("QUOTA")) return result end end # Sends the GETQUOTA command along with specified +mailbox+. # If this mailbox exists, then an array containing a # Net::IMAP::MailboxQuota object is returned. This # command is generally only available to server admin. def getquota(mailbox) synchronize do send_command("GETQUOTA", mailbox) return @responses.delete("QUOTA") end end # Sends a SETQUOTA command along with the specified +mailbox+ and # +quota+. If +quota+ is nil, then +quota+ will be unset for that # mailbox. Typically one needs to be logged in as a server admin # for this to work. The IMAP quota commands are described in # [RFC-2087]. def setquota(mailbox, quota) if quota.nil? data = '()' else data = '(STORAGE ' + quota.to_s + ')' end send_command("SETQUOTA", mailbox, RawData.new(data)) end # Sends the SETACL command along with +mailbox+, +user+ and the # +rights+ that user is to have on that mailbox. If +rights+ is nil, # then that user will be stripped of any rights to that mailbox. # The IMAP ACL commands are described in [RFC-2086]. def setacl(mailbox, user, rights) if rights.nil? send_command("SETACL", mailbox, user, "") else send_command("SETACL", mailbox, user, rights) end end # Send the GETACL command along with a specified +mailbox+. # If this mailbox exists, an array containing objects of # Net::IMAP::MailboxACLItem will be returned. def getacl(mailbox) synchronize do send_command("GETACL", mailbox) return @responses.delete("ACL")[-1] end end # Sends a LSUB command, and returns a subset of names from the set # of names that the user has declared as being "active" or # "subscribed." +refname+ and +mailbox+ are interpreted as # for #list(). # The return value is an array of +Net::IMAP::MailboxList+. def lsub(refname, mailbox) synchronize do send_command("LSUB", refname, mailbox) return @responses.delete("LSUB") end end # Sends a STATUS command, and returns the status of the indicated # +mailbox+. +attr+ is a list of one or more attributes whose # statuses are to be requested. Supported attributes include: # # MESSAGES:: the number of messages in the mailbox. # RECENT:: the number of recent messages in the mailbox. # UNSEEN:: the number of unseen messages in the mailbox. # # The return value is a hash of attributes. For example: # # p imap.status("inbox", ["MESSAGES", "RECENT"]) # #=> {"RECENT"=>0, "MESSAGES"=>44} # # A Net::IMAP::NoResponseError is raised if status values # for +mailbox+ cannot be returned; for instance, because it # does not exist. def status(mailbox, attr) synchronize do send_command("STATUS", mailbox, attr) return @responses.delete("STATUS")[-1].attr end end # Sends a APPEND command to append the +message+ to the end of # the +mailbox+. The optional +flags+ argument is an array of # flags initially passed to the new message. The optional # +date_time+ argument specifies the creation time to assign to the # new message; it defaults to the current time. # For example: # # imap.append("inbox", <:: a set of message sequence numbers. ',' indicates # an interval, ':' indicates a range. For instance, # '2,10:12,15' means "2,10,11,12,15". # # BEFORE :: messages with an internal date strictly before # . The date argument has a format similar # to 8-Aug-2002. # # BODY :: messages that contain within their body. # # CC :: messages containing in their CC field. # # FROM :: messages that contain in their FROM field. # # NEW:: messages with the \Recent, but not the \Seen, flag set. # # NOT :: negate the following search key. # # OR :: "or" two search keys together. # # ON :: messages with an internal date exactly equal to , # which has a format similar to 8-Aug-2002. # # SINCE :: messages with an internal date on or after . # # SUBJECT :: messages with in their subject. # # TO :: messages with in their TO field. # # For example: # # p imap.search(["SUBJECT", "hello", "NOT", "NEW"]) # #=> [1, 6, 7, 8] def search(keys, charset = nil) return search_internal("SEARCH", keys, charset) end # Similar to #search(), but returns unique identifiers. def uid_search(keys, charset = nil) return search_internal("UID SEARCH", keys, charset) end # Sends a FETCH command to retrieve data associated with a message # in the mailbox. # # The +set+ parameter is a number or a range between two numbers, # or an array of those. The number is a message sequence number, # where -1 repesents a '*' for use in range notation like 100..-1 # being interpreted as '100:*'. Beware that the +exclude_end?+ # property of a Range object is ignored, and the contents of a # range are independent of the order of the range endpoints as per # the protocol specification, so 1...5, 5..1 and 5...1 are all # equivalent to 1..5. # # +attr+ is a list of attributes to fetch; see the documentation # for Net::IMAP::FetchData for a list of valid attributes. # # The return value is an array of Net::IMAP::FetchData or nil # (instead of an empty array) if there is no matching message. # # For example: # # p imap.fetch(6..8, "UID") # #=> [#98}>, \\ # #99}>, \\ # #100}>] # p imap.fetch(6, "BODY[HEADER.FIELDS (SUBJECT)]") # #=> [#"Subject: test\r\n\r\n"}>] # data = imap.uid_fetch(98, ["RFC822.SIZE", "INTERNALDATE"])[0] # p data.seqno # #=> 6 # p data.attr["RFC822.SIZE"] # #=> 611 # p data.attr["INTERNALDATE"] # #=> "12-Oct-2000 22:40:59 +0900" # p data.attr["UID"] # #=> 98 def fetch(set, attr) return fetch_internal("FETCH", set, attr) end # Similar to #fetch(), but +set+ contains unique identifiers. def uid_fetch(set, attr) return fetch_internal("UID FETCH", set, attr) end # Sends a STORE command to alter data associated with messages # in the mailbox, in particular their flags. The +set+ parameter # is a number, an array of numbers, or a Range object. Each number # is a message sequence number. +attr+ is the name of a data item # to store: 'FLAGS' will replace the message's flag list # with the provided one, '+FLAGS' will add the provided flags, # and '-FLAGS' will remove them. +flags+ is a list of flags. # # The return value is an array of Net::IMAP::FetchData. For example: # # p imap.store(6..8, "+FLAGS", [:Deleted]) # #=> [#[:Seen, :Deleted]}>, \\ # #[:Seen, :Deleted]}>, \\ # #[:Seen, :Deleted]}>] def store(set, attr, flags) return store_internal("STORE", set, attr, flags) end # Similar to #store(), but +set+ contains unique identifiers. def uid_store(set, attr, flags) return store_internal("UID STORE", set, attr, flags) end # Sends a COPY command to copy the specified message(s) to the end # of the specified destination +mailbox+. The +set+ parameter is # a number, an array of numbers, or a Range object. The number is # a message sequence number. def copy(set, mailbox) copy_internal("COPY", set, mailbox) end # Similar to #copy(), but +set+ contains unique identifiers. def uid_copy(set, mailbox) copy_internal("UID COPY", set, mailbox) end # Sends a SORT command to sort messages in the mailbox. # Returns an array of message sequence numbers. For example: # # p imap.sort(["FROM"], ["ALL"], "US-ASCII") # #=> [1, 2, 3, 5, 6, 7, 8, 4, 9] # p imap.sort(["DATE"], ["SUBJECT", "hello"], "US-ASCII") # #=> [6, 7, 8, 1] # # See [SORT-THREAD-EXT] for more details. def sort(sort_keys, search_keys, charset) return sort_internal("SORT", sort_keys, search_keys, charset) end # Similar to #sort(), but returns an array of unique identifiers. def uid_sort(sort_keys, search_keys, charset) return sort_internal("UID SORT", sort_keys, search_keys, charset) end # Adds a response handler. For example, to detect when # the server sends a new EXISTS response (which normally # indicates new messages being added to the mailbox), # add the following handler after selecting the # mailbox: # # imap.add_response_handler { |resp| # if resp.kind_of?(Net::IMAP::UntaggedResponse) and resp.name == "EXISTS" # puts "Mailbox now has #{resp.data} messages" # end # } # def add_response_handler(handler = Proc.new) @response_handlers.push(handler) end # Removes the response handler. def remove_response_handler(handler) @response_handlers.delete(handler) end # Similar to #search(), but returns message sequence numbers in threaded # format, as a Net::IMAP::ThreadMember tree. The supported algorithms # are: # # ORDEREDSUBJECT:: split into single-level threads according to subject, # ordered by date. # REFERENCES:: split into threads by parent/child relationships determined # by which message is a reply to which. # # Unlike #search(), +charset+ is a required argument. US-ASCII # and UTF-8 are sample values. # # See [SORT-THREAD-EXT] for more details. def thread(algorithm, search_keys, charset) return thread_internal("THREAD", algorithm, search_keys, charset) end # Similar to #thread(), but returns unique identifiers instead of # message sequence numbers. def uid_thread(algorithm, search_keys, charset) return thread_internal("UID THREAD", algorithm, search_keys, charset) end # Sends an IDLE command that waits for notifications of new or expunged # messages. Yields responses from the server during the IDLE. # # Use #idle_done() to leave IDLE. def idle(&response_handler) raise LocalJumpError, "no block given" unless response_handler response = nil synchronize do tag = Thread.current[:net_imap_tag] = generate_tag put_string("#{tag} IDLE#{CRLF}") begin add_response_handler(response_handler) @idle_done_cond = new_cond @idle_done_cond.wait @idle_done_cond = nil if @receiver_thread_terminating raise Net::IMAP::Error, "connection closed" end ensure unless @receiver_thread_terminating remove_response_handler(response_handler) put_string("DONE#{CRLF}") response = get_tagged_response(tag, "IDLE") end end end return response end # Leaves IDLE. def idle_done synchronize do if @idle_done_cond.nil? raise Net::IMAP::Error, "not during IDLE" end @idle_done_cond.signal end end # Decode a string from modified UTF-7 format to UTF-8. # # UTF-7 is a 7-bit encoding of Unicode [UTF7]. IMAP uses a # slightly modified version of this to encode mailbox names # containing non-ASCII characters; see [IMAP] section 5.1.3. # # Net::IMAP does _not_ automatically encode and decode # mailbox names to and from UTF-7. def self.decode_utf7(s) return s.gsub(/&([^-]+)?-/n) { if $1 ($1.tr(",", "/") + "===").unpack("m")[0].encode(Encoding::UTF_8, Encoding::UTF_16BE) else "&" end } end # Encode a string from UTF-8 format to modified UTF-7. def self.encode_utf7(s) return s.gsub(/(&)|[^\x20-\x7e]+/) { if $1 "&-" else base64 = [$&.encode(Encoding::UTF_16BE)].pack("m") "&" + base64.delete("=\n").tr("/", ",") + "-" end }.force_encoding("ASCII-8BIT") end # Formats +time+ as an IMAP-style date. def self.format_date(time) return time.strftime('%d-%b-%Y') end # Formats +time+ as an IMAP-style date-time. def self.format_datetime(time) return time.strftime('%d-%b-%Y %H:%M %z') end private CRLF = "\r\n" # :nodoc: PORT = 143 # :nodoc: SSL_PORT = 993 # :nodoc: @@debug = false @@authenticators = {} @@max_flag_count = 10000 # :call-seq: # Net::IMAP.new(host, options = {}) # # Creates a new Net::IMAP object and connects it to the specified # +host+. # # +options+ is an option hash, each key of which is a symbol. # # The available options are: # # port:: Port number (default value is 143 for imap, or 993 for imaps) # ssl:: If options[:ssl] is true, then an attempt will be made # to use SSL (now TLS) to connect to the server. For this to work # OpenSSL [OSSL] and the Ruby OpenSSL [RSSL] extensions need to # be installed. # If options[:ssl] is a hash, it's passed to # OpenSSL::SSL::SSLContext#set_params as parameters. # # The most common errors are: # # Errno::ECONNREFUSED:: Connection refused by +host+ or an intervening # firewall. # Errno::ETIMEDOUT:: Connection timed out (possibly due to packets # being dropped by an intervening firewall). # Errno::ENETUNREACH:: There is no route to that network. # SocketError:: Hostname not known or other socket error. # Net::IMAP::ByeResponseError:: The connected to the host was successful, but # it immediately said goodbye. def initialize(host, port_or_options = {}, usessl = false, certs = nil, verify = true) super() @host = host begin options = port_or_options.to_hash rescue NoMethodError # for backward compatibility options = {} options[:port] = port_or_options if usessl options[:ssl] = create_ssl_params(certs, verify) end end @port = options[:port] || (options[:ssl] ? SSL_PORT : PORT) @tag_prefix = "RUBY" @tagno = 0 @parser = ResponseParser.new @sock = TCPSocket.open(@host, @port) begin if options[:ssl] start_tls_session(options[:ssl]) @usessl = true else @usessl = false end @responses = Hash.new([].freeze) @tagged_responses = {} @response_handlers = [] @tagged_response_arrival = new_cond @continuation_request_arrival = new_cond @idle_done_cond = nil @logout_command_tag = nil @debug_output_bol = true @exception = nil @greeting = get_response if @greeting.nil? raise Error, "connection closed" end if @greeting.name == "BYE" raise ByeResponseError, @greeting end @client_thread = Thread.current @receiver_thread = Thread.start { begin receive_responses rescue Exception end } @receiver_thread_terminating = false rescue Exception @sock.close raise end end def receive_responses connection_closed = false until connection_closed synchronize do @exception = nil end begin resp = get_response rescue Exception => e synchronize do @sock.close @exception = e end break end unless resp synchronize do @exception = EOFError.new("end of file reached") end break end begin synchronize do case resp when TaggedResponse @tagged_responses[resp.tag] = resp @tagged_response_arrival.broadcast if resp.tag == @logout_command_tag return end when UntaggedResponse record_response(resp.name, resp.data) if resp.data.instance_of?(ResponseText) && (code = resp.data.code) record_response(code.name, code.data) end if resp.name == "BYE" && @logout_command_tag.nil? @sock.close @exception = ByeResponseError.new(resp) connection_closed = true end when ContinuationRequest @continuation_request_arrival.signal end @response_handlers.each do |handler| handler.call(resp) end end rescue Exception => e @exception = e synchronize do @tagged_response_arrival.broadcast @continuation_request_arrival.broadcast end end end synchronize do @receiver_thread_terminating = true @tagged_response_arrival.broadcast @continuation_request_arrival.broadcast if @idle_done_cond @idle_done_cond.signal end end end def get_tagged_response(tag, cmd) until @tagged_responses.key?(tag) raise @exception if @exception @tagged_response_arrival.wait end resp = @tagged_responses.delete(tag) case resp.name when /\A(?:NO)\z/ni raise NoResponseError, resp when /\A(?:BAD)\z/ni raise BadResponseError, resp else return resp end end def get_response buff = "" while true s = @sock.gets(CRLF) break unless s buff.concat(s) if /\{(\d+)\}\r\n/n =~ s s = @sock.read($1.to_i) buff.concat(s) else break end end return nil if buff.length == 0 if @@debug $stderr.print(buff.gsub(/^/n, "S: ")) end return @parser.parse(buff) end def record_response(name, data) unless @responses.has_key?(name) @responses[name] = [] end @responses[name].push(data) end def send_command(cmd, *args, &block) synchronize do args.each do |i| validate_data(i) end tag = generate_tag put_string(tag + " " + cmd) args.each do |i| put_string(" ") send_data(i) end put_string(CRLF) if cmd == "LOGOUT" @logout_command_tag = tag end if block add_response_handler(block) end begin return get_tagged_response(tag, cmd) ensure if block remove_response_handler(block) end end end end def generate_tag @tagno += 1 return format("%s%04d", @tag_prefix, @tagno) end def put_string(str) @sock.print(str) if @@debug if @debug_output_bol $stderr.print("C: ") end $stderr.print(str.gsub(/\n(?!\z)/n, "\nC: ")) if /\r\n\z/n.match(str) @debug_output_bol = true else @debug_output_bol = false end end end def validate_data(data) case data when nil when String when Integer NumValidator.ensure_number(data) when Array data.each do |i| validate_data(i) end when Time when Symbol else data.validate end end def send_data(data) case data when nil put_string("NIL") when String send_string_data(data) when Integer send_number_data(data) when Array send_list_data(data) when Time send_time_data(data) when Symbol send_symbol_data(data) else data.send_data(self) end end def send_string_data(str) case str when "" put_string('""') when /[\x80-\xff\r\n]/n # literal send_literal(str) when /[(){ \x00-\x1f\x7f%*"\\]/n # quoted string send_quoted_string(str) else put_string(str) end end def send_quoted_string(str) put_string('"' + str.gsub(/["\\]/n, "\\\\\\&") + '"') end def send_literal(str) put_string("{" + str.bytesize.to_s + "}" + CRLF) @continuation_request_arrival.wait raise @exception if @exception put_string(str) end def send_number_data(num) put_string(num.to_s) end def send_list_data(list) put_string("(") first = true list.each do |i| if first first = false else put_string(" ") end send_data(i) end put_string(")") end DATE_MONTH = %w(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec) def send_time_data(time) t = time.dup.gmtime s = format('"%2d-%3s-%4d %02d:%02d:%02d +0000"', t.day, DATE_MONTH[t.month - 1], t.year, t.hour, t.min, t.sec) put_string(s) end def send_symbol_data(symbol) put_string("\\" + symbol.to_s) end def search_internal(cmd, keys, charset) if keys.instance_of?(String) keys = [RawData.new(keys)] else normalize_searching_criteria(keys) end synchronize do if charset send_command(cmd, "CHARSET", charset, *keys) else send_command(cmd, *keys) end return @responses.delete("SEARCH")[-1] end end def fetch_internal(cmd, set, attr) case attr when String then attr = RawData.new(attr) when Array then attr = attr.map { |arg| arg.is_a?(String) ? RawData.new(arg) : arg } end synchronize do @responses.delete("FETCH") send_command(cmd, MessageSet.new(set), attr) return @responses.delete("FETCH") end end def store_internal(cmd, set, attr, flags) if attr.instance_of?(String) attr = RawData.new(attr) end synchronize do @responses.delete("FETCH") send_command(cmd, MessageSet.new(set), attr, flags) return @responses.delete("FETCH") end end def copy_internal(cmd, set, mailbox) send_command(cmd, MessageSet.new(set), mailbox) end def sort_internal(cmd, sort_keys, search_keys, charset) if search_keys.instance_of?(String) search_keys = [RawData.new(search_keys)] else normalize_searching_criteria(search_keys) end normalize_searching_criteria(search_keys) synchronize do send_command(cmd, sort_keys, charset, *search_keys) return @responses.delete("SORT")[-1] end end def thread_internal(cmd, algorithm, search_keys, charset) if search_keys.instance_of?(String) search_keys = [RawData.new(search_keys)] else normalize_searching_criteria(search_keys) end normalize_searching_criteria(search_keys) send_command(cmd, algorithm, charset, *search_keys) return @responses.delete("THREAD")[-1] end def normalize_searching_criteria(keys) keys.collect! do |i| case i when -1, Range, Array MessageSet.new(i) else i end end end def create_ssl_params(certs = nil, verify = true) params = {} if certs if File.file?(certs) params[:ca_file] = certs elsif File.directory?(certs) params[:ca_path] = certs end end if verify params[:verify_mode] = VERIFY_PEER else params[:verify_mode] = VERIFY_NONE end return params end def start_tls_session(params = {}) unless defined?(OpenSSL::SSL) raise "SSL extension not installed" end if @sock.kind_of?(OpenSSL::SSL::SSLSocket) raise RuntimeError, "already using SSL" end begin params = params.to_hash rescue NoMethodError params = {} end context = SSLContext.new context.set_params(params) if defined?(VerifyCallbackProc) context.verify_callback = VerifyCallbackProc end @sock = SSLSocket.new(@sock, context) @sock.sync_close = true @sock.connect if context.verify_mode != VERIFY_NONE @sock.post_connection_check(@host) end end class RawData # :nodoc: def send_data(imap) imap.send(:put_string, @data) end def validate end private def initialize(data) @data = data end end class Atom # :nodoc: def send_data(imap) imap.send(:put_string, @data) end def validate end private def initialize(data) @data = data end end class QuotedString # :nodoc: def send_data(imap) imap.send(:send_quoted_string, @data) end def validate end private def initialize(data) @data = data end end class Literal # :nodoc: def send_data(imap) imap.send(:send_literal, @data) end def validate end private def initialize(data) @data = data end end class MessageSet # :nodoc: def send_data(imap) imap.send(:put_string, format_internal(@data)) end def validate validate_internal(@data) end private def initialize(data) @data = data end def format_internal(data) case data when "*" return data when Integer if data == -1 return "*" else return data.to_s end when Range return format_internal(data.first) + ":" + format_internal(data.last) when Array return data.collect {|i| format_internal(i)}.join(",") when ThreadMember return data.seqno.to_s + ":" + data.children.collect {|i| format_internal(i).join(",")} end end def validate_internal(data) case data when "*" when Integer NumValidator.ensure_nz_number(data) when Range when Array data.each do |i| validate_internal(i) end when ThreadMember data.children.each do |i| validate_internal(i) end else raise DataFormatError, data.inspect end end end # Common validators of number and nz_number types module NumValidator # :nodoc class << self # Check is passed argument valid 'number' in RFC 3501 terminology def valid_number?(num) # [RFC 3501] # number = 1*DIGIT # ; Unsigned 32-bit integer # ; (0 <= n < 4,294,967,296) num >= 0 && num < 4294967296 end # Check is passed argument valid 'nz_number' in RFC 3501 terminology def valid_nz_number?(num) # [RFC 3501] # nz-number = digit-nz *DIGIT # ; Non-zero unsigned 32-bit integer # ; (0 < n < 4,294,967,296) num != 0 && valid_number?(num) end # Ensure argument is 'number' or raise DataFormatError def ensure_number(num) return if valid_number?(num) msg = "number must be unsigned 32-bit integer: #{num}" raise DataFormatError, msg end # Ensure argument is 'nz_number' or raise DataFormatError def ensure_nz_number(num) return if valid_nz_number?(num) msg = "nz_number must be non-zero unsigned 32-bit integer: #{num}" raise DataFormatError, msg end end end # Net::IMAP::ContinuationRequest represents command continuation requests. # # The command continuation request response is indicated by a "+" token # instead of a tag. This form of response indicates that the server is # ready to accept the continuation of a command from the client. The # remainder of this response is a line of text. # # continue_req ::= "+" SPACE (resp_text / base64) # # ==== Fields: # # data:: Returns the data (Net::IMAP::ResponseText). # # raw_data:: Returns the raw data string. ContinuationRequest = Struct.new(:data, :raw_data) # Net::IMAP::UntaggedResponse represents untagged responses. # # Data transmitted by the server to the client and status responses # that do not indicate command completion are prefixed with the token # "*", and are called untagged responses. # # response_data ::= "*" SPACE (resp_cond_state / resp_cond_bye / # mailbox_data / message_data / capability_data) # # ==== Fields: # # name:: Returns the name, such as "FLAGS", "LIST", or "FETCH". # # data:: Returns the data such as an array of flag symbols, # a (()) object. # # raw_data:: Returns the raw data string. UntaggedResponse = Struct.new(:name, :data, :raw_data) # Net::IMAP::TaggedResponse represents tagged responses. # # The server completion result response indicates the success or # failure of the operation. It is tagged with the same tag as the # client command which began the operation. # # response_tagged ::= tag SPACE resp_cond_state CRLF # # tag ::= 1* # # resp_cond_state ::= ("OK" / "NO" / "BAD") SPACE resp_text # # ==== Fields: # # tag:: Returns the tag. # # name:: Returns the name, one of "OK", "NO", or "BAD". # # data:: Returns the data. See (()). # # raw_data:: Returns the raw data string. # TaggedResponse = Struct.new(:tag, :name, :data, :raw_data) # Net::IMAP::ResponseText represents texts of responses. # The text may be prefixed by the response code. # # resp_text ::= ["[" resp_text_code "]" SPACE] (text_mime2 / text) # ;; text SHOULD NOT begin with "[" or "=" # # ==== Fields: # # code:: Returns the response code. See (()). # # text:: Returns the text. # ResponseText = Struct.new(:code, :text) # Net::IMAP::ResponseCode represents response codes. # # resp_text_code ::= "ALERT" / "PARSE" / # "PERMANENTFLAGS" SPACE "(" #(flag / "\*") ")" / # "READ-ONLY" / "READ-WRITE" / "TRYCREATE" / # "UIDVALIDITY" SPACE nz_number / # "UNSEEN" SPACE nz_number / # atom [SPACE 1*] # # ==== Fields: # # name:: Returns the name, such as "ALERT", "PERMANENTFLAGS", or "UIDVALIDITY". # # data:: Returns the data, if it exists. # ResponseCode = Struct.new(:name, :data) # Net::IMAP::MailboxList represents contents of the LIST response. # # mailbox_list ::= "(" #("\Marked" / "\Noinferiors" / # "\Noselect" / "\Unmarked" / flag_extension) ")" # SPACE (<"> QUOTED_CHAR <"> / nil) SPACE mailbox # # ==== Fields: # # attr:: Returns the name attributes. Each name attribute is a symbol # capitalized by String#capitalize, such as :Noselect (not :NoSelect). # # delim:: Returns the hierarchy delimiter. # # name:: Returns the mailbox name. # MailboxList = Struct.new(:attr, :delim, :name) # Net::IMAP::MailboxQuota represents contents of GETQUOTA response. # This object can also be a response to GETQUOTAROOT. In the syntax # specification below, the delimiter used with the "#" construct is a # single space (SPACE). # # quota_list ::= "(" #quota_resource ")" # # quota_resource ::= atom SPACE number SPACE number # # quota_response ::= "QUOTA" SPACE astring SPACE quota_list # # ==== Fields: # # mailbox:: The mailbox with the associated quota. # # usage:: Current storage usage of the mailbox. # # quota:: Quota limit imposed on the mailbox. # MailboxQuota = Struct.new(:mailbox, :usage, :quota) # Net::IMAP::MailboxQuotaRoot represents part of the GETQUOTAROOT # response. (GETQUOTAROOT can also return Net::IMAP::MailboxQuota.) # # quotaroot_response ::= "QUOTAROOT" SPACE astring *(SPACE astring) # # ==== Fields: # # mailbox:: The mailbox with the associated quota. # # quotaroots:: Zero or more quotaroots that affect the quota on the # specified mailbox. # MailboxQuotaRoot = Struct.new(:mailbox, :quotaroots) # Net::IMAP::MailboxACLItem represents the response from GETACL. # # acl_data ::= "ACL" SPACE mailbox *(SPACE identifier SPACE rights) # # identifier ::= astring # # rights ::= astring # # ==== Fields: # # user:: Login name that has certain rights to the mailbox # that was specified with the getacl command. # # rights:: The access rights the indicated user has to the # mailbox. # MailboxACLItem = Struct.new(:user, :rights, :mailbox) # Net::IMAP::StatusData represents the contents of the STATUS response. # # ==== Fields: # # mailbox:: Returns the mailbox name. # # attr:: Returns a hash. Each key is one of "MESSAGES", "RECENT", "UIDNEXT", # "UIDVALIDITY", "UNSEEN". Each value is a number. # StatusData = Struct.new(:mailbox, :attr) # Net::IMAP::FetchData represents the contents of the FETCH response. # # ==== Fields: # # seqno:: Returns the message sequence number. # (Note: not the unique identifier, even for the UID command response.) # # attr:: Returns a hash. Each key is a data item name, and each value is # its value. # # The current data items are: # # [BODY] # A form of BODYSTRUCTURE without extension data. # [BODY[
]<>] # A string expressing the body contents of the specified section. # [BODYSTRUCTURE] # An object that describes the [MIME-IMB] body structure of a message. # See Net::IMAP::BodyTypeBasic, Net::IMAP::BodyTypeText, # Net::IMAP::BodyTypeMessage, Net::IMAP::BodyTypeMultipart. # [ENVELOPE] # A Net::IMAP::Envelope object that describes the envelope # structure of a message. # [FLAGS] # A array of flag symbols that are set for this message. Flag symbols # are capitalized by String#capitalize. # [INTERNALDATE] # A string representing the internal date of the message. # [RFC822] # Equivalent to BODY[]. # [RFC822.HEADER] # Equivalent to BODY.PEEK[HEADER]. # [RFC822.SIZE] # A number expressing the [RFC-822] size of the message. # [RFC822.TEXT] # Equivalent to BODY[TEXT]. # [UID] # A number expressing the unique identifier of the message. # FetchData = Struct.new(:seqno, :attr) # Net::IMAP::Envelope represents envelope structures of messages. # # ==== Fields: # # date:: Returns a string that represents the date. # # subject:: Returns a string that represents the subject. # # from:: Returns an array of Net::IMAP::Address that represents the from. # # sender:: Returns an array of Net::IMAP::Address that represents the sender. # # reply_to:: Returns an array of Net::IMAP::Address that represents the reply-to. # # to:: Returns an array of Net::IMAP::Address that represents the to. # # cc:: Returns an array of Net::IMAP::Address that represents the cc. # # bcc:: Returns an array of Net::IMAP::Address that represents the bcc. # # in_reply_to:: Returns a string that represents the in-reply-to. # # message_id:: Returns a string that represents the message-id. # Envelope = Struct.new(:date, :subject, :from, :sender, :reply_to, :to, :cc, :bcc, :in_reply_to, :message_id) # # Net::IMAP::Address represents electronic mail addresses. # # ==== Fields: # # name:: Returns the phrase from [RFC-822] mailbox. # # route:: Returns the route from [RFC-822] route-addr. # # mailbox:: nil indicates end of [RFC-822] group. # If non-nil and host is nil, returns [RFC-822] group name. # Otherwise, returns [RFC-822] local-part. # # host:: nil indicates [RFC-822] group syntax. # Otherwise, returns [RFC-822] domain name. # Address = Struct.new(:name, :route, :mailbox, :host) # # Net::IMAP::ContentDisposition represents Content-Disposition fields. # # ==== Fields: # # dsp_type:: Returns the disposition type. # # param:: Returns a hash that represents parameters of the Content-Disposition # field. # ContentDisposition = Struct.new(:dsp_type, :param) # Net::IMAP::ThreadMember represents a thread-node returned # by Net::IMAP#thread. # # ==== Fields: # # seqno:: The sequence number of this message. # # children:: An array of Net::IMAP::ThreadMember objects for mail # items that are children of this in the thread. # ThreadMember = Struct.new(:seqno, :children) # Net::IMAP::BodyTypeBasic represents basic body structures of messages. # # ==== Fields: # # media_type:: Returns the content media type name as defined in [MIME-IMB]. # # subtype:: Returns the content subtype name as defined in [MIME-IMB]. # # param:: Returns a hash that represents parameters as defined in [MIME-IMB]. # # content_id:: Returns a string giving the content id as defined in [MIME-IMB]. # # description:: Returns a string giving the content description as defined in # [MIME-IMB]. # # encoding:: Returns a string giving the content transfer encoding as defined in # [MIME-IMB]. # # size:: Returns a number giving the size of the body in octets. # # md5:: Returns a string giving the body MD5 value as defined in [MD5]. # # disposition:: Returns a Net::IMAP::ContentDisposition object giving # the content disposition. # # language:: Returns a string or an array of strings giving the body # language value as defined in [LANGUAGE-TAGS]. # # extension:: Returns extension data. # # multipart?:: Returns false. # class BodyTypeBasic < Struct.new(:media_type, :subtype, :param, :content_id, :description, :encoding, :size, :md5, :disposition, :language, :extension) def multipart? return false end # Obsolete: use +subtype+ instead. Calling this will # generate a warning message to +stderr+, then return # the value of +subtype+. def media_subtype $stderr.printf("warning: media_subtype is obsolete.\n") $stderr.printf(" use subtype instead.\n") return subtype end end # Net::IMAP::BodyTypeText represents TEXT body structures of messages. # # ==== Fields: # # lines:: Returns the size of the body in text lines. # # And Net::IMAP::BodyTypeText has all fields of Net::IMAP::BodyTypeBasic. # class BodyTypeText < Struct.new(:media_type, :subtype, :param, :content_id, :description, :encoding, :size, :lines, :md5, :disposition, :language, :extension) def multipart? return false end # Obsolete: use +subtype+ instead. Calling this will # generate a warning message to +stderr+, then return # the value of +subtype+. def media_subtype $stderr.printf("warning: media_subtype is obsolete.\n") $stderr.printf(" use subtype instead.\n") return subtype end end # Net::IMAP::BodyTypeMessage represents MESSAGE/RFC822 body structures of messages. # # ==== Fields: # # envelope:: Returns a Net::IMAP::Envelope giving the envelope structure. # # body:: Returns an object giving the body structure. # # And Net::IMAP::BodyTypeMessage has all methods of Net::IMAP::BodyTypeText. # class BodyTypeMessage < Struct.new(:media_type, :subtype, :param, :content_id, :description, :encoding, :size, :envelope, :body, :lines, :md5, :disposition, :language, :extension) def multipart? return false end # Obsolete: use +subtype+ instead. Calling this will # generate a warning message to +stderr+, then return # the value of +subtype+. def media_subtype $stderr.printf("warning: media_subtype is obsolete.\n") $stderr.printf(" use subtype instead.\n") return subtype end end # Net::IMAP::BodyTypeAttachment represents attachment body structures # of messages. # # ==== Fields: # # media_type:: Returns the content media type name. # # subtype:: Returns +nil+. # # param:: Returns a hash that represents parameters. # # multipart?:: Returns false. # class BodyTypeAttachment < Struct.new(:media_type, :subtype, :param) def multipart? return false end end # Net::IMAP::BodyTypeMultipart represents multipart body structures # of messages. # # ==== Fields: # # media_type:: Returns the content media type name as defined in [MIME-IMB]. # # subtype:: Returns the content subtype name as defined in [MIME-IMB]. # # parts:: Returns multiple parts. # # param:: Returns a hash that represents parameters as defined in [MIME-IMB]. # # disposition:: Returns a Net::IMAP::ContentDisposition object giving # the content disposition. # # language:: Returns a string or an array of strings giving the body # language value as defined in [LANGUAGE-TAGS]. # # extension:: Returns extension data. # # multipart?:: Returns true. # class BodyTypeMultipart < Struct.new(:media_type, :subtype, :parts, :param, :disposition, :language, :extension) def multipart? return true end # Obsolete: use +subtype+ instead. Calling this will # generate a warning message to +stderr+, then return # the value of +subtype+. def media_subtype $stderr.printf("warning: media_subtype is obsolete.\n") $stderr.printf(" use subtype instead.\n") return subtype end end class BodyTypeExtension < Struct.new(:media_type, :subtype, :params, :content_id, :description, :encoding, :size) def multipart? return false end end class ResponseParser # :nodoc: def initialize @str = nil @pos = nil @lex_state = nil @token = nil @flag_symbols = {} end def parse(str) @str = str @pos = 0 @lex_state = EXPR_BEG @token = nil return response end private EXPR_BEG = :EXPR_BEG EXPR_DATA = :EXPR_DATA EXPR_TEXT = :EXPR_TEXT EXPR_RTEXT = :EXPR_RTEXT EXPR_CTEXT = :EXPR_CTEXT T_SPACE = :SPACE T_NIL = :NIL T_NUMBER = :NUMBER T_ATOM = :ATOM T_QUOTED = :QUOTED T_LPAR = :LPAR T_RPAR = :RPAR T_BSLASH = :BSLASH T_STAR = :STAR T_LBRA = :LBRA T_RBRA = :RBRA T_LITERAL = :LITERAL T_PLUS = :PLUS T_PERCENT = :PERCENT T_CRLF = :CRLF T_EOF = :EOF T_TEXT = :TEXT BEG_REGEXP = /\G(?:\ (?# 1: SPACE )( +)|\ (?# 2: NIL )(NIL)(?=[\x80-\xff(){ \x00-\x1f\x7f%*"\\\[\]+])|\ (?# 3: NUMBER )(\d+)(?=[\x80-\xff(){ \x00-\x1f\x7f%*"\\\[\]+])|\ (?# 4: ATOM )([^\x80-\xff(){ \x00-\x1f\x7f%*"\\\[\]+]+)|\ (?# 5: QUOTED )"((?:[^\x00\r\n"\\]|\\["\\])*)"|\ (?# 6: LPAR )(\()|\ (?# 7: RPAR )(\))|\ (?# 8: BSLASH )(\\)|\ (?# 9: STAR )(\*)|\ (?# 10: LBRA )(\[)|\ (?# 11: RBRA )(\])|\ (?# 12: LITERAL )\{(\d+)\}\r\n|\ (?# 13: PLUS )(\+)|\ (?# 14: PERCENT )(%)|\ (?# 15: CRLF )(\r\n)|\ (?# 16: EOF )(\z))/ni DATA_REGEXP = /\G(?:\ (?# 1: SPACE )( )|\ (?# 2: NIL )(NIL)|\ (?# 3: NUMBER )(\d+)|\ (?# 4: QUOTED )"((?:[^\x00\r\n"\\]|\\["\\])*)"|\ (?# 5: LITERAL )\{(\d+)\}\r\n|\ (?# 6: LPAR )(\()|\ (?# 7: RPAR )(\)))/ni TEXT_REGEXP = /\G(?:\ (?# 1: TEXT )([^\x00\r\n]*))/ni RTEXT_REGEXP = /\G(?:\ (?# 1: LBRA )(\[)|\ (?# 2: TEXT )([^\x00\r\n]*))/ni CTEXT_REGEXP = /\G(?:\ (?# 1: TEXT )([^\x00\r\n\]]*))/ni Token = Struct.new(:symbol, :value) def response token = lookahead case token.symbol when T_PLUS result = continue_req when T_STAR result = response_untagged else result = response_tagged end match(T_CRLF) match(T_EOF) return result end def continue_req match(T_PLUS) match(T_SPACE) return ContinuationRequest.new(resp_text, @str) end def response_untagged match(T_STAR) match(T_SPACE) token = lookahead if token.symbol == T_NUMBER return numeric_response elsif token.symbol == T_ATOM case token.value when /\A(?:OK|NO|BAD|BYE|PREAUTH)\z/ni return response_cond when /\A(?:FLAGS)\z/ni return flags_response when /\A(?:LIST|LSUB|XLIST)\z/ni return list_response when /\A(?:QUOTA)\z/ni return getquota_response when /\A(?:QUOTAROOT)\z/ni return getquotaroot_response when /\A(?:ACL)\z/ni return getacl_response when /\A(?:SEARCH|SORT)\z/ni return search_response when /\A(?:THREAD)\z/ni return thread_response when /\A(?:STATUS)\z/ni return status_response when /\A(?:CAPABILITY)\z/ni return capability_response else return text_response end else parse_error("unexpected token %s", token.symbol) end end def response_tagged tag = atom match(T_SPACE) token = match(T_ATOM) name = token.value.upcase match(T_SPACE) return TaggedResponse.new(tag, name, resp_text, @str) end def response_cond token = match(T_ATOM) name = token.value.upcase match(T_SPACE) return UntaggedResponse.new(name, resp_text, @str) end def numeric_response n = number match(T_SPACE) token = match(T_ATOM) name = token.value.upcase case name when "EXISTS", "RECENT", "EXPUNGE" return UntaggedResponse.new(name, n, @str) when "FETCH" shift_token match(T_SPACE) data = FetchData.new(n, msg_att(n)) return UntaggedResponse.new(name, data, @str) end end def msg_att(n) match(T_LPAR) attr = {} while true token = lookahead case token.symbol when T_RPAR shift_token break when T_SPACE shift_token next end case token.value when /\A(?:ENVELOPE)\z/ni name, val = envelope_data when /\A(?:FLAGS)\z/ni name, val = flags_data when /\A(?:INTERNALDATE)\z/ni name, val = internaldate_data when /\A(?:RFC822(?:\.HEADER|\.TEXT)?)\z/ni name, val = rfc822_text when /\A(?:RFC822\.SIZE)\z/ni name, val = rfc822_size when /\A(?:BODY(?:STRUCTURE)?)\z/ni name, val = body_data when /\A(?:UID)\z/ni name, val = uid_data else parse_error("unknown attribute `%s' for {%d}", token.value, n) end attr[name] = val end return attr end def envelope_data token = match(T_ATOM) name = token.value.upcase match(T_SPACE) return name, envelope end def envelope @lex_state = EXPR_DATA token = lookahead if token.symbol == T_NIL shift_token result = nil else match(T_LPAR) date = nstring match(T_SPACE) subject = nstring match(T_SPACE) from = address_list match(T_SPACE) sender = address_list match(T_SPACE) reply_to = address_list match(T_SPACE) to = address_list match(T_SPACE) cc = address_list match(T_SPACE) bcc = address_list match(T_SPACE) in_reply_to = nstring match(T_SPACE) message_id = nstring match(T_RPAR) result = Envelope.new(date, subject, from, sender, reply_to, to, cc, bcc, in_reply_to, message_id) end @lex_state = EXPR_BEG return result end def flags_data token = match(T_ATOM) name = token.value.upcase match(T_SPACE) return name, flag_list end def internaldate_data token = match(T_ATOM) name = token.value.upcase match(T_SPACE) token = match(T_QUOTED) return name, token.value end def rfc822_text token = match(T_ATOM) name = token.value.upcase token = lookahead if token.symbol == T_LBRA shift_token match(T_RBRA) end match(T_SPACE) return name, nstring end def rfc822_size token = match(T_ATOM) name = token.value.upcase match(T_SPACE) return name, number end def body_data token = match(T_ATOM) name = token.value.upcase token = lookahead if token.symbol == T_SPACE shift_token return name, body end name.concat(section) token = lookahead if token.symbol == T_ATOM name.concat(token.value) shift_token end match(T_SPACE) data = nstring return name, data end def body @lex_state = EXPR_DATA token = lookahead if token.symbol == T_NIL shift_token result = nil else match(T_LPAR) token = lookahead if token.symbol == T_LPAR result = body_type_mpart else result = body_type_1part end match(T_RPAR) end @lex_state = EXPR_BEG return result end def body_type_1part token = lookahead case token.value when /\A(?:TEXT)\z/ni return body_type_text when /\A(?:MESSAGE)\z/ni return body_type_msg when /\A(?:ATTACHMENT)\z/ni return body_type_attachment when /\A(?:MIXED)\z/ni return body_type_mixed else return body_type_basic end end def body_type_basic mtype, msubtype = media_type token = lookahead if token.symbol == T_RPAR return BodyTypeBasic.new(mtype, msubtype) end match(T_SPACE) param, content_id, desc, enc, size = body_fields md5, disposition, language, extension = body_ext_1part return BodyTypeBasic.new(mtype, msubtype, param, content_id, desc, enc, size, md5, disposition, language, extension) end def body_type_text mtype, msubtype = media_type match(T_SPACE) param, content_id, desc, enc, size = body_fields match(T_SPACE) lines = number md5, disposition, language, extension = body_ext_1part return BodyTypeText.new(mtype, msubtype, param, content_id, desc, enc, size, lines, md5, disposition, language, extension) end def body_type_msg mtype, msubtype = media_type match(T_SPACE) param, content_id, desc, enc, size = body_fields token = lookahead if token.symbol == T_RPAR # If this is not message/rfc822, we shouldn't apply the RFC822 # spec to it. We should handle anything other than # message/rfc822 using multipart extension data [rfc3501] (i.e. # the data itself won't be returned, we would have to retrieve it # with BODYSTRUCTURE instead of with BODY # Also, sometimes a message/rfc822 is included as a large # attachment instead of having all of the other details # (e.g. attaching a .eml file to an email) if msubtype == "RFC822" return BodyTypeMessage.new(mtype, msubtype, param, content_id, desc, enc, size, nil, nil, nil, nil, nil, nil, nil) else return BodyTypeExtension.new(mtype, msubtype, param, content_id, desc, enc, size) end end match(T_SPACE) env = envelope match(T_SPACE) b = body match(T_SPACE) lines = number md5, disposition, language, extension = body_ext_1part return BodyTypeMessage.new(mtype, msubtype, param, content_id, desc, enc, size, env, b, lines, md5, disposition, language, extension) end def body_type_attachment mtype = case_insensitive_string match(T_SPACE) param = body_fld_param return BodyTypeAttachment.new(mtype, nil, param) end def body_type_mixed mtype = "MULTIPART" msubtype = case_insensitive_string param, disposition, language, extension = body_ext_mpart return BodyTypeBasic.new(mtype, msubtype, param, nil, nil, nil, nil, nil, disposition, language, extension) end def body_type_mpart parts = [] while true token = lookahead if token.symbol == T_SPACE shift_token break end parts.push(body) end mtype = "MULTIPART" msubtype = case_insensitive_string param, disposition, language, extension = body_ext_mpart return BodyTypeMultipart.new(mtype, msubtype, parts, param, disposition, language, extension) end def media_type mtype = case_insensitive_string token = lookahead if token.symbol != T_SPACE return mtype, nil end match(T_SPACE) msubtype = case_insensitive_string return mtype, msubtype end def body_fields param = body_fld_param match(T_SPACE) content_id = nstring match(T_SPACE) desc = nstring match(T_SPACE) enc = case_insensitive_string match(T_SPACE) size = number return param, content_id, desc, enc, size end def body_fld_param token = lookahead if token.symbol == T_NIL shift_token return nil end match(T_LPAR) param = {} while true token = lookahead case token.symbol when T_RPAR shift_token break when T_SPACE shift_token end name = case_insensitive_string match(T_SPACE) val = string param[name] = val end return param end def body_ext_1part token = lookahead if token.symbol == T_SPACE shift_token else return nil end md5 = nstring token = lookahead if token.symbol == T_SPACE shift_token else return md5 end disposition = body_fld_dsp token = lookahead if token.symbol == T_SPACE shift_token else return md5, disposition end language = body_fld_lang token = lookahead if token.symbol == T_SPACE shift_token else return md5, disposition, language end extension = body_extensions return md5, disposition, language, extension end def body_ext_mpart token = lookahead if token.symbol == T_SPACE shift_token else return nil end param = body_fld_param token = lookahead if token.symbol == T_SPACE shift_token else return param end disposition = body_fld_dsp token = lookahead if token.symbol == T_SPACE shift_token else return param, disposition end language = body_fld_lang token = lookahead if token.symbol == T_SPACE shift_token else return param, disposition, language end extension = body_extensions return param, disposition, language, extension end def body_fld_dsp token = lookahead if token.symbol == T_NIL shift_token return nil end match(T_LPAR) dsp_type = case_insensitive_string match(T_SPACE) param = body_fld_param match(T_RPAR) return ContentDisposition.new(dsp_type, param) end def body_fld_lang token = lookahead if token.symbol == T_LPAR shift_token result = [] while true token = lookahead case token.symbol when T_RPAR shift_token return result when T_SPACE shift_token end result.push(case_insensitive_string) end else lang = nstring if lang return lang.upcase else return lang end end end def body_extensions result = [] while true token = lookahead case token.symbol when T_RPAR return result when T_SPACE shift_token end result.push(body_extension) end end def body_extension token = lookahead case token.symbol when T_LPAR shift_token result = body_extensions match(T_RPAR) return result when T_NUMBER return number else return nstring end end def section str = "" token = match(T_LBRA) str.concat(token.value) token = match(T_ATOM, T_NUMBER, T_RBRA) if token.symbol == T_RBRA str.concat(token.value) return str end str.concat(token.value) token = lookahead if token.symbol == T_SPACE shift_token str.concat(token.value) token = match(T_LPAR) str.concat(token.value) while true token = lookahead case token.symbol when T_RPAR str.concat(token.value) shift_token break when T_SPACE shift_token str.concat(token.value) end str.concat(format_string(astring)) end end token = match(T_RBRA) str.concat(token.value) return str end def format_string(str) case str when "" return '""' when /[\x80-\xff\r\n]/n # literal return "{" + str.bytesize.to_s + "}" + CRLF + str when /[(){ \x00-\x1f\x7f%*"\\]/n # quoted string return '"' + str.gsub(/["\\]/n, "\\\\\\&") + '"' else # atom return str end end def uid_data token = match(T_ATOM) name = token.value.upcase match(T_SPACE) return name, number end def text_response token = match(T_ATOM) name = token.value.upcase match(T_SPACE) @lex_state = EXPR_TEXT token = match(T_TEXT) @lex_state = EXPR_BEG return UntaggedResponse.new(name, token.value) end def flags_response token = match(T_ATOM) name = token.value.upcase match(T_SPACE) return UntaggedResponse.new(name, flag_list, @str) end def list_response token = match(T_ATOM) name = token.value.upcase match(T_SPACE) return UntaggedResponse.new(name, mailbox_list, @str) end def mailbox_list attr = flag_list match(T_SPACE) token = match(T_QUOTED, T_NIL) if token.symbol == T_NIL delim = nil else delim = token.value end match(T_SPACE) name = astring return MailboxList.new(attr, delim, name) end def getquota_response # If quota never established, get back # `NO Quota root does not exist'. # If quota removed, get `()' after the # folder spec with no mention of `STORAGE'. token = match(T_ATOM) name = token.value.upcase match(T_SPACE) mailbox = astring match(T_SPACE) match(T_LPAR) token = lookahead case token.symbol when T_RPAR shift_token data = MailboxQuota.new(mailbox, nil, nil) return UntaggedResponse.new(name, data, @str) when T_ATOM shift_token match(T_SPACE) token = match(T_NUMBER) usage = token.value match(T_SPACE) token = match(T_NUMBER) quota = token.value match(T_RPAR) data = MailboxQuota.new(mailbox, usage, quota) return UntaggedResponse.new(name, data, @str) else parse_error("unexpected token %s", token.symbol) end end def getquotaroot_response # Similar to getquota, but only admin can use getquota. token = match(T_ATOM) name = token.value.upcase match(T_SPACE) mailbox = astring quotaroots = [] while true token = lookahead break unless token.symbol == T_SPACE shift_token quotaroots.push(astring) end data = MailboxQuotaRoot.new(mailbox, quotaroots) return UntaggedResponse.new(name, data, @str) end def getacl_response token = match(T_ATOM) name = token.value.upcase match(T_SPACE) mailbox = astring data = [] token = lookahead if token.symbol == T_SPACE shift_token while true token = lookahead case token.symbol when T_CRLF break when T_SPACE shift_token end user = astring match(T_SPACE) rights = astring data.push(MailboxACLItem.new(user, rights, mailbox)) end end return UntaggedResponse.new(name, data, @str) end def search_response token = match(T_ATOM) name = token.value.upcase token = lookahead if token.symbol == T_SPACE shift_token data = [] while true token = lookahead case token.symbol when T_CRLF break when T_SPACE shift_token when T_NUMBER data.push(number) when T_LPAR # TODO: include the MODSEQ value in a response shift_token match(T_ATOM) match(T_SPACE) match(T_NUMBER) match(T_RPAR) end end else data = [] end return UntaggedResponse.new(name, data, @str) end def thread_response token = match(T_ATOM) name = token.value.upcase token = lookahead if token.symbol == T_SPACE threads = [] while true shift_token token = lookahead case token.symbol when T_LPAR threads << thread_branch(token) when T_CRLF break end end else # no member threads = [] end return UntaggedResponse.new(name, threads, @str) end def thread_branch(token) rootmember = nil lastmember = nil while true shift_token # ignore first T_LPAR token = lookahead case token.symbol when T_NUMBER # new member newmember = ThreadMember.new(number, []) if rootmember.nil? rootmember = newmember else lastmember.children << newmember end lastmember = newmember when T_SPACE # do nothing when T_LPAR if rootmember.nil? # dummy member lastmember = rootmember = ThreadMember.new(nil, []) end lastmember.children << thread_branch(token) when T_RPAR break end end return rootmember end def status_response token = match(T_ATOM) name = token.value.upcase match(T_SPACE) mailbox = astring match(T_SPACE) match(T_LPAR) attr = {} while true token = lookahead case token.symbol when T_RPAR shift_token break when T_SPACE shift_token end token = match(T_ATOM) key = token.value.upcase match(T_SPACE) val = number attr[key] = val end data = StatusData.new(mailbox, attr) return UntaggedResponse.new(name, data, @str) end def capability_response token = match(T_ATOM) name = token.value.upcase match(T_SPACE) data = [] while true token = lookahead case token.symbol when T_CRLF break when T_SPACE shift_token next end data.push(atom.upcase) end return UntaggedResponse.new(name, data, @str) end def resp_text @lex_state = EXPR_RTEXT token = lookahead if token.symbol == T_LBRA code = resp_text_code else code = nil end token = match(T_TEXT) @lex_state = EXPR_BEG return ResponseText.new(code, token.value) end def resp_text_code @lex_state = EXPR_BEG match(T_LBRA) token = match(T_ATOM) name = token.value.upcase case name when /\A(?:ALERT|PARSE|READ-ONLY|READ-WRITE|TRYCREATE|NOMODSEQ)\z/n result = ResponseCode.new(name, nil) when /\A(?:PERMANENTFLAGS)\z/n match(T_SPACE) result = ResponseCode.new(name, flag_list) when /\A(?:UIDVALIDITY|UIDNEXT|UNSEEN)\z/n match(T_SPACE) result = ResponseCode.new(name, number) else token = lookahead if token.symbol == T_SPACE shift_token @lex_state = EXPR_CTEXT token = match(T_TEXT) @lex_state = EXPR_BEG result = ResponseCode.new(name, token.value) else result = ResponseCode.new(name, nil) end end match(T_RBRA) @lex_state = EXPR_RTEXT return result end def address_list token = lookahead if token.symbol == T_NIL shift_token return nil else result = [] match(T_LPAR) while true token = lookahead case token.symbol when T_RPAR shift_token break when T_SPACE shift_token end result.push(address) end return result end end ADDRESS_REGEXP = /\G\ (?# 1: NAME )(?:NIL|"((?:[^\x80-\xff\x00\r\n"\\]|\\["\\])*)") \ (?# 2: ROUTE )(?:NIL|"((?:[^\x80-\xff\x00\r\n"\\]|\\["\\])*)") \ (?# 3: MAILBOX )(?:NIL|"((?:[^\x80-\xff\x00\r\n"\\]|\\["\\])*)") \ (?# 4: HOST )(?:NIL|"((?:[^\x80-\xff\x00\r\n"\\]|\\["\\])*)")\ \)/ni def address match(T_LPAR) if @str.index(ADDRESS_REGEXP, @pos) # address does not include literal. @pos = $~.end(0) name = $1 route = $2 mailbox = $3 host = $4 for s in [name, route, mailbox, host] if s s.gsub!(/\\(["\\])/n, "\\1") end end else name = nstring match(T_SPACE) route = nstring match(T_SPACE) mailbox = nstring match(T_SPACE) host = nstring match(T_RPAR) end return Address.new(name, route, mailbox, host) end FLAG_REGEXP = /\ (?# FLAG )\\([^\x80-\xff(){ \x00-\x1f\x7f%"\\]+)|\ (?# ATOM )([^\x80-\xff(){ \x00-\x1f\x7f%*"\\]+)/n def flag_list if @str.index(/\(([^)]*)\)/ni, @pos) @pos = $~.end(0) return $1.scan(FLAG_REGEXP).collect { |flag, atom| if atom atom else symbol = flag.capitalize.untaint.intern @flag_symbols[symbol] = true if @flag_symbols.length > IMAP.max_flag_count raise FlagCountError, "number of flag symbols exceeded" end symbol end } else parse_error("invalid flag list") end end def nstring token = lookahead if token.symbol == T_NIL shift_token return nil else return string end end def astring token = lookahead if string_token?(token) return string else return atom end end def string token = lookahead if token.symbol == T_NIL shift_token return nil end token = match(T_QUOTED, T_LITERAL) return token.value end STRING_TOKENS = [T_QUOTED, T_LITERAL, T_NIL] def string_token?(token) return STRING_TOKENS.include?(token.symbol) end def case_insensitive_string token = lookahead if token.symbol == T_NIL shift_token return nil end token = match(T_QUOTED, T_LITERAL) return token.value.upcase end def atom result = "" while true token = lookahead if atom_token?(token) result.concat(token.value) shift_token else if result.empty? parse_error("unexpected token %s", token.symbol) else return result end end end end ATOM_TOKENS = [ T_ATOM, T_NUMBER, T_NIL, T_LBRA, T_RBRA, T_PLUS ] def atom_token?(token) return ATOM_TOKENS.include?(token.symbol) end def number token = lookahead if token.symbol == T_NIL shift_token return nil end token = match(T_NUMBER) return token.value.to_i end def nil_atom match(T_NIL) return nil end def match(*args) token = lookahead unless args.include?(token.symbol) parse_error('unexpected token %s (expected %s)', token.symbol.id2name, args.collect {|i| i.id2name}.join(" or ")) end shift_token return token end def lookahead unless @token @token = next_token end return @token end def shift_token @token = nil end def next_token case @lex_state when EXPR_BEG if @str.index(BEG_REGEXP, @pos) @pos = $~.end(0) if $1 return Token.new(T_SPACE, $+) elsif $2 return Token.new(T_NIL, $+) elsif $3 return Token.new(T_NUMBER, $+) elsif $4 return Token.new(T_ATOM, $+) elsif $5 return Token.new(T_QUOTED, $+.gsub(/\\(["\\])/n, "\\1")) elsif $6 return Token.new(T_LPAR, $+) elsif $7 return Token.new(T_RPAR, $+) elsif $8 return Token.new(T_BSLASH, $+) elsif $9 return Token.new(T_STAR, $+) elsif $10 return Token.new(T_LBRA, $+) elsif $11 return Token.new(T_RBRA, $+) elsif $12 len = $+.to_i val = @str[@pos, len] @pos += len return Token.new(T_LITERAL, val) elsif $13 return Token.new(T_PLUS, $+) elsif $14 return Token.new(T_PERCENT, $+) elsif $15 return Token.new(T_CRLF, $+) elsif $16 return Token.new(T_EOF, $+) else parse_error("[Net::IMAP BUG] BEG_REGEXP is invalid") end else @str.index(/\S*/n, @pos) parse_error("unknown token - %s", $&.dump) end when EXPR_DATA if @str.index(DATA_REGEXP, @pos) @pos = $~.end(0) if $1 return Token.new(T_SPACE, $+) elsif $2 return Token.new(T_NIL, $+) elsif $3 return Token.new(T_NUMBER, $+) elsif $4 return Token.new(T_QUOTED, $+.gsub(/\\(["\\])/n, "\\1")) elsif $5 len = $+.to_i val = @str[@pos, len] @pos += len return Token.new(T_LITERAL, val) elsif $6 return Token.new(T_LPAR, $+) elsif $7 return Token.new(T_RPAR, $+) else parse_error("[Net::IMAP BUG] DATA_REGEXP is invalid") end else @str.index(/\S*/n, @pos) parse_error("unknown token - %s", $&.dump) end when EXPR_TEXT if @str.index(TEXT_REGEXP, @pos) @pos = $~.end(0) if $1 return Token.new(T_TEXT, $+) else parse_error("[Net::IMAP BUG] TEXT_REGEXP is invalid") end else @str.index(/\S*/n, @pos) parse_error("unknown token - %s", $&.dump) end when EXPR_RTEXT if @str.index(RTEXT_REGEXP, @pos) @pos = $~.end(0) if $1 return Token.new(T_LBRA, $+) elsif $2 return Token.new(T_TEXT, $+) else parse_error("[Net::IMAP BUG] RTEXT_REGEXP is invalid") end else @str.index(/\S*/n, @pos) parse_error("unknown token - %s", $&.dump) end when EXPR_CTEXT if @str.index(CTEXT_REGEXP, @pos) @pos = $~.end(0) if $1 return Token.new(T_TEXT, $+) else parse_error("[Net::IMAP BUG] CTEXT_REGEXP is invalid") end else @str.index(/\S*/n, @pos) #/ parse_error("unknown token - %s", $&.dump) end else parse_error("invalid @lex_state - %s", @lex_state.inspect) end end def parse_error(fmt, *args) if IMAP.debug $stderr.printf("@str: %s\n", @str.dump) $stderr.printf("@pos: %d\n", @pos) $stderr.printf("@lex_state: %s\n", @lex_state) if @token $stderr.printf("@token.symbol: %s\n", @token.symbol) $stderr.printf("@token.value: %s\n", @token.value.inspect) end end raise ResponseParseError, format(fmt, *args) end end # Authenticator for the "LOGIN" authentication type. See # #authenticate(). class LoginAuthenticator def process(data) case @state when STATE_USER @state = STATE_PASSWORD return @user when STATE_PASSWORD return @password end end private STATE_USER = :USER STATE_PASSWORD = :PASSWORD def initialize(user, password) @user = user @password = password @state = STATE_USER end end add_authenticator "LOGIN", LoginAuthenticator # Authenticator for the "PLAIN" authentication type. See # #authenticate(). class PlainAuthenticator def process(data) return "\0#{@user}\0#{@password}" end private def initialize(user, password) @user = user @password = password end end add_authenticator "PLAIN", PlainAuthenticator # Authenticator for the "CRAM-MD5" authentication type. See # #authenticate(). class CramMD5Authenticator def process(challenge) digest = hmac_md5(challenge, @password) return @user + " " + digest end private def initialize(user, password) @user = user @password = password end def hmac_md5(text, key) if key.length > 64 key = Digest::MD5.digest(key) end k_ipad = key + "\0" * (64 - key.length) k_opad = key + "\0" * (64 - key.length) for i in 0..63 k_ipad[i] = (k_ipad[i].ord ^ 0x36).chr k_opad[i] = (k_opad[i].ord ^ 0x5c).chr end digest = Digest::MD5.digest(k_ipad + text) return Digest::MD5.hexdigest(k_opad + digest) end end add_authenticator "CRAM-MD5", CramMD5Authenticator # Authenticator for the "DIGEST-MD5" authentication type. See # #authenticate(). class DigestMD5Authenticator def process(challenge) case @stage when STAGE_ONE @stage = STAGE_TWO sparams = {} c = StringScanner.new(challenge) while c.scan(/(?:\s*,)?\s*(\w+)=("(?:[^\\"]+|\\.)*"|[^,]+)\s*/) k, v = c[1], c[2] if v =~ /^"(.*)"$/ v = $1 if v =~ /,/ v = v.split(',') end end sparams[k] = v end raise DataFormatError, "Bad Challenge: '#{challenge}'" unless c.rest.size == 0 raise Error, "Server does not support auth (qop = #{sparams['qop'].join(',')})" unless sparams['qop'].include?("auth") response = { :nonce => sparams['nonce'], :username => @user, :realm => sparams['realm'], :cnonce => Digest::MD5.hexdigest("%.15f:%.15f:%d" % [Time.now.to_f, rand, Process.pid.to_s]), :'digest-uri' => 'imap/' + sparams['realm'], :qop => 'auth', :maxbuf => 65535, :nc => "%08d" % nc(sparams['nonce']), :charset => sparams['charset'], } response[:authzid] = @authname unless @authname.nil? # now, the real thing a0 = Digest::MD5.digest( [ response.values_at(:username, :realm), @password ].join(':') ) a1 = [ a0, response.values_at(:nonce,:cnonce) ].join(':') a1 << ':' + response[:authzid] unless response[:authzid].nil? a2 = "AUTHENTICATE:" + response[:'digest-uri'] a2 << ":00000000000000000000000000000000" if response[:qop] and response[:qop] =~ /^auth-(?:conf|int)$/ response[:response] = Digest::MD5.hexdigest( [ Digest::MD5.hexdigest(a1), response.values_at(:nonce, :nc, :cnonce, :qop), Digest::MD5.hexdigest(a2) ].join(':') ) return response.keys.map {|key| qdval(key.to_s, response[key]) }.join(',') when STAGE_TWO @stage = nil # if at the second stage, return an empty string if challenge =~ /rspauth=/ return '' else raise ResponseParseError, challenge end else raise ResponseParseError, challenge end end def initialize(user, password, authname = nil) @user, @password, @authname = user, password, authname @nc, @stage = {}, STAGE_ONE end private STAGE_ONE = :stage_one STAGE_TWO = :stage_two def nc(nonce) if @nc.has_key? nonce @nc[nonce] = @nc[nonce] + 1 else @nc[nonce] = 1 end return @nc[nonce] end # some responses need quoting def qdval(k, v) return if k.nil? or v.nil? if %w"username authzid realm nonce cnonce digest-uri qop".include? k v.gsub!(/([\\"])/, "\\\1") return '%s="%s"' % [k, v] else return '%s=%s' % [k, v] end end end add_authenticator "DIGEST-MD5", DigestMD5Authenticator # Superclass of IMAP errors. class Error < StandardError end # Error raised when data is in the incorrect format. class DataFormatError < Error end # Error raised when a response from the server is non-parseable. class ResponseParseError < Error end # Superclass of all errors used to encapsulate "fail" responses # from the server. class ResponseError < Error # The response that caused this error attr_accessor :response def initialize(response) @response = response super @response.data.text end end # Error raised upon a "NO" response from the server, indicating # that the client command could not be completed successfully. class NoResponseError < ResponseError end # Error raised upon a "BAD" response from the server, indicating # that the client command violated the IMAP protocol, or an internal # server failure has occurred. class BadResponseError < ResponseError end # Error raised upon a "BYE" response from the server, indicating # that the client is not being allowed to login, or has been timed # out due to inactivity. class ByeResponseError < ResponseError end # Error raised when too many flags are interned to symbols. class FlagCountError < Error end end end PK!ȁtt2.2.0/net/ftp.rbnu[# # = net/ftp.rb - FTP Client Library # # Written by Shugo Maeda . # # Documentation by Gavin Sinclair, sourced from "Programming Ruby" (Hunt/Thomas) # and "Ruby In a Nutshell" (Matsumoto), used with permission. # # This library is distributed under the terms of the Ruby license. # You can freely distribute/modify this library. # # It is included in the Ruby standard library. # # See the Net::FTP class for an overview. # require "socket" require "monitor" require "net/protocol" module Net # :stopdoc: class FTPError < StandardError; end class FTPReplyError < FTPError; end class FTPTempError < FTPError; end class FTPPermError < FTPError; end class FTPProtoError < FTPError; end class FTPConnectionError < FTPError; end # :startdoc: # # This class implements the File Transfer Protocol. If you have used a # command-line FTP program, and are familiar with the commands, you will be # able to use this class easily. Some extra features are included to take # advantage of Ruby's style and strengths. # # == Example # # require 'net/ftp' # # === Example 1 # # ftp = Net::FTP.new('example.com') # ftp.login # files = ftp.chdir('pub/lang/ruby/contrib') # files = ftp.list('n*') # ftp.getbinaryfile('nif.rb-0.91.gz', 'nif.gz', 1024) # ftp.close # # === Example 2 # # Net::FTP.open('example.com') do |ftp| # ftp.login # files = ftp.chdir('pub/lang/ruby/contrib') # files = ftp.list('n*') # ftp.getbinaryfile('nif.rb-0.91.gz', 'nif.gz', 1024) # end # # == Major Methods # # The following are the methods most likely to be useful to users: # - FTP.open # - #getbinaryfile # - #gettextfile # - #putbinaryfile # - #puttextfile # - #chdir # - #nlst # - #size # - #rename # - #delete # class FTP include MonitorMixin # :stopdoc: FTP_PORT = 21 CRLF = "\r\n" DEFAULT_BLOCKSIZE = BufferedIO::BUFSIZE # :startdoc: # When +true+, transfers are performed in binary mode. Default: +true+. attr_reader :binary # When +true+, the connection is in passive mode. Default: +false+. attr_accessor :passive # When +true+, all traffic to and from the server is written # to +$stdout+. Default: +false+. attr_accessor :debug_mode # Sets or retrieves the +resume+ status, which decides whether incomplete # transfers are resumed or restarted. Default: +false+. attr_accessor :resume # Number of seconds to wait for the connection to open. Any number # may be used, including Floats for fractional seconds. If the FTP # object cannot open a connection in this many seconds, it raises a # Net::OpenTimeout exception. The default value is +nil+. attr_accessor :open_timeout # Number of seconds to wait for one block to be read (via one read(2) # call). Any number may be used, including Floats for fractional # seconds. If the FTP object cannot read data in this many seconds, # it raises a Timeout::Error exception. The default value is 60 seconds. attr_reader :read_timeout # Setter for the read_timeout attribute. def read_timeout=(sec) @sock.read_timeout = sec @read_timeout = sec end # The server's welcome message. attr_reader :welcome # The server's last response code. attr_reader :last_response_code alias lastresp last_response_code # The server's last response. attr_reader :last_response # # A synonym for FTP.new, but with a mandatory host parameter. # # If a block is given, it is passed the +FTP+ object, which will be closed # when the block finishes, or when an exception is raised. # def FTP.open(host, user = nil, passwd = nil, acct = nil) if block_given? ftp = new(host, user, passwd, acct) begin yield ftp ensure ftp.close end else new(host, user, passwd, acct) end end # # Creates and returns a new +FTP+ object. If a +host+ is given, a connection # is made. Additionally, if the +user+ is given, the given user name, # password, and (optionally) account are used to log in. See #login. # def initialize(host = nil, user = nil, passwd = nil, acct = nil) super() @binary = true @passive = false @debug_mode = false @resume = false @sock = NullSocket.new @logged_in = false @open_timeout = nil @read_timeout = 60 if host connect(host) if user login(user, passwd, acct) end end end # A setter to toggle transfers in binary mode. # +newmode+ is either +true+ or +false+ def binary=(newmode) if newmode != @binary @binary = newmode send_type_command if @logged_in end end # Sends a command to destination host, with the current binary sendmode # type. # # If binary mode is +true+, then "TYPE I" (image) is sent, otherwise "TYPE # A" (ascii) is sent. def send_type_command # :nodoc: if @binary voidcmd("TYPE I") else voidcmd("TYPE A") end end private :send_type_command # Toggles transfers in binary mode and yields to a block. # This preserves your current binary send mode, but allows a temporary # transaction with binary sendmode of +newmode+. # # +newmode+ is either +true+ or +false+ def with_binary(newmode) # :nodoc: oldmode = binary self.binary = newmode begin yield ensure self.binary = oldmode end end private :with_binary # Obsolete def return_code # :nodoc: $stderr.puts("warning: Net::FTP#return_code is obsolete and do nothing") return "\n" end # Obsolete def return_code=(s) # :nodoc: $stderr.puts("warning: Net::FTP#return_code= is obsolete and do nothing") end # Constructs a socket with +host+ and +port+. # # If SOCKSSocket is defined and the environment (ENV) defines # SOCKS_SERVER, then a SOCKSSocket is returned, else a TCPSocket is # returned. def open_socket(host, port) # :nodoc: return Timeout.timeout(@open_timeout, Net::OpenTimeout) { if defined? SOCKSSocket and ENV["SOCKS_SERVER"] @passive = true sock = SOCKSSocket.open(host, port) else sock = TCPSocket.open(host, port) end io = BufferedSocket.new(sock) io.read_timeout = @read_timeout io } end private :open_socket # # Establishes an FTP connection to host, optionally overriding the default # port. If the environment variable +SOCKS_SERVER+ is set, sets up the # connection through a SOCKS proxy. Raises an exception (typically # Errno::ECONNREFUSED) if the connection cannot be established. # def connect(host, port = FTP_PORT) if @debug_mode print "connect: ", host, ", ", port, "\n" end synchronize do @sock = open_socket(host, port) voidresp end end # # Set the socket used to connect to the FTP server. # # May raise FTPReplyError if +get_greeting+ is false. def set_socket(sock, get_greeting = true) synchronize do @sock = sock if get_greeting voidresp end end end # If string +s+ includes the PASS command (password), then the contents of # the password are cleaned from the string using "*" def sanitize(s) # :nodoc: if s =~ /^PASS /i return s[0, 5] + "*" * (s.length - 5) else return s end end private :sanitize # Ensures that +line+ has a control return / line feed (CRLF) and writes # it to the socket. def putline(line) # :nodoc: if @debug_mode print "put: ", sanitize(line), "\n" end if /[\r\n]/ =~ line raise ArgumentError, "A line must not contain CR or LF" end line = line + CRLF @sock.write(line) end private :putline # Reads a line from the sock. If EOF, then it will raise EOFError def getline # :nodoc: line = @sock.readline # if get EOF, raise EOFError line.sub!(/(\r\n|\n|\r)\z/n, "") if @debug_mode print "get: ", sanitize(line), "\n" end return line end private :getline # Receive a section of lines until the response code's match. def getmultiline # :nodoc: line = getline buff = line if line[3] == ?- code = line[0, 3] begin line = getline buff << "\n" << line end until line[0, 3] == code and line[3] != ?- end return buff << "\n" end private :getmultiline # Receives a response from the destination host. # # Returns the response code or raises FTPTempError, FTPPermError, or # FTPProtoError def getresp # :nodoc: @last_response = getmultiline @last_response_code = @last_response[0, 3] case @last_response_code when /\A[123]/ return @last_response when /\A4/ raise FTPTempError, @last_response when /\A5/ raise FTPPermError, @last_response else raise FTPProtoError, @last_response end end private :getresp # Receives a response. # # Raises FTPReplyError if the first position of the response code is not # equal 2. def voidresp # :nodoc: resp = getresp if resp[0] != ?2 raise FTPReplyError, resp end end private :voidresp # # Sends a command and returns the response. # def sendcmd(cmd) synchronize do putline(cmd) return getresp end end # # Sends a command and expect a response beginning with '2'. # def voidcmd(cmd) synchronize do putline(cmd) voidresp end end # Constructs and send the appropriate PORT (or EPRT) command def sendport(host, port) # :nodoc: af = (@sock.peeraddr)[0] if af == "AF_INET" cmd = "PORT " + (host.split(".") + port.divmod(256)).join(",") elsif af == "AF_INET6" cmd = sprintf("EPRT |2|%s|%d|", host, port) else raise FTPProtoError, host end voidcmd(cmd) end private :sendport # Constructs a TCPServer socket def makeport # :nodoc: TCPServer.open(@sock.addr[3], 0) end private :makeport # sends the appropriate command to enable a passive connection def makepasv # :nodoc: if @sock.peeraddr[0] == "AF_INET" host, port = parse227(sendcmd("PASV")) else host, port = parse229(sendcmd("EPSV")) # host, port = parse228(sendcmd("LPSV")) end return host, port end private :makepasv # Constructs a connection for transferring data def transfercmd(cmd, rest_offset = nil) # :nodoc: if @passive host, port = makepasv conn = open_socket(host, port) if @resume and rest_offset resp = sendcmd("REST " + rest_offset.to_s) if resp[0] != ?3 raise FTPReplyError, resp end end resp = sendcmd(cmd) # skip 2XX for some ftp servers resp = getresp if resp[0] == ?2 if resp[0] != ?1 raise FTPReplyError, resp end else sock = makeport begin sendport(sock.addr[3], sock.addr[1]) if @resume and rest_offset resp = sendcmd("REST " + rest_offset.to_s) if resp[0] != ?3 raise FTPReplyError, resp end end resp = sendcmd(cmd) # skip 2XX for some ftp servers resp = getresp if resp[0] == ?2 if resp[0] != ?1 raise FTPReplyError, resp end conn = BufferedSocket.new(sock.accept) conn.read_timeout = @read_timeout sock.shutdown(Socket::SHUT_WR) rescue nil sock.read rescue nil ensure sock.close end end return conn end private :transfercmd # # Logs in to the remote host. The session must have been # previously connected. If +user+ is the string "anonymous" and # the +password+ is +nil+, "anonymous@" is used as a password. If # the +acct+ parameter is not +nil+, an FTP ACCT command is sent # following the successful login. Raises an exception on error # (typically Net::FTPPermError). # def login(user = "anonymous", passwd = nil, acct = nil) if user == "anonymous" and passwd == nil passwd = "anonymous@" end resp = "" synchronize do resp = sendcmd('USER ' + user) if resp[0] == ?3 raise FTPReplyError, resp if passwd.nil? resp = sendcmd('PASS ' + passwd) end if resp[0] == ?3 raise FTPReplyError, resp if acct.nil? resp = sendcmd('ACCT ' + acct) end end if resp[0] != ?2 raise FTPReplyError, resp end @welcome = resp send_type_command @logged_in = true end # # Puts the connection into binary (image) mode, issues the given command, # and fetches the data returned, passing it to the associated block in # chunks of +blocksize+ characters. Note that +cmd+ is a server command # (such as "RETR myfile"). # def retrbinary(cmd, blocksize, rest_offset = nil) # :yield: data synchronize do with_binary(true) do begin conn = transfercmd(cmd, rest_offset) loop do data = conn.read(blocksize) break if data == nil yield(data) end conn.shutdown(Socket::SHUT_WR) conn.read_timeout = 1 conn.read ensure conn.close if conn end voidresp end end end # # Puts the connection into ASCII (text) mode, issues the given command, and # passes the resulting data, one line at a time, to the associated block. If # no block is given, prints the lines. Note that +cmd+ is a server command # (such as "RETR myfile"). # def retrlines(cmd) # :yield: line synchronize do with_binary(false) do begin conn = transfercmd(cmd) loop do line = conn.gets break if line == nil yield(line.sub(/\r?\n\z/, ""), !line.match(/\n\z/).nil?) end conn.shutdown(Socket::SHUT_WR) conn.read_timeout = 1 conn.read ensure conn.close if conn end voidresp end end end # # Puts the connection into binary (image) mode, issues the given server-side # command (such as "STOR myfile"), and sends the contents of the file named # +file+ to the server. If the optional block is given, it also passes it # the data, in chunks of +blocksize+ characters. # def storbinary(cmd, file, blocksize, rest_offset = nil) # :yield: data if rest_offset file.seek(rest_offset, IO::SEEK_SET) end synchronize do with_binary(true) do conn = transfercmd(cmd) loop do buf = file.read(blocksize) break if buf == nil conn.write(buf) yield(buf) if block_given? end conn.close voidresp end end rescue Errno::EPIPE # EPIPE, in this case, means that the data connection was unexpectedly # terminated. Rather than just raising EPIPE to the caller, check the # response on the control connection. If getresp doesn't raise a more # appropriate exception, re-raise the original exception. getresp raise end # # Puts the connection into ASCII (text) mode, issues the given server-side # command (such as "STOR myfile"), and sends the contents of the file # named +file+ to the server, one line at a time. If the optional block is # given, it also passes it the lines. # def storlines(cmd, file) # :yield: line synchronize do with_binary(false) do conn = transfercmd(cmd) loop do buf = file.gets break if buf == nil if buf[-2, 2] != CRLF buf = buf.chomp + CRLF end conn.write(buf) yield(buf) if block_given? end conn.close voidresp end end rescue Errno::EPIPE # EPIPE, in this case, means that the data connection was unexpectedly # terminated. Rather than just raising EPIPE to the caller, check the # response on the control connection. If getresp doesn't raise a more # appropriate exception, re-raise the original exception. getresp raise end # # Retrieves +remotefile+ in binary mode, storing the result in +localfile+. # If +localfile+ is nil, returns retrieved data. # If a block is supplied, it is passed the retrieved data in +blocksize+ # chunks. # def getbinaryfile(remotefile, localfile = File.basename(remotefile), blocksize = DEFAULT_BLOCKSIZE) # :yield: data result = nil if localfile if @resume rest_offset = File.size?(localfile) f = File.open(localfile, "a") else rest_offset = nil f = File.open(localfile, "w") end elsif !block_given? result = "" end begin f.binmode if localfile retrbinary("RETR " + remotefile.to_s, blocksize, rest_offset) do |data| f.write(data) if localfile yield(data) if block_given? result.concat(data) if result end return result ensure f.close if localfile end end # # Retrieves +remotefile+ in ASCII (text) mode, storing the result in # +localfile+. # If +localfile+ is nil, returns retrieved data. # If a block is supplied, it is passed the retrieved data one # line at a time. # def gettextfile(remotefile, localfile = File.basename(remotefile)) # :yield: line result = nil if localfile f = File.open(localfile, "w") elsif !block_given? result = "" end begin retrlines("RETR " + remotefile) do |line, newline| l = newline ? line + "\n" : line f.print(l) if localfile yield(line, newline) if block_given? result.concat(l) if result end return result ensure f.close if localfile end end # # Retrieves +remotefile+ in whatever mode the session is set (text or # binary). See #gettextfile and #getbinaryfile. # def get(remotefile, localfile = File.basename(remotefile), blocksize = DEFAULT_BLOCKSIZE, &block) # :yield: data if @binary getbinaryfile(remotefile, localfile, blocksize, &block) else gettextfile(remotefile, localfile, &block) end end # # Transfers +localfile+ to the server in binary mode, storing the result in # +remotefile+. If a block is supplied, calls it, passing in the transmitted # data in +blocksize+ chunks. # def putbinaryfile(localfile, remotefile = File.basename(localfile), blocksize = DEFAULT_BLOCKSIZE, &block) # :yield: data if @resume begin rest_offset = size(remotefile) rescue Net::FTPPermError rest_offset = nil end else rest_offset = nil end f = File.open(localfile) begin f.binmode if rest_offset storbinary("APPE " + remotefile, f, blocksize, rest_offset, &block) else storbinary("STOR " + remotefile, f, blocksize, rest_offset, &block) end ensure f.close end end # # Transfers +localfile+ to the server in ASCII (text) mode, storing the result # in +remotefile+. If callback or an associated block is supplied, calls it, # passing in the transmitted data one line at a time. # def puttextfile(localfile, remotefile = File.basename(localfile), &block) # :yield: line f = File.open(localfile) begin storlines("STOR " + remotefile, f, &block) ensure f.close end end # # Transfers +localfile+ to the server in whatever mode the session is set # (text or binary). See #puttextfile and #putbinaryfile. # def put(localfile, remotefile = File.basename(localfile), blocksize = DEFAULT_BLOCKSIZE, &block) if @binary putbinaryfile(localfile, remotefile, blocksize, &block) else puttextfile(localfile, remotefile, &block) end end # # Sends the ACCT command. # # This is a less common FTP command, to send account # information if the destination host requires it. # def acct(account) cmd = "ACCT " + account voidcmd(cmd) end # # Returns an array of filenames in the remote directory. # def nlst(dir = nil) cmd = "NLST" if dir cmd = cmd + " " + dir end files = [] retrlines(cmd) do |line| files.push(line) end return files end # # Returns an array of file information in the directory (the output is like # `ls -l`). If a block is given, it iterates through the listing. # def list(*args, &block) # :yield: line cmd = "LIST" args.each do |arg| cmd = cmd + " " + arg.to_s end if block retrlines(cmd, &block) else lines = [] retrlines(cmd) do |line| lines << line end return lines end end alias ls list alias dir list # # Renames a file on the server. # def rename(fromname, toname) resp = sendcmd("RNFR " + fromname) if resp[0] != ?3 raise FTPReplyError, resp end voidcmd("RNTO " + toname) end # # Deletes a file on the server. # def delete(filename) resp = sendcmd("DELE " + filename) if resp[0, 3] == "250" return elsif resp[0] == ?5 raise FTPPermError, resp else raise FTPReplyError, resp end end # # Changes the (remote) directory. # def chdir(dirname) if dirname == ".." begin voidcmd("CDUP") return rescue FTPPermError => e if e.message[0, 3] != "500" raise e end end end cmd = "CWD " + dirname voidcmd(cmd) end # # Returns the size of the given (remote) filename. # def size(filename) with_binary(true) do resp = sendcmd("SIZE " + filename) if resp[0, 3] != "213" raise FTPReplyError, resp end return resp[3..-1].strip.to_i end end MDTM_REGEXP = /^(\d\d\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)/ # :nodoc: # # Returns the last modification time of the (remote) file. If +local+ is # +true+, it is returned as a local time, otherwise it's a UTC time. # def mtime(filename, local = false) str = mdtm(filename) ary = str.scan(MDTM_REGEXP)[0].collect {|i| i.to_i} return local ? Time.local(*ary) : Time.gm(*ary) end # # Creates a remote directory. # def mkdir(dirname) resp = sendcmd("MKD " + dirname) return parse257(resp) end # # Removes a remote directory. # def rmdir(dirname) voidcmd("RMD " + dirname) end # # Returns the current remote directory. # def pwd resp = sendcmd("PWD") return parse257(resp) end alias getdir pwd # # Returns system information. # def system resp = sendcmd("SYST") if resp[0, 3] != "215" raise FTPReplyError, resp end return resp[4 .. -1] end # # Aborts the previous command (ABOR command). # def abort line = "ABOR" + CRLF print "put: ABOR\n" if @debug_mode @sock.send(line, Socket::MSG_OOB) resp = getmultiline unless ["426", "226", "225"].include?(resp[0, 3]) raise FTPProtoError, resp end return resp end # # Returns the status (STAT command). # def status line = "STAT" + CRLF print "put: STAT\n" if @debug_mode @sock.send(line, Socket::MSG_OOB) return getresp end # # Returns the raw last modification time of the (remote) file in the format # "YYYYMMDDhhmmss" (MDTM command). # # Use +mtime+ if you want a parsed Time instance. # def mdtm(filename) resp = sendcmd("MDTM " + filename) if resp[0, 3] == "213" return resp[3 .. -1].strip end end # # Issues the HELP command. # def help(arg = nil) cmd = "HELP" if arg cmd = cmd + " " + arg end sendcmd(cmd) end # # Exits the FTP session. # def quit voidcmd("QUIT") end # # Issues a NOOP command. # # Does nothing except return a response. # def noop voidcmd("NOOP") end # # Issues a SITE command. # def site(arg) cmd = "SITE " + arg voidcmd(cmd) end # # Closes the connection. Further operations are impossible until you open # a new connection with #connect. # def close if @sock and not @sock.closed? begin @sock.shutdown(Socket::SHUT_WR) rescue nil orig, self.read_timeout = self.read_timeout, 3 @sock.read rescue nil ensure @sock.close self.read_timeout = orig end end end # # Returns +true+ iff the connection is closed. # def closed? @sock == nil or @sock.closed? end # handler for response code 227 # (Entering Passive Mode (h1,h2,h3,h4,p1,p2)) # # Returns host and port. def parse227(resp) # :nodoc: if resp[0, 3] != "227" raise FTPReplyError, resp end if m = /\((?\d+(,\d+){3}),(?\d+,\d+)\)/.match(resp) return parse_pasv_ipv4_host(m["host"]), parse_pasv_port(m["port"]) else raise FTPProtoError, resp end end private :parse227 # handler for response code 228 # (Entering Long Passive Mode) # # Returns host and port. def parse228(resp) # :nodoc: if resp[0, 3] != "228" raise FTPReplyError, resp end if m = /\(4,4,(?\d+(,\d+){3}),2,(?\d+,\d+)\)/.match(resp) return parse_pasv_ipv4_host(m["host"]), parse_pasv_port(m["port"]) elsif m = /\(6,16,(?\d+(,(\d+)){15}),2,(?\d+,\d+)\)/.match(resp) return parse_pasv_ipv6_host(m["host"]), parse_pasv_port(m["port"]) else raise FTPProtoError, resp end end private :parse228 def parse_pasv_ipv4_host(s) return s.tr(",", ".") end private :parse_pasv_ipv4_host def parse_pasv_ipv6_host(s) return s.split(/,/).map { |i| "%02x" % i.to_i }.each_slice(2).map(&:join).join(":") end private :parse_pasv_ipv6_host def parse_pasv_port(s) return s.split(/,/).map(&:to_i).inject { |x, y| (x << 8) + y } end private :parse_pasv_port # handler for response code 229 # (Extended Passive Mode Entered) # # Returns host and port. def parse229(resp) # :nodoc: if resp[0, 3] != "229" raise FTPReplyError, resp end if m = /\((?[!-~])\k\k(?\d+)\k\)/.match(resp) return @sock.peeraddr[3], m["port"].to_i else raise FTPProtoError, resp end end private :parse229 # handler for response code 257 # ("PATHNAME" created) # # Returns host and port. def parse257(resp) # :nodoc: if resp[0, 3] != "257" raise FTPReplyError, resp end if resp[3, 2] != ' "' return "" end dirname = "" i = 5 n = resp.length while i < n c = resp[i, 1] i = i + 1 if c == '"' if i > n or resp[i, 1] != '"' break end i = i + 1 end dirname = dirname + c end return dirname end private :parse257 # :stopdoc: class NullSocket def read_timeout=(sec) end def closed? true end def close end def method_missing(mid, *args) raise FTPConnectionError, "not connected" end end class BufferedSocket < BufferedIO [:addr, :peeraddr, :send, :shutdown].each do |method| define_method(method) { |*args| @io.__send__(method, *args) } end def read(len = nil) if len s = super(len, "", true) return s.empty? ? nil : s else result = "" while s = super(DEFAULT_BLOCKSIZE, "", true) break if s.empty? result << s end return result end end def gets line = readuntil("\n", true) return line.empty? ? nil : line end def readline line = gets if line.nil? raise EOFError, "end of file reached" end return line end end # :startdoc: end end # Documentation comments: # - sourced from pickaxe and nutshell, with improvements (hopefully) PK!y2.2.0/net/http/request.rbnu[# HTTP request class. # This class wraps together the request header and the request path. # You cannot use this class directly. Instead, you should use one of its # subclasses: Net::HTTP::Get, Net::HTTP::Post, Net::HTTP::Head. # class Net::HTTPRequest < Net::HTTPGenericRequest # Creates an HTTP request object for +path+. # # +initheader+ are the default headers to use. Net::HTTP adds # Accept-Encoding to enable compression of the response body unless # Accept-Encoding or Range are supplied in +initheader+. def initialize(path, initheader = nil) super self.class::METHOD, self.class::REQUEST_HAS_BODY, self.class::RESPONSE_HAS_BODY, path, initheader end end PK!ܘGHBB2.2.0/net/http/backward.rbnu[# for backward compatibility # :enddoc: class Net::HTTP ProxyMod = ProxyDelta end module Net HTTPSession = Net::HTTP end module Net::NetPrivate HTTPRequest = ::Net::HTTPRequest end Net::HTTPInformationCode = Net::HTTPInformation Net::HTTPSuccessCode = Net::HTTPSuccess Net::HTTPRedirectionCode = Net::HTTPRedirection Net::HTTPRetriableCode = Net::HTTPRedirection Net::HTTPClientErrorCode = Net::HTTPClientError Net::HTTPFatalErrorCode = Net::HTTPClientError Net::HTTPServerErrorCode = Net::HTTPServerError Net::HTTPResponceReceiver = Net::HTTPResponse PK!.92.2.0/net/http/proxy_delta.rbnu[module Net::HTTP::ProxyDelta #:nodoc: internal use only private def conn_address proxy_address() end def conn_port proxy_port() end def edit_path(path) use_ssl? ? path : "http://#{addr_port()}#{path}" end end PK!J cKJ%J%!2.2.0/net/http/generic_request.rbnu[# HTTPGenericRequest is the parent of the HTTPRequest class. # Do not use this directly; use a subclass of HTTPRequest. # # Mixes in the HTTPHeader module to provide easier access to HTTP headers. # class Net::HTTPGenericRequest include Net::HTTPHeader def initialize(m, reqbody, resbody, uri_or_path, initheader = nil) @method = m @request_has_body = reqbody @response_has_body = resbody if URI === uri_or_path then @uri = uri_or_path.dup host = @uri.hostname.dup host << ":".freeze << @uri.port.to_s if @uri.port != @uri.default_port @path = uri_or_path.request_uri raise ArgumentError, "no HTTP request path given" unless @path else @uri = nil host = nil raise ArgumentError, "no HTTP request path given" unless uri_or_path raise ArgumentError, "HTTP request path is empty" if uri_or_path.empty? @path = uri_or_path.dup end @decode_content = false if @response_has_body and Net::HTTP::HAVE_ZLIB then if !initheader || !initheader.keys.any? { |k| %w[accept-encoding range].include? k.downcase } then @decode_content = true initheader = initheader ? initheader.dup : {} initheader["accept-encoding"] = "gzip;q=1.0,deflate;q=0.6,identity;q=0.3" end end initialize_http_header initheader self['Accept'] ||= '*/*' self['User-Agent'] ||= 'Ruby' self['Host'] ||= host if host @body = nil @body_stream = nil @body_data = nil end attr_reader :method attr_reader :path attr_reader :uri # Automatically set to false if the user sets the Accept-Encoding header. # This indicates they wish to handle Content-encoding in responses # themselves. attr_reader :decode_content def inspect "\#<#{self.class} #{@method}>" end ## # Don't automatically decode response content-encoding if the user indicates # they want to handle it. def []=(key, val) # :nodoc: @decode_content = false if key.downcase == 'accept-encoding' super key, val end def request_body_permitted? @request_has_body end def response_body_permitted? @response_has_body end def body_exist? warn "Net::HTTPRequest#body_exist? is obsolete; use response_body_permitted?" if $VERBOSE response_body_permitted? end attr_reader :body def body=(str) @body = str @body_stream = nil @body_data = nil str end attr_reader :body_stream def body_stream=(input) @body = nil @body_stream = input @body_data = nil input end def set_body_internal(str) #:nodoc: internal use only raise ArgumentError, "both of body argument and HTTPRequest#body set" if str and (@body or @body_stream) self.body = str if str if @body.nil? && @body_stream.nil? && @body_data.nil? && request_body_permitted? self.body = '' end end # # write # def exec(sock, ver, path) #:nodoc: internal use only if @body send_request_with_body sock, ver, path, @body elsif @body_stream send_request_with_body_stream sock, ver, path, @body_stream elsif @body_data send_request_with_body_data sock, ver, path, @body_data else write_header sock, ver, path end end def update_uri(addr, port, ssl) # :nodoc: internal use only # reflect the connection and @path to @uri return unless @uri if ssl scheme = 'https'.freeze klass = URI::HTTPS else scheme = 'http'.freeze klass = URI::HTTP end if host = self['host'] host.sub!(/:.*/s, ''.freeze) elsif host = @uri.host else host = addr end # convert the class of the URI if @uri.is_a?(klass) @uri.host = host @uri.port = port else @uri = klass.new( scheme, @uri.userinfo, host, port, nil, @uri.path, nil, @uri.query, nil) end end private class Chunker #:nodoc: def initialize(sock) @sock = sock @prev = nil end def write(buf) # avoid memcpy() of buf, buf can huge and eat memory bandwidth @sock.write("#{buf.bytesize.to_s(16)}\r\n") rv = @sock.write(buf) @sock.write("\r\n") rv end def finish @sock.write("0\r\n\r\n") end end def send_request_with_body(sock, ver, path, body) self.content_length = body.bytesize delete 'Transfer-Encoding' supply_default_content_type write_header sock, ver, path wait_for_continue sock, ver if sock.continue_timeout sock.write body end def send_request_with_body_stream(sock, ver, path, f) unless content_length() or chunked? raise ArgumentError, "Content-Length not given and Transfer-Encoding is not `chunked'" end supply_default_content_type write_header sock, ver, path wait_for_continue sock, ver if sock.continue_timeout if chunked? chunker = Chunker.new(sock) IO.copy_stream(f, chunker) chunker.finish else # copy_stream can sendfile() to sock.io unless we use SSL. # If sock.io is an SSLSocket, copy_stream will hit SSL_write() IO.copy_stream(f, sock.io) end end def send_request_with_body_data(sock, ver, path, params) if /\Amultipart\/form-data\z/i !~ self.content_type self.content_type = 'application/x-www-form-urlencoded' return send_request_with_body(sock, ver, path, URI.encode_www_form(params)) end opt = @form_option.dup require 'securerandom' unless defined?(SecureRandom) opt[:boundary] ||= SecureRandom.urlsafe_base64(40) self.set_content_type(self.content_type, boundary: opt[:boundary]) if chunked? write_header sock, ver, path encode_multipart_form_data(sock, params, opt) else require 'tempfile' file = Tempfile.new('multipart') file.binmode encode_multipart_form_data(file, params, opt) file.rewind self.content_length = file.size write_header sock, ver, path IO.copy_stream(file, sock) file.close(true) end end def encode_multipart_form_data(out, params, opt) charset = opt[:charset] boundary = opt[:boundary] require 'securerandom' unless defined?(SecureRandom) boundary ||= SecureRandom.urlsafe_base64(40) chunked_p = chunked? buf = '' params.each do |key, value, h={}| key = quote_string(key, charset) filename = h.key?(:filename) ? h[:filename] : value.respond_to?(:to_path) ? File.basename(value.to_path) : nil buf << "--#{boundary}\r\n" if filename filename = quote_string(filename, charset) type = h[:content_type] || 'application/octet-stream' buf << "Content-Disposition: form-data; " \ "name=\"#{key}\"; filename=\"#{filename}\"\r\n" \ "Content-Type: #{type}\r\n\r\n" if !out.respond_to?(:write) || !value.respond_to?(:read) # if +out+ is not an IO or +value+ is not an IO buf << (value.respond_to?(:read) ? value.read : value) elsif value.respond_to?(:size) && chunked_p # if +out+ is an IO and +value+ is a File, use IO.copy_stream flush_buffer(out, buf, chunked_p) out << "%x\r\n" % value.size if chunked_p IO.copy_stream(value, out) out << "\r\n" if chunked_p else # +out+ is an IO, and +value+ is not a File but an IO flush_buffer(out, buf, chunked_p) 1 while flush_buffer(out, value.read(4096), chunked_p) end else # non-file field: # HTML5 says, "The parts of the generated multipart/form-data # resource that correspond to non-file fields must not have a # Content-Type header specified." buf << "Content-Disposition: form-data; name=\"#{key}\"\r\n\r\n" buf << (value.respond_to?(:read) ? value.read : value) end buf << "\r\n" end buf << "--#{boundary}--\r\n" flush_buffer(out, buf, chunked_p) out << "0\r\n\r\n" if chunked_p end def quote_string(str, charset) str = str.encode(charset, fallback:->(c){'&#%d;'%c.encode("UTF-8").ord}) if charset str.gsub(/[\\"]/, '\\\\\&') end def flush_buffer(out, buf, chunked_p) return unless buf out << "%x\r\n"%buf.bytesize if chunked_p out << buf out << "\r\n" if chunked_p buf.clear end def supply_default_content_type return if content_type() warn 'net/http: warning: Content-Type did not set; using application/x-www-form-urlencoded' if $VERBOSE set_content_type 'application/x-www-form-urlencoded' end ## # Waits up to the continue timeout for a response from the server provided # we're speaking HTTP 1.1 and are expecting a 100-continue response. def wait_for_continue(sock, ver) if ver >= '1.1' and @header['expect'] and @header['expect'].include?('100-continue') if IO.select([sock.io], nil, nil, sock.continue_timeout) res = Net::HTTPResponse.read_new(sock) unless res.kind_of?(Net::HTTPContinue) res.decode_content = @decode_content throw :response, res end end end end def write_header(sock, ver, path) reqline = "#{@method} #{path} HTTP/#{ver}" if /[\r\n]/ =~ reqline raise ArgumentError, "A Request-Line must not contain CR or LF" end buf = "" buf << reqline << "\r\n" each_capitalized do |k,v| buf << "#{k}: #{v}\r\n" end buf << "\r\n" sock.write buf end end PK!t4y 2.2.0/net/http/requests.rbnu[# # HTTP/1.1 methods --- RFC2616 # # See Net::HTTPGenericRequest for attributes and methods. # See Net::HTTP for usage examples. class Net::HTTP::Get < Net::HTTPRequest METHOD = 'GET' REQUEST_HAS_BODY = false RESPONSE_HAS_BODY = true end # See Net::HTTPGenericRequest for attributes and methods. # See Net::HTTP for usage examples. class Net::HTTP::Head < Net::HTTPRequest METHOD = 'HEAD' REQUEST_HAS_BODY = false RESPONSE_HAS_BODY = false end # See Net::HTTPGenericRequest for attributes and methods. # See Net::HTTP for usage examples. class Net::HTTP::Post < Net::HTTPRequest METHOD = 'POST' REQUEST_HAS_BODY = true RESPONSE_HAS_BODY = true end # See Net::HTTPGenericRequest for attributes and methods. # See Net::HTTP for usage examples. class Net::HTTP::Put < Net::HTTPRequest METHOD = 'PUT' REQUEST_HAS_BODY = true RESPONSE_HAS_BODY = true end # See Net::HTTPGenericRequest for attributes and methods. # See Net::HTTP for usage examples. class Net::HTTP::Delete < Net::HTTPRequest METHOD = 'DELETE' REQUEST_HAS_BODY = false RESPONSE_HAS_BODY = true end # See Net::HTTPGenericRequest for attributes and methods. class Net::HTTP::Options < Net::HTTPRequest METHOD = 'OPTIONS' REQUEST_HAS_BODY = false RESPONSE_HAS_BODY = true end # See Net::HTTPGenericRequest for attributes and methods. class Net::HTTP::Trace < Net::HTTPRequest METHOD = 'TRACE' REQUEST_HAS_BODY = false RESPONSE_HAS_BODY = true end # # PATCH method --- RFC5789 # # See Net::HTTPGenericRequest for attributes and methods. class Net::HTTP::Patch < Net::HTTPRequest METHOD = 'PATCH' REQUEST_HAS_BODY = true RESPONSE_HAS_BODY = true end # # WebDAV methods --- RFC2518 # # See Net::HTTPGenericRequest for attributes and methods. class Net::HTTP::Propfind < Net::HTTPRequest METHOD = 'PROPFIND' REQUEST_HAS_BODY = true RESPONSE_HAS_BODY = true end # See Net::HTTPGenericRequest for attributes and methods. class Net::HTTP::Proppatch < Net::HTTPRequest METHOD = 'PROPPATCH' REQUEST_HAS_BODY = true RESPONSE_HAS_BODY = true end # See Net::HTTPGenericRequest for attributes and methods. class Net::HTTP::Mkcol < Net::HTTPRequest METHOD = 'MKCOL' REQUEST_HAS_BODY = true RESPONSE_HAS_BODY = true end # See Net::HTTPGenericRequest for attributes and methods. class Net::HTTP::Copy < Net::HTTPRequest METHOD = 'COPY' REQUEST_HAS_BODY = false RESPONSE_HAS_BODY = true end # See Net::HTTPGenericRequest for attributes and methods. class Net::HTTP::Move < Net::HTTPRequest METHOD = 'MOVE' REQUEST_HAS_BODY = false RESPONSE_HAS_BODY = true end # See Net::HTTPGenericRequest for attributes and methods. class Net::HTTP::Lock < Net::HTTPRequest METHOD = 'LOCK' REQUEST_HAS_BODY = true RESPONSE_HAS_BODY = true end # See Net::HTTPGenericRequest for attributes and methods. class Net::HTTP::Unlock < Net::HTTPRequest METHOD = 'UNLOCK' REQUEST_HAS_BODY = true RESPONSE_HAS_BODY = true end PK!D2.2.0/net/http/exceptions.rbnu[# Net::HTTP exception class. # You cannot use Net::HTTPExceptions directly; instead, you must use # its subclasses. module Net::HTTPExceptions def initialize(msg, res) #:nodoc: super msg @response = res end attr_reader :response alias data response #:nodoc: obsolete end class Net::HTTPError < Net::ProtocolError include Net::HTTPExceptions end class Net::HTTPRetriableError < Net::ProtoRetriableError include Net::HTTPExceptions end class Net::HTTPServerException < Net::ProtoServerError # We cannot use the name "HTTPServerError", it is the name of the response. include Net::HTTPExceptions end class Net::HTTPFatalError < Net::ProtoFatalError include Net::HTTPExceptions end PK!Ղ992.2.0/net/http/header.rbnu[# The HTTPHeader module defines methods for reading and writing # HTTP headers. # # It is used as a mixin by other classes, to provide hash-like # access to HTTP header values. Unlike raw hash access, HTTPHeader # provides access via case-insensitive keys. It also provides # methods for accessing commonly-used HTTP header values in more # convenient formats. # module Net::HTTPHeader def initialize_http_header(initheader) @header = {} return unless initheader initheader.each do |key, value| warn "net/http: warning: duplicated HTTP header: #{key}" if key?(key) and $VERBOSE @header[key.downcase] = [value.strip] end end def size #:nodoc: obsolete @header.size end alias length size #:nodoc: obsolete # Returns the header field corresponding to the case-insensitive key. # For example, a key of "Content-Type" might return "text/html" def [](key) a = @header[key.downcase] or return nil a.join(', ') end # Sets the header field corresponding to the case-insensitive key. def []=(key, val) unless val @header.delete key.downcase return val end @header[key.downcase] = [val] end # [Ruby 1.8.3] # Adds a value to a named header field, instead of replacing its value. # Second argument +val+ must be a String. # See also #[]=, #[] and #get_fields. # # request.add_field 'X-My-Header', 'a' # p request['X-My-Header'] #=> "a" # p request.get_fields('X-My-Header') #=> ["a"] # request.add_field 'X-My-Header', 'b' # p request['X-My-Header'] #=> "a, b" # p request.get_fields('X-My-Header') #=> ["a", "b"] # request.add_field 'X-My-Header', 'c' # p request['X-My-Header'] #=> "a, b, c" # p request.get_fields('X-My-Header') #=> ["a", "b", "c"] # def add_field(key, val) if @header.key?(key.downcase) @header[key.downcase].push val else @header[key.downcase] = [val] end end # [Ruby 1.8.3] # Returns an array of header field strings corresponding to the # case-insensitive +key+. This method allows you to get duplicated # header fields without any processing. See also #[]. # # p response.get_fields('Set-Cookie') # #=> ["session=al98axx; expires=Fri, 31-Dec-1999 23:58:23", # "query=rubyscript; expires=Fri, 31-Dec-1999 23:58:23"] # p response['Set-Cookie'] # #=> "session=al98axx; expires=Fri, 31-Dec-1999 23:58:23, query=rubyscript; expires=Fri, 31-Dec-1999 23:58:23" # def get_fields(key) return nil unless @header[key.downcase] @header[key.downcase].dup end # Returns the header field corresponding to the case-insensitive key. # Returns the default value +args+, or the result of the block, or # raises an IndexError if there's no header field named +key+ # See Hash#fetch def fetch(key, *args, &block) #:yield: +key+ a = @header.fetch(key.downcase, *args, &block) a.kind_of?(Array) ? a.join(', ') : a end # Iterates through the header names and values, passing in the name # and value to the code block supplied. # # Example: # # response.header.each_header {|key,value| puts "#{key} = #{value}" } # def each_header #:yield: +key+, +value+ block_given? or return enum_for(__method__) @header.each do |k,va| yield k, va.join(', ') end end alias each each_header # Iterates through the header names in the header, passing # each header name to the code block. def each_name(&block) #:yield: +key+ block_given? or return enum_for(__method__) @header.each_key(&block) end alias each_key each_name # Iterates through the header names in the header, passing # capitalized header names to the code block. # # Note that header names are capitalized systematically; # capitalization may not match that used by the remote HTTP # server in its response. def each_capitalized_name #:yield: +key+ block_given? or return enum_for(__method__) @header.each_key do |k| yield capitalize(k) end end # Iterates through header values, passing each value to the # code block. def each_value #:yield: +value+ block_given? or return enum_for(__method__) @header.each_value do |va| yield va.join(', ') end end # Removes a header field, specified by case-insensitive key. def delete(key) @header.delete(key.downcase) end # true if +key+ header exists. def key?(key) @header.key?(key.downcase) end # Returns a Hash consisting of header names and array of values. # e.g. # {"cache-control" => ["private"], # "content-type" => ["text/html"], # "date" => ["Wed, 22 Jun 2005 22:11:50 GMT"]} def to_hash @header.dup end # As for #each_header, except the keys are provided in capitalized form. # # Note that header names are capitalized systematically; # capitalization may not match that used by the remote HTTP # server in its response. def each_capitalized block_given? or return enum_for(__method__) @header.each do |k,v| yield capitalize(k), v.join(', ') end end alias canonical_each each_capitalized def capitalize(name) name.split(/-/).map {|s| s.capitalize }.join('-') end private :capitalize # Returns an Array of Range objects which represent the Range: # HTTP header field, or +nil+ if there is no such header. def range return nil unless @header['range'] value = self['Range'] # byte-range-set = *( "," OWS ) ( byte-range-spec / suffix-byte-range-spec ) # *( OWS "," [ OWS ( byte-range-spec / suffix-byte-range-spec ) ] ) # corrected collected ABNF # http://tools.ietf.org/html/draft-ietf-httpbis-p5-range-19#section-5.4.1 # http://tools.ietf.org/html/draft-ietf-httpbis-p5-range-19#appendix-C # http://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-19#section-3.2.5 unless /\Abytes=((?:,[ \t]*)*(?:\d+-\d*|-\d+)(?:[ \t]*,(?:[ \t]*\d+-\d*|-\d+)?)*)\z/ =~ value raise Net::HTTPHeaderSyntaxError, "invalid syntax for byte-ranges-specifier: '#{value}'" end byte_range_set = $1 result = byte_range_set.split(/,/).map {|spec| m = /(\d+)?\s*-\s*(\d+)?/i.match(spec) or raise Net::HTTPHeaderSyntaxError, "invalid byte-range-spec: '#{spec}'" d1 = m[1].to_i d2 = m[2].to_i if m[1] and m[2] if d1 > d2 raise Net::HTTPHeaderSyntaxError, "last-byte-pos MUST greater than or equal to first-byte-pos but '#{spec}'" end d1..d2 elsif m[1] d1..-1 elsif m[2] -d2..-1 else raise Net::HTTPHeaderSyntaxError, 'range is not specified' end } # if result.empty? # byte-range-set must include at least one byte-range-spec or suffix-byte-range-spec # but above regexp already denies it. if result.size == 1 && result[0].begin == 0 && result[0].end == -1 raise Net::HTTPHeaderSyntaxError, 'only one suffix-byte-range-spec with zero suffix-length' end result end # Sets the HTTP Range: header. # Accepts either a Range object as a single argument, # or a beginning index and a length from that index. # Example: # # req.range = (0..1023) # req.set_range 0, 1023 # def set_range(r, e = nil) unless r @header.delete 'range' return r end r = (r...r+e) if e case r when Numeric n = r.to_i rangestr = (n > 0 ? "0-#{n-1}" : "-#{-n}") when Range first = r.first last = r.end last -= 1 if r.exclude_end? if last == -1 rangestr = (first > 0 ? "#{first}-" : "-#{-first}") else raise Net::HTTPHeaderSyntaxError, 'range.first is negative' if first < 0 raise Net::HTTPHeaderSyntaxError, 'range.last is negative' if last < 0 raise Net::HTTPHeaderSyntaxError, 'must be .first < .last' if first > last rangestr = "#{first}-#{last}" end else raise TypeError, 'Range/Integer is required' end @header['range'] = ["bytes=#{rangestr}"] r end alias range= set_range # Returns an Integer object which represents the HTTP Content-Length: # header field, or +nil+ if that field was not provided. def content_length return nil unless key?('Content-Length') len = self['Content-Length'].slice(/\d+/) or raise Net::HTTPHeaderSyntaxError, 'wrong Content-Length format' len.to_i end def content_length=(len) unless len @header.delete 'content-length' return nil end @header['content-length'] = [len.to_i.to_s] end # Returns "true" if the "transfer-encoding" header is present and # set to "chunked". This is an HTTP/1.1 feature, allowing the # the content to be sent in "chunks" without at the outset # stating the entire content length. def chunked? return false unless @header['transfer-encoding'] field = self['Transfer-Encoding'] (/(?:\A|[^\-\w])chunked(?![\-\w])/i =~ field) ? true : false end # Returns a Range object which represents the value of the Content-Range: # header field. # For a partial entity body, this indicates where this fragment # fits inside the full entity body, as range of byte offsets. def content_range return nil unless @header['content-range'] m = %ri.match(self['Content-Range']) or raise Net::HTTPHeaderSyntaxError, 'wrong Content-Range format' m[1].to_i .. m[2].to_i end # The length of the range represented in Content-Range: header. def range_length r = content_range() or return nil r.end - r.begin + 1 end # Returns a content type string such as "text/html". # This method returns nil if Content-Type: header field does not exist. def content_type return nil unless main_type() if sub_type() then "#{main_type()}/#{sub_type()}" else main_type() end end # Returns a content type string such as "text". # This method returns nil if Content-Type: header field does not exist. def main_type return nil unless @header['content-type'] self['Content-Type'].split(';').first.to_s.split('/')[0].to_s.strip end # Returns a content type string such as "html". # This method returns nil if Content-Type: header field does not exist # or sub-type is not given (e.g. "Content-Type: text"). def sub_type return nil unless @header['content-type'] _, sub = *self['Content-Type'].split(';').first.to_s.split('/') return nil unless sub sub.strip end # Any parameters specified for the content type, returned as a Hash. # For example, a header of Content-Type: text/html; charset=EUC-JP # would result in type_params returning {'charset' => 'EUC-JP'} def type_params result = {} list = self['Content-Type'].to_s.split(';') list.shift list.each do |param| k, v = *param.split('=', 2) result[k.strip] = v.strip end result end # Sets the content type in an HTTP header. # The +type+ should be a full HTTP content type, e.g. "text/html". # The +params+ are an optional Hash of parameters to add after the # content type, e.g. {'charset' => 'iso-8859-1'} def set_content_type(type, params = {}) @header['content-type'] = [type + params.map{|k,v|"; #{k}=#{v}"}.join('')] end alias content_type= set_content_type # Set header fields and a body from HTML form data. # +params+ should be an Array of Arrays or # a Hash containing HTML form data. # Optional argument +sep+ means data record separator. # # Values are URL encoded as necessary and the content-type is set to # application/x-www-form-urlencoded # # Example: # http.form_data = {"q" => "ruby", "lang" => "en"} # http.form_data = {"q" => ["ruby", "perl"], "lang" => "en"} # http.set_form_data({"q" => "ruby", "lang" => "en"}, ';') # def set_form_data(params, sep = '&') query = URI.encode_www_form(params) query.gsub!(/&/, sep) if sep != '&' self.body = query self.content_type = 'application/x-www-form-urlencoded' end alias form_data= set_form_data # Set a HTML form data set. # +params+ is the form data set; it is an Array of Arrays or a Hash # +enctype is the type to encode the form data set. # It is application/x-www-form-urlencoded or multipart/form-data. # +formpot+ is an optional hash to specify the detail. # # boundary:: the boundary of the multipart message # charset:: the charset of the message. All names and the values of # non-file fields are encoded as the charset. # # Each item of params is an array and contains following items: # +name+:: the name of the field # +value+:: the value of the field, it should be a String or a File # +opt+:: an optional hash to specify additional information # # Each item is a file field or a normal field. # If +value+ is a File object or the +opt+ have a filename key, # the item is treated as a file field. # # If Transfer-Encoding is set as chunked, this send the request in # chunked encoding. Because chunked encoding is HTTP/1.1 feature, # you must confirm the server to support HTTP/1.1 before sending it. # # Example: # http.set_form([["q", "ruby"], ["lang", "en"]]) # # See also RFC 2388, RFC 2616, HTML 4.01, and HTML5 # def set_form(params, enctype='application/x-www-form-urlencoded', formopt={}) @body_data = params @body = nil @body_stream = nil @form_option = formopt case enctype when /\Aapplication\/x-www-form-urlencoded\z/i, /\Amultipart\/form-data\z/i self.content_type = enctype else raise ArgumentError, "invalid enctype: #{enctype}" end end # Set the Authorization: header for "Basic" authorization. def basic_auth(account, password) @header['authorization'] = [basic_encode(account, password)] end # Set Proxy-Authorization: header for "Basic" authorization. def proxy_basic_auth(account, password) @header['proxy-authorization'] = [basic_encode(account, password)] end def basic_encode(account, password) 'Basic ' + ["#{account}:#{password}"].pack('m').delete("\r\n") end private :basic_encode def connection_close? tokens(@header['connection']).include?('close') or tokens(@header['proxy-connection']).include?('close') end def connection_keep_alive? tokens(@header['connection']).include?('keep-alive') or tokens(@header['proxy-connection']).include?('keep-alive') end def tokens(vals) return [] unless vals vals.map {|v| v.split(',') }.flatten\ .reject {|str| str.strip.empty? }\ .map {|tok| tok.strip.downcase } end private :tokens end PK!U("("2.2.0/net/http/responses.rbnu[# :stopdoc: class Net::HTTPUnknownResponse < Net::HTTPResponse HAS_BODY = true EXCEPTION_TYPE = Net::HTTPError end class Net::HTTPInformation < Net::HTTPResponse # 1xx HAS_BODY = false EXCEPTION_TYPE = Net::HTTPError end class Net::HTTPSuccess < Net::HTTPResponse # 2xx HAS_BODY = true EXCEPTION_TYPE = Net::HTTPError end class Net::HTTPRedirection < Net::HTTPResponse # 3xx HAS_BODY = true EXCEPTION_TYPE = Net::HTTPRetriableError end class Net::HTTPClientError < Net::HTTPResponse # 4xx HAS_BODY = true EXCEPTION_TYPE = Net::HTTPServerException # for backward compatibility end class Net::HTTPServerError < Net::HTTPResponse # 5xx HAS_BODY = true EXCEPTION_TYPE = Net::HTTPFatalError # for backward compatibility end class Net::HTTPContinue < Net::HTTPInformation # 100 HAS_BODY = false end class Net::HTTPSwitchProtocol < Net::HTTPInformation # 101 HAS_BODY = false end # 102 - RFC 2518; removed in RFC 4918 class Net::HTTPOK < Net::HTTPSuccess # 200 HAS_BODY = true end class Net::HTTPCreated < Net::HTTPSuccess # 201 HAS_BODY = true end class Net::HTTPAccepted < Net::HTTPSuccess # 202 HAS_BODY = true end class Net::HTTPNonAuthoritativeInformation < Net::HTTPSuccess # 203 HAS_BODY = true end class Net::HTTPNoContent < Net::HTTPSuccess # 204 HAS_BODY = false end class Net::HTTPResetContent < Net::HTTPSuccess # 205 HAS_BODY = false end class Net::HTTPPartialContent < Net::HTTPSuccess # 206 HAS_BODY = true end class Net::HTTPMultiStatus < Net::HTTPSuccess # 207 - RFC 4918 HAS_BODY = true end # 208 Already Reported - RFC 5842; experimental class Net::HTTPIMUsed < Net::HTTPSuccess # 226 - RFC 3229 HAS_BODY = true end class Net::HTTPMultipleChoices < Net::HTTPRedirection # 300 HAS_BODY = true end Net::HTTPMultipleChoice = Net::HTTPMultipleChoices class Net::HTTPMovedPermanently < Net::HTTPRedirection # 301 HAS_BODY = true end class Net::HTTPFound < Net::HTTPRedirection # 302 HAS_BODY = true end Net::HTTPMovedTemporarily = Net::HTTPFound class Net::HTTPSeeOther < Net::HTTPRedirection # 303 HAS_BODY = true end class Net::HTTPNotModified < Net::HTTPRedirection # 304 HAS_BODY = false end class Net::HTTPUseProxy < Net::HTTPRedirection # 305 HAS_BODY = false end # 306 Switch Proxy - no longer unused class Net::HTTPTemporaryRedirect < Net::HTTPRedirection # 307 HAS_BODY = true end class Net::HTTPPermanentRedirect < Net::HTTPRedirection # 308 HAS_BODY = true end class Net::HTTPBadRequest < Net::HTTPClientError # 400 HAS_BODY = true end class Net::HTTPUnauthorized < Net::HTTPClientError # 401 HAS_BODY = true end class Net::HTTPPaymentRequired < Net::HTTPClientError # 402 HAS_BODY = true end class Net::HTTPForbidden < Net::HTTPClientError # 403 HAS_BODY = true end class Net::HTTPNotFound < Net::HTTPClientError # 404 HAS_BODY = true end class Net::HTTPMethodNotAllowed < Net::HTTPClientError # 405 HAS_BODY = true end class Net::HTTPNotAcceptable < Net::HTTPClientError # 406 HAS_BODY = true end class Net::HTTPProxyAuthenticationRequired < Net::HTTPClientError # 407 HAS_BODY = true end class Net::HTTPRequestTimeOut < Net::HTTPClientError # 408 HAS_BODY = true end class Net::HTTPConflict < Net::HTTPClientError # 409 HAS_BODY = true end class Net::HTTPGone < Net::HTTPClientError # 410 HAS_BODY = true end class Net::HTTPLengthRequired < Net::HTTPClientError # 411 HAS_BODY = true end class Net::HTTPPreconditionFailed < Net::HTTPClientError # 412 HAS_BODY = true end class Net::HTTPRequestEntityTooLarge < Net::HTTPClientError # 413 HAS_BODY = true end class Net::HTTPRequestURITooLong < Net::HTTPClientError # 414 HAS_BODY = true end Net::HTTPRequestURITooLarge = Net::HTTPRequestURITooLong class Net::HTTPUnsupportedMediaType < Net::HTTPClientError # 415 HAS_BODY = true end class Net::HTTPRequestedRangeNotSatisfiable < Net::HTTPClientError # 416 HAS_BODY = true end class Net::HTTPExpectationFailed < Net::HTTPClientError # 417 HAS_BODY = true end # 418 I'm a teapot - RFC 2324; a joke RFC # 420 Enhance Your Calm - Twitter class Net::HTTPUnprocessableEntity < Net::HTTPClientError # 422 - RFC 4918 HAS_BODY = true end class Net::HTTPLocked < Net::HTTPClientError # 423 - RFC 4918 HAS_BODY = true end class Net::HTTPFailedDependency < Net::HTTPClientError # 424 - RFC 4918 HAS_BODY = true end # 425 Unordered Collection - existed only in draft class Net::HTTPUpgradeRequired < Net::HTTPClientError # 426 - RFC 2817 HAS_BODY = true end class Net::HTTPPreconditionRequired < Net::HTTPClientError # 428 - RFC 6585 HAS_BODY = true end class Net::HTTPTooManyRequests < Net::HTTPClientError # 429 - RFC 6585 HAS_BODY = true end class Net::HTTPRequestHeaderFieldsTooLarge < Net::HTTPClientError # 431 - RFC 6585 HAS_BODY = true end # 444 No Response - Nginx # 449 Retry With - Microsoft # 450 Blocked by Windows Parental Controls - Microsoft # 499 Client Closed Request - Nginx class Net::HTTPInternalServerError < Net::HTTPServerError # 500 HAS_BODY = true end class Net::HTTPNotImplemented < Net::HTTPServerError # 501 HAS_BODY = true end class Net::HTTPBadGateway < Net::HTTPServerError # 502 HAS_BODY = true end class Net::HTTPServiceUnavailable < Net::HTTPServerError # 503 HAS_BODY = true end class Net::HTTPGatewayTimeOut < Net::HTTPServerError # 504 HAS_BODY = true end class Net::HTTPVersionNotSupported < Net::HTTPServerError # 505 HAS_BODY = true end # 506 Variant Also Negotiates - RFC 2295; experimental class Net::HTTPInsufficientStorage < Net::HTTPServerError # 507 - RFC 4918 HAS_BODY = true end # 508 Loop Detected - RFC 5842; experimental # 509 Bandwidth Limit Exceeded - Apache bw/limited extension # 510 Not Extended - RFC 2774; experimental class Net::HTTPNetworkAuthenticationRequired < Net::HTTPServerError # 511 - RFC 6585 HAS_BODY = true end class Net::HTTPResponse CODE_CLASS_TO_OBJ = { '1' => Net::HTTPInformation, '2' => Net::HTTPSuccess, '3' => Net::HTTPRedirection, '4' => Net::HTTPClientError, '5' => Net::HTTPServerError } CODE_TO_OBJ = { '100' => Net::HTTPContinue, '101' => Net::HTTPSwitchProtocol, '200' => Net::HTTPOK, '201' => Net::HTTPCreated, '202' => Net::HTTPAccepted, '203' => Net::HTTPNonAuthoritativeInformation, '204' => Net::HTTPNoContent, '205' => Net::HTTPResetContent, '206' => Net::HTTPPartialContent, '207' => Net::HTTPMultiStatus, '226' => Net::HTTPIMUsed, '300' => Net::HTTPMultipleChoices, '301' => Net::HTTPMovedPermanently, '302' => Net::HTTPFound, '303' => Net::HTTPSeeOther, '304' => Net::HTTPNotModified, '305' => Net::HTTPUseProxy, '307' => Net::HTTPTemporaryRedirect, '400' => Net::HTTPBadRequest, '401' => Net::HTTPUnauthorized, '402' => Net::HTTPPaymentRequired, '403' => Net::HTTPForbidden, '404' => Net::HTTPNotFound, '405' => Net::HTTPMethodNotAllowed, '406' => Net::HTTPNotAcceptable, '407' => Net::HTTPProxyAuthenticationRequired, '408' => Net::HTTPRequestTimeOut, '409' => Net::HTTPConflict, '410' => Net::HTTPGone, '411' => Net::HTTPLengthRequired, '412' => Net::HTTPPreconditionFailed, '413' => Net::HTTPRequestEntityTooLarge, '414' => Net::HTTPRequestURITooLong, '415' => Net::HTTPUnsupportedMediaType, '416' => Net::HTTPRequestedRangeNotSatisfiable, '417' => Net::HTTPExpectationFailed, '422' => Net::HTTPUnprocessableEntity, '423' => Net::HTTPLocked, '424' => Net::HTTPFailedDependency, '426' => Net::HTTPUpgradeRequired, '428' => Net::HTTPPreconditionRequired, '429' => Net::HTTPTooManyRequests, '431' => Net::HTTPRequestHeaderFieldsTooLarge, '500' => Net::HTTPInternalServerError, '501' => Net::HTTPNotImplemented, '502' => Net::HTTPBadGateway, '503' => Net::HTTPServiceUnavailable, '504' => Net::HTTPGatewayTimeOut, '505' => Net::HTTPVersionNotSupported, '507' => Net::HTTPInsufficientStorage, '511' => Net::HTTPNetworkAuthenticationRequired, } end # :startdoc: PK!Kaz(z(2.2.0/net/http/response.rbnu[# HTTP response class. # # This class wraps together the response header and the response body (the # entity requested). # # It mixes in the HTTPHeader module, which provides access to response # header values both via hash-like methods and via individual readers. # # Note that each possible HTTP response code defines its own # HTTPResponse subclass. These are listed below. # # All classes are defined under the Net module. Indentation indicates # inheritance. For a list of the classes see Net::HTTP. # # class Net::HTTPResponse class << self # true if the response has a body. def body_permitted? self::HAS_BODY end def exception_type # :nodoc: internal use only self::EXCEPTION_TYPE end def read_new(sock) #:nodoc: internal use only httpv, code, msg = read_status_line(sock) res = response_class(code).new(httpv, code, msg) each_response_header(sock) do |k,v| res.add_field k, v end res end private def read_status_line(sock) str = sock.readline m = /\AHTTP(?:\/(\d+\.\d+))?\s+(\d\d\d)(?:\s+(.*))?\z/in.match(str) or raise Net::HTTPBadResponse, "wrong status line: #{str.dump}" m.captures end def response_class(code) CODE_TO_OBJ[code] or CODE_CLASS_TO_OBJ[code[0,1]] or Net::HTTPUnknownResponse end def each_response_header(sock) key = value = nil while true line = sock.readuntil("\n", true).sub(/\s+\z/, '') break if line.empty? if line[0] == ?\s or line[0] == ?\t and value value << ' ' unless value.empty? value << line.strip else yield key, value if key key, value = line.strip.split(/\s*:\s*/, 2) raise Net::HTTPBadResponse, 'wrong header line format' if value.nil? end end yield key, value if key end end # next is to fix bug in RDoc, where the private inside class << self # spills out. public include Net::HTTPHeader def initialize(httpv, code, msg) #:nodoc: internal use only @http_version = httpv @code = code @message = msg initialize_http_header nil @body = nil @read = false @uri = nil @decode_content = false end # The HTTP version supported by the server. attr_reader :http_version # The HTTP result code string. For example, '302'. You can also # determine the response type by examining which response subclass # the response object is an instance of. attr_reader :code # The HTTP result message sent by the server. For example, 'Not Found'. attr_reader :message alias msg message # :nodoc: obsolete # The URI used to fetch this response. The response URI is only available # if a URI was used to create the request. attr_reader :uri # Set to true automatically when the request did not contain an # Accept-Encoding header from the user. attr_accessor :decode_content def inspect "#<#{self.class} #{@code} #{@message} readbody=#{@read}>" end # # response <-> exception relationship # def code_type #:nodoc: self.class end def error! #:nodoc: raise error_type().new(@code + ' ' + @message.dump, self) end def error_type #:nodoc: self.class::EXCEPTION_TYPE end # Raises an HTTP error if the response is not 2xx (success). def value error! unless self.kind_of?(Net::HTTPSuccess) end def uri= uri # :nodoc: @uri = uri.dup if uri end # # header (for backward compatibility only; DO NOT USE) # def response #:nodoc: warn "#{caller(1)[0]}: warning: Net::HTTPResponse#response is obsolete" if $VERBOSE self end def header #:nodoc: warn "#{caller(1)[0]}: warning: Net::HTTPResponse#header is obsolete" if $VERBOSE self end def read_header #:nodoc: warn "#{caller(1)[0]}: warning: Net::HTTPResponse#read_header is obsolete" if $VERBOSE self end # # body # def reading_body(sock, reqmethodallowbody) #:nodoc: internal use only @socket = sock @body_exist = reqmethodallowbody && self.class.body_permitted? begin yield self.body # ensure to read body ensure @socket = nil end end # Gets the entity body returned by the remote HTTP server. # # If a block is given, the body is passed to the block, and # the body is provided in fragments, as it is read in from the socket. # # Calling this method a second or subsequent time for the same # HTTPResponse object will return the value already read. # # http.request_get('/index.html') {|res| # puts res.read_body # } # # http.request_get('/index.html') {|res| # p res.read_body.object_id # 538149362 # p res.read_body.object_id # 538149362 # } # # # using iterator # http.request_get('/index.html') {|res| # res.read_body do |segment| # print segment # end # } # def read_body(dest = nil, &block) if @read raise IOError, "#{self.class}\#read_body called twice" if dest or block return @body end to = procdest(dest, block) stream_check if @body_exist read_body_0 to @body = to else @body = nil end @read = true @body end # Returns the full entity body. # # Calling this method a second or subsequent time will return the # string already read. # # http.request_get('/index.html') {|res| # puts res.body # } # # http.request_get('/index.html') {|res| # p res.body.object_id # 538149362 # p res.body.object_id # 538149362 # } # def body read_body() end # Because it may be necessary to modify the body, Eg, decompression # this method facilitates that. def body=(value) @body = value end alias entity body #:nodoc: obsolete private ## # Checks for a supported Content-Encoding header and yields an Inflate # wrapper for this response's socket when zlib is present. If the # Content-Encoding is unsupported or zlib is missing the plain socket is # yielded. # # If a Content-Range header is present a plain socket is yielded as the # bytes in the range may not be a complete deflate block. def inflater # :nodoc: return yield @socket unless Net::HTTP::HAVE_ZLIB return yield @socket unless @decode_content return yield @socket if self['content-range'] v = self['content-encoding'] case v && v.downcase when 'deflate', 'gzip', 'x-gzip' then self.delete 'content-encoding' inflate_body_io = Inflater.new(@socket) begin yield inflate_body_io ensure orig_err = $! begin inflate_body_io.finish rescue => err raise orig_err || err end end when 'none', 'identity' then self.delete 'content-encoding' yield @socket else yield @socket end end def read_body_0(dest) inflater do |inflate_body_io| if chunked? read_chunked dest, inflate_body_io return end @socket = inflate_body_io clen = content_length() if clen @socket.read clen, dest, true # ignore EOF return end clen = range_length() if clen @socket.read clen, dest return end @socket.read_all dest end end ## # read_chunked reads from +@socket+ for chunk-size, chunk-extension, CRLF, # etc. and +chunk_data_io+ for chunk-data which may be deflate or gzip # encoded. # # See RFC 2616 section 3.6.1 for definitions def read_chunked(dest, chunk_data_io) # :nodoc: total = 0 while true line = @socket.readline hexlen = line.slice(/[0-9a-fA-F]+/) or raise Net::HTTPBadResponse, "wrong chunk size line: #{line}" len = hexlen.hex break if len == 0 begin chunk_data_io.read len, dest ensure total += len @socket.read 2 # \r\n end end until @socket.readline.empty? # none end end def stream_check raise IOError, 'attempt to read body out of block' if @socket.closed? end def procdest(dest, block) raise ArgumentError, 'both arg and block given for HTTP method' if dest and block if block Net::ReadAdapter.new(block) else dest || '' end end ## # Inflater is a wrapper around Net::BufferedIO that transparently inflates # zlib and gzip streams. class Inflater # :nodoc: ## # Creates a new Inflater wrapping +socket+ def initialize socket @socket = socket # zlib with automatic gzip detection @inflate = Zlib::Inflate.new(32 + Zlib::MAX_WBITS) end ## # Finishes the inflate stream. def finish return if @inflate.total_in == 0 @inflate.finish end ## # Returns a Net::ReadAdapter that inflates each read chunk into +dest+. # # This allows a large response body to be inflated without storing the # entire body in memory. def inflate_adapter(dest) if dest.respond_to?(:set_encoding) dest.set_encoding(Encoding::ASCII_8BIT) elsif dest.respond_to?(:force_encoding) dest.force_encoding(Encoding::ASCII_8BIT) end block = proc do |compressed_chunk| @inflate.inflate(compressed_chunk) do |chunk| dest << chunk end end Net::ReadAdapter.new(block) end ## # Reads +clen+ bytes from the socket, inflates them, then writes them to # +dest+. +ignore_eof+ is passed down to Net::BufferedIO#read # # Unlike Net::BufferedIO#read, this method returns more than +clen+ bytes. # At this time there is no way for a user of Net::HTTPResponse to read a # specific number of bytes from the HTTP response body, so this internal # API does not return the same number of bytes as were requested. # # See https://bugs.ruby-lang.org/issues/6492 for further discussion. def read clen, dest, ignore_eof = false temp_dest = inflate_adapter(dest) @socket.read clen, temp_dest, ignore_eof end ## # Reads the rest of the socket, inflates it, then writes it to +dest+. def read_all dest temp_dest = inflate_adapter(dest) @socket.read_all temp_dest end end end PK!Aoxox2.2.0/net/smtp.rbnu[# = net/smtp.rb # # Copyright (c) 1999-2007 Yukihiro Matsumoto. # # Copyright (c) 1999-2007 Minero Aoki. # # Written & maintained by Minero Aoki . # # Documented by William Webber and Minero Aoki. # # This program is free software. You can re-distribute and/or # modify this program under the same terms as Ruby itself. # # NOTE: You can find Japanese version of this document at: # http://www.ruby-lang.org/ja/man/html/net_smtp.html # # $Id: smtp.rb 46793 2014-07-11 19:22:19Z kosaki $ # # See Net::SMTP for documentation. # require 'net/protocol' require 'digest/md5' require 'timeout' begin require 'openssl' rescue LoadError end module Net # Module mixed in to all SMTP error classes module SMTPError # This *class* is a module for backward compatibility. # In later release, this module becomes a class. end # Represents an SMTP authentication error. class SMTPAuthenticationError < ProtoAuthError include SMTPError end # Represents SMTP error code 420 or 450, a temporary error. class SMTPServerBusy < ProtoServerError include SMTPError end # Represents an SMTP command syntax error (error code 500) class SMTPSyntaxError < ProtoSyntaxError include SMTPError end # Represents a fatal SMTP error (error code 5xx, except for 500) class SMTPFatalError < ProtoFatalError include SMTPError end # Unexpected reply code returned from server. class SMTPUnknownError < ProtoUnknownError include SMTPError end # Command is not supported on server. class SMTPUnsupportedCommand < ProtocolError include SMTPError end # # == What is This Library? # # This library provides functionality to send internet # mail via SMTP, the Simple Mail Transfer Protocol. For details of # SMTP itself, see [RFC2821] (http://www.ietf.org/rfc/rfc2821.txt). # # == What is This Library NOT? # # This library does NOT provide functions to compose internet mails. # You must create them by yourself. If you want better mail support, # try RubyMail or TMail or search for alternatives in # {RubyGems.org}[https://rubygems.org/] or {The Ruby # Toolbox}[https://www.ruby-toolbox.com/]. # # FYI: the official documentation on internet mail is: [RFC2822] (http://www.ietf.org/rfc/rfc2822.txt). # # == Examples # # === Sending Messages # # You must open a connection to an SMTP server before sending messages. # The first argument is the address of your SMTP server, and the second # argument is the port number. Using SMTP.start with a block is the simplest # way to do this. This way, the SMTP connection is closed automatically # after the block is executed. # # require 'net/smtp' # Net::SMTP.start('your.smtp.server', 25) do |smtp| # # Use the SMTP object smtp only in this block. # end # # Replace 'your.smtp.server' with your SMTP server. Normally # your system manager or internet provider supplies a server # for you. # # Then you can send messages. # # msgstr = < # To: Destination Address # Subject: test message # Date: Sat, 23 Jun 2001 16:26:43 +0900 # Message-Id: # # This is a test message. # END_OF_MESSAGE # # require 'net/smtp' # Net::SMTP.start('your.smtp.server', 25) do |smtp| # smtp.send_message msgstr, # 'your@mail.address', # 'his_address@example.com' # end # # === Closing the Session # # You MUST close the SMTP session after sending messages, by calling # the #finish method: # # # using SMTP#finish # smtp = Net::SMTP.start('your.smtp.server', 25) # smtp.send_message msgstr, 'from@address', 'to@address' # smtp.finish # # You can also use the block form of SMTP.start/SMTP#start. This closes # the SMTP session automatically: # # # using block form of SMTP.start # Net::SMTP.start('your.smtp.server', 25) do |smtp| # smtp.send_message msgstr, 'from@address', 'to@address' # end # # I strongly recommend this scheme. This form is simpler and more robust. # # === HELO domain # # In almost all situations, you must provide a third argument # to SMTP.start/SMTP#start. This is the domain name which you are on # (the host to send mail from). It is called the "HELO domain". # The SMTP server will judge whether it should send or reject # the SMTP session by inspecting the HELO domain. # # Net::SMTP.start('your.smtp.server', 25, # 'mail.from.domain') { |smtp| ... } # # === SMTP Authentication # # The Net::SMTP class supports three authentication schemes; # PLAIN, LOGIN and CRAM MD5. (SMTP Authentication: [RFC2554]) # To use SMTP authentication, pass extra arguments to # SMTP.start/SMTP#start. # # # PLAIN # Net::SMTP.start('your.smtp.server', 25, 'mail.from.domain', # 'Your Account', 'Your Password', :plain) # # LOGIN # Net::SMTP.start('your.smtp.server', 25, 'mail.from.domain', # 'Your Account', 'Your Password', :login) # # # CRAM MD5 # Net::SMTP.start('your.smtp.server', 25, 'mail.from.domain', # 'Your Account', 'Your Password', :cram_md5) # class SMTP Revision = %q$Revision: 46793 $.split[1] # The default SMTP port number, 25. def SMTP.default_port 25 end # The default mail submission port number, 587. def SMTP.default_submission_port 587 end # The default SMTPS port number, 465. def SMTP.default_tls_port 465 end class << self alias default_ssl_port default_tls_port end def SMTP.default_ssl_context OpenSSL::SSL::SSLContext.new end # # Creates a new Net::SMTP object. # # +address+ is the hostname or ip address of your SMTP # server. +port+ is the port to connect to; it defaults to # port 25. # # This method does not open the TCP connection. You can use # SMTP.start instead of SMTP.new if you want to do everything # at once. Otherwise, follow SMTP.new with SMTP#start. # def initialize(address, port = nil) @address = address @port = (port || SMTP.default_port) @esmtp = true @capabilities = nil @socket = nil @started = false @open_timeout = 30 @read_timeout = 60 @error_occurred = false @debug_output = nil @tls = false @starttls = false @ssl_context = nil end # Provide human-readable stringification of class state. def inspect "#<#{self.class} #{@address}:#{@port} started=#{@started}>" end # # Set whether to use ESMTP or not. This should be done before # calling #start. Note that if #start is called in ESMTP mode, # and the connection fails due to a ProtocolError, the SMTP # object will automatically switch to plain SMTP mode and # retry (but not vice versa). # attr_accessor :esmtp # +true+ if the SMTP object uses ESMTP (which it does by default). alias :esmtp? :esmtp # true if server advertises STARTTLS. # You cannot get valid value before opening SMTP session. def capable_starttls? capable?('STARTTLS') end def capable?(key) return nil unless @capabilities @capabilities[key] ? true : false end private :capable? # true if server advertises AUTH PLAIN. # You cannot get valid value before opening SMTP session. def capable_plain_auth? auth_capable?('PLAIN') end # true if server advertises AUTH LOGIN. # You cannot get valid value before opening SMTP session. def capable_login_auth? auth_capable?('LOGIN') end # true if server advertises AUTH CRAM-MD5. # You cannot get valid value before opening SMTP session. def capable_cram_md5_auth? auth_capable?('CRAM-MD5') end def auth_capable?(type) return nil unless @capabilities return false unless @capabilities['AUTH'] @capabilities['AUTH'].include?(type) end private :auth_capable? # Returns supported authentication methods on this server. # You cannot get valid value before opening SMTP session. def capable_auth_types return [] unless @capabilities return [] unless @capabilities['AUTH'] @capabilities['AUTH'] end # true if this object uses SMTP/TLS (SMTPS). def tls? @tls end alias ssl? tls? # Enables SMTP/TLS (SMTPS: SMTP over direct TLS connection) for # this object. Must be called before the connection is established # to have any effect. +context+ is a OpenSSL::SSL::SSLContext object. def enable_tls(context = SMTP.default_ssl_context) raise 'openssl library not installed' unless defined?(OpenSSL) raise ArgumentError, "SMTPS and STARTTLS is exclusive" if @starttls @tls = true @ssl_context = context end alias enable_ssl enable_tls # Disables SMTP/TLS for this object. Must be called before the # connection is established to have any effect. def disable_tls @tls = false @ssl_context = nil end alias disable_ssl disable_tls # Returns truth value if this object uses STARTTLS. # If this object always uses STARTTLS, returns :always. # If this object uses STARTTLS when the server support TLS, returns :auto. def starttls? @starttls end # true if this object uses STARTTLS. def starttls_always? @starttls == :always end # true if this object uses STARTTLS when server advertises STARTTLS. def starttls_auto? @starttls == :auto end # Enables SMTP/TLS (STARTTLS) for this object. # +context+ is a OpenSSL::SSL::SSLContext object. def enable_starttls(context = SMTP.default_ssl_context) raise 'openssl library not installed' unless defined?(OpenSSL) raise ArgumentError, "SMTPS and STARTTLS is exclusive" if @tls @starttls = :always @ssl_context = context end # Enables SMTP/TLS (STARTTLS) for this object if server accepts. # +context+ is a OpenSSL::SSL::SSLContext object. def enable_starttls_auto(context = SMTP.default_ssl_context) raise 'openssl library not installed' unless defined?(OpenSSL) raise ArgumentError, "SMTPS and STARTTLS is exclusive" if @tls @starttls = :auto @ssl_context = context end # Disables SMTP/TLS (STARTTLS) for this object. Must be called # before the connection is established to have any effect. def disable_starttls @starttls = false @ssl_context = nil end # The address of the SMTP server to connect to. attr_reader :address # The port number of the SMTP server to connect to. attr_reader :port # Seconds to wait while attempting to open a connection. # If the connection cannot be opened within this time, a # Net::OpenTimeout is raised. The default value is 30 seconds. attr_accessor :open_timeout # Seconds to wait while reading one block (by one read(2) call). # If the read(2) call does not complete within this time, a # Net::ReadTimeout is raised. The default value is 60 seconds. attr_reader :read_timeout # Set the number of seconds to wait until timing-out a read(2) # call. def read_timeout=(sec) @socket.read_timeout = sec if @socket @read_timeout = sec end # # WARNING: This method causes serious security holes. # Use this method for only debugging. # # Set an output stream for debug logging. # You must call this before #start. # # # example # smtp = Net::SMTP.new(addr, port) # smtp.set_debug_output $stderr # smtp.start do |smtp| # .... # end # def debug_output=(arg) @debug_output = arg end alias set_debug_output debug_output= # # SMTP session control # # # Creates a new Net::SMTP object and connects to the server. # # This method is equivalent to: # # Net::SMTP.new(address, port).start(helo_domain, account, password, authtype) # # === Example # # Net::SMTP.start('your.smtp.server') do |smtp| # smtp.send_message msgstr, 'from@example.com', ['dest@example.com'] # end # # === Block Usage # # If called with a block, the newly-opened Net::SMTP object is yielded # to the block, and automatically closed when the block finishes. If called # without a block, the newly-opened Net::SMTP object is returned to # the caller, and it is the caller's responsibility to close it when # finished. # # === Parameters # # +address+ is the hostname or ip address of your smtp server. # # +port+ is the port to connect to; it defaults to port 25. # # +helo+ is the _HELO_ _domain_ provided by the client to the # server (see overview comments); it defaults to 'localhost'. # # The remaining arguments are used for SMTP authentication, if required # or desired. +user+ is the account name; +secret+ is your password # or other authentication token; and +authtype+ is the authentication # type, one of :plain, :login, or :cram_md5. See the discussion of # SMTP Authentication in the overview notes. # # === Errors # # This method may raise: # # * Net::SMTPAuthenticationError # * Net::SMTPServerBusy # * Net::SMTPSyntaxError # * Net::SMTPFatalError # * Net::SMTPUnknownError # * Net::OpenTimeout # * Net::ReadTimeout # * IOError # def SMTP.start(address, port = nil, helo = 'localhost', user = nil, secret = nil, authtype = nil, &block) # :yield: smtp new(address, port).start(helo, user, secret, authtype, &block) end # +true+ if the SMTP session has been started. def started? @started end # # Opens a TCP connection and starts the SMTP session. # # === Parameters # # +helo+ is the _HELO_ _domain_ that you'll dispatch mails from; see # the discussion in the overview notes. # # If both of +user+ and +secret+ are given, SMTP authentication # will be attempted using the AUTH command. +authtype+ specifies # the type of authentication to attempt; it must be one of # :login, :plain, and :cram_md5. See the notes on SMTP Authentication # in the overview. # # === Block Usage # # When this methods is called with a block, the newly-started SMTP # object is yielded to the block, and automatically closed after # the block call finishes. Otherwise, it is the caller's # responsibility to close the session when finished. # # === Example # # This is very similar to the class method SMTP.start. # # require 'net/smtp' # smtp = Net::SMTP.new('smtp.mail.server', 25) # smtp.start(helo_domain, account, password, authtype) do |smtp| # smtp.send_message msgstr, 'from@example.com', ['dest@example.com'] # end # # The primary use of this method (as opposed to SMTP.start) # is probably to set debugging (#set_debug_output) or ESMTP # (#esmtp=), which must be done before the session is # started. # # === Errors # # If session has already been started, an IOError will be raised. # # This method may raise: # # * Net::SMTPAuthenticationError # * Net::SMTPServerBusy # * Net::SMTPSyntaxError # * Net::SMTPFatalError # * Net::SMTPUnknownError # * Net::OpenTimeout # * Net::ReadTimeout # * IOError # def start(helo = 'localhost', user = nil, secret = nil, authtype = nil) # :yield: smtp if block_given? begin do_start helo, user, secret, authtype return yield(self) ensure do_finish end else do_start helo, user, secret, authtype return self end end # Finishes the SMTP session and closes TCP connection. # Raises IOError if not started. def finish raise IOError, 'not yet started' unless started? do_finish end private def tcp_socket(address, port) TCPSocket.open address, port end def do_start(helo_domain, user, secret, authtype) raise IOError, 'SMTP session already started' if @started if user or secret check_auth_method(authtype || DEFAULT_AUTH_TYPE) check_auth_args user, secret end s = Timeout.timeout(@open_timeout, Net::OpenTimeout) do tcp_socket(@address, @port) end logging "Connection opened: #{@address}:#{@port}" @socket = new_internet_message_io(tls? ? tlsconnect(s) : s) check_response critical { recv_response() } do_helo helo_domain if starttls_always? or (capable_starttls? and starttls_auto?) unless capable_starttls? raise SMTPUnsupportedCommand, "STARTTLS is not supported on this server" end starttls @socket = new_internet_message_io(tlsconnect(s)) # helo response may be different after STARTTLS do_helo helo_domain end authenticate user, secret, (authtype || DEFAULT_AUTH_TYPE) if user @started = true ensure unless @started # authentication failed, cancel connection. s.close if s and not s.closed? @socket = nil end end def ssl_socket(socket, context) OpenSSL::SSL::SSLSocket.new socket, context end def tlsconnect(s) verified = false s = ssl_socket(s, @ssl_context) logging "TLS connection started" s.sync_close = true s.connect if @ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE s.post_connection_check(@address) end verified = true s ensure s.close unless verified end def new_internet_message_io(s) io = InternetMessageIO.new(s) io.read_timeout = @read_timeout io.debug_output = @debug_output io end def do_helo(helo_domain) res = @esmtp ? ehlo(helo_domain) : helo(helo_domain) @capabilities = res.capabilities rescue SMTPError if @esmtp @esmtp = false @error_occurred = false retry end raise end def do_finish quit if @socket and not @socket.closed? and not @error_occurred ensure @started = false @error_occurred = false @socket.close if @socket and not @socket.closed? @socket = nil end # # Message Sending # public # # Sends +msgstr+ as a message. Single CR ("\r") and LF ("\n") found # in the +msgstr+, are converted into the CR LF pair. You cannot send a # binary message with this method. +msgstr+ should include both # the message headers and body. # # +from_addr+ is a String representing the source mail address. # # +to_addr+ is a String or Strings or Array of Strings, representing # the destination mail address or addresses. # # === Example # # Net::SMTP.start('smtp.example.com') do |smtp| # smtp.send_message msgstr, # 'from@example.com', # ['dest@example.com', 'dest2@example.com'] # end # # === Errors # # This method may raise: # # * Net::SMTPServerBusy # * Net::SMTPSyntaxError # * Net::SMTPFatalError # * Net::SMTPUnknownError # * Net::ReadTimeout # * IOError # def send_message(msgstr, from_addr, *to_addrs) raise IOError, 'closed session' unless @socket mailfrom from_addr rcptto_list(to_addrs) {data msgstr} end alias send_mail send_message alias sendmail send_message # obsolete # # Opens a message writer stream and gives it to the block. # The stream is valid only in the block, and has these methods: # # puts(str = ''):: outputs STR and CR LF. # print(str):: outputs STR. # printf(fmt, *args):: outputs sprintf(fmt,*args). # write(str):: outputs STR and returns the length of written bytes. # <<(str):: outputs STR and returns self. # # If a single CR ("\r") or LF ("\n") is found in the message, # it is converted to the CR LF pair. You cannot send a binary # message with this method. # # === Parameters # # +from_addr+ is a String representing the source mail address. # # +to_addr+ is a String or Strings or Array of Strings, representing # the destination mail address or addresses. # # === Example # # Net::SMTP.start('smtp.example.com', 25) do |smtp| # smtp.open_message_stream('from@example.com', ['dest@example.com']) do |f| # f.puts 'From: from@example.com' # f.puts 'To: dest@example.com' # f.puts 'Subject: test message' # f.puts # f.puts 'This is a test message.' # end # end # # === Errors # # This method may raise: # # * Net::SMTPServerBusy # * Net::SMTPSyntaxError # * Net::SMTPFatalError # * Net::SMTPUnknownError # * Net::ReadTimeout # * IOError # def open_message_stream(from_addr, *to_addrs, &block) # :yield: stream raise IOError, 'closed session' unless @socket mailfrom from_addr rcptto_list(to_addrs) {data(&block)} end alias ready open_message_stream # obsolete # # Authentication # public DEFAULT_AUTH_TYPE = :plain def authenticate(user, secret, authtype = DEFAULT_AUTH_TYPE) check_auth_method authtype check_auth_args user, secret send auth_method(authtype), user, secret end def auth_plain(user, secret) check_auth_args user, secret res = critical { get_response('AUTH PLAIN ' + base64_encode("\0#{user}\0#{secret}")) } check_auth_response res res end def auth_login(user, secret) check_auth_args user, secret res = critical { check_auth_continue get_response('AUTH LOGIN') check_auth_continue get_response(base64_encode(user)) get_response(base64_encode(secret)) } check_auth_response res res end def auth_cram_md5(user, secret) check_auth_args user, secret res = critical { res0 = get_response('AUTH CRAM-MD5') check_auth_continue res0 crammed = cram_md5_response(secret, res0.cram_md5_challenge) get_response(base64_encode("#{user} #{crammed}")) } check_auth_response res res end private def check_auth_method(type) unless respond_to?(auth_method(type), true) raise ArgumentError, "wrong authentication type #{type}" end end def auth_method(type) "auth_#{type.to_s.downcase}".intern end def check_auth_args(user, secret, authtype = DEFAULT_AUTH_TYPE) unless user raise ArgumentError, 'SMTP-AUTH requested but missing user name' end unless secret raise ArgumentError, 'SMTP-AUTH requested but missing secret phrase' end end def base64_encode(str) # expects "str" may not become too long [str].pack('m').gsub(/\s+/, '') end IMASK = 0x36 OMASK = 0x5c # CRAM-MD5: [RFC2195] def cram_md5_response(secret, challenge) tmp = Digest::MD5.digest(cram_secret(secret, IMASK) + challenge) Digest::MD5.hexdigest(cram_secret(secret, OMASK) + tmp) end CRAM_BUFSIZE = 64 def cram_secret(secret, mask) secret = Digest::MD5.digest(secret) if secret.size > CRAM_BUFSIZE buf = secret.ljust(CRAM_BUFSIZE, "\0") 0.upto(buf.size - 1) do |i| buf[i] = (buf[i].ord ^ mask).chr end buf end # # SMTP command dispatcher # public # Aborts the current mail transaction def rset getok('RSET') end def starttls getok('STARTTLS') end def helo(domain) getok("HELO #{domain}") end def ehlo(domain) getok("EHLO #{domain}") end def mailfrom(from_addr) if $SAFE > 0 raise SecurityError, 'tainted from_addr' if from_addr.tainted? end getok("MAIL FROM:<#{from_addr}>") end def rcptto_list(to_addrs) raise ArgumentError, 'mail destination not given' if to_addrs.empty? ok_users = [] unknown_users = [] to_addrs.flatten.each do |addr| begin rcptto addr rescue SMTPAuthenticationError unknown_users << addr.dump else ok_users << addr end end raise ArgumentError, 'mail destination not given' if ok_users.empty? ret = yield unless unknown_users.empty? raise SMTPAuthenticationError, "failed to deliver for #{unknown_users.join(', ')}" end ret end def rcptto(to_addr) if $SAFE > 0 raise SecurityError, 'tainted to_addr' if to_addr.tainted? end getok("RCPT TO:<#{to_addr}>") end # This method sends a message. # If +msgstr+ is given, sends it as a message. # If block is given, yield a message writer stream. # You must write message before the block is closed. # # # Example 1 (by string) # smtp.data(<"/") {|i,o,e,t| # p o.read.chomp #=> "/" # } # # wait_thr.value waits for the termination of the process. # The block form also waits for the process when it returns. # # Closing stdin, stdout and stderr does not wait for the process to complete. # # You should be careful to avoid deadlocks. # Since pipes are fixed length buffers, # Open3.popen3("prog") {|i, o, e, t| o.read } deadlocks if # the program generates too much output on stderr. # You should read stdout and stderr simultaneously (using threads or IO.select). # However, if you don't need stderr output, you can use Open3.popen2. # If merged stdout and stderr output is not a problem, you can use Open3.popen2e. # If you really need stdout and stderr output as separate strings, you can consider Open3.capture3. # def popen3(*cmd, **opts, &block) in_r, in_w = IO.pipe opts[:in] = in_r in_w.sync = true out_r, out_w = IO.pipe opts[:out] = out_w err_r, err_w = IO.pipe opts[:err] = err_w popen_run(cmd, opts, [in_r, out_w, err_w], [in_w, out_r, err_r], &block) end module_function :popen3 # Open3.popen2 is similar to Open3.popen3 except that it doesn't create a pipe for # the standard error stream. # # Block form: # # Open3.popen2([env,] cmd... [, opts]) {|stdin, stdout, wait_thr| # pid = wait_thr.pid # pid of the started process. # ... # exit_status = wait_thr.value # Process::Status object returned. # } # # Non-block form: # # stdin, stdout, wait_thr = Open3.popen2([env,] cmd... [, opts]) # ... # stdin.close # stdin and stdout should be closed explicitly in this form. # stdout.close # # See Process.spawn for the optional hash arguments _env_ and _opts_. # # Example: # # Open3.popen2("wc -c") {|i,o,t| # i.print "answer to life the universe and everything" # i.close # p o.gets #=> "42\n" # } # # Open3.popen2("bc -q") {|i,o,t| # i.puts "obase=13" # i.puts "6 * 9" # p o.gets #=> "42\n" # } # # Open3.popen2("dc") {|i,o,t| # i.print "42P" # i.close # p o.read #=> "*" # } # def popen2(*cmd, **opts, &block) in_r, in_w = IO.pipe opts[:in] = in_r in_w.sync = true out_r, out_w = IO.pipe opts[:out] = out_w popen_run(cmd, opts, [in_r, out_w], [in_w, out_r], &block) end module_function :popen2 # Open3.popen2e is similar to Open3.popen3 except that it merges # the standard output stream and the standard error stream. # # Block form: # # Open3.popen2e([env,] cmd... [, opts]) {|stdin, stdout_and_stderr, wait_thr| # pid = wait_thr.pid # pid of the started process. # ... # exit_status = wait_thr.value # Process::Status object returned. # } # # Non-block form: # # stdin, stdout_and_stderr, wait_thr = Open3.popen2e([env,] cmd... [, opts]) # ... # stdin.close # stdin and stdout_and_stderr should be closed explicitly in this form. # stdout_and_stderr.close # # See Process.spawn for the optional hash arguments _env_ and _opts_. # # Example: # # check gcc warnings # source = "foo.c" # Open3.popen2e("gcc", "-Wall", source) {|i,oe,t| # oe.each {|line| # if /warning/ =~ line # ... # end # } # } # def popen2e(*cmd, **opts, &block) in_r, in_w = IO.pipe opts[:in] = in_r in_w.sync = true out_r, out_w = IO.pipe opts[[:out, :err]] = out_w popen_run(cmd, opts, [in_r, out_w], [in_w, out_r], &block) end module_function :popen2e def popen_run(cmd, opts, child_io, parent_io) # :nodoc: pid = spawn(*cmd, opts) wait_thr = Process.detach(pid) child_io.each {|io| io.close } result = [*parent_io, wait_thr] if defined? yield begin return yield(*result) ensure parent_io.each{|io| io.close unless io.closed?} wait_thr.join end end result end module_function :popen_run class << self private :popen_run end # Open3.capture3 captures the standard output and the standard error of a command. # # stdout_str, stderr_str, status = Open3.capture3([env,] cmd... [, opts]) # # The arguments env, cmd and opts are passed to Open3.popen3 except # opts[:stdin_data] and opts[:binmode]. See Process.spawn. # # If opts[:stdin_data] is specified, it is sent to the command's standard input. # # If opts[:binmode] is true, internal pipes are set to binary mode. # # Examples: # # # dot is a command of graphviz. # graph = <<'End' # digraph g { # a -> b # } # End # drawn_graph, dot_log = Open3.capture3("dot -v", :stdin_data=>graph) # # o, e, s = Open3.capture3("echo abc; sort >&2", :stdin_data=>"foo\nbar\nbaz\n") # p o #=> "abc\n" # p e #=> "bar\nbaz\nfoo\n" # p s #=> # # # # generate a thumbnail image using the convert command of ImageMagick. # # However, if the image is really stored in a file, # # system("convert", "-thumbnail", "80", "png:#{filename}", "png:-") is better # # because of reduced memory consumption. # # But if the image is stored in a DB or generated by the gnuplot Open3.capture2 example, # # Open3.capture3 should be considered. # # # image = File.read("/usr/share/openclipart/png/animals/mammals/sheep-md-v0.1.png", :binmode=>true) # thumbnail, err, s = Open3.capture3("convert -thumbnail 80 png:- png:-", :stdin_data=>image, :binmode=>true) # if s.success? # STDOUT.binmode; print thumbnail # end # def capture3(*cmd, stdin_data: '', binmode: false, **opts) popen3(*cmd, opts) {|i, o, e, t| if binmode i.binmode o.binmode e.binmode end out_reader = Thread.new { o.read } err_reader = Thread.new { e.read } begin i.write stdin_data rescue Errno::EPIPE end i.close [out_reader.value, err_reader.value, t.value] } end module_function :capture3 # Open3.capture2 captures the standard output of a command. # # stdout_str, status = Open3.capture2([env,] cmd... [, opts]) # # The arguments env, cmd and opts are passed to Open3.popen3 except # opts[:stdin_data] and opts[:binmode]. See Process.spawn. # # If opts[:stdin_data] is specified, it is sent to the command's standard input. # # If opts[:binmode] is true, internal pipes are set to binary mode. # # Example: # # # factor is a command for integer factorization. # o, s = Open3.capture2("factor", :stdin_data=>"42") # p o #=> "42: 2 3 7\n" # # # generate x**2 graph in png using gnuplot. # gnuplot_commands = <<"End" # set terminal png # plot x**2, "-" with lines # 1 14 # 2 1 # 3 8 # 4 5 # e # End # image, s = Open3.capture2("gnuplot", :stdin_data=>gnuplot_commands, :binmode=>true) # def capture2(*cmd, stdin_data: nil, binmode: false, **opts) popen2(*cmd, opts) {|i, o, t| if binmode i.binmode o.binmode end out_reader = Thread.new { o.read } if stdin_data begin i.write stdin_data rescue Errno::EPIPE end end i.close [out_reader.value, t.value] } end module_function :capture2 # Open3.capture2e captures the standard output and the standard error of a command. # # stdout_and_stderr_str, status = Open3.capture2e([env,] cmd... [, opts]) # # The arguments env, cmd and opts are passed to Open3.popen3 except # opts[:stdin_data] and opts[:binmode]. See Process.spawn. # # If opts[:stdin_data] is specified, it is sent to the command's standard input. # # If opts[:binmode] is true, internal pipes are set to binary mode. # # Example: # # # capture make log # make_log, s = Open3.capture2e("make") # def capture2e(*cmd, stdin_data: nil, binmode: false, **opts) popen2e(*cmd, opts) {|i, oe, t| if binmode i.binmode oe.binmode end outerr_reader = Thread.new { oe.read } if stdin_data begin i.write stdin_data rescue Errno::EPIPE end end i.close [outerr_reader.value, t.value] } end module_function :capture2e # Open3.pipeline_rw starts a list of commands as a pipeline with pipes # which connect to stdin of the first command and stdout of the last command. # # Open3.pipeline_rw(cmd1, cmd2, ... [, opts]) {|first_stdin, last_stdout, wait_threads| # ... # } # # first_stdin, last_stdout, wait_threads = Open3.pipeline_rw(cmd1, cmd2, ... [, opts]) # ... # first_stdin.close # last_stdout.close # # Each cmd is a string or an array. # If it is an array, the elements are passed to Process.spawn. # # cmd: # commandline command line string which is passed to a shell # [env, commandline, opts] command line string which is passed to a shell # [env, cmdname, arg1, ..., opts] command name and one or more arguments (no shell) # [env, [cmdname, argv0], arg1, ..., opts] command name and arguments including argv[0] (no shell) # # Note that env and opts are optional, as for Process.spawn. # # The options to pass to Process.spawn are constructed by merging # +opts+, the last hash element of the array, and # specifications for the pipes between each of the commands. # # Example: # # Open3.pipeline_rw("tr -dc A-Za-z", "wc -c") {|i, o, ts| # i.puts "All persons more than a mile high to leave the court." # i.close # p o.gets #=> "42\n" # } # # Open3.pipeline_rw("sort", "cat -n") {|stdin, stdout, wait_thrs| # stdin.puts "foo" # stdin.puts "bar" # stdin.puts "baz" # stdin.close # send EOF to sort. # p stdout.read #=> " 1\tbar\n 2\tbaz\n 3\tfoo\n" # } def pipeline_rw(*cmds, **opts, &block) in_r, in_w = IO.pipe opts[:in] = in_r in_w.sync = true out_r, out_w = IO.pipe opts[:out] = out_w pipeline_run(cmds, opts, [in_r, out_w], [in_w, out_r], &block) end module_function :pipeline_rw # Open3.pipeline_r starts a list of commands as a pipeline with a pipe # which connects to stdout of the last command. # # Open3.pipeline_r(cmd1, cmd2, ... [, opts]) {|last_stdout, wait_threads| # ... # } # # last_stdout, wait_threads = Open3.pipeline_r(cmd1, cmd2, ... [, opts]) # ... # last_stdout.close # # Each cmd is a string or an array. # If it is an array, the elements are passed to Process.spawn. # # cmd: # commandline command line string which is passed to a shell # [env, commandline, opts] command line string which is passed to a shell # [env, cmdname, arg1, ..., opts] command name and one or more arguments (no shell) # [env, [cmdname, argv0], arg1, ..., opts] command name and arguments including argv[0] (no shell) # # Note that env and opts are optional, as for Process.spawn. # # Example: # # Open3.pipeline_r("zcat /var/log/apache2/access.log.*.gz", # [{"LANG"=>"C"}, "grep", "GET /favicon.ico"], # "logresolve") {|o, ts| # o.each_line {|line| # ... # } # } # # Open3.pipeline_r("yes", "head -10") {|o, ts| # p o.read #=> "y\ny\ny\ny\ny\ny\ny\ny\ny\ny\n" # p ts[0].value #=> # # p ts[1].value #=> # # } # def pipeline_r(*cmds, **opts, &block) out_r, out_w = IO.pipe opts[:out] = out_w pipeline_run(cmds, opts, [out_w], [out_r], &block) end module_function :pipeline_r # Open3.pipeline_w starts a list of commands as a pipeline with a pipe # which connects to stdin of the first command. # # Open3.pipeline_w(cmd1, cmd2, ... [, opts]) {|first_stdin, wait_threads| # ... # } # # first_stdin, wait_threads = Open3.pipeline_w(cmd1, cmd2, ... [, opts]) # ... # first_stdin.close # # Each cmd is a string or an array. # If it is an array, the elements are passed to Process.spawn. # # cmd: # commandline command line string which is passed to a shell # [env, commandline, opts] command line string which is passed to a shell # [env, cmdname, arg1, ..., opts] command name and one or more arguments (no shell) # [env, [cmdname, argv0], arg1, ..., opts] command name and arguments including argv[0] (no shell) # # Note that env and opts are optional, as for Process.spawn. # # Example: # # Open3.pipeline_w("bzip2 -c", :out=>"/tmp/hello.bz2") {|i, ts| # i.puts "hello" # } # def pipeline_w(*cmds, **opts, &block) in_r, in_w = IO.pipe opts[:in] = in_r in_w.sync = true pipeline_run(cmds, opts, [in_r], [in_w], &block) end module_function :pipeline_w # Open3.pipeline_start starts a list of commands as a pipeline. # No pipes are created for stdin of the first command and # stdout of the last command. # # Open3.pipeline_start(cmd1, cmd2, ... [, opts]) {|wait_threads| # ... # } # # wait_threads = Open3.pipeline_start(cmd1, cmd2, ... [, opts]) # ... # # Each cmd is a string or an array. # If it is an array, the elements are passed to Process.spawn. # # cmd: # commandline command line string which is passed to a shell # [env, commandline, opts] command line string which is passed to a shell # [env, cmdname, arg1, ..., opts] command name and one or more arguments (no shell) # [env, [cmdname, argv0], arg1, ..., opts] command name and arguments including argv[0] (no shell) # # Note that env and opts are optional, as for Process.spawn. # # Example: # # # Run xeyes in 10 seconds. # Open3.pipeline_start("xeyes") {|ts| # sleep 10 # t = ts[0] # Process.kill("TERM", t.pid) # p t.value #=> # # } # # # Convert pdf to ps and send it to a printer. # # Collect error message of pdftops and lpr. # pdf_file = "paper.pdf" # printer = "printer-name" # err_r, err_w = IO.pipe # Open3.pipeline_start(["pdftops", pdf_file, "-"], # ["lpr", "-P#{printer}"], # :err=>err_w) {|ts| # err_w.close # p err_r.read # error messages of pdftops and lpr. # } # def pipeline_start(*cmds, **opts, &block) if block pipeline_run(cmds, opts, [], [], &block) else ts, = pipeline_run(cmds, opts, [], []) ts end end module_function :pipeline_start # Open3.pipeline starts a list of commands as a pipeline. # It waits for the completion of the commands. # No pipes are created for stdin of the first command and # stdout of the last command. # # status_list = Open3.pipeline(cmd1, cmd2, ... [, opts]) # # Each cmd is a string or an array. # If it is an array, the elements are passed to Process.spawn. # # cmd: # commandline command line string which is passed to a shell # [env, commandline, opts] command line string which is passed to a shell # [env, cmdname, arg1, ..., opts] command name and one or more arguments (no shell) # [env, [cmdname, argv0], arg1, ..., opts] command name and arguments including argv[0] (no shell) # # Note that env and opts are optional, as Process.spawn. # # Example: # # fname = "/usr/share/man/man1/ruby.1.gz" # p Open3.pipeline(["zcat", fname], "nroff -man", "less") # #=> [#, # # #, # # #] # # fname = "/usr/share/man/man1/ls.1.gz" # Open3.pipeline(["zcat", fname], "nroff -man", "colcrt") # # # convert PDF to PS and send to a printer by lpr # pdf_file = "paper.pdf" # printer = "printer-name" # Open3.pipeline(["pdftops", pdf_file, "-"], # ["lpr", "-P#{printer}"]) # # # count lines # Open3.pipeline("sort", "uniq -c", :in=>"names.txt", :out=>"count") # # # cyclic pipeline # r,w = IO.pipe # w.print "ibase=14\n10\n" # Open3.pipeline("bc", "tee /dev/tty", :in=>r, :out=>w) # #=> 14 # # 18 # # 22 # # 30 # # 42 # # 58 # # 78 # # 106 # # 202 # def pipeline(*cmds, **opts) pipeline_run(cmds, opts, [], []) {|ts| ts.map {|t| t.value } } end module_function :pipeline def pipeline_run(cmds, pipeline_opts, child_io, parent_io) # :nodoc: if cmds.empty? raise ArgumentError, "no commands" end opts_base = pipeline_opts.dup opts_base.delete :in opts_base.delete :out wait_thrs = [] r = nil cmds.each_with_index {|cmd, i| cmd_opts = opts_base.dup if String === cmd cmd = [cmd] else cmd_opts.update cmd.pop if Hash === cmd.last end if i == 0 if !cmd_opts.include?(:in) if pipeline_opts.include?(:in) cmd_opts[:in] = pipeline_opts[:in] end end else cmd_opts[:in] = r end if i != cmds.length - 1 r2, w2 = IO.pipe cmd_opts[:out] = w2 else if !cmd_opts.include?(:out) if pipeline_opts.include?(:out) cmd_opts[:out] = pipeline_opts[:out] end end end pid = spawn(*cmd, cmd_opts) wait_thrs << Process.detach(pid) r.close if r w2.close if w2 r = r2 } result = parent_io + [wait_thrs] child_io.each {|io| io.close } if defined? yield begin return yield(*result) ensure parent_io.each{|io| io.close unless io.closed?} wait_thrs.each {|t| t.join } end end result end module_function :pipeline_run class << self private :pipeline_run end end PK!%2.2.0/drb/timeridconv.rbnu[require 'drb/drb' require 'monitor' module DRb # Timer id conversion keeps objects alive for a certain amount of time after # their last access. The default time period is 600 seconds and can be # changed upon initialization. # # To use TimerIdConv: # # DRb.install_id_conv TimerIdConv.new 60 # one minute class TimerIdConv < DRbIdConv class TimerHolder2 # :nodoc: include MonitorMixin class InvalidIndexError < RuntimeError; end def initialize(keeping=600) super() @sentinel = Object.new @gc = {} @renew = {} @keeping = keeping @expires = Time.now + @keeping end def add(obj) synchronize do rotate key = obj.__id__ @renew[key] = obj return key end end def fetch(key, dv=@sentinel) synchronize do rotate obj = peek(key) if obj == @sentinel return dv unless dv == @sentinel raise InvalidIndexError end @renew[key] = obj # KeepIt return obj end end private def peek(key) synchronize do return @renew.fetch(key) { @gc.fetch(key, @sentinel) } end end def rotate synchronize do return if @expires > Time.now @gc = @renew # GCed @renew = {} @expires = Time.now + @keeping end end def keeper Thread.new do loop do rotate sleep(@keeping) end end end end # Creates a new TimerIdConv which will hold objects for +keeping+ seconds. def initialize(keeping=600) @holder = TimerHolder2.new(keeping) end def to_obj(ref) # :nodoc: return super if ref.nil? @holder.fetch(ref) rescue TimerHolder2::InvalidIndexError raise "invalid reference" end def to_id(obj) # :nodoc: return @holder.add(obj) end end end # DRb.install_id_conv(TimerIdConv.new) PK!c2.2.0/drb/eq.rbnu[module DRb class DRbObject # :nodoc: def ==(other) return false unless DRbObject === other (@ref == other.__drbref) && (@uri == other.__drburi) end def hash [@uri, @ref].hash end alias eql? == end end PK!g|2.2.0/drb/invokemethod.rbnu[# for ruby-1.8.0 module DRb # :nodoc: all class DRbServer module InvokeMethod18Mixin def block_yield(x) if x.size == 1 && x[0].class == Array x[0] = DRbArray.new(x[0]) end @block.call(*x) end def perform_with_block @obj.__send__(@msg_id, *@argv) do |*x| jump_error = nil begin block_value = block_yield(x) rescue LocalJumpError jump_error = $! end if jump_error case jump_error.reason when :break break(jump_error.exit_value) else raise jump_error end end block_value end end end end end PK!Z1+2.2.0/drb/extservm.rbnu[=begin external service manager Copyright (c) 2000 Masatoshi SEKI =end require 'drb/drb' require 'thread' require 'monitor' module DRb class ExtServManager include DRbUndumped include MonitorMixin @@command = {} def self.command @@command end def self.command=(cmd) @@command = cmd end def initialize super() @cond = new_cond @servers = {} @waiting = [] @queue = Queue.new @thread = invoke_thread @uri = nil end attr_accessor :uri def service(name) synchronize do while true server = @servers[name] return server if server && server.alive? invoke_service(name) @cond.wait end end end def regist(name, ro) synchronize do @servers[name] = ro @cond.signal end self end def unregist(name) synchronize do @servers.delete(name) end end private def invoke_thread Thread.new do while true name = @queue.pop invoke_service_command(name, @@command[name]) end end end def invoke_service(name) @queue.push(name) end def invoke_service_command(name, command) raise "invalid command. name: #{name}" unless command synchronize do return if @servers.include?(name) @servers[name] = false end uri = @uri || DRb.uri if command.respond_to? :to_ary command = command.to_ary + [uri, name] pid = spawn(*command) else pid = spawn("#{command} #{uri} #{name}") end th = Process.detach(pid) th[:drb_service] = name th end end end PK!rr 2.2.0/drb/gw.rbnu[require 'drb/drb' require 'monitor' module DRb # Gateway id conversion forms a gateway between different DRb protocols or # networks. # # The gateway needs to install this id conversion and create servers for # each of the protocols or networks it will be a gateway between. It then # needs to create a server that attaches to each of these networks. For # example: # # require 'drb/drb' # require 'drb/unix' # require 'drb/gw' # # DRb.install_id_conv DRb::GWIdConv.new # gw = DRb::GW.new # s1 = DRb::DRbServer.new 'drbunix:/path/to/gateway', gw # s2 = DRb::DRbServer.new 'druby://example:10000', gw # # s1.thread.join # s2.thread.join # # Each client must register services with the gateway, for example: # # DRb.start_service 'drbunix:', nil # an anonymous server # gw = DRbObject.new nil, 'drbunix:/path/to/gateway' # gw[:unix] = some_service # DRb.thread.join class GWIdConv < DRbIdConv def to_obj(ref) # :nodoc: if Array === ref && ref[0] == :DRbObject return DRbObject.new_with(ref[1], ref[2]) end super(ref) end end # The GW provides a synchronized store for participants in the gateway to # communicate. class GW include MonitorMixin # Creates a new GW def initialize super() @hash = {} end # Retrieves +key+ from the GW def [](key) synchronize do @hash[key] end end # Stores value +v+ at +key+ in the GW def []=(key, v) synchronize do @hash[key] = v end end end class DRbObject # :nodoc: def self._load(s) uri, ref = Marshal.load(s) if DRb.uri == uri return ref ? DRb.to_obj(ref) : DRb.front end self.new_with(DRb.uri, [:DRbObject, uri, ref]) end def _dump(lv) if DRb.uri == @uri if Array === @ref && @ref[0] == :DRbObject Marshal.dump([@ref[1], @ref[2]]) else Marshal.dump([@uri, @ref]) # ?? end else Marshal.dump([DRb.uri, [:DRbObject, @uri, @ref]]) end end end end =begin DRb.install_id_conv(DRb::GWIdConv.new) front = DRb::GW.new s1 = DRb::DRbServer.new('drbunix:/tmp/gw_b_a', front) s2 = DRb::DRbServer.new('drbunix:/tmp/gw_b_c', front) s1.thread.join s2.thread.join =end =begin # foo.rb require 'drb/drb' class Foo include DRbUndumped def initialize(name, peer=nil) @name = name @peer = peer end def ping(obj) puts "#{@name}: ping: #{obj.inspect}" @peer.ping(self) if @peer end end =end =begin # gw_a.rb require 'drb/unix' require 'foo' obj = Foo.new('a') DRb.start_service("drbunix:/tmp/gw_a", obj) robj = DRbObject.new_with_uri('drbunix:/tmp/gw_b_a') robj[:a] = obj DRb.thread.join =end =begin # gw_c.rb require 'drb/unix' require 'foo' foo = Foo.new('c', nil) DRb.start_service("drbunix:/tmp/gw_c", nil) robj = DRbObject.new_with_uri("drbunix:/tmp/gw_b_c") puts "c->b" a = robj[:a] sleep 2 a.ping(foo) DRb.thread.join =end PK!BvNN2.2.0/drb/acl.rbnu[# Copyright (c) 2000,2002,2003 Masatoshi SEKI # # acl.rb is copyrighted free software by Masatoshi SEKI. # You can redistribute it and/or modify it under the same terms as Ruby. require 'ipaddr' ## # Simple Access Control Lists. # # Access control lists are composed of "allow" and "deny" halves to control # access. Use "all" or "*" to match any address. To match a specific address # use any address or address mask that IPAddr can understand. # # Example: # # list = %w[ # deny all # allow 192.168.1.1 # allow ::ffff:192.168.1.2 # allow 192.168.1.3 # ] # # # From Socket#peeraddr, see also ACL#allow_socket? # addr = ["AF_INET", 10, "lc630", "192.168.1.3"] # # acl = ACL.new # p acl.allow_addr?(addr) # => true # # acl = ACL.new(list, ACL::DENY_ALLOW) # p acl.allow_addr?(addr) # => true class ACL ## # The current version of ACL VERSION=["2.0.0"] ## # An entry in an ACL class ACLEntry ## # Creates a new entry using +str+. # # +str+ may be "*" or "all" to match any address, an IP address string # to match a specific address, an IP address mask per IPAddr, or one # containing "*" to match part of an IPv4 address. def initialize(str) if str == '*' or str == 'all' @pat = [:all] elsif str.include?('*') @pat = [:name, dot_pat(str)] else begin @pat = [:ip, IPAddr.new(str)] rescue ArgumentError @pat = [:name, dot_pat(str)] end end end private ## # Creates a regular expression to match IPv4 addresses def dot_pat_str(str) list = str.split('.').collect { |s| (s == '*') ? '.+' : s } list.join("\\.") end private ## # Creates a Regexp to match an address. def dot_pat(str) exp = "^" + dot_pat_str(str) + "$" Regexp.new(exp) end public ## # Matches +addr+ against this entry. def match(addr) case @pat[0] when :all true when :ip begin ipaddr = IPAddr.new(addr[3]) ipaddr = ipaddr.ipv4_mapped if @pat[1].ipv6? && ipaddr.ipv4? rescue ArgumentError return false end (@pat[1].include?(ipaddr)) ? true : false when :name (@pat[1] =~ addr[2]) ? true : false else false end end end ## # A list of ACLEntry objects. Used to implement the allow and deny halves # of an ACL class ACLList ## # Creates an empty ACLList def initialize @list = [] end public ## # Matches +addr+ against each ACLEntry in this list. def match(addr) @list.each do |e| return true if e.match(addr) end false end public ## # Adds +str+ as an ACLEntry in this list def add(str) @list.push(ACLEntry.new(str)) end end ## # Default to deny DENY_ALLOW = 0 ## # Default to allow ALLOW_DENY = 1 ## # Creates a new ACL from +list+ with an evaluation +order+ of DENY_ALLOW or # ALLOW_DENY. # # An ACL +list+ is an Array of "allow" or "deny" and an address or address # mask or "all" or "*" to match any address: # # %w[ # deny all # allow 192.0.2.2 # allow 192.0.2.128/26 # ] def initialize(list=nil, order = DENY_ALLOW) @order = order @deny = ACLList.new @allow = ACLList.new install_list(list) if list end public ## # Allow connections from Socket +soc+? def allow_socket?(soc) allow_addr?(soc.peeraddr) end public ## # Allow connections from addrinfo +addr+? It must be formatted like # Socket#peeraddr: # # ["AF_INET", 10, "lc630", "192.0.2.1"] def allow_addr?(addr) case @order when DENY_ALLOW return true if @allow.match(addr) return false if @deny.match(addr) return true when ALLOW_DENY return false if @deny.match(addr) return true if @allow.match(addr) return false else false end end public ## # Adds +list+ of ACL entries to this ACL. def install_list(list) i = 0 while i < list.size permission, domain = list.slice(i,2) case permission.downcase when 'allow' @allow.add(domain) when 'deny' @deny.add(domain) else raise "Invalid ACL entry #{list}" end i += 2 end end end PK!>!i0.0.2.2.0/drb/ssl.rbnu[require 'socket' require 'openssl' require 'drb/drb' require 'singleton' module DRb # The protocol for DRb over an SSL socket # # The URI for a DRb socket over SSL is: # drbssl://:?. The option is optional class DRbSSLSocket < DRbTCPSocket # SSLConfig handles the needed SSL information for establishing a # DRbSSLSocket connection, including generating the X509 / RSA pair. # # An instance of this config can be passed to DRbSSLSocket.new, # DRbSSLSocket.open and DRbSSLSocket.open_server # # See DRb::DRbSSLSocket::SSLConfig.new for more details class SSLConfig # Default values for a SSLConfig instance. # # See DRb::DRbSSLSocket::SSLConfig.new for more details DEFAULT = { :SSLCertificate => nil, :SSLPrivateKey => nil, :SSLClientCA => nil, :SSLCACertificatePath => nil, :SSLCACertificateFile => nil, :SSLTmpDhCallback => nil, :SSLVerifyMode => ::OpenSSL::SSL::VERIFY_NONE, :SSLVerifyDepth => nil, :SSLVerifyCallback => nil, # custom verification :SSLCertificateStore => nil, # Must specify if you use auto generated certificate. :SSLCertName => nil, # e.g. [["CN","fqdn.example.com"]] :SSLCertComment => "Generated by Ruby/OpenSSL" } # Create a new DRb::DRbSSLSocket::SSLConfig instance # # The DRb::DRbSSLSocket will take either a +config+ Hash or an instance # of SSLConfig, and will setup the certificate for its session for the # configuration. If want it to generate a generic certificate, the bare # minimum is to provide the :SSLCertName # # === Config options # # From +config+ Hash: # # :SSLCertificate :: # An instance of OpenSSL::X509::Certificate. If this is not provided, # then a generic X509 is generated, with a correspond :SSLPrivateKey # # :SSLPrivateKey :: # A private key instance, like OpenSSL::PKey::RSA. This key must be # the key that signed the :SSLCertificate # # :SSLClientCA :: # An OpenSSL::X509::Certificate, or Array of certificates that will # used as ClientCAs in the SSL Context # # :SSLCACertificatePath :: # A path to the directory of CA certificates. The certificates must # be in PEM format. # # :SSLCACertificateFile :: # A path to a CA certificate file, in PEM format. # # :SSLTmpDhCallback :: # A DH callback. See OpenSSL::SSL::SSLContext.tmp_dh_callback # # :SSLVerifyMode :: # This is the SSL verification mode. See OpenSSL::SSL::VERIFY_* for # available modes. The default is OpenSSL::SSL::VERIFY_NONE # # :SSLVerifyDepth :: # Number of CA certificates to walk, when verifying a certificate # chain. # # :SSLVerifyCallback :: # A callback to be used for additional verification. See # OpenSSL::SSL::SSLContext.verify_callback # # :SSLCertificateStore :: # A OpenSSL::X509::Store used for verification of certificates # # :SSLCertName :: # Issuer name for the certificate. This is required when generating # the certificate (if :SSLCertificate and :SSLPrivateKey were not # given). The value of this is to be an Array of pairs: # # [["C", "Raleigh"], ["ST","North Carolina"], # ["CN","fqdn.example.com"]] # # See also OpenSSL::X509::Name # # :SSLCertComment :: # A comment to be used for generating the certificate. The default is # "Generated by Ruby/OpenSSL" # # # === Example # # These values can be added after the fact, like a Hash. # # require 'drb/ssl' # c = DRb::DRbSSLSocket::SSLConfig.new {} # c[:SSLCertificate] = # OpenSSL::X509::Certificate.new(File.read('mycert.crt')) # c[:SSLPrivateKey] = OpenSSL::PKey::RSA.new(File.read('mycert.key')) # c[:SSLVerifyMode] = OpenSSL::SSL::VERIFY_PEER # c[:SSLCACertificatePath] = "/etc/ssl/certs/" # c.setup_certificate # # or # # require 'drb/ssl' # c = DRb::DRbSSLSocket::SSLConfig.new({ # :SSLCertName => [["CN" => DRb::DRbSSLSocket.getservername]] # }) # c.setup_certificate # def initialize(config) @config = config @cert = config[:SSLCertificate] @pkey = config[:SSLPrivateKey] @ssl_ctx = nil end # A convenience method to access the values like a Hash def [](key); @config[key] || DEFAULT[key] end # Connect to IO +tcp+, with context of the current certificate # configuration def connect(tcp) ssl = ::OpenSSL::SSL::SSLSocket.new(tcp, @ssl_ctx) ssl.sync = true ssl.connect ssl end # Accept connection to IO +tcp+, with context of the current certificate # configuration def accept(tcp) ssl = OpenSSL::SSL::SSLSocket.new(tcp, @ssl_ctx) ssl.sync = true ssl.accept ssl end # Ensures that :SSLCertificate and :SSLPrivateKey have been provided # or that a new certificate is generated with the other parameters # provided. def setup_certificate if @cert && @pkey return end rsa = OpenSSL::PKey::RSA.new(1024){|p, n| next unless self[:verbose] case p when 0; $stderr.putc "." # BN_generate_prime when 1; $stderr.putc "+" # BN_generate_prime when 2; $stderr.putc "*" # searching good prime, # n = #of try, # but also data from BN_generate_prime when 3; $stderr.putc "\n" # found good prime, n==0 - p, n==1 - q, # but also data from BN_generate_prime else; $stderr.putc "*" # BN_generate_prime end } cert = OpenSSL::X509::Certificate.new cert.version = 3 cert.serial = 0 name = OpenSSL::X509::Name.new(self[:SSLCertName]) cert.subject = name cert.issuer = name cert.not_before = Time.now cert.not_after = Time.now + (365*24*60*60) cert.public_key = rsa.public_key ef = OpenSSL::X509::ExtensionFactory.new(nil,cert) cert.extensions = [ ef.create_extension("basicConstraints","CA:FALSE"), ef.create_extension("subjectKeyIdentifier", "hash") ] ef.issuer_certificate = cert cert.add_extension(ef.create_extension("authorityKeyIdentifier", "keyid:always,issuer:always")) if comment = self[:SSLCertComment] cert.add_extension(ef.create_extension("nsComment", comment)) end cert.sign(rsa, OpenSSL::Digest::SHA1.new) @cert = cert @pkey = rsa end # Establish the OpenSSL::SSL::SSLContext with the configuration # parameters provided. def setup_ssl_context ctx = ::OpenSSL::SSL::SSLContext.new ctx.cert = @cert ctx.key = @pkey ctx.client_ca = self[:SSLClientCA] ctx.ca_path = self[:SSLCACertificatePath] ctx.ca_file = self[:SSLCACertificateFile] ctx.tmp_dh_callback = self[:SSLTmpDhCallback] ctx.verify_mode = self[:SSLVerifyMode] ctx.verify_depth = self[:SSLVerifyDepth] ctx.verify_callback = self[:SSLVerifyCallback] ctx.cert_store = self[:SSLCertificateStore] @ssl_ctx = ctx end end # Parse the dRuby +uri+ for an SSL connection. # # Expects drbssl://... # # Raises DRbBadScheme or DRbBadURI if +uri+ is not matching or malformed def self.parse_uri(uri) # :nodoc: if uri =~ /^drbssl:\/\/(.*?):(\d+)(\?(.*))?$/ host = $1 port = $2.to_i option = $4 [host, port, option] else raise(DRbBadScheme, uri) unless uri =~ /^drbssl:/ raise(DRbBadURI, 'can\'t parse uri:' + uri) end end # Return an DRb::DRbSSLSocket instance as a client-side connection, # with the SSL connected. This is called from DRb::start_service or while # connecting to a remote object: # # DRb.start_service 'drbssl://localhost:0', front, config # # +uri+ is the URI we are connected to, # 'drbssl://localhost:0' above, +config+ is our # configuration. Either a Hash or DRb::DRbSSLSocket::SSLConfig def self.open(uri, config) host, port, = parse_uri(uri) host.untaint port.untaint soc = TCPSocket.open(host, port) ssl_conf = SSLConfig::new(config) ssl_conf.setup_ssl_context ssl = ssl_conf.connect(soc) self.new(uri, ssl, ssl_conf, true) end # Returns a DRb::DRbSSLSocket instance as a server-side connection, with # the SSL connected. This is called from DRb::start_service or while # connecting to a remote object: # # DRb.start_service 'drbssl://localhost:0', front, config # # +uri+ is the URI we are connected to, # 'drbssl://localhost:0' above, +config+ is our # configuration. Either a Hash or DRb::DRbSSLSocket::SSLConfig def self.open_server(uri, config) uri = 'drbssl://:0' unless uri host, port, = parse_uri(uri) if host.size == 0 host = getservername soc = open_server_inaddr_any(host, port) else soc = TCPServer.open(host, port) end port = soc.addr[1] if port == 0 @uri = "drbssl://#{host}:#{port}" ssl_conf = SSLConfig.new(config) ssl_conf.setup_certificate ssl_conf.setup_ssl_context self.new(@uri, soc, ssl_conf, false) end # This is a convenience method to parse +uri+ and separate out any # additional options appended in the +uri+. # # Returns an option-less uri and the option => [uri,option] # # The +config+ is completely unused, so passing nil is sufficient. def self.uri_option(uri, config) # :nodoc: host, port, option = parse_uri(uri) return "drbssl://#{host}:#{port}", option end # Create a DRb::DRbSSLSocket instance. # # +uri+ is the URI we are connected to. # +soc+ is the tcp socket we are bound to. # +config+ is our configuration. Either a Hash or SSLConfig # +is_established+ is a boolean of whether +soc+ is currently established # # This is called automatically based on the DRb protocol. def initialize(uri, soc, config, is_established) @ssl = is_established ? soc : nil super(uri, soc.to_io, config) end # Returns the SSL stream def stream; @ssl; end # :nodoc: # Closes the SSL stream before closing the dRuby connection. def close # :nodoc: if @ssl @ssl.close @ssl = nil end super end def accept # :nodoc: begin while true soc = accept_or_shutdown return nil unless soc break if (@acl ? @acl.allow_socket?(soc) : true) soc.close end begin ssl = @config.accept(soc) rescue Exception soc.close raise end self.class.new(uri, ssl, @config, true) rescue OpenSSL::SSL::SSLError warn("#{__FILE__}:#{__LINE__}: warning: #{$!.message} (#{$!.class})") if @config[:verbose] retry end end end DRbProtocol.add_protocol(DRbSSLSocket) end PK! +  2.2.0/drb/extserv.rbnu[=begin external service Copyright (c) 2000,2002 Masatoshi SEKI =end require 'drb/drb' require 'monitor' module DRb class ExtServ include MonitorMixin include DRbUndumped def initialize(there, name, server=nil) super() @server = server || DRb::primary_server @name = name ro = DRbObject.new(nil, there) synchronize do @invoker = ro.regist(name, DRbObject.new(self, @server.uri)) end end attr_reader :server def front DRbObject.new(nil, @server.uri) end def stop_service synchronize do @invoker.unregist(@name) server = @server @server = nil server.stop_service true end end def alive? @server ? @server.alive? : false end end end PK!FCII2.2.0/drb/drb.rbnu[# # = drb/drb.rb # # Distributed Ruby: _dRuby_ version 2.0.4 # # Copyright (c) 1999-2003 Masatoshi SEKI. You can redistribute it and/or # modify it under the same terms as Ruby. # # Author:: Masatoshi SEKI # # Documentation:: William Webber (william@williamwebber.com) # # == Overview # # dRuby is a distributed object system for Ruby. It allows an object in one # Ruby process to invoke methods on an object in another Ruby process on the # same or a different machine. # # The Ruby standard library contains the core classes of the dRuby package. # However, the full package also includes access control lists and the # Rinda tuple-space distributed task management system, as well as a # large number of samples. The full dRuby package can be downloaded from # the dRuby home page (see *References*). # # For an introduction and examples of usage see the documentation to the # DRb module. # # == References # # [http://www2a.biglobe.ne.jp/~seki/ruby/druby.html] # The dRuby home page, in Japanese. Contains the full dRuby package # and links to other Japanese-language sources. # # [http://www2a.biglobe.ne.jp/~seki/ruby/druby.en.html] # The English version of the dRuby home page. # # [http://pragprog.com/book/sidruby/the-druby-book] # The dRuby Book: Distributed and Parallel Computing with Ruby # by Masatoshi Seki and Makoto Inoue # # [http://www.ruby-doc.org/docs/ProgrammingRuby/html/ospace.html] # The chapter from *Programming* *Ruby* by Dave Thomas and Andy Hunt # which discusses dRuby. # # [http://www.clio.ne.jp/home/web-i31s/Flotuard/Ruby/PRC2K_seki/dRuby.en.html] # Translation of presentation on Ruby by Masatoshi Seki. require 'socket' require 'thread' require 'fcntl' require 'drb/eq' # # == Overview # # dRuby is a distributed object system for Ruby. It is written in # pure Ruby and uses its own protocol. No add-in services are needed # beyond those provided by the Ruby runtime, such as TCP sockets. It # does not rely on or interoperate with other distributed object # systems such as CORBA, RMI, or .NET. # # dRuby allows methods to be called in one Ruby process upon a Ruby # object located in another Ruby process, even on another machine. # References to objects can be passed between processes. Method # arguments and return values are dumped and loaded in marshalled # format. All of this is done transparently to both the caller of the # remote method and the object that it is called upon. # # An object in a remote process is locally represented by a # DRb::DRbObject instance. This acts as a sort of proxy for the # remote object. Methods called upon this DRbObject instance are # forwarded to its remote object. This is arranged dynamically at run # time. There are no statically declared interfaces for remote # objects, such as CORBA's IDL. # # dRuby calls made into a process are handled by a DRb::DRbServer # instance within that process. This reconstitutes the method call, # invokes it upon the specified local object, and returns the value to # the remote caller. Any object can receive calls over dRuby. There # is no need to implement a special interface, or mixin special # functionality. Nor, in the general case, does an object need to # explicitly register itself with a DRbServer in order to receive # dRuby calls. # # One process wishing to make dRuby calls upon another process must # somehow obtain an initial reference to an object in the remote # process by some means other than as the return value of a remote # method call, as there is initially no remote object reference it can # invoke a method upon. This is done by attaching to the server by # URI. Each DRbServer binds itself to a URI such as # 'druby://example.com:8787'. A DRbServer can have an object attached # to it that acts as the server's *front* *object*. A DRbObject can # be explicitly created from the server's URI. This DRbObject's # remote object will be the server's front object. This front object # can then return references to other Ruby objects in the DRbServer's # process. # # Method calls made over dRuby behave largely the same as normal Ruby # method calls made within a process. Method calls with blocks are # supported, as are raising exceptions. In addition to a method's # standard errors, a dRuby call may also raise one of the # dRuby-specific errors, all of which are subclasses of DRb::DRbError. # # Any type of object can be passed as an argument to a dRuby call or # returned as its return value. By default, such objects are dumped # or marshalled at the local end, then loaded or unmarshalled at the # remote end. The remote end therefore receives a copy of the local # object, not a distributed reference to it; methods invoked upon this # copy are executed entirely in the remote process, not passed on to # the local original. This has semantics similar to pass-by-value. # # However, if an object cannot be marshalled, a dRuby reference to it # is passed or returned instead. This will turn up at the remote end # as a DRbObject instance. All methods invoked upon this remote proxy # are forwarded to the local object, as described in the discussion of # DRbObjects. This has semantics similar to the normal Ruby # pass-by-reference. # # The easiest way to signal that we want an otherwise marshallable # object to be passed or returned as a DRbObject reference, rather # than marshalled and sent as a copy, is to include the # DRb::DRbUndumped mixin module. # # dRuby supports calling remote methods with blocks. As blocks (or # rather the Proc objects that represent them) are not marshallable, # the block executes in the local, not the remote, context. Each # value yielded to the block is passed from the remote object to the # local block, then the value returned by each block invocation is # passed back to the remote execution context to be collected, before # the collected values are finally returned to the local context as # the return value of the method invocation. # # == Examples of usage # # For more dRuby samples, see the +samples+ directory in the full # dRuby distribution. # # === dRuby in client/server mode # # This illustrates setting up a simple client-server drb # system. Run the server and client code in different terminals, # starting the server code first. # # ==== Server code # # require 'drb/drb' # # # The URI for the server to connect to # URI="druby://localhost:8787" # # class TimeServer # # def get_current_time # return Time.now # end # # end # # # The object that handles requests on the server # FRONT_OBJECT=TimeServer.new # # $SAFE = 1 # disable eval() and friends # # DRb.start_service(URI, FRONT_OBJECT) # # Wait for the drb server thread to finish before exiting. # DRb.thread.join # # ==== Client code # # require 'drb/drb' # # # The URI to connect to # SERVER_URI="druby://localhost:8787" # # # Start a local DRbServer to handle callbacks. # # # # Not necessary for this small example, but will be required # # as soon as we pass a non-marshallable object as an argument # # to a dRuby call. # # # # Note: this must be called at least once per process to take any effect. # # This is particularly important if your application forks. # DRb.start_service # # timeserver = DRbObject.new_with_uri(SERVER_URI) # puts timeserver.get_current_time # # === Remote objects under dRuby # # This example illustrates returning a reference to an object # from a dRuby call. The Logger instances live in the server # process. References to them are returned to the client process, # where methods can be invoked upon them. These methods are # executed in the server process. # # ==== Server code # # require 'drb/drb' # # URI="druby://localhost:8787" # # class Logger # # # Make dRuby send Logger instances as dRuby references, # # not copies. # include DRb::DRbUndumped # # def initialize(n, fname) # @name = n # @filename = fname # end # # def log(message) # File.open(@filename, "a") do |f| # f.puts("#{Time.now}: #{@name}: #{message}") # end # end # # end # # # We have a central object for creating and retrieving loggers. # # This retains a local reference to all loggers created. This # # is so an existing logger can be looked up by name, but also # # to prevent loggers from being garbage collected. A dRuby # # reference to an object is not sufficient to prevent it being # # garbage collected! # class LoggerFactory # # def initialize(bdir) # @basedir = bdir # @loggers = {} # end # # def get_logger(name) # if !@loggers.has_key? name # # make the filename safe, then declare it to be so # fname = name.gsub(/[.\/\\\:]/, "_").untaint # @loggers[name] = Logger.new(name, @basedir + "/" + fname) # end # return @loggers[name] # end # # end # # FRONT_OBJECT=LoggerFactory.new("/tmp/dlog") # # $SAFE = 1 # disable eval() and friends # # DRb.start_service(URI, FRONT_OBJECT) # DRb.thread.join # # ==== Client code # # require 'drb/drb' # # SERVER_URI="druby://localhost:8787" # # DRb.start_service # # log_service=DRbObject.new_with_uri(SERVER_URI) # # ["loga", "logb", "logc"].each do |logname| # # logger=log_service.get_logger(logname) # # logger.log("Hello, world!") # logger.log("Goodbye, world!") # logger.log("=== EOT ===") # # end # # == Security # # As with all network services, security needs to be considered when # using dRuby. By allowing external access to a Ruby object, you are # not only allowing outside clients to call the methods you have # defined for that object, but by default to execute arbitrary Ruby # code on your server. Consider the following: # # # !!! UNSAFE CODE !!! # ro = DRbObject::new_with_uri("druby://your.server.com:8989") # class << ro # undef :instance_eval # force call to be passed to remote object # end # ro.instance_eval("`rm -rf *`") # # The dangers posed by instance_eval and friends are such that a # DRbServer should generally be run with $SAFE set to at least # level 1. This will disable eval() and related calls on strings # passed across the wire. The sample usage code given above follows # this practice. # # A DRbServer can be configured with an access control list to # selectively allow or deny access from specified IP addresses. The # main druby distribution provides the ACL class for this purpose. In # general, this mechanism should only be used alongside, rather than # as a replacement for, a good firewall. # # == dRuby internals # # dRuby is implemented using three main components: a remote method # call marshaller/unmarshaller; a transport protocol; and an # ID-to-object mapper. The latter two can be directly, and the first # indirectly, replaced, in order to provide different behaviour and # capabilities. # # Marshalling and unmarshalling of remote method calls is performed by # a DRb::DRbMessage instance. This uses the Marshal module to dump # the method call before sending it over the transport layer, then # reconstitute it at the other end. There is normally no need to # replace this component, and no direct way is provided to do so. # However, it is possible to implement an alternative marshalling # scheme as part of an implementation of the transport layer. # # The transport layer is responsible for opening client and server # network connections and forwarding dRuby request across them. # Normally, it uses DRb::DRbMessage internally to manage marshalling # and unmarshalling. The transport layer is managed by # DRb::DRbProtocol. Multiple protocols can be installed in # DRbProtocol at the one time; selection between them is determined by # the scheme of a dRuby URI. The default transport protocol is # selected by the scheme 'druby:', and implemented by # DRb::DRbTCPSocket. This uses plain TCP/IP sockets for # communication. An alternative protocol, using UNIX domain sockets, # is implemented by DRb::DRbUNIXSocket in the file drb/unix.rb, and # selected by the scheme 'drbunix:'. A sample implementation over # HTTP can be found in the samples accompanying the main dRuby # distribution. # # The ID-to-object mapping component maps dRuby object ids to the # objects they refer to, and vice versa. The implementation to use # can be specified as part of a DRb::DRbServer's configuration. The # default implementation is provided by DRb::DRbIdConv. It uses an # object's ObjectSpace id as its dRuby id. This means that the dRuby # reference to that object only remains meaningful for the lifetime of # the object's process and the lifetime of the object within that # process. A modified implementation is provided by DRb::TimerIdConv # in the file drb/timeridconv.rb. This implementation retains a local # reference to all objects exported over dRuby for a configurable # period of time (defaulting to ten minutes), to prevent them being # garbage-collected within this time. Another sample implementation # is provided in sample/name.rb in the main dRuby distribution. This # allows objects to specify their own id or "name". A dRuby reference # can be made persistent across processes by having each process # register an object using the same dRuby name. # module DRb # Superclass of all errors raised in the DRb module. class DRbError < RuntimeError; end # Error raised when an error occurs on the underlying communication # protocol. class DRbConnError < DRbError; end # Class responsible for converting between an object and its id. # # This, the default implementation, uses an object's local ObjectSpace # __id__ as its id. This means that an object's identification over # drb remains valid only while that object instance remains alive # within the server runtime. # # For alternative mechanisms, see DRb::TimerIdConv in rdb/timeridconv.rb # and DRbNameIdConv in sample/name.rb in the full drb distribution. class DRbIdConv # Convert an object reference id to an object. # # This implementation looks up the reference id in the local object # space and returns the object it refers to. def to_obj(ref) ObjectSpace._id2ref(ref) end # Convert an object into a reference id. # # This implementation returns the object's __id__ in the local # object space. def to_id(obj) obj.nil? ? nil : obj.__id__ end end # Mixin module making an object undumpable or unmarshallable. # # If an object which includes this module is returned by method # called over drb, then the object remains in the server space # and a reference to the object is returned, rather than the # object being marshalled and moved into the client space. module DRbUndumped def _dump(dummy) # :nodoc: raise TypeError, 'can\'t dump' end end # Error raised by the DRb module when an attempt is made to refer to # the context's current drb server but the context does not have one. # See #current_server. class DRbServerNotFound < DRbError; end # Error raised by the DRbProtocol module when it cannot find any # protocol implementation support the scheme specified in a URI. class DRbBadURI < DRbError; end # Error raised by a dRuby protocol when it doesn't support the # scheme specified in a URI. See DRb::DRbProtocol. class DRbBadScheme < DRbError; end # An exception wrapping a DRb::DRbUnknown object class DRbUnknownError < DRbError # Create a new DRbUnknownError for the DRb::DRbUnknown object +unknown+ def initialize(unknown) @unknown = unknown super(unknown.name) end # Get the wrapped DRb::DRbUnknown object. attr_reader :unknown def self._load(s) # :nodoc: Marshal::load(s) end def _dump(lv) # :nodoc: Marshal::dump(@unknown) end end # An exception wrapping an error object class DRbRemoteError < DRbError # Creates a new remote error that wraps the Exception +error+ def initialize(error) @reason = error.class.to_s super("#{error.message} (#{error.class})") set_backtrace(error.backtrace) end # the class of the error, as a string. attr_reader :reason end # Class wrapping a marshalled object whose type is unknown locally. # # If an object is returned by a method invoked over drb, but the # class of the object is unknown in the client namespace, or # the object is a constant unknown in the client namespace, then # the still-marshalled object is returned wrapped in a DRbUnknown instance. # # If this object is passed as an argument to a method invoked over # drb, then the wrapped object is passed instead. # # The class or constant name of the object can be read from the # +name+ attribute. The marshalled object is held in the +buf+ # attribute. class DRbUnknown # Create a new DRbUnknown object. # # +buf+ is a string containing a marshalled object that could not # be unmarshalled. +err+ is the error message that was raised # when the unmarshalling failed. It is used to determine the # name of the unmarshalled object. def initialize(err, buf) case err.to_s when /uninitialized constant (\S+)/ @name = $1 when /undefined class\/module (\S+)/ @name = $1 else @name = nil end @buf = buf end # The name of the unknown thing. # # Class name for unknown objects; variable name for unknown # constants. attr_reader :name # Buffer contained the marshalled, unknown object. attr_reader :buf def self._load(s) # :nodoc: begin Marshal::load(s) rescue NameError, ArgumentError DRbUnknown.new($!, s) end end def _dump(lv) # :nodoc: @buf end # Attempt to load the wrapped marshalled object again. # # If the class of the object is now known locally, the object # will be unmarshalled and returned. Otherwise, a new # but identical DRbUnknown object will be returned. def reload self.class._load(@buf) end # Create a DRbUnknownError exception containing this object. def exception DRbUnknownError.new(self) end end # An Array wrapper that can be sent to another server via DRb. # # All entries in the array will be dumped or be references that point to # the local server. class DRbArray # Creates a new DRbArray that either dumps or wraps all the items in the # Array +ary+ so they can be loaded by a remote DRb server. def initialize(ary) @ary = ary.collect { |obj| if obj.kind_of? DRbUndumped DRbObject.new(obj) else begin Marshal.dump(obj) obj rescue DRbObject.new(obj) end end } end def self._load(s) # :nodoc: Marshal::load(s) end def _dump(lv) # :nodoc: Marshal.dump(@ary) end end # Handler for sending and receiving drb messages. # # This takes care of the low-level marshalling and unmarshalling # of drb requests and responses sent over the wire between server # and client. This relieves the implementor of a new drb # protocol layer with having to deal with these details. # # The user does not have to directly deal with this object in # normal use. class DRbMessage def initialize(config) # :nodoc: @load_limit = config[:load_limit] @argc_limit = config[:argc_limit] end def dump(obj, error=false) # :nodoc: obj = make_proxy(obj, error) if obj.kind_of? DRbUndumped begin str = Marshal::dump(obj) rescue str = Marshal::dump(make_proxy(obj, error)) end [str.size].pack('N') + str end def load(soc) # :nodoc: begin sz = soc.read(4) # sizeof (N) rescue raise(DRbConnError, $!.message, $!.backtrace) end raise(DRbConnError, 'connection closed') if sz.nil? raise(DRbConnError, 'premature header') if sz.size < 4 sz = sz.unpack('N')[0] raise(DRbConnError, "too large packet #{sz}") if @load_limit < sz begin str = soc.read(sz) rescue raise(DRbConnError, $!.message, $!.backtrace) end raise(DRbConnError, 'connection closed') if str.nil? raise(DRbConnError, 'premature marshal format(can\'t read)') if str.size < sz DRb.mutex.synchronize do begin save = Thread.current[:drb_untaint] Thread.current[:drb_untaint] = [] Marshal::load(str) rescue NameError, ArgumentError DRbUnknown.new($!, str) ensure Thread.current[:drb_untaint].each do |x| x.untaint end Thread.current[:drb_untaint] = save end end end def send_request(stream, ref, msg_id, arg, b) # :nodoc: ary = [] ary.push(dump(ref.__drbref)) ary.push(dump(msg_id.id2name)) ary.push(dump(arg.length)) arg.each do |e| ary.push(dump(e)) end ary.push(dump(b)) stream.write(ary.join('')) rescue raise(DRbConnError, $!.message, $!.backtrace) end def recv_request(stream) # :nodoc: ref = load(stream) ro = DRb.to_obj(ref) msg = load(stream) argc = load(stream) raise(DRbConnError, "too many arguments") if @argc_limit < argc argv = Array.new(argc, nil) argc.times do |n| argv[n] = load(stream) end block = load(stream) return ro, msg, argv, block end def send_reply(stream, succ, result) # :nodoc: stream.write(dump(succ) + dump(result, !succ)) rescue raise(DRbConnError, $!.message, $!.backtrace) end def recv_reply(stream) # :nodoc: succ = load(stream) result = load(stream) [succ, result] end private def make_proxy(obj, error=false) # :nodoc: if error DRbRemoteError.new(obj) else DRbObject.new(obj) end end end # Module managing the underlying network protocol(s) used by drb. # # By default, drb uses the DRbTCPSocket protocol. Other protocols # can be defined. A protocol must define the following class methods: # # [open(uri, config)] Open a client connection to the server at +uri+, # using configuration +config+. Return a protocol # instance for this connection. # [open_server(uri, config)] Open a server listening at +uri+, # using configuration +config+. Return a # protocol instance for this listener. # [uri_option(uri, config)] Take a URI, possibly containing an option # component (e.g. a trailing '?param=val'), # and return a [uri, option] tuple. # # All of these methods should raise a DRbBadScheme error if the URI # does not identify the protocol they support (e.g. "druby:" for # the standard Ruby protocol). This is how the DRbProtocol module, # given a URI, determines which protocol implementation serves that # protocol. # # The protocol instance returned by #open_server must have the # following methods: # # [accept] Accept a new connection to the server. Returns a protocol # instance capable of communicating with the client. # [close] Close the server connection. # [uri] Get the URI for this server. # # The protocol instance returned by #open must have the following methods: # # [send_request (ref, msg_id, arg, b)] # Send a request to +ref+ with the given message id and arguments. # This is most easily implemented by calling DRbMessage.send_request, # providing a stream that sits on top of the current protocol. # [recv_reply] # Receive a reply from the server and return it as a [success-boolean, # reply-value] pair. This is most easily implemented by calling # DRb.recv_reply, providing a stream that sits on top of the # current protocol. # [alive?] # Is this connection still alive? # [close] # Close this connection. # # The protocol instance returned by #open_server().accept() must have # the following methods: # # [recv_request] # Receive a request from the client and return a [object, message, # args, block] tuple. This is most easily implemented by calling # DRbMessage.recv_request, providing a stream that sits on top of # the current protocol. # [send_reply(succ, result)] # Send a reply to the client. This is most easily implemented # by calling DRbMessage.send_reply, providing a stream that sits # on top of the current protocol. # [close] # Close this connection. # # A new protocol is registered with the DRbProtocol module using # the add_protocol method. # # For examples of other protocols, see DRbUNIXSocket in drb/unix.rb, # and HTTP0 in sample/http0.rb and sample/http0serv.rb in the full # drb distribution. module DRbProtocol # Add a new protocol to the DRbProtocol module. def add_protocol(prot) @protocol.push(prot) end module_function :add_protocol # Open a client connection to +uri+ with the configuration +config+. # # The DRbProtocol module asks each registered protocol in turn to # try to open the URI. Each protocol signals that it does not handle that # URI by raising a DRbBadScheme error. If no protocol recognises the # URI, then a DRbBadURI error is raised. If a protocol accepts the # URI, but an error occurs in opening it, a DRbConnError is raised. def open(uri, config, first=true) @protocol.each do |prot| begin return prot.open(uri, config) rescue DRbBadScheme rescue DRbConnError raise($!) rescue raise(DRbConnError, "#{uri} - #{$!.inspect}") end end if first && (config[:auto_load] != false) auto_load(uri, config) return open(uri, config, false) end raise DRbBadURI, 'can\'t parse uri:' + uri end module_function :open # Open a server listening for connections at +uri+ with # configuration +config+. # # The DRbProtocol module asks each registered protocol in turn to # try to open a server at the URI. Each protocol signals that it does # not handle that URI by raising a DRbBadScheme error. If no protocol # recognises the URI, then a DRbBadURI error is raised. If a protocol # accepts the URI, but an error occurs in opening it, the underlying # error is passed on to the caller. def open_server(uri, config, first=true) @protocol.each do |prot| begin return prot.open_server(uri, config) rescue DRbBadScheme end end if first && (config[:auto_load] != false) auto_load(uri, config) return open_server(uri, config, false) end raise DRbBadURI, 'can\'t parse uri:' + uri end module_function :open_server # Parse +uri+ into a [uri, option] pair. # # The DRbProtocol module asks each registered protocol in turn to # try to parse the URI. Each protocol signals that it does not handle that # URI by raising a DRbBadScheme error. If no protocol recognises the # URI, then a DRbBadURI error is raised. def uri_option(uri, config, first=true) @protocol.each do |prot| begin uri, opt = prot.uri_option(uri, config) # opt = nil if opt == '' return uri, opt rescue DRbBadScheme end end if first && (config[:auto_load] != false) auto_load(uri, config) return uri_option(uri, config, false) end raise DRbBadURI, 'can\'t parse uri:' + uri end module_function :uri_option def auto_load(uri, config) # :nodoc: if uri =~ /^drb([a-z0-9]+):/ require("drb/#{$1}") rescue nil end end module_function :auto_load end # The default drb protocol which communicates over a TCP socket. # # The DRb TCP protocol URI looks like: # druby://:?. The option is optional. class DRbTCPSocket # :stopdoc: private def self.parse_uri(uri) if uri =~ /^druby:\/\/(.*?):(\d+)(\?(.*))?$/ host = $1 port = $2.to_i option = $4 [host, port, option] else raise(DRbBadScheme, uri) unless uri =~ /^druby:/ raise(DRbBadURI, 'can\'t parse uri:' + uri) end end public # Open a client connection to +uri+ (DRb URI string) using configuration # +config+. # # This can raise DRb::DRbBadScheme or DRb::DRbBadURI if +uri+ is not for a # recognized protocol. See DRb::DRbServer.new for information on built-in # URI protocols. def self.open(uri, config) host, port, = parse_uri(uri) host.untaint port.untaint soc = TCPSocket.open(host, port) self.new(uri, soc, config) end # Returns the hostname of this server def self.getservername host = Socket::gethostname begin Socket::gethostbyname(host)[0] rescue 'localhost' end end # For the families available for +host+, returns a TCPServer on +port+. # If +port+ is 0 the first available port is used. IPv4 servers are # preferred over IPv6 servers. def self.open_server_inaddr_any(host, port) infos = Socket::getaddrinfo(host, nil, Socket::AF_UNSPEC, Socket::SOCK_STREAM, 0, Socket::AI_PASSIVE) families = Hash[*infos.collect { |af, *_| af }.uniq.zip([]).flatten] return TCPServer.open('0.0.0.0', port) if families.has_key?('AF_INET') return TCPServer.open('::', port) if families.has_key?('AF_INET6') return TCPServer.open(port) # :stopdoc: end # Open a server listening for connections at +uri+ using # configuration +config+. def self.open_server(uri, config) uri = 'druby://:0' unless uri host, port, _ = parse_uri(uri) config = {:tcp_original_host => host}.update(config) if host.size == 0 host = getservername soc = open_server_inaddr_any(host, port) else soc = TCPServer.open(host, port) end port = soc.addr[1] if port == 0 config[:tcp_port] = port uri = "druby://#{host}:#{port}" self.new(uri, soc, config) end # Parse +uri+ into a [uri, option] pair. def self.uri_option(uri, config) host, port, option = parse_uri(uri) return "druby://#{host}:#{port}", option end # Create a new DRbTCPSocket instance. # # +uri+ is the URI we are connected to. # +soc+ is the tcp socket we are bound to. +config+ is our # configuration. def initialize(uri, soc, config={}) @uri = uri @socket = soc @config = config @acl = config[:tcp_acl] @msg = DRbMessage.new(config) set_sockopt(@socket) @shutdown_pipe_r, @shutdown_pipe_w = IO.pipe end # Get the URI that we are connected to. attr_reader :uri # Get the address of our TCP peer (the other end of the socket # we are bound to. def peeraddr @socket.peeraddr end # Get the socket. def stream; @socket; end # On the client side, send a request to the server. def send_request(ref, msg_id, arg, b) @msg.send_request(stream, ref, msg_id, arg, b) end # On the server side, receive a request from the client. def recv_request @msg.recv_request(stream) end # On the server side, send a reply to the client. def send_reply(succ, result) @msg.send_reply(stream, succ, result) end # On the client side, receive a reply from the server. def recv_reply @msg.recv_reply(stream) end public # Close the connection. # # If this is an instance returned by #open_server, then this stops # listening for new connections altogether. If this is an instance # returned by #open or by #accept, then it closes this particular # client-server session. def close if @socket @socket.close @socket = nil end close_shutdown_pipe end def close_shutdown_pipe if @shutdown_pipe_r && !@shutdown_pipe_r.closed? @shutdown_pipe_r.close @shutdown_pipe_r = nil end if @shutdown_pipe_w && !@shutdown_pipe_w.closed? @shutdown_pipe_w.close @shutdown_pipe_w = nil end end private :close_shutdown_pipe # On the server side, for an instance returned by #open_server, # accept a client connection and return a new instance to handle # the server's side of this client-server session. def accept while true s = accept_or_shutdown return nil unless s break if (@acl ? @acl.allow_socket?(s) : true) s.close end if @config[:tcp_original_host].to_s.size == 0 uri = "druby://#{s.addr[3]}:#{@config[:tcp_port]}" else uri = @uri end self.class.new(uri, s, @config) end def accept_or_shutdown readables, = IO.select([@socket, @shutdown_pipe_r]) if readables.include? @shutdown_pipe_r return nil end @socket.accept end private :accept_or_shutdown # Graceful shutdown def shutdown @shutdown_pipe_w.close if @shutdown_pipe_w && !@shutdown_pipe_w.closed? end # Check to see if this connection is alive. def alive? return false unless @socket if IO.select([@socket], nil, nil, 0) close return false end true end def set_sockopt(soc) # :nodoc: soc.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1) soc.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) if defined? Fcntl::FD_CLOEXEC end end module DRbProtocol @protocol = [DRbTCPSocket] # default end class DRbURIOption # :nodoc: I don't understand the purpose of this class... def initialize(option) @option = option.to_s end attr_reader :option def to_s; @option; end def ==(other) return false unless DRbURIOption === other @option == other.option end def hash @option.hash end alias eql? == end # Object wrapping a reference to a remote drb object. # # Method calls on this object are relayed to the remote # object that this object is a stub for. class DRbObject # Unmarshall a marshalled DRbObject. # # If the referenced object is located within the local server, then # the object itself is returned. Otherwise, a new DRbObject is # created to act as a stub for the remote referenced object. def self._load(s) uri, ref = Marshal.load(s) if DRb.here?(uri) obj = DRb.to_obj(ref) if ((! obj.tainted?) && Thread.current[:drb_untaint]) Thread.current[:drb_untaint].push(obj) end return obj end self.new_with(uri, ref) end # Creates a DRb::DRbObject given the reference information to the remote # host +uri+ and object +ref+. def self.new_with(uri, ref) it = self.allocate it.instance_variable_set(:@uri, uri) it.instance_variable_set(:@ref, ref) it end # Create a new DRbObject from a URI alone. def self.new_with_uri(uri) self.new(nil, uri) end # Marshall this object. # # The URI and ref of the object are marshalled. def _dump(lv) Marshal.dump([@uri, @ref]) end # Create a new remote object stub. # # +obj+ is the (local) object we want to create a stub for. Normally # this is +nil+. +uri+ is the URI of the remote object that this # will be a stub for. def initialize(obj, uri=nil) @uri = nil @ref = nil if obj.nil? return if uri.nil? @uri, option = DRbProtocol.uri_option(uri, DRb.config) @ref = DRbURIOption.new(option) unless option.nil? else @uri = uri ? uri : (DRb.uri rescue nil) @ref = obj ? DRb.to_id(obj) : nil end end # Get the URI of the remote object. def __drburi @uri end # Get the reference of the object, if local. def __drbref @ref end undef :to_s undef :to_a if respond_to?(:to_a) # Routes respond_to? to the referenced remote object. def respond_to?(msg_id, priv=false) case msg_id when :_dump true when :marshal_dump false else method_missing(:respond_to?, msg_id, priv) end end # Routes method calls to the referenced remote object. def method_missing(msg_id, *a, &b) if DRb.here?(@uri) obj = DRb.to_obj(@ref) DRb.current_server.check_insecure_method(obj, msg_id) return obj.__send__(msg_id, *a, &b) end succ, result = self.class.with_friend(@uri) do DRbConn.open(@uri) do |conn| conn.send_message(self, msg_id, a, b) end end if succ return result elsif DRbUnknown === result raise result else bt = self.class.prepare_backtrace(@uri, result) result.set_backtrace(bt + caller) raise result end end # Given the +uri+ of another host executes the block provided. def self.with_friend(uri) # :nodoc: friend = DRb.fetch_server(uri) return yield() unless friend save = Thread.current['DRb'] Thread.current['DRb'] = { 'server' => friend } return yield ensure Thread.current['DRb'] = save if friend end # Returns a modified backtrace from +result+ with the +uri+ where each call # in the backtrace came from. def self.prepare_backtrace(uri, result) # :nodoc: prefix = "(#{uri}) " bt = [] result.backtrace.each do |x| break if /`__send__'$/ =~ x if /^\(druby:\/\// =~ x bt.push(x) else bt.push(prefix + x) end end bt end def pretty_print(q) # :nodoc: q.pp_object(self) end def pretty_print_cycle(q) # :nodoc: q.object_address_group(self) { q.breakable q.text '...' } end end # Class handling the connection between a DRbObject and the # server the real object lives on. # # This class maintains a pool of connections, to reduce the # overhead of starting and closing down connections for each # method call. # # This class is used internally by DRbObject. The user does # not normally need to deal with it directly. class DRbConn POOL_SIZE = 16 # :nodoc: @mutex = Mutex.new @pool = [] def self.open(remote_uri) # :nodoc: begin conn = nil @mutex.synchronize do #FIXME new_pool = [] @pool.each do |c| if conn.nil? and c.uri == remote_uri conn = c if c.alive? else new_pool.push c end end @pool = new_pool end conn = self.new(remote_uri) unless conn succ, result = yield(conn) return succ, result ensure if conn if succ @mutex.synchronize do @pool.unshift(conn) @pool.pop.close while @pool.size > POOL_SIZE end else conn.close end end end end def initialize(remote_uri) # :nodoc: @uri = remote_uri @protocol = DRbProtocol.open(remote_uri, DRb.config) end attr_reader :uri # :nodoc: def send_message(ref, msg_id, arg, block) # :nodoc: @protocol.send_request(ref, msg_id, arg, block) @protocol.recv_reply end def close # :nodoc: @protocol.close @protocol = nil end def alive? # :nodoc: return false unless @protocol @protocol.alive? end end # Class representing a drb server instance. # # A DRbServer must be running in the local process before any incoming # dRuby calls can be accepted, or any local objects can be passed as # dRuby references to remote processes, even if those local objects are # never actually called remotely. You do not need to start a DRbServer # in the local process if you are only making outgoing dRuby calls # passing marshalled parameters. # # Unless multiple servers are being used, the local DRbServer is normally # started by calling DRb.start_service. class DRbServer @@acl = nil @@idconv = DRbIdConv.new @@secondary_server = nil @@argc_limit = 256 @@load_limit = 256 * 102400 @@verbose = false @@safe_level = 0 # Set the default value for the :argc_limit option. # # See #new(). The initial default value is 256. def self.default_argc_limit(argc) @@argc_limit = argc end # Set the default value for the :load_limit option. # # See #new(). The initial default value is 25 MB. def self.default_load_limit(sz) @@load_limit = sz end # Set the default access control list to +acl+. The default ACL is +nil+. # # See also DRb::ACL and #new() def self.default_acl(acl) @@acl = acl end # Set the default value for the :id_conv option. # # See #new(). The initial default value is a DRbIdConv instance. def self.default_id_conv(idconv) @@idconv = idconv end # Set the default safe level to +level+. The default safe level is 0 # # See #new for more information. def self.default_safe_level(level) @@safe_level = level end # Set the default value of the :verbose option. # # See #new(). The initial default value is false. def self.verbose=(on) @@verbose = on end # Get the default value of the :verbose option. def self.verbose @@verbose end def self.make_config(hash={}) # :nodoc: default_config = { :idconv => @@idconv, :verbose => @@verbose, :tcp_acl => @@acl, :load_limit => @@load_limit, :argc_limit => @@argc_limit, :safe_level => @@safe_level } default_config.update(hash) end # Create a new DRbServer instance. # # +uri+ is the URI to bind to. This is normally of the form # 'druby://:' where is a hostname of # the local machine. If nil, then the system's default hostname # will be bound to, on a port selected by the system; these value # can be retrieved from the +uri+ attribute. 'druby:' specifies # the default dRuby transport protocol: another protocol, such # as 'drbunix:', can be specified instead. # # +front+ is the front object for the server, that is, the object # to which remote method calls on the server will be passed. If # nil, then the server will not accept remote method calls. # # If +config_or_acl+ is a hash, it is the configuration to # use for this server. The following options are recognised: # # :idconv :: an id-to-object conversion object. This defaults # to an instance of the class DRb::DRbIdConv. # :verbose :: if true, all unsuccessful remote calls on objects # in the server will be logged to $stdout. false # by default. # :tcp_acl :: the access control list for this server. See # the ACL class from the main dRuby distribution. # :load_limit :: the maximum message size in bytes accepted by # the server. Defaults to 25 MB (26214400). # :argc_limit :: the maximum number of arguments to a remote # method accepted by the server. Defaults to # 256. # :safe_level :: The safe level of the DRbServer. The attribute # sets $SAFE for methods performed in the main_loop. # Defaults to 0. # # The default values of these options can be modified on # a class-wide basis by the class methods #default_argc_limit, # #default_load_limit, #default_acl, #default_id_conv, # and #verbose= # # If +config_or_acl+ is not a hash, but is not nil, it is # assumed to be the access control list for this server. # See the :tcp_acl option for more details. # # If no other server is currently set as the primary server, # this will become the primary server. # # The server will immediately start running in its own thread. def initialize(uri=nil, front=nil, config_or_acl=nil) if Hash === config_or_acl config = config_or_acl.dup else acl = config_or_acl || @@acl config = { :tcp_acl => acl } end @config = self.class.make_config(config) @protocol = DRbProtocol.open_server(uri, @config) @uri = @protocol.uri @exported_uri = [@uri] @front = front @idconv = @config[:idconv] @safe_level = @config[:safe_level] @grp = ThreadGroup.new @thread = run DRb.regist_server(self) end # The URI of this DRbServer. attr_reader :uri # The main thread of this DRbServer. # # This is the thread that listens for and accepts connections # from clients, not that handles each client's request-response # session. attr_reader :thread # The front object of the DRbServer. # # This object receives remote method calls made on the server's # URI alone, with an object id. attr_reader :front # The configuration of this DRbServer attr_reader :config # The safe level for this server. This is a number corresponding to # $SAFE. # # The default safe_level is 0 attr_reader :safe_level # Set whether to operate in verbose mode. # # In verbose mode, failed calls are logged to stdout. def verbose=(v); @config[:verbose]=v; end # Get whether the server is in verbose mode. # # In verbose mode, failed calls are logged to stdout. def verbose; @config[:verbose]; end # Is this server alive? def alive? @thread.alive? end # Is +uri+ the URI for this server? def here?(uri) @exported_uri.include?(uri) end # Stop this server. def stop_service DRb.remove_server(self) if Thread.current['DRb'] && Thread.current['DRb']['server'] == self Thread.current['DRb']['stop_service'] = true else if @protocol.respond_to? :shutdown @protocol.shutdown else @thread.kill # xxx: Thread#kill end @thread.join end end # Convert a dRuby reference to the local object it refers to. def to_obj(ref) return front if ref.nil? return front[ref.to_s] if DRbURIOption === ref @idconv.to_obj(ref) end # Convert a local object to a dRuby reference. def to_id(obj) return nil if obj.__id__ == front.__id__ @idconv.to_id(obj) end private ## # Starts the DRb main loop in a new thread. def run Thread.start do begin while main_loop end ensure @protocol.close if @protocol end end end # List of insecure methods. # # These methods are not callable via dRuby. INSECURE_METHOD = [ :__send__ ] # Has a method been included in the list of insecure methods? def insecure_method?(msg_id) INSECURE_METHOD.include?(msg_id) end # Coerce an object to a string, providing our own representation if # to_s is not defined for the object. def any_to_s(obj) obj.to_s + ":#{obj.class}" rescue sprintf("#<%s:0x%lx>", obj.class, obj.__id__) end # Check that a method is callable via dRuby. # # +obj+ is the object we want to invoke the method on. +msg_id+ is the # method name, as a Symbol. # # If the method is an insecure method (see #insecure_method?) a # SecurityError is thrown. If the method is private or undefined, # a NameError is thrown. def check_insecure_method(obj, msg_id) return true if Proc === obj && msg_id == :__drb_yield raise(ArgumentError, "#{any_to_s(msg_id)} is not a symbol") unless Symbol == msg_id.class raise(SecurityError, "insecure method `#{msg_id}'") if insecure_method?(msg_id) if obj.private_methods.include?(msg_id) desc = any_to_s(obj) raise NoMethodError, "private method `#{msg_id}' called for #{desc}" elsif obj.protected_methods.include?(msg_id) desc = any_to_s(obj) raise NoMethodError, "protected method `#{msg_id}' called for #{desc}" else true end end public :check_insecure_method class InvokeMethod # :nodoc: def initialize(drb_server, client) @drb_server = drb_server @safe_level = drb_server.safe_level @client = client end def perform @result = nil @succ = false setup_message if $SAFE < @safe_level info = Thread.current['DRb'] if @block @result = Thread.new { Thread.current['DRb'] = info $SAFE = @safe_level perform_with_block }.value else @result = Thread.new { Thread.current['DRb'] = info $SAFE = @safe_level perform_without_block }.value end else if @block @result = perform_with_block else @result = perform_without_block end end @succ = true if @msg_id == :to_ary && @result.class == Array @result = DRbArray.new(@result) end return @succ, @result rescue StandardError, ScriptError, Interrupt @result = $! return @succ, @result end private def init_with_client obj, msg, argv, block = @client.recv_request @obj = obj @msg_id = msg.intern @argv = argv @block = block end def check_insecure_method @drb_server.check_insecure_method(@obj, @msg_id) end def setup_message init_with_client check_insecure_method end def perform_without_block if Proc === @obj && @msg_id == :__drb_yield if @argv.size == 1 ary = @argv else ary = [@argv] end ary.collect(&@obj)[0] else @obj.__send__(@msg_id, *@argv) end end end require 'drb/invokemethod' class InvokeMethod include InvokeMethod18Mixin end # The main loop performed by a DRbServer's internal thread. # # Accepts a connection from a client, and starts up its own # thread to handle it. This thread loops, receiving requests # from the client, invoking them on a local object, and # returning responses, until the client closes the connection # or a local method call fails. def main_loop client0 = @protocol.accept return nil if !client0 Thread.start(client0) do |client| @grp.add Thread.current Thread.current['DRb'] = { 'client' => client , 'server' => self } DRb.mutex.synchronize do client_uri = client.uri @exported_uri << client_uri unless @exported_uri.include?(client_uri) end loop do begin succ = false invoke_method = InvokeMethod.new(self, client) succ, result = invoke_method.perform if !succ && verbose p result result.backtrace.each do |x| puts x end end client.send_reply(succ, result) rescue nil ensure client.close unless succ if Thread.current['DRb']['stop_service'] Thread.new { stop_service } end break unless succ end end end end end @primary_server = nil # Start a dRuby server locally. # # The new dRuby server will become the primary server, even # if another server is currently the primary server. # # +uri+ is the URI for the server to bind to. If nil, # the server will bind to random port on the default local host # name and use the default dRuby protocol. # # +front+ is the server's front object. This may be nil. # # +config+ is the configuration for the new server. This may # be nil. # # See DRbServer::new. def start_service(uri=nil, front=nil, config=nil) @primary_server = DRbServer.new(uri, front, config) end module_function :start_service # The primary local dRuby server. # # This is the server created by the #start_service call. attr_accessor :primary_server module_function :primary_server=, :primary_server # Get the 'current' server. # # In the context of execution taking place within the main # thread of a dRuby server (typically, as a result of a remote # call on the server or one of its objects), the current # server is that server. Otherwise, the current server is # the primary server. # # If the above rule fails to find a server, a DRbServerNotFound # error is raised. def current_server drb = Thread.current['DRb'] server = (drb && drb['server']) ? drb['server'] : @primary_server raise DRbServerNotFound unless server return server end module_function :current_server # Stop the local dRuby server. # # This operates on the primary server. If there is no primary # server currently running, it is a noop. def stop_service @primary_server.stop_service if @primary_server @primary_server = nil end module_function :stop_service # Get the URI defining the local dRuby space. # # This is the URI of the current server. See #current_server. def uri drb = Thread.current['DRb'] client = (drb && drb['client']) if client uri = client.uri return uri if uri end current_server.uri end module_function :uri # Is +uri+ the URI for the current local server? def here?(uri) current_server.here?(uri) rescue false # (current_server.uri rescue nil) == uri end module_function :here? # Get the configuration of the current server. # # If there is no current server, this returns the default configuration. # See #current_server and DRbServer::make_config. def config current_server.config rescue DRbServer.make_config end module_function :config # Get the front object of the current server. # # This raises a DRbServerNotFound error if there is no current server. # See #current_server. def front current_server.front end module_function :front # Convert a reference into an object using the current server. # # This raises a DRbServerNotFound error if there is no current server. # See #current_server. def to_obj(ref) current_server.to_obj(ref) end # Get a reference id for an object using the current server. # # This raises a DRbServerNotFound error if there is no current server. # See #current_server. def to_id(obj) current_server.to_id(obj) end module_function :to_id module_function :to_obj # Get the thread of the primary server. # # This returns nil if there is no primary server. See #primary_server. def thread @primary_server ? @primary_server.thread : nil end module_function :thread # Set the default id conversion object. # # This is expected to be an instance such as DRb::DRbIdConv that responds to # #to_id and #to_obj that can convert objects to and from DRb references. # # See DRbServer#default_id_conv. def install_id_conv(idconv) DRbServer.default_id_conv(idconv) end module_function :install_id_conv # Set the default ACL to +acl+. # # See DRb::DRbServer.default_acl. def install_acl(acl) DRbServer.default_acl(acl) end module_function :install_acl @mutex = Mutex.new def mutex # :nodoc: @mutex end module_function :mutex @server = {} # Registers +server+ with DRb. # # This is called when a new DRb::DRbServer is created. # # If there is no primary server then +server+ becomes the primary server. # # Example: # # require 'drb' # # s = DRb::DRbServer.new # automatically calls regist_server # DRb.fetch_server s.uri #=> # def regist_server(server) @server[server.uri] = server mutex.synchronize do @primary_server = server unless @primary_server end end module_function :regist_server # Removes +server+ from the list of registered servers. def remove_server(server) @server.delete(server.uri) end module_function :remove_server # Retrieves the server with the given +uri+. # # See also regist_server and remove_server. def fetch_server(uri) @server[uri] end module_function :fetch_server end # :stopdoc: DRbObject = DRb::DRbObject DRbUndumped = DRb::DRbUndumped DRbIdConv = DRb::DRbIdConv PK!s`H  2.2.0/drb/unix.rbnu[require 'socket' require 'drb/drb' require 'tmpdir' raise(LoadError, "UNIXServer is required") unless defined?(UNIXServer) module DRb # Implements DRb over a UNIX socket # # DRb UNIX socket URIs look like drbunix:?. The # option is optional. class DRbUNIXSocket < DRbTCPSocket # :stopdoc: def self.parse_uri(uri) if /^drbunix:(.*?)(\?(.*))?$/ =~ uri filename = $1 option = $3 [filename, option] else raise(DRbBadScheme, uri) unless uri =~ /^drbunix:/ raise(DRbBadURI, 'can\'t parse uri:' + uri) end end def self.open(uri, config) filename, = parse_uri(uri) filename.untaint soc = UNIXSocket.open(filename) self.new(uri, soc, config) end def self.open_server(uri, config) filename, = parse_uri(uri) if filename.size == 0 soc = temp_server filename = soc.path uri = 'drbunix:' + soc.path else soc = UNIXServer.open(filename) end owner = config[:UNIXFileOwner] group = config[:UNIXFileGroup] if owner || group require 'etc' owner = Etc.getpwnam( owner ).uid if owner group = Etc.getgrnam( group ).gid if group File.chown owner, group, filename end mode = config[:UNIXFileMode] File.chmod(mode, filename) if mode self.new(uri, soc, config, true) end def self.uri_option(uri, config) filename, option = parse_uri(uri) return "drbunix:#{filename}", option end def initialize(uri, soc, config={}, server_mode = false) super(uri, soc, config) set_sockopt(@socket) @server_mode = server_mode @acl = nil end # import from tempfile.rb Max_try = 10 private def self.temp_server tmpdir = Dir::tmpdir n = 0 while true begin tmpname = sprintf('%s/druby%d.%d', tmpdir, $$, n) lock = tmpname + '.lock' unless File.exist?(tmpname) or File.exist?(lock) Dir.mkdir(lock) break end rescue raise "cannot generate tempfile `%s'" % tmpname if n >= Max_try #sleep(1) end n += 1 end soc = UNIXServer.new(tmpname) Dir.rmdir(lock) soc end public def close return unless @socket path = @socket.path if @server_mode @socket.close File.unlink(path) if @server_mode @socket = nil close_shutdown_pipe end def accept s = accept_or_shutdown return nil unless s self.class.new(nil, s, @config) end def set_sockopt(soc) soc.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) if defined? Fcntl::FD_CLOEXEC end end DRbProtocol.add_protocol(DRbUNIXSocket) # :startdoc: end PK!Z||2.2.0/drb/observer.rbnu[require 'observer' module DRb # The Observable module extended to DRb. See Observable for details. module DRbObservable include Observable # Notifies observers of a change in state. See also # Observable#notify_observers def notify_observers(*arg) if defined? @observer_state and @observer_state if defined? @observer_peers @observer_peers.each do |observer, method| begin observer.send(method, *arg) rescue delete_observer(observer) end end end @observer_state = false end end end end PK!ȍ-  2.2.0/sync.rbnu[# # sync.rb - 2 phase lock with counter # $Release Version: 1.0$ # $Revision: 40825 $ # by Keiju ISHITSUKA(keiju@ishitsuka.com) # # -- # Sync_m, Synchronizer_m # Usage: # obj.extend(Sync_m) # or # class Foo # include Sync_m # : # end # # Sync_m#sync_mode # Sync_m#sync_locked?, locked? # Sync_m#sync_shared?, shared? # Sync_m#sync_exclusive?, sync_exclusive? # Sync_m#sync_try_lock, try_lock # Sync_m#sync_lock, lock # Sync_m#sync_unlock, unlock # # Sync, Synchronizer: # Usage: # sync = Sync.new # # Sync#mode # Sync#locked? # Sync#shared? # Sync#exclusive? # Sync#try_lock(mode) -- mode = :EX, :SH, :UN # Sync#lock(mode) -- mode = :EX, :SH, :UN # Sync#unlock # Sync#synchronize(mode) {...} # # unless defined? Thread raise "Thread not available for this ruby interpreter" end ## # A module that provides a two-phase lock with a counter. module Sync_m # lock mode UN = :UN SH = :SH EX = :EX # exceptions class Err < StandardError def Err.Fail(*opt) fail self, sprintf(self::Message, *opt) end class UnknownLocker < Err Message = "Thread(%s) not locked." def UnknownLocker.Fail(th) super(th.inspect) end end class LockModeFailer < Err Message = "Unknown lock mode(%s)" def LockModeFailer.Fail(mode) if mode.id2name mode = id2name end super(mode) end end end def Sync_m.define_aliases(cl) cl.module_eval %q{ alias locked? sync_locked? alias shared? sync_shared? alias exclusive? sync_exclusive? alias lock sync_lock alias unlock sync_unlock alias try_lock sync_try_lock alias synchronize sync_synchronize } end def Sync_m.append_features(cl) super # do nothing for Modules # make aliases for Classes. define_aliases(cl) unless cl.instance_of?(Module) self end def Sync_m.extend_object(obj) super obj.sync_extend end def sync_extend unless (defined? locked? and defined? shared? and defined? exclusive? and defined? lock and defined? unlock and defined? try_lock and defined? synchronize) Sync_m.define_aliases(singleton_class) end sync_initialize end # accessing def sync_locked? sync_mode != UN end def sync_shared? sync_mode == SH end def sync_exclusive? sync_mode == EX end # locking methods. def sync_try_lock(mode = EX) return unlock if mode == UN @sync_mutex.synchronize do sync_try_lock_sub(mode) end end def sync_lock(m = EX) return unlock if m == UN Thread.handle_interrupt(StandardError => :on_blocking) do while true @sync_mutex.synchronize do begin if sync_try_lock_sub(m) return self else if sync_sh_locker[Thread.current] sync_upgrade_waiting.push [Thread.current, sync_sh_locker[Thread.current]] sync_sh_locker.delete(Thread.current) else unless sync_waiting.include?(Thread.current) || sync_upgrade_waiting.reverse_each.any?{|w| w.first == Thread.current } sync_waiting.push Thread.current end end @sync_mutex.sleep end ensure sync_waiting.delete(Thread.current) end end end end self end def sync_unlock(m = EX) wakeup_threads = [] @sync_mutex.synchronize do if sync_mode == UN Err::UnknownLocker.Fail(Thread.current) end m = sync_mode if m == EX and sync_mode == SH runnable = false case m when UN Err::UnknownLocker.Fail(Thread.current) when EX if sync_ex_locker == Thread.current if (self.sync_ex_count = sync_ex_count - 1) == 0 self.sync_ex_locker = nil if sync_sh_locker.include?(Thread.current) self.sync_mode = SH else self.sync_mode = UN end runnable = true end else Err::UnknownLocker.Fail(Thread.current) end when SH if (count = sync_sh_locker[Thread.current]).nil? Err::UnknownLocker.Fail(Thread.current) else if (sync_sh_locker[Thread.current] = count - 1) == 0 sync_sh_locker.delete(Thread.current) if sync_sh_locker.empty? and sync_ex_count == 0 self.sync_mode = UN runnable = true end end end end if runnable if sync_upgrade_waiting.size > 0 th, count = sync_upgrade_waiting.shift sync_sh_locker[th] = count th.wakeup wakeup_threads.push th else wait = sync_waiting self.sync_waiting = [] for th in wait th.wakeup wakeup_threads.push th end end end end for th in wakeup_threads th.run end self end def sync_synchronize(mode = EX) Thread.handle_interrupt(StandardError => :on_blocking) do sync_lock(mode) begin yield ensure sync_unlock end end end attr_accessor :sync_mode attr_accessor :sync_waiting attr_accessor :sync_upgrade_waiting attr_accessor :sync_sh_locker attr_accessor :sync_ex_locker attr_accessor :sync_ex_count def sync_inspect sync_iv = instance_variables.select{|iv| /^@sync_/ =~ iv.id2name}.collect{|iv| iv.id2name + '=' + instance_eval(iv.id2name).inspect}.join(",") print "<#{self.class}.extend Sync_m: #{inspect}, " end private def sync_initialize @sync_mode = UN @sync_waiting = [] @sync_upgrade_waiting = [] @sync_sh_locker = Hash.new @sync_ex_locker = nil @sync_ex_count = 0 @sync_mutex = Mutex.new end def initialize(*args) super sync_initialize end def sync_try_lock_sub(m) case m when SH case sync_mode when UN self.sync_mode = m sync_sh_locker[Thread.current] = 1 ret = true when SH count = 0 unless count = sync_sh_locker[Thread.current] sync_sh_locker[Thread.current] = count + 1 ret = true when EX # in EX mode, lock will upgrade to EX lock if sync_ex_locker == Thread.current self.sync_ex_count = sync_ex_count + 1 ret = true else ret = false end end when EX if sync_mode == UN or sync_mode == SH && sync_sh_locker.size == 1 && sync_sh_locker.include?(Thread.current) self.sync_mode = m self.sync_ex_locker = Thread.current self.sync_ex_count = 1 ret = true elsif sync_mode == EX && sync_ex_locker == Thread.current self.sync_ex_count = sync_ex_count + 1 ret = true else ret = false end else Err::LockModeFailer.Fail mode end return ret end end ## # An alias for Sync_m from sync.rb Synchronizer_m = Sync_m ## # A class that provides two-phase lock with a counter. See Sync_m for # details. class Sync include Sync_m end ## # An alias for Sync from sync.rb. See Sync_m for details. Synchronizer = Sync PK!uXLL 2.2.0/set.rbnu[#-- # set.rb - defines the Set class #++ # Copyright (c) 2002-2013 Akinori MUSHA # # Documentation by Akinori MUSHA and Gavin Sinclair. # # All rights reserved. You can redistribute and/or modify it under the same # terms as Ruby. # # $Id: set.rb 47085 2014-08-06 11:28:21Z knu $ # # == Overview # # This library provides the Set class, which deals with a collection # of unordered values with no duplicates. It is a hybrid of Array's # intuitive inter-operation facilities and Hash's fast lookup. If you # need to keep values sorted in some order, use the SortedSet class. # # The method +to_set+ is added to Enumerable for convenience. # # See the Set and SortedSet documentation for examples of usage. # # Set implements a collection of unordered values with no duplicates. # This is a hybrid of Array's intuitive inter-operation facilities and # Hash's fast lookup. # # Set is easy to use with Enumerable objects (implementing +each+). # Most of the initializer methods and binary operators accept generic # Enumerable objects besides sets and arrays. An Enumerable object # can be converted to Set using the +to_set+ method. # # Set uses Hash as storage, so you must note the following points: # # * Equality of elements is determined according to Object#eql? and # Object#hash. # * Set assumes that the identity of each element does not change # while it is stored. Modifying an element of a set will render the # set to an unreliable state. # * When a string is to be stored, a frozen copy of the string is # stored instead unless the original string is already frozen. # # == Comparison # # The comparison operators <, >, <= and >= are implemented as # shorthand for the {proper_,}{subset?,superset?} methods. However, # the <=> operator is intentionally left out because not every pair of # sets is comparable. ({x,y} vs. {x,z} for example) # # == Example # # require 'set' # s1 = Set.new [1, 2] # -> # # s2 = [1, 2].to_set # -> # # s1 == s2 # -> true # s1.add("foo") # -> # # s1.merge([2, 6]) # -> # # s1.subset? s2 # -> false # s2.subset? s1 # -> true # # == Contact # # - Akinori MUSHA (current maintainer) # class Set include Enumerable # Creates a new set containing the given objects. def self.[](*ary) new(ary) end # Creates a new set containing the elements of the given enumerable # object. # # If a block is given, the elements of enum are preprocessed by the # given block. def initialize(enum = nil, &block) # :yields: o @hash ||= Hash.new enum.nil? and return if block do_with_enum(enum) { |o| add(block[o]) } else merge(enum) end end def do_with_enum(enum, &block) # :nodoc: if enum.respond_to?(:each_entry) enum.each_entry(&block) if block elsif enum.respond_to?(:each) enum.each(&block) if block else raise ArgumentError, "value must be enumerable" end end private :do_with_enum # Dup internal hash. def initialize_dup(orig) super @hash = orig.instance_variable_get(:@hash).dup end # Clone internal hash. def initialize_clone(orig) super @hash = orig.instance_variable_get(:@hash).clone end def freeze # :nodoc: @hash.freeze super end def taint # :nodoc: @hash.taint super end def untaint # :nodoc: @hash.untaint super end # Returns the number of elements. def size @hash.size end alias length size # Returns true if the set contains no elements. def empty? @hash.empty? end # Removes all elements and returns self. def clear @hash.clear self end # Replaces the contents of the set with the contents of the given # enumerable object and returns self. def replace(enum) if enum.instance_of?(self.class) @hash.replace(enum.instance_variable_get(:@hash)) self else do_with_enum(enum) clear merge(enum) end end # Converts the set to an array. The order of elements is uncertain. def to_a @hash.keys end # Returns self if no arguments are given. Otherwise, converts the # set to another with klass.new(self, *args, &block). # # In subclasses, returns klass.new(self, *args, &block) unless # overridden. def to_set(klass = Set, *args, &block) return self if instance_of?(Set) && klass == Set && block.nil? && args.empty? klass.new(self, *args, &block) end def flatten_merge(set, seen = Set.new) # :nodoc: set.each { |e| if e.is_a?(Set) if seen.include?(e_id = e.object_id) raise ArgumentError, "tried to flatten recursive Set" end seen.add(e_id) flatten_merge(e, seen) seen.delete(e_id) else add(e) end } self end protected :flatten_merge # Returns a new set that is a copy of the set, flattening each # containing set recursively. def flatten self.class.new.flatten_merge(self) end # Equivalent to Set#flatten, but replaces the receiver with the # result in place. Returns nil if no modifications were made. def flatten! if detect { |e| e.is_a?(Set) } replace(flatten()) else nil end end # Returns true if the set contains the given object. def include?(o) @hash.include?(o) end alias member? include? # Returns true if the set is a superset of the given set. def superset?(set) set.is_a?(Set) or raise ArgumentError, "value must be a set" return false if size < set.size set.all? { |o| include?(o) } end alias >= superset? # Returns true if the set is a proper superset of the given set. def proper_superset?(set) set.is_a?(Set) or raise ArgumentError, "value must be a set" return false if size <= set.size set.all? { |o| include?(o) } end alias > proper_superset? # Returns true if the set is a subset of the given set. def subset?(set) set.is_a?(Set) or raise ArgumentError, "value must be a set" return false if set.size < size all? { |o| set.include?(o) } end alias <= subset? # Returns true if the set is a proper subset of the given set. def proper_subset?(set) set.is_a?(Set) or raise ArgumentError, "value must be a set" return false if set.size <= size all? { |o| set.include?(o) } end alias < proper_subset? # Returns true if the set and the given set have at least one # element in common. # # e.g.: # # require 'set' # Set[1, 2, 3].intersect? Set[4, 5] # => false # Set[1, 2, 3].intersect? Set[3, 4] # => true def intersect?(set) set.is_a?(Set) or raise ArgumentError, "value must be a set" if size < set.size any? { |o| set.include?(o) } else set.any? { |o| include?(o) } end end # Returns true if the set and the given set have no element in # common. This method is the opposite of +intersect?+. # # e.g.: # # require 'set' # Set[1, 2, 3].disjoint? Set[3, 4] # => false # Set[1, 2, 3].disjoint? Set[4, 5] # => true def disjoint?(set) !intersect?(set) end # Calls the given block once for each element in the set, passing # the element as parameter. Returns an enumerator if no block is # given. def each(&block) block or return enum_for(__method__) @hash.each_key(&block) self end # Adds the given object to the set and returns self. Use +merge+ to # add many elements at once. def add(o) @hash[o] = true self end alias << add # Adds the given object to the set and returns self. If the # object is already in the set, returns nil. def add?(o) if include?(o) nil else add(o) end end # Deletes the given object from the set and returns self. Use +subtract+ to # delete many items at once. def delete(o) @hash.delete(o) self end # Deletes the given object from the set and returns self. If the # object is not in the set, returns nil. def delete?(o) if include?(o) delete(o) else nil end end # Deletes every element of the set for which block evaluates to # true, and returns self. def delete_if block_given? or return enum_for(__method__) # @hash.delete_if should be faster, but using it breaks the order # of enumeration in subclasses. select { |o| yield o }.each { |o| @hash.delete(o) } self end # Deletes every element of the set for which block evaluates to # false, and returns self. def keep_if block_given? or return enum_for(__method__) # @hash.keep_if should be faster, but using it breaks the order of # enumeration in subclasses. reject { |o| yield o }.each { |o| @hash.delete(o) } self end # Replaces the elements with ones returned by collect(). def collect! block_given? or return enum_for(__method__) set = self.class.new each { |o| set << yield(o) } replace(set) end alias map! collect! # Equivalent to Set#delete_if, but returns nil if no changes were # made. def reject!(&block) block or return enum_for(__method__) n = size delete_if(&block) size == n ? nil : self end # Equivalent to Set#keep_if, but returns nil if no changes were # made. def select!(&block) block or return enum_for(__method__) n = size keep_if(&block) size == n ? nil : self end # Merges the elements of the given enumerable object to the set and # returns self. def merge(enum) if enum.instance_of?(self.class) @hash.update(enum.instance_variable_get(:@hash)) else do_with_enum(enum) { |o| add(o) } end self end # Deletes every element that appears in the given enumerable object # and returns self. def subtract(enum) do_with_enum(enum) { |o| delete(o) } self end # Returns a new set built by merging the set and the elements of the # given enumerable object. def |(enum) dup.merge(enum) end alias + | ## alias union | ## # Returns a new set built by duplicating the set, removing every # element that appears in the given enumerable object. def -(enum) dup.subtract(enum) end alias difference - ## # Returns a new set containing elements common to the set and the # given enumerable object. def &(enum) n = self.class.new do_with_enum(enum) { |o| n.add(o) if include?(o) } n end alias intersection & ## # Returns a new set containing elements exclusive between the set # and the given enumerable object. (set ^ enum) is equivalent to # ((set | enum) - (set & enum)). def ^(enum) n = Set.new(enum) each { |o| if n.include?(o) then n.delete(o) else n.add(o) end } n end # Returns true if two sets are equal. The equality of each couple # of elements is defined according to Object#eql?. def ==(other) if self.equal?(other) true elsif other.instance_of?(self.class) @hash == other.instance_variable_get(:@hash) elsif other.is_a?(Set) && self.size == other.size other.all? { |o| @hash.include?(o) } else false end end def hash # :nodoc: @hash.hash end def eql?(o) # :nodoc: return false unless o.is_a?(Set) @hash.eql?(o.instance_variable_get(:@hash)) end # Classifies the set by the return value of the given block and # returns a hash of {value => set of elements} pairs. The block is # called once for each element of the set, passing the element as # parameter. # # e.g.: # # require 'set' # files = Set.new(Dir.glob("*.rb")) # hash = files.classify { |f| File.mtime(f).year } # p hash # => {2000=>#, # # 2001=>#, # # 2002=>#} def classify # :yields: o block_given? or return enum_for(__method__) h = {} each { |i| x = yield(i) (h[x] ||= self.class.new).add(i) } h end # Divides the set into a set of subsets according to the commonality # defined by the given block. # # If the arity of the block is 2, elements o1 and o2 are in common # if block.call(o1, o2) is true. Otherwise, elements o1 and o2 are # in common if block.call(o1) == block.call(o2). # # e.g.: # # require 'set' # numbers = Set[1, 3, 4, 6, 9, 10, 11] # set = numbers.divide { |i,j| (i - j).abs == 1 } # p set # => #, # # #, # # #, # # #}> def divide(&func) func or return enum_for(__method__) if func.arity == 2 require 'tsort' class << dig = {} # :nodoc: include TSort alias tsort_each_node each_key def tsort_each_child(node, &block) fetch(node).each(&block) end end each { |u| dig[u] = a = [] each{ |v| func.call(u, v) and a << v } } set = Set.new() dig.each_strongly_connected_component { |css| set.add(self.class.new(css)) } set else Set.new(classify(&func).values) end end InspectKey = :__inspect_key__ # :nodoc: # Returns a string containing a human-readable representation of the # set. ("#") def inspect ids = (Thread.current[InspectKey] ||= []) if ids.include?(object_id) return sprintf('#<%s: {...}>', self.class.name) end begin ids << object_id return sprintf('#<%s: {%s}>', self.class, to_a.inspect[1..-2]) ensure ids.pop end end def pretty_print(pp) # :nodoc: pp.text sprintf('#<%s: {', self.class.name) pp.nest(1) { pp.seplist(self) { |o| pp.pp o } } pp.text "}>" end def pretty_print_cycle(pp) # :nodoc: pp.text sprintf('#<%s: {%s}>', self.class.name, empty? ? '' : '...') end end # # SortedSet implements a Set that guarantees that its elements are # yielded in sorted order (according to the return values of their # #<=> methods) when iterating over them. # # All elements that are added to a SortedSet must respond to the <=> # method for comparison. # # Also, all elements must be mutually comparable: el1 <=> # el2 must not return nil for any elements el1 # and el2, else an ArgumentError will be raised when # iterating over the SortedSet. # # == Example # # require "set" # # set = SortedSet.new([2, 1, 5, 6, 4, 5, 3, 3, 3]) # ary = [] # # set.each do |obj| # ary << obj # end # # p ary # => [1, 2, 3, 4, 5, 6] # # set2 = SortedSet.new([1, 2, "3"]) # set2.each { |obj| } # => raises ArgumentError: comparison of Fixnum with String failed # class SortedSet < Set @@setup = false class << self def [](*ary) # :nodoc: new(ary) end def setup # :nodoc: @@setup and return module_eval { # a hack to shut up warning alias old_init initialize } begin require 'rbtree' module_eval <<-END, __FILE__, __LINE__+1 def initialize(*args) @hash = RBTree.new super end def add(o) o.respond_to?(:<=>) or raise ArgumentError, "value must respond to <=>" super end alias << add END rescue LoadError module_eval <<-END, __FILE__, __LINE__+1 def initialize(*args) @keys = nil super end def clear @keys = nil super end def replace(enum) @keys = nil super end def add(o) o.respond_to?(:<=>) or raise ArgumentError, "value must respond to <=>" @keys = nil super end alias << add def delete(o) @keys = nil @hash.delete(o) self end def delete_if block_given? or return enum_for(__method__) n = @hash.size super @keys = nil if @hash.size != n self end def keep_if block_given? or return enum_for(__method__) n = @hash.size super @keys = nil if @hash.size != n self end def merge(enum) @keys = nil super end def each(&block) block or return enum_for(__method__) to_a.each(&block) self end def to_a (@keys = @hash.keys).sort! unless @keys @keys end END end module_eval { # a hack to shut up warning remove_method :old_init } @@setup = true end end def initialize(*args, &block) # :nodoc: SortedSet.setup initialize(*args, &block) end end module Enumerable # Makes a set from the enumerable object with given arguments. # Needs to +require "set"+ to use this method. def to_set(klass = Set, *args, &block) klass.new(self, *args, &block) end end # =begin # == RestricedSet class # RestricedSet implements a set with restrictions defined by a given # block. # # === Super class # Set # # === Class Methods # --- RestricedSet::new(enum = nil) { |o| ... } # --- RestricedSet::new(enum = nil) { |rset, o| ... } # Creates a new restricted set containing the elements of the given # enumerable object. Restrictions are defined by the given block. # # If the block's arity is 2, it is called with the RestrictedSet # itself and an object to see if the object is allowed to be put in # the set. # # Otherwise, the block is called with an object to see if the object # is allowed to be put in the set. # # === Instance Methods # --- restriction_proc # Returns the restriction procedure of the set. # # =end # # class RestricedSet < Set # def initialize(*args, &block) # @proc = block or raise ArgumentError, "missing a block" # # if @proc.arity == 2 # instance_eval %{ # def add(o) # @hash[o] = true if @proc.call(self, o) # self # end # alias << add # # def add?(o) # if include?(o) || !@proc.call(self, o) # nil # else # @hash[o] = true # self # end # end # # def replace(enum) # enum.respond_to?(:each) or raise ArgumentError, "value must be enumerable" # clear # enum.each_entry { |o| add(o) } # # self # end # # def merge(enum) # enum.respond_to?(:each) or raise ArgumentError, "value must be enumerable" # enum.each_entry { |o| add(o) } # # self # end # } # else # instance_eval %{ # def add(o) # if @proc.call(o) # @hash[o] = true # end # self # end # alias << add # # def add?(o) # if include?(o) || !@proc.call(o) # nil # else # @hash[o] = true # self # end # end # } # end # # super(*args) # end # # def restriction_proc # @proc # end # end # Tests have been moved to test/test_set.rb. PK!Fd 2.2.0/digest/sha2.rbnu[#-- # sha2.rb - defines Digest::SHA2 class which wraps up the SHA256, # SHA384, and SHA512 classes. #++ # Copyright (c) 2006 Akinori MUSHA # # All rights reserved. You can redistribute and/or modify it under the same # terms as Ruby. # # $Id: sha2.rb 35293 2012-04-10 22:41:04Z drbrain $ require 'digest' require 'digest/sha2.so' module Digest # # A meta digest provider class for SHA256, SHA384 and SHA512. # class SHA2 < Digest::Class # call-seq: # Digest::SHA2.new(bitlen = 256) -> digest_obj # # Creates a new SHA2 hash object with a given bit length. # # Valid bit lengths are 256, 384 and 512. def initialize(bitlen = 256) case bitlen when 256 @sha2 = Digest::SHA256.new when 384 @sha2 = Digest::SHA384.new when 512 @sha2 = Digest::SHA512.new else raise ArgumentError, "unsupported bit length: %s" % bitlen.inspect end @bitlen = bitlen end # call-seq: # digest_obj.reset -> digest_obj # # Resets the digest to the initial state and returns self. def reset @sha2.reset self end # call-seq: # digest_obj.update(string) -> digest_obj # digest_obj << string -> digest_obj # # Updates the digest using a given _string_ and returns self. def update(str) @sha2.update(str) self end alias << update def finish # :nodoc: @sha2.digest! end private :finish # call-seq: # digest_obj.block_length -> Integer # # Returns the block length of the digest in bytes. # # Digest::SHA256.new.block_length * 8 # # => 512 # Digest::SHA384.new.block_length * 8 # # => 1024 # Digest::SHA512.new.block_length * 8 # # => 1024 def block_length @sha2.block_length end # call-seq: # digest_obj.digest_length -> Integer # # Returns the length of the hash value of the digest in bytes. # # Digest::SHA256.new.digest_length * 8 # # => 256 # Digest::SHA384.new.digest_length * 8 # # => 384 # Digest::SHA512.new.digest_length * 8 # # => 512 # # For example, digests produced by Digest::SHA256 will always be 32 bytes # (256 bits) in size. def digest_length @sha2.digest_length end def initialize_copy(other) # :nodoc: @sha2 = other.instance_eval { @sha2.clone } end def inspect # :nodoc: "#<%s:%d %s>" % [self.class.name, @bitlen, hexdigest] end end end PK!r/2ǰ2.2.0/English.rbnu[# Include the English library file in a Ruby script, and you can # reference the global variables such as \VAR{\$\_} using less # cryptic names, listed in the following table.% \vref{tab:english}. # # Without 'English': # # $\ = ' -- ' # "waterbuffalo" =~ /buff/ # print $', $$, "\n" # # With English: # # require "English" # # $OUTPUT_FIELD_SEPARATOR = ' -- ' # "waterbuffalo" =~ /buff/ # print $POSTMATCH, $PID, "\n" # # Below is a full list of descriptive aliases and their associated global # variable: # # $ERROR_INFO:: $! # $ERROR_POSITION:: $@ # $FS:: $; # $FIELD_SEPARATOR:: $; # $OFS:: $, # $OUTPUT_FIELD_SEPARATOR:: $, # $RS:: $/ # $INPUT_RECORD_SEPARATOR:: $/ # $ORS:: $\ # $OUTPUT_RECORD_SEPARATOR:: $\ # $INPUT_LINE_NUMBER:: $. # $NR:: $. # $LAST_READ_LINE:: $_ # $DEFAULT_OUTPUT:: $> # $DEFAULT_INPUT:: $< # $PID:: $$ # $PROCESS_ID:: $$ # $CHILD_STATUS:: $? # $LAST_MATCH_INFO:: $~ # $IGNORECASE:: $= # $ARGV:: $* # $MATCH:: $& # $PREMATCH:: $` # $POSTMATCH:: $' # $LAST_PAREN_MATCH:: $+ # module English end if false # The exception object passed to +raise+. alias $ERROR_INFO $! # The stack backtrace generated by the last # exception. See Kernel.caller for details. Thread local. alias $ERROR_POSITION $@ # The default separator pattern used by String.split. May be # set from the command line using the -F flag. alias $FS $; # The default separator pattern used by String.split. May be # set from the command line using the -F flag. alias $FIELD_SEPARATOR $; # The separator string output between the parameters to methods such # as Kernel.print and Array.join. Defaults to +nil+, # which adds no text. alias $OFS $, # The separator string output between the parameters to methods such # as Kernel.print and Array.join. Defaults to +nil+, # which adds no text. alias $OUTPUT_FIELD_SEPARATOR $, # The input record separator (newline by default). This is the value # that routines such as Kernel.gets use to determine record # boundaries. If set to +nil+, +gets+ will read the entire file. alias $RS $/ # The input record separator (newline by default). This is the value # that routines such as Kernel.gets use to determine record # boundaries. If set to +nil+, +gets+ will read the entire file. alias $INPUT_RECORD_SEPARATOR $/ # The string appended to the output of every call to methods such as # Kernel.print and IO.write. The default value is # +nil+. alias $ORS $\ # The string appended to the output of every call to methods such as # Kernel.print and IO.write. The default value is # +nil+. alias $OUTPUT_RECORD_SEPARATOR $\ # The number of the last line read from the current input file. alias $INPUT_LINE_NUMBER $. # The number of the last line read from the current input file. alias $NR $. # The last line read by Kernel.gets or # Kernel.readline. Many string-related functions in the # +Kernel+ module operate on $_ by default. The variable is # local to the current scope. Thread local. alias $LAST_READ_LINE $_ # The destination of output for Kernel.print # and Kernel.printf. The default value is # $stdout. alias $DEFAULT_OUTPUT $> # An object that provides access to the concatenation # of the contents of all the files # given as command-line arguments, or $stdin # (in the case where there are no # arguments). $< supports methods similar to a # +File+ object: # +inmode+, +close+, # closed?, +each+, # each_byte, each_line, # +eof+, eof?, +file+, # +filename+, +fileno+, # +getc+, +gets+, +lineno+, # lineno=, +path+, # +pos+, pos=, # +read+, +readchar+, # +readline+, +readlines+, # +rewind+, +seek+, +skip+, # +tell+, to_a, to_i, # to_io, to_s, along with the # methods in +Enumerable+. The method +file+ # returns a +File+ object for the file currently # being read. This may change as $< reads # through the files on the command line. Read only. alias $DEFAULT_INPUT $< # The process number of the program being executed. Read only. alias $PID $$ # The process number of the program being executed. Read only. alias $PROCESS_ID $$ # The exit status of the last child process to terminate. Read # only. Thread local. alias $CHILD_STATUS $? # A +MatchData+ object that encapsulates the results of a successful # pattern match. The variables $&, $`, $', # and $1 to $9 are all derived from # $~. Assigning to $~ changes the values of these # derived variables. This variable is local to the current # scope. alias $LAST_MATCH_INFO $~ # If set to any value apart from +nil+ or +false+, all pattern matches # will be case insensitive, string comparisons will ignore case, and # string hash values will be case insensitive. Deprecated alias $IGNORECASE $= # An array of strings containing the command-line # options from the invocation of the program. Options # used by the Ruby interpreter will have been # removed. Read only. Also known simply as +ARGV+. alias $ARGV $* # The string matched by the last successful pattern # match. This variable is local to the current # scope. Read only. alias $MATCH $& # The string preceding the match in the last # successful pattern match. This variable is local to # the current scope. Read only. alias $PREMATCH $` # The string following the match in the last # successful pattern match. This variable is local to # the current scope. Read only. alias $POSTMATCH $' # The contents of the highest-numbered group matched in the last # successful pattern match. Thus, in "cat" =~ /(c|a)(t|z)/, # $+ will be set to "t". This variable is local to the # current scope. Read only. alias $LAST_PAREN_MATCH $+ PK!')2.2.0/cgi/cookie.rbnu[require 'cgi/util' class CGI # Class representing an HTTP cookie. # # In addition to its specific fields and methods, a Cookie instance # is a delegator to the array of its values. # # See RFC 2965. # # == Examples of use # cookie1 = CGI::Cookie.new("name", "value1", "value2", ...) # cookie1 = CGI::Cookie.new("name" => "name", "value" => "value") # cookie1 = CGI::Cookie.new('name' => 'name', # 'value' => ['value1', 'value2', ...], # 'path' => 'path', # optional # 'domain' => 'domain', # optional # 'expires' => Time.now, # optional # 'secure' => true # optional # ) # # cgi.out("cookie" => [cookie1, cookie2]) { "string" } # # name = cookie1.name # values = cookie1.value # path = cookie1.path # domain = cookie1.domain # expires = cookie1.expires # secure = cookie1.secure # # cookie1.name = 'name' # cookie1.value = ['value1', 'value2', ...] # cookie1.path = 'path' # cookie1.domain = 'domain' # cookie1.expires = Time.now + 30 # cookie1.secure = true class Cookie < Array @@accept_charset="UTF-8" unless defined?(@@accept_charset) # Create a new CGI::Cookie object. # # :call-seq: # Cookie.new(name_string,*value) # Cookie.new(options_hash) # # +name_string+:: # The name of the cookie; in this form, there is no #domain or # #expiration. The #path is gleaned from the +SCRIPT_NAME+ environment # variable, and #secure is false. # *value:: # value or list of values of the cookie # +options_hash+:: # A Hash of options to initialize this Cookie. Possible options are: # # name:: the name of the cookie. Required. # value:: the cookie's value or list of values. # path:: the path for which this cookie applies. Defaults to the # the value of the +SCRIPT_NAME+ environment variable. # domain:: the domain for which this cookie applies. # expires:: the time at which this cookie expires, as a +Time+ object. # secure:: whether this cookie is a secure cookie or not (default to # false). Secure cookies are only transmitted to HTTPS # servers. # # These keywords correspond to attributes of the cookie object. def initialize(name = "", *value) @domain = nil @expires = nil if name.kind_of?(String) @name = name %r|^(.*/)|.match(ENV["SCRIPT_NAME"]) @path = ($1 or "") @secure = false return super(value) end options = name unless options.has_key?("name") raise ArgumentError, "`name' required" end @name = options["name"] value = Array(options["value"]) # simple support for IE if options["path"] @path = options["path"] else %r|^(.*/)|.match(ENV["SCRIPT_NAME"]) @path = ($1 or "") end @domain = options["domain"] @expires = options["expires"] @secure = options["secure"] == true ? true : false super(value) end # Name of this cookie, as a +String+ attr_accessor :name # Path for which this cookie applies, as a +String+ attr_accessor :path # Domain for which this cookie applies, as a +String+ attr_accessor :domain # Time at which this cookie expires, as a +Time+ attr_accessor :expires # True if this cookie is secure; false otherwise attr_reader("secure") # Returns the value or list of values for this cookie. def value self end # Replaces the value of this cookie with a new value or list of values. def value=(val) replace(Array(val)) end # Set whether the Cookie is a secure cookie or not. # # +val+ must be a boolean. def secure=(val) @secure = val if val == true or val == false @secure end # Convert the Cookie to its string representation. def to_s val = collect{|v| CGI.escape(v) }.join("&") buf = "#{@name}=#{val}" buf << "; domain=#{@domain}" if @domain buf << "; path=#{@path}" if @path buf << "; expires=#{CGI::rfc1123_date(@expires)}" if @expires buf << "; secure" if @secure == true buf end # Parse a raw cookie string into a hash of cookie-name=>Cookie # pairs. # # cookies = CGI::Cookie.parse("raw_cookie_string") # # { "name1" => cookie1, "name2" => cookie2, ... } # def self.parse(raw_cookie) cookies = Hash.new([]) return cookies unless raw_cookie raw_cookie.split(/[;,]\s?/).each do |pairs| name, values = pairs.split('=',2) next unless name and values name = CGI.unescape(name) values ||= "" values = values.split('&').collect{|v| CGI.unescape(v,@@accept_charset) } if cookies.has_key?(name) values = cookies[name].value + values end cookies[name] = Cookie.new(name, *values) end cookies end # A summary of cookie string. def inspect "#" end end # class Cookie end PK!@Wll2.2.0/cgi/html.rbnu[class CGI # Base module for HTML-generation mixins. # # Provides methods for code generation for tags following # the various DTD element types. module TagMaker # :nodoc: # Generate code for an element with required start and end tags. # # - - def nn_element(element, attributes = {}) s = nOE_element(element, attributes) if block_given? s << yield.to_s end s << "" end def nn_element_def(attributes = {}, &block) nn_element(__callee__, attributes, &block) end # Generate code for an empty element. # # - O EMPTY def nOE_element(element, attributes = {}) attributes={attributes=>nil} if attributes.kind_of?(String) s = "<#{element.upcase}" attributes.each do|name, value| next unless value s << " " s << CGI::escapeHTML(name.to_s) if value != true s << '="' s << CGI::escapeHTML(value.to_s) s << '"' end end s << ">" end def nOE_element_def(attributes = {}, &block) nOE_element(__callee__, attributes, &block) end # Generate code for an element for which the end (and possibly the # start) tag is optional. # # O O or - O def nO_element(element, attributes = {}) s = nOE_element(element, attributes) if block_given? s << yield.to_s s << "" end s end def nO_element_def(attributes = {}, &block) nO_element(__callee__, attributes, &block) end end # TagMaker # Mixin module providing HTML generation methods. # # For example, # cgi.a("http://www.example.com") { "Example" } # # => "Example" # # Modules Html3, Html4, etc., contain more basic HTML-generation methods # (+#title+, +#h1+, etc.). # # See class CGI for a detailed example. # module HtmlExtension # Generate an Anchor element as a string. # # +href+ can either be a string, giving the URL # for the HREF attribute, or it can be a hash of # the element's attributes. # # The body of the element is the string returned by the no-argument # block passed in. # # a("http://www.example.com") { "Example" } # # => "Example" # # a("HREF" => "http://www.example.com", "TARGET" => "_top") { "Example" } # # => "Example" # def a(href = "") # :yield: attributes = if href.kind_of?(String) { "HREF" => href } else href end super(attributes) end # Generate a Document Base URI element as a String. # # +href+ can either by a string, giving the base URL for the HREF # attribute, or it can be a has of the element's attributes. # # The passed-in no-argument block is ignored. # # base("http://www.example.com/cgi") # # => "" def base(href = "") # :yield: attributes = if href.kind_of?(String) { "HREF" => href } else href end super(attributes) end # Generate a BlockQuote element as a string. # # +cite+ can either be a string, give the URI for the source of # the quoted text, or a hash, giving all attributes of the element, # or it can be omitted, in which case the element has no attributes. # # The body is provided by the passed-in no-argument block # # blockquote("http://www.example.com/quotes/foo.html") { "Foo!" } # #=> "
Foo!
def blockquote(cite = {}) # :yield: attributes = if cite.kind_of?(String) { "CITE" => cite } else cite end super(attributes) end # Generate a Table Caption element as a string. # # +align+ can be a string, giving the alignment of the caption # (one of top, bottom, left, or right). It can be a hash of # all the attributes of the element. Or it can be omitted. # # The body of the element is provided by the passed-in no-argument block. # # caption("left") { "Capital Cities" } # # => Capital Cities def caption(align = {}) # :yield: attributes = if align.kind_of?(String) { "ALIGN" => align } else align end super(attributes) end # Generate a Checkbox Input element as a string. # # The attributes of the element can be specified as three arguments, # +name+, +value+, and +checked+. +checked+ is a boolean value; # if true, the CHECKED attribute will be included in the element. # # Alternatively, the attributes can be specified as a hash. # # checkbox("name") # # = checkbox("NAME" => "name") # # checkbox("name", "value") # # = checkbox("NAME" => "name", "VALUE" => "value") # # checkbox("name", "value", true) # # = checkbox("NAME" => "name", "VALUE" => "value", "CHECKED" => true) def checkbox(name = "", value = nil, checked = nil) attributes = if name.kind_of?(String) { "TYPE" => "checkbox", "NAME" => name, "VALUE" => value, "CHECKED" => checked } else name["TYPE"] = "checkbox" name end input(attributes) end # Generate a sequence of checkbox elements, as a String. # # The checkboxes will all have the same +name+ attribute. # Each checkbox is followed by a label. # There will be one checkbox for each value. Each value # can be specified as a String, which will be used both # as the value of the VALUE attribute and as the label # for that checkbox. A single-element array has the # same effect. # # Each value can also be specified as a three-element array. # The first element is the VALUE attribute; the second is the # label; and the third is a boolean specifying whether this # checkbox is CHECKED. # # Each value can also be specified as a two-element # array, by omitting either the value element (defaults # to the same as the label), or the boolean checked element # (defaults to false). # # checkbox_group("name", "foo", "bar", "baz") # # foo # # bar # # baz # # checkbox_group("name", ["foo"], ["bar", true], "baz") # # foo # # bar # # baz # # checkbox_group("name", ["1", "Foo"], ["2", "Bar", true], "Baz") # # Foo # # Bar # # Baz # # checkbox_group("NAME" => "name", # "VALUES" => ["foo", "bar", "baz"]) # # checkbox_group("NAME" => "name", # "VALUES" => [["foo"], ["bar", true], "baz"]) # # checkbox_group("NAME" => "name", # "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"]) def checkbox_group(name = "", *values) if name.kind_of?(Hash) values = name["VALUES"] name = name["NAME"] end values.collect{|value| if value.kind_of?(String) checkbox(name, value) + value else if value[-1] == true || value[-1] == false checkbox(name, value[0], value[-1]) + value[-2] else checkbox(name, value[0]) + value[-1] end end }.join end # Generate an File Upload Input element as a string. # # The attributes of the element can be specified as three arguments, # +name+, +size+, and +maxlength+. +maxlength+ is the maximum length # of the file's _name_, not of the file's _contents_. # # Alternatively, the attributes can be specified as a hash. # # See #multipart_form() for forms that include file uploads. # # file_field("name") # # # # file_field("name", 40) # # # # file_field("name", 40, 100) # # # # file_field("NAME" => "name", "SIZE" => 40) # # def file_field(name = "", size = 20, maxlength = nil) attributes = if name.kind_of?(String) { "TYPE" => "file", "NAME" => name, "SIZE" => size.to_s } else name["TYPE"] = "file" name end attributes["MAXLENGTH"] = maxlength.to_s if maxlength input(attributes) end # Generate a Form element as a string. # # +method+ should be either "get" or "post", and defaults to the latter. # +action+ defaults to the current CGI script name. +enctype+ # defaults to "application/x-www-form-urlencoded". # # Alternatively, the attributes can be specified as a hash. # # See also #multipart_form() for forms that include file uploads. # # form{ "string" } # #
string
# # form("get") { "string" } # #
string
# # form("get", "url") { "string" } # #
string
# # form("METHOD" => "post", "ENCTYPE" => "enctype") { "string" } # #
string
def form(method = "post", action = script_name, enctype = "application/x-www-form-urlencoded") attributes = if method.kind_of?(String) { "METHOD" => method, "ACTION" => action, "ENCTYPE" => enctype } else unless method.has_key?("METHOD") method["METHOD"] = "post" end unless method.has_key?("ENCTYPE") method["ENCTYPE"] = enctype end method end if block_given? body = yield else body = "" end if @output_hidden body << @output_hidden.collect{|k,v| "" }.join end super(attributes){body} end # Generate a Hidden Input element as a string. # # The attributes of the element can be specified as two arguments, # +name+ and +value+. # # Alternatively, the attributes can be specified as a hash. # # hidden("name") # # # # hidden("name", "value") # # # # hidden("NAME" => "name", "VALUE" => "reset", "ID" => "foo") # # def hidden(name = "", value = nil) attributes = if name.kind_of?(String) { "TYPE" => "hidden", "NAME" => name, "VALUE" => value } else name["TYPE"] = "hidden" name end input(attributes) end # Generate a top-level HTML element as a string. # # The attributes of the element are specified as a hash. The # pseudo-attribute "PRETTY" can be used to specify that the generated # HTML string should be indented. "PRETTY" can also be specified as # a string as the sole argument to this method. The pseudo-attribute # "DOCTYPE", if given, is used as the leading DOCTYPE SGML tag; it # should include the entire text of this tag, including angle brackets. # # The body of the html element is supplied as a block. # # html{ "string" } # # string # # html("LANG" => "ja") { "string" } # # string # # html("DOCTYPE" => false) { "string" } # # string # # html("DOCTYPE" => '') { "string" } # # string # # html("PRETTY" => " ") { "" } # # # # # # # # # # # # html("PRETTY" => "\t") { "" } # # # # # # # # # # # # html("PRETTY") { "" } # # = html("PRETTY" => " ") { "" } # # html(if $VERBOSE then "PRETTY" end) { "HTML string" } # def html(attributes = {}) # :yield: if nil == attributes attributes = {} elsif "PRETTY" == attributes attributes = { "PRETTY" => true } end pretty = attributes.delete("PRETTY") pretty = " " if true == pretty buf = "" if attributes.has_key?("DOCTYPE") if attributes["DOCTYPE"] buf << attributes.delete("DOCTYPE") else attributes.delete("DOCTYPE") end else buf << doctype end buf << super(attributes) if pretty CGI::pretty(buf, pretty) else buf end end # Generate an Image Button Input element as a string. # # +src+ is the URL of the image to use for the button. +name+ # is the input name. +alt+ is the alternative text for the image. # # Alternatively, the attributes can be specified as a hash. # # image_button("url") # # # # image_button("url", "name", "string") # # # # image_button("SRC" => "url", "ALT" => "string") # # def image_button(src = "", name = nil, alt = nil) attributes = if src.kind_of?(String) { "TYPE" => "image", "SRC" => src, "NAME" => name, "ALT" => alt } else src["TYPE"] = "image" src["SRC"] ||= "" src end input(attributes) end # Generate an Image element as a string. # # +src+ is the URL of the image. +alt+ is the alternative text for # the image. +width+ is the width of the image, and +height+ is # its height. # # Alternatively, the attributes can be specified as a hash. # # img("src", "alt", 100, 50) # # alt # # img("SRC" => "src", "ALT" => "alt", "WIDTH" => 100, "HEIGHT" => 50) # # alt def img(src = "", alt = "", width = nil, height = nil) attributes = if src.kind_of?(String) { "SRC" => src, "ALT" => alt } else src end attributes["WIDTH"] = width.to_s if width attributes["HEIGHT"] = height.to_s if height super(attributes) end # Generate a Form element with multipart encoding as a String. # # Multipart encoding is used for forms that include file uploads. # # +action+ is the action to perform. +enctype+ is the encoding # type, which defaults to "multipart/form-data". # # Alternatively, the attributes can be specified as a hash. # # multipart_form{ "string" } # #
string
# # multipart_form("url") { "string" } # #
string
def multipart_form(action = nil, enctype = "multipart/form-data") attributes = if action == nil { "METHOD" => "post", "ENCTYPE" => enctype } elsif action.kind_of?(String) { "METHOD" => "post", "ACTION" => action, "ENCTYPE" => enctype } else unless action.has_key?("METHOD") action["METHOD"] = "post" end unless action.has_key?("ENCTYPE") action["ENCTYPE"] = enctype end action end if block_given? form(attributes){ yield } else form(attributes) end end # Generate a Password Input element as a string. # # +name+ is the name of the input field. +value+ is its default # value. +size+ is the size of the input field display. +maxlength+ # is the maximum length of the inputted password. # # Alternatively, attributes can be specified as a hash. # # password_field("name") # # # # password_field("name", "value") # # # # password_field("password", "value", 80, 200) # # # # password_field("NAME" => "name", "VALUE" => "value") # # def password_field(name = "", value = nil, size = 40, maxlength = nil) attributes = if name.kind_of?(String) { "TYPE" => "password", "NAME" => name, "VALUE" => value, "SIZE" => size.to_s } else name["TYPE"] = "password" name end attributes["MAXLENGTH"] = maxlength.to_s if maxlength input(attributes) end # Generate a Select element as a string. # # +name+ is the name of the element. The +values+ are the options that # can be selected from the Select menu. Each value can be a String or # a one, two, or three-element Array. If a String or a one-element # Array, this is both the value of that option and the text displayed for # it. If a three-element Array, the elements are the option value, displayed # text, and a boolean value specifying whether this option starts as selected. # The two-element version omits either the option value (defaults to the same # as the display text) or the boolean selected specifier (defaults to false). # # The attributes and options can also be specified as a hash. In this # case, options are specified as an array of values as described above, # with the hash key of "VALUES". # # popup_menu("name", "foo", "bar", "baz") # # # # popup_menu("name", ["foo"], ["bar", true], "baz") # # # # popup_menu("name", ["1", "Foo"], ["2", "Bar", true], "Baz") # # # # popup_menu("NAME" => "name", "SIZE" => 2, "MULTIPLE" => true, # "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"]) # # def popup_menu(name = "", *values) if name.kind_of?(Hash) values = name["VALUES"] size = name["SIZE"].to_s if name["SIZE"] multiple = name["MULTIPLE"] name = name["NAME"] else size = nil multiple = nil end select({ "NAME" => name, "SIZE" => size, "MULTIPLE" => multiple }){ values.collect{|value| if value.kind_of?(String) option({ "VALUE" => value }){ value } else if value[value.size - 1] == true option({ "VALUE" => value[0], "SELECTED" => true }){ value[value.size - 2] } else option({ "VALUE" => value[0] }){ value[value.size - 1] } end end }.join } end # Generates a radio-button Input element. # # +name+ is the name of the input field. +value+ is the value of # the field if checked. +checked+ specifies whether the field # starts off checked. # # Alternatively, the attributes can be specified as a hash. # # radio_button("name", "value") # # # # radio_button("name", "value", true) # # # # radio_button("NAME" => "name", "VALUE" => "value", "ID" => "foo") # # def radio_button(name = "", value = nil, checked = nil) attributes = if name.kind_of?(String) { "TYPE" => "radio", "NAME" => name, "VALUE" => value, "CHECKED" => checked } else name["TYPE"] = "radio" name end input(attributes) end # Generate a sequence of radio button Input elements, as a String. # # This works the same as #checkbox_group(). However, it is not valid # to have more than one radiobutton in a group checked. # # radio_group("name", "foo", "bar", "baz") # # foo # # bar # # baz # # radio_group("name", ["foo"], ["bar", true], "baz") # # foo # # bar # # baz # # radio_group("name", ["1", "Foo"], ["2", "Bar", true], "Baz") # # Foo # # Bar # # Baz # # radio_group("NAME" => "name", # "VALUES" => ["foo", "bar", "baz"]) # # radio_group("NAME" => "name", # "VALUES" => [["foo"], ["bar", true], "baz"]) # # radio_group("NAME" => "name", # "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"]) def radio_group(name = "", *values) if name.kind_of?(Hash) values = name["VALUES"] name = name["NAME"] end values.collect{|value| if value.kind_of?(String) radio_button(name, value) + value else if value[-1] == true || value[-1] == false radio_button(name, value[0], value[-1]) + value[-2] else radio_button(name, value[0]) + value[-1] end end }.join end # Generate a reset button Input element, as a String. # # This resets the values on a form to their initial values. +value+ # is the text displayed on the button. +name+ is the name of this button. # # Alternatively, the attributes can be specified as a hash. # # reset # # # # reset("reset") # # # # reset("VALUE" => "reset", "ID" => "foo") # # def reset(value = nil, name = nil) attributes = if (not value) or value.kind_of?(String) { "TYPE" => "reset", "VALUE" => value, "NAME" => name } else value["TYPE"] = "reset" value end input(attributes) end alias scrolling_list popup_menu # Generate a submit button Input element, as a String. # # +value+ is the text to display on the button. +name+ is the name # of the input. # # Alternatively, the attributes can be specified as a hash. # # submit # # # # submit("ok") # # # # submit("ok", "button1") # # # # submit("VALUE" => "ok", "NAME" => "button1", "ID" => "foo") # # def submit(value = nil, name = nil) attributes = if (not value) or value.kind_of?(String) { "TYPE" => "submit", "VALUE" => value, "NAME" => name } else value["TYPE"] = "submit" value end input(attributes) end # Generate a text field Input element, as a String. # # +name+ is the name of the input field. +value+ is its initial # value. +size+ is the size of the input area. +maxlength+ # is the maximum length of input accepted. # # Alternatively, the attributes can be specified as a hash. # # text_field("name") # # # # text_field("name", "value") # # # # text_field("name", "value", 80) # # # # text_field("name", "value", 80, 200) # # # # text_field("NAME" => "name", "VALUE" => "value") # # def text_field(name = "", value = nil, size = 40, maxlength = nil) attributes = if name.kind_of?(String) { "TYPE" => "text", "NAME" => name, "VALUE" => value, "SIZE" => size.to_s } else name["TYPE"] = "text" name end attributes["MAXLENGTH"] = maxlength.to_s if maxlength input(attributes) end # Generate a TextArea element, as a String. # # +name+ is the name of the textarea. +cols+ is the number of # columns and +rows+ is the number of rows in the display. # # Alternatively, the attributes can be specified as a hash. # # The body is provided by the passed-in no-argument block # # textarea("name") # # = textarea("NAME" => "name", "COLS" => 70, "ROWS" => 10) # # textarea("name", 40, 5) # # = textarea("NAME" => "name", "COLS" => 40, "ROWS" => 5) def textarea(name = "", cols = 70, rows = 10) # :yield: attributes = if name.kind_of?(String) { "NAME" => name, "COLS" => cols.to_s, "ROWS" => rows.to_s } else name end super(attributes) end end # HtmlExtension # Mixin module for HTML version 3 generation methods. module Html3 # :nodoc: include TagMaker # The DOCTYPE declaration for this version of HTML def doctype %|| end instance_method(:nn_element_def).tap do |m| # - - for element in %w[ A TT I B U STRIKE BIG SMALL SUB SUP EM STRONG DFN CODE SAMP KBD VAR CITE FONT ADDRESS DIV CENTER MAP APPLET PRE XMP LISTING DL OL UL DIR MENU SELECT TABLE TITLE STYLE SCRIPT H1 H2 H3 H4 H5 H6 TEXTAREA FORM BLOCKQUOTE CAPTION ] define_method(element.downcase, m) end end instance_method(:nOE_element_def).tap do |m| # - O EMPTY for element in %w[ IMG BASE BASEFONT BR AREA LINK PARAM HR INPUT ISINDEX META ] define_method(element.downcase, m) end end instance_method(:nO_element_def).tap do |m| # O O or - O for element in %w[ HTML HEAD BODY P PLAINTEXT DT DD LI OPTION TR TH TD ] define_method(element.downcase, m) end end end # Html3 # Mixin module for HTML version 4 generation methods. module Html4 # :nodoc: include TagMaker # The DOCTYPE declaration for this version of HTML def doctype %|| end # Initialize the HTML generation methods for this version. # - - instance_method(:nn_element_def).tap do |m| for element in %w[ TT I B BIG SMALL EM STRONG DFN CODE SAMP KBD VAR CITE ABBR ACRONYM SUB SUP SPAN BDO ADDRESS DIV MAP OBJECT H1 H2 H3 H4 H5 H6 PRE Q INS DEL DL OL UL LABEL SELECT OPTGROUP FIELDSET LEGEND BUTTON TABLE TITLE STYLE SCRIPT NOSCRIPT TEXTAREA FORM A BLOCKQUOTE CAPTION ] define_method(element.downcase, m) end end # - O EMPTY instance_method(:nOE_element_def).tap do |m| for element in %w[ IMG BASE BR AREA LINK PARAM HR INPUT COL META ] define_method(element.downcase, m) end end # O O or - O instance_method(:nO_element_def).tap do |m| for element in %w[ HTML BODY P DT DD LI OPTION THEAD TFOOT TBODY COLGROUP TR TH TD HEAD ] define_method(element.downcase, m) end end end # Html4 # Mixin module for HTML version 4 transitional generation methods. module Html4Tr # :nodoc: include TagMaker # The DOCTYPE declaration for this version of HTML def doctype %|| end # Initialise the HTML generation methods for this version. # - - instance_method(:nn_element_def).tap do |m| for element in %w[ TT I B U S STRIKE BIG SMALL EM STRONG DFN CODE SAMP KBD VAR CITE ABBR ACRONYM FONT SUB SUP SPAN BDO ADDRESS DIV CENTER MAP OBJECT APPLET H1 H2 H3 H4 H5 H6 PRE Q INS DEL DL OL UL DIR MENU LABEL SELECT OPTGROUP FIELDSET LEGEND BUTTON TABLE IFRAME NOFRAMES TITLE STYLE SCRIPT NOSCRIPT TEXTAREA FORM A BLOCKQUOTE CAPTION ] define_method(element.downcase, m) end end # - O EMPTY instance_method(:nOE_element_def).tap do |m| for element in %w[ IMG BASE BASEFONT BR AREA LINK PARAM HR INPUT COL ISINDEX META ] define_method(element.downcase, m) end end # O O or - O instance_method(:nO_element_def).tap do |m| for element in %w[ HTML BODY P DT DD LI OPTION THEAD TFOOT TBODY COLGROUP TR TH TD HEAD ] define_method(element.downcase, m) end end end # Html4Tr # Mixin module for generating HTML version 4 with framesets. module Html4Fr # :nodoc: include TagMaker # The DOCTYPE declaration for this version of HTML def doctype %|| end # Initialise the HTML generation methods for this version. # - - instance_method(:nn_element_def).tap do |m| for element in %w[ FRAMESET ] define_method(element.downcase, m) end end # - O EMPTY instance_method(:nOE_element_def).tap do |m| for element in %w[ FRAME ] define_method(element.downcase, m) end end end # Html4Fr # Mixin module for HTML version 5 generation methods. module Html5 # :nodoc: include TagMaker # The DOCTYPE declaration for this version of HTML def doctype %|| end # Initialise the HTML generation methods for this version. # - - instance_method(:nn_element_def).tap do |m| for element in %w[ SECTION NAV ARTICLE ASIDE HGROUP HEADER FOOTER FIGURE FIGCAPTION S TIME U MARK RUBY BDI IFRAME VIDEO AUDIO CANVAS DATALIST OUTPUT PROGRESS METER DETAILS SUMMARY MENU DIALOG I B SMALL EM STRONG DFN CODE SAMP KBD VAR CITE ABBR SUB SUP SPAN BDO ADDRESS DIV MAP OBJECT H1 H2 H3 H4 H5 H6 PRE Q INS DEL DL OL UL LABEL SELECT FIELDSET LEGEND BUTTON TABLE TITLE STYLE SCRIPT NOSCRIPT TEXTAREA FORM A BLOCKQUOTE CAPTION ] define_method(element.downcase, m) end end # - O EMPTY instance_method(:nOE_element_def).tap do |m| for element in %w[ IMG BASE BR AREA LINK PARAM HR INPUT COL META COMMAND EMBED KEYGEN SOURCE TRACK WBR ] define_method(element.downcase, m) end end # O O or - O instance_method(:nO_element_def).tap do |m| for element in %w[ HTML HEAD BODY P DT DD LI OPTION THEAD TFOOT TBODY OPTGROUP COLGROUP RT RP TR TH TD ] define_method(element.downcase, m) end end end # Html5 class HTML3 include Html3 include HtmlExtension end class HTML4 include Html4 include HtmlExtension end class HTML4Tr include Html4Tr include HtmlExtension end class HTML4Fr include Html4Tr include Html4Fr include HtmlExtension end class HTML5 include Html5 include HtmlExtension end end PK!}] 2.2.0/cgi/session/pstore.rbnu[# # cgi/session/pstore.rb - persistent storage of marshalled session data # # Documentation: William Webber (william@williamwebber.com) # # == Overview # # This file provides the CGI::Session::PStore class, which builds # persistent of session data on top of the pstore library. See # cgi/session.rb for more details on session storage managers. require 'cgi/session' require 'pstore' class CGI class Session # PStore-based session storage class. # # This builds upon the top-level PStore class provided by the # library file pstore.rb. Session data is marshalled and stored # in a file. File locking and transaction services are provided. class PStore # Create a new CGI::Session::PStore instance # # This constructor is used internally by CGI::Session. The # user does not generally need to call it directly. # # +session+ is the session for which this instance is being # created. The session id must only contain alphanumeric # characters; automatically generated session ids observe # this requirement. # # +option+ is a hash of options for the initializer. The # following options are recognised: # # tmpdir:: the directory to use for storing the PStore # file. Defaults to Dir::tmpdir (generally "/tmp" # on Unix systems). # prefix:: the prefix to add to the session id when generating # the filename for this session's PStore file. # Defaults to the empty string. # # This session's PStore file will be created if it does # not exist, or opened if it does. def initialize(session, option={}) dir = option['tmpdir'] || Dir::tmpdir prefix = option['prefix'] || '' id = session.session_id require 'digest/md5' md5 = Digest::MD5.hexdigest(id)[0,16] path = dir+"/"+prefix+md5 path.untaint if File::exist?(path) @hash = nil else unless session.new_session raise CGI::Session::NoSession, "uninitialized session" end @hash = {} end @p = ::PStore.new(path) @p.transaction do |p| File.chmod(0600, p.path) end end # Restore session state from the session's PStore file. # # Returns the session state as a hash. def restore unless @hash @p.transaction do @hash = @p['hash'] || {} end end @hash end # Save session state to the session's PStore file. def update @p.transaction do @p['hash'] = @hash end end # Update and close the session's PStore file. def close update end # Close and delete the session's PStore file. def delete path = @p.path File::unlink path end end end end # :enddoc: PK!b>2.2.0/cgi/util.rbnu[class CGI; module Util; end; extend Util; end module CGI::Util @@accept_charset="UTF-8" unless defined?(@@accept_charset) # URL-encode a string. # url_encoded_string = CGI::escape("'Stop!' said Fred") # # => "%27Stop%21%27+said+Fred" def escape(string) encoding = string.encoding string.b.gsub(/([^ a-zA-Z0-9_.-]+)/) do |m| '%' + m.unpack('H2' * m.bytesize).join('%').upcase end.tr(' ', '+').force_encoding(encoding) end # URL-decode a string with encoding(optional). # string = CGI::unescape("%27Stop%21%27+said+Fred") # # => "'Stop!' said Fred" def unescape(string,encoding=@@accept_charset) str=string.tr('+', ' ').b.gsub(/((?:%[0-9a-fA-F]{2})+)/) do |m| [m.delete('%')].pack('H*') end.force_encoding(encoding) str.valid_encoding? ? str : str.force_encoding(string.encoding) end # The set of special characters and their escaped values TABLE_FOR_ESCAPE_HTML__ = { "'" => ''', '&' => '&', '"' => '"', '<' => '<', '>' => '>', } # Escape special characters in HTML, namely &\"<> # CGI::escapeHTML('Usage: foo "bar" ') # # => "Usage: foo "bar" <baz>" def escapeHTML(string) string.gsub(/['&\"<>]/, TABLE_FOR_ESCAPE_HTML__) end # Unescape a string that has been HTML-escaped # CGI::unescapeHTML("Usage: foo "bar" <baz>") # # => "Usage: foo \"bar\" " def unescapeHTML(string) return string unless string.include? '&' enc = string.encoding if enc != Encoding::UTF_8 && [Encoding::UTF_16BE, Encoding::UTF_16LE, Encoding::UTF_32BE, Encoding::UTF_32LE].include?(enc) return string.gsub(Regexp.new('&(apos|amp|quot|gt|lt|#[0-9]+|#x[0-9A-Fa-f]+);'.encode(enc))) do case $1.encode(Encoding::US_ASCII) when 'apos' then "'".encode(enc) when 'amp' then '&'.encode(enc) when 'quot' then '"'.encode(enc) when 'gt' then '>'.encode(enc) when 'lt' then '<'.encode(enc) when /\A#0*(\d+)\z/ then $1.to_i.chr(enc) when /\A#x([0-9a-f]+)\z/i then $1.hex.chr(enc) end end end asciicompat = Encoding.compatible?(string, "a") string.gsub(/&(apos|amp|quot|gt|lt|\#[0-9]+|\#[xX][0-9A-Fa-f]+);/) do match = $1.dup case match when 'apos' then "'" when 'amp' then '&' when 'quot' then '"' when 'gt' then '>' when 'lt' then '<' when /\A#0*(\d+)\z/ n = $1.to_i if enc == Encoding::UTF_8 or enc == Encoding::ISO_8859_1 && n < 256 or asciicompat && n < 128 n.chr(enc) else "&##{$1};" end when /\A#x([0-9a-f]+)\z/i n = $1.hex if enc == Encoding::UTF_8 or enc == Encoding::ISO_8859_1 && n < 256 or asciicompat && n < 128 n.chr(enc) else "&#x#{$1};" end else "&#{match};" end end end # Synonym for CGI::escapeHTML(str) alias escape_html escapeHTML # Synonym for CGI::unescapeHTML(str) alias unescape_html unescapeHTML # Escape only the tags of certain HTML elements in +string+. # # Takes an element or elements or array of elements. Each element # is specified by the name of the element, without angle brackets. # This matches both the start and the end tag of that element. # The attribute list of the open tag will also be escaped (for # instance, the double-quotes surrounding attribute values). # # print CGI::escapeElement('
', "A", "IMG") # # "
<A HREF="url"></A>" # # print CGI::escapeElement('
', ["A", "IMG"]) # # "
<A HREF="url"></A>" def escapeElement(string, *elements) elements = elements[0] if elements[0].kind_of?(Array) unless elements.empty? string.gsub(/<\/?(?:#{elements.join("|")})(?!\w)(?:.|\n)*?>/i) do CGI::escapeHTML($&) end else string end end # Undo escaping such as that done by CGI::escapeElement() # # print CGI::unescapeElement( # CGI::escapeHTML('
'), "A", "IMG") # # "<BR>" # # print CGI::unescapeElement( # CGI::escapeHTML('
'), ["A", "IMG"]) # # "<BR>" def unescapeElement(string, *elements) elements = elements[0] if elements[0].kind_of?(Array) unless elements.empty? string.gsub(/<\/?(?:#{elements.join("|")})(?!\w)(?:.|\n)*?>/i) do unescapeHTML($&) end else string end end # Synonym for CGI::escapeElement(str) alias escape_element escapeElement # Synonym for CGI::unescapeElement(str) alias unescape_element unescapeElement # Abbreviated day-of-week names specified by RFC 822 RFC822_DAYS = %w[ Sun Mon Tue Wed Thu Fri Sat ] # Abbreviated month names specified by RFC 822 RFC822_MONTHS = %w[ Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ] # Format a +Time+ object as a String using the format specified by RFC 1123. # # CGI::rfc1123_date(Time.now) # # Sat, 01 Jan 2000 00:00:00 GMT def rfc1123_date(time) t = time.clone.gmtime return format("%s, %.2d %s %.4d %.2d:%.2d:%.2d GMT", RFC822_DAYS[t.wday], t.day, RFC822_MONTHS[t.month-1], t.year, t.hour, t.min, t.sec) end # Prettify (indent) an HTML string. # # +string+ is the HTML string to indent. +shift+ is the indentation # unit to use; it defaults to two spaces. # # print CGI::pretty("") # # # # # # # # # # print CGI::pretty("", "\t") # # # # # # # # # def pretty(string, shift = " ") lines = string.gsub(/(?!\A)<.*?>/m, "\n\\0").gsub(/<.*?>(?!\n)/m, "\\0\n") end_pos = 0 while end_pos = lines.index(/^<\/(\w+)/, end_pos) element = $1.dup start_pos = lines.rindex(/^\s*<#{element}/i, end_pos) lines[start_pos ... end_pos] = "__" + lines[start_pos ... end_pos].gsub(/\n(?!\z)/, "\n" + shift) + "__" end lines.gsub(/^((?:#{Regexp::quote(shift)})*)__(?=<\/?\w)/, '\1') end alias h escapeHTML end PK!l[H[H2.2.0/cgi/session.rbnu[# # cgi/session.rb - session support for cgi scripts # # Copyright (C) 2001 Yukihiro "Matz" Matsumoto # Copyright (C) 2000 Network Applied Communication Laboratory, Inc. # Copyright (C) 2000 Information-technology Promotion Agency, Japan # # Author: Yukihiro "Matz" Matsumoto # # Documentation: William Webber (william@williamwebber.com) require 'cgi' require 'tmpdir' class CGI # == Overview # # This file provides the CGI::Session class, which provides session # support for CGI scripts. A session is a sequence of HTTP requests # and responses linked together and associated with a single client. # Information associated with the session is stored # on the server between requests. A session id is passed between client # and server with every request and response, transparently # to the user. This adds state information to the otherwise stateless # HTTP request/response protocol. # # == Lifecycle # # A CGI::Session instance is created from a CGI object. By default, # this CGI::Session instance will start a new session if none currently # exists, or continue the current session for this client if one does # exist. The +new_session+ option can be used to either always or # never create a new session. See #new() for more details. # # #delete() deletes a session from session storage. It # does not however remove the session id from the client. If the client # makes another request with the same id, the effect will be to start # a new session with the old session's id. # # == Setting and retrieving session data. # # The Session class associates data with a session as key-value pairs. # This data can be set and retrieved by indexing the Session instance # using '[]', much the same as hashes (although other hash methods # are not supported). # # When session processing has been completed for a request, the # session should be closed using the close() method. This will # store the session's state to persistent storage. If you want # to store the session's state to persistent storage without # finishing session processing for this request, call the update() # method. # # == Storing session state # # The caller can specify what form of storage to use for the session's # data with the +database_manager+ option to CGI::Session::new. The # following storage classes are provided as part of the standard library: # # CGI::Session::FileStore:: stores data as plain text in a flat file. Only # works with String data. This is the default # storage type. # CGI::Session::MemoryStore:: stores data in an in-memory hash. The data # only persists for as long as the current Ruby # interpreter instance does. # CGI::Session::PStore:: stores data in Marshalled format. Provided by # cgi/session/pstore.rb. Supports data of any type, # and provides file-locking and transaction support. # # Custom storage types can also be created by defining a class with # the following methods: # # new(session, options) # restore # returns hash of session data. # update # close # delete # # Changing storage type mid-session does not work. Note in particular # that by default the FileStore and PStore session data files have the # same name. If your application switches from one to the other without # making sure that filenames will be different # and clients still have old sessions lying around in cookies, then # things will break nastily! # # == Maintaining the session id. # # Most session state is maintained on the server. However, a session # id must be passed backwards and forwards between client and server # to maintain a reference to this session state. # # The simplest way to do this is via cookies. The CGI::Session class # provides transparent support for session id communication via cookies # if the client has cookies enabled. # # If the client has cookies disabled, the session id must be included # as a parameter of all requests sent by the client to the server. The # CGI::Session class in conjunction with the CGI class will transparently # add the session id as a hidden input field to all forms generated # using the CGI#form() HTML generation method. No built-in support is # provided for other mechanisms, such as URL re-writing. The caller is # responsible for extracting the session id from the session_id # attribute and manually encoding it in URLs and adding it as a hidden # input to HTML forms created by other mechanisms. Also, session expiry # is not automatically handled. # # == Examples of use # # === Setting the user's name # # require 'cgi' # require 'cgi/session' # require 'cgi/session/pstore' # provides CGI::Session::PStore # # cgi = CGI.new("html4") # # session = CGI::Session.new(cgi, # 'database_manager' => CGI::Session::PStore, # use PStore # 'session_key' => '_rb_sess_id', # custom session key # 'session_expires' => Time.now + 30 * 60, # 30 minute timeout # 'prefix' => 'pstore_sid_') # PStore option # if cgi.has_key?('user_name') and cgi['user_name'] != '' # # coerce to String: cgi[] returns the # # string-like CGI::QueryExtension::Value # session['user_name'] = cgi['user_name'].to_s # elsif !session['user_name'] # session['user_name'] = "guest" # end # session.close # # === Creating a new session safely # # require 'cgi' # require 'cgi/session' # # cgi = CGI.new("html4") # # # We make sure to delete an old session if one exists, # # not just to free resources, but to prevent the session # # from being maliciously hijacked later on. # begin # session = CGI::Session.new(cgi, 'new_session' => false) # session.delete # rescue ArgumentError # if no old session # end # session = CGI::Session.new(cgi, 'new_session' => true) # session.close # class Session class NoSession < RuntimeError #:nodoc: end # The id of this session. attr_reader :session_id, :new_session def Session::callback(dbman) #:nodoc: Proc.new{ dbman[0].close unless dbman.empty? } end # Create a new session id. # # The session id is an MD5 hash based upon the time, # a random number, and a constant string. This routine # is used internally for automatically generated # session ids. def create_new_id require 'securerandom' begin session_id = SecureRandom.hex(16) rescue NotImplementedError require 'digest/md5' md5 = Digest::MD5::new now = Time::now md5.update(now.to_s) md5.update(String(now.usec)) md5.update(String(rand(0))) md5.update(String($$)) md5.update('foobar') session_id = md5.hexdigest end session_id end private :create_new_id # Create a new CGI::Session object for +request+. # # +request+ is an instance of the +CGI+ class (see cgi.rb). # +option+ is a hash of options for initialising this # CGI::Session instance. The following options are # recognised: # # session_key:: the parameter name used for the session id. # Defaults to '_session_id'. # session_id:: the session id to use. If not provided, then # it is retrieved from the +session_key+ parameter # of the request, or automatically generated for # a new session. # new_session:: if true, force creation of a new session. If not set, # a new session is only created if none currently # exists. If false, a new session is never created, # and if none currently exists and the +session_id+ # option is not set, an ArgumentError is raised. # database_manager:: the name of the class providing storage facilities # for session state persistence. Built-in support # is provided for +FileStore+ (the default), # +MemoryStore+, and +PStore+ (from # cgi/session/pstore.rb). See the documentation for # these classes for more details. # # The following options are also recognised, but only apply if the # session id is stored in a cookie. # # session_expires:: the time the current session expires, as a # +Time+ object. If not set, the session will terminate # when the user's browser is closed. # session_domain:: the hostname domain for which this session is valid. # If not set, defaults to the hostname of the server. # session_secure:: if +true+, this session will only work over HTTPS. # session_path:: the path for which this session applies. Defaults # to the directory of the CGI script. # # +option+ is also passed on to the session storage class initializer; see # the documentation for each session storage class for the options # they support. # # The retrieved or created session is automatically added to +request+ # as a cookie, and also to its +output_hidden+ table, which is used # to add hidden input elements to forms. # # *WARNING* the +output_hidden+ # fields are surrounded by a
tag in HTML 4 generation, which # is _not_ invisible on many browsers; you may wish to disable the # use of fieldsets with code similar to the following # (see http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-list/37805) # # cgi = CGI.new("html4") # class << cgi # undef_method :fieldset # end # def initialize(request, option={}) @new_session = false session_key = option['session_key'] || '_session_id' session_id = option['session_id'] unless session_id if option['new_session'] session_id = create_new_id @new_session = true end end unless session_id if request.key?(session_key) session_id = request[session_key] session_id = session_id.read if session_id.respond_to?(:read) end unless session_id session_id, = request.cookies[session_key] end unless session_id unless option.fetch('new_session', true) raise ArgumentError, "session_key `%s' should be supplied"%session_key end session_id = create_new_id @new_session = true end end @session_id = session_id dbman = option['database_manager'] || FileStore begin @dbman = dbman::new(self, option) rescue NoSession unless option.fetch('new_session', true) raise ArgumentError, "invalid session_id `%s'"%session_id end session_id = @session_id = create_new_id unless session_id @new_session=true retry end request.instance_eval do @output_hidden = {session_key => session_id} unless option['no_hidden'] @output_cookies = [ Cookie::new("name" => session_key, "value" => session_id, "expires" => option['session_expires'], "domain" => option['session_domain'], "secure" => option['session_secure'], "path" => if option['session_path'] option['session_path'] elsif ENV["SCRIPT_NAME"] File::dirname(ENV["SCRIPT_NAME"]) else "" end) ] unless option['no_cookies'] end @dbprot = [@dbman] ObjectSpace::define_finalizer(self, Session::callback(@dbprot)) end # Retrieve the session data for key +key+. def [](key) @data ||= @dbman.restore @data[key] end # Set the session data for key +key+. def []=(key, val) @write_lock ||= true @data ||= @dbman.restore @data[key] = val end # Store session data on the server. For some session storage types, # this is a no-op. def update @dbman.update end # Store session data on the server and close the session storage. # For some session storage types, this is a no-op. def close @dbman.close @dbprot.clear end # Delete the session from storage. Also closes the storage. # # Note that the session's data is _not_ automatically deleted # upon the session expiring. def delete @dbman.delete @dbprot.clear end # File-based session storage class. # # Implements session storage as a flat file of 'key=value' values. # This storage type only works directly with String values; the # user is responsible for converting other types to Strings when # storing and from Strings when retrieving. class FileStore # Create a new FileStore instance. # # This constructor is used internally by CGI::Session. The # user does not generally need to call it directly. # # +session+ is the session for which this instance is being # created. The session id must only contain alphanumeric # characters; automatically generated session ids observe # this requirement. # # +option+ is a hash of options for the initializer. The # following options are recognised: # # tmpdir:: the directory to use for storing the FileStore # file. Defaults to Dir::tmpdir (generally "/tmp" # on Unix systems). # prefix:: the prefix to add to the session id when generating # the filename for this session's FileStore file. # Defaults to "cgi_sid_". # suffix:: the prefix to add to the session id when generating # the filename for this session's FileStore file. # Defaults to the empty string. # # This session's FileStore file will be created if it does # not exist, or opened if it does. def initialize(session, option={}) dir = option['tmpdir'] || Dir::tmpdir prefix = option['prefix'] || 'cgi_sid_' suffix = option['suffix'] || '' id = session.session_id require 'digest/md5' md5 = Digest::MD5.hexdigest(id)[0,16] @path = dir+"/"+prefix+md5+suffix if File::exist? @path @hash = nil else unless session.new_session raise CGI::Session::NoSession, "uninitialized session" end @hash = {} end end # Restore session state from the session's FileStore file. # # Returns the session state as a hash. def restore unless @hash @hash = {} begin lockf = File.open(@path+".lock", "r") lockf.flock File::LOCK_SH f = File.open(@path, 'r') for line in f line.chomp! k, v = line.split('=',2) @hash[CGI::unescape(k)] = Marshal.restore(CGI::unescape(v)) end ensure f.close unless f.nil? lockf.close if lockf end end @hash end # Save session state to the session's FileStore file. def update return unless @hash begin lockf = File.open(@path+".lock", File::CREAT|File::RDWR, 0600) lockf.flock File::LOCK_EX f = File.open(@path+".new", File::CREAT|File::TRUNC|File::WRONLY, 0600) for k,v in @hash f.printf "%s=%s\n", CGI::escape(k), CGI::escape(String(Marshal.dump(v))) end f.close File.rename @path+".new", @path ensure f.close if f and !f.closed? lockf.close if lockf end end # Update and close the session's FileStore file. def close update end # Close and delete the session's FileStore file. def delete File::unlink @path+".lock" rescue nil File::unlink @path+".new" rescue nil File::unlink @path rescue nil end end # In-memory session storage class. # # Implements session storage as a global in-memory hash. Session # data will only persist for as long as the Ruby interpreter # instance does. class MemoryStore GLOBAL_HASH_TABLE = {} #:nodoc: # Create a new MemoryStore instance. # # +session+ is the session this instance is associated with. # +option+ is a list of initialisation options. None are # currently recognized. def initialize(session, option=nil) @session_id = session.session_id unless GLOBAL_HASH_TABLE.key?(@session_id) unless session.new_session raise CGI::Session::NoSession, "uninitialized session" end GLOBAL_HASH_TABLE[@session_id] = {} end end # Restore session state. # # Returns session data as a hash. def restore GLOBAL_HASH_TABLE[@session_id] end # Update session state. # # A no-op. def update # don't need to update; hash is shared end # Close session storage. # # A no-op. def close # don't need to close end # Delete the session state. def delete GLOBAL_HASH_TABLE.delete(@session_id) end end # Dummy session storage class. # # Implements session storage place holder. No actual storage # will be done. class NullStore # Create a new NullStore instance. # # +session+ is the session this instance is associated with. # +option+ is a list of initialisation options. None are # currently recognised. def initialize(session, option=nil) end # Restore (empty) session state. def restore {} end # Update session state. # # A no-op. def update end # Close session storage. # # A no-op. def close end # Delete the session state. # # A no-op. def delete end end end end PK!n*rr2.2.0/cgi/core.rbnu[#-- # Methods for generating HTML, parsing CGI-related parameters, and # generating HTTP responses. #++ class CGI $CGI_ENV = ENV # for FCGI support # String for carriage return CR = "\015" # String for linefeed LF = "\012" # Standard internet newline sequence EOL = CR + LF REVISION = '$Id: core.rb 46973 2014-07-27 11:04:28Z hsbt $' #:nodoc: # Whether processing will be required in binary vs text NEEDS_BINMODE = File::BINARY != 0 # Path separators in different environments. PATH_SEPARATOR = {'UNIX'=>'/', 'WINDOWS'=>'\\', 'MACINTOSH'=>':'} # HTTP status codes. HTTP_STATUS = { "OK" => "200 OK", "PARTIAL_CONTENT" => "206 Partial Content", "MULTIPLE_CHOICES" => "300 Multiple Choices", "MOVED" => "301 Moved Permanently", "REDIRECT" => "302 Found", "NOT_MODIFIED" => "304 Not Modified", "BAD_REQUEST" => "400 Bad Request", "AUTH_REQUIRED" => "401 Authorization Required", "FORBIDDEN" => "403 Forbidden", "NOT_FOUND" => "404 Not Found", "METHOD_NOT_ALLOWED" => "405 Method Not Allowed", "NOT_ACCEPTABLE" => "406 Not Acceptable", "LENGTH_REQUIRED" => "411 Length Required", "PRECONDITION_FAILED" => "412 Precondition Failed", "SERVER_ERROR" => "500 Internal Server Error", "NOT_IMPLEMENTED" => "501 Method Not Implemented", "BAD_GATEWAY" => "502 Bad Gateway", "VARIANT_ALSO_VARIES" => "506 Variant Also Negotiates" } # :startdoc: # Synonym for ENV. def env_table ENV end # Synonym for $stdin. def stdinput $stdin end # Synonym for $stdout. def stdoutput $stdout end private :env_table, :stdinput, :stdoutput # Create an HTTP header block as a string. # # :call-seq: # http_header(content_type_string="text/html") # http_header(headers_hash) # # Includes the empty line that ends the header block. # # +content_type_string+:: # If this form is used, this string is the Content-Type # +headers_hash+:: # A Hash of header values. The following header keys are recognized: # # type:: The Content-Type header. Defaults to "text/html" # charset:: The charset of the body, appended to the Content-Type header. # nph:: A boolean value. If true, prepend protocol string and status # code, and date; and sets default values for "server" and # "connection" if not explicitly set. # status:: # The HTTP status code as a String, returned as the Status header. The # values are: # # OK:: 200 OK # PARTIAL_CONTENT:: 206 Partial Content # MULTIPLE_CHOICES:: 300 Multiple Choices # MOVED:: 301 Moved Permanently # REDIRECT:: 302 Found # NOT_MODIFIED:: 304 Not Modified # BAD_REQUEST:: 400 Bad Request # AUTH_REQUIRED:: 401 Authorization Required # FORBIDDEN:: 403 Forbidden # NOT_FOUND:: 404 Not Found # METHOD_NOT_ALLOWED:: 405 Method Not Allowed # NOT_ACCEPTABLE:: 406 Not Acceptable # LENGTH_REQUIRED:: 411 Length Required # PRECONDITION_FAILED:: 412 Precondition Failed # SERVER_ERROR:: 500 Internal Server Error # NOT_IMPLEMENTED:: 501 Method Not Implemented # BAD_GATEWAY:: 502 Bad Gateway # VARIANT_ALSO_VARIES:: 506 Variant Also Negotiates # # server:: The server software, returned as the Server header. # connection:: The connection type, returned as the Connection header (for # instance, "close". # length:: The length of the content that will be sent, returned as the # Content-Length header. # language:: The language of the content, returned as the Content-Language # header. # expires:: The time on which the current content expires, as a +Time+ # object, returned as the Expires header. # cookie:: # A cookie or cookies, returned as one or more Set-Cookie headers. The # value can be the literal string of the cookie; a CGI::Cookie object; # an Array of literal cookie strings or Cookie objects; or a hash all of # whose values are literal cookie strings or Cookie objects. # # These cookies are in addition to the cookies held in the # @output_cookies field. # # Other headers can also be set; they are appended as key: value. # # Examples: # # http_header # # Content-Type: text/html # # http_header("text/plain") # # Content-Type: text/plain # # http_header("nph" => true, # "status" => "OK", # == "200 OK" # # "status" => "200 GOOD", # "server" => ENV['SERVER_SOFTWARE'], # "connection" => "close", # "type" => "text/html", # "charset" => "iso-2022-jp", # # Content-Type: text/html; charset=iso-2022-jp # "length" => 103, # "language" => "ja", # "expires" => Time.now + 30, # "cookie" => [cookie1, cookie2], # "my_header1" => "my_value" # "my_header2" => "my_value") # # This method does not perform charset conversion. def http_header(options='text/html') if options.is_a?(String) content_type = options buf = _header_for_string(content_type) elsif options.is_a?(Hash) if options.size == 1 && options.has_key?('type') content_type = options['type'] buf = _header_for_string(content_type) else buf = _header_for_hash(options.dup) end else raise ArgumentError.new("expected String or Hash but got #{options.class}") end if defined?(MOD_RUBY) _header_for_modruby(buf) return '' else buf << EOL # empty line of separator return buf end end # http_header() # This method is an alias for #http_header, when HTML5 tag maker is inactive. # # NOTE: use #http_header to create HTTP header blocks, this alias is only # provided for backwards compatibility. # # Using #header with the HTML5 tag maker will create a
element. alias :header :http_header def _header_for_string(content_type) #:nodoc: buf = '' if nph?() buf << "#{$CGI_ENV['SERVER_PROTOCOL'] || 'HTTP/1.0'} 200 OK#{EOL}" buf << "Date: #{CGI.rfc1123_date(Time.now)}#{EOL}" buf << "Server: #{$CGI_ENV['SERVER_SOFTWARE']}#{EOL}" buf << "Connection: close#{EOL}" end buf << "Content-Type: #{content_type}#{EOL}" if @output_cookies @output_cookies.each {|cookie| buf << "Set-Cookie: #{cookie}#{EOL}" } end return buf end # _header_for_string private :_header_for_string def _header_for_hash(options) #:nodoc: buf = '' ## add charset to option['type'] options['type'] ||= 'text/html' charset = options.delete('charset') options['type'] += "; charset=#{charset}" if charset ## NPH options.delete('nph') if defined?(MOD_RUBY) if options.delete('nph') || nph?() protocol = $CGI_ENV['SERVER_PROTOCOL'] || 'HTTP/1.0' status = options.delete('status') status = HTTP_STATUS[status] || status || '200 OK' buf << "#{protocol} #{status}#{EOL}" buf << "Date: #{CGI.rfc1123_date(Time.now)}#{EOL}" options['server'] ||= $CGI_ENV['SERVER_SOFTWARE'] || '' options['connection'] ||= 'close' end ## common headers status = options.delete('status') buf << "Status: #{HTTP_STATUS[status] || status}#{EOL}" if status server = options.delete('server') buf << "Server: #{server}#{EOL}" if server connection = options.delete('connection') buf << "Connection: #{connection}#{EOL}" if connection type = options.delete('type') buf << "Content-Type: #{type}#{EOL}" #if type length = options.delete('length') buf << "Content-Length: #{length}#{EOL}" if length language = options.delete('language') buf << "Content-Language: #{language}#{EOL}" if language expires = options.delete('expires') buf << "Expires: #{CGI.rfc1123_date(expires)}#{EOL}" if expires ## cookie if cookie = options.delete('cookie') case cookie when String, Cookie buf << "Set-Cookie: #{cookie}#{EOL}" when Array arr = cookie arr.each {|c| buf << "Set-Cookie: #{c}#{EOL}" } when Hash hash = cookie hash.each_value {|c| buf << "Set-Cookie: #{c}#{EOL}" } end end if @output_cookies @output_cookies.each {|c| buf << "Set-Cookie: #{c}#{EOL}" } end ## other headers options.each do |key, value| buf << "#{key}: #{value}#{EOL}" end return buf end # _header_for_hash private :_header_for_hash def nph? #:nodoc: return /IIS\/(\d+)/.match($CGI_ENV['SERVER_SOFTWARE']) && $1.to_i < 5 end def _header_for_modruby(buf) #:nodoc: request = Apache::request buf.scan(/([^:]+): (.+)#{EOL}/o) do |name, value| warn sprintf("name:%s value:%s\n", name, value) if $DEBUG case name when 'Set-Cookie' request.headers_out.add(name, value) when /^status$/i request.status_line = value request.status = value.to_i when /^content-type$/i request.content_type = value when /^content-encoding$/i request.content_encoding = value when /^location$/i request.status = 302 if request.status == 200 request.headers_out[name] = value else request.headers_out[name] = value end end request.send_http_header return '' end private :_header_for_modruby # Print an HTTP header and body to $DEFAULT_OUTPUT ($>) # # :call-seq: # cgi.out(content_type_string='text/html') # cgi.out(headers_hash) # # +content_type_string+:: # If a string is passed, it is assumed to be the content type. # +headers_hash+:: # This is a Hash of headers, similar to that used by #http_header. # +block+:: # A block is required and should evaluate to the body of the response. # # Content-Length is automatically calculated from the size of # the String returned by the content block. # # If ENV['REQUEST_METHOD'] == "HEAD", then only the header # is output (the content block is still required, but it is ignored). # # If the charset is "iso-2022-jp" or "euc-jp" or "shift_jis" then the # content is converted to this charset, and the language is set to "ja". # # Example: # # cgi = CGI.new # cgi.out{ "string" } # # Content-Type: text/html # # Content-Length: 6 # # # # string # # cgi.out("text/plain") { "string" } # # Content-Type: text/plain # # Content-Length: 6 # # # # string # # cgi.out("nph" => true, # "status" => "OK", # == "200 OK" # "server" => ENV['SERVER_SOFTWARE'], # "connection" => "close", # "type" => "text/html", # "charset" => "iso-2022-jp", # # Content-Type: text/html; charset=iso-2022-jp # "language" => "ja", # "expires" => Time.now + (3600 * 24 * 30), # "cookie" => [cookie1, cookie2], # "my_header1" => "my_value", # "my_header2" => "my_value") { "string" } # # HTTP/1.1 200 OK # # Date: Sun, 15 May 2011 17:35:54 GMT # # Server: Apache 2.2.0 # # Connection: close # # Content-Type: text/html; charset=iso-2022-jp # # Content-Length: 6 # # Content-Language: ja # # Expires: Tue, 14 Jun 2011 17:35:54 GMT # # Set-Cookie: foo # # Set-Cookie: bar # # my_header1: my_value # # my_header2: my_value # # # # string def out(options = "text/html") # :yield: options = { "type" => options } if options.kind_of?(String) content = yield options["length"] = content.bytesize.to_s output = stdoutput output.binmode if defined? output.binmode output.print http_header(options) output.print content unless "HEAD" == env_table['REQUEST_METHOD'] end # Print an argument or list of arguments to the default output stream # # cgi = CGI.new # cgi.print # default: cgi.print == $DEFAULT_OUTPUT.print def print(*options) stdoutput.print(*options) end # Parse an HTTP query string into a hash of key=>value pairs. # # params = CGI::parse("query_string") # # {"name1" => ["value1", "value2", ...], # # "name2" => ["value1", "value2", ...], ... } # def CGI::parse(query) params = {} query.split(/[&;]/).each do |pairs| key, value = pairs.split('=',2).collect{|v| CGI::unescape(v) } next unless key params[key] ||= [] params[key].push(value) if value end params.default=[].freeze params end # Maximum content length of post data ##MAX_CONTENT_LENGTH = 2 * 1024 * 1024 # Maximum number of request parameters when multipart MAX_MULTIPART_COUNT = 128 # Mixin module that provides the following: # # 1. Access to the CGI environment variables as methods. See # documentation to the CGI class for a list of these variables. The # methods are exposed by removing the leading +HTTP_+ (if it exists) and # downcasing the name. For example, +auth_type+ will return the # environment variable +AUTH_TYPE+, and +accept+ will return the value # for +HTTP_ACCEPT+. # # 2. Access to cookies, including the cookies attribute. # # 3. Access to parameters, including the params attribute, and overloading # #[] to perform parameter value lookup by key. # # 4. The initialize_query method, for initializing the above # mechanisms, handling multipart forms, and allowing the # class to be used in "offline" mode. # module QueryExtension %w[ CONTENT_LENGTH SERVER_PORT ].each do |env| define_method(env.sub(/^HTTP_/, '').downcase) do (val = env_table[env]) && Integer(val) end end %w[ AUTH_TYPE CONTENT_TYPE GATEWAY_INTERFACE PATH_INFO PATH_TRANSLATED QUERY_STRING REMOTE_ADDR REMOTE_HOST REMOTE_IDENT REMOTE_USER REQUEST_METHOD SCRIPT_NAME SERVER_NAME SERVER_PROTOCOL SERVER_SOFTWARE HTTP_ACCEPT HTTP_ACCEPT_CHARSET HTTP_ACCEPT_ENCODING HTTP_ACCEPT_LANGUAGE HTTP_CACHE_CONTROL HTTP_FROM HTTP_HOST HTTP_NEGOTIATE HTTP_PRAGMA HTTP_REFERER HTTP_USER_AGENT ].each do |env| define_method(env.sub(/^HTTP_/, '').downcase) do env_table[env] end end # Get the raw cookies as a string. def raw_cookie env_table["HTTP_COOKIE"] end # Get the raw RFC2965 cookies as a string. def raw_cookie2 env_table["HTTP_COOKIE2"] end # Get the cookies as a hash of cookie-name=>Cookie pairs. attr_accessor :cookies # Get the parameters as a hash of name=>values pairs, where # values is an Array. attr_reader :params # Get the uploaded files as a hash of name=>values pairs attr_reader :files # Set all the parameters. def params=(hash) @params.clear @params.update(hash) end ## # Parses multipart form elements according to # http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.2 # # Returns a hash of multipart form parameters with bodies of type StringIO or # Tempfile depending on whether the multipart form element exceeds 10 KB # # params[name => body] # def read_multipart(boundary, content_length) ## read first boundary stdin = stdinput first_line = "--#{boundary}#{EOL}" content_length -= first_line.bytesize status = stdin.read(first_line.bytesize) raise EOFError.new("no content body") unless status raise EOFError.new("bad content body") unless first_line == status ## parse and set params params = {} @files = {} boundary_rexp = /--#{Regexp.quote(boundary)}(#{EOL}|--)/ boundary_size = "#{EOL}--#{boundary}#{EOL}".bytesize buf = '' bufsize = 10 * 1024 max_count = MAX_MULTIPART_COUNT n = 0 tempfiles = [] while true (n += 1) < max_count or raise StandardError.new("too many parameters.") ## create body (StringIO or Tempfile) body = create_body(bufsize < content_length) tempfiles << body if defined?(Tempfile) && body.kind_of?(Tempfile) class << body if method_defined?(:path) alias local_path path else def local_path nil end end attr_reader :original_filename, :content_type end ## find head and boundary head = nil separator = EOL * 2 until head && matched = boundary_rexp.match(buf) if !head && pos = buf.index(separator) len = pos + EOL.bytesize head = buf[0, len] buf = buf[(pos+separator.bytesize)..-1] else if head && buf.size > boundary_size len = buf.size - boundary_size body.print(buf[0, len]) buf[0, len] = '' end c = stdin.read(bufsize < content_length ? bufsize : content_length) raise EOFError.new("bad content body") if c.nil? || c.empty? buf << c content_length -= c.bytesize end end ## read to end of boundary m = matched len = m.begin(0) s = buf[0, len] if s =~ /(\r?\n)\z/ s = buf[0, len - $1.bytesize] end body.print(s) buf = buf[m.end(0)..-1] boundary_end = m[1] content_length = -1 if boundary_end == '--' ## reset file cursor position body.rewind ## original filename /Content-Disposition:.* filename=(?:"(.*?)"|([^;\r\n]*))/i.match(head) filename = $1 || $2 || '' filename = CGI.unescape(filename) if unescape_filename?() body.instance_variable_set(:@original_filename, filename.taint) ## content type /Content-Type: (.*)/i.match(head) (content_type = $1 || '').chomp! body.instance_variable_set(:@content_type, content_type.taint) ## query parameter name /Content-Disposition:.* name=(?:"(.*?)"|([^;\r\n]*))/i.match(head) name = $1 || $2 || '' if body.original_filename.empty? value=body.read.dup.force_encoding(@accept_charset) body.close! if defined?(Tempfile) && body.kind_of?(Tempfile) (params[name] ||= []) << value unless value.valid_encoding? if @accept_charset_error_block @accept_charset_error_block.call(name,value) else raise InvalidEncoding,"Accept-Charset encoding error" end end class << params[name].last;self;end.class_eval do define_method(:read){self} define_method(:original_filename){""} define_method(:content_type){""} end else (params[name] ||= []) << body @files[name]=body end ## break loop break if content_length == -1 end raise EOFError, "bad boundary end of body part" unless boundary_end =~ /--/ params.default = [] params rescue Exception if tempfiles tempfiles.each {|t| if t.path t.close! end } end raise end # read_multipart private :read_multipart def create_body(is_large) #:nodoc: if is_large require 'tempfile' body = Tempfile.new('CGI', encoding: Encoding::ASCII_8BIT) else begin require 'stringio' body = StringIO.new("".force_encoding(Encoding::ASCII_8BIT)) rescue LoadError require 'tempfile' body = Tempfile.new('CGI', encoding: Encoding::ASCII_8BIT) end end body.binmode if defined? body.binmode return body end def unescape_filename? #:nodoc: user_agent = $CGI_ENV['HTTP_USER_AGENT'] return /Mac/i.match(user_agent) && /Mozilla/i.match(user_agent) && !/MSIE/i.match(user_agent) end # offline mode. read name=value pairs on standard input. def read_from_cmdline require "shellwords" string = unless ARGV.empty? ARGV.join(' ') else if STDIN.tty? STDERR.print( %|(offline mode: enter name=value pairs on standard input)\n| ) end array = readlines rescue nil if not array.nil? array.join(' ').gsub(/\n/n, '') else "" end end.gsub(/\\=/n, '%3D').gsub(/\\&/n, '%26') words = Shellwords.shellwords(string) if words.find{|x| /=/n.match(x) } words.join('&') else words.join('+') end end private :read_from_cmdline # A wrapper class to use a StringIO object as the body and switch # to a TempFile when the passed threshold is passed. # Initialize the data from the query. # # Handles multipart forms (in particular, forms that involve file uploads). # Reads query parameters in the @params field, and cookies into @cookies. def initialize_query() if ("POST" == env_table['REQUEST_METHOD']) and %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?|.match(env_table['CONTENT_TYPE']) current_max_multipart_length = @max_multipart_length.respond_to?(:call) ? @max_multipart_length.call : @max_multipart_length raise StandardError.new("too large multipart data.") if env_table['CONTENT_LENGTH'].to_i > current_max_multipart_length boundary = $1.dup @multipart = true @params = read_multipart(boundary, Integer(env_table['CONTENT_LENGTH'])) else @multipart = false @params = CGI::parse( case env_table['REQUEST_METHOD'] when "GET", "HEAD" if defined?(MOD_RUBY) Apache::request.args or "" else env_table['QUERY_STRING'] or "" end when "POST" stdinput.binmode if defined? stdinput.binmode stdinput.read(Integer(env_table['CONTENT_LENGTH'])) or '' else read_from_cmdline end.dup.force_encoding(@accept_charset) ) unless Encoding.find(@accept_charset) == Encoding::ASCII_8BIT @params.each do |key,values| values.each do |value| unless value.valid_encoding? if @accept_charset_error_block @accept_charset_error_block.call(key,value) else raise InvalidEncoding,"Accept-Charset encoding error" end end end end end end @cookies = CGI::Cookie::parse((env_table['HTTP_COOKIE'] or env_table['COOKIE'])) end private :initialize_query # Returns whether the form contained multipart/form-data def multipart? @multipart end # Get the value for the parameter with a given key. # # If the parameter has multiple values, only the first will be # retrieved; use #params to get the array of values. def [](key) params = @params[key] return '' unless params value = params[0] if @multipart if value return value elsif defined? StringIO StringIO.new("".force_encoding(Encoding::ASCII_8BIT)) else Tempfile.new("CGI",encoding: Encoding::ASCII_8BIT) end else str = if value then value.dup else "" end str end end # Return all query parameter names as an array of String. def keys(*args) @params.keys(*args) end # Returns true if a given query string parameter exists. def has_key?(*args) @params.has_key?(*args) end alias key? has_key? alias include? has_key? end # QueryExtension # Exception raised when there is an invalid encoding detected class InvalidEncoding < Exception; end # @@accept_charset is default accept character set. # This default value default is "UTF-8" # If you want to change the default accept character set # when create a new CGI instance, set this: # # CGI.accept_charset = "EUC-JP" # @@accept_charset="UTF-8" # Return the accept character set for all new CGI instances. def self.accept_charset @@accept_charset end # Set the accept character set for all new CGI instances. def self.accept_charset=(accept_charset) @@accept_charset=accept_charset end # Return the accept character set for this CGI instance. attr_reader :accept_charset # @@max_multipart_length is the maximum length of multipart data. # The default value is 128 * 1024 * 1024 bytes # # The default can be set to something else in the CGI constructor, # via the :max_multipart_length key in the option hash. # # See CGI.new documentation. # @@max_multipart_length= 128 * 1024 * 1024 # Create a new CGI instance. # # :call-seq: # CGI.new(tag_maker) { block } # CGI.new(options_hash = {}) { block } # # # tag_maker:: # This is the same as using the +options_hash+ form with the value { # :tag_maker => tag_maker } Note that it is recommended to use the # +options_hash+ form, since it also allows you specify the charset you # will accept. # options_hash:: # A Hash that recognizes three options: # # :accept_charset:: # specifies encoding of received query string. If omitted, # @@accept_charset is used. If the encoding is not valid, a # CGI::InvalidEncoding will be raised. # # Example. Suppose @@accept_charset is "UTF-8" # # when not specified: # # cgi=CGI.new # @accept_charset # => "UTF-8" # # when specified as "EUC-JP": # # cgi=CGI.new(:accept_charset => "EUC-JP") # => "EUC-JP" # # :tag_maker:: # String that specifies which version of the HTML generation methods to # use. If not specified, no HTML generation methods will be loaded. # # The following values are supported: # # "html3":: HTML 3.x # "html4":: HTML 4.0 # "html4Tr":: HTML 4.0 Transitional # "html4Fr":: HTML 4.0 with Framesets # "html5":: HTML 5 # # :max_multipart_length:: # Specifies maximum length of multipart data. Can be an Integer scalar or # a lambda, that will be evaluated when the request is parsed. This # allows more complex logic to be set when determining whether to accept # multipart data (e.g. consult a registered users upload allowance) # # Default is 128 * 1024 * 1024 bytes # # cgi=CGI.new(:max_multipart_length => 268435456) # simple scalar # # cgi=CGI.new(:max_multipart_length => -> {check_filesystem}) # lambda # # block:: # If provided, the block is called when an invalid encoding is # encountered. For example: # # encoding_errors={} # cgi=CGI.new(:accept_charset=>"EUC-JP") do |name,value| # encoding_errors[name] = value # end # # Finally, if the CGI object is not created in a standard CGI call # environment (that is, it can't locate REQUEST_METHOD in its environment), # then it will run in "offline" mode. In this mode, it reads its parameters # from the command line or (failing that) from standard input. Otherwise, # cookies and other parameters are parsed automatically from the standard # CGI locations, which varies according to the REQUEST_METHOD. def initialize(options = {}, &block) # :yields: name, value @accept_charset_error_block = block_given? ? block : nil @options={ :accept_charset=>@@accept_charset, :max_multipart_length=>@@max_multipart_length } case options when Hash @options.merge!(options) when String @options[:tag_maker]=options end @accept_charset=@options[:accept_charset] @max_multipart_length=@options[:max_multipart_length] if defined?(MOD_RUBY) && !ENV.key?("GATEWAY_INTERFACE") Apache.request.setup_cgi_env end extend QueryExtension @multipart = false initialize_query() # set @params, @cookies @output_cookies = nil @output_hidden = nil case @options[:tag_maker] when "html3" require 'cgi/html' extend Html3 extend HtmlExtension when "html4" require 'cgi/html' extend Html4 extend HtmlExtension when "html4Tr" require 'cgi/html' extend Html4Tr extend HtmlExtension when "html4Fr" require 'cgi/html' extend Html4Tr extend Html4Fr extend HtmlExtension when "html5" require 'cgi/html' extend Html5 extend HtmlExtension end end end # class CGI PK!:9 9 2.2.0/resolv.rbnu[require 'socket' require 'timeout' require 'thread' begin require 'securerandom' rescue LoadError end # Resolv is a thread-aware DNS resolver library written in Ruby. Resolv can # handle multiple DNS requests concurrently without blocking the entire Ruby # interpreter. # # See also resolv-replace.rb to replace the libc resolver with Resolv. # # Resolv can look up various DNS resources using the DNS module directly. # # Examples: # # p Resolv.getaddress "www.ruby-lang.org" # p Resolv.getname "210.251.121.214" # # Resolv::DNS.open do |dns| # ress = dns.getresources "www.ruby-lang.org", Resolv::DNS::Resource::IN::A # p ress.map { |r| r.address } # ress = dns.getresources "ruby-lang.org", Resolv::DNS::Resource::IN::MX # p ress.map { |r| [r.exchange.to_s, r.preference] } # end # # # == Bugs # # * NIS is not supported. # * /etc/nsswitch.conf is not supported. class Resolv ## # Looks up the first IP address for +name+. def self.getaddress(name) DefaultResolver.getaddress(name) end ## # Looks up all IP address for +name+. def self.getaddresses(name) DefaultResolver.getaddresses(name) end ## # Iterates over all IP addresses for +name+. def self.each_address(name, &block) DefaultResolver.each_address(name, &block) end ## # Looks up the hostname of +address+. def self.getname(address) DefaultResolver.getname(address) end ## # Looks up all hostnames for +address+. def self.getnames(address) DefaultResolver.getnames(address) end ## # Iterates over all hostnames for +address+. def self.each_name(address, &proc) DefaultResolver.each_name(address, &proc) end ## # Creates a new Resolv using +resolvers+. def initialize(resolvers=[Hosts.new, DNS.new]) @resolvers = resolvers end ## # Looks up the first IP address for +name+. def getaddress(name) each_address(name) {|address| return address} raise ResolvError.new("no address for #{name}") end ## # Looks up all IP address for +name+. def getaddresses(name) ret = [] each_address(name) {|address| ret << address} return ret end ## # Iterates over all IP addresses for +name+. def each_address(name) if AddressRegex =~ name yield name return end yielded = false @resolvers.each {|r| r.each_address(name) {|address| yield address.to_s yielded = true } return if yielded } end ## # Looks up the hostname of +address+. def getname(address) each_name(address) {|name| return name} raise ResolvError.new("no name for #{address}") end ## # Looks up all hostnames for +address+. def getnames(address) ret = [] each_name(address) {|name| ret << name} return ret end ## # Iterates over all hostnames for +address+. def each_name(address) yielded = false @resolvers.each {|r| r.each_name(address) {|name| yield name.to_s yielded = true } return if yielded } end ## # Indicates a failure to resolve a name or address. class ResolvError < StandardError; end ## # Indicates a timeout resolving a name or address. class ResolvTimeout < Timeout::Error; end ## # Resolv::Hosts is a hostname resolver that uses the system hosts file. class Hosts begin raise LoadError unless /mswin|mingw|cygwin/ =~ RUBY_PLATFORM require 'win32/resolv' DefaultFileName = Win32::Resolv.get_hosts_path rescue LoadError DefaultFileName = '/etc/hosts' end ## # Creates a new Resolv::Hosts, using +filename+ for its data source. def initialize(filename = DefaultFileName) @filename = filename @mutex = Mutex.new @initialized = nil end def lazy_initialize # :nodoc: @mutex.synchronize { unless @initialized @name2addr = {} @addr2name = {} open(@filename, 'rb') {|f| f.each {|line| line.sub!(/#.*/, '') addr, hostname, *aliases = line.split(/\s+/) next unless addr addr.untaint hostname.untaint @addr2name[addr] = [] unless @addr2name.include? addr @addr2name[addr] << hostname @addr2name[addr] += aliases @name2addr[hostname] = [] unless @name2addr.include? hostname @name2addr[hostname] << addr aliases.each {|n| n.untaint @name2addr[n] = [] unless @name2addr.include? n @name2addr[n] << addr } } } @name2addr.each {|name, arr| arr.reverse!} @initialized = true end } self end ## # Gets the IP address of +name+ from the hosts file. def getaddress(name) each_address(name) {|address| return address} raise ResolvError.new("#{@filename} has no name: #{name}") end ## # Gets all IP addresses for +name+ from the hosts file. def getaddresses(name) ret = [] each_address(name) {|address| ret << address} return ret end ## # Iterates over all IP addresses for +name+ retrieved from the hosts file. def each_address(name, &proc) lazy_initialize if @name2addr.include?(name) @name2addr[name].each(&proc) end end ## # Gets the hostname of +address+ from the hosts file. def getname(address) each_name(address) {|name| return name} raise ResolvError.new("#{@filename} has no address: #{address}") end ## # Gets all hostnames for +address+ from the hosts file. def getnames(address) ret = [] each_name(address) {|name| ret << name} return ret end ## # Iterates over all hostnames for +address+ retrieved from the hosts file. def each_name(address, &proc) lazy_initialize if @addr2name.include?(address) @addr2name[address].each(&proc) end end end ## # Resolv::DNS is a DNS stub resolver. # # Information taken from the following places: # # * STD0013 # * RFC 1035 # * ftp://ftp.isi.edu/in-notes/iana/assignments/dns-parameters # * etc. class DNS ## # Default DNS Port Port = 53 ## # Default DNS UDP packet size UDPSize = 512 ## # Creates a new DNS resolver. See Resolv::DNS.new for argument details. # # Yields the created DNS resolver to the block, if given, otherwise # returns it. def self.open(*args) dns = new(*args) return dns unless block_given? begin yield dns ensure dns.close end end ## # Creates a new DNS resolver. # # +config_info+ can be: # # nil:: Uses /etc/resolv.conf. # String:: Path to a file using /etc/resolv.conf's format. # Hash:: Must contain :nameserver, :search and :ndots keys. # :nameserver_port can be used to specify port number of nameserver address. # # The value of :nameserver should be an address string or # an array of address strings. # - :nameserver => '8.8.8.8' # - :nameserver => ['8.8.8.8', '8.8.4.4'] # # The value of :nameserver_port should be an array of # pair of nameserver address and port number. # - :nameserver_port => [['8.8.8.8', 53], ['8.8.4.4', 53]] # # Example: # # Resolv::DNS.new(:nameserver => ['210.251.121.21'], # :search => ['ruby-lang.org'], # :ndots => 1) def initialize(config_info=nil) @mutex = Mutex.new @config = Config.new(config_info) @initialized = nil end # Sets the resolver timeouts. This may be a single positive number # or an array of positive numbers representing timeouts in seconds. # If an array is specified, a DNS request will retry and wait for # each successive interval in the array until a successful response # is received. Specifying +nil+ reverts to the default timeouts: # [ 5, second = 5 * 2 / nameserver_count, 2 * second, 4 * second ] # # Example: # # dns.timeouts = 3 # def timeouts=(values) @config.timeouts = values end def lazy_initialize # :nodoc: @mutex.synchronize { unless @initialized @config.lazy_initialize @initialized = true end } self end ## # Closes the DNS resolver. def close @mutex.synchronize { if @initialized @initialized = false end } end ## # Gets the IP address of +name+ from the DNS resolver. # # +name+ can be a Resolv::DNS::Name or a String. Retrieved address will # be a Resolv::IPv4 or Resolv::IPv6 def getaddress(name) each_address(name) {|address| return address} raise ResolvError.new("DNS result has no information for #{name}") end ## # Gets all IP addresses for +name+ from the DNS resolver. # # +name+ can be a Resolv::DNS::Name or a String. Retrieved addresses will # be a Resolv::IPv4 or Resolv::IPv6 def getaddresses(name) ret = [] each_address(name) {|address| ret << address} return ret end ## # Iterates over all IP addresses for +name+ retrieved from the DNS # resolver. # # +name+ can be a Resolv::DNS::Name or a String. Retrieved addresses will # be a Resolv::IPv4 or Resolv::IPv6 def each_address(name) each_resource(name, Resource::IN::A) {|resource| yield resource.address} if use_ipv6? each_resource(name, Resource::IN::AAAA) {|resource| yield resource.address} end end def use_ipv6? # :nodoc: begin list = Socket.ip_address_list rescue NotImplementedError return true end list.any? {|a| a.ipv6? && !a.ipv6_loopback? && !a.ipv6_linklocal? } end private :use_ipv6? ## # Gets the hostname for +address+ from the DNS resolver. # # +address+ must be a Resolv::IPv4, Resolv::IPv6 or a String. Retrieved # name will be a Resolv::DNS::Name. def getname(address) each_name(address) {|name| return name} raise ResolvError.new("DNS result has no information for #{address}") end ## # Gets all hostnames for +address+ from the DNS resolver. # # +address+ must be a Resolv::IPv4, Resolv::IPv6 or a String. Retrieved # names will be Resolv::DNS::Name instances. def getnames(address) ret = [] each_name(address) {|name| ret << name} return ret end ## # Iterates over all hostnames for +address+ retrieved from the DNS # resolver. # # +address+ must be a Resolv::IPv4, Resolv::IPv6 or a String. Retrieved # names will be Resolv::DNS::Name instances. def each_name(address) case address when Name ptr = address when IPv4::Regex ptr = IPv4.create(address).to_name when IPv6::Regex ptr = IPv6.create(address).to_name else raise ResolvError.new("cannot interpret as address: #{address}") end each_resource(ptr, Resource::IN::PTR) {|resource| yield resource.name} end ## # Look up the +typeclass+ DNS resource of +name+. # # +name+ must be a Resolv::DNS::Name or a String. # # +typeclass+ should be one of the following: # # * Resolv::DNS::Resource::IN::A # * Resolv::DNS::Resource::IN::AAAA # * Resolv::DNS::Resource::IN::ANY # * Resolv::DNS::Resource::IN::CNAME # * Resolv::DNS::Resource::IN::HINFO # * Resolv::DNS::Resource::IN::MINFO # * Resolv::DNS::Resource::IN::MX # * Resolv::DNS::Resource::IN::NS # * Resolv::DNS::Resource::IN::PTR # * Resolv::DNS::Resource::IN::SOA # * Resolv::DNS::Resource::IN::TXT # * Resolv::DNS::Resource::IN::WKS # # Returned resource is represented as a Resolv::DNS::Resource instance, # i.e. Resolv::DNS::Resource::IN::A. def getresource(name, typeclass) each_resource(name, typeclass) {|resource| return resource} raise ResolvError.new("DNS result has no information for #{name}") end ## # Looks up all +typeclass+ DNS resources for +name+. See #getresource for # argument details. def getresources(name, typeclass) ret = [] each_resource(name, typeclass) {|resource| ret << resource} return ret end ## # Iterates over all +typeclass+ DNS resources for +name+. See # #getresource for argument details. def each_resource(name, typeclass, &proc) fetch_resource(name, typeclass) {|reply, reply_name| extract_resources(reply, reply_name, typeclass, &proc) } end def fetch_resource(name, typeclass) lazy_initialize requester = make_udp_requester senders = {} begin @config.resolv(name) {|candidate, tout, nameserver, port| msg = Message.new msg.rd = 1 msg.add_question(candidate, typeclass) unless sender = senders[[candidate, nameserver, port]] sender = requester.sender(msg, candidate, nameserver, port) next if !sender senders[[candidate, nameserver, port]] = sender end reply, reply_name = requester.request(sender, tout) case reply.rcode when RCode::NoError if reply.tc == 1 and not Requester::TCP === requester requester.close # Retry via TCP: requester = make_tcp_requester(nameserver, port) senders = {} # This will use TCP for all remaining candidates (assuming the # current candidate does not already respond successfully via # TCP). This makes sense because we already know the full # response will not fit in an untruncated UDP packet. redo else yield(reply, reply_name) end return when RCode::NXDomain raise Config::NXDomain.new(reply_name.to_s) else raise Config::OtherResolvError.new(reply_name.to_s) end } ensure requester.close end end def make_udp_requester # :nodoc: nameserver_port = @config.nameserver_port if nameserver_port.length == 1 Requester::ConnectedUDP.new(*nameserver_port[0]) else Requester::UnconnectedUDP.new(*nameserver_port) end end def make_tcp_requester(host, port) # :nodoc: return Requester::TCP.new(host, port) end def extract_resources(msg, name, typeclass) # :nodoc: if typeclass < Resource::ANY n0 = Name.create(name) msg.each_answer {|n, ttl, data| yield data if n0 == n } end yielded = false n0 = Name.create(name) msg.each_answer {|n, ttl, data| if n0 == n case data when typeclass yield data yielded = true when Resource::CNAME n0 = data.name end end } return if yielded msg.each_answer {|n, ttl, data| if n0 == n case data when typeclass yield data end end } end if defined? SecureRandom def self.random(arg) # :nodoc: begin SecureRandom.random_number(arg) rescue NotImplementedError rand(arg) end end else def self.random(arg) # :nodoc: rand(arg) end end def self.rangerand(range) # :nodoc: base = range.begin len = range.end - range.begin if !range.exclude_end? len += 1 end base + random(len) end RequestID = {} # :nodoc: RequestIDMutex = Mutex.new # :nodoc: def self.allocate_request_id(host, port) # :nodoc: id = nil RequestIDMutex.synchronize { h = (RequestID[[host, port]] ||= {}) begin id = rangerand(0x0000..0xffff) end while h[id] h[id] = true } id end def self.free_request_id(host, port, id) # :nodoc: RequestIDMutex.synchronize { key = [host, port] if h = RequestID[key] h.delete id if h.empty? RequestID.delete key end end } end def self.bind_random_port(udpsock, bind_host="0.0.0.0") # :nodoc: begin port = rangerand(1024..65535) udpsock.bind(bind_host, port) rescue Errno::EADDRINUSE, # POSIX Errno::EACCES, # SunOS: See PRIV_SYS_NFS in privileges(5) Errno::EPERM # FreeBSD: security.mac.portacl.port_high is configurable. See mac_portacl(4). retry end end class Requester # :nodoc: def initialize @senders = {} @socks = nil end def request(sender, tout) start = Time.now timelimit = start + tout begin sender.send rescue Errno::EHOSTUNREACH, # multi-homed IPv6 may generate this Errno::ENETUNREACH raise ResolvTimeout end while true before_select = Time.now timeout = timelimit - before_select if timeout <= 0 raise ResolvTimeout end select_result = IO.select(@socks, nil, nil, timeout) if !select_result after_select = Time.now next if after_select < timelimit raise ResolvTimeout end begin reply, from = recv_reply(select_result[0]) rescue Errno::ECONNREFUSED, # GNU/Linux, FreeBSD Errno::ECONNRESET # Windows # No name server running on the server? # Don't wait anymore. raise ResolvTimeout end begin msg = Message.decode(reply) rescue DecodeError next # broken DNS message ignored end if s = sender_for(from, msg) break else # unexpected DNS message ignored end end return msg, s.data end def sender_for(addr, msg) @senders[[addr,msg.id]] end def close socks = @socks @socks = nil if socks socks.each {|sock| sock.close } end end class Sender # :nodoc: def initialize(msg, data, sock) @msg = msg @data = data @sock = sock end end class UnconnectedUDP < Requester # :nodoc: def initialize(*nameserver_port) super() @nameserver_port = nameserver_port @socks_hash = {} @socks = [] nameserver_port.each {|host, port| if host.index(':') bind_host = "::" af = Socket::AF_INET6 else bind_host = "0.0.0.0" af = Socket::AF_INET end next if @socks_hash[bind_host] begin sock = UDPSocket.new(af) rescue Errno::EAFNOSUPPORT next # The kernel doesn't support the address family. end sock.do_not_reverse_lookup = true DNS.bind_random_port(sock, bind_host) @socks << sock @socks_hash[bind_host] = sock } end def recv_reply(readable_socks) reply, from = readable_socks[0].recvfrom(UDPSize) return reply, [from[3],from[1]] end def sender(msg, data, host, port=Port) sock = @socks_hash[host.index(':') ? "::" : "0.0.0.0"] return nil if !sock service = [host, port] id = DNS.allocate_request_id(host, port) request = msg.encode request[0,2] = [id].pack('n') return @senders[[service, id]] = Sender.new(request, data, sock, host, port) end def close super @senders.each_key {|service, id| DNS.free_request_id(service[0], service[1], id) } end class Sender < Requester::Sender # :nodoc: def initialize(msg, data, sock, host, port) super(msg, data, sock) @host = host @port = port end attr_reader :data def send raise "@sock is nil." if @sock.nil? @sock.send(@msg, 0, @host, @port) end end end class ConnectedUDP < Requester # :nodoc: def initialize(host, port=Port) super() @host = host @port = port is_ipv6 = host.index(':') sock = UDPSocket.new(is_ipv6 ? Socket::AF_INET6 : Socket::AF_INET) @socks = [sock] sock.do_not_reverse_lookup = true DNS.bind_random_port(sock, is_ipv6 ? "::" : "0.0.0.0") sock.connect(host, port) end def recv_reply(readable_socks) reply = readable_socks[0].recv(UDPSize) return reply, nil end def sender(msg, data, host=@host, port=@port) unless host == @host && port == @port raise RequestError.new("host/port don't match: #{host}:#{port}") end id = DNS.allocate_request_id(@host, @port) request = msg.encode request[0,2] = [id].pack('n') return @senders[[nil,id]] = Sender.new(request, data, @socks[0]) end def close super @senders.each_key {|from, id| DNS.free_request_id(@host, @port, id) } end class Sender < Requester::Sender # :nodoc: def send raise "@sock is nil." if @sock.nil? @sock.send(@msg, 0) end attr_reader :data end end class MDNSOneShot < UnconnectedUDP # :nodoc: def sender(msg, data, host, port=Port) id = DNS.allocate_request_id(host, port) request = msg.encode request[0,2] = [id].pack('n') sock = @socks_hash[host.index(':') ? "::" : "0.0.0.0"] return @senders[id] = UnconnectedUDP::Sender.new(request, data, sock, host, port) end def sender_for(addr, msg) @senders[msg.id] end end class TCP < Requester # :nodoc: def initialize(host, port=Port) super() @host = host @port = port sock = TCPSocket.new(@host, @port) @socks = [sock] @senders = {} end def recv_reply(readable_socks) len = readable_socks[0].read(2).unpack('n')[0] reply = @socks[0].read(len) return reply, nil end def sender(msg, data, host=@host, port=@port) unless host == @host && port == @port raise RequestError.new("host/port don't match: #{host}:#{port}") end id = DNS.allocate_request_id(@host, @port) request = msg.encode request[0,2] = [request.length, id].pack('nn') return @senders[[nil,id]] = Sender.new(request, data, @socks[0]) end class Sender < Requester::Sender # :nodoc: def send @sock.print(@msg) @sock.flush end attr_reader :data end def close super @senders.each_key {|from,id| DNS.free_request_id(@host, @port, id) } end end ## # Indicates a problem with the DNS request. class RequestError < StandardError end end class Config # :nodoc: def initialize(config_info=nil) @mutex = Mutex.new @config_info = config_info @initialized = nil @timeouts = nil end def timeouts=(values) if values values = Array(values) values.each do |t| Numeric === t or raise ArgumentError, "#{t.inspect} is not numeric" t > 0.0 or raise ArgumentError, "timeout=#{t} must be positive" end @timeouts = values else @timeouts = nil end end def Config.parse_resolv_conf(filename) nameserver = [] search = nil ndots = 1 open(filename, 'rb') {|f| f.each {|line| line.sub!(/[#;].*/, '') keyword, *args = line.split(/\s+/) args.each { |arg| arg.untaint } next unless keyword case keyword when 'nameserver' nameserver += args when 'domain' next if args.empty? search = [args[0]] when 'search' next if args.empty? search = args when 'options' args.each {|arg| case arg when /\Andots:(\d+)\z/ ndots = $1.to_i end } end } } return { :nameserver => nameserver, :search => search, :ndots => ndots } end def Config.default_config_hash(filename="/etc/resolv.conf") if File.exist? filename config_hash = Config.parse_resolv_conf(filename) else if /mswin|cygwin|mingw|bccwin/ =~ RUBY_PLATFORM require 'win32/resolv' search, nameserver = Win32::Resolv.get_resolv_info config_hash = {} config_hash[:nameserver] = nameserver if nameserver config_hash[:search] = [search].flatten if search end end config_hash || {} end def lazy_initialize @mutex.synchronize { unless @initialized @nameserver_port = [] @search = nil @ndots = 1 case @config_info when nil config_hash = Config.default_config_hash when String config_hash = Config.parse_resolv_conf(@config_info) when Hash config_hash = @config_info.dup if String === config_hash[:nameserver] config_hash[:nameserver] = [config_hash[:nameserver]] end if String === config_hash[:search] config_hash[:search] = [config_hash[:search]] end else raise ArgumentError.new("invalid resolv configuration: #{@config_info.inspect}") end if config_hash.include? :nameserver @nameserver_port = config_hash[:nameserver].map {|ns| [ns, Port] } end if config_hash.include? :nameserver_port @nameserver_port = config_hash[:nameserver_port].map {|ns, port| [ns, (port || Port)] } end @search = config_hash[:search] if config_hash.include? :search @ndots = config_hash[:ndots] if config_hash.include? :ndots if @nameserver_port.empty? @nameserver_port << ['0.0.0.0', Port] end if @search @search = @search.map {|arg| Label.split(arg) } else hostname = Socket.gethostname if /\./ =~ hostname @search = [Label.split($')] else @search = [[]] end end if !@nameserver_port.kind_of?(Array) || @nameserver_port.any? {|ns_port| !(Array === ns_port) || ns_port.length != 2 !(String === ns_port[0]) || !(Integer === ns_port[1]) } raise ArgumentError.new("invalid nameserver config: #{@nameserver_port.inspect}") end if !@search.kind_of?(Array) || !@search.all? {|ls| ls.all? {|l| Label::Str === l } } raise ArgumentError.new("invalid search config: #{@search.inspect}") end if !@ndots.kind_of?(Integer) raise ArgumentError.new("invalid ndots config: #{@ndots.inspect}") end @initialized = true end } self end def single? lazy_initialize if @nameserver_port.length == 1 return @nameserver_port[0] else return nil end end def nameserver_port @nameserver_port end def generate_candidates(name) candidates = nil name = Name.create(name) if name.absolute? candidates = [name] else if @ndots <= name.length - 1 candidates = [Name.new(name.to_a)] else candidates = [] end candidates.concat(@search.map {|domain| Name.new(name.to_a + domain)}) fname = Name.create("#{name}.") if !candidates.include?(fname) candidates << fname end end return candidates end InitialTimeout = 5 def generate_timeouts ts = [InitialTimeout] ts << ts[-1] * 2 / @nameserver_port.length ts << ts[-1] * 2 ts << ts[-1] * 2 return ts end def resolv(name) candidates = generate_candidates(name) timeouts = @timeouts || generate_timeouts begin candidates.each {|candidate| begin timeouts.each {|tout| @nameserver_port.each {|nameserver, port| begin yield candidate, tout, nameserver, port rescue ResolvTimeout end } } raise ResolvError.new("DNS resolv timeout: #{name}") rescue NXDomain end } rescue ResolvError end end ## # Indicates no such domain was found. class NXDomain < ResolvError end ## # Indicates some other unhandled resolver error was encountered. class OtherResolvError < ResolvError end end module OpCode # :nodoc: Query = 0 IQuery = 1 Status = 2 Notify = 4 Update = 5 end module RCode # :nodoc: NoError = 0 FormErr = 1 ServFail = 2 NXDomain = 3 NotImp = 4 Refused = 5 YXDomain = 6 YXRRSet = 7 NXRRSet = 8 NotAuth = 9 NotZone = 10 BADVERS = 16 BADSIG = 16 BADKEY = 17 BADTIME = 18 BADMODE = 19 BADNAME = 20 BADALG = 21 end ## # Indicates that the DNS response was unable to be decoded. class DecodeError < StandardError end ## # Indicates that the DNS request was unable to be encoded. class EncodeError < StandardError end module Label # :nodoc: def self.split(arg) labels = [] arg.scan(/[^\.]+/) {labels << Str.new($&)} return labels end class Str # :nodoc: def initialize(string) @string = string @downcase = string.downcase end attr_reader :string, :downcase def to_s return @string end def inspect return "#<#{self.class} #{self}>" end def ==(other) return self.class == other.class && @downcase == other.downcase end def eql?(other) return self == other end def hash return @downcase.hash end end end ## # A representation of a DNS name. class Name ## # Creates a new DNS name from +arg+. +arg+ can be: # # Name:: returns +arg+. # String:: Creates a new Name. def self.create(arg) case arg when Name return arg when String return Name.new(Label.split(arg), /\.\z/ =~ arg ? true : false) else raise ArgumentError.new("cannot interpret as DNS name: #{arg.inspect}") end end def initialize(labels, absolute=true) # :nodoc: labels = labels.map {|label| case label when String then Label::Str.new(label) when Label::Str then label else raise ArgumentError, "unexpected label: #{label.inspect}" end } @labels = labels @absolute = absolute end def inspect # :nodoc: "#<#{self.class}: #{self}#{@absolute ? '.' : ''}>" end ## # True if this name is absolute. def absolute? return @absolute end def ==(other) # :nodoc: return false unless Name === other return false unless @absolute == other.absolute? return @labels == other.to_a end alias eql? == # :nodoc: ## # Returns true if +other+ is a subdomain. # # Example: # # domain = Resolv::DNS::Name.create("y.z") # p Resolv::DNS::Name.create("w.x.y.z").subdomain_of?(domain) #=> true # p Resolv::DNS::Name.create("x.y.z").subdomain_of?(domain) #=> true # p Resolv::DNS::Name.create("y.z").subdomain_of?(domain) #=> false # p Resolv::DNS::Name.create("z").subdomain_of?(domain) #=> false # p Resolv::DNS::Name.create("x.y.z.").subdomain_of?(domain) #=> false # p Resolv::DNS::Name.create("w.z").subdomain_of?(domain) #=> false # def subdomain_of?(other) raise ArgumentError, "not a domain name: #{other.inspect}" unless Name === other return false if @absolute != other.absolute? other_len = other.length return false if @labels.length <= other_len return @labels[-other_len, other_len] == other.to_a end def hash # :nodoc: return @labels.hash ^ @absolute.hash end def to_a # :nodoc: return @labels end def length # :nodoc: return @labels.length end def [](i) # :nodoc: return @labels[i] end ## # returns the domain name as a string. # # The domain name doesn't have a trailing dot even if the name object is # absolute. # # Example: # # p Resolv::DNS::Name.create("x.y.z.").to_s #=> "x.y.z" # p Resolv::DNS::Name.create("x.y.z").to_s #=> "x.y.z" def to_s return @labels.join('.') end end class Message # :nodoc: @@identifier = -1 def initialize(id = (@@identifier += 1) & 0xffff) @id = id @qr = 0 @opcode = 0 @aa = 0 @tc = 0 @rd = 0 # recursion desired @ra = 0 # recursion available @rcode = 0 @question = [] @answer = [] @authority = [] @additional = [] end attr_accessor :id, :qr, :opcode, :aa, :tc, :rd, :ra, :rcode attr_reader :question, :answer, :authority, :additional def ==(other) return @id == other.id && @qr == other.qr && @opcode == other.opcode && @aa == other.aa && @tc == other.tc && @rd == other.rd && @ra == other.ra && @rcode == other.rcode && @question == other.question && @answer == other.answer && @authority == other.authority && @additional == other.additional end def add_question(name, typeclass) @question << [Name.create(name), typeclass] end def each_question @question.each {|name, typeclass| yield name, typeclass } end def add_answer(name, ttl, data) @answer << [Name.create(name), ttl, data] end def each_answer @answer.each {|name, ttl, data| yield name, ttl, data } end def add_authority(name, ttl, data) @authority << [Name.create(name), ttl, data] end def each_authority @authority.each {|name, ttl, data| yield name, ttl, data } end def add_additional(name, ttl, data) @additional << [Name.create(name), ttl, data] end def each_additional @additional.each {|name, ttl, data| yield name, ttl, data } end def each_resource each_answer {|name, ttl, data| yield name, ttl, data} each_authority {|name, ttl, data| yield name, ttl, data} each_additional {|name, ttl, data| yield name, ttl, data} end def encode return MessageEncoder.new {|msg| msg.put_pack('nnnnnn', @id, (@qr & 1) << 15 | (@opcode & 15) << 11 | (@aa & 1) << 10 | (@tc & 1) << 9 | (@rd & 1) << 8 | (@ra & 1) << 7 | (@rcode & 15), @question.length, @answer.length, @authority.length, @additional.length) @question.each {|q| name, typeclass = q msg.put_name(name) msg.put_pack('nn', typeclass::TypeValue, typeclass::ClassValue) } [@answer, @authority, @additional].each {|rr| rr.each {|r| name, ttl, data = r msg.put_name(name) msg.put_pack('nnN', data.class::TypeValue, data.class::ClassValue, ttl) msg.put_length16 {data.encode_rdata(msg)} } } }.to_s end class MessageEncoder # :nodoc: def initialize @data = '' @names = {} yield self end def to_s return @data end def put_bytes(d) @data << d end def put_pack(template, *d) @data << d.pack(template) end def put_length16 length_index = @data.length @data << "\0\0" data_start = @data.length yield data_end = @data.length @data[length_index, 2] = [data_end - data_start].pack("n") end def put_string(d) self.put_pack("C", d.length) @data << d end def put_string_list(ds) ds.each {|d| self.put_string(d) } end def put_name(d) put_labels(d.to_a) end def put_labels(d) d.each_index {|i| domain = d[i..-1] if idx = @names[domain] self.put_pack("n", 0xc000 | idx) return else @names[domain] = @data.length self.put_label(d[i]) end } @data << "\0" end def put_label(d) self.put_string(d.to_s) end end def Message.decode(m) o = Message.new(0) MessageDecoder.new(m) {|msg| id, flag, qdcount, ancount, nscount, arcount = msg.get_unpack('nnnnnn') o.id = id o.qr = (flag >> 15) & 1 o.opcode = (flag >> 11) & 15 o.aa = (flag >> 10) & 1 o.tc = (flag >> 9) & 1 o.rd = (flag >> 8) & 1 o.ra = (flag >> 7) & 1 o.rcode = flag & 15 (1..qdcount).each { name, typeclass = msg.get_question o.add_question(name, typeclass) } (1..ancount).each { name, ttl, data = msg.get_rr o.add_answer(name, ttl, data) } (1..nscount).each { name, ttl, data = msg.get_rr o.add_authority(name, ttl, data) } (1..arcount).each { name, ttl, data = msg.get_rr o.add_additional(name, ttl, data) } } return o end class MessageDecoder # :nodoc: def initialize(data) @data = data @index = 0 @limit = data.length yield self end def inspect "\#<#{self.class}: #{@data[0, @index].inspect} #{@data[@index..-1].inspect}>" end def get_length16 len, = self.get_unpack('n') save_limit = @limit @limit = @index + len d = yield(len) if @index < @limit raise DecodeError.new("junk exists") elsif @limit < @index raise DecodeError.new("limit exceeded") end @limit = save_limit return d end def get_bytes(len = @limit - @index) raise DecodeError.new("limit exceeded") if @limit < @index + len d = @data[@index, len] @index += len return d end def get_unpack(template) len = 0 template.each_byte {|byte| byte = "%c" % byte case byte when ?c, ?C len += 1 when ?n len += 2 when ?N len += 4 else raise StandardError.new("unsupported template: '#{byte.chr}' in '#{template}'") end } raise DecodeError.new("limit exceeded") if @limit < @index + len arr = @data.unpack("@#{@index}#{template}") @index += len return arr end def get_string raise DecodeError.new("limit exceeded") if @limit <= @index len = @data[@index].ord raise DecodeError.new("limit exceeded") if @limit < @index + 1 + len d = @data[@index + 1, len] @index += 1 + len return d end def get_string_list strings = [] while @index < @limit strings << self.get_string end strings end def get_name return Name.new(self.get_labels) end def get_labels prev_index = @index save_index = nil d = [] while true raise DecodeError.new("limit exceeded") if @limit <= @index case @data[@index].ord when 0 @index += 1 if save_index @index = save_index end return d when 192..255 idx = self.get_unpack('n')[0] & 0x3fff if prev_index <= idx raise DecodeError.new("non-backward name pointer") end prev_index = idx if !save_index save_index = @index end @index = idx else d << self.get_label end end end def get_label return Label::Str.new(self.get_string) end def get_question name = self.get_name type, klass = self.get_unpack("nn") return name, Resource.get_class(type, klass) end def get_rr name = self.get_name type, klass, ttl = self.get_unpack('nnN') typeclass = Resource.get_class(type, klass) res = self.get_length16 { typeclass.decode_rdata self } res.instance_variable_set :@ttl, ttl return name, ttl, res end end end ## # A DNS query abstract class. class Query def encode_rdata(msg) # :nodoc: raise EncodeError.new("#{self.class} is query.") end def self.decode_rdata(msg) # :nodoc: raise DecodeError.new("#{self.class} is query.") end end ## # A DNS resource abstract class. class Resource < Query ## # Remaining Time To Live for this Resource. attr_reader :ttl ClassHash = {} # :nodoc: def encode_rdata(msg) # :nodoc: raise NotImplementedError.new end def self.decode_rdata(msg) # :nodoc: raise NotImplementedError.new end def ==(other) # :nodoc: return false unless self.class == other.class s_ivars = self.instance_variables s_ivars.sort! s_ivars.delete :@ttl o_ivars = other.instance_variables o_ivars.sort! o_ivars.delete :@ttl return s_ivars == o_ivars && s_ivars.collect {|name| self.instance_variable_get name} == o_ivars.collect {|name| other.instance_variable_get name} end def eql?(other) # :nodoc: return self == other end def hash # :nodoc: h = 0 vars = self.instance_variables vars.delete :@ttl vars.each {|name| h ^= self.instance_variable_get(name).hash } return h end def self.get_class(type_value, class_value) # :nodoc: return ClassHash[[type_value, class_value]] || Generic.create(type_value, class_value) end ## # A generic resource abstract class. class Generic < Resource ## # Creates a new generic resource. def initialize(data) @data = data end ## # Data for this generic resource. attr_reader :data def encode_rdata(msg) # :nodoc: msg.put_bytes(data) end def self.decode_rdata(msg) # :nodoc: return self.new(msg.get_bytes) end def self.create(type_value, class_value) # :nodoc: c = Class.new(Generic) c.const_set(:TypeValue, type_value) c.const_set(:ClassValue, class_value) Generic.const_set("Type#{type_value}_Class#{class_value}", c) ClassHash[[type_value, class_value]] = c return c end end ## # Domain Name resource abstract class. class DomainName < Resource ## # Creates a new DomainName from +name+. def initialize(name) @name = name end ## # The name of this DomainName. attr_reader :name def encode_rdata(msg) # :nodoc: msg.put_name(@name) end def self.decode_rdata(msg) # :nodoc: return self.new(msg.get_name) end end # Standard (class generic) RRs ClassValue = nil # :nodoc: ## # An authoritative name server. class NS < DomainName TypeValue = 2 # :nodoc: end ## # The canonical name for an alias. class CNAME < DomainName TypeValue = 5 # :nodoc: end ## # Start Of Authority resource. class SOA < Resource TypeValue = 6 # :nodoc: ## # Creates a new SOA record. See the attr documentation for the # details of each argument. def initialize(mname, rname, serial, refresh, retry_, expire, minimum) @mname = mname @rname = rname @serial = serial @refresh = refresh @retry = retry_ @expire = expire @minimum = minimum end ## # Name of the host where the master zone file for this zone resides. attr_reader :mname ## # The person responsible for this domain name. attr_reader :rname ## # The version number of the zone file. attr_reader :serial ## # How often, in seconds, a secondary name server is to check for # updates from the primary name server. attr_reader :refresh ## # How often, in seconds, a secondary name server is to retry after a # failure to check for a refresh. attr_reader :retry ## # Time in seconds that a secondary name server is to use the data # before refreshing from the primary name server. attr_reader :expire ## # The minimum number of seconds to be used for TTL values in RRs. attr_reader :minimum def encode_rdata(msg) # :nodoc: msg.put_name(@mname) msg.put_name(@rname) msg.put_pack('NNNNN', @serial, @refresh, @retry, @expire, @minimum) end def self.decode_rdata(msg) # :nodoc: mname = msg.get_name rname = msg.get_name serial, refresh, retry_, expire, minimum = msg.get_unpack('NNNNN') return self.new( mname, rname, serial, refresh, retry_, expire, minimum) end end ## # A Pointer to another DNS name. class PTR < DomainName TypeValue = 12 # :nodoc: end ## # Host Information resource. class HINFO < Resource TypeValue = 13 # :nodoc: ## # Creates a new HINFO running +os+ on +cpu+. def initialize(cpu, os) @cpu = cpu @os = os end ## # CPU architecture for this resource. attr_reader :cpu ## # Operating system for this resource. attr_reader :os def encode_rdata(msg) # :nodoc: msg.put_string(@cpu) msg.put_string(@os) end def self.decode_rdata(msg) # :nodoc: cpu = msg.get_string os = msg.get_string return self.new(cpu, os) end end ## # Mailing list or mailbox information. class MINFO < Resource TypeValue = 14 # :nodoc: def initialize(rmailbx, emailbx) @rmailbx = rmailbx @emailbx = emailbx end ## # Domain name responsible for this mail list or mailbox. attr_reader :rmailbx ## # Mailbox to use for error messages related to the mail list or mailbox. attr_reader :emailbx def encode_rdata(msg) # :nodoc: msg.put_name(@rmailbx) msg.put_name(@emailbx) end def self.decode_rdata(msg) # :nodoc: rmailbx = msg.get_string emailbx = msg.get_string return self.new(rmailbx, emailbx) end end ## # Mail Exchanger resource. class MX < Resource TypeValue= 15 # :nodoc: ## # Creates a new MX record with +preference+, accepting mail at # +exchange+. def initialize(preference, exchange) @preference = preference @exchange = exchange end ## # The preference for this MX. attr_reader :preference ## # The host of this MX. attr_reader :exchange def encode_rdata(msg) # :nodoc: msg.put_pack('n', @preference) msg.put_name(@exchange) end def self.decode_rdata(msg) # :nodoc: preference, = msg.get_unpack('n') exchange = msg.get_name return self.new(preference, exchange) end end ## # Unstructured text resource. class TXT < Resource TypeValue = 16 # :nodoc: def initialize(first_string, *rest_strings) @strings = [first_string, *rest_strings] end ## # Returns an Array of Strings for this TXT record. attr_reader :strings ## # Returns the concatenated string from +strings+. def data @strings.join("") end def encode_rdata(msg) # :nodoc: msg.put_string_list(@strings) end def self.decode_rdata(msg) # :nodoc: strings = msg.get_string_list return self.new(*strings) end end ## # Location resource class LOC < Resource TypeValue = 29 # :nodoc: def initialize(version, ssize, hprecision, vprecision, latitude, longitude, altitude) @version = version @ssize = Resolv::LOC::Size.create(ssize) @hprecision = Resolv::LOC::Size.create(hprecision) @vprecision = Resolv::LOC::Size.create(vprecision) @latitude = Resolv::LOC::Coord.create(latitude) @longitude = Resolv::LOC::Coord.create(longitude) @altitude = Resolv::LOC::Alt.create(altitude) end ## # Returns the version value for this LOC record which should always be 00 attr_reader :version ## # The spherical size of this LOC # in meters using scientific notation as 2 integers of XeY attr_reader :ssize ## # The horizontal precision using ssize type values # in meters using scientific notation as 2 integers of XeY # for precision use value/2 e.g. 2m = +/-1m attr_reader :hprecision ## # The vertical precision using ssize type values # in meters using scientific notation as 2 integers of XeY # for precision use value/2 e.g. 2m = +/-1m attr_reader :vprecision ## # The latitude for this LOC where 2**31 is the equator # in thousandths of an arc second as an unsigned 32bit integer attr_reader :latitude ## # The longitude for this LOC where 2**31 is the prime meridian # in thousandths of an arc second as an unsigned 32bit integer attr_reader :longitude ## # The altitude of the LOC above a reference sphere whose surface sits 100km below the WGS84 spheroid # in centimeters as an unsigned 32bit integer attr_reader :altitude def encode_rdata(msg) # :nodoc: msg.put_bytes(@version) msg.put_bytes(@ssize.scalar) msg.put_bytes(@hprecision.scalar) msg.put_bytes(@vprecision.scalar) msg.put_bytes(@latitude.coordinates) msg.put_bytes(@longitude.coordinates) msg.put_bytes(@altitude.altitude) end def self.decode_rdata(msg) # :nodoc: version = msg.get_bytes(1) ssize = msg.get_bytes(1) hprecision = msg.get_bytes(1) vprecision = msg.get_bytes(1) latitude = msg.get_bytes(4) longitude = msg.get_bytes(4) altitude = msg.get_bytes(4) return self.new( version, Resolv::LOC::Size.new(ssize), Resolv::LOC::Size.new(hprecision), Resolv::LOC::Size.new(vprecision), Resolv::LOC::Coord.new(latitude,"lat"), Resolv::LOC::Coord.new(longitude,"lon"), Resolv::LOC::Alt.new(altitude) ) end end ## # A Query type requesting any RR. class ANY < Query TypeValue = 255 # :nodoc: end ClassInsensitiveTypes = [ # :nodoc: NS, CNAME, SOA, PTR, HINFO, MINFO, MX, TXT, LOC, ANY ] ## # module IN contains ARPA Internet specific RRs. module IN ClassValue = 1 # :nodoc: ClassInsensitiveTypes.each {|s| c = Class.new(s) c.const_set(:TypeValue, s::TypeValue) c.const_set(:ClassValue, ClassValue) ClassHash[[s::TypeValue, ClassValue]] = c self.const_set(s.name.sub(/.*::/, ''), c) } ## # IPv4 Address resource class A < Resource TypeValue = 1 ClassValue = IN::ClassValue ClassHash[[TypeValue, ClassValue]] = self # :nodoc: ## # Creates a new A for +address+. def initialize(address) @address = IPv4.create(address) end ## # The Resolv::IPv4 address for this A. attr_reader :address def encode_rdata(msg) # :nodoc: msg.put_bytes(@address.address) end def self.decode_rdata(msg) # :nodoc: return self.new(IPv4.new(msg.get_bytes(4))) end end ## # Well Known Service resource. class WKS < Resource TypeValue = 11 ClassValue = IN::ClassValue ClassHash[[TypeValue, ClassValue]] = self # :nodoc: def initialize(address, protocol, bitmap) @address = IPv4.create(address) @protocol = protocol @bitmap = bitmap end ## # The host these services run on. attr_reader :address ## # IP protocol number for these services. attr_reader :protocol ## # A bit map of enabled services on this host. # # If protocol is 6 (TCP) then the 26th bit corresponds to the SMTP # service (port 25). If this bit is set, then an SMTP server should # be listening on TCP port 25; if zero, SMTP service is not # supported. attr_reader :bitmap def encode_rdata(msg) # :nodoc: msg.put_bytes(@address.address) msg.put_pack("n", @protocol) msg.put_bytes(@bitmap) end def self.decode_rdata(msg) # :nodoc: address = IPv4.new(msg.get_bytes(4)) protocol, = msg.get_unpack("n") bitmap = msg.get_bytes return self.new(address, protocol, bitmap) end end ## # An IPv6 address record. class AAAA < Resource TypeValue = 28 ClassValue = IN::ClassValue ClassHash[[TypeValue, ClassValue]] = self # :nodoc: ## # Creates a new AAAA for +address+. def initialize(address) @address = IPv6.create(address) end ## # The Resolv::IPv6 address for this AAAA. attr_reader :address def encode_rdata(msg) # :nodoc: msg.put_bytes(@address.address) end def self.decode_rdata(msg) # :nodoc: return self.new(IPv6.new(msg.get_bytes(16))) end end ## # SRV resource record defined in RFC 2782 # # These records identify the hostname and port that a service is # available at. class SRV < Resource TypeValue = 33 ClassValue = IN::ClassValue ClassHash[[TypeValue, ClassValue]] = self # :nodoc: # Create a SRV resource record. # # See the documentation for #priority, #weight, #port and #target # for +priority+, +weight+, +port and +target+ respectively. def initialize(priority, weight, port, target) @priority = priority.to_int @weight = weight.to_int @port = port.to_int @target = Name.create(target) end # The priority of this target host. # # A client MUST attempt to contact the target host with the # lowest-numbered priority it can reach; target hosts with the same # priority SHOULD be tried in an order defined by the weight field. # The range is 0-65535. Note that it is not widely implemented and # should be set to zero. attr_reader :priority # A server selection mechanism. # # The weight field specifies a relative weight for entries with the # same priority. Larger weights SHOULD be given a proportionately # higher probability of being selected. The range of this number is # 0-65535. Domain administrators SHOULD use Weight 0 when there # isn't any server selection to do, to make the RR easier to read # for humans (less noisy). Note that it is not widely implemented # and should be set to zero. attr_reader :weight # The port on this target host of this service. # # The range is 0-65535. attr_reader :port # The domain name of the target host. # # A target of "." means that the service is decidedly not available # at this domain. attr_reader :target def encode_rdata(msg) # :nodoc: msg.put_pack("n", @priority) msg.put_pack("n", @weight) msg.put_pack("n", @port) msg.put_name(@target) end def self.decode_rdata(msg) # :nodoc: priority, = msg.get_unpack("n") weight, = msg.get_unpack("n") port, = msg.get_unpack("n") target = msg.get_name return self.new(priority, weight, port, target) end end end end end ## # A Resolv::DNS IPv4 address. class IPv4 ## # Regular expression IPv4 addresses must match. Regex256 = /0 |1(?:[0-9][0-9]?)? |2(?:[0-4][0-9]?|5[0-5]?|[6-9])? |[3-9][0-9]?/x Regex = /\A(#{Regex256})\.(#{Regex256})\.(#{Regex256})\.(#{Regex256})\z/ def self.create(arg) case arg when IPv4 return arg when Regex if (0..255) === (a = $1.to_i) && (0..255) === (b = $2.to_i) && (0..255) === (c = $3.to_i) && (0..255) === (d = $4.to_i) return self.new([a, b, c, d].pack("CCCC")) else raise ArgumentError.new("IPv4 address with invalid value: " + arg) end else raise ArgumentError.new("cannot interpret as IPv4 address: #{arg.inspect}") end end def initialize(address) # :nodoc: unless address.kind_of?(String) raise ArgumentError, 'IPv4 address must be a string' end unless address.length == 4 raise ArgumentError, "IPv4 address expects 4 bytes but #{address.length} bytes" end @address = address end ## # A String representation of this IPv4 address. ## # The raw IPv4 address as a String. attr_reader :address def to_s # :nodoc: return sprintf("%d.%d.%d.%d", *@address.unpack("CCCC")) end def inspect # :nodoc: return "#<#{self.class} #{self}>" end ## # Turns this IPv4 address into a Resolv::DNS::Name. def to_name return DNS::Name.create( '%d.%d.%d.%d.in-addr.arpa.' % @address.unpack('CCCC').reverse) end def ==(other) # :nodoc: return @address == other.address end def eql?(other) # :nodoc: return self == other end def hash # :nodoc: return @address.hash end end ## # A Resolv::DNS IPv6 address. class IPv6 ## # IPv6 address format a:b:c:d:e:f:g:h Regex_8Hex = /\A (?:[0-9A-Fa-f]{1,4}:){7} [0-9A-Fa-f]{1,4} \z/x ## # Compressed IPv6 address format a::b Regex_CompressedHex = /\A ((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?) :: ((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?) \z/x ## # IPv4 mapped IPv6 address format a:b:c:d:e:f:w.x.y.z Regex_6Hex4Dec = /\A ((?:[0-9A-Fa-f]{1,4}:){6,6}) (\d+)\.(\d+)\.(\d+)\.(\d+) \z/x ## # Compressed IPv4 mapped IPv6 address format a::b:w.x.y.z Regex_CompressedHex4Dec = /\A ((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?) :: ((?:[0-9A-Fa-f]{1,4}:)*) (\d+)\.(\d+)\.(\d+)\.(\d+) \z/x ## # A composite IPv6 address Regexp. Regex = / (?:#{Regex_8Hex}) | (?:#{Regex_CompressedHex}) | (?:#{Regex_6Hex4Dec}) | (?:#{Regex_CompressedHex4Dec})/x ## # Creates a new IPv6 address from +arg+ which may be: # # IPv6:: returns +arg+. # String:: +arg+ must match one of the IPv6::Regex* constants def self.create(arg) case arg when IPv6 return arg when String address = '' if Regex_8Hex =~ arg arg.scan(/[0-9A-Fa-f]+/) {|hex| address << [hex.hex].pack('n')} elsif Regex_CompressedHex =~ arg prefix = $1 suffix = $2 a1 = '' a2 = '' prefix.scan(/[0-9A-Fa-f]+/) {|hex| a1 << [hex.hex].pack('n')} suffix.scan(/[0-9A-Fa-f]+/) {|hex| a2 << [hex.hex].pack('n')} omitlen = 16 - a1.length - a2.length address << a1 << "\0" * omitlen << a2 elsif Regex_6Hex4Dec =~ arg prefix, a, b, c, d = $1, $2.to_i, $3.to_i, $4.to_i, $5.to_i if (0..255) === a && (0..255) === b && (0..255) === c && (0..255) === d prefix.scan(/[0-9A-Fa-f]+/) {|hex| address << [hex.hex].pack('n')} address << [a, b, c, d].pack('CCCC') else raise ArgumentError.new("not numeric IPv6 address: " + arg) end elsif Regex_CompressedHex4Dec =~ arg prefix, suffix, a, b, c, d = $1, $2, $3.to_i, $4.to_i, $5.to_i, $6.to_i if (0..255) === a && (0..255) === b && (0..255) === c && (0..255) === d a1 = '' a2 = '' prefix.scan(/[0-9A-Fa-f]+/) {|hex| a1 << [hex.hex].pack('n')} suffix.scan(/[0-9A-Fa-f]+/) {|hex| a2 << [hex.hex].pack('n')} omitlen = 12 - a1.length - a2.length address << a1 << "\0" * omitlen << a2 << [a, b, c, d].pack('CCCC') else raise ArgumentError.new("not numeric IPv6 address: " + arg) end else raise ArgumentError.new("not numeric IPv6 address: " + arg) end return IPv6.new(address) else raise ArgumentError.new("cannot interpret as IPv6 address: #{arg.inspect}") end end def initialize(address) # :nodoc: unless address.kind_of?(String) && address.length == 16 raise ArgumentError.new('IPv6 address must be 16 bytes') end @address = address end ## # The raw IPv6 address as a String. attr_reader :address def to_s # :nodoc: address = sprintf("%X:%X:%X:%X:%X:%X:%X:%X", *@address.unpack("nnnnnnnn")) unless address.sub!(/(^|:)0(:0)+(:|$)/, '::') address.sub!(/(^|:)0(:|$)/, '::') end return address end def inspect # :nodoc: return "#<#{self.class} #{self}>" end ## # Turns this IPv6 address into a Resolv::DNS::Name. #-- # ip6.arpa should be searched too. [RFC3152] def to_name return DNS::Name.new( @address.unpack("H32")[0].split(//).reverse + ['ip6', 'arpa']) end def ==(other) # :nodoc: return @address == other.address end def eql?(other) # :nodoc: return self == other end def hash # :nodoc: return @address.hash end end ## # Resolv::MDNS is a one-shot Multicast DNS (mDNS) resolver. It blindly # makes queries to the mDNS addresses without understanding anything about # multicast ports. # # Information taken form the following places: # # * RFC 6762 class MDNS < DNS ## # Default mDNS Port Port = 5353 ## # Default IPv4 mDNS address AddressV4 = '224.0.0.251' ## # Default IPv6 mDNS address AddressV6 = 'ff02::fb' ## # Default mDNS addresses Addresses = [ [AddressV4, Port], [AddressV6, Port], ] ## # Creates a new one-shot Multicast DNS (mDNS) resolver. # # +config_info+ can be: # # nil:: # Uses the default mDNS addresses # # Hash:: # Must contain :nameserver or :nameserver_port like # Resolv::DNS#initialize. def initialize(config_info=nil) if config_info then super({ nameserver_port: Addresses }.merge(config_info)) else super(nameserver_port: Addresses) end end ## # Iterates over all IP addresses for +name+ retrieved from the mDNS # resolver, provided name ends with "local". If the name does not end in # "local" no records will be returned. # # +name+ can be a Resolv::DNS::Name or a String. Retrieved addresses will # be a Resolv::IPv4 or Resolv::IPv6 def each_address(name) name = Resolv::DNS::Name.create(name) return unless name.to_a.last == 'local' super(name) end def make_udp_requester # :nodoc: nameserver_port = @config.nameserver_port Requester::MDNSOneShot.new(*nameserver_port) end end module LOC ## # A Resolv::LOC::Size class Size Regex = /^(\d+\.*\d*)[m]$/ ## # Creates a new LOC::Size from +arg+ which may be: # # LOC::Size:: returns +arg+. # String:: +arg+ must match the LOC::Size::Regex constant def self.create(arg) case arg when Size return arg when String scalar = '' if Regex =~ arg scalar = [(($1.to_f*(1e2)).to_i.to_s[0].to_i*(2**4)+(($1.to_f*(1e2)).to_i.to_s.length-1))].pack("C") else raise ArgumentError.new("not a properly formed Size string: " + arg) end return Size.new(scalar) else raise ArgumentError.new("cannot interpret as Size: #{arg.inspect}") end end def initialize(scalar) @scalar = scalar end ## # The raw size attr_reader :scalar def to_s # :nodoc: s = @scalar.unpack("H2").join.to_s return ((s[0].to_i)*(10**(s[1].to_i-2))).to_s << "m" end def inspect # :nodoc: return "#<#{self.class} #{self}>" end def ==(other) # :nodoc: return @scalar == other.scalar end def eql?(other) # :nodoc: return self == other end def hash # :nodoc: return @scalar.hash end end ## # A Resolv::LOC::Coord class Coord Regex = /^(\d+)\s(\d+)\s(\d+\.\d+)\s([NESW])$/ ## # Creates a new LOC::Coord from +arg+ which may be: # # LOC::Coord:: returns +arg+. # String:: +arg+ must match the LOC::Coord::Regex constant def self.create(arg) case arg when Coord return arg when String coordinates = '' if Regex =~ arg && $1<180 hemi = ($4[/([NE])/,1]) || ($4[/([SW])/,1]) ? 1 : -1 coordinates = [(($1.to_i*(36e5))+($2.to_i*(6e4))+($3.to_f*(1e3)))*hemi+(2**31)].pack("N") (orientation ||= '') << $4[[/NS/],1] ? 'lat' : 'lon' else raise ArgumentError.new("not a properly formed Coord string: " + arg) end return Coord.new(coordinates,orientation) else raise ArgumentError.new("cannot interpret as Coord: #{arg.inspect}") end end def initialize(coordinates,orientation) unless coordinates.kind_of?(String) raise ArgumentError.new("Coord must be a 32bit unsigned integer in hex format: #{coordinates.inspect}") end unless orientation.kind_of?(String) && orientation[/^lon$|^lat$/] raise ArgumentError.new('Coord expects orientation to be a String argument of "lat" or "lon"') end @coordinates = coordinates @orientation = orientation end ## # The raw coordinates attr_reader :coordinates ## The orientation of the hemisphere as 'lat' or 'lon' attr_reader :orientation def to_s # :nodoc: c = @coordinates.unpack("N").join.to_i val = (c - (2**31)).abs fracsecs = (val % 1e3).to_i.to_s val = val / 1e3 secs = (val % 60).to_i.to_s val = val / 60 mins = (val % 60).to_i.to_s degs = (val / 60).to_i.to_s posi = (c >= 2**31) case posi when true hemi = @orientation[/^lat$/] ? "N" : "E" else hemi = @orientation[/^lon$/] ? "W" : "S" end return degs << " " << mins << " " << secs << "." << fracsecs << " " << hemi end def inspect # :nodoc: return "#<#{self.class} #{self}>" end def ==(other) # :nodoc: return @coordinates == other.coordinates end def eql?(other) # :nodoc: return self == other end def hash # :nodoc: return @coordinates.hash end end ## # A Resolv::LOC::Alt class Alt Regex = /^([+-]*\d+\.*\d*)[m]$/ ## # Creates a new LOC::Alt from +arg+ which may be: # # LOC::Alt:: returns +arg+. # String:: +arg+ must match the LOC::Alt::Regex constant def self.create(arg) case arg when Alt return arg when String altitude = '' if Regex =~ arg altitude = [($1.to_f*(1e2))+(1e7)].pack("N") else raise ArgumentError.new("not a properly formed Alt string: " + arg) end return Alt.new(altitude) else raise ArgumentError.new("cannot interpret as Alt: #{arg.inspect}") end end def initialize(altitude) @altitude = altitude end ## # The raw altitude attr_reader :altitude def to_s # :nodoc: a = @altitude.unpack("N").join.to_i return ((a.to_f/1e2)-1e5).to_s + "m" end def inspect # :nodoc: return "#<#{self.class} #{self}>" end def ==(other) # :nodoc: return @altitude == other.altitude end def eql?(other) # :nodoc: return self == other end def hash # :nodoc: return @altitude.hash end end end ## # Default resolver to use for Resolv class methods. DefaultResolver = self.new ## # Replaces the resolvers in the default resolver with +new_resolvers+. This # allows resolvers to be changed for resolv-replace. def DefaultResolver.replace_resolvers new_resolvers @resolvers = new_resolvers end ## # Address Regexp to use for matching IP addresses. AddressRegex = /(?:#{IPv4::Regex})|(?:#{IPv6::Regex})/ end PK! q_J_J 2.2.0/mkmf.rbnu[# -*- coding: us-ascii -*- # module to create Makefile for extension modules # invoke like: ruby -r mkmf extconf.rb require 'rbconfig' require 'fileutils' require 'shellwords' # :stopdoc: class String # Wraps a string in escaped quotes if it contains whitespace. def quote /\s/ =~ self ? "\"#{self}\"" : "#{self}" end # Escape whitespaces for Makefile. def unspace gsub(/\s/, '\\\\\\&') end # Generates a string used as cpp macro name. def tr_cpp strip.upcase.tr_s("^A-Z0-9_*", "_").tr_s("*", "P") end def funcall_style /\)\z/ =~ self ? dup : "#{self}()" end def sans_arguments self[/\A[^()]+/] end end class Array # Wraps all strings in escaped quotes if they contain whitespace. def quote map {|s| s.quote} end end # :startdoc: ## # mkmf.rb is used by Ruby C extensions to generate a Makefile which will # correctly compile and link the C extension to Ruby and a third-party # library. module MakeMakefile #### defer until this module become global-state free. # def self.extended(obj) # obj.init_mkmf # super # end # # def initialize(*args, rbconfig: RbConfig, **rest) # init_mkmf(rbconfig::MAKEFILE_CONFIG, rbconfig::CONFIG) # super(*args, **rest) # end ## # The makefile configuration using the defaults from when Ruby was built. CONFIG = RbConfig::MAKEFILE_CONFIG ORIG_LIBPATH = ENV['LIB'] ## # Extensions for files compiled with a C compiler C_EXT = %w[c m] ## # Extensions for files complied with a C++ compiler CXX_EXT = %w[cc mm cxx cpp] unless File.exist?(File.join(*File.split(__FILE__).tap {|d, b| b.swapcase})) CXX_EXT.concat(%w[C]) end ## # Extensions for source files SRC_EXT = C_EXT + CXX_EXT ## # Extensions for header files HDR_EXT = %w[h hpp] $static = nil $config_h = '$(arch_hdrdir)/ruby/config.h' $default_static = $static unless defined? $configure_args $configure_args = {} args = CONFIG["configure_args"] if ENV["CONFIGURE_ARGS"] args << " " << ENV["CONFIGURE_ARGS"] end for arg in Shellwords::shellwords(args) arg, val = arg.split('=', 2) next unless arg arg.tr!('_', '-') if arg.sub!(/^(?!--)/, '--') val or next arg.downcase! end next if /^--(?:top|topsrc|src|cur)dir$/ =~ arg $configure_args[arg] = val || true end for arg in ARGV arg, val = arg.split('=', 2) next unless arg arg.tr!('_', '-') if arg.sub!(/^(?!--)/, '--') val or next arg.downcase! end $configure_args[arg] = val || true end end $libdir = CONFIG["libdir"] $rubylibdir = CONFIG["rubylibdir"] $archdir = CONFIG["archdir"] $sitedir = CONFIG["sitedir"] $sitelibdir = CONFIG["sitelibdir"] $sitearchdir = CONFIG["sitearchdir"] $vendordir = CONFIG["vendordir"] $vendorlibdir = CONFIG["vendorlibdir"] $vendorarchdir = CONFIG["vendorarchdir"] $mswin = /mswin/ =~ RUBY_PLATFORM $bccwin = /bccwin/ =~ RUBY_PLATFORM $mingw = /mingw/ =~ RUBY_PLATFORM $cygwin = /cygwin/ =~ RUBY_PLATFORM $netbsd = /netbsd/ =~ RUBY_PLATFORM $os2 = /os2/ =~ RUBY_PLATFORM $beos = /beos/ =~ RUBY_PLATFORM $haiku = /haiku/ =~ RUBY_PLATFORM $solaris = /solaris/ =~ RUBY_PLATFORM $universal = /universal/ =~ RUBY_PLATFORM $dest_prefix_pattern = (File::PATH_SEPARATOR == ';' ? /\A([[:alpha:]]:)?/ : /\A/) # :stopdoc: def config_string(key, config = CONFIG) s = config[key] and !s.empty? and block_given? ? yield(s) : s end module_function :config_string def dir_re(dir) Regexp.new('\$(?:\('+dir+'\)|\{'+dir+'\})(?:\$(?:\(target_prefix\)|\{target_prefix\}))?') end module_function :dir_re def relative_from(path, base) dir = File.join(path, "") if File.expand_path(dir) == File.expand_path(dir, base) path else File.join(base, path) end end INSTALL_DIRS = [ [dir_re('commondir'), "$(RUBYCOMMONDIR)"], [dir_re('sitedir'), "$(RUBYCOMMONDIR)"], [dir_re('vendordir'), "$(RUBYCOMMONDIR)"], [dir_re('rubylibdir'), "$(RUBYLIBDIR)"], [dir_re('archdir'), "$(RUBYARCHDIR)"], [dir_re('sitelibdir'), "$(RUBYLIBDIR)"], [dir_re('vendorlibdir'), "$(RUBYLIBDIR)"], [dir_re('sitearchdir'), "$(RUBYARCHDIR)"], [dir_re('vendorarchdir'), "$(RUBYARCHDIR)"], [dir_re('rubyhdrdir'), "$(RUBYHDRDIR)"], [dir_re('sitehdrdir'), "$(SITEHDRDIR)"], [dir_re('vendorhdrdir'), "$(VENDORHDRDIR)"], [dir_re('bindir'), "$(BINDIR)"], ] def install_dirs(target_prefix = nil) if $extout dirs = [ ['BINDIR', '$(extout)/bin'], ['RUBYCOMMONDIR', '$(extout)/common'], ['RUBYLIBDIR', '$(RUBYCOMMONDIR)$(target_prefix)'], ['RUBYARCHDIR', '$(extout)/$(arch)$(target_prefix)'], ['HDRDIR', '$(extout)/include/ruby$(target_prefix)'], ['ARCHHDRDIR', '$(extout)/include/$(arch)/ruby$(target_prefix)'], ['extout', "#$extout"], ['extout_prefix', "#$extout_prefix"], ] elsif $extmk dirs = [ ['BINDIR', '$(bindir)'], ['RUBYCOMMONDIR', '$(rubylibdir)'], ['RUBYLIBDIR', '$(rubylibdir)$(target_prefix)'], ['RUBYARCHDIR', '$(archdir)$(target_prefix)'], ['HDRDIR', '$(rubyhdrdir)/ruby$(target_prefix)'], ['ARCHHDRDIR', '$(rubyhdrdir)/$(arch)/ruby$(target_prefix)'], ] elsif $configure_args.has_key?('--vendor') dirs = [ ['BINDIR', '$(bindir)'], ['RUBYCOMMONDIR', '$(vendordir)$(target_prefix)'], ['RUBYLIBDIR', '$(vendorlibdir)$(target_prefix)'], ['RUBYARCHDIR', '$(vendorarchdir)$(target_prefix)'], ['HDRDIR', '$(rubyhdrdir)/ruby$(target_prefix)'], ['ARCHHDRDIR', '$(rubyhdrdir)/$(arch)/ruby$(target_prefix)'], ] else dirs = [ ['BINDIR', '$(bindir)'], ['RUBYCOMMONDIR', '$(sitedir)$(target_prefix)'], ['RUBYLIBDIR', '$(sitelibdir)$(target_prefix)'], ['RUBYARCHDIR', '$(sitearchdir)$(target_prefix)'], ['HDRDIR', '$(rubyhdrdir)/ruby$(target_prefix)'], ['ARCHHDRDIR', '$(rubyhdrdir)/$(arch)/ruby$(target_prefix)'], ] end dirs << ['target_prefix', (target_prefix ? "/#{target_prefix}" : "")] dirs end def map_dir(dir, map = nil) map ||= INSTALL_DIRS map.inject(dir) {|d, (orig, new)| d.gsub(orig, new)} end topdir = File.dirname(File.dirname(__FILE__)) path = File.expand_path($0) until (dir = File.dirname(path)) == path if File.identical?(dir, topdir) $extmk = true if %r"\A(?:ext|enc|tool|test)\z" =~ File.basename(path) break end path = dir end $extmk ||= false if not $extmk and File.exist?(($hdrdir = RbConfig::CONFIG["rubyhdrdir"]) + "/ruby/ruby.h") $topdir = $hdrdir $top_srcdir = $hdrdir $arch_hdrdir = RbConfig::CONFIG["rubyarchhdrdir"] elsif File.exist?(($hdrdir = ($top_srcdir ||= topdir) + "/include") + "/ruby.h") $topdir ||= RbConfig::CONFIG["topdir"] $arch_hdrdir = "$(extout)/include/$(arch)" else abort "mkmf.rb can't find header files for ruby at #{$hdrdir}/ruby.h" end CONFTEST = "conftest".freeze CONFTEST_C = "#{CONFTEST}.c" OUTFLAG = CONFIG['OUTFLAG'] COUTFLAG = CONFIG['COUTFLAG'] CPPOUTFILE = config_string('CPPOUTFILE') {|str| str.sub(/\bconftest\b/, CONFTEST)} def rm_f(*files) opt = (Hash === files.last ? [files.pop] : []) FileUtils.rm_f(Dir[*files.flatten], *opt) end module_function :rm_f def rm_rf(*files) opt = (Hash === files.last ? [files.pop] : []) FileUtils.rm_rf(Dir[*files.flatten], *opt) end module_function :rm_rf # Returns time stamp of the +target+ file if it exists and is newer than or # equal to all of +times+. def modified?(target, times) (t = File.mtime(target)) rescue return nil Array === times or times = [times] t if times.all? {|n| n <= t} end def split_libs(*strs) strs.map {|s| s.split(/\s+(?=-|\z)/)}.flatten end def merge_libs(*libs) libs.inject([]) do |x, y| y = y.inject([]) {|ary, e| ary.last == e ? ary : ary << e} y.each_with_index do |v, yi| if xi = x.rindex(v) x[(xi+1)..-1] = merge_libs(y[(yi+1)..-1], x[(xi+1)..-1]) x[xi, 0] = y[0...yi] break end end and x.concat(y) x end end # This is a custom logging module. It generates an mkmf.log file when you # run your extconf.rb script. This can be useful for debugging unexpected # failures. # # This module and its associated methods are meant for internal use only. # module Logging @log = nil @logfile = 'mkmf.log' @orgerr = $stderr.dup @orgout = $stdout.dup @postpone = 0 @quiet = $extmk def self::log_open @log ||= File::open(@logfile, 'wb') @log.sync = true end def self::log_opened? @log and not @log.closed? end def self::open log_open $stderr.reopen(@log) $stdout.reopen(@log) yield ensure $stderr.reopen(@orgerr) $stdout.reopen(@orgout) end def self::message(*s) log_open @log.printf(*s) end def self::logfile file @logfile = file log_close end def self::log_close if @log and not @log.closed? @log.flush @log.close @log = nil end end def self::postpone tmplog = "mkmftmp#{@postpone += 1}.log" open do log, *save = @log, @logfile, @orgout, @orgerr @log, @logfile, @orgout, @orgerr = nil, tmplog, log, log begin log.print(open {yield @log}) ensure @log.close if @log and not @log.closed? File::open(tmplog) {|t| FileUtils.copy_stream(t, log)} if File.exist?(tmplog) @log, @logfile, @orgout, @orgerr = log, *save @postpone -= 1 MakeMakefile.rm_f tmplog end end end class << self attr_accessor :quiet end end def libpath_env # used only if native compiling if libpathenv = config_string("LIBPATHENV") pathenv = ENV[libpathenv] libpath = RbConfig.expand($DEFLIBPATH.join(File::PATH_SEPARATOR)) {libpathenv => [libpath, pathenv].compact.join(File::PATH_SEPARATOR)} else {} end end def xsystem command, opts = nil varpat = /\$\((\w+)\)|\$\{(\w+)\}/ if varpat =~ command vars = Hash.new {|h, k| h[k] = ENV[k]} command = command.dup nil while command.gsub!(varpat) {vars[$1||$2]} end Logging::open do puts command.quote if opts and opts[:werror] result = nil Logging.postpone do |log| result = (system(libpath_env, command) and File.zero?(log.path)) "" end result else system(libpath_env, command) end end end def xpopen command, *mode, &block Logging::open do case mode[0] when nil, /^r/ puts "#{command} |" else puts "| #{command}" end IO.popen(libpath_env, command, *mode, &block) end end def log_src(src, heading="checked program was") src = src.split(/^/) fmt = "%#{src.size.to_s.size}d: %s" Logging::message <<"EOM" #{heading}: /* begin */ EOM src.each_with_index {|line, no| Logging::message fmt, no+1, line} Logging::message <<"EOM" /* end */ EOM end def create_tmpsrc(src) src = "#{COMMON_HEADERS}\n#{src}" src = yield(src) if block_given? src.gsub!(/[ \t]+$/, '') src.gsub!(/\A\n+|^\n+$/, '') src.sub!(/[^\n]\z/, "\\&\n") count = 0 begin open(CONFTEST_C, "wb") do |cfile| cfile.print src end rescue Errno::EACCES if (count += 1) < 5 sleep 0.2 retry end end src end def have_devel? unless defined? $have_devel $have_devel = true $have_devel = try_link(MAIN_DOES_NOTHING) end $have_devel end def try_do(src, command, *opts, &b) unless have_devel? raise < $hdrdir.quote, 'src' => "#{CONFTEST_C}", 'arch_hdrdir' => $arch_hdrdir.quote, 'top_srcdir' => $top_srcdir.quote, 'INCFLAGS' => "#$INCFLAGS", 'CPPFLAGS' => "#$CPPFLAGS", 'CFLAGS' => "#$CFLAGS", 'ARCH_FLAG' => "#$ARCH_FLAG", 'LDFLAGS' => "#$LDFLAGS #{ldflags}", 'LOCAL_LIBS' => "#$LOCAL_LIBS #$libs", 'LIBS' => "#{librubyarg} #{opt} #$LIBS") conf['LIBPATH'] = libpathflag(libpath.map {|s| RbConfig::expand(s.dup, conf)}) RbConfig::expand(TRY_LINK.dup, conf) end def cc_command(opt="") conf = RbConfig::CONFIG.merge('hdrdir' => $hdrdir.quote, 'srcdir' => $srcdir.quote, 'arch_hdrdir' => $arch_hdrdir.quote, 'top_srcdir' => $top_srcdir.quote) RbConfig::expand("$(CC) #$INCFLAGS #$CPPFLAGS #$CFLAGS #$ARCH_FLAG #{opt} -c #{CONFTEST_C}", conf) end def cpp_command(outfile, opt="") conf = RbConfig::CONFIG.merge('hdrdir' => $hdrdir.quote, 'srcdir' => $srcdir.quote, 'arch_hdrdir' => $arch_hdrdir.quote, 'top_srcdir' => $top_srcdir.quote) if $universal and (arch_flag = conf['ARCH_FLAG']) and !arch_flag.empty? conf['ARCH_FLAG'] = arch_flag.gsub(/(?:\G|\s)-arch\s+\S+/, '') end RbConfig::expand("$(CPP) #$INCFLAGS #$CPPFLAGS #$CFLAGS #{opt} #{CONFTEST_C} #{outfile}", conf) end def libpathflag(libpath=$LIBPATH|$DEFLIBPATH) libpath.map{|x| case x when "$(topdir)", /\A\./ LIBPATHFLAG else LIBPATHFLAG+RPATHFLAG end % x.quote }.join end def with_werror(opt, opts = nil) if opts if opts[:werror] and config_string("WERRORFLAG") {|flag| opt = opt ? "#{opt} #{flag}" : flag} (opts = opts.dup).delete(:werror) end yield(opt, opts) else yield(opt) end end def try_link0(src, opt="", *opts, &b) # :nodoc: cmd = link_command("", opt) if $universal require 'tmpdir' Dir.mktmpdir("mkmf_", oldtmpdir = ENV["TMPDIR"]) do |tmpdir| begin ENV["TMPDIR"] = tmpdir try_do(src, cmd, *opts, &b) ensure ENV["TMPDIR"] = oldtmpdir end end else try_do(src, cmd, *opts, &b) end and begin st = File.stat(CONFTEST+$EXEEXT) st.file? and st.executable? end end # Returns whether or not the +src+ can be compiled as a C source and linked # with its depending libraries successfully. +opt+ is passed to the linker # as options. Note that +$CFLAGS+ and +$LDFLAGS+ are also passed to the # linker. # # If a block given, it is called with the source before compilation. You can # modify the source in the block. # # [+src+] a String which contains a C source # [+opt+] a String which contains linker options def try_link(src, opt="", *opts, &b) try_link0(src, opt, *opts, &b) ensure MakeMakefile.rm_f "#{CONFTEST}*", "c0x32*" end # Returns whether or not the +src+ can be compiled as a C source. +opt+ is # passed to the C compiler as options. Note that +$CFLAGS+ is also passed to # the compiler. # # If a block given, it is called with the source before compilation. You can # modify the source in the block. # # [+src+] a String which contains a C source # [+opt+] a String which contains compiler options def try_compile(src, opt="", *opts, &b) with_werror(opt, *opts) {|_opt, *_opts| try_do(src, cc_command(_opt), *_opts, &b)} and File.file?("#{CONFTEST}.#{$OBJEXT}") ensure MakeMakefile.rm_f "#{CONFTEST}*" end # Returns whether or not the +src+ can be preprocessed with the C # preprocessor. +opt+ is passed to the preprocessor as options. Note that # +$CFLAGS+ is also passed to the preprocessor. # # If a block given, it is called with the source before preprocessing. You # can modify the source in the block. # # [+src+] a String which contains a C source # [+opt+] a String which contains preprocessor options def try_cpp(src, opt="", *opts, &b) try_do(src, cpp_command(CPPOUTFILE, opt), *opts, &b) and File.file?("#{CONFTEST}.i") ensure MakeMakefile.rm_f "#{CONFTEST}*" end alias_method :try_header, (config_string('try_header') || :try_cpp) def cpp_include(header) if header header = [header] unless header.kind_of? Array header.map {|h| String === h ? "#include <#{h}>\n" : h}.join else "" end end def with_cppflags(flags) cppflags = $CPPFLAGS $CPPFLAGS = flags ret = yield ensure $CPPFLAGS = cppflags unless ret end def try_cppflags(flags) try_header(MAIN_DOES_NOTHING, flags) end def with_cflags(flags) cflags = $CFLAGS $CFLAGS = flags ret = yield ensure $CFLAGS = cflags unless ret end def try_cflags(flags) try_compile(MAIN_DOES_NOTHING, flags) end def with_ldflags(flags) ldflags = $LDFLAGS $LDFLAGS = flags ret = yield ensure $LDFLAGS = ldflags unless ret end def try_ldflags(flags) try_link(MAIN_DOES_NOTHING, flags) end def try_static_assert(expr, headers = nil, opt = "", &b) headers = cpp_include(headers) try_compile(< 0", headers, opt) # positive constant elsif try_static_assert("#{const} == 0", headers, opt) return 0 else # not a constant return nil end upper = 1 until try_static_assert("#{const} <= #{upper}", headers, opt) lower = upper upper <<= 1 end return nil unless lower while upper > lower + 1 mid = (upper + lower) / 2 if try_static_assert("#{const} > #{mid}", headers, opt) lower = mid else upper = mid end end upper = -upper if neg return upper else src = %{#{includes} #include /*top*/ typedef#{neg ? '' : ' unsigned'} #ifdef PRI_LL_PREFIX #define PRI_CONFTEST_PREFIX PRI_LL_PREFIX LONG_LONG #else #define PRI_CONFTEST_PREFIX "l" long #endif conftest_type; conftest_type conftest_const = (conftest_type)(#{const}); int main() {printf("%"PRI_CONFTEST_PREFIX"#{neg ? 'd' : 'u'}\\n", conftest_const); return 0;} } begin if try_link0(src, opt, &b) xpopen("./#{CONFTEST}") do |f| return Integer(f.gets) end end ensure MakeMakefile.rm_f "#{CONFTEST}*" end end nil end # You should use +have_func+ rather than +try_func+. # # [+func+] a String which contains a symbol name # [+libs+] a String which contains library names. # [+headers+] a String or an Array of strings which contains names of header # files. def try_func(func, libs, headers = nil, opt = "", &b) headers = cpp_include(headers) case func when /^&/ decltype = proc {|x|"const volatile void *#{x}"} when /\)$/ call = func else call = "#{func}()" decltype = proc {|x| "void ((*#{x})())"} end if opt and !opt.empty? [[:to_str], [:join, " "], [:to_s]].each do |meth, *args| if opt.respond_to?(meth) break opt = opt.send(meth, *args) end end opt = "#{opt} #{libs}" else opt = libs end decltype && try_link(<<"SRC", opt, &b) or #{headers} /*top*/ extern int t(void); #{MAIN_DOES_NOTHING 't'} int t(void) { #{decltype["volatile p"]}; p = (#{decltype[]})#{func}; return 0; } SRC call && try_link(<<"SRC", opt, &b) #{headers} /*top*/ extern int t(void); #{MAIN_DOES_NOTHING 't'} int t(void) { #{call}; return 0; } SRC end # You should use +have_var+ rather than +try_var+. def try_var(var, headers = nil, opt = "", &b) headers = cpp_include(headers) try_compile(<<"SRC", opt, &b) #{headers} /*top*/ extern int t(void); #{MAIN_DOES_NOTHING 't'} int t(void) { const volatile void *volatile p; p = &(&#{var})[0]; return 0; } SRC end # Returns whether or not the +src+ can be preprocessed with the C # preprocessor and matches with +pat+. # # If a block given, it is called with the source before compilation. You can # modify the source in the block. # # [+pat+] a Regexp or a String # [+src+] a String which contains a C source # [+opt+] a String which contains preprocessor options # # NOTE: When pat is a Regexp the matching will be checked in process, # otherwise egrep(1) will be invoked to check it. def egrep_cpp(pat, src, opt = "", &b) src = create_tmpsrc(src, &b) xpopen(cpp_command('', opt)) do |f| if Regexp === pat puts(" ruby -ne 'print if #{pat.inspect}'") f.grep(pat) {|l| puts "#{f.lineno}: #{l}" return true } false else puts(" egrep '#{pat}'") begin stdin = $stdin.dup $stdin.reopen(f) system("egrep", pat) ensure $stdin.reopen(stdin) end end end ensure MakeMakefile.rm_f "#{CONFTEST}*" log_src(src) end # This is used internally by the have_macro? method. def macro_defined?(macro, src, opt = "", &b) src = src.sub(/[^\n]\z/, "\\&\n") try_compile(src + <<"SRC", opt, &b) /*top*/ #ifndef #{macro} # error |:/ === #{macro} undefined === /:| #endif SRC end # Returns whether or not: # * the +src+ can be compiled as a C source, # * the result object can be linked with its depending libraries # successfully, # * the linked file can be invoked as an executable # * and the executable exits successfully # # +opt+ is passed to the linker as options. Note that +$CFLAGS+ and # +$LDFLAGS+ are also passed to the linker. # # If a block given, it is called with the source before compilation. You can # modify the source in the block. # # [+src+] a String which contains a C source # [+opt+] a String which contains linker options # # Returns true when the executable exits successfully, false when it fails, # or nil when preprocessing, compilation or link fails. def try_run(src, opt = "", &b) raise "cannot run test program while cross compiling" if CROSS_COMPILING if try_link0(src, opt, &b) xsystem("./#{CONFTEST}") else nil end ensure MakeMakefile.rm_f "#{CONFTEST}*" end def install_files(mfile, ifiles, map = nil, srcprefix = nil) ifiles or return ifiles.empty? and return srcprefix ||= "$(srcdir)/#{srcprefix}".chomp('/') RbConfig::expand(srcdir = srcprefix.dup) dirs = [] path = Hash.new {|h, i| h[i] = dirs.push([i])[-1]} ifiles.each do |files, dir, prefix| dir = map_dir(dir, map) prefix &&= %r|\A#{Regexp.quote(prefix)}/?| if /\A\.\// =~ files # install files which are in current working directory. files = files[2..-1] len = nil else # install files which are under the $(srcdir). files = File.join(srcdir, files) len = srcdir.size end f = nil Dir.glob(files) do |fx| f = fx f[0..len] = "" if len case File.basename(f) when *$NONINSTALLFILES next end d = File.dirname(f) d.sub!(prefix, "") if prefix d = (d.empty? || d == ".") ? dir : File.join(dir, d) f = File.join(srcprefix, f) if len path[d] << f end unless len or f d = File.dirname(files) d.sub!(prefix, "") if prefix d = (d.empty? || d == ".") ? dir : File.join(dir, d) path[d] << files end end dirs end def install_rb(mfile, dest, srcdir = nil) install_files(mfile, [["lib/**/*.rb", dest, "lib"]], nil, srcdir) end def append_library(libs, lib) # :no-doc: format(LIBARG, lib) + " " + libs end def message(*s) unless Logging.quiet and not $VERBOSE printf(*s) $stdout.flush end end # This emits a string to stdout that allows users to see the results of the # various have* and find* methods as they are tested. # # Internal use only. # def checking_for(m, fmt = nil) f = caller[0][/in `([^<].*)'$/, 1] and f << ": " #` for vim #' m = "checking #{/\Acheck/ =~ f ? '' : 'for '}#{m}... " message "%s", m a = r = nil Logging::postpone do r = yield a = (fmt ? "#{fmt % r}" : r ? "yes" : "no") << "\n" "#{f}#{m}-------------------- #{a}\n" end message(a) Logging::message "--------------------\n\n" r end def checking_message(target, place = nil, opt = nil) [["in", place], ["with", opt]].inject("#{target}") do |msg, (pre, noun)| if noun [[:to_str], [:join, ","], [:to_s]].each do |meth, *args| if noun.respond_to?(meth) break noun = noun.send(meth, *args) end end msg << " #{pre} #{noun}" unless noun.empty? end msg end end # :startdoc: # Returns whether or not +macro+ is defined either in the common header # files or within any +headers+ you provide. # # Any options you pass to +opt+ are passed along to the compiler. # def have_macro(macro, headers = nil, opt = "", &b) checking_for checking_message(macro, headers, opt) do macro_defined?(macro, cpp_include(headers), opt, &b) end end # Returns whether or not the given entry point +func+ can be found within # +lib+. If +func+ is +nil+, the main() entry point is used by # default. If found, it adds the library to list of libraries to be used # when linking your extension. # # If +headers+ are provided, it will include those header files as the # header files it looks in when searching for +func+. # # The real name of the library to be linked can be altered by # --with-FOOlib configuration option. # def have_library(lib, func = nil, headers = nil, opt = "", &b) func = "main" if !func or func.empty? lib = with_config(lib+'lib', lib) checking_for checking_message(func.funcall_style, LIBARG%lib, opt) do if COMMON_LIBS.include?(lib) true else libs = append_library($libs, lib) if try_func(func, libs, headers, opt, &b) $libs = libs true else false end end end end # Returns whether or not the entry point +func+ can be found within the # library +lib+ in one of the +paths+ specified, where +paths+ is an array # of strings. If +func+ is +nil+ , then the main() function is # used as the entry point. # # If +lib+ is found, then the path it was found on is added to the list of # library paths searched and linked against. # def find_library(lib, func, *paths, &b) func = "main" if !func or func.empty? lib = with_config(lib+'lib', lib) paths = paths.collect {|path| path.split(File::PATH_SEPARATOR)}.flatten checking_for checking_message(func.funcall_style, LIBARG%lib) do libpath = $LIBPATH libs = append_library($libs, lib) begin until r = try_func(func, libs, &b) or paths.empty? $LIBPATH = libpath | [paths.shift] end if r $libs = libs libpath = nil end ensure $LIBPATH = libpath if libpath end r end end # Returns whether or not the function +func+ can be found in the common # header files, or within any +headers+ that you provide. If found, a macro # is passed as a preprocessor constant to the compiler using the function # name, in uppercase, prepended with +HAVE_+. # # To check functions in an additional library, you need to check that # library first using have_library(). The +func+ shall be # either mere function name or function name with arguments. # # For example, if have_func('foo') returned +true+, then the # +HAVE_FOO+ preprocessor macro would be passed to the compiler. # def have_func(func, headers = nil, opt = "", &b) checking_for checking_message(func.funcall_style, headers, opt) do if try_func(func, $libs, headers, opt, &b) $defs << "-DHAVE_#{func.sans_arguments.tr_cpp}" true else false end end end # Returns whether or not the variable +var+ can be found in the common # header files, or within any +headers+ that you provide. If found, a macro # is passed as a preprocessor constant to the compiler using the variable # name, in uppercase, prepended with +HAVE_+. # # To check variables in an additional library, you need to check that # library first using have_library(). # # For example, if have_var('foo') returned true, then the # +HAVE_FOO+ preprocessor macro would be passed to the compiler. # def have_var(var, headers = nil, opt = "", &b) checking_for checking_message(var, headers, opt) do if try_var(var, headers, opt, &b) $defs.push(format("-DHAVE_%s", var.tr_cpp)) true else false end end end # Returns whether or not the given +header+ file can be found on your system. # If found, a macro is passed as a preprocessor constant to the compiler # using the header file name, in uppercase, prepended with +HAVE_+. # # For example, if have_header('foo.h') returned true, then the # +HAVE_FOO_H+ preprocessor macro would be passed to the compiler. # def have_header(header, preheaders = nil, opt = "", &b) checking_for header do if try_header(cpp_include(preheaders)+cpp_include(header), opt, &b) $defs.push(format("-DHAVE_%s", header.tr_cpp)) true else false end end end # Returns whether or not the given +framework+ can be found on your system. # If found, a macro is passed as a preprocessor constant to the compiler # using the framework name, in uppercase, prepended with +HAVE_FRAMEWORK_+. # # For example, if have_framework('Ruby') returned true, then # the +HAVE_FRAMEWORK_RUBY+ preprocessor macro would be passed to the # compiler. # # If +fw+ is a pair of the framework name and its header file name # that header file is checked, instead of the normally used header # file which is named same as the framework. def have_framework(fw, &b) if Array === fw fw, header = *fw else header = "#{fw}.h" end checking_for fw do src = cpp_include("#{fw}/#{header}") << "\n" "int main(void){return 0;}" opt = " -framework #{fw}" if try_link(src, opt, &b) or (objc = try_link(src, "-ObjC#{opt}", &b)) $defs.push(format("-DHAVE_FRAMEWORK_%s", fw.tr_cpp)) # TODO: non-worse way than this hack, to get rid of separating # option and its argument. $LDFLAGS << " -ObjC" if objc and /(\A|\s)-ObjC(\s|\z)/ !~ $LDFLAGS $LIBS << opt true else false end end end # Instructs mkmf to search for the given +header+ in any of the +paths+ # provided, and returns whether or not it was found in those paths. # # If the header is found then the path it was found on is added to the list # of included directories that are sent to the compiler (via the # -I switch). # def find_header(header, *paths) message = checking_message(header, paths) header = cpp_include(header) checking_for message do if try_header(header) true else found = false paths.each do |dir| opt = "-I#{dir}".quote if try_header(header, opt) $INCFLAGS << " " << opt found = true break end end found end end end # Returns whether or not the struct of type +type+ contains +member+. If # it does not, or the struct type can't be found, then false is returned. # You may optionally specify additional +headers+ in which to look for the # struct (in addition to the common header files). # # If found, a macro is passed as a preprocessor constant to the compiler # using the type name and the member name, in uppercase, prepended with # +HAVE_+. # # For example, if have_struct_member('struct foo', 'bar') # returned true, then the +HAVE_STRUCT_FOO_BAR+ preprocessor macro would be # passed to the compiler. # # +HAVE_ST_BAR+ is also defined for backward compatibility. # def have_struct_member(type, member, headers = nil, opt = "", &b) checking_for checking_message("#{type}.#{member}", headers) do if try_compile(<<"SRC", opt, &b) #{cpp_include(headers)} /*top*/ int s = (char *)&((#{type}*)0)->#{member} - (char *)0; #{MAIN_DOES_NOTHING} SRC $defs.push(format("-DHAVE_%s_%s", type.tr_cpp, member.tr_cpp)) $defs.push(format("-DHAVE_ST_%s", member.tr_cpp)) # backward compatibility true else false end end end # Returns whether or not the static type +type+ is defined. # # See also +have_type+ # def try_type(type, headers = nil, opt = "", &b) if try_compile(<<"SRC", opt, &b) #{cpp_include(headers)} /*top*/ typedef #{type} conftest_type; int conftestval[sizeof(conftest_type)?1:-1]; SRC $defs.push(format("-DHAVE_TYPE_%s", type.tr_cpp)) true else false end end # Returns whether or not the static type +type+ is defined. You may # optionally pass additional +headers+ to check against in addition to the # common header files. # # You may also pass additional flags to +opt+ which are then passed along to # the compiler. # # If found, a macro is passed as a preprocessor constant to the compiler # using the type name, in uppercase, prepended with +HAVE_TYPE_+. # # For example, if have_type('foo') returned true, then the # +HAVE_TYPE_FOO+ preprocessor macro would be passed to the compiler. # def have_type(type, headers = nil, opt = "", &b) checking_for checking_message(type, headers, opt) do try_type(type, headers, opt, &b) end end # Returns where the static type +type+ is defined. # # You may also pass additional flags to +opt+ which are then passed along to # the compiler. # # See also +have_type+. # def find_type(type, opt, *headers, &b) opt ||= "" fmt = "not found" def fmt.%(x) x ? x.respond_to?(:join) ? x.join(",") : x : self end checking_for checking_message(type, nil, opt), fmt do headers.find do |h| try_type(type, h, opt, &b) end end end # Returns whether or not the constant +const+ is defined. # # See also +have_const+ # def try_const(const, headers = nil, opt = "", &b) const, type = *const if try_compile(<<"SRC", opt, &b) #{cpp_include(headers)} /*top*/ typedef #{type || 'int'} conftest_type; conftest_type conftestval = #{type ? '' : '(int)'}#{const}; SRC $defs.push(format("-DHAVE_CONST_%s", const.tr_cpp)) true else false end end # Returns whether or not the constant +const+ is defined. You may # optionally pass the +type+ of +const+ as [const, type], # such as: # # have_const(%w[PTHREAD_MUTEX_INITIALIZER pthread_mutex_t], "pthread.h") # # You may also pass additional +headers+ to check against in addition to the # common header files, and additional flags to +opt+ which are then passed # along to the compiler. # # If found, a macro is passed as a preprocessor constant to the compiler # using the type name, in uppercase, prepended with +HAVE_CONST_+. # # For example, if have_const('foo') returned true, then the # +HAVE_CONST_FOO+ preprocessor macro would be passed to the compiler. # def have_const(const, headers = nil, opt = "", &b) checking_for checking_message([*const].compact.join(' '), headers, opt) do try_const(const, headers, opt, &b) end end # :stopdoc: STRING_OR_FAILED_FORMAT = "%s" def STRING_OR_FAILED_FORMAT.%(x) # :nodoc: x ? super : "failed" end def typedef_expr(type, headers) typename, member = type.split('.', 2) prelude = cpp_include(headers).split(/$/) prelude << "typedef #{typename} rbcv_typedef_;\n" return "rbcv_typedef_", member, prelude end def try_signedness(type, member, headers = nil, opts = nil) raise ArgumentError, "don't know how to tell signedness of members" if member if try_static_assert("(#{type})-1 < 0", headers, opts) return -1 elsif try_static_assert("(#{type})-1 > 0", headers, opts) return +1 end end # :startdoc: # Returns the size of the given +type+. You may optionally specify # additional +headers+ to search in for the +type+. # # If found, a macro is passed as a preprocessor constant to the compiler # using the type name, in uppercase, prepended with +SIZEOF_+, followed by # the type name, followed by =X where "X" is the actual size. # # For example, if check_sizeof('mystruct') returned 12, then # the SIZEOF_MYSTRUCT=12 preprocessor macro would be passed to # the compiler. # def check_sizeof(type, headers = nil, opts = "", &b) typedef, member, prelude = typedef_expr(type, headers) prelude << "static #{typedef} *rbcv_ptr_;\n" prelude = [prelude] expr = "sizeof((*rbcv_ptr_)#{"." << member if member})" fmt = STRING_OR_FAILED_FORMAT checking_for checking_message("size of #{type}", headers), fmt do if size = try_constant(expr, prelude, opts, &b) $defs.push(format("-DSIZEOF_%s=%s", type.tr_cpp, size)) size end end end # Returns the signedness of the given +type+. You may optionally specify # additional +headers+ to search in for the +type+. # # If the +type+ is found and is a numeric type, a macro is passed as a # preprocessor constant to the compiler using the +type+ name, in uppercase, # prepended with +SIGNEDNESS_OF_+, followed by the +type+ name, followed by # =X where "X" is positive integer if the +type+ is unsigned # and a negative integer if the +type+ is signed. # # For example, if +size_t+ is defined as unsigned, then # check_signedness('size_t') would return +1 and the # SIGNEDNESS_OF_SIZE_T=+1 preprocessor macro would be passed to # the compiler. The SIGNEDNESS_OF_INT=-1 macro would be set # for check_signedness('int') # def check_signedness(type, headers = nil, opts = nil, &b) typedef, member, prelude = typedef_expr(type, headers) signed = nil checking_for("signedness of #{type}", STRING_OR_FAILED_FORMAT) do signed = try_signedness(typedef, member, [prelude], opts, &b) or next nil $defs.push("-DSIGNEDNESS_OF_%s=%+d" % [type.tr_cpp, signed]) signed < 0 ? "signed" : "unsigned" end signed end # Returns the convertible integer type of the given +type+. You may # optionally specify additional +headers+ to search in for the +type+. # _convertible_ means actually the same type, or typedef'd from the same # type. # # If the +type+ is a integer type and the _convertible_ type is found, # the following macros are passed as preprocessor constants to the compiler # using the +type+ name, in uppercase. # # * +TYPEOF_+, followed by the +type+ name, followed by =X # where "X" is the found _convertible_ type name. # * +TYP2NUM+ and +NUM2TYP+, # where +TYP+ is the +type+ name in uppercase with replacing an +_t+ # suffix with "T", followed by =X where "X" is the macro name # to convert +type+ to an Integer object, and vice versa. # # For example, if +foobar_t+ is defined as unsigned long, then # convertible_int("foobar_t") would return "unsigned long", and # define these macros: # # #define TYPEOF_FOOBAR_T unsigned long # #define FOOBART2NUM ULONG2NUM # #define NUM2FOOBART NUM2ULONG # def convertible_int(type, headers = nil, opts = nil, &b) type, macname = *type checking_for("convertible type of #{type}", STRING_OR_FAILED_FORMAT) do if UNIVERSAL_INTS.include?(type) type else typedef, member, prelude = typedef_expr(type, headers, &b) if member prelude << "static rbcv_typedef_ rbcv_var;" compat = UNIVERSAL_INTS.find {|t| try_static_assert("sizeof(rbcv_var.#{member}) == sizeof(#{t})", [prelude], opts, &b) } else next unless signed = try_signedness(typedef, member, [prelude]) u = "unsigned " if signed > 0 prelude << "extern rbcv_typedef_ foo();" compat = UNIVERSAL_INTS.find {|t| try_compile([prelude, "extern #{u}#{t} foo();"].join("\n"), opts, :werror=>true, &b) } end if compat macname ||= type.sub(/_(?=t\z)/, '').tr_cpp conv = (compat == "long long" ? "LL" : compat.upcase) compat = "#{u}#{compat}" typename = type.tr_cpp $defs.push(format("-DSIZEOF_%s=SIZEOF_%s", typename, compat.tr_cpp)) $defs.push(format("-DTYPEOF_%s=%s", typename, compat.quote)) $defs.push(format("-DPRI_%s_PREFIX=PRI_%s_PREFIX", macname, conv)) conv = (u ? "U" : "") + conv $defs.push(format("-D%s2NUM=%s2NUM", macname, conv)) $defs.push(format("-DNUM2%s=NUM2%s", macname, conv)) compat end end end end # :stopdoc: # Used internally by the what_type? method to determine if +type+ is a scalar # pointer. def scalar_ptr_type?(type, member = nil, headers = nil, &b) try_compile(<<"SRC", &b) # pointer #{cpp_include(headers)} /*top*/ volatile #{type} conftestval; extern int t(void); #{MAIN_DOES_NOTHING 't'} int t(void) {return (int)(1-*(conftestval#{member ? ".#{member}" : ""}));} SRC end # Used internally by the what_type? method to determine if +type+ is a scalar # pointer. def scalar_type?(type, member = nil, headers = nil, &b) try_compile(<<"SRC", &b) # pointer #{cpp_include(headers)} /*top*/ volatile #{type} conftestval; extern int t(void); #{MAIN_DOES_NOTHING 't'} int t(void) {return (int)(1-(conftestval#{member ? ".#{member}" : ""}));} SRC end # Used internally by the what_type? method to check if the _typeof_ GCC # extension is available. def have_typeof? return $typeof if defined?($typeof) $typeof = %w[__typeof__ typeof].find do |t| try_compile(<--with-_config_ or # --without-_config_ option. Returns +true+ if the with option is # given, +false+ if the without option is given, and the default value # otherwise. # # This can be useful for adding custom definitions, such as debug # information. # # Example: # # if with_config("debug") # $defs.push("-DOSSL_DEBUG") unless $defs.include? "-DOSSL_DEBUG" # end # def with_config(config, default=nil) config = config.sub(/^--with[-_]/, '') val = arg_config("--with-"+config) do if arg_config("--without-"+config) false elsif block_given? yield(config, default) else break default end end case val when "yes" true when "no" false else val end end # Tests for the presence of an --enable-_config_ or # --disable-_config_ option. Returns +true+ if the enable option is # given, +false+ if the disable option is given, and the default value # otherwise. # # This can be useful for adding custom definitions, such as debug # information. # # Example: # # if enable_config("debug") # $defs.push("-DOSSL_DEBUG") unless $defs.include? "-DOSSL_DEBUG" # end # def enable_config(config, default=nil) if arg_config("--enable-"+config) true elsif arg_config("--disable-"+config) false elsif block_given? yield(config, default) else return default end end # Generates a header file consisting of the various macro definitions # generated by other methods such as have_func and have_header. These are # then wrapped in a custom #ifndef based on the +header+ file # name, which defaults to "extconf.h". # # For example: # # # extconf.rb # require 'mkmf' # have_func('realpath') # have_header('sys/utime.h') # create_header # create_makefile('foo') # # The above script would generate the following extconf.h file: # # #ifndef EXTCONF_H # #define EXTCONF_H # #define HAVE_REALPATH 1 # #define HAVE_SYS_UTIME_H 1 # #endif # # Given that the create_header method generates a file based on definitions # set earlier in your extconf.rb file, you will probably want to make this # one of the last methods you call in your script. # def create_header(header = "extconf.h") message "creating %s\n", header sym = header.tr_cpp hdr = ["#ifndef #{sym}\n#define #{sym}\n"] for line in $defs case line when /^-D([^=]+)(?:=(.*))?/ hdr << "#define #$1 #{$2 ? Shellwords.shellwords($2)[0].gsub(/(?=\t+)/, "\\\n") : 1}\n" when /^-U(.*)/ hdr << "#undef #$1\n" end end hdr << "#endif\n" hdr = hdr.join("") log_src(hdr, "#{header} is") unless (IO.read(header) == hdr rescue false) open(header, "wb") do |hfile| hfile.write(hdr) end end $extconf_h = header end # call-seq: # dir_config(target) # dir_config(target, prefix) # dir_config(target, idefault, ldefault) # # Sets a +target+ name that the user can then use to configure # various "with" options with on the command line by using that # name. For example, if the target is set to "foo", then the user # could use the --with-foo-dir=prefix, # --with-foo-include=dir and # --with-foo-lib=dir command line options to tell where # to search for header/library files. # # You may pass along additional parameters to specify default # values. If one is given it is taken as default +prefix+, and if # two are given they are taken as "include" and "lib" defaults in # that order. # # In any case, the return value will be an array of determined # "include" and "lib" directories, either of which can be nil if no # corresponding command line option is given when no default value # is specified. # # Note that dir_config only adds to the list of places to search for # libraries and include files. It does not link the libraries into your # application. # def dir_config(target, idefault=nil, ldefault=nil) if dir = with_config(target + "-dir", (idefault unless ldefault)) defaults = Array === dir ? dir : dir.split(File::PATH_SEPARATOR) idefault = ldefault = nil end idir = with_config(target + "-include", idefault) $arg_config.last[1] ||= "${#{target}-dir}/include" ldir = with_config(target + "-lib", ldefault) $arg_config.last[1] ||= "${#{target}-dir}/#{_libdir_basename}" idirs = idir ? Array === idir ? idir.dup : idir.split(File::PATH_SEPARATOR) : [] if defaults idirs.concat(defaults.collect {|d| d + "/include"}) idir = ([idir] + idirs).compact.join(File::PATH_SEPARATOR) end unless idirs.empty? idirs.collect! {|d| "-I" + d} idirs -= Shellwords.shellwords($CPPFLAGS) unless idirs.empty? $CPPFLAGS = (idirs.quote << $CPPFLAGS).join(" ") end end ldirs = ldir ? Array === ldir ? ldir.dup : ldir.split(File::PATH_SEPARATOR) : [] if defaults ldirs.concat(defaults.collect {|d| "#{d}/#{_libdir_basename}"}) ldir = ([ldir] + ldirs).compact.join(File::PATH_SEPARATOR) end $LIBPATH = ldirs | $LIBPATH [idir, ldir] end # Returns compile/link information about an installed library in a # tuple of [cflags, ldflags, libs], by using the # command found first in the following commands: # # 1. If --with-{pkg}-config={command} is given via # command line option: {command} {option} # # 2. {pkg}-config {option} # # 3. pkg-config {option} {pkg} # # Where {option} is, for instance, --cflags. # # The values obtained are appended to +$CFLAGS+, +$LDFLAGS+ and # +$libs+. # # If an option argument is given, the config command is # invoked with the option and a stripped output string is returned # without modifying any of the global values mentioned above. def pkg_config(pkg, option=nil) if pkgconfig = with_config("#{pkg}-config") and find_executable0(pkgconfig) # iff package specific config command is given elsif ($PKGCONFIG ||= (pkgconfig = with_config("pkg-config", ("pkg-config" unless CROSS_COMPILING))) && find_executable0(pkgconfig) && pkgconfig) and system("#{$PKGCONFIG} --exists #{pkg}") # default to pkg-config command pkgconfig = $PKGCONFIG get = proc {|opt| opt = IO.popen("#{$PKGCONFIG} --#{opt} #{pkg}", err:[:child, :out], &:read) opt.strip if $?.success? } elsif find_executable0(pkgconfig = "#{pkg}-config") # default to package specific config command, as a last resort. else pkgconfig = nil end if pkgconfig get ||= proc {|opt| opt = IO.popen("#{pkgconfig} --#{opt}", err:[:child, :out], &:read) opt.strip if $?.success? } end orig_ldflags = $LDFLAGS if get and option get[option] elsif get and try_ldflags(ldflags = get['libs']) if incflags = get['cflags-only-I'] $INCFLAGS << " " << incflags cflags = get['cflags-only-other'] else cflags = get['cflags'] end libs = get['libs-only-l'] if cflags $CFLAGS += " " << cflags $CXXFLAGS += " " << cflags end if libs ldflags = (Shellwords.shellwords(ldflags) - Shellwords.shellwords(libs)).quote.join(" ") else libs, ldflags = Shellwords.shellwords(ldflags).partition {|s| s =~ /-l([^ ]+)/ }.map {|l|l.quote.join(" ")} end $libs += " " << libs $LDFLAGS = [orig_ldflags, ldflags].join(' ') Logging::message "package configuration for %s\n", pkg Logging::message "cflags: %s\nldflags: %s\nlibs: %s\n\n", cflags, ldflags, libs [cflags, ldflags, libs] else Logging::message "package configuration for %s is not found\n", pkg nil end end # :stopdoc: def with_destdir(dir) dir = dir.sub($dest_prefix_pattern, '') /\A\$[\(\{]/ =~ dir ? dir : "$(DESTDIR)"+dir end # Converts forward slashes to backslashes. Aimed at MS Windows. # # Internal use only. # def winsep(s) s.tr('/', '\\') end # Converts native path to format acceptable in Makefile # # Internal use only. # if !CROSS_COMPILING case CONFIG['build_os'] when 'mingw32' def mkintpath(path) # mingw uses make from msys and it needs special care # converts from C:\some\path to /C/some/path path = path.dup path.tr!('\\', '/') path.sub!(/\A([A-Za-z]):(?=\/)/, '/\1') path end when 'cygwin' if CONFIG['target_os'] != 'cygwin' def mkintpath(path) IO.popen(["cygpath", "-u", path], &:read).chomp end end end end unless method_defined?(:mkintpath) def mkintpath(path) path end end def configuration(srcdir) mk = [] vpath = $VPATH.dup CONFIG["hdrdir"] ||= $hdrdir mk << %{ SHELL = /bin/sh # V=0 quiet, V=1 verbose. other values don't work. V = 0 Q1 = $(V:1=) Q = $(Q1:0=@) ECHO1 = $(V:1=@#{CONFIG['NULLCMD']}) ECHO = $(ECHO1:0=@echo) NULLCMD = #{CONFIG['NULLCMD']} #### Start of system configuration section. #### #{"top_srcdir = " + $top_srcdir.sub(%r"\A#{Regexp.quote($topdir)}/", "$(topdir)/") if $extmk} srcdir = #{srcdir.gsub(/\$\((srcdir)\)|\$\{(srcdir)\}/) {mkintpath(CONFIG[$1||$2]).unspace}} topdir = #{mkintpath(topdir = $extmk ? CONFIG["topdir"] : $topdir).unspace} hdrdir = #{(hdrdir = CONFIG["hdrdir"]) == topdir ? "$(topdir)" : mkintpath(hdrdir).unspace} arch_hdrdir = #{$arch_hdrdir.quote} PATH_SEPARATOR = #{CONFIG['PATH_SEPARATOR']} VPATH = #{vpath.join(CONFIG['PATH_SEPARATOR'])} } if $extmk mk << "RUBYLIB =\n""RUBYOPT = -\n" end prefix = mkintpath(CONFIG["prefix"]) if destdir = prefix[$dest_prefix_pattern, 1] mk << "\nDESTDIR = #{destdir}\n" prefix = prefix[destdir.size..-1] end mk << "prefix = #{with_destdir(prefix).unspace}\n" CONFIG.each do |key, var| mk << "#{key} = #{with_destdir(mkintpath(var)).unspace}\n" if /.prefix$/ =~ key end CONFIG.each do |key, var| next if /^abs_/ =~ key next if /^(?:src|top|hdr)dir$/ =~ key next unless /dir$/ =~ key mk << "#{key} = #{with_destdir(var)}\n" end if !$extmk and !$configure_args.has_key?('--ruby') and sep = config_string('BUILD_FILE_SEPARATOR') sep = ":/=#{sep}" else sep = "" end possible_command = (proc {|s| s if /top_srcdir/ !~ s} unless $extmk) extconf_h = $extconf_h ? "-DRUBY_EXTCONF_H=\\\"$(RUBY_EXTCONF_H)\\\" " : $defs.join(" ") << " " headers = %w[ $(hdrdir)/ruby.h $(hdrdir)/ruby/ruby.h $(hdrdir)/ruby/defines.h $(hdrdir)/ruby/missing.h $(hdrdir)/ruby/intern.h $(hdrdir)/ruby/st.h $(hdrdir)/ruby/subst.h ] if RULE_SUBST headers.each {|h| h.sub!(/.*/, &RULE_SUBST.method(:%))} end headers << $config_h headers << '$(RUBY_EXTCONF_H)' if $extconf_h mk << %{ CC = #{CONFIG['CC']} CXX = #{CONFIG['CXX']} LIBRUBY = #{CONFIG['LIBRUBY']} LIBRUBY_A = #{CONFIG['LIBRUBY_A']} LIBRUBYARG_SHARED = #$LIBRUBYARG_SHARED LIBRUBYARG_STATIC = #$LIBRUBYARG_STATIC empty = OUTFLAG = #{OUTFLAG}$(empty) COUTFLAG = #{COUTFLAG}$(empty) RUBY_EXTCONF_H = #{$extconf_h} cflags = #{CONFIG['cflags']} optflags = #{CONFIG['optflags']} debugflags = #{CONFIG['debugflags']} warnflags = #{$warnflags} CCDLFLAGS = #{$static ? '' : CONFIG['CCDLFLAGS']} CFLAGS = $(CCDLFLAGS) #$CFLAGS $(ARCH_FLAG) INCFLAGS = -I. #$INCFLAGS DEFS = #{CONFIG['DEFS']} CPPFLAGS = #{extconf_h}#{$CPPFLAGS} CXXFLAGS = $(CCDLFLAGS) #$CXXFLAGS $(ARCH_FLAG) ldflags = #{$LDFLAGS} dldflags = #{$DLDFLAGS} #{CONFIG['EXTDLDFLAGS']} ARCH_FLAG = #{$ARCH_FLAG} DLDFLAGS = $(ldflags) $(dldflags) $(ARCH_FLAG) LDSHARED = #{CONFIG['LDSHARED']} LDSHAREDXX = #{config_string('LDSHAREDXX') || '$(LDSHARED)'} AR = #{CONFIG['AR']} EXEEXT = #{CONFIG['EXEEXT']} } CONFIG.each do |key, val| mk << "#{key} = #{val}\n" if /^RUBY.*NAME/ =~ key end mk << %{ arch = #{CONFIG['arch']} sitearch = #{CONFIG['sitearch']} ruby_version = #{RbConfig::CONFIG['ruby_version']} ruby = #{$ruby.sub(%r[\A#{Regexp.quote(RbConfig::CONFIG['bindir'])}(?=/|\z)]) {'$(bindir)'}} RUBY = $(ruby#{sep}) ruby_headers = #{headers.join(' ')} RM = #{config_string('RM', &possible_command) || '$(RUBY) -run -e rm -- -f'} RM_RF = #{'$(RUBY) -run -e rm -- -rf'} RMDIRS = #{config_string('RMDIRS', &possible_command) || '$(RUBY) -run -e rmdir -- -p'} MAKEDIRS = #{config_string('MAKEDIRS', &possible_command) || '@$(RUBY) -run -e mkdir -- -p'} INSTALL = #{config_string('INSTALL', &possible_command) || '@$(RUBY) -run -e install -- -vp'} INSTALL_PROG = #{config_string('INSTALL_PROG') || '$(INSTALL) -m 0755'} INSTALL_DATA = #{config_string('INSTALL_DATA') || '$(INSTALL) -m 0644'} COPY = #{config_string('CP', &possible_command) || '@$(RUBY) -run -e cp -- -v'} TOUCH = exit > #### End of system configuration section. #### preload = #{defined?($preload) && $preload ? $preload.join(' ') : ''} } if $nmake == ?b mk.each do |x| x.gsub!(/^(MAKEDIRS|INSTALL_(?:PROG|DATA))+\s*=.*\n/) do "!ifndef " + $1 + "\n" + $& + "!endif\n" end end end mk end def timestamp_file(name, target_prefix = nil) if target_prefix pat = [] install_dirs.each do |n, d| pat << n if /\$\(target_prefix\)\z/ =~ d end name = name.gsub(/\$\((#{pat.join("|")})\)/) {$&+target_prefix} end name = name.gsub(/(\$[({]|[})])|(\/+)|[^-.\w]+/) {$1 ? "" : $2 ? ".-." : "_"} "$(TIMESTAMP_DIR)/.#{name}.time" end # :startdoc: # creates a stub Makefile. # def dummy_makefile(srcdir) configuration(srcdir) << <require 'test/foo'. # # The +srcprefix+ should be used when your source files are not in the same # directory as your build script. This will not only eliminate the need for # you to manually copy the source files into the same directory as your # build script, but it also sets the proper +target_prefix+ in the generated # Makefile. # # Setting the +target_prefix+ will, in turn, install the generated binary in # a directory under your RbConfig::CONFIG['sitearchdir'] that # mimics your local filesystem when you run make install. # # For example, given the following file tree: # # ext/ # extconf.rb # test/ # foo.c # # And given the following code: # # create_makefile('test/foo', 'test') # # That will set the +target_prefix+ in the generated Makefile to "test". # That, in turn, will create the following file tree when installed via the # make install command: # # /path/to/ruby/sitearchdir/test/foo.so # # It is recommended that you use this approach to generate your makefiles, # instead of copying files around manually, because some third party # libraries may depend on the +target_prefix+ being set properly. # # The +srcprefix+ argument can be used to override the default source # directory, i.e. the current directory. It is included as part of the # +VPATH+ and added to the list of +INCFLAGS+. # def create_makefile(target, srcprefix = nil) $target = target libpath = $LIBPATH|$DEFLIBPATH message "creating Makefile\n" MakeMakefile.rm_f "#{CONFTEST}*" if CONFIG["DLEXT"] == $OBJEXT for lib in libs = $libs.split lib.sub!(/-l(.*)/, %%"lib\\1.#{$LIBEXT}"%) end $defs.push(format("-DEXTLIB='%s'", libs.join(","))) end if target.include?('/') target_prefix, target = File.split(target) target_prefix[0,0] = '/' else target_prefix = "" end srcprefix ||= "$(srcdir)/#{srcprefix}".chomp('/') RbConfig.expand(srcdir = srcprefix.dup) ext = ".#{$OBJEXT}" orig_srcs = Dir[File.join(srcdir, "*.{#{SRC_EXT.join(%q{,})}}")] if not $objs srcs = $srcs || orig_srcs objs = srcs.inject(Hash.new {[]}) {|h, f| h[File.basename(f, ".*") << ext] <<= f; h} $objs = objs.keys unless objs.delete_if {|b, f| f.size == 1}.empty? dups = objs.sort.map {|b, f| "#{b[/.*\./]}{#{f.collect {|n| n[/([^.]+)\z/]}.join(',')}}" } abort "source files duplication - #{dups.join(", ")}" end else $objs.collect! {|o| File.basename(o, ".*") << ext} unless $OBJEXT == "o" srcs = $srcs || $objs.collect {|o| o.chomp(ext) << ".c"} end $srcs = srcs hdrs = Dir[File.join(srcdir, "*.{#{HDR_EXT.join(%q{,})}}")] target = nil if $objs.empty? if target and EXPORT_PREFIX if File.exist?(File.join(srcdir, target + '.def')) deffile = "$(srcdir)/$(TARGET).def" unless EXPORT_PREFIX.empty? makedef = %{-pe "$_.sub!(/^(?=\\w)/,'#{EXPORT_PREFIX}') unless 1../^EXPORTS$/i"} end else makedef = %{-e "puts 'EXPORTS', '$(TARGET_ENTRY)'"} end if makedef $cleanfiles << '$(DEFFILE)' origdef = deffile deffile = "$(TARGET)-$(arch).def" end end origdef ||= '' if $extout and $INSTALLFILES $cleanfiles.concat($INSTALLFILES.collect {|files, dir|File.join(dir, files.sub(/\A\.\//, ''))}) $distcleandirs.concat($INSTALLFILES.collect {|files, dir| dir}) end if $extmk and $static $defs << "-DRUBY_EXPORT=1" end if $extmk and not $extconf_h create_header end libpath = libpathflag(libpath) dllib = target ? "$(TARGET).#{CONFIG['DLEXT']}" : "" staticlib = target ? "$(TARGET).#$LIBEXT" : "" mfile = open("Makefile", "wb") conf = configuration(srcprefix) conf = yield(conf) if block_given? mfile.puts(conf) mfile.print " libpath = #{($LIBPATH|$DEFLIBPATH).join(" ")} LIBPATH = #{libpath} DEFFILE = #{deffile} CLEANFILES = #{$cleanfiles.join(' ')} DISTCLEANFILES = #{$distcleanfiles.join(' ')} DISTCLEANDIRS = #{$distcleandirs.join(' ')} extout = #{$extout && $extout.quote} extout_prefix = #{$extout_prefix} target_prefix = #{target_prefix} LOCAL_LIBS = #{$LOCAL_LIBS} LIBS = #{$LIBRUBYARG} #{$libs} #{$LIBS} ORIG_SRCS = #{orig_srcs.collect(&File.method(:basename)).join(' ')} SRCS = $(ORIG_SRCS) #{(srcs - orig_srcs).collect(&File.method(:basename)).join(' ')} OBJS = #{$objs.join(" ")} HDRS = #{hdrs.map{|h| '$(srcdir)/' + File.basename(h)}.join(' ')} TARGET = #{target} TARGET_NAME = #{target && target[/\A\w+/]} TARGET_ENTRY = #{EXPORT_PREFIX || ''}Init_$(TARGET_NAME) DLLIB = #{dllib} EXTSTATIC = #{$static || ""} STATIC_LIB = #{staticlib unless $static.nil?} #{!$extout && defined?($installed_list) ? "INSTALLED_LIST = #{$installed_list}\n" : ""} TIMESTAMP_DIR = #{$extout ? '$(extout)/.timestamp' : '.'} " #" # TODO: fixme install_dirs.each {|d| mfile.print("%-14s= %s\n" % d) if /^[[:upper:]]/ =~ d[0]} n = ($extout ? '$(RUBYARCHDIR)/' : '') + '$(TARGET)' mfile.print " TARGET_SO = #{($extout ? '$(RUBYARCHDIR)/' : '')}$(DLLIB) CLEANLIBS = #{n}.#{CONFIG['DLEXT']} #{config_string('cleanlibs') {|t| t.gsub(/\$\*/) {n}}} CLEANOBJS = *.#{$OBJEXT} #{config_string('cleanobjs') {|t| t.gsub(/\$\*/, "$(TARGET)#{deffile ? '-$(arch)': ''}")} if target} *.bak all: #{$extout ? "install" : target ? "$(DLLIB)" : "Makefile"} static: $(STATIC_LIB)#{$extout ? " install-rb" : ""} .PHONY: all install static install-so install-rb .PHONY: clean clean-so clean-static clean-rb " mfile.print CLEANINGS fsep = config_string('BUILD_FILE_SEPARATOR') {|s| s unless s == "/"} if fsep sep = ":/=#{fsep}" fseprepl = proc {|s| s = s.gsub("/", fsep) s = s.gsub(/(\$\(\w+)(\))/) {$1+sep+$2} s.gsub(/(\$\{\w+)(\})/) {$1+sep+$2} } rsep = ":#{fsep}=/" else fseprepl = proc {|s| s} sep = "" rsep = "" end dirs = [] mfile.print "install: install-so install-rb\n\n" sodir = (dir = "$(RUBYARCHDIR)").dup mfile.print("install-so: ") if target f = "$(DLLIB)" dest = "#{dir}/#{f}" if $extout mfile.puts dest mfile.print "clean-so::\n" mfile.print "\t-$(Q)$(RM) #{fseprepl[dest]}\n" mfile.print "\t-$(Q)$(RMDIRS) #{fseprepl[dir]}#{$ignore_error}\n" else mfile.print "#{f} #{timestamp_file(dir, target_prefix)}\n" mfile.print "\t$(INSTALL_PROG) #{fseprepl[f]} #{dir}\n" if defined?($installed_list) mfile.print "\t@echo #{dir}/#{File.basename(f)}>>$(INSTALLED_LIST)\n" end end mfile.print "clean-static::\n" mfile.print "\t-$(Q)$(RM) $(STATIC_LIB)\n" else mfile.puts "Makefile" end mfile.print("install-rb: pre-install-rb install-rb-default\n") mfile.print("install-rb-default: pre-install-rb-default\n") mfile.print("pre-install-rb: Makefile\n") mfile.print("pre-install-rb-default: Makefile\n") for sfx, i in [["-default", [["lib/**/*.rb", "$(RUBYLIBDIR)", "lib"]]], ["", $INSTALLFILES]] files = install_files(mfile, i, nil, srcprefix) or next for dir, *files in files unless dirs.include?(dir) dirs << dir mfile.print "pre-install-rb#{sfx}: #{timestamp_file(dir, target_prefix)}\n" end for f in files dest = "#{dir}/#{File.basename(f)}" mfile.print("install-rb#{sfx}: #{dest}\n") mfile.print("#{dest}: #{f} #{timestamp_file(dir, target_prefix)}\n") mfile.print("\t$(Q) $(#{$extout ? 'COPY' : 'INSTALL_DATA'}) #{f} $(@D)\n") if defined?($installed_list) and !$extout mfile.print("\t@echo #{dest}>>$(INSTALLED_LIST)\n") end if $extout mfile.print("clean-rb#{sfx}::\n") mfile.print("\t-$(Q)$(RM) #{fseprepl[dest]}\n") end end end mfile.print "pre-install-rb#{sfx}:\n" if files.empty? mfile.print("\t@$(NULLCMD)\n") else mfile.print("\t$(ECHO) installing#{sfx.sub(/^-/, " ")} #{target} libraries\n") end if $extout dirs.uniq! unless dirs.empty? mfile.print("clean-rb#{sfx}::\n") for dir in dirs.sort_by {|d| -d.count('/')} mfile.print("\t-$(Q)$(RMDIRS) #{fseprepl[dir]}#{$ignore_error}\n") end end end end dirs.unshift(sodir) if target and !dirs.include?(sodir) dirs.each do |d| t = timestamp_file(d, target_prefix) mfile.print "#{t}:\n\t$(Q) $(MAKEDIRS) $(@D) #{d}\n\t$(Q) $(TOUCH) $@\n" end mfile.print <<-SITEINSTALL site-install: site-install-so site-install-rb site-install-so: install-so site-install-rb: install-rb SITEINSTALL return unless target mfile.puts SRC_EXT.collect {|e| ".path.#{e} = $(VPATH)"} if $nmake == ?b mfile.print ".SUFFIXES: .#{(SRC_EXT + [$OBJEXT, $ASMEXT]).compact.join(' .')}\n" mfile.print "\n" compile_command = "\n\t$(ECHO) compiling $(<#{rsep})\n\t$(Q) %s\n\n" command = compile_command % COMPILE_CXX asm_command = compile_command.sub(/compiling/, 'translating') % ASSEMBLE_CXX CXX_EXT.each do |e| each_compile_rules do |rule| mfile.printf(rule, e, $OBJEXT) mfile.print(command) mfile.printf(rule, e, $ASMEXT) mfile.print(asm_command) end end command = compile_command % COMPILE_C asm_command = compile_command.sub(/compiling/, 'translating') % ASSEMBLE_C C_EXT.each do |e| each_compile_rules do |rule| mfile.printf(rule, e, $OBJEXT) mfile.print(command) mfile.printf(rule, e, $ASMEXT) mfile.print(asm_command) end end mfile.print "$(RUBYARCHDIR)/" if $extout mfile.print "$(DLLIB): " mfile.print "$(DEFFILE) " if makedef mfile.print "$(OBJS) Makefile" mfile.print " #{timestamp_file('$(RUBYARCHDIR)', target_prefix)}" if $extout mfile.print "\n" mfile.print "\t$(ECHO) linking shared-object #{target_prefix.sub(/\A\/(.*)/, '\1/')}$(DLLIB)\n" mfile.print "\t-$(Q)$(RM) $(@#{sep})\n" link_so = LINK_SO.gsub(/^/, "\t$(Q) ") if srcs.any?(&%r"\.(?:#{CXX_EXT.join('|')})\z".method(:===)) link_so = link_so.sub(/\bLDSHARED\b/, '\&XX') end mfile.print link_so, "\n\n" unless $static.nil? mfile.print "$(STATIC_LIB): $(OBJS)\n\t-$(Q)$(RM) $(@#{sep})\n\t" mfile.print "$(ECHO) linking static-library $(@#{rsep})\n\t$(Q) " mfile.print "$(AR) #{config_string('ARFLAGS') || 'cru '}$@ $(OBJS)" config_string('RANLIB') do |ranlib| mfile.print "\n\t-$(Q)#{ranlib} $(@) 2> /dev/null || true" end end mfile.print "\n\n" if makedef mfile.print "$(DEFFILE): #{origdef}\n" mfile.print "\t$(ECHO) generating $(@#{rsep})\n" mfile.print "\t$(Q) $(RUBY) #{makedef} #{origdef} > $@\n\n" end depend = File.join(srcdir, "depend") if File.exist?(depend) mfile.print("###\n", *depend_rules(File.read(depend))) else mfile.print "$(OBJS): $(HDRS) $(ruby_headers)\n" end $makefile_created = true ensure mfile.close if mfile end # :stopdoc: def init_mkmf(config = CONFIG, rbconfig = RbConfig::CONFIG) $makefile_created = false $arg_config = [] $enable_shared = config['ENABLE_SHARED'] == 'yes' $defs = [] $extconf_h = nil if $warnflags = CONFIG['warnflags'] and CONFIG['GCC'] == 'yes' # turn warnings into errors only for bundled extensions. config['warnflags'] = $warnflags.gsub(/(\A|\s)-Werror[-=]/, '\1-W') if /icc\z/ =~ config['CC'] config['warnflags'].gsub!(/(\A|\s)-W(?:division-by-zero|deprecated-declarations)/, '\1') end RbConfig.expand(rbconfig['warnflags'] = config['warnflags'].dup) config.each do |key, val| RbConfig.expand(rbconfig[key] = val.dup) if /warnflags/ =~ val end $warnflags = config['warnflags'] unless $extmk end $CFLAGS = with_config("cflags", arg_config("CFLAGS", config["CFLAGS"])).dup $CXXFLAGS = (with_config("cxxflags", arg_config("CXXFLAGS", config["CXXFLAGS"]))||'').dup $ARCH_FLAG = with_config("arch_flag", arg_config("ARCH_FLAG", config["ARCH_FLAG"])).dup $CPPFLAGS = with_config("cppflags", arg_config("CPPFLAGS", config["CPPFLAGS"])).dup $LDFLAGS = with_config("ldflags", arg_config("LDFLAGS", config["LDFLAGS"])).dup $INCFLAGS = "-I$(arch_hdrdir)" $INCFLAGS << " -I$(hdrdir)/ruby/backward" unless $extmk $INCFLAGS << " -I$(hdrdir) -I$(srcdir)" $DLDFLAGS = with_config("dldflags", arg_config("DLDFLAGS", config["DLDFLAGS"])).dup $LIBEXT = config['LIBEXT'].dup $OBJEXT = config["OBJEXT"].dup $EXEEXT = config["EXEEXT"].dup $ASMEXT = config_string('ASMEXT', &:dup) || 'S' $LIBS = "#{config['LIBS']} #{config['DLDLIBS']}" $LIBRUBYARG = "" $LIBRUBYARG_STATIC = config['LIBRUBYARG_STATIC'] $LIBRUBYARG_SHARED = config['LIBRUBYARG_SHARED'] $DEFLIBPATH = [$extmk ? "$(topdir)" : "$(#{config["libdirname"] || "libdir"})"] $DEFLIBPATH.unshift(".") $LIBPATH = [] $INSTALLFILES = [] $NONINSTALLFILES = [/~\z/, /\A#.*#\z/, /\A\.#/, /\.bak\z/i, /\.orig\z/, /\.rej\z/, /\.l[ao]\z/, /\.o\z/] $VPATH = %w[$(srcdir) $(arch_hdrdir)/ruby $(hdrdir)/ruby] $objs = nil $srcs = nil $libs = "" if $enable_shared or RbConfig.expand(config["LIBRUBY"].dup) != RbConfig.expand(config["LIBRUBY_A"].dup) $LIBRUBYARG = config['LIBRUBYARG'] end $LOCAL_LIBS = "" $cleanfiles = config_string('CLEANFILES') {|s| Shellwords.shellwords(s)} || [] $cleanfiles << "mkmf.log" $distcleanfiles = config_string('DISTCLEANFILES') {|s| Shellwords.shellwords(s)} || [] $distcleandirs = config_string('DISTCLEANDIRS') {|s| Shellwords.shellwords(s)} || [] $extout ||= nil $extout_prefix ||= nil $arg_config.clear dir_config("opt") end FailedMessage = < 1000000) {\n" + refs.map {|n|" printf(\"%p\", &#{n});\n"}.join("") + " }\n" end end src end extend self init_mkmf $make = with_config("make-prog", ENV["MAKE"] || "make") make, = Shellwords.shellwords($make) $nmake = nil case when $mswin $nmake = ?m if /nmake/i =~ make when $bccwin $nmake = ?b if /Borland/i =~ `#{make} -h` end $ignore_error = $nmake ? '' : ' 2> /dev/null || true' RbConfig::CONFIG["srcdir"] = CONFIG["srcdir"] = $srcdir = arg_config("--srcdir", File.dirname($0)) $configure_args["--topsrcdir"] ||= $srcdir if $curdir = arg_config("--curdir") RbConfig.expand(curdir = $curdir.dup) else curdir = $curdir = "." end unless File.expand_path(RbConfig::CONFIG["topdir"]) == File.expand_path(curdir) CONFIG["topdir"] = $curdir RbConfig::CONFIG["topdir"] = curdir end $configure_args["--topdir"] ||= $curdir $ruby = arg_config("--ruby", File.join(RbConfig::CONFIG["bindir"], CONFIG["ruby_install_name"])) RbConfig.expand(CONFIG["RUBY_SO_NAME"]) # :startdoc: split = Shellwords.method(:shellwords).to_proc EXPORT_PREFIX = config_string('EXPORT_PREFIX') {|s| s.strip} hdr = ['#include "ruby.h"' "\n"] config_string('COMMON_MACROS') do |s| Shellwords.shellwords(s).each do |w| w, v = w.split(/=/, 2) hdr << "#ifndef #{w}" hdr << "#define #{[w, v].compact.join(" ")}" hdr << "#endif /* #{w} */" end end config_string('COMMON_HEADERS') do |s| Shellwords.shellwords(s).each {|w| hdr << "#include <#{w}>"} end ## # Common headers for Ruby C extensions COMMON_HEADERS = hdr.join("\n") ## # Common libraries for Ruby C extensions COMMON_LIBS = config_string('COMMON_LIBS', &split) || [] ## # make compile rules COMPILE_RULES = config_string('COMPILE_RULES', &split) || %w[.%s.%s:] RULE_SUBST = config_string('RULE_SUBST') ## # Command which will compile C files in the generated Makefile COMPILE_C = config_string('COMPILE_C') || '$(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $<' ## # Command which will compile C++ files in the generated Makefile COMPILE_CXX = config_string('COMPILE_CXX') || '$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<' ## # Command which will translate C files to assembler sources in the generated Makefile ASSEMBLE_C = config_string('ASSEMBLE_C') || COMPILE_C.sub(/(?<=\s)-c(?=\s)/, '-S') ## # Command which will translate C++ files to assembler sources in the generated Makefile ASSEMBLE_CXX = config_string('ASSEMBLE_CXX') || COMPILE_CXX.sub(/(?<=\s)-c(?=\s)/, '-S') ## # Command which will compile a program in order to test linking a library TRY_LINK = config_string('TRY_LINK') || "$(CC) #{OUTFLAG}#{CONFTEST}#{$EXEEXT} $(INCFLAGS) $(CPPFLAGS) " \ "$(CFLAGS) $(src) $(LIBPATH) $(LDFLAGS) $(ARCH_FLAG) $(LOCAL_LIBS) $(LIBS)" ## # Command which will link a shared library LINK_SO = (config_string('LINK_SO') || "").sub(/^$/) do if CONFIG["DLEXT"] == $OBJEXT "ld $(DLDFLAGS) -r -o $@ $(OBJS)\n" else "$(LDSHARED) #{OUTFLAG}$@ $(OBJS) " \ "$(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)" end end ## # Argument which will add a library path to the linker LIBPATHFLAG = config_string('LIBPATHFLAG') || ' -L%s' RPATHFLAG = config_string('RPATHFLAG') || '' ## # Argument which will add a library to the linker LIBARG = config_string('LIBARG') || '-l%s' ## # A C main function which does no work MAIN_DOES_NOTHING = config_string('MAIN_DOES_NOTHING') || "int main(int argc, char **argv)\n{\n return 0;\n}" UNIVERSAL_INTS = config_string('UNIVERSAL_INTS') {|s| Shellwords.shellwords(s)} || %w[int short long long\ long] sep = config_string('BUILD_FILE_SEPARATOR') {|s| ":/=#{s}" if s != "/"} || "" ## # Makefile rules that will clean the extension build directory CLEANINGS = " clean-static:: clean-rb-default:: clean-rb:: clean-so:: clean: clean-so clean-static clean-rb-default clean-rb \t\t-$(Q)$(RM) $(CLEANLIBS#{sep}) $(CLEANOBJS#{sep}) $(CLEANFILES#{sep}) .*.time distclean-rb-default:: distclean-rb:: distclean-so:: distclean-static:: distclean: clean distclean-so distclean-static distclean-rb-default distclean-rb \t\t-$(Q)$(RM) Makefile $(RUBY_EXTCONF_H) #{CONFTEST}.* mkmf.log \t\t-$(Q)$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES#{sep}) \t\t-$(Q)$(RMDIRS) $(DISTCLEANDIRS#{sep})#{$ignore_error} realclean: distclean " end include MakeMakefile if not $extmk and /\A(extconf|makefile).rb\z/ =~ File.basename($0) END {mkmf_failed($0)} end PK!K^"G G 2.2.0/uri.rbnu[# URI is a module providing classes to handle Uniform Resource Identifiers # (RFC2396[http://tools.ietf.org/html/rfc2396]) # # == Features # # * Uniform handling of handling URIs # * Flexibility to introduce custom URI schemes # * Flexibility to have an alternate URI::Parser (or just different patterns # and regexp's) # # == Basic example # # require 'uri' # # uri = URI("http://foo.com/posts?id=30&limit=5#time=1305298413") # #=> # # uri.scheme # #=> "http" # uri.host # #=> "foo.com" # uri.path # #=> "/posts" # uri.query # #=> "id=30&limit=5" # uri.fragment # #=> "time=1305298413" # # uri.to_s # #=> "http://foo.com/posts?id=30&limit=5#time=1305298413" # # == Adding custom URIs # # module URI # class RSYNC < Generic # DEFAULT_PORT = 873 # end # @@schemes['RSYNC'] = RSYNC # end # #=> URI::RSYNC # # URI.scheme_list # #=> {"FTP"=>URI::FTP, "HTTP"=>URI::HTTP, "HTTPS"=>URI::HTTPS, # "LDAP"=>URI::LDAP, "LDAPS"=>URI::LDAPS, "MAILTO"=>URI::MailTo, # "RSYNC"=>URI::RSYNC} # # uri = URI("rsync://rsync.foo.com") # #=> # # # == RFC References # # A good place to view an RFC spec is http://www.ietf.org/rfc.html # # Here is a list of all related RFC's. # - RFC822[http://tools.ietf.org/html/rfc822] # - RFC1738[http://tools.ietf.org/html/rfc1738] # - RFC2255[http://tools.ietf.org/html/rfc2255] # - RFC2368[http://tools.ietf.org/html/rfc2368] # - RFC2373[http://tools.ietf.org/html/rfc2373] # - RFC2396[http://tools.ietf.org/html/rfc2396] # - RFC2732[http://tools.ietf.org/html/rfc2732] # - RFC3986[http://tools.ietf.org/html/rfc3986] # # == Class tree # # - URI::Generic (in uri/generic.rb) # - URI::FTP - (in uri/ftp.rb) # - URI::HTTP - (in uri/http.rb) # - URI::HTTPS - (in uri/https.rb) # - URI::LDAP - (in uri/ldap.rb) # - URI::LDAPS - (in uri/ldaps.rb) # - URI::MailTo - (in uri/mailto.rb) # - URI::Parser - (in uri/common.rb) # - URI::REGEXP - (in uri/common.rb) # - URI::REGEXP::PATTERN - (in uri/common.rb) # - URI::Util - (in uri/common.rb) # - URI::Escape - (in uri/common.rb) # - URI::Error - (in uri/common.rb) # - URI::InvalidURIError - (in uri/common.rb) # - URI::InvalidComponentError - (in uri/common.rb) # - URI::BadURIError - (in uri/common.rb) # # == Copyright Info # # Author:: Akira Yamada # Documentation:: # Akira Yamada # Dmitry V. Sabanin # Vincent Batts # License:: # Copyright (c) 2001 akira yamada # You can redistribute it and/or modify it under the same term as Ruby. # Revision:: $Id: uri.rb 48243 2014-11-03 00:33:44Z naruse $ # module URI # :stopdoc: VERSION_CODE = '001000'.freeze VERSION = VERSION_CODE.scan(/../).collect{|n| n.to_i}.join('.').freeze # :startdoc: end require 'uri/common' require 'uri/generic' require 'uri/ftp' require 'uri/http' require 'uri/https' require 'uri/ldap' require 'uri/ldaps' require 'uri/mailto' PK!8ܓ$$2.2.0/securerandom.rbnu[# -*- coding: us-ascii -*- begin require 'openssl' rescue LoadError end # == Secure random number generator interface. # # This library is an interface for secure random number generator which is # suitable for generating session key in HTTP cookies, etc. # # You can use this library in your application by requiring it: # # require 'securerandom' # # It supports following secure random number generators. # # * openssl # * /dev/urandom # * Win32 # # === Examples # # Hexadecimal string. # # require 'securerandom' # # p SecureRandom.hex(10) #=> "52750b30ffbc7de3b362" # p SecureRandom.hex(10) #=> "92b15d6c8dc4beb5f559" # p SecureRandom.hex(13) #=> "39b290146bea6ce975c37cfc23" # # Base64 string. # # p SecureRandom.base64(10) #=> "EcmTPZwWRAozdA==" # p SecureRandom.base64(10) #=> "KO1nIU+p9DKxGg==" # p SecureRandom.base64(12) #=> "7kJSM/MzBJI+75j8" # # Binary string. # # p SecureRandom.random_bytes(10) #=> "\016\t{\370g\310pbr\301" # p SecureRandom.random_bytes(10) #=> "\323U\030TO\234\357\020\a\337" module SecureRandom if /mswin|mingw/ =~ RUBY_PLATFORM require "fiddle/import" module AdvApi32 # :nodoc: extend Fiddle::Importer dlload "advapi32" extern "int CryptAcquireContext(void*, void*, void*, unsigned long, unsigned long)" extern "int CryptGenRandom(void*, unsigned long, void*)" def self.get_provider hProvStr = " " * Fiddle::SIZEOF_VOIDP prov_rsa_full = 1 crypt_verifycontext = 0xF0000000 if CryptAcquireContext(hProvStr, nil, nil, prov_rsa_full, crypt_verifycontext) == 0 raise SystemCallError, "CryptAcquireContext failed: #{lastWin32ErrorMessage}" end type = Fiddle::SIZEOF_VOIDP == Fiddle::SIZEOF_LONG_LONG ? 'q' : 'l' hProv, = hProvStr.unpack(type) hProv end def self.gen_random(n) @hProv ||= get_provider bytes = " ".force_encoding("ASCII-8BIT") * n if CryptGenRandom(@hProv, bytes.size, bytes) == 0 raise SystemCallError, "CryptGenRandom failed: #{Kernel32.last_error_message}" end bytes end end module Kernel32 # :nodoc: extend Fiddle::Importer dlload "kernel32" extern "unsigned long GetLastError()" extern "unsigned long FormatMessageA(unsigned long, void*, unsigned long, unsigned long, void*, unsigned long, void*)" # Following code is based on David Garamond's GUID library for Ruby. def self.last_error_message format_message_ignore_inserts = 0x00000200 format_message_from_system = 0x00001000 code = GetLastError() msg = "\0" * 1024 len = FormatMessageA(format_message_ignore_inserts + format_message_from_system, 0, code, 0, msg, 1024, nil) msg[0, len].force_encoding("filesystem").tr("\r", '').chomp end end end # SecureRandom.random_bytes generates a random binary string. # # The argument _n_ specifies the length of the result string. # # If _n_ is not specified or is nil, 16 is assumed. # It may be larger in future. # # The result may contain any byte: "\x00" - "\xff". # # p SecureRandom.random_bytes #=> "\xD8\\\xE0\xF4\r\xB2\xFC*WM\xFF\x83\x18\xF45\xB6" # p SecureRandom.random_bytes #=> "m\xDC\xFC/\a\x00Uf\xB2\xB2P\xBD\xFF6S\x97" # # If secure random number generator is not available, # NotImplementedError is raised. def self.random_bytes(n=nil) n = n ? n.to_int : 16 gen_random(n) end if defined?(OpenSSL::Random) && !defined?(AdvApi32) def self.gen_random(n) @pid = 0 unless defined?(@pid) pid = $$ unless @pid == pid now = Process.clock_gettime(Process::CLOCK_REALTIME, :nanosecond) ary = [now, @pid, pid] OpenSSL::Random.random_add(ary.join("").to_s, 0.0) @pid = pid end return OpenSSL::Random.random_bytes(n) end elsif defined?(AdvApi32) def self.gen_random(n) return AdvApi32.gen_random(n) end def self.lastWin32ErrorMessage # :nodoc: # for compatibility return Kernel32.last_error_message end else def self.gen_random(n) flags = File::RDONLY flags |= File::NONBLOCK if defined? File::NONBLOCK flags |= File::NOCTTY if defined? File::NOCTTY begin File.open("/dev/urandom", flags) {|f| unless f.stat.chardev? break end ret = f.read(n) unless ret.length == n raise NotImplementedError, "Unexpected partial read from random device: only #{ret.length} for #{n} bytes" end return ret } rescue Errno::ENOENT end raise NotImplementedError, "No random device" end end # SecureRandom.hex generates a random hexadecimal string. # # The argument _n_ specifies the length, in bytes, of the random number to be generated. # The length of the resulting hexadecimal string is twice _n_. # # If _n_ is not specified or is nil, 16 is assumed. # It may be larger in future. # # The result may contain 0-9 and a-f. # # p SecureRandom.hex #=> "eb693ec8252cd630102fd0d0fb7c3485" # p SecureRandom.hex #=> "91dc3bfb4de5b11d029d376634589b61" # # If secure random number generator is not available, # NotImplementedError is raised. def self.hex(n=nil) random_bytes(n).unpack("H*")[0] end # SecureRandom.base64 generates a random base64 string. # # The argument _n_ specifies the length, in bytes, of the random number # to be generated. The length of the result string is about 4/3 of _n_. # # If _n_ is not specified or is nil, 16 is assumed. # It may be larger in future. # # The result may contain A-Z, a-z, 0-9, "+", "/" and "=". # # p SecureRandom.base64 #=> "/2BuBuLf3+WfSKyQbRcc/A==" # p SecureRandom.base64 #=> "6BbW0pxO0YENxn38HMUbcQ==" # # If secure random number generator is not available, # NotImplementedError is raised. # # See RFC 3548 for the definition of base64. def self.base64(n=nil) [random_bytes(n)].pack("m*").delete("\n") end # SecureRandom.urlsafe_base64 generates a random URL-safe base64 string. # # The argument _n_ specifies the length, in bytes, of the random number # to be generated. The length of the result string is about 4/3 of _n_. # # If _n_ is not specified or is nil, 16 is assumed. # It may be larger in future. # # The boolean argument _padding_ specifies the padding. # If it is false or nil, padding is not generated. # Otherwise padding is generated. # By default, padding is not generated because "=" may be used as a URL delimiter. # # The result may contain A-Z, a-z, 0-9, "-" and "_". # "=" is also used if _padding_ is true. # # p SecureRandom.urlsafe_base64 #=> "b4GOKm4pOYU_-BOXcrUGDg" # p SecureRandom.urlsafe_base64 #=> "UZLdOkzop70Ddx-IJR0ABg" # # p SecureRandom.urlsafe_base64(nil, true) #=> "i0XQ-7gglIsHGV2_BNPrdQ==" # p SecureRandom.urlsafe_base64(nil, true) #=> "-M8rLhr7JEpJlqFGUMmOxg==" # # If secure random number generator is not available, # NotImplementedError is raised. # # See RFC 3548 for the definition of URL-safe base64. def self.urlsafe_base64(n=nil, padding=false) s = [random_bytes(n)].pack("m*") s.delete!("\n") s.tr!("+/", "-_") s.delete!("=") unless padding s end # SecureRandom.random_number generates a random number. # # If a positive integer is given as _n_, # SecureRandom.random_number returns an integer: # 0 <= SecureRandom.random_number(n) < n. # # p SecureRandom.random_number(100) #=> 15 # p SecureRandom.random_number(100) #=> 88 # # If 0 is given or an argument is not given, # SecureRandom.random_number returns a float: # 0.0 <= SecureRandom.random_number() < 1.0. # # p SecureRandom.random_number #=> 0.596506046187744 # p SecureRandom.random_number #=> 0.350621695741409 # def self.random_number(n=0) if 0 < n if defined? OpenSSL::BN OpenSSL::BN.rand_range(n).to_i else hex = n.to_s(16) hex = '0' + hex if (hex.length & 1) == 1 bin = [hex].pack("H*") mask = bin[0].ord mask |= mask >> 1 mask |= mask >> 2 mask |= mask >> 4 begin rnd = SecureRandom.random_bytes(bin.length) rnd[0] = (rnd[0].ord & mask).chr end until rnd < bin rnd.unpack("H*")[0].hex end else # assumption: Float::MANT_DIG <= 64 if defined? OpenSSL::BN i64 = OpenSSL::BN.rand(64, -1).to_i else i64 = SecureRandom.random_bytes(8).unpack("Q")[0] end Math.ldexp(i64 >> (64-Float::MANT_DIG), -Float::MANT_DIG) end end # SecureRandom.uuid generates a v4 random UUID (Universally Unique IDentifier). # # p SecureRandom.uuid #=> "2d931510-d99f-494a-8c67-87feb05e1594" # p SecureRandom.uuid #=> "bad85eb9-0713-4da7-8d36-07a8e4b00eab" # p SecureRandom.uuid #=> "62936e70-1815-439b-bf89-8492855a7e6b" # # The version 4 UUID is purely random (except the version). # It doesn't contain meaningful information such as MAC address, time, etc. # # See RFC 4122 for details of UUID. # def self.uuid ary = self.random_bytes(16).unpack("NnnnnN") ary[2] = (ary[2] & 0x0fff) | 0x4000 ary[3] = (ary[3] & 0x3fff) | 0x8000 "%08x-%04x-%04x-%04x-%04x%08x" % ary end end PK!k3K92.2.0/openssl.rbnu[=begin = $RCSfile$ -- Loader for all OpenSSL C-space and Ruby-space definitions = Info 'OpenSSL for Ruby 2' project Copyright (C) 2002 Michal Rokos All rights reserved. = Licence This program is licenced under the same licence as Ruby. (See the file 'LICENCE'.) = Version $Id: openssl.rb 32664 2011-07-25 06:30:07Z nahi $ =end require 'openssl.so' require 'openssl/bn' require 'openssl/cipher' require 'openssl/config' require 'openssl/digest' require 'openssl/x509' require 'openssl/ssl' PK!,i!2.2.0/matrix/lup_decomposition.rbnu[class Matrix # Adapted from JAMA: http://math.nist.gov/javanumerics/jama/ # # For an m-by-n matrix A with m >= n, the LU decomposition is an m-by-n # unit lower triangular matrix L, an n-by-n upper triangular matrix U, # and a m-by-m permutation matrix P so that L*U = P*A. # If m < n, then L is m-by-m and U is m-by-n. # # The LUP decomposition with pivoting always exists, even if the matrix is # singular, so the constructor will never fail. The primary use of the # LU decomposition is in the solution of square systems of simultaneous # linear equations. This will fail if singular? returns true. # class LUPDecomposition # Returns the lower triangular factor +L+ include Matrix::ConversionHelper def l Matrix.build(@row_count, [@column_count, @row_count].min) do |i, j| if (i > j) @lu[i][j] elsif (i == j) 1 else 0 end end end # Returns the upper triangular factor +U+ def u Matrix.build([@column_count, @row_count].min, @column_count) do |i, j| if (i <= j) @lu[i][j] else 0 end end end # Returns the permutation matrix +P+ def p rows = Array.new(@row_count){Array.new(@row_count, 0)} @pivots.each_with_index{|p, i| rows[i][p] = 1} Matrix.send :new, rows, @row_count end # Returns +L+, +U+, +P+ in an array def to_ary [l, u, p] end alias_method :to_a, :to_ary # Returns the pivoting indices attr_reader :pivots # Returns +true+ if +U+, and hence +A+, is singular. def singular? () @column_count.times do |j| if (@lu[j][j] == 0) return true end end false end # Returns the determinant of +A+, calculated efficiently # from the factorization. def det if (@row_count != @column_count) Matrix.Raise Matrix::ErrDimensionMismatch end d = @pivot_sign @column_count.times do |j| d *= @lu[j][j] end d end alias_method :determinant, :det # Returns +m+ so that A*m = b, # or equivalently so that L*U*m = P*b # +b+ can be a Matrix or a Vector def solve b if (singular?) Matrix.Raise Matrix::ErrNotRegular, "Matrix is singular." end if b.is_a? Matrix if (b.row_count != @row_count) Matrix.Raise Matrix::ErrDimensionMismatch end # Copy right hand side with pivoting nx = b.column_count m = @pivots.map{|row| b.row(row).to_a} # Solve L*Y = P*b @column_count.times do |k| (k+1).upto(@column_count-1) do |i| nx.times do |j| m[i][j] -= m[k][j]*@lu[i][k] end end end # Solve U*m = Y (@column_count-1).downto(0) do |k| nx.times do |j| m[k][j] = m[k][j].quo(@lu[k][k]) end k.times do |i| nx.times do |j| m[i][j] -= m[k][j]*@lu[i][k] end end end Matrix.send :new, m, nx else # same algorithm, specialized for simpler case of a vector b = convert_to_array(b) if (b.size != @row_count) Matrix.Raise Matrix::ErrDimensionMismatch end # Copy right hand side with pivoting m = b.values_at(*@pivots) # Solve L*Y = P*b @column_count.times do |k| (k+1).upto(@column_count-1) do |i| m[i] -= m[k]*@lu[i][k] end end # Solve U*m = Y (@column_count-1).downto(0) do |k| m[k] = m[k].quo(@lu[k][k]) k.times do |i| m[i] -= m[k]*@lu[i][k] end end Vector.elements(m, false) end end def initialize a raise TypeError, "Expected Matrix but got #{a.class}" unless a.is_a?(Matrix) # Use a "left-looking", dot-product, Crout/Doolittle algorithm. @lu = a.to_a @row_count = a.row_count @column_count = a.column_count @pivots = Array.new(@row_count) @row_count.times do |i| @pivots[i] = i end @pivot_sign = 1 lu_col_j = Array.new(@row_count) # Outer loop. @column_count.times do |j| # Make a copy of the j-th column to localize references. @row_count.times do |i| lu_col_j[i] = @lu[i][j] end # Apply previous transformations. @row_count.times do |i| lu_row_i = @lu[i] # Most of the time is spent in the following dot product. kmax = [i, j].min s = 0 kmax.times do |k| s += lu_row_i[k]*lu_col_j[k] end lu_row_i[j] = lu_col_j[i] -= s end # Find pivot and exchange if necessary. p = j (j+1).upto(@row_count-1) do |i| if (lu_col_j[i].abs > lu_col_j[p].abs) p = i end end if (p != j) @column_count.times do |k| t = @lu[p][k]; @lu[p][k] = @lu[j][k]; @lu[j][k] = t end k = @pivots[p]; @pivots[p] = @pivots[j]; @pivots[j] = k @pivot_sign = -@pivot_sign end # Compute multipliers. if (j < @row_count && @lu[j][j] != 0) (j+1).upto(@row_count-1) do |i| @lu[i][j] = @lu[i][j].quo(@lu[j][j]) end end end end end end PK!qVV(2.2.0/matrix/eigenvalue_decomposition.rbnu[class Matrix # Adapted from JAMA: http://math.nist.gov/javanumerics/jama/ # Eigenvalues and eigenvectors of a real matrix. # # Computes the eigenvalues and eigenvectors of a matrix A. # # If A is diagonalizable, this provides matrices V and D # such that A = V*D*V.inv, where D is the diagonal matrix with entries # equal to the eigenvalues and V is formed by the eigenvectors. # # If A is symmetric, then V is orthogonal and thus A = V*D*V.t class EigenvalueDecomposition # Constructs the eigenvalue decomposition for a square matrix +A+ # def initialize(a) # @d, @e: Arrays for internal storage of eigenvalues. # @v: Array for internal storage of eigenvectors. # @h: Array for internal storage of nonsymmetric Hessenberg form. raise TypeError, "Expected Matrix but got #{a.class}" unless a.is_a?(Matrix) @size = a.row_count @d = Array.new(@size, 0) @e = Array.new(@size, 0) if (@symmetric = a.symmetric?) @v = a.to_a tridiagonalize diagonalize else @v = Array.new(@size) { Array.new(@size, 0) } @h = a.to_a @ort = Array.new(@size, 0) reduce_to_hessenberg hessenberg_to_real_schur end end # Returns the eigenvector matrix +V+ # def eigenvector_matrix Matrix.send(:new, build_eigenvectors.transpose) end alias v eigenvector_matrix # Returns the inverse of the eigenvector matrix +V+ # def eigenvector_matrix_inv r = Matrix.send(:new, build_eigenvectors) r = r.transpose.inverse unless @symmetric r end alias v_inv eigenvector_matrix_inv # Returns the eigenvalues in an array # def eigenvalues values = @d.dup @e.each_with_index{|imag, i| values[i] = Complex(values[i], imag) unless imag == 0} values end # Returns an array of the eigenvectors # def eigenvectors build_eigenvectors.map{|ev| Vector.send(:new, ev)} end # Returns the block diagonal eigenvalue matrix +D+ # def eigenvalue_matrix Matrix.diagonal(*eigenvalues) end alias d eigenvalue_matrix # Returns [eigenvector_matrix, eigenvalue_matrix, eigenvector_matrix_inv] # def to_ary [v, d, v_inv] end alias_method :to_a, :to_ary private def build_eigenvectors # JAMA stores complex eigenvectors in a strange way # See http://web.archive.org/web/20111016032731/http://cio.nist.gov/esd/emaildir/lists/jama/msg01021.html @e.each_with_index.map do |imag, i| if imag == 0 Array.new(@size){|j| @v[j][i]} elsif imag > 0 Array.new(@size){|j| Complex(@v[j][i], @v[j][i+1])} else Array.new(@size){|j| Complex(@v[j][i-1], -@v[j][i])} end end end # Complex scalar division. def cdiv(xr, xi, yr, yi) if (yr.abs > yi.abs) r = yi/yr d = yr + r*yi [(xr + r*xi)/d, (xi - r*xr)/d] else r = yr/yi d = yi + r*yr [(r*xr + xi)/d, (r*xi - xr)/d] end end # Symmetric Householder reduction to tridiagonal form. def tridiagonalize # This is derived from the Algol procedures tred2 by # Bowdler, Martin, Reinsch, and Wilkinson, Handbook for # Auto. Comp., Vol.ii-Linear Algebra, and the corresponding # Fortran subroutine in EISPACK. @size.times do |j| @d[j] = @v[@size-1][j] end # Householder reduction to tridiagonal form. (@size-1).downto(0+1) do |i| # Scale to avoid under/overflow. scale = 0.0 h = 0.0 i.times do |k| scale = scale + @d[k].abs end if (scale == 0.0) @e[i] = @d[i-1] i.times do |j| @d[j] = @v[i-1][j] @v[i][j] = 0.0 @v[j][i] = 0.0 end else # Generate Householder vector. i.times do |k| @d[k] /= scale h += @d[k] * @d[k] end f = @d[i-1] g = Math.sqrt(h) if (f > 0) g = -g end @e[i] = scale * g h -= f * g @d[i-1] = f - g i.times do |j| @e[j] = 0.0 end # Apply similarity transformation to remaining columns. i.times do |j| f = @d[j] @v[j][i] = f g = @e[j] + @v[j][j] * f (j+1).upto(i-1) do |k| g += @v[k][j] * @d[k] @e[k] += @v[k][j] * f end @e[j] = g end f = 0.0 i.times do |j| @e[j] /= h f += @e[j] * @d[j] end hh = f / (h + h) i.times do |j| @e[j] -= hh * @d[j] end i.times do |j| f = @d[j] g = @e[j] j.upto(i-1) do |k| @v[k][j] -= (f * @e[k] + g * @d[k]) end @d[j] = @v[i-1][j] @v[i][j] = 0.0 end end @d[i] = h end # Accumulate transformations. 0.upto(@size-1-1) do |i| @v[@size-1][i] = @v[i][i] @v[i][i] = 1.0 h = @d[i+1] if (h != 0.0) 0.upto(i) do |k| @d[k] = @v[k][i+1] / h end 0.upto(i) do |j| g = 0.0 0.upto(i) do |k| g += @v[k][i+1] * @v[k][j] end 0.upto(i) do |k| @v[k][j] -= g * @d[k] end end end 0.upto(i) do |k| @v[k][i+1] = 0.0 end end @size.times do |j| @d[j] = @v[@size-1][j] @v[@size-1][j] = 0.0 end @v[@size-1][@size-1] = 1.0 @e[0] = 0.0 end # Symmetric tridiagonal QL algorithm. def diagonalize # This is derived from the Algol procedures tql2, by # Bowdler, Martin, Reinsch, and Wilkinson, Handbook for # Auto. Comp., Vol.ii-Linear Algebra, and the corresponding # Fortran subroutine in EISPACK. 1.upto(@size-1) do |i| @e[i-1] = @e[i] end @e[@size-1] = 0.0 f = 0.0 tst1 = 0.0 eps = Float::EPSILON @size.times do |l| # Find small subdiagonal element tst1 = [tst1, @d[l].abs + @e[l].abs].max m = l while (m < @size) do if (@e[m].abs <= eps*tst1) break end m+=1 end # If m == l, @d[l] is an eigenvalue, # otherwise, iterate. if (m > l) iter = 0 begin iter = iter + 1 # (Could check iteration count here.) # Compute implicit shift g = @d[l] p = (@d[l+1] - g) / (2.0 * @e[l]) r = Math.hypot(p, 1.0) if (p < 0) r = -r end @d[l] = @e[l] / (p + r) @d[l+1] = @e[l] * (p + r) dl1 = @d[l+1] h = g - @d[l] (l+2).upto(@size-1) do |i| @d[i] -= h end f += h # Implicit QL transformation. p = @d[m] c = 1.0 c2 = c c3 = c el1 = @e[l+1] s = 0.0 s2 = 0.0 (m-1).downto(l) do |i| c3 = c2 c2 = c s2 = s g = c * @e[i] h = c * p r = Math.hypot(p, @e[i]) @e[i+1] = s * r s = @e[i] / r c = p / r p = c * @d[i] - s * g @d[i+1] = h + s * (c * g + s * @d[i]) # Accumulate transformation. @size.times do |k| h = @v[k][i+1] @v[k][i+1] = s * @v[k][i] + c * h @v[k][i] = c * @v[k][i] - s * h end end p = -s * s2 * c3 * el1 * @e[l] / dl1 @e[l] = s * p @d[l] = c * p # Check for convergence. end while (@e[l].abs > eps*tst1) end @d[l] = @d[l] + f @e[l] = 0.0 end # Sort eigenvalues and corresponding vectors. 0.upto(@size-2) do |i| k = i p = @d[i] (i+1).upto(@size-1) do |j| if (@d[j] < p) k = j p = @d[j] end end if (k != i) @d[k] = @d[i] @d[i] = p @size.times do |j| p = @v[j][i] @v[j][i] = @v[j][k] @v[j][k] = p end end end end # Nonsymmetric reduction to Hessenberg form. def reduce_to_hessenberg # This is derived from the Algol procedures orthes and ortran, # by Martin and Wilkinson, Handbook for Auto. Comp., # Vol.ii-Linear Algebra, and the corresponding # Fortran subroutines in EISPACK. low = 0 high = @size-1 (low+1).upto(high-1) do |m| # Scale column. scale = 0.0 m.upto(high) do |i| scale = scale + @h[i][m-1].abs end if (scale != 0.0) # Compute Householder transformation. h = 0.0 high.downto(m) do |i| @ort[i] = @h[i][m-1]/scale h += @ort[i] * @ort[i] end g = Math.sqrt(h) if (@ort[m] > 0) g = -g end h -= @ort[m] * g @ort[m] = @ort[m] - g # Apply Householder similarity transformation # @h = (I-u*u'/h)*@h*(I-u*u')/h) m.upto(@size-1) do |j| f = 0.0 high.downto(m) do |i| f += @ort[i]*@h[i][j] end f = f/h m.upto(high) do |i| @h[i][j] -= f*@ort[i] end end 0.upto(high) do |i| f = 0.0 high.downto(m) do |j| f += @ort[j]*@h[i][j] end f = f/h m.upto(high) do |j| @h[i][j] -= f*@ort[j] end end @ort[m] = scale*@ort[m] @h[m][m-1] = scale*g end end # Accumulate transformations (Algol's ortran). @size.times do |i| @size.times do |j| @v[i][j] = (i == j ? 1.0 : 0.0) end end (high-1).downto(low+1) do |m| if (@h[m][m-1] != 0.0) (m+1).upto(high) do |i| @ort[i] = @h[i][m-1] end m.upto(high) do |j| g = 0.0 m.upto(high) do |i| g += @ort[i] * @v[i][j] end # Double division avoids possible underflow g = (g / @ort[m]) / @h[m][m-1] m.upto(high) do |i| @v[i][j] += g * @ort[i] end end end end end # Nonsymmetric reduction from Hessenberg to real Schur form. def hessenberg_to_real_schur # This is derived from the Algol procedure hqr2, # by Martin and Wilkinson, Handbook for Auto. Comp., # Vol.ii-Linear Algebra, and the corresponding # Fortran subroutine in EISPACK. # Initialize nn = @size n = nn-1 low = 0 high = nn-1 eps = Float::EPSILON exshift = 0.0 p=q=r=s=z=0 # Store roots isolated by balanc and compute matrix norm norm = 0.0 nn.times do |i| if (i < low || i > high) @d[i] = @h[i][i] @e[i] = 0.0 end ([i-1, 0].max).upto(nn-1) do |j| norm = norm + @h[i][j].abs end end # Outer loop over eigenvalue index iter = 0 while (n >= low) do # Look for single small sub-diagonal element l = n while (l > low) do s = @h[l-1][l-1].abs + @h[l][l].abs if (s == 0.0) s = norm end if (@h[l][l-1].abs < eps * s) break end l-=1 end # Check for convergence # One root found if (l == n) @h[n][n] = @h[n][n] + exshift @d[n] = @h[n][n] @e[n] = 0.0 n-=1 iter = 0 # Two roots found elsif (l == n-1) w = @h[n][n-1] * @h[n-1][n] p = (@h[n-1][n-1] - @h[n][n]) / 2.0 q = p * p + w z = Math.sqrt(q.abs) @h[n][n] = @h[n][n] + exshift @h[n-1][n-1] = @h[n-1][n-1] + exshift x = @h[n][n] # Real pair if (q >= 0) if (p >= 0) z = p + z else z = p - z end @d[n-1] = x + z @d[n] = @d[n-1] if (z != 0.0) @d[n] = x - w / z end @e[n-1] = 0.0 @e[n] = 0.0 x = @h[n][n-1] s = x.abs + z.abs p = x / s q = z / s r = Math.sqrt(p * p+q * q) p /= r q /= r # Row modification (n-1).upto(nn-1) do |j| z = @h[n-1][j] @h[n-1][j] = q * z + p * @h[n][j] @h[n][j] = q * @h[n][j] - p * z end # Column modification 0.upto(n) do |i| z = @h[i][n-1] @h[i][n-1] = q * z + p * @h[i][n] @h[i][n] = q * @h[i][n] - p * z end # Accumulate transformations low.upto(high) do |i| z = @v[i][n-1] @v[i][n-1] = q * z + p * @v[i][n] @v[i][n] = q * @v[i][n] - p * z end # Complex pair else @d[n-1] = x + p @d[n] = x + p @e[n-1] = z @e[n] = -z end n -= 2 iter = 0 # No convergence yet else # Form shift x = @h[n][n] y = 0.0 w = 0.0 if (l < n) y = @h[n-1][n-1] w = @h[n][n-1] * @h[n-1][n] end # Wilkinson's original ad hoc shift if (iter == 10) exshift += x low.upto(n) do |i| @h[i][i] -= x end s = @h[n][n-1].abs + @h[n-1][n-2].abs x = y = 0.75 * s w = -0.4375 * s * s end # MATLAB's new ad hoc shift if (iter == 30) s = (y - x) / 2.0 s *= s + w if (s > 0) s = Math.sqrt(s) if (y < x) s = -s end s = x - w / ((y - x) / 2.0 + s) low.upto(n) do |i| @h[i][i] -= s end exshift += s x = y = w = 0.964 end end iter = iter + 1 # (Could check iteration count here.) # Look for two consecutive small sub-diagonal elements m = n-2 while (m >= l) do z = @h[m][m] r = x - z s = y - z p = (r * s - w) / @h[m+1][m] + @h[m][m+1] q = @h[m+1][m+1] - z - r - s r = @h[m+2][m+1] s = p.abs + q.abs + r.abs p /= s q /= s r /= s if (m == l) break end if (@h[m][m-1].abs * (q.abs + r.abs) < eps * (p.abs * (@h[m-1][m-1].abs + z.abs + @h[m+1][m+1].abs))) break end m-=1 end (m+2).upto(n) do |i| @h[i][i-2] = 0.0 if (i > m+2) @h[i][i-3] = 0.0 end end # Double QR step involving rows l:n and columns m:n m.upto(n-1) do |k| notlast = (k != n-1) if (k != m) p = @h[k][k-1] q = @h[k+1][k-1] r = (notlast ? @h[k+2][k-1] : 0.0) x = p.abs + q.abs + r.abs next if x == 0 p /= x q /= x r /= x end s = Math.sqrt(p * p + q * q + r * r) if (p < 0) s = -s end if (s != 0) if (k != m) @h[k][k-1] = -s * x elsif (l != m) @h[k][k-1] = -@h[k][k-1] end p += s x = p / s y = q / s z = r / s q /= p r /= p # Row modification k.upto(nn-1) do |j| p = @h[k][j] + q * @h[k+1][j] if (notlast) p += r * @h[k+2][j] @h[k+2][j] = @h[k+2][j] - p * z end @h[k][j] = @h[k][j] - p * x @h[k+1][j] = @h[k+1][j] - p * y end # Column modification 0.upto([n, k+3].min) do |i| p = x * @h[i][k] + y * @h[i][k+1] if (notlast) p += z * @h[i][k+2] @h[i][k+2] = @h[i][k+2] - p * r end @h[i][k] = @h[i][k] - p @h[i][k+1] = @h[i][k+1] - p * q end # Accumulate transformations low.upto(high) do |i| p = x * @v[i][k] + y * @v[i][k+1] if (notlast) p += z * @v[i][k+2] @v[i][k+2] = @v[i][k+2] - p * r end @v[i][k] = @v[i][k] - p @v[i][k+1] = @v[i][k+1] - p * q end end # (s != 0) end # k loop end # check convergence end # while (n >= low) # Backsubstitute to find vectors of upper triangular form if (norm == 0.0) return end (nn-1).downto(0) do |n| p = @d[n] q = @e[n] # Real vector if (q == 0) l = n @h[n][n] = 1.0 (n-1).downto(0) do |i| w = @h[i][i] - p r = 0.0 l.upto(n) do |j| r += @h[i][j] * @h[j][n] end if (@e[i] < 0.0) z = w s = r else l = i if (@e[i] == 0.0) if (w != 0.0) @h[i][n] = -r / w else @h[i][n] = -r / (eps * norm) end # Solve real equations else x = @h[i][i+1] y = @h[i+1][i] q = (@d[i] - p) * (@d[i] - p) + @e[i] * @e[i] t = (x * s - z * r) / q @h[i][n] = t if (x.abs > z.abs) @h[i+1][n] = (-r - w * t) / x else @h[i+1][n] = (-s - y * t) / z end end # Overflow control t = @h[i][n].abs if ((eps * t) * t > 1) i.upto(n) do |j| @h[j][n] = @h[j][n] / t end end end end # Complex vector elsif (q < 0) l = n-1 # Last vector component imaginary so matrix is triangular if (@h[n][n-1].abs > @h[n-1][n].abs) @h[n-1][n-1] = q / @h[n][n-1] @h[n-1][n] = -(@h[n][n] - p) / @h[n][n-1] else cdivr, cdivi = cdiv(0.0, -@h[n-1][n], @h[n-1][n-1]-p, q) @h[n-1][n-1] = cdivr @h[n-1][n] = cdivi end @h[n][n-1] = 0.0 @h[n][n] = 1.0 (n-2).downto(0) do |i| ra = 0.0 sa = 0.0 l.upto(n) do |j| ra = ra + @h[i][j] * @h[j][n-1] sa = sa + @h[i][j] * @h[j][n] end w = @h[i][i] - p if (@e[i] < 0.0) z = w r = ra s = sa else l = i if (@e[i] == 0) cdivr, cdivi = cdiv(-ra, -sa, w, q) @h[i][n-1] = cdivr @h[i][n] = cdivi else # Solve complex equations x = @h[i][i+1] y = @h[i+1][i] vr = (@d[i] - p) * (@d[i] - p) + @e[i] * @e[i] - q * q vi = (@d[i] - p) * 2.0 * q if (vr == 0.0 && vi == 0.0) vr = eps * norm * (w.abs + q.abs + x.abs + y.abs + z.abs) end cdivr, cdivi = cdiv(x*r-z*ra+q*sa, x*s-z*sa-q*ra, vr, vi) @h[i][n-1] = cdivr @h[i][n] = cdivi if (x.abs > (z.abs + q.abs)) @h[i+1][n-1] = (-ra - w * @h[i][n-1] + q * @h[i][n]) / x @h[i+1][n] = (-sa - w * @h[i][n] - q * @h[i][n-1]) / x else cdivr, cdivi = cdiv(-r-y*@h[i][n-1], -s-y*@h[i][n], z, q) @h[i+1][n-1] = cdivr @h[i+1][n] = cdivi end end # Overflow control t = [@h[i][n-1].abs, @h[i][n].abs].max if ((eps * t) * t > 1) i.upto(n) do |j| @h[j][n-1] = @h[j][n-1] / t @h[j][n] = @h[j][n] / t end end end end end end # Vectors of isolated roots nn.times do |i| if (i < low || i > high) i.upto(nn-1) do |j| @v[i][j] = @h[i][j] end end end # Back transformation to get eigenvectors of original matrix (nn-1).downto(low) do |j| low.upto(high) do |i| z = 0.0 low.upto([j, high].min) do |k| z += @v[i][k] * @h[k][j] end @v[i][j] = z end end end end end PK!R 2.2.0/abbrev.rbnu[#-- # Copyright (c) 2001,2003 Akinori MUSHA # # All rights reserved. You can redistribute and/or modify it under # the same terms as Ruby. # # $Idaemons: /home/cvs/rb/abbrev.rb,v 1.2 2001/05/30 09:37:45 knu Exp $ # $RoughId: abbrev.rb,v 1.4 2003/10/14 19:45:42 knu Exp $ # $Id: abbrev.rb 46784 2014-07-11 08:16:05Z hsbt $ #++ ## # Calculates the set of unambiguous abbreviations for a given set of strings. # # require 'abbrev' # require 'pp' # # pp Abbrev.abbrev(['ruby']) # #=> {"ruby"=>"ruby", "rub"=>"ruby", "ru"=>"ruby", "r"=>"ruby"} # # pp Abbrev.abbrev(%w{ ruby rules }) # # _Generates:_ # { "ruby" => "ruby", # "rub" => "ruby", # "rules" => "rules", # "rule" => "rules", # "rul" => "rules" } # # It also provides an array core extension, Array#abbrev. # # pp %w{ summer winter }.abbrev # # _Generates:_ # { "summer" => "summer", # "summe" => "summer", # "summ" => "summer", # "sum" => "summer", # "su" => "summer", # "s" => "summer", # "winter" => "winter", # "winte" => "winter", # "wint" => "winter", # "win" => "winter", # "wi" => "winter", # "w" => "winter" } module Abbrev # Given a set of strings, calculate the set of unambiguous abbreviations for # those strings, and return a hash where the keys are all the possible # abbreviations and the values are the full strings. # # Thus, given +words+ is "car" and "cone", the keys pointing to "car" would # be "ca" and "car", while those pointing to "cone" would be "co", "con", and # "cone". # # require 'abbrev' # # Abbrev.abbrev(%w{ car cone }) # #=> {"ca"=>"car", "con"=>"cone", "co"=>"cone", "car"=>"car", "cone"=>"cone"} # # The optional +pattern+ parameter is a pattern or a string. Only input # strings that match the pattern or start with the string are included in the # output hash. # # Abbrev.abbrev(%w{car box cone crab}, /b/) # #=> {"box"=>"box", "bo"=>"box", "b"=>"box", "crab" => "crab"} # # Abbrev.abbrev(%w{car box cone}, 'ca') # #=> {"car"=>"car", "ca"=>"car"} def abbrev(words, pattern = nil) table = {} seen = Hash.new(0) if pattern.is_a?(String) pattern = /\A#{Regexp.quote(pattern)}/ # regard as a prefix end words.each do |word| next if word.empty? word.size.downto(1) { |len| abbrev = word[0...len] next if pattern && pattern !~ abbrev case seen[abbrev] += 1 when 1 table[abbrev] = word when 2 table.delete(abbrev) else break end } end words.each do |word| next if pattern && pattern !~ word table[word] = word end table end module_function :abbrev end class Array # Calculates the set of unambiguous abbreviations for the strings in +self+. # # require 'abbrev' # %w{ car cone }.abbrev # #=> {"car"=>"car", "ca"=>"car", "cone"=>"cone", "con"=>"cone", "co"=>"cone"} # # The optional +pattern+ parameter is a pattern or a string. Only input # strings that match the pattern or start with the string are included in the # output hash. # # %w{ fast boat day }.abbrev(/^.a/) # #=> {"fast"=>"fast", "fas"=>"fast", "fa"=>"fast", "day"=>"day", "da"=>"day"} # # Abbrev.abbrev(%w{car box cone}, "ca") # #=> {"car"=>"car", "ca"=>"car"} # # See also Abbrev.abbrev def abbrev(pattern = nil) Abbrev::abbrev(self, pattern) end end PK!ޖ2.2.0/shellwords.rbnu[## # == Manipulates strings like the UNIX Bourne shell # # This module manipulates strings according to the word parsing rules # of the UNIX Bourne shell. # # The shellwords() function was originally a port of shellwords.pl, # but modified to conform to POSIX / SUSv3 (IEEE Std 1003.1-2001 [1]). # # === Usage # # You can use Shellwords to parse a string into a Bourne shell friendly Array. # # require 'shellwords' # # argv = Shellwords.split('three blind "mice"') # argv #=> ["three", "blind", "mice"] # # Once you've required Shellwords, you can use the #split alias # String#shellsplit. # # argv = "see how they run".shellsplit # argv #=> ["see", "how", "they", "run"] # # Be careful you don't leave a quote unmatched. # # argv = "they all ran after the farmer's wife".shellsplit # #=> ArgumentError: Unmatched double quote: ... # # In this case, you might want to use Shellwords.escape, or its alias # String#shellescape. # # This method will escape the String for you to safely use with a Bourne shell. # # argv = Shellwords.escape("special's.txt") # argv #=> "special\\'s.txt" # system("cat " + argv) # # Shellwords also comes with a core extension for Array, Array#shelljoin. # # argv = %w{ls -lta lib} # system(argv.shelljoin) # # You can use this method to create an escaped string out of an array of tokens # separated by a space. In this example we used the literal shortcut for # Array.new. # # === Authors # * Wakou Aoyama # * Akinori MUSHA # # === Contact # * Akinori MUSHA (current maintainer) # # === Resources # # 1: {IEEE Std 1003.1-2004}[http://pubs.opengroup.org/onlinepubs/009695399/toc.htm] module Shellwords # Splits a string into an array of tokens in the same way the UNIX # Bourne shell does. # # argv = Shellwords.split('here are "two words"') # argv #=> ["here", "are", "two words"] # # String#shellsplit is a shortcut for this function. # # argv = 'here are "two words"'.shellsplit # argv #=> ["here", "are", "two words"] def shellsplit(line) words = [] field = '' line.scan(/\G\s*(?>([^\s\\\'\"]+)|'([^\']*)'|"((?:[^\"\\]|\\.)*)"|(\\.?)|(\S))(\s|\z)?/m) do |word, sq, dq, esc, garbage, sep| raise ArgumentError, "Unmatched double quote: #{line.inspect}" if garbage field << (word || sq || (dq || esc).gsub(/\\(.)/, '\\1')) if sep words << field field = '' end end words end alias shellwords shellsplit module_function :shellsplit, :shellwords class << self alias split shellsplit end # Escapes a string so that it can be safely used in a Bourne shell # command line. +str+ can be a non-string object that responds to # +to_s+. # # Note that a resulted string should be used unquoted and is not # intended for use in double quotes nor in single quotes. # # argv = Shellwords.escape("It's better to give than to receive") # argv #=> "It\\'s\\ better\\ to\\ give\\ than\\ to\\ receive" # # String#shellescape is a shorthand for this function. # # argv = "It's better to give than to receive".shellescape # argv #=> "It\\'s\\ better\\ to\\ give\\ than\\ to\\ receive" # # # Search files in lib for method definitions # pattern = "^[ \t]*def " # open("| grep -Ern #{pattern.shellescape} lib") { |grep| # grep.each_line { |line| # file, lineno, matched_line = line.split(':', 3) # # ... # } # } # # It is the caller's responsibility to encode the string in the right # encoding for the shell environment where this string is used. # # Multibyte characters are treated as multibyte characters, not as bytes. # # Returns an empty quoted String if +str+ has a length of zero. def shellescape(str) str = str.to_s # An empty argument will be skipped, so return empty quotes. return "''" if str.empty? str = str.dup # Treat multibyte characters as is. It is the caller's responsibility # to encode the string in the right encoding for the shell # environment. str.gsub!(/([^A-Za-z0-9_\-.,:\/@\n])/, "\\\\\\1") # A LF cannot be escaped with a backslash because a backslash + LF # combo is regarded as a line continuation and simply ignored. str.gsub!(/\n/, "'\n'") return str end module_function :shellescape class << self alias escape shellescape end # Builds a command line string from an argument list, +array+. # # All elements are joined into a single string with fields separated by a # space, where each element is escaped for the Bourne shell and stringified # using +to_s+. # # ary = ["There's", "a", "time", "and", "place", "for", "everything"] # argv = Shellwords.join(ary) # argv #=> "There\\'s a time and place for everything" # # Array#shelljoin is a shortcut for this function. # # ary = ["Don't", "rock", "the", "boat"] # argv = ary.shelljoin # argv #=> "Don\\'t rock the boat" # # You can also mix non-string objects in the elements as allowed in Array#join. # # output = `#{['ps', '-p', $$].shelljoin}` # def shelljoin(array) array.map { |arg| shellescape(arg) }.join(' ') end module_function :shelljoin class << self alias join shelljoin end end class String # call-seq: # str.shellsplit => array # # Splits +str+ into an array of tokens in the same way the UNIX # Bourne shell does. # # See Shellwords.shellsplit for details. def shellsplit Shellwords.split(self) end # call-seq: # str.shellescape => string # # Escapes +str+ so that it can be safely used in a Bourne shell # command line. # # See Shellwords.shellescape for details. def shellescape Shellwords.escape(self) end end class Array # call-seq: # array.shelljoin => string # # Builds a command line string from an argument list +array+ joining # all elements escaped for the Bourne shell and separated by a space. # # See Shellwords.shelljoin for details. def shelljoin Shellwords.join(self) end end PK!g288 2.2.0/pp.rbnu[require 'prettyprint' module Kernel # Returns a pretty printed object as a string. # # In order to use this method you must first require the PP module: # # require 'pp' # # See the PP module for more information. def pretty_inspect PP.pp(self, '') end private # prints arguments in pretty form. # # pp returns argument(s). def pp(*objs) # :nodoc: objs.each {|obj| PP.pp(obj) } objs.size <= 1 ? objs.first : objs end module_function :pp # :nodoc: end ## # A pretty-printer for Ruby objects. # # All examples assume you have loaded the PP class with: # require 'pp' # ## # == What PP Does # # Standard output by #p returns this: # #, @group_queue=#], []]>, @buffer=[], @newline="\n", @group_stack=[#], @buffer_width=0, @indent=0, @maxwidth=79, @output_width=2, @output=#> # # Pretty-printed output returns this: # #, # @group_queue= # #], # []]>, # @group_stack= # [#], # @indent=0, # @maxwidth=79, # @newline="\n", # @output=#, # @output_width=2> # ## # == Usage # # pp(obj) #=> obj # pp obj #=> obj # pp(obj1, obj2, ...) #=> [obj1, obj2, ...] # pp() #=> nil # # Output obj(s) to $> in pretty printed format. # # It returns obj(s). # ## # == Output Customization # # To define a customized pretty printing function for your classes, # redefine method #pretty_print(pp) in the class. # # #pretty_print takes the +pp+ argument, which is an instance of the PP class. # The method uses #text, #breakable, #nest, #group and #pp to print the # object. # ## # == Pretty-Print JSON # # To pretty-print JSON refer to JSON#pretty_generate. # ## # == Author # Tanaka Akira class PP < PrettyPrint # Outputs +obj+ to +out+ in pretty printed format of # +width+ columns in width. # # If +out+ is omitted, $> is assumed. # If +width+ is omitted, 79 is assumed. # # PP.pp returns +out+. def PP.pp(obj, out=$>, width=79) q = PP.new(out, width) q.guard_inspect_key {q.pp obj} q.flush #$pp = q out << "\n" end # Outputs +obj+ to +out+ like PP.pp but with no indent and # newline. # # PP.singleline_pp returns +out+. def PP.singleline_pp(obj, out=$>) q = SingleLine.new(out) q.guard_inspect_key {q.pp obj} q.flush out end # :stopdoc: def PP.mcall(obj, mod, meth, *args, &block) mod.instance_method(meth).bind(obj).call(*args, &block) end # :startdoc: @sharing_detection = false class << self # Returns the sharing detection flag as a boolean value. # It is false by default. attr_accessor :sharing_detection end module PPMethods # Yields to a block # and preserves the previous set of objects being printed. def guard_inspect_key if Thread.current[:__recursive_key__] == nil Thread.current[:__recursive_key__] = {}.taint end if Thread.current[:__recursive_key__][:inspect] == nil Thread.current[:__recursive_key__][:inspect] = {}.taint end save = Thread.current[:__recursive_key__][:inspect] begin Thread.current[:__recursive_key__][:inspect] = {}.taint yield ensure Thread.current[:__recursive_key__][:inspect] = save end end # Check whether the object_id +id+ is in the current buffer of objects # to be pretty printed. Used to break cycles in chains of objects to be # pretty printed. def check_inspect_key(id) Thread.current[:__recursive_key__] && Thread.current[:__recursive_key__][:inspect] && Thread.current[:__recursive_key__][:inspect].include?(id) end # Adds the object_id +id+ to the set of objects being pretty printed, so # as to not repeat objects. def push_inspect_key(id) Thread.current[:__recursive_key__][:inspect][id] = true end # Removes an object from the set of objects being pretty printed. def pop_inspect_key(id) Thread.current[:__recursive_key__][:inspect].delete id end # Adds +obj+ to the pretty printing buffer # using Object#pretty_print or Object#pretty_print_cycle. # # Object#pretty_print_cycle is used when +obj+ is already # printed, a.k.a the object reference chain has a cycle. def pp(obj) id = obj.object_id if check_inspect_key(id) group {obj.pretty_print_cycle self} return end begin push_inspect_key(id) group {obj.pretty_print self} ensure pop_inspect_key(id) unless PP.sharing_detection end end # A convenience method which is same as follows: # # group(1, '#<' + obj.class.name, '>') { ... } def object_group(obj, &block) # :yield: group(1, '#<' + obj.class.name, '>', &block) end # A convenience method, like object_group, but also reformats the Object's # object_id. def object_address_group(obj, &block) str = Kernel.instance_method(:to_s).bind(obj).call str.chomp!('>') group(1, str, '>', &block) end # A convenience method which is same as follows: # # text ',' # breakable def comma_breakable text ',' breakable end # Adds a separated list. # The list is separated by comma with breakable space, by default. # # #seplist iterates the +list+ using +iter_method+. # It yields each object to the block given for #seplist. # The procedure +separator_proc+ is called between each yields. # # If the iteration is zero times, +separator_proc+ is not called at all. # # If +separator_proc+ is nil or not given, # +lambda { comma_breakable }+ is used. # If +iter_method+ is not given, :each is used. # # For example, following 3 code fragments has similar effect. # # q.seplist([1,2,3]) {|v| xxx v } # # q.seplist([1,2,3], lambda { q.comma_breakable }, :each) {|v| xxx v } # # xxx 1 # q.comma_breakable # xxx 2 # q.comma_breakable # xxx 3 def seplist(list, sep=nil, iter_method=:each) # :yield: element sep ||= lambda { comma_breakable } first = true list.__send__(iter_method) {|*v| if first first = false else sep.call end yield(*v) } end # A present standard failsafe for pretty printing any given Object def pp_object(obj) object_address_group(obj) { seplist(obj.pretty_print_instance_variables, lambda { text ',' }) {|v| breakable v = v.to_s if Symbol === v text v text '=' group(1) { breakable '' pp(obj.instance_eval(v)) } } } end # A pretty print for a Hash def pp_hash(obj) group(1, '{', '}') { seplist(obj, nil, :each_pair) {|k, v| group { pp k text '=>' group(1) { breakable '' pp v } } } } end end include PPMethods class SingleLine < PrettyPrint::SingleLine # :nodoc: include PPMethods end module ObjectMixin # :nodoc: # 1. specific pretty_print # 2. specific inspect # 3. generic pretty_print # A default pretty printing method for general objects. # It calls #pretty_print_instance_variables to list instance variables. # # If +self+ has a customized (redefined) #inspect method, # the result of self.inspect is used but it obviously has no # line break hints. # # This module provides predefined #pretty_print methods for some of # the most commonly used built-in classes for convenience. def pretty_print(q) method_method = Object.instance_method(:method).bind(self) begin inspect_method = method_method.call(:inspect) rescue NameError end if inspect_method && /\(Kernel\)#/ !~ inspect_method.inspect q.text self.inspect elsif !inspect_method && self.respond_to?(:inspect) q.text self.inspect else q.pp_object(self) end end # A default pretty printing method for general objects that are # detected as part of a cycle. def pretty_print_cycle(q) q.object_address_group(self) { q.breakable q.text '...' } end # Returns a sorted array of instance variable names. # # This method should return an array of names of instance variables as symbols or strings as: # +[:@a, :@b]+. def pretty_print_instance_variables instance_variables.sort end # Is #inspect implementation using #pretty_print. # If you implement #pretty_print, it can be used as follows. # # alias inspect pretty_print_inspect # # However, doing this requires that every class that #inspect is called on # implement #pretty_print, or a RuntimeError will be raised. def pretty_print_inspect if /\(PP::ObjectMixin\)#/ =~ Object.instance_method(:method).bind(self).call(:pretty_print).inspect raise "pretty_print is not overridden for #{self.class}" end PP.singleline_pp(self, '') end end end class Array # :nodoc: def pretty_print(q) # :nodoc: q.group(1, '[', ']') { q.seplist(self) {|v| q.pp v } } end def pretty_print_cycle(q) # :nodoc: q.text(empty? ? '[]' : '[...]') end end class Hash # :nodoc: def pretty_print(q) # :nodoc: q.pp_hash self end def pretty_print_cycle(q) # :nodoc: q.text(empty? ? '{}' : '{...}') end end class << ENV # :nodoc: def pretty_print(q) # :nodoc: h = {} ENV.keys.sort.each {|k| h[k] = ENV[k] } q.pp_hash h end end class Struct # :nodoc: def pretty_print(q) # :nodoc: q.group(1, sprintf("#') { q.seplist(PP.mcall(self, Struct, :members), lambda { q.text "," }) {|member| q.breakable q.text member.to_s q.text '=' q.group(1) { q.breakable '' q.pp self[member] } } } end def pretty_print_cycle(q) # :nodoc: q.text sprintf("#", PP.mcall(self, Kernel, :class).name) end end class Range # :nodoc: def pretty_print(q) # :nodoc: q.pp self.begin q.breakable '' q.text(self.exclude_end? ? '...' : '..') q.breakable '' q.pp self.end end end class File < IO # :nodoc: class Stat # :nodoc: def pretty_print(q) # :nodoc: require 'etc.so' q.object_group(self) { q.breakable q.text sprintf("dev=0x%x", self.dev); q.comma_breakable q.text "ino="; q.pp self.ino; q.comma_breakable q.group { m = self.mode q.text sprintf("mode=0%o", m) q.breakable q.text sprintf("(%s %c%c%c%c%c%c%c%c%c)", self.ftype, (m & 0400 == 0 ? ?- : ?r), (m & 0200 == 0 ? ?- : ?w), (m & 0100 == 0 ? (m & 04000 == 0 ? ?- : ?S) : (m & 04000 == 0 ? ?x : ?s)), (m & 0040 == 0 ? ?- : ?r), (m & 0020 == 0 ? ?- : ?w), (m & 0010 == 0 ? (m & 02000 == 0 ? ?- : ?S) : (m & 02000 == 0 ? ?x : ?s)), (m & 0004 == 0 ? ?- : ?r), (m & 0002 == 0 ? ?- : ?w), (m & 0001 == 0 ? (m & 01000 == 0 ? ?- : ?T) : (m & 01000 == 0 ? ?x : ?t))) } q.comma_breakable q.text "nlink="; q.pp self.nlink; q.comma_breakable q.group { q.text "uid="; q.pp self.uid begin pw = Etc.getpwuid(self.uid) rescue ArgumentError end if pw q.breakable; q.text "(#{pw.name})" end } q.comma_breakable q.group { q.text "gid="; q.pp self.gid begin gr = Etc.getgrgid(self.gid) rescue ArgumentError end if gr q.breakable; q.text "(#{gr.name})" end } q.comma_breakable q.group { q.text sprintf("rdev=0x%x", self.rdev) if self.rdev_major && self.rdev_minor q.breakable q.text sprintf('(%d, %d)', self.rdev_major, self.rdev_minor) end } q.comma_breakable q.text "size="; q.pp self.size; q.comma_breakable q.text "blksize="; q.pp self.blksize; q.comma_breakable q.text "blocks="; q.pp self.blocks; q.comma_breakable q.group { t = self.atime q.text "atime="; q.pp t q.breakable; q.text "(#{t.tv_sec})" } q.comma_breakable q.group { t = self.mtime q.text "mtime="; q.pp t q.breakable; q.text "(#{t.tv_sec})" } q.comma_breakable q.group { t = self.ctime q.text "ctime="; q.pp t q.breakable; q.text "(#{t.tv_sec})" } } end end end class MatchData # :nodoc: def pretty_print(q) # :nodoc: nc = [] self.regexp.named_captures.each {|name, indexes| indexes.each {|i| nc[i] = name } } q.object_group(self) { q.breakable q.seplist(0...self.size, lambda { q.breakable }) {|i| if i == 0 q.pp self[i] else if nc[i] q.text nc[i] else q.pp i end q.text ':' q.pp self[i] end } } end end class Object < BasicObject # :nodoc: include PP::ObjectMixin end [Numeric, Symbol, FalseClass, TrueClass, NilClass, Module].each {|c| c.class_eval { def pretty_print_cycle(q) q.text inspect end } } [Numeric, FalseClass, TrueClass, Module].each {|c| c.class_eval { def pretty_print(q) q.text inspect end } } PK!a:992.2.0/tsort.rbnu[#-- # tsort.rb - provides a module for topological sorting and strongly connected components. #++ # # # TSort implements topological sorting using Tarjan's algorithm for # strongly connected components. # # TSort is designed to be able to be used with any object which can be # interpreted as a directed graph. # # TSort requires two methods to interpret an object as a graph, # tsort_each_node and tsort_each_child. # # * tsort_each_node is used to iterate for all nodes over a graph. # * tsort_each_child is used to iterate for child nodes of a given node. # # The equality of nodes are defined by eql? and hash since # TSort uses Hash internally. # # == A Simple Example # # The following example demonstrates how to mix the TSort module into an # existing class (in this case, Hash). Here, we're treating each key in # the hash as a node in the graph, and so we simply alias the required # #tsort_each_node method to Hash's #each_key method. For each key in the # hash, the associated value is an array of the node's child nodes. This # choice in turn leads to our implementation of the required #tsort_each_child # method, which fetches the array of child nodes and then iterates over that # array using the user-supplied block. # # require 'tsort' # # class Hash # include TSort # alias tsort_each_node each_key # def tsort_each_child(node, &block) # fetch(node).each(&block) # end # end # # {1=>[2, 3], 2=>[3], 3=>[], 4=>[]}.tsort # #=> [3, 2, 1, 4] # # {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}.strongly_connected_components # #=> [[4], [2, 3], [1]] # # == A More Realistic Example # # A very simple `make' like tool can be implemented as follows: # # require 'tsort' # # class Make # def initialize # @dep = {} # @dep.default = [] # end # # def rule(outputs, inputs=[], &block) # triple = [outputs, inputs, block] # outputs.each {|f| @dep[f] = [triple]} # @dep[triple] = inputs # end # # def build(target) # each_strongly_connected_component_from(target) {|ns| # if ns.length != 1 # fs = ns.delete_if {|n| Array === n} # raise TSort::Cyclic.new("cyclic dependencies: #{fs.join ', '}") # end # n = ns.first # if Array === n # outputs, inputs, block = n # inputs_time = inputs.map {|f| File.mtime f}.max # begin # outputs_time = outputs.map {|f| File.mtime f}.min # rescue Errno::ENOENT # outputs_time = nil # end # if outputs_time == nil || # inputs_time != nil && outputs_time <= inputs_time # sleep 1 if inputs_time != nil && inputs_time.to_i == Time.now.to_i # block.call # end # end # } # end # # def tsort_each_child(node, &block) # @dep[node].each(&block) # end # include TSort # end # # def command(arg) # print arg, "\n" # system arg # end # # m = Make.new # m.rule(%w[t1]) { command 'date > t1' } # m.rule(%w[t2]) { command 'date > t2' } # m.rule(%w[t3]) { command 'date > t3' } # m.rule(%w[t4], %w[t1 t3]) { command 'cat t1 t3 > t4' } # m.rule(%w[t5], %w[t4 t2]) { command 'cat t4 t2 > t5' } # m.build('t5') # # == Bugs # # * 'tsort.rb' is wrong name because this library uses # Tarjan's algorithm for strongly connected components. # Although 'strongly_connected_components.rb' is correct but too long. # # == References # # R. E. Tarjan, "Depth First Search and Linear Graph Algorithms", # SIAM Journal on Computing, Vol. 1, No. 2, pp. 146-160, June 1972. # module TSort class Cyclic < StandardError end # Returns a topologically sorted array of nodes. # The array is sorted from children to parents, i.e. # the first element has no child and the last node has no parent. # # If there is a cycle, TSort::Cyclic is raised. # # class G # include TSort # def initialize(g) # @g = g # end # def tsort_each_child(n, &b) @g[n].each(&b) end # def tsort_each_node(&b) @g.each_key(&b) end # end # # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]}) # p graph.tsort #=> [4, 2, 3, 1] # # graph = G.new({1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}) # p graph.tsort # raises TSort::Cyclic # def tsort each_node = method(:tsort_each_node) each_child = method(:tsort_each_child) TSort.tsort(each_node, each_child) end # Returns a topologically sorted array of nodes. # The array is sorted from children to parents, i.e. # the first element has no child and the last node has no parent. # # The graph is represented by _each_node_ and _each_child_. # _each_node_ should have +call+ method which yields for each node in the graph. # _each_child_ should have +call+ method which takes a node argument and yields for each child node. # # If there is a cycle, TSort::Cyclic is raised. # # g = {1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]} # each_node = lambda {|&b| g.each_key(&b) } # each_child = lambda {|n, &b| g[n].each(&b) } # p TSort.tsort(each_node, each_child) #=> [4, 2, 3, 1] # # g = {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]} # each_node = lambda {|&b| g.each_key(&b) } # each_child = lambda {|n, &b| g[n].each(&b) } # p TSort.tsort(each_node, each_child) # raises TSort::Cyclic # def TSort.tsort(each_node, each_child) TSort.tsort_each(each_node, each_child).to_a end # The iterator version of the #tsort method. # obj.tsort_each is similar to obj.tsort.each, but # modification of _obj_ during the iteration may lead to unexpected results. # # #tsort_each returns +nil+. # If there is a cycle, TSort::Cyclic is raised. # # class G # include TSort # def initialize(g) # @g = g # end # def tsort_each_child(n, &b) @g[n].each(&b) end # def tsort_each_node(&b) @g.each_key(&b) end # end # # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]}) # graph.tsort_each {|n| p n } # #=> 4 # # 2 # # 3 # # 1 # def tsort_each(&block) # :yields: node each_node = method(:tsort_each_node) each_child = method(:tsort_each_child) TSort.tsort_each(each_node, each_child, &block) end # The iterator version of the TSort.tsort method. # # The graph is represented by _each_node_ and _each_child_. # _each_node_ should have +call+ method which yields for each node in the graph. # _each_child_ should have +call+ method which takes a node argument and yields for each child node. # # g = {1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]} # each_node = lambda {|&b| g.each_key(&b) } # each_child = lambda {|n, &b| g[n].each(&b) } # TSort.tsort_each(each_node, each_child) {|n| p n } # #=> 4 # # 2 # # 3 # # 1 # def TSort.tsort_each(each_node, each_child) # :yields: node return to_enum(__method__, each_node, each_child) unless block_given? TSort.each_strongly_connected_component(each_node, each_child) {|component| if component.size == 1 yield component.first else raise Cyclic.new("topological sort failed: #{component.inspect}") end } end # Returns strongly connected components as an array of arrays of nodes. # The array is sorted from children to parents. # Each elements of the array represents a strongly connected component. # # class G # include TSort # def initialize(g) # @g = g # end # def tsort_each_child(n, &b) @g[n].each(&b) end # def tsort_each_node(&b) @g.each_key(&b) end # end # # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]}) # p graph.strongly_connected_components #=> [[4], [2], [3], [1]] # # graph = G.new({1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}) # p graph.strongly_connected_components #=> [[4], [2, 3], [1]] # def strongly_connected_components each_node = method(:tsort_each_node) each_child = method(:tsort_each_child) TSort.strongly_connected_components(each_node, each_child) end # Returns strongly connected components as an array of arrays of nodes. # The array is sorted from children to parents. # Each elements of the array represents a strongly connected component. # # The graph is represented by _each_node_ and _each_child_. # _each_node_ should have +call+ method which yields for each node in the graph. # _each_child_ should have +call+ method which takes a node argument and yields for each child node. # # g = {1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]} # each_node = lambda {|&b| g.each_key(&b) } # each_child = lambda {|n, &b| g[n].each(&b) } # p TSort.strongly_connected_components(each_node, each_child) # #=> [[4], [2], [3], [1]] # # g = {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]} # each_node = lambda {|&b| g.each_key(&b) } # each_child = lambda {|n, &b| g[n].each(&b) } # p TSort.strongly_connected_components(each_node, each_child) # #=> [[4], [2, 3], [1]] # def TSort.strongly_connected_components(each_node, each_child) TSort.each_strongly_connected_component(each_node, each_child).to_a end # The iterator version of the #strongly_connected_components method. # obj.each_strongly_connected_component is similar to # obj.strongly_connected_components.each, but # modification of _obj_ during the iteration may lead to unexpected results. # # #each_strongly_connected_component returns +nil+. # # class G # include TSort # def initialize(g) # @g = g # end # def tsort_each_child(n, &b) @g[n].each(&b) end # def tsort_each_node(&b) @g.each_key(&b) end # end # # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]}) # graph.each_strongly_connected_component {|scc| p scc } # #=> [4] # # [2] # # [3] # # [1] # # graph = G.new({1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}) # graph.each_strongly_connected_component {|scc| p scc } # #=> [4] # # [2, 3] # # [1] # def each_strongly_connected_component(&block) # :yields: nodes each_node = method(:tsort_each_node) each_child = method(:tsort_each_child) TSort.each_strongly_connected_component(each_node, each_child, &block) end # The iterator version of the TSort.strongly_connected_components method. # # The graph is represented by _each_node_ and _each_child_. # _each_node_ should have +call+ method which yields for each node in the graph. # _each_child_ should have +call+ method which takes a node argument and yields for each child node. # # g = {1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]} # each_node = lambda {|&b| g.each_key(&b) } # each_child = lambda {|n, &b| g[n].each(&b) } # TSort.each_strongly_connected_component(each_node, each_child) {|scc| p scc } # #=> [4] # # [2] # # [3] # # [1] # # g = {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]} # each_node = lambda {|&b| g.each_key(&b) } # each_child = lambda {|n, &b| g[n].each(&b) } # TSort.each_strongly_connected_component(each_node, each_child) {|scc| p scc } # #=> [4] # # [2, 3] # # [1] # def TSort.each_strongly_connected_component(each_node, each_child) # :yields: nodes return to_enum(__method__, each_node, each_child) unless block_given? id_map = {} stack = [] each_node.call {|node| unless id_map.include? node TSort.each_strongly_connected_component_from(node, each_child, id_map, stack) {|c| yield c } end } nil end # Iterates over strongly connected component in the subgraph reachable from # _node_. # # Return value is unspecified. # # #each_strongly_connected_component_from doesn't call #tsort_each_node. # # class G # include TSort # def initialize(g) # @g = g # end # def tsort_each_child(n, &b) @g[n].each(&b) end # def tsort_each_node(&b) @g.each_key(&b) end # end # # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]}) # graph.each_strongly_connected_component_from(2) {|scc| p scc } # #=> [4] # # [2] # # graph = G.new({1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}) # graph.each_strongly_connected_component_from(2) {|scc| p scc } # #=> [4] # # [2, 3] # def each_strongly_connected_component_from(node, id_map={}, stack=[], &block) # :yields: nodes TSort.each_strongly_connected_component_from(node, method(:tsort_each_child), id_map, stack, &block) end # Iterates over strongly connected components in a graph. # The graph is represented by _node_ and _each_child_. # # _node_ is the first node. # _each_child_ should have +call+ method which takes a node argument # and yields for each child node. # # Return value is unspecified. # # #TSort.each_strongly_connected_component_from is a class method and # it doesn't need a class to represent a graph which includes TSort. # # graph = {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]} # each_child = lambda {|n, &b| graph[n].each(&b) } # TSort.each_strongly_connected_component_from(1, each_child) {|scc| # p scc # } # #=> [4] # # [2, 3] # # [1] # def TSort.each_strongly_connected_component_from(node, each_child, id_map={}, stack=[]) # :yields: nodes return to_enum(__method__, node, each_child, id_map, stack) unless block_given? minimum_id = node_id = id_map[node] = id_map.size stack_length = stack.length stack << node each_child.call(node) {|child| if id_map.include? child child_id = id_map[child] minimum_id = child_id if child_id && child_id < minimum_id else sub_minimum_id = TSort.each_strongly_connected_component_from(child, each_child, id_map, stack) {|c| yield c } minimum_id = sub_minimum_id if sub_minimum_id < minimum_id end } if node_id == minimum_id component = stack.slice!(stack_length .. -1) component.each {|n| id_map[n] = nil} yield component end minimum_id end # Should be implemented by a extended class. # # #tsort_each_node is used to iterate for all nodes over a graph. # def tsort_each_node # :yields: node raise NotImplementedError.new end # Should be implemented by a extended class. # # #tsort_each_child is used to iterate for child nodes of _node_. # def tsort_each_child(node) # :yields: child raise NotImplementedError.new end end PK!hx``2.2.0/mathn.rbnu[#-- # $Release Version: 0.5 $ # $Revision: 1.1.1.1.4.1 $ ## # = mathn # # mathn serves to make mathematical operations more precise in Ruby # and to integrate other mathematical standard libraries. # # Without mathn: # # 3 / 2 => 1 # Integer # # With mathn: # # 3 / 2 => 3/2 # Rational # # mathn keeps value in exact terms. # # Without mathn: # # 20 / 9 * 3 * 14 / 7 * 3 / 2 # => 18 # # With mathn: # # 20 / 9 * 3 * 14 / 7 * 3 / 2 # => 20 # # # When you require 'mathn', the libraries for Prime, CMath, Matrix and Vector # are also loaded. # # == Copyright # # Author: Keiju ISHITSUKA (SHL Japan Inc.) #-- # class Numeric follows to make this documentation findable in a reasonable # location warn('lib/mathn.rb is deprecated') if $VERBOSE class Numeric; end require "cmath.rb" require "matrix.rb" require "prime.rb" require "mathn/rational" require "mathn/complex" unless defined?(Math.exp!) Object.instance_eval{remove_const :Math} Math = CMath # :nodoc: end ## # When mathn is required, Fixnum's division is enhanced to # return more precise values from mathematical expressions. # # 2/3*3 # => 0 # require 'mathn' # 2/3*3 # => 2 class Fixnum remove_method :/ ## # +/+ defines the Rational division for Fixnum. # # 1/3 # => (1/3) alias / quo end ## # When mathn is required Bignum's division is enhanced to # return more precise values from mathematical expressions. # # (2**72) / ((2**70) * 3) # => 4/3 class Bignum remove_method :/ ## # +/+ defines the Rational division for Bignum. # # (2**72) / ((2**70) * 3) # => 4/3 alias / quo end ## # When mathn is required, the Math module changes as follows: # # Standard Math module behaviour: # Math.sqrt(4/9) # => 0.0 # Math.sqrt(4.0/9.0) # => 0.666666666666667 # Math.sqrt(- 4/9) # => Errno::EDOM: Numerical argument out of domain - sqrt # # After require 'mathn', this is changed to: # # require 'mathn' # Math.sqrt(4/9) # => 2/3 # Math.sqrt(4.0/9.0) # => 0.666666666666667 # Math.sqrt(- 4/9) # => Complex(0, 2/3) module Math remove_method(:sqrt) ## # Computes the square root of +a+. It makes use of Complex and # Rational to have no rounding errors if possible. # # Math.sqrt(4/9) # => 2/3 # Math.sqrt(- 4/9) # => Complex(0, 2/3) # Math.sqrt(4.0/9.0) # => 0.666666666666667 def sqrt(a) if a.kind_of?(Complex) abs = sqrt(a.real*a.real + a.imag*a.imag) x = sqrt((a.real + abs)/Rational(2)) y = sqrt((-a.real + abs)/Rational(2)) if a.imag >= 0 Complex(x, y) else Complex(x, -y) end elsif a.respond_to?(:nan?) and a.nan? a elsif a >= 0 rsqrt(a) else Complex(0,rsqrt(-a)) end end ## # Compute square root of a non negative number. This method is # internally used by +Math.sqrt+. def rsqrt(a) if a.kind_of?(Float) sqrt!(a) elsif a.kind_of?(Rational) rsqrt(a.numerator)/rsqrt(a.denominator) else src = a max = 2 ** 32 byte_a = [src & 0xffffffff] # ruby's bug while (src >= max) and (src >>= 32) byte_a.unshift src & 0xffffffff end answer = 0 main = 0 side = 0 for elm in byte_a main = (main << 32) + elm side <<= 16 if answer != 0 if main * 4 < side * side applo = main.div(side) else applo = ((sqrt!(side * side + 4 * main) - side)/2.0).to_i + 1 end else applo = sqrt!(main).to_i + 1 end while (x = (side + applo) * applo) > main applo -= 1 end main -= x answer = (answer << 16) + applo side += applo * 2 end if main == 0 answer else sqrt!(a) end end end class << self remove_method(:sqrt) end module_function :sqrt module_function :rsqrt end PK!/2.2.0/rdoc/markup/heading.rbnu[## # A heading with a level (1-6) and text RDoc::Markup::Heading = Struct.new :level, :text do @to_html = nil @to_label = nil ## # A singleton RDoc::Markup::ToLabel formatter for headings. def self.to_label @to_label ||= RDoc::Markup::ToLabel.new end ## # A singleton plain HTML formatter for headings. Used for creating labels # for the Table of Contents def self.to_html return @to_html if @to_html markup = RDoc::Markup.new markup.add_special RDoc::CrossReference::CROSSREF_REGEXP, :CROSSREF @to_html = RDoc::Markup::ToHtml.new nil def @to_html.handle_special_CROSSREF special special.text.sub(/^\\/, '') end @to_html end ## # Calls #accept_heading on +visitor+ def accept visitor visitor.accept_heading self end ## # An HTML-safe anchor reference for this header. def aref "label-#{self.class.to_label.convert text.dup}" end ## # Creates a fully-qualified label which will include the label from # +context+. This helps keep ids unique in HTML. def label context = nil label = aref label = [context.aref, label].compact.join '-' if context and context.respond_to? :aref label end ## # HTML markup of the text of this label without the surrounding header # element. def plain_html self.class.to_html.to_html(text.dup) end def pretty_print q # :nodoc: q.group 2, "[head: #{level} ", ']' do q.pp text end end end PK!fР2.2.0/rdoc/markup/attributes.rbnu[## # We manage a set of attributes. Each attribute has a symbol name and a bit # value. class RDoc::Markup::Attributes ## # The special attribute type. See RDoc::Markup#add_special attr_reader :special ## # Creates a new attributes set. def initialize @special = 1 @name_to_bitmap = [ [:_SPECIAL_, @special], ] @next_bitmap = @special << 1 end ## # Returns a unique bit for +name+ def bitmap_for name bitmap = @name_to_bitmap.assoc name unless bitmap then bitmap = @next_bitmap @next_bitmap <<= 1 @name_to_bitmap << [name, bitmap] else bitmap = bitmap.last end bitmap end ## # Returns a string representation of +bitmap+ def as_string bitmap return 'none' if bitmap.zero? res = [] @name_to_bitmap.each do |name, bit| res << name if (bitmap & bit) != 0 end res.join ',' end ## # yields each attribute name in +bitmap+ def each_name_of bitmap return enum_for __method__, bitmap unless block_given? @name_to_bitmap.each do |name, bit| next if bit == @special yield name.to_s if (bitmap & bit) != 0 end end end PK!'>''2.2.0/rdoc/markup/list.rbnu[## # A List is a homogeneous set of ListItems. # # The supported list types include: # # :BULLET:: # An unordered list # :LABEL:: # An unordered definition list, but using an alternate RDoc::Markup syntax # :LALPHA:: # An ordered list using increasing lowercase English letters # :NOTE:: # An unordered definition list # :NUMBER:: # An ordered list using increasing Arabic numerals # :UALPHA:: # An ordered list using increasing uppercase English letters # # Definition lists behave like HTML definition lists. Each list item can # describe multiple terms. See RDoc::Markup::ListItem for how labels and # definition are stored as list items. class RDoc::Markup::List ## # The list's type attr_accessor :type ## # Items in the list attr_reader :items ## # Creates a new list of +type+ with +items+. Valid list types are: # +:BULLET+, +:LABEL+, +:LALPHA+, +:NOTE+, +:NUMBER+, +:UALPHA+ def initialize type = nil, *items @type = type @items = [] @items.concat items end ## # Appends +item+ to the list def << item @items << item end def == other # :nodoc: self.class == other.class and @type == other.type and @items == other.items end ## # Runs this list and all its #items through +visitor+ def accept visitor visitor.accept_list_start self @items.each do |item| item.accept visitor end visitor.accept_list_end self end ## # Is the list empty? def empty? @items.empty? end ## # Returns the last item in the list def last @items.last end def pretty_print q # :nodoc: q.group 2, "[list: #{@type} ", ']' do q.seplist @items do |item| q.pp item end end end ## # Appends +items+ to the list def push *items @items.concat items end end PK!H22(2.2.0/rdoc/markup/to_joined_paragraph.rbnu[## # Joins the parts of an RDoc::Markup::Paragraph into a single String. # # This allows for easier maintenance and testing of Markdown support. # # This formatter only works on Paragraph instances. Attempting to process # other markup syntax items will not work. class RDoc::Markup::ToJoinedParagraph < RDoc::Markup::Formatter def initialize # :nodoc: super nil end def start_accepting # :nodoc: end def end_accepting # :nodoc: end ## # Converts the parts of +paragraph+ to a single entry. def accept_paragraph paragraph parts = [] string = false paragraph.parts.each do |part| if String === part then if string then string << part else parts << part string = part end else parts << part string = false end end parts = parts.map do |part| if String === part then part.rstrip else part end end # TODO use Enumerable#chunk when Ruby 1.8 support is dropped #parts = paragraph.parts.chunk do |part| # String === part #end.map do |string, chunk| # string ? chunk.join.rstrip : chunk #end.flatten paragraph.parts.replace parts end alias accept_block_quote ignore alias accept_heading ignore alias accept_list_end ignore alias accept_list_item_end ignore alias accept_list_item_start ignore alias accept_list_start ignore alias accept_raw ignore alias accept_rule ignore alias accept_verbatim ignore end PK!v6!!2.2.0/rdoc/markup/to_html.rbnu[require 'cgi' ## # Outputs RDoc markup as HTML. class RDoc::Markup::ToHtml < RDoc::Markup::Formatter include RDoc::Text # :section: Utilities ## # Maps RDoc::Markup::Parser::LIST_TOKENS types to HTML tags LIST_TYPE_TO_HTML = { :BULLET => ['
    ', '
'], :LABEL => ['
', '
'], :LALPHA => ['
    ', '
'], :NOTE => ['
', '
'], :NUMBER => ['
    ', '
'], :UALPHA => ['
    ', '
'], } attr_reader :res # :nodoc: attr_reader :in_list_entry # :nodoc: attr_reader :list # :nodoc: ## # The RDoc::CodeObject HTML is being generated for. This is used to # generate namespaced URI fragments attr_accessor :code_object ## # Path to this document for relative links attr_accessor :from_path # :section: ## # Creates a new formatter that will output HTML def initialize options, markup = nil super @code_object = nil @from_path = '' @in_list_entry = nil @list = nil @th = nil @hard_break = "
\n" # external links @markup.add_special(/(?:link:|https?:|mailto:|ftp:|irc:|www\.)\S+\w/, :HYPERLINK) add_special_RDOCLINK add_special_TIDYLINK init_tags end # :section: Special Handling # # These methods handle special markup added by RDoc::Markup#add_special. def handle_RDOCLINK url # :nodoc: case url when /^rdoc-ref:/ $' when /^rdoc-label:/ text = $' text = case text when /\Alabel-/ then $' when /\Afootmark-/ then $' when /\Afoottext-/ then $' else text end gen_url url, text when /^rdoc-image:/ "" else url =~ /\Ardoc-[a-z]+:/ $' end end ## # +special+ is a
def handle_special_HARD_BREAK special '
' end ## # +special+ is a potential link. The following schemes are handled: # # mailto::: # Inserted as-is. # http::: # Links are checked to see if they reference an image. If so, that image # gets inserted using an tag. Otherwise a conventional # is used. # link::: # Reference to a local file relative to the output directory. def handle_special_HYPERLINK(special) url = special.text gen_url url, url end ## # +special+ is an rdoc-schemed link that will be converted into a hyperlink. # # For the +rdoc-ref+ scheme the named reference will be returned without # creating a link. # # For the +rdoc-label+ scheme the footnote and label prefixes are stripped # when creating a link. All other contents will be linked verbatim. def handle_special_RDOCLINK special handle_RDOCLINK special.text end ## # This +special+ is a link where the label is different from the URL # label[url] or {long label}[url] def handle_special_TIDYLINK(special) text = special.text return text unless text =~ /^\{(.*)\}\[(.*?)\]$/ or text =~ /^(\S+)\[(.*?)\]$/ label = $1 url = $2 label = handle_RDOCLINK label if /^rdoc-image:/ =~ label gen_url url, label end # :section: Visitor # # These methods implement the HTML visitor. ## # Prepares the visitor for HTML generation def start_accepting @res = [] @in_list_entry = [] @list = [] end ## # Returns the generated output def end_accepting @res.join end ## # Adds +block_quote+ to the output def accept_block_quote block_quote @res << "\n
" block_quote.parts.each do |part| part.accept self end @res << "
\n" end ## # Adds +paragraph+ to the output def accept_paragraph paragraph @res << "\n

" text = paragraph.text @hard_break text = text.gsub(/\r?\n/, ' ') @res << wrap(to_html(text)) @res << "

\n" end ## # Adds +verbatim+ to the output def accept_verbatim verbatim text = verbatim.text.rstrip klass = nil content = if verbatim.ruby? or parseable? text then begin tokens = RDoc::RubyLex.tokenize text, @options klass = ' class="ruby"' RDoc::TokenStream.to_html tokens rescue RDoc::RubyLex::Error CGI.escapeHTML text end else CGI.escapeHTML text end if @options.pipe then @res << "\n
#{CGI.escapeHTML text}
\n" else @res << "\n#{content}\n" end end ## # Adds +rule+ to the output def accept_rule rule @res << "
\n" end ## # Prepares the visitor for consuming +list+ def accept_list_start(list) @list << list.type @res << html_list_name(list.type, true) @in_list_entry.push false end ## # Finishes consumption of +list+ def accept_list_end(list) @list.pop if tag = @in_list_entry.pop @res << tag end @res << html_list_name(list.type, false) << "\n" end ## # Prepares the visitor for consuming +list_item+ def accept_list_item_start(list_item) if tag = @in_list_entry.last @res << tag end @res << list_item_start(list_item, @list.last) end ## # Finishes consumption of +list_item+ def accept_list_item_end(list_item) @in_list_entry[-1] = list_end_for(@list.last) end ## # Adds +blank_line+ to the output def accept_blank_line(blank_line) # @res << annotate("

") << "\n" end ## # Adds +heading+ to the output. The headings greater than 6 are trimmed to # level 6. def accept_heading heading level = [6, heading.level].min label = heading.label @code_object @res << if @options.output_decoration "\n" else "\n" end @res << to_html(heading.text) unless @options.pipe then @res << "" @res << " " end @res << "\n" end ## # Adds +raw+ to the output def accept_raw raw @res << raw.parts.join("\n") end # :section: Utilities ## # CGI-escapes +text+ def convert_string(text) CGI.escapeHTML text end ## # Generate a link to +url+ with content +text+. Handles the special cases # for img: and link: described under handle_special_HYPERLINK def gen_url url, text scheme, url, id = parse_url url if %w[http https link].include?(scheme) and url =~ /\.(gif|png|jpg|jpeg|bmp)$/ then "" else text = text.sub %r%^#{scheme}:/*%i, '' text = text.sub %r%^[*\^](\d+)$%, '\1' link = "#{text}" link = "#{link}" if /"foot/ =~ id link end end ## # Determines the HTML list element for +list_type+ and +open_tag+ def html_list_name(list_type, open_tag) tags = LIST_TYPE_TO_HTML[list_type] raise RDoc::Error, "Invalid list type: #{list_type.inspect}" unless tags tags[open_tag ? 0 : 1] end ## # Maps attributes to HTML tags def init_tags add_tag :BOLD, "", "" add_tag :TT, "", "" add_tag :EM, "", "" end ## # Returns the HTML tag for +list_type+, possible using a label from # +list_item+ def list_item_start(list_item, list_type) case list_type when :BULLET, :LALPHA, :NUMBER, :UALPHA then "

  • " when :LABEL, :NOTE then Array(list_item.label).map do |label| "
    #{to_html label}\n" end.join << "
    " else raise RDoc::Error, "Invalid list type: #{list_type.inspect}" end end ## # Returns the HTML end-tag for +list_type+ def list_end_for(list_type) case list_type when :BULLET, :LALPHA, :NUMBER, :UALPHA then "
  • " when :LABEL, :NOTE then "" else raise RDoc::Error, "Invalid list type: #{list_type.inspect}" end end ## # Returns true if text is valid ruby syntax def parseable? text eval("BEGIN {return true}\n#{text}") rescue SyntaxError false end ## # Converts +item+ to HTML using RDoc::Text#to_html def to_html item super convert_flow @am.flow item end end PK!AWDaCaC(2.2.0/rdoc/markup/formatter_test_case.rbnu[require 'minitest/unit' ## # Test case for creating new RDoc::Markup formatters. See # test/test_rdoc_markup_to_*.rb for examples. # # This test case adds a variety of tests to your subclass when # #add_visitor_tests is called. Most tests set up a scenario then call a # method you will provide to perform the assertion on the output. # # Your subclass must instantiate a visitor and assign it to @to. # # For example, test_accept_blank_line sets up a RDoc::Markup::BlockLine then # calls accept_blank_line on your visitor. You are responsible for asserting # that the output is correct. # # Example: # # class TestRDocMarkupToNewFormat < RDoc::Markup::FormatterTestCase # # add_visitor_tests # # def setup # super # # @to = RDoc::Markup::ToNewFormat.new # end # # def accept_blank_line # assert_equal :junk, @to.res.join # end # # # ... # # end class RDoc::Markup::FormatterTestCase < RDoc::TestCase ## # Call #setup when inheriting from this test case. # # Provides the following instance variables: # # +@m+:: RDoc::Markup.new # +@RM+:: RDoc::Markup # to reduce typing # +@bullet_list+:: @RM::List.new :BULLET, # ... # +@label_list+:: @RM::List.new :LABEL, # ... # +@lalpha_list+:: @RM::List.new :LALPHA, # ... # +@note_list+:: @RM::List.new :NOTE, # ... # +@number_list+:: @RM::List.new :NUMBER, # ... # +@ualpha_list+:: @RM::List.new :UALPHA, # ... def setup super @options = RDoc::Options.new @m = @RM.new @bullet_list = @RM::List.new(:BULLET, @RM::ListItem.new(nil, @RM::Paragraph.new('l1')), @RM::ListItem.new(nil, @RM::Paragraph.new('l2'))) @label_list = @RM::List.new(:LABEL, @RM::ListItem.new('cat', @RM::Paragraph.new('cats are cool')), @RM::ListItem.new('dog', @RM::Paragraph.new('dogs are cool too'))) @lalpha_list = @RM::List.new(:LALPHA, @RM::ListItem.new(nil, @RM::Paragraph.new('l1')), @RM::ListItem.new(nil, @RM::Paragraph.new('l2'))) @note_list = @RM::List.new(:NOTE, @RM::ListItem.new('cat', @RM::Paragraph.new('cats are cool')), @RM::ListItem.new('dog', @RM::Paragraph.new('dogs are cool too'))) @number_list = @RM::List.new(:NUMBER, @RM::ListItem.new(nil, @RM::Paragraph.new('l1')), @RM::ListItem.new(nil, @RM::Paragraph.new('l2'))) @ualpha_list = @RM::List.new(:UALPHA, @RM::ListItem.new(nil, @RM::Paragraph.new('l1')), @RM::ListItem.new(nil, @RM::Paragraph.new('l2'))) end ## # Call to add the visitor tests to your test case def self.add_visitor_tests class_eval do ## # Calls start_accepting which needs to verify startup state def test_start_accepting @to.start_accepting start_accepting end ## # Calls end_accepting on your test case which needs to call # @to.end_accepting and verify document generation def test_end_accepting @to.start_accepting @to.res << 'hi' end_accepting end ## # Calls accept_blank_line def test_accept_blank_line @to.start_accepting @to.accept_blank_line @RM::BlankLine.new accept_blank_line end ## # Calls accept_block_quote def test_accept_block_quote @to.start_accepting @to.accept_block_quote block para 'quote' accept_block_quote end ## # Test case that calls @to.accept_document def test_accept_document @to.start_accepting @to.accept_document @RM::Document.new @RM::Paragraph.new 'hello' accept_document end ## # Calls accept_heading with a level 5 RDoc::Markup::Heading def test_accept_heading @to.start_accepting @to.accept_heading @RM::Heading.new(5, 'Hello') accept_heading end ## # Calls accept_heading_1 with a level 1 RDoc::Markup::Heading def test_accept_heading_1 @to.start_accepting @to.accept_heading @RM::Heading.new(1, 'Hello') accept_heading_1 end ## # Calls accept_heading_2 with a level 2 RDoc::Markup::Heading def test_accept_heading_2 @to.start_accepting @to.accept_heading @RM::Heading.new(2, 'Hello') accept_heading_2 end ## # Calls accept_heading_3 with a level 3 RDoc::Markup::Heading def test_accept_heading_3 # HACK this doesn't belong here skip "No String#chars, upgrade your ruby" unless ''.respond_to? :chars @to.start_accepting @to.accept_heading @RM::Heading.new(3, 'Hello') accept_heading_3 end ## # Calls accept_heading_4 with a level 4 RDoc::Markup::Heading def test_accept_heading_4 @to.start_accepting @to.accept_heading @RM::Heading.new(4, 'Hello') accept_heading_4 end ## # Calls accept_heading_b with a bold level 1 RDoc::Markup::Heading def test_accept_heading_b @to.start_accepting @to.accept_heading @RM::Heading.new(1, '*Hello*') accept_heading_b end ## # Calls accept_heading_suppressed_crossref with a level 1 # RDoc::Markup::Heading containing a suppressed crossref def test_accept_heading_suppressed_crossref # HACK to_html_crossref test @to.start_accepting @to.accept_heading @RM::Heading.new(1, '\\Hello') accept_heading_suppressed_crossref end ## # Calls accept_paragraph def test_accept_paragraph @to.start_accepting @to.accept_paragraph @RM::Paragraph.new('hi') accept_paragraph end ## # Calls accept_paragraph_b with a RDoc::Markup::Paragraph containing # bold words def test_accept_paragraph_b @to.start_accepting @to.accept_paragraph @RM::Paragraph.new('reg bold words reg') accept_paragraph_b end ## # Calls accept_paragraph_br with a RDoc::Markup::Paragraph containing # a \
    def test_accept_paragraph_br @to.start_accepting @to.accept_paragraph para 'one
    two' accept_paragraph_br end ## # Calls accept_paragraph with a Paragraph containing a hard break def test_accept_paragraph_break @to.start_accepting @to.accept_paragraph para('hello', hard_break, 'world') accept_paragraph_break end ## # Calls accept_paragraph_i with a RDoc::Markup::Paragraph containing # emphasized words def test_accept_paragraph_i @to.start_accepting @to.accept_paragraph @RM::Paragraph.new('reg italic words reg') accept_paragraph_i end ## # Calls accept_paragraph_plus with a RDoc::Markup::Paragraph containing # teletype words def test_accept_paragraph_plus @to.start_accepting @to.accept_paragraph @RM::Paragraph.new('reg +teletype+ reg') accept_paragraph_plus end ## # Calls accept_paragraph_star with a RDoc::Markup::Paragraph containing # bold words def test_accept_paragraph_star @to.start_accepting @to.accept_paragraph @RM::Paragraph.new('reg *bold* reg') accept_paragraph_star end ## # Calls accept_paragraph_underscore with a RDoc::Markup::Paragraph # containing emphasized words def test_accept_paragraph_underscore @to.start_accepting @to.accept_paragraph @RM::Paragraph.new('reg _italic_ reg') accept_paragraph_underscore end ## # Calls accept_verbatim with a RDoc::Markup::Verbatim def test_accept_verbatim @to.start_accepting @to.accept_verbatim @RM::Verbatim.new("hi\n", " world\n") accept_verbatim end ## # Calls accept_raw with a RDoc::Markup::Raw def test_accept_raw @to.start_accepting @to.accept_raw @RM::Raw.new("", "
    NameCount", "
    a1", "
    b2", "
    ") accept_raw end ## # Calls accept_rule with a RDoc::Markup::Rule def test_accept_rule @to.start_accepting @to.accept_rule @RM::Rule.new(4) accept_rule end ## # Calls accept_list_item_start_bullet def test_accept_list_item_start_bullet @to.start_accepting @to.accept_list_start @bullet_list @to.accept_list_item_start @bullet_list.items.first accept_list_item_start_bullet end ## # Calls accept_list_item_start_label def test_accept_list_item_start_label @to.start_accepting @to.accept_list_start @label_list @to.accept_list_item_start @label_list.items.first accept_list_item_start_label end ## # Calls accept_list_item_start_lalpha def test_accept_list_item_start_lalpha @to.start_accepting @to.accept_list_start @lalpha_list @to.accept_list_item_start @lalpha_list.items.first accept_list_item_start_lalpha end ## # Calls accept_list_item_start_note def test_accept_list_item_start_note @to.start_accepting @to.accept_list_start @note_list @to.accept_list_item_start @note_list.items.first accept_list_item_start_note end ## # Calls accept_list_item_start_note_2 def test_accept_list_item_start_note_2 list = list(:NOTE, item('teletype', para('teletype description'))) @to.start_accepting list.accept @to @to.end_accepting accept_list_item_start_note_2 end ## # Calls accept_list_item_start_note_multi_description def test_accept_list_item_start_note_multi_description list = list(:NOTE, item(%w[label], para('description one')), item(nil, para('description two'))) @to.start_accepting list.accept @to @to.end_accepting accept_list_item_start_note_multi_description end ## # Calls accept_list_item_start_note_multi_label def test_accept_list_item_start_note_multi_label list = list(:NOTE, item(%w[one two], para('two headers'))) @to.start_accepting list.accept @to @to.end_accepting accept_list_item_start_note_multi_label end ## # Calls accept_list_item_start_number def test_accept_list_item_start_number @to.start_accepting @to.accept_list_start @number_list @to.accept_list_item_start @number_list.items.first accept_list_item_start_number end ## # Calls accept_list_item_start_ualpha def test_accept_list_item_start_ualpha @to.start_accepting @to.accept_list_start @ualpha_list @to.accept_list_item_start @ualpha_list.items.first accept_list_item_start_ualpha end ## # Calls accept_list_item_end_bullet def test_accept_list_item_end_bullet @to.start_accepting @to.accept_list_start @bullet_list @to.accept_list_item_start @bullet_list.items.first @to.accept_list_item_end @bullet_list.items.first accept_list_item_end_bullet end ## # Calls accept_list_item_end_label def test_accept_list_item_end_label @to.start_accepting @to.accept_list_start @label_list @to.accept_list_item_start @label_list.items.first @to.accept_list_item_end @label_list.items.first accept_list_item_end_label end ## # Calls accept_list_item_end_lalpha def test_accept_list_item_end_lalpha @to.start_accepting @to.accept_list_start @lalpha_list @to.accept_list_item_start @lalpha_list.items.first @to.accept_list_item_end @lalpha_list.items.first accept_list_item_end_lalpha end ## # Calls accept_list_item_end_note def test_accept_list_item_end_note @to.start_accepting @to.accept_list_start @note_list @to.accept_list_item_start @note_list.items.first @to.accept_list_item_end @note_list.items.first accept_list_item_end_note end ## # Calls accept_list_item_end_number def test_accept_list_item_end_number @to.start_accepting @to.accept_list_start @number_list @to.accept_list_item_start @number_list.items.first @to.accept_list_item_end @number_list.items.first accept_list_item_end_number end ## # Calls accept_list_item_end_ualpha def test_accept_list_item_end_ualpha @to.start_accepting @to.accept_list_start @ualpha_list @to.accept_list_item_start @ualpha_list.items.first @to.accept_list_item_end @ualpha_list.items.first accept_list_item_end_ualpha end ## # Calls accept_list_start_bullet def test_accept_list_start_bullet @to.start_accepting @to.accept_list_start @bullet_list accept_list_start_bullet end ## # Calls accept_list_start_label def test_accept_list_start_label @to.start_accepting @to.accept_list_start @label_list accept_list_start_label end ## # Calls accept_list_start_lalpha def test_accept_list_start_lalpha @to.start_accepting @to.accept_list_start @lalpha_list accept_list_start_lalpha end ## # Calls accept_list_start_note def test_accept_list_start_note @to.start_accepting @to.accept_list_start @note_list accept_list_start_note end ## # Calls accept_list_start_number def test_accept_list_start_number @to.start_accepting @to.accept_list_start @number_list accept_list_start_number end ## # Calls accept_list_start_ualpha def test_accept_list_start_ualpha @to.start_accepting @to.accept_list_start @ualpha_list accept_list_start_ualpha end ## # Calls accept_list_end_bullet def test_accept_list_end_bullet @to.start_accepting @to.accept_list_start @bullet_list @to.accept_list_end @bullet_list accept_list_end_bullet end ## # Calls accept_list_end_label def test_accept_list_end_label @to.start_accepting @to.accept_list_start @label_list @to.accept_list_end @label_list accept_list_end_label end ## # Calls accept_list_end_lalpha def test_accept_list_end_lalpha @to.start_accepting @to.accept_list_start @lalpha_list @to.accept_list_end @lalpha_list accept_list_end_lalpha end ## # Calls accept_list_end_number def test_accept_list_end_number @to.start_accepting @to.accept_list_start @number_list @to.accept_list_end @number_list accept_list_end_number end ## # Calls accept_list_end_note def test_accept_list_end_note @to.start_accepting @to.accept_list_start @note_list @to.accept_list_end @note_list accept_list_end_note end ## # Calls accept_list_end_ualpha def test_accept_list_end_ualpha @to.start_accepting @to.accept_list_start @ualpha_list @to.accept_list_end @ualpha_list accept_list_end_ualpha end ## # Calls list_nested with a two-level list def test_list_nested doc = @RM::Document.new( @RM::List.new(:BULLET, @RM::ListItem.new(nil, @RM::Paragraph.new('l1'), @RM::List.new(:BULLET, @RM::ListItem.new(nil, @RM::Paragraph.new('l1.1')))), @RM::ListItem.new(nil, @RM::Paragraph.new('l2')))) doc.accept @to list_nested end ## # Calls list_verbatim with a list containing a verbatim block def test_list_verbatim # HACK overblown doc = doc( list(:BULLET, item(nil, para('list stuff'), blank_line, verb("* list\n", " with\n", "\n", " second\n", "\n", " 1. indented\n", " 2. numbered\n", "\n", " third\n", "\n", "* second\n")))) doc.accept @to list_verbatim end end end end PK!$AEb2.2.0/rdoc/markup/to_bs.rbnu[## # Outputs RDoc markup with hot backspace action! You will probably need a # pager to use this output format. # # This formatter won't work on 1.8.6 because it lacks String#chars. class RDoc::Markup::ToBs < RDoc::Markup::ToRdoc ## # Returns a new ToBs that is ready for hot backspace action! def initialize markup = nil super @in_b = false @in_em = false end ## # Sets a flag that is picked up by #annotate to do the right thing in # #convert_string def init_tags add_tag :BOLD, '+b', '-b' add_tag :EM, '+_', '-_' add_tag :TT, '' , '' # we need in_tt information maintained end ## # Makes heading text bold. def accept_heading heading use_prefix or @res << ' ' * @indent @res << @headings[heading.level][0] @in_b = true @res << attributes(heading.text) @in_b = false @res << @headings[heading.level][1] @res << "\n" end ## # Turns on or off special handling for +convert_string+ def annotate tag case tag when '+b' then @in_b = true when '-b' then @in_b = false when '+_' then @in_em = true when '-_' then @in_em = false end '' end ## # Calls convert_string on the result of convert_special def convert_special special convert_string super end ## # Adds bold or underline mixed with backspaces def convert_string string return string unless string.respond_to? :chars # your ruby is lame return string unless @in_b or @in_em chars = if @in_b then string.chars.map do |char| "#{char}\b#{char}" end elsif @in_em then string.chars.map do |char| "_\b#{char}" end end chars.join end end PK!Upp2.2.0/rdoc/markup/to_test.rbnu[## # This Markup outputter is used for testing purposes. class RDoc::Markup::ToTest < RDoc::Markup::Formatter # :stopdoc: ## # :section: Visitor def start_accepting @res = [] @list = [] end def end_accepting @res end def accept_paragraph(paragraph) @res << convert_flow(@am.flow(paragraph.text)) end def accept_raw raw @res << raw.parts.join end def accept_verbatim(verbatim) @res << verbatim.text.gsub(/^(\S)/, ' \1') end def accept_list_start(list) @list << case list.type when :BULLET then '*' when :NUMBER then '1' else list.type end end def accept_list_end(list) @list.pop end def accept_list_item_start(list_item) @res << "#{' ' * (@list.size - 1)}#{@list.last}: " end def accept_list_item_end(list_item) end def accept_blank_line(blank_line) @res << "\n" end def accept_heading(heading) @res << "#{'=' * heading.level} #{heading.text}" end def accept_rule(rule) @res << '-' * rule.weight end # :startdoc: end PK!X!$2.2.0/rdoc/markup/to_html_snippet.rbnu[## # Outputs RDoc markup as paragraphs with inline markup only. class RDoc::Markup::ToHtmlSnippet < RDoc::Markup::ToHtml ## # After this many characters the input will be cut off. attr_reader :character_limit ## # The number of characters seen so far. attr_reader :characters # :nodoc: ## # The attribute bitmask attr_reader :mask ## # After this many paragraphs the input will be cut off. attr_reader :paragraph_limit ## # Count of paragraphs found attr_reader :paragraphs ## # Creates a new ToHtmlSnippet formatter that will cut off the input on the # next word boundary after the given number of +characters+ or +paragraphs+ # of text have been encountered. def initialize options, characters = 100, paragraphs = 3, markup = nil super options, markup @character_limit = characters @paragraph_limit = paragraphs @characters = 0 @mask = 0 @paragraphs = 0 @markup.add_special RDoc::CrossReference::CROSSREF_REGEXP, :CROSSREF end ## # Adds +heading+ to the output as a paragraph def accept_heading heading @res << "

    #{to_html heading.text}\n" add_paragraph end ## # Raw sections are untrusted and ignored alias accept_raw ignore ## # Rules are ignored alias accept_rule ignore def accept_paragraph paragraph para = @in_list_entry.last || "

    " text = paragraph.text @hard_break @res << "#{para}#{wrap to_html text}\n" add_paragraph end ## # Finishes consumption of +list_item+ def accept_list_item_end list_item end ## # Prepares the visitor for consuming +list_item+ def accept_list_item_start list_item @res << list_item_start(list_item, @list.last) end ## # Prepares the visitor for consuming +list+ def accept_list_start list @list << list.type @res << html_list_name(list.type, true) @in_list_entry.push '' end ## # Adds +verbatim+ to the output def accept_verbatim verbatim throw :done if @characters >= @character_limit input = verbatim.text.rstrip text = truncate input text << ' ...' unless text == input super RDoc::Markup::Verbatim.new text add_paragraph end ## # Prepares the visitor for HTML snippet generation def start_accepting super @characters = 0 end ## # Removes escaping from the cross-references in +special+ def handle_special_CROSSREF special special.text.sub(/\A\\/, '') end ## # +special+ is a
    def handle_special_HARD_BREAK special @characters -= 4 '
    ' end ## # Lists are paragraphs, but notes and labels have a separator def list_item_start list_item, list_type throw :done if @characters >= @character_limit case list_type when :BULLET, :LALPHA, :NUMBER, :UALPHA then "

    " when :LABEL, :NOTE then labels = Array(list_item.label).map do |label| to_html label end.join ', ' labels << " — " unless labels.empty? start = "

    #{labels}" @characters += 1 # try to include the label start else raise RDoc::Error, "Invalid list type: #{list_type.inspect}" end end ## # Returns just the text of +link+, +url+ is only used to determine the link # type. def gen_url url, text if url =~ /^rdoc-label:([^:]*)(?::(.*))?/ then type = "link" elsif url =~ /([A-Za-z]+):(.*)/ then type = $1 else type = "http" end if (type == "http" or type == "https" or type == "link") and url =~ /\.(gif|png|jpg|jpeg|bmp)$/ then '' else text.sub(%r%^#{type}:/*%, '') end end ## # In snippets, there are no lists def html_list_name list_type, open_tag '' end ## # Throws +:done+ when paragraph_limit paragraphs have been encountered def add_paragraph @paragraphs += 1 throw :done if @paragraphs >= @paragraph_limit end ## # Marks up +content+ def convert content catch :done do return super end end_accepting end ## # Converts flow items +flow+ def convert_flow flow throw :done if @characters >= @character_limit res = [] @mask = 0 flow.each do |item| case item when RDoc::Markup::AttrChanger then off_tags res, item on_tags res, item when String then text = convert_string item res << truncate(text) when RDoc::Markup::Special then text = convert_special item res << truncate(text) else raise "Unknown flow element: #{item.inspect}" end if @characters >= @character_limit then off_tags res, RDoc::Markup::AttrChanger.new(0, @mask) break end end res << ' ...' if @characters >= @character_limit res.join end ## # Maintains a bitmask to allow HTML elements to be closed properly. See # RDoc::Markup::Formatter. def on_tags res, item @mask ^= item.turn_on super end ## # Maintains a bitmask to allow HTML elements to be closed properly. See # RDoc::Markup::Formatter. def off_tags res, item @mask ^= item.turn_off super end ## # Truncates +text+ at the end of the first word after the character_limit. def truncate text length = text.length characters = @characters @characters += length return text if @characters < @character_limit remaining = @character_limit - characters text =~ /\A(.{#{remaining},}?)(\s|$)/m # TODO word-break instead of \s? $1 end end PK!:|\ll'2.2.0/rdoc/markup/indented_paragraph.rbnu[## # An Indented Paragraph of text class RDoc::Markup::IndentedParagraph < RDoc::Markup::Raw ## # The indent in number of spaces attr_reader :indent ## # Creates a new IndentedParagraph containing +parts+ indented with +indent+ # spaces def initialize indent, *parts @indent = indent super(*parts) end def == other # :nodoc: super and indent == other.indent end ## # Calls #accept_indented_paragraph on +visitor+ def accept visitor visitor.accept_indented_paragraph self end ## # Joins the raw paragraph text and converts inline HardBreaks to the # +hard_break+ text followed by the indent. def text hard_break = nil @parts.map do |part| if RDoc::Markup::HardBreak === part then '%1$s%3$*2$s' % [hard_break, @indent, ' '] if hard_break else part end end.join end end PK!,\\ 2.2.0/rdoc/markup/to_markdown.rbnu[# :markup: markdown ## # Outputs parsed markup as Markdown class RDoc::Markup::ToMarkdown < RDoc::Markup::ToRdoc ## # Creates a new formatter that will output Markdown format text def initialize markup = nil super @headings[1] = ['# ', ''] @headings[2] = ['## ', ''] @headings[3] = ['### ', ''] @headings[4] = ['#### ', ''] @headings[5] = ['##### ', ''] @headings[6] = ['###### ', ''] add_special_RDOCLINK add_special_TIDYLINK @hard_break = " \n" end ## # Maps attributes to HTML sequences def init_tags add_tag :BOLD, '**', '**' add_tag :EM, '*', '*' add_tag :TT, '`', '`' end ## # Adds a newline to the output def handle_special_HARD_BREAK special " \n" end ## # Finishes consumption of `list` def accept_list_end list @res << "\n" super end ## # Finishes consumption of `list_item` def accept_list_item_end list_item width = case @list_type.last when :BULLET then 4 when :NOTE, :LABEL then use_prefix 4 else @list_index[-1] = @list_index.last.succ 4 end @indent -= width end ## # Prepares the visitor for consuming `list_item` def accept_list_item_start list_item type = @list_type.last case type when :NOTE, :LABEL then bullets = Array(list_item.label).map do |label| attributes(label).strip end.join "\n" bullets << "\n:" @prefix = ' ' * @indent @indent += 4 @prefix << bullets + (' ' * (@indent - 1)) else bullet = type == :BULLET ? '*' : @list_index.last.to_s + '.' @prefix = (' ' * @indent) + bullet.ljust(4) @indent += 4 end end ## # Prepares the visitor for consuming `list` def accept_list_start list case list.type when :BULLET, :LABEL, :NOTE then @list_index << nil when :LALPHA, :NUMBER, :UALPHA then @list_index << 1 else raise RDoc::Error, "invalid list type #{list.type}" end @list_width << 4 @list_type << list.type end ## # Adds `rule` to the output def accept_rule rule use_prefix or @res << ' ' * @indent @res << '-' * 3 @res << "\n" end ## # Outputs `verbatim` indented 4 columns def accept_verbatim verbatim indent = ' ' * (@indent + 4) verbatim.parts.each do |part| @res << indent unless part == "\n" @res << part end @res << "\n" unless @res =~ /\n\z/ end ## # Creates a Markdown-style URL from +url+ with +text+. def gen_url url, text scheme, url, = parse_url url "[#{text.sub(%r{^#{scheme}:/*}i, '')}](#{url})" end ## # Handles rdoc- type links for footnotes. def handle_rdoc_link url case url when /^rdoc-ref:/ then $' when /^rdoc-label:footmark-(\d+)/ then "[^#{$1}]:" when /^rdoc-label:foottext-(\d+)/ then "[^#{$1}]" when /^rdoc-label:label-/ then gen_url url, $' when /^rdoc-image:/ then "![](#{$'})" when /^rdoc-[a-z]+:/ then $' end end ## # Converts the RDoc markup tidylink into a Markdown.style link. def handle_special_TIDYLINK special text = special.text return text unless text =~ /\{(.*?)\}\[(.*?)\]/ or text =~ /(\S+)\[(.*?)\]/ label = $1 url = $2 if url =~ /^rdoc-label:foot/ then handle_rdoc_link url else gen_url url, label end end ## # Converts the rdoc-...: links into a Markdown.style links. def handle_special_RDOCLINK special handle_rdoc_link special.text end end PK!3ɀ2.2.0/rdoc/markup/to_ansi.rbnu[## # Outputs RDoc markup with vibrant ANSI color! class RDoc::Markup::ToAnsi < RDoc::Markup::ToRdoc ## # Creates a new ToAnsi visitor that is ready to output vibrant ANSI color! def initialize markup = nil super @headings.clear @headings[1] = ["\e[1;32m", "\e[m"] # bold @headings[2] = ["\e[4;32m", "\e[m"] # underline @headings[3] = ["\e[32m", "\e[m"] # just green end ## # Maps attributes to ANSI sequences def init_tags add_tag :BOLD, "\e[1m", "\e[m" add_tag :TT, "\e[7m", "\e[m" add_tag :EM, "\e[4m", "\e[m" end ## # Overrides indent width to ensure output lines up correctly. def accept_list_item_end list_item width = case @list_type.last when :BULLET then 2 when :NOTE, :LABEL then if @prefix then @res << @prefix.strip @prefix = nil end @res << "\n" unless res.length == 1 2 else bullet = @list_index.last.to_s @list_index[-1] = @list_index.last.succ bullet.length + 2 end @indent -= width end ## # Adds coloring to note and label list items def accept_list_item_start list_item bullet = case @list_type.last when :BULLET then '*' when :NOTE, :LABEL then labels = Array(list_item.label).map do |label| attributes(label).strip end.join "\n" labels << ":\n" unless labels.empty? labels else @list_index.last.to_s + '.' end case @list_type.last when :NOTE, :LABEL then @indent += 2 @prefix = bullet + (' ' * @indent) else @prefix = (' ' * @indent) + bullet.ljust(bullet.length + 1) width = bullet.gsub(/\e\[[\d;]*m/, '').length + 1 @indent += width end end ## # Starts accepting with a reset screen def start_accepting super @res = ["\e[0m"] end end PK!iu002.2.0/rdoc/markup/to_label.rbnu[require 'cgi' ## # Creates HTML-safe labels suitable for use in id attributes. Tidylinks are # converted to their link part and cross-reference links have the suppression # marks removed (\\SomeClass is converted to SomeClass). class RDoc::Markup::ToLabel < RDoc::Markup::Formatter attr_reader :res # :nodoc: ## # Creates a new formatter that will output HTML-safe labels def initialize markup = nil super nil, markup @markup.add_special RDoc::CrossReference::CROSSREF_REGEXP, :CROSSREF @markup.add_special(/(((\{.*?\})|\b\S+?)\[\S+?\])/, :TIDYLINK) add_tag :BOLD, '', '' add_tag :TT, '', '' add_tag :EM, '', '' @res = [] end ## # Converts +text+ to an HTML-safe label def convert text label = convert_flow @am.flow text CGI.escape(label).gsub('%', '-').sub(/^-/, '') end ## # Converts the CROSSREF +special+ to plain text, removing the suppression # marker, if any def handle_special_CROSSREF special text = special.text text.sub(/^\\/, '') end ## # Converts the TIDYLINK +special+ to just the text part def handle_special_TIDYLINK special text = special.text return text unless text =~ /\{(.*?)\}\[(.*?)\]/ or text =~ /(\S+)\[(.*?)\]/ $1 end alias accept_blank_line ignore alias accept_block_quote ignore alias accept_heading ignore alias accept_list_end ignore alias accept_list_item_end ignore alias accept_list_item_start ignore alias accept_list_start ignore alias accept_paragraph ignore alias accept_raw ignore alias accept_rule ignore alias accept_verbatim ignore alias end_accepting ignore alias handle_special_HARD_BREAK ignore alias start_accepting ignore end PK!i"2.2.0/rdoc/markup/include.rbnu[## # A file included at generation time. Objects of this class are created by # RDoc::RD for an extension-less include. # # This implementation in incomplete. class RDoc::Markup::Include ## # The filename to be included, without extension attr_reader :file ## # Directories to search for #file attr_reader :include_path ## # Creates a new include that will import +file+ from +include_path+ def initialize file, include_path @file = file @include_path = include_path end def == other # :nodoc: self.class === other and @file == other.file and @include_path == other.include_path end def pretty_print q # :nodoc: q.group 2, '[incl ', ']' do q.text file q.breakable q.text 'from ' q.pp include_path end end end PK!DKz z 2.2.0/rdoc/markup/document.rbnu[## # A Document containing lists, headings, paragraphs, etc. class RDoc::Markup::Document include Enumerable ## # The file this document was created from. See also # RDoc::ClassModule#add_comment attr_reader :file ## # If a heading is below the given level it will be omitted from the # table_of_contents attr_accessor :omit_headings_below ## # The parts of the Document attr_reader :parts ## # Creates a new Document with +parts+ def initialize *parts @parts = [] @parts.concat parts @file = nil @omit_headings_from_table_of_contents_below = nil end ## # Appends +part+ to the document def << part case part when RDoc::Markup::Document then unless part.empty? then parts.concat part.parts parts << RDoc::Markup::BlankLine.new end when String then raise ArgumentError, "expected RDoc::Markup::Document and friends, got String" unless part.empty? else parts << part end end def == other # :nodoc: self.class == other.class and @file == other.file and @parts == other.parts end ## # Runs this document and all its #items through +visitor+ def accept visitor visitor.start_accepting visitor.accept_document self visitor.end_accepting end ## # Concatenates the given +parts+ onto the document def concat parts self.parts.concat parts end ## # Enumerator for the parts of this document def each &block @parts.each(&block) end ## # Does this document have no parts? def empty? @parts.empty? or (@parts.length == 1 and merged? and @parts.first.empty?) end ## # The file this Document was created from. def file= location @file = case location when RDoc::TopLevel then location.relative_name else location end end ## # When this is a collection of documents (#file is not set and this document # contains only other documents as its direct children) #merge replaces # documents in this class with documents from +other+ when the file matches # and adds documents from +other+ when the files do not. # # The information in +other+ is preferred over the receiver def merge other if empty? then @parts = other.parts return self end other.parts.each do |other_part| self.parts.delete_if do |self_part| self_part.file and self_part.file == other_part.file end self.parts << other_part end self end ## # Does this Document contain other Documents? def merged? RDoc::Markup::Document === @parts.first end def pretty_print q # :nodoc: start = @file ? "[doc (#{@file}): " : '[doc: ' q.group 2, start, ']' do q.seplist @parts do |part| q.pp part end end end ## # Appends +parts+ to the document def push *parts self.parts.concat parts end ## # Returns an Array of headings in the document. # # Require 'rdoc/markup/formatter' before calling this method. def table_of_contents accept RDoc::Markup::ToTableOfContents.to_toc end end PK!1q52.2.0/rdoc/markup/list_item.rbnu[## # An item within a List that contains paragraphs, headings, etc. # # For BULLET, NUMBER, LALPHA and UALPHA lists, the label will always be nil. # For NOTE and LABEL lists, the list label may contain: # # * a single String for a single label # * an Array of Strings for a list item with multiple terms # * nil for an extra description attached to a previously labeled list item class RDoc::Markup::ListItem ## # The label for the ListItem attr_accessor :label ## # Parts of the ListItem attr_reader :parts ## # Creates a new ListItem with an optional +label+ containing +parts+ def initialize label = nil, *parts @label = label @parts = [] @parts.concat parts end ## # Appends +part+ to the ListItem def << part @parts << part end def == other # :nodoc: self.class == other.class and @label == other.label and @parts == other.parts end ## # Runs this list item and all its #parts through +visitor+ def accept visitor visitor.accept_list_item_start self @parts.each do |part| part.accept visitor end visitor.accept_list_item_end self end ## # Is the ListItem empty? def empty? @parts.empty? end ## # Length of parts in the ListItem def length @parts.length end def pretty_print q # :nodoc: q.group 2, '[item: ', ']' do case @label when Array then q.pp @label q.text ';' q.breakable when String then q.pp @label q.text ';' q.breakable end q.seplist @parts do |part| q.pp part end end end ## # Adds +parts+ to the ListItem def push *parts @parts.concat parts end end PK!XT\2.2.0/rdoc/markup/rule.rbnu[## # A horizontal rule with a weight class RDoc::Markup::Rule < Struct.new :weight ## # Calls #accept_rule on +visitor+ def accept visitor visitor.accept_rule self end def pretty_print q # :nodoc: q.group 2, '[rule:', ']' do q.pp weight end end end PK!\cb!2.2.0/rdoc/markup/attr_changer.rbnu[class RDoc::Markup AttrChanger = Struct.new :turn_on, :turn_off # :nodoc: end ## # An AttrChanger records a change in attributes. It contains a bitmap of the # attributes to turn on, and a bitmap of those to turn off. class RDoc::Markup::AttrChanger def to_s # :nodoc: "Attr: +#{turn_on}/-#{turn_off}" end def inspect # :nodoc: '+%d/-%d' % [turn_on, turn_off] end end PK!},$$2.2.0/rdoc/markup/formatter.rbnu[## # Base class for RDoc markup formatters # # Formatters are a visitor that converts an RDoc::Markup tree (from a comment) # into some kind of output. RDoc ships with formatters for converting back to # rdoc, ANSI text, HTML, a Table of Contents and other formats. # # If you'd like to write your own Formatter use # RDoc::Markup::FormatterTestCase. If you're writing a text-output formatter # use RDoc::Markup::TextFormatterTestCase which provides extra test cases. class RDoc::Markup::Formatter ## # Tag for inline markup containing a +bit+ for the bitmask and the +on+ and # +off+ triggers. InlineTag = Struct.new(:bit, :on, :off) ## # Converts a target url to one that is relative to a given path def self.gen_relative_url path, target from = File.dirname path to, to_file = File.split target from = from.split "/" to = to.split "/" from.delete '.' to.delete '.' while from.size > 0 and to.size > 0 and from[0] == to[0] do from.shift to.shift end from.fill ".." from.concat to from << to_file File.join(*from) end ## # Creates a new Formatter def initialize options, markup = nil @options = options @markup = markup || RDoc::Markup.new @am = @markup.attribute_manager @am.add_special(/
    /, :HARD_BREAK) @attributes = @am.attributes @attr_tags = [] @in_tt = 0 @tt_bit = @attributes.bitmap_for :TT @hard_break = '' @from_path = '.' end ## # Adds +document+ to the output def accept_document document document.parts.each do |item| case item when RDoc::Markup::Document then # HACK accept_document item else item.accept self end end end ## # Adds a special for links of the form rdoc-...: def add_special_RDOCLINK @markup.add_special(/rdoc-[a-z]+:[^\s\]]+/, :RDOCLINK) end ## # Adds a special for links of the form {}[] and [] def add_special_TIDYLINK @markup.add_special(/(?: \{.*?\} | # multi-word label \b[^\s{}]+? # single-word label ) \[\S+?\] # link target /x, :TIDYLINK) end ## # Add a new set of tags for an attribute. We allow separate start and end # tags for flexibility def add_tag(name, start, stop) attr = @attributes.bitmap_for name @attr_tags << InlineTag.new(attr, start, stop) end ## # Allows +tag+ to be decorated with additional information. def annotate(tag) tag end ## # Marks up +content+ def convert content @markup.convert content, self end ## # Converts flow items +flow+ def convert_flow(flow) res = [] flow.each do |item| case item when String then res << convert_string(item) when RDoc::Markup::AttrChanger then off_tags res, item on_tags res, item when RDoc::Markup::Special then res << convert_special(item) else raise "Unknown flow element: #{item.inspect}" end end res.join end ## # Converts added specials. See RDoc::Markup#add_special def convert_special special return special.text if in_tt? handled = false @attributes.each_name_of special.type do |name| method_name = "handle_special_#{name}" if respond_to? method_name then special.text = send method_name, special handled = true end end unless handled then special_name = @attributes.as_string special.type raise RDoc::Error, "Unhandled special #{special_name}: #{special}" end special.text end ## # Converts a string to be fancier if desired def convert_string string string end ## # Use ignore in your subclass to ignore the content of a node. # # ## # # We don't support raw nodes in ToNoRaw # # alias accept_raw ignore def ignore *node end ## # Are we currently inside tt tags? def in_tt? @in_tt > 0 end ## # Turns on tags for +item+ on +res+ def on_tags res, item attr_mask = item.turn_on return if attr_mask.zero? @attr_tags.each do |tag| if attr_mask & tag.bit != 0 then res << annotate(tag.on) @in_tt += 1 if tt? tag end end end ## # Turns off tags for +item+ on +res+ def off_tags res, item attr_mask = item.turn_off return if attr_mask.zero? @attr_tags.reverse_each do |tag| if attr_mask & tag.bit != 0 then @in_tt -= 1 if tt? tag res << annotate(tag.off) end end end ## # Extracts and a scheme, url and an anchor id from +url+ and returns them. def parse_url url case url when /^rdoc-label:([^:]*)(?::(.*))?/ then scheme = 'link' path = "##{$1}" id = " id=\"#{$2}\"" if $2 when /([A-Za-z]+):(.*)/ then scheme = $1.downcase path = $2 when /^#/ then else scheme = 'http' path = url url = url end if scheme == 'link' then url = if path[0, 1] == '#' then # is this meaningful? path else self.class.gen_relative_url @from_path, path end end [scheme, url, id] end ## # Is +tag+ a tt tag? def tt? tag tag.bit == @tt_bit end end PK!z!!yy2.2.0/rdoc/markup/to_rdoc.rbnu[## # Outputs RDoc markup as RDoc markup! (mostly) class RDoc::Markup::ToRdoc < RDoc::Markup::Formatter ## # Current indent amount for output in characters attr_accessor :indent ## # Output width in characters attr_accessor :width ## # Stack of current list indexes for alphabetic and numeric lists attr_reader :list_index ## # Stack of list types attr_reader :list_type ## # Stack of list widths for indentation attr_reader :list_width ## # Prefix for the next list item. See #use_prefix attr_reader :prefix ## # Output accumulator attr_reader :res ## # Creates a new formatter that will output (mostly) \RDoc markup def initialize markup = nil super nil, markup @markup.add_special(/\\\S/, :SUPPRESSED_CROSSREF) @width = 78 init_tags @headings = {} @headings.default = [] @headings[1] = ['= ', ''] @headings[2] = ['== ', ''] @headings[3] = ['=== ', ''] @headings[4] = ['==== ', ''] @headings[5] = ['===== ', ''] @headings[6] = ['====== ', ''] @hard_break = "\n" end ## # Maps attributes to HTML sequences def init_tags add_tag :BOLD, "", "" add_tag :TT, "", "" add_tag :EM, "", "" end ## # Adds +blank_line+ to the output def accept_blank_line blank_line @res << "\n" end ## # Adds +paragraph+ to the output def accept_block_quote block_quote @indent += 2 block_quote.parts.each do |part| @prefix = '> ' part.accept self end @indent -= 2 end ## # Adds +heading+ to the output def accept_heading heading use_prefix or @res << ' ' * @indent @res << @headings[heading.level][0] @res << attributes(heading.text) @res << @headings[heading.level][1] @res << "\n" end ## # Finishes consumption of +list+ def accept_list_end list @list_index.pop @list_type.pop @list_width.pop end ## # Finishes consumption of +list_item+ def accept_list_item_end list_item width = case @list_type.last when :BULLET then 2 when :NOTE, :LABEL then if @prefix then @res << @prefix.strip @prefix = nil end @res << "\n" 2 else bullet = @list_index.last.to_s @list_index[-1] = @list_index.last.succ bullet.length + 2 end @indent -= width end ## # Prepares the visitor for consuming +list_item+ def accept_list_item_start list_item type = @list_type.last case type when :NOTE, :LABEL then bullets = Array(list_item.label).map do |label| attributes(label).strip end.join "\n" bullets << ":\n" unless bullets.empty? @prefix = ' ' * @indent @indent += 2 @prefix << bullets + (' ' * @indent) else bullet = type == :BULLET ? '*' : @list_index.last.to_s + '.' @prefix = (' ' * @indent) + bullet.ljust(bullet.length + 1) width = bullet.length + 1 @indent += width end end ## # Prepares the visitor for consuming +list+ def accept_list_start list case list.type when :BULLET then @list_index << nil @list_width << 1 when :LABEL, :NOTE then @list_index << nil @list_width << 2 when :LALPHA then @list_index << 'a' @list_width << list.items.length.to_s.length when :NUMBER then @list_index << 1 @list_width << list.items.length.to_s.length when :UALPHA then @list_index << 'A' @list_width << list.items.length.to_s.length else raise RDoc::Error, "invalid list type #{list.type}" end @list_type << list.type end ## # Adds +paragraph+ to the output def accept_paragraph paragraph text = paragraph.text @hard_break wrap attributes text end ## # Adds +paragraph+ to the output def accept_indented_paragraph paragraph @indent += paragraph.indent text = paragraph.text @hard_break wrap attributes text @indent -= paragraph.indent end ## # Adds +raw+ to the output def accept_raw raw @res << raw.parts.join("\n") end ## # Adds +rule+ to the output def accept_rule rule use_prefix or @res << ' ' * @indent @res << '-' * (@width - @indent) @res << "\n" end ## # Outputs +verbatim+ indented 2 columns def accept_verbatim verbatim indent = ' ' * (@indent + 2) verbatim.parts.each do |part| @res << indent unless part == "\n" @res << part end @res << "\n" unless @res =~ /\n\z/ end ## # Applies attribute-specific markup to +text+ using RDoc::AttributeManager def attributes text flow = @am.flow text.dup convert_flow flow end ## # Returns the generated output def end_accepting @res.join end ## # Removes preceding \\ from the suppressed crossref +special+ def handle_special_SUPPRESSED_CROSSREF special text = special.text text = text.sub('\\', '') unless in_tt? text end ## # Adds a newline to the output def handle_special_HARD_BREAK special "\n" end ## # Prepares the visitor for text generation def start_accepting @res = [""] @indent = 0 @prefix = nil @list_index = [] @list_type = [] @list_width = [] end ## # Adds the stored #prefix to the output and clears it. Lists generate a # prefix for later consumption. def use_prefix prefix, @prefix = @prefix, nil @res << prefix if prefix prefix end ## # Wraps +text+ to #width def wrap text return unless text && !text.empty? text_len = @width - @indent text_len = 20 if text_len < 20 re = /^(.{0,#{text_len}})[ \n]/ next_prefix = ' ' * @indent prefix = @prefix || next_prefix @prefix = nil @res << prefix while text.length > text_len if text =~ re then @res << $1 text.slice!(0, $&.length) else @res << text.slice!(0, text_len) end @res << "\n" << next_prefix end if text.empty? then @res.pop @res.pop else @res << text @res << "\n" end end end PK!+2.2.0/rdoc/markup/to_tt_only.rbnu[## # Extracts sections of text enclosed in plus, tt or code. Used to discover # undocumented parameters. class RDoc::Markup::ToTtOnly < RDoc::Markup::Formatter ## # Stack of list types attr_reader :list_type ## # Output accumulator attr_reader :res ## # Creates a new tt-only formatter. def initialize markup = nil super nil, markup add_tag :TT, nil, nil end ## # Adds tts from +block_quote+ to the output def accept_block_quote block_quote tt_sections block_quote.text end ## # Pops the list type for +list+ from #list_type def accept_list_end list @list_type.pop end ## # Pushes the list type for +list+ onto #list_type def accept_list_start list @list_type << list.type end ## # Prepares the visitor for consuming +list_item+ def accept_list_item_start list_item case @list_type.last when :NOTE, :LABEL then Array(list_item.label).map do |label| tt_sections label end.flatten end end ## # Adds +paragraph+ to the output def accept_paragraph paragraph tt_sections(paragraph.text) end ## # Does nothing to +markup_item+ because it doesn't have any user-built # content def do_nothing markup_item end alias accept_blank_line do_nothing # :nodoc: alias accept_heading do_nothing # :nodoc: alias accept_list_item_end do_nothing # :nodoc: alias accept_raw do_nothing # :nodoc: alias accept_rule do_nothing # :nodoc: alias accept_verbatim do_nothing # :nodoc: ## # Extracts tt sections from +text+ def tt_sections text flow = @am.flow text.dup flow.each do |item| case item when String then @res << item if in_tt? when RDoc::Markup::AttrChanger then off_tags res, item on_tags res, item when RDoc::Markup::Special then @res << convert_special(item) if in_tt? # TODO can this happen? else raise "Unknown flow element: #{item.inspect}" end end res end ## # Returns an Array of items that were wrapped in plus, tt or code. def end_accepting @res.compact end ## # Prepares the visitor for gathering tt sections def start_accepting @res = [] @list_type = [] end end PK!82.2.0/rdoc/markup/raw.rbnu[## # A section of text that is added to the output document as-is class RDoc::Markup::Raw ## # The component parts of the list attr_reader :parts ## # Creates a new Raw containing +parts+ def initialize *parts @parts = [] @parts.concat parts end ## # Appends +text+ def << text @parts << text end def == other # :nodoc: self.class == other.class and @parts == other.parts end ## # Calls #accept_raw+ on +visitor+ def accept visitor visitor.accept_raw self end ## # Appends +other+'s parts def merge other @parts.concat other.parts end def pretty_print q # :nodoc: self.class.name =~ /.*::(\w{1,4})/i q.group 2, "[#{$1.downcase}: ", ']' do q.seplist @parts do |part| q.pp part end end end ## # Appends +texts+ onto this Paragraph def push *texts self.parts.concat texts end ## # The raw text def text @parts.join ' ' end end PK![l&2.2.0/rdoc/markup/attribute_manager.rbnu[## # Manages changes of attributes in a block of text class RDoc::Markup::AttributeManager ## # The NUL character NULL = "\000".freeze #-- # We work by substituting non-printing characters in to the text. For now # I'm assuming that I can substitute a character in the range 0..8 for a 7 # bit character without damaging the encoded string, but this might be # optimistic #++ A_PROTECT = 004 # :nodoc: ## # Special mask character to prevent inline markup handling PROTECT_ATTR = A_PROTECT.chr # :nodoc: ## # The attributes enabled for this markup object. attr_reader :attributes ## # This maps delimiters that occur around words (such as *bold* or +tt+) # where the start and end delimiters and the same. This lets us optimize # the regexp attr_reader :matching_word_pairs ## # And this is used when the delimiters aren't the same. In this case the # hash maps a pattern to the attribute character attr_reader :word_pair_map ## # This maps HTML tags to the corresponding attribute char attr_reader :html_tags ## # A \ in front of a character that would normally be processed turns off # processing. We do this by turning \< into <#{PROTECT} attr_reader :protectable ## # And this maps _special_ sequences to a name. A special sequence is # something like a WikiWord attr_reader :special ## # Creates a new attribute manager that understands bold, emphasized and # teletype text. def initialize @html_tags = {} @matching_word_pairs = {} @protectable = %w[<] @special = [] @word_pair_map = {} @attributes = RDoc::Markup::Attributes.new add_word_pair "*", "*", :BOLD add_word_pair "_", "_", :EM add_word_pair "+", "+", :TT add_html "em", :EM add_html "i", :EM add_html "b", :BOLD add_html "tt", :TT add_html "code", :TT end ## # Return an attribute object with the given turn_on and turn_off bits set def attribute(turn_on, turn_off) RDoc::Markup::AttrChanger.new turn_on, turn_off end ## # Changes the current attribute from +current+ to +new+ def change_attribute current, new diff = current ^ new attribute(new & diff, current & diff) end ## # Used by the tests to change attributes by name from +current_set+ to # +new_set+ def changed_attribute_by_name current_set, new_set current = new = 0 current_set.each do |name| current |= @attributes.bitmap_for(name) end new_set.each do |name| new |= @attributes.bitmap_for(name) end change_attribute(current, new) end ## # Copies +start_pos+ to +end_pos+ from the current string def copy_string(start_pos, end_pos) res = @str[start_pos...end_pos] res.gsub!(/\000/, '') res end ## # Map attributes like textto the sequence # \001\002\001\003, where is a per-attribute specific # character def convert_attrs(str, attrs) # first do matching ones tags = @matching_word_pairs.keys.join("") re = /(^|\W)([#{tags}])([#\\]?[\w:.\/-]+?\S?)\2(\W|$)/ 1 while str.gsub!(re) do attr = @matching_word_pairs[$2] attrs.set_attrs($`.length + $1.length + $2.length, $3.length, attr) $1 + NULL * $2.length + $3 + NULL * $2.length + $4 end # then non-matching unless @word_pair_map.empty? then @word_pair_map.each do |regexp, attr| str.gsub!(regexp) { attrs.set_attrs($`.length + $1.length, $2.length, attr) NULL * $1.length + $2 + NULL * $3.length } end end end ## # Converts HTML tags to RDoc attributes def convert_html(str, attrs) tags = @html_tags.keys.join '|' 1 while str.gsub!(/<(#{tags})>(.*?)<\/\1>/i) { attr = @html_tags[$1.downcase] html_length = $1.length + 2 seq = NULL * html_length attrs.set_attrs($`.length + html_length, $2.length, attr) seq + $2 + seq + NULL } end ## # Converts special sequences to RDoc attributes def convert_specials str, attrs @special.each do |regexp, attribute| str.scan(regexp) do capture = $~.size == 1 ? 0 : 1 s, e = $~.offset capture attrs.set_attrs s, e - s, attribute | @attributes.special end end end ## # Escapes special sequences of text to prevent conversion to RDoc def mask_protected_sequences # protect __send__, __FILE__, etc. @str.gsub!(/__([a-z]+)__/i, "_#{PROTECT_ATTR}_#{PROTECT_ATTR}\\1_#{PROTECT_ATTR}_#{PROTECT_ATTR}") @str.gsub!(/(\A|[^\\])\\([#{Regexp.escape @protectable.join}])/m, "\\1\\2#{PROTECT_ATTR}") @str.gsub!(/\\(\\[#{Regexp.escape @protectable.join}])/m, "\\1") end ## # Unescapes special sequences of text def unmask_protected_sequences @str.gsub!(/(.)#{PROTECT_ATTR}/, "\\1\000") end ## # Adds a markup class with +name+ for words wrapped in the +start+ and # +stop+ character. To make words wrapped with "*" bold: # # am.add_word_pair '*', '*', :BOLD def add_word_pair(start, stop, name) raise ArgumentError, "Word flags may not start with '<'" if start[0,1] == '<' bitmap = @attributes.bitmap_for name if start == stop then @matching_word_pairs[start] = bitmap else pattern = /(#{Regexp.escape start})(\S+)(#{Regexp.escape stop})/ @word_pair_map[pattern] = bitmap end @protectable << start[0,1] @protectable.uniq! end ## # Adds a markup class with +name+ for words surrounded by HTML tag +tag+. # To process emphasis tags: # # am.add_html 'em', :EM def add_html(tag, name) @html_tags[tag.downcase] = @attributes.bitmap_for name end ## # Adds a special handler for +pattern+ with +name+. A simple URL handler # would be: # # @am.add_special(/((https?:)\S+\w)/, :HYPERLINK) def add_special pattern, name @special << [pattern, @attributes.bitmap_for(name)] end ## # Processes +str+ converting attributes, HTML and specials def flow str @str = str mask_protected_sequences @attrs = RDoc::Markup::AttrSpan.new @str.length convert_attrs @str, @attrs convert_html @str, @attrs convert_specials @str, @attrs unmask_protected_sequences split_into_flow end ## # Debug method that prints a string along with its attributes def display_attributes puts puts @str.tr(NULL, "!") bit = 1 16.times do |bno| line = "" @str.length.times do |i| if (@attrs[i] & bit) == 0 line << " " else if bno.zero? line << "S" else line << ("%d" % (bno+1)) end end end puts(line) unless line =~ /^ *$/ bit <<= 1 end end ## # Splits the string into chunks by attribute change def split_into_flow res = [] current_attr = 0 str_len = @str.length # skip leading invisible text i = 0 i += 1 while i < str_len and @str[i].chr == "\0" start_pos = i # then scan the string, chunking it on attribute changes while i < str_len new_attr = @attrs[i] if new_attr != current_attr if i > start_pos res << copy_string(start_pos, i) start_pos = i end res << change_attribute(current_attr, new_attr) current_attr = new_attr if (current_attr & @attributes.special) != 0 then i += 1 while i < str_len and (@attrs[i] & @attributes.special) != 0 res << RDoc::Markup::Special.new(current_attr, copy_string(start_pos, i)) start_pos = i next end end # move on, skipping any invisible characters begin i += 1 end while i < str_len and @str[i].chr == "\0" end # tidy up trailing text if start_pos < str_len res << copy_string(start_pos, str_len) end # and reset to all attributes off res << change_attribute(current_attr, 0) if current_attr != 0 res end end PK!coXX2.2.0/rdoc/markup/inline.rbnu[warn "requiring rdoc/markup/inline is deprecated and will be removed in RDoc 4." if $-w PK!ծA2.2.0/rdoc/markup/hard_break.rbnu[## # A hard-break in the middle of a paragraph. class RDoc::Markup::HardBreak @instance = new ## # RDoc::Markup::HardBreak is a singleton def self.new @instance end ## # Calls #accept_hard_break on +visitor+ def accept visitor visitor.accept_hard_break self end def == other # :nodoc: self.class === other end def pretty_print q # :nodoc: q.text "[break]" end end PK!vaii2.2.0/rdoc/markup/blank_line.rbnu[## # An empty line. This class is a singleton. class RDoc::Markup::BlankLine @instance = new ## # RDoc::Markup::BlankLine is a singleton def self.new @instance end ## # Calls #accept_blank_line on +visitor+ def accept visitor visitor.accept_blank_line self end def pretty_print q # :nodoc: q.text 'blankline' end end PK! 2.2.0/rdoc/markup/block_quote.rbnu[## # A quoted section which contains markup items. class RDoc::Markup::BlockQuote < RDoc::Markup::Raw ## # Calls #accept_block_quote on +visitor+ def accept visitor visitor.accept_block_quote self end end PK!>.>)2.2.0/rdoc/markup/to_table_of_contents.rbnu[## # Extracts just the RDoc::Markup::Heading elements from a # RDoc::Markup::Document to help build a table of contents class RDoc::Markup::ToTableOfContents < RDoc::Markup::Formatter @to_toc = nil ## # Singleton for table-of-contents generation def self.to_toc @to_toc ||= new end ## # Output accumulator attr_reader :res ## # Omits headings with a level less than the given level. attr_accessor :omit_headings_below def initialize # :nodoc: super nil @omit_headings_below = nil end ## # Adds +document+ to the output, using its heading cutoff if present def accept_document document @omit_headings_below = document.omit_headings_below super end ## # Adds +heading+ to the table of contents def accept_heading heading @res << heading unless suppressed? heading end ## # Returns the table of contents def end_accepting @res end ## # Prepares the visitor for text generation def start_accepting @omit_headings_below = nil @res = [] end ## # Returns true if +heading+ is below the display threshold def suppressed? heading return false unless @omit_headings_below heading.level > @omit_headings_below end # :stopdoc: alias accept_block_quote ignore alias accept_raw ignore alias accept_rule ignore alias accept_blank_line ignore alias accept_paragraph ignore alias accept_verbatim ignore alias accept_list_end ignore alias accept_list_item_start ignore alias accept_list_item_end ignore alias accept_list_end_bullet ignore alias accept_list_start ignore # :startdoc: end PK!| -2.2.0/rdoc/markup/text_formatter_test_case.rbnu[## # Test case for creating new plain-text RDoc::Markup formatters. See also # RDoc::Markup::FormatterTestCase # # See test_rdoc_markup_to_rdoc.rb for a complete example. # # Example: # # class TestRDocMarkupToNewTextFormat < RDoc::Markup::TextFormatterTestCase # # add_visitor_tests # add_text_tests # # def setup # super # # @to = RDoc::Markup::ToNewTextFormat.new # end # # def accept_blank_line # assert_equal :junk, @to.res.join # end # # # ... # # end class RDoc::Markup::TextFormatterTestCase < RDoc::Markup::FormatterTestCase ## # Adds test cases to the calling TestCase. def self.add_text_tests self.class_eval do ## # Test case that calls @to.accept_heading def test_accept_heading_indent @to.start_accepting @to.indent = 3 @to.accept_heading @RM::Heading.new(1, 'Hello') accept_heading_indent end ## # Test case that calls @to.accept_rule def test_accept_rule_indent @to.start_accepting @to.indent = 3 @to.accept_rule @RM::Rule.new(1) accept_rule_indent end ## # Test case that calls @to.accept_verbatim def test_accept_verbatim_indent @to.start_accepting @to.indent = 2 @to.accept_verbatim @RM::Verbatim.new("hi\n", " world\n") accept_verbatim_indent end ## # Test case that calls @to.accept_verbatim with a big indent def test_accept_verbatim_big_indent @to.start_accepting @to.indent = 2 @to.accept_verbatim @RM::Verbatim.new("hi\n", "world\n") accept_verbatim_big_indent end ## # Test case that calls @to.accept_paragraph with an indent def test_accept_paragraph_indent @to.start_accepting @to.indent = 3 @to.accept_paragraph @RM::Paragraph.new(('words ' * 30).strip) accept_paragraph_indent end ## # Test case that calls @to.accept_paragraph with a long line def test_accept_paragraph_wrap @to.start_accepting @to.accept_paragraph @RM::Paragraph.new(('words ' * 30).strip) accept_paragraph_wrap end ## # Test case that calls @to.attributes with an escaped # cross-reference. If this test doesn't pass something may be very # wrong. def test_attributes assert_equal 'Dog', @to.attributes("\\Dog") end end end end PK!RR*//%2.2.0/rdoc/markup/to_html_crossref.rbnu[## # Subclass of the RDoc::Markup::ToHtml class that supports looking up method # names, classes, etc to create links. RDoc::CrossReference is used to # generate those links based on the current context. class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml # :stopdoc: ALL_CROSSREF_REGEXP = RDoc::CrossReference::ALL_CROSSREF_REGEXP CLASS_REGEXP_STR = RDoc::CrossReference::CLASS_REGEXP_STR CROSSREF_REGEXP = RDoc::CrossReference::CROSSREF_REGEXP METHOD_REGEXP_STR = RDoc::CrossReference::METHOD_REGEXP_STR # :startdoc: ## # RDoc::CodeObject for generating references attr_accessor :context ## # Should we show '#' characters on method references? attr_accessor :show_hash ## # Creates a new crossref resolver that generates links relative to +context+ # which lives at +from_path+ in the generated files. '#' characters on # references are removed unless +show_hash+ is true. Only method names # preceded by '#' or '::' are linked, unless +hyperlink_all+ is true. def initialize(options, from_path, context, markup = nil) raise ArgumentError, 'from_path cannot be nil' if from_path.nil? super options, markup @context = context @from_path = from_path @hyperlink_all = @options.hyperlink_all @show_hash = @options.show_hash crossref_re = @hyperlink_all ? ALL_CROSSREF_REGEXP : CROSSREF_REGEXP @markup.add_special crossref_re, :CROSSREF @cross_reference = RDoc::CrossReference.new @context end ## # Creates a link to the reference +name+ if the name exists. If +text+ is # given it is used as the link text, otherwise +name+ is used. def cross_reference name, text = nil lookup = name name = name[1..-1] unless @show_hash if name[0, 1] == '#' name = "#{CGI.unescape $'} at #{$1}" if name =~ /(.*[^#:])@/ text = name unless text link lookup, text end ## # We're invoked when any text matches the CROSSREF pattern. If we find the # corresponding reference, generate a link. If the name we're looking for # contains no punctuation, we look for it up the module/class chain. For # example, ToHtml is found, even without the RDoc::Markup:: prefix, # because we look for it in module Markup first. def handle_special_CROSSREF(special) name = special.text return name if name =~ /@[\w-]+\.[\w-]/ # labels that look like emails unless @hyperlink_all then # This ensures that words entirely consisting of lowercase letters will # not have cross-references generated (to suppress lots of erroneous # cross-references to "new" in text, for instance) return name if name =~ /\A[a-z]*\z/ end cross_reference name end ## # Handles rdoc-ref: scheme links and allows RDoc::Markup::ToHtml to # handle other schemes. def handle_special_HYPERLINK special return cross_reference $' if special.text =~ /\Ardoc-ref:/ super end ## # +special+ is an rdoc-schemed link that will be converted into a hyperlink. # For the rdoc-ref scheme the cross-reference will be looked up and the # given name will be used. # # All other contents are handled by # {the superclass}[rdoc-ref:RDoc::Markup::ToHtml#handle_special_RDOCLINK] def handle_special_RDOCLINK special url = special.text case url when /\Ardoc-ref:/ then cross_reference $' else super end end ## # Generates links for rdoc-ref: scheme URLs and allows # RDoc::Markup::ToHtml to handle other schemes. def gen_url url, text return super unless url =~ /\Ardoc-ref:/ cross_reference $', text end ## # Creates an HTML link to +name+ with the given +text+. def link name, text original_name = name if name =~ /(.*[^#:])@/ then name = $1 label = $' end ref = @cross_reference.resolve name, text text = ref.output_name @context if RDoc::MethodAttr === ref and text == original_name case ref when String then ref else path = ref.as_href @from_path if path =~ /#/ then path << "-label-#{label}" elsif ref.sections and ref.sections.any? { |section| label == section.title } then path << "##{label}" else path << "#label-#{label}" end if label "#{text}" end end end PK!Gss2.2.0/rdoc/markup/special.rbnu[## # Hold details of a special sequence class RDoc::Markup::Special ## # Special type attr_reader :type ## # Special text attr_accessor :text ## # Creates a new special sequence of +type+ with +text+ def initialize(type, text) @type, @text = type, text end ## # Specials are equal when the have the same text and type def ==(o) self.text == o.text && self.type == o.type end def inspect # :nodoc: "#" % [ object_id, @type, text.dump] end def to_s # :nodoc: "Special: type=#{type} text=#{text.dump}" end end PK!u2.2.0/rdoc/markup/verbatim.rbnu[## # A section of verbatim text class RDoc::Markup::Verbatim < RDoc::Markup::Raw ## # Format of this verbatim section attr_accessor :format def initialize *parts # :nodoc: super @format = nil end def == other # :nodoc: super and @format == other.format end ## # Calls #accept_verbatim on +visitor+ def accept visitor visitor.accept_verbatim self end ## # Collapses 3+ newlines into two newlines def normalize parts = [] newlines = 0 @parts.each do |part| case part when /^\s*\n/ then newlines += 1 parts << part if newlines == 1 else newlines = 0 parts << part end end parts.pop if parts.last =~ /\A\r?\n\z/ @parts = parts end def pretty_print q # :nodoc: self.class.name =~ /.*::(\w{1,4})/i q.group 2, "[#{$1.downcase}: ", ']' do if @format then q.text "format: #{@format}" q.breakable end q.seplist @parts do |part| q.pp part end end end ## # Is this verbatim section Ruby code? def ruby? @format ||= nil # TODO for older ri data, switch the tree to marshal_dump @format == :ruby end ## # The text of the section def text @parts.join end end PK!S:2.2.0/rdoc/markup/paragraph.rbnu[## # A Paragraph of text class RDoc::Markup::Paragraph < RDoc::Markup::Raw ## # Calls #accept_paragraph on +visitor+ def accept visitor visitor.accept_paragraph self end ## # Joins the raw paragraph text and converts inline HardBreaks to the # +hard_break+ text. def text hard_break = '' @parts.map do |part| if RDoc::Markup::HardBreak === part then hard_break else part end end.join end end PK!aD 2.2.0/rdoc/markup/pre_process.rbnu[## # Handle common directives that can occur in a block of text: # # \:include: filename # # Directives can be escaped by preceding them with a backslash. # # RDoc plugin authors can register additional directives to be handled by # using RDoc::Markup::PreProcess::register. # # Any directive that is not built-in to RDoc (including those registered via # plugins) will be stored in the metadata hash on the CodeObject the comment # is attached to. See RDoc::Markup@Directives for the list of built-in # directives. class RDoc::Markup::PreProcess ## # An RDoc::Options instance that will be filled in with overrides from # directives attr_accessor :options ## # Adds a post-process handler for directives. The handler will be called # with the result RDoc::Comment (or text String) and the code object for the # comment (if any). def self.post_process &block @post_processors << block end ## # Registered post-processors def self.post_processors @post_processors end ## # Registers +directive+ as one handled by RDoc. If a block is given the # directive will be replaced by the result of the block, otherwise the # directive will be removed from the processed text. # # The block will be called with the directive name and the directive # parameter: # # RDoc::Markup::PreProcess.register 'my-directive' do |directive, param| # # replace text, etc. # end def self.register directive, &block @registered[directive] = block end ## # Registered directives def self.registered @registered end ## # Clears all registered directives and post-processors def self.reset @post_processors = [] @registered = {} end reset ## # Creates a new pre-processor for +input_file_name+ that will look for # included files in +include_path+ def initialize(input_file_name, include_path) @input_file_name = input_file_name @include_path = include_path @options = nil end ## # Look for directives in the given +text+. # # Options that we don't handle are yielded. If the block returns false the # directive is restored to the text. If the block returns nil or no block # was given the directive is handled according to the registered directives. # If a String was returned the directive is replaced with the string. # # If no matching directive was registered the directive is restored to the # text. # # If +code_object+ is given and the directive is unknown then the # directive's parameter is set as metadata on the +code_object+. See # RDoc::CodeObject#metadata for details. def handle text, code_object = nil, &block if RDoc::Comment === text then comment = text text = text.text end encoding = text.encoding if defined?(Encoding) # regexp helper (square brackets for optional) # $1 $2 $3 $4 $5 # [prefix][\]:directive:[spaces][param]newline text.gsub!(/^([ \t]*(?:#|\/?\*)?[ \t]*)(\\?):(\w+):([ \t]*)(.+)?(\r?\n|$)/) do # skip something like ':toto::' next $& if $4.empty? and $5 and $5[0, 1] == ':' # skip if escaped next "#$1:#$3:#$4#$5\n" unless $2.empty? # This is not in handle_directive because I didn't want to pass another # argument into it if comment and $3 == 'markup' then next "#{$1.strip}\n" unless $5 comment.format = $5.downcase next "#{$1.strip}\n" end handle_directive $1, $3, $5, code_object, encoding, &block end comment = text unless comment self.class.post_processors.each do |handler| handler.call comment, code_object end text end ## # Performs the actions described by +directive+ and its parameter +param+. # # +code_object+ is used for directives that operate on a class or module. # +prefix+ is used to ensure the replacement for handled directives is # correct. +encoding+ is used for the include directive. # # For a list of directives in RDoc see RDoc::Markup. #-- # When 1.8.7 support is ditched prefix can be defaulted to '' def handle_directive prefix, directive, param, code_object = nil, encoding = nil blankline = "#{prefix.strip}\n" directive = directive.downcase case directive when 'arg', 'args' then return "#{prefix}:#{directive}: #{param}\n" unless code_object code_object.params = param blankline when 'category' then if RDoc::Context === code_object then section = code_object.add_section param code_object.temporary_section = section end blankline # ignore category if we're not on an RDoc::Context when 'doc' then return blankline unless code_object code_object.document_self = true code_object.force_documentation = true blankline when 'enddoc' then return blankline unless code_object code_object.done_documenting = true blankline when 'include' then filename = param.split.first include_file filename, prefix, encoding when 'main' then @options.main_page = param if @options.respond_to? :main_page blankline when 'nodoc' then return blankline unless code_object code_object.document_self = nil # notify nodoc code_object.document_children = param !~ /all/i blankline when 'notnew', 'not_new', 'not-new' then return blankline unless RDoc::AnyMethod === code_object code_object.dont_rename_initialize = true blankline when 'startdoc' then return blankline unless code_object code_object.start_doc code_object.force_documentation = true blankline when 'stopdoc' then return blankline unless code_object code_object.stop_doc blankline when 'title' then @options.default_title = param if @options.respond_to? :default_title= blankline when 'yield', 'yields' then return blankline unless code_object # remove parameter &block code_object.params.sub!(/,?\s*&\w+/, '') if code_object.params code_object.block_params = param blankline else result = yield directive, param if block_given? case result when nil then code_object.metadata[directive] = param if code_object if RDoc::Markup::PreProcess.registered.include? directive then handler = RDoc::Markup::PreProcess.registered[directive] result = handler.call directive, param if handler else result = "#{prefix}:#{directive}: #{param}\n" end when false then result = "#{prefix}:#{directive}: #{param}\n" end result end end ## # Handles the :include: _filename_ directive. # # If the first line of the included file starts with '#', and contains # an encoding information in the form 'coding:' or 'coding=', it is # removed. # # If all lines in the included file start with a '#', this leading '#' # is removed before inclusion. The included content is indented like # the :include: directive. #-- # so all content will be verbatim because of the likely space after '#'? # TODO shift left the whole file content in that case # TODO comment stop/start #-- and #++ in included file must be processed here def include_file name, indent, encoding full_name = find_include_file name unless full_name then warn "Couldn't find file to include '#{name}' from #{@input_file_name}" return '' end content = RDoc::Encoding.read_file full_name, encoding, true # strip magic comment content = content.sub(/\A# .*coding[=:].*$/, '').lstrip # strip leading '#'s, but only if all lines start with them if content =~ /^[^#]/ then content.gsub(/^/, indent) else content.gsub(/^#?/, indent) end end ## # Look for the given file in the directory containing the current file, # and then in each of the directories specified in the RDOC_INCLUDE path def find_include_file(name) to_search = [File.dirname(@input_file_name)].concat @include_path to_search.each do |dir| full_name = File.join(dir, name) stat = File.stat(full_name) rescue next return full_name if stat.readable? end nil end end PK!!]2.2.0/rdoc/markup/attr_span.rbnu[## # An array of attributes which parallels the characters in a string. class RDoc::Markup::AttrSpan ## # Creates a new AttrSpan for +length+ characters def initialize(length) @attrs = Array.new(length, 0) end ## # Toggles +bits+ from +start+ to +length+ def set_attrs(start, length, bits) for i in start ... (start+length) @attrs[i] |= bits end end ## # Accesses flags for character +n+ def [](n) @attrs[n] end end PK!882.2.0/rdoc/markup/parser.rbnu[require 'strscan' ## # A recursive-descent parser for RDoc markup. # # The parser tokenizes an input string then parses the tokens into a Document. # Documents can be converted into output formats by writing a visitor like # RDoc::Markup::ToHTML. # # The parser only handles the block-level constructs Paragraph, List, # ListItem, Heading, Verbatim, BlankLine and Rule. Inline markup such as # \+blah\+ is handled separately by RDoc::Markup::AttributeManager. # # To see what markup the Parser implements read RDoc. To see how to use # RDoc markup to format text in your program read RDoc::Markup. class RDoc::Markup::Parser include RDoc::Text ## # List token types LIST_TOKENS = [ :BULLET, :LABEL, :LALPHA, :NOTE, :NUMBER, :UALPHA, ] ## # Parser error subclass class Error < RuntimeError; end ## # Raised when the parser is unable to handle the given markup class ParseError < Error; end ## # Enables display of debugging information attr_accessor :debug ## # Token accessor attr_reader :tokens ## # Parses +str+ into a Document. # # Use RDoc::Markup#parse instead of this method. def self.parse str parser = new parser.tokenize str doc = RDoc::Markup::Document.new parser.parse doc end ## # Returns a token stream for +str+, for testing def self.tokenize str parser = new parser.tokenize str parser.tokens end ## # Creates a new Parser. See also ::parse def initialize @binary_input = nil @current_token = nil @debug = false @have_encoding = Object.const_defined? :Encoding @have_byteslice = ''.respond_to? :byteslice @input = nil @input_encoding = nil @line = 0 @line_pos = 0 @s = nil @tokens = [] end ## # Builds a Heading of +level+ def build_heading level type, text, = get text = case type when :TEXT then skip :NEWLINE text else unget '' end RDoc::Markup::Heading.new level, text end ## # Builds a List flush to +margin+ def build_list margin p :list_start => margin if @debug list = RDoc::Markup::List.new label = nil until @tokens.empty? do type, data, column, = get case type when *LIST_TOKENS then if column < margin || (list.type && list.type != type) then unget break end list.type = type peek_type, _, column, = peek_token case type when :NOTE, :LABEL then label = [] unless label if peek_type == :NEWLINE then # description not on the same line as LABEL/NOTE # skip the trailing newline & any blank lines below while peek_type == :NEWLINE get peek_type, _, column, = peek_token end # we may be: # - at end of stream # - at a column < margin: # [text] # blah blah blah # - at the same column, but with a different type of list item # [text] # * blah blah # - at the same column, with the same type of list item # [one] # [two] # In all cases, we have an empty description. # In the last case only, we continue. if peek_type.nil? || column < margin then empty = true elsif column == margin then case peek_type when type empty = :continue when *LIST_TOKENS empty = true else empty = false end else empty = false end if empty then label << data next if empty == :continue break end end else data = nil end if label then data = label << data label = nil end list_item = RDoc::Markup::ListItem.new data parse list_item, column list << list_item else unget break end end p :list_end => margin if @debug if list.empty? then return nil unless label return nil unless [:LABEL, :NOTE].include? list.type list_item = RDoc::Markup::ListItem.new label, RDoc::Markup::BlankLine.new list << list_item end list end ## # Builds a Paragraph that is flush to +margin+ def build_paragraph margin p :paragraph_start => margin if @debug paragraph = RDoc::Markup::Paragraph.new until @tokens.empty? do type, data, column, = get if type == :TEXT and column == margin then paragraph << data break if peek_token.first == :BREAK data << ' ' if skip :NEWLINE else unget break end end paragraph.parts.last.sub!(/ \z/, '') # cleanup p :paragraph_end => margin if @debug paragraph end ## # Builds a Verbatim that is indented from +margin+. # # The verbatim block is shifted left (the least indented lines start in # column 0). Each part of the verbatim is one line of text, always # terminated by a newline. Blank lines always consist of a single newline # character, and there is never a single newline at the end of the verbatim. def build_verbatim margin p :verbatim_begin => margin if @debug verbatim = RDoc::Markup::Verbatim.new min_indent = nil generate_leading_spaces = true line = '' until @tokens.empty? do type, data, column, = get if type == :NEWLINE then line << data verbatim << line line = '' generate_leading_spaces = true next end if column <= margin unget break end if generate_leading_spaces then indent = column - margin line << ' ' * indent min_indent = indent if min_indent.nil? || indent < min_indent generate_leading_spaces = false end case type when :HEADER then line << '=' * data _, _, peek_column, = peek_token peek_column ||= column + data indent = peek_column - column - data line << ' ' * indent when :RULE then width = 2 + data line << '-' * width _, _, peek_column, = peek_token peek_column ||= column + width indent = peek_column - column - width line << ' ' * indent when :BREAK, :TEXT then line << data else # *LIST_TOKENS list_marker = case type when :BULLET then data when :LABEL then "[#{data}]" when :NOTE then "#{data}::" else # :LALPHA, :NUMBER, :UALPHA "#{data}." end line << list_marker peek_type, _, peek_column = peek_token unless peek_type == :NEWLINE then peek_column ||= column + list_marker.length indent = peek_column - column - list_marker.length line << ' ' * indent end end end verbatim << line << "\n" unless line.empty? verbatim.parts.each { |p| p.slice!(0, min_indent) unless p == "\n" } if min_indent > 0 verbatim.normalize p :verbatim_end => margin if @debug verbatim end ## # The character offset for the input string at the given +byte_offset+ def char_pos byte_offset if @have_byteslice then @input.byteslice(0, byte_offset).length elsif @have_encoding then matched = @binary_input[0, byte_offset] matched.force_encoding @input_encoding matched.length else byte_offset end end ## # Pulls the next token from the stream. def get @current_token = @tokens.shift p :get => @current_token if @debug @current_token end ## # Parses the tokens into an array of RDoc::Markup::XXX objects, # and appends them to the passed +parent+ RDoc::Markup::YYY object. # # Exits at the end of the token stream, or when it encounters a token # in a column less than +indent+ (unless it is a NEWLINE). # # Returns +parent+. def parse parent, indent = 0 p :parse_start => indent if @debug until @tokens.empty? do type, data, column, = get case type when :BREAK then parent << RDoc::Markup::BlankLine.new skip :NEWLINE, false next when :NEWLINE then # trailing newlines are skipped below, so this is a blank line parent << RDoc::Markup::BlankLine.new skip :NEWLINE, false next end # indentation change: break or verbatim if column < indent then unget break elsif column > indent then unget parent << build_verbatim(indent) next end # indentation is the same case type when :HEADER then parent << build_heading(data) when :RULE then parent << RDoc::Markup::Rule.new(data) skip :NEWLINE when :TEXT then unget parse_text parent, indent when *LIST_TOKENS then unget parent << build_list(indent) else type, data, column, line = @current_token raise ParseError, "Unhandled token #{type} (#{data.inspect}) at #{line}:#{column}" end end p :parse_end => indent if @debug parent end ## # Small hook that is overridden by RDoc::TomDoc def parse_text parent, indent # :nodoc: parent << build_paragraph(indent) end ## # Returns the next token on the stream without modifying the stream def peek_token token = @tokens.first || [] p :peek => token if @debug token end ## # Creates the StringScanner def setup_scanner input @line = 0 @line_pos = 0 @input = input.dup if @have_encoding and not @have_byteslice then @input_encoding = @input.encoding @binary_input = @input.force_encoding Encoding::BINARY end @s = StringScanner.new input end ## # Skips the next token if its type is +token_type+. # # Optionally raises an error if the next token is not of the expected type. def skip token_type, error = true type, = get return unless type # end of stream return @current_token if token_type == type unget raise ParseError, "expected #{token_type} got #{@current_token.inspect}" if error end ## # Turns text +input+ into a stream of tokens def tokenize input setup_scanner input until @s.eos? do pos = @s.pos # leading spaces will be reflected by the column of the next token # the only thing we loose are trailing spaces at the end of the file next if @s.scan(/ +/) # note: after BULLET, LABEL, etc., # indent will be the column of the next non-newline token @tokens << case # [CR]LF => :NEWLINE when @s.scan(/\r?\n/) then token = [:NEWLINE, @s.matched, *token_pos(pos)] @line_pos = char_pos @s.pos @line += 1 token # === text => :HEADER then :TEXT when @s.scan(/(=+)(\s*)/) then level = @s[1].length header = [:HEADER, level, *token_pos(pos)] if @s[2] =~ /^\r?\n/ then @s.pos -= @s[2].length header else pos = @s.pos @s.scan(/.*/) @tokens << header [:TEXT, @s.matched.sub(/\r$/, ''), *token_pos(pos)] end # --- (at least 3) and nothing else on the line => :RULE when @s.scan(/(-{3,}) *\r?$/) then [:RULE, @s[1].length - 2, *token_pos(pos)] # * or - followed by white space and text => :BULLET when @s.scan(/([*-]) +(\S)/) then @s.pos -= @s[2].bytesize # unget \S [:BULLET, @s[1], *token_pos(pos)] # A. text, a. text, 12. text => :UALPHA, :LALPHA, :NUMBER when @s.scan(/([a-z]|\d+)\. +(\S)/i) then # FIXME if tab(s), the column will be wrong # either support tabs everywhere by first expanding them to # spaces, or assume that they will have been replaced # before (and provide a check for that at least in debug # mode) list_label = @s[1] @s.pos -= @s[2].bytesize # unget \S list_type = case list_label when /[a-z]/ then :LALPHA when /[A-Z]/ then :UALPHA when /\d/ then :NUMBER else raise ParseError, "BUG token #{list_label}" end [list_type, list_label, *token_pos(pos)] # [text] followed by spaces or end of line => :LABEL when @s.scan(/\[(.*?)\]( +|\r?$)/) then [:LABEL, @s[1], *token_pos(pos)] # text:: followed by spaces or end of line => :NOTE when @s.scan(/(.*?)::( +|\r?$)/) then [:NOTE, @s[1], *token_pos(pos)] # anything else: :TEXT else @s.scan(/(.*?)( )?\r?$/) token = [:TEXT, @s[1], *token_pos(pos)] if @s[2] then @tokens << token [:BREAK, @s[2], *token_pos(pos + @s[1].length)] else token end end end self end ## # Calculates the column (by character) and line of the current token based # on +byte_offset+. def token_pos byte_offset offset = char_pos byte_offset [offset - @line_pos, @line] end ## # Returns the current token to the token stream def unget token = @current_token p :unget => token if @debug raise Error, 'too many #ungets' if token == @tokens.first @tokens.unshift token if token end end PK!2.2.0/rdoc/erbio.rbnu[require 'erb' ## # A subclass of ERB that writes directly to an IO. Credit to Aaron Patterson # and Masatoshi SEKI. # # To use: # # erbio = RDoc::ERBIO.new '<%= "hello world" %>', nil, nil # # open 'hello.txt', 'w' do |io| # erbio.result binding # end # # Note that binding must enclose the io you wish to output on. class RDoc::ERBIO < ERB ## # Defaults +eoutvar+ to 'io', otherwise is identical to ERB's initialize def initialize str, safe_level = nil, trim_mode = nil, eoutvar = 'io' super end ## # Instructs +compiler+ how to write to +io_variable+ def set_eoutvar compiler, io_variable compiler.put_cmd = "#{io_variable}.write" compiler.insert_cmd = "#{io_variable}.write" compiler.pre_cmd = [] compiler.post_cmd = [] end end PK!#Q''2.2.0/rdoc/rd.rbnu[## # RDoc::RD implements the RD format from the rdtool gem. # # To choose RD as your only default format see # RDoc::Options@Saved+Options for instructions on setting up a # .doc_options file to store your project default. # # == LICENSE # # The grammar that produces RDoc::RD::BlockParser and RDoc::RD::InlineParser # is included in RDoc under the Ruby License. # # You can find the original source for rdtool at # https://github.com/uwabami/rdtool/ # # You can use, re-distribute or change these files under Ruby's License or GPL. # # 1. You may make and give away verbatim copies of the source form of the # software without restriction, provided that you duplicate all of the # original copyright notices and associated disclaimers. # # 2. You may modify your copy of the software in any way, provided that # you do at least ONE of the following: # # a. place your modifications in the Public Domain or otherwise # make them Freely Available, such as by posting said # modifications to Usenet or an equivalent medium, or by allowing # the author to include your modifications in the software. # # b. use the modified software only within your corporation or # organization. # # c. give non-standard binaries non-standard names, with # instructions on where to get the original software distribution. # # d. make other distribution arrangements with the author. # # 3. You may distribute the software in object code or binary form, # provided that you do at least ONE of the following: # # a. distribute the binaries and library files of the software, # together with instructions (in the manual page or equivalent) # on where to get the original distribution. # # b. accompany the distribution with the machine-readable source of # the software. # # c. give non-standard binaries non-standard names, with # instructions on where to get the original software distribution. # # d. make other distribution arrangements with the author. # # 4. You may modify and include the part of the software into any other # software (possibly commercial). But some files in the distribution # are not written by the author, so that they are not under these terms. # # For the list of those files and their copying conditions, see the # file LEGAL. # # 5. The scripts and library files supplied as input to or produced as # output from the software do not automatically fall under the # copyright of the software, but belong to whomever generated them, # and may be sold commercially, and may be aggregated with this # software. # # 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE. class RDoc::RD ## # Parses +rd+ source and returns an RDoc::Markup::Document. If the # =begin or =end lines are missing they will be added. def self.parse rd rd = rd.lines.to_a if rd.find { |i| /\S/ === i } and !rd.find{|i| /^=begin\b/ === i } then rd.unshift("=begin\n").push("=end\n") end parser = RDoc::RD::BlockParser.new document = parser.parse rd # isn't this always true? document.parts.shift if RDoc::Markup::BlankLine === document.parts.first document.parts.pop if RDoc::Markup::BlankLine === document.parts.last document end autoload :BlockParser, 'rdoc/rd/block_parser' autoload :InlineParser, 'rdoc/rd/inline_parser' autoload :Inline, 'rdoc/rd/inline' end PK![>>2.2.0/rdoc/text.rbnu[# coding: utf-8 ## # For RDoc::Text#to_html require 'strscan' ## # For RDoc::Text#snippet begin gem 'json' rescue Gem::LoadError end require 'json' ## # Methods for manipulating comment text module RDoc::Text ## # Maps markup formats to classes that can parse them. If the format is # unknown, "rdoc" format is used. MARKUP_FORMAT = { 'markdown' => RDoc::Markdown, 'rdoc' => RDoc::Markup, 'rd' => RDoc::RD, 'tomdoc' => RDoc::TomDoc, } MARKUP_FORMAT.default = RDoc::Markup ## # Maps an encoding to a Hash of characters properly transcoded for that # encoding. # # See also encode_fallback. TO_HTML_CHARACTERS = Hash.new do |h, encoding| h[encoding] = { :close_dquote => encode_fallback('”', encoding, '"'), :close_squote => encode_fallback('’', encoding, '\''), :copyright => encode_fallback('©', encoding, '(c)'), :ellipsis => encode_fallback('…', encoding, '...'), :em_dash => encode_fallback('—', encoding, '---'), :en_dash => encode_fallback('–', encoding, '--'), :open_dquote => encode_fallback('“', encoding, '"'), :open_squote => encode_fallback('‘', encoding, '\''), :trademark => encode_fallback('®', encoding, '(r)'), } end if Object.const_defined? :Encoding ## # Transcodes +character+ to +encoding+ with a +fallback+ character. def self.encode_fallback character, encoding, fallback character.encode(encoding, :fallback => { character => fallback }, :undef => :replace, :replace => fallback) end ## # Expands tab characters in +text+ to eight spaces def expand_tabs text expanded = [] text.each_line do |line| nil while line.gsub!(/(?:\G|\r)((?:.{8})*?)([^\t\r\n]{0,7})\t/) do r = "#{$1}#{$2}#{' ' * (8 - $2.size)}" r.force_encoding text.encoding if Object.const_defined? :Encoding r end expanded << line end expanded.join end ## # Flush +text+ left based on the shortest line def flush_left text indent = 9999 text.each_line do |line| line_indent = line =~ /\S/ || 9999 indent = line_indent if indent > line_indent end empty = '' empty.force_encoding text.encoding if Object.const_defined? :Encoding text.gsub(/^ {0,#{indent}}/, empty) end ## # Convert a string in markup format into HTML. # # Requires the including class to implement #formatter def markup text if @store.rdoc.options locale = @store.rdoc.options.locale else locale = nil end if locale i18n_text = RDoc::I18n::Text.new(text) text = i18n_text.translate(locale) end parse(text).accept formatter end ## # Strips hashes, expands tabs then flushes +text+ to the left def normalize_comment text return text if text.empty? text = strip_stars text text = strip_hashes text text = expand_tabs text text = flush_left text text = strip_newlines text text end ## # Normalizes +text+ then builds a RDoc::Markup::Document from it def parse text, format = 'rdoc' return text if RDoc::Markup::Document === text return text.parse if RDoc::Comment === text text = normalize_comment text # TODO remove, should not be necessary return RDoc::Markup::Document.new if text =~ /\A\n*\z/ MARKUP_FORMAT[format].parse text end ## # The first +limit+ characters of +text+ as HTML def snippet text, limit = 100 document = parse text RDoc::Markup::ToHtmlSnippet.new(options, limit).convert document end ## # Strips leading # characters from +text+ def strip_hashes text return text if text =~ /^(?>\s*)[^\#]/ empty = '' empty.force_encoding text.encoding if Object.const_defined? :Encoding text.gsub(/^\s*(#+)/) { $1.tr '#', ' ' }.gsub(/^\s+$/, empty) end ## # Strips leading and trailing \n characters from +text+ def strip_newlines text text.gsub(/\A\n*(.*?)\n*\z/m) do $1 end # block preserves String encoding end ## # Strips /* */ style comments def strip_stars text return text unless text =~ %r%/\*.*\*/%m encoding = text.encoding if Object.const_defined? :Encoding text = text.gsub %r%Document-method:\s+[\w:.#=!?]+%, '' space = ' ' space.force_encoding encoding if encoding text.sub! %r%/\*+% do space * $&.length end text.sub! %r%\*+/% do space * $&.length end text.gsub! %r%^[ \t]*\*%m do space * $&.length end empty = '' empty.force_encoding encoding if encoding text.gsub(/^\s+$/, empty) end ## # Converts ampersand, dashes, ellipsis, quotes, copyright and registered # trademark symbols in +text+ to properly encoded characters. def to_html text if Object.const_defined? :Encoding then html = ''.encode text.encoding encoded = RDoc::Text::TO_HTML_CHARACTERS[text.encoding] else html = '' encoded = { :close_dquote => '”', :close_squote => '’', :copyright => '©', :ellipsis => '…', :em_dash => '—', :en_dash => '–', :open_dquote => '“', :open_squote => '‘', :trademark => '®', } end s = StringScanner.new text insquotes = false indquotes = false after_word = nil until s.eos? do case when s.scan(/<(tt|code)>.*?<\/\1>/) then # skip contents of tt html << s.matched.gsub('\\\\', '\\') when s.scan(/<(tt|code)>.*?/) then warn "mismatched <#{s[1]}> tag" # TODO signal file/line html << s.matched when s.scan(/<[^>]+\/?s*>/) then # skip HTML tags html << s.matched when s.scan(/\\(\S)/) then # unhandled suppressed crossref html << s[1] after_word = nil when s.scan(/\.\.\.(\.?)/) then html << s[1] << encoded[:ellipsis] after_word = nil when s.scan(/\(c\)/) then html << encoded[:copyright] after_word = nil when s.scan(/\(r\)/) then html << encoded[:trademark] after_word = nil when s.scan(/---/) then html << encoded[:em_dash] after_word = nil when s.scan(/--/) then html << encoded[:en_dash] after_word = nil when s.scan(/"|"/) then html << encoded[indquotes ? :close_dquote : :open_dquote] indquotes = !indquotes after_word = nil when s.scan(/``/) then # backtick double quote html << encoded[:open_dquote] after_word = nil when s.scan(/''/) then # tick double quote html << encoded[:close_dquote] after_word = nil when s.scan(/'/) then # single quote if insquotes html << encoded[:close_squote] insquotes = false elsif after_word # Mary's dog, my parents' house: do not start paired quotes html << encoded[:close_squote] else html << encoded[:open_squote] insquotes = true end after_word = nil else # advance to the next potentially significant character match = s.scan(/.+?(?=[<\\.("'`&-])/) #" if match then html << match after_word = match =~ /\w$/ else html << s.rest break end end end html end ## # Wraps +txt+ to +line_len+ def wrap(txt, line_len = 76) res = [] sp = 0 ep = txt.length while sp < ep # scan back for a space p = sp + line_len - 1 if p >= ep p = ep else while p > sp and txt[p] != ?\s p -= 1 end if p <= sp p = sp + line_len while p < ep and txt[p] != ?\s p += 1 end end end res << txt[sp...p] << "\n" sp = p sp += 1 while sp < ep and txt[sp] == ?\s end res.join.strip end end PK! ˩2.2.0/rdoc/anon_class.rbnu[## # An anonymous class like: # # c = Class.new do end # # AnonClass is currently not used. class RDoc::AnonClass < RDoc::ClassModule end PK! ۝L-L-2.2.0/rdoc/ruby_token.rbnu[#-- # irb/ruby-token.rb - ruby tokens # $Release Version: 0.9.5$ # $Revision: 11708 $ # $Date: 2007-02-12 15:01:19 -0800 (Mon, 12 Feb 2007) $ # by Keiju ISHITSUKA(keiju@ruby-lang.org) #++ # Definitions of all tokens involved in the lexical analysis. # # This class is not documented because it is so deep in the internals. module RDoc::RubyToken # :stopdoc: EXPR_BEG = :EXPR_BEG EXPR_MID = :EXPR_MID EXPR_END = :EXPR_END EXPR_ARG = :EXPR_ARG EXPR_FNAME = :EXPR_FNAME EXPR_DOT = :EXPR_DOT EXPR_CLASS = :EXPR_CLASS # for ruby 1.4X if !defined?(Symbol) Symbol = Integer end def set_token_position(line, char) @prev_line_no = line @prev_char_no = char end class Token def initialize(seek, line_no, char_no, text = nil) @seek = seek @line_no = line_no @char_no = char_no @text = text end attr_reader :seek attr_reader :line_no attr_reader :char_no attr_accessor :text def ==(other) self.class == other.class and other.line_no == @line_no and other.char_no == @char_no and other.text == @text end ## # Because we're used in contexts that expect to return a token, we set the # text string and then return ourselves def set_text(text) @text = text self end def inspect # :nodoc: klass = self.class.name.split('::').last "{%s %d, %d:%d %p}" % [klass, @seek, @line_no, @char_no, @text] end end class TkNode < Token def initialize(seek, line_no, char_no, node = nil) super seek, line_no, char_no @node = node end attr_reader:node def ==(other) self.class == other.class and other.line_no == @line_no and other.char_no == @char_no and other.node == @node end def set_text text @node = text self end alias text node def inspect # :nodoc: klass = self.class.name.split('::').last "{%s %d, %d:%d %p}" % [klass, @seek, @line_no, @char_no, @node] end end class TkId < Token def initialize(seek, line_no, char_no, name) super(seek, line_no, char_no) @name = name end attr_reader:name def ==(other) self.class == other.class and other.line_no == @line_no and other.char_no == @char_no and other.name == @name end def set_text text @name = text self end alias text name def inspect # :nodoc: klass = self.class.name.split('::').last "{%s %d, %d:%d %p}" % [klass, @seek, @line_no, @char_no, @name] end end class TkKW < TkId end class TkVal < Token def initialize(seek, line_no, char_no, value = nil) super(seek, line_no, char_no) @value = value end attr_accessor :value def ==(other) self.class == other.class and other.line_no == @line_no and other.char_no == @char_no and other.value == @value end def set_text text @value = text self end alias text value def inspect # :nodoc: klass = self.class.name.split('::').last "{%s %s, %d:%d %p}" % [klass, @seek, @line_no, @char_no, @value] end end class TkOp < Token def initialize(seek, line_no, char_no, name = nil) super seek, line_no, char_no @name = name end attr_accessor :name def ==(other) self.class == other.class and other.line_no == @line_no and other.char_no == @char_no and other.name == @name end def set_text text @name = text self end alias text name def inspect # :nodoc: klass = self.class.name.split('::').last "{%s %d, %d:%d %p}" % [klass, @seek, @line_no, @char_no, @name] end end class TkOPASGN < TkOp def initialize(seek, line_no, char_no, op) super(seek, line_no, char_no) op = TkReading2Token[op][0] unless op.kind_of?(Symbol) @op = op @text = nil end attr_reader:op def ==(other) self.class == other.class and other.line_no == @line_no and other.char_no == @char_no and other.op == @op end def text @text ||= "#{TkToken2Reading[op]}=" end def inspect # :nodoc: klass = self.class.name.split('::').last "{%s %d, %d:%d %p}" % [klass, @seek, @line_no, @char_no, @op] end end class TkUnknownChar < Token def initialize(seek, line_no, char_no, name) super(seek, line_no, char_no) @name = name end attr_reader:name def ==(other) self.class == other.class and other.line_no == @line_no and other.char_no == @char_no and other.name == @name end def set_text text @name = text self end alias text name def inspect # :nodoc: klass = self.class.name.split('::').last "{%s %d, %d:%d %p}" % [klass, @seek, @line_no, @char_no, @name] end end class TkError < Token end def Token(token, value = nil) value ||= TkToken2Reading[token] case token when String if (tk = TkReading2Token[token]).nil? IRB.fail TkReading2TokenNoKey, token end tk = Token(tk[0], value) if tk.kind_of?(TkOp) then tk.name = token end when Symbol if (tk = TkSymbol2Token[token]).nil? IRB.fail TkSymbol2TokenNoKey, token end tk = Token(tk[0], value) else if token.instance_method(:initialize).arity == 3 then tk = token.new(@prev_seek, @prev_line_no, @prev_char_no) tk.set_text value else tk = token.new(@prev_seek, @prev_line_no, @prev_char_no, value) end end tk end TokenDefinitions = [ [:TkCLASS, TkKW, "class", :EXPR_CLASS], [:TkMODULE, TkKW, "module", :EXPR_BEG], [:TkDEF, TkKW, "def", :EXPR_FNAME], [:TkUNDEF, TkKW, "undef", :EXPR_FNAME], [:TkBEGIN, TkKW, "begin", :EXPR_BEG], [:TkRESCUE, TkKW, "rescue", :EXPR_MID], [:TkENSURE, TkKW, "ensure", :EXPR_BEG], [:TkEND, TkKW, "end", :EXPR_END], [:TkIF, TkKW, "if", :EXPR_BEG, :TkIF_MOD], [:TkUNLESS, TkKW, "unless", :EXPR_BEG, :TkUNLESS_MOD], [:TkTHEN, TkKW, "then", :EXPR_BEG], [:TkELSIF, TkKW, "elsif", :EXPR_BEG], [:TkELSE, TkKW, "else", :EXPR_BEG], [:TkCASE, TkKW, "case", :EXPR_BEG], [:TkWHEN, TkKW, "when", :EXPR_BEG], [:TkWHILE, TkKW, "while", :EXPR_BEG, :TkWHILE_MOD], [:TkUNTIL, TkKW, "until", :EXPR_BEG, :TkUNTIL_MOD], [:TkFOR, TkKW, "for", :EXPR_BEG], [:TkBREAK, TkKW, "break", :EXPR_MID], [:TkNEXT, TkKW, "next", :EXPR_END], [:TkREDO, TkKW, "redo", :EXPR_END], [:TkRETRY, TkKW, "retry", :EXPR_END], [:TkIN, TkKW, "in", :EXPR_BEG], [:TkDO, TkKW, "do", :EXPR_BEG], [:TkRETURN, TkKW, "return", :EXPR_MID], [:TkYIELD, TkKW, "yield", :EXPR_END], [:TkSUPER, TkKW, "super", :EXPR_END], [:TkSELF, TkKW, "self", :EXPR_END], [:TkNIL, TkKW, "nil", :EXPR_END], [:TkTRUE, TkKW, "true", :EXPR_END], [:TkFALSE, TkKW, "false", :EXPR_END], [:TkAND, TkKW, "and", :EXPR_BEG], [:TkOR, TkKW, "or", :EXPR_BEG], [:TkNOT, TkKW, "not", :EXPR_BEG], [:TkIF_MOD, TkKW], [:TkUNLESS_MOD, TkKW], [:TkWHILE_MOD, TkKW], [:TkUNTIL_MOD, TkKW], [:TkALIAS, TkKW, "alias", :EXPR_FNAME], [:TkDEFINED, TkKW, "defined?", :EXPR_END], [:TklBEGIN, TkKW, "BEGIN", :EXPR_END], [:TklEND, TkKW, "END", :EXPR_END], [:Tk__LINE__, TkKW, "__LINE__", :EXPR_END], [:Tk__FILE__, TkKW, "__FILE__", :EXPR_END], [:TkIDENTIFIER, TkId], [:TkFID, TkId], [:TkGVAR, TkId], [:TkCVAR, TkId], [:TkIVAR, TkId], [:TkCONSTANT, TkId], [:TkINTEGER, TkVal], [:TkFLOAT, TkVal], [:TkSTRING, TkVal], [:TkHEREDOC, TkVal], [:TkXSTRING, TkVal], [:TkREGEXP, TkVal], [:TkSYMBOL, TkVal], [:TkCHAR, TkVal], [:TkDSTRING, TkNode], [:TkDXSTRING, TkNode], [:TkDREGEXP, TkNode], [:TkNTH_REF, TkNode], [:TkBACK_REF, TkNode], [:TkUPLUS, TkOp, "+@"], [:TkUMINUS, TkOp, "-@"], [:TkPOW, TkOp, "**"], [:TkCMP, TkOp, "<=>"], [:TkEQ, TkOp, "=="], [:TkEQQ, TkOp, "==="], [:TkNEQ, TkOp, "!="], [:TkGEQ, TkOp, ">="], [:TkLEQ, TkOp, "<="], [:TkANDOP, TkOp, "&&"], [:TkOROP, TkOp, "||"], [:TkMATCH, TkOp, "=~"], [:TkNMATCH, TkOp, "!~"], [:TkDOT2, TkOp, ".."], [:TkDOT3, TkOp, "..."], [:TkAREF, TkOp, "[]"], [:TkASET, TkOp, "[]="], [:TkLSHFT, TkOp, "<<"], [:TkRSHFT, TkOp, ">>"], [:TkCOLON2, TkOp, '::'], [:TkCOLON3, TkOp, '::'], #[:OPASGN, TkOp], # +=, -= etc. # [:TkASSOC, TkOp, "=>"], [:TkQUESTION, TkOp, "?"], #? [:TkCOLON, TkOp, ":"], #: [:TkfLPAREN, Token, "("], # func( # [:TkfLBRACK, Token, "["], # func[ # [:TkfLBRACE, Token, "{"], # func{ # [:TkSYMBEG, Token, ":"], # :SYMBOL [:TkAMPER, TkOp, "&"], [:TkGT, TkOp, ">"], [:TkLT, TkOp, "<"], [:TkPLUS, TkOp, "+"], [:TkSTAR, TkOp, "*"], [:TkMINUS, TkOp, "-"], [:TkMULT, TkOp, "*"], [:TkDIV, TkOp, "/"], [:TkMOD, TkOp, "%"], [:TkBITOR, TkOp, "|"], [:TkBITXOR, TkOp, "^"], [:TkBITAND, TkOp, "&"], [:TkBITNOT, TkOp, "~"], [:TkNOTOP, TkOp, "!"], [:TkBACKQUOTE, TkOp, "`"], [:TkASSIGN, Token, "="], [:TkDOT, Token, "."], [:TkLPAREN, Token, "("], #(exp) [:TkLBRACK, Token, "["], #[arry] [:TkLBRACE, Token, "{"], #{hash} [:TkRPAREN, Token, ")"], [:TkRBRACK, Token, "]"], [:TkRBRACE, Token, "}"], [:TkCOMMA, Token, ","], [:TkSEMICOLON, Token, ";"], [:TkCOMMENT, TkVal], [:TkSPACE, Token, " "], [:TkNL, Token, "\n"], [:TkEND_OF_SCRIPT], [:TkBACKSLASH, TkUnknownChar, "\\"], [:TkAT, TkUnknownChar, "@"], [:TkDOLLAR, TkUnknownChar, "$"], ] # {reading => token_class} # {reading => [token_class, *opt]} TkReading2Token = {} TkToken2Reading = {} TkSymbol2Token = {} def self.def_token(token_n, super_token = Token, reading = nil, *opts) token_n = token_n.id2name if token_n.kind_of?(Symbol) if const_defined?(token_n) IRB.fail AlreadyDefinedToken, token_n end token_c = eval("class #{token_n} < #{super_token}; end; #{token_n}") if reading TkToken2Reading[token_c] = reading return if TkReading2Token[reading] if opts.empty? TkReading2Token[reading] = [token_c] else TkReading2Token[reading] = [token_c].concat(opts) end end TkSymbol2Token[token_n.intern] = token_c end for defs in TokenDefinitions def_token(*defs) end def_token :TkRD_COMMENT, TkCOMMENT NEWLINE_TOKEN = TkNL.new 0, 0, 0, "\n" class TkSYMBOL def to_sym @sym ||= text[1..-1].intern end end # :startdoc: end PK!b{{2.2.0/rdoc/options.rbnu[require 'optparse' require 'pathname' ## # RDoc::Options handles the parsing and storage of options # # == Saved Options # # You can save some options like the markup format in the # .rdoc_options file in your gem. The easiest way to do this is: # # rdoc --markup tomdoc --write-options # # Which will automatically create the file and fill it with the options you # specified. # # The following options will not be saved since they interfere with the user's # preferences or with the normal operation of RDoc: # # * +--coverage-report+ # * +--dry-run+ # * +--encoding+ # * +--force-update+ # * +--format+ # * +--pipe+ # * +--quiet+ # * +--template+ # * +--verbose+ # # == Custom Options # # Generators can hook into RDoc::Options to add generator-specific command # line options. # # When --format is encountered in ARGV, RDoc calls ::setup_options on # the generator class to add extra options to the option parser. Options for # custom generators must occur after --format. rdoc --help # will list options for all installed generators. # # Example: # # class RDoc::Generator::Spellcheck # RDoc::RDoc.add_generator self # # def self.setup_options rdoc_options # op = rdoc_options.option_parser # # op.on('--spell-dictionary DICTIONARY', # RDoc::Options::Path) do |dictionary| # rdoc_options.spell_dictionary = dictionary # end # end # end # # Of course, RDoc::Options does not respond to +spell_dictionary+ by default # so you will need to add it: # # class RDoc::Options # # ## # # The spell dictionary used by the spell-checking plugin. # # attr_accessor :spell_dictionary # # end # # == Option Validators # # OptionParser validators will validate and cast user input values. In # addition to the validators that ship with OptionParser (String, Integer, # Float, TrueClass, FalseClass, Array, Regexp, Date, Time, URI, etc.), # RDoc::Options adds Path, PathArray and Template. class RDoc::Options ## # The deprecated options. DEPRECATED = { '--accessor' => 'support discontinued', '--diagram' => 'support discontinued', '--help-output' => 'support discontinued', '--image-format' => 'was an option for --diagram', '--inline-source' => 'source code is now always inlined', '--merge' => 'ri now always merges class information', '--one-file' => 'support discontinued', '--op-name' => 'support discontinued', '--opname' => 'support discontinued', '--promiscuous' => 'files always only document their content', '--ri-system' => 'Ruby installers use other techniques', } ## # RDoc options ignored (or handled specially) by --write-options SPECIAL = %w[ coverage_report dry_run encoding files force_output force_update generator generator_name generator_options generators op_dir option_parser pipe rdoc_include root static_path stylesheet_url template template_dir update_output_dir verbosity write_options ] ## # Option validator for OptionParser that matches a directory that exists on # the filesystem. Directory = Object.new ## # Option validator for OptionParser that matches a file or directory that # exists on the filesystem. Path = Object.new ## # Option validator for OptionParser that matches a comma-separated list of # files or directories that exist on the filesystem. PathArray = Object.new ## # Option validator for OptionParser that matches a template directory for an # installed generator that lives in # "rdoc/generator/template/#{template_name}" Template = Object.new ## # Character-set for HTML output. #encoding is preferred over #charset attr_accessor :charset ## # If true, RDoc will not write any files. attr_accessor :dry_run ## # The output encoding. All input files will be transcoded to this encoding. # # The default encoding is UTF-8. This is set via --encoding. attr_accessor :encoding ## # Files matching this pattern will be excluded attr_accessor :exclude ## # The list of files to be processed attr_accessor :files ## # Create the output even if the output directory does not look # like an rdoc output directory attr_accessor :force_output ## # Scan newer sources than the flag file if true. attr_accessor :force_update ## # Formatter to mark up text with attr_accessor :formatter ## # Description of the output generator (set with the --format option) attr_accessor :generator ## # For #== attr_reader :generator_name # :nodoc: ## # Loaded generator options. Used to prevent --help from loading the same # options multiple times. attr_accessor :generator_options ## # Old rdoc behavior: hyperlink all words that match a method name, # even if not preceded by '#' or '::' attr_accessor :hyperlink_all ## # Include line numbers in the source code attr_accessor :line_numbers ## # The output locale. attr_accessor :locale ## # The directory where locale data live. attr_accessor :locale_dir ## # Name of the file, class or module to display in the initial index page (if # not specified the first file we encounter is used) attr_accessor :main_page ## # The default markup format. The default is 'rdoc'. 'markdown', 'tomdoc' # and 'rd' are also built-in. attr_accessor :markup ## # If true, only report on undocumented files attr_accessor :coverage_report ## # The name of the output directory attr_accessor :op_dir ## # The OptionParser for this instance attr_accessor :option_parser ## # Output heading decorations? attr_accessor :output_decoration ## # Directory where guides, FAQ, and other pages not associated with a class # live. You may leave this unset if these are at the root of your project. attr_accessor :page_dir ## # Is RDoc in pipe mode? attr_accessor :pipe ## # Array of directories to search for files to satisfy an :include: attr_accessor :rdoc_include ## # Root of the source documentation will be generated for. Set this when # building documentation outside the source directory. Defaults to the # current directory. attr_accessor :root ## # Include the '#' at the front of hyperlinked instance method names attr_accessor :show_hash ## # Directory to copy static files from attr_accessor :static_path ## # The number of columns in a tab attr_accessor :tab_width ## # Template to be used when generating output attr_accessor :template ## # Directory the template lives in attr_accessor :template_dir ## # Additional template stylesheets attr_accessor :template_stylesheets ## # Documentation title attr_accessor :title ## # Should RDoc update the timestamps in the output dir? attr_accessor :update_output_dir ## # Verbosity, zero means quiet attr_accessor :verbosity ## # URL of web cvs frontend attr_accessor :webcvs ## # Minimum visibility of a documented method. One of +:public+, +:protected+, # +:private+ or +:nodoc+. # # The +:nodoc+ visibility ignores all directives related to visibility. The # other visibilities may be overridden on a per-method basis with the :doc: # directive. attr_reader :visibility def initialize # :nodoc: init_ivars end def init_ivars # :nodoc: @dry_run = false @exclude = [] @files = nil @force_output = false @force_update = true @generator = nil @generator_name = nil @generator_options = [] @generators = RDoc::RDoc::GENERATORS @hyperlink_all = false @line_numbers = false @locale = nil @locale_name = nil @locale_dir = 'locale' @main_page = nil @markup = 'rdoc' @coverage_report = false @op_dir = nil @page_dir = nil @pipe = false @output_decoration = true @rdoc_include = [] @root = Pathname(Dir.pwd) @show_hash = false @static_path = [] @stylesheet_url = nil # TODO remove in RDoc 4 @tab_width = 8 @template = nil @template_dir = nil @template_stylesheets = [] @title = nil @update_output_dir = true @verbosity = 1 @visibility = :protected @webcvs = nil @write_options = false if Object.const_defined? :Encoding then @encoding = Encoding::UTF_8 @charset = @encoding.name else @encoding = nil @charset = 'UTF-8' end end def init_with map # :nodoc: init_ivars encoding = map['encoding'] @encoding = if Object.const_defined? :Encoding then encoding ? Encoding.find(encoding) : encoding end @charset = map['charset'] @exclude = map['exclude'] @generator_name = map['generator_name'] @hyperlink_all = map['hyperlink_all'] @line_numbers = map['line_numbers'] @locale_name = map['locale_name'] @locale_dir = map['locale_dir'] @main_page = map['main_page'] @markup = map['markup'] @op_dir = map['op_dir'] @show_hash = map['show_hash'] @tab_width = map['tab_width'] @template_dir = map['template_dir'] @title = map['title'] @visibility = map['visibility'] @webcvs = map['webcvs'] @rdoc_include = sanitize_path map['rdoc_include'] @static_path = sanitize_path map['static_path'] end def yaml_initialize tag, map # :nodoc: init_with map end def == other # :nodoc: self.class === other and @encoding == other.encoding and @generator_name == other.generator_name and @hyperlink_all == other.hyperlink_all and @line_numbers == other.line_numbers and @locale == other.locale and @locale_dir == other.locale_dir and @main_page == other.main_page and @markup == other.markup and @op_dir == other.op_dir and @rdoc_include == other.rdoc_include and @show_hash == other.show_hash and @static_path == other.static_path and @tab_width == other.tab_width and @template == other.template and @title == other.title and @visibility == other.visibility and @webcvs == other.webcvs end ## # Check that the files on the command line exist def check_files @files.delete_if do |file| if File.exist? file then if File.readable? file then false else warn "file '#{file}' not readable" true end else warn "file '#{file}' not found" true end end end ## # Ensure only one generator is loaded def check_generator if @generator then raise OptionParser::InvalidOption, "generator already set to #{@generator_name}" end end ## # Set the title, but only if not already set. Used to set the title # from a source file, so that a title set from the command line # will have the priority. def default_title=(string) @title ||= string end ## # For dumping YAML def encode_with coder # :nodoc: encoding = @encoding ? @encoding.name : nil coder.add 'encoding', encoding coder.add 'static_path', sanitize_path(@static_path) coder.add 'rdoc_include', sanitize_path(@rdoc_include) ivars = instance_variables.map { |ivar| ivar.to_s[1..-1] } ivars -= SPECIAL ivars.sort.each do |ivar| coder.add ivar, instance_variable_get("@#{ivar}") end end ## # Completes any unfinished option setup business such as filtering for # existent files, creating a regexp for #exclude and setting a default # #template. def finish @op_dir ||= 'doc' @rdoc_include << "." if @rdoc_include.empty? root = @root.to_s @rdoc_include << root unless @rdoc_include.include?(root) if @exclude.nil? or Regexp === @exclude then # done, #finish is being re-run elsif @exclude.empty? then @exclude = nil else @exclude = Regexp.new(@exclude.join("|")) end finish_page_dir check_files # If no template was specified, use the default template for the output # formatter unless @template then @template = @generator_name @template_dir = template_dir_for @template end if @locale_name @locale = RDoc::I18n::Locale[@locale_name] @locale.load(@locale_dir) else @locale = nil end self end ## # Fixes the page_dir to be relative to the root_dir and adds the page_dir to # the files list. def finish_page_dir return unless @page_dir @files << @page_dir.to_s page_dir = @page_dir.expand_path.relative_path_from @root @page_dir = page_dir end ## # Returns a properly-space list of generators and their descriptions. def generator_descriptions lengths = [] generators = RDoc::RDoc::GENERATORS.map do |name, generator| lengths << name.length description = generator::DESCRIPTION if generator.const_defined? :DESCRIPTION [name, description] end longest = lengths.max generators.sort.map do |name, description| if description then " %-*s - %s" % [longest, name, description] else " #{name}" end end.join "\n" end ## # Parses command line options. def parse argv ignore_invalid = true argv.insert(0, *ENV['RDOCOPT'].split) if ENV['RDOCOPT'] opts = OptionParser.new do |opt| @option_parser = opt opt.program_name = File.basename $0 opt.version = RDoc::VERSION opt.release = nil opt.summary_indent = ' ' * 4 opt.banner = <<-EOF Usage: #{opt.program_name} [options] [names...] Files are parsed, and the information they contain collected, before any output is produced. This allows cross references between all files to be resolved. If a name is a directory, it is traversed. If no names are specified, all Ruby files in the current directory (and subdirectories) are processed. How RDoc generates output depends on the output formatter being used, and on the options you give. Options can be specified via the RDOCOPT environment variable, which functions similar to the RUBYOPT environment variable for ruby. $ export RDOCOPT="--show-hash" will make rdoc show hashes in method links by default. Command-line options always will override those in RDOCOPT. Available formatters: #{generator_descriptions} RDoc understands the following file formats: EOF parsers = Hash.new { |h,parser| h[parser] = [] } RDoc::Parser.parsers.each do |regexp, parser| parsers[parser.name.sub('RDoc::Parser::', '')] << regexp.source end parsers.sort.each do |parser, regexp| opt.banner << " - #{parser}: #{regexp.join ', '}\n" end opt.banner << " - TomDoc: Only in ruby files\n" opt.banner << "\n The following options are deprecated:\n\n" name_length = DEPRECATED.keys.sort_by { |k| k.length }.last.length DEPRECATED.sort_by { |k,| k }.each do |name, reason| opt.banner << " %*1$2$s %3$s\n" % [-name_length, name, reason] end opt.accept Template do |template| template_dir = template_dir_for template unless template_dir then $stderr.puts "could not find template #{template}" nil else [template, template_dir] end end opt.accept Directory do |directory| directory = File.expand_path directory raise OptionParser::InvalidArgument unless File.directory? directory directory end opt.accept Path do |path| path = File.expand_path path raise OptionParser::InvalidArgument unless File.exist? path path end opt.accept PathArray do |paths,| paths = if paths then paths.split(',').map { |d| d unless d.empty? } end paths.map do |path| path = File.expand_path path raise OptionParser::InvalidArgument unless File.exist? path path end end opt.separator nil opt.separator "Parsing options:" opt.separator nil if Object.const_defined? :Encoding then opt.on("--encoding=ENCODING", "-e", Encoding.list.map { |e| e.name }, "Specifies the output encoding. All files", "read will be converted to this encoding.", "The default encoding is UTF-8.", "--encoding is preferred over --charset") do |value| @encoding = Encoding.find value @charset = @encoding.name # may not be valid value end opt.separator nil end opt.on("--locale=NAME", "Specifies the output locale.") do |value| @locale_name = value end opt.on("--locale-data-dir=DIR", "Specifies the directory where locale data live.") do |value| @locale_dir = value end opt.separator nil opt.on("--all", "-a", "Synonym for --visibility=private.") do |value| @visibility = :private end opt.separator nil opt.on("--exclude=PATTERN", "-x", Regexp, "Do not process files or directories", "matching PATTERN.") do |value| @exclude << value end opt.separator nil opt.on("--extension=NEW=OLD", "-E", "Treat files ending with .new as if they", "ended with .old. Using '-E cgi=rb' will", "cause xxx.cgi to be parsed as a Ruby file.") do |value| new, old = value.split(/=/, 2) unless new and old then raise OptionParser::InvalidArgument, "Invalid parameter to '-E'" end unless RDoc::Parser.alias_extension old, new then raise OptionParser::InvalidArgument, "Unknown extension .#{old} to -E" end end opt.separator nil opt.on("--[no-]force-update", "-U", "Forces rdoc to scan all sources even if", "newer than the flag file.") do |value| @force_update = value end opt.separator nil opt.on("--pipe", "-p", "Convert RDoc on stdin to HTML") do @pipe = true end opt.separator nil opt.on("--tab-width=WIDTH", "-w", Integer, "Set the width of tab characters.") do |value| raise OptionParser::InvalidArgument, "#{value} is an invalid tab width" if value <= 0 @tab_width = value end opt.separator nil opt.on("--visibility=VISIBILITY", "-V", RDoc::VISIBILITIES + [:nodoc], "Minimum visibility to document a method.", "One of 'public', 'protected' (the default),", "'private' or 'nodoc' (show everything)") do |value| @visibility = value end opt.separator nil markup_formats = RDoc::Text::MARKUP_FORMAT.keys.sort opt.on("--markup=MARKUP", markup_formats, "The markup format for the named files.", "The default is rdoc. Valid values are:", markup_formats.join(', ')) do |value| @markup = value end opt.separator nil opt.on("--root=ROOT", Directory, "Root of the source tree documentation", "will be generated for. Set this when", "building documentation outside the", "source directory. Default is the", "current directory.") do |root| @root = Pathname(root) end opt.separator nil opt.on("--page-dir=DIR", Directory, "Directory where guides, your FAQ or", "other pages not associated with a class", "live. Set this when you don't store", "such files at your project root.", "NOTE: Do not use the same file name in", "the page dir and the root of your project") do |page_dir| @page_dir = Pathname(page_dir) end opt.separator nil opt.separator "Common generator options:" opt.separator nil opt.on("--force-output", "-O", "Forces rdoc to write the output files,", "even if the output directory exists", "and does not seem to have been created", "by rdoc.") do |value| @force_output = value end opt.separator nil generator_text = @generators.keys.map { |name| " #{name}" }.sort opt.on("-f", "--fmt=FORMAT", "--format=FORMAT", @generators.keys, "Set the output formatter. One of:", *generator_text) do |value| check_generator @generator_name = value.downcase setup_generator end opt.separator nil opt.on("--include=DIRECTORIES", "-i", PathArray, "Set (or add to) the list of directories to", "be searched when satisfying :include:", "requests. Can be used more than once.") do |value| @rdoc_include.concat value.map { |dir| dir.strip } end opt.separator nil opt.on("--[no-]coverage-report=[LEVEL]", "--[no-]dcov", "-C", Integer, "Prints a report on undocumented items.", "Does not generate files.") do |value| value = 0 if value.nil? # Integer converts -C to nil @coverage_report = value @force_update = true if value end opt.separator nil opt.on("--output=DIR", "--op", "-o", "Set the output directory.") do |value| @op_dir = value end opt.separator nil opt.on("-d", "Deprecated --diagram option.", "Prevents firing debug mode", "with legacy invocation.") do |value| end opt.separator nil opt.separator 'HTML generator options:' opt.separator nil opt.on("--charset=CHARSET", "-c", "Specifies the output HTML character-set.", "Use --encoding instead of --charset if", "available.") do |value| @charset = value end opt.separator nil opt.on("--hyperlink-all", "-A", "Generate hyperlinks for all words that", "correspond to known methods, even if they", "do not start with '#' or '::' (legacy", "behavior).") do |value| @hyperlink_all = value end opt.separator nil opt.on("--main=NAME", "-m", "NAME will be the initial page displayed.") do |value| @main_page = value end opt.separator nil opt.on("--[no-]line-numbers", "-N", "Include line numbers in the source code.", "By default, only the number of the first", "line is displayed, in a leading comment.") do |value| @line_numbers = value end opt.separator nil opt.on("--show-hash", "-H", "A name of the form #name in a comment is a", "possible hyperlink to an instance method", "name. When displayed, the '#' is removed", "unless this option is specified.") do |value| @show_hash = value end opt.separator nil opt.on("--template=NAME", "-T", Template, "Set the template used when generating", "output. The default depends on the", "formatter used.") do |(template, template_dir)| @template = template @template_dir = template_dir end opt.separator nil opt.on("--template-stylesheets=FILES", PathArray, "Set (or add to) the list of files to", "include with the html template.") do |value| @template_stylesheets << value end opt.separator nil opt.on("--title=TITLE", "-t", "Set TITLE as the title for HTML output.") do |value| @title = value end opt.separator nil opt.on("--copy-files=PATH", Path, "Specify a file or directory to copy static", "files from.", "If a file is given it will be copied into", "the output dir. If a directory is given the", "entire directory will be copied.", "You can use this multiple times") do |value| @static_path << value end opt.separator nil opt.on("--webcvs=URL", "-W", "Specify a URL for linking to a web frontend", "to CVS. If the URL contains a '\%s', the", "name of the current file will be", "substituted; if the URL doesn't contain a", "'\%s', the filename will be appended to it.") do |value| @webcvs = value end opt.separator nil opt.separator "ri generator options:" opt.separator nil opt.on("--ri", "-r", "Generate output for use by `ri`. The files", "are stored in the '.rdoc' directory under", "your home directory unless overridden by a", "subsequent --op parameter, so no special", "privileges are needed.") do |value| check_generator @generator_name = "ri" @op_dir ||= RDoc::RI::Paths::HOMEDIR setup_generator end opt.separator nil opt.on("--ri-site", "-R", "Generate output for use by `ri`. The files", "are stored in a site-wide directory,", "making them accessible to others, so", "special privileges are needed.") do |value| check_generator @generator_name = "ri" @op_dir = RDoc::RI::Paths.site_dir setup_generator end opt.separator nil opt.separator "Generic options:" opt.separator nil opt.on("--write-options", "Write .rdoc_options to the current", "directory with the given options. Not all", "options will be used. See RDoc::Options", "for details.") do |value| @write_options = true end opt.separator nil opt.on("--[no-]dry-run", "Don't write any files") do |value| @dry_run = value end opt.separator nil opt.on("-D", "--[no-]debug", "Displays lots on internal stuff.") do |value| $DEBUG_RDOC = value end opt.separator nil opt.on("--[no-]ignore-invalid", "Ignore invalid options and continue", "(default true).") do |value| ignore_invalid = value end opt.separator nil opt.on("--quiet", "-q", "Don't show progress as we parse.") do |value| @verbosity = 0 end opt.separator nil opt.on("--verbose", "-V", "Display extra progress as RDoc parses") do |value| @verbosity = 2 end opt.separator nil opt.on("--version", "-v", "print the version") do puts opt.version exit end opt.separator nil opt.on("--help", "-h", "Display this help") do RDoc::RDoc::GENERATORS.each_key do |generator| setup_generator generator end puts opt.help exit end opt.separator nil end setup_generator 'darkfish' if argv.grep(/\A(-f|--fmt|--format|-r|-R|--ri|--ri-site)\b/).empty? deprecated = [] invalid = [] begin opts.parse! argv rescue OptionParser::ParseError => e if DEPRECATED[e.args.first] then deprecated << e.args.first elsif %w[--format --ri -r --ri-site -R].include? e.args.first then raise else invalid << e.args.join(' ') end retry end unless @generator then @generator = RDoc::Generator::Darkfish @generator_name = 'darkfish' end if @pipe and not argv.empty? then @pipe = false invalid << '-p (with files)' end unless quiet then deprecated.each do |opt| $stderr.puts 'option ' << opt << ' is deprecated: ' << DEPRECATED[opt] end end unless invalid.empty? then invalid = "invalid options: #{invalid.join ', '}" if ignore_invalid then unless quiet then $stderr.puts invalid $stderr.puts '(invalid options are ignored)' end else unless quiet then $stderr.puts opts end $stderr.puts invalid exit 1 end end @files = argv.dup finish if @write_options then write_options exit end self end ## # Don't display progress as we process the files def quiet @verbosity.zero? end ## # Set quietness to +bool+ def quiet= bool @verbosity = bool ? 0 : 1 end ## # Removes directories from +path+ that are outside the current directory def sanitize_path path require 'pathname' dot = Pathname.new('.').expand_path path.reject do |item| path = Pathname.new(item).expand_path relative = path.relative_path_from(dot).to_s relative.start_with? '..' end end ## # Set up an output generator for the named +generator_name+. # # If the found generator responds to :setup_options it will be called with # the options instance. This allows generators to add custom options or set # default options. def setup_generator generator_name = @generator_name @generator = @generators[generator_name] unless @generator then raise OptionParser::InvalidArgument, "Invalid output formatter #{generator_name}" end return if @generator_options.include? @generator @generator_name = generator_name @generator_options << @generator if @generator.respond_to? :setup_options then @option_parser ||= OptionParser.new @generator.setup_options self end end ## # Finds the template dir for +template+ def template_dir_for template template_path = File.join 'rdoc', 'generator', 'template', template $LOAD_PATH.map do |path| File.join File.expand_path(path), template_path end.find do |dir| File.directory? dir end end ## # This is compatibility code for syck def to_yaml opts = {} # :nodoc: return super if YAML.const_defined?(:ENGINE) and not YAML::ENGINE.syck? YAML.quick_emit self, opts do |out| out.map taguri, to_yaml_style do |map| encode_with map end end end # Sets the minimum visibility of a documented method. # # Accepts +:public+, +:protected+, +:private+, +:nodoc+, or +:all+. # # When +:all+ is passed, visibility is set to +:private+, similarly to # RDOCOPT="--all", see #visibility for more information. def visibility= visibility case visibility when :all @visibility = :private else @visibility = visibility end end ## # Displays a warning using Kernel#warn if we're being verbose def warn message super message if @verbosity > 1 end ## # Writes the YAML file .rdoc_options to the current directory containing the # parsed options. def write_options RDoc.load_yaml open '.rdoc_options', 'w' do |io| io.set_encoding Encoding::UTF_8 if Object.const_defined? :Encoding YAML.dump self, io end end end PK!i))2.2.0/rdoc/stats.rbnu[## # RDoc statistics collector which prints a summary and report of a project's # documentation totals. class RDoc::Stats include RDoc::Text ## # Output level for the coverage report attr_reader :coverage_level ## # Count of files parsed during parsing attr_reader :files_so_far ## # Total number of files found attr_reader :num_files ## # Creates a new Stats that will have +num_files+. +verbosity+ defaults to 1 # which will create an RDoc::Stats::Normal outputter. def initialize store, num_files, verbosity = 1 @num_files = num_files @store = store @coverage_level = 0 @doc_items = nil @files_so_far = 0 @fully_documented = false @num_params = 0 @percent_doc = nil @start = Time.now @undoc_params = 0 @display = case verbosity when 0 then Quiet.new num_files when 1 then Normal.new num_files else Verbose.new num_files end end ## # Records the parsing of an alias +as+. def add_alias as @display.print_alias as end ## # Records the parsing of an attribute +attribute+ def add_attribute attribute @display.print_attribute attribute end ## # Records the parsing of a class +klass+ def add_class klass @display.print_class klass end ## # Records the parsing of +constant+ def add_constant constant @display.print_constant constant end ## # Records the parsing of +file+ def add_file(file) @files_so_far += 1 @display.print_file @files_so_far, file end ## # Records the parsing of +method+ def add_method(method) @display.print_method method end ## # Records the parsing of a module +mod+ def add_module(mod) @display.print_module mod end ## # Call this to mark the beginning of parsing for display purposes def begin_adding @display.begin_adding end ## # Calculates documentation totals and percentages for classes, modules, # constants, attributes and methods. def calculate return if @doc_items ucm = @store.unique_classes_and_modules classes = @store.unique_classes.reject { |cm| cm.full_name == 'Object' } constants = [] ucm.each { |cm| constants.concat cm.constants } methods = [] ucm.each { |cm| methods.concat cm.method_list } attributes = [] ucm.each { |cm| attributes.concat cm.attributes } @num_attributes, @undoc_attributes = doc_stats attributes @num_classes, @undoc_classes = doc_stats classes @num_constants, @undoc_constants = doc_stats constants @num_methods, @undoc_methods = doc_stats methods @num_modules, @undoc_modules = doc_stats @store.unique_modules @num_items = @num_attributes + @num_classes + @num_constants + @num_methods + @num_modules + @num_params @undoc_items = @undoc_attributes + @undoc_classes + @undoc_constants + @undoc_methods + @undoc_modules + @undoc_params @doc_items = @num_items - @undoc_items end ## # Sets coverage report level. Accepted values are: # # false or nil:: No report # 0:: Classes, modules, constants, attributes, methods # 1:: Level 0 + method parameters def coverage_level= level level = -1 unless level @coverage_level = level end ## # Returns the length and number of undocumented items in +collection+. def doc_stats collection visible = collection.select { |item| item.display? } [visible.length, visible.count { |item| not item.documented? }] end ## # Call this to mark the end of parsing for display purposes def done_adding @display.done_adding end ## # The documentation status of this project. +true+ when 100%, +false+ when # less than 100% and +nil+ when unknown. # # Set by calling #calculate def fully_documented? @fully_documented end ## # A report that says you did a great job! def great_job report = RDoc::Markup::Document.new report << RDoc::Markup::Paragraph.new('100% documentation!') report << RDoc::Markup::Paragraph.new('Great Job!') report end ## # Calculates the percentage of items documented. def percent_doc return @percent_doc if @percent_doc @fully_documented = (@num_items - @doc_items) == 0 @percent_doc = @doc_items.to_f / @num_items * 100 if @num_items.nonzero? @percent_doc ||= 0 @percent_doc end ## # Returns a report on which items are not documented def report if @coverage_level > 0 then extend RDoc::Text end if @coverage_level.zero? then calculate return great_job if @num_items == @doc_items end ucm = @store.unique_classes_and_modules report = RDoc::Markup::Document.new report << RDoc::Markup::Paragraph.new('The following items are not documented:') report << RDoc::Markup::BlankLine.new ucm.sort.each do |cm| body = report_class_module(cm) { [ report_constants(cm), report_attributes(cm), report_methods(cm), ].compact } report << body if body end if @coverage_level > 0 then calculate return great_job if @num_items == @doc_items end report end ## # Returns a report on undocumented attributes in ClassModule +cm+ def report_attributes cm return if cm.attributes.empty? report = [] cm.each_attribute do |attr| next if attr.documented? line = attr.line ? ":#{attr.line}" : nil report << " #{attr.definition} :#{attr.name} # in file #{attr.file.full_name}#{line}\n" report << "\n" end report end ## # Returns a report on undocumented items in ClassModule +cm+ def report_class_module cm return if cm.fully_documented? and @coverage_level.zero? return unless cm.display? report = RDoc::Markup::Document.new if cm.in_files.empty? then report << RDoc::Markup::Paragraph.new("#{cm.definition} is referenced but empty.") report << RDoc::Markup::Paragraph.new("It probably came from another project. I'm sorry I'm holding it against you.") return report elsif cm.documented? then documented = true klass = RDoc::Markup::Verbatim.new("#{cm.definition} # is documented\n") else report << RDoc::Markup::Paragraph.new('In files:') list = RDoc::Markup::List.new :BULLET cm.in_files.each do |file| para = RDoc::Markup::Paragraph.new file.full_name list << RDoc::Markup::ListItem.new(nil, para) end report << list report << RDoc::Markup::BlankLine.new klass = RDoc::Markup::Verbatim.new("#{cm.definition}\n") end klass << "\n" body = yield.flatten # HACK remove #flatten if body.empty? then return if documented klass.parts.pop else klass.parts.concat body end klass << "end\n" report << klass report end ## # Returns a report on undocumented constants in ClassModule +cm+ def report_constants cm return if cm.constants.empty? report = [] cm.each_constant do |constant| # TODO constant aliases are listed in the summary but not reported # figure out what to do here next if constant.documented? || constant.is_alias_for line = constant.line ? ":#{constant.line}" : line report << " # in file #{constant.file.full_name}#{line}\n" report << " #{constant.name} = nil\n" report << "\n" end report end ## # Returns a report on undocumented methods in ClassModule +cm+ def report_methods cm return if cm.method_list.empty? report = [] cm.each_method do |method| next if method.documented? and @coverage_level.zero? if @coverage_level > 0 then params, undoc = undoc_params method @num_params += params unless undoc.empty? then @undoc_params += undoc.length undoc = undoc.map do |param| "+#{param}+" end param_report = " # #{undoc.join ', '} is not documented\n" end end next if method.documented? and not param_report line = method.line ? ":#{method.line}" : nil scope = method.singleton ? 'self.' : nil report << " # in file #{method.file.full_name}#{line}\n" report << param_report if param_report report << " def #{scope}#{method.name}#{method.params}; end\n" report << "\n" end report end ## # Returns a summary of the collected statistics. def summary calculate num_width = [@num_files, @num_items].max.to_s.length undoc_width = [ @undoc_attributes, @undoc_classes, @undoc_constants, @undoc_items, @undoc_methods, @undoc_modules, @undoc_params, ].max.to_s.length report = RDoc::Markup::Verbatim.new report << "Files: %*d\n" % [num_width, @num_files] report << "\n" report << "Classes: %*d (%*d undocumented)\n" % [ num_width, @num_classes, undoc_width, @undoc_classes] report << "Modules: %*d (%*d undocumented)\n" % [ num_width, @num_modules, undoc_width, @undoc_modules] report << "Constants: %*d (%*d undocumented)\n" % [ num_width, @num_constants, undoc_width, @undoc_constants] report << "Attributes: %*d (%*d undocumented)\n" % [ num_width, @num_attributes, undoc_width, @undoc_attributes] report << "Methods: %*d (%*d undocumented)\n" % [ num_width, @num_methods, undoc_width, @undoc_methods] report << "Parameters: %*d (%*d undocumented)\n" % [ num_width, @num_params, undoc_width, @undoc_params] if @coverage_level > 0 report << "\n" report << "Total: %*d (%*d undocumented)\n" % [ num_width, @num_items, undoc_width, @undoc_items] report << "%6.2f%% documented\n" % percent_doc report << "\n" report << "Elapsed: %0.1fs\n" % (Time.now - @start) RDoc::Markup::Document.new report end ## # Determines which parameters in +method+ were not documented. Returns a # total parameter count and an Array of undocumented methods. def undoc_params method @formatter ||= RDoc::Markup::ToTtOnly.new params = method.param_list params = params.map { |param| param.gsub(/^\*\*?/, '') } return 0, [] if params.empty? document = parse method.comment tts = document.accept @formatter undoc = params - tts [params.length, undoc] end autoload :Quiet, 'rdoc/stats/quiet' autoload :Normal, 'rdoc/stats/normal' autoload :Verbose, 'rdoc/stats/verbose' end PK!^̞2.2.0/rdoc/i18n.rbnu[## # This module provides i18n realated features. module RDoc::I18n autoload :Locale, 'rdoc/i18n/locale' autoload :Text, 'rdoc/i18n/text' end PK!82.2.0/rdoc/require.rbnu[## # A file loaded by \#require class RDoc::Require < RDoc::CodeObject ## # Name of the required file attr_accessor :name ## # Creates a new Require that loads +name+ with +comment+ def initialize(name, comment) super() @name = name.gsub(/'|"/, "") #' @top_level = nil self.comment = comment end def inspect # :nodoc: "#<%s:0x%x require '%s' in %s>" % [ self.class, object_id, @name, parent_file_name, ] end def to_s # :nodoc: "require #{name} in: #{parent}" end ## # The RDoc::TopLevel corresponding to this require, or +nil+ if not found. def top_level @top_level ||= begin tl = RDoc::TopLevel.all_files_hash[name + '.rb'] if tl.nil? and RDoc::TopLevel.all_files.first.full_name =~ %r(^lib/) then # second chance tl = RDoc::TopLevel.all_files_hash['lib/' + name + '.rb'] end tl end end end PK!l2 2.2.0/rdoc/mixin.rbnu[## # A Mixin adds features from a module into another context. RDoc::Include and # RDoc::Extend are both mixins. class RDoc::Mixin < RDoc::CodeObject ## # Name of included module attr_accessor :name ## # Creates a new Mixin for +name+ with +comment+ def initialize(name, comment) super() @name = name self.comment = comment @module = nil # cache for module if found end ## # Mixins are sorted by name def <=> other return unless self.class === other name <=> other.name end def == other # :nodoc: self.class === other and @name == other.name end alias eql? == # :nodoc: ## # Full name based on #module def full_name m = self.module RDoc::ClassModule === m ? m.full_name : @name end def hash # :nodoc: [@name, self.module].hash end def inspect # :nodoc: "#<%s:0x%x %s.%s %s>" % [ self.class, object_id, parent_name, self.class.name.downcase, @name, ] end ## # Attempts to locate the included module object. Returns the name if not # known. # # The scoping rules of Ruby to resolve the name of an included module are: # - first look into the children of the current context; # - if not found, look into the children of included modules, # in reverse inclusion order; # - if still not found, go up the hierarchy of names. # # This method has O(n!) behavior when the module calling # include is referencing nonexistent modules. Avoid calling #module until # after all the files are parsed. This behavior is due to ruby's constant # lookup behavior. # # As of the beginning of October, 2011, no gem includes nonexistent modules. def module return @module if @module # search the current context return @name unless parent full_name = parent.child_name(@name) @module = @store.modules_hash[full_name] return @module if @module return @name if @name =~ /^::/ # search the includes before this one, in reverse order searched = parent.includes.take_while { |i| i != self }.reverse searched.each do |i| inc = i.module next if String === inc full_name = inc.child_name(@name) @module = @store.modules_hash[full_name] return @module if @module end # go up the hierarchy of names up = parent.parent while up full_name = up.child_name(@name) @module = @store.modules_hash[full_name] return @module if @module up = up.parent end @name end ## # Sets the store for this class or module and its contained code objects. def store= store super @file = @store.add_file @file.full_name if @file end def to_s # :nodoc: "#{self.class.name.downcase} #@name in: #{parent}" end end PK!+ s s2.2.0/rdoc/context.rbnu[require 'cgi' ## # A Context is something that can hold modules, classes, methods, attributes, # aliases, requires, and includes. Classes, modules, and files are all # Contexts. class RDoc::Context < RDoc::CodeObject include Comparable ## # Types of methods TYPES = %w[class instance] ## # If a context has these titles it will be sorted in this order. TOMDOC_TITLES = [nil, 'Public', 'Internal', 'Deprecated'] # :nodoc: TOMDOC_TITLES_SORT = TOMDOC_TITLES.sort_by { |title| title.to_s } # :nodoc: ## # Class/module aliases attr_reader :aliases ## # All attr* methods attr_reader :attributes ## # Block params to be used in the next MethodAttr parsed under this context attr_accessor :block_params ## # Constants defined attr_reader :constants ## # Sets the current documentation section of documentation attr_writer :current_section ## # Files this context is found in attr_reader :in_files ## # Modules this context includes attr_reader :includes ## # Modules this context is extended with attr_reader :extends ## # Methods defined in this context attr_reader :method_list ## # Name of this class excluding namespace. See also full_name attr_reader :name ## # Files this context requires attr_reader :requires ## # Use this section for the next method, attribute or constant added. attr_accessor :temporary_section ## # Hash old_name => [aliases], for aliases # that haven't (yet) been resolved to a method/attribute. # (Not to be confused with the aliases of the context.) attr_accessor :unmatched_alias_lists ## # Aliases that could not be resolved. attr_reader :external_aliases ## # Current visibility of this context attr_accessor :visibility ## # Hash of registered methods. Attributes are also registered here, # twice if they are RW. attr_reader :methods_hash ## # Params to be used in the next MethodAttr parsed under this context attr_accessor :params ## # Hash of registered constants. attr_reader :constants_hash ## # Creates an unnamed empty context with public current visibility def initialize super @in_files = [] @name ||= "unknown" @parent = nil @visibility = :public @current_section = Section.new self, nil, nil @sections = { nil => @current_section } @temporary_section = nil @classes = {} @modules = {} initialize_methods_etc end ## # Sets the defaults for methods and so-forth def initialize_methods_etc @method_list = [] @attributes = [] @aliases = [] @requires = [] @includes = [] @extends = [] @constants = [] @external_aliases = [] # This Hash maps a method name to a list of unmatched aliases (aliases of # a method not yet encountered). @unmatched_alias_lists = {} @methods_hash = {} @constants_hash = {} @params = nil @store ||= nil end ## # Contexts are sorted by full_name def <=>(other) return nil unless RDoc::CodeObject === other full_name <=> other.full_name end ## # Adds an item of type +klass+ with the given +name+ and +comment+ to the # context. # # Currently only RDoc::Extend and RDoc::Include are supported. def add klass, name, comment if RDoc::Extend == klass then ext = RDoc::Extend.new name, comment add_extend ext elsif RDoc::Include == klass then incl = RDoc::Include.new name, comment add_include incl else raise NotImplementedError, "adding a #{klass} is not implemented" end end ## # Adds +an_alias+ that is automatically resolved def add_alias an_alias return an_alias unless @document_self method_attr = find_method(an_alias.old_name, an_alias.singleton) || find_attribute(an_alias.old_name, an_alias.singleton) if method_attr then method_attr.add_alias an_alias, self else add_to @external_aliases, an_alias unmatched_alias_list = @unmatched_alias_lists[an_alias.pretty_old_name] ||= [] unmatched_alias_list.push an_alias end an_alias end ## # Adds +attribute+ if not already there. If it is (as method(s) or attribute), # updates the comment if it was empty. # # The attribute is registered only if it defines a new method. # For instance, attr_reader :foo will not be registered # if method +foo+ exists, but attr_accessor :foo will be registered # if method +foo+ exists, but foo= does not. def add_attribute attribute return attribute unless @document_self # mainly to check for redefinition of an attribute as a method # TODO find a policy for 'attr_reader :foo' + 'def foo=()' register = false key = nil if attribute.rw.index 'R' then key = attribute.pretty_name known = @methods_hash[key] if known then known.comment = attribute.comment if known.comment.empty? elsif registered = @methods_hash[attribute.pretty_name << '='] and RDoc::Attr === registered then registered.rw = 'RW' else @methods_hash[key] = attribute register = true end end if attribute.rw.index 'W' then key = attribute.pretty_name << '=' known = @methods_hash[key] if known then known.comment = attribute.comment if known.comment.empty? elsif registered = @methods_hash[attribute.pretty_name] and RDoc::Attr === registered then registered.rw = 'RW' else @methods_hash[key] = attribute register = true end end if register then attribute.visibility = @visibility add_to @attributes, attribute resolve_aliases attribute end attribute end ## # Adds a class named +given_name+ with +superclass+. # # Both +given_name+ and +superclass+ may contain '::', and are # interpreted relative to the +self+ context. This allows handling correctly # examples like these: # class RDoc::Gauntlet < Gauntlet # module Mod # class Object # implies < ::Object # class SubObject < Object # this is _not_ ::Object # # Given class Container::Item RDoc assumes +Container+ is a module # unless it later sees class Container. +add_class+ automatically # upgrades +given_name+ to a class in this case. def add_class class_type, given_name, superclass = '::Object' # superclass +nil+ is passed by the C parser in the following cases: # - registering Object in 1.8 (correct) # - registering BasicObject in 1.9 (correct) # - registering RubyVM in 1.9 in iseq.c (incorrect: < Object in vm.c) # # If we later find a superclass for a registered class with a nil # superclass, we must honor it. # find the name & enclosing context if given_name =~ /^:+(\w+)$/ then full_name = $1 enclosing = top_level name = full_name.split(/:+/).last else full_name = child_name given_name if full_name =~ /^(.+)::(\w+)$/ then name = $2 ename = $1 enclosing = @store.classes_hash[ename] || @store.modules_hash[ename] # HACK: crashes in actionpack/lib/action_view/helpers/form_helper.rb (metaprogramming) unless enclosing then # try the given name at top level (will work for the above example) enclosing = @store.classes_hash[given_name] || @store.modules_hash[given_name] return enclosing if enclosing # not found: create the parent(s) names = ename.split('::') enclosing = self names.each do |n| enclosing = enclosing.classes_hash[n] || enclosing.modules_hash[n] || enclosing.add_module(RDoc::NormalModule, n) end end else name = full_name enclosing = self end end # fix up superclass if full_name == 'BasicObject' then superclass = nil elsif full_name == 'Object' then superclass = defined?(::BasicObject) ? '::BasicObject' : nil end # find the superclass full name if superclass then if superclass =~ /^:+/ then superclass = $' #' else if superclass =~ /^(\w+):+(.+)$/ then suffix = $2 mod = find_module_named($1) superclass = mod.full_name + '::' + suffix if mod else mod = find_module_named(superclass) superclass = mod.full_name if mod end end # did we believe it was a module? mod = @store.modules_hash.delete superclass upgrade_to_class mod, RDoc::NormalClass, mod.parent if mod # e.g., Object < Object superclass = nil if superclass == full_name end klass = @store.classes_hash[full_name] if klass then # if TopLevel, it may not be registered in the classes: enclosing.classes_hash[name] = klass # update the superclass if needed if superclass then existing = klass.superclass existing = existing.full_name unless existing.is_a?(String) if existing if existing.nil? || (existing == 'Object' && superclass != 'Object') then klass.superclass = superclass end end else # this is a new class mod = @store.modules_hash.delete full_name if mod then klass = upgrade_to_class mod, RDoc::NormalClass, enclosing klass.superclass = superclass unless superclass.nil? else klass = class_type.new name, superclass enclosing.add_class_or_module(klass, enclosing.classes_hash, @store.classes_hash) end end klass.parent = self klass end ## # Adds the class or module +mod+ to the modules or # classes Hash +self_hash+, and to +all_hash+ (either # TopLevel::modules_hash or TopLevel::classes_hash), # unless #done_documenting is +true+. Sets the #parent of +mod+ # to +self+, and its #section to #current_section. Returns +mod+. def add_class_or_module mod, self_hash, all_hash mod.section = current_section # TODO declaring context? something is # wrong here... mod.parent = self mod.store = @store unless @done_documenting then self_hash[mod.name] = mod # this must be done AFTER adding mod to its parent, so that the full # name is correct: all_hash[mod.full_name] = mod end mod end ## # Adds +constant+ if not already there. If it is, updates the comment, # value and/or is_alias_for of the known constant if they were empty/nil. def add_constant constant return constant unless @document_self # HACK: avoid duplicate 'PI' & 'E' in math.c (1.8.7 source code) # (this is a #ifdef: should be handled by the C parser) known = @constants_hash[constant.name] if known then known.comment = constant.comment if known.comment.empty? known.value = constant.value if known.value.nil? or known.value.strip.empty? known.is_alias_for ||= constant.is_alias_for else @constants_hash[constant.name] = constant add_to @constants, constant end constant end ## # Adds included module +include+ which should be an RDoc::Include def add_include include add_to @includes, include include end ## # Adds extension module +ext+ which should be an RDoc::Extend def add_extend ext add_to @extends, ext ext end ## # Adds +method+ if not already there. If it is (as method or attribute), # updates the comment if it was empty. def add_method method return method unless @document_self # HACK: avoid duplicate 'new' in io.c & struct.c (1.8.7 source code) key = method.pretty_name known = @methods_hash[key] if known then if @store then # otherwise we are loading known.comment = method.comment if known.comment.empty? previously = ", previously in #{known.file}" unless method.file == known.file @store.rdoc.options.warn \ "Duplicate method #{known.full_name} in #{method.file}#{previously}" end else @methods_hash[key] = method method.visibility = @visibility add_to @method_list, method resolve_aliases method end method end ## # Adds a module named +name+. If RDoc already knows +name+ is a class then # that class is returned instead. See also #add_class. def add_module(class_type, name) mod = @classes[name] || @modules[name] return mod if mod full_name = child_name name mod = @store.modules_hash[full_name] || class_type.new(name) add_class_or_module mod, @modules, @store.modules_hash end ## # Adds an alias from +from+ (a class or module) to +name+ which was defined # in +file+. def add_module_alias from, name, file return from if @done_documenting to_name = child_name name # if we already know this name, don't register an alias: # see the metaprogramming in lib/active_support/basic_object.rb, # where we already know BasicObject is a class when we find # BasicObject = BlankSlate return from if @store.find_class_or_module to_name to = from.dup to.name = name to.full_name = nil if to.module? then @store.modules_hash[to_name] = to @modules[name] = to else @store.classes_hash[to_name] = to @classes[name] = to end # Registers a constant for this alias. The constant value and comment # will be updated later, when the Ruby parser adds the constant const = RDoc::Constant.new name, nil, to.comment const.record_location file const.is_alias_for = from add_constant const to end ## # Adds +require+ to this context's top level def add_require(require) return require unless @document_self if RDoc::TopLevel === self then add_to @requires, require else parent.add_require require end end ## # Returns a section with +title+, creating it if it doesn't already exist. # +comment+ will be appended to the section's comment. # # A section with a +title+ of +nil+ will return the default section. # # See also RDoc::Context::Section def add_section title, comment = nil if section = @sections[title] then section.add_comment comment if comment else section = Section.new self, title, comment @sections[title] = section end section end ## # Adds +thing+ to the collection +array+ def add_to array, thing array << thing if @document_self thing.parent = self thing.store = @store if @store thing.section = current_section end ## # Is there any content? # # This means any of: comment, aliases, methods, attributes, external # aliases, require, constant. # # Includes and extends are also checked unless includes == false. def any_content(includes = true) @any_content ||= !( @comment.empty? && @method_list.empty? && @attributes.empty? && @aliases.empty? && @external_aliases.empty? && @requires.empty? && @constants.empty? ) @any_content || (includes && !(@includes + @extends).empty? ) end ## # Creates the full name for a child with +name+ def child_name name if name =~ /^:+/ $' #' elsif RDoc::TopLevel === self then name else "#{self.full_name}::#{name}" end end ## # Class attributes def class_attributes @class_attributes ||= attributes.select { |a| a.singleton } end ## # Class methods def class_method_list @class_method_list ||= method_list.select { |a| a.singleton } end ## # Array of classes in this context def classes @classes.values end ## # All classes and modules in this namespace def classes_and_modules classes + modules end ## # Hash of classes keyed by class name def classes_hash @classes end ## # The current documentation section that new items will be added to. If # temporary_section is available it will be used. def current_section if section = @temporary_section then @temporary_section = nil else section = @current_section end section end ## # Is part of this thing was defined in +file+? def defined_in?(file) @in_files.include?(file) end def display(method_attr) # :nodoc: if method_attr.is_a? RDoc::Attr "#{method_attr.definition} #{method_attr.pretty_name}" else "method #{method_attr.pretty_name}" end end ## # Iterator for ancestors for duck-typing. Does nothing. See # RDoc::ClassModule#each_ancestor. # # This method exists to make it easy to work with Context subclasses that # aren't part of RDoc. def each_ancestor # :nodoc: end ## # Iterator for attributes def each_attribute # :yields: attribute @attributes.each { |a| yield a } end ## # Iterator for classes and modules def each_classmodule(&block) # :yields: module classes_and_modules.sort.each(&block) end ## # Iterator for constants def each_constant # :yields: constant @constants.each {|c| yield c} end ## # Iterator for included modules def each_include # :yields: include @includes.each do |i| yield i end end ## # Iterator for extension modules def each_extend # :yields: extend @extends.each do |e| yield e end end ## # Iterator for methods def each_method # :yields: method return enum_for __method__ unless block_given? @method_list.sort.each { |m| yield m } end ## # Iterator for each section's contents sorted by title. The +section+, the # section's +constants+ and the sections +attributes+ are yielded. The # +constants+ and +attributes+ collections are sorted. # # To retrieve methods in a section use #methods_by_type with the optional # +section+ parameter. # # NOTE: Do not edit collections yielded by this method def each_section # :yields: section, constants, attributes return enum_for __method__ unless block_given? constants = @constants.group_by do |constant| constant.section end attributes = @attributes.group_by do |attribute| attribute.section end constants.default = [] attributes.default = [] sort_sections.each do |section| yield section, constants[section].sort, attributes[section].sort end end ## # Finds an attribute +name+ with singleton value +singleton+. def find_attribute(name, singleton) name = $1 if name =~ /^(.*)=$/ @attributes.find { |a| a.name == name && a.singleton == singleton } end ## # Finds an attribute with +name+ in this context def find_attribute_named(name) case name when /\A#/ then find_attribute name[1..-1], false when /\A::/ then find_attribute name[2..-1], true else @attributes.find { |a| a.name == name } end end ## # Finds a class method with +name+ in this context def find_class_method_named(name) @method_list.find { |meth| meth.singleton && meth.name == name } end ## # Finds a constant with +name+ in this context def find_constant_named(name) @constants.find {|m| m.name == name} end ## # Find a module at a higher scope def find_enclosing_module_named(name) parent && parent.find_module_named(name) end ## # Finds an external alias +name+ with singleton value +singleton+. def find_external_alias(name, singleton) @external_aliases.find { |m| m.name == name && m.singleton == singleton } end ## # Finds an external alias with +name+ in this context def find_external_alias_named(name) case name when /\A#/ then find_external_alias name[1..-1], false when /\A::/ then find_external_alias name[2..-1], true else @external_aliases.find { |a| a.name == name } end end ## # Finds a file with +name+ in this context def find_file_named name @store.find_file_named name end ## # Finds an instance method with +name+ in this context def find_instance_method_named(name) @method_list.find { |meth| !meth.singleton && meth.name == name } end ## # Finds a method, constant, attribute, external alias, module or file # named +symbol+ in this context. def find_local_symbol(symbol) find_method_named(symbol) or find_constant_named(symbol) or find_attribute_named(symbol) or find_external_alias_named(symbol) or find_module_named(symbol) or find_file_named(symbol) end ## # Finds a method named +name+ with singleton value +singleton+. def find_method(name, singleton) @method_list.find { |m| m.name == name && m.singleton == singleton } end ## # Finds a instance or module method with +name+ in this context def find_method_named(name) case name when /\A#/ then find_method name[1..-1], false when /\A::/ then find_method name[2..-1], true else @method_list.find { |meth| meth.name == name } end end ## # Find a module with +name+ using ruby's scoping rules def find_module_named(name) res = @modules[name] || @classes[name] return res if res return self if self.name == name find_enclosing_module_named name end ## # Look up +symbol+, first as a module, then as a local symbol. def find_symbol(symbol) find_symbol_module(symbol) || find_local_symbol(symbol) end ## # Look up a module named +symbol+. def find_symbol_module(symbol) result = nil # look for a class or module 'symbol' case symbol when /^::/ then result = @store.find_class_or_module symbol when /^(\w+):+(.+)$/ suffix = $2 top = $1 searched = self while searched do mod = searched.find_module_named(top) break unless mod result = @store.find_class_or_module "#{mod.full_name}::#{suffix}" break if result || searched.is_a?(RDoc::TopLevel) searched = searched.parent end else searched = self while searched do result = searched.find_module_named(symbol) break if result || searched.is_a?(RDoc::TopLevel) searched = searched.parent end end result end ## # The full name for this context. This method is overridden by subclasses. def full_name '(unknown)' end ## # Does this context and its methods and constants all have documentation? # # (Yes, fully documented doesn't mean everything.) def fully_documented? documented? and attributes.all? { |a| a.documented? } and method_list.all? { |m| m.documented? } and constants.all? { |c| c.documented? } end ## # URL for this with a +prefix+ def http_url(prefix) path = name_for_path path = path.gsub(/<<\s*(\w*)/, 'from-\1') if path =~ /<'class' or # 'instance') and visibility (+:public+, +:protected+, +:private+). # # If +section+ is provided only methods in that RDoc::Context::Section will # be returned. def methods_by_type section = nil methods = {} TYPES.each do |type| visibilities = {} RDoc::VISIBILITIES.each do |vis| visibilities[vis] = [] end methods[type] = visibilities end each_method do |method| next if section and not method.section == section methods[method.type][method.visibility] << method end methods end ## # Yields AnyMethod and Attr entries matching the list of names in +methods+. def methods_matching(methods, singleton = false, &block) (@method_list + @attributes).each do |m| yield m if methods.include?(m.name) and m.singleton == singleton end each_ancestor do |parent| parent.methods_matching(methods, singleton, &block) end end ## # Array of modules in this context def modules @modules.values end ## # Hash of modules keyed by module name def modules_hash @modules end ## # Name to use to generate the url. # #full_name by default. def name_for_path full_name end ## # Changes the visibility for new methods to +visibility+ def ongoing_visibility=(visibility) @visibility = visibility end ## # Record +top_level+ as a file +self+ is in. def record_location(top_level) @in_files << top_level unless @in_files.include?(top_level) end ## # Should we remove this context from the documentation? # # The answer is yes if: # * #received_nodoc is +true+ # * #any_content is +false+ (not counting includes) # * All #includes are modules (not a string), and their module has # #remove_from_documentation? == true # * All classes and modules have #remove_from_documentation? == true def remove_from_documentation? @remove_from_documentation ||= @received_nodoc && !any_content(false) && @includes.all? { |i| !i.module.is_a?(String) && i.module.remove_from_documentation? } && classes_and_modules.all? { |cm| cm.remove_from_documentation? } end ## # Removes methods and attributes with a visibility less than +min_visibility+. #-- # TODO mark the visibility of attributes in the template (if not public?) def remove_invisible min_visibility return if [:private, :nodoc].include? min_visibility remove_invisible_in @method_list, min_visibility remove_invisible_in @attributes, min_visibility end ## # Only called when min_visibility == :public or :private def remove_invisible_in array, min_visibility # :nodoc: if min_visibility == :public then array.reject! { |e| e.visibility != :public and not e.force_documentation } else array.reject! { |e| e.visibility == :private and not e.force_documentation } end end ## # Tries to resolve unmatched aliases when a method or attribute has just # been added. def resolve_aliases added # resolve any pending unmatched aliases key = added.pretty_name unmatched_alias_list = @unmatched_alias_lists[key] return unless unmatched_alias_list unmatched_alias_list.each do |unmatched_alias| added.add_alias unmatched_alias, self @external_aliases.delete unmatched_alias end @unmatched_alias_lists.delete key end ## # Returns RDoc::Context::Section objects referenced in this context for use # in a table of contents. def section_contents used_sections = {} each_method do |method| next unless method.display? used_sections[method.section] = true end # order found sections sections = sort_sections.select do |section| used_sections[section] end # only the default section is used return [] if sections.length == 1 and not sections.first.title sections end ## # Sections in this context def sections @sections.values end def sections_hash # :nodoc: @sections end ## # Sets the current section to a section with +title+. See also #add_section def set_current_section title, comment @current_section = add_section title, comment end ## # Given an array +methods+ of method names, set the visibility of each to # +visibility+ def set_visibility_for(methods, visibility, singleton = false) methods_matching methods, singleton do |m| m.visibility = visibility end end ## # Sorts sections alphabetically (default) or in TomDoc fashion (none, # Public, Internal, Deprecated) def sort_sections titles = @sections.map { |title, _| title } if titles.length > 1 and TOMDOC_TITLES_SORT == (titles | TOMDOC_TITLES).sort_by { |title| title.to_s } then @sections.values_at(*TOMDOC_TITLES).compact else @sections.sort_by { |title, _| title.to_s }.map { |_, section| section } end end def to_s # :nodoc: "#{self.class.name} #{self.full_name}" end ## # Return the TopLevel that owns us #-- # FIXME we can be 'owned' by several TopLevel (see #record_location & # #in_files) def top_level return @top_level if defined? @top_level @top_level = self @top_level = @top_level.parent until RDoc::TopLevel === @top_level @top_level end ## # Upgrades NormalModule +mod+ in +enclosing+ to a +class_type+ def upgrade_to_class mod, class_type, enclosing enclosing.modules_hash.delete mod.name klass = RDoc::ClassModule.from_module class_type, mod klass.store = @store # if it was there, then we keep it even if done_documenting @store.classes_hash[mod.full_name] = klass enclosing.classes_hash[mod.name] = klass klass end autoload :Section, 'rdoc/context/section' end PK!-<-2.2.0/rdoc/generator/pot/message_extractor.rbnu[## # Extracts message from RDoc::Store class RDoc::Generator::POT::MessageExtractor ## # Creates a message extractor for +store+. def initialize store @store = store @po = RDoc::Generator::POT::PO.new end ## # Extracts messages from +store+, stores them into # RDoc::Generator::POT::PO and returns it. def extract @store.all_classes_and_modules.each do |klass| extract_from_klass(klass) end @po end private def extract_from_klass klass extract_text(klass.comment_location, klass.full_name) klass.each_section do |section, constants, attributes| extract_text(section.title ,"#{klass.full_name}: section title") section.comments.each do |comment| extract_text(comment, "#{klass.full_name}: #{section.title}") end end klass.each_constant do |constant| extract_text(constant.comment, constant.full_name) end klass.each_attribute do |attribute| extract_text(attribute.comment, attribute.full_name) end klass.each_method do |method| extract_text(method.comment, method.full_name) end end def extract_text text, comment, location = nil return if text.nil? options = { :extracted_comment => comment, :references => [location].compact, } i18n_text = RDoc::I18n::Text.new(text) i18n_text.extract_messages do |part| @po.add(entry(part[:paragraph], options)) end end def entry msgid, options RDoc::Generator::POT::POEntry.new(msgid, options) end end PK! $2.2.0/rdoc/generator/pot/po_entry.rbnu[## # A PO entry in PO class RDoc::Generator::POT::POEntry # The msgid content attr_reader :msgid # The msgstr content attr_reader :msgstr # The comment content created by translator (PO editor) attr_reader :translator_comment # The comment content extracted from source file attr_reader :extracted_comment # The locations where the PO entry is extracted attr_reader :references # The flags of the PO entry attr_reader :flags ## # Creates a PO entry for +msgid+. Other valus can be specified by # +options+. def initialize msgid, options = {} @msgid = msgid @msgstr = options[:msgstr] || "" @translator_comment = options[:translator_comment] @extracted_comment = options[:extracted_comment] @references = options[:references] || [] @flags = options[:flags] || [] end ## # Returns the PO entry in PO format. def to_s entry = '' entry << format_translator_comment entry << format_extracted_comment entry << format_references entry << format_flags entry << <<-ENTRY msgid #{format_message(@msgid)} msgstr #{format_message(@msgstr)} ENTRY end ## # Merges the PO entry with +other_entry+. def merge other_entry options = { :extracted_comment => merge_string(@extracted_comment, other_entry.extracted_comment), :translator_comment => merge_string(@translator_comment, other_entry.translator_comment), :references => merge_array(@references, other_entry.references), :flags => merge_array(@flags, other_entry.flags), } self.class.new(@msgid, options) end private def format_comment mark, comment return '' unless comment return '' if comment.empty? formatted_comment = '' comment.each_line do |line| formatted_comment << "#{mark} #{line}" end formatted_comment << "\n" unless formatted_comment.end_with?("\n") formatted_comment end def format_translator_comment format_comment('#', @translator_comment) end def format_extracted_comment format_comment('#.', @extracted_comment) end def format_references return '' if @references.empty? formatted_references = '' @references.sort.each do |file, line| formatted_references << "\#: #{file}:#{line}\n" end formatted_references end def format_flags return '' if @flags.empty? formatted_flags = flags.join(",") "\#, #{formatted_flags}\n" end def format_message message return "\"#{escape(message)}\"" unless message.include?("\n") formatted_message = '""' message.each_line do |line| formatted_message << "\n" formatted_message << "\"#{escape(line)}\"" end formatted_message end def escape string string.gsub(/["\\\t\n]/) do |special_character| case special_character when "\t" "\\t" when "\n" "\\n" else "\\#{special_character}" end end end def merge_string string1, string2 [string1, string2].compact.join("\n") end def merge_array array1, array2 (array1 + array2).uniq end end PK!Vt}}2.2.0/rdoc/generator/pot/po.rbnu[## # Generates a PO format text class RDoc::Generator::POT::PO ## # Creates an object that represents PO format. def initialize @entries = {} add_header end ## # Adds a PO entry to the PO. def add entry existing_entry = @entries[entry.msgid] if existing_entry entry = existing_entry.merge(entry) end @entries[entry.msgid] = entry end ## # Returns PO format text for the PO. def to_s po = '' sort_entries.each do |entry| po << "\n" unless po.empty? po << entry.to_s end po end private def add_header add(header_entry) end def header_entry comment = <<-COMMENT SOME DESCRIPTIVE TITLE. Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER This file is distributed under the same license as the PACKAGE package. FIRST AUTHOR , YEAR. COMMENT content = <<-CONTENT Project-Id-Version: PACKAGE VERSEION Report-Msgid-Bugs-To: PO-Revision-Date: YEAR-MO_DA HO:MI+ZONE Last-Translator: FULL NAME Language-Team: LANGUAGE Language: MIME-Version: 1.0 Content-Type: text/plain; charset=CHARSET Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=INTEGER; plural=EXPRESSION; CONTENT options = { :msgstr => content, :translator_comment => comment, :flags => ['fuzzy'], } RDoc::Generator::POT::POEntry.new('', options) end def sort_entries headers, messages = @entries.values.partition do |entry| entry.msgid.empty? end # TODO: sort by location sorted_messages = messages.sort_by do |entry| entry.msgid end headers + sorted_messages end end PK!_H/ / 2.2.0/rdoc/generator/pot.rbnu[## # Generates a POT file. # # Here is a translator work flow with the generator. # # == Create .pot # # You create .pot file by pot formatter: # # % rdoc --format pot # # It generates doc/rdoc.pot. # # == Create .po # # You create .po file from doc/rdoc.pot. This operation is needed only # the first time. This work flow assumes that you are a translator # for Japanese. # # You create locale/ja/rdoc.po from doc/rdoc.pot. You can use msginit # provided by GNU gettext or rmsginit provided by gettext gem. This # work flow uses gettext gem because it is more portable than GNU # gettext for Rubyists. Gettext gem is implemented by pure Ruby. # # % gem install gettext # % mkdir -p locale/ja # % rmsginit --input doc/rdoc.pot --output locale/ja/rdoc.po --locale ja # # Translate messages in .po # # You translate messages in .po by a PO file editor. po-mode.el exists # for Emacs users. There are some GUI tools such as GTranslator. # There are some Web services such as POEditor and Tansifex. You can # edit by your favorite text editor because .po is a text file. # Generate localized documentation # # You can generate localized documentation with locale/ja/rdoc.po: # # % rdoc --locale ja # # You can find documentation in Japanese in doc/. Yay! # # == Update translation # # You need to update translation when your application is added or # modified messages. # # You can update .po by the following command lines: # # % rdoc --format pot # % rmsgmerge --update locale/ja/rdoc.po doc/rdoc.pot # # You edit locale/ja/rdoc.po to translate new messages. class RDoc::Generator::POT RDoc::RDoc.add_generator self ## # Description of this generator DESCRIPTION = 'creates .pot file' ## # Set up a new .pot generator def initialize store, options #:not-new: @options = options @store = store end ## # Writes .pot to disk. def generate po = extract_messages pot_path = 'rdoc.pot' File.open(pot_path, "w") do |pot| pot.print(po.to_s) end end def class_dir nil end private def extract_messages extractor = MessageExtractor.new(@store) extractor.extract end autoload :MessageExtractor, 'rdoc/generator/pot/message_extractor' autoload :PO, 'rdoc/generator/pot/po' autoload :POEntry, 'rdoc/generator/pot/po_entry' end PK! .COO92.2.0/rdoc/generator/template/json_index/js/navigation.jsnu[/* * Navigation allows movement using the arrow keys through the search results. * * When using this library you will need to set scrollIntoView to the * appropriate function for your layout. Use scrollInWindow if the container * is not scrollable and scrollInElement if the container is a separate * scrolling region. */ Navigation = new function() { this.initNavigation = function() { var _this = this; $(document).keydown(function(e) { _this.onkeydown(e); }).keyup(function(e) { _this.onkeyup(e); }); this.navigationActive = true; } this.setNavigationActive = function(state) { this.navigationActive = state; this.clearMoveTimeout(); } this.onkeyup = function(e) { if (!this.navigationActive) return; switch(e.keyCode) { case 37: //Event.KEY_LEFT: case 38: //Event.KEY_UP: case 39: //Event.KEY_RIGHT: case 40: //Event.KEY_DOWN: this.clearMoveTimeout(); break; } } this.onkeydown = function(e) { if (!this.navigationActive) return; switch(e.keyCode) { case 37: //Event.KEY_LEFT: if (this.moveLeft()) e.preventDefault(); break; case 38: //Event.KEY_UP: if (e.keyCode == 38 || e.ctrlKey) { if (this.moveUp()) e.preventDefault(); this.startMoveTimeout(false); } break; case 39: //Event.KEY_RIGHT: if (this.moveRight()) e.preventDefault(); break; case 40: //Event.KEY_DOWN: if (e.keyCode == 40 || e.ctrlKey) { if (this.moveDown()) e.preventDefault(); this.startMoveTimeout(true); } break; case 13: //Event.KEY_RETURN: if (this.$current) e.preventDefault(); this.select(this.$current); break; } if (e.ctrlKey && e.shiftKey) this.select(this.$current); } this.clearMoveTimeout = function() { clearTimeout(this.moveTimeout); this.moveTimeout = null; } this.startMoveTimeout = function(isDown) { if (!$.browser.mozilla && !$.browser.opera) return; if (this.moveTimeout) this.clearMoveTimeout(); var _this = this; var go = function() { if (!_this.moveTimeout) return; _this[isDown ? 'moveDown' : 'moveUp'](); _this.moveTimout = setTimeout(go, 100); } this.moveTimeout = setTimeout(go, 200); } this.moveRight = function() { } this.moveLeft = function() { } this.move = function(isDown) { } this.moveUp = function() { return this.move(false); } this.moveDown = function() { return this.move(true); } /* * Scrolls to the given element in the scrollable element view. */ this.scrollInElement = function(element, view) { var offset, viewHeight, viewScroll, height; offset = element.offsetTop; height = element.offsetHeight; viewHeight = view.offsetHeight; viewScroll = view.scrollTop; if (offset - viewScroll + height > viewHeight) { view.scrollTop = offset - viewHeight + height; } if (offset < viewScroll) { view.scrollTop = offset; } } /* * Scrolls to the given element in the window. The second argument is * ignored */ this.scrollInWindow = function(element, ignored) { var offset, viewHeight, viewScroll, height; offset = element.offsetTop; height = element.offsetHeight; viewHeight = window.innerHeight; viewScroll = window.scrollY; if (offset - viewScroll + height > viewHeight) { window.scrollTo(window.scrollX, offset - viewHeight + height); } if (offset < viewScroll) { window.scrollTo(window.scrollX, offset); } } } PK!q72.2.0/rdoc/generator/template/json_index/js/searcher.jsnu[Searcher = function(data) { this.data = data; this.handlers = []; } Searcher.prototype = new function() { // search is performed in chunks of 1000 for non-blocking user input var CHUNK_SIZE = 1000; // do not try to find more than 100 results var MAX_RESULTS = 100; var huid = 1; var suid = 1; var runs = 0; this.find = function(query) { var queries = splitQuery(query); var regexps = buildRegexps(queries); var highlighters = buildHilighters(queries); var state = { from: 0, pass: 0, limit: MAX_RESULTS, n: suid++}; var _this = this; this.currentSuid = state.n; if (!query) return; var run = function() { // stop current search thread if new search started if (state.n != _this.currentSuid) return; var results = performSearch(_this.data, regexps, queries, highlighters, state); var hasMore = (state.limit > 0 && state.pass < 4); triggerResults.call(_this, results, !hasMore); if (hasMore) { setTimeout(run, 2); } runs++; }; runs = 0; // start search thread run(); } /* ----- Events ------ */ this.ready = function(fn) { fn.huid = huid; this.handlers.push(fn); } /* ----- Utilities ------ */ function splitQuery(query) { return jQuery.grep(query.split(/(\s+|::?|\(\)?)/), function(string) { return string.match(/\S/) }); } function buildRegexps(queries) { return jQuery.map(queries, function(query) { return new RegExp(query.replace(/(.)/g, '([$1])([^$1]*?)'), 'i') }); } function buildHilighters(queries) { return jQuery.map(queries, function(query) { return jQuery.map(query.split(''), function(l, i) { return '\u0001$' + (i*2+1) + '\u0002$' + (i*2+2); }).join(''); }); } // function longMatchRegexp(index, longIndex, regexps) { // for (var i = regexps.length - 1; i >= 0; i--){ // if (!index.match(regexps[i]) && !longIndex.match(regexps[i])) return false; // }; // return true; // } /* ----- Mathchers ------ */ /* * This record matches if the index starts with queries[0] and the record * matches all of the regexps */ function matchPassBeginning(index, longIndex, queries, regexps) { if (index.indexOf(queries[0]) != 0) return false; for (var i=1, l = regexps.length; i < l; i++) { if (!index.match(regexps[i]) && !longIndex.match(regexps[i])) return false; }; return true; } /* * This record matches if the longIndex starts with queries[0] and the * longIndex matches all of the regexps */ function matchPassLongIndex(index, longIndex, queries, regexps) { if (longIndex.indexOf(queries[0]) != 0) return false; for (var i=1, l = regexps.length; i < l; i++) { if (!longIndex.match(regexps[i])) return false; }; return true; } /* * This record matches if the index contains queries[0] and the record * matches all of the regexps */ function matchPassContains(index, longIndex, queries, regexps) { if (index.indexOf(queries[0]) == -1) return false; for (var i=1, l = regexps.length; i < l; i++) { if (!index.match(regexps[i]) && !longIndex.match(regexps[i])) return false; }; return true; } /* * This record matches if regexps[0] matches the index and the record * matches all of the regexps */ function matchPassRegexp(index, longIndex, queries, regexps) { if (!index.match(regexps[0])) return false; for (var i=1, l = regexps.length; i < l; i++) { if (!index.match(regexps[i]) && !longIndex.match(regexps[i])) return false; }; return true; } /* ----- Highlighters ------ */ function highlightRegexp(info, queries, regexps, highlighters) { var result = createResult(info); for (var i=0, l = regexps.length; i < l; i++) { result.title = result.title.replace(regexps[i], highlighters[i]); result.namespace = result.namespace.replace(regexps[i], highlighters[i]); }; return result; } function hltSubstring(string, pos, length) { return string.substring(0, pos) + '\u0001' + string.substring(pos, pos + length) + '\u0002' + string.substring(pos + length); } function highlightQuery(info, queries, regexps, highlighters) { var result = createResult(info); var pos = 0; var lcTitle = result.title.toLowerCase(); pos = lcTitle.indexOf(queries[0]); if (pos != -1) { result.title = hltSubstring(result.title, pos, queries[0].length); } result.namespace = result.namespace.replace(regexps[0], highlighters[0]); for (var i=1, l = regexps.length; i < l; i++) { result.title = result.title.replace(regexps[i], highlighters[i]); result.namespace = result.namespace.replace(regexps[i], highlighters[i]); }; return result; } function createResult(info) { var result = {}; result.title = info[0]; result.namespace = info[1]; result.path = info[2]; result.params = info[3]; result.snippet = info[4]; return result; } /* ----- Searching ------ */ function performSearch(data, regexps, queries, highlighters, state) { var searchIndex = data.searchIndex; var longSearchIndex = data.longSearchIndex; var info = data.info; var result = []; var i = state.from; var l = searchIndex.length; var togo = CHUNK_SIZE; var matchFunc, hltFunc; while (state.pass < 4 && state.limit > 0 && togo > 0) { if (state.pass == 0) { matchFunc = matchPassBeginning; hltFunc = highlightQuery; } else if (state.pass == 1) { matchFunc = matchPassLongIndex; hltFunc = highlightQuery; } else if (state.pass == 2) { matchFunc = matchPassContains; hltFunc = highlightQuery; } else if (state.pass == 3) { matchFunc = matchPassRegexp; hltFunc = highlightRegexp; } for (; togo > 0 && i < l && state.limit > 0; i++, togo--) { if (info[i].n == state.n) continue; if (matchFunc(searchIndex[i], longSearchIndex[i], queries, regexps)) { info[i].n = state.n; result.push(hltFunc(info[i], queries, regexps, highlighters)); state.limit--; } }; if (searchIndex.length <= i) { state.pass++; i = state.from = 0; } else { state.from = i; } } return result; } function triggerResults(results, isLast) { jQuery.each(this.handlers, function(i, fn) { fn.call(this, results, isLast) }) } } PK!-G2.2.0/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtmlnu[<% comment = if current.respond_to? :comment_location then current.comment_location else current.comment end table = current.parse(comment).table_of_contents if table.length > 1 then %>

    <% end %> PK!>qq;2.2.0/rdoc/generator/template/darkfish/fonts/Lato-Light.ttfnu[GPOSjNKGSUBV.TLOS/28M`cmapRԟN@cvt &7g|8fpgm zAg gaspgtglyfiS(headDeJ޼6hheaix$hmtxESvJTkern2lllocaKpPP,maxp> R| name UR:post:\cprepx9qH 0JDFLTlatnkernkernJnv$R ^ h B l  & rjZjL*|DV: !.!##L#$4$~%&J'$'()*+f+,6,-.(./t//0:0|2"233T334&4l455b566L667B778889d99:&::;@<=>j?,?@hABCzDEFG*GHfIK V B V#$V&*2497:7<?7DFGHRTmBoByB}BVVVVVVVVBB BBBVK V B V#$V&*2497:7<?7DFGHRTmBoByB}BVVVVVVVVBB BBBV"#&*24FGHRTK V B V#$V&*2497:7<?7DFGHRTmBoByB}BVVVVVVVVBB BBBV- v#&*247L9L:P`Q`R)S`T)U`VDX`YLZt[g\L]mLoLw`yL}L))))))`))))))````))`)LLLLLLL $k7 7 7GG"<#$&*-o24DFGHIJ{PQRSTUVWXY[\]l7mor7tFuFwy{F|7}77G77G7I7 7 7"%$-DFGHJRTVl7mor7t7u7y{7|7}777771#&*24FGHIRTWYZ\moy}i t  y`yt"%#$t&*-824DF`G`H`J[PQR`ST`UVXYZ[\lm`o`rt-u-wy`{-|}`ttttttt````````````t`````yy```t0"%#&*24FGHRTVY\moy}"#&*24FGHRT6V V V"#&*--24789:?DEHIKNPQRSUYZ[\^lmoprtuy{|} 8DFLTlatncase&case,liga2liga8sups>supsD,>B      @ LO,{tu CjqvI,xxDP`KtyPL@Jz  &   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ardeixpkvjsgwl|cnm}byqz`T@ ~1DS[a~    " & 0 : D !"!&"""""""+"H"`"e%&i 1ARZ`x    & 0 9 D !"!&"""""""+"H"`"d%&i{uq[H$I޸ޡޞ:ڜ`T@ ~1DS[a~    " & 0 : D !"!&"""""""+"H"`"e%&i 1ARZ`x    & 0 9 D !"!&"""""""+"H"`"d%&i{uq[H$I޸ޡޞ:ڜ/'37;BK PX@3 `f[[ Q CQ D@4hf[[ Q CQ DY@ ;:$$#,$ +>32#'&>54.#"#"'4632#"&!!7!!332#"&tA1!""'5-PS\88\SP-<""!5) ,@) BQ D   $+#"&/!#"&/  u  ܙ$ܙ$V<6:5BK-PX@(  Y  C Q C D@&  Z  Y  C DY@:98766421/-,(&#"!#!+#"&547!+#"&5<?3#76;>;!323+32%!!^)VV*^R(W*_*_*W(R*REm  &!Fp&!{,F \;FQ@) ! LA*7BK PX@2j  h f_ SC TD@1j  h fk SC TDY@NMCB;965$#$ +.'7632.54>?>;#".'+4.'>H  &4EX8 De>4e_ $ e?  '?]A/_WJ7:mf  $2Tm<P}U,,Lc8LqL&bP'!'#|4QwZEe>K?"!(% (4G[X?-(0K`W'0DX?@<[ [ CSC C SDUS((%"&((($ +#".54>324.#"32>>;+#".54>324.#"32>0Rl<>mP..Pm>>lQ/L#=Q--P<##mP..Pm>>lQ.L#7>;#"&/#".54>7.54>32>7&'CxY5  ":W;*Y-l~OKsG4Z|HGG3^;^s8F}m[&5BkJ(.Ng8 D<*%C\7RVHHI ^[4X?$2aZHmVPVFwX2MrM& 9N/N_n @BQ D $+#"&/  ܙ$(+.54>7yx*Mi@@iM* wyve vuuv eb(+4'&54?'&5476Zyw *Lj@@jL*xyv vuuv {51@.1-,($# BMQE55+5467'7>7./7.=3>?'.'t 4   m,n n-n  m-m n-n m ,@)MYQE +!!#!5!iQNR=I;In@B ?S D"+74632'&5467>7#"&n0'+/(8"  %/U#2;0)URL    '5@$2d)5z@MQE+!!d/zQi"@SD($+74>32#"&i!""'5M""!5@kD""++6;[ 'n')-%I?'@SCSD((($+#".54>324.#"32>?PiiOOiiPdBoRRpBBpRRoBĺWWWWHHGG*@' Bh CR D%+%!47#"/3!!5E  J5'J|"& (iJ2>@;. BhSCQ D-,+)$" 22+2>3!2!5467>54.#"#"&#'>ZQpB1To=E E#co CqW9 0 Kr/_`P~w><8" =rtzENsJ$)Ie<#[b3HU@RD Bhh[SCSDB@;910/.&$HH +2#".'763232>54.#5>54.#"#"/>eQm?+Kf#[b3?^ @[ C D!#+!+#!"&/3467![ Ve UV^4 j /&/@@=-,Bh[Q CSD(#&(#"+#!>32#".'763232>54.#"'!UCx7nq:Nd;j^N  1MiFRi;-[^9H>o|^(?q\p|B#.'$5d]L[3s02@/B[ CSD-+#! +2#".54676;>32>54.#"t[o?E{gcu@T`"TZ4;1ZQVa43]NX`2N7.54>32'2>54.#"2>54.#"DfyD-RqD>`A"9j_^k9"B`>DqR.DyfQ`4Dj<Vi32+>74.#"32>=Wk32#"&4>32#"&!""'5!""'5M""!5D""!5J-H@ (B?K#PX@SCS D@[S DY,*$($+4>32#"&4632'&5467>7#"&!""'50'+/(8"  %/j""!5#2;0)URL    '5@$2 5(+ !'*) A   Ae!@YMQE+!!!!;;,JJ 5(+546767.'&= *(" A   A)!(:9@6BhfSCSD(&#-$+>32#'54>54.#"#"'4>32#"&!DQ`8F|]7/HTI3 A0GSG0*H^3BaB&!""'5 2'*NqFLnS?78")>:3232>54.#"3267632#"$&546$32%2>7.#"XY8R8R6A}t5]%[ %09hP/a}mqd pzvq:e$MG>P3"Zg9(;]W]S'D\5UV.I,7 54&#!yt9'JkE@zqc3`Y3bY*0]U8hXAZd5CkK(K2Rh7|2D@ABhfSCSD,*"  22+%2#".54>32#".#"32>7> (,h{XbeMob/ +=TnF؜WVyLwdV* +/K5g  i+@*- %Y뒖W(:'y @S CS D!(!$+#!!24.#!!2>ybbjRҀcҕRĤbbTT" .@+YQ CQ D +!!!!!"lUSU" (@%YQ C D +!!!#"{gUUv|C4H@E! Bh[SCSD,*%# 44+%2>7!"&=!#".546$32#"'.#"2Ixg]/ 5rYddQvf/  9ahޝUVC+} 8 %:'g  g+?),,0&X쓖X @Y C D+!#!#3!3gggvgZl^@ C D+!#3^ggY'@$Bh CSD#'$+#"&'>7>3232>53;mb-\1  #-LzV-gw|? 0cf"&@#B[ C D'(' +32>7>;#"&'.+#3VT ;S!S  [ff  K X d  V@ CR D+%!!38fWWH %@"Bh C D!5(+>7>;#47+"'#32z  ,GZYF;  y#J (@ C D!+2&53#"'#3 Z1hY2 6yY{'@SCSD((($+#".54>324.#"32>bccbjRҀ~їSS~ҕRĤgg  hgWW씕VVS *@'[S C D !+#!2#%!2>54&#!VfmEu^g7:]q?R4\}J{0T@  BKPX@SCSCD@kSCSDY(((%&+#"&'#".54>324.#"32>+PsHpV ?NccbjRҀ~їSS~ҕRk~-v Fg  hgWW씕VV"2@/ B[S C D" *!+#!2#"&'.#'32>54&#!Vfi8i]Y ;')^g6ƽQeA  >L-TvJW==@:=BhfSCSD;9(&!#!+#".#"#"&'763232>54.54>32~  )FiMMuO)=dd==tlL  (8J`=T[0=dd=6hbnH%-&,Ld7H^B-,5PuWYtCcV,#)#3XyEKaA,*4Qy[Ge=FH#n @Q C D+!#!5nf W0W#@  CSD +%2>53#".53fp;fJ||NjJg;oIG~cku˗VVukc~H@B C D* +3267>;#Q P[ j.46, y' @#B C D,; +32>7>;2>7>;#&'#Ue   eNC\^][u..  u,- y4@B C D(")!+ 32>7>; #"&'+e  beB J ] L T% @ B C D,"+#32>7>;gYZHH? v++ s $@!Q CQ D +!!547!5~ #U%U '@$[OQE !#+!+32>$  $@kD" +32#"&')'n' %"k !@[OQE!"+46;#"&=!!k= s $  @ Bk D,!+3#"&'.'+ <UD    G L3@MQE+!5DDV @kD  +2#"&/ 6  kC'7T@Q-Bh[SC C SD)(/.(7)7"  '' +!"/#".54>754&#"#"/>32%2>7)QXf=3`J-HwuHeF, NmPxO(J:aSH#ͅ?!6H(@,>aD?lP0h(0(NP3_Sx5->$#32#"&'#"32>54&`Bm9oih6hc?9ZXY-XfmPQOzf[VE@ubXX,9@6,BhfSCSD(&#(#"+#".#"32>32#".54>321  #:W>V[01ZNHa?% FXg8_q?5W#q@ BK%PX@CSCS D@!CSC CSDY@## +!"/#"&54>323%267.#"c Bn9oie6`^c?:XXY-ZjmPKHNQ@f[ UF@ubX%0H@EBh[SCSD'&,+&0'0 %% +2#!32>32#".54>"!4.Ti; 14`TKnK, Oao8fxA=skMzY7 ,Pp:oips:!)! 4%GkJG0Z~NPX/n_BK!PX@SCQC D@[SC DY@!$%! +3'&=354>32#"&#"!!nj,PqD? )1S7.54>4.'32>2>54.#"Ao,4]OVF*0ugik6h[2; -GO3]1Rkuv3&A.-W~RLa7@dD#$Ec??dE$$Ed ! &_6HuS.B+.-QC>rX5+I`6Or@9.-()[HuT./9  '1;#,K7 ">V.%B\88]B$$B]88\B%-@*BCSC D##+33>32#4&#"_EnR}R*_bBUe4bW|eXG&@#SCC D +##".54>32_    W!!G'4@1 BSCCSD$"!$%+#"&'76323265#".54>32;Y<. QN    4XA% 0 XQbW!!0@-B[CC D%(%!+3267>;#"&'.+# . TI   S ^-`{ _   @C D+#_Q,8@5+ BCSC D,,##&&! +332>32>32#4&#"#4&#"4 BKU/mATc4JvS,`~u4_I+_toQ6)D1q>Z;1`Z|&KpJ|aV1@.BCSC D#$!+332>32#4&#"4 DoR}R*_bBVi4bW|eXW',@)SCSD'' +2#".54>2>54.#"kt==tkku==ukYY,,YYYY--YIuuHHuuIK=rdcs>>scdr=$D@ABCSCSCD$$&%!+32>32#"&'"32>54&4  Bn9nif6Bc>9YXY-C ZjmPJIg\VF@ubW#D@ABCSCSCD##&#+##"&54>32763267.#"`Bl9oig6 c?6YXY-XfmPNLp]f[RH@ub8@5 BhCSC D#$%!+332>32#".#"20u-L" !0q-yB yY<=@:<BhfSCSD:8'%" #!+#".#"#"&'7>3232>54.54>32 #9S<6Y?#0NchcN0/YSi< &=[C?`@!0NcicN0.UzL[;h4E&/>, ':T5bJ,464@#x@ !BKPX@%jhQCSD@#jh[SDY@ ## +"&5#"&=7>;!!32>32eq  -9%2$4&&upu % d G]);& **3-@*BC CSD$!#+32673#"/#".5逃aC`5 EoS|R*cXVh4bW|@ BC D,!+!#32>7>;T\KH  J H *+ * @#BC D*!); +32>76;2>76;#"'.'+I  '  FFC **-*+(#v@BC D("(!+ 3267>; #"&'+[ $  Xj[  U Z h @BCD,""++32>7>;{D[OO  K I  J: @QCQ D+!!547!5!:d)qK&MK?H3@0*B[[OSG@>;83-+4.#52>54.54>;+";2#".54>):##:)&HiB7!+G3)55)3G+!7BiH&!7)=)7!7hhi8=hM+* 8P19lii5%>./=%5ijl81P8 *+Mh=8ihhQ@QD+3#KKiH5@2B[[OSGEDCB530-3)++546;2>54.54>7.54>54.+"&=323"}&HiB7 !+G3)55)3G+! 7BiH&)9##9)7hhi8=hM+* 8P18lji5%=/.>%5iil91P8 *+Mh=8ihh7!7)=)79@6jk[OSG +2>53#".#"#4>32 %=*N 734632#"&A5'""'5&-PS\88\SP-'5""70;U@R 6&,BjhfkSCTD##'# +.54>?>;#".'>32+M`r>@{s $ W5  !7P8+KfC' EXh: $/Y}N,\a3 JtpM :.!"' 1% bo@i?qCQ:@@=3)Bh[SCS D#&#%&%" +46;4>32#"'.#"!#!>3!#!5>5#C4gfLtW>&  ->V327'#"&''7.732>54.#"($1-n?>m-1$*)$2-n>>m-1$)H+Ic88cJ++Jc88cI+>m-2$*)$2-n?>m-2$)($2-n?8bI++Ib88cJ++JcU( 8@5 B Z Y C D *! +!3267>;!!!!#!5!5!ZZO Z  YPY[n_nhg#!' :v:~:vQ@YQD+3#3#KKKK}kH\A@>HZP=#BhfWSDFD-+(&!#!+#".#"#"&'7>3232>54.5467.54>32>54.'( #9S<8[@#2RhmhR2TR6C/YSi< &>\D>`B"4VmqmV4[g7E.UzL[;'CX`c-G>$=QZ]+YJ 5F'.D7.07F]>S{#&bEApR0C6" % "32#".54>32 W     U,H\@ BKPX@4hf[[ SCSDKPX@4hf[[ SCSD@4hf[[ SCSDYY@ YW*,((#&(%! +632#".54>32#".#"3264>32#".732>54.#"8 ;t`s@Cxc4WJ@ !:[DSa55^MU{S4]dd]44]dc]4;ghhg ;FAvfdwB)! 5bWZa3)Pc^44^cd^44^dhhiij>5&4B@? ,Bh[WSD('.-'4(4$##' +#"&/#".54>754&#"#"/>322>755  15=$!<.*]iDI+;(  0jCeh!81+!*G D$ %9'$A13LO 0-ub"D8' %%(+55   z     { z     S=K PX@_MQE@kMQEY+!#!=R'd)5z@MQE+!!d/zQU/FO:BKPX@/h  [ [SCSDKPX@/h  [ [SCSD@/h  [ [SCSDYY@00OMIG0F0E)!(*,& +4>32#".732>54.#"#32#"&'.#'32654&+U4]dd]44]dc]4;ghhgUu  P nywlvc^44^cd^44^dhhiiyusvd _ @a[\T5%@MQE+!!!%A[D'@WSD((($+4>32#".732>54.#"[/Qn??nQ//Qn??nQ/G$>T00T=$$=T00T>$n>mQ..Qm>>lQ//Ql>0T>$$>T00T?$$?TmP 7@4YYMQE  +!!#!5!!!iQNRRUjInIIa;W-g@ + BK#PX@h[SD@!h[OQEY@(&#! --+2>3!2!546?>54.#"#"&/>V,N9!*8'&1%'4>H |W1I0(E?;*89< #4"G7`fb|=W?@=BKPX@,hh[[SD@1hh[[OSGY@;964.-,+#!?? +2#".'7>3232>54.#5>54.#"#"/>\,L7 H).J5[Y'3?I{W/C+BWTB0M73C$  (%*4!4%1K?"2!A;`f @kD #++7>3 9  0@-BCS CD&$!#+32673#"/#"&'#"&5逃aC`5 Ffb%0cXX\MH+X$6B*@'hiS D+##!#".54>3UVgr==rgR  y8bMP\2o@OSG($+4>32#".$&&$P&&%%V@  BK PX@^jTD@jjTDY@+232654.'73#"&'76(390A'*=Y]1D()N  ,&! `<;0! 5RO BKPX@jjQD@jjMRFY$+37#"/733! :%~ c1W;)@&WSD +2#".54>2654&#"wBjJ''JjBDjK''KjDhiihkii*OoEEoO**OoEEoO*rqqr)'(+7'&547>7.'&54?'&547>7.'&54?      &  %     &  %   q#-O@L! Bh  Z [  CS  D-+(&#"$!" +%3+#5!"/3%37#"/733!47!+>;~m?`C : ( *$ #%~ c1w} dK-=Ge@b710+ Bhh  Z [  CS  DGEB@=<;:9853/.(&#! -- +2>3!2!546?>54.#"#"&/>%37#"/733!+>;f,N9!*8'&1%'4>I| : ( *1I0(E?;*89< #4"@>`f%~ c1b dSqPU_]@N  $SBK PX@B h  h  [[ \ S CS DK PX@B h  h  [[ \ SCS DK PX@B h  h  [[ \ S CS D@B h  h  [[ \ SCS DYYY@!_]ZXUTKHEC=<;:20)' PP!"+%3+#5!"/32#".'7>3232>54.#5>54.#"#*.'>47!+>;~m?`CZ,L7 H).J5[Y'3>J { ( *$ /C+BWTB0M73C$  (%*4!4%1K?"2!G5`f} d*);5@2BhfSCTD('#-$+#".54>?332>324>32#"&DQ`8E}]70GTJ3 A0GTG0*H^3E_@$ !""'52')MoGLkM924#*<45E]B6U;#+#O""!5&$ [&$ [&$ `&$`&$ `&$`4@1YYQ CS D" +!!!!!!!+!HjK8 O i USUc7.|Oh@e<B M Bhf hSCSC S  DKIA@:820(&!OO +232654.'7.54>32#".#"32>7>32#"&'76(390A'$ZeMob/ +=TnF؜WVyLwdV*  (,eyUY]1D()N  ,&! sn i+@*- %Y뒖W(:'+.J5K<;0! "&( Z"&( Z"&( _"&( _&, N&, E&, N&, 1!,@)YS CS D!%(!+3!2#!#%4.#!!!!2>1bbRҀclҕRbbT@T&1{&2 {&2 {&2 {&2{&2 D  (+  ' 7 t34u5pn 4t4vp6o{!-9b@ 21&%BKPX@kCSCSD@jkSCSDY**%(%$+#"&'+7&54>327>;.#"4&'32>bsQ ,lwcySo 7eo$^UGj~їSrVNEdҕRĤg=9` hC?`갠R954&#!VffEu^g7]q?R4\}J'J>@;BhSC CSDED?='%" JJ+2#"&'7>3232>54.54>54.#"#4>UZ./GRG/!7EIE7!2Z~Me< %\G87:%$1$!):DS8I?*+X^eo;kC&DCkC&DvkC&DkCi&DkCW&DjkC&DkBR]@:@BK1PX@5hh  [ S C SD@?hh  [ S CSC SDY@&TSYXS]T]NLDC><7520-,$" BB+2#!32>32#"&'#".54>754&#"#"&/>32>32>5"!4.K`7 l0X|LGdD& JZe4/Uly7?lP.HwuHeF, Mk~/ͅ?!32#".#"32>32#"&'76(390A'%Wg8V[01ZNHa?% -jY]1D()N  ,&! vKsrK>5" =reio:"(" :NO<;0! X&HCX&HvX&HXW&Hj"V&C&v&W&jY}6J6@3<2B65@[SD87B@7J8J.,$"+&54?.'.546?7#".54>32.'2>7.#" ~327>;.#"2>54'h<>=tklQ !&DF=ukX7W 2/0-vKY[.iYZ.P WiCvuHOmCuI1-th9*,?s>rds]E&XC&Xv&XW&Xj&\v!@@=BCSCSCD!!&#+3>32#"&'"32>54&_Bm9nif6Bc>9YXY-XgmPNLg\VF@ubW&\jc&/O@L,BAhZ C CSD('#!&& +2#"&54>7&'!+3"32>!.'F T/L^'1INCfC 23&@2&z"KB92*e y/A'05 ++kBRn@k-H 6Bh h  [SC SCSDDCJICRDR?=1/*(%# BB +2#"&54>7&/#".54>754&#"#"&/>3232>2>7 T/L^)4 )QXf=3`J-HwuHeF, NmPxO(.(@2&:aSH#ͅ?!6H"KB ;3+ (@,>aD?lP0h(0( NP3_Sx "-705 (->$#7!!!!!!#32>$ T/L^&1RPl[.(@2&"KB82+USU "-705 XCNg@d2Bh h  [  SCSCSDEDJIDNEN@>0.+)$"CC +2#"&54>7"#".54>32#!32>3232>"!4. T/L^!+ fxA=sjTi; 14`TKnK, 7EP*,&@2&MzY7 ,Pp"KB4/)GkJ:oips:!)! *" ",505 0Z~NPX/@C D+#_:#@  B CR D+%!!54?3c rf? WKeB ]9#@  BC D+7#54?[ _Y2 TZ4Tv&1 &Qv{7 4@  BKPX@+YSCQ C S DK%PX@)YSCQ C S DK)PX@3YSCQ C Q C SD@1YSCQ CQ C SDYYY@ 1/%(% +!!!!!#".54>32!4.#"32>7l%k]ߠYY߇]k%EJsrKKrsJ2SUNRY/f  h0ZRM=XX씕WWWW2FQa@^. Bh  [ S C SDHG43MLGQHQ><3F4F,*"  22+2#!32>32#"&'#".54>32>2>54.#""!4.K`7 l0Y|LCcE) JZe4,*Ĕbm::mc*E^xZR{R))R{RS|S))S|?HsR1W(Ie>scdr=n4^RU]1W&6  Y&VvW&6Y&V&< 4s&= hJ:&]vs&=kJ:&]s&=kJ:&]v#2@/YSCSD##"" +#543>7'&=37>3#"!{` DlX$3`N7 _ض$5`N7 eb\+0 FpR '3FpRG (@Bk D* +#"/&'+73(A CU  ( @Bk D' +32?>;# C AU 5%q5 @W D +".5332>53$B[9E(A00A)E9['DZ2%B22B%2ZD'}@SD($+#".54>32}    F!!xs=K'PX@WSD@[OSGY$&($+4>32#".732654&#"x/?##?//?##?/:@32@@23@$<++<$$;,,;$2@@22@@ +@(B@jSD+2#"&54>732> T/L^-81.(@2&"KB"=6, "-705 &*iQKPX@WS D@[OSGY@ +2673#".#"#4>32+,;%6"!;63*,=&6"";537/$?.!'!9-$?.!'!| #@ SD   #++7>3!+7>3 * R /   .s\BK1PX@SCS D@SC CSDY@!$## ++#!#"&'7632325#5463s_,mi4 $e=nt '" f@MQE+!!fGf@MQE+!!fG!.(+.5467L=&2#!&K&N;3d6;=n(+'&547>54'&547L=&2#&K&N;2e6:=n(+7'&547>54'&547L=&2#&K&N;2e6:=!;)(+.5467.5467L=&2#L=&2#!&K&N;3d6;=&K&N;3d6;=n')(+'&547>54'&547%'&547>54'&547L=&2#JL=&2#&K&N;2e6:=&K&N;2e6:=n')(+7'&547>54'&547%'&547>54'&547L=&2#JL=&2#&K&N;2e6:=&K&N;2e6:=@ BKPX@CCSCDK%PX@ZCCD@`ZCDYY@ #!""+463632>72!#"'!MS  RN     -@  &" BKPX@/  `  [CCSC  DK%PX@-  `Z  [CC  D@/`  `Z  [C  DYY@+)('%#! !"#+7!!5463632>72!!#.'#"'"&5|MS  RN}NR  SM   B  1i|@OSG($+4>32#"..Pj<=lP..Pl=32#"&%4>32#"&%4>32#"&i!""'5!""'5!""'5M""!5'""!5'""!5Wz'0DXlK@H[   [ CSC C  S D}{sqig_]US((%"&((($+#".54>324.#"32>>;+#".54>324.#"32>%#".54>324.#"32>0Rl<>mP..Pm>>lQ/L#=Q--P<##mP..Pm>>lQ.L#mP..Pm>>lQ.L#7.'&54?    &  %   6 @ C D#"+'+>;k ( * doN[@X ; Bh  h [   [SC S  DNMHGFEA?97$##%'$+3>32#".#"!#!!#!32>32#".'#53.547#Zn@m]Q% "1CY:ZqJZ HpZ>_H4$ %$TfxFqT_ҒN,A+#%?zv /2' |~@%+% #.K5Nً;'10HH#C@@ BhS  CS  D##!4% +67>;#7+"'#32###5 9> ?9 WG l,z*E?x;;h}71@.1BSCS D76***+!>54.#"!"&=!5.54>32!#c`r>VooŔV>q` byDe뇇eDxbkOwg~~??~~gwO4\mؖOO؉m\4{.BC@@4Bh[SCSD0/:8/B0B#+(($+>32#".54>32>54&#"#"&'2>7.#"$CCG(W_2GԌQ`5Iq5cVD1K8%  MRoO +GeEbk9(If=# H~6f[rɖV9W;;5- &Gy3cN/IdKvR+ @B CR D+3!7!&'^\M *  ySz!+&M $@!Q CD +##!##5bbRkkRW&@# BQ CQD+!!!!547 &5W{[ ` RR$1. z@MQE+!!=I("@ Bj[ D*# +#"&=!267>;#5:  :O .)%' IJ ';OL@IK-B[  O  SG=<)(GE32>32%2>7.#"!2>54.#"7\NCCN[79hO//Oh97[NCCN\79hO//OhF,KB;;BK,,M:!!:M+M9!!9M+-KB;;BK(BW//VC(+PsGGrP+(CW..WC(+PrGGsP+N&@S--T@&:V78V::V87V:&@T--S@&K)*@'BSCSD!%)U$+>32#"&#"#"&'7>3232>7 :Vo@'9  4XC- ?]xE!A "<`G/ >WU+ +  DgHcZ* '  GqQ/d@a('B[[[ O SG,*%# //  +267#".#"'>32267#".#"'>32 4Xd84ec`.7Wc<4fc_.4Xd84ec`.7Wc<4fc_*-:+/$,$-8-0$,$-:+.$,$-8-/$,$pkK PX@)^_ ZMQE@'jk ZMQEY@  +!3!!!!#!5!7!uGth@vHvThDe JJJPO!@ @MQE+!! ''%v>     ?xIPO!@ @MQE+5467>7.'.=!5! &&& (?    >If"@ BMQE+3 # >7 .'BnBL  N  @@S@CD+3#kaBK!PX@SCQC  D@[SC  DY@!$%! +3'&=354>32#"&#"!#!nj6g_!G +!G`{ 'U\g7 0 R<}"K!PX@SCQC  DK1PX@[SC  D@![CSC  DYY@""A15! +3'&=354>32;#.#"!!nj4d`"IE<H_6w0KvQ+ { 'AXn>nO/Y~NAGR @jD  +2+:  0[ "6M6  @ja  +2#"&'%tG   2E%@OSG&(($+#".54>32#".54632   0!    !1 U5q@MQE+!!Uaq<J @ja #++7>3J  F  <@Bja, +#"&/.'+73?>;# J IZ{{2 (@%jOSG   +"&5332653$|v@R``R@vpfGQQGbt8{@OSG($+#".54>32{  }!@[OSG$&($+4>32#".732654&#"}-="">-->""=-5@32@@23@^";**;"#:**:#2@@22@@*)1@.[OSG +2673#".#"#4>32*,6"5"!<85*+8$4""<84P7+#;- % 8*"<- % j +@(OSG   #++7>3!+7>3 / q  4  m @kD  +2+U  3 #;U< .U_<ʓ^pӡ6z V6:z/VWgjXXb {mndiI?x!kl |x|VY(;{;{W# sXXkIVkDXDWXK:7::W.DW\Y4:#JX?XXiCUXI'MUjjdMUI[mabI:6IWjS*      7|VVVV '1;{;{;{;{;{;{kkkkkkIkXXXXX"0Y::W:W:W:W:Wm:W::::. k|XX*:X9:{W:W\YW\YsJsJsJvI I II5IIxII&I|.:7nnnn`iWkk6Hh{TMTWc(TJ*lIIIIUII I I2II}I*IjIl#`  V B V#$V&*2497:7<?7DFGHRTmBoByB}BVVVVVVVVBB  BBBV V  B  V # $V & * 2 4 97 :7 < ?7 D F G H R T mB oB yB }B V V V V V V V  V  B B B B B V # & * 2 4 F G H R T V  B  V # $V & * 2 4 97 :7 < ?7 D F G H R T mB oB yB }B V V V V V V V  V  B B B B B V   v#&*247L9L:7P`7Q`7R)7S`7T)7U`7VD7X`7YL7Zt7[g7\L7]7mL7oL7w`7yL7}L7777777777777777777777)7)7)7)7)7)7`7)7)7)7)7)7)7`7`7`7`7777)7)7`77)7L7L7L7L7L7L7L78 8888$88888888888979 9 79 79G99G9999"<9#9$9&9*9-o92949D9F9G9H9I9J{9P9Q9R9S9T9U9V9W9X9Y9[9\9]9l79m9o9r79tF9uF9w9y9{F9|79}99999999999999999999999999999999999999999999999997979G97979G999979:7: : 7: 7:::::"%:$:-:D:F:G:H:J:R:T:V:l7:m:o:r7:t7:u7:y:{7:|7:}::::::::::::::::::::::::::::::::::7:7::7:7:::::7:;;#;&;*;2;4;F;G;H;I;R;T;W;Y;Z;\;m;o;y;};;;;;;;;;;;;;;;;;;;;;;;;;;;;;<< t< < <y<`<y<t<<<"%<#<$t<&<*<-8<2<4<D<F`<G`<H`<J[<P<Q<R`<S<T`<U<V<X<Y<Z<[<\<l<m`<o`<r<t-<u-<w<y`<{-<|<}`<t<t<t<t<t<t<t<<<<<<<<<<<<<<<`<`<`<`<`<`<<`<`<`<`<`<`<<<<<t<<<`<`<<<`<`<`<<<y<<<y<`<`<`<<t=="%=#=&=*=2=4=F=G=H=R=T=V=Y=\=m=o=y=}=============================>#>&>*>2>4>F>G>H>R>T>>>>>>>>>>>>>>>>>>>>>>>>?V? V? V??"?#?&?*?--?2?4?7?8?9?:?# #&#n#$"$$%.%d%%&.&t&'0'))r)~)))))*********++T+`+l+x++++,P,\,h,t,,,-P-\-h-t---.x///(/4/@/L/X/d/p/0000&020>011 11$101<1122223<334*4\4h4t5<5556666(646@6L6X6d66777D7n778R88899>9d99::V:;t;;<<= =>=>4>??F?p???@@A^AAB6BxBBCbCCCD D.D\DDDE$EhEE`"/n   ( ( 0% % 4  2( Z 6 J ^ Pl  P  `     0 V d    4n   Copyright (c) 2010-2013 by tyPoland Lukasz Dziedzic with Reserved Font Name "Lato". Licensed under the SIL Open Font License, Version 1.1.Lato LightRegulartyPolandLukaszDziedzic: Lato Light: 2013Version 1.105; Western+Polish opensourceLato-LightLato is a trademark of tyPoland Lukasz Dziedzic.Lukasz DziedzicLato is a sanserif typeface family designed in the Summer 2010 by Warsaw-based designer Lukasz Dziedzic ("Lato" means "Summer" in Polish). It tries to carefully balance some potentially conflicting priorities: it should seem quite "transparent" when used in body text but would display some original traits when used in larger sizes. The classical proportions, particularly visible in the uppercase, give the letterforms familiar harmony and elegance. At the same time, its sleek sanserif look makes evident the fact that Lato was designed in 2010, even though it does not follow any current trend. The semi-rounded details of the letters give Lato a feeling of warmth, while the strong structure provides stability and seriousness.http://www.typoland.com/http://www.typoland.com/designers/Lukasz_Dziedzic/Copyright (c) 2013-2013 by tyPoland Lukasz Dziedzic (http://www.typoland.com/) with Reserved Font Name "Lato". Licensed under the SIL Open Font License, Version 1.1 (http://scripts.sil.org/OFL).http://scripts.sil.org/OFLCopyright (c) 2010-2013 by tyPoland Lukasz Dziedzic with Reserved Font Name "Lato". Licensed under the SIL Open Font License, Version 1.1.Lato LightRegulartyPolandLukaszDziedzic: Lato Light: 2013Lato-LightVersion 1.105; Western+Polish opensourceLato is a trademark of tyPoland Lukasz Dziedzic.Lukasz DziedzicLato is a sanserif typeface family designed in the Summer 2010 by Warsaw-based designer Lukasz Dziedzic ("Lato" means "Summer" in Polish). It tries to carefully balance some potentially conflicting priorities: it should seem quite "transparent" when used in body text but would display some original traits when used in larger sizes. The classical proportions, particularly visible in the uppercase, give the letterforms familiar harmony and elegance. At the same time, its sleek sanserif look makes evident the fact that Lato was designed in 2010, even though it does not follow any current trend. The semi-rounded details of the letters give Lato a feeling of warmth, while the strong structure provides stability and seriousness.http://www.typoland.com/http://www.typoland.com/designers/Lukasz_Dziedzic/Copyright (c) 2013-2013 by tyPoland Lukasz Dziedzic (http://www.typoland.com/) with Reserved Font Name "Lato". Licensed under the SIL Open Font License, Version 1.1 (http://scripts.sil.org/OFL).http://scripts.sil.org/OFLLatoLightZD  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghjikmlnoqprsutvwxzy{}|~      !"#NULLuni00A0uni00ADmacronperiodcenteredAogonekaogonekEogonekeogonekNacutenacuteSacutesacuteZacutezacute Zdotaccent zdotaccentuni02C9EuroDeltauni2669undercommaaccent grave.case dieresis.case macron.case acute.casecircumflex.case caron.case breve.casedotaccent.case ring.case tilde.casehungarumlaut.case caron.saltbKbKVV, `f-, d P&ZE[X!#!X PPX!@Y 8PX!8YY Ead(PX! E 0PX!0Y PX f a PX` PX! ` 6PX!6``YYY+YY#PXeYY-, E %ad CPX#B#B!!Y`-,#!#! dbB #B *! C +0%QX`PaRYX#Y! @SX+!@Y#PXeY-,C+C`B-,#B# #Bab`*-, E EcEb`D`-, E +#%` E#a d PX!0PX @YY#PXeY%#aDD`-,EaD- ,` CJPX #BY CJRX #BY- , b c#a C` ` #B#- ,KTXDY$ e#x- ,KQXKSXDY!Y$e#x- , CUX CaB +YC%B %B %B# %PXC`%B #a *!#a #a *!C`%B%a *!Y CG CG`b EcEb`#DC>C`B-,ETX #B `a  BB` +m+"Y-,+-,+-,+-,+-,+-,+-,+-,+-,+-, +-,+ETX #B `a  BB` +m+"Y-,+-,+-,+-,+-,+-,+- ,+-!,+-",+-#, +-$, <`-%, ` ` C#`C%a`$*!-&,%+%*-', G EcEb`#a8# UX G EcEb`#a8!Y-(,ETX'*0"Y-),+ETX'*0"Y-*, 5`-+,EcEb+EcEb+D>#8**-,, < G EcEb`Ca8--,.<-., < G EcEb`CaCc8-/,% . G#B%IG#G#a Xb!Y#B.*-0,%%G#G#aE+e.# <8-1,%% .G#G#a #BE+ `PX @QX  &YBB# C #G#G#a#F`Cb` + a C`d#CadPXCaC`Y%ba# &#Fa8#CF%CG#G#a` Cb`# +#C`+%a%b&a %`d#%`dPX!#!Y# &#Fa8Y-2, & .G#G#a#<8-3, #B F#G+#a8-4,%%G#G#aTX. <#!%%G#G#a %%G#G#a%%I%aEc# Xb!YcEb`#.# <8#!Y-5, C .G#G#a ` `fb# <8-6,# .F%FRX ,1+!# <#B#8&+C.&+-?, G#B.,*-@, G#B.,*-A,-*-B,/*-C,E# . F#a8&+-D,#BC+-E,<+-F,<+-G,<+-H,<+-I,=+-J,=+-K,=+-L,=+-M,9+-N,9+-O,9+-P,9+-Q,;+-R,;+-S,;+-T,;+-U,>+-V,>+-W,>+-X,>+-Y,:+-Z,:+-[,:+-\,:+-],2+.&+-^,2+6+-_,2+7+-`,2+8+-a,3+.&+-b,3+6+-c,3+7+-d,3+8+-e,4+.&+-f,4+6+-g,4+7+-h,4+8+-i,5+.&+-j,5+6+-k,5+7+-l,5+8+-m,+e$Px0-KKRXYc #D#pE (`f UX%aEc#b#D * **Y( ERD *D$QX@XD&QXXDYYYYDPK!䍒TtTtC2.2.0/rdoc/generator/template/darkfish/fonts/Lato-RegularItalic.ttfnu[ DSIGtLGPOS,HPGSUBV.TI|OS/2ٮJ`cmapRԟJcvt 'i8fpgm zAj4 gaspiglyfmrO>headd6hhea`L$hmtx4WpTkern@BglocaE/R,maxpC T nameUTpost:]fXprepx9s 0JDFLTlatnkernkernGrTv   V 8,^$^ 0 DJJJL F !z" ##P#$4$~%x&&'()*++,J,-n../$/V///1242n2233V3344J4445567778~88:;";;<=2>,?&?@ABC8CDE.F(> UU$U96:0<-?6DFGHRTmoy}UUUUUUU-U-U> UU$U96:0<-?6DFGHRTmoy}UUUUUUU-U-U-#&*24DFGHRTkp> UU$U96:0<-?6DFGHRTmoy}UUUUUUU-U-U0 ;#&*24759,:|<;?,YrZ\|klm;o;pry;|};;rr;;;;;;& ^^$7A9;<@=?lr|@@^^^0 ;#&*24759,:|<;?,YrZ\|klm;o;pry;|};;rr;;;;;;q6 6 6AA":#$&*-i24DFGHPQRSTUVXYZ\]kl6mopr6tPuPwy{P|6}66A66AA$ $79;<=?@`lr|:J J J#&*->247|89: |LL|"$|-:DFGHPQRSTUXw||||||||LLL| $+  #&*24IWYZ\klmopry|}3 ;#&*24789J:h<,?JY|Z\|klm;o;prt,u,y;{,|};,||,;;;;;$ $79;<=?@`lr|/ vCCv$v-JDFGHRTvvvvvvvvCCCv$ $79;<=?@`lr|#&*2478kpf |LLL|ff"'#$|&*-824D/F/G/H/JEPfQfR/SfT/UfVJXfYWZ[Z\L]_kmLoLpwfyL}L|||||||/////////////f//////ffffWW|///f/JJ___LLLLLLLL| $q6 6 6AA":#$&*-i24DFGHPQRSTUVXYZ\]kl6mopr6tPuPwy{P|6}66A66AAN: : :$-DFGHJPQRSTUVXl:r:t<u<w{<|:::::+  #&*24IWYZ\klmopry|}m7 r 7 7'J'r"2#$r&*-824DAFAGAHAJWPQRASTAUVAX]kl7mJoJpr7t>u>wyJ{>|7}JrrrrrrrAAAAAAAAAAAAAAAAAAArAAAAAAJJ77'77'J'JJr"##&*24kmopy}-#&*24DFGHRTkp:J J J#&*->247|89: UU$U96:0<-?6DFGHRTmoy}UUUUUUU-U-U& ^^$7A9;<@=?lr|@@^^^& ^^$7A9;<@=?lr|@@^^^$ $79;<=?@`lr|> UU$U96:0<-?6DFGHRTmoy}UUUUUUU-U-U TT$T9:::<(?:TTTTTTT(T(T TT$T9:::<(?:TTTTTTT(T(T& ^^$7A9;<@=?lr|@@^^^ TT$T9:::<(?:TTTTTTT(T(T> UU$U96:0<-?6DFGHRTmoy}UUUUUUU-U-U& ^^$7A9;<@=?lr|@@^^^:J J J#&*->247|89:247|89:247|89:247|89:247|89:247|89:u>wyJ{>|7}JrrrrrrrAAAAAAAAAAAAAAAAAAArAAAAAAJJ77'77'J'JJr$ $79;<=?@`lr| @[`lr| @[`lr| @[`lr| @[`lr| @[`lr| Y\lrtu{| @[`lr| @[`lr| @[`lr| @[`lr| @[`lr| @[`lr|. rr$DFGHRTrrr @[`lr|. rr$DFGHRTrrr:J J J#&*->247|89:u>wyJ{>|7}JrrrrrrrAAAAAAAAAAAAAAAAAAArAAAAAAJJ77'77'J'JJr"##&*24kmopy}"##&*24kmopy}"##&*24kmopy}& ^^$7A9;<@=?lr|@@^^^& ^^$7A9;<@=?lr|@@^^^> UU$U96:0<-?6DFGHRTmoy}UUUUUUU-U-U> UU$U96:0<-?6DFGHRTmoy}UUUUUUU-U-U0 ;#&*24759,:|<;?,YrZ\|klm;o;pry;|};;rr;;;;;;> UU$U96:0<-?6DFGHRTmoy}UUUUUUU-U-U> UU$U96:0<-?6DFGHRTmoy}UUUUUUU-U-U0 ;#&*24759,:|<;?,YrZ\|klm;o;pry;|};;rr;;;;;;& ^^$7A9;<@=?lr|@@^^^0 ;#&*24759,:|<;?,YrZ\|klm;o;pry;|};;rr;;;;;;& ^^$7A9;<@=?lr|@@^^^& ^^$7A9;<@=?lr|@@^^^> UU$U96:0<-?6DFGHRTmoy}UUUUUUU-U-U:J J J#&*->247|89:?EHIKNPQRSUYZ[\^klmoprtuy{|} 8DFLTlatncase&case,liga2liga8sups>supsD,>B      @ LO,{tu CjqvIxxtP`KtyPLJz  &   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ardeixpkvjsgwl|cnm}byqz`T@ ~1DS[a~    " & 0 : D !"!&"""""""+"H"`"e%&i 1ARZ`x    & 0 9 D !"!&"""""""+"H"`"d%&i{uq[H$I޸ޡޞ:ڜ`T@ ~1DS[a~    " & 0 : D !"!&"""""""+"H"`"e%&i 1ARZ`x    & 0 9 D !"!&"""""""+"H"`"d%&i{uq[H$I޸ޡޞ:ڜ-(8<@J@GBhf[[ Q CQ D@?($#-$ +>32#'.54>54&#"#"'4632#"&!!7!!9DO.?gI)-60#z -5-I9)8(  c>0((0>22cu&#@[87P;+&%ia /(&.8'3</@)(?g6, !&@#Q CSD +#>74>32#".F uF!-."".-!-UV\44\VU->."".-""- *@' BQ D   $+#"&=!#"&=$"%$"%ߛ""!ߛ""!6<@H@E  Y  C Q C D@?>=<<6431.-(&##!#!+#"&547#+#"546?3#7>;>;3323+32%3# Nqt 0M+j'&v -NMv&%jjX ]#( 7KGk X G 7KGbf8CN@J) ?BAK PX@$jhfkCDK PX@$jhfkCD@$jhfkCDYY#'#%+.'7632.54>?>;#".'+4.'>w?=+A\Dg>w]9B|o@&g30 %6I2]@~c>Fu"@":N,`JsP)5H)WHkG" aKN&1/1KoRSxL Q;@"!2IlO_S,A0#2Oh*?1%-DUZ'1EYKPX@'[ [SC S DK PX@+[ [SC C SD@/[ [ CSC C SDYY@ VT((%#&((($ +#".54>324.#"32>>;+#".54>324.#"32>;`{A8^C%6]}F8^C&$1(G4$1'G5w | ~:`|A8]C%6]}F8]D%$1(G5$1'G6xcj7)MoFck8)NpH2H."JsQ1E-!GqU  ci7)MnFcl8)NpH2G."JrQ1F-!Hr9BN@;LK.&BKPX@*hSCS CS D@(hSCS CSDY@IG20)'#! BB+2#"'.#">7>;#"./#".54>7.54>3267FrR-e)<)3R; /2B)6w[G `^Rb65]}H'%9iq#=T1_Fsr,Nj>!8-&C[49x?gBGs` zWf1[QOu\ B?Rj>8W<VF> @ BQ D $+#"&=$"%ߛ""!zS  (+.547* Q*;& UuG JrN)JC .VS / r  (+4.'&546? '.547>9) R);& TuF IsN)1IC /WT. ra6C@0,+'$# BKPX@ kD@ jaY@ 66+7>7'767&/7&546?3>?'.'i !$$$3T  # 2a!  dIefIe  ! dIe fHd  sA .@+jkMRF +!!#!7!5f55i6SQ2$@ ?S D"+74632'&54>7#"&2A6.1F- *' 4A{/B'3-a_Z&  &5E*Ea<@MQE+!!s8-'@SD($+74>32#".-"--""--"n."".-""-. @kD#"++>;]:I4 I "!Oj',@)SCSD'' +2#".54>2>54.#"_sAb~`sAb TqB-Le8TqB-LeIےkIۓJkYxj0Yxi0*@' Bh CR D$+7!7#"&/3!!6{,֌M Kq/J4;@80 BhSCQ D-+'% 44+2>3!2!7>7>54.#"#"&/>Sf99bJQ)R&HIrO)#>U2p% # Wc/ZR[~Cx  "5;)AusxE6R6ufbf4]XCU@R? Bhh[SCSD<:64.-,+#!CC +2#".'763232>54.#7>54.#"#"&/>Tb6*MmCz{VjdjBP,B\ARW.Nf">T2r& # Xc.UxIOyZ;#pl{B.\_:W:8Zr;0Q;"{5P5vebf4-f'@$ B\ C D!#+3+#!"&/3>7!./"+ b{W79DF.@@=,+Bh[Q CSD(#&(""+#!632#".'763232>54.#"'!<379so\ii4]u?p_N=/C_CSd7$HnK2sDgM$/9dQ~͐O)6J%8eV9]C$h022@/B[ CSD/-%# +2#".54>7>;>32>54.#"Oe:Tvbl99W<3.%7$Dd@Oa6'Ge>O^5l2`WoPwy}E3,$)!;cH(5^L=cE%8_~$@!BQ C D$'++>7!"&=7  'D-+)uR>3GD@AB[SCSD54! ?=4G5G+) 3!3 +".5467.54>32'2>54.#"2>54.#"cr>aaHiZe6t|QcN~Z0-Lc5Bz_9$FdQqG :X;HoL'9Y3^Q)&bXq@4[{F-#uiw?.RtF@Z9$LwS5W?#4Sf3-N;"-Lh:+P=%w12@/B[SC D.,&$ +".54>32+>74.#"32>5K`7Rp^h8;T6c0.=P%D_:I{Z3xO~Y0M0\TiN;jXH}vvB<6-/:_D%2Y{Ju5Zv-';K$PX@SCSD@[SDY((($+74>32#".4>32#".-"--""--"d"--""--"n."".-""- ."".-""-.,D ?K$PX@SCS D@[S DY@ )'"+74632'&54>7#"&4>32#"..A6.1F- *' 4Ai"--""--"{/B'3-a_Z&  &5E*E."".-""-W(+6#/+-   '0!@YMQE+!!!!Z:X=Ѓ}X(+ 7>7%>7.'%.54>7/+Z|o   '0n%95@2BhfSCSD(&#*$+>32#7>54&#"#"'4>32#".!KWc8FqP*/HWO= %w 5LWI1_Q8R;'  !-."".-!4(*Je;TvW?;@+0JA>H[=NZ$."".-""-MMTdf@c [ <Bh[  [  [OSGVU^\UdVdLJ@>9731)'TT +%"&'#".54>3232>54.#"3267>32#".54>32%2>7&#"FR?H0G. ?[wT?[)!3aK.DzelPvL  k_0 3HR_ɥu@O؊םYu3WC( GrI9H $@!BZ C D# +!#"&'!+3!.'N %> ^zQB&&Cae*=@: B[S CS D*(" !+3!2# !2>54&#%32>54&+aph2%JoJGy?OxP(QyQ(|-SwI@tbLpcxB*NnE_q+MlAggd/D@A BhfSCSD'%"  //+%2>32#".546$32#".#"BfN7) A^̍KtL|fS$@(EmWtʔU:g ' Qfq\䉻6{2F+N (/(]o{Ba= @S CS D!(!$+#!!24.#!!2>=qՔP7g]Ό2xƎO1vZlyA[aA (@%YQ CQ D+!!!!!!.<=uϱ/aA "@YQ C D+!!!#!.?L/d%:G@D& Bh[SCSD20+)" ::+%2>7#"&50>17!#".546$32#"'.#"4ZOI$' C6sRӖQsSnY%< 5KjK{͓R;l D O':']芹3z2D(N  )%^q~CaE @Z C D+!#!#3!3QEPOOr}@ C D+!#3=QKPXBBYKPX@ CSD@h CSDY#%"+#"&'7>3232>736^0 !+4\J3 um"N~\r% &@# B\ C D'(% +3267>;#".'.+#3B#-,%# '+QQ"  #Y  <naf@ CR D+%!!3/7av"&@#Bh C D!6(+67>;#>7+"'#324 3 /.['*' g#.~++. {aE@B C D!+2>73#"&'#3r j^ ` )gHd)@SCSD(((&+#".546$324.#"32>4_kӕOrӕO8g]vƎP8g]xƎO2zڹh8^扷3|_m|D_m|C^ri/@,[S C D !+#!2# 32>54.#nBrm6JυtJUX."DhE6dVqM4]L:\A#d0P BKPX@SCSCD@kSCSDY(((%&+#"&'#".546$324.#"32>3^R!"56q<ӕOrӕO8g]vƎP8g]xƎO2yظ4w^扷3|_m|D_m|C^rU#7@4B[S C D#",!+#!2#"'.# 32>54&#vJyrm54bW 51 "%/DUY-Y0YNWwS&(0WwGms ==@:=BhfSCSD;9(&#!#"+#".#"#"&'7>3232>54.54>32 &;T?@dE$0NeheN0FtAB,DdKEoM*0NcicN0@xln9#)#(E\54G3')2JhJfPeVY -7-,NmB7I2%&0JlOX|JTI{ @Q C D+!#!7YW$#@  CSD +%2>73#".5473vPeA kjc{ow>jk'Ko>mZi{ӛXHj-/i&K|Z1|W@B C D, +32>7>;#|%7 M**L!g,!@' B C D,> +32>7>;2>7>;#.'#  $+  ' / ( < : :gO&&@B C D'"(!+ 3267>; #"&'+ l  z Q$l q $y@ B C D,"+#32>7>;GG  } !=;^44>$@!Q CQ D+!!7>7!7 " l7< l; !W'@$[OQE!#+!+32!WřC  lq @kD# +32#"&'lI +iH2"9" )'@$ B[OQE!#+!!7>;#"&57X ĘC80@ Bk D+!+3#"&'.'+>rg z`+,+X@MQE+!7+ttM @kD  +2#"&' kc  0+^@ BK"PX@SCS D@SC CSDY@ $!++*' +!#"&57#".54>322>7.#"0\#$S]f732#"&'#"32>54&OX&X`h6"?YmFQ* 0b[P &j74\L<)V4=eF'R_6D?Au32#".#"32>3234]^e:X[/Mrd38 +A3E{\58Q6-F6)!,9L-eG'!65*s@ BK"PX@CSCS D@!CSC CSDY@$"** +!"&57#"&54>323%2>7.#"#&Zck7"?YmFJ{+E90a[O!&j6OY0V$AjK)R^6:6-?;iV 5,^Yw};q*9b@ 0BK PX@hSCSD@hSCSDY@ ,++9,9*&%*+32>32#".54>32%">54.q6uv0K;-& ,3afo@W`4!?[uQMpH#?jR:d #8BoYB  #75K2:k^NxW2,DRB4[{G19B$' ?#g@ BK2PX@"SCQCQD@MWSDY@ ##T%#++'.5737>32#"&#"3ve.KFd AcI>3  +I8& aKW NbW]0\8ZA];K^@9$BKPX@+ [[CSCSD@.h [[SCSDY@=<[YSQEC32.5467#".54>32!2>54&#"4&'.#"32>0"(")1)BzmWe7RY$G# &^<:eL,5fbnQ~ ~6R9YN6R8W 6_*RxN&yoBmM+2PD<32#>54&#"OSOes|LL=B-_ZNATvy+{%RP1ZN_GK PX@SCC D@SCC DY@  +##".54>32zz#,,!",,# >-##-.##/g(Y BK PX@SCCSD@SCCSDY@%#U%+#"&'7>323267#".54>32-LiC#2 GE #-+!"+,#=iN- ` IQ@>-##-.##/N0@-B\CC D%(%!+3267>;#"&'.+#jOy 0 "; Ws  X@C D+33X?G0Z@  BK"PX@SC D@CSC DY@00&%$$! +332>32>32#654&#"#>54&#"GzY<KcgbLhpoLL2;+VPEAM/;0YOD?<~2{1(KG+S{P0GD0[RGP@ BK"PX@SC D@CSC DY@ &$!+332>32#>54&#"GyY<Qmq}LL=A0c\O:<Ć*{%RO4_S7#NK PX@SCSD@SCSDY@## +%2>54&#"".54>32IxT.nhJwT.mYSd8PnSd8P}P_O_9ldb9lcc+@BK PX@SCSCDK"PX@SCSCD@!CSCSCDYY@#!++(&!+32>32#"&'"32>54&Y<&Zcl8"?YmFK|*60c\O &k74\L<)VM5#".54>322>7.#"p ;#PZb432&#"GzY AY** /,a38 * 99@69BhfSCSD/#%/#"+#".#"#"&'7>3232>54.54>32 !/D0-J6>^m^>7gZa/, 0I81O7>^l^>3`V[2S ,;!/8)&:ZHFa:E6D #2C&3<(#7XI@w\7=4_>0b+BK2PX@#jhQCSD@!jh\SDY@ %#(+&+74>7#"&54>?>;!!32>32#"&?q K^, =/)( %0}?ap$:/ 9)2 31 U+1j`#LBK"PX@CT D@C CTDY@ ##*!&+32>73#"&54>57#"&5467bL=B.a[N?zX"Qjq}L|$RP2\P "("Q*K@BC D, +32>7>;#K :t%J$$I& Q. @'BC D*!,< +32>7>;2>7>;#"'.'+Q] Jq W{ t#A A#p#B! C# "! R"@BC D(")!+32>7>; #"&'+h    !   /+Q@ BCD,"!++32>7>;<)  @)*+Y@QCQ D+!!7>7!7!P 6  K#&J #ߌ1YE7@4&:B[[OSG=;303++4𑯎.54>;+";2#".54>85 JI-YV1  'B/"3;5@#C= 2EfC" & 4Bhw|575ai7MEoQ;?<MgA![?;2>5<&454>7.54>54&+"&54>573285 JI-YV1  'B/"3;5@#C= 2EfC" & 4Bhw|575ai7M EoQ32AI%Ef@4f_V$AI%EeA4f_VeUFCpP, '!TGCpP-!'! !&@#SCQD +>73 4>32#".C  hB."--""--"-UW\45\VU-."".-""-&/8@%BK PX@.jhfkSCSD@.jhfkSCSDY@ ##'#+.54>?>;#".'>32+R`4Mф"@-R}04 +=*@[?* '!S`i6!@tjZ]0 Dq`~מ\ ?1< "<#6&Dv>?@<+Bh[SCS D&&%#%&" +#!>3!#!7>7#7>;>32#"&'.#"!zY 60<  ;#9+$q! PmT{X9K#2H4AkQ3 Kj*I p /C..F ^zF&B[5, 0$+OpEF+`#7?@< !B @ ?WSD42*((+467'7>327'#"&''7.732>54.#"![,h:9f+Y"![,h99e,Z!#>Q//S=$$=S//Q>#9e,Z"![,g:9f+\!![,g:.Q=$$=Q./R>##>R~"8@5 B Z Y C D"! ,! +!32>7>;!!!!#!7!7!6ʐ  _ "6 V '' V p'!:; =cicAci5@YQD+3#3#;FVA@>FTL;!BhfWSDDB+)&$#!+#".#"#"&'7>3232>54.5467.54>32>54.'R!/B0/K6DfvfDY_%-6f^a00 !0I:2O7)BUYUB)ag%.3aW[/:Zn3:26Ug1E9.>".A88JdH[)!U9J`7D6B "3E))<0(*0?R8Y'"X>AvZ5>6/B82V51D70#P^'@S D((($+#".54>32#".54>32? )(() g))))((**((**]+Ga@ BK PX@5h f[[ SCSD@5h f[[ SCSDY@\ZPNB@42(&++ +2#".54>32#".#"32>%4>32#".732>54.#"; <9tbs?Dzbm9. 2M:GpP**Kg>?V9!.4`ee_44_ed`4e,QsXXsR-cXsQ,@BIDzdeyCC8A -TxKMyR+e`44`ed`44`eYtS--StYe.Sv?-9L@I!Bh[ WSD/.32.9/9%# -- +"&/#"&54>?6454&#"#"&/>32'26?.04AR%Vj(0"0$6xD,D//.G$ B\9*H 1  ED(K;&& .6 (2.4G(P&#m*"%%(+774 o ;]4 o ;      >=K PX@_MQE@kMQEY+!#![4$9^ a<@MQE+!!s8^3IV>BK PX@/h  [ [SCSD@/h  [ [SCSDY@44VTLJ4I4H)!*,,& +4>32#".732>54.#"#!2#"'.#'32>54.+^4`ee`44`ee`4e,RrXXsR-c焄b kj ! Ps8M/+F4e`44`ed`44`eYtS--StYee|}z^ . r(:&%8$pA@MQE+!!~Aq''@WSD((($+4>32#".732>54.#"3XvDEwX22XwEDvX3}6I**I66I**I6hCvW22WvCBuW33WuA*I66I**J77J3PK <@9jhZMQE  +!!#!7!!!/e--j/Dr{$d-9@6+ Bh[SD(&#! --+26;2!7>?>54&#"#"&/>`m0?"2* 6(6**A!CddS,HA<  *  89:-0+2 ji|d:S@P6Bhh[[SD31.,('&%:: +2#".'763232>54>54&#"#"&/>.K5980Nd48Q7" : +!"5%FV [S5,2=@5HWd->$-E7<]?!1G/!%011Y=>,-.+ 4P4 @kD #++7>3f" %2@/BCT CD%%'%!&+32673#"&=#"&'#"&5<7\SVQF=]|gFPA^#U %Y  RYJB lHC/+$H k7*@'hiS D+##!#".54>3ܵ붝j]i9Hq77]2Z~MZtC@OSG($+4>32#".)67((76)Q8((86))6w KPX@  B@  BYK PX@^TDKPX@jTD@jjTDYY@ +232654&'73#"&'76E(+GB:k JC!;Q0&B (# R?.$9'5z^N BK2PX@jjQD@jjMRFY$+37#"&/733!6 y   hNy u,\ 6]<!)@&WSD!! +2#".54>2654&#":]A"0UxH;^A#0Wy ZYA?2E+@%Ea;37#"&/733!>73n Ujw/F1!Gu6 y  hNy uI  >] [,\ 6],\ 7Hb@_B;5Bhh   Z [  CT D HGFEDC?=9820,* 7 7#" +%+>;26;2!7>?>54&#"#"&/>%37#"&/733!/F1!G`m3C$2* 6(6*/=  +6 y   hNy u5 [IdS-LC>!8*  89:-04) ji<,\ 6]zTZ~@{P " / X B  h h  h [  [\ S C DZYMKGEA@?>8631+)TT##!#+3+#7!"&/3+>;%2#".'763232>54>54&#"#"&/>>73 n Ujw/F1!Gu.K5980Nd48Q7" : 46"5%FV [S5,2@ 15HW I  >] [->$-E7<]?!1G/,2%011Y=>,-0% 4P4c,u';5@2BhfSCSD(&#,$+#".54>?332>324>32#".u!LWb8DoQ,/IWN: $u 1HSF/-;!7S<'  !-."".-!4''HgAQsS<56$-B:8CV;)?+$."".-""-&$ O&$ _&$ O&$O&$ O-&$P9@6AYYQ CS D# +!!!!!!!+!L*: &$@dJKPX@9= HB@9= HBYK PX@0hfSCSC SDKPX@0hfSCSC SD@7hf hSCSCSDYY@FD<;64/-%# JJ +232654&'7.546$32#".#"32>32#"&'76(+GB0r~BtL|fS$@(EmWtʔU:gUBfN7) AWߒJC!;Q0&B (# v dڀ6{2F+N (/(]o{B ' Q^o:?.$9'5aA&( $aA&( $aA&( $aA&( $V &, &, g&, &, E!,@)YS CS D!%(!+3!2#!#%4.#!!!!2>SPԕOpQ{7f]>\ ?2xŎN Z㈷vlyAn[aE&1d&2 d&2 d&2 d&2d&2 l9W  (+  ' 7 9|8fnPg0]d]e[]Z0%1=g@5*)# BK PX@kCSCSD@jkSCSDY**'(%&+#"&'+.546$327>;.#"%4&'32>4_kaCm=JMRrhEY `EJ+)2OvƎP$"<0wHxƎO2zڹh82/ T錷3|;6p Ta<.1_*X;&'^$&8 $&8 $&8 $&8 y&< < ++,@)\[ C D"( +32+#3 32>54&#rn6J΅!3JUX.6cUqLa4]Lt3&P}@ JGBAK,PX@(hSCSCQD@%hWSCSDY@LKFD=;%# PP+2#"&'7>3232>54.54>54.#"+'&573>Y~Q&/FQF/+@K@+>iOY10 "-@0*G3.DQD.1JWJ1-I4>mU: l.KFn(^6Se/D`H638&#/)+=XAV_3E6B "6I*0?.(4H8>XE:@P8;0CtUKW!M\K0&DCi0&Dv+0&D"0&D"0&Dj"0&D6GUbG@ E?"BK PX@5hh  [ S C SDKPX@5hh  [ S C SDK,PX@?hh  [ S CSC SD@Jhh  [ S CS CSC SDYYY@&WV\[VbWbQOIHCA<:75/.(&  GG+232>32#"&'#"&54>7>54#"#"&/>32>32>7">54&]W8wxGc>(!)!7QP`UT^%32#".#"32>32#"&'76(+GB2JqL'Mrd38 +A3E{\58Q6-F6)!,/TTW1JC!;Q0&B (# y CkT{hGDC Kf>eG'!63H-<?.$9'5;q&HC;&Hv;q&H;&Hj=&C_u&v"^&/w&j<1E6@37-B10@[SD32=;2E3E+)!+.54?.'&54?7#".54>32.'2>7.#")`7%XFqQ^FȂRe8E}ia0LL!AoX> &32#"&4>32#"&B&2'&21;X&2'&20<2&(1$>f2&(1$>%)4@32#"BK PX@!CSCSCDKPX@!CSCSCDKPX@!kCSCSD@!jkSCSDYYY@+**4+4&$+"'+7.54>327>;&#"2>54&'|Z$:C(+Pn}[" Z'+P8NJzY1I{Y1 F7=15Xb@.5WcYBZ-LsMg,K ,`&XC++`&Xv++`&X++`&Xj++Q&\v++%,p@ BK PX@!CSCSCD@!CSCSCDY@$",,(%+3>32#"&'#"32>54&%ݰY&X`h6"?YmFK{+.'0b\O!&k74\L<)V4=eF'R_6;6&!.' Y0LRVB N %_-&(   @F:?n)^g !*3 ' QB&&C04F(KPX@&;BK"PX@&;B@&;BYYK PX@#SC SCSDKPX@#SC SCSDK"PX@*hSC SCSD@.hSC C SCSDYYY@65?<5F6F1/('$"44 +2#"&54>7.57#".54>32#32>2>7.#"> Y0LR*:"$S]f7G Y0LRVB/<=ui-&(  @F:?n) !*3 ' ;qAPKPX@G2B@G2BYK PX@*h SCSCSDKPX@*h SCSCSD@1hh SCSCSDYY@CBBPCP><0.)' AA +2#"&5467.54>3232>3232>">54.I Y0LRI9U_2!?[uQMpH#6uv0K;-& ,MT+$(  ?jR:d #8 @F::f(324.#"32>;=qZuFhKkS h/ZSmI0[SmHr~\ㇹ6~&Ge?j|Dck|Cb.4FU@ L2 "BK PX@$h S C SD@$h S C SDY@ HG65GUHU><5F6F0.&$ 44 +232>32#"&'#".54>32>2>54&#"">54.AhJ'8\~ym0K;-&,2afp@i'E΁QzQ)Ukk#?IQ}U+]aN|X/.JH;fP8 h&'="?X5)LC;0& #74L1tsny;eHXe[ZfvNqsLy/VB( .YQ3:A!*! &6 #&Vv++ &6 ,&V~++y&< < ++&= 8Y&]v++&=8Y&]++&=8Y&]++i'6@3 BYSCSD''#"+#763>7'.546767376$3#"!2 :.UH8*0 /UI9+G!˹[7:^E  ſ_;^E}Q@Bk D, +#"&/.'+3r d w q@Bk D( +32?>;#qx d  spAq @W D +".5467332>73r>V6y4B'6#z&Eg!:M- 3?)9!6aI+@SD($+#".54>32#.-""-.#:-""-/##/kJ=KPX@WSD@[OSGY$&($+4>32#".732654&#" 7H()I8 8I)(H7 d6/-77-/6#*D22D*)D00D),88,-88/t YKPX@ B@@ B@YKPX@ SD@jSDY@ +2#"&54>732>R Y0LR.@%W-&(  @F:"@:2 !*3 ' hQK*PX@WS D@O[SGY@ +273#".#"#>32Ai!2B% 5-) (j"3A%!4-()X/M7#-,.N8#) #@ SD   #++7>3!+7>3H"S   !YBK(PX@SCS D@SC CSDY@! 6##++#!#"&'7>3267#7>3"|lkOz=<;N D#u}w H ?C?  @MQE+!!}o@MQE+!!7}(+.5467j^/ ! %J%dL  09@"6 (+'&5467>54&'&547pj^0 ! %J%dL  08@#6 (+7'&5467>54&'&547j^0 ! %J%dL  08@#6 1(+.5467.5467j^/ ! j^/ ! %J%dL  09@"6 *%J%dL  09@"6 1(+'&5467>54&'&547%'&5467>54&'&547yj^0 ! j^0 ! %J%dL  08@#6 *%J%dL  08@#6 1(+7'&5467>54&'&547%'&5467>54&'&547j^0 ! j^0 ! %J%dL  08@#6 *%J%dL  08@#6 %,@)  BCSCD$&$"+>3632>32! #"&'!,*?G#)33#P$KIF &!6H0+u6/, ) D B9E@B  )!("B[C SCD98'%#&$" +>3632>32!!#.'#"&'#"&5<>7!!,*?G#)33#P$KIF &"Pj.*?G!0+O$KIG&!kP/, '(v://  (,KPX@ SD@OSGY($+4>32#".:eLMe;;eMLe:SMe;;eMMd;;d-,';@SD((((($+74>32#".%4>32#".%4>32#".-"--""--""--""--"!..""..!n."".-""-."".-""-."".-""-Z'1EYmKPX@+[   [SC  S  DK PX@/[   [SC C  S D@3[   [ CSC C  S DYY@~|trjh`^VT((%#&((($+#".54>324.#"32>>;+#".54>324.#"32>%#".54>324.#"32>;`{A8^C%6]}F8^C&$1(G4$1'G5w | ~:`|A8]C%6]}F8]D%$1(G5$1'G6):`{A8^C%6]}F8]D%$1(F5#1'F6xcj7)MoFck8)NpH2H."JsQ1E-!GqU  ci7)MnFcl8)NpH2G."JrQ1F-!HrRci7)MnFcl8)NpH2G."JrQ1F-!Hr(+74 o ;   w(+'&54767&'&54?5  p!;{   c @ C D#"+'+>;?/F1!G5 [*B[@X 4 Bh  h [   [SC S  DBA?>=<861/"##%%$+3>32#".#"!#!!#!32>32#".'#7367#T!wp;C  &6J3MoT0dRoI. ASގqv>  ̎LcWB  4f`7#H&6-6-DeqRҀcJGI6%B@?BhS  CS  D%%!4( +>7>;#7+"'#32'###7  fGk. }.iGg 54.#"!"&546767!7.54>32!5Ti<5aReH*Lj@4/LxR,0X|`zȎNAwf~ (JxpZ_0BzMyY:O%TvTatQ+Lprěla A3HB@?"Bh[SCSD54?=4H5H#*++$+>32#".5467>32>7>54&#"#"&'2>7.#"'JMT0ItQ,n݉HwT._g^" e\'C7) :qdU .I5K{\: ]9*8lc?!/X~P#sʔVRQ"=9 7or-S@'>mWgp @ B CR D+)3!.'ԩ   9 !9 $@!Q CD +##!##7Ȳɱȼ]]$@!BQ CQD+!!!!7>7 &5<7RA ! ;4;A ^@MQE+!![Ll"@Bj[ D,'!+!##"&5<>7!2>7>;p"Ne [n  [ A 7Q=';OL@IK-B[  O  SG=<)(GE32>32%2>7.#"!2>54.#"{3P?1DNX35[C'7\xB3O@2DMX35\D'7]y!<86$,4!&A1$1S%B1$1!;86%+4!8K))K8!(KhARi=!9K))K9!(KiARi<5E''E4!32#"#"&'7>32>7)#A*\nOg}F D 6Q=,CWnuf_- L :^B7^@[0!/"B[[ O[ SG42+)&$77  +2>7#".#"'>322>7#".#"'>32@80% (u=4c_\-90% )wB4d^\81% 'v=4c_\-81% )wB5c_[W  l0."(" i31!)!  m/-!(!  h31!)!}kK PX@)^_ ZMQE@'jk ZMQEY@  +!733!!!#7!7!7!}w5}PwSʃZP @ @MQE+!!3-2/*>yz  z{ iP@ @MQE+%!7!7>7%>7.'%.54657n>2/aPz  z"@ BMQE+3 #>7 &'|y|  54&&EF,#& ~-KPX@ kD@ jaY@ +3v 0>'s@  BK2PX@(SCQC CQD@MWSC DY@''W%#+#!+'&5737>32#"&#"yk}f.KFc( Izk''#  SzU1 `KX #O8]n=Z $HnK5>!@ BK PX@(SCQC CQDK&PX@(SCQC CQDK2PX@,CSCQC CQD@$MWCSC DYYY@!!#!%# ++'&5737>32;#.#"3wg.KFb( BnaG5w-_+uaKX !Q7TpA Z$ 7G25K0PX@ QD@MQEY@ +#2~mQRU   @ja  +2#"&/  '@OSG((($+#".54>32#".54>32P%##%X$$$$$$%%$$%%(@MQE+!!4f  @ja #++7>3  f  @Bja& +#"&/+73ǃ r   kk  @Bja !+#'327>3ƒ r  kk(@%jOSG +"&547332673syoNOp,Ie^^ c><4T< *@OSG($+#".54>32"-,!!,-",!!,,"",V-!@[OSG$&($+4>32#".732654&#"4D&'E44E'&D4Y6/-77-/6{'B//B'&@..@&+99+-881@.O[SG +2673#".#"#>32)^.>% 82.'a.>%!82-|*%*G5 -%*H5  b +@(OSG   #++7>3!+7>3(S'])  } @kD  +2+ +$ <] 9^I D{_< ʓ^pӡ - VO'-{6GZ9(z(s2a-O/]-DhR-.++}Madia+aaEdpa61raaoadhrdr ?{?|Zy|(!l(8M0Ob<5;]?$O_gNXGG7 0G _`KQQZ(1X(9{~X;8^=]xka=^8p38;k#8kwd+a+a+a+a6V66g6Eoadddddl0????yhI3000000b<;;;;=_"/<G77777s````Q%Q0db<+a;_YLoaGd.    y|Z|Z|Z8Q8q8p8888/8h8x,,B-OZVVwA*/]+A YxL={+Z+i>G>8G8U8888f888*8888gP`  UU$U96:0<-?6DFGHRTmoy}UUUUUUU-U-U U    U $U 96 :0 <- ?6 D F G H R T m o y } U U U U U U U - U - U # & * 2 4 D F G H R T k p U    U $U 96 :0 <- ?6 D F G H R T m o y } U U U U U U U - U - U  ;#&*24759,:|<;?,YrZ\|klm;o;pry;|};;rr;;;;;;   ^^$7A9;<@=?lr|@@^^^  ;#&*24759,:|<;?,YrZ\|klm;o;pry;|};;rr;;;;;;6  6 6AA":#$&*-i24DFGHPQRSTUVXYZ\]kl6mopr6tPuPwy{P|6}66A66AA## # # # ##$#7#9#;#<#=#?#@#`#l#r#|##################$J$ J$ J$$#$&$*$->$2$4$7|$8$9$:$<u><w<yJ<{><|7<}J<r<r<r<r<r<r<r<<<<<<<<A<A<A<A<A<A<A<A<A<A<A<A<A<<A<A<A<A<A<A<<<<<r<A<<A<A<<<A<A<A<<<<J<J<7<7<'<7<7<'<J<'<J<J<r=="#=#=&=*=2=4=k=m=o=p=y=}==============>#>&>*>2>4>D>F>G>H>R>T>k>p>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>?J? J? J??#?&?*?->?2?4?7|?8?9?:?247|89:247|89:247|89:247|89:247|89:247|89:u>wyJ{>|7}JrrrrrrrAAAAAAAAAAAAAAAAAAArAAAAAAJJ77'77'J'JJr $79;<=?@`lr| @[`lr| @[`lr| @[`lr| @[`lr| @[`lr| Y\lrtu{| @[`lr| @[`lr| @[`lr| @[`lr| @[`lr| @[`lr| rr$DFGHRTrrr @[`lr| rr$DFGHRTrrrJ J J#&*->247|89:u>wyJ{>|7}JrrrrrrrAAAAAAAAAAAAAAAAAAArAAAAAAJJ77'77'J'JJr"##&*24kmopy}"##&*24kmopy}"##&*24kmopy} ^^$7A9;<@=?lr|@@^^^ ^^$7A9;<@=?lr|@@^^^ UU$U96:0<-?6DFGHRTmoy}UUUUUUU-U-U UU$U96:0<-?6DFGHRTmoy}UUUUUUU-U-U ;#&*24759,:|<;?,YrZ\|klm;o;pry;|};;rr;;;;;; UU$U96:0<-?6DFGHRTmoy}UUUUUUU-U-U UU$U96:0<-?6DFGHRTmoy}UUUUUUU-U-U ;#&*24759,:|<;?,YrZ\|klm;o;pry;|};;rr;;;;;; ^^$7A9;<@=?lr|@@^^^ ;#&*24759,:|<;?,YrZ\|klm;o;pry;|};;rr;;;;;; ^^$7A9;<@=?lr|@@^^^ ^^$7A9;<@=?lr|@@^^^ UU$U96:0<-?6DFGHRTmoy}UUUUUUU-U-UJ J J#&*->247|89:|LrF(HxXd`(t(.lR@f|@@ !!l!"&"l#<##$,$F%%%b%&&&&'2'^'((Z()")**++ ++$+0+<+,n,z,,,,,,,--*-6-B-N-Z-f-. .,.8.D.P.b./R/^/j/v///0111111112 22222223L444*4<4N4`4456|667"788P8~889~:8:D:T:`:p:::::::;8;h;;;;>H>>?4?@@:@AAABBCCxDD0D\DDDEEFRFFG0GpGHHHIIJIdIIIJJ:JzJJKb"/n n) ( 0+ C R . 2F x: T h  p R|  P  `4 0   0  d  . 4Copyright (c) 2010-2013 by tyPoland Lukasz Dziedzic with Reserved Font Name "Lato". Licensed under the SIL Open Font License, Version 1.1.LatoItalictyPolandLukaszDziedzic: Lato Italic: 2013Lato ItalicVersion 1.105; Western+Polish opensourceLato-ItalicLato is a trademark of tyPoland Lukasz Dziedzic.tyPoland Lukasz DziedzicLukasz DziedzicLato is a sanserif typeface family designed in the Summer 2010 by Warsaw-based designer Lukasz Dziedzic ("Lato" means "Summer" in Polish). It tries to carefully balance some potentially conflicting priorities: it should seem quite "transparent" when used in body text but would display some original traits when used in larger sizes. The classical proportions, particularly visible in the uppercase, give the letterforms familiar harmony and elegance. At the same time, its sleek sanserif look makes evident the fact that Lato was designed in 2010, even though it does not follow any current trend. The semi-rounded details of the letters give Lato a feeling of warmth, while the strong structure provides stability and seriousness.http://www.typoland.com/http://www.typoland.com/designers/Lukasz_Dziedzic/Copyright (c) 2010-2013 by tyPoland Lukasz Dziedzic (http://www.typoland.com/) with Reserved Font Name "Lato". Licensed under the SIL Open Font License, Version 1.1 (http://scripts.sil.org/OFL).http://scripts.sil.org/OFLCopyright (c) 2010-2013 by tyPoland Lukasz Dziedzic with Reserved Font Name "Lato". Licensed under the SIL Open Font License, Version 1.1.LatoItalictyPolandLukaszDziedzic: Lato Italic: 2013Lato-ItalicVersion 1.105; Western+Polish opensourceLato is a trademark of tyPoland Lukasz Dziedzic.tyPoland Lukasz DziedzicLukasz DziedzicLato is a sanserif typeface family designed in the Summer 2010 by Warsaw-based designer Lukasz Dziedzic ("Lato" means "Summer" in Polish). It tries to carefully balance some potentially conflicting priorities: it should seem quite "transparent" when used in body text but would display some original traits when used in larger sizes. The classical proportions, particularly visible in the uppercase, give the letterforms familiar harmony and elegance. At the same time, its sleek sanserif look makes evident the fact that Lato was designed in 2010, even though it does not follow any current trend. The semi-rounded details of the letters give Lato a feeling of warmth, while the strong structure provides stability and seriousness.http://www.typoland.com/http://www.typoland.com/designers/Lukasz_Dziedzic/Copyright (c) 2010-2013 by tyPoland Lukasz Dziedzic (http://www.typoland.com/) with Reserved Font Name "Lato". Licensed under the SIL Open Font License, Version 1.1 (http://scripts.sil.org/OFL).http://scripts.sil.org/OFLrt  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghjikmlnoqprsutvwxzy{}|~      !"#NULLuni00A0uni00ADmacronperiodcenteredAogonekaogonekEogonekeogonekNacutenacuteSacutesacuteZacutezacute Zdotaccent zdotaccentuni02C9EuroDeltauni2669undercommaaccent grave.case dieresis.case macron.case acute.casecircumflex.case caron.case breve.casedotaccent.case ring.case tilde.casehungarumlaut.case caron.saltVV, `f-, d P&ZE[X!#!X PPX!@Y 8PX!8YY Ead(PX! E 0PX!0Y PX f a PX` PX! ` 6PX!6``YYY+YY#PXeYY-, E %ad CPX#B#B!!Y`-,#!#! dbB #B *! C +0%QX`PaRYX#Y! @SX+!@Y#PXeY-,C+C`B-,#B# #Bab`*-, E EcEb`D`-, E +#%` E#a d PX!0PX @YY#PXeY%#aDD`-,EaD- ,` CJPX #BY CJRX #BY- , b c#a C` ` #B#- ,KTXDY$ e#x- ,KQXKSXDY!Y$e#x- , CUX CaB +YC%B %B %B# %PXC`%B #a *!#a #a *!C`%B%a *!Y CG CG`b EcEb`#DC>C`B-,ETX #B `a  BB` +m+"Y-,+-,+-,+-,+-,+-,+-,+-,+-,+-, +-,+ETX #B `a  BB` +m+"Y-,+-,+-,+-,+-,+-,+- ,+-!,+-",+-#, +-$, <`-%, ` ` C#`C%a`$*!-&,%+%*-', G EcEb`#a8# UX G EcEb`#a8!Y-(,ETX'*0"Y-),+ETX'*0"Y-*, 5`-+,EcEb+EcEb+D>#8**-,, < G EcEb`Ca8--,.<-., < G EcEb`CaCc8-/,% . G#B%IG#G#a Xb!Y#B.*-0,%%G#G#aE+e.# <8-1,%% .G#G#a #BE+ `PX @QX  &YBB# C #G#G#a#F`Cb` + a C`d#CadPXCaC`Y%ba# &#Fa8#CF%CG#G#a` Cb`# +#C`+%a%b&a %`d#%`dPX!#!Y# &#Fa8Y-2, & .G#G#a#<8-3, #B F#G+#a8-4,%%G#G#aTX. <#!%%G#G#a %%G#G#a%%I%aEc# Xb!YcEb`#.# <8#!Y-5, C .G#G#a ` `fb# <8-6,# .F%FRX ,1+!# <#B#8&+C.&+-?, G#B.,*-@, G#B.,*-A,-*-B,/*-C,E# . F#a8&+-D,#BC+-E,<+-F,<+-G,<+-H,<+-I,=+-J,=+-K,=+-L,=+-M,9+-N,9+-O,9+-P,9+-Q,;+-R,;+-S,;+-T,;+-U,>+-V,>+-W,>+-X,>+-Y,:+-Z,:+-[,:+-\,:+-],2+.&+-^,2+6+-_,2+7+-`,2+8+-a,3+.&+-b,3+6+-c,3+7+-d,3+8+-e,4+.&+-f,4+6+-g,4+7+-h,4+8+-i,5+.&+-j,5+6+-k,5+7+-l,5+8+-m,+e$Px0-KKRXYc #D#pE (`f UX%aEc#b#D * **Y( ERD *D$QX@XD&QXXDYYYYDPK!5  C2.2.0/rdoc/generator/template/darkfish/fonts/SourceCodePro-Bold.ttfnu[pFFTMfhOS/2sx`cmap_ceXcvt "fpgmY7 `sgaspglyfpeheadu6hheaA4$hmtxf]~locabk3 <vmaxpSX nameDp;Xpost6z 3prep~ AZR_<:Qc XXKX^2    ADBE "` MXSF@~@FFJ8R3*#.<>=5tFbb T7A^l,@J;DkAB&J$F2@8JiV<=HC/7R4HO*L>$H/H/t51>%Fji4`C$Gp+FFeF>0<g 7^^^^JJJJB&&&&&T@@@@I=======C7777OOOO/H/////F/>>>>H = = =7C7C7C7CA/^7^7^7^7^7,4,4,4,4@JOJOJOJOJO;*DLLk>k>k>k !>BHBHBH&/&/&/ FtFeFt2525252511@>@>@>@>@>@>8F8F8F:.&/@> =JO&/@>@>@>@>@>,4&/251* H/H467/< 42S|pE"svA/A/,4@H@Hk>7>k>A$BHBHBHFjFjFB2525118F1@P4FFOC[-COX$F4 ~1Ie~7CRTYaeoy $(.1CIMPRX[!%+;Ico    " : D q y "" 4Lh7CPTXaeoy#&.1CGMORV[  $*6BZl    " 9 D p t } ""wnl@% zsrmkZWTSROM zjbRJHE?}zuigfc_]Z   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abctfgkzrmxluiyn~ep?od6{vs}~|w,K PXYD _^-, EiD`-,*!-, F%FRX#Y Id F had%F hadRX#eY/ SXi TX!@Yi TX!@eYY:-, F%FRX#Y F jad%F jadRX#Y/-,K &PXQXD@DY!! EPXD!YY-, EiD` E}iD`-,*-,K &SX@Y &SX#!#Y &SX#!#Y &SX#!#Y &SX#!@#Y &SX%EPX#!#!%E#!#!Y!YD- ,KSXED!!Y-+++% +.& ++ E}iDK`RXYs H  B {   6D.4jlbFDT  L  V  > * r ( ,&\zt2VtTl(T0^f6Pn,4p>pz $ 0 < H T ` l !!!!&!2!!!!!!!"""""""##|######$~$$$$$$$$$%n%z%%%%%%&v&&&&&'*'6'B'N'Z'f'(v((((((((((()))))))*4*******+++ +,+8+D+,,&,2,>,J,V,b,-4-@-h-t-----.. ..$.0.<.H....////&///////0:00001 11"1.1:1F1R1^1j1v111111111112222*2333(343@3L3X3d3p3|334"4z45B566l6x66666666666777 7,787D78*868B8N8Z8999:l:;;h;>`>>?2?n?@$@,@4@X@|@@@@@@@@@@@@@A.AAAABBPBdBBBCC@CbCCCCDD6DjDDDEE0EEF:FGG^GGHJHHI IDIIIIIIIIJJJ J,J8JDJRJbJnJzJJJJJJJJJJKKKK&K2K>KJKVKbKnKzKKKKKKKKKKKL L~LLLLLLLLLMM,MPMZMhMvMMMMMNN4N>NHNRN\NfNpNzNNNNNNNNOOOO&O0O:OP.PQdQR:RSJST$TTUUULUpUVV@VVW WWX X,X>XRXrXXXYYYEX/>Y ܸ01'3#4632#"&`49++99++9-77--99S/' | FEX/ >YEX / >YEX/>YEX/>Y++ иииииии017#537#53733733#3##7##7#JUO[ThTO[ T_UgUh ^n^^n^nn@ ,G/'/&ܹܺ&9и&9&)01.#"#5.'732654.546753#?)E+AKA+VTb1h&@0U0$&+ALA+XLb4M.+>-?])!d!*>.AV + H'D&J AEX3/3 >YEX!/!>YEX/>Y!3!9 !39 +ии3ܸии ;>017327.'>54&#"&'#".54>7.54>32>71( #?-%{, 3(#DF%Y73N5&*<%JS#,=  %.C$$#").'/PD3,&; J,/ +01'3##ZM +01.5467bqqbRYQ)@-RW䎎WAWv;i`Y+A~M +01>54&'7~-@)QYRbqqbr+Y`i;vWAW䎎W@[6//9и и 01?'7737'xa N a@ttDG++GD,F^6 +и 01#53533##llhh' +0165#".54632'A/>>jh-a &/8[Q` F~EX / >Y0174>32#"&++@44@i+  +2CCJ`EX/>Y01#3{I{f8 '3KEX / >YEX/>Y (9(/.01".54>32"32>54."&54632,7Z@##@Z77Z@##@Z7)))) ++ ++ +T|QQzS))SzQQ|T+!1R>>S33S>>R1)##))##)R{ =EX / >YEX/>Yи й01%!53#5>7398O#lwwwo[ 3!CEX/ >YEX / >Yк 9017>54&#"'>32>;!:DpP,62&?O17=%2R;!&AT.?#T9cVL"/1'O& 5J.(SSS(|*-SEX/ >YEX*/*>Y *9 / " 901732654.#52654&#"'>32#"&'n O,4C,J8^M2,&@!J/k>4V>"@9,E/1)#.{ YEX/ >YEX / >Y+ и и и015467###5!533U$`}P PkO6pe~.{$UEX/ >YEX!/!>Y +!!9и01732654&#"'!!>32#"&'p I-6EA3A &,O<#)EZ1Ss'%2102 *A|w0J35R93&<!2WEX/// >YEX%/%>Y+%%/9 /01%2>54&#".#">32#".54>32:#4*<$< 5)"S$*G5%?R.1\H,.Mb5Df b '1+"&3 /L8!$0J22N8$LwTYT)->{3EX/ >YEX/>Y 013>7!5!#+D2WEX'/' >YEX:/:>Y' 9 //и//ܸ 01732654.'7654&#"4>75.54>32#".B1-7)8"#0.,#1F!+(5 9P/0M65&,  =Z:7X>!*/'( 2+2%-$%',/& G3(A.-A'-F (3 &@/.@52WEX%/% >YEX///>Y+/%9%/01267.#"32>7#".54>32#"&'<$#4c< 5)#S#*H5%?R.1]H+.Lc4Df!V#%3 '1+/M8!%0J21O8$LwTYT)."'C'"'Cty;+и/9и/01%%t ~F&tby;+и/9и/015%5%5~ b)*EX'/'>Y +'!ܸ01&>54&#"'>324632#"&'"* 0R$b<+K7 $("9++99++9!5*"  K(2)=)!0("%+-77--99m&6@? '+1+:+>+19=01%#'##".54>754.#"3267#".54>3232675&N <)/"#A\9 2!#F8#$;L)-;**T6YEX / >Y  + 01'.'###3#n    (˰˜<1n34m1YEX/>Y%9%/ %9&0132+2654&+254&+T3W@% *FH&D[560143@v9=@&>/,& JB2H/+%% Y+'799EX/ >YEX/>Y 014>32.#"3267#".70TrA?a!Q6##:+\J#9QR|?pT1BQX.3 [6N1eo Y`+T}A, 9EX/ >YEX / >Y 0132+72>54.+AGtR--QpD&?--?&&OzTT|Q(w1P;:O/b^ MEX/ >YEX / >Y 9/ 01!!3#!!^%H|{|l CEX/ >YEX / >Y 9/01!!3##l||,##MEX/ >YEX/>Y 9/014>32.#"32675#53#".,/Qn?B] Q2' 6(MN" _!l??mQ.BRW.3 [6N1eo px0+T}@ IEX/ >YEX / >Y 9 /и 013353###@tJ AEX/ >YEX / >Yи 0173#5!#3!JĘ<|||l|;5EX/ >YEX/>Y0173265#5!#".':B32:]C:84H3D'{R0U@% )DR kEX/ >YEX/ >YEX / >YEX/>Y9 9 и 01333##D֣L xdk +EX/ >YEX/>Y013!!k"K|AMEX/ >YEX/>Y+и и0133?3#54>7##/##AB?w32A21uZZtOTOOTOBYEX/ >YEX / >Y 9к 9  0133.=3#'##B8849tE6|:&25EX / >YEX/>Y 01".54>32'2654&#",:aE&&Ea::aE&&Ea:3<<33<< /X~PP}U--V}OP~X/scbnnbcsJ7GEX/ >YEX/>Y 9 / 0132+#254&+J5]E()F\4[w<;R1Q;9T6Rh3*$ND *KEX/ >YEX/>Y'+$01"32654&#".'.54>323267)4::43;;00PA0Xh&D`;:`D&^QC# nbcsscbnJ .A&P}U--V}O#FHSEX / >YEX / >Y 9 /  и 013254&+'##32Hw<;H}M4[E(@4`a0&/N:H]2'/IEX/ >YEX,/,>Y,9 ,901732654./.54>32.#"#"&'%W+3/%T3&#?X5YEX/>Y01#5!##Ô||@3EX/ >YEX/>Y 01332653#"&5@,//-swxv`;>>;oI 3EX/ >YEX / >Y 0133>73#NMı6e66e60tT!MEX/ >YEX / >Y + ии 0133>?33>73#'.'##-Y+Q)  '*R**R*(T**S)[tAAF]EX/ >YEX/>Y99 к 9к90133>?3#'.'##г?   :G  DO={33{33H@EX/ >YEX / >YEX/>Y901733>?3#ҞBBҔ&H''H&P8# =EX/ >YEX/>Yи017!5!!!825Y{YI|h++01!#3!'N@NJ`EX/>Y013#J{I{ih++01#5!!5'JNNV &EX/ >Yܺ9 013#/##vy.--.yt<\ +01!5 6nn>~=)EX/>YEX/>YEX/>Y9/! !99$%0174>7.#"'>32#'##".732675=$O|X33$I*43u@hxx &Z0&<*% !:7H**?,"&`&nr8')6+RH)!EX/>YEX/>YEX/>YEX/>Y99!013>32#"&'##732654#"HI$.K3$YEX/>Y 0174>32&#"3267#".C/Oh9;_ D77@PM>'B<-m3;dK*>aB#&['LAAL]&##Ba/#EX/>YEX / >YEX/>YEX / >Y99!0174>32'53#'##".732675.#"/$;L)+:x H&/M72.*));=`C$MC3$$C`?JDD7"#CEX/>YEX/>Y# + 0174>32!3267#".%4&#"7+H]29X:Q7"=!0*h2:dJ+f.3(> =`C$$@W3$ 81X#C`t*4.0RIVEX/>YEX/>YEX / >Yи  01&#"3###5754>32-170-6T:+K B*-s}m +J7  4-<DPEX"/">YEX%/%>YEX$/$>YEX@/@>YEX / >Y@  ии 7/ܹE1E/91и%&$'"K0132654&+"&'475.54675.54>323##"';2#".2654&#"C;#xM!&#:M*.$e  7K+ $ (,\bg*LnC0S<"--++># $=& ( 2A,-C- k #+>)  :C'B/0k))())())HeEX/>YEX/>YEX/>YEX / >Y 9013>32#4&#"#H#)1TM )-_ l^2.O;EX/>YEX/>Yܸ 01!##%"&54632OZ +77++77}0))33))0*<AEX/>YEX/>Yܸ01!#"&'73265#%"&54632OZ5YC.K +15' +77++77.-R>%i 36e0))33))0LI mEX/>YEX/>YEX / >YEX/>Y 9 9 и 013373#'#L˟IkM}> 5EX/>YEX/>Y01!3267#"&5#># &!""&^_ l o_$= EX/>YEX / >YEX/>YEX / >YEX/>YEX/>Y 9 и  0133>32>32#4#"#4#"#$n 1+!- 5*4:q >+)("/UKQ.0Q.HeEX/>YEX/>YEX/>YEX / >Y90133>32#4&#"#Hx  S8TN )-B .l^2./)5EX/>YEX/>Y0174>32#".732654&#"/*G[11[G**G[11[G*33333333>aB##Ba>>aB##Ba>ALLAALLHH) EX / >YEX/>YEX/>YEX/>Y 9 9  01#33>32#"'732654#"ۓx N(.J4$YEX / >YEX/>YEX / >Y99!0174>32373#57#".732675.#"/$;L)*A sF#/M72.*));=`C$!3XL $C`?JDDt$TEX/>YEX/>YEX/>Y9 0133>32.#"#tx %hYEX,/,>Y,9,901732654&'.54>32.#"#"&'w+W23,IYEX/>Yии 01#5?33#3267#".5}y260!Q0;R3}ms9/ j  9P1> eEX / >YEX/>YEX/>YEX/>Y901!#'##"&5332673 x !P6UL*+G&-l^22.!F9 <EX/>YEX / >YEX / >Y0133>?3#N    N&L''L&T!tEX/>YEX / >YEX/>YEX!/!>YEX/>Y!9к90133>?33>?3#'.'## g! M %H&&J#%H&&H%#G(D3%2eEX/>YEX / >YEX/>YEX/>Y9и и01'33>?3#'.'##ѡ3    ,9  1P+,PR,+R>;[EX/>YEX/>YEX/>YEX/>Y 901326?33>?3#"&'7]+1 גS   I*6G/&H$#K'%K% /G/pF =EX/>YEX/>Yи017#5!!!F )O.sNsjh7+34++  +' 9014>54.'5>54.546;#";#"& 5((5 Z`M)( .66. ()M`Z *''  V  ('+Q=N(N-93  39.L)N=m +013#낂ih7+5++'(+ ('9012>54&54675.54654.+532+5' .66. ')M`Z 5))5 Z`MJ)L.93  39-N(N=Q+'(  V  ''*Q=N4$'++ и01>323267#".#"4 T/.'#&X T/.'#'NC(*)NC(*REX/>Y ܸ01#737#"&54632p`49++99++9)-77--99` $\EX/ >Y! + + и/!и/  и / ܸи/01#5.54>753&'>77$$%#D"Q1O8 :N/Q'?C$@--AE__(AX65V?)a]Z C&*WEX/ >YEX/>Y +и  и#01%!5>54'#57.54>32.#"3#&4BpT "Y#O,07||[O6 V(/L5*'P.0$[$4$?4S*"+ (+01?&5467'76327'#"'32654&#"$Q"PIY0642YIQ"RIZ47.Zi2$$22$$2R.A 7RJZZJR-@!7RJ[ [ -55--559{lEX/ >YEX / >YEX/>Y 9 йиܸйи 013>?33#3##5#535#53=={!B !B F7FF7F%m++013##낂Jl:G AO+%+>+.%9>+9.9к8.9801654.'7.#"#"&'732654.5467.54632 3>$ 2=%86(=G=(+) 0H/7j"T3<';E;',&]U:\ Q!&!' -@-,A&":*)+K3-@/&C(DU)p;E'EMEX/ >YEX/>Y#-й4Aй:014>32#".732>54.#"4>32.#"3267#".-Mf99fM--Mf99fM-@9P11P99P11P980?"'57 %'&!/7!&?.ENzU--UzNN{W..W{N>dH''Hd>=dG&&Gd>,G2= =-3< D3IU+'|F^~ +01!#5!Fl~F~e7'5>=+ +62+)и2/и4и101".54>32'2>54.#"'32#'##72654&++)H66H))H66H)5''5 4''41Y#.*<:N76J,,J66J,,J61(8##8((8##8( "M<32'2654&#"-5''55''5%%%%'4 5''5 4'F)! )) !)F6 DEX/>Y+ܸии  01#53533##!!ll4&hh6h>><K's'/EX/>YEX / >YEX / >YEX/>Y  9013326733:7#"&'##"&'#>#"0 %19 >%%6*"+2,`]Tm0.,- YEX/ >Y013##".54>;|4(1WB&&AV1*$;W9?U5#U<.'|Q|'D&G|'D&R'D&gF)*EX'/'>Y +'!ܸ01%3267#".54>'7#"&54632'"* 0Q$b<+K7 $("8,+88+,8"4*" ! J)2(>)!0("%+-77--99 O6&&# O6&&$ O6&&% OG&&& OH&&* O}&&,SfEX/ >YEX/>YEX / >Y ++01#!5##!#3#7  pv-|vv1]+]|||7#9&(/0^6&*#^6&*$^6&*%^H&**J6&.#J6&.$J6&.%JH&.*2!SEX/ >YEX/>Y+и01#5732+72>54.+3#GEEFtR--PqC&?--?&kk-B&OzTT|Q(w1P;:O/GBG&3&&26&4#&26&4$&26&4%&2G&4&&2H&4*Tp# ) + 9 и и01?'77'TIIIJJJC*}EX&/& >YEX/>Y&9и&9 и& иии (01732654&/&#"#"''7.54>327%3<&)3<<&Ea:R;3N@&Ea:U?5Nsc!l$nb,$'*kBP~X/,I2]+rFP}U-0M2@6&:#@6&:$@6&:%@H&:*H6&>$I69EX/ >YEX/>Y ++01332+#7254&+I[5]E()F\4[w<;Rc1P;:S6{h3)=;9ZEX/>YEX9/9>YEX/>Y""94%49014>32#"&'732654.54>54&#"#=8V90H.")",A+*?"1*")")&.P;!/= $1'!%3$"<,d ".!,(+#<3=&F=&F=&F=&F=&F=&FQ09EEX / >YEX/>YEX&/&>YEX,/,>Y1+ ,9/ & 9&)& 96,<C017467.#"'>32>32#3267#"&'#".%4.#"3267./or94*P+,7:,&:'0#%2H 6G'C""3# %.!1+MS#$`(!%$&AW1" 33 ^*#)$(7$140' )C#$&H)7"&J 7"&J 7"&J 7"&J O&-O&-O&-O&-/&4kEX///>YEX/>Y# +&/9&/9)и2и,01%265<'.#"#".54>32.''7&'77,4=8 6? ,@O#A_<3ZC($>O,$B1#&x+3@&I"&kLK :<-Y76T:-I KA<Y)EAH&S/)&T/)&T/)&T/)&T/)&TFIK %+ܸܸܸ01"&546324632#"&!!,#..##..t.##..##.4+""++""+"++""++ h/) *}EX&/&>YEX/>Y&9и&9 и& иии (01732654&/&#"%#"''7.54>327"33$"33!*G[1L?,7.!*G[1L>-7{QAAQA#!X7>aB#(5*8 X7>aB#'6+> &Z> &Z> &Z> &Z>;&^HH)$EX/>YEX/>YEX/>YEX/>Y99"$01#3>32#"&'532>54&#"ۓG&.J3%;&^ O-&&'=&F O6&&(=&F !e (eEX/ >YEX/>YEX/>YEX/>Y% ++01'.'##"&54>7#'##33267n   ;0B ('(˰!  <1n34m1<61-)!t =.+1=EX/>YEX-/->YEX/>YEX / >Y-9/ (и-590174>7.#"'>323267#"&54>7'##".732675=$O|X33$I*43u@hx1' :-= &Z0&<*% !:7H**?,"&`&nr0B.-%:')6+R796&($6C$&H)796&(%6C$&H)79W&()6C$&H)796&(.6C$&H)A,6&).x&I82/R *EX/>YEX'/'>YEX/>YEX/>Y )+!9!9   и $и)%01&#"3267#'##".54>32'5#53533}'**<2.*Bx H&/M7$;L)+:BO!>BE?3$"A\;:]A"M,GJJ^-&*'7"&J ^6&*(7"&J ^W&*)7"&J ^!*#^EX/ >YEX / >YEX"/">Y++"01!!3#!#3267#"&54>7!^% !;0C |{|  J1-(!7."18^EX"/">YEX/>YEX/>Y8*+."501%3267#"&5467#".54>32!3267'4&#"!+  :-;% :dJ++H]29X:Q7"=!A.3(> .$B.-%:#C`>=`C$$@W3$ 81*4.0^6&*.7"&J ,#6&,%4-<&L,#6&,(4-<&L,#W&,)4-<&L,#&,"4-<&L9@6&-%f&M%j0UEX/ >YEX/ >YEX/>YEX / >Yܹܸи ии01#37#####57533533====UUA`___EX/>YEX/>YEX/>YEX / >Y+9ии01>32#4&#"##57533##)1TM )-BB l^ 2.,AKJG/JG&.&O&-J-&.'O&-J6&.(O&-J!#`EX/ >YEX / >YEX"/">Y+"и0173#5!#3#3267#".54>7#JĘ)" ";) |||l|/ J #(!O.&gEX/>YEX/>YEX/>YEX/>Y ܸ!01#5!3267#"&54>7#"&54632Z( :-=  *C+77++77}s/B.-%90))33))0JW&.)O/EX/>YEX/>Y01!##OZ};6&/%*<&\-DR&0LI&PLI mEX/>YEX/>YEX/>YEX / >Y 9 9 и 013?3#'#L˟JH{k 6&1$> m&Q$7k &1 > &Q>k &18> &Q8k'&1 9&Q!  IEX/ >YEX/>Y9и и 01%!55737 KJJ||)r)Tqrq> WEX/>YEX/>Y 9  и  ии01%#"&=575#5!73267 ""&^_qq# & o_R?u@tPuQ B6&3$H&SB&3H&SB6&3.H&S&mEX/>YEX$/$>YEX#/#>YEX/>Y +&#9&!0167#"&54632%>32#4&#"#3.i )25*9=WXfG2JE!x p/[2*.7UKR}(-k]!1-@&2-&4'/)&T&26&4(/)&T&26&4-/)&TS!OEX/ >YEX/>Y  + и014>3!#3#3!".7;#"*Je;"yy:bH(((ITzO&{{|(Q|T;Q1/N P 4=EX/>YEX/>YEX*/*>YEX0/0>Y5+0 *9*#-*9:01732654&#"4>32>32#3267#"&'#".%4.#"  3D&+<>%%:'/#"2F'C:-&C2 "AMMAAMMA>aB#/'*,&AW133 ^(%&'#Bam$14FH6&7$t$&W'FH&7e$&WFH6&7.t$&W'2'6&8$5&X 2'6&8%5&X 2#'&8/5#&X 2'6&8.5&X #9&9/1#&t&YI96&9.1&&Y8@G&:&> &Z@-&:'> &Z@6&:(> &Z@}&:,> &Z@6&:->&Z@!(REX/ >YEX / >YEX%/%>Y+%%013326533267#"&54>7.5@,./.>>$ ";0Cjh`;>>;o^w  J1-&v>.!(EX/>YEX'/'>YEX/>YEX / >YEX/>Y к9#&01!3267#"&54>7'##"&5332673 2& :-= !P6UL*+/B.-%I&-l^22.!FT6&<%T&\H6&>%>;&^HH&>*8#6&?$F&_8#W&?)F&_8#6&?.F&_) )EX/>YEX#/#>YEX/>YEX/>Y"+9 9  "!и"&и'01732654#"'>32#"&'###57533#-)8[/-I$.K3$`B#" 6,AKJG/:0"CEX / >YEX/>Y+ 013267>32#".547!.#"5*'7 "[?7[B$%B]88\B$`;6#2KKLKG )-W}PP~W.-V}OSU.&+BEX&/& >Y+ +& и 01.#"3##"&'7>?#5737>32 &'s-G6!2 WK2I4 +#7k-N:! l 6+e+7N2&S ,GEX$/$ >YEX/>Y$$9&01%2654&#"#".54>32>54&',3<<33<<= >0$)&Ea::aE&&Ea:B8 sscbnnbcs)3< +RP~X//X~PP}U- /I~ -GEX$/$>YEX/>Y$$9'01%2654&#"#".54>32>54&',33333332 <."(*G[11[G**G[15$ kLAALLAAL)3: !_=>aB##Ba>>aB# @$"JEX/ >YEX/ >YEX / >Y 01#"&5332653>54&'w !.swxv,//-F $)+`;>>;  >n#aEX/>YEX/>YEX/>YEX / >Y 9 01#'##"&5332673>54&'Q 8)x !P6UL*+1 )19 >G&-l^22.!F  O6&&.=&FJ6&..O&-&26&4./)&T@6&:.> &Z@&:1> 9&Z0@&:3> P&Z2@&:5> P&Z4@&:7> P&Z6,#6&,.4-<&L&!2&2KEX/ >YEX / >Y#+ и '-01#"&5467.54>323267'2654&#";0C(YEX/>YEX$/$>Yи$* 001467.54>323267#"&32654&#"%-Q<$*F[21\F*.@'$ :-=33333333w&8(BZ9>aB##Ba>2L<-.B.ALLAALL2'&8 5&X9&91&t&YD*<5EX/>YEX/>Y01!#"&'73265#OZ5YC.K +15'.-R>%i 36e 0 ,cEX$/$ >YEX/>Y иии и$ 9  и"и!01%2654&+3#3254&++5#5732)<>==Bjj5g336FH'C\5KK3W?$49i644/@GF$Q$ OE4K1A%<,)JH")vEX/>YEX/>YEX/>Y9/9!$%013267#"&533>324&#">"$O|X33$I*43u@hxx &Z0%=*% !:7H*g*?-"&a&nr8')6+R/ #EX/>YEX/>YEX/>YEX/>Y99 01732675.#"4>32373#'##".2.*));$;N*&C sx K$/M7JDDH=`C$!33$$C`H) "EX/>YEX/>YEX/>YEX/>Y99 01%4#"3267#"&'##33>32^+,):$YEX/>Y 01%#"&'732654&#"'>32,Kg:5i+<=%AQI< :D h?9cK+>aB##&]LAAL[&#Ba6!#CEX/>YEX/>Y+  01%#"&'73267!.54>32.#"!+Jd:2h*0!="7N  >[;0ZD) 7*25>`C#X18 $3W@$$C`0.4*7"#CEX/>YEX/>Y#+ 017467!.#"'>32#".732677O A6"B1+g2;aE&)F]3:X<12+;$ 61\$C`=YEX/>YEX/>YEX / >Y99 !$%(01326?#".54>32373#"&'2675.#"#M79I#/M7#;N+N9 s*j,+*$6,/#@$AY69]A$?3 eo!0>BYEX/>YEX/>YEX/>Y 901#57#"&5332673S8TM )-_-l^22.K 9 EX/>YEX/>YEX/>YEX/>YEX / >YEX/>Y9  9  01!#'##"&'#"&533273326739n 1, - 5*4:q >+)(!0UK\.0O.O4TEX/>YEX/>YEX/>Y9 01!#'##"&'732673x %hYEX/>Yии 01%3##5#5354&#"'>32}y260!Q0;R3sss9/ j 9Q19 @EX / >YEX/>YEX / >Y 901!#'.'##39N    N&L''L&T!i /EX/>YEX / >YEX/>YEX/>Y 99901!#'.'##'.'##33>?3T g! M %H&&J#%H&&H%#G(D39REX/>YEX/>YEX/>Y 9 01&#"#'.'##>32). גS   I)5E.$O(-#K'%K% .H1pH  cEX/>YEX / >YEX/>YEX/>Y9 9 01###73753 ˟J}$H{:/ /EX/>Y+9013>32#54&#"#h5$92hhp<H>˾4EX/ >Y+ܸ013#"&'7326=#7"&54632$<.0 "~&&''M7) I #~!##!U6/EX/ >Y +90133>32.#"#V@#5hMH)'V",SM!Z/EX/ >YEX / >YEX/ >Yи  0133>?33>?3#'.'##SfG^1xwM02dd00f/,#fMAEX/ >YEX / >Y+9017326?33>?3#"&'7 h/  (ct ". ?./ 0N""  ++0126548'2$$2QNNQ2&&6E88Ep + +01"3&546p2%%2QNNQ&&6E88E>>yx +013#ZP>>~xb +01#3xZk>9$.?=(EX/>Y +0133267#"&=# %D|MK//EX/ >YEX / >Y 9и и01'33>?3#'&'##holioo"l3333>~ +013#Yk> +01#73EkY>>+ܸ013#'##|dk55k__?'+ܹ и01>3232673#".#"# >. K >. K?IFHGP +01!!]> +  ܸ01".'332673,%7$RR$7>+9 ++ 9+9 +01"&54632,+77++7790))33))0p; + и01"&546323"&54632#,,##++#++##,,;-"!--!"--"!--!"--+ܹ01>54&'7$+\L&3g J1(% $  + ܸ01"&54632'2654&#",3>>33>>3$7//77//77=+и013#73#u_Zu_[ԗ>+ܸ013373#k55kd|``E=+и01#'3#'3Z_uf[_u= a +01632#"5467a8 B03'S*Cm +0167#"&546328B03J'S*C"~+01>54&'7"% e .># ,)!0 +01"&54632,+77++770))33))0( + и01"&546323"&54632''''''''())(())(+ ܹ01'>54&'7D50@$ $/*'&% ;6#+и ܹ 01%3'>54&'V 0@$ $/"/#% ; .EX/>Y +014>733267#"& S6 :-=w&*-B.. +01".'332673,#3"RR"3&3""3&C +01!5!^U"9/+ + + 901467&#"'>32#'##"&732675\g5.%!L(AJU309d 6)_5: +CIN!:2 5T/EX/>Y++99013>32#"'##732654#"h/?G(30) Qh  #8p1\K*C-+#_ *2U!T /EX / >Y++99014>32'53#'##"&732675.#"(3%gT0@Lk $(A,1o2 [R/*  *U"!++ +014>32#327#".74&#"/; &9%2"&'#D&@0 '(@-+:!#=,@L! zUBNdEX#/# >Y>+!I+8 +C.+ 89 и.1ии#&01732654&+"&'475.54675.54>323##"&';2#".72654&#",%&1( U4'4A&2  YEX/ >Y 9  9 013373#'#hrq|pQ-h}},QsUT///EX/ >Y ++9и0133>32>32#54#"#54#"#sN . $#'c P bM)6 :1U++014>32#".732654&#"/Y ++ 9 901%#33>32#"&'732654#"hU3?F(3'  #8_ \K*C-E *2UIEX/ >YEX/ >Y +и 01#5?33#327#".5EJ W #3(8"MVVQn$ J &5!MAEX / >YEX/ >Y+901#'##"&=3326753U5#92hh-H=̿ vM 3 /EX / >YEX/ >Y 0133>?3#vh0  0cuxM22U+ +014>32&#"3267#".3C%"50'//$ )@&@0)@-@0*)1 A,@8 /EX/ >Y+ и01.#"3##5#5754>32#Y и017#5!3!#;Q7QA,&)/&I AC,&)/C&I ,#-&,'4-<&L@&-H&M@.&-H.&Mk &1 > &Q>7 -&1&' > &Q'>kC &1 >C &Q>A&2$=&RBW&3)H&SB&3H&SBC&3HC&SFH&7j$&WFH-&7&'j$&W&'FCH&7BC$&W2'W&8)5&X 2'&8 5&X9&91&t&YDC9&91C&t&YDT6&<#T&\T6&<$T&\TH&<*T&\HW&>)>;&^8#&? F&_1&d&Y@5*hEX/ >YEX)/)>YEX/>Y! + ! 9%%9014>32#"&'732654&/7.#"#@:[@WqH*!+@+8LL 33 K%-(.Q<#eRz +9%(F3&Y( 3V}$=>ZH6&>#>;&^H&> H&^Hv&>+>;&^HG&>&>;&^P6 +01!!PH6oD6 +01!!06o"  +01632#"&546757 (36*8=WXkD01*.7TLR}("  +0167#"&54632i )36*932,#<,,<##<,,>77 +01%'7'?>>77Gp +01?'733e/ 0*/EX/ >Yܸ 013#5#7"&54632h}&&''M~!##! _\!_\"U:/ /EX/ >Y+90133>32#54&#"#U5%83hhM*H>˾KWWWWWKWWWKWKWWWKWK W!W"WU!!+++014673.#"'>32#".73267)!&#@ L]-; &9&X %# ?\Q(?-+: ! O3 4EX$/$ >YEX/>Yй$ии ииܸии$!и$#ܸ(#)и(+и1и2и2/01%&+#7&'#7.54>?33273&'672  2 4&($-&Z6 2  2KY"?X7 2  2 2Q02%veKf7R).cciy vFqT4 gbdq O h +C&1}EX/ >YEX/>Y +$'+ и/' и$и/ *и,01%!5>7#573.'#57&54>32.#"3#3#&-?pO[C"Y#O,07||[A,E  E/L5*'P.0 K  J)<{ +EX#/# >YEX'/' >YEX/>YEX/>Y+&+к #9 и& и#ииииии/и&!и!/&)01#3#3'3'#'3'#3##'##5#575#57533533;/!*;/!*GEEYKjFFFFYKjEV0:0:~0:404:;{ !cEX/ >YEX/>Y++  иии 01267#53.##+##575323,6 6,5=+?P,,DD,P?*>3&#IH&"+>)|U'?-[2-VEX/>Y"+ "ܸ'и-)и-,017!!.#"3267#'##"&54>32'5#5353h] "2*##Hd ;#N]2? %/yJJh +&0,aDn$b\*B/CJ11-G1mEX/ >YEX/>Y($+(+и( и$и$!и.01%#".'#57&45<7#57>32.#"3!3#3267G)d=3XG2 @77@l3_%Q4 3BB1#6P-/9U8E  Dpz(&O>9JK7:;{ 5EX./. >YEX$/$>Y "+.йܹ ии и &и)и*и-и4016454&'#27#53&##3#+##575#575323w">~}@5;;F .YEX/>Y&+ии"013#5.54>753.#"3275#KI)b2S<"!YEX/ >YEX / >YEX / >Y   ܸܸ!и"01#5.54>753.'67C012/!O/Q5ZA$#@Z7Q*NQ"+#jTUj$-ed0RrJGrT4][' O Z (X {pEX/ >YEX/ >YEX / >Yиииий  и /01#3##'#5327#573.+5! %LJI6VJtQ E8J12J@QuGDu$'{#]EX/ >YEX/>Y9"ииииии01%>54&'7'5575575377 9,y;odUUUU}",  DiE")Q)7)Q)~MQM7MQMF~ +01!!F4~hGpD(EX/>Y +01".54>32'2654&#", 6((6 6((6  ,?''=++=''?,O(33$$33(8 EX / >Y+01%#5>73#Q Sk@ D,EX/>Y+017>54&#"'>323!5'>@)Y+ +' 901732654춮&#"'>32#"&'-#& "*D)+ #$1F#` 7  > !! &%88EX / >Y+ +и 01%57###5#5733A"!3^x3c>;B==3ȹ8 DEX/>Y+ + 9 01732654&#"'73#>32#"&'++Յ 2;$1"D#` X#3.(D &FEX/>Y# ++#901%2654#"7.#">32#"&54>323&d &"'.6!.HN)=) 6C ."0.)]J"=.8&EX/>Y+ 013>7#5!#  # p"854W8 ;Y#+449#901%32654&'7654&#"4675.54>32#"& 5 &"-6H  #1Y++$9$ 01%3267.#"3267#"&54>32#"&'%  #3 &!!.-6!.#8'*=(!6  -!//),>%!=/  +017467.93O)**)O39Ow800g78g008w +01%'>54&'793O)**)O39Pw800g87g008ww6 +013#Qu6x6 +01#73VuQx6+ܸ0173#'#``q55xx==G++ܸи 01".#"#>3232673k" K<'" K<ECEC- +01!!-]6 +ܸ 01"&'332673,BAQQAB66BW +01"&54632,%00%%00+""++""+H + и01"&546323"&54632''''''''((((((((v+ܹ01>54&'7$+\L&3 I1(%}  + ܸ01"&54632'2654&#",3>>33>>35--55--576+и017373#?}Y}Zcxxxx6+ܸ01#'337``q556xx==#+и ܹ 01%3'>54&'V!1@# #/"/#% ; ;9 ++ ииܹ01"&546323"&54632%!!########;#$$##$$#E+ + ܹи 01!!"&546323"&54632*########E$##$$##$;P%+ +и 013#"&546323"&54632;~s^########Po#$$##$$#) + ܸܸи 013#"&546323"&546322vu########x$##$$##$;P++ܹи013373#"&546323"&54632d..dV|%########P::o#$$##$$# ++ ииܹ01"&546323"&54632#'337########*``q55$##$$##$xx<<;P) + ܸܸи 01#'3"&54632#"&54632p^s~r########o#$$##$$#) + ܸܸи 01#'3"&54632#"&54632wuvi########Vx$##$$##$$[ +01'3^$E!+ ܹ01.54>7OC61@$ $/+!'&&; 6>.e#A`   '$9 , E u F ( / $ . 4Q  2 # H9Typographic alternatesTypographic alternatesSource Code ProSource Code ProBoldBold1.017;ADBE;SourceCodePro-Bold;ADOBE1.017;ADBE;SourceCodePro-Bold;ADOBESource Code Pro BoldSource Code Pro BoldVersion 1.017;PS Version 1.000;hotconv 1.0.70;makeotf.lib2.5.5900Version 1.017;PS Version 1.000;hotconv 1.0.70;makeotf.lib2.5.5900SourceCodePro-BoldSourceCodePro-BoldSource is a trademark of Adobe Systems Incorporated in the United States and/or other countries.Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries.Adobe Systems IncorporatedAdobe Systems IncorporatedPaul D. HuntPaul D. Hunthttp://www.adobe.com/typehttp://www.adobe.com/typeCopyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. This Font Software is licensed under the SIL Open Font License, Version 1.1. This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL ----------------------------------------------------------- SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ----------------------------------------------------------- PREAMBLE The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. DEFINITIONS "Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. "Reserved Font Name" refers to any names specified as such after the copyright statement(s). "Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). "Modified Version" refers to any derivative made by adding to, deleting, or substituting -- in part or in whole -- any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. "Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. PERMISSION & CONDITIONS Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. TERMINATION This license becomes null and void if any of the above conditions are not met. DISCLAIMER THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. This Font Software is licensed under the SIL Open Font License, Version 1.1. This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL ----------------------------------------------------------- SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ----------------------------------------------------------- PREAMBLE The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. DEFINITIONS "Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. "Reserved Font Name" refers to any names specified as such after the copyright statement(s). "Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). "Modified Version" refers to any derivative made by adding to, deleting, or substituting -- in part or in whole -- any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. "Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. PERMISSION & CONDITIONS Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. TERMINATION This license becomes null and void if any of the above conditions are not met. DISCLAIMER THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. http://www.adobe.com/type/legal.htmlhttp://www.adobe.com/type/legal.html2:  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`a bcdefghjikmlnoqprsutvwxzy{}|~     !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXNULLCRuni00A0uni00ADtwo.sups three.supsuni00B5one.supsAmacronamacronAbreveabreveAogonekaogonek Ccircumflex ccircumflex Cdotaccent cdotaccentDcarondcaronDcroatEmacronemacronEbreveebreve Edotaccent edotaccentEogonekeogonekEcaronecaron Gcircumflex gcircumflex Gdotaccent gdotaccentuni0122uni0123 Hcircumflex hcircumflexHbarhbarItildeitildeImacronimacronuni012Cuni012DIogonekiogonek Jcircumflex jcircumflexuni0136uni0137 kgreenlandicLacutelacuteuni013Buni013CLcaronlcaronLdotldotNacutenacuteuni0145uni0146Ncaronncaron napostropheOmacronomacronuni014Euni014F Ohungarumlaut ohungarumlautRacuteracuteuni0156uni0157RcaronrcaronSacutesacute Scircumflex scircumflexuni015Euni015Funi0162uni0163TcarontcaronUtildeutildeUmacronumacronUbreveubreveUringuring Uhungarumlaut uhungarumlautUogonekuogonek Wcircumflex wcircumflex Ycircumflex ycircumflexZacutezacute Zdotaccent zdotaccentuni0180uni018Funi0192OhornohornUhornuhornuni01CDuni01CEuni01CFuni01D0uni01D1uni01D2uni01D3uni01D4uni01D5uni01D6uni01D7uni01D8uni01D9uni01DAuni01DBuni01DCGcarongcaronuni01EAuni01EBuni0218uni0219uni021Auni021Buni0237uni0243uni0250uni0251uni0252uni0254uni0258uni0259uni0261uni0265uni026Funi0279uni0287uni028Cuni028Duni028Euni029Eh.supsj.supsr.supsw.supsy.supsuni02BBuni02BCuni02BEuni02BFuni02C8uni02C9uni02CAuni02CBuni02CCl.supss.supsx.supsuni0300uni0301uni0302uni0303uni0304uni0306uni0307uni0308uni0309uni030Auni030Buni030Cuni030Funi0312uni0313uni031Buni0323uni0324uni0326uni0327uni0328uni032Euni0331a.supsb.supsd.supse.supsg.supsk.supsm.supso.supsp.supst.supsu.supsv.supsc.supsf.supsz.supsuni1E0Cuni1E0Duni1E0Euni1E0Funi1E20uni1E21uni1E24uni1E25uni1E2Auni1E2Buni1E36uni1E37uni1E38uni1E39uni1E3Auni1E3Buni1E42uni1E43uni1E44uni1E45uni1E46uni1E47uni1E48uni1E49uni1E5Auni1E5Buni1E5Cuni1E5Duni1E5Euni1E5Funi1E60uni1E61uni1E62uni1E63uni1E6Cuni1E6Duni1E6Euni1E6FWgravewgraveWacutewacute Wdieresis wdieresisuni1E8Euni1E8Funi1E92uni1E93uni1E97uni1E9EYgraveygraveuni1EF4uni1EF5uni1EF6uni1EF7uni1EF8uni1EF9 zero.supsi.sups four.sups five.supssix.sups seven.sups eight.sups nine.supsparenleft.supsparenright.supsn.sups zero.subsone.substwo.subs three.subs four.subs five.subssix.subs seven.subs eight.subs nine.subsparenleft.subsparenright.subs uni0259.sups colonmonetarylirauni20A6pesetadongEurouni20B1uni20B2uni20B5uni20B9uni20BAuni2215 zero.dnomone.dnomtwo.dnom three.dnom four.dnom five.dnomsix.dnom seven.dnom eight.dnom nine.dnomparenleft.dnomparenright.dnom uni0300.cap uni0301.cap uni0302.cap uni0303.cap uni0304.cap uni0306.cap uni0307.cap uni0308.cap uni0309.cap uni030A.cap uni030B.cap uni030C.cap uni0327.cap uni03080304uni03080304.cap uni03080301uni03080301.cap uni0308030Cuni0308030C.cap uni03080300uni03080300.cap uni030C.a uni0326.amUwPK!՞ww=2.2.0/rdoc/generator/template/darkfish/fonts/Lato-Regular.ttfnu[ DSIGwGPOS,KGSUBV.TLOS/2ٮiM`cmapRԟNPcvt 'm`8fpgm zAm gaspmXglyf*~ʙS8Bheade|6hhea$hmtx[`TkernlBjT,lloca.V,maxp< X< name $X\^post:]iprepx9w, 0JDFLTlatnkernkernJnv$R ^ h B l  & rjZjL*|DV: !.!##L#$4$~%&J'$'()*+f+,6,-.(./t//0:0|2"233T334&4l455b566L667B778889d99:&::;@<=>j?,?@hABCzDEFG*GHfIK JNJ#$J&*2490:0<?0DFGHRTmNoNyN}NJJJJJJJJNNNNNJK JNJ#$J&*2490:0<?0DFGHRTmNoNyN}NJJJJJJJJNNNNNJ"#&*24FGHRTK JNJ#$J&*2490:0<?0DFGHRTmNoNyN}NJJJJJJJJNNNNNJ-  x#&*247L9L:?DEHIKNPQRSUYZ[\^lmoprtuy{|} 8DFLTlatncase&case,liga2liga8sups>supsD,>B      @ LO,{tu CjqvIxxxP`KtyPL@Jz  &   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ardeixpkvjsgwl|cnm}byqz`T@ ~1DS[a~    " & 0 : D !"!&"""""""+"H"`"e%&i 1ARZ`x    & 0 9 D !"!&"""""""+"H"`"d%&i{uq[H$I޸ޡޞ:ڜ`T@ ~1DS[a~    " & 0 : D !"!&"""""""+"H"`"e%&i 1ARZ`x    & 0 9 D !"!&"""""""+"H"`"d%&i{uq[H$I޸ޡޞ:ڜ-%59=J@GBhf[[ Q CQ D=<($#*$ +>32#'&>54&#"#"'4632#"&!!7!!9DO.?gI)-60#z -70 I9)8(  c>0((0>22cu&#@[87P;+&%iu"3+(.:(3</@)(?g6, !&@#Q CSD +#.54>32#". y +!..""..!-VW[44[WV-<."".-""- ,@) BQ D   $+#"&/!#"&/3ޛ ## "ޛ ## "6Q>BH@E  Y  C Q C DBA@?>>86530/*(##!#!+#"&5467#+#"&546?3#7>;>;3323+32%3#TQ GG-OUA $'H+PTTO!I %&A AY"Z% 9FJf"ZK 9Fj$g8CN~@J( I>) ? 4BK PX@$hfSCSD@$hfSCSDY#&#&+.'7>32.54>?>;#".'+4.'>yH50FaD%FkA9mh Bi<+):L1!HpE324.#"32>>;+#".54>324.#"32>4Wt?DsV00VsDCuU11A%%A00A%%A1  54Ws?DsV00VsDCtV01A%%A00A%%A1?T[00[TV\00\VB\;;\BA[99[w RT[00[TV\00\VB]::]BAZ99ZRx?K@8IH+%BKPX@*hSCS CS D@(hSCS CSDY@FD/-(&"  ??+2#"&'.#">7>;#"&/#".54>7.54>3267O_7o 1E.2P9"6&&-nFB,$^PyJ/SrD=:5d0Nd4pDYjk3To<8. 9M-#@AE&]CJsa[j6g]F}jTMNI_7AcD#RD93 @ BQ D $+#"&/3ޛ ## " (+.54>7!nh OKiAAiKO  imum 0szyt1lJ (+4'&546?'.54676*mi  OKiAAiKO hnu1tyzs0 `_0J@-)($  BKPX@ QD@MQEY@ 00+5467'767./7.=3>?'.'b!,$%#,# X ,!!, _"cKd eKd %) cKd  eKd !'d" ,@)MYQE +!!#!5!ikUR^P@?S D$+74>32'&547>7#".^,/0G-    *{)'3-a_Z&   %0:!!-d R@MQE+!!dXQ@SD($+74>32#".X!..""..!n."".-""- @kD#"++>;7KY 0!K#" "<L'@SCSD((($+#".54>324.#"32>LQmnPPnmQ7]zBBz\77\zBBz]7̼XXXX켤߈;;ߤވ;;*@' Bh CR D&+%!47#"&/3!!4  8,- Mqh$3;@8/ BhSCQ D,*$" 33+2>3!2!5467>54.#"#"&/>Y[sB0Rk<(R&"D9^C$(F^66\G1   ]P{6g^P}u=~ "l=(:klo??_> 9N/bf5l.JU@RF Bhh[SCSDCA;910/.&$JJ +2#".'763232>54.#5>54.#"#"&/>l[o>#A\9KcrpHL(DeKKqK&Qp[R%'D]66\G0   ]P{4`SDkQ8%co;9dP  I@,1N`/:`F(&B\8>\< 9O.bf5(`&@#B[ C D!#+3+#!"&/3467!fy[< ;l.@@=,+Bh[Q CSD(#&(""+#!632#".'763232>54.#"'!09>Bp_pt;Pm?tdV!63HaCKxU.'OvO6t>ptK&1Bt]rF*6L&0Y|MClL*!l2.2@/B[ CSD+)! +2#".5467>;>32>54.#"VtDHml|CT[k2 3|(MoGHtS-,PpCHtQ+n9mfc~HEp^z#'LErR-.RpBFqO*1Smn<@Q C D$'++>7!"&=< .'Z P",S%*y`&3GD@AB[SCSD54! ?=4G5G+) 3!3 +".5467.54>32'2>54.#"2>54.#"CkFqs>rbar>tpGkFoM)1Sl;;lS1)MoFFc>!Aa@@aA!>c9j^&*tOf::fOt*&^j9'Gc32+>74.#"32>%QnAF~hgxA,=' 0&7+Li?BmM*'IiAHoL(L6ic^zFDzg>oji8;4,.CmL)+Lj?DkJ&/Nfy';K$PX@SCSD@[SDY((($+74>32#".4>32#".!..""..!!..""..!n."".-""- ."".-""-y2D?K$PX@SCS D@[S DY@ /-%#$+74>32'&547>7#".4>32#".,/0G-    *!..""..!{)'3-a_Z&   %0:!!-."".-""-W(+?--  !@YMQE+!!!![[>ևW(+75467%>7.'%.=++?  oJ"(<9@6BhfSCSD(&#-$+>32#'54>54.#"#"'4>32#"."KYg3232>54.#"3267632#"$&54>32%2>7&#"Nb :N54&#%!2>54&#!Ʉ{;!CeDCx6SwM$RxO&4`W5bTB[l; &E_9o$@[6~vZ .D@ABhfSCSD)'..+2#".546$32#".#"32>76 LXbi Y? (6Jb@sMMi@fWK&( SfrkkbTY  O҂ґL 1" @S CS D!(!$+#!!24.#!!2>ffHsUsH̡ggАLL! .@+YQ CQ D +!!!!!!P-$! (@%YQ C D +!!!#!PL Z@4K@H! Bh[SCSD,*%# 44+%2>7#"&=!#"$&546$32#"'.#"-:aVL&6uYigU}j.7>YySyĊJM <n':'kj/C*X (%OтՔN8 @Y C D+!#!#3!38t@ C D+!#3<QKPXBBYKPX@ CSD@h CSDY!&$+#"'>7>3232>53;smai<2BgG%xF9(TZ:"&@# B[ C D)(% +3267>;#".'.+#3I&-) %*: !X% $Y  9  p@ CR D+%!!3pl£#%@"Bh C D!6)+>7>;#467+"'#32o  --  53q g0--2 8@ C D!+2.53#"&'#3>bd 1g70\'@SCSD((($+#"$&546$324.#"32>ffffHtsHHstH̡kk  llґNN҄ёMM*@'[S C D !+#!2#'32>54&+ɄAFȁSV,?tedxC,OnB\$0s BK PX@kSCSDKPX@SCSCD@kSCSDYY(((%&+#"&'#"$&546$324.#"32>)NpFp$89{CfffHtsHHstHe/sk  llґNN҄ёMM#2@/B[S C D#!,!+#!2#"'.#'32>54&+Ɓ>0[S$5((UW,V7h[LiJ())Kh?:==@:=BhfSCSD;9(&#!#"+#".#"#"&'7>3232>54.54>32 -EaEAdC";a{{a;@{rQ86QsSElK(;`{{`;;pkxJ")"#53#".53Ya3OԄԔO3a7>;#  " "P++P"g( @#B C D+< +32>7>;2>7>;#&'#"(  Q#8!O )#A  >""?4C!<gE)%@B C D("(!+ 3267>; #"&'+'va %   PY@ B C D,"+#32>7>; H G ::_#>>"-V $@!Q CQ D +!!547!52,H"Lv '@$[OQE !#+!+32pFF @kD# +32#"&'L!0 YK8 " '"#Z !@[OQE!"+46;#"&=!!Zp3F@ Bk D+!+3#"&'.'+sf z`+,+[@MQE+!5xx& @kD  +2#"&'! f \z)9}@ !/BKPX@'h[SCS D@+h[SC CSDY@+*10*9+9%##' +!#"&/#".54>754&#"#"&/>322>75zO (LT_:;gL-BecAYA/ TvUZ.2/NE?{l1,<^$9'!BeE32#"&'#"32654.?iXd632#".54>32E#6M8JrM'*LmDAT8$ 2Bn_xE?ysj?A 5dX\a3&AQKF|qNE?H%p@ BK"PX@CSCS D@!CSC CSDY@%%+!"/#".54>323%267.#"[& AlWd632#".54>"!4.#[p?^0TtHCaF/ 2!\ip7iHAzr'"B_=sl*`_/$A(;&GʃjM>gK)]@ BK2PX@SCQC D@YSC DY@ 4%+3'.=354>32+"!!p1[PD: .K6%] IbW]0Y6XA]29M]@2A*BKPX@, [[CS CSD@/h [[S CSDY@ONWUN]O]JH@>#!99 +2!#"'#".5467.54>7.54>4.'32>2>54&#"Bs/*s"9eSG? !:`zz`:Azoon7_S+3!0 KU9f*H^hl19G#HmJHrO*6S8qlkq8RB! APJyV..$% 2XFAz_9,Ja5KiC8/.**]JyU.&. N6";+0BN6K-]nn]-K6-@*BCSC D##+33>32#4&#"AgSU,ilO:ES7eV{sLAGK PX@SCC D@SCC DY@  +##".54>32X#.-##-.# >-##-/##/(Y BK PX@SCCSD@SCCSDY@%#U%+#"&'7>323265#".54>32X EmL!6 NB#.-##-.#=iN- ` IQ@>-##-/##/0@-B[CC D%(%!+3267>;#"&'.+#K.@ 2 Ws   X@C D+#X?*V) BKPX@SC D@CSC DY@**##&$! +332>32>32#4&#"#4&#"j& 8\gEVa2P}W.hc,O<#b^Bq/%hEXra7P43b\{w{<[<{zxG= LBKPX@SC D@CSC DY@ #$!+332>32#4&#"j& BkSU,ilO:%nIZ7eV{sLAH#NK PX@SCSD@SCSDY@## +2#".54>2654&#",o}CC}oo~DD~oLpK%%KpJwxIIxwJxɴ4bZZa4%@ BK PX@SCSCDKPX@SCSCD@!CSCSCDYY@%%($!+32>32#"&'"32654.j& AmWd69@PIB6ʻc[*H%KPX@ B@ BYK PX@SCSCDKPX@SCSCD@!CSCSCDYY@%%(#+##".54>32763267.#"Ų@iWd632#"&#"f 4g*D:4]}*jwlg{><=@:<BhfSCSD:8'%" #!+#".#"#"&'7>3232>54.54>32 &7L4-H3-J^c^J-2b]j<*(9Q=4N4-J_c_J-0\Vd:N(5'4&!([A:kQ0?7,>!t@ BK2PX@$jhQCTD@"jh[TDY@ !!+"&5#"&=7>;!!32>32xz)Z">1) 4.~lG9@>U+1zLBKPX@CS D@C CSDY@ $!#+32673#"/#".5,jkN:j& BjSV+zs~JB %mIY7dV@BC D, +32>7>;#ct$H##H$ . @'BC D*!,< +32>7>;2>7>;#"'.'+ M      t$C""C$p#D!!H "/0R"@BC D("(!+ 3267>; #"&'+  c  @@BCD,""++32>7>; ^  ,,}FU@QCQ D+!!5467!5!U ) '#&J #ߌ,@3@0$B[[OSG86303++4춮.54>;+";2#".54>FCCF)S{R5 MY)7!!7)YM 5R{S)?QkP@2bbd4EtT.OeV8hcb2&A3% %4@%2bch8WdP/TtE4ccbp@QD+3#把X,@5@2B[[OSG?>=<1/,)3)++546;2654.54>7.54>54&+"&=323"*R{R5 MY)7!!7)YM 5R{R*FCCF2bcc4EtT/PdW8hcb2%@4% %3A&2bch8VeO.TtE4dbb2@PkQt9@6jkO[SG +2673#".#"#4>32AI%Ef@4f_V$AI%EeA4f_VeUFCpP, '!TGCpP-!'! !&@#SCQD +4>734>32#". y "--""--"-UW\44\WU--""-.""..7@ 32&*BK PX@)jhfTCSDK PX@)jhfTCSD@)jhfTCSDYY@ ##'#+.54>?>;#".'>32+1\q?B~w BR6. !-?*4?U;& 0 " ?HJ9c4[>@@=7+Bh[SCS D%&#&'%" +46;4>32#"&'.#"!#!>3!#!5>5#4 6nnNy^EH   )3B-?`@ {929 <">0$^{G'DZ4. /#*NnDHKm-Ls "3E.!`#7?@< !B @ ?WSD42*((+467'7>327'#"&''7.732>54.#"![,h:9f+Y"![,h99e,Y"#>Q//S=$$=S//Q>#9e,Z"![,g:9f+\"![,g:.Q=$$=Q./R>##>R,S"8@5 B Z Y C D"! ,! +!32>7>;!!!!#!5!5!2h !g3TTq(#:;"6fig;gip@YQD+3#3#把rHZA@>HXN=#BhfWSDFD-+(&!#!+#".#"#"&'7>3232>54.5467.54>32>54.'1 &7L40M51OfifO1NT1>2a\j<)(:U?2O62RhnhR2V]2?0\Vd:Fm>604FOT(B6*8&9/+.7G\=Q&%bEFwW2E6D #->&-B3*,3F]@N}#&iK:kP0>73G95K/$8.&##IV{'3K PX@ S D@OSGY((($+#".54>32#".54>32 )(() g)))) ((**((**D.Jb@ BK PX@4hf[[ SCSD@4hf[[ SCSDY@ _],,*(#%(%" +>32#".54>32#".#"32>4>32#".732>54.#"  =9tbs?Ezbl9. 2L;FqO++Lj>0B0%R4_ee_44_ee_4d,RrXc-RsXb@BIDzdeyCD7A -TxKMyR+  e`44`ed`44`eYtS-dYvS.e\?T)5E@B!-Bh[WSD+*/.*5+5%##' +#"&/#".54>754&#"#"&/>322675T< .28"&A0&Xk:9&2%4yI6T:3J$Fa<4H 1  )<)"C5#%?< *1."BK PX@/h  [ [SCSD@/h  [ [SCSDY@44VTLJ4I4H)!*,,& +4>32#".732>54.#"#!2#"'.#'32>54.+D4_ee_44_ee_4d,RrXc-RsXb kj ! Pt7M/+F4e`44`ed`44`eYtS-dYvS.e|}z^ . r(:&%8$RD@MQE+!!>DuF''@WSD((($+4>32#".732>54.#"F2XwEEwX22XwEEwX26I**H66H**I6hCvW22WvCBuW33WuA*I66I**J77JdP" 7@4YYMQE  +!!#!5!!!ikkBpx%RQe-9@6+ Bh[SD(&"  --+2>;2!546?>54&#"#"&/>Z4U:M+  455370* jjT|Re=S@P9Bhh[[SD640.*)('== +2#".'763232>54.#5>54&#"#"&/>b3R; wBE*E[09T=+7 + / 'A/WG:009  C,ATe3D(-N>7T91H/ (+W<424/( 5O5U @kD #++7>3Uj!  z3@0BCS CD&$!#+32673#"/#"&'#"&5,liN:j& CWJp'Y&)nmxJB %mHD3.*W&($*7*@'hiS D+##!#".54>3۝hu??uh77]=iQVe8|@OSG($+4>32#".|)68((86)Q8((86))6 KPX@  B@  BYK PX@^TDKPX@jTD@jjTDYY@+232654.'73#"&'76 *+)<&+pZQ 9P0)J ! PE6 3$7xD_O BK$PX@jjQD@jjMRFY$+37#"/733!k  'li+X 8zUH<)@&WSD +2#".54>2654&#"~FqP,,PqFGrQ,,QrGTSSTWSS+PsGHtQ++QtHGsP+iddhhddi %%(+7'&54767&'&54?%'&54767&'&54?:   :(:   :   {{   f| &0O@L$ Bh  Z [  CS  D0.+)&% $!# +3+#5!"&/3%37#"/733!4673+>;m Rm V|k  'li,L2. M A  9;+X 8zU,\ f]-=Ge@b710+ Bhh  Z [  CS  DGEB@=<;:9853/.(&"  -- +2>;2!546?>54&#"#"&/>%37#"/733!+>;f4U:M+  455370* jj3+X 8zUv\ D}NT^x@uJ  %RB h  h  [[ \ S CS D^\YWTSGEA?;:980.)'!NN!#+3+#5!"&/32#".'763232>54.#5>54&#"#"&/>4673+>;m Rm V|B3R; wBE*E[09T=+7 + / 'A/WG:009  C,AT,L2. M A  93D(-N>7T91H/ (+W<424/( 5O5\,\ ,)=9@6BhfSCTD('#-$+#".54>?332>324>32#".KXh2/ IB@:> IBYK PX@0hfSCSC SDK PX@0hfSCSC SDKPX@0hfSCSC SD@7hf hSCSCSDYYY@GE=<861/'% KK +232654.'7.546$32#".#"32>7632#"&'76 *+)<&$Vi Y? (6Jb@sMMi@fWK& LSZQ 9P0)J ! v ukbTY  O҂ґL 1" Sap7E6 3$7!&( 7!&( 7!&( B!&( B&, &, {&, x&, 2!,@)YS CS D!%(!+3!2#!#%4.#!!!!2>2ffHt}UtH gg2АLrL8&1\&2 \&2 \&2 \&2\&2 ~X  (+  ' 7 b__d_YX`b`dY`X\!-8h@21&%BKPX@kCSCSD@jkSCSDY)*%(%$+#"&'+&546$327>;.#"4&'32>flOd:Np{fsSR dgpAKE54&+ɄAFȁSV,?tedxC,OnBvHwKPXBBYKPX@hSCSD@#hSC CSDY@CB=;%# HH+2#"&'7>3232>54.54>54.#"#4>gb/+@K@+5P]P59dOa<)(7K5,F18TbT8-CNC-8Y?DoO+E<]n332#"&'#".54>754&#"#"&/>32>32>5"!4.Rg;.MiAE\=&/!Wcj4u7Wjw;ErS-BecAYA/ Tqx!6{l1dQ9cI*=`E)X8#FjH32#".#"32>32#"&'76 *+)<&%Sf:?ysj?/#6M8JrM'*LmDAT8$ 2;aZQ 9P0)J ! y OqqNE?@ 5dX\a3& AHJ:E6 3$7J&HCJ&HvJ&HJ{&Hj&C(&v6&){&jL4H6@3:0B43@[SD65@>5H6H.,$"+.54?.'.54?7#".54>32.'2>7.#"g-e9`Q#a{xb}H>thdAu^_GsQ.4Kc>KqL'.Pi) H"><0z9 C1|nVB{p^~JVW@6mo+Q?%2WwDQV-&QH&RCH&RvH&RH&RH{&Rjd"++@([YOSG(((%+!!4>32#".4>32#".dBb!--""--!!--""--!."".-""-S."".-""-@-I!+5t@43%$ BAK PX@ jkSCSD@ jkSCSDY@ -,,5-5%%(%'+#"&'+7.54>327>;&#"2>54'=BC}oL67;CBFD~oO8D Z;IoLtO(7KsO(4OFtDvxI" JE|wJ&#[aN86d$5dZ`0z&XCz&Xvz&Xz{&Xj&\v#q@ BK PX@!CSCSCD@!CSCSCDY@##(#+3>32#"&'"32654.?iWd6!&'d ]3XeO< }"==%*"1* ?  BOB:e&Zg '/&+ G6Q)E\CS@;I BKPX@1h  [SC SCSD@8hh  [SC SCSDY@EDKJDSES%##.%#' +!32>32#"&54>7&/#".54>754&#"#"&/>322>75z*"1*  ]3Xe'5 (LT_:;gL-BecAYA/ TvUZ.2/NE?{l1,< '/&+ BOB83- ^$9'!BeE ]3XeO=A@=E>E97+)&$  << +2#"&5467.54>32#!32>3232>"!4. ]3XeB4g~FAzn[p?^0TtHCaF/ 22R'!1* '"B_BOB5]%HȁjM=sl*`_/$AgK)X@C D+#X ,#@  B CR D+%!!54?3lһ%ā"*_ V6K#@  BC D+7#54? MfCLi D8&1 &Qv\'02@  BKPX@"YS C S DK"PX@,YSCQ  C S DK,PX@6YSCQ  C Q C SDK0PX@4YSCQ  C Q C SD@2YSCQ  CQ C SDYYYY@-+#!(# +!!!!!5#".54>3254.#"32>'P-T\\ꎡT@whhxAAxhhw@$xk  ly3ӔOOӄӓNNHu0@K@ . BK PX@,h  [ S C SD@,h  [ S C SDY@$BA21GFAKBK:81@2@,*"  00+2#!32>32#"&'#".54>32>2654.#""!4.Rg;.MiA=Y@- 3!Wcj4w76du@@wf52"DhEGhE"e=`E*&Vv:&6>&V&< DV&= NFU&]vV&=XFU&]V&=XFU&]j#6@3 BYSCTD###"+#5432>7'.=37>3#"!Y<-Q?,Y.Q@- B&͹^9:\DIƿb:]Dd @Bk D' +#"/+3dw {ߦ~~ d@Bk D+ +32>?>;#{   wߦ }  } RDq D @W D +".5332>532MhA~"9++9"~Ai+Ib7!9((9!7bI+@SD($+#".54>32#.-""-.#:-""-/##/jk=KPX@WSD@[OSGY$&($+4>32#".732654&#"j 7H()I8 8I)(H7 d6/-77-/6#*D22D*)D00D),88,-88 YKPX@ B@@ B@YKPX@ SD@jSDY@ +2#"&54>732> ]3Xe+;"\*"1* BOB;6/ '/&+ YQK.PX@WS D@O[SGY@ +2673#".#"#4>32$'l/A(#=60Ho0B'#=6/-*,/O8"X0O9"^ #@ SD   #++7>3!+7>3 J !!V!  0!YBK(PX@SCS D@SC CSDY@! 6##++#!#"&'7>3265#54>3sy"BB9 H$rw K >B|@   @MQE+!!  @MQE+!!2:'(+.5467rYP7 0a0ZE"  ,16 D&  ZF(+'.547>54&'&547YO7 0`0[E"  -16 D&  ZF(+%'.547>54&'&547YO7 0`0[E"  -16 D&  :W1(+.5467.5467rYP7 YP7 0a0ZE"  ,16 D&  ,0a0ZE"  ,16 D&  Zv1(+'.547>54&'&547%'.547>54&'&547YO7 YO7 0`0[E"  -16 D&  ,0`0[E"  -16 D&  Zv1(+%'.547>54&'&547%'.547>54&'&547YO7 YO7 0`0[E"  -16 D&  ,0`0[E"  -16 D&  v3@0 BCSCD#$&"+4632632>72!#"'!v)+"LPP'(57&NE,(x&75(w0 0<` v/G@D %$ B[C SCD/.$$#$&" +4632632>72!!#.'#"'"&=!!v)+"LPP'(57&NE,(x(,EN&75(NE+)w0 0<<00<X,KPX@ SD@OSGY($+4>32#".;dLMe;;eMLd;SMe;;eMMd;;dXV';@SD((((($+74>32#".%4>32#".%4>32#".X!..""..!!..""..!!..""..!n."".-""-."".-""-."".-""-H'1EYmKPX@+[   [SC  S  DK"PX@/[   [SC C  S D@3[   [ CSC C  S DYY@~|trjh`^VT((%#&((($+#".54>324.#"32>>;+#".54>324.#"32>%#".54>324.#"32>4Wt?DsV00VsDCuU11A%%A00A%%A1  54Ws?DsV00VsDCtV01A%%A00A%%A1h4Wt?DsV00VsDCuU11A%%A00A%%A1?T[00[TV\00\VB\;;\BA[99[}  RT[00[TV\00\VB]::]BAZ99ZAT[00[TV\00\VB]::]BAZ99Z(+5:  :   (+'&54767&'&54?:   :{   D# @ C D#"+'+>;,L2. M5\ "rG[@X 5 Bh  h [   [SC S  DGF@?>=9720"###%$+3>32#".#"!#!!#!32>32#".'#53&45467#"_lF=%>aK #j6R<+   KFЏtW~ˏLdXD &.&7(8 % FfqOӃf)@I)&C@@BhS  CS  D&&!4) +>7>;#7+"'#32'###5  jn  nj ~U/ mKMHP iiV~71@.1BSCS D76***+!>54.#"!"&=!5.54>32!#DQc7E{dd{E7bQ$`l;cc;m`$Ag]km88mk]gAJ#d`e֚VVրe`d#\2*>C@@0Bh[SCSD,+64+>,>#'(($+>32#".54>32>54&#"#"&'2>7.#"\'INV3Zh9IݔVh:Lph0|*G8*  xBw`G &>W:TX- mWAfF%b @ B CR D+3!%!.'`SM   g:"";> $@!Q CD +##!##5 WWT&@#BQ CQD+!!!!5467 .5Te=Q u ;4;A  \@MQE+!!\."@ Bj[ D,# +#"&=!2>7>;#)O  s֕!)9e D"8GP: ';OL@IK-B[  O  SG=<)(GE32>32%2>7.#"!2>54.#"8[MAAL\7>qU22Uq>7\LAAM[8>pV22VpO$>7227>$$?00?$?//?$$>8228>";L**L;"0Y|LL|X1";L**L;"1X|LL|Y05E''E4/H00H//H00H/4E''E5\#(@%BSCSD6''"+>32#"#"&'7>32>7v&E do AcK#J   :W=%CV  mvf_- L ;]B~7@0!/"BK PX@+[[ O[ SGKPX@$[[ WSD@+[[ O[ SGYY@42+)&$77  +2>7#".#"'>322>7#".#"'>326." #p=4ge_-8." #qB5hd_-6." #p=4ge_-8." #qB5hd_Z r/.!(!  m31!)!  q0.!)! m31!(!~kK PX@)^_ ZMQE@'jk ZMQEY@  +!733!!!#7!5!7!rr_2wwK_VȇP!@@MQE+!!G.32yz   z{ P!@ @MQE+5467%67.'%.=!5!)81GJz   z"@ BMQE+3 #>7 &'|z|  54&&EF+#&@CD+3#!a@ BK2PX@SCQC D@YSC DY@!!U%+3'.=354>32#"&#"!#!p:ts&O dT] I8]p> ] 3`BK&PX@SCQC DK2PX@"CSCQC D@ YCSC DYY@A!% +3'.=354>32;#.#"!!p4hhSHd6m(] I6TpB Y*6 @SD  +2+h  >1P 2H4  @ja  +2#"&'% Ӌ  v'@OSG((($+#".54>32#".54>32)'')((((''))''))D'"@MQE+!!D"j  @ja #++7>3    x@Bja* +#"&/&'+73x     __ x@ Bja,!+#'32>?>;     ^^J (@%jOSG   +"&53326533sNVVNssr;==;i|@OSG($+#".54>32"-,!!,-",!!,,"",v-!@[OSG$&($+4>32#".732654&#"v3D&'E55E'&D3Y6/-77-/6{'B//B'&@..@&+99+-88V1@.O[SG +2673#".#"#4>32#%b*>(#@;4"%d+?'#@:4)%+H5+$+I4N  +@(OSG   #++7>3!+7>3V&!`(   | @SD  +2+   >9 !;ZBGC_<ʓ^pӡD- V DC'-6j$H~RXXJ `d^dX<hl(lln`"lVP ZZlZfx<R0<\<\$:PVXXZf&\^J^HJ2XjXXHP^H&d>,XzFX,XXXt4,Xrf<D\d<DfFdRTfXz:*"|fxHffD,P P P P P P BZZffff*2<\<\<\<\<\~<\\\\\\\`\JJJJJRLXXHXHXHXHXHdX@XzXzXzXzPP \ZZJJ>,6X\HH:d>$:d>VFVFVFjffff ffjfff^0Xj:ZZ:ZZvvX HxxfD"@V\pX>XTz.X: tffffDffffffvffNfl#`  JNJ#$J&*2490:0<?0DFGHRTmNoNyN}NJJJJJJJJNNNNNJ J  N  J # $J & * 2 4 90 :0 < ?0 D F G H R T mN oN yN }N J J J J J J J  J  N N   N N N J # & * 2 4 F G H R T J  N  J # $J & * 2 4 90 :0 < ?0 D F G H R T mN oN yN }N J J J J J J J  J  N N   N N N J  x#&*247L9L:#>&>*>2>4>F>G>H>R>T>>>>>>>>>>>>>>>>>>>>>>>>?J? J? J??"?#?&?*?-2?2?4?7|?8?9x?:?<\??x?Y?\?lJ?m?o?rJ?tH?uH?y?{H?|J?}????????????\???\???J?J?J?J????JDD D DYDZD\DlDrDtDuD{D|DDDDDEE E E E9E:E?E@EYE[E\E`ElErE|EEEEEHH H H H9H:H?H@HYH[H\H`HlHrH|HHHHHIDI DI DI~I~IlDIrDItdIudI{dI|DIDIDI~IDIDI~IDKK K KYKZK\KlKrKtKuK{K|KKKKKNFNGNHNRNTNNNNNNNNNNNNNNNPP P PYPZP\PlPrPtPuP{P|PPPPPQQ Q QYQZQ\QlQrQtQuQ{Q|QQQQQRR R R R9R:R?R@RYR[R\R`RlRrR|RRRRRSS S S S9S:S?S@SYS[S\S`SlSrS|SSSSSU|U|UDUUUUUUUUU|U|Y Y|Y|YY$YFYGYHYRYTYYYYYYYYYYYYYYYYYYYYYYYY|Y|YZZZZ[F[G[H[R[T[[[[[[[[[[[[[[[\ \|\|\\$\F\G\H\R\T\\\\\\\\\\\\\\\\\\\\\\\\|\|\^#^&^*^2^4^F^G^H^R^T^^^^^^^^^^^^^^^^^^^^^^^^l JllNllJl#l$Jl&l*l2l4l90l:0l<l?0lDlFlGlHlRlTlmNloNlyNl}NlJlJlJlJlJlJlJllllllllllllllllllllllllllllJllllllllNlNlllNlNlNlJmNm m Nm Nmxmxmm$m7Lm9m:m;m<`m=m?mlNmrNm|Nmmmmmmmm`mm`mmmmNmNmxmNmNmxmNmoNo o No Noxoxoo$o7Lo9o:o;o<`o=o?olNorNo|Noooooooo`oo`ooooNoNoxoNoNoxoNopp p p p pppp$p7p9p;p<p=p?p@p`plprp|pppppppppppppppppppppr JrrNrrJr#r$Jr&r*r2r4r90r:0r<r?0rDrFrGrHrRrTrmNroNryNr}NrJrJrJrJrJrJrJrrrrrrrrrrrrrrrrrrrrrrrrrrrrJrrrrrrrrNrNrrrNrNrNrJt HtHt$Ht9:t::t<(t?:tHtHtHtHtHtHtHt(tHt(tHu HuHu$Hu9:u::u<(u?:uHuHuHuHuHuHuHu(uHu(uHyNy y Ny Nyxyxyy$y7Ly9y:y;y<`y=y?ylNyrNy|Nyyyyyyyy`yy`yyyyNyNyxyNyNyxyNy{ H{H{$H{9:{::{<({?:{H{H{H{H{H{H{H{({H{({H| J||N||J|#|$J|&|*|2|4|90|:0|<|?0|D|F|G|H|R|T|mN|oN|yN|}N|J|J|J|J|J|J|J||||||||||||||||||||||||||||J||||||||N|N|||N|N|N|J}N} } N} N}x}x}}$}7L}9}:};}<`}=}?}lN}rN}|N}}}}}}}}`}}`}}}}N}N}x}N}N}x}N}J J J"#&*-2247|89x:<\?xY\lJmorJtHuHy{H|J}\\JJJJJJ J J"#&*-2247|89x:<\?xY\lJmorJtHuHy{H|J}\\JJJJJJ J J"#&*-2247|89x:<\?xY\lJmorJtHuHy{H|J}\\JJJJJJ J J"#&*-2247|89x:<\?xY\lJmorJtHuHy{H|J}\\JJJJJJ J J"#&*-2247|89x:<\?xY\lJmorJtHuHy{H|J}\\JJJJJJ J J"#&*-2247|89x:<\?xY\lJmorJtHuHy{H|J}\\JJJJJjmjojyj}jjjjjj $79;<=?@`lr| $79;<=?@`lr| $79;<=?@`lr| $79;<=?@`lr| $79;<=?@`lr| $79;<=?@`lr| $ $ $ $ \  h`h\""#$\&*-824DF`G`H`JTPQR`ST`UVXYZ[|\lm`o`rt2u2wy`{2|}`\\\\\\\````````````\`````hh```\ $79;<=?@`lr| YZ\lrtu{| YZ\lrtu{| YZ\lrtu{| YZ\lrtu{| YZ\lrtu{| YZ\lrtu{| 9:?@Y[\`lr| 9:?@Y[\`lr| 9:?@Y[\`lr| 9:?@Y[\`lr| 9:?@Y[\`lr| YZ\lrtu{| 9:?@Y[\`lr| 9:?@Y[\`lr| 9:?@Y[\`lr| 9:?@Y[\`lr| 9:?@Y[\`lr| 9:?@Y[\`lr| 9:?@Y[\`lr|J J J"#&*-2247|89x:<\?xY\lJmorJtHuHy{H|J}\\JJJJJ YZ\lrtu{|jmjojyj}jjjjjj 9:?@Y[\`lr|t t t9^:&`.d8TvlHPTn"`N*ZN  z !!"# #j##$n$$% %l%&&X&&'('l''(l))*>*J*V*b*n*z**++++,,, ,,,8,,,,,,,,------......../00000000111111112(2222223d3p44445d6"6<6p66678T8`8l8x888888889*9R9999:4::;;x;;;<<0<~<==j=>>p?~???@~@ADAABBNBhBC8CD8DDEEHE^EF8F`FFFGG4GbGGGH@HzHb"/n n* ( 0/ G V 2 2J |> X l t T  P  `> 0   0  d  8 4Copyright (c) 2010-2013 by tyPoland Lukasz Dziedzic with Reserved Font Name "Lato". Licensed under the SIL Open Font License, Version 1.1.LatoRegulartyPolandLukaszDziedzic: Lato Regular: 2013Lato RegularVersion 1.105; Western+Polish opensourceLato-RegularLato is a trademark of tyPoland Lukasz Dziedzic.tyPoland Lukasz DziedzicLukasz DziedzicLato is a sanserif typeface family designed in the Summer 2010 by Warsaw-based designer Lukasz Dziedzic ("Lato" means "Summer" in Polish). It tries to carefully balance some potentially conflicting priorities: it should seem quite "transparent" when used in body text but would display some original traits when used in larger sizes. The classical proportions, particularly visible in the uppercase, give the letterforms familiar harmony and elegance. At the same time, its sleek sanserif look makes evident the fact that Lato was designed in 2010, even though it does not follow any current trend. The semi-rounded details of the letters give Lato a feeling of warmth, while the strong structure provides stability and seriousness.http://www.typoland.com/http://www.typoland.com/designers/Lukasz_Dziedzic/Copyright (c) 2010-2013 by tyPoland Lukasz Dziedzic (http://www.typoland.com/) with Reserved Font Name "Lato". Licensed under the SIL Open Font License, Version 1.1 (http://scripts.sil.org/OFL).http://scripts.sil.org/OFLCopyright (c) 2010-2013 by tyPoland Lukasz Dziedzic with Reserved Font Name "Lato". Licensed under the SIL Open Font License, Version 1.1.LatoRegulartyPolandLukaszDziedzic: Lato Regular: 2013Lato-RegularVersion 1.105; Western+Polish opensourceLato is a trademark of tyPoland Lukasz Dziedzic.tyPoland Lukasz DziedzicLukasz DziedzicLato is a sanserif typeface family designed in the Summer 2010 by Warsaw-based designer Lukasz Dziedzic ("Lato" means "Summer" in Polish). It tries to carefully balance some potentially conflicting priorities: it should seem quite "transparent" when used in body text but would display some original traits when used in larger sizes. The classical proportions, particularly visible in the uppercase, give the letterforms familiar harmony and elegance. At the same time, its sleek sanserif look makes evident the fact that Lato was designed in 2010, even though it does not follow any current trend. The semi-rounded details of the letters give Lato a feeling of warmth, while the strong structure provides stability and seriousness.http://www.typoland.com/http://www.typoland.com/designers/Lukasz_Dziedzic/Copyright (c) 2010-2013 by tyPoland Lukasz Dziedzic (http://www.typoland.com/) with Reserved Font Name "Lato". Licensed under the SIL Open Font License, Version 1.1 (http://scripts.sil.org/OFL).http://scripts.sil.org/OFLtx  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghjikmlnoqprsutvwxzy{}|~      !"#NULLuni00A0uni00ADmacronperiodcenteredAogonekaogonekEogonekeogonekNacutenacuteSacutesacuteZacutezacute Zdotaccent zdotaccentuni02C9EuroDeltauni2669undercommaaccent grave.case dieresis.case macron.case acute.casecircumflex.case caron.case breve.casedotaccent.case ring.case tilde.casehungarumlaut.case caron.saltVV, `f-, d P&ZE[X!#!X PPX!@Y 8PX!8YY Ead(PX! E 0PX!0Y PX f a PX` PX! ` 6PX!6``YYY+YY#PXeYY-, E %ad CPX#B#B!!Y`-,#!#! dbB #B *! C +0%QX`PaRYX#Y! @SX+!@Y#PXeY-,C+C`B-,#B# #Bab`*-, E EcEb`D`-, E +#%` E#a d PX!0PX @YY#PXeY%#aDD`-,EaD- ,` CJPX #BY CJRX #BY- , b c#a C` ` #B#- ,KTXDY$ e#x- ,KQXKSXDY!Y$e#x- , CUX CaB +YC%B %B %B# %PXC`%B #a *!#a #a *!C`%B%a *!Y CG CG`b EcEb`#DC>C`B-,ETX #B `a  BB` +m+"Y-,+-,+-,+-,+-,+-,+-,+-,+-,+-, +-,+ETX #B `a  BB` +m+"Y-,+-,+-,+-,+-,+-,+- ,+-!,+-",+-#, +-$, <`-%, ` ` C#`C%a`$*!-&,%+%*-', G EcEb`#a8# UX G EcEb`#a8!Y-(,ETX'*0"Y-),+ETX'*0"Y-*, 5`-+,EcEb+EcEb+D>#8**-,, < G EcEb`Ca8--,.<-., < G EcEb`CaCc8-/,% . G#B%IG#G#a Xb!Y#B.*-0,%%G#G#aE+e.# <8-1,%% .G#G#a #BE+ `PX @QX  &YBB# C #G#G#a#F`Cb` + a C`d#CadPXCaC`Y%ba# &#Fa8#CF%CG#G#a` Cb`# +#C`+%a%b&a %`d#%`dPX!#!Y# &#Fa8Y-2, & .G#G#a#<8-3, #B F#G+#a8-4,%%G#G#aTX. <#!%%G#G#a %%G#G#a%%I%aEc# Xb!YcEb`#.# <8#!Y-5, C .G#G#a ` `fb# <8-6,# .F%FRX ,1+!# <#B#8&+C.&+-?, G#B.,*-@, G#B.,*-A,-*-B,/*-C,E# . F#a8&+-D,#BC+-E,<+-F,<+-G,<+-H,<+-I,=+-J,=+-K,=+-L,=+-M,9+-N,9+-O,9+-P,9+-Q,;+-R,;+-S,;+-T,;+-U,>+-V,>+-W,>+-X,>+-Y,:+-Z,:+-[,:+-\,:+-],2+.&+-^,2+6+-_,2+7+-`,2+8+-a,3+.&+-b,3+6+-c,3+7+-d,3+8+-e,4+.&+-f,4+6+-g,4+7+-h,4+8+-i,5+.&+-j,5+6+-k,5+7+-l,5+8+-m,+e$Px0-KKRXYc #D#pE (`f UX%aEc#b#D * **Y( ERD *D$QX@XD&QXXDYYYYDPK!ZooA2.2.0/rdoc/generator/template/darkfish/fonts/Lato-LightItalic.ttfnu[GPOS'HPGSUBV.TIlOS/28J|`cmapRԟJcvt &6e8fpgm zAe gaspeglyf^Oheadd6hhea1$hmtx?kTkernOQ@gloca)N4,maxp> P` nameBbdP}post:\bprepx9op 0JDFLTlatnkernkernGrTv   V 8,^$^ 0 DJJJL F !z" ##P#$4$~%x&&'()*++,J,-n../$/V///1242n2233V3344J4445567778~88:;";;<=2>,?&?@ABC8CDE.F(> [jyj[$[9>:A</?>DFGHRTmyoyyy}y[[[[[[[/[/yyjjyjyy[> [jyj[$[9>:A</?>DFGHRTmyoyyy}y[[[[[[[/[/yyjjyjyy[-#&*24DFGHRTkp> [jyj[$[9>:A</?>DFGHRTmyoyyy}y[[[[[[[/[/yyjjyjyy[0= = =I#&*247A9=:m > >GG"F#$&*-o24DFGHPQRSTUVXYZ\]kl>mopr>tPuPwy{P|>}>>G>>GG$ $79;<=?@`lr|:V V V#&*-224789: LL"$-.DFGHPQRSTUXwLLL $+  #&*24IWYZ\klmopry|}3 $#&*24789V:y<=?VYzZ\zklm$o$prt=u=y${=|}$=zz=$$$$$$ $79;<=?@`lr|/ ==$-VDFGHRT===$ $79;<=?@`lr|#&*2478kpf LLL]]"-#$&*-824D)F)G)H)JAP]Q]R)S]T)U]VFX]YQZy[b\L]ekmLoLpw]yL}L)))))))))))))]))))))]]]]QQ)))])FFeeeLLLLLLLL $q> > >GG"F#$&*-o24DFGHPQRSTUVXYZ\]kl>mopr>tPuPwy{P|>}>>G>>GGNF F F$-DFGHJPQRSTUVXlFrFt<u<w{<|FFFFF+  #&*24IWYZ\klmopry|}m4 ~ 4 4[V[~"2#$~&*-824DGFGGGHGJ_PQRGSTGUVGX]kl4mVoVpr4t2u2wyV{2|4}V~~~~~~~GGGGGGGGGGGGGGGGGGG~GGGGGGVV44[44[V[VV~" #&*24kmopy}-#&*24DFGHRTkp:V V V#&*-224789: [jyj[$[9>:A</?>DFGHRTmyoyyy}y[[[[[[[/[/yyjjyjyy[&y y yjj$7G9; [jyj[$[9>:A</?>DFGHRTmyoyyy}y[[[[[[[/[/yyjjyjyy[ ee$e9F:F<(?Feeeeeee(e(e ee$e9F:F<(?Feeeeeee(e(e&y y yjj$7G9; [jyj[$[9>:A</?>DFGHRTmyoyyy}y[[[[[[[/[/yyjjyjyy[&y y yjj$7G9; [jyj[$[9>:A</?>DFGHRTmyoyyy}y[[[[[[[/[/yyjjyjyy[> [jyj[$[9>:A</?>DFGHRTmyoyyy}y[[[[[[[/[/yyjjyjyy[0= = =I#&*247A9=:m [jyj[$[9>:A</?>DFGHRTmyoyyy}y[[[[[[[/[/yyjjyjyy[> [jyj[$[9>:A</?>DFGHRTmyoyyy}y[[[[[[[/[/yyjjyjyy[0= = =I#&*247A9=:m [jyj[$[9>:A</?>DFGHRTmyoyyy}y[[[[[[[/[/yyjjyjyy[:V V V#&*-224789:?EHIKNPQRSUYZ[\^klmoprtuy{|} 8DFLTlatncase&case,liga2liga8sups>supsD,>B      @ LO,{tu CjqvI,xxAP`KtyPLJz  &   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ardeixpkvjsgwl|cnm}byqz`T@ ~1DS[a~    " & 0 : D !"!&"""""""+"H"`"e%&i 1ARZ`x    & 0 9 D !"!&"""""""+"H"`"d%&i{uq[H$I޸ޡޞ:ڜ`T@ ~1DS[a~    " & 0 : D !"!&"""""""+"H"`"e%&i 1ARZ`x    & 0 9 D !"!&"""""""+"H"`"d%&i{uq[H$I޸ޡޞ:ڜ/,8<@BK PX@3 `f[[ Q CQ D@4hf[[ Q CQ DY@@?>=<;:9751/+)&$$ +>32#'.<54>54.#"#"'4632#"&!!7!!374>32#"&F  >F!""'5-PS\88\SP-<""!5t ,@) Bk D   $+#"&'7!#"&'7e$  &]$  &ܚ$ܚ$Pr:>yK)PX@(  Y  C Q C D@&  Z  Y  C DY@>=<;::5320-,'%#"!#!+#"&547!+#"546?3#76;>;!323+32%!!' Ԇ)ۂ )։(+)   ,E  l%D  m$yErB[9DO@! *BK PX@2j  h f_ SC SD@1j  h fk SC SDY@LKA@#$#$ +.'7632.54>?>;#".'+4.'>ေ>  "/AU8oc6M9*,6Tl}8'0DXuKPX@+[ [SC C SD@/[ [ CSC C SDY@ US((%"&((($ +#".54>324.#"32>>;+#".54>324.#"32>7Zt>3W?#4XvA3V?$J.>$0XC'-?$0WC(XAB7Zt>3W>#4XuA3V?$J.=$0XC(.?$0WB(qgh4&ImGgi5&JmI7>;#"&/#".54>7.54>32>7>hJ)40K6=eI(>;a2A <TDM/lzGG|\6:cM106b0.J_2>si^(GrP,)Kh?  E:%,Mi>EINHG ^[ 3V>#-U|NRy\FFPd8BeD"!:P/Vize @ Bk D $+#"&'7e$  &ܚ$H  (+.54>7!2! ++<' 4UxR& S~T+OH  XPVr w  (+4.'&546?'&547>\!1! ++<' 4UxR& S~T++OH  YPVr w ;*@'40/+'&" Bja;;+7>7'7>7./7.5<?3>?'.'x    2   n+n  n,n   n,n  n+n   3 .@+jkMRF +!!#!7!7O7L8Q 8=G;G?@B ?S D"+74632'.54>7#"&?0'+/(8"'$ %/U#2;0)URL  %9J,2c*x@MQE+!!n RxN:@SD&$+74>32#"&:!#7''5M""'55@kD""++6; !&''/$Z`',@)SCSD'' +2#".54>2>54.#"\r@by\r@b.cQ5\}GcQ5]}HّjHّGj_)ʂz;_Ƀ{;)@&Bh CR D$+%!7#"/3!!F I5(HE 'iHF51<@9- BhSCQ D+)#! 11+2>3!2!7>7>54.#"#"/>Kc9;eK G#hq !K}Z2-Mf9Du_F.\~*S}R[D8!5! C{|NCcA 'Ig?Zb4q<HU@RD Bhh[SCSDB@:80/.-%#HH +2#".'763232>54.#7>54.#"#"/>K`73XwCEgF#Qhaf< ) 2OpNag6$Vm ak8,Kd9Dv`F.[~)OvLP~^? 7Oe:`xD.\Y GhF"Ci@7aG)B2X|L@_?'Hg@Zb4>^+@( B\ C D!#+!+#!"&/367!Z1T2g;Tk 5b2 i - 'g8-@@=+*Bh[Q CSD(#&(""+#!632#".'763232>54.#"'!2kgg3[m:hXI  -HgF[yF(TXn8{_$6aP}NJJ#-'%=riBmN,%r32@/B[ CSD0.&$ +2#".54>7>;>32>54.#"Tb6QoYf7:Z> Q&>B*PsJ^p=,QtG_o=M5`RlJ7h\:qwH *K#?G-DtU0=lWFrP+Do$@!BQ C D$'++>7!"&57 H. #   >f&%;OD@A B[SCSD=<'&GE7.54>32'2>54.#"2>54.#"^m<6`MmpBxfW_1)MpH6]E'2XwE2^H+Z22@/B[SC D/-%# +".54>32+>74.#"32>MP^3OiUc5:V7H T >BV+NnBVl=)MnD]i8Z3\OfI8fVDrosEI&L)BHCqQ-9gVClK(Ai:Z;K#PX@SCSD@[SDY&&&$+74>32#"&4>32#"&:!#7''5f!#7''5M""'55D""'55<e)K@ B ?K#PX@SCS D@[S DY@ (& "+74632'.54>7#"&4>32#"&<0'+/(8"'$ %/o!#7''5U#2;0)URL  %9J,2<""'55 5(+%(BA     c!@YMQE+!!!!; /:+GG 5(+ 767>7&'&5<>7L%(A    ~'95@2BhfSCSD(&#,$+>32#7>54.#"#"'4>32#"&EQ\4=gK*1LYQ< @9NZL2 9M,>\@( "!""'5 3'&Fa;SvXA<>(,E>?PhH/K5#*# g""!5a2Wlf@c ^ ?Bh[  [  [OSGYXb`XlYlOMCA=;86,*"  WW +%"&5<7#".54>3232>54.#"3267632#".54>32%2>7.#"IG?L-B*!>ZqN1T!';sZ7Lg\a7Vz_ o^JP[ǡq=I҉ՙTD?lT7%AXck4!9*X $@!BZ C D# +!#"&'!+3!.'XLeLb>E   b z*5*=@: B[S CS D*(" !+3!2# !2654.#%!2>54&#!yfb/,QtICsJD)OsJa\,*OrHD|eIybp<:]B$H:_zAw~/D@A BhfSCSD'%" //+%2>32#".546$32#".#"ItZA. #.ixPzŋKp ItaQ&  )N}`aBvE%+%*/K5X⊹3y,B*( ,5,h|NjJ-@S CS D!(!&+#!!24.#!!2>-1[g$}ʍLg?uhxޢZ/}ڵb3Uދy†Hc? (@%YQ CQ D+!!!!!!4WG7 I 5PR? "@YQ C D+!!!#!4WJO Pd5Su9G@D$ Bh[SCSD1/(& 99+%2>7#"504>7!#".546$32#"'.#"CobZ-0k?5o}R͐MnM~hV&  '7Kb?]BzA*  %:'Y㊻3w,@)'!h|njK! @Z C D+!#!#3!3sdSSddR(RdYk@ C D+!#3 dd'@$Bh CSD#%$+#"&'7>3232>73}HnW6Y+  #1#;lW= xduq76%Wi &@# B\ C D'(% +3267>;#"&'.+#3^M"(PQ~P * TTcdL X f  UX@ CR D+7!!3h 6cUU<!'@$Bh C D!6(+67>;#>7+"'#32- ~EW nWD   y #F!@B C D!+2>73#"'#3b W. QW1 0 y-Gq'@SCSD((($+#".546$324.#"32>qm|ȍLn}ɍLg?vgޣ\@vgޢ[0xY≺3xY{ŋKh{ŊKg? /@,[S C D   !+#!2# 32>54&#GFcTJvT^k:;lHSq5aU#N ||ȍLn}ɍLg?vgޣ\@vgޢ[0⼓1{ C2Y≺3xY{ŋKh{ŊKg3!7@4 B[S C D! *!+#!2#"'.# 32>54&#POcP54.54>32  ";]FLwS,2QgmgQ2B{mS:((0GgKQsDKH @Q C D+!#!7 8c6 T3T#@  CSD +%2>73#".5473o]uL kdl]sgo:kdl-WFH~clu˖VG|e,-l(Th; @B C D, +32>7>;#O&   GN:Y c00 y~( @#B C D+; +32>7>;2>7>;#.'#N MY Yh)) h)) y  /@ B C D)"'!+ 32676; #"&'+Y -cY   b  4r p @ B C D,"+#32>7>;gIcIX+ SGH? d!  ,$@!Q CQ D+!!7>7!728 A  !  R! RDD'@$[OQE!#+!+32D& ̼ #   qH@kD" +32#"&'q'' %$+ '@$ B[OQE!#+!!7>;#"5(˻ # v @ Bk D+!+3#"&'&'+\;UC   F L1@MQE+!7 +AA~@kD+2#"/s5 <s+^@ BK%PX@SCS D@SC CSDY@ #!++*' +!#"&5#".54>322>7&#".!&[gr=?^? ,QpR32#"&'#"32>54&f]a'`ju32#".#"32>325_[^5VT*!>XnI1OB6 1N;Tk=AbC5TA1& ;L,;jVOvV1#2! % ZlEvV0")" @.p@ "BK%PX@CSCS D@!CSC CSDY@&$.. +!"&5#".54>323%2>7.#"!'alv=AbB" ;UlIQ,I\I9rk]$#+E?mYE/f =Q_42\QLb9GGKQ@?tc N@3Xt@FF,=7@42BhSCSD.--=.=*&%,+32>32#".54>32%">54.F8`Ќ5UC3( 1]_f:SX.;WpOIe?PcCO,,G%)JB;1')$($ 4K07eZKzZ4)=GgDqQ%)0361(B%^BK!PX@kSCQD@kYSDY@%%!$%$ ++'&546737>32#"&#"!2j*#~ :Wn?8  (-Q?-  ~w ~UV+ 0 AhK{F>Td@<& CBBKPX@+ [[CSCSD@.h [[SCSDY@VU^\UdVdQOGD7642*( +#".54>32.5467#".54>32!4&'.#"32>2>54&#"(/(#*#@tdO_4Kb"D#")[69bG(1]W3Z# l 1X)ca1'Hf>N[2@eF$n]@dE$l7ZKA>@$3016@'?uZ6 =X8HoL(4 #H3$GgDEh?  L1F%?T.+C-*FZ 6Wo8hi3Tm9jnf,@)BCSC D%%+33>32#654&#"f^\(akp9po ^KMS6pi^$AKuQ*2]|.)fj7gZx&@#SCC D +##".54>32Ny]yW !m(4@1 BSCCSD%#!%%+#"&'7>323267#".54>32J(?W5)JR 4XA% XQbW !c0@-B\CC D%(%!+3267>;#"&'.+#rm% R9   lP $=] { _   u@C D+33u]Q^5Z@  BK)PX@SC D@CSC DY@55%&($! +332>32>32#>54&#"#654&#"^x+#NqdU']gl5k^ ]K>M1eaW#C]K :JrI?$ꛫ~v"'PwO'} 6_|7Z]-Z\|E6TWо^!P@ BK)PX@SC D@CSC DY@ !!%&!+332>32#654&#"^x+")cnt;op ^KMS8rk^$=$O}W- 2[|.)ej9i]G%,@)SCSD%% +%2>54&#"".54>32Wf7~:fVE/wP]3HlP]3I>[g)JexFK8j`yߪe9i^yޫf2-m@ !BK)PX@SCSCD@!CSCSCDY@%#--*&!+32>32#"&'"32>54&2+# 'amv=AbB" ;UlHQ+;9sj^$#,E?mYE/fF$Q_42[PMb9HF?tdO@3XuA<s.6@3#BSCSCD&$..*) +#"&547#".54>322>?&#"6O&Yeo32&#"^x+#Dc)+.(k=<$أY!<=@:<BhfSCSD:8'%" #!+#".#"#"&'7>3232>54.54>32 2J73[C'&?OTO?&3^Ra/ 5R>;aE&&>PSP>&2Z|JT|0i"9K*)8)%4K5@x]8C6" ' 'DY2,<+#2H4:kS144l@+g@ &BK!PX@#jhQCSD@!jh\SDY@ %#(&&+74>7#"5?>;!!32>32#"&DB ./ E=0!3&(r9R]$9,5) d G)4!A:**3Zr"P@ BK%PX@CT D@C CTDY@ ""'!%+32>73#"&5#"&54>7!KMS7pj^$@^x,)cmt:oo /(fk8i\O|U- 3ZS@BC D+ +3267>;#SI  GN ,*0 Vx) @#BC D(!+: +32>76;2>7>;#"'&5+VC V$ F BVD B))** (V@BC D("(!+3267>; #"&'+sP    TP   Pr q 0  Q V@ BCD,"!++32>7>;CJ   I   <@QCQ D+!!7>7!7!6a/ ^  K& MKGFD7@4"5B[[OSG<:303)+4𑯎&54>;+";20#".54>D9J\+NoE3:P1 '?.*")"'8#38U:#*#9I;tw<-TF3 )5 =vw{A)B0  %BY4D{ut@QD+3#KKD7@45"B[[OSG<:303)+3"+7>;2>54&54>7.54>54.+"&504>732D9J\+NoE3:P1 '>/*")"'9"37V:#*#9I;tw<-TF3 (6 =vw{A(C0  %BY4D{utP9@6jk[OSG +2>53#".#"#4>32%=*N 734632#"&D ) C 5'#7''5&-PS\88\SP-'7#'55/:K@H%BjhfkSCSD##'# +.54>?>;#".'>32+Vb4Lˀ# #)V.  4N8KlI* J]l:$ #)LmEir= @o`לX ;- "' 1% Q]7lJi=C@@+ Bh[SCS D%&%##(" +#!>3!#!7>7#7>;>32#"'.#"!a%'#/)5$=/*$ LzfPuQ4(  &;XAN`= $ ,F9/'@ #4I5W% )]uC%?V0 <.4_O$D#79@6! B @ ?WSD42*((+467'7>327'#"&''7.732>54.#"(#2-n?>n-1%))#1-n?>m,1$)H+Ib89cJ++Jc98bI+>m-2%*)$2-n?>m-2$)($2-m?8bI++Ib88cJ++Jc!8@5 B Z Y C D! +! +!32>7>;!!!!#!7!7![M   N[o/]/nhd## 9v88v@YQD+3#3#KKKKX}bEYA@>EWM:#BhfWSDCA,*'%!#!+#".#"#"&'763232>54.5467.54>32>54.'K  1I76[B%(BUXUB(^](22]Ta0  4P>>bD$ImmIdq*42Z}LS{0!8IPR$NC2CJL#`M #:N*)>3,-3AR7^&"U;Dy\5B6" % 'CY2=S@:GaGU)!V>;lR145&<2+(+&kE(?3*&&+gvqm%3K'PX@ S D@OSGY&(($+#".54>32#".54632 V 0"   "1 k/Ka@ BKPX@4hf[[ SCSDKPX@4hf[[ SCSD@4hf[[ SCSDYY@ ^\*,*(#&(%" +>32#".54>32#".#"32>4>32#".732>54.#"Y";t`s@Cwc4WJA !;[DSa55_Ld0:L@I!Bh[ WSD21651:2:%#00 +"&=#".54>7>454#"#"&/>32'26? 4cB2&)[go'8)   1i?*>)  =[+9G D.11!*H7! w/-1A$ 4Ya*5)KB.)%%(+77    =     z   { z   T=K PX@_MQE@kMQEY+!#!<.O$'c*x@MQE+!!n RxNq1GP<BKPX@/h  [ [SCSDKPX@/h  [ [SCSD@/h  [ [SCSDYY@22PNJH2G2F)!**,& +4>32#".732>54.#"#32#"'.#'32654&+q4^dd^44^cc^432#".732>54.#"0Qm>?nQ//Qn?>mQ0E$>U00T=$$=T00U>$n>mQ..Qm>>lQ//Ql>0T>$$>T00T?$$?T<P8 <@9jhZMQE  +!!#!7!!!2 O1L1S2VjGlGGV/g@ - BK!PX@h[SD@!h[OQEY@+)%# //+2>3!2!767%>54.#"#"/>(E33C%(' "=,#/9Z $V,?*-LD?!;>@$-B= `e|V>@:BKPX@,hh[[SD@1hh[[OSGY@8631+*)( >> +2#".'763232>54.#7>54.#"#"/>(D2UE@A+H^3!3C$  ('0;-!2RH+B;0I2T@kD"++7>3T7 $7@4#BCS CD$$&(!&+32673#"50>7#"&'#"&5RcjXH][z3K]Xn(.cmybX ;3X[JD*R#yB4*@'hiS D+##!#".54>34 UVm\h8EnR  y-SwKVi;@OSG($+4>32#".$&&$P&&%%TV@  BK PX@^jTD@jjTDY@+232654.'73#"&'764#3:(8"8:'JN2E(&D  2* a73!5% lQN BKPX@jjQD@jjMRFY$+37#"/733!C 9R%h5;#)@&WSD## +2#".54>2>54&#"7U;+OpE8V;+Oq7T8RR:U8R$C]9O[2$B]9O\2*MlBYk+NlAYj%#(+7'&54767&'&54?'&54767&'&54?     ' '   ' '  `(.Q@N" Bh  h   Z \  C D.-('&%$#%"#!" +%3+#7!"5'3+6;37#"/733!>7!n=A &$(C  9R'"U d#k%w h5t |H9Jb@_D=7Bhh   Z [  CT D JIHGFEB@;:52/- 9 9"" +%+6;2>3!2!7>7%>54.#"#*/>%37#"/733!w &$(y(E33C%(' "=,#/>X C  9R d#K,?*-LD?! ;>@$-F9`e %w h5rY_y@vU ! . B  h h  h [  [\ S C D_^SPMKEDCB:820*(YY"#!#+%3+#7!"5'3+6;%2#".'763232>54.#7>54.#"#*/>>7! n=A &$((D2UE@A+H^3!3C$ -%0;-!2RH+E80I2 |;(:5@2BhfSCSD('#,$+#".54>?332>324>32#"&;DP\4;gL+1KZP; >6MXK1!8K)=]B'!""'53'%Db>RtS=68%+?99KeG0L5$*$P""!5X&$ @X&$ HX&$ @X&$@X&$ @X&$@:@7BYYQ CS D# +!!!!!!+!!6 W XMwz  5PRb z5+Lh@e9? J Bhf hSCSC S  DHF>=750.&$!LL +232654.'7.546$32#".#"32>32#"&'76#3:(8"/rFp ItaQ&  )N}`aBvbItZA. #-dsLJN2E(&D  2* r^܅3y,B*( ,5,h|NjJ%+%*-I5L73!5% ?&( G?&( G?&( G?&( G&, &, &, &, E`!,@)YS CS D!%(!+3!2#!#%4.#!!!!2>MR}ɍLl$T?ugHsJxݡZUމry†H>c!&1q&2 q&2 q&2 q&2q&2 )C  (+  ' 7 )cF6Z,9C 3u3wp4pO!-9b@ 21&%BKPX@kCSCSD@jkSCSDY**%(%$+#"&'+7.546$327>;.#"%4&'32>qmhC")JNnmEz 4DHw:6%:`ޣ\"409Zޢ[0x>9Q卺3xE? QvE<@h(oE67g&8 &8 &8 &8 &< &Y,@)\[ C D"& +32+#3 32>54&#Ju#cd-T^k:ilHT54.54>54.#"+'&573>InJ%4MZM4.EQE.6_M]~0  3L::^B$/HRH/5O]O54T=A{cE p*#W|-I\.FdL<:A+)3'&7TBL\3C6! % (E]58F0#-B58RC=GZ?D9&Bv^zv (_K<s&DCT<&Dv-<s&D<h&D<m&Dj<s&D22jGWd@?E!BK)PX@5hh  [ S C SD@?hh  [ S CSC SDY@&YX^]XdYdSQIHCA=;860/'% GG+232>32#"&'#".54>?>54&#"#"/>32>32>7">54&Z7]D&>y5UD3( 0\`g:t[jo08]C%F \[BaF. Qcrt 9=0B'=oY< GtY; {4b ;Q0:hN0))$($ 3K1MjA8W32#".#"32>32#"&'76#3:(8"1OtM&!>XnI1OB6 1N;Tk=AbC5TA1& 2XVV/ JN2E(&D  2* u?iSOvV1#2! % ZlEvV0")" 7I,P73!5% FF&HCFF&HvFF&HFQm&Hja`&Cx'&vB%&IDm&jIy7I5@20B76 @[SD98A?8I9I,*" +&54?.'&54?7#".54>324654&'267.#"3vD QC +H4@~L^5Ayi1`TE\UI! +GeDZ`2*Hc. y#0 =3 o(f~Yn9h[mU9X=K,3dO1H|^M{V.^j&Q++G&RC++G&Rv++G&R++Gj&R++Go&Rj++3^#+@([YOSG&&&%+!!4>32#"&4>32#"&U%$.&$,X%$.%#-G{&1#%/Y&1#%/  *5u@ 43$#BKPX@!kCSCSD@!jkSCSDY@,++5,5'%  +"'+7.54>327>;&#"2>54&'YF !&+-HlDq-= 2u),I7GnWh9Wg9G K`5[yߪe(&S5XyޫfWGYAZkBn*GBr&XC++r&Xv++r&X++ro&Xj++V&\v++;0?@<"BCSCSCD(&00*%+3>32#"&'#"32>54&;]b'`ktC#?mYF/gN\32[PMb9HGE@ud'6"3XuAVo&\j++'0L@I-BAhZ C CSD)($"''+2#"&54>7.'!+332>!.'  Q+BK*6eLbg7.3*$E  !B:">6. b y $0<")0 +,<s4FK%PX@&;B@&;BYK%PX@*hSC SCSD@.hSC C SCSDY@65><5F6F1/('$"44 +2#"&54>7.5#".54>32#32>2>7&#",  Q+BK-8!&[gr=?^? ,QpR7!!!!!!#32>X  Q+BK*6 WG7 I p3+3*$!B:">6.RPR $0<")0 FFL]e@bR9@?Bh h SCSCSDNMM]N]IG>=750.LL +2#"&54>7"#".54>3232>32732>">54.C  Q+BK$/ SX.;WpOIe?8`Ќ5UC3( /XZ_6)-3+3*$PcCO,,G!B:93-7eZKzZ4)=G)JB;1')$($ 1H0 $0<")0 DqQ%)0361(xN@C D+#Ny]y0!@ B CR D+%!!7>?3g ~Dh 6H  [c= UMf@ ^S8@BC D+46?37#S L]H _\Z TvW2 VV!&1 ^&Qv++ 46@  BKPX@*YSCQ  C S DKPX@4YSCQ  CS C S DK#PX@*YSCQ  C S DK%PX@4YSCQ  CS C S D@2YSCQ  CQ C SDYYYY@1/'% (% +!!!!!#".54>324.#"32> ZG2 H '+qVo}CeWrQ,]7g]w̕U8h\x̔TRPR>N{U-Wއ6z5aVgx‰Kkx‰Ij68N]S@PT6$Bh S C SDPO:9O]P]FD9N:N42*(" 88 +232>32#"&'#".54>32>2>54.#"">54.=aD#8^ƃy5UD3( 0\`g:yUi~GOtK$Mix:8GrW>(:W;Zh88Z~H{_? {-0J 9O0%F@80'  $($ 3K1EnL):aEZuvI2Vs?CoO+Tۈ6fP0q:k_:EN'6)'&6 !&Vv++'&6 !&V++&< &,&= F <&]v++,&=F <&]++,&=F <&]++U%SKPX@ YSCSDKPX@ YSCSDKPX@ YSCSDKPX@ YSCSDKPX@ YSCSDKPX@ YSCSDKPX@ YSCSD@ YSCSDYYYYYYY@%%"" +#763>7'&546737>3#"!VwW%3eWE//"5dWE1f b\+/FqS  1 FqREoR @Bk D' +#"/+73R= { AS r @Bk D' +32?6;#A { ?S rq$qa @W D+".547332>73e5K.C 3&,?+C#=Y5H*4%3B&2ZD'2@SD($+#".54>32    F!!s=K'PX@WSD@[OSGY$&($+4>32#".732654&#"/?##?//?##?/:@32@@23@$<++<$$;,,;$2@@22@@7\ +@(B@jSD+2#"&54>732>F  Q+BK1>-3+3*$!B:%C:/ $0<")0 |nhQKPX@WS D@[OSGY@ +2673#".#"#>32(.9(6 1-+&0:)5 2,*7/$>.!(!:-$?-!'! #@ SD   #++7>3!+7>3 ) =-  Y\BK1PX@SCS D@SC CSDY@!$## ++#!#"&'7632327#7>3Yq]qVVsb0  V$d;ns & ! ld@MQE+!!+dEBd@MQE+!! VdE#(+&5467\H):#7;XB 1v?/*\(+'&5467>54&'&547E\H*8 7;XA 1v?, (+7'&5467>54&'&547\H*8 7;XA 1v?,#)(+&5467&5467\H):\H):#7;XB 1v?/*7;XB 1v?/*e+(+'&5467>54&'&547%'&5467>54&'&547T\H*8 8\H*8 7;XA 1v?,7;XA 1v?,+(+7'&5467>54&'&547%'&5467>54&'&547|\H*8 8\H*8 7;XA 1v?,7;XA 1v?,"YKPX@#CSCSCD@OCSCDY@ $!#"+>3>32>72! #"'!FK/  GLF=O  h=&  f6* BKPX@6   `   [CSCSC  D@1   `O   [CSC  DY@661.,+)'$##!##+%!7>3>32>72!!#.'#"'"&5467XFK/  GLFZ_FK,  G&OOM$ & +'  91|@OSG($+4>32#".9.Pi<=lP..Pl=32#"&%4>32#"&%4>32#"&:!#7''5!""'5!#7''5M""'55'""!5'""'55}'0DXlKPX@/[   [SC C  S D@3[   [ CSC C  S DY@}{sqig_]US((%"&((($+#".54>324.#"32>>;+#".54>324.#"32>%#".54>324.#"32>7Zt>3W?#4XvA3V?$J.>$0XC'-?$0WC(XAB7Zt>3W>#4XuA3V?$J.=$0XC(.?$0WB(6Zt?3W>#4XuA3V?$J.=$0WC'->$0WC'qgh4&ImGgi5&JmI32#".#"!#!!#!32>32#".5#73>7#Lqr@jWI %,@W:_`e 4aY>cM:)  )^l|Fnu<^ғN,A*$$@}u *X0 zC%+% !.K5Qه9/Y*H&9@6BhiS  D&&!4) +>7>;#7+"'#32'###7 6E<6  754.#"!"504>7!7.54>32!,dyDCv]p˛[0Y|L+3N]4lrÍPKghYyjn7I׎VhF Rw\YFv}͛h3W/AC@@5"Bh[SCSD10;90A1A#)**$+>32#".54>32>54&#"#"'2>7.#"%BBD&EjH& kԂClM)&EawK1WG4ol-G6% NKv_!7V?fr=t=# 5d^AI,SvKRtT/7T:NV&Fx4dN0``yi @ B CR D+)3!.'ijYj%&w $@!Q CD +##!##7w __ PiiP*@' BQ CQD+!!!767 &5467 IR RR$2- {@MQE+!!< GES"@Bj[ D+%!+!##"&5467!267>;RM9  7 )#( L';OL@IK-B[  O  SG=<)(GE32>32%2>7.#"!2>54.#"3O?3"HPX30T>$3Un<3O?3"GPX31U?$2Up(IDA -4@(-P=$-<m0Q;"-<$(ICA!,5?'BV..VB'$C`32#"&#"#"&'7>3232>7EZl;$4  `"Kas@;  6[J7>WU+ , dZ) ' GrQ7d@a!0"/B[[[ O SG42+)&$77  +2>7#".#"'>322>7#".#"'>3243-% #i83a]\.3,% #h<4a][2-& #h84a]\/3,$ $h<5a]Z( 8+.$,$ 6-/$,$ 8*/$,$ 6-0%+% pkK PX@)^_ ZMQE@'jk ZMQEY@  +!3!!!!#!7!7!F͇ FEZ>c GGGgPO@@MQE+!!&)$@A v>    xIuPQ@ @MQE+%!7!7>767.'&5<>7c AG&)$PI>    f"@ BMQE+3 # >7 .'BnBL  M  @@S ~@ja+3v 0@T%k@ BK!PX@"kSCQC D@ k[SC DY@ !&%$ +!#!+'&5737>32#"&#"8w^nFl*"~ DlX%$  ,"<}v *U\e6. @$@ BK!PX@$kSC QC DK%PX@"k [SC DK)PX@&k [CSC D@-hk [CSC DYYY@$$!!%$ ++'&5737>32;#.#"!3l*"~ BjYE94]/h0EqU7 ~v *BXm> nL /X~NBFS-K1PX@ jD@ jaY@ +#n;N[{ @ja  +2#"&/ I   6 @OSG$$$"+#"&54632#"&546324/../O.--.,, -- ,, --6p@MQE+!! p:, @ja #++7>3  I @Bja+ +#"&/.'+73GGW@Bja+ +326?>;#GGW(@%jOSG +"&547332673gc>DNXU? {XT9AQHcr@8@OSG($+#".54>32  1!@[OSG$&($+4>32#".732654&#"-<"">-->""<-5?32@@23?^";**;"#:**:#2@@22@@1@.[OSG +2673#".#"#>32&/4&4 3/-&/7'4 4.-O7+"<, & 9*"<, %  +@(OSG   #++7>3!+7>3 -Z3 @kD  +2+ $U !;XB -M_< ʓ^pӡ  V /TPr}M((?dc:ZFq>gf:<++av?`p&BnF'5ETS,(Dq(<f]H@F8Bqfxmxcu^^G2<^!lrSSVVVF (GX(PTXXvMkk2dcMqr<y2????&&&&EnOEEEESF;<<<<<<2]HFFFFaxBII^GGGGG rrrrV;V< ]H?Fx02Sn^6'!'!S,F ,F ,F or27|<nn ggg,,f9`: }EE )!l(+WTbELe+g+u@@S{,@gP`  [jyj[$[9>:A</?>DFGHRTmyoyyy}y[[[[[[[/[/yyjjyjyy[ [ j y j [ $[ 9> :A </ ?> D F G H R T my oy yy }y [ [ [ [ [ [ [ / [ / y y j j y j y y [ # & * 2 4 D F G H R T k p [ j y j [ $[ 9> :A </ ?> D F G H R T my oy yy }y [ [ [ [ [ [ [ / [ / y y j j y j y y [= = =I#&*247A9=:m  > >GG"F#$&*-o24DFGHPQRSTUVXYZ\]kl>mopr>tPuPwy{P|>}>>G>>GG## # # # ##$#7#9#;#<#=#?#@#`#l#r#|##################$V$ V$ V$$#$&$*$-2$2$4$7$8$9$:$9 9 >9 >9G99G9999"F9#9$9&9*9-o92949D9F9G9H9P9Q9R9S9T9U9V9X9Y9Z9\9]9k9l>9m9o9p9r>9tP9uP9w9y9{P9|>9}99999999999999999999999999999999999999999999999999999999>9>9G9>9>9G99G999:F: : F: F::::::$:-:D:F:G:H:J:P:Q:R:S:T:U:V:X:lF:rF:t<:u<:w:{<:|F::::::::::::::::::::::::::::::::::::::::F:F::F:F:::;; ; ;;#;&;*;2;4;I;W;Y;Z;\;k;l;m;o;p;r;y;|;};;;;;;;;;;;;;;;;;;;;<4< ~< 4< 4<[<V<[<~<<<"2<#<$~<&<*<-8<2<4<DG<FG<GG<HG<J_<P<Q<RG<S<TG<U<VG<X<]<k<l4<mV<oV<p<r4<t2<u2<w<yV<{2<|4<}V<~<~<~<~<~<~<~<<<<<<<<G<G<G<G<G<G<G<G<G<G<G<G<G<<G<G<G<G<G<G<<<<<~<G<<G<G<<<G<G<G<<<<V<V<4<4<[<4<4<[<V<[<V<V<~==" =#=&=*=2=4=k=m=o=p=y=}==============>#>&>*>2>4>D>F>G>H>R>T>k>p>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>?V? V? V??#?&?*?-2?2?4?7?8?9?:?l:Al</l?>lDlFlGlHlRlTlmyloylyyl}yl[l[l[l[l[l[l[l/llllllllllllllllllll[lllll/lylyljljlyljlylyl[mym m ym ymjmjmm$m7Gm9m;mr:Ar</r?>rDrFrGrHrRrTrmyroyryyr}yr[r[r[r[r[r[r[r/rrrrrrrrrrrrrrrrrrrr[rrrrr/ryryrjrjryrjryryr[t etet$et9Ft:Ft<(t?Ftetetetetetetet(tet(teu eueu$eu9Fu:Fu<(u?Fueueueueueueueu(ueu(ueyyy y yy yyjyjyy$y7Gy9y;y|:A|</|?>|D|F|G|H|R|T|my|oy|yy|}y|[|[|[|[|[|[|[|/||||||||||||||||||||[|||||/|y|y|j|j|y|j|y|y|[}y} } y} y}j}j}}$}7G}9};}:A</?>DFGHRTmyoyyy}y[[[[[[[/[/yyjjyjyy[ [jyj[$[9>:A</?>DFGHRTmyoyyy}y[[[[[[[/[/yyjjyjyy[= = =I#&*247A9=:m:A</?>DFGHRTmyoyyy}y[[[[[[[/[/yyjjyjyy[ [jyj[$[9>:A</?>DFGHRTmyoyyy}y[[[[[[[/[/yyjjyjyy[= = =I#&*247A9=:m:A</?>DFGHRTmyoyyy}y[[[[[[[/[/yyjjyjyy[V V V#&*-224789:tTn<4t@x  n L r  l  B l  "^NR@ P :jrN"jPj@ jjdd$  n !*!|"f"#&#V#p$@$Z$$%`&& &v&&'6'|'( ()$)*X*d*p*|****+++++++++,>,J,V,b,n,z,,-<-H-T-`-l-x-.j.v...../0<0H0T0`0l0x0001 121D1V1h1z112j2|22223,3>34r4~445556.6:6L7:77888 8,888J8V8h8t89l9999:&:t:; ;>;;;;<"(>T>???@@@AjABBBBBBCjCDBDDEE`EzEFFFGG(GJGxGGHHDHHHd"/n   /(0B B Q - 2E w9 S g  { ^   P   `U    0  d   4  Copyright (c) 2010-2013 by tyPoland Lukasz Dziedzic with Reserved Font Name "Lato". Licensed under the SIL Open Font License, Version 1.1.Lato LightItalictyPolandLukaszDziedzic: Lato Light Italic: 2013Lato Light ItalicVersion 1.105; Western+Polish opensourceLato-LightItalicLato is a trademark of tyPoland Lukasz Dziedzic.Lukasz DziedzicLato is a sanserif typeface family designed in the Summer 2010 by Warsaw-based designer Lukasz Dziedzic ("Lato" means "Summer" in Polish). It tries to carefully balance some potentially conflicting priorities: it should seem quite "transparent" when used in body text but would display some original traits when used in larger sizes. The classical proportions, particularly visible in the uppercase, give the letterforms familiar harmony and elegance. At the same time, its sleek sanserif look makes evident the fact that Lato was designed in 2010, even though it does not follow any current trend. The semi-rounded details of the letters give Lato a feeling of warmth, while the strong structure provides stability and seriousness.http://www.typoland.com/http://www.typoland.com/designers/Lukasz_Dziedzic/Copyright (c) 2013-2013 by tyPoland Lukasz Dziedzic (http://www.typoland.com/) with Reserved Font Name "Lato". Licensed under the SIL Open Font License, Version 1.1 (http://scripts.sil.org/OFL).http://scripts.sil.org/OFLCopyright (c) 2010-2013 by tyPoland Lukasz Dziedzic with Reserved Font Name "Lato". Licensed under the SIL Open Font License, Version 1.1.Lato LightItalictyPolandLukaszDziedzic: Lato Light Italic: 2013Lato-LightItalicVersion 1.105; Western+Polish opensourceLato is a trademark of tyPoland Lukasz Dziedzic.Lukasz DziedzicLato is a sanserif typeface family designed in the Summer 2010 by Warsaw-based designer Lukasz Dziedzic ("Lato" means "Summer" in Polish). It tries to carefully balance some potentially conflicting priorities: it should seem quite "transparent" when used in body text but would display some original traits when used in larger sizes. The classical proportions, particularly visible in the uppercase, give the letterforms familiar harmony and elegance. At the same time, its sleek sanserif look makes evident the fact that Lato was designed in 2010, even though it does not follow any current trend. The semi-rounded details of the letters give Lato a feeling of warmth, while the strong structure provides stability and seriousness.http://www.typoland.com/http://www.typoland.com/designers/Lukasz_Dziedzic/Copyright (c) 2013-2013 by tyPoland Lukasz Dziedzic (http://www.typoland.com/) with Reserved Font Name "Lato". Licensed under the SIL Open Font License, Version 1.1 (http://scripts.sil.org/OFL).http://scripts.sil.org/OFLLatoLight ItalicXA  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghjikmlnoqprsutvwxzy{}|~      !"#NULLuni00A0uni00ADmacronperiodcenteredAogonekaogonekEogonekeogonekNacutenacuteSacutesacuteZacutezacute Zdotaccent zdotaccentuni02C9EuroDeltauni2669undercommaaccent grave.case dieresis.case macron.case acute.casecircumflex.case caron.case breve.casedotaccent.case ring.case tilde.casehungarumlaut.case caron.salt_K_KVV, `f-, d P&ZE[X!#!X PPX!@Y 8PX!8YY Ead(PX! E 0PX!0Y PX f a PX` PX! ` 6PX!6``YYY+YY#PXeYY-, E %ad CPX#B#B!!Y`-,#!#! dbB #B *! C +0%QX`PaRYX#Y! @SX+!@Y#PXeY-,C+C`B-,#B# #Bab`*-, E EcEb`D`-, E +#%` E#a d PX!0PX @YY#PXeY%#aDD`-,EaD- ,` CJPX #BY CJRX #BY- , b c#a C` ` #B#- ,KTXDY$ e#x- ,KQXKSXDY!Y$e#x- , CUX CaB +YC%B %B %B# %PXC`%B #a *!#a #a *!C`%B%a *!Y CG CG`b EcEb`#DC>C`B-,ETX #B `a  BB` +m+"Y-,+-,+-,+-,+-,+-,+-,+-,+-,+-, +-,+ETX #B `a  BB` +m+"Y-,+-,+-,+-,+-,+-,+- ,+-!,+-",+-#, +-$, <`-%, ` ` C#`C%a`$*!-&,%+%*-', G EcEb`#a8# UX G EcEb`#a8!Y-(,ETX'*0"Y-),+ETX'*0"Y-*, 5`-+,EcEb+EcEb+D>#8**-,, < G EcEb`Ca8--,.<-., < G EcEb`CaCc8-/,% . G#B%IG#G#a Xb!Y#B.*-0,%%G#G#aE+e.# <8-1,%% .G#G#a #BE+ `PX @QX  &YBB# C #G#G#a#F`Cb` + a C`d#CadPXCaC`Y%ba# &#Fa8#CF%CG#G#a` Cb`# +#C`+%a%b&a %`d#%`dPX!#!Y# &#Fa8Y-2, & .G#G#a#<8-3, #B F#G+#a8-4,%%G#G#aTX. <#!%%G#G#a %%G#G#a%%I%aEc# Xb!YcEb`#.# <8#!Y-5, C .G#G#a ` `fb# <8-6,# .F%FRX ,1+!# <#B#8&+C.&+-?, G#B.,*-@, G#B.,*-A,-*-B,/*-C,E# . F#a8&+-D,#BC+-E,<+-F,<+-G,<+-H,<+-I,=+-J,=+-K,=+-L,=+-M,9+-N,9+-O,9+-P,9+-Q,;+-R,;+-S,;+-T,;+-U,>+-V,>+-W,>+-X,>+-Y,:+-Z,:+-[,:+-\,:+-],2+.&+-^,2+6+-_,2+7+-`,2+8+-a,3+.&+-b,3+6+-c,3+7+-d,3+8+-e,4+.&+-f,4+6+-g,4+7+-h,4+8+-i,5+.&+-j,5+6+-k,5+7+-l,5+8+-m,+e$Px0-KKRXYc #D#pE (`f UX%aEc#b#D * **Y( ERD *D$QX@XD&QXXDYYYYDPK!׫  F2.2.0/rdoc/generator/template/darkfish/fonts/SourceCodePro-Regular.ttfnu[pFFTMfhOS/2r x`cmap_ceXcvt q "fpgmY7 `sgaspglyf'bheadu6hhea;4$hmtxzpF~loca <vmaxpSX nameqBP;dpost6z 3prep&# AZ½jV_<vv:Vj XXKX^2    ADBE@ "` MXWU*zTUUcGbE9'8MFDCxUkm1 gBUs5O_QbQS0f1dC*O+ 6&Acco<Q]P<EgH]Z7jQ<]<]<HEM3@1GxcLqM:5[SUUpUMHa'{ Bssss____S00000f-OOOO&eXQQQQQQPEEEEZZZZ<]<<<<<U<MMMM1]1 Q Q QBPBPBPBPU3<sEsEsEsEsE5H5H5H5HO _Z_Z_Z_Z_ZQ7bjjQQQ+5QS]S]S]0<0<0<! ddtdCHCHCHCH*E*EOMOMOMOMOMOM &1&AGAGAG>10<OM Q_Z0<OMOMOMOMOM5H0<CH*E7^<]=?E<M.?631Rl#U<U<5HO]O]QCQQQ<S]S]S]dddMCHCH*E*E   &1AGEO&1&1&1&1P_gg`N/+m:+T`l8U4 ~1Ie~7CRTYaeoy $(.1CIMPRX[!%+;Ico    " : D q y "" 4Lh7CPTXaeoy#&.1CGMORV[  $*6BZl    " 9 D p t } ""wnl@% zsrmkZWTSROM zjbRJHE?}zuigfc_]Z   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abctfgkzrmxluiyn~ep?od6{vs}~|w,K PXYD _^-, EiD`-,*!-, F%FRX#Y Id F had%F hadRX#eY/ SXi TX!@Yi TX!@eYY:-, F%FRX#Y F jad%F jadRX#Y/-,K &PXQXD@DY!! EPXD!YY-, EiD` E}iD`-,*-,K &SX@Y &SX#!#Y &SX#!#Y &SX#!#Y &SX#!@#Y &SX%EPX#!#!%E#!#!Y!YD- ,KSXED!!Y-+++@6*!+M@2$++ E}iDK`RXYDV 3  > ~   8D$4>td`HD P  B  R  : 4 ~ D  XR$&vLjVbLV`Vj  8 dpx*2,6@H   0 @ P !B!N!Z!f!r!~!!!!!" """".":"F"t"### #,#8#|#$$$$($4$@$%%%%(%4%@%L%X%d%%&&& &,&8&x'' ''$'0'<''''''(b))))&)2)>)J)V)b)n)z)**"*.*:*F*R*^*+H+T+`+l+x++++++++,@,,,,,,,-X---....*.|........//l/x/////0&020>0J0V0b0n01h1t111111111112222(242@2L2X2d2p2|222223 333333333444 45 5h56H6777*767B7N7Z7f7r7~7777777778`888999T9:H:;8;;<<<===>4>p>?8??@ @F@@AA A0AVA^AfAAAAAAAAAAABBhBBBCC8CLCzCCCD(DJDhDDDEEERE~EEFFFjFG"GfHHDHHI2I|IIJ.JpJJJJJJJJJK KK"K.KYEX/>Y ܸ01'3#4632#"&P 8-++++@^^#))#$**`&  sWEX/ >YEX / >YEX/>YEX/>Y++ иииииии017#537#53733733#3##7##7#OVU[55QWV]669::9U1G/,/+ܹܺ+9и!+9+.01.#"#5.'732654.546753"(3;/GRG//A'<8d#'&[9<=/FSF/YI<7J -&$*<. 7),9)1&) )9,?P*='{M&*A GEX3/3 >YEX!/!>YEX/>Y!!393!9+и и3и;Eи>иG0173267.'>54&#"&'#".54>7.54>32>73z".:0U" *F%!#&jAH$W8,H3#,%5!=B(2 S-)L4$<5- *d6=-:!%+67#(0C( 6-')O#!8*H: 4/)3^'(_9Av4.`c +01'3#n8AnnP +01.5467hyyh-e__e-Q䑑Q*UU*zP  +01>54&'7ze__e-hyyhUU*Q䑑QTo,//9и и 01?'7737'l 0 l*xxF.77.FUh, +и 01#53533## BB+>>+ +01>7#"&54632>>  .0 --]SO<%&%'E;XyU+i} EX / >Y0174632#"&/""//""/H&//&&..c`EX/>Y01#3JHJfG 'KEX/ >YEX/>Y  9/"01"&54632"32654."&54632,kzzkkzzk!8)UCCU)8!%%%% TAcEEcA# ## #b~ =EX / >YEX/>Yи й01%!53#5>73R3L=DDD5E CEX/ >YEX/>Yк9017>54&#"'>32>;!IQ}U,DG-M/+cD0M6+NlA=?1HtaT(7F- /,51F*-[ai;G93SEX/ >YEX0/0>Y 09 /& 901732>54.#52>54&#"'>32#"&'c Y>!8)8X?9O2G;-P ,(f>-M9 L< 9,$?T0Sp#.+/"? ,/6$4#-)<':J)6!*D/7#'!~ YEX/ >YEX / >Y+ и и и01%5>7###5!533p"cN?Xc=/B7t8 ~(UEX/ >YEX#/#>Y +##9и01732>54&#"'!!>32#".'a$+5 ";,UH(8",i5%.P;"'BU.+E7- &6!BJ3G 1K44P7M 0WEX-/- >YEX#/#>Y+##-9 -01%2>54&#".#">32#".54>32A2$FB&T) UB$&F5!&_0,I5#:M+4YB%,Ja4;W 5%3 BE'/]`@iM&-1J1.K6&MsM`U''F~3EX/ >YEX/>Y 013>7!5!#2M7?R2V[~CG3H^D @WEX)/) >YEXY) 9 /1и1/ܸ  01732654.'7654&#"4>75.54>32#".WJHL6I*/>PB?6B.=&1(95H+/I39(.":U76W2!- A:F0A8/) !4* I3%<+-?%-O &3"$>./@C  0WEX#/# >YEX-/->Y+-#9#-01267.#"32>7#".54>32#"&'%T* SG1$EYB%&E5 ']1,I4";M*4ZB%-J`4;W 6'.^`%4BEAhM&,1J1.K6&MsM`U'&}'f+'fx0h;+и/9и/01%%xu-kOOU&kk0h;+и/9и/015%5%5-u-OOm)*EX'/'>Y +'!ܸ017&>54&#"'>324632#"&#,'77&A1"\:*D1'-%f++++$8.('**7-#.)9$!3+(,3 #))#$**1p"{4=?%+/+8+;+/9:01%#'##".546754.#"3267#".54>323275"2G'/#$9'-R?%$>T1-C'R2;jP/-Pk>4L2+%88hXd:*"1MN$@0*S}SP}V--3c```1$@W3#(@~7 8 AEX/ >YEX / >Y  + 01'.'###3#  ?U^X d7m99m7dCpg!%WEX/ >YEX/>Y$9$/ $9%0132+2654&+2654&+g2S;!9:HP$A[7æTIMLVcU\ZWc&=+1O ND0H0x:76/?C=9B*!9EX/ >YEX/>Y 014>32.#"3267#".B+Nl@iM,HO~X/0 5!%Eb=>cF&-2.WU% 9EX/ >YEX / >Y 0132+72654&+U'LpIpoopHN{U-D}}s MEX/ >YEX / >Y 9/ 01!!!!!!sKaFGG CEX/ >YEX / >Y 9/01!!!!# SFF5'MEX/ >YEX#/#>Y##9/014>32.#"32675#53#".5+Mk@!6-#/>0.K63L0#< d@>hL*HOW/5"%Eb=>cF&E ,.WO  IEX/ >YEX / >Y 9 /и 013!3#!#OTTTTp5_ AEX/ >YEX / >Yи 0173#5!#3!_fGFFGQ5EX / >YEX/>Y 0173265!5!#"&'H&GAf3S=8i",*KQrFA.Q<#49bC kEX/ >YEX/ >YEX / >YEX/>Y9 9 и 01333##bT^]rTIjU+EX/ >YEX/>Y013!!REiGQMEX/ >YEX/>Y+и и013373#4>7##/##Q\]! \\G+Z-Z,Fjjpq675576SYEX/ >YEX / >Y 9к 9  0133.53#'##SUB OUB Ob1k4Tp3g30('5EX / >YEX/>Y 01".54>32'2>54.#",8\C%%C\87]C%%C]7%>++>%&=++= 0YOO}W./W}NOY0I&Gc>=bD%%Db=>cG&f!GEX/ >YEX/>Y 9 / 0132+#2654&+f6Z?##@Y6vSWSUUk-J64L2HAFG71])4KEX$/$ >YEX/>Y1+$.0132>54.#"#"&'.54>323267+=&%=++=%&=+$Wm/M7$B\87\B$4K-J3 K=dG''Gd==cE%%EcXC7WvGO}W//W~NFtW8 *+d)SEX/ >YEX / >Y 9 /  и 0132654&+##32mMQQMmuS2T="PCY?@A4,F3M\C3IEX/ >YEX0/0>Y09 0901732654./.54>32.#"#"&'u%b6FL +^2) 9O/>h$, M1YEX/>Y01#5!##TJFFO 3EX/ >YEX/>Y 01332>53#".5OT%22&Q!:Q00R;!f3G++G3hGb??bG+-3EX/ >YEX/>Y 0133>73#+Xj iUa;d:546bp N!MEX/ >YEX / >Y + ии 0133>?33>73#.'## S5   E;E  2Oa\K  HZd*O))P)(Q))P)o<<6"]EX/ >YEX/>Y99 к 9к90133>?3#'.'##\\  ZX\c bXS=++33&2@EX/ >YEX / >YEX/>Y901%33>?3#Xc$&_VT&K((L&ZA =EX/ >YEX/>Yи017!5!!!Aou&2F2Gh++01!#3!00c`EX/>Y013#cJHJchw++01#5!!55h00o &EX/ >Yܺ9 013#/##HHB11BH~YEX/>YEX/>Y9/ ' '99*+0174>7.#"'>32#'##".732675Q'U^1#0X" 17> daC)c4"<-P'*Q*Ni?~)=,,!%8  m[B .#3' %#']'EX/>YEX/>YEX/>YEX/>Y99$'013>32#"&'##732>54.#"]R#W+1L3$=P+#Q#BR#G 6(!4$ I&^"(#A[8>bD##6r1H-(B/#&P!9EX/>YEX/>Y 0174>32.#"3267#".P+Jc7YEX / >YEX/>YEX / >Y99 0174>32'53#'##".73275.#"<%=P+-D"RDS-0M8UKDHA!? 7);_B$"Z8@-"A^>XbI1DE'CEX/>YEX/>Y' +"0174>32!3267#".%4&#"E*EY/4R91C(+G"$\;6_G)LD7,<_B#!,6"#A^dIN'8$gBVEX/>YEX/>YEX / >Yи  01.#"3###5754632/3 B9Q_eHDz C<,C]>)YlH 6EUEX%/%>YEX(/(>YEX'/'>YEXC/C>YEX / >YC ии :2ܹF5F295и()'*%N0132>54&+"&'4675.54675.54>323##"&';2#"&2654.#"QN*D078_%#G)'#4E'( ɂ3E'+&50m^[&Fd>ku/A))BQ&0$#)8 &1?,(@- ?4 '>+  4>">.Fk>5**5>] eEX/>YEX/>YEX/>YEX / >Y 9013>32#4&#"#]R'X9WQR4<%$&Rs)6ca#EC !Z;EX/>YEX/>Yܸ 01!##%"&54632Z4R%%&&"##"7'!AEX/>YEX/>Yܸ01!#"&'732>5#%"&54632Z4/N;&H9$0 %%&&-K7= "1"##"j> mEX/>YEX/>YEX / >YEX/>Y 9 9 и 01333#'#jR^\sRoQ5EX/>YEX / >Y013327#"&5#Q3,(4!:(NQ6/> XW<, EX/>YEX / >YEX/>YEX / >YEX/>YEX/>Y 9и 0133>32>32#4#"#4#"#<@1*J4)37O5&B7$O@"*T&.MIUV%&UV%&] eEX/>YEX/>YEX/>YEX / >Y90133>32#4&#"#]D&X9WQR4<%$&RS)6ca#EC !<'5EX/>YEX/>Y#0174>32#".732>54.#"<'BW00WB''BW00WB'U)9##9))9##9)=_B""B_=<_A""A_<*D11D**E22E]3%EX / >YEX/>YEX/>YEX/>Y 9 9 "%01#33>32#"&'732654.#"RD"Y-1K3$=P,"O!#FBT!4$ I&)> *#A[9>aD#!?f[(B/#&<3$EX/>YEX / >YEX/>YEX / >Y99 0174>32373#57#".73275.#"<%=P+-F#BR Q-0M8UKDHA!? 7);_B$" 6MX+"A^>XbI1DTEX/>YEX/>YEX/>Y9 0133>32.#"#D&oD.#7e,Rs;D G ?LH-IEX/>YEX*/*>Y*9*901732654&'.54>32.#"#"&'p)^BB@EY&C23M27h$( N-". RBc_7Q4Hy-v$, , #*3%%5 '@84(-E"nM/EX/>YEX/>Yии01#5?33#3267#".5Ή D 0##8!P(5H+>C!1" < 5J-MeEX / >YEX/>YEX/>YEX/>Y901!#'##"&5332673C%W9XQS3=*D)RU+6ca.EC+/Q3% <EX/>YEX / >YEX / >Y0133>73#3Sp  pO\%G##G%P!tEX/>YEX / >YEX/>YEX!/!>YEX/>Y!9к90133>?33>73#'.'##T; ;F< ;Njc:  8b#B""C"#B""B##E% D*@eEX/>YEX / >YEX/>YEX/>Y9и и017'33>?3#'.'##[M  IWZU!PXk*,ip.+p1/'[EX/>YEX/>YEX/>YEX/>Y901326?33>73#"'7T  3@Sw  jN$2A)$;-$ J##I! $>- AG =EX/>YEX/>Yи017!5!!!GMX3,wC,Cxh9+34++  +' 9014>54.#52>54&54>;#";#". 9,,9 .F/=4&1 '44' 1&4=/F.1..40]4'3 0 #+[/13  313T.# 0 3Q +013#JJch9+7++'(+ ('9012>54&54675.54654.+5323"+5&1 &44& 1&3=/E. 9,,9 .E/=h #.T313  31/[+# 0 3'4]04..1'3 0L '++ и01>3232>7#".#"LH&/)'  5H&/)')F7 "F6 "4HuEX/>Y ܸ01#737#"&54632RP 8-++++Z^^X$))$#**q%\EX/ >Y" +!+!и/"и/  и / ܸи/01#5.54>753.'>7:8@?9H'3-J56J*3,@(- 4 XBCX "gh$=T54S<$jg"4M)WEX/ >YEX/>Y +и  и#01%!5>54'#57.54>32.#"3#;?=uc 7M0>U0;*BE %&GG2_94 = *D0+ /A4 ; 85F:SA 4&+ 0+01?.5467'76327'#"'732>54.#":TS,W0?>1W,TT,X9>1WP ++  ++ U:##;V-Z%%Z-V;##:U-Y&Y1$$11$$15#~lEX/ >YEX / >YEX/>Y 9 йиܸйи 013>?33#3##5#535#53\!"\RR~!C##C!/A00A/@Q++013##JJJJ5M0[GO/(+D+2(9D/9 29 к<29<01%>54.'.#"#"&'732654.5467.54>32s #)>I %)?IT8#*&*?I?*1)*;$7\ 2=*)-*>J>*3(&8&2Q&"",!)!+!k%$+=.0<'2$&!-(&*=.-@'/$"L:'EMEX/ >YEX/>Y#-й4Aй:014>32#".732>54.#"4>32.#"3267#".)Ic99cI))Ic99cI). ;S22S; ;S22S; F.;!#1".85-&4&";,CL{U..U{LM{W//W{MBkM**MkBBjL))LjB+F2'K;BM*3INS4&sUhi +01!#5!UBiU+ip?'5>=+ +62+)и2/и4и101".54>32'2>54.#"32#'##72654&+,'E33E''D33D'7''7 6((6)L /..#))C?4H,,H44H,,H4%*;$#;++;#$;*$SFFfCY ++01".54>32'2654&#",-##-.""."**"!**!//""//!..#%..%#.U, DEX/>Y+ܸии  01#53533##!! BBR0>>A>=ME.(s(/EX/>YEX / >YEX/>YEX/>Y 9 01332>733:7#"&'##"&'#MS49&&'S  &$ Q/#;SCE +#5:85 &;43H%EX/ >YEX/ >Y013##".54>;QQ6 5ZB%$?V2+ 25R9;Q3}+vaNa4&s?~'{M&<~'{M&'U'{M&{<'*EX%/%>Y +%ܸ01%3267#"&54>'7#"&54632g#,'87&A0!]:Te'-$g,++,$8.('+*6-#.TH!3+(,2!$))$#** 82&&# 82&&$ 82&&% 83&&& 8-&&* 8k&&,OfEX/ >YEX/>YEX / >Y ++01#!5##!#3#=+.IWCL6i6wGFGB+*&(//s2&*#s2&*$s2&*%s-&**_2&.#_2&.$_2&.%_-&.*+ SEX/ >YEX / >Y+  и01#5732+72654&+3#[KKpoopHA* D}}/S3&3&0(2&4#0(2&4$0(2&4%0(3&4&0(-&4*f~ ) + 9 и и01?'77'f,,,----, /}EX+/+ >YEX/>Y+9и +9  и+ и и#и -01732>54/.#"#"''7.54>3277 %>+8!&=+L%C]7Z@50?%C\8\?6/t&Gc>Y@8%Db=_@+sHOY0=O ]-vIO}W.=O O 2&:#O 2&:$O 2&:%O -&:*&22&>$e!9EX/ >YEX/>Y ++01332+#72654&+eTv6Z?##@Y6vTWSUUkn.I64M2@GG6X49ZEX/>YEX9/9>YEX/>Y""94%49014>32#"&'732654.54>54&#"#X4J/(=*",5,+<%*F !4*--4-",*7?R.L6)5&5,) $5' 6(:/&!-#"1-/ %1KKQ&FQ&FQ&FQ&FQ&FQ&FU.7DEX / >YEX/>YEX&/&>YEX,/,>Y/+ ,9/ & 9&)& 94,;B017467.#"'>32>32!3267#"&'#"&%4.#"3267./||'/AP-0;E0%7%<;/A&5H)O&\OIW6E8 8*/3$=P- L] 60+-.K8+RI'($#5:P+&H*E&JE&JE&JE&JZ&0Z&0Z&0Z&0<9kEX4/4>YEX/>Y' +*49*49-и7и001%2>5<'.#"#".54>32.''7.'77,(;'#R'(=),<{BP!>X7/VB'"=S2/T=.<"&(J"85H,  /&,;"&=+*=y< 0}EX,/,>YEX/>Y,9и ,9  и, и!и$и .01732>54&/.#"#"''7.54>327):#9) 2#9) 5 'BW0S?3%5 'BW0S?3%\&1E*!:&2F*!8 Y7<_A"0;> X6=_B"0;M&ZM&ZM&ZM&Z1/'&^]3%EX/>YEX/>YEX/>YEX/>Y99"%01#3>32#"&'532>54&#"RR#V+1L3%=P+$L!#E 7(AI H&W"(#A[9>aD#"\1H-Pc#&1/'&^ 8&&'Q&F 82&&(Q&F ,W %eEX/ >YEX/>YEX/>YEX/>Y# ++01'.'##"&54>7#'##3327  .(7 >?U^#- d7m99m7d= ,+&  p= Q24BEX/>YEX0/0>YEX/>YEX#/#>Y09/ #+и0:>0174>7.#"'>32327#"&54>7'##".732675Q'U^1#0X" 17> da*,.&4)c4"<-P'*Q*Ni?~)=,,!%8  m[; ) +*%  > .#3' %#'B*2&($/P&H+B*2&(%/P&H+B*5&()/P&H+B*2&(./P&H+U%2&).3T&I8+<C ,EX / >YEX)/)>YEX/>YEX/>Y++# 9#   9 и&и+'01.#"327#'##".54>32'5#53533!? 8)KDHAHDS-0M8%=P+-D"RH`.A'S]I@- ?Z;9[@""ZB0]]s&*'E&Js2&*(E&Js5&*)E&Js,!!^EX/ >YEX / >YEX / >Y++ 01!!!!!#3267#"&5467!sK!  .'8/FGG%- ,+*AE25>^EX$/$>YEX/>YEX/>Y>,+2$901%3267#"&54>7#".54>32!3267'4&#""-   -&4  "6_G)*EY/4R91C(+G"LD7,-)$!) +*$  #A^<<_B#!,IN'8$s2&*.E&J52&,%H 6&L52&,(H 6&L55&,)H 6&L5(&,#H 6&L9O 2&-%  \&M%f* NEX/ >YEX/ >YEX/>YEX / >Yܹܸи ии01!!7##!##5753!533ETTEETTEoo5*uuuu EX/>YEX/>YEX/>YEX/>Y+9 ии01>32#4&#"##57533#'X9WQR4<%$&RIIR)6caEC !;+]]0I_3&.&Z&0_&.'Z&0_2&.(Z&0_,`EX/ >YEX / >YEX/>Y+и0173#5!#3#327#"&5467#_ ".(7*GFFG4- ,++<Z2&gEX/>YEX/>YEX/>YEX/>Y ܸ!01#5!3267#"&54>7#"&54632<4#  -&5   %%&&C6) +*# J"##"_5&.)Z/EX/>YEX/>Y01!##Z4RQ2&/%7'&\0b(C&0&j(>&P#j> mEX/>YEX/>YEX/>YEX / >Y 9 9 и 01373#'#jR^\sRn2&1$Qf&Q$4(&1.Q(&QG&18|Q&Q8&1+&Q5 IEX/ >YEX/>Y9и и 01%!55737iQQRGG+C,ixDxQWEX / >YEX/>Y 9 и  ии01%#"&=575#537327!:(NQ||3,(4 XWGFGC[G[6/S2&3$] &SS(&3]( &S S2&3.] &SV&mEX/>YEX$/$>YEX#/#>YEX/>Y +&#9&!01>7#"&54632%>32#4&#"#305  '* (2LC #P5OLS.4'='RDO5' #+@9Kv#<%3`^)B@)(L0(&4'<&T0(2&4(<&T0(2&4-<&T!OOEX/ >YEX / >Y +  и01463!#3#3!".7;#"!}”>aD$VTVVTKFGG-U{N~ T;DEX/>YEX/>YEX2/2>YEX7/7>Y<'+7292+529A01732>54.#"4>32>32#3267#"&'#".%4.#"X &%%& M0@%/EA0"5#:6';#0H+]&@/-0*E11E**D22D*=_A"=87>$YEX / >YEX'/'>Y+''01332>533267#"&54>7.5OT$23%QE750  -(8  nkf3G++G3hft=- ,+! }M2%EX/>YEX$/$>YEX/>YEX / >YEX/>Y к9 #01!327#"&5467'##"&5332673-).&40 %W9XQS3=*D)R6 ) +*)=Q+6ca.EC+/Q N2&<%P&\&22&>%1/'&^&2-&>*A2&?$G&_A5&?)G&_A2&?.G&_ +EX/>YEX%/%>YEX / >YEX/>Y!$+9  9  $#и$(и!)01732654&#"'>32#"&'###57533##G@T@I I&#W+1L3$=P+#Q#BIIRraVL]#&D"("=X6<^A"#6;+]]0I>&#CEX / >YEX/>Y+  013267>32#".5467!.#"RBDWV:9Z?"$A\77Y>"TP)Ajvxi7 )/W}OO~Y00Y|L v!1(BEX%/% >Y+  +% и !01.#"3##"&'7326?#5737>32#(>,*4- hF) PT0J$/??.K6 >OM;8dh 024GEX,/, >YEX"/">Y, ",9.01%2>54.#"#".54>32>54&',%>++>%&=++= 9-,0%C]78\C%%C\8?5'(=&Gc>=bD%%Db=>cG& -2 +[OY00YOO}W.  <,e4GEX,/,>YEX"/">Y, ",9.01%2>54.#"#".54>32>54&',#9))9##9))9 8,&.'BW00WB''BW061,)81D**E22E**D1- ,2 !eC<_A""A_<=_B"  Ov(JEX/ >YEX!/! >YEX/>Y!01#".5332>53>54&'_ '!:Q00R;!T%22&#(0 $Gb??bGf3G++G3#  MVo#aEX/>YEX/>YEX / >YEX/>Y 9 01#'##"&5332673>54&'? "C%W9XQS3=*D)#0o #:U+6ca.EC+/Q"  82&&.Q&F_2&..Z&00(2&4.<&TO 2&:.M&ZO &:1M&Z0O &:3M7&Z2O &:5M7&Z4O &:7M7&Z652&,.H 6&L0,(%9KEX/ >YEX / >Y#+ и &001#"&5467.54>32327'2>54.#"-(8$A]=%C\87]C%`O W%>++>%&=++= ,+!;:_zAO}W./W}N"  &Gc>=bD%%Db=>cG&<2(<\EX/>YEX/>YEX&/&>Yи&.8014>7.54>323267#"&32>54.#" /T>$'BW00WB'-@(#$  .&4Y)9##9))9##9)y!$A\:=_B""B_=3M;+8) +*D11D**E22EC(&8 H(&X *(.&9E("n&YO7'5EX/>YEX/>Y01!#"&'732>5#Z4/N;&H9$0 -K7= "1) -cEX%/% >YEX/>Y иии и% 9 !и#и"01%2654&+3#32654&++5#5732&U^\WkZTJNL^HP$A[7MM2S;!8;?CFAYEX/>YEX/>Y9/ 9'*+013267#"&533>324.#">(U^0#0Y" 17> dbD(d3"=-P'*Q*Nh?h)=,-!%8  m[*B .$3' %#'< $EX/>YEX/>YEX/>YEX / >Y 9 9 0173275.#"4>32373#'##".KDHA!? 7)U$>P,+H"BDT./M8XbI1D+;_B$" 6@-"A^]%EX/>YEX!/!>YEX/>YEX/>Y!!9!9 01%4&#"32>7#"&'##33>32AI$J #E 6(U$=P+$P#BDZ11K3Sc%$ 2F0>bD##6@-#A[=!5EX/>YEX/>Y 01%#"&'732>54.#"'>32)Fa79d'%M-)E1.B',F*_B5]F)<_A"($5#1D**E25*"B_?'CEX/>YEX/>Y+ "01%#"&'732>7!.54>32.#")G_6;\$"G+(B0">U31V@%T PB7*<^A#"6+?'  3TYEX/>Y#+ 017467!.#"'>32#".73267E{UT*J!$^99\A$$AY53S; LQBHR JY8"B^<<_B# =W+ONRK<'!/EX/>YEX/>YEX/>YEX / >Y99 "$%(01326?#".54>32373#"&'7275.#"}&P%FKT-/M8$=Q,+J Bvm0a(FC!@ 7*MjF;b*"?[99\@##6\jI0A'R`M3aEX / >YEX/>YEX/>YEX/>Y 901#57#"&5332>73R'X9WQR4<%$&Rͮr(7ca.EC !S. EX/>YEX/>YEX/>YEX/>YEX / >YEX/>Y9 9 01!#'##"'#"&533267332673@1*J4)38O5&C6%N@"*T&.MI\V%&`V%&`?TEX/>YEX/>YEX/>Y9 01!#'##"&'732673D&oD.#7e,Rs;D G ?L6xAEX/>YEX/>Yии 01%3##5#5354&#"'>32 D5F#8!P(5H+CCCAD = 5J-3% @EX / >YEX/>YEX / >Y 901!#.'##3%Sp  pO\%H##H%P!i /EX/>YEX / >YEX/>YEX/>Y 99901!#.'##'.'##33>?3PT; ;F< ;Njc:  8b#B""C"#B""B##E% D*1'REX/>YEX/>YEX/>Y901.#"#.'##>32  0=Sw  jN $0>'!<.? J##I!*$>.A3 cEX/>YEX / >YEX/>YEX/>Y9 9 01###73753R^\sR%n:/ /EX/>Y+9013>32#54&#"#@8$94@$'@}E!A>*'w4EX/ >Y +ܸ013#"&'73265#7"&54632 6(-" / F2& .+(rN6/EX/ >Y +90133>32.#"#6B'# =@FK', 6(2RF!Z/EX/ >YEX / >YEX/ >Yи  0133>?33>?3#'.'##R@% $3%$YEX / >Y+9017326?33>?3#"&'7% @E <><5  #@//3@1^|^  ++0126548'3,,3EHHE*#"*$>45>h + +01"3&546h3++3EHHE*"#*$>54>==_EX/>Y013#f8Y==m_B +01#3_f8@?Jn2C;(EX/>Y +0133267#"&5#đ  "62Q 2<86N-+*++*990132654.'.54632.#"#"&'7%(& +"G@$?-&!,#IF+LS  (5(   )9FK//EX/ >YEX / >Y 9и и01'33>?3#'.'##fD+&DhoE/  +CBBFF=m +013#ZZ?є= +01#73*?ZZ==+ܸ013#'## Fa?CC?єccC'+ܹ и01>323273#".#"#+(  /+(  /C0=6/>7Y +013#9? + ܸ01".'332>73,!/ 3&% 3 /?'/ 3/'Jn +01"&54632,&&&&J"##"L + и01"&546323"&54632L     )+ܹ01>54'7 S BH(O'0)&   + ܸ01"&54632'2654&#",)44))44)3**22**3%;+и013#73#IX7HX7ʏ=+ܸ013373#?CC?aFccl;+и01#'3#'37XIM7XH;!Z +01632#"5467Z3&+#E#? _ +0167#"&5463262&+@.E#>#e+01>54&'7#**; '4   (n +01"&54632,&&&&"##"7 + и01"&546323"&54632(p+ ܹ01'>54&'73.(5(10#"  (&+p+и ܹ 01%3'>54&'5#(5(1!5   )2EX/>Y +014673327#"&.: $.&4y)@7 ) +2 +01".'332673, /3$##$3/%-//-%U +01#53:N#9/+ +!+ 9 01467.#"'>32#'##"&732675fm'4H(?=49 +Y++99 013>32#"&'##732654&#"@5BD(522@((4'.),}8YK)A- K ?93=( T /EX / >Y++99014>32'53#'##"&73275.#"(5+@55?LB.*+(&'5'?,6y,%XQ7=(>N !++ +014>32#3267#".74&#"+9DH=/*;##<-+(#7'?,SE 17 )+?B-00-rNAMdEX%/% >Y?+"H+7 +B0+ 79 и02ии%(01732654&+"&'475.54675.54>323##"';2#"&72654&#"326?%#; 65 #/ R ".?G@>0D*FO((((% (  )+0 ) "$))-& (( & S/ /EX/>YEX/ >Y 9  9 013373#'#@G|GkF@ИCUNT///EX/ >Y ++9и0133>32>32#54#"#54#"#2 !1 $"%=5  =F*7403.3N++014>32#".732654&#"+9 9,,9 9+B1++11++1(?++?((?++?(5@@54AANT/EX/ >Y ++ 9 9017#33>32#"'732654&#"@46AD(5/.((4'.'.k$YK)A-%. ?93=(IEX/ >YEX/ >Y +и 01#5?33#3267#"&5MP5"- 0H80ZZ3**. J=FAEX / >YEX/ >Y+901#'##"&=332675349%74@#)@3!A>*&F 3 /EX / >YEX/ >Y 0133>?3#B= >=vJF00N+ +014>32.#"3267#"./="#2 !0<:0(; #=,(?+) A45@ )+?8 /EX/ >Y+  и01.#"3###5754632"*$?OOAE-*#30:GF 4 /EX/ >Y и017#5!3!ս&3"3U%&)<&IUU%&))1/'&^A&? G&_E"@&YO3*hEX/ >YEX)/)>YEX/>Y! + ! 9%%9014>32#"&'732654./7.#"#O9X;NbuXR-?(4S03,0&?1v9,DLU2W?$TFbH'C1(!5?2*$ 6"0Y^`&22&>#1/'&^&2&>1"'&^&2h&>+1/'&^ &23&>&1/'&^P  +01!!PH HD  +01!!0 H^|  +01632#"&5467|/5 '* '3LDO4( #*?9Kw#^  +01>7#"&5463205  '* (2LCO5' #+@9Kv#|_^&sg^&sg|'ss +01%".54>32,6))66))6s'6!!6''6!!6'4 +01757ř''P#"4 +01%'7'R''#P" <p +01?'7!!M#*/EX/ >Yܸ 013##7"&54632@Fr lC!llC"N:/ /EX/ >Y+90133>32#54&#"#57%85@$'@F0!A>*'KWWaWWWKWWWKWKWWWKWK W !W l"WN!+++014673.#"'>32#"&732673/*;#GV)7 CM9-)'/ /5 )XQ'?+T>001/`" 7EX&/& >YEX/>Yй& и  иииܸии&#и&%ܸ)%*и),и3и4и4/01%.#*#7.'#7.546?33273.'>7!>  '>A$#&#T6 &  &DNvg &  &-1  <#7G  dLs!(0ccm|#qgbgr / #N4EX/ >YEX/>Y+и   ии 'и(и -и.01%!5>=#573.'#57.54>32.#"3#3#;?=|W aP7M0>U0;*BEξ %&GG2_9,-%*D0+ /A4#115F/'~ /EX'/' >YEX+/+ >YEX/>YEX/>Y'ܹ и иии'ииии"и #и&и)и-015#3#3/5#'3'#3##'##5#575#57533533ZD7>H;C5HHTapAJJJJTfkAH=.+;&f<+&<%*+*~ !cEX/ >YEX/>Y++  иии 01267#3.##+##575323ENNE*@%Y$+$ܸ)и/+и/.017!!.#"3267#'##"&54>32'5#5353yz-)944N:>'L[1?!'5G11y +>Ex,S+a\)B/S"1CC:61mEX/ >YEX/>Y("+(+и( и"и"и.01%#"&'#57&45<7#57>32.#"!!!#32676&\>b@;;@j3X1;&JZ&XE+AQ,1v+  ,v-!/!bW1  0U`$#+*~ 4EX/// >YEX%/%>Y #+/йܹ ии и 'и*и+и.и301>54&'#27#3.##3#+##575#575323;p!G6*A@H )8F'EOKKKKNsJ  ;tKK?"h  )"1!y$;%x7AT*uEX/ >YEX/ >YEX/>YEX/>Y*'+ܸܸ#01%#5.54>753.#"32675#53CX<2T dd2TtHFsU3ec,.!%Db<>bD%E`"%{EX/ >YEX/ >YEX / >YEX / >Y   ܸܸ!и"017#5.54>753.'>7JHMMH!O354V>"!=W55/O12 "6Elp &0dc1TvIGtT4a`+/#l ~pEX/ >YEX/ >YEX / >Yиииий  и /01#3##'#53267!573.+5! !+IG]I^YOS`L ]LOM5#1LXC:<,.&D8~$]EX/ >YEX/>Y 9 #ии ииии017>54&'7'575575377%NA)E:fOhhhhTB)=' ?^>050H041ǞV5VHV4WU+i +01!!URi> <p= (EX/>Y+ 01"&54632'2654&#",=NN==NN= .. .. XONTTNOX29<<55<<9a1EX/>Y+01%#5>73#"R!)2?* =,EX/>Y +017>54&#"'>323#NS&';$6>!,$;N! !#52'')5=$<EX!/!>Y+ +! 901732654#52654&#"'>32#"&'1#`*'(=#/;8 'F3#CQ3&&,(7&-018EX / >Y+ +и 01%57###5#5733N-629G2t8RAI+IIɽ1DEX/>Y+ + 9 01732654&#"'73#632#"&'-%$  2>F6*<Q 6F 300:= &FEX/>Y#++#9 01%2654&#"7.#">32#"&546328#,o+4-34+;NUE,&&" ;95*&QGV[1&EX/>Y+ 013>7#53# $ ( A'A;:5$#??D(= 8<EX4/4>Y%+449%901732654.'7>54&#"4675.54>32#".')/W,r'*2A!%"-.!P < n %  /%!  %!  = $FEX!/!>Y ++!9!0173267.#"3267#"&54632#"&'#,*2-33@3;NUE-&$ 995*,54&'7l72.-((-.27Ko1 -c;;c-!2o_2 +013#^XE2p2 +01#73>EX^p2+ܸ0173#'#`P`CCCppDD3++ܸи 01".#"#>3232673h .,$ .,/=.> +013#92 + ܸ 01".'332673,,2""""2,(''(e5 +01"&54632,!!!!- + и01"&546323"&54632h+ܹ01>54'7 S BH('0)& k  + ܸ01"&54632'2654&#",)44)(55(/)(00()/$2+и017373#BMSMT;pppp2+ܸ01#'337`P`CCC2ppDD+k+и ܹ 01%3'>54&'6#(5(1!5   )L ++ ииܹ01"&546323"&54632'3#L/+ + ܹи 013#"&546323"&54632&.L7%+ +и 013#"&546323"&54632IOg:!7g) + ܸܸи 013#"&546323"&54632R[pD#o|L7++ܹи013373#"&546323"&54632=??=[F37@@g ++ ииܹ01"&546323"&546327#'337`P`CCCooDDL7) + ܸܸи 01#'3"&54632#"&54632a:gOsg) + ܸܸи 01#'3"&54632#"&54632_Dp[|Go$A +01'3 ;$9+ ܹ01.54>7H3.(4'1$!  )&>.e&"A$`    '$: , E u L  2 * : 4]  2 ## H9Typographic alternatesTypographic alternatesSource Code ProSource Code ProRegularRegular1.017;ADBE;SourceCodePro-Regular;ADOBE1.017;ADBE;SourceCodePro-Regular;ADOBESource Code ProSource Code ProVersion 1.017;PS Version 1.000;hotconv 1.0.70;makeotf.lib2.5.5900Version 1.017;PS Version 1.000;hotconv 1.0.70;makeotf.lib2.5.5900SourceCodePro-RegularSourceCodePro-RegularSource is a trademark of Adobe Systems Incorporated in the United States and/or other countries.Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries.Adobe Systems IncorporatedAdobe Systems IncorporatedPaul D. HuntPaul D. Hunthttp://www.adobe.com/typehttp://www.adobe.com/typeCopyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. This Font Software is licensed under the SIL Open Font License, Version 1.1. This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL ----------------------------------------------------------- SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ----------------------------------------------------------- PREAMBLE The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. DEFINITIONS "Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. "Reserved Font Name" refers to any names specified as such after the copyright statement(s). "Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). "Modified Version" refers to any derivative made by adding to, deleting, or substituting -- in part or in whole -- any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. "Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. PERMISSION & CONDITIONS Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. TERMINATION This license becomes null and void if any of the above conditions are not met. DISCLAIMER THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. This Font Software is licensed under the SIL Open Font License, Version 1.1. This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL ----------------------------------------------------------- SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ----------------------------------------------------------- PREAMBLE The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. DEFINITIONS "Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. "Reserved Font Name" refers to any names specified as such after the copyright statement(s). "Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). "Modified Version" refers to any derivative made by adding to, deleting, or substituting -- in part or in whole -- any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. "Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. PERMISSION & CONDITIONS Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. TERMINATION This license becomes null and void if any of the above conditions are not met. DISCLAIMER THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. http://www.adobe.com/type/legal.htmlhttp://www.adobe.com/type/legal.html2:  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`a bcdefghjikmlnoqprsutvwxzy{}|~     !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXNULLCRuni00A0uni00ADtwo.sups three.supsuni00B5one.supsAmacronamacronAbreveabreveAogonekaogonek Ccircumflex ccircumflex Cdotaccent cdotaccentDcarondcaronDcroatEmacronemacronEbreveebreve Edotaccent edotaccentEogonekeogonekEcaronecaron Gcircumflex gcircumflex Gdotaccent gdotaccentuni0122uni0123 Hcircumflex hcircumflexHbarhbarItildeitildeImacronimacronuni012Cuni012DIogonekiogonek Jcircumflex jcircumflexuni0136uni0137 kgreenlandicLacutelacuteuni013Buni013CLcaronlcaronLdotldotNacutenacuteuni0145uni0146Ncaronncaron napostropheOmacronomacronuni014Euni014F Ohungarumlaut ohungarumlautRacuteracuteuni0156uni0157RcaronrcaronSacutesacute Scircumflex scircumflexuni015Euni015Funi0162uni0163TcarontcaronUtildeutildeUmacronumacronUbreveubreveUringuring Uhungarumlaut uhungarumlautUogonekuogonek Wcircumflex wcircumflex Ycircumflex ycircumflexZacutezacute Zdotaccent zdotaccentuni0180uni018Funi0192OhornohornUhornuhornuni01CDuni01CEuni01CFuni01D0uni01D1uni01D2uni01D3uni01D4uni01D5uni01D6uni01D7uni01D8uni01D9uni01DAuni01DBuni01DCGcarongcaronuni01EAuni01EBuni0218uni0219uni021Auni021Buni0237uni0243uni0250uni0251uni0252uni0254uni0258uni0259uni0261uni0265uni026Funi0279uni0287uni028Cuni028Duni028Euni029Eh.supsj.supsr.supsw.supsy.supsuni02BBuni02BCuni02BEuni02BFuni02C8uni02C9uni02CAuni02CBuni02CCl.supss.supsx.supsuni0300uni0301uni0302uni0303uni0304uni0306uni0307uni0308uni0309uni030Auni030Buni030Cuni030Funi0312uni0313uni031Buni0323uni0324uni0326uni0327uni0328uni032Euni0331a.supsb.supsd.supse.supsg.supsk.supsm.supso.supsp.supst.supsu.supsv.supsc.supsf.supsz.supsuni1E0Cuni1E0Duni1E0Euni1E0Funi1E20uni1E21uni1E24uni1E25uni1E2Auni1E2Buni1E36uni1E37uni1E38uni1E39uni1E3Auni1E3Buni1E42uni1E43uni1E44uni1E45uni1E46uni1E47uni1E48uni1E49uni1E5Auni1E5Buni1E5Cuni1E5Duni1E5Euni1E5Funi1E60uni1E61uni1E62uni1E63uni1E6Cuni1E6Duni1E6Euni1E6FWgravewgraveWacutewacute Wdieresis wdieresisuni1E8Euni1E8Funi1E92uni1E93uni1E97uni1E9EYgraveygraveuni1EF4uni1EF5uni1EF6uni1EF7uni1EF8uni1EF9 zero.supsi.sups four.sups five.supssix.sups seven.sups eight.sups nine.supsparenleft.supsparenright.supsn.sups zero.subsone.substwo.subs three.subs four.subs five.subssix.subs seven.subs eight.subs nine.subsparenleft.subsparenright.subs uni0259.sups colonmonetarylirauni20A6pesetadongEurouni20B1uni20B2uni20B5uni20B9uni20BAuni2215 zero.dnomone.dnomtwo.dnom three.dnom four.dnom five.dnomsix.dnom seven.dnom eight.dnom nine.dnomparenleft.dnomparenright.dnom uni0300.cap uni0301.cap uni0302.cap uni0303.cap uni0304.cap uni0306.cap uni0307.cap uni0308.cap uni0309.cap uni030A.cap uni030B.cap uni030C.cap uni0327.cap uni03080304uni03080304.cap uni03080301uni03080301.cap uni0308030Cuni0308030C.cap uni03080300uni03080300.cap uni030C.a uni0326.amUPK!A->2.2.0/rdoc/generator/template/darkfish/_sidebar_in_files.rhtmlnu[ PK! [::22.2.0/rdoc/generator/template/darkfish/index.rhtmlnu[
    <% if @options.main_page and main_page = @files.find { |f| f.full_name == @options.main_page } then %> <%= main_page.description %> <% else %>

    This is the API documentation for <%= @title %>. <% end %>

    PK!̈́&``42.2.0/rdoc/generator/template/darkfish/_footer.rhtmlnu[ PK!xb$22.2.0/rdoc/generator/template/darkfish/class.rhtmlnu[

    <%= klass.type %> <%= klass.full_name %>

    <%= klass.description %>
    <% klass.each_section do |section, constants, attributes| %> <% constants = constants.select { |const| const.display? } %> <% attributes = attributes.select { |attr| attr.display? } %>
    <% if section.title then %>

    <%= section.title %>

    ↑ top
    <% end %> <% if section.comment then %>
    <%= section.description %>
    <% end %> <% unless constants.empty? then %>

    Constants

    <% constants.each do |const| %>
    <%= const.name %> <% if const.comment then %>
    <%= const.description.strip %> <% else %>
    (Not documented) <% end %> <% end %>
    <% end %> <% unless attributes.empty? then %>

    Attributes

    <% attributes.each do |attrib| %>
    <%= h attrib.name %>[<%= attrib.rw %>]
    <% if attrib.comment then %> <%= attrib.description.strip %> <% else %>

    (Not documented) <% end %>

    <% end %>
    <% end %> <% klass.methods_by_type(section).each do |type, visibilities| next if visibilities.empty? visibilities.each do |visibility, methods| next if methods.empty? %>

    <%= visibility.to_s.capitalize %> <%= type.capitalize %> Methods

    <% methods.each do |method| %>
    "> <% if method.call_seq then %> <% method.call_seq.strip.split("\n").each_with_index do |call_seq, i| %>
    <%= h(call_seq.strip. gsub( /^\w+\./m, '')). gsub(/(.*)[-=]>/, '\1→') %> <% if i == 0 and method.token_stream then %> click to toggle source <% end %>
    <% end %> <% else %>
    <%= h method.name %><%= method.param_seq %> <% if method.token_stream then %> click to toggle source <% end %>
    <% end %>
    <% if method.comment then %> <%= method.description.strip %> <% else %>

    (Not documented) <% end %> <% if method.calls_super then %>

    Calls superclass method <%= method.superclass_method ? method.formatter.link(method.superclass_method.full_name, method.superclass_method.full_name) : nil %>
    <% end %> <% if method.token_stream then %>
    <%= method.markup_code %>
    <% end %>
    <% unless method.aliases.empty? then %>
    Also aliased as: <%= method.aliases.map do |aka| if aka.parent then # HACK lib/rexml/encodings %{#{h aka.name}} else h aka.name end end.join ", " %>
    <% end %> <% if method.is_alias_for then %> <% end %>
    <% end %>
    <% end end %>
    <% end %>
    PK!̸QQ?2.2.0/rdoc/generator/template/darkfish/_sidebar_installed.rhtmlnu[ PK! NNN>2.2.0/rdoc/generator/template/darkfish/servlet_not_found.rhtmlnu[

    Not Found

    <%= message %>

    PK!+<ߐ<<>2.2.0/rdoc/generator/template/darkfish/_sidebar_sections.rhtmlnu[<% unless klass.sections.length == 1 then %> <% end %> PK!>2.2.0/rdoc/generator/template/darkfish/table_of_contents.rhtmlnu[

    <%= h @title %>

    <% simple_files = @files.select { |f| f.text? } %> <% unless simple_files.empty? then %>

    Pages

      <% simple_files.sort.each do |file| %>
    • <%= h file.page_name %> <% # HACK table_of_contents should not exist on Document table = file.parse(file.comment).table_of_contents unless table.empty? then %> <% end %>
    • <% end %>
    <% end %>

    Classes and Modules

      <% @modsort.each do |klass| %>
    • <%= klass.full_name %> <% table = [] table.concat klass.parse(klass.comment_location).table_of_contents table.concat klass.section_contents unless table.empty? then %> <% end %>
    • <% end %>

    Methods

      <% @store.all_classes_and_modules.map do |mod| mod.method_list end.flatten.sort.each do |method| %>
    • <%= h method.pretty_name %><%= method.parent.full_name %> <% end %>
    PK!.u  =2.2.0/rdoc/generator/template/darkfish/_sidebar_classes.rhtmlnu[ PK!=2.2.0/rdoc/generator/template/darkfish/_sidebar_methods.rhtmlnu[<% unless klass.method_list.empty? then %> <% end %> PK!=>2.2.0/rdoc/generator/template/darkfish/_sidebar_includes.rhtmlnu[<% unless klass.includes.empty? then %> <% end %> PK! |;ff32.2.0/rdoc/generator/template/darkfish/js/jquery.jsnu[/*! jQuery v1.6.4 http://jquery.com/ | http://jquery.org/license */ (function(a,b){function cu(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cr(a){if(!cg[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){ch||(ch=c.createElement("iframe"),ch.frameBorder=ch.width=ch.height=0),b.appendChild(ch);if(!ci||!ch.createElement)ci=(ch.contentWindow||ch.contentDocument).document,ci.write((c.compatMode==="CSS1Compat"?"":"")+""),ci.close();d=ci.createElement(a),ci.body.appendChild(d),e=f.css(d,"display"),b.removeChild(ch)}cg[a]=e}return cg[a]}function cq(a,b){var c={};f.each(cm.concat.apply([],cm.slice(0,b)),function(){c[this]=a});return c}function cp(){cn=b}function co(){setTimeout(cp,0);return cn=f.now()}function cf(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ce(){try{return new a.XMLHttpRequest}catch(b){}}function b$(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g0){c!=="border"&&f.each(e,function(){c||(d-=parseFloat(f.css(a,"padding"+this))||0),c==="margin"?d+=parseFloat(f.css(a,c+this))||0:d-=parseFloat(f.css(a,"border"+this+"Width"))||0});return d+"px"}d=bv(a,b,b);if(d<0||d==null)d=a.style[b]||0;d=parseFloat(d)||0,c&&f.each(e,function(){d+=parseFloat(f.css(a,"padding"+this))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+this+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+this))||0)});return d+"px"}function bl(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bd,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function bk(a){f.nodeName(a,"input")?bj(a):"getElementsByTagName"in a&&f.grep(a.getElementsByTagName("input"),bj)}function bj(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bi(a){return"getElementsByTagName"in a?a.getElementsByTagName("*"):"querySelectorAll"in a?a.querySelectorAll("*"):[]}function bh(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bg(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c=f.expando,d=f.data(a),e=f.data(b,d);if(d=d[c]){var g=d.events;e=e[c]=f.extend({},d);if(g){delete e.handle,e.events={};for(var h in g)for(var i=0,j=g[h].length;i=0===c})}function U(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function M(a,b){return(a&&a!=="*"?a+".":"")+b.replace(y,"`").replace(z,"&")}function L(a){var b,c,d,e,g,h,i,j,k,l,m,n,o,p=[],q=[],r=f._data(this,"events");if(!(a.liveFired===this||!r||!r.live||a.target.disabled||a.button&&a.type==="click")){a.namespace&&(n=new RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)")),a.liveFired=this;var s=r.live.slice(0);for(i=0;ic)break;a.currentTarget=e.elem,a.data=e.handleObj.data,a.handleObj=e.handleObj,o=e.handleObj.origHandler.apply(e.elem,arguments);if(o===!1||a.isPropagationStopped()){c=e.level,o===!1&&(b=!1);if(a.isImmediatePropagationStopped())break}}return b}}function J(a,c,d){var e=f.extend({},d[0]);e.type=a,e.originalEvent={},e.liveFired=b,f.event.handle.call(c,e),e.isDefaultPrevented()&&d[0].preventDefault()}function D(){return!0}function C(){return!1}function m(a,c,d){var e=c+"defer",g=c+"queue",h=c+"mark",i=f.data(a,e,b,!0);i&&(d==="queue"||!f.data(a,g,b,!0))&&(d==="mark"||!f.data(a,h,b,!0))&&setTimeout(function(){!f.data(a,g,b,!0)&&!f.data(a,h,b,!0)&&(f.removeData(a,e,!0),i.resolve())},0)}function l(a){for(var b in a)if(b!=="toJSON")return!1;return!0}function k(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(j,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNaN(d)?i.test(d)?f.parseJSON(d):d:parseFloat(d)}catch(g){}f.data(a,c,d)}else d=b}return d}var c=a.document,d=a.navigator,e=a.location,f=function(){function K(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(K,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/\d/,n=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,o=/^[\],:{}\s]*$/,p=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,q=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,r=/(?:^|:|,)(?:\s*\[)+/g,s=/(webkit)[ \/]([\w.]+)/,t=/(opera)(?:.*version)?[ \/]([\w.]+)/,u=/(msie) ([\w.]+)/,v=/(mozilla)(?:.*? rv:([\w.]+))?/,w=/-([a-z]|[0-9])/ig,x=/^-ms-/,y=function(a,b){return(b+"").toUpperCase()},z=d.userAgent,A,B,C,D=Object.prototype.toString,E=Object.prototype.hasOwnProperty,F=Array.prototype.push,G=Array.prototype.slice,H=String.prototype.trim,I=Array.prototype.indexOf,J={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=n.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.6.4",length:0,size:function(){return this.length},toArray:function(){return G.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?F.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),B.done(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(G.apply(this,arguments),"slice",G.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:F,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;B.resolveWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").unbind("ready")}},bindReady:function(){if(!B){B=e._Deferred();if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",C,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",C),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&K()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNaN:function(a){return a==null||!m.test(a)||isNaN(a)},type:function(a){return a==null?String(a):J[D.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!E.call(a,"constructor")&&!E.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||E.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw a},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(o.test(b.replace(p,"@").replace(q,"]").replace(r,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(x,"ms-").replace(w,y)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i1?h.call(arguments,0):c,--e||g.resolveWith(g,h.call(b,0))}}var b=arguments,c=0,d=b.length,e=d,g=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred();if(d>1){for(;c
    a",d=a.getElementsByTagName("*"),e=a.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=a.getElementsByTagName("input")[0],k={leadingWhitespace:a.firstChild.nodeType===3,tbody:!a.getElementsByTagName("tbody").length,htmlSerialize:!!a.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55$/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:a.className!=="t",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,k.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,k.optDisabled=!h.disabled;try{delete a.test}catch(v){k.deleteExpando=!1}!a.addEventListener&&a.attachEvent&&a.fireEvent&&(a.attachEvent("onclick",function(){k.noCloneEvent=!1}),a.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),k.radioValue=i.value==="t",i.setAttribute("checked","checked"),a.appendChild(i),l=c.createDocumentFragment(),l.appendChild(a.firstChild),k.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,a.innerHTML="",a.style.width=a.style.paddingLeft="1px",m=c.getElementsByTagName("body")[0],o=c.createElement(m?"div":"body"),p={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},m&&f.extend(p,{position:"absolute",left:"-1000px",top:"-1000px"});for(t in p)o.style[t]=p[t];o.appendChild(a),n=m||b,n.insertBefore(o,n.firstChild),k.appendChecked=i.checked,k.boxModel=a.offsetWidth===2,"zoom"in a.style&&(a.style.display="inline",a.style.zoom=1,k.inlineBlockNeedsLayout=a.offsetWidth===2,a.style.display="",a.innerHTML="
    ",k.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML="
    t
    ",q=a.getElementsByTagName("td"),u=q[0].offsetHeight===0,q[0].style.display="",q[1].style.display="none",k.reliableHiddenOffsets=u&&q[0].offsetHeight===0,a.innerHTML="",c.defaultView&&c.defaultView.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",a.appendChild(j),k.reliableMarginRight=(parseInt((c.defaultView.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0),o.innerHTML="",n.removeChild(o);if(a.attachEvent)for(t in{submit:1,change:1,focusin:1})s="on"+t,u=s in a,u||(a.setAttribute(s,"return;"),u=typeof a[s]=="function"),k[t+"Bubbles"]=u;o=l=g=h=m=j=a=i=null;return k}(),f.boxModel=f.support.boxModel;var i=/^(?:\{.*\}|\[.*\])$/,j=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!l(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i=f.expando,j=typeof c=="string",k=a.nodeType,l=k?f.cache:a,m=k?a[f.expando]:a[f.expando]&&f.expando;if((!m||e&&m&&l[m]&&!l[m][i])&&j&&d===b)return;m||(k?a[f.expando]=m=++f.uuid:m=f.expando),l[m]||(l[m]={},k||(l[m].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?l[m][i]=f.extend(l[m][i],c):l[m]=f.extend(l[m],c);g=l[m],e&&(g[i]||(g[i]={}),g=g[i]),d!==b&&(g[f.camelCase(c)]=d);if(c==="events"&&!g[c])return g[i]&&g[i].events;j?(h=g[c],h==null&&(h=g[f.camelCase(c)])):h=g;return h}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e=f.expando,g=a.nodeType,h=g?f.cache:a,i=g?a[f.expando]:f.expando;if(!h[i])return;if(b){d=c?h[i][e]:h[i];if(d){d[b]||(b=f.camelCase(b)),delete d[b];if(!l(d))return}}if(c){delete h[i][e];if(!l(h[i]))return}var j=h[i][e];f.support.deleteExpando||!h.setInterval?delete h[i]:h[i]=null,j?(h[i]={},g||(h[i].toJSON=f.noop),h[i][e]=j):g&&(f.support.deleteExpando?delete a[f.expando]:a.removeAttribute?a.removeAttribute(f.expando):a[f.expando]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d=null;if(typeof a=="undefined"){if(this.length){d=f.data(this[0]);if(this[0].nodeType===1){var e=this[0].attributes,g;for(var h=0,i=e.length;h-1)return!0;return!1},val:function(a){var c,d,e=this[0];if(!arguments.length){if(e){c=f.valHooks[e.nodeName.toLowerCase()]||f.valHooks[e.type];if(c&&"get"in c&&(d=c.get(e,"value"))!==b)return d;d=e.value;return typeof d=="string"?d.replace(p,""):d==null?"":d}return b}var g=f.isFunction(a);return this.each(function(d){var e=f(this),h;if(this.nodeType===1){g?h=a.call(this,d,e.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c=a.selectedIndex,d=[],e=a.options,g=a.type==="select-one";if(c<0)return null;for(var h=g?c:0,i=g?c+1:e.length;h=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attrFix:{tabindex:"tabIndex"},attr:function(a,c,d,e){var g=a.nodeType;if(!a||g===3||g===8||g===2)return b;if(e&&c in f.attrFn)return f(a)[c](d);if(!("getAttribute"in a))return f.prop(a,c,d);var h,i,j=g!==1||!f.isXMLDoc(a);j&&(c=f.attrFix[c]||c,i=f.attrHooks[c],i||(t.test(c)?i=v:u&&(i=u)));if(d!==b){if(d===null){f.removeAttr(a,c);return b}if(i&&"set"in i&&j&&(h=i.set(a,d,c))!==b)return h;a.setAttribute(c,""+d);return d}if(i&&"get"in i&&j&&(h=i.get(a,c))!==null)return h;h=a.getAttribute(c);return h===null?b:h},removeAttr:function(a,b){var c;a.nodeType===1&&(b=f.attrFix[b]||b,f.attr(a,b,""),a.removeAttribute(b),t.test(b)&&(c=f.propFix[b]||b)in a&&(a[c]=!1))},attrHooks:{type:{set:function(a,b){if(q.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(u&&f.nodeName(a,"button"))return u.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(u&&f.nodeName(a,"button"))return u.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e=a.nodeType;if(!a||e===3||e===8||e===2)return b;var g,h,i=e!==1||!f.isXMLDoc(a);i&&(c=f.propFix[c]||c,h=f.propHooks[c]);return d!==b?h&&"set"in h&&(g=h.set(a,d,c))!==b?g:a[c]=d:h&&"get"in h&&(g=h.get(a,c))!==null?g:a[c]},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):r.test(a.nodeName)||s.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabIndex=f.propHooks.tabIndex,v={get:function(a,c){var d;return f.prop(a,c)===!0||(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},f.support.getSetAttribute||(u=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&d.nodeValue!==""?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})})),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var w=/\.(.*)$/,x=/^(?:textarea|input|select)$/i,y=/\./g,z=/ /g,A=/[^\w\s.|`]/g,B=function(a){return a.replace(A,"\\$&")};f.event={add:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){if(d===!1)d=C;else if(!d)return;var g,h;d.handler&&(g=d,d=g.handler),d.guid||(d.guid=f.guid++);var i=f._data(a);if(!i)return;var j=i.events,k=i.handle;j||(i.events=j={}),k||(i.handle=k=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.handle.apply(k.elem,arguments):b}),k.elem=a,c=c.split(" ");var l,m=0,n;while(l=c[m++]){h=g?f.extend({},g):{handler:d,data:e},l.indexOf(".")>-1?(n=l.split("."),l=n.shift(),h.namespace=n.slice(0).sort().join(".")):(n=[],h.namespace=""),h.type=l,h.guid||(h.guid=d.guid);var o=j[l],p=f.event.special[l]||{};if(!o){o=j[l]=[];if(!p.setup||p.setup.call(a,e,n,k)===!1)a.addEventListener?a.addEventListener(l,k,!1):a.attachEvent&&a.attachEvent("on"+l,k)}p.add&&(p.add.call(a,h),h.handler.guid||(h.handler.guid=d.guid)),o.push(h),f.event.global[l]=!0}a=null}},global:{},remove:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){d===!1&&(d=C);var g,h,i,j,k=0,l,m,n,o,p,q,r,s=f.hasData(a)&&f._data(a),t=s&&s.events;if(!s||!t)return;c&&c.type&&(d=c.handler,c=c.type);if(!c||typeof c=="string"&&c.charAt(0)==="."){c=c||"";for(h in t)f.event.remove(a,h+c);return}c=c.split(" ");while(h=c[k++]){r=h,q=null,l=h.indexOf(".")<0,m=[],l||(m=h.split("."),h=m.shift(),n=new RegExp("(^|\\.)"+f.map(m.slice(0).sort(),B).join("\\.(?:.*\\.)?")+"(\\.|$)")),p=t[h];if(!p)continue;if(!d){for(j=0;j=0&&(h=h.slice(0,-1),j=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if(!!e&&!f.event.customEvent[h]||!!f.event.global[h]){c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.exclusive=j,c.namespace=i.join("."),c.namespace_re=new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)");if(g||!e)c.preventDefault(),c.stopPropagation();if(!e){f.each(f.cache,function(){var a=f.expando,b=this[a];b&&b.events&&b.events[h]&&f.event.trigger(c,d,b.handle.elem)});return}if(e.nodeType===3||e.nodeType===8)return;c.result=b,c.target=e,d=d!=null?f.makeArray(d):[],d.unshift(c);var k=e,l=h.indexOf(":")<0?"on"+h:"";do{var m=f._data(k,"handle");c.currentTarget=k,m&&m.apply(k,d),l&&f.acceptData(k)&&k[l]&&k[l].apply(k,d)===!1&&(c.result=!1,c.preventDefault()),k=k.parentNode||k.ownerDocument||k===c.target.ownerDocument&&a}while(k&&!c.isPropagationStopped());if(!c.isDefaultPrevented()){var n,o=f.event.special[h]||{};if((!o._default||o._default.call(e.ownerDocument,c)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)){try{l&&e[h]&&(n=e[l],n&&(e[l]=null),f.event.triggered=h,e[h]())}catch(p){}n&&(e[l]=n),f.event.triggered=b}}return c.result}},handle:function(c){c=f.event.fix(c||a.event);var d=((f._data(this,"events")||{})[c.type]||[]).slice(0),e=!c.exclusive&&!c.namespace,g=Array.prototype.slice.call(arguments,0);g[0]=c,c.currentTarget=this;for(var h=0,i=d.length;h-1?f.map(a.options,function(a){return a.selected}).join("-"):"":f.nodeName(a,"select")&&(c=a.selectedIndex);return c},I=function(c){var d=c.target,e,g;if(!!x.test(d.nodeName)&&!d.readOnly){e=f._data(d,"_change_data"),g=H(d),(c.type!=="focusout"||d.type!=="radio")&&f._data(d,"_change_data",g);if(e===b||g===e)return;if(e!=null||g)c.type="change",c.liveFired=b,f.event.trigger(c,arguments[1],d)}};f.event.special.change={filters:{focusout:I,beforedeactivate:I,click:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(c==="radio"||c==="checkbox"||f.nodeName(b,"select"))&&I.call(this,a)},keydown:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(a.keyCode===13&&!f.nodeName(b,"textarea")||a.keyCode===32&&(c==="checkbox"||c==="radio")||c==="select-multiple")&&I.call(this,a)},beforeactivate:function(a){var b=a.target;f._data(b,"_change_data",H(b))}},setup:function(a,b){if(this.type==="file")return!1;for(var c in G)f.event.add(this,c+".specialChange",G[c]);return x.test(this.nodeName)},teardown:function(a){f.event.remove(this,".specialChange");return x.test(this.nodeName)}},G=f.event.special.change.filters,G.focus=G.beforeactivate}f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){function e(a){var c=f.event.fix(a);c.type=b,c.originalEvent={},f.event.trigger(c,null,c.target),c.isDefaultPrevented()&&a.preventDefault()}var d=0;f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.each(["bind","one"],function(a,c){f.fn[c]=function(a,d,e){var g;if(typeof a=="object"){for(var h in a)this[c](h,d,a[h],e);return this}if(arguments.length===2||d===!1)e=d,d=b;c==="one"?(g=function(a){f(this).unbind(a,g);return e.apply(this,arguments)},g.guid=e.guid||f.guid++):g=e;if(a==="unload"&&c!=="one")this.one(a,d,e);else for(var i=0,j=this.length;i0?this.bind(b,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0)}),function(){function u(a,b,c,d,e,f){for(var g=0,h=d.length;g0){j=i;break}}i=i[a]}d[g]=j}}}function t(a,b,c,d,e,f){for(var g=0,h=d.length;g+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d=0,e=Object.prototype.toString,g=!1,h=!0,i=/\\/g,j=/\W/;[0,0].sort(function(){h=!1;return 0});var k=function(b,d,f,g){f=f||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return f;var i,j,n,o,q,r,s,t,u=!0,w=k.isXML(d),x=[],y=b;do{a.exec(""),i=a.exec(y);if(i){y=i[3],x.push(i[1]);if(i[2]){o=i[3];break}}}while(i);if(x.length>1&&m.exec(b))if(x.length===2&&l.relative[x[0]])j=v(x[0]+x[1],d);else{j=l.relative[x[0]]?[d]:k(x.shift(),d);while(x.length)b=x.shift(),l.relative[b]&&(b+=x.shift()),j=v(b,j)}else{!g&&x.length>1&&d.nodeType===9&&!w&&l.match.ID.test(x[0])&&!l.match.ID.test(x[x.length-1])&&(q=k.find(x.shift(),d,w),d=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]);if(d){q=g?{expr:x.pop(),set:p(g)}:k.find(x.pop(),x.length===1&&(x[0]==="~"||x[0]==="+")&&d.parentNode?d.parentNode:d,w),j=q.expr?k.filter(q.expr,q.set):q.set,x.length>0?n=p(j):u=!1;while(x.length)r=x.pop(),s=r,l.relative[r]?s=x.pop():r="",s==null&&(s=d),l.relative[r](n,s,w)}else n=x=[]}n||(n=j),n||k.error(r||b);if(e.call(n)==="[object Array]")if(!u)f.push.apply(f,n);else if(d&&d.nodeType===1)for(t=0;n[t]!=null;t++)n[t]&&(n[t]===!0||n[t].nodeType===1&&k.contains(d,n[t]))&&f.push(j[t]);else for(t=0;n[t]!=null;t++)n[t]&&n[t].nodeType===1&&f.push(j[t]);else p(n,f);o&&(k(o,h,f,g),k.uniqueSort(f));return f};k.uniqueSort=function(a){if(r){g=h,a.sort(r);if(g)for(var b=1;b0},k.find=function(a,b,c){var d;if(!a)return[];for(var e=0,f=l.order.length;e":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!j.test(b)){b=b.toLowerCase();for(;e=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(i,"")},TAG:function(a,b){return a[1].replace(i,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||k.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&k.error(a[0]);a[0]=d++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(i,"");!f&&l.attrMap[g]&&(a[1]=l.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(i,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=k(b[3],null,null,c);else{var g=k.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(l.match.POS.test(b[0])||l.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!k(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return bc[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=l.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||k.getText([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=l.attrHandle[c]?l.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=l.setFilters[e];if(f)return f(a,c,b,d)}}},m=l.match.POS,n=function(a,b){return"\\"+(b-0+1)};for(var o in l.match)l.match[o]=new RegExp(l.match[o].source+/(?![^\[]*\])(?![^\(]*\))/.source),l.leftMatch[o]=new RegExp(/(^(?:.|\r|\n)*?)/.source+l.match[o].source.replace(/\\(\d+)/g,n));var p=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(q){p=function(a,b){var c=0,d=b||[];if(e.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var f=a.length;c",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(l.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},l.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(l.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(l.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=k,b=c.createElement("div"),d="__sizzle__";b.innerHTML="

    ";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){k=function(b,e,f,g){e=e||c;if(!g&&!k.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return p(e.getElementsByTagName(b),f);if(h[2]&&l.find.CLASS&&e.getElementsByClassName)return p(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return p([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return p([],f);if(i.id===h[3])return p([i],f)}try{return p(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var m=e,n=e.getAttribute("id"),o=n||d,q=e.parentNode,r=/^\s*[+~]/.test(b);n?o=o.replace(/'/g,"\\$&"):e.setAttribute("id",o),r&&q&&(e=e.parentNode);try{if(!r||q)return p(e.querySelectorAll("[id='"+o+"'] "+b),f)}catch(s){}finally{n||m.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)k[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}k.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(a))try{if(e||!l.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return k(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="
    ";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;l.order.splice(1,0,"CLASS"),l.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?k.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?k.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:k.contains=function(){return!1},k.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var v=function(a,b){var c,d=[],e="",f=b.nodeType?[b]:b;while(c=l.match.PSEUDO.exec(a))e+=c[0],a=a.replace(l.match.PSEUDO,"");a=l.relative[a]?a+"*":a;for(var g=0,h=f.length;g0)for(h=g;h0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h,i,j={},k=1;if(g&&a.length){for(d=0,e=a.length;d-1:f(g).is(h))&&c.push({selector:i,elem:g,level:k});g=g.parentNode,k++}}return c}var l=S.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(U(c[0])||U(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c),g=R.call(arguments);N.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!T[a]?f.unique(e):e,(this.length>1||P.test(d))&&O.test(a)&&(e=e.reverse());return this.pushStack(e,a,g.join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/",""],legend:[1,"
    ","
    "],thead:[1,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],col:[2,"","
    "],area:[1,"",""],_default:[0,"",""]};be.optgroup=be.option,be.tbody=be.tfoot=be.colgroup=be.caption=be.thead,be.th=be.td,f.support.htmlSerialize||(be._default=[1,"div
    ","
    "]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){f(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f(arguments[0]).toArray());return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!be[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1>");try{for(var c=0,d=this.length;c1&&l0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d=a.cloneNode(!0),e,g,h;if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bh(a,d),e=bi(a),g=bi(d);for(h=0;e[h];++h)g[h]&&bh(e[h],g[h])}if(b){bg(a,d);if(c){e=bi(a),g=bi(d);for(h=0;e[h];++h)bg(e[h],g[h])}}e=g=null;return d},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!_.test(k))k=b.createTextNode(k);else{k=k.replace(Y,"<$1>");var l=(Z.exec(k)||["",""])[1].toLowerCase(),m=be[l]||be._default,n=m[0],o=b.createElement("div");o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=$.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]===""&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&X.test(k)&&o.insertBefore(b.createTextNode(X.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bn.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNaN(b)?"":"alpha(opacity="+b*100+")",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bm,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bm.test(g)?g.replace(bm,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bv(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bw=function(a,c){var d,e,g;c=c.replace(bo,"-$1").toLowerCase();if(!(e=a.ownerDocument.defaultView))return b;if(g=e.getComputedStyle(a,null))d=g.getPropertyValue(c),d===""&&!f.contains(a.ownerDocument.documentElement,a)&&(d=f.style(a,c));return d}),c.documentElement.currentStyle&&(bx=function(a,b){var c,d=a.currentStyle&&a.currentStyle[b],e=a.runtimeStyle&&a.runtimeStyle[b],f=a.style;!bp.test(d)&&bq.test(d)&&(c=f.left,e&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":d||0,d=f.pixelLeft+"px",f.left=c,e&&(a.runtimeStyle.left=e));return d===""?"auto":d}),bv=bw||bx,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bz=/%20/g,bA=/\[\]$/,bB=/\r?\n/g,bC=/#.*$/,bD=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bE=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bF=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bG=/^(?:GET|HEAD)$/,bH=/^\/\//,bI=/\?/,bJ=/)<[^<]*)*<\/script>/gi,bK=/^(?:select|textarea)/i,bL=/\s+/,bM=/([?&])_=[^&]*/,bN=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bO=f.fn.load,bP={},bQ={},bR,bS,bT=["*/"]+["*"];try{bR=e.href}catch(bU){bR=c.createElement("a"),bR.href="",bR=bR.href}bS=bN.exec(bR.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bO)return bO.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("
    ").append(c.replace(bJ,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bK.test(this.nodeName)||bE.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bB,"\r\n")}}):{name:b.name,value:c.replace(bB,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.bind(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?bX(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),bX(a,b);return a},ajaxSettings:{url:bR,isLocal:bF.test(bS[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bT},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bV(bP),ajaxTransport:bV(bQ),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?bZ(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=b$(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.resolveWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f._Deferred(),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bD.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.done,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bC,"").replace(bH,bS[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bL),d.crossDomain==null&&(r=bN.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bS[1]&&r[2]==bS[2]&&(r[3]||(r[1]==="http:"?80:443))==(bS[3]||(bS[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),bW(bP,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bG.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bI.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bM,"$1_="+x);d.url=y+(y===d.url?(bI.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bT+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=bW(bQ,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){s<2?w(-1,z):f.error(z)}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)bY(g,a[g],c,e);return d.join("&").replace(bz,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var b_=f.now(),ca=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+b_++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ca.test(b.url)||e&&ca.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ca,l),b.url===j&&(e&&(k=k.replace(ca,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cb=a.ActiveXObject?function(){for(var a in cd)cd[a](0,1)}:!1,cc=0,cd;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ce()||cf()}:ce,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cb&&delete cd[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cc,cb&&(cd||(cd={},f(a).unload(cb)),cd[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cg={},ch,ci,cj=/^(?:toggle|show|hide)$/,ck=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cl,cm=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cn;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cq("show",3),a,b,c);for(var g=0,h=this.length;g=e.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),e.animatedProperties[this.prop]=!0;for(g in e.animatedProperties)e.animatedProperties[g]!==!0&&(c=!1);if(c){e.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){d.style["overflow"+b]=e.overflow[a]}),e.hide&&f(d).hide();if(e.hide||e.show)for(var i in e.animatedProperties)f.style(d,i,e.orig[i]);e.complete.call(d)}return!1}e.duration==Infinity?this.now=b:(h=b-this.startTime,this.state=h/e.duration,this.pos=f.easing[e.animatedProperties[this.prop]](this.state,h,0,1,e.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){for(var a=f.timers,b=0;b
    ";f.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"}),b.innerHTML=j,a.insertBefore(b,a.firstChild),d=b.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,this.doesNotAddBorder=e.offsetTop!==5,this.doesAddBorderForTableAndCells=h.offsetTop===5,e.style.position="fixed",e.style.top="20px",this.supportsFixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",this.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i,a.removeChild(b),f.offset.initialize=f.noop},bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.offset.initialize(),f.offset.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=ct.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!ct.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cu(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cu(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a&&a.style?parseFloat(f.css(a,d,"padding")):null},f.fn["outer"+c]=function(a){var b=this[0];return b&&b.style?parseFloat(f.css(b,d,a?"margin":"border")):null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c],h=e.document.body;return e.document.compatMode==="CSS1Compat"&&g||h&&h["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var i=f.css(e,d),j=parseFloat(i);return f.isNaN(j)?i:j}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f})(window);PK!l1j 32.2.0/rdoc/generator/template/darkfish/js/search.jsnu[Search = function(data, input, result) { this.data = data; this.$input = $(input); this.$result = $(result); this.$current = null; this.$view = this.$result.parent(); this.searcher = new Searcher(data.index); this.init(); } Search.prototype = $.extend({}, Navigation, new function() { var suid = 1; this.init = function() { var _this = this; var observer = function(e) { switch(e.originalEvent.keyCode) { case 38: // Event.KEY_UP case 40: // Event.KEY_DOWN return; } _this.search(_this.$input[0].value); }; this.$input.keyup(observer); this.$input.click(observer); // mac's clear field this.searcher.ready(function(results, isLast) { _this.addResults(results, isLast); }) this.initNavigation(); this.setNavigationActive(false); } this.search = function(value, selectFirstMatch) { value = jQuery.trim(value).toLowerCase(); if (value) { this.setNavigationActive(true); } else { this.setNavigationActive(false); } if (value == '') { this.lastQuery = value; this.$result.empty(); this.$result.attr('aria-expanded', 'false'); this.setNavigationActive(false); } else if (value != this.lastQuery) { this.lastQuery = value; this.$result.attr('aria-busy', 'true'); this.$result.attr('aria-expanded', 'true'); this.firstRun = true; this.searcher.find(value); } } this.addResults = function(results, isLast) { var target = this.$result.get(0); if (this.firstRun && (results.length > 0 || isLast)) { this.$current = null; this.$result.empty(); } for (var i=0, l = results.length; i < l; i++) { var item = this.renderItem.call(this, results[i]); item.setAttribute('id', 'search-result-' + target.childElementCount); target.appendChild(item); }; if (this.firstRun && results.length > 0) { this.firstRun = false; this.$current = $(target.firstChild); this.$current.addClass('search-selected'); } if (jQuery.browser.msie) this.$element[0].className += ''; if (isLast) this.$result.attr('aria-busy', 'false'); } this.move = function(isDown) { if (!this.$current) return; var $next = this.$current[isDown ? 'next' : 'prev'](); if ($next.length) { this.$current.removeClass('search-selected'); $next.addClass('search-selected'); this.$input.attr('aria-activedescendant', $next.attr('id')); this.scrollIntoView($next[0], this.$view[0]); this.$current = $next; this.$input.val($next[0].firstChild.firstChild.text); this.$input.select(); } return true; } this.hlt = function(html) { return this.escapeHTML(html). replace(/\u0001/g, ''). replace(/\u0002/g, ''); } this.escapeHTML = function(html) { return html.replace(/[&<>]/g, function(c) { return '&#' + c.charCodeAt(0) + ';'; }); } }); PK!ġ::52.2.0/rdoc/generator/template/darkfish/js/darkfish.jsnu[/** * * Darkfish Page Functions * $Id: darkfish.js 53 2009-01-07 02:52:03Z deveiant $ * * Author: Michael Granger * */ /* Provide console simulation for firebug-less environments */ if (!("console" in window) || !("firebug" in console)) { var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"]; window.console = {}; for (var i = 0; i < names.length; ++i) window.console[names[i]] = function() {}; }; /** * Unwrap the first element that matches the given @expr@ from the targets and return them. */ $.fn.unwrap = function( expr ) { return this.each( function() { $(this).parents( expr ).eq( 0 ).after( this ).remove(); }); }; function showSource( e ) { var target = e.target; var codeSections = $(target). parents('.method-detail'). find('.method-source-code'); $(target). parents('.method-detail'). find('.method-source-code'). slideToggle(); }; function hookSourceViews() { $('.method-heading').click( showSource ); }; function hookSearch() { var input = $('#search-field').eq(0); var result = $('#search-results').eq(0); $(result).show(); var search_section = $('#search-section').get(0); $(search_section).show(); var search = new Search(search_data, input, result); search.renderItem = function(result) { var li = document.createElement('li'); var html = ''; // TODO add relative path to <% if @options.template_stylesheets.flatten.any? then %> <% @options.template_stylesheets.flatten.each do |stylesheet| %> <% end %> <% end %> PK!*f<2.2.0/rdoc/generator/template/darkfish/_sidebar_search.rhtmlnu[ PK!G˸ 2.2.0/rdoc/generator/markup.rbnu[## # Handle common RDoc::Markup tasks for various CodeObjects # # This module is loaded by generators. It allows RDoc's CodeObject tree to # avoid loading generator code to improve startup time for +ri+. module RDoc::Generator::Markup ## # Generates a relative URL from this object's path to +target_path+ def aref_to(target_path) RDoc::Markup::ToHtml.gen_relative_url path, target_path end ## # Generates a relative URL from +from_path+ to this object's path def as_href(from_path) RDoc::Markup::ToHtml.gen_relative_url from_path, path end ## # Handy wrapper for marking up this object's comment def description markup @comment end ## # Creates an RDoc::Markup::ToHtmlCrossref formatter def formatter return @formatter if defined? @formatter options = @store.rdoc.options this = RDoc::Context === self ? self : @parent @formatter = RDoc::Markup::ToHtmlCrossref.new options, this.path, this @formatter.code_object = self @formatter end ## # Build a webcvs URL starting for the given +url+ with +full_path+ appended # as the destination path. If +url+ contains '%s' +full_path+ will be # will replace the %s using sprintf on the +url+. def cvs_url(url, full_path) if /%s/ =~ url then sprintf url, full_path else url + full_path end end end class RDoc::CodeObject include RDoc::Generator::Markup end class RDoc::MethodAttr @add_line_numbers = false class << self ## # Allows controlling whether #markup_code adds line numbers to # the source code. attr_accessor :add_line_numbers end ## # Prepend +src+ with line numbers. Relies on the first line of a source # code listing having: # # # File xxxxx, line dddd # # If it has this comment then line numbers are added to +src+ and the , # line dddd portion of the comment is removed. def add_line_numbers(src) return unless src.sub!(/\A(.*)(, line (\d+))/, '\1') first = $3.to_i - 1 last = first + src.count("\n") size = last.to_s.length line = first src.gsub!(/^/) do res = if line == first then " " * (size + 1) else "%2$*1$d " % [size, line] end line += 1 res end end ## # Turns the method's token stream into HTML. # # Prepends line numbers if +add_line_numbers+ is true. def markup_code return '' unless @token_stream src = RDoc::TokenStream.to_html @token_stream # dedent the source indent = src.length lines = src.lines.to_a lines.shift if src =~ /\A.*#\ *File/i # remove '# File' comment lines.each do |line| if line =~ /^ *(?=\S)/ n = $&.length indent = n if n < indent break if n == 0 end end src.gsub!(/^#{' ' * indent}/, '') if indent > 0 add_line_numbers(src) if RDoc::MethodAttr.add_line_numbers src end end class RDoc::ClassModule ## # Handy wrapper for marking up this class or module's comment def description markup @comment_location end end class RDoc::Context::Section include RDoc::Generator::Markup end class RDoc::TopLevel ## # Returns a URL for this source file on some web repository. Use the -W # command line option to set. def cvs_url url = @store.rdoc.options.webcvs if /%s/ =~ url then url % @relative_name else url + @relative_name end end end PK!$%zz"2.2.0/rdoc/generator/json_index.rbnu[require 'json' require 'zlib' ## # The JsonIndex generator is designed to complement an HTML generator and # produces a JSON search index. This generator is derived from sdoc by # Vladimir Kolesnikov and contains verbatim code written by him. # # This generator is designed to be used with a regular HTML generator: # # class RDoc::Generator::Darkfish # def initialize options # # ... # @base_dir = Pathname.pwd.expand_path # # @json_index = RDoc::Generator::JsonIndex.new self, options # end # # def generate # # ... # @json_index.generate # end # end # # == Index Format # # The index is output as a JSON file assigned to the global variable # +search_data+. The structure is: # # var search_data = { # "index": { # "searchIndex": # ["a", "b", ...], # "longSearchIndex": # ["a", "a::b", ...], # "info": [ # ["A", "A", "A.html", "", ""], # ["B", "A::B", "A::B.html", "", ""], # ... # ] # } # } # # The same item is described across the +searchIndex+, +longSearchIndex+ and # +info+ fields. The +searchIndex+ field contains the item's short name, the # +longSearchIndex+ field contains the full_name (when appropriate) and the # +info+ field contains the item's name, full_name, path, parameters and a # snippet of the item's comment. # # == LICENSE # # Copyright (c) 2009 Vladimir Kolesnikov # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. class RDoc::Generator::JsonIndex include RDoc::Text ## # Where the search index lives in the generated output SEARCH_INDEX_FILE = File.join 'js', 'search_index.js' attr_reader :index # :nodoc: ## # Creates a new generator. +parent_generator+ is used to determine the # class_dir and file_dir of links in the output index. # # +options+ are the same options passed to the parent generator. def initialize parent_generator, options @parent_generator = parent_generator @store = parent_generator.store @options = options @template_dir = File.expand_path '../template/json_index', __FILE__ @base_dir = @parent_generator.base_dir @classes = nil @files = nil @index = nil end ## # Builds the JSON index as a Hash. def build_index reset @store.all_files.sort, @store.all_classes_and_modules.sort index_classes index_methods index_pages { :index => @index } end ## # Output progress information if debugging is enabled def debug_msg *msg return unless $DEBUG_RDOC $stderr.puts(*msg) end ## # Writes the JSON index to disk def generate debug_msg "Generating JSON index" debug_msg " writing search index to %s" % SEARCH_INDEX_FILE data = build_index return if @options.dry_run out_dir = @base_dir + @options.op_dir index_file = out_dir + SEARCH_INDEX_FILE FileUtils.mkdir_p index_file.dirname, :verbose => $DEBUG_RDOC index_file.open 'w', 0644 do |io| io.set_encoding Encoding::UTF_8 if Object.const_defined? :Encoding io.write 'var search_data = ' JSON.dump data, io, 0 end Dir.chdir @template_dir do Dir['**/*.js'].each do |source| dest = File.join out_dir, source FileUtils.install source, dest, :mode => 0644, :verbose => $DEBUG_RDOC end end end ## # Compress the search_index.js file using gzip def generate_gzipped debug_msg "Compressing generated JSON index" out_dir = @base_dir + @options.op_dir search_index_file = out_dir + SEARCH_INDEX_FILE outfile = out_dir + "#{search_index_file}.gz" debug_msg "Reading the JSON index file from %s" % search_index_file search_index = search_index_file.read debug_msg "Writing gzipped search index to %s" % outfile Zlib::GzipWriter.open(outfile) do |gz| gz.mtime = File.mtime(search_index_file) gz.orig_name = search_index_file.to_s gz.write search_index gz.close end # GZip the rest of the js files Dir.chdir @template_dir do Dir['**/*.js'].each do |source| dest = out_dir + source outfile = out_dir + "#{dest}.gz" debug_msg "Reading the original js file from %s" % dest data = dest.read debug_msg "Writing gzipped file to %s" % outfile Zlib::GzipWriter.open(outfile) do |gz| gz.mtime = File.mtime(dest) gz.orig_name = dest.to_s gz.write data gz.close end end end end ## # Adds classes and modules to the index def index_classes debug_msg " generating class search index" documented = @classes.uniq.select do |klass| klass.document_self_or_methods end documented.each do |klass| debug_msg " #{klass.full_name}" record = klass.search_record @index[:searchIndex] << search_string(record.shift) @index[:longSearchIndex] << search_string(record.shift) @index[:info] << record end end ## # Adds methods to the index def index_methods debug_msg " generating method search index" list = @classes.uniq.map do |klass| klass.method_list end.flatten.sort_by do |method| [method.name, method.parent.full_name] end list.each do |method| debug_msg " #{method.full_name}" record = method.search_record @index[:searchIndex] << "#{search_string record.shift}()" @index[:longSearchIndex] << "#{search_string record.shift}()" @index[:info] << record end end ## # Adds pages to the index def index_pages debug_msg " generating pages search index" pages = @files.select do |file| file.text? end pages.each do |page| debug_msg " #{page.page_name}" record = page.search_record @index[:searchIndex] << search_string(record.shift) @index[:longSearchIndex] << '' record.shift @index[:info] << record end end ## # The directory classes are written to def class_dir @parent_generator.class_dir end ## # The directory files are written to def file_dir @parent_generator.file_dir end def reset files, classes # :nodoc: @files = files @classes = classes @index = { :searchIndex => [], :longSearchIndex => [], :info => [] } end ## # Removes whitespace and downcases +string+ def search_string string string.downcase.gsub(/\s/, '') end end PK!S'hNhN 2.2.0/rdoc/generator/darkfish.rbnu[# -*- mode: ruby; ruby-indent-level: 2; tab-width: 2 -*- require 'erb' require 'fileutils' require 'pathname' require 'rdoc/generator/markup' ## # Darkfish RDoc HTML Generator # # $Id: darkfish.rb 52 2009-01-07 02:08:11Z deveiant $ # # == Author/s # * Michael Granger (ged@FaerieMUD.org) # # == Contributors # * Mahlon E. Smith (mahlon@martini.nu) # * Eric Hodel (drbrain@segment7.net) # # == License # # Copyright (c) 2007, 2008, Michael Granger. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # * Neither the name of the author/s, nor the names of the project's # contributors may be used to endorse or promote products derived from this # software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # == Attributions # # Darkfish uses the {Silk Icons}[http://www.famfamfam.com/lab/icons/silk/] set # by Mark James. class RDoc::Generator::Darkfish RDoc::RDoc.add_generator self include ERB::Util ## # Stylesheets, fonts, etc. that are included in RDoc. BUILTIN_STYLE_ITEMS = # :nodoc: %w[ css/fonts.css fonts/Lato-Light.ttf fonts/Lato-LightItalic.ttf fonts/Lato-Regular.ttf fonts/Lato-RegularItalic.ttf fonts/SourceCodePro-Bold.ttf fonts/SourceCodePro-Regular.ttf css/rdoc.css ] ## # Path to this file's parent directory. Used to find templates and other # resources. GENERATOR_DIR = File.join 'rdoc', 'generator' ## # Release Version VERSION = '3' ## # Description of this generator DESCRIPTION = 'HTML generator, written by Michael Granger' ## # The relative path to style sheets and javascript. By default this is set # the same as the rel_prefix. attr_accessor :asset_rel_path ## # The path to generate files into, combined with --op from the # options for a full path. attr_reader :base_dir ## # Classes and modules to be used by this generator, not necessarily # displayed. See also #modsort attr_reader :classes ## # No files will be written when dry_run is true. attr_accessor :dry_run ## # When false the generate methods return a String instead of writing to a # file. The default is true. attr_accessor :file_output ## # Files to be displayed by this generator attr_reader :files ## # The JSON index generator for this Darkfish generator attr_reader :json_index ## # Methods to be displayed by this generator attr_reader :methods ## # Sorted list of classes and modules to be displayed by this generator attr_reader :modsort ## # The RDoc::Store that is the source of the generated content attr_reader :store ## # The directory where the template files live attr_reader :template_dir # :nodoc: ## # The output directory attr_reader :outputdir ## # Initialize a few instance variables before we start def initialize store, options @store = store @options = options @asset_rel_path = '' @base_dir = Pathname.pwd.expand_path @dry_run = @options.dry_run @file_output = true @template_dir = Pathname.new options.template_dir @template_cache = {} @classes = nil @context = nil @files = nil @methods = nil @modsort = nil @json_index = RDoc::Generator::JsonIndex.new self, options end ## # Output progress information if debugging is enabled def debug_msg *msg return unless $DEBUG_RDOC $stderr.puts(*msg) end ## # Directory where generated class HTML files live relative to the output # dir. def class_dir nil end ## # Directory where generated class HTML files live relative to the output # dir. def file_dir nil end ## # Create the directories the generated docs will live in if they don't # already exist. def gen_sub_directories @outputdir.mkpath end ## # Copy over the stylesheet into the appropriate place in the output # directory. def write_style_sheet debug_msg "Copying static files" options = { :verbose => $DEBUG_RDOC, :noop => @dry_run } BUILTIN_STYLE_ITEMS.each do |item| install_rdoc_static_file @template_dir + item, "./#{item}", options end @options.template_stylesheets.each do |stylesheet| FileUtils.cp stylesheet, '.', options end Dir[(@template_dir + "{js,images}/**/*").to_s].each do |path| next if File.directory? path next if File.basename(path) =~ /^\./ dst = Pathname.new(path).relative_path_from @template_dir install_rdoc_static_file @template_dir + path, dst, options end end ## # Build the initial indices and output objects based on an array of TopLevel # objects containing the extracted information. def generate setup write_style_sheet generate_index generate_class_files generate_file_files generate_table_of_contents @json_index.generate @json_index.generate_gzipped copy_static rescue => e debug_msg "%s: %s\n %s" % [ e.class.name, e.message, e.backtrace.join("\n ") ] raise end ## # Copies static files from the static_path into the output directory def copy_static return if @options.static_path.empty? fu_options = { :verbose => $DEBUG_RDOC, :noop => @dry_run } @options.static_path.each do |path| unless File.directory? path then FileUtils.install path, @outputdir, fu_options.merge(:mode => 0644) next end Dir.chdir path do Dir[File.join('**', '*')].each do |entry| dest_file = @outputdir + entry if File.directory? entry then FileUtils.mkdir_p entry, fu_options else FileUtils.install entry, dest_file, fu_options.merge(:mode => 0644) end end end end end ## # Return a list of the documented modules sorted by salience first, then # by name. def get_sorted_module_list classes classes.select do |klass| klass.display? end.sort end ## # Generate an index page which lists all the classes which are documented. def generate_index setup template_file = @template_dir + 'index.rhtml' return unless template_file.exist? debug_msg "Rendering the index page..." out_file = @base_dir + @options.op_dir + 'index.html' rel_prefix = @outputdir.relative_path_from out_file.dirname search_index_rel_prefix = rel_prefix search_index_rel_prefix += @asset_rel_path if @file_output # suppress 1.9.3 warning asset_rel_prefix = asset_rel_prefix = rel_prefix + @asset_rel_path @title = @options.title render_template template_file, out_file do |io| binding end rescue => e error = RDoc::Error.new \ "error generating index.html: #{e.message} (#{e.class})" error.set_backtrace e.backtrace raise error end ## # Generates a class file for +klass+ def generate_class klass, template_file = nil setup current = klass template_file ||= @template_dir + 'class.rhtml' debug_msg " working on %s (%s)" % [klass.full_name, klass.path] out_file = @outputdir + klass.path rel_prefix = @outputdir.relative_path_from out_file.dirname search_index_rel_prefix = rel_prefix search_index_rel_prefix += @asset_rel_path if @file_output # suppress 1.9.3 warning asset_rel_prefix = asset_rel_prefix = rel_prefix + @asset_rel_path svninfo = svninfo = get_svninfo(current) @title = "#{klass.type} #{klass.full_name} - #{@options.title}" debug_msg " rendering #{out_file}" render_template template_file, out_file do |io| binding end end ## # Generate a documentation file for each class and module def generate_class_files setup template_file = @template_dir + 'class.rhtml' template_file = @template_dir + 'classpage.rhtml' unless template_file.exist? return unless template_file.exist? debug_msg "Generating class documentation in #{@outputdir}" current = nil @classes.each do |klass| current = klass generate_class klass, template_file end rescue => e error = RDoc::Error.new \ "error generating #{current.path}: #{e.message} (#{e.class})" error.set_backtrace e.backtrace raise error end ## # Generate a documentation file for each file def generate_file_files setup page_file = @template_dir + 'page.rhtml' fileinfo_file = @template_dir + 'fileinfo.rhtml' # for legacy templates filepage_file = @template_dir + 'filepage.rhtml' unless page_file.exist? or fileinfo_file.exist? return unless page_file.exist? or fileinfo_file.exist? or filepage_file.exist? debug_msg "Generating file documentation in #{@outputdir}" out_file = nil current = nil @files.each do |file| current = file if file.text? and page_file.exist? then generate_page file next end template_file = nil out_file = @outputdir + file.path debug_msg " working on %s (%s)" % [file.full_name, out_file] rel_prefix = @outputdir.relative_path_from out_file.dirname search_index_rel_prefix = rel_prefix search_index_rel_prefix += @asset_rel_path if @file_output # suppress 1.9.3 warning asset_rel_prefix = asset_rel_prefix = rel_prefix + @asset_rel_path unless filepage_file then if file.text? then next unless page_file.exist? template_file = page_file @title = file.page_name else next unless fileinfo_file.exist? template_file = fileinfo_file @title = "File: #{file.base_name}" end end @title += " - #{@options.title}" template_file ||= filepage_file render_template template_file, out_file do |io| binding end end rescue => e error = RDoc::Error.new "error generating #{out_file}: #{e.message} (#{e.class})" error.set_backtrace e.backtrace raise error end ## # Generate a page file for +file+ def generate_page file setup template_file = @template_dir + 'page.rhtml' out_file = @outputdir + file.path debug_msg " working on %s (%s)" % [file.full_name, out_file] rel_prefix = @outputdir.relative_path_from out_file.dirname search_index_rel_prefix = rel_prefix search_index_rel_prefix += @asset_rel_path if @file_output # suppress 1.9.3 warning current = current = file asset_rel_prefix = asset_rel_prefix = rel_prefix + @asset_rel_path @title = "#{file.page_name} - #{@options.title}" debug_msg " rendering #{out_file}" render_template template_file, out_file do |io| binding end end ## # Generates the 404 page for the RDoc servlet def generate_servlet_not_found message setup template_file = @template_dir + 'servlet_not_found.rhtml' return unless template_file.exist? debug_msg "Rendering the servlet 404 Not Found page..." rel_prefix = rel_prefix = '' search_index_rel_prefix = rel_prefix search_index_rel_prefix += @asset_rel_path if @file_output # suppress 1.9.3 warning asset_rel_prefix = asset_rel_prefix = '' @title = 'Not Found' render_template template_file do |io| binding end rescue => e error = RDoc::Error.new \ "error generating servlet_not_found: #{e.message} (#{e.class})" error.set_backtrace e.backtrace raise error end ## # Generates the servlet root page for the RDoc servlet def generate_servlet_root installed setup template_file = @template_dir + 'servlet_root.rhtml' return unless template_file.exist? debug_msg 'Rendering the servlet root page...' rel_prefix = '.' asset_rel_prefix = rel_prefix search_index_rel_prefix = asset_rel_prefix search_index_rel_prefix += @asset_rel_path if @file_output @title = 'Local RDoc Documentation' render_template template_file do |io| binding end rescue => e error = RDoc::Error.new \ "error generating servlet_root: #{e.message} (#{e.class})" error.set_backtrace e.backtrace raise error end ## # Generate an index page which lists all the classes which are documented. def generate_table_of_contents setup template_file = @template_dir + 'table_of_contents.rhtml' return unless template_file.exist? debug_msg "Rendering the Table of Contents..." out_file = @outputdir + 'table_of_contents.html' rel_prefix = @outputdir.relative_path_from out_file.dirname search_index_rel_prefix = rel_prefix search_index_rel_prefix += @asset_rel_path if @file_output # suppress 1.9.3 warning asset_rel_prefix = asset_rel_prefix = rel_prefix + @asset_rel_path @title = "Table of Contents - #{@options.title}" render_template template_file, out_file do |io| binding end rescue => e error = RDoc::Error.new \ "error generating table_of_contents.html: #{e.message} (#{e.class})" error.set_backtrace e.backtrace raise error end def install_rdoc_static_file source, destination, options # :nodoc: return unless source.exist? begin FileUtils.mkdir_p File.dirname(destination), options begin FileUtils.ln source, destination, options rescue Errno::EEXIST FileUtils.rm destination retry end rescue FileUtils.cp source, destination, options end end ## # Prepares for generation of output from the current directory def setup return if instance_variable_defined? :@outputdir @outputdir = Pathname.new(@options.op_dir).expand_path @base_dir return unless @store @classes = @store.all_classes_and_modules.sort @files = @store.all_files.sort @methods = @classes.map { |m| m.method_list }.flatten.sort @modsort = get_sorted_module_list @classes end ## # Return a string describing the amount of time in the given number of # seconds in terms a human can understand easily. def time_delta_string seconds return 'less than a minute' if seconds < 60 return "#{seconds / 60} minute#{seconds / 60 == 1 ? '' : 's'}" if seconds < 3000 # 50 minutes return 'about one hour' if seconds < 5400 # 90 minutes return "#{seconds / 3600} hours" if seconds < 64800 # 18 hours return 'one day' if seconds < 86400 # 1 day return 'about one day' if seconds < 172800 # 2 days return "#{seconds / 86400} days" if seconds < 604800 # 1 week return 'about one week' if seconds < 1209600 # 2 week return "#{seconds / 604800} weeks" if seconds < 7257600 # 3 months return "#{seconds / 2419200} months" if seconds < 31536000 # 1 year return "#{seconds / 31536000} years" end # %q$Id: darkfish.rb 52 2009-01-07 02:08:11Z deveiant $" SVNID_PATTERN = / \$Id:\s (\S+)\s # filename (\d+)\s # rev (\d{4}-\d{2}-\d{2})\s # Date (YYYY-MM-DD) (\d{2}:\d{2}:\d{2}Z)\s # Time (HH:MM:SSZ) (\w+)\s # committer \$$ /x ## # Try to extract Subversion information out of the first constant whose # value looks like a subversion Id tag. If no matching constant is found, # and empty hash is returned. def get_svninfo klass constants = klass.constants or return {} constants.find { |c| c.value =~ SVNID_PATTERN } or return {} filename, rev, date, time, committer = $~.captures commitdate = Time.parse "#{date} #{time}" return { :filename => filename, :rev => Integer(rev), :commitdate => commitdate, :commitdelta => time_delta_string(Time.now - commitdate), :committer => committer, } end ## # Creates a template from its components and the +body_file+. # # For backwards compatibility, if +body_file+ contains " #{head_file.read} #{body} #{footer_file.read} TEMPLATE end ## # Renders the ERb contained in +file_name+ relative to the template # directory and returns the result based on the current context. def render file_name template_file = @template_dir + file_name template = template_for template_file, false, RDoc::ERBPartial template.filename = template_file.to_s template.result @context end ## # Load and render the erb template in the given +template_file+ and write # it out to +out_file+. # # Both +template_file+ and +out_file+ should be Pathname-like objects. # # An io will be yielded which must be captured by binding in the caller. def render_template template_file, out_file = nil # :yield: io io_output = out_file && !@dry_run && @file_output erb_klass = io_output ? RDoc::ERBIO : ERB template = template_for template_file, true, erb_klass if io_output then debug_msg "Outputting to %s" % [out_file.expand_path] out_file.dirname.mkpath out_file.open 'w', 0644 do |io| io.set_encoding @options.encoding if Object.const_defined? :Encoding @context = yield io template_result template, @context, template_file end else @context = yield nil output = template_result template, @context, template_file debug_msg " would have written %d characters to %s" % [ output.length, out_file.expand_path ] if @dry_run output end end ## # Creates the result for +template+ with +context+. If an error is raised a # Pathname +template_file+ will indicate the file where the error occurred. def template_result template, context, template_file template.filename = template_file.to_s template.result context rescue NoMethodError => e raise RDoc::Error, "Error while evaluating %s: %s" % [ template_file.expand_path, e.message, ], e.backtrace end ## # Retrieves a cache template for +file+, if present, or fills the cache. def template_for file, page = true, klass = ERB template = @template_cache[file] return template if template if page then template = assemble_template file erbout = 'io' else template = file.read template = template.encode @options.encoding if Object.const_defined? :Encoding file_var = File.basename(file).sub(/\..*/, '') erbout = "_erbout_#{file_var}" end template = klass.new template, nil, '<>', erbout @template_cache[file] = template template end end PK!sox2.2.0/rdoc/generator/ri.rbnu[## # Generates ri data files class RDoc::Generator::RI RDoc::RDoc.add_generator self ## # Description of this generator DESCRIPTION = 'creates ri data files' ## # Set up a new ri generator def initialize store, options #:not-new: @options = options @store = store @store.path = '.' end ## # Writes the parsed data store to disk for use by ri. def generate @store.save end end PK!d$$2.2.0/rdoc/method_attr.rbnu[## # Abstract class representing either a method or an attribute. class RDoc::MethodAttr < RDoc::CodeObject include Comparable ## # Name of this method/attribute. attr_accessor :name ## # public, protected, private attr_accessor :visibility ## # Is this a singleton method/attribute? attr_accessor :singleton ## # Source file token stream attr_reader :text ## # Array of other names for this method/attribute attr_reader :aliases ## # The method/attribute we're aliasing attr_accessor :is_alias_for #-- # The attributes below are for AnyMethod only. # They are left here for the time being to # allow ri to operate. # TODO modify ri to avoid calling these on attributes. #++ ## # Parameters yielded by the called block attr_reader :block_params ## # Parameters for this method attr_accessor :params ## # Different ways to call this method attr_accessor :call_seq ## # The call_seq or the param_seq with method name, if there is no call_seq. attr_reader :arglists ## # Pretty parameter list for this method attr_reader :param_seq ## # Creates a new MethodAttr from token stream +text+ and method or attribute # name +name+. # # Usually this is called by super from a subclass. def initialize text, name super() @text = text @name = name @aliases = [] @is_alias_for = nil @parent_name = nil @singleton = nil @visibility = :public @see = false @arglists = nil @block_params = nil @call_seq = nil @param_seq = nil @params = nil end ## # Resets cached data for the object so it can be rebuilt by accessor methods def initialize_copy other # :nodoc: @full_name = nil end def initialize_visibility # :nodoc: super @see = nil end ## # Order by #singleton then #name def <=>(other) return unless other.respond_to?(:singleton) && other.respond_to?(:name) [ @singleton ? 0 : 1, name] <=> [other.singleton ? 0 : 1, other.name] end def == other # :nodoc: equal?(other) or self.class == other.class and full_name == other.full_name end ## # A method/attribute is documented if any of the following is true: # - it was marked with :nodoc:; # - it has a comment; # - it is an alias for a documented method; # - it has a +#see+ method that is documented. def documented? super or (is_alias_for and is_alias_for.documented?) or (see and see.documented?) end ## # A method/attribute to look at, # in particular if this method/attribute has no documentation. # # It can be a method/attribute of the superclass or of an included module, # including the Kernel module, which is always appended to the included # modules. # # Returns +nil+ if there is no such method/attribute. # The +#is_alias_for+ method/attribute, if any, is not included. # # Templates may generate a "see also ..." if this method/attribute # has documentation, and "see ..." if it does not. def see @see = find_see if @see == false @see end ## # Sets the store for this class or module and its contained code objects. def store= store super @file = @store.add_file @file.full_name if @file end def find_see # :nodoc: return nil if singleton || is_alias_for # look for the method other = find_method_or_attribute name return other if other # if it is a setter, look for a getter return nil unless name =~ /[a-z_]=$/i # avoid == or === return find_method_or_attribute name[0..-2] end def find_method_or_attribute name # :nodoc: return nil unless parent.respond_to? :ancestors searched = parent.ancestors kernel = @store.modules_hash['Kernel'] searched << kernel if kernel && parent != kernel && !searched.include?(kernel) searched.each do |ancestor| next if String === ancestor next if parent == ancestor other = ancestor.find_method_named('#' << name) || ancestor.find_attribute_named(name) return other if other end nil end ## # Abstract method. Contexts in their building phase call this # to register a new alias for this known method/attribute. # # - creates a new AnyMethod/Attribute named an_alias.new_name; # - adds +self+ as an alias for the new method or attribute # - adds the method or attribute to #aliases # - adds the method or attribute to +context+. def add_alias(an_alias, context) raise NotImplementedError end ## # HTML fragment reference for this method def aref type = singleton ? 'c' : 'i' # % characters are not allowed in html names => dash instead "#{aref_prefix}-#{type}-#{html_name}" end ## # Prefix for +aref+, defined by subclasses. def aref_prefix raise NotImplementedError end ## # Attempts to sanitize the content passed by the Ruby parser: # remove outer parentheses, etc. def block_params=(value) # 'yield.to_s' or 'assert yield, msg' return @block_params = '' if value =~ /^[\.,]/ # remove trailing 'if/unless ...' return @block_params = '' if value =~ /^(if|unless)\s/ value = $1.strip if value =~ /^(.+)\s(if|unless)\s/ # outer parentheses value = $1 if value =~ /^\s*\((.*)\)\s*$/ value = value.strip # proc/lambda return @block_params = $1 if value =~ /^(proc|lambda)(\s*\{|\sdo)/ # surrounding +...+ or [...] value = $1.strip if value =~ /^\+(.*)\+$/ value = $1.strip if value =~ /^\[(.*)\]$/ return @block_params = '' if value.empty? # global variable return @block_params = 'str' if value =~ /^\$[&0-9]$/ # wipe out array/hash indices value.gsub!(/(\w)\[[^\[]+\]/, '\1') # remove @ from class/instance variables value.gsub!(/@@?([a-z0-9_]+)/, '\1') # method calls => method name value.gsub!(/([A-Z:a-z0-9_]+)\.([a-z0-9_]+)(\s*\(\s*[a-z0-9_.,\s]*\s*\)\s*)?/) do case $2 when 'to_s' then $1 when 'const_get' then 'const' when 'new' then $1.split('::').last. # ClassName => class_name gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2'). gsub(/([a-z\d])([A-Z])/,'\1_\2'). downcase else $2 end end # class prefixes value.gsub!(/[A-Za-z0-9_:]+::/, '') # simple expressions value = $1 if value =~ /^([a-z0-9_]+)\s*[-*+\/]/ @block_params = value.strip end ## # HTML id-friendly method/attribute name def html_name require 'cgi' CGI.escape(@name.gsub('-', '-2D')).gsub('%','-').sub(/^-/, '') end ## # Full method/attribute name including namespace def full_name @full_name ||= "#{parent_name}#{pretty_name}" end def inspect # :nodoc: alias_for = @is_alias_for ? " (alias for #{@is_alias_for.name})" : nil visibility = self.visibility visibility = "forced #{visibility}" if force_documentation "#<%s:0x%x %s (%s)%s>" % [ self.class, object_id, full_name, visibility, alias_for, ] end ## # '::' for a class method/attribute, '#' for an instance method. def name_prefix @singleton ? '::' : '#' end ## # Name for output to HTML. For class methods the full name with a "." is # used like +SomeClass.method_name+. For instance methods the class name is # used if +context+ does not match the parent. # # This is to help prevent people from using :: to call class methods. def output_name context return "#{name_prefix}#{@name}" if context == parent "#{parent_name}#{@singleton ? '.' : '#'}#{@name}" end ## # Method/attribute name with class/instance indicator def pretty_name "#{name_prefix}#{@name}" end ## # Type of method/attribute (class or instance) def type singleton ? 'class' : 'instance' end ## # Path to this method for use with HTML generator output. def path "#{@parent.path}##{aref}" end ## # Name of our parent with special handling for un-marshaled methods def parent_name @parent_name || super end def pretty_print q # :nodoc: alias_for = if @is_alias_for.respond_to? :name then "alias for #{@is_alias_for.name}" elsif Array === @is_alias_for then "alias for #{@is_alias_for.last}" end q.group 2, "[#{self.class.name} #{full_name} #{visibility}", "]" do if alias_for then q.breakable q.text alias_for end if text then q.breakable q.text "text:" q.breakable q.pp @text end unless comment.empty? then q.breakable q.text "comment:" q.breakable q.pp @comment end end end ## # Used by RDoc::Generator::JsonIndex to create a record for the search # engine. def search_record [ @name, full_name, @name, @parent.full_name, path, params, snippet(@comment), ] end def to_s # :nodoc: if @is_alias_for "#{self.class.name}: #{full_name} -> #{is_alias_for}" else "#{self.class.name}: #{full_name}" end end end PK!V  2.2.0/rdoc/tom_doc.rbnu[# :markup: tomdoc # A parser for TomDoc based on TomDoc 1.0.0-rc1 (02adef9b5a) # # The TomDoc specification can be found at: # # http://tomdoc.org # # The latest version of the TomDoc specification can be found at: # # https://github.com/mojombo/tomdoc/blob/master/tomdoc.md # # To choose TomDoc as your only default format see RDoc::Options@Saved+Options # for instructions on setting up a .rdoc_options file to store # your project default. # # There are a few differences between this parser and the specification. A # best-effort was made to follow the specification as closely as possible but # some choices to deviate were made. # # A future version of RDoc will warn when a MUST or MUST NOT is violated and # may warn when a SHOULD or SHOULD NOT is violated. RDoc will always try # to emit documentation even if given invalid TomDoc. # # Here are some implementation choices this parser currently makes: # # This parser allows rdoc-style inline markup but you should not depended on # it. # # This parser allows a space between the comment and the method body. # # This parser does not require the default value to be described for an # optional argument. # # This parser does not examine the order of sections. An Examples section may # precede the Arguments section. # # This class is documented in TomDoc format. Since this is a subclass of the # RDoc markup parser there isn't much to see here, unfortunately. class RDoc::TomDoc < RDoc::Markup::Parser # Internal: Token accessor attr_reader :tokens # Internal: Adds a post-processor which sets the RDoc section based on the # comment's status. # # Returns nothing. def self.add_post_processor # :nodoc: RDoc::Markup::PreProcess.post_process do |comment, code_object| next unless code_object and RDoc::Comment === comment and comment.format == 'tomdoc' comment.text.gsub!(/(\A\s*# )(Public|Internal|Deprecated):\s+/) do section = code_object.add_section $2 code_object.temporary_section = section $1 end end end add_post_processor # Public: Parses TomDoc from text # # text - A String containing TomDoc-format text. # # Examples # # RDoc::TomDoc.parse <<-TOMDOC # This method does some things # # Returns nothing. # TOMDOC # # => # # # Returns an RDoc::Markup::Document representing the TomDoc format. def self.parse text parser = new parser.tokenize text doc = RDoc::Markup::Document.new parser.parse doc doc end # Internal: Extracts the Signature section's method signature # # comment - An RDoc::Comment that will be parsed and have the signature # extracted # # Returns a String containing the signature and nil if not def self.signature comment return unless comment.tomdoc? document = comment.parse signature = nil found_heading = false found_signature = false document.parts.delete_if do |part| next false if found_signature found_heading ||= RDoc::Markup::Heading === part && part.text == 'Signature' next false unless found_heading next true if RDoc::Markup::BlankLine === part if RDoc::Markup::Verbatim === part then signature = part found_signature = true end end signature and signature.text end # Public: Creates a new TomDoc parser. See also RDoc::Markup::parse def initialize super @section = nil @seen_returns = false end # Internal: Builds a heading from the token stream # # level - The level of heading to create # # Returns an RDoc::Markup::Heading def build_heading level heading = super @section = heading.text heading end # Internal: Builds a verbatim from the token stream. A verbatim in the # Examples section will be marked as in Ruby format. # # margin - The indentation from the margin for lines that belong to this # verbatim section. # # Returns an RDoc::Markup::Verbatim def build_verbatim margin verbatim = super verbatim.format = :ruby if @section == 'Examples' verbatim end # Internal: Builds a paragraph from the token stream # # margin - Unused # # Returns an RDoc::Markup::Paragraph. def build_paragraph margin p :paragraph_start => margin if @debug paragraph = RDoc::Markup::Paragraph.new until @tokens.empty? do type, data, = get case type when :TEXT then @section = 'Returns' if data =~ /\AReturns/ paragraph << data when :NEWLINE then if :TEXT == peek_token[0] then paragraph << ' ' else break end else unget break end end p :paragraph_end => margin if @debug paragraph end ## # Detects a section change to "Returns" and adds a heading def parse_text parent, indent # :nodoc: paragraph = build_paragraph indent if false == @seen_returns and 'Returns' == @section then @seen_returns = true parent << RDoc::Markup::Heading.new(3, 'Returns') parent << RDoc::Markup::BlankLine.new end parent << paragraph end # Internal: Turns text into an Array of tokens # # text - A String containing TomDoc-format text. # # Returns self. def tokenize text text.sub!(/\A(Public|Internal|Deprecated):\s+/, '') setup_scanner text until @s.eos? do pos = @s.pos # leading spaces will be reflected by the column of the next token # the only thing we loose are trailing spaces at the end of the file next if @s.scan(/ +/) @tokens << case when @s.scan(/\r?\n/) then token = [:NEWLINE, @s.matched, *token_pos(pos)] @line_pos = char_pos @s.pos @line += 1 token when @s.scan(/(Examples|Signature)$/) then @tokens << [:HEADER, 3, *token_pos(pos)] [:TEXT, @s[1], *token_pos(pos)] when @s.scan(/([:\w][\w\[\]]*)[ ]+- /) then [:NOTE, @s[1], *token_pos(pos)] else @s.scan(/.*/) [:TEXT, @s.matched.sub(/\r$/, ''), *token_pos(pos)] end end self end end PK!&Ӡ2.2.0/rdoc/task.rbnu[#-- # Copyright (c) 2003, 2004 Jim Weirich, 2009 Eric Hodel # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #++ require 'rubygems' begin gem 'rdoc' rescue Gem::LoadError end unless defined?(RDoc) begin gem 'rake' rescue Gem::LoadError end unless defined?(Rake) require 'rdoc' require 'rake' require 'rake/tasklib' ## # RDoc::Task creates the following rake tasks to generate and clean up RDoc # output: # # [rdoc] # Main task for this RDoc task. # # [clobber_rdoc] # Delete all the rdoc files. This target is automatically added to the main # clobber target. # # [rerdoc] # Rebuild the rdoc files from scratch, even if they are not out of date. # # Simple Example: # # require 'rdoc/task' # # RDoc::Task.new do |rdoc| # rdoc.main = "README.rdoc" # rdoc.rdoc_files.include("README.rdoc", "lib/**/*.rb") # end # # The +rdoc+ object passed to the block is an RDoc::Task object. See the # attributes list for the RDoc::Task class for available customization options. # # == Specifying different task names # # You may wish to give the task a different name, such as if you are # generating two sets of documentation. For instance, if you want to have a # development set of documentation including private methods: # # require 'rdoc/task' # # RDoc::Task.new :rdoc_dev do |rdoc| # rdoc.main = "README.doc" # rdoc.rdoc_files.include("README.rdoc", "lib/**/*.rb") # rdoc.options << "--all" # end # # The tasks would then be named :rdoc_dev, # :clobber_rdoc_dev, and :rerdoc_dev. # # If you wish to have completely different task names, then pass a Hash as # first argument. With the :rdoc, :clobber_rdoc and # :rerdoc options, you can customize the task names to your liking. # # For example: # # require 'rdoc/task' # # RDoc::Task.new(:rdoc => "rdoc", :clobber_rdoc => "rdoc:clean", # :rerdoc => "rdoc:force") # # This will create the tasks :rdoc, :rdoc:clean and # :rdoc:force. class RDoc::Task < Rake::TaskLib ## # Name of the main, top level task. (default is :rdoc) attr_accessor :name ## # Comment markup format. rdoc, rd and tomdoc are supported. (default is # 'rdoc') attr_accessor :markup ## # Name of directory to receive the html output files. (default is "html") attr_accessor :rdoc_dir ## # Title of RDoc documentation. (defaults to rdoc's default) attr_accessor :title ## # Name of file to be used as the main, top level file of the RDoc. (default # is none) attr_accessor :main ## # Name of template to be used by rdoc. (defaults to rdoc's default) attr_accessor :template ## # Name of format generator (--format) used by rdoc. (defaults to # rdoc's default) attr_accessor :generator ## # List of files to be included in the rdoc generation. (default is []) attr_accessor :rdoc_files ## # Additional list of options to be passed rdoc. (default is []) attr_accessor :options ## # Whether to run the rdoc process as an external shell (default is false) attr_accessor :external ## # Create an RDoc task with the given name. See the RDoc::Task class overview # for documentation. def initialize name = :rdoc # :yield: self defaults check_names name @name = name yield self if block_given? define end ## # Ensures that +names+ only includes names for the :rdoc, :clobber_rdoc and # :rerdoc. If other names are given an ArgumentError is raised. def check_names names return unless Hash === names invalid_options = names.keys.map { |k| k.to_sym } - [:rdoc, :clobber_rdoc, :rerdoc] unless invalid_options.empty? then raise ArgumentError, "invalid options: #{invalid_options.join ', '}" end end ## # Task description for the clobber rdoc task or its renamed equivalent def clobber_task_description "Remove RDoc HTML files" end ## # Sets default task values def defaults @name = :rdoc @rdoc_files = Rake::FileList.new @rdoc_dir = 'html' @main = nil @title = nil @template = nil @generator = nil @options = [] end ## # All source is inline now. This method is deprecated def inline_source # :nodoc: warn "RDoc::Task#inline_source is deprecated" true end ## # All source is inline now. This method is deprecated def inline_source=(value) # :nodoc: warn "RDoc::Task#inline_source is deprecated" end ## # Create the tasks defined by this task lib. def define desc rdoc_task_description task rdoc_task_name desc rerdoc_task_description task rerdoc_task_name => [clobber_task_name, rdoc_task_name] desc clobber_task_description task clobber_task_name do rm_r @rdoc_dir rescue nil end task :clobber => [clobber_task_name] directory @rdoc_dir rdoc_target_deps = [ @rdoc_files, Rake.application.rakefile ].flatten.compact task rdoc_task_name => [rdoc_target] file rdoc_target => rdoc_target_deps do @before_running_rdoc.call if @before_running_rdoc args = option_list + @rdoc_files $stderr.puts "rdoc #{args.join ' '}" if Rake.application.options.trace RDoc::RDoc.new.document args end self end ## # List of options that will be supplied to RDoc def option_list result = @options.dup result << "-o" << @rdoc_dir result << "--main" << main if main result << "--markup" << markup if markup result << "--title" << title if title result << "-T" << template if template result << '-f' << generator if generator result end ## # The block passed to this method will be called just before running the # RDoc generator. It is allowed to modify RDoc::Task attributes inside the # block. def before_running_rdoc(&block) @before_running_rdoc = block end ## # Task description for the rdoc task or its renamed equivalent def rdoc_task_description 'Build RDoc HTML files' end ## # Task description for the rerdoc task or its renamed description def rerdoc_task_description "Rebuild RDoc HTML files" end private def rdoc_target "#{rdoc_dir}/created.rid" end def rdoc_task_name case name when Hash then (name[:rdoc] || "rdoc").to_s else name.to_s end end def clobber_task_name case name when Hash then (name[:clobber_rdoc] || "clobber_rdoc").to_s else "clobber_#{name}" end end def rerdoc_task_name case name when Hash then (name[:rerdoc] || "rerdoc").to_s else "re#{name}" end end end # :stopdoc: module Rake ## # For backwards compatibility RDocTask = RDoc::Task end # :startdoc: PK!y툃%%2.2.0/rdoc/code_object.rbnu[## # Base class for the RDoc code tree. # # We contain the common stuff for contexts (which are containers) and other # elements (methods, attributes and so on) # # Here's the tree of the CodeObject subclasses: # # * RDoc::Context # * RDoc::TopLevel # * RDoc::ClassModule # * RDoc::AnonClass (never used so far) # * RDoc::NormalClass # * RDoc::NormalModule # * RDoc::SingleClass # * RDoc::MethodAttr # * RDoc::Attr # * RDoc::AnyMethod # * RDoc::GhostMethod # * RDoc::MetaMethod # * RDoc::Alias # * RDoc::Constant # * RDoc::Mixin # * RDoc::Require # * RDoc::Include class RDoc::CodeObject include RDoc::Text ## # Our comment attr_reader :comment ## # Do we document our children? attr_reader :document_children ## # Do we document ourselves? attr_reader :document_self ## # Are we done documenting (ie, did we come across a :enddoc:)? attr_reader :done_documenting ## # Which file this code object was defined in attr_reader :file ## # Force documentation of this CodeObject attr_reader :force_documentation ## # Line in #file where this CodeObject was defined attr_accessor :line ## # Hash of arbitrary metadata for this CodeObject attr_reader :metadata ## # Offset in #file where this CodeObject was defined #-- # TODO character or byte? attr_accessor :offset ## # Sets the parent CodeObject attr_writer :parent ## # Did we ever receive a +:nodoc:+ directive? attr_reader :received_nodoc ## # Set the section this CodeObject is in attr_writer :section ## # The RDoc::Store for this object. attr_reader :store ## # We are the model of the code, but we know that at some point we will be # worked on by viewers. By implementing the Viewable protocol, viewers can # associated themselves with these objects. attr_accessor :viewer ## # Creates a new CodeObject that will document itself and its children def initialize @metadata = {} @comment = '' @parent = nil @parent_name = nil # for loading @parent_class = nil # for loading @section = nil @section_title = nil # for loading @file = nil @full_name = nil @store = nil @track_visibility = true initialize_visibility end ## # Initializes state for visibility of this CodeObject and its children. def initialize_visibility # :nodoc: @document_children = true @document_self = true @done_documenting = false @force_documentation = false @received_nodoc = false @ignored = false @suppressed = false @track_visibility = true end ## # Replaces our comment with +comment+, unless it is empty. def comment=(comment) @comment = case comment when NilClass then '' when RDoc::Markup::Document then comment when RDoc::Comment then comment.normalize else if comment and not comment.empty? then normalize_comment comment else # HACK correct fix is to have #initialize create @comment # with the correct encoding if String === @comment and Object.const_defined? :Encoding and @comment.empty? then @comment.force_encoding comment.encoding end @comment end end end ## # Should this CodeObject be displayed in output? # # A code object should be displayed if: # # * The item didn't have a nodoc or wasn't in a container that had nodoc # * The item wasn't ignored # * The item has documentation and was not suppressed def display? @document_self and not @ignored and (documented? or not @suppressed) end ## # Enables or disables documentation of this CodeObject's children unless it # has been turned off by :enddoc: def document_children=(document_children) return unless @track_visibility @document_children = document_children unless @done_documenting end ## # Enables or disables documentation of this CodeObject unless it has been # turned off by :enddoc:. If the argument is +nil+ it means the # documentation is turned off by +:nodoc:+. def document_self=(document_self) return unless @track_visibility return if @done_documenting @document_self = document_self @received_nodoc = true if document_self.nil? end ## # Does this object have a comment with content or is #received_nodoc true? def documented? @received_nodoc or !@comment.empty? end ## # Turns documentation on/off, and turns on/off #document_self # and #document_children. # # Once documentation has been turned off (by +:enddoc:+), # the object will refuse to turn #document_self or # #document_children on, so +:doc:+ and +:start_doc:+ directives # will have no effect in the current file. def done_documenting=(value) return unless @track_visibility @done_documenting = value @document_self = !value @document_children = @document_self end ## # Yields each parent of this CodeObject. See also # RDoc::ClassModule#each_ancestor def each_parent code_object = self while code_object = code_object.parent do yield code_object end self end ## # File name where this CodeObject was found. # # See also RDoc::Context#in_files def file_name return unless @file @file.absolute_name end ## # Force the documentation of this object unless documentation # has been turned off by :enddoc: #-- # HACK untested, was assigning to an ivar def force_documentation=(value) @force_documentation = value unless @done_documenting end ## # Sets the full_name overriding any computed full name. # # Set to +nil+ to clear RDoc's cached value def full_name= full_name @full_name = full_name end ## # Use this to ignore a CodeObject and all its children until found again # (#record_location is called). An ignored item will not be displayed in # documentation. # # See github issue #55 # # The ignored status is temporary in order to allow implementation details # to be hidden. At the end of processing a file RDoc allows all classes # and modules to add new documentation to previously created classes. # # If a class was ignored (via stopdoc) then reopened later with additional # documentation it should be displayed. If a class was ignored and never # reopened it should not be displayed. The ignore flag allows this to # occur. def ignore return unless @track_visibility @ignored = true stop_doc end ## # Has this class been ignored? # # See also #ignore def ignored? @ignored end ## # The options instance from the store this CodeObject is attached to, or a # default options instance if the CodeObject is not attached. # # This is used by Text#snippet def options if @store and @store.rdoc then @store.rdoc.options else RDoc::Options.new end end ## # Our parent CodeObject. The parent may be missing for classes loaded from # legacy RI data stores. def parent return @parent if @parent return nil unless @parent_name if @parent_class == RDoc::TopLevel then @parent = @store.add_file @parent_name else @parent = @store.find_class_or_module @parent_name return @parent if @parent begin @parent = @store.load_class @parent_name rescue RDoc::Store::MissingFileError nil end end end ## # File name of our parent def parent_file_name @parent ? @parent.base_name : '(unknown)' end ## # Name of our parent def parent_name @parent ? @parent.full_name : '(unknown)' end ## # Records the RDoc::TopLevel (file) where this code object was defined def record_location top_level @ignored = false @suppressed = false @file = top_level end ## # The section this CodeObject is in. Sections allow grouping of constants, # attributes and methods inside a class or module. def section return @section if @section @section = parent.add_section @section_title if parent end ## # Enable capture of documentation unless documentation has been # turned off by :enddoc: def start_doc return if @done_documenting @document_self = true @document_children = true @ignored = false @suppressed = false end ## # Disable capture of documentation def stop_doc return unless @track_visibility @document_self = false @document_children = false end ## # Sets the +store+ that contains this CodeObject def store= store @store = store return unless @track_visibility if :nodoc == options.visibility then initialize_visibility @track_visibility = false end end ## # Use this to suppress a CodeObject and all its children until the next file # it is seen in or documentation is discovered. A suppressed item with # documentation will be displayed while an ignored item with documentation # may not be displayed. def suppress return unless @track_visibility @suppressed = true stop_doc end ## # Has this class been suppressed? # # See also #suppress def suppressed? @suppressed end end PK!gܤ2.2.0/rdoc/test_case.rbnu[require 'rubygems' begin gem 'minitest', '~> 4.0' unless defined?(Test::Unit) rescue NoMethodError, Gem::LoadError # for ruby tests end require 'minitest/autorun' require 'minitest/benchmark' if ENV['BENCHMARK'] require 'fileutils' require 'pp' require 'tempfile' require 'tmpdir' require 'stringio' require 'rdoc' ## # RDoc::TestCase is an abstract TestCase to provide common setup and teardown # across all RDoc tests. The test case uses minitest, so all the assertions # of minitest may be used. # # The testcase provides the following: # # * A reset code-object tree # * A reset markup preprocessor (RDoc::Markup::PreProcess) # * The @RM alias of RDoc::Markup (for less typing) # * @pwd containing the current working directory # * FileUtils, pp, Tempfile, Dir.tmpdir and StringIO class RDoc::TestCase < MiniTest::Unit::TestCase ## # Abstract test-case setup def setup super @top_level = nil @have_encoding = Object.const_defined? :Encoding @RM = RDoc::Markup RDoc::Markup::PreProcess.reset @pwd = Dir.pwd @store = RDoc::Store.new @rdoc = RDoc::RDoc.new @rdoc.store = @store @rdoc.options = RDoc::Options.new g = Object.new def g.class_dir() end def g.file_dir() end @rdoc.generator = g end ## # Asserts +path+ is a file def assert_file path assert File.file?(path), "#{path} is not a file" end ## # Asserts +path+ is a directory def assert_directory path assert File.directory?(path), "#{path} is not a directory" end ## # Refutes +path+ exists def refute_file path refute File.exist?(path), "#{path} exists" end ## # Shortcut for RDoc::Markup::BlankLine.new def blank_line @RM::BlankLine.new end ## # Shortcut for RDoc::Markup::BlockQuote.new with +contents+ def block *contents @RM::BlockQuote.new(*contents) end ## # Creates an RDoc::Comment with +text+ which was defined on +top_level+. # By default the comment has the 'rdoc' format. def comment text, top_level = @top_level RDoc::Comment.new text, top_level end ## # Shortcut for RDoc::Markup::Document.new with +contents+ def doc *contents @RM::Document.new(*contents) end ## # Shortcut for RDoc::Markup::HardBreak.new def hard_break @RM::HardBreak.new end ## # Shortcut for RDoc::Markup::Heading.new with +level+ and +text+ def head level, text @RM::Heading.new level, text end ## # Shortcut for RDoc::Markup::ListItem.new with +label+ and +parts+ def item label = nil, *parts @RM::ListItem.new label, *parts end ## # Shortcut for RDoc::Markup::List.new with +type+ and +items+ def list type = nil, *items @RM::List.new type, *items end ## # Enables pretty-print output def mu_pp obj # :nodoc: s = '' s = PP.pp obj, s s = s.force_encoding Encoding.default_external if defined? Encoding s.chomp end ## # Shortcut for RDoc::Markup::Paragraph.new with +contents+ def para *a @RM::Paragraph.new(*a) end ## # Shortcut for RDoc::Markup::Rule.new with +weight+ def rule weight @RM::Rule.new weight end ## # Shortcut for RDoc::Markup::Raw.new with +contents+ def raw *contents @RM::Raw.new(*contents) end ## # Creates a temporary directory changes the current directory to it for the # duration of the block. # # Depends upon Dir.mktmpdir def temp_dir skip "No Dir::mktmpdir, upgrade your ruby" unless Dir.respond_to? :mktmpdir Dir.mktmpdir do |temp_dir| Dir.chdir temp_dir do yield temp_dir end end end ## # Shortcut for RDoc::Markup::Verbatim.new with +parts+ def verb *parts @RM::Verbatim.new(*parts) end ## # run capture_io with setting $VERBOSE = true def verbose_capture_io capture_io do begin orig_verbose = $VERBOSE $VERBOSE = true yield ensure $VERBOSE = orig_verbose end end end end # This hack allows autoload to work when Dir.pwd is changed for Ruby 1.8 since # -I paths are not expanded. $LOAD_PATH.each do |load_path| break if load_path[0] == ?/ load_path.replace File.expand_path load_path end if RUBY_VERSION < '1.9' PK!m d d 2.2.0/rdoc/i18n/text.rbnu[## # An i18n supported text. # # This object provides the following two features: # # * Extracts translation messages from wrapped raw text. # * Translates wrapped raw text in specified locale. # # Wrapped raw text is one of String, RDoc::Comment or Array of them. class RDoc::I18n::Text ## # Creates a new i18n supported text for +raw+ text. def initialize(raw) @raw = raw end ## # Extracts translation target messages and yields each message. # # Each yielded message is a Hash. It consists of the followings: # # :type :: :paragraph # :paragraph :: String (The translation target message itself.) # :line_no :: Integer (The line number of the :paragraph is started.) # # The above content may be added in the future. def extract_messages parse do |part| case part[:type] when :empty_line # ignore when :paragraph yield(part) end end end # Translates raw text into +locale+. def translate(locale) translated_text = '' parse do |part| case part[:type] when :paragraph translated_text << locale.translate(part[:paragraph]) when :empty_line translated_text << part[:line] else raise "should not reach here: unexpected type: #{type}" end end translated_text end private def parse(&block) paragraph = '' paragraph_start_line = 0 line_no = 0 each_line(@raw) do |line| line_no += 1 case line when /\A\s*\z/ if paragraph.empty? emit_empty_line_event(line, line_no, &block) else paragraph << line emit_paragraph_event(paragraph, paragraph_start_line, line_no, &block) paragraph = '' end else paragraph_start_line = line_no if paragraph.empty? paragraph << line end end unless paragraph.empty? emit_paragraph_event(paragraph, paragraph_start_line, line_no, &block) end end def each_line(raw, &block) case raw when RDoc::Comment raw.text.each_line(&block) when Array raw.each do |comment, location| each_line(comment, &block) end else raw.each_line(&block) end end def emit_empty_line_event(line, line_no) part = { :type => :empty_line, :line => line, :line_no => line_no, } yield(part) end def emit_paragraph_event(paragraph, paragraph_start_line, line_no, &block) paragraph_part = { :type => :paragraph, :line_no => paragraph_start_line, } match_data = /(\s*)\z/.match(paragraph) if match_data paragraph_part[:paragraph] = match_data.pre_match yield(paragraph_part) emit_empty_line_event(match_data[1], line_no, &block) else paragraph_part[:paragraph] = paragraph yield(paragraph_part) end end end PK!׶=vH H 2.2.0/rdoc/i18n/locale.rbnu[## # A message container for a locale. # # This object provides the following two features: # # * Loads translated messages from .po file. # * Translates a message into the locale. class RDoc::I18n::Locale @@locales = {} # :nodoc: class << self ## # Returns the locale object for +locale_name+. def [](locale_name) @@locales[locale_name] ||= new(locale_name) end ## # Sets the locale object for +locale_name+. # # Normally, this method is not used. This method is useful for # testing. def []=(locale_name, locale) @@locales[locale_name] = locale end end ## # The name of the locale. It uses IETF language tag format # +[language[_territory][.codeset][@modifier]]+. # # See also {BCP 47 - Tags for Identifying # Languages}[http://tools.ietf.org/rfc/bcp/bcp47.txt]. attr_reader :name ## # Creates a new locale object for +name+ locale. +name+ must # follow IETF language tag format. def initialize(name) @name = name @messages = {} end ## # Loads translation messages from +locale_directory+/+@name+/rdoc.po # or +locale_directory+/+@name+.po. The former has high priority. # # This method requires gettext gem for parsing .po file. If you # don't have gettext gem, this method doesn't load .po file. This # method warns and returns +false+. # # Returns +true+ if succeeded, +false+ otherwise. def load(locale_directory) return false if @name.nil? po_file_candidates = [ File.join(locale_directory, @name, 'rdoc.po'), File.join(locale_directory, "#{@name}.po"), ] po_file = po_file_candidates.find do |po_file_candidate| File.exist?(po_file_candidate) end return false unless po_file begin require 'gettext/po_parser' require 'gettext/mo' rescue LoadError warn('Need gettext gem for i18n feature:') warn(' gem install gettext') return false end po_parser = GetText::POParser.new messages = GetText::MO.new po_parser.report_warning = false po_parser.parse_file(po_file, messages) @messages.merge!(messages) true end ## # Translates the +message+ into locale. If there is no tranlsation # messages for +message+ in locale, +message+ itself is returned. def translate(message) @messages[message] || message end end PK!m$r)zYzY2.2.0/rdoc/store.rbnu[require 'fileutils' ## # A set of rdoc data for a single project (gem, path, etc.). # # The store manages reading and writing ri data for a project and maintains a # cache of methods, classes and ancestors in the store. # # The store maintains a #cache of its contents for faster lookup. After # adding items to the store it must be flushed using #save_cache. The cache # contains the following structures: # # @cache = { # :ancestors => {}, # class name => ancestor names # :attributes => {}, # class name => attributes # :class_methods => {}, # class name => class methods # :instance_methods => {}, # class name => instance methods # :modules => [], # classes and modules in this store # :pages => [], # page names # } #-- # TODO need to prune classes class RDoc::Store ## # Errors raised from loading or saving the store class Error < RDoc::Error end ## # Raised when a stored file for a class, module, page or method is missing. class MissingFileError < Error ## # The store the file should exist in attr_reader :store ## # The file the #name should be saved as attr_reader :file ## # The name of the object the #file would be loaded from attr_reader :name ## # Creates a new MissingFileError for the missing +file+ for the given # +name+ that should have been in the +store+. def initialize store, file, name @store = store @file = file @name = name end def message # :nodoc: "store at #{@store.path} missing file #{@file} for #{@name}" end end ## # Stores the name of the C variable a class belongs to. This helps wire up # classes defined from C across files. attr_reader :c_enclosure_classes # :nodoc: attr_reader :c_enclosure_names # :nodoc: ## # Maps C variables to class or module names for each parsed C file. attr_reader :c_class_variables ## # Maps C variables to singleton class names for each parsed C file. attr_reader :c_singleton_class_variables ## # If true this Store will not write any files attr_accessor :dry_run ## # Path this store reads or writes attr_accessor :path ## # The RDoc::RDoc driver for this parse tree. This allows classes consulting # the documentation tree to access user-set options, for example. attr_accessor :rdoc ## # Type of ri datastore this was loaded from. See RDoc::RI::Driver, # RDoc::RI::Paths. attr_accessor :type ## # The contents of the Store attr_reader :cache ## # The encoding of the contents in the Store attr_accessor :encoding ## # Creates a new Store of +type+ that will load or save to +path+ def initialize path = nil, type = nil @dry_run = false @encoding = nil @path = path @rdoc = nil @type = type @cache = { :ancestors => {}, :attributes => {}, :class_methods => {}, :c_class_variables => {}, :c_singleton_class_variables => {}, :encoding => @encoding, :instance_methods => {}, :main => nil, :modules => [], :pages => [], :title => nil, } @classes_hash = {} @modules_hash = {} @files_hash = {} @c_enclosure_classes = {} @c_enclosure_names = {} @c_class_variables = {} @c_singleton_class_variables = {} @unique_classes = nil @unique_modules = nil end ## # Adds +module+ as an enclosure (namespace) for the given +variable+ for C # files. def add_c_enclosure variable, namespace @c_enclosure_classes[variable] = namespace end ## # Adds C variables from an RDoc::Parser::C def add_c_variables c_parser filename = c_parser.top_level.relative_name @c_class_variables[filename] = make_variable_map c_parser.classes @c_singleton_class_variables[filename] = c_parser.singleton_classes end ## # Adds the file with +name+ as an RDoc::TopLevel to the store. Returns the # created RDoc::TopLevel. def add_file absolute_name, relative_name = absolute_name unless top_level = @files_hash[relative_name] then top_level = RDoc::TopLevel.new absolute_name, relative_name top_level.store = self @files_hash[relative_name] = top_level end top_level end ## # Returns all classes discovered by RDoc def all_classes @classes_hash.values end ## # Returns all classes and modules discovered by RDoc def all_classes_and_modules @classes_hash.values + @modules_hash.values end ## # All TopLevels known to RDoc def all_files @files_hash.values end ## # Returns all modules discovered by RDoc def all_modules modules_hash.values end ## # Ancestors cache accessor. Maps a klass name to an Array of its ancestors # in this store. If Foo in this store inherits from Object, Kernel won't be # listed (it will be included from ruby's ri store). def ancestors @cache[:ancestors] end ## # Attributes cache accessor. Maps a class to an Array of its attributes. def attributes @cache[:attributes] end ## # Path to the cache file def cache_path File.join @path, 'cache.ri' end ## # Path to the ri data for +klass_name+ def class_file klass_name name = klass_name.split('::').last File.join class_path(klass_name), "cdesc-#{name}.ri" end ## # Class methods cache accessor. Maps a class to an Array of its class # methods (not full name). def class_methods @cache[:class_methods] end ## # Path where data for +klass_name+ will be stored (methods or class data) def class_path klass_name File.join @path, *klass_name.split('::') end ## # Hash of all classes known to RDoc def classes_hash @classes_hash end ## # Removes empty items and ensures item in each collection are unique and # sorted def clean_cache_collection collection # :nodoc: collection.each do |name, item| if item.empty? then collection.delete name else # HACK mongrel-1.1.5 documents its files twice item.uniq! item.sort! end end end ## # Prepares the RDoc code object tree for use by a generator. # # It finds unique classes/modules defined, and replaces classes/modules that # are aliases for another one by a copy with RDoc::ClassModule#is_alias_for # set. # # It updates the RDoc::ClassModule#constant_aliases attribute of "real" # classes or modules. # # It also completely removes the classes and modules that should be removed # from the documentation and the methods that have a visibility below # +min_visibility+, which is the --visibility option. # # See also RDoc::Context#remove_from_documentation? def complete min_visibility fix_basic_object_inheritance # cache included modules before they are removed from the documentation all_classes_and_modules.each { |cm| cm.ancestors } unless min_visibility == :nodoc then remove_nodoc @classes_hash remove_nodoc @modules_hash end @unique_classes = find_unique @classes_hash @unique_modules = find_unique @modules_hash unique_classes_and_modules.each do |cm| cm.complete min_visibility end @files_hash.each_key do |file_name| tl = @files_hash[file_name] unless tl.text? then tl.modules_hash.clear tl.classes_hash.clear tl.classes_or_modules.each do |cm| name = cm.full_name if cm.type == 'class' then tl.classes_hash[name] = cm if @classes_hash[name] else tl.modules_hash[name] = cm if @modules_hash[name] end end end end end ## # Hash of all files known to RDoc def files_hash @files_hash end ## # Finds the enclosure (namespace) for the given C +variable+. def find_c_enclosure variable @c_enclosure_classes.fetch variable do break unless name = @c_enclosure_names[variable] mod = find_class_or_module name unless mod then loaded_mod = load_class_data name file = loaded_mod.in_files.first return unless file # legacy data source file.store = self mod = file.add_module RDoc::NormalModule, name end @c_enclosure_classes[variable] = mod end end ## # Finds the class with +name+ in all discovered classes def find_class_named name @classes_hash[name] end ## # Finds the class with +name+ starting in namespace +from+ def find_class_named_from name, from from = find_class_named from unless RDoc::Context === from until RDoc::TopLevel === from do return nil unless from klass = from.find_class_named name return klass if klass from = from.parent end find_class_named name end ## # Finds the class or module with +name+ def find_class_or_module name name = $' if name =~ /^::/ @classes_hash[name] || @modules_hash[name] end ## # Finds the file with +name+ in all discovered files def find_file_named name @files_hash[name] end ## # Finds the module with +name+ in all discovered modules def find_module_named name @modules_hash[name] end ## # Returns the RDoc::TopLevel that is a text file and has the given # +file_name+ def find_text_page file_name @files_hash.each_value.find do |file| file.text? and file.full_name == file_name end end ## # Finds unique classes/modules defined in +all_hash+, # and returns them as an array. Performs the alias # updates in +all_hash+: see ::complete. #-- # TODO aliases should be registered by Context#add_module_alias def find_unique all_hash unique = [] all_hash.each_pair do |full_name, cm| unique << cm if full_name == cm.full_name end unique end ## # Fixes the erroneous BasicObject < Object in 1.9. # # Because we assumed all classes without a stated superclass # inherit from Object, we have the above wrong inheritance. # # We fix BasicObject right away if we are running in a Ruby # version >= 1.9. If not, we may be documenting 1.9 source # while running under 1.8: we search the files of BasicObject # for "object.c", and fix the inheritance if we find it. def fix_basic_object_inheritance basic = classes_hash['BasicObject'] return unless basic if RUBY_VERSION >= '1.9' basic.superclass = nil elsif basic.in_files.any? { |f| File.basename(f.full_name) == 'object.c' } basic.superclass = nil end end ## # Friendly rendition of #path def friendly_path case type when :gem then parent = File.expand_path '..', @path "gem #{File.basename parent}" when :home then '~/.rdoc' when :site then 'ruby site' when :system then 'ruby core' else @path end end def inspect # :nodoc: "#<%s:0x%x %s %p>" % [self.class, object_id, @path, module_names.sort] end ## # Instance methods cache accessor. Maps a class to an Array of its # instance methods (not full name). def instance_methods @cache[:instance_methods] end ## # Loads all items from this store into memory. This recreates a # documentation tree for use by a generator def load_all load_cache module_names.each do |module_name| mod = find_class_or_module(module_name) || load_class(module_name) # load method documentation since the loaded class/module does not have # it loaded_methods = mod.method_list.map do |method| load_method module_name, method.full_name end mod.method_list.replace loaded_methods loaded_attributes = mod.attributes.map do |attribute| load_method module_name, attribute.full_name end mod.attributes.replace loaded_attributes end all_classes_and_modules.each do |mod| descendent_re = /^#{mod.full_name}::[^:]+$/ module_names.each do |name| next unless name =~ descendent_re descendent = find_class_or_module name case descendent when RDoc::NormalClass then mod.classes_hash[name] = descendent when RDoc::NormalModule then mod.modules_hash[name] = descendent end end end @cache[:pages].each do |page_name| page = load_page page_name @files_hash[page_name] = page end end ## # Loads cache file for this store def load_cache #orig_enc = @encoding open cache_path, 'rb' do |io| @cache = Marshal.load io.read end load_enc = @cache[:encoding] # TODO this feature will be time-consuming to add: # a) Encodings may be incompatible but transcodeable # b) Need to warn in the appropriate spots, wherever they may be # c) Need to handle cross-cache differences in encodings # d) Need to warn when generating into a cache with different encodings # #if orig_enc and load_enc != orig_enc then # warn "Cached encoding #{load_enc} is incompatible with #{orig_enc}\n" \ # "from #{path}/cache.ri" unless # Encoding.compatible? orig_enc, load_enc #end @encoding = load_enc unless @encoding @cache[:pages] ||= [] @cache[:main] ||= nil @cache[:c_class_variables] ||= {} @cache[:c_singleton_class_variables] ||= {} @cache[:c_class_variables].each do |_, map| map.each do |variable, name| @c_enclosure_names[variable] = name end end @cache rescue Errno::ENOENT end ## # Loads ri data for +klass_name+ and hooks it up to this store. def load_class klass_name obj = load_class_data klass_name obj.store = self case obj when RDoc::NormalClass then @classes_hash[klass_name] = obj when RDoc::NormalModule then @modules_hash[klass_name] = obj end end ## # Loads ri data for +klass_name+ def load_class_data klass_name file = class_file klass_name open file, 'rb' do |io| Marshal.load io.read end rescue Errno::ENOENT => e error = MissingFileError.new(self, file, klass_name) error.set_backtrace e.backtrace raise error end ## # Loads ri data for +method_name+ in +klass_name+ def load_method klass_name, method_name file = method_file klass_name, method_name open file, 'rb' do |io| obj = Marshal.load io.read obj.store = self obj.parent = find_class_or_module(klass_name) || load_class(klass_name) unless obj.parent obj end rescue Errno::ENOENT => e error = MissingFileError.new(self, file, klass_name + method_name) error.set_backtrace e.backtrace raise error end ## # Loads ri data for +page_name+ def load_page page_name file = page_file page_name open file, 'rb' do |io| obj = Marshal.load io.read obj.store = self obj end rescue Errno::ENOENT => e error = MissingFileError.new(self, file, page_name) error.set_backtrace e.backtrace raise error end ## # Gets the main page for this RDoc store. This page is used as the root of # the RDoc server. def main @cache[:main] end ## # Sets the main page for this RDoc store. def main= page @cache[:main] = page end ## # Converts the variable => ClassModule map +variables+ from a C parser into # a variable => class name map. def make_variable_map variables map = {} variables.each { |variable, class_module| map[variable] = class_module.full_name } map end ## # Path to the ri data for +method_name+ in +klass_name+ def method_file klass_name, method_name method_name = method_name.split('::').last method_name =~ /#(.*)/ method_type = $1 ? 'i' : 'c' method_name = $1 if $1 method_name = if ''.respond_to? :ord then method_name.gsub(/\W/) { "%%%02x" % $&[0].ord } else method_name.gsub(/\W/) { "%%%02x" % $&[0] } end File.join class_path(klass_name), "#{method_name}-#{method_type}.ri" end ## # Modules cache accessor. An Array of all the module (and class) names in # the store. def module_names @cache[:modules] end ## # Hash of all modules known to RDoc def modules_hash @modules_hash end ## # Returns the RDoc::TopLevel that is a text file and has the given +name+ def page name @files_hash.each_value.find do |file| file.text? and file.page_name == name end end ## # Path to the ri data for +page_name+ def page_file page_name file_name = File.basename(page_name).gsub('.', '_') File.join @path, File.dirname(page_name), "page-#{file_name}.ri" end ## # Removes from +all_hash+ the contexts that are nodoc or have no content. # # See RDoc::Context#remove_from_documentation? def remove_nodoc all_hash all_hash.keys.each do |name| context = all_hash[name] all_hash.delete(name) if context.remove_from_documentation? end end ## # Saves all entries in the store def save load_cache all_classes_and_modules.each do |klass| save_class klass klass.each_method do |method| save_method klass, method end klass.each_attribute do |attribute| save_method klass, attribute end end all_files.each do |file| save_page file end save_cache end ## # Writes the cache file for this store def save_cache clean_cache_collection @cache[:ancestors] clean_cache_collection @cache[:attributes] clean_cache_collection @cache[:class_methods] clean_cache_collection @cache[:instance_methods] @cache[:modules].uniq! @cache[:modules].sort! @cache[:pages].uniq! @cache[:pages].sort! @cache[:encoding] = @encoding # this gets set twice due to assert_cache @cache[:c_class_variables].merge! @c_class_variables @cache[:c_singleton_class_variables].merge! @c_singleton_class_variables return if @dry_run marshal = Marshal.dump @cache open cache_path, 'wb' do |io| io.write marshal end end ## # Writes the ri data for +klass+ (or module) def save_class klass full_name = klass.full_name FileUtils.mkdir_p class_path(full_name) unless @dry_run @cache[:modules] << full_name path = class_file full_name begin disk_klass = load_class full_name klass = disk_klass.merge klass rescue MissingFileError end # BasicObject has no ancestors ancestors = klass.direct_ancestors.compact.map do |ancestor| # HACK for classes we don't know about (class X < RuntimeError) String === ancestor ? ancestor : ancestor.full_name end @cache[:ancestors][full_name] ||= [] @cache[:ancestors][full_name].concat ancestors attribute_definitions = klass.attributes.map do |attribute| "#{attribute.definition} #{attribute.name}" end unless attribute_definitions.empty? then @cache[:attributes][full_name] ||= [] @cache[:attributes][full_name].concat attribute_definitions end to_delete = [] unless klass.method_list.empty? then @cache[:class_methods][full_name] ||= [] @cache[:instance_methods][full_name] ||= [] class_methods, instance_methods = klass.method_list.partition { |meth| meth.singleton } class_methods = class_methods. map { |method| method.name } instance_methods = instance_methods.map { |method| method.name } attribute_names = klass.attributes.map { |attr| attr.name } old = @cache[:class_methods][full_name] - class_methods to_delete.concat old.map { |method| method_file full_name, "#{full_name}::#{method}" } old = @cache[:instance_methods][full_name] - instance_methods - attribute_names to_delete.concat old.map { |method| method_file full_name, "#{full_name}##{method}" } @cache[:class_methods][full_name] = class_methods @cache[:instance_methods][full_name] = instance_methods end return if @dry_run FileUtils.rm_f to_delete marshal = Marshal.dump klass open path, 'wb' do |io| io.write marshal end end ## # Writes the ri data for +method+ on +klass+ def save_method klass, method full_name = klass.full_name FileUtils.mkdir_p class_path(full_name) unless @dry_run cache = if method.singleton then @cache[:class_methods] else @cache[:instance_methods] end cache[full_name] ||= [] cache[full_name] << method.name return if @dry_run marshal = Marshal.dump method open method_file(full_name, method.full_name), 'wb' do |io| io.write marshal end end ## # Writes the ri data for +page+ def save_page page return unless page.text? path = page_file page.full_name FileUtils.mkdir_p File.dirname(path) unless @dry_run cache[:pages] ||= [] cache[:pages] << page.full_name return if @dry_run marshal = Marshal.dump page open path, 'wb' do |io| io.write marshal end end ## # Source of the contents of this store. # # For a store from a gem the source is the gem name. For a store from the # home directory the source is "home". For system ri store (the standard # library documentation) the source is"ruby". For a store from the site # ri directory the store is "site". For other stores the source is the # #path. def source case type when :gem then File.basename File.expand_path '..', @path when :home then 'home' when :site then 'site' when :system then 'ruby' else @path end end ## # Gets the title for this RDoc store. This is used as the title in each # page on the RDoc server def title @cache[:title] end ## # Sets the title page for this RDoc store. def title= title @cache[:title] = title end ## # Returns the unique classes discovered by RDoc. # # ::complete must have been called prior to using this method. def unique_classes @unique_classes end ## # Returns the unique classes and modules discovered by RDoc. # ::complete must have been called prior to using this method. def unique_classes_and_modules @unique_classes + @unique_modules end ## # Returns the unique modules discovered by RDoc. # ::complete must have been called prior to using this method. def unique_modules @unique_modules end end PK! pp2.2.0/rdoc/markup.rbnu[## # RDoc::Markup parses plain text documents and attempts to decompose them into # their constituent parts. Some of these parts are high-level: paragraphs, # chunks of verbatim text, list entries and the like. Other parts happen at # the character level: a piece of bold text, a word in code font. This markup # is similar in spirit to that used on WikiWiki webs, where folks create web # pages using a simple set of formatting rules. # # RDoc::Markup and other markup formats do no output formatting, this is # handled by the RDoc::Markup::Formatter subclasses. # # = Supported Formats # # Besides the RDoc::Markup format, the following formats are built in to RDoc: # # markdown:: # The markdown format as described by # http://daringfireball.net/projects/markdown/. See RDoc::Markdown for # details on the parser and supported extensions. # rd:: # The rdtool format. See RDoc::RD for details on the parser and format. # tomdoc:: # The TomDoc format as described by http://tomdoc.org/. See RDoc::TomDoc # for details on the parser and supported extensions. # # You can choose a markup format using the following methods: # # per project:: # If you build your documentation with rake use RDoc::Task#markup. # # If you build your documentation by hand run: # # rdoc --markup your_favorite_format --write-options # # and commit .rdoc_options and ship it with your packaged gem. # per file:: # At the top of the file use the :markup: directive to set the # default format for the rest of the file. # per comment:: # Use the :markup: directive at the top of a comment you want # to write in a different format. # # = RDoc::Markup # # RDoc::Markup is extensible at runtime: you can add \new markup elements to # be recognized in the documents that RDoc::Markup parses. # # RDoc::Markup is intended to be the basis for a family of tools which share # the common requirement that simple, plain-text should be rendered in a # variety of different output formats and media. It is envisaged that # RDoc::Markup could be the basis for formatting RDoc style comment blocks, # Wiki entries, and online FAQs. # # == Synopsis # # This code converts +input_string+ to HTML. The conversion takes place in # the +convert+ method, so you can use the same RDoc::Markup converter to # convert multiple input strings. # # require 'rdoc' # # h = RDoc::Markup::ToHtml.new(RDoc::Options.new) # # puts h.convert(input_string) # # You can extend the RDoc::Markup parser to recognize new markup # sequences, and to add special processing for text that matches a # regular expression. Here we make WikiWords significant to the parser, # and also make the sequences {word} and \text... signify # strike-through text. We then subclass the HTML output class to deal # with these: # # require 'rdoc' # # class WikiHtml < RDoc::Markup::ToHtml # def handle_special_WIKIWORD(special) # "" + special.text + "" # end # end # # markup = RDoc::Markup.new # markup.add_word_pair("{", "}", :STRIKE) # markup.add_html("no", :STRIKE) # # markup.add_special(/\b([A-Z][a-z]+[A-Z]\w+)/, :WIKIWORD) # # wh = WikiHtml.new RDoc::Options.new, markup # wh.add_tag(:STRIKE, "", "") # # puts "#{wh.convert ARGF.read}" # # == Encoding # # Where Encoding support is available, RDoc will automatically convert all # documents to the same output encoding. The output encoding can be set via # RDoc::Options#encoding and defaults to Encoding.default_external. # # = \RDoc Markup Reference # # == Block Markup # # === Paragraphs and Verbatim # # The markup engine looks for a document's natural left margin. This is # used as the initial margin for the document. # # Consecutive lines starting at this margin are considered to be a # paragraph. Empty lines separate paragraphs. # # Any line that starts to the right of the current margin is treated # as verbatim text. This is useful for code listings: # # 3.times { puts "Ruby" } # # In verbatim text, two or more blank lines are collapsed into one, # and trailing blank lines are removed: # # This is the first line # # # This is the second non-blank line, # after 2 blank lines in the source markup. # # # There were two trailing blank lines right above this paragraph, that # have been removed. In addition, the verbatim text has been shifted # left, so the amount of indentation of verbatim text is unimportant. # # For HTML output RDoc makes a small effort to determine if a verbatim section # contains Ruby source code. If so, the verbatim block will be marked up as # HTML. Triggers include "def", "class", "module", "require", the "hash # rocket"# (=>) or a block call with a parameter. # # === Headers # # A line starting with an equal sign (=) is treated as a # heading. Level one headings have one equals sign, level two headings # have two, and so on until level six, which is the maximum # (seven hyphens or more result in a level six heading). # # For example, the above header was obtained with: # # === Headers # # In HTML output headers have an id matching their name. The above example's # HTML is: # #

    Headers

    # # If a heading is inside a method body the id will be prefixed with the # method's id. If the above header where in the documentation for a method # such as: # # ## # # This method does fun things # # # # = Example # # # # Example of fun things goes here ... # # def do_fun_things # end # # The header's id would be: # #

    Example

    # # The label can be linked-to using SomeClass@Headers. See # {Links}[RDoc::Markup@Links] for further details. # # === Rules # # A line starting with three or more hyphens (at the current indent) # generates a horizontal rule. # # --- # # produces: # # --- # # === Simple Lists # # If a paragraph starts with a "*", "-", "." or ".", # then it is taken to be the start of a list. The margin is increased to be # the first non-space following the list start flag. Subsequent lines # should be indented to this new margin until the list ends. For example: # # * this is a list with three paragraphs in # the first item. This is the first paragraph. # # And this is the second paragraph. # # 1. This is an indented, numbered list. # 2. This is the second item in that list # # This is the third conventional paragraph in the # first list item. # # * This is the second item in the original list # # produces: # # * this is a list with three paragraphs in # the first item. This is the first paragraph. # # And this is the second paragraph. # # 1. This is an indented, numbered list. # 2. This is the second item in that list # # This is the third conventional paragraph in the # first list item. # # * This is the second item in the original list # # === Labeled Lists # # You can also construct labeled lists, sometimes called description # or definition lists. Do this by putting the label in square brackets # and indenting the list body: # # [cat] a small furry mammal # that seems to sleep a lot # # [ant] a little insect that is known # to enjoy picnics # # produces: # # [cat] a small furry mammal # that seems to sleep a lot # # [ant] a little insect that is known # to enjoy picnics # # If you want the list bodies to line up to the left of the labels, # use two colons: # # cat:: a small furry mammal # that seems to sleep a lot # # ant:: a little insect that is known # to enjoy picnics # # produces: # # cat:: a small furry mammal # that seems to sleep a lot # # ant:: a little insect that is known # to enjoy picnics # # Notice that blank lines right after the label are ignored in labeled lists: # # [one] # # definition 1 # # [two] # # definition 2 # # produces the same output as # # [one] definition 1 # [two] definition 2 # # # === Lists and Verbatim # # If you want to introduce a verbatim section right after a list, it has to be # less indented than the list item bodies, but more indented than the list # label, letter, digit or bullet. For instance: # # * point 1 # # * point 2, first paragraph # # point 2, second paragraph # verbatim text inside point 2 # point 2, third paragraph # verbatim text outside of the list (the list is therefore closed) # regular paragraph after the list # # produces: # # * point 1 # # * point 2, first paragraph # # point 2, second paragraph # verbatim text inside point 2 # point 2, third paragraph # verbatim text outside of the list (the list is therefore closed) # regular paragraph after the list # # == Text Markup # # === Bold, Italic, Typewriter Text # # You can use markup within text (except verbatim) to change the # appearance of parts of that text. Out of the box, RDoc::Markup # supports word-based and general markup. # # Word-based markup uses flag characters around individual words: # # \*_word_\*:: displays _word_ in a *bold* font # \__word_\_:: displays _word_ in an _emphasized_ font # \+_word_\+:: displays _word_ in a +code+ font # # General markup affects text between a start delimiter and an end # delimiter. Not surprisingly, these delimiters look like HTML markup. # # \_text_:: displays _text_ in a *bold* font # \_text_:: displays _text_ in an _emphasized_ font # (alternate tag: \) # \_text_\:: displays _text_ in a +code+ font # (alternate tag: \) # # Unlike conventional Wiki markup, general markup can cross line # boundaries. You can turn off the interpretation of markup by # preceding the first character with a backslash (see Escaping # Text Markup, below). # # === Links # # Links to starting with +http:+, +https:+, +mailto:+, +ftp:+ or +www.+ # are recognized. An HTTP url that references an external image is converted # into an inline image element. # # Classes and methods will be automatically linked to their definition. For # example, RDoc::Markup will link to this documentation. By default # methods will only be automatically linked if they contain an _ (all # methods can be automatically linked through the --hyperlink-all # command line option). # # Single-word methods can be linked by using the # character for # instance methods or :: for class methods. For example, # #convert links to #convert. A class or method may be combined like # RDoc::Markup#convert. # # A heading inside the documentation can be linked by following the class # or method by an @ then the heading name. # RDoc::Markup@Links will link to this section like this: # RDoc::Markup@Links. Spaces in headings with multiple words must be escaped # with + like RDoc::Markup@Escaping+Text+Markup. # Punctuation and other special characters must be escaped like CGI.escape. # # The @ can also be used to link to sections. If a section and a # heading share the same name the section is preferred for the link. # # Links can also be of the form label[url], in which case +label+ is # used in the displayed text, and +url+ is used as the target. If +label+ # contains multiple words, put it in braces: {multi word label}[url]. # The +url+ may be an +http:+-type link or a cross-reference to a class, # module or method with a label. # # Links with the rdoc-image: scheme will create an image tag for # HTML output. Only fully-qualified URLs are supported. # # Links with the rdoc-ref: scheme will link to the referenced class, # module, method, file, etc. If the referenced item is does not exist # no link will be generated and rdoc-ref: will be removed from the # resulting text. # # Links starting with rdoc-label:label_name will link to the # +label_name+. You can create a label for the current link (for # bidirectional links) by supplying a name for the current link like # rdoc-label:label-other:label-mine. # # Links starting with +link:+ refer to local files whose path is relative to # the --op directory. Use rdoc-ref: instead of # link: to link to files generated by RDoc as the link target may # be different across RDoc generators. # # Example links: # # https://github.com/rdoc/rdoc # mailto:user@example.com # {RDoc Documentation}[http://rdoc.rubyforge.org] # {RDoc Markup}[rdoc-ref:RDoc::Markup] # # === Escaping Text Markup # # Text markup can be escaped with a backslash, as in \, which was obtained # with \\. Except in verbatim sections and between \ tags, # to produce a backslash you have to double it unless it is followed by a # space, tab or newline. Otherwise, the HTML formatter will discard it, as it # is used to escape potential links: # # * The \ must be doubled if not followed by white space: \\. # * But not in \ tags: in a Regexp, \S matches non-space. # * This is a link to {ruby-lang}[www.ruby-lang.org]. # * This is not a link, however: \{ruby-lang.org}[www.ruby-lang.org]. # * This will not be linked to \RDoc::RDoc#document # # generates: # # * The \ must be doubled if not followed by white space: \\. # * But not in \ tags: in a Regexp, \S matches non-space. # * This is a link to {ruby-lang}[www.ruby-lang.org] # * This is not a link, however: \{ruby-lang.org}[www.ruby-lang.org] # * This will not be linked to \RDoc::RDoc#document # # Inside \ tags, more precisely, leading backslashes are removed only if # followed by a markup character (<*_+), a backslash, or a known link # reference (a known class or method). So in the example above, the backslash # of \S would be removed if there was a class or module named +S+ in # the current context. # # This behavior is inherited from RDoc version 1, and has been kept for # compatibility with existing RDoc documentation. # # === Conversion of characters # # HTML will convert two/three dashes to an em-dash. Other common characters are # converted as well: # # em-dash:: -- or --- # ellipsis:: ... # # single quotes:: 'text' or `text' # double quotes:: "text" or ``text'' # # copyright:: (c) # registered trademark:: (r) # # produces: # # em-dash:: -- or --- # ellipsis:: ... # # single quotes:: 'text' or `text' # double quotes:: "text" or ``text'' # # copyright:: (c) # registered trademark:: (r) # # # == Documenting Source Code # # Comment blocks can be written fairly naturally, either using # on # successive lines of the comment, or by including the comment in # a =begin/=end block. If you use the latter form, # the =begin line _must_ be flagged with an +rdoc+ tag: # # =begin rdoc # Documentation to be processed by RDoc. # # ... # =end # # RDoc stops processing comments if it finds a comment line starting # with -- right after the # character (otherwise, # it will be treated as a rule if it has three dashes or more). # This can be used to separate external from internal comments, # or to stop a comment being associated with a method, class, or module. # Commenting can be turned back on with a line that starts with ++. # # ## # # Extract the age and calculate the date-of-birth. # #-- # # FIXME: fails if the birthday falls on February 29th # #++ # # The DOB is returned as a Time object. # # def get_dob(person) # # ... # end # # Names of classes, files, and any method names containing an underscore or # preceded by a hash character are automatically linked from comment text to # their description. This linking works inside the current class or module, # and with ancestor methods (in included modules or in the superclass). # # Method parameter lists are extracted and displayed with the method # description. If a method calls +yield+, then the parameters passed to yield # will also be displayed: # # def fred # ... # yield line, address # # This will get documented as: # # fred() { |line, address| ... } # # You can override this using a comment containing ':yields: ...' immediately # after the method definition # # def fred # :yields: index, position # # ... # # yield line, address # # which will get documented as # # fred() { |index, position| ... } # # +:yields:+ is an example of a documentation directive. These appear # immediately after the start of the document element they are modifying. # # RDoc automatically cross-references words with underscores or camel-case. # To suppress cross-references, prefix the word with a \ character. To # include special characters like "\n", you'll need to use # two \ characters in normal text, but only one in \ text: # # "\\n" or "\n" # # produces: # # "\\n" or "\n" # # == Directives # # Directives are keywords surrounded by ":" characters. # # === Controlling what is documented # # [+:nodoc:+ / :nodoc: all] # This directive prevents documentation for the element from # being generated. For classes and modules, methods, aliases, # constants, and attributes directly within the affected class or # module also will be omitted. By default, though, modules and # classes within that class or module _will_ be documented. This is # turned off by adding the +all+ modifier. # # module MyModule # :nodoc: # class Input # end # end # # module OtherModule # :nodoc: all # class Output # end # end # # In the above code, only class MyModule::Input will be documented. # # The +:nodoc:+ directive, like +:enddoc:+, +:stopdoc:+ and +:startdoc:+ # presented below, is local to the current file: if you do not want to # document a module that appears in several files, specify +:nodoc:+ on each # appearance, at least once per file. # # [+:stopdoc:+ / +:startdoc:+] # Stop and start adding new documentation elements to the current container. # For example, if a class has a number of constants that you don't want to # document, put a +:stopdoc:+ before the first, and a +:startdoc:+ after the # last. If you don't specify a +:startdoc:+ by the end of the container, # disables documentation for the rest of the current file. # # [+:doc:+] # Forces a method or attribute to be documented even if it wouldn't be # otherwise. Useful if, for example, you want to include documentation of a # particular private method. # # [+:enddoc:+] # Document nothing further at the current level: directives +:startdoc:+ and # +:doc:+ that appear after this will not be honored for the current container # (file, class or module), in the current file. # # [+:notnew:+ / +:not_new:+ / +:not-new:+ ] # Only applicable to the +initialize+ instance method. Normally RDoc # assumes that the documentation and parameters for +initialize+ are # actually for the +new+ method, and so fakes out a +new+ for the class. # The +:notnew:+ directive stops this. Remember that +initialize+ is private, # so you won't see the documentation unless you use the +-a+ command line # option. # # === Method arguments # # [+:arg:+ or +:args:+ _parameters_] # Overrides the default argument handling with exactly these parameters. # # ## # # :args: a, b # # def some_method(*a) # end # # [+:yield:+ or +:yields:+ _parameters_] # Overrides the default yield discovery with these parameters. # # ## # # :yields: key, value # # def each_thing &block # @things.each(&block) # end # # [+:call-seq:+] # Lines up to the next blank line or lines with a common prefix in the # comment are treated as the method's calling sequence, overriding the # default parsing of method parameters and yield arguments. # # Multiple lines may be used. # # # :call-seq: # # ARGF.readlines(sep=$/) -> array # # ARGF.readlines(limit) -> array # # ARGF.readlines(sep, limit) -> array # # # # ARGF.to_a(sep=$/) -> array # # ARGF.to_a(limit) -> array # # ARGF.to_a(sep, limit) -> array # # # # The remaining lines are documentation ... # # === Sections # # Sections allow you to group methods in a class into sensible containers. If # you use the sections 'Public', 'Internal' and 'Deprecated' (the three # allowed method statuses from TomDoc) the sections will be displayed in that # order placing the most useful methods at the top. Otherwise, sections will # be displayed in alphabetical order. # # [+:category:+ _section_] # Adds this item to the named +section+ overriding the current section. Use # this to group methods by section in RDoc output while maintaining a # sensible ordering (like alphabetical). # # # :category: Utility Methods # # # # CGI escapes +text+ # # def convert_string text # CGI.escapeHTML text # end # # An empty category will place the item in the default category: # # # :category: # # # # This method is in the default category # # def some_method # # ... # end # # Unlike the :section: directive, :category: is not sticky. The category # only applies to the item immediately following the comment. # # Use the :section: directive to provide introductory text for a section of # documentation. # # [+:section:+ _title_] # Provides section introductory text in RDoc output. The title following # +:section:+ is used as the section name and the remainder of the comment # containing the section is used as introductory text. A section's comment # block must be separated from following comment blocks. Use an empty title # to switch to the default section. # # The :section: directive is sticky, so subsequent methods, aliases, # attributes, and classes will be contained in this section until the # section is changed. The :category: directive will override the :section: # directive. # # A :section: comment block may have one or more lines before the :section: # directive. These will be removed, and any identical lines at the end of # the block are also removed. This allows you to add visual cues to the # section. # # Example: # # # ---------------------------------------- # # :section: My Section # # This is the section that I wrote. # # See it glisten in the noon-day sun. # # ---------------------------------------- # # ## # # Comment for some_method # # def some_method # # ... # end # # === Other directives # # [+:markup:+ _type_] # Overrides the default markup type for this comment with the specified # markup type. For Ruby files, if the first comment contains this directive # it is applied automatically to all comments in the file. # # Unless you are converting between markup formats you should use a # .rdoc_options file to specify the default documentation # format for your entire project. See RDoc::Options@Saved+Options for # instructions. # # At the top of a file the +:markup:+ directive applies to the entire file: # # # coding: UTF-8 # # :markup: TomDoc # # # TomDoc comment here ... # # class MyClass # # ... # # For just one comment: # # # ... # end # # # :markup: RDoc # # # # This is a comment in RDoc markup format ... # # def some_method # # ... # # See Markup@CONTRIBUTING for instructions on adding a new markup format. # # [+:include:+ _filename_] # Include the contents of the named file at this point. This directive # must appear alone on one line, possibly preceded by spaces. In this # position, it can be escaped with a \ in front of the first colon. # # The file will be searched for in the directories listed by the +--include+ # option, or in the current directory by default. The contents of the file # will be shifted to have the same indentation as the ':' at the start of # the +:include:+ directive. # # [+:title:+ _text_] # Sets the title for the document. Equivalent to the --title # command line parameter. (The command line parameter overrides any :title: # directive in the source). # # [+:main:+ _name_] # Equivalent to the --main command line parameter. # #-- # Original Author:: Dave Thomas, dave@pragmaticprogrammer.com # License:: Ruby license class RDoc::Markup ## # An AttributeManager which handles inline markup. attr_reader :attribute_manager ## # Parses +str+ into an RDoc::Markup::Document. def self.parse str RDoc::Markup::Parser.parse str rescue RDoc::Markup::Parser::Error => e $stderr.puts <<-EOF While parsing markup, RDoc encountered a #{e.class}: #{e} \tfrom #{e.backtrace.join "\n\tfrom "} ---8<--- #{text} ---8<--- RDoc #{RDoc::VERSION} Ruby #{RUBY_VERSION}-p#{RUBY_PATCHLEVEL} #{RUBY_RELEASE_DATE} Please file a bug report with the above information at: https://github.com/rdoc/rdoc/issues EOF raise end ## # Take a block of text and use various heuristics to determine its # structure (paragraphs, lists, and so on). Invoke an event handler as we # identify significant chunks. def initialize attribute_manager = nil @attribute_manager = attribute_manager || RDoc::Markup::AttributeManager.new @output = nil end ## # Add to the sequences used to add formatting to an individual word (such # as *bold*). Matching entries will generate attributes that the output # formatters can recognize by their +name+. def add_word_pair(start, stop, name) @attribute_manager.add_word_pair(start, stop, name) end ## # Add to the sequences recognized as general markup. def add_html(tag, name) @attribute_manager.add_html(tag, name) end ## # Add to other inline sequences. For example, we could add WikiWords using # something like: # # parser.add_special(/\b([A-Z][a-z]+[A-Z]\w+)/, :WIKIWORD) # # Each wiki word will be presented to the output formatter via the # accept_special method. def add_special(pattern, name) @attribute_manager.add_special(pattern, name) end ## # We take +input+, parse it if necessary, then invoke the output +formatter+ # using a Visitor to render the result. def convert input, formatter document = case input when RDoc::Markup::Document then input else RDoc::Markup::Parser.parse input end document.accept formatter end autoload :Parser, 'rdoc/markup/parser' autoload :PreProcess, 'rdoc/markup/pre_process' # Inline markup classes autoload :AttrChanger, 'rdoc/markup/attr_changer' autoload :AttrSpan, 'rdoc/markup/attr_span' autoload :Attributes, 'rdoc/markup/attributes' autoload :AttributeManager, 'rdoc/markup/attribute_manager' autoload :Special, 'rdoc/markup/special' # RDoc::Markup AST autoload :BlankLine, 'rdoc/markup/blank_line' autoload :BlockQuote, 'rdoc/markup/block_quote' autoload :Document, 'rdoc/markup/document' autoload :HardBreak, 'rdoc/markup/hard_break' autoload :Heading, 'rdoc/markup/heading' autoload :Include, 'rdoc/markup/include' autoload :IndentedParagraph, 'rdoc/markup/indented_paragraph' autoload :List, 'rdoc/markup/list' autoload :ListItem, 'rdoc/markup/list_item' autoload :Paragraph, 'rdoc/markup/paragraph' autoload :Raw, 'rdoc/markup/raw' autoload :Rule, 'rdoc/markup/rule' autoload :Verbatim, 'rdoc/markup/verbatim' # Formatters autoload :Formatter, 'rdoc/markup/formatter' autoload :FormatterTestCase, 'rdoc/markup/formatter_test_case' autoload :TextFormatterTestCase, 'rdoc/markup/text_formatter_test_case' autoload :ToAnsi, 'rdoc/markup/to_ansi' autoload :ToBs, 'rdoc/markup/to_bs' autoload :ToHtml, 'rdoc/markup/to_html' autoload :ToHtmlCrossref, 'rdoc/markup/to_html_crossref' autoload :ToHtmlSnippet, 'rdoc/markup/to_html_snippet' autoload :ToLabel, 'rdoc/markup/to_label' autoload :ToMarkdown, 'rdoc/markup/to_markdown' autoload :ToRdoc, 'rdoc/markup/to_rdoc' autoload :ToTableOfContents, 'rdoc/markup/to_table_of_contents' autoload :ToTest, 'rdoc/markup/to_test' autoload :ToTtOnly, 'rdoc/markup/to_tt_only' end PK!UQNN2.2.0/rdoc/class_module.rbnu[## # ClassModule is the base class for objects representing either a class or a # module. class RDoc::ClassModule < RDoc::Context ## # 1:: # RDoc 3.7 # * Added visibility, singleton and file to attributes # * Added file to constants # * Added file to includes # * Added file to methods # 2:: # RDoc 3.13 # * Added extends # 3:: # RDoc 4.0 # * Added sections # * Added in_files # * Added parent name # * Complete Constant dump MARSHAL_VERSION = 3 # :nodoc: ## # Constants that are aliases for this class or module attr_accessor :constant_aliases ## # Comment and the location it came from. Use #add_comment to add comments attr_accessor :comment_location attr_accessor :diagram # :nodoc: ## # Class or module this constant is an alias for attr_accessor :is_alias_for ## # Return a RDoc::ClassModule of class +class_type+ that is a copy # of module +module+. Used to promote modules to classes. #-- # TODO move to RDoc::NormalClass (I think) def self.from_module class_type, mod klass = class_type.new mod.name mod.comment_location.each do |comment, location| klass.add_comment comment, location end klass.parent = mod.parent klass.section = mod.section klass.viewer = mod.viewer klass.attributes.concat mod.attributes klass.method_list.concat mod.method_list klass.aliases.concat mod.aliases klass.external_aliases.concat mod.external_aliases klass.constants.concat mod.constants klass.includes.concat mod.includes klass.extends.concat mod.extends klass.methods_hash.update mod.methods_hash klass.constants_hash.update mod.constants_hash klass.current_section = mod.current_section klass.in_files.concat mod.in_files klass.sections.concat mod.sections klass.unmatched_alias_lists = mod.unmatched_alias_lists klass.current_section = mod.current_section klass.visibility = mod.visibility klass.classes_hash.update mod.classes_hash klass.modules_hash.update mod.modules_hash klass.metadata.update mod.metadata klass.document_self = mod.received_nodoc ? nil : mod.document_self klass.document_children = mod.document_children klass.force_documentation = mod.force_documentation klass.done_documenting = mod.done_documenting # update the parent of all children (klass.attributes + klass.method_list + klass.aliases + klass.external_aliases + klass.constants + klass.includes + klass.extends + klass.classes + klass.modules).each do |obj| obj.parent = klass obj.full_name = nil end klass end ## # Creates a new ClassModule with +name+ with optional +superclass+ # # This is a constructor for subclasses, and must never be called directly. def initialize(name, superclass = nil) @constant_aliases = [] @diagram = nil @is_alias_for = nil @name = name @superclass = superclass @comment_location = [] # [[comment, location]] super() end ## # Adds +comment+ to this ClassModule's list of comments at +location+. This # method is preferred over #comment= since it allows ri data to be updated # across multiple runs. def add_comment comment, location return unless document_self original = comment comment = case comment when RDoc::Comment then comment.normalize else normalize_comment comment end @comment_location.delete_if { |(_, l)| l == location } @comment_location << [comment, location] self.comment = original end def add_things my_things, other_things # :nodoc: other_things.each do |group, things| my_things[group].each { |thing| yield false, thing } if my_things.include? group things.each do |thing| yield true, thing end end end ## # Ancestors list for this ClassModule: the list of included modules # (classes will add their superclass if any). # # Returns the included classes or modules, not the includes # themselves. The returned values are either String or # RDoc::NormalModule instances (see RDoc::Include#module). # # The values are returned in reverse order of their inclusion, # which is the order suitable for searching methods/attributes # in the ancestors. The superclass, if any, comes last. def ancestors includes.map { |i| i.module }.reverse end def aref_prefix # :nodoc: raise NotImplementedError, "missing aref_prefix for #{self.class}" end ## # HTML fragment reference for this module or class. See # RDoc::NormalClass#aref and RDoc::NormalModule#aref def aref "#{aref_prefix}-#{full_name}" end ## # Ancestors of this class or module only alias direct_ancestors ancestors ## # Clears the comment. Used by the Ruby parser. def clear_comment @comment = '' end ## # This method is deprecated, use #add_comment instead. # # Appends +comment+ to the current comment, but separated by a rule. Works # more like +=. def comment= comment # :nodoc: comment = case comment when RDoc::Comment then comment.normalize else normalize_comment comment end comment = "#{@comment}\n---\n#{comment}" unless @comment.empty? super comment end ## # Prepares this ClassModule for use by a generator. # # See RDoc::Store#complete def complete min_visibility update_aliases remove_nodoc_children update_includes remove_invisible min_visibility end ## # Does this ClassModule or any of its methods have document_self set? def document_self_or_methods document_self || method_list.any?{ |m| m.document_self } end ## # Does this class or module have a comment with content or is # #received_nodoc true? def documented? return true if @received_nodoc return false if @comment_location.empty? @comment_location.any? { |comment, _| not comment.empty? } end ## # Iterates the ancestors of this class or module for which an # RDoc::ClassModule exists. def each_ancestor # :yields: module return enum_for __method__ unless block_given? ancestors.each do |mod| next if String === mod next if self == mod yield mod end end ## # Looks for a symbol in the #ancestors. See Context#find_local_symbol. def find_ancestor_local_symbol symbol each_ancestor do |m| res = m.find_local_symbol(symbol) return res if res end nil end ## # Finds a class or module with +name+ in this namespace or its descendants def find_class_named name return self if full_name == name return self if @name == name @classes.values.find do |klass| next if klass == self klass.find_class_named name end end ## # Return the fully qualified name of this class or module def full_name @full_name ||= if RDoc::ClassModule === parent then "#{parent.full_name}::#{@name}" else @name end end ## # TODO: filter included items by #display? def marshal_dump # :nodoc: attrs = attributes.sort.map do |attr| next unless attr.display? [ attr.name, attr.rw, attr.visibility, attr.singleton, attr.file_name, ] end.compact method_types = methods_by_type.map do |type, visibilities| visibilities = visibilities.map do |visibility, methods| method_names = methods.map do |method| next unless method.display? [method.name, method.file_name] end.compact [visibility, method_names.uniq] end [type, visibilities] end [ MARSHAL_VERSION, @name, full_name, @superclass, parse(@comment_location), attrs, constants.select { |constant| constant.display? }, includes.map do |incl| next unless incl.display? [incl.name, parse(incl.comment), incl.file_name] end.compact, method_types, extends.map do |ext| next unless ext.display? [ext.name, parse(ext.comment), ext.file_name] end.compact, @sections.values, @in_files.map do |tl| tl.relative_name end, parent.full_name, parent.class, ] end def marshal_load array # :nodoc: initialize_visibility initialize_methods_etc @current_section = nil @document_self = true @done_documenting = false @parent = nil @temporary_section = nil @visibility = nil @classes = {} @modules = {} @name = array[1] @full_name = array[2] @superclass = array[3] @comment = array[4] @comment_location = if RDoc::Markup::Document === @comment.parts.first then @comment else RDoc::Markup::Document.new @comment end array[5].each do |name, rw, visibility, singleton, file| singleton ||= false visibility ||= :public attr = RDoc::Attr.new nil, name, rw, nil, singleton add_attribute attr attr.visibility = visibility attr.record_location RDoc::TopLevel.new file end array[6].each do |constant, comment, file| case constant when RDoc::Constant then add_constant constant else constant = add_constant RDoc::Constant.new(constant, nil, comment) constant.record_location RDoc::TopLevel.new file end end array[7].each do |name, comment, file| incl = add_include RDoc::Include.new(name, comment) incl.record_location RDoc::TopLevel.new file end array[8].each do |type, visibilities| visibilities.each do |visibility, methods| @visibility = visibility methods.each do |name, file| method = RDoc::AnyMethod.new nil, name method.singleton = true if type == 'class' method.record_location RDoc::TopLevel.new file add_method method end end end array[9].each do |name, comment, file| ext = add_extend RDoc::Extend.new(name, comment) ext.record_location RDoc::TopLevel.new file end if array[9] # Support Marshal version 1 sections = (array[10] || []).map do |section| [section.title, section] end @sections = Hash[*sections.flatten] @current_section = add_section nil @in_files = [] (array[11] || []).each do |filename| record_location RDoc::TopLevel.new filename end @parent_name = array[12] @parent_class = array[13] end ## # Merges +class_module+ into this ClassModule. # # The data in +class_module+ is preferred over the receiver. def merge class_module @parent = class_module.parent @parent_name = class_module.parent_name other_document = parse class_module.comment_location if other_document then document = parse @comment_location document = document.merge other_document @comment = @comment_location = document end cm = class_module other_files = cm.in_files merge_collections attributes, cm.attributes, other_files do |add, attr| if add then add_attribute attr else @attributes.delete attr @methods_hash.delete attr.pretty_name end end merge_collections constants, cm.constants, other_files do |add, const| if add then add_constant const else @constants.delete const @constants_hash.delete const.name end end merge_collections includes, cm.includes, other_files do |add, incl| if add then add_include incl else @includes.delete incl end end @includes.uniq! # clean up merge_collections extends, cm.extends, other_files do |add, ext| if add then add_extend ext else @extends.delete ext end end @extends.uniq! # clean up merge_collections method_list, cm.method_list, other_files do |add, meth| if add then add_method meth else @method_list.delete meth @methods_hash.delete meth.pretty_name end end merge_sections cm self end ## # Merges collection +mine+ with +other+ preferring other. +other_files+ is # used to help determine which items should be deleted. # # Yields whether the item should be added or removed (true or false) and the # item to be added or removed. # # merge_collections things, other.things, other.in_files do |add, thing| # if add then # # add the thing # else # # remove the thing # end # end def merge_collections mine, other, other_files, &block # :nodoc: my_things = mine. group_by { |thing| thing.file } other_things = other.group_by { |thing| thing.file } remove_things my_things, other_files, &block add_things my_things, other_things, &block end ## # Merges the comments in this ClassModule with the comments in the other # ClassModule +cm+. def merge_sections cm # :nodoc: my_sections = sections.group_by { |section| section.title } other_sections = cm.sections.group_by { |section| section.title } other_files = cm.in_files remove_things my_sections, other_files do |_, section| @sections.delete section.title end other_sections.each do |group, sections| if my_sections.include? group my_sections[group].each do |my_section| other_section = cm.sections_hash[group] my_comments = my_section.comments other_comments = other_section.comments other_files = other_section.in_files merge_collections my_comments, other_comments, other_files do |add, comment| if add then my_section.add_comment comment else my_section.remove_comment comment end end end else sections.each do |section| add_section group, section.comments end end end end ## # Does this object represent a module? def module? false end ## # Allows overriding the initial name. # # Used for modules and classes that are constant aliases. def name= new_name @name = new_name end ## # Parses +comment_location+ into an RDoc::Markup::Document composed of # multiple RDoc::Markup::Documents with their file set. def parse comment_location case comment_location when String then super when Array then docs = comment_location.map do |comment, location| doc = super comment doc.file = location doc end RDoc::Markup::Document.new(*docs) when RDoc::Comment then doc = super comment_location.text, comment_location.format doc.file = comment_location.location doc when RDoc::Markup::Document then return comment_location else raise ArgumentError, "unknown comment class #{comment_location.class}" end end ## # Path to this class or module for use with HTML generator output. def path http_url @store.rdoc.generator.class_dir end ## # Name to use to generate the url: # modules and classes that are aliases for another # module or class return the name of the latter. def name_for_path is_alias_for ? is_alias_for.full_name : full_name end ## # Returns the classes and modules that are not constants # aliasing another class or module. For use by formatters # only (caches its result). def non_aliases @non_aliases ||= classes_and_modules.reject { |cm| cm.is_alias_for } end ## # Updates the child modules or classes of class/module +parent+ by # deleting the ones that have been removed from the documentation. # # +parent_hash+ is either parent.modules_hash or # parent.classes_hash and +all_hash+ is ::all_modules_hash or # ::all_classes_hash. def remove_nodoc_children prefix = self.full_name + '::' modules_hash.each_key do |name| full_name = prefix + name modules_hash.delete name unless @store.modules_hash[full_name] end classes_hash.each_key do |name| full_name = prefix + name classes_hash.delete name unless @store.classes_hash[full_name] end end def remove_things my_things, other_files # :nodoc: my_things.delete_if do |file, things| next false unless other_files.include? file things.each do |thing| yield false, thing end true end end ## # Search record used by RDoc::Generator::JsonIndex def search_record [ name, full_name, full_name, '', path, '', snippet(@comment_location), ] end ## # Sets the store for this class or module and its contained code objects. def store= store super @attributes .each do |attr| attr.store = store end @constants .each do |const| const.store = store end @includes .each do |incl| incl.store = store end @extends .each do |ext| ext.store = store end @method_list.each do |meth| meth.store = store end end ## # Get the superclass of this class. Attempts to retrieve the superclass # object, returns the name if it is not known. def superclass @store.find_class_named(@superclass) || @superclass end ## # Set the superclass of this class to +superclass+ def superclass=(superclass) raise NoMethodError, "#{full_name} is a module" if module? @superclass = superclass end def to_s # :nodoc: if is_alias_for then "#{self.class.name} #{self.full_name} -> #{is_alias_for}" else super end end ## # 'module' or 'class' def type module? ? 'module' : 'class' end ## # Updates the child modules & classes by replacing the ones that are # aliases through a constant. # # The aliased module/class is replaced in the children and in # RDoc::Store#modules_hash or RDoc::Store#classes_hash # by a copy that has RDoc::ClassModule#is_alias_for set to # the aliased module/class, and this copy is added to #aliases # of the aliased module/class. # # Formatters can use the #non_aliases method to retrieve children that # are not aliases, for instance to list the namespace content, since # the aliased modules are included in the constants of the class/module, # that are listed separately. def update_aliases constants.each do |const| next unless cm = const.is_alias_for cm_alias = cm.dup cm_alias.name = const.name # Don't move top-level aliases under Object, they look ugly there unless RDoc::TopLevel === cm_alias.parent then cm_alias.parent = self cm_alias.full_name = nil # force update for new parent end cm_alias.aliases.clear cm_alias.is_alias_for = cm if cm.module? then @store.modules_hash[cm_alias.full_name] = cm_alias modules_hash[const.name] = cm_alias else @store.classes_hash[cm_alias.full_name] = cm_alias classes_hash[const.name] = cm_alias end cm.aliases << cm_alias end end ## # Deletes from #includes those whose module has been removed from the # documentation. #-- # FIXME: includes are not reliably removed, see _possible_bug test case def update_includes includes.reject! do |include| mod = include.module !(String === mod) && @store.modules_hash[mod.full_name].nil? end includes.uniq! end ## # Deletes from #extends those whose module has been removed from the # documentation. #-- # FIXME: like update_includes, extends are not reliably removed def update_extends extends.reject! do |ext| mod = ext.module !(String === mod) && @store.modules_hash[mod.full_name].nil? end extends.uniq! end end PK! 2.2.0/rdoc/generator.rbnu[## # RDoc uses generators to turn parsed source code in the form of an # RDoc::CodeObject tree into some form of output. RDoc comes with the HTML # generator RDoc::Generator::Darkfish and an ri data generator # RDoc::Generator::RI. # # == Registering a Generator # # Generators are registered by calling RDoc::RDoc.add_generator with the class # of the generator: # # class My::Awesome::Generator # RDoc::RDoc.add_generator self # end # # == Adding Options to +rdoc+ # # Before option processing in +rdoc+, RDoc::Options will call ::setup_options # on the generator class with an RDoc::Options instance. The generator can # use RDoc::Options#option_parser to add command-line options to the +rdoc+ # tool. See RDoc::Options@Custom+Options for an example and see OptionParser # for details on how to add options. # # You can extend the RDoc::Options instance with additional accessors for your # generator. # # == Generator Instantiation # # After parsing, RDoc::RDoc will instantiate a generator by calling # #initialize with an RDoc::Store instance and an RDoc::Options instance. # # The RDoc::Store instance holds documentation for parsed source code. In # RDoc 3 and earlier the RDoc::TopLevel class held this data. When upgrading # a generator from RDoc 3 and earlier you should only need to replace # RDoc::TopLevel with the store instance. # # RDoc will then call #generate on the generator instance. You can use the # various methods on RDoc::Store and in the RDoc::CodeObject tree to create # your desired output format. module RDoc::Generator autoload :Markup, 'rdoc/generator/markup' autoload :Darkfish, 'rdoc/generator/darkfish' autoload :JsonIndex, 'rdoc/generator/json_index' autoload :RI, 'rdoc/generator/ri' autoload :POT, 'rdoc/generator/pot' end PK!K2.2.0/rdoc/include.rbnu[## # A Module included in a class with \#include # # RDoc::Include.new 'Enumerable', 'comment ...' class RDoc::Include < RDoc::Mixin end PK!Z2.2.0/rdoc/extend.rbnu[## # A Module extension to a class with \#extend # # RDoc::Extend.new 'Enumerable', 'comment ...' class RDoc::Extend < RDoc::Mixin end PK!2.2.0/rdoc/markdown.rbnu[# coding: UTF-8 # :markup: markdown ## # RDoc::Markdown as described by the [markdown syntax][syntax]. # # To choose Markdown as your only default format see # RDoc::Options@Saved+Options for instructions on setting up a `.doc_options` # file to store your project default. # # ## Usage # # Here is a brief example of using this parse to read a markdown file by hand. # # data = File.read("README.md") # formatter = RDoc::Markup::ToHtml.new(RDoc::Options.new, nil) # html = RDoc::Markdown.parse(data).accept(@formatter) # # # do something with html # # ## Extensions # # The following markdown extensions are supported by the parser, but not all # are used in RDoc output by default. # # ### RDoc # # The RDoc Markdown parser has the following built-in behaviors that cannot be # disabled. # # Underscores embedded in words are never interpreted as emphasis. (While the # [markdown dingus][dingus] emphasizes in-word underscores, neither the # Markdown syntax nor MarkdownTest mention this behavior.) # # For HTML output, RDoc always auto-links bare URLs. # # ### Break on Newline # # The break_on_newline extension converts all newlines into hard line breaks # as in [Github Flavored Markdown][GFM]. This extension is disabled by # default. # # ### CSS # # The #css extension enables CSS blocks to be included in the output, but they # are not used for any built-in RDoc output format. This extension is disabled # by default. # # Example: # # # # ### Definition Lists # # The definition_lists extension allows definition lists using the [PHP # Markdown Extra syntax][PHPE], but only one label and definition are supported # at this time. This extension is enabled by default. # # Example: # # ``` # cat # : A small furry mammal # that seems to sleep a lot # # ant # : A little insect that is known # to enjoy picnics # # ``` # # Produces: # # cat # : A small furry mammal # that seems to sleep a lot # # ant # : A little insect that is known # to enjoy picnics # # ### Github # # The #github extension enables a partial set of [Github Flavored Markdown] # [GFM]. This extension is enabled by default. # # Supported github extensions include: # # #### Fenced code blocks # # Use ` ``` ` around a block of code instead of indenting it four spaces. # # #### Syntax highlighting # # Use ` ``` ruby ` as the start of a code fence to add syntax highlighting. # (Currently only `ruby` syntax is supported). # # ### HTML # # Enables raw HTML to be included in the output. This extension is enabled by # default. # # Example: # # # ... #
    # # ### Notes # # The #notes extension enables footnote support. This extension is enabled by # default. # # Example: # # Here is some text[^1] including an inline footnote ^[for short footnotes] # # ... # # [^1]: With the footnote text down at the bottom # # Produces: # # Here is some text[^1] including an inline footnote ^[for short footnotes] # # [^1]: With the footnote text down at the bottom # # ## Limitations # # * Link titles are not used # * Footnotes are collapsed into a single paragraph # # ## Author # # This markdown parser is a port to kpeg from [peg-markdown][pegmarkdown] by # John MacFarlane. # # It is used under the MIT license: # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. # # The port to kpeg was performed by Eric Hodel and Evan Phoenix # # [dingus]: http://daringfireball.net/projects/markdown/dingus # [GFM]: http://github.github.com/github-flavored-markdown/ # [pegmarkdown]: https://github.com/jgm/peg-markdown # [PHPE]: http://michelf.com/projects/php-markdown/extra/#def-list # [syntax]: http://daringfireball.net/projects/markdown/syntax #-- # Last updated to jgm/peg-markdown commit 8f8fc22ef0 class RDoc::Markdown # :stopdoc: # This is distinct from setup_parser so that a standalone parser # can redefine #initialize and still have access to the proper # parser setup code. def initialize(str, debug=false) setup_parser(str, debug) end # Prepares for parsing +str+. If you define a custom initialize you must # call this method before #parse def setup_parser(str, debug=false) set_string str, 0 @memoizations = Hash.new { |h,k| h[k] = {} } @result = nil @failed_rule = nil @failing_rule_offset = -1 setup_foreign_grammar end attr_reader :string attr_reader :failing_rule_offset attr_accessor :result, :pos def current_column(target=pos) if c = string.rindex("\n", target-1) return target - c - 1 end target + 1 end def current_line(target=pos) cur_offset = 0 cur_line = 0 string.each_line do |line| cur_line += 1 cur_offset += line.size return cur_line if cur_offset >= target end -1 end def lines lines = [] string.each_line { |l| lines << l } lines end def get_text(start) @string[start..@pos-1] end # Sets the string and current parsing position for the parser. def set_string string, pos @string = string @string_size = string ? string.size : 0 @pos = pos end def show_pos width = 10 if @pos < width "#{@pos} (\"#{@string[0,@pos]}\" @ \"#{@string[@pos,width]}\")" else "#{@pos} (\"... #{@string[@pos - width, width]}\" @ \"#{@string[@pos,width]}\")" end end def failure_info l = current_line @failing_rule_offset c = current_column @failing_rule_offset if @failed_rule.kind_of? Symbol info = self.class::Rules[@failed_rule] "line #{l}, column #{c}: failed rule '#{info.name}' = '#{info.rendered}'" else "line #{l}, column #{c}: failed rule '#{@failed_rule}'" end end def failure_caret l = current_line @failing_rule_offset c = current_column @failing_rule_offset line = lines[l-1] "#{line}\n#{' ' * (c - 1)}^" end def failure_character l = current_line @failing_rule_offset c = current_column @failing_rule_offset lines[l-1][c-1, 1] end def failure_oneline l = current_line @failing_rule_offset c = current_column @failing_rule_offset char = lines[l-1][c-1, 1] if @failed_rule.kind_of? Symbol info = self.class::Rules[@failed_rule] "@#{l}:#{c} failed rule '#{info.name}', got '#{char}'" else "@#{l}:#{c} failed rule '#{@failed_rule}', got '#{char}'" end end class ParseError < RuntimeError end def raise_error raise ParseError, failure_oneline end def show_error(io=STDOUT) error_pos = @failing_rule_offset line_no = current_line(error_pos) col_no = current_column(error_pos) io.puts "On line #{line_no}, column #{col_no}:" if @failed_rule.kind_of? Symbol info = self.class::Rules[@failed_rule] io.puts "Failed to match '#{info.rendered}' (rule '#{info.name}')" else io.puts "Failed to match rule '#{@failed_rule}'" end io.puts "Got: #{string[error_pos,1].inspect}" line = lines[line_no-1] io.puts "=> #{line}" io.print(" " * (col_no + 3)) io.puts "^" end def set_failed_rule(name) if @pos > @failing_rule_offset @failed_rule = name @failing_rule_offset = @pos end end attr_reader :failed_rule def match_string(str) len = str.size if @string[pos,len] == str @pos += len return str end return nil end def scan(reg) if m = reg.match(@string[@pos..-1]) width = m.end(0) @pos += width return true end return nil end if "".respond_to? :ord def get_byte if @pos >= @string_size return nil end s = @string[@pos].ord @pos += 1 s end else def get_byte if @pos >= @string_size return nil end s = @string[@pos] @pos += 1 s end end def parse(rule=nil) # We invoke the rules indirectly via apply # instead of by just calling them as methods because # if the rules use left recursion, apply needs to # manage that. if !rule apply(:_root) else method = rule.gsub("-","_hyphen_") apply :"_#{method}" end end class MemoEntry def initialize(ans, pos) @ans = ans @pos = pos @result = nil @set = false @left_rec = false end attr_reader :ans, :pos, :result, :set attr_accessor :left_rec def move!(ans, pos, result) @ans = ans @pos = pos @result = result @set = true @left_rec = false end end def external_invoke(other, rule, *args) old_pos = @pos old_string = @string set_string other.string, other.pos begin if val = __send__(rule, *args) other.pos = @pos other.result = @result else other.set_failed_rule "#{self.class}##{rule}" end val ensure set_string old_string, old_pos end end def apply_with_args(rule, *args) memo_key = [rule, args] if m = @memoizations[memo_key][@pos] @pos = m.pos if !m.set m.left_rec = true return nil end @result = m.result return m.ans else m = MemoEntry.new(nil, @pos) @memoizations[memo_key][@pos] = m start_pos = @pos ans = __send__ rule, *args lr = m.left_rec m.move! ans, @pos, @result # Don't bother trying to grow the left recursion # if it's failing straight away (thus there is no seed) if ans and lr return grow_lr(rule, args, start_pos, m) else return ans end return ans end end def apply(rule) if m = @memoizations[rule][@pos] @pos = m.pos if !m.set m.left_rec = true return nil end @result = m.result return m.ans else m = MemoEntry.new(nil, @pos) @memoizations[rule][@pos] = m start_pos = @pos ans = __send__ rule lr = m.left_rec m.move! ans, @pos, @result # Don't bother trying to grow the left recursion # if it's failing straight away (thus there is no seed) if ans and lr return grow_lr(rule, nil, start_pos, m) else return ans end return ans end end def grow_lr(rule, args, start_pos, m) while true @pos = start_pos @result = m.result if args ans = __send__ rule, *args else ans = __send__ rule end return nil unless ans break if @pos <= m.pos m.move! ans, @pos, @result end @result = m.result @pos = m.pos return m.ans end class RuleInfo def initialize(name, rendered) @name = name @rendered = rendered end attr_reader :name, :rendered end def self.rule_info(name, rendered) RuleInfo.new(name, rendered) end # :startdoc: require 'rubygems' require 'rdoc' require 'rdoc/markup/to_joined_paragraph' require 'rdoc/markdown/entities' if RUBY_VERSION > '1.9' then require 'rdoc/markdown/literals_1_9' else require 'rdoc/markdown/literals_1_8' end ## # Supported extensions EXTENSIONS = [] ## # Extensions enabled by default DEFAULT_EXTENSIONS = [ :definition_lists, :github, :html, :notes, ] # :section: Extensions ## # Creates extension methods for the `name` extension to enable and disable # the extension and to query if they are active. def self.extension name EXTENSIONS << name define_method "#{name}?" do extension? name end define_method "#{name}=" do |enable| extension name, enable end end ## # Converts all newlines into hard breaks extension :break_on_newline ## # Allow style blocks extension :css ## # Allow PHP Markdown Extras style definition lists extension :definition_lists ## # Allow Github Flavored Markdown extension :github ## # Allow HTML extension :html ## # Enables the notes extension extension :notes # :section: ## # Parses the `markdown` document into an RDoc::Document using the default # extensions. def self.parse markdown parser = new parser.parse markdown end # TODO remove when kpeg 0.10 is released alias orig_initialize initialize # :nodoc: ## # Creates a new markdown parser that enables the given +extensions+. def initialize extensions = DEFAULT_EXTENSIONS, debug = false @debug = debug @formatter = RDoc::Markup::ToJoinedParagraph.new @extensions = extensions @references = nil @unlinked_references = nil @footnotes = nil @note_order = nil end ## # Wraps `text` in emphasis for rdoc inline formatting def emphasis text if text =~ /\A[a-z\d.\/]+\z/i then "_#{text}_" else "#{text}" end end ## # :category: Extensions # # Is the extension `name` enabled? def extension? name @extensions.include? name end ## # :category: Extensions # # Enables or disables the extension with `name` def extension name, enable if enable then @extensions |= [name] else @extensions -= [name] end end ## # Parses `text` in a clone of this parser. This is used for handling nested # lists the same way as markdown_parser. def inner_parse text # :nodoc: parser = clone parser.setup_parser text, @debug parser.peg_parse doc = parser.result doc.accept @formatter doc.parts end ## # Finds a link reference for `label` and creates a new link to it with # `content` as the link text. If `label` was not encountered in the # reference-gathering parser pass the label and content are reconstructed # with the linking `text` (usually whitespace). def link_to content, label = content, text = nil raise 'enable notes extension' if content.start_with? '^' and label.equal? content if ref = @references[label] then "{#{content}}[#{ref}]" elsif label.equal? content then "[#{content}]#{text}" else "[#{content}]#{text}[#{label}]" end end ## # Creates an RDoc::Markup::ListItem by parsing the `unparsed` content from # the first parsing pass. def list_item_from unparsed parsed = inner_parse unparsed.join RDoc::Markup::ListItem.new nil, *parsed end ## # Stores `label` as a note and fills in previously unknown note references. def note label #foottext = "rdoc-label:foottext-#{label}:footmark-#{label}" #ref.replace foottext if ref = @unlinked_notes.delete(label) @notes[label] = foottext #"{^1}[rdoc-label:footmark-#{label}:foottext-#{label}] " end ## # Creates a new link for the footnote `reference` and adds the reference to # the note order list for proper display at the end of the document. def note_for ref @note_order << ref label = @note_order.length "{*#{label}}[rdoc-label:foottext-#{label}:footmark-#{label}]" end ## # The internal kpeg parse method alias peg_parse parse # :nodoc: ## # Creates an RDoc::Markup::Paragraph from `parts` and including # extension-specific behavior def paragraph parts parts = parts.map do |part| if "\n" == part then RDoc::Markup::HardBreak.new else part end end if break_on_newline? RDoc::Markup::Paragraph.new(*parts) end ## # Parses `markdown` into an RDoc::Document def parse markdown @references = {} @unlinked_references = {} markdown += "\n\n" setup_parser markdown, @debug peg_parse 'References' if notes? then @footnotes = {} setup_parser markdown, @debug peg_parse 'Notes' # using note_order on the first pass would be a bug @note_order = [] end setup_parser markdown, @debug peg_parse doc = result if notes? and not @footnotes.empty? then doc << RDoc::Markup::Rule.new(1) @note_order.each_with_index do |ref, index| label = index + 1 note = @footnotes[ref] link = "{^#{label}}[rdoc-label:footmark-#{label}:foottext-#{label}] " note.parts.unshift link doc << note end end doc.accept @formatter doc end ## # Stores `label` as a reference to `link` and fills in previously unknown # link references. def reference label, link if ref = @unlinked_references.delete(label) then ref.replace link end @references[label] = link end ## # Wraps `text` in strong markup for rdoc inline formatting def strong text if text =~ /\A[a-z\d.\/-]+\z/i then "*#{text}*" else "#{text}" end end # :stopdoc: def setup_foreign_grammar @_grammar_literals = RDoc::Markdown::Literals.new(nil) end # root = Doc def _root _tmp = apply(:_Doc) set_failed_rule :_root unless _tmp return _tmp end # Doc = BOM? Block*:a { RDoc::Markup::Document.new(*a.compact) } def _Doc _save = self.pos while true # sequence _save1 = self.pos _tmp = apply(:_BOM) unless _tmp _tmp = true self.pos = _save1 end unless _tmp self.pos = _save break end _ary = [] while true _tmp = apply(:_Block) _ary << @result if _tmp break unless _tmp end _tmp = true @result = _ary a = @result unless _tmp self.pos = _save break end @result = begin; RDoc::Markup::Document.new(*a.compact) ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Doc unless _tmp return _tmp end # Block = @BlankLine* (BlockQuote | Verbatim | CodeFence | Note | Reference | HorizontalRule | Heading | OrderedList | BulletList | DefinitionList | HtmlBlock | StyleBlock | Para | Plain) def _Block _save = self.pos while true # sequence while true _tmp = _BlankLine() break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _save2 = self.pos while true # choice _tmp = apply(:_BlockQuote) break if _tmp self.pos = _save2 _tmp = apply(:_Verbatim) break if _tmp self.pos = _save2 _tmp = apply(:_CodeFence) break if _tmp self.pos = _save2 _tmp = apply(:_Note) break if _tmp self.pos = _save2 _tmp = apply(:_Reference) break if _tmp self.pos = _save2 _tmp = apply(:_HorizontalRule) break if _tmp self.pos = _save2 _tmp = apply(:_Heading) break if _tmp self.pos = _save2 _tmp = apply(:_OrderedList) break if _tmp self.pos = _save2 _tmp = apply(:_BulletList) break if _tmp self.pos = _save2 _tmp = apply(:_DefinitionList) break if _tmp self.pos = _save2 _tmp = apply(:_HtmlBlock) break if _tmp self.pos = _save2 _tmp = apply(:_StyleBlock) break if _tmp self.pos = _save2 _tmp = apply(:_Para) break if _tmp self.pos = _save2 _tmp = apply(:_Plain) break if _tmp self.pos = _save2 break end # end choice unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Block unless _tmp return _tmp end # Para = @NonindentSpace Inlines:a @BlankLine+ { paragraph a } def _Para _save = self.pos while true # sequence _tmp = _NonindentSpace() unless _tmp self.pos = _save break end _tmp = apply(:_Inlines) a = @result unless _tmp self.pos = _save break end _save1 = self.pos _tmp = _BlankLine() if _tmp while true _tmp = _BlankLine() break unless _tmp end _tmp = true else self.pos = _save1 end unless _tmp self.pos = _save break end @result = begin; paragraph a ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Para unless _tmp return _tmp end # Plain = Inlines:a { paragraph a } def _Plain _save = self.pos while true # sequence _tmp = apply(:_Inlines) a = @result unless _tmp self.pos = _save break end @result = begin; paragraph a ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Plain unless _tmp return _tmp end # AtxInline = !@Newline !(@Sp? /#*/ @Sp @Newline) Inline def _AtxInline _save = self.pos while true # sequence _save1 = self.pos _tmp = _Newline() _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save break end _save2 = self.pos _save3 = self.pos while true # sequence _save4 = self.pos _tmp = _Sp() unless _tmp _tmp = true self.pos = _save4 end unless _tmp self.pos = _save3 break end _tmp = scan(/\A(?-mix:#*)/) unless _tmp self.pos = _save3 break end _tmp = _Sp() unless _tmp self.pos = _save3 break end _tmp = _Newline() unless _tmp self.pos = _save3 end break end # end sequence _tmp = _tmp ? nil : true self.pos = _save2 unless _tmp self.pos = _save break end _tmp = apply(:_Inline) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_AtxInline unless _tmp return _tmp end # AtxStart = < /\#{1,6}/ > { text.length } def _AtxStart _save = self.pos while true # sequence _text_start = self.pos _tmp = scan(/\A(?-mix:\#{1,6})/) if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end @result = begin; text.length ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_AtxStart unless _tmp return _tmp end # AtxHeading = AtxStart:s @Sp? AtxInline+:a (@Sp? /#*/ @Sp)? @Newline { RDoc::Markup::Heading.new(s, a.join) } def _AtxHeading _save = self.pos while true # sequence _tmp = apply(:_AtxStart) s = @result unless _tmp self.pos = _save break end _save1 = self.pos _tmp = _Sp() unless _tmp _tmp = true self.pos = _save1 end unless _tmp self.pos = _save break end _save2 = self.pos _ary = [] _tmp = apply(:_AtxInline) if _tmp _ary << @result while true _tmp = apply(:_AtxInline) _ary << @result if _tmp break unless _tmp end _tmp = true @result = _ary else self.pos = _save2 end a = @result unless _tmp self.pos = _save break end _save3 = self.pos _save4 = self.pos while true # sequence _save5 = self.pos _tmp = _Sp() unless _tmp _tmp = true self.pos = _save5 end unless _tmp self.pos = _save4 break end _tmp = scan(/\A(?-mix:#*)/) unless _tmp self.pos = _save4 break end _tmp = _Sp() unless _tmp self.pos = _save4 end break end # end sequence unless _tmp _tmp = true self.pos = _save3 end unless _tmp self.pos = _save break end _tmp = _Newline() unless _tmp self.pos = _save break end @result = begin; RDoc::Markup::Heading.new(s, a.join) ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_AtxHeading unless _tmp return _tmp end # SetextHeading = (SetextHeading1 | SetextHeading2) def _SetextHeading _save = self.pos while true # choice _tmp = apply(:_SetextHeading1) break if _tmp self.pos = _save _tmp = apply(:_SetextHeading2) break if _tmp self.pos = _save break end # end choice set_failed_rule :_SetextHeading unless _tmp return _tmp end # SetextBottom1 = /={3,}/ @Newline def _SetextBottom1 _save = self.pos while true # sequence _tmp = scan(/\A(?-mix:={3,})/) unless _tmp self.pos = _save break end _tmp = _Newline() unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_SetextBottom1 unless _tmp return _tmp end # SetextBottom2 = /-{3,}/ @Newline def _SetextBottom2 _save = self.pos while true # sequence _tmp = scan(/\A(?-mix:-{3,})/) unless _tmp self.pos = _save break end _tmp = _Newline() unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_SetextBottom2 unless _tmp return _tmp end # SetextHeading1 = &(@RawLine SetextBottom1) @StartList:a (!@Endline Inline:b { a << b })+ @Sp? @Newline SetextBottom1 { RDoc::Markup::Heading.new(1, a.join) } def _SetextHeading1 _save = self.pos while true # sequence _save1 = self.pos _save2 = self.pos while true # sequence _tmp = _RawLine() unless _tmp self.pos = _save2 break end _tmp = apply(:_SetextBottom1) unless _tmp self.pos = _save2 end break end # end sequence self.pos = _save1 unless _tmp self.pos = _save break end _tmp = _StartList() a = @result unless _tmp self.pos = _save break end _save3 = self.pos _save4 = self.pos while true # sequence _save5 = self.pos _tmp = _Endline() _tmp = _tmp ? nil : true self.pos = _save5 unless _tmp self.pos = _save4 break end _tmp = apply(:_Inline) b = @result unless _tmp self.pos = _save4 break end @result = begin; a << b ; end _tmp = true unless _tmp self.pos = _save4 end break end # end sequence if _tmp while true _save6 = self.pos while true # sequence _save7 = self.pos _tmp = _Endline() _tmp = _tmp ? nil : true self.pos = _save7 unless _tmp self.pos = _save6 break end _tmp = apply(:_Inline) b = @result unless _tmp self.pos = _save6 break end @result = begin; a << b ; end _tmp = true unless _tmp self.pos = _save6 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save3 end unless _tmp self.pos = _save break end _save8 = self.pos _tmp = _Sp() unless _tmp _tmp = true self.pos = _save8 end unless _tmp self.pos = _save break end _tmp = _Newline() unless _tmp self.pos = _save break end _tmp = apply(:_SetextBottom1) unless _tmp self.pos = _save break end @result = begin; RDoc::Markup::Heading.new(1, a.join) ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_SetextHeading1 unless _tmp return _tmp end # SetextHeading2 = &(@RawLine SetextBottom2) @StartList:a (!@Endline Inline:b { a << b })+ @Sp? @Newline SetextBottom2 { RDoc::Markup::Heading.new(2, a.join) } def _SetextHeading2 _save = self.pos while true # sequence _save1 = self.pos _save2 = self.pos while true # sequence _tmp = _RawLine() unless _tmp self.pos = _save2 break end _tmp = apply(:_SetextBottom2) unless _tmp self.pos = _save2 end break end # end sequence self.pos = _save1 unless _tmp self.pos = _save break end _tmp = _StartList() a = @result unless _tmp self.pos = _save break end _save3 = self.pos _save4 = self.pos while true # sequence _save5 = self.pos _tmp = _Endline() _tmp = _tmp ? nil : true self.pos = _save5 unless _tmp self.pos = _save4 break end _tmp = apply(:_Inline) b = @result unless _tmp self.pos = _save4 break end @result = begin; a << b ; end _tmp = true unless _tmp self.pos = _save4 end break end # end sequence if _tmp while true _save6 = self.pos while true # sequence _save7 = self.pos _tmp = _Endline() _tmp = _tmp ? nil : true self.pos = _save7 unless _tmp self.pos = _save6 break end _tmp = apply(:_Inline) b = @result unless _tmp self.pos = _save6 break end @result = begin; a << b ; end _tmp = true unless _tmp self.pos = _save6 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save3 end unless _tmp self.pos = _save break end _save8 = self.pos _tmp = _Sp() unless _tmp _tmp = true self.pos = _save8 end unless _tmp self.pos = _save break end _tmp = _Newline() unless _tmp self.pos = _save break end _tmp = apply(:_SetextBottom2) unless _tmp self.pos = _save break end @result = begin; RDoc::Markup::Heading.new(2, a.join) ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_SetextHeading2 unless _tmp return _tmp end # Heading = (SetextHeading | AtxHeading) def _Heading _save = self.pos while true # choice _tmp = apply(:_SetextHeading) break if _tmp self.pos = _save _tmp = apply(:_AtxHeading) break if _tmp self.pos = _save break end # end choice set_failed_rule :_Heading unless _tmp return _tmp end # BlockQuote = BlockQuoteRaw:a { RDoc::Markup::BlockQuote.new(*a) } def _BlockQuote _save = self.pos while true # sequence _tmp = apply(:_BlockQuoteRaw) a = @result unless _tmp self.pos = _save break end @result = begin; RDoc::Markup::BlockQuote.new(*a) ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_BlockQuote unless _tmp return _tmp end # BlockQuoteRaw = @StartList:a (">" " "? Line:l { a << l } (!">" !@BlankLine Line:c { a << c })* (@BlankLine:n { a << n })*)+ { inner_parse a.join } def _BlockQuoteRaw _save = self.pos while true # sequence _tmp = _StartList() a = @result unless _tmp self.pos = _save break end _save1 = self.pos _save2 = self.pos while true # sequence _tmp = match_string(">") unless _tmp self.pos = _save2 break end _save3 = self.pos _tmp = match_string(" ") unless _tmp _tmp = true self.pos = _save3 end unless _tmp self.pos = _save2 break end _tmp = apply(:_Line) l = @result unless _tmp self.pos = _save2 break end @result = begin; a << l ; end _tmp = true unless _tmp self.pos = _save2 break end while true _save5 = self.pos while true # sequence _save6 = self.pos _tmp = match_string(">") _tmp = _tmp ? nil : true self.pos = _save6 unless _tmp self.pos = _save5 break end _save7 = self.pos _tmp = _BlankLine() _tmp = _tmp ? nil : true self.pos = _save7 unless _tmp self.pos = _save5 break end _tmp = apply(:_Line) c = @result unless _tmp self.pos = _save5 break end @result = begin; a << c ; end _tmp = true unless _tmp self.pos = _save5 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save2 break end while true _save9 = self.pos while true # sequence _tmp = _BlankLine() n = @result unless _tmp self.pos = _save9 break end @result = begin; a << n ; end _tmp = true unless _tmp self.pos = _save9 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save2 end break end # end sequence if _tmp while true _save10 = self.pos while true # sequence _tmp = match_string(">") unless _tmp self.pos = _save10 break end _save11 = self.pos _tmp = match_string(" ") unless _tmp _tmp = true self.pos = _save11 end unless _tmp self.pos = _save10 break end _tmp = apply(:_Line) l = @result unless _tmp self.pos = _save10 break end @result = begin; a << l ; end _tmp = true unless _tmp self.pos = _save10 break end while true _save13 = self.pos while true # sequence _save14 = self.pos _tmp = match_string(">") _tmp = _tmp ? nil : true self.pos = _save14 unless _tmp self.pos = _save13 break end _save15 = self.pos _tmp = _BlankLine() _tmp = _tmp ? nil : true self.pos = _save15 unless _tmp self.pos = _save13 break end _tmp = apply(:_Line) c = @result unless _tmp self.pos = _save13 break end @result = begin; a << c ; end _tmp = true unless _tmp self.pos = _save13 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save10 break end while true _save17 = self.pos while true # sequence _tmp = _BlankLine() n = @result unless _tmp self.pos = _save17 break end @result = begin; a << n ; end _tmp = true unless _tmp self.pos = _save17 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save10 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save1 end unless _tmp self.pos = _save break end @result = begin; inner_parse a.join ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_BlockQuoteRaw unless _tmp return _tmp end # NonblankIndentedLine = !@BlankLine IndentedLine def _NonblankIndentedLine _save = self.pos while true # sequence _save1 = self.pos _tmp = _BlankLine() _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save break end _tmp = apply(:_IndentedLine) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_NonblankIndentedLine unless _tmp return _tmp end # VerbatimChunk = @BlankLine*:a NonblankIndentedLine+:b { a.concat b } def _VerbatimChunk _save = self.pos while true # sequence _ary = [] while true _tmp = _BlankLine() _ary << @result if _tmp break unless _tmp end _tmp = true @result = _ary a = @result unless _tmp self.pos = _save break end _save2 = self.pos _ary = [] _tmp = apply(:_NonblankIndentedLine) if _tmp _ary << @result while true _tmp = apply(:_NonblankIndentedLine) _ary << @result if _tmp break unless _tmp end _tmp = true @result = _ary else self.pos = _save2 end b = @result unless _tmp self.pos = _save break end @result = begin; a.concat b ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_VerbatimChunk unless _tmp return _tmp end # Verbatim = VerbatimChunk+:a { RDoc::Markup::Verbatim.new(*a.flatten) } def _Verbatim _save = self.pos while true # sequence _save1 = self.pos _ary = [] _tmp = apply(:_VerbatimChunk) if _tmp _ary << @result while true _tmp = apply(:_VerbatimChunk) _ary << @result if _tmp break unless _tmp end _tmp = true @result = _ary else self.pos = _save1 end a = @result unless _tmp self.pos = _save break end @result = begin; RDoc::Markup::Verbatim.new(*a.flatten) ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Verbatim unless _tmp return _tmp end # HorizontalRule = @NonindentSpace ("*" @Sp "*" @Sp "*" (@Sp "*")* | "-" @Sp "-" @Sp "-" (@Sp "-")* | "_" @Sp "_" @Sp "_" (@Sp "_")*) @Sp @Newline @BlankLine+ { RDoc::Markup::Rule.new 1 } def _HorizontalRule _save = self.pos while true # sequence _tmp = _NonindentSpace() unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _save2 = self.pos while true # sequence _tmp = match_string("*") unless _tmp self.pos = _save2 break end _tmp = _Sp() unless _tmp self.pos = _save2 break end _tmp = match_string("*") unless _tmp self.pos = _save2 break end _tmp = _Sp() unless _tmp self.pos = _save2 break end _tmp = match_string("*") unless _tmp self.pos = _save2 break end while true _save4 = self.pos while true # sequence _tmp = _Sp() unless _tmp self.pos = _save4 break end _tmp = match_string("*") unless _tmp self.pos = _save4 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save2 end break end # end sequence break if _tmp self.pos = _save1 _save5 = self.pos while true # sequence _tmp = match_string("-") unless _tmp self.pos = _save5 break end _tmp = _Sp() unless _tmp self.pos = _save5 break end _tmp = match_string("-") unless _tmp self.pos = _save5 break end _tmp = _Sp() unless _tmp self.pos = _save5 break end _tmp = match_string("-") unless _tmp self.pos = _save5 break end while true _save7 = self.pos while true # sequence _tmp = _Sp() unless _tmp self.pos = _save7 break end _tmp = match_string("-") unless _tmp self.pos = _save7 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save5 end break end # end sequence break if _tmp self.pos = _save1 _save8 = self.pos while true # sequence _tmp = match_string("_") unless _tmp self.pos = _save8 break end _tmp = _Sp() unless _tmp self.pos = _save8 break end _tmp = match_string("_") unless _tmp self.pos = _save8 break end _tmp = _Sp() unless _tmp self.pos = _save8 break end _tmp = match_string("_") unless _tmp self.pos = _save8 break end while true _save10 = self.pos while true # sequence _tmp = _Sp() unless _tmp self.pos = _save10 break end _tmp = match_string("_") unless _tmp self.pos = _save10 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save8 end break end # end sequence break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = _Sp() unless _tmp self.pos = _save break end _tmp = _Newline() unless _tmp self.pos = _save break end _save11 = self.pos _tmp = _BlankLine() if _tmp while true _tmp = _BlankLine() break unless _tmp end _tmp = true else self.pos = _save11 end unless _tmp self.pos = _save break end @result = begin; RDoc::Markup::Rule.new 1 ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HorizontalRule unless _tmp return _tmp end # Bullet = !HorizontalRule @NonindentSpace /[+*-]/ @Spacechar+ def _Bullet _save = self.pos while true # sequence _save1 = self.pos _tmp = apply(:_HorizontalRule) _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save break end _tmp = _NonindentSpace() unless _tmp self.pos = _save break end _tmp = scan(/\A(?-mix:[+*-])/) unless _tmp self.pos = _save break end _save2 = self.pos _tmp = _Spacechar() if _tmp while true _tmp = _Spacechar() break unless _tmp end _tmp = true else self.pos = _save2 end unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Bullet unless _tmp return _tmp end # BulletList = &Bullet (ListTight | ListLoose):a { RDoc::Markup::List.new(:BULLET, *a) } def _BulletList _save = self.pos while true # sequence _save1 = self.pos _tmp = apply(:_Bullet) self.pos = _save1 unless _tmp self.pos = _save break end _save2 = self.pos while true # choice _tmp = apply(:_ListTight) break if _tmp self.pos = _save2 _tmp = apply(:_ListLoose) break if _tmp self.pos = _save2 break end # end choice a = @result unless _tmp self.pos = _save break end @result = begin; RDoc::Markup::List.new(:BULLET, *a) ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_BulletList unless _tmp return _tmp end # ListTight = ListItemTight+:a @BlankLine* !(Bullet | Enumerator) { a } def _ListTight _save = self.pos while true # sequence _save1 = self.pos _ary = [] _tmp = apply(:_ListItemTight) if _tmp _ary << @result while true _tmp = apply(:_ListItemTight) _ary << @result if _tmp break unless _tmp end _tmp = true @result = _ary else self.pos = _save1 end a = @result unless _tmp self.pos = _save break end while true _tmp = _BlankLine() break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _save3 = self.pos _save4 = self.pos while true # choice _tmp = apply(:_Bullet) break if _tmp self.pos = _save4 _tmp = apply(:_Enumerator) break if _tmp self.pos = _save4 break end # end choice _tmp = _tmp ? nil : true self.pos = _save3 unless _tmp self.pos = _save break end @result = begin; a ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_ListTight unless _tmp return _tmp end # ListLoose = @StartList:a (ListItem:b @BlankLine* { a << b })+ { a } def _ListLoose _save = self.pos while true # sequence _tmp = _StartList() a = @result unless _tmp self.pos = _save break end _save1 = self.pos _save2 = self.pos while true # sequence _tmp = apply(:_ListItem) b = @result unless _tmp self.pos = _save2 break end while true _tmp = _BlankLine() break unless _tmp end _tmp = true unless _tmp self.pos = _save2 break end @result = begin; a << b ; end _tmp = true unless _tmp self.pos = _save2 end break end # end sequence if _tmp while true _save4 = self.pos while true # sequence _tmp = apply(:_ListItem) b = @result unless _tmp self.pos = _save4 break end while true _tmp = _BlankLine() break unless _tmp end _tmp = true unless _tmp self.pos = _save4 break end @result = begin; a << b ; end _tmp = true unless _tmp self.pos = _save4 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save1 end unless _tmp self.pos = _save break end @result = begin; a ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_ListLoose unless _tmp return _tmp end # ListItem = (Bullet | Enumerator) @StartList:a ListBlock:b { a << b } (ListContinuationBlock:c { a.push(*c) })* { list_item_from a } def _ListItem _save = self.pos while true # sequence _save1 = self.pos while true # choice _tmp = apply(:_Bullet) break if _tmp self.pos = _save1 _tmp = apply(:_Enumerator) break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = _StartList() a = @result unless _tmp self.pos = _save break end _tmp = apply(:_ListBlock) b = @result unless _tmp self.pos = _save break end @result = begin; a << b ; end _tmp = true unless _tmp self.pos = _save break end while true _save3 = self.pos while true # sequence _tmp = apply(:_ListContinuationBlock) c = @result unless _tmp self.pos = _save3 break end @result = begin; a.push(*c) ; end _tmp = true unless _tmp self.pos = _save3 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save break end @result = begin; list_item_from a ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_ListItem unless _tmp return _tmp end # ListItemTight = (Bullet | Enumerator) ListBlock:a (!@BlankLine ListContinuationBlock:b { a.push(*b) })* !ListContinuationBlock { list_item_from a } def _ListItemTight _save = self.pos while true # sequence _save1 = self.pos while true # choice _tmp = apply(:_Bullet) break if _tmp self.pos = _save1 _tmp = apply(:_Enumerator) break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_ListBlock) a = @result unless _tmp self.pos = _save break end while true _save3 = self.pos while true # sequence _save4 = self.pos _tmp = _BlankLine() _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = apply(:_ListContinuationBlock) b = @result unless _tmp self.pos = _save3 break end @result = begin; a.push(*b) ; end _tmp = true unless _tmp self.pos = _save3 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _save5 = self.pos _tmp = apply(:_ListContinuationBlock) _tmp = _tmp ? nil : true self.pos = _save5 unless _tmp self.pos = _save break end @result = begin; list_item_from a ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_ListItemTight unless _tmp return _tmp end # ListBlock = !@BlankLine Line:a ListBlockLine*:c { [a, *c] } def _ListBlock _save = self.pos while true # sequence _save1 = self.pos _tmp = _BlankLine() _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save break end _tmp = apply(:_Line) a = @result unless _tmp self.pos = _save break end _ary = [] while true _tmp = apply(:_ListBlockLine) _ary << @result if _tmp break unless _tmp end _tmp = true @result = _ary c = @result unless _tmp self.pos = _save break end @result = begin; [a, *c] ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_ListBlock unless _tmp return _tmp end # ListContinuationBlock = @StartList:a @BlankLine* { a << "\n" } (Indent ListBlock:b { a.concat b })+ { a } def _ListContinuationBlock _save = self.pos while true # sequence _tmp = _StartList() a = @result unless _tmp self.pos = _save break end while true _tmp = _BlankLine() break unless _tmp end _tmp = true unless _tmp self.pos = _save break end @result = begin; a << "\n" ; end _tmp = true unless _tmp self.pos = _save break end _save2 = self.pos _save3 = self.pos while true # sequence _tmp = apply(:_Indent) unless _tmp self.pos = _save3 break end _tmp = apply(:_ListBlock) b = @result unless _tmp self.pos = _save3 break end @result = begin; a.concat b ; end _tmp = true unless _tmp self.pos = _save3 end break end # end sequence if _tmp while true _save4 = self.pos while true # sequence _tmp = apply(:_Indent) unless _tmp self.pos = _save4 break end _tmp = apply(:_ListBlock) b = @result unless _tmp self.pos = _save4 break end @result = begin; a.concat b ; end _tmp = true unless _tmp self.pos = _save4 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save2 end unless _tmp self.pos = _save break end @result = begin; a ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_ListContinuationBlock unless _tmp return _tmp end # Enumerator = @NonindentSpace [0-9]+ "." @Spacechar+ def _Enumerator _save = self.pos while true # sequence _tmp = _NonindentSpace() unless _tmp self.pos = _save break end _save1 = self.pos _save2 = self.pos _tmp = get_byte if _tmp unless _tmp >= 48 and _tmp <= 57 self.pos = _save2 _tmp = nil end end if _tmp while true _save3 = self.pos _tmp = get_byte if _tmp unless _tmp >= 48 and _tmp <= 57 self.pos = _save3 _tmp = nil end end break unless _tmp end _tmp = true else self.pos = _save1 end unless _tmp self.pos = _save break end _tmp = match_string(".") unless _tmp self.pos = _save break end _save4 = self.pos _tmp = _Spacechar() if _tmp while true _tmp = _Spacechar() break unless _tmp end _tmp = true else self.pos = _save4 end unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Enumerator unless _tmp return _tmp end # OrderedList = &Enumerator (ListTight | ListLoose):a { RDoc::Markup::List.new(:NUMBER, *a) } def _OrderedList _save = self.pos while true # sequence _save1 = self.pos _tmp = apply(:_Enumerator) self.pos = _save1 unless _tmp self.pos = _save break end _save2 = self.pos while true # choice _tmp = apply(:_ListTight) break if _tmp self.pos = _save2 _tmp = apply(:_ListLoose) break if _tmp self.pos = _save2 break end # end choice a = @result unless _tmp self.pos = _save break end @result = begin; RDoc::Markup::List.new(:NUMBER, *a) ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_OrderedList unless _tmp return _tmp end # ListBlockLine = !@BlankLine !(Indent? (Bullet | Enumerator)) !HorizontalRule OptionallyIndentedLine def _ListBlockLine _save = self.pos while true # sequence _save1 = self.pos _tmp = _BlankLine() _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save break end _save2 = self.pos _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_Indent) unless _tmp _tmp = true self.pos = _save4 end unless _tmp self.pos = _save3 break end _save5 = self.pos while true # choice _tmp = apply(:_Bullet) break if _tmp self.pos = _save5 _tmp = apply(:_Enumerator) break if _tmp self.pos = _save5 break end # end choice unless _tmp self.pos = _save3 end break end # end sequence _tmp = _tmp ? nil : true self.pos = _save2 unless _tmp self.pos = _save break end _save6 = self.pos _tmp = apply(:_HorizontalRule) _tmp = _tmp ? nil : true self.pos = _save6 unless _tmp self.pos = _save break end _tmp = apply(:_OptionallyIndentedLine) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_ListBlockLine unless _tmp return _tmp end # HtmlOpenAnchor = "<" Spnl ("a" | "A") Spnl HtmlAttribute* ">" def _HtmlOpenAnchor _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("a") break if _tmp self.pos = _save1 _tmp = match_string("A") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlOpenAnchor unless _tmp return _tmp end # HtmlCloseAnchor = "<" Spnl "/" ("a" | "A") Spnl ">" def _HtmlCloseAnchor _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("a") break if _tmp self.pos = _save1 _tmp = match_string("A") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlCloseAnchor unless _tmp return _tmp end # HtmlAnchor = HtmlOpenAnchor (HtmlAnchor | !HtmlCloseAnchor .)* HtmlCloseAnchor def _HtmlAnchor _save = self.pos while true # sequence _tmp = apply(:_HtmlOpenAnchor) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlAnchor) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlCloseAnchor) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlCloseAnchor) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlAnchor unless _tmp return _tmp end # HtmlBlockOpenAddress = "<" Spnl ("address" | "ADDRESS") Spnl HtmlAttribute* ">" def _HtmlBlockOpenAddress _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("address") break if _tmp self.pos = _save1 _tmp = match_string("ADDRESS") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenAddress unless _tmp return _tmp end # HtmlBlockCloseAddress = "<" Spnl "/" ("address" | "ADDRESS") Spnl ">" def _HtmlBlockCloseAddress _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("address") break if _tmp self.pos = _save1 _tmp = match_string("ADDRESS") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseAddress unless _tmp return _tmp end # HtmlBlockAddress = HtmlBlockOpenAddress (HtmlBlockAddress | !HtmlBlockCloseAddress .)* HtmlBlockCloseAddress def _HtmlBlockAddress _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenAddress) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockAddress) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseAddress) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseAddress) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockAddress unless _tmp return _tmp end # HtmlBlockOpenBlockquote = "<" Spnl ("blockquote" | "BLOCKQUOTE") Spnl HtmlAttribute* ">" def _HtmlBlockOpenBlockquote _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("blockquote") break if _tmp self.pos = _save1 _tmp = match_string("BLOCKQUOTE") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenBlockquote unless _tmp return _tmp end # HtmlBlockCloseBlockquote = "<" Spnl "/" ("blockquote" | "BLOCKQUOTE") Spnl ">" def _HtmlBlockCloseBlockquote _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("blockquote") break if _tmp self.pos = _save1 _tmp = match_string("BLOCKQUOTE") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseBlockquote unless _tmp return _tmp end # HtmlBlockBlockquote = HtmlBlockOpenBlockquote (HtmlBlockBlockquote | !HtmlBlockCloseBlockquote .)* HtmlBlockCloseBlockquote def _HtmlBlockBlockquote _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenBlockquote) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockBlockquote) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseBlockquote) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseBlockquote) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockBlockquote unless _tmp return _tmp end # HtmlBlockOpenCenter = "<" Spnl ("center" | "CENTER") Spnl HtmlAttribute* ">" def _HtmlBlockOpenCenter _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("center") break if _tmp self.pos = _save1 _tmp = match_string("CENTER") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenCenter unless _tmp return _tmp end # HtmlBlockCloseCenter = "<" Spnl "/" ("center" | "CENTER") Spnl ">" def _HtmlBlockCloseCenter _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("center") break if _tmp self.pos = _save1 _tmp = match_string("CENTER") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseCenter unless _tmp return _tmp end # HtmlBlockCenter = HtmlBlockOpenCenter (HtmlBlockCenter | !HtmlBlockCloseCenter .)* HtmlBlockCloseCenter def _HtmlBlockCenter _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenCenter) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockCenter) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseCenter) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseCenter) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCenter unless _tmp return _tmp end # HtmlBlockOpenDir = "<" Spnl ("dir" | "DIR") Spnl HtmlAttribute* ">" def _HtmlBlockOpenDir _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("dir") break if _tmp self.pos = _save1 _tmp = match_string("DIR") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenDir unless _tmp return _tmp end # HtmlBlockCloseDir = "<" Spnl "/" ("dir" | "DIR") Spnl ">" def _HtmlBlockCloseDir _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("dir") break if _tmp self.pos = _save1 _tmp = match_string("DIR") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseDir unless _tmp return _tmp end # HtmlBlockDir = HtmlBlockOpenDir (HtmlBlockDir | !HtmlBlockCloseDir .)* HtmlBlockCloseDir def _HtmlBlockDir _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenDir) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockDir) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseDir) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseDir) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockDir unless _tmp return _tmp end # HtmlBlockOpenDiv = "<" Spnl ("div" | "DIV") Spnl HtmlAttribute* ">" def _HtmlBlockOpenDiv _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("div") break if _tmp self.pos = _save1 _tmp = match_string("DIV") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenDiv unless _tmp return _tmp end # HtmlBlockCloseDiv = "<" Spnl "/" ("div" | "DIV") Spnl ">" def _HtmlBlockCloseDiv _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("div") break if _tmp self.pos = _save1 _tmp = match_string("DIV") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseDiv unless _tmp return _tmp end # HtmlBlockDiv = HtmlBlockOpenDiv (HtmlBlockDiv | !HtmlBlockCloseDiv .)* HtmlBlockCloseDiv def _HtmlBlockDiv _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenDiv) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockDiv) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseDiv) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseDiv) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockDiv unless _tmp return _tmp end # HtmlBlockOpenDl = "<" Spnl ("dl" | "DL") Spnl HtmlAttribute* ">" def _HtmlBlockOpenDl _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("dl") break if _tmp self.pos = _save1 _tmp = match_string("DL") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenDl unless _tmp return _tmp end # HtmlBlockCloseDl = "<" Spnl "/" ("dl" | "DL") Spnl ">" def _HtmlBlockCloseDl _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("dl") break if _tmp self.pos = _save1 _tmp = match_string("DL") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseDl unless _tmp return _tmp end # HtmlBlockDl = HtmlBlockOpenDl (HtmlBlockDl | !HtmlBlockCloseDl .)* HtmlBlockCloseDl def _HtmlBlockDl _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenDl) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockDl) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseDl) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseDl) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockDl unless _tmp return _tmp end # HtmlBlockOpenFieldset = "<" Spnl ("fieldset" | "FIELDSET") Spnl HtmlAttribute* ">" def _HtmlBlockOpenFieldset _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("fieldset") break if _tmp self.pos = _save1 _tmp = match_string("FIELDSET") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenFieldset unless _tmp return _tmp end # HtmlBlockCloseFieldset = "<" Spnl "/" ("fieldset" | "FIELDSET") Spnl ">" def _HtmlBlockCloseFieldset _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("fieldset") break if _tmp self.pos = _save1 _tmp = match_string("FIELDSET") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseFieldset unless _tmp return _tmp end # HtmlBlockFieldset = HtmlBlockOpenFieldset (HtmlBlockFieldset | !HtmlBlockCloseFieldset .)* HtmlBlockCloseFieldset def _HtmlBlockFieldset _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenFieldset) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockFieldset) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseFieldset) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseFieldset) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockFieldset unless _tmp return _tmp end # HtmlBlockOpenForm = "<" Spnl ("form" | "FORM") Spnl HtmlAttribute* ">" def _HtmlBlockOpenForm _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("form") break if _tmp self.pos = _save1 _tmp = match_string("FORM") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenForm unless _tmp return _tmp end # HtmlBlockCloseForm = "<" Spnl "/" ("form" | "FORM") Spnl ">" def _HtmlBlockCloseForm _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("form") break if _tmp self.pos = _save1 _tmp = match_string("FORM") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseForm unless _tmp return _tmp end # HtmlBlockForm = HtmlBlockOpenForm (HtmlBlockForm | !HtmlBlockCloseForm .)* HtmlBlockCloseForm def _HtmlBlockForm _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenForm) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockForm) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseForm) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseForm) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockForm unless _tmp return _tmp end # HtmlBlockOpenH1 = "<" Spnl ("h1" | "H1") Spnl HtmlAttribute* ">" def _HtmlBlockOpenH1 _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("h1") break if _tmp self.pos = _save1 _tmp = match_string("H1") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenH1 unless _tmp return _tmp end # HtmlBlockCloseH1 = "<" Spnl "/" ("h1" | "H1") Spnl ">" def _HtmlBlockCloseH1 _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("h1") break if _tmp self.pos = _save1 _tmp = match_string("H1") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseH1 unless _tmp return _tmp end # HtmlBlockH1 = HtmlBlockOpenH1 (HtmlBlockH1 | !HtmlBlockCloseH1 .)* HtmlBlockCloseH1 def _HtmlBlockH1 _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenH1) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockH1) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseH1) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseH1) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockH1 unless _tmp return _tmp end # HtmlBlockOpenH2 = "<" Spnl ("h2" | "H2") Spnl HtmlAttribute* ">" def _HtmlBlockOpenH2 _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("h2") break if _tmp self.pos = _save1 _tmp = match_string("H2") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenH2 unless _tmp return _tmp end # HtmlBlockCloseH2 = "<" Spnl "/" ("h2" | "H2") Spnl ">" def _HtmlBlockCloseH2 _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("h2") break if _tmp self.pos = _save1 _tmp = match_string("H2") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseH2 unless _tmp return _tmp end # HtmlBlockH2 = HtmlBlockOpenH2 (HtmlBlockH2 | !HtmlBlockCloseH2 .)* HtmlBlockCloseH2 def _HtmlBlockH2 _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenH2) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockH2) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseH2) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseH2) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockH2 unless _tmp return _tmp end # HtmlBlockOpenH3 = "<" Spnl ("h3" | "H3") Spnl HtmlAttribute* ">" def _HtmlBlockOpenH3 _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("h3") break if _tmp self.pos = _save1 _tmp = match_string("H3") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenH3 unless _tmp return _tmp end # HtmlBlockCloseH3 = "<" Spnl "/" ("h3" | "H3") Spnl ">" def _HtmlBlockCloseH3 _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("h3") break if _tmp self.pos = _save1 _tmp = match_string("H3") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseH3 unless _tmp return _tmp end # HtmlBlockH3 = HtmlBlockOpenH3 (HtmlBlockH3 | !HtmlBlockCloseH3 .)* HtmlBlockCloseH3 def _HtmlBlockH3 _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenH3) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockH3) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseH3) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseH3) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockH3 unless _tmp return _tmp end # HtmlBlockOpenH4 = "<" Spnl ("h4" | "H4") Spnl HtmlAttribute* ">" def _HtmlBlockOpenH4 _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("h4") break if _tmp self.pos = _save1 _tmp = match_string("H4") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenH4 unless _tmp return _tmp end # HtmlBlockCloseH4 = "<" Spnl "/" ("h4" | "H4") Spnl ">" def _HtmlBlockCloseH4 _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("h4") break if _tmp self.pos = _save1 _tmp = match_string("H4") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseH4 unless _tmp return _tmp end # HtmlBlockH4 = HtmlBlockOpenH4 (HtmlBlockH4 | !HtmlBlockCloseH4 .)* HtmlBlockCloseH4 def _HtmlBlockH4 _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenH4) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockH4) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseH4) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseH4) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockH4 unless _tmp return _tmp end # HtmlBlockOpenH5 = "<" Spnl ("h5" | "H5") Spnl HtmlAttribute* ">" def _HtmlBlockOpenH5 _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("h5") break if _tmp self.pos = _save1 _tmp = match_string("H5") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenH5 unless _tmp return _tmp end # HtmlBlockCloseH5 = "<" Spnl "/" ("h5" | "H5") Spnl ">" def _HtmlBlockCloseH5 _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("h5") break if _tmp self.pos = _save1 _tmp = match_string("H5") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseH5 unless _tmp return _tmp end # HtmlBlockH5 = HtmlBlockOpenH5 (HtmlBlockH5 | !HtmlBlockCloseH5 .)* HtmlBlockCloseH5 def _HtmlBlockH5 _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenH5) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockH5) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseH5) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseH5) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockH5 unless _tmp return _tmp end # HtmlBlockOpenH6 = "<" Spnl ("h6" | "H6") Spnl HtmlAttribute* ">" def _HtmlBlockOpenH6 _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("h6") break if _tmp self.pos = _save1 _tmp = match_string("H6") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenH6 unless _tmp return _tmp end # HtmlBlockCloseH6 = "<" Spnl "/" ("h6" | "H6") Spnl ">" def _HtmlBlockCloseH6 _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("h6") break if _tmp self.pos = _save1 _tmp = match_string("H6") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseH6 unless _tmp return _tmp end # HtmlBlockH6 = HtmlBlockOpenH6 (HtmlBlockH6 | !HtmlBlockCloseH6 .)* HtmlBlockCloseH6 def _HtmlBlockH6 _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenH6) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockH6) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseH6) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseH6) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockH6 unless _tmp return _tmp end # HtmlBlockOpenMenu = "<" Spnl ("menu" | "MENU") Spnl HtmlAttribute* ">" def _HtmlBlockOpenMenu _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("menu") break if _tmp self.pos = _save1 _tmp = match_string("MENU") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenMenu unless _tmp return _tmp end # HtmlBlockCloseMenu = "<" Spnl "/" ("menu" | "MENU") Spnl ">" def _HtmlBlockCloseMenu _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("menu") break if _tmp self.pos = _save1 _tmp = match_string("MENU") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseMenu unless _tmp return _tmp end # HtmlBlockMenu = HtmlBlockOpenMenu (HtmlBlockMenu | !HtmlBlockCloseMenu .)* HtmlBlockCloseMenu def _HtmlBlockMenu _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenMenu) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockMenu) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseMenu) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseMenu) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockMenu unless _tmp return _tmp end # HtmlBlockOpenNoframes = "<" Spnl ("noframes" | "NOFRAMES") Spnl HtmlAttribute* ">" def _HtmlBlockOpenNoframes _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("noframes") break if _tmp self.pos = _save1 _tmp = match_string("NOFRAMES") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenNoframes unless _tmp return _tmp end # HtmlBlockCloseNoframes = "<" Spnl "/" ("noframes" | "NOFRAMES") Spnl ">" def _HtmlBlockCloseNoframes _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("noframes") break if _tmp self.pos = _save1 _tmp = match_string("NOFRAMES") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseNoframes unless _tmp return _tmp end # HtmlBlockNoframes = HtmlBlockOpenNoframes (HtmlBlockNoframes | !HtmlBlockCloseNoframes .)* HtmlBlockCloseNoframes def _HtmlBlockNoframes _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenNoframes) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockNoframes) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseNoframes) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseNoframes) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockNoframes unless _tmp return _tmp end # HtmlBlockOpenNoscript = "<" Spnl ("noscript" | "NOSCRIPT") Spnl HtmlAttribute* ">" def _HtmlBlockOpenNoscript _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("noscript") break if _tmp self.pos = _save1 _tmp = match_string("NOSCRIPT") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenNoscript unless _tmp return _tmp end # HtmlBlockCloseNoscript = "<" Spnl "/" ("noscript" | "NOSCRIPT") Spnl ">" def _HtmlBlockCloseNoscript _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("noscript") break if _tmp self.pos = _save1 _tmp = match_string("NOSCRIPT") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseNoscript unless _tmp return _tmp end # HtmlBlockNoscript = HtmlBlockOpenNoscript (HtmlBlockNoscript | !HtmlBlockCloseNoscript .)* HtmlBlockCloseNoscript def _HtmlBlockNoscript _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenNoscript) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockNoscript) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseNoscript) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseNoscript) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockNoscript unless _tmp return _tmp end # HtmlBlockOpenOl = "<" Spnl ("ol" | "OL") Spnl HtmlAttribute* ">" def _HtmlBlockOpenOl _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("ol") break if _tmp self.pos = _save1 _tmp = match_string("OL") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenOl unless _tmp return _tmp end # HtmlBlockCloseOl = "<" Spnl "/" ("ol" | "OL") Spnl ">" def _HtmlBlockCloseOl _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("ol") break if _tmp self.pos = _save1 _tmp = match_string("OL") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseOl unless _tmp return _tmp end # HtmlBlockOl = HtmlBlockOpenOl (HtmlBlockOl | !HtmlBlockCloseOl .)* HtmlBlockCloseOl def _HtmlBlockOl _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenOl) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockOl) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseOl) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseOl) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOl unless _tmp return _tmp end # HtmlBlockOpenP = "<" Spnl ("p" | "P") Spnl HtmlAttribute* ">" def _HtmlBlockOpenP _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("p") break if _tmp self.pos = _save1 _tmp = match_string("P") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenP unless _tmp return _tmp end # HtmlBlockCloseP = "<" Spnl "/" ("p" | "P") Spnl ">" def _HtmlBlockCloseP _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("p") break if _tmp self.pos = _save1 _tmp = match_string("P") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseP unless _tmp return _tmp end # HtmlBlockP = HtmlBlockOpenP (HtmlBlockP | !HtmlBlockCloseP .)* HtmlBlockCloseP def _HtmlBlockP _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenP) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockP) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseP) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseP) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockP unless _tmp return _tmp end # HtmlBlockOpenPre = "<" Spnl ("pre" | "PRE") Spnl HtmlAttribute* ">" def _HtmlBlockOpenPre _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("pre") break if _tmp self.pos = _save1 _tmp = match_string("PRE") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenPre unless _tmp return _tmp end # HtmlBlockClosePre = "<" Spnl "/" ("pre" | "PRE") Spnl ">" def _HtmlBlockClosePre _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("pre") break if _tmp self.pos = _save1 _tmp = match_string("PRE") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockClosePre unless _tmp return _tmp end # HtmlBlockPre = HtmlBlockOpenPre (HtmlBlockPre | !HtmlBlockClosePre .)* HtmlBlockClosePre def _HtmlBlockPre _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenPre) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockPre) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockClosePre) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockClosePre) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockPre unless _tmp return _tmp end # HtmlBlockOpenTable = "<" Spnl ("table" | "TABLE") Spnl HtmlAttribute* ">" def _HtmlBlockOpenTable _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("table") break if _tmp self.pos = _save1 _tmp = match_string("TABLE") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenTable unless _tmp return _tmp end # HtmlBlockCloseTable = "<" Spnl "/" ("table" | "TABLE") Spnl ">" def _HtmlBlockCloseTable _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("table") break if _tmp self.pos = _save1 _tmp = match_string("TABLE") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseTable unless _tmp return _tmp end # HtmlBlockTable = HtmlBlockOpenTable (HtmlBlockTable | !HtmlBlockCloseTable .)* HtmlBlockCloseTable def _HtmlBlockTable _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenTable) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockTable) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseTable) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseTable) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockTable unless _tmp return _tmp end # HtmlBlockOpenUl = "<" Spnl ("ul" | "UL") Spnl HtmlAttribute* ">" def _HtmlBlockOpenUl _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("ul") break if _tmp self.pos = _save1 _tmp = match_string("UL") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenUl unless _tmp return _tmp end # HtmlBlockCloseUl = "<" Spnl "/" ("ul" | "UL") Spnl ">" def _HtmlBlockCloseUl _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("ul") break if _tmp self.pos = _save1 _tmp = match_string("UL") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseUl unless _tmp return _tmp end # HtmlBlockUl = HtmlBlockOpenUl (HtmlBlockUl | !HtmlBlockCloseUl .)* HtmlBlockCloseUl def _HtmlBlockUl _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenUl) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockUl) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseUl) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseUl) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockUl unless _tmp return _tmp end # HtmlBlockOpenDd = "<" Spnl ("dd" | "DD") Spnl HtmlAttribute* ">" def _HtmlBlockOpenDd _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("dd") break if _tmp self.pos = _save1 _tmp = match_string("DD") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenDd unless _tmp return _tmp end # HtmlBlockCloseDd = "<" Spnl "/" ("dd" | "DD") Spnl ">" def _HtmlBlockCloseDd _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("dd") break if _tmp self.pos = _save1 _tmp = match_string("DD") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseDd unless _tmp return _tmp end # HtmlBlockDd = HtmlBlockOpenDd (HtmlBlockDd | !HtmlBlockCloseDd .)* HtmlBlockCloseDd def _HtmlBlockDd _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenDd) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockDd) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseDd) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseDd) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockDd unless _tmp return _tmp end # HtmlBlockOpenDt = "<" Spnl ("dt" | "DT") Spnl HtmlAttribute* ">" def _HtmlBlockOpenDt _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("dt") break if _tmp self.pos = _save1 _tmp = match_string("DT") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenDt unless _tmp return _tmp end # HtmlBlockCloseDt = "<" Spnl "/" ("dt" | "DT") Spnl ">" def _HtmlBlockCloseDt _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("dt") break if _tmp self.pos = _save1 _tmp = match_string("DT") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseDt unless _tmp return _tmp end # HtmlBlockDt = HtmlBlockOpenDt (HtmlBlockDt | !HtmlBlockCloseDt .)* HtmlBlockCloseDt def _HtmlBlockDt _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenDt) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockDt) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseDt) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseDt) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockDt unless _tmp return _tmp end # HtmlBlockOpenFrameset = "<" Spnl ("frameset" | "FRAMESET") Spnl HtmlAttribute* ">" def _HtmlBlockOpenFrameset _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("frameset") break if _tmp self.pos = _save1 _tmp = match_string("FRAMESET") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenFrameset unless _tmp return _tmp end # HtmlBlockCloseFrameset = "<" Spnl "/" ("frameset" | "FRAMESET") Spnl ">" def _HtmlBlockCloseFrameset _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("frameset") break if _tmp self.pos = _save1 _tmp = match_string("FRAMESET") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseFrameset unless _tmp return _tmp end # HtmlBlockFrameset = HtmlBlockOpenFrameset (HtmlBlockFrameset | !HtmlBlockCloseFrameset .)* HtmlBlockCloseFrameset def _HtmlBlockFrameset _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenFrameset) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockFrameset) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseFrameset) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseFrameset) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockFrameset unless _tmp return _tmp end # HtmlBlockOpenLi = "<" Spnl ("li" | "LI") Spnl HtmlAttribute* ">" def _HtmlBlockOpenLi _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("li") break if _tmp self.pos = _save1 _tmp = match_string("LI") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenLi unless _tmp return _tmp end # HtmlBlockCloseLi = "<" Spnl "/" ("li" | "LI") Spnl ">" def _HtmlBlockCloseLi _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("li") break if _tmp self.pos = _save1 _tmp = match_string("LI") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseLi unless _tmp return _tmp end # HtmlBlockLi = HtmlBlockOpenLi (HtmlBlockLi | !HtmlBlockCloseLi .)* HtmlBlockCloseLi def _HtmlBlockLi _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenLi) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockLi) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseLi) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseLi) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockLi unless _tmp return _tmp end # HtmlBlockOpenTbody = "<" Spnl ("tbody" | "TBODY") Spnl HtmlAttribute* ">" def _HtmlBlockOpenTbody _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("tbody") break if _tmp self.pos = _save1 _tmp = match_string("TBODY") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenTbody unless _tmp return _tmp end # HtmlBlockCloseTbody = "<" Spnl "/" ("tbody" | "TBODY") Spnl ">" def _HtmlBlockCloseTbody _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("tbody") break if _tmp self.pos = _save1 _tmp = match_string("TBODY") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseTbody unless _tmp return _tmp end # HtmlBlockTbody = HtmlBlockOpenTbody (HtmlBlockTbody | !HtmlBlockCloseTbody .)* HtmlBlockCloseTbody def _HtmlBlockTbody _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenTbody) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockTbody) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseTbody) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseTbody) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockTbody unless _tmp return _tmp end # HtmlBlockOpenTd = "<" Spnl ("td" | "TD") Spnl HtmlAttribute* ">" def _HtmlBlockOpenTd _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("td") break if _tmp self.pos = _save1 _tmp = match_string("TD") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenTd unless _tmp return _tmp end # HtmlBlockCloseTd = "<" Spnl "/" ("td" | "TD") Spnl ">" def _HtmlBlockCloseTd _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("td") break if _tmp self.pos = _save1 _tmp = match_string("TD") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseTd unless _tmp return _tmp end # HtmlBlockTd = HtmlBlockOpenTd (HtmlBlockTd | !HtmlBlockCloseTd .)* HtmlBlockCloseTd def _HtmlBlockTd _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenTd) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockTd) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseTd) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseTd) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockTd unless _tmp return _tmp end # HtmlBlockOpenTfoot = "<" Spnl ("tfoot" | "TFOOT") Spnl HtmlAttribute* ">" def _HtmlBlockOpenTfoot _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("tfoot") break if _tmp self.pos = _save1 _tmp = match_string("TFOOT") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenTfoot unless _tmp return _tmp end # HtmlBlockCloseTfoot = "<" Spnl "/" ("tfoot" | "TFOOT") Spnl ">" def _HtmlBlockCloseTfoot _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("tfoot") break if _tmp self.pos = _save1 _tmp = match_string("TFOOT") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseTfoot unless _tmp return _tmp end # HtmlBlockTfoot = HtmlBlockOpenTfoot (HtmlBlockTfoot | !HtmlBlockCloseTfoot .)* HtmlBlockCloseTfoot def _HtmlBlockTfoot _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenTfoot) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockTfoot) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseTfoot) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseTfoot) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockTfoot unless _tmp return _tmp end # HtmlBlockOpenTh = "<" Spnl ("th" | "TH") Spnl HtmlAttribute* ">" def _HtmlBlockOpenTh _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("th") break if _tmp self.pos = _save1 _tmp = match_string("TH") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenTh unless _tmp return _tmp end # HtmlBlockCloseTh = "<" Spnl "/" ("th" | "TH") Spnl ">" def _HtmlBlockCloseTh _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("th") break if _tmp self.pos = _save1 _tmp = match_string("TH") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseTh unless _tmp return _tmp end # HtmlBlockTh = HtmlBlockOpenTh (HtmlBlockTh | !HtmlBlockCloseTh .)* HtmlBlockCloseTh def _HtmlBlockTh _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenTh) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockTh) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseTh) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseTh) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockTh unless _tmp return _tmp end # HtmlBlockOpenThead = "<" Spnl ("thead" | "THEAD") Spnl HtmlAttribute* ">" def _HtmlBlockOpenThead _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("thead") break if _tmp self.pos = _save1 _tmp = match_string("THEAD") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenThead unless _tmp return _tmp end # HtmlBlockCloseThead = "<" Spnl "/" ("thead" | "THEAD") Spnl ">" def _HtmlBlockCloseThead _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("thead") break if _tmp self.pos = _save1 _tmp = match_string("THEAD") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseThead unless _tmp return _tmp end # HtmlBlockThead = HtmlBlockOpenThead (HtmlBlockThead | !HtmlBlockCloseThead .)* HtmlBlockCloseThead def _HtmlBlockThead _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenThead) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockThead) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseThead) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseThead) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockThead unless _tmp return _tmp end # HtmlBlockOpenTr = "<" Spnl ("tr" | "TR") Spnl HtmlAttribute* ">" def _HtmlBlockOpenTr _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("tr") break if _tmp self.pos = _save1 _tmp = match_string("TR") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenTr unless _tmp return _tmp end # HtmlBlockCloseTr = "<" Spnl "/" ("tr" | "TR") Spnl ">" def _HtmlBlockCloseTr _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("tr") break if _tmp self.pos = _save1 _tmp = match_string("TR") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseTr unless _tmp return _tmp end # HtmlBlockTr = HtmlBlockOpenTr (HtmlBlockTr | !HtmlBlockCloseTr .)* HtmlBlockCloseTr def _HtmlBlockTr _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenTr) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockTr) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseTr) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseTr) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockTr unless _tmp return _tmp end # HtmlBlockOpenScript = "<" Spnl ("script" | "SCRIPT") Spnl HtmlAttribute* ">" def _HtmlBlockOpenScript _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("script") break if _tmp self.pos = _save1 _tmp = match_string("SCRIPT") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenScript unless _tmp return _tmp end # HtmlBlockCloseScript = "<" Spnl "/" ("script" | "SCRIPT") Spnl ">" def _HtmlBlockCloseScript _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("script") break if _tmp self.pos = _save1 _tmp = match_string("SCRIPT") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseScript unless _tmp return _tmp end # HtmlBlockScript = HtmlBlockOpenScript (!HtmlBlockCloseScript .)* HtmlBlockCloseScript def _HtmlBlockScript _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenScript) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # sequence _save3 = self.pos _tmp = apply(:_HtmlBlockCloseScript) _tmp = _tmp ? nil : true self.pos = _save3 unless _tmp self.pos = _save2 break end _tmp = get_byte unless _tmp self.pos = _save2 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseScript) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockScript unless _tmp return _tmp end # HtmlBlockInTags = (HtmlAnchor | HtmlBlockAddress | HtmlBlockBlockquote | HtmlBlockCenter | HtmlBlockDir | HtmlBlockDiv | HtmlBlockDl | HtmlBlockFieldset | HtmlBlockForm | HtmlBlockH1 | HtmlBlockH2 | HtmlBlockH3 | HtmlBlockH4 | HtmlBlockH5 | HtmlBlockH6 | HtmlBlockMenu | HtmlBlockNoframes | HtmlBlockNoscript | HtmlBlockOl | HtmlBlockP | HtmlBlockPre | HtmlBlockTable | HtmlBlockUl | HtmlBlockDd | HtmlBlockDt | HtmlBlockFrameset | HtmlBlockLi | HtmlBlockTbody | HtmlBlockTd | HtmlBlockTfoot | HtmlBlockTh | HtmlBlockThead | HtmlBlockTr | HtmlBlockScript) def _HtmlBlockInTags _save = self.pos while true # choice _tmp = apply(:_HtmlAnchor) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockAddress) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockBlockquote) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockCenter) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockDir) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockDiv) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockDl) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockFieldset) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockForm) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockH1) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockH2) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockH3) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockH4) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockH5) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockH6) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockMenu) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockNoframes) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockNoscript) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockOl) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockP) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockPre) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockTable) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockUl) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockDd) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockDt) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockFrameset) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockLi) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockTbody) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockTd) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockTfoot) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockTh) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockThead) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockTr) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockScript) break if _tmp self.pos = _save break end # end choice set_failed_rule :_HtmlBlockInTags unless _tmp return _tmp end # HtmlBlock = < (HtmlBlockInTags | HtmlComment | HtmlBlockSelfClosing | HtmlUnclosed) > @BlankLine+ { if html? then RDoc::Markup::Raw.new text end } def _HtmlBlock _save = self.pos while true # sequence _text_start = self.pos _save1 = self.pos while true # choice _tmp = apply(:_HtmlBlockInTags) break if _tmp self.pos = _save1 _tmp = apply(:_HtmlComment) break if _tmp self.pos = _save1 _tmp = apply(:_HtmlBlockSelfClosing) break if _tmp self.pos = _save1 _tmp = apply(:_HtmlUnclosed) break if _tmp self.pos = _save1 break end # end choice if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end _save2 = self.pos _tmp = _BlankLine() if _tmp while true _tmp = _BlankLine() break unless _tmp end _tmp = true else self.pos = _save2 end unless _tmp self.pos = _save break end @result = begin; if html? then RDoc::Markup::Raw.new text end ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlock unless _tmp return _tmp end # HtmlUnclosed = "<" Spnl HtmlUnclosedType Spnl HtmlAttribute* Spnl ">" def _HtmlUnclosed _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = apply(:_HtmlUnclosedType) unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlUnclosed unless _tmp return _tmp end # HtmlUnclosedType = ("HR" | "hr") def _HtmlUnclosedType _save = self.pos while true # choice _tmp = match_string("HR") break if _tmp self.pos = _save _tmp = match_string("hr") break if _tmp self.pos = _save break end # end choice set_failed_rule :_HtmlUnclosedType unless _tmp return _tmp end # HtmlBlockSelfClosing = "<" Spnl HtmlBlockType Spnl HtmlAttribute* "/" Spnl ">" def _HtmlBlockSelfClosing _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockType) unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockSelfClosing unless _tmp return _tmp end # HtmlBlockType = ("ADDRESS" | "BLOCKQUOTE" | "CENTER" | "DD" | "DIR" | "DIV" | "DL" | "DT" | "FIELDSET" | "FORM" | "FRAMESET" | "H1" | "H2" | "H3" | "H4" | "H5" | "H6" | "HR" | "ISINDEX" | "LI" | "MENU" | "NOFRAMES" | "NOSCRIPT" | "OL" | "P" | "PRE" | "SCRIPT" | "TABLE" | "TBODY" | "TD" | "TFOOT" | "TH" | "THEAD" | "TR" | "UL" | "address" | "blockquote" | "center" | "dd" | "dir" | "div" | "dl" | "dt" | "fieldset" | "form" | "frameset" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "hr" | "isindex" | "li" | "menu" | "noframes" | "noscript" | "ol" | "p" | "pre" | "script" | "table" | "tbody" | "td" | "tfoot" | "th" | "thead" | "tr" | "ul") def _HtmlBlockType _save = self.pos while true # choice _tmp = match_string("ADDRESS") break if _tmp self.pos = _save _tmp = match_string("BLOCKQUOTE") break if _tmp self.pos = _save _tmp = match_string("CENTER") break if _tmp self.pos = _save _tmp = match_string("DD") break if _tmp self.pos = _save _tmp = match_string("DIR") break if _tmp self.pos = _save _tmp = match_string("DIV") break if _tmp self.pos = _save _tmp = match_string("DL") break if _tmp self.pos = _save _tmp = match_string("DT") break if _tmp self.pos = _save _tmp = match_string("FIELDSET") break if _tmp self.pos = _save _tmp = match_string("FORM") break if _tmp self.pos = _save _tmp = match_string("FRAMESET") break if _tmp self.pos = _save _tmp = match_string("H1") break if _tmp self.pos = _save _tmp = match_string("H2") break if _tmp self.pos = _save _tmp = match_string("H3") break if _tmp self.pos = _save _tmp = match_string("H4") break if _tmp self.pos = _save _tmp = match_string("H5") break if _tmp self.pos = _save _tmp = match_string("H6") break if _tmp self.pos = _save _tmp = match_string("HR") break if _tmp self.pos = _save _tmp = match_string("ISINDEX") break if _tmp self.pos = _save _tmp = match_string("LI") break if _tmp self.pos = _save _tmp = match_string("MENU") break if _tmp self.pos = _save _tmp = match_string("NOFRAMES") break if _tmp self.pos = _save _tmp = match_string("NOSCRIPT") break if _tmp self.pos = _save _tmp = match_string("OL") break if _tmp self.pos = _save _tmp = match_string("P") break if _tmp self.pos = _save _tmp = match_string("PRE") break if _tmp self.pos = _save _tmp = match_string("SCRIPT") break if _tmp self.pos = _save _tmp = match_string("TABLE") break if _tmp self.pos = _save _tmp = match_string("TBODY") break if _tmp self.pos = _save _tmp = match_string("TD") break if _tmp self.pos = _save _tmp = match_string("TFOOT") break if _tmp self.pos = _save _tmp = match_string("TH") break if _tmp self.pos = _save _tmp = match_string("THEAD") break if _tmp self.pos = _save _tmp = match_string("TR") break if _tmp self.pos = _save _tmp = match_string("UL") break if _tmp self.pos = _save _tmp = match_string("address") break if _tmp self.pos = _save _tmp = match_string("blockquote") break if _tmp self.pos = _save _tmp = match_string("center") break if _tmp self.pos = _save _tmp = match_string("dd") break if _tmp self.pos = _save _tmp = match_string("dir") break if _tmp self.pos = _save _tmp = match_string("div") break if _tmp self.pos = _save _tmp = match_string("dl") break if _tmp self.pos = _save _tmp = match_string("dt") break if _tmp self.pos = _save _tmp = match_string("fieldset") break if _tmp self.pos = _save _tmp = match_string("form") break if _tmp self.pos = _save _tmp = match_string("frameset") break if _tmp self.pos = _save _tmp = match_string("h1") break if _tmp self.pos = _save _tmp = match_string("h2") break if _tmp self.pos = _save _tmp = match_string("h3") break if _tmp self.pos = _save _tmp = match_string("h4") break if _tmp self.pos = _save _tmp = match_string("h5") break if _tmp self.pos = _save _tmp = match_string("h6") break if _tmp self.pos = _save _tmp = match_string("hr") break if _tmp self.pos = _save _tmp = match_string("isindex") break if _tmp self.pos = _save _tmp = match_string("li") break if _tmp self.pos = _save _tmp = match_string("menu") break if _tmp self.pos = _save _tmp = match_string("noframes") break if _tmp self.pos = _save _tmp = match_string("noscript") break if _tmp self.pos = _save _tmp = match_string("ol") break if _tmp self.pos = _save _tmp = match_string("p") break if _tmp self.pos = _save _tmp = match_string("pre") break if _tmp self.pos = _save _tmp = match_string("script") break if _tmp self.pos = _save _tmp = match_string("table") break if _tmp self.pos = _save _tmp = match_string("tbody") break if _tmp self.pos = _save _tmp = match_string("td") break if _tmp self.pos = _save _tmp = match_string("tfoot") break if _tmp self.pos = _save _tmp = match_string("th") break if _tmp self.pos = _save _tmp = match_string("thead") break if _tmp self.pos = _save _tmp = match_string("tr") break if _tmp self.pos = _save _tmp = match_string("ul") break if _tmp self.pos = _save break end # end choice set_failed_rule :_HtmlBlockType unless _tmp return _tmp end # StyleOpen = "<" Spnl ("style" | "STYLE") Spnl HtmlAttribute* ">" def _StyleOpen _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("style") break if _tmp self.pos = _save1 _tmp = match_string("STYLE") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_StyleOpen unless _tmp return _tmp end # StyleClose = "<" Spnl "/" ("style" | "STYLE") Spnl ">" def _StyleClose _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("style") break if _tmp self.pos = _save1 _tmp = match_string("STYLE") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_StyleClose unless _tmp return _tmp end # InStyleTags = StyleOpen (!StyleClose .)* StyleClose def _InStyleTags _save = self.pos while true # sequence _tmp = apply(:_StyleOpen) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # sequence _save3 = self.pos _tmp = apply(:_StyleClose) _tmp = _tmp ? nil : true self.pos = _save3 unless _tmp self.pos = _save2 break end _tmp = get_byte unless _tmp self.pos = _save2 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_StyleClose) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_InStyleTags unless _tmp return _tmp end # StyleBlock = < InStyleTags > @BlankLine* { if css? then RDoc::Markup::Raw.new text end } def _StyleBlock _save = self.pos while true # sequence _text_start = self.pos _tmp = apply(:_InStyleTags) if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end while true _tmp = _BlankLine() break unless _tmp end _tmp = true unless _tmp self.pos = _save break end @result = begin; if css? then RDoc::Markup::Raw.new text end ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_StyleBlock unless _tmp return _tmp end # Inlines = (!@Endline Inline:i { i } | @Endline:c &Inline { c })+:chunks @Endline? { chunks } def _Inlines _save = self.pos while true # sequence _save1 = self.pos _ary = [] _save2 = self.pos while true # choice _save3 = self.pos while true # sequence _save4 = self.pos _tmp = _Endline() _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = apply(:_Inline) i = @result unless _tmp self.pos = _save3 break end @result = begin; i ; end _tmp = true unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 _save5 = self.pos while true # sequence _tmp = _Endline() c = @result unless _tmp self.pos = _save5 break end _save6 = self.pos _tmp = apply(:_Inline) self.pos = _save6 unless _tmp self.pos = _save5 break end @result = begin; c ; end _tmp = true unless _tmp self.pos = _save5 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice if _tmp _ary << @result while true _save7 = self.pos while true # choice _save8 = self.pos while true # sequence _save9 = self.pos _tmp = _Endline() _tmp = _tmp ? nil : true self.pos = _save9 unless _tmp self.pos = _save8 break end _tmp = apply(:_Inline) i = @result unless _tmp self.pos = _save8 break end @result = begin; i ; end _tmp = true unless _tmp self.pos = _save8 end break end # end sequence break if _tmp self.pos = _save7 _save10 = self.pos while true # sequence _tmp = _Endline() c = @result unless _tmp self.pos = _save10 break end _save11 = self.pos _tmp = apply(:_Inline) self.pos = _save11 unless _tmp self.pos = _save10 break end @result = begin; c ; end _tmp = true unless _tmp self.pos = _save10 end break end # end sequence break if _tmp self.pos = _save7 break end # end choice _ary << @result if _tmp break unless _tmp end _tmp = true @result = _ary else self.pos = _save1 end chunks = @result unless _tmp self.pos = _save break end _save12 = self.pos _tmp = _Endline() unless _tmp _tmp = true self.pos = _save12 end unless _tmp self.pos = _save break end @result = begin; chunks ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Inlines unless _tmp return _tmp end # Inline = (Str | @Endline | UlOrStarLine | @Space | Strong | Emph | Image | Link | NoteReference | InlineNote | Code | RawHtml | Entity | EscapedChar | Symbol) def _Inline _save = self.pos while true # choice _tmp = apply(:_Str) break if _tmp self.pos = _save _tmp = _Endline() break if _tmp self.pos = _save _tmp = apply(:_UlOrStarLine) break if _tmp self.pos = _save _tmp = _Space() break if _tmp self.pos = _save _tmp = apply(:_Strong) break if _tmp self.pos = _save _tmp = apply(:_Emph) break if _tmp self.pos = _save _tmp = apply(:_Image) break if _tmp self.pos = _save _tmp = apply(:_Link) break if _tmp self.pos = _save _tmp = apply(:_NoteReference) break if _tmp self.pos = _save _tmp = apply(:_InlineNote) break if _tmp self.pos = _save _tmp = apply(:_Code) break if _tmp self.pos = _save _tmp = apply(:_RawHtml) break if _tmp self.pos = _save _tmp = apply(:_Entity) break if _tmp self.pos = _save _tmp = apply(:_EscapedChar) break if _tmp self.pos = _save _tmp = apply(:_Symbol) break if _tmp self.pos = _save break end # end choice set_failed_rule :_Inline unless _tmp return _tmp end # Space = @Spacechar+ { " " } def _Space _save = self.pos while true # sequence _save1 = self.pos _tmp = _Spacechar() if _tmp while true _tmp = _Spacechar() break unless _tmp end _tmp = true else self.pos = _save1 end unless _tmp self.pos = _save break end @result = begin; " " ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Space unless _tmp return _tmp end # Str = @StartList:a < @NormalChar+ > { a = text } (StrChunk:c { a << c })* { a } def _Str _save = self.pos while true # sequence _tmp = _StartList() a = @result unless _tmp self.pos = _save break end _text_start = self.pos _save1 = self.pos _tmp = _NormalChar() if _tmp while true _tmp = _NormalChar() break unless _tmp end _tmp = true else self.pos = _save1 end if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end @result = begin; a = text ; end _tmp = true unless _tmp self.pos = _save break end while true _save3 = self.pos while true # sequence _tmp = apply(:_StrChunk) c = @result unless _tmp self.pos = _save3 break end @result = begin; a << c ; end _tmp = true unless _tmp self.pos = _save3 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save break end @result = begin; a ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Str unless _tmp return _tmp end # StrChunk = < (@NormalChar | /_+/ &Alphanumeric)+ > { text } def _StrChunk _save = self.pos while true # sequence _text_start = self.pos _save1 = self.pos _save2 = self.pos while true # choice _tmp = _NormalChar() break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _tmp = scan(/\A(?-mix:_+)/) unless _tmp self.pos = _save3 break end _save4 = self.pos _tmp = apply(:_Alphanumeric) self.pos = _save4 unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice if _tmp while true _save5 = self.pos while true # choice _tmp = _NormalChar() break if _tmp self.pos = _save5 _save6 = self.pos while true # sequence _tmp = scan(/\A(?-mix:_+)/) unless _tmp self.pos = _save6 break end _save7 = self.pos _tmp = apply(:_Alphanumeric) self.pos = _save7 unless _tmp self.pos = _save6 end break end # end sequence break if _tmp self.pos = _save5 break end # end choice break unless _tmp end _tmp = true else self.pos = _save1 end if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end @result = begin; text ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_StrChunk unless _tmp return _tmp end # EscapedChar = "\\" !@Newline < /[:\\`|*_{}\[\]()#+.!><-]/ > { text } def _EscapedChar _save = self.pos while true # sequence _tmp = match_string("\\") unless _tmp self.pos = _save break end _save1 = self.pos _tmp = _Newline() _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save break end _text_start = self.pos _tmp = scan(/\A(?-mix:[:\\`|*_{}\[\]()#+.!><-])/) if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end @result = begin; text ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_EscapedChar unless _tmp return _tmp end # Entity = (HexEntity | DecEntity | CharEntity):a { a } def _Entity _save = self.pos while true # sequence _save1 = self.pos while true # choice _tmp = apply(:_HexEntity) break if _tmp self.pos = _save1 _tmp = apply(:_DecEntity) break if _tmp self.pos = _save1 _tmp = apply(:_CharEntity) break if _tmp self.pos = _save1 break end # end choice a = @result unless _tmp self.pos = _save break end @result = begin; a ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Entity unless _tmp return _tmp end # Endline = (@LineBreak | @TerminalEndline | @NormalEndline) def _Endline _save = self.pos while true # choice _tmp = _LineBreak() break if _tmp self.pos = _save _tmp = _TerminalEndline() break if _tmp self.pos = _save _tmp = _NormalEndline() break if _tmp self.pos = _save break end # end choice set_failed_rule :_Endline unless _tmp return _tmp end # NormalEndline = @Sp @Newline !@BlankLine !">" !AtxStart !(Line /={3,}|-{3,}=/ @Newline) { "\n" } def _NormalEndline _save = self.pos while true # sequence _tmp = _Sp() unless _tmp self.pos = _save break end _tmp = _Newline() unless _tmp self.pos = _save break end _save1 = self.pos _tmp = _BlankLine() _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save break end _save2 = self.pos _tmp = match_string(">") _tmp = _tmp ? nil : true self.pos = _save2 unless _tmp self.pos = _save break end _save3 = self.pos _tmp = apply(:_AtxStart) _tmp = _tmp ? nil : true self.pos = _save3 unless _tmp self.pos = _save break end _save4 = self.pos _save5 = self.pos while true # sequence _tmp = apply(:_Line) unless _tmp self.pos = _save5 break end _tmp = scan(/\A(?-mix:={3,}|-{3,}=)/) unless _tmp self.pos = _save5 break end _tmp = _Newline() unless _tmp self.pos = _save5 end break end # end sequence _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save break end @result = begin; "\n" ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_NormalEndline unless _tmp return _tmp end # TerminalEndline = @Sp @Newline @Eof def _TerminalEndline _save = self.pos while true # sequence _tmp = _Sp() unless _tmp self.pos = _save break end _tmp = _Newline() unless _tmp self.pos = _save break end _tmp = _Eof() unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_TerminalEndline unless _tmp return _tmp end # LineBreak = " " @NormalEndline { RDoc::Markup::HardBreak.new } def _LineBreak _save = self.pos while true # sequence _tmp = match_string(" ") unless _tmp self.pos = _save break end _tmp = _NormalEndline() unless _tmp self.pos = _save break end @result = begin; RDoc::Markup::HardBreak.new ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_LineBreak unless _tmp return _tmp end # Symbol = < @SpecialChar > { text } def _Symbol _save = self.pos while true # sequence _text_start = self.pos _tmp = _SpecialChar() if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end @result = begin; text ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Symbol unless _tmp return _tmp end # UlOrStarLine = (UlLine | StarLine):a { a } def _UlOrStarLine _save = self.pos while true # sequence _save1 = self.pos while true # choice _tmp = apply(:_UlLine) break if _tmp self.pos = _save1 _tmp = apply(:_StarLine) break if _tmp self.pos = _save1 break end # end choice a = @result unless _tmp self.pos = _save break end @result = begin; a ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_UlOrStarLine unless _tmp return _tmp end # StarLine = (< /\*{4,}/ > { text } | < @Spacechar /\*+/ &@Spacechar > { text }) def _StarLine _save = self.pos while true # choice _save1 = self.pos while true # sequence _text_start = self.pos _tmp = scan(/\A(?-mix:\*{4,})/) if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save1 break end @result = begin; text ; end _tmp = true unless _tmp self.pos = _save1 end break end # end sequence break if _tmp self.pos = _save _save2 = self.pos while true # sequence _text_start = self.pos _save3 = self.pos while true # sequence _tmp = _Spacechar() unless _tmp self.pos = _save3 break end _tmp = scan(/\A(?-mix:\*+)/) unless _tmp self.pos = _save3 break end _save4 = self.pos _tmp = _Spacechar() self.pos = _save4 unless _tmp self.pos = _save3 end break end # end sequence if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save2 break end @result = begin; text ; end _tmp = true unless _tmp self.pos = _save2 end break end # end sequence break if _tmp self.pos = _save break end # end choice set_failed_rule :_StarLine unless _tmp return _tmp end # UlLine = (< /_{4,}/ > { text } | < @Spacechar /_+/ &@Spacechar > { text }) def _UlLine _save = self.pos while true # choice _save1 = self.pos while true # sequence _text_start = self.pos _tmp = scan(/\A(?-mix:_{4,})/) if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save1 break end @result = begin; text ; end _tmp = true unless _tmp self.pos = _save1 end break end # end sequence break if _tmp self.pos = _save _save2 = self.pos while true # sequence _text_start = self.pos _save3 = self.pos while true # sequence _tmp = _Spacechar() unless _tmp self.pos = _save3 break end _tmp = scan(/\A(?-mix:_+)/) unless _tmp self.pos = _save3 break end _save4 = self.pos _tmp = _Spacechar() self.pos = _save4 unless _tmp self.pos = _save3 end break end # end sequence if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save2 break end @result = begin; text ; end _tmp = true unless _tmp self.pos = _save2 end break end # end sequence break if _tmp self.pos = _save break end # end choice set_failed_rule :_UlLine unless _tmp return _tmp end # Emph = (EmphStar | EmphUl) def _Emph _save = self.pos while true # choice _tmp = apply(:_EmphStar) break if _tmp self.pos = _save _tmp = apply(:_EmphUl) break if _tmp self.pos = _save break end # end choice set_failed_rule :_Emph unless _tmp return _tmp end # OneStarOpen = !StarLine "*" !@Spacechar !@Newline def _OneStarOpen _save = self.pos while true # sequence _save1 = self.pos _tmp = apply(:_StarLine) _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save break end _tmp = match_string("*") unless _tmp self.pos = _save break end _save2 = self.pos _tmp = _Spacechar() _tmp = _tmp ? nil : true self.pos = _save2 unless _tmp self.pos = _save break end _save3 = self.pos _tmp = _Newline() _tmp = _tmp ? nil : true self.pos = _save3 unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_OneStarOpen unless _tmp return _tmp end # OneStarClose = !@Spacechar !@Newline Inline:a "*" { a } def _OneStarClose _save = self.pos while true # sequence _save1 = self.pos _tmp = _Spacechar() _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save break end _save2 = self.pos _tmp = _Newline() _tmp = _tmp ? nil : true self.pos = _save2 unless _tmp self.pos = _save break end _tmp = apply(:_Inline) a = @result unless _tmp self.pos = _save break end _tmp = match_string("*") unless _tmp self.pos = _save break end @result = begin; a ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_OneStarClose unless _tmp return _tmp end # EmphStar = OneStarOpen @StartList:a (!OneStarClose Inline:l { a << l })* OneStarClose:l { a << l } { emphasis a.join } def _EmphStar _save = self.pos while true # sequence _tmp = apply(:_OneStarOpen) unless _tmp self.pos = _save break end _tmp = _StartList() a = @result unless _tmp self.pos = _save break end while true _save2 = self.pos while true # sequence _save3 = self.pos _tmp = apply(:_OneStarClose) _tmp = _tmp ? nil : true self.pos = _save3 unless _tmp self.pos = _save2 break end _tmp = apply(:_Inline) l = @result unless _tmp self.pos = _save2 break end @result = begin; a << l ; end _tmp = true unless _tmp self.pos = _save2 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_OneStarClose) l = @result unless _tmp self.pos = _save break end @result = begin; a << l ; end _tmp = true unless _tmp self.pos = _save break end @result = begin; emphasis a.join ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_EmphStar unless _tmp return _tmp end # OneUlOpen = !UlLine "_" !@Spacechar !@Newline def _OneUlOpen _save = self.pos while true # sequence _save1 = self.pos _tmp = apply(:_UlLine) _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save break end _tmp = match_string("_") unless _tmp self.pos = _save break end _save2 = self.pos _tmp = _Spacechar() _tmp = _tmp ? nil : true self.pos = _save2 unless _tmp self.pos = _save break end _save3 = self.pos _tmp = _Newline() _tmp = _tmp ? nil : true self.pos = _save3 unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_OneUlOpen unless _tmp return _tmp end # OneUlClose = !@Spacechar !@Newline Inline:a "_" { a } def _OneUlClose _save = self.pos while true # sequence _save1 = self.pos _tmp = _Spacechar() _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save break end _save2 = self.pos _tmp = _Newline() _tmp = _tmp ? nil : true self.pos = _save2 unless _tmp self.pos = _save break end _tmp = apply(:_Inline) a = @result unless _tmp self.pos = _save break end _tmp = match_string("_") unless _tmp self.pos = _save break end @result = begin; a ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_OneUlClose unless _tmp return _tmp end # EmphUl = OneUlOpen @StartList:a (!OneUlClose Inline:l { a << l })* OneUlClose:l { a << l } { emphasis a.join } def _EmphUl _save = self.pos while true # sequence _tmp = apply(:_OneUlOpen) unless _tmp self.pos = _save break end _tmp = _StartList() a = @result unless _tmp self.pos = _save break end while true _save2 = self.pos while true # sequence _save3 = self.pos _tmp = apply(:_OneUlClose) _tmp = _tmp ? nil : true self.pos = _save3 unless _tmp self.pos = _save2 break end _tmp = apply(:_Inline) l = @result unless _tmp self.pos = _save2 break end @result = begin; a << l ; end _tmp = true unless _tmp self.pos = _save2 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_OneUlClose) l = @result unless _tmp self.pos = _save break end @result = begin; a << l ; end _tmp = true unless _tmp self.pos = _save break end @result = begin; emphasis a.join ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_EmphUl unless _tmp return _tmp end # Strong = (StrongStar | StrongUl) def _Strong _save = self.pos while true # choice _tmp = apply(:_StrongStar) break if _tmp self.pos = _save _tmp = apply(:_StrongUl) break if _tmp self.pos = _save break end # end choice set_failed_rule :_Strong unless _tmp return _tmp end # TwoStarOpen = !StarLine "**" !@Spacechar !@Newline def _TwoStarOpen _save = self.pos while true # sequence _save1 = self.pos _tmp = apply(:_StarLine) _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save break end _tmp = match_string("**") unless _tmp self.pos = _save break end _save2 = self.pos _tmp = _Spacechar() _tmp = _tmp ? nil : true self.pos = _save2 unless _tmp self.pos = _save break end _save3 = self.pos _tmp = _Newline() _tmp = _tmp ? nil : true self.pos = _save3 unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_TwoStarOpen unless _tmp return _tmp end # TwoStarClose = !@Spacechar !@Newline Inline:a "**" { a } def _TwoStarClose _save = self.pos while true # sequence _save1 = self.pos _tmp = _Spacechar() _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save break end _save2 = self.pos _tmp = _Newline() _tmp = _tmp ? nil : true self.pos = _save2 unless _tmp self.pos = _save break end _tmp = apply(:_Inline) a = @result unless _tmp self.pos = _save break end _tmp = match_string("**") unless _tmp self.pos = _save break end @result = begin; a ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_TwoStarClose unless _tmp return _tmp end # StrongStar = TwoStarOpen @StartList:a (!TwoStarClose Inline:l { a << l })* TwoStarClose:l { a << l } { strong a.join } def _StrongStar _save = self.pos while true # sequence _tmp = apply(:_TwoStarOpen) unless _tmp self.pos = _save break end _tmp = _StartList() a = @result unless _tmp self.pos = _save break end while true _save2 = self.pos while true # sequence _save3 = self.pos _tmp = apply(:_TwoStarClose) _tmp = _tmp ? nil : true self.pos = _save3 unless _tmp self.pos = _save2 break end _tmp = apply(:_Inline) l = @result unless _tmp self.pos = _save2 break end @result = begin; a << l ; end _tmp = true unless _tmp self.pos = _save2 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_TwoStarClose) l = @result unless _tmp self.pos = _save break end @result = begin; a << l ; end _tmp = true unless _tmp self.pos = _save break end @result = begin; strong a.join ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_StrongStar unless _tmp return _tmp end # TwoUlOpen = !UlLine "__" !@Spacechar !@Newline def _TwoUlOpen _save = self.pos while true # sequence _save1 = self.pos _tmp = apply(:_UlLine) _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save break end _tmp = match_string("__") unless _tmp self.pos = _save break end _save2 = self.pos _tmp = _Spacechar() _tmp = _tmp ? nil : true self.pos = _save2 unless _tmp self.pos = _save break end _save3 = self.pos _tmp = _Newline() _tmp = _tmp ? nil : true self.pos = _save3 unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_TwoUlOpen unless _tmp return _tmp end # TwoUlClose = !@Spacechar !@Newline Inline:a "__" { a } def _TwoUlClose _save = self.pos while true # sequence _save1 = self.pos _tmp = _Spacechar() _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save break end _save2 = self.pos _tmp = _Newline() _tmp = _tmp ? nil : true self.pos = _save2 unless _tmp self.pos = _save break end _tmp = apply(:_Inline) a = @result unless _tmp self.pos = _save break end _tmp = match_string("__") unless _tmp self.pos = _save break end @result = begin; a ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_TwoUlClose unless _tmp return _tmp end # StrongUl = TwoUlOpen @StartList:a (!TwoUlClose Inline:i { a << i })* TwoUlClose:l { a << l } { strong a.join } def _StrongUl _save = self.pos while true # sequence _tmp = apply(:_TwoUlOpen) unless _tmp self.pos = _save break end _tmp = _StartList() a = @result unless _tmp self.pos = _save break end while true _save2 = self.pos while true # sequence _save3 = self.pos _tmp = apply(:_TwoUlClose) _tmp = _tmp ? nil : true self.pos = _save3 unless _tmp self.pos = _save2 break end _tmp = apply(:_Inline) i = @result unless _tmp self.pos = _save2 break end @result = begin; a << i ; end _tmp = true unless _tmp self.pos = _save2 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_TwoUlClose) l = @result unless _tmp self.pos = _save break end @result = begin; a << l ; end _tmp = true unless _tmp self.pos = _save break end @result = begin; strong a.join ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_StrongUl unless _tmp return _tmp end # Image = "!" (ExplicitLink | ReferenceLink):a { "rdoc-image:#{a[/\[(.*)\]/, 1]}" } def _Image _save = self.pos while true # sequence _tmp = match_string("!") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = apply(:_ExplicitLink) break if _tmp self.pos = _save1 _tmp = apply(:_ReferenceLink) break if _tmp self.pos = _save1 break end # end choice a = @result unless _tmp self.pos = _save break end @result = begin; "rdoc-image:#{a[/\[(.*)\]/, 1]}" ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Image unless _tmp return _tmp end # Link = (ExplicitLink | ReferenceLink | AutoLink) def _Link _save = self.pos while true # choice _tmp = apply(:_ExplicitLink) break if _tmp self.pos = _save _tmp = apply(:_ReferenceLink) break if _tmp self.pos = _save _tmp = apply(:_AutoLink) break if _tmp self.pos = _save break end # end choice set_failed_rule :_Link unless _tmp return _tmp end # ReferenceLink = (ReferenceLinkDouble | ReferenceLinkSingle) def _ReferenceLink _save = self.pos while true # choice _tmp = apply(:_ReferenceLinkDouble) break if _tmp self.pos = _save _tmp = apply(:_ReferenceLinkSingle) break if _tmp self.pos = _save break end # end choice set_failed_rule :_ReferenceLink unless _tmp return _tmp end # ReferenceLinkDouble = Label:content < Spnl > !"[]" Label:label { link_to content, label, text } def _ReferenceLinkDouble _save = self.pos while true # sequence _tmp = apply(:_Label) content = @result unless _tmp self.pos = _save break end _text_start = self.pos _tmp = apply(:_Spnl) if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end _save1 = self.pos _tmp = match_string("[]") _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save break end _tmp = apply(:_Label) label = @result unless _tmp self.pos = _save break end @result = begin; link_to content, label, text ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_ReferenceLinkDouble unless _tmp return _tmp end # ReferenceLinkSingle = Label:content < (Spnl "[]")? > { link_to content, content, text } def _ReferenceLinkSingle _save = self.pos while true # sequence _tmp = apply(:_Label) content = @result unless _tmp self.pos = _save break end _text_start = self.pos _save1 = self.pos _save2 = self.pos while true # sequence _tmp = apply(:_Spnl) unless _tmp self.pos = _save2 break end _tmp = match_string("[]") unless _tmp self.pos = _save2 end break end # end sequence unless _tmp _tmp = true self.pos = _save1 end if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end @result = begin; link_to content, content, text ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_ReferenceLinkSingle unless _tmp return _tmp end # ExplicitLink = Label:l Spnl "(" @Sp Source:s Spnl Title @Sp ")" { "{#{l}}[#{s}]" } def _ExplicitLink _save = self.pos while true # sequence _tmp = apply(:_Label) l = @result unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("(") unless _tmp self.pos = _save break end _tmp = _Sp() unless _tmp self.pos = _save break end _tmp = apply(:_Source) s = @result unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = apply(:_Title) unless _tmp self.pos = _save break end _tmp = _Sp() unless _tmp self.pos = _save break end _tmp = match_string(")") unless _tmp self.pos = _save break end @result = begin; "{#{l}}[#{s}]" ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_ExplicitLink unless _tmp return _tmp end # Source = ("<" < SourceContents > ">" | < SourceContents >) { text } def _Source _save = self.pos while true # sequence _save1 = self.pos while true # choice _save2 = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save2 break end _text_start = self.pos _tmp = apply(:_SourceContents) if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save2 break end _tmp = match_string(">") unless _tmp self.pos = _save2 end break end # end sequence break if _tmp self.pos = _save1 _text_start = self.pos _tmp = apply(:_SourceContents) if _tmp text = get_text(_text_start) end break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end @result = begin; text ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Source unless _tmp return _tmp end # SourceContents = (((!"(" !")" !">" Nonspacechar)+ | "(" SourceContents ")")* | "") def _SourceContents _save = self.pos while true # choice while true _save2 = self.pos while true # choice _save3 = self.pos _save4 = self.pos while true # sequence _save5 = self.pos _tmp = match_string("(") _tmp = _tmp ? nil : true self.pos = _save5 unless _tmp self.pos = _save4 break end _save6 = self.pos _tmp = match_string(")") _tmp = _tmp ? nil : true self.pos = _save6 unless _tmp self.pos = _save4 break end _save7 = self.pos _tmp = match_string(">") _tmp = _tmp ? nil : true self.pos = _save7 unless _tmp self.pos = _save4 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save4 end break end # end sequence if _tmp while true _save8 = self.pos while true # sequence _save9 = self.pos _tmp = match_string("(") _tmp = _tmp ? nil : true self.pos = _save9 unless _tmp self.pos = _save8 break end _save10 = self.pos _tmp = match_string(")") _tmp = _tmp ? nil : true self.pos = _save10 unless _tmp self.pos = _save8 break end _save11 = self.pos _tmp = match_string(">") _tmp = _tmp ? nil : true self.pos = _save11 unless _tmp self.pos = _save8 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save8 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save3 end break if _tmp self.pos = _save2 _save12 = self.pos while true # sequence _tmp = match_string("(") unless _tmp self.pos = _save12 break end _tmp = apply(:_SourceContents) unless _tmp self.pos = _save12 break end _tmp = match_string(")") unless _tmp self.pos = _save12 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true break if _tmp self.pos = _save _tmp = match_string("") break if _tmp self.pos = _save break end # end choice set_failed_rule :_SourceContents unless _tmp return _tmp end # Title = (TitleSingle | TitleDouble | ""):a { a } def _Title _save = self.pos while true # sequence _save1 = self.pos while true # choice _tmp = apply(:_TitleSingle) break if _tmp self.pos = _save1 _tmp = apply(:_TitleDouble) break if _tmp self.pos = _save1 _tmp = match_string("") break if _tmp self.pos = _save1 break end # end choice a = @result unless _tmp self.pos = _save break end @result = begin; a ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Title unless _tmp return _tmp end # TitleSingle = "'" (!("'" @Sp (")" | @Newline)) .)* "'" def _TitleSingle _save = self.pos while true # sequence _tmp = match_string("'") unless _tmp self.pos = _save break end while true _save2 = self.pos while true # sequence _save3 = self.pos _save4 = self.pos while true # sequence _tmp = match_string("'") unless _tmp self.pos = _save4 break end _tmp = _Sp() unless _tmp self.pos = _save4 break end _save5 = self.pos while true # choice _tmp = match_string(")") break if _tmp self.pos = _save5 _tmp = _Newline() break if _tmp self.pos = _save5 break end # end choice unless _tmp self.pos = _save4 end break end # end sequence _tmp = _tmp ? nil : true self.pos = _save3 unless _tmp self.pos = _save2 break end _tmp = get_byte unless _tmp self.pos = _save2 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string("'") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_TitleSingle unless _tmp return _tmp end # TitleDouble = "\"" (!("\"" @Sp (")" | @Newline)) .)* "\"" def _TitleDouble _save = self.pos while true # sequence _tmp = match_string("\"") unless _tmp self.pos = _save break end while true _save2 = self.pos while true # sequence _save3 = self.pos _save4 = self.pos while true # sequence _tmp = match_string("\"") unless _tmp self.pos = _save4 break end _tmp = _Sp() unless _tmp self.pos = _save4 break end _save5 = self.pos while true # choice _tmp = match_string(")") break if _tmp self.pos = _save5 _tmp = _Newline() break if _tmp self.pos = _save5 break end # end choice unless _tmp self.pos = _save4 end break end # end sequence _tmp = _tmp ? nil : true self.pos = _save3 unless _tmp self.pos = _save2 break end _tmp = get_byte unless _tmp self.pos = _save2 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string("\"") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_TitleDouble unless _tmp return _tmp end # AutoLink = (AutoLinkUrl | AutoLinkEmail) def _AutoLink _save = self.pos while true # choice _tmp = apply(:_AutoLinkUrl) break if _tmp self.pos = _save _tmp = apply(:_AutoLinkEmail) break if _tmp self.pos = _save break end # end choice set_failed_rule :_AutoLink unless _tmp return _tmp end # AutoLinkUrl = "<" < /[A-Za-z]+/ "://" (!@Newline !">" .)+ > ">" { text } def _AutoLinkUrl _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _text_start = self.pos _save1 = self.pos while true # sequence _tmp = scan(/\A(?-mix:[A-Za-z]+)/) unless _tmp self.pos = _save1 break end _tmp = match_string("://") unless _tmp self.pos = _save1 break end _save2 = self.pos _save3 = self.pos while true # sequence _save4 = self.pos _tmp = _Newline() _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _save5 = self.pos _tmp = match_string(">") _tmp = _tmp ? nil : true self.pos = _save5 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence if _tmp while true _save6 = self.pos while true # sequence _save7 = self.pos _tmp = _Newline() _tmp = _tmp ? nil : true self.pos = _save7 unless _tmp self.pos = _save6 break end _save8 = self.pos _tmp = match_string(">") _tmp = _tmp ? nil : true self.pos = _save8 unless _tmp self.pos = _save6 break end _tmp = get_byte unless _tmp self.pos = _save6 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save2 end unless _tmp self.pos = _save1 end break end # end sequence if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save break end @result = begin; text ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_AutoLinkUrl unless _tmp return _tmp end # AutoLinkEmail = "<" "mailto:"? < /[\w+.\/!%~$-]+/i "@" (!@Newline !">" .)+ > ">" { "mailto:#{text}" } def _AutoLinkEmail _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _save1 = self.pos _tmp = match_string("mailto:") unless _tmp _tmp = true self.pos = _save1 end unless _tmp self.pos = _save break end _text_start = self.pos _save2 = self.pos while true # sequence _tmp = scan(/\A(?i-mx:[\w+.\/!%~$-]+)/) unless _tmp self.pos = _save2 break end _tmp = match_string("@") unless _tmp self.pos = _save2 break end _save3 = self.pos _save4 = self.pos while true # sequence _save5 = self.pos _tmp = _Newline() _tmp = _tmp ? nil : true self.pos = _save5 unless _tmp self.pos = _save4 break end _save6 = self.pos _tmp = match_string(">") _tmp = _tmp ? nil : true self.pos = _save6 unless _tmp self.pos = _save4 break end _tmp = get_byte unless _tmp self.pos = _save4 end break end # end sequence if _tmp while true _save7 = self.pos while true # sequence _save8 = self.pos _tmp = _Newline() _tmp = _tmp ? nil : true self.pos = _save8 unless _tmp self.pos = _save7 break end _save9 = self.pos _tmp = match_string(">") _tmp = _tmp ? nil : true self.pos = _save9 unless _tmp self.pos = _save7 break end _tmp = get_byte unless _tmp self.pos = _save7 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save3 end unless _tmp self.pos = _save2 end break end # end sequence if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save break end @result = begin; "mailto:#{text}" ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_AutoLinkEmail unless _tmp return _tmp end # Reference = @NonindentSpace !"[]" Label:label ":" Spnl RefSrc:link RefTitle @BlankLine+ { # TODO use title reference label, link nil } def _Reference _save = self.pos while true # sequence _tmp = _NonindentSpace() unless _tmp self.pos = _save break end _save1 = self.pos _tmp = match_string("[]") _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save break end _tmp = apply(:_Label) label = @result unless _tmp self.pos = _save break end _tmp = match_string(":") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = apply(:_RefSrc) link = @result unless _tmp self.pos = _save break end _tmp = apply(:_RefTitle) unless _tmp self.pos = _save break end _save2 = self.pos _tmp = _BlankLine() if _tmp while true _tmp = _BlankLine() break unless _tmp end _tmp = true else self.pos = _save2 end unless _tmp self.pos = _save break end @result = begin; # TODO use title reference label, link nil ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Reference unless _tmp return _tmp end # Label = "[" (!"^" &{ notes? } | &. &{ !notes? }) @StartList:a (!"]" Inline:l { a << l })* "]" { a.join.gsub(/\s+/, ' ') } def _Label _save = self.pos while true # sequence _tmp = match_string("[") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _save2 = self.pos while true # sequence _save3 = self.pos _tmp = match_string("^") _tmp = _tmp ? nil : true self.pos = _save3 unless _tmp self.pos = _save2 break end _save4 = self.pos _tmp = begin; notes? ; end self.pos = _save4 unless _tmp self.pos = _save2 end break end # end sequence break if _tmp self.pos = _save1 _save5 = self.pos while true # sequence _save6 = self.pos _tmp = get_byte self.pos = _save6 unless _tmp self.pos = _save5 break end _save7 = self.pos _tmp = begin; !notes? ; end self.pos = _save7 unless _tmp self.pos = _save5 end break end # end sequence break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = _StartList() a = @result unless _tmp self.pos = _save break end while true _save9 = self.pos while true # sequence _save10 = self.pos _tmp = match_string("]") _tmp = _tmp ? nil : true self.pos = _save10 unless _tmp self.pos = _save9 break end _tmp = apply(:_Inline) l = @result unless _tmp self.pos = _save9 break end @result = begin; a << l ; end _tmp = true unless _tmp self.pos = _save9 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string("]") unless _tmp self.pos = _save break end @result = begin; a.join.gsub(/\s+/, ' ') ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Label unless _tmp return _tmp end # RefSrc = < Nonspacechar+ > { text } def _RefSrc _save = self.pos while true # sequence _text_start = self.pos _save1 = self.pos _tmp = apply(:_Nonspacechar) if _tmp while true _tmp = apply(:_Nonspacechar) break unless _tmp end _tmp = true else self.pos = _save1 end if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end @result = begin; text ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_RefSrc unless _tmp return _tmp end # RefTitle = (RefTitleSingle | RefTitleDouble | RefTitleParens | EmptyTitle) def _RefTitle _save = self.pos while true # choice _tmp = apply(:_RefTitleSingle) break if _tmp self.pos = _save _tmp = apply(:_RefTitleDouble) break if _tmp self.pos = _save _tmp = apply(:_RefTitleParens) break if _tmp self.pos = _save _tmp = apply(:_EmptyTitle) break if _tmp self.pos = _save break end # end choice set_failed_rule :_RefTitle unless _tmp return _tmp end # EmptyTitle = "" def _EmptyTitle _tmp = match_string("") set_failed_rule :_EmptyTitle unless _tmp return _tmp end # RefTitleSingle = Spnl "'" < (!("'" @Sp @Newline | @Newline) .)* > "'" { text } def _RefTitleSingle _save = self.pos while true # sequence _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("'") unless _tmp self.pos = _save break end _text_start = self.pos while true _save2 = self.pos while true # sequence _save3 = self.pos _save4 = self.pos while true # choice _save5 = self.pos while true # sequence _tmp = match_string("'") unless _tmp self.pos = _save5 break end _tmp = _Sp() unless _tmp self.pos = _save5 break end _tmp = _Newline() unless _tmp self.pos = _save5 end break end # end sequence break if _tmp self.pos = _save4 _tmp = _Newline() break if _tmp self.pos = _save4 break end # end choice _tmp = _tmp ? nil : true self.pos = _save3 unless _tmp self.pos = _save2 break end _tmp = get_byte unless _tmp self.pos = _save2 end break end # end sequence break unless _tmp end _tmp = true if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end _tmp = match_string("'") unless _tmp self.pos = _save break end @result = begin; text ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_RefTitleSingle unless _tmp return _tmp end # RefTitleDouble = Spnl "\"" < (!("\"" @Sp @Newline | @Newline) .)* > "\"" { text } def _RefTitleDouble _save = self.pos while true # sequence _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("\"") unless _tmp self.pos = _save break end _text_start = self.pos while true _save2 = self.pos while true # sequence _save3 = self.pos _save4 = self.pos while true # choice _save5 = self.pos while true # sequence _tmp = match_string("\"") unless _tmp self.pos = _save5 break end _tmp = _Sp() unless _tmp self.pos = _save5 break end _tmp = _Newline() unless _tmp self.pos = _save5 end break end # end sequence break if _tmp self.pos = _save4 _tmp = _Newline() break if _tmp self.pos = _save4 break end # end choice _tmp = _tmp ? nil : true self.pos = _save3 unless _tmp self.pos = _save2 break end _tmp = get_byte unless _tmp self.pos = _save2 end break end # end sequence break unless _tmp end _tmp = true if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end _tmp = match_string("\"") unless _tmp self.pos = _save break end @result = begin; text ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_RefTitleDouble unless _tmp return _tmp end # RefTitleParens = Spnl "(" < (!(")" @Sp @Newline | @Newline) .)* > ")" { text } def _RefTitleParens _save = self.pos while true # sequence _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("(") unless _tmp self.pos = _save break end _text_start = self.pos while true _save2 = self.pos while true # sequence _save3 = self.pos _save4 = self.pos while true # choice _save5 = self.pos while true # sequence _tmp = match_string(")") unless _tmp self.pos = _save5 break end _tmp = _Sp() unless _tmp self.pos = _save5 break end _tmp = _Newline() unless _tmp self.pos = _save5 end break end # end sequence break if _tmp self.pos = _save4 _tmp = _Newline() break if _tmp self.pos = _save4 break end # end choice _tmp = _tmp ? nil : true self.pos = _save3 unless _tmp self.pos = _save2 break end _tmp = get_byte unless _tmp self.pos = _save2 end break end # end sequence break unless _tmp end _tmp = true if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end _tmp = match_string(")") unless _tmp self.pos = _save break end @result = begin; text ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_RefTitleParens unless _tmp return _tmp end # References = (Reference | SkipBlock)* def _References while true _save1 = self.pos while true # choice _tmp = apply(:_Reference) break if _tmp self.pos = _save1 _tmp = apply(:_SkipBlock) break if _tmp self.pos = _save1 break end # end choice break unless _tmp end _tmp = true set_failed_rule :_References unless _tmp return _tmp end # Ticks1 = "`" !"`" def _Ticks1 _save = self.pos while true # sequence _tmp = match_string("`") unless _tmp self.pos = _save break end _save1 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Ticks1 unless _tmp return _tmp end # Ticks2 = "``" !"`" def _Ticks2 _save = self.pos while true # sequence _tmp = match_string("``") unless _tmp self.pos = _save break end _save1 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Ticks2 unless _tmp return _tmp end # Ticks3 = "```" !"`" def _Ticks3 _save = self.pos while true # sequence _tmp = match_string("```") unless _tmp self.pos = _save break end _save1 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Ticks3 unless _tmp return _tmp end # Ticks4 = "````" !"`" def _Ticks4 _save = self.pos while true # sequence _tmp = match_string("````") unless _tmp self.pos = _save break end _save1 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Ticks4 unless _tmp return _tmp end # Ticks5 = "`````" !"`" def _Ticks5 _save = self.pos while true # sequence _tmp = match_string("`````") unless _tmp self.pos = _save break end _save1 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Ticks5 unless _tmp return _tmp end # Code = (Ticks1 @Sp < ((!"`" Nonspacechar)+ | !Ticks1 /`+/ | !(@Sp Ticks1) (@Spacechar | @Newline !@BlankLine))+ > @Sp Ticks1 | Ticks2 @Sp < ((!"`" Nonspacechar)+ | !Ticks2 /`+/ | !(@Sp Ticks2) (@Spacechar | @Newline !@BlankLine))+ > @Sp Ticks2 | Ticks3 @Sp < ((!"`" Nonspacechar)+ | !Ticks3 /`+/ | !(@Sp Ticks3) (@Spacechar | @Newline !@BlankLine))+ > @Sp Ticks3 | Ticks4 @Sp < ((!"`" Nonspacechar)+ | !Ticks4 /`+/ | !(@Sp Ticks4) (@Spacechar | @Newline !@BlankLine))+ > @Sp Ticks4 | Ticks5 @Sp < ((!"`" Nonspacechar)+ | !Ticks5 /`+/ | !(@Sp Ticks5) (@Spacechar | @Newline !@BlankLine))+ > @Sp Ticks5) { "#{text}" } def _Code _save = self.pos while true # sequence _save1 = self.pos while true # choice _save2 = self.pos while true # sequence _tmp = apply(:_Ticks1) unless _tmp self.pos = _save2 break end _tmp = _Sp() unless _tmp self.pos = _save2 break end _text_start = self.pos _save3 = self.pos _save4 = self.pos while true # choice _save5 = self.pos _save6 = self.pos while true # sequence _save7 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save7 unless _tmp self.pos = _save6 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save6 end break end # end sequence if _tmp while true _save8 = self.pos while true # sequence _save9 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save9 unless _tmp self.pos = _save8 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save8 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save5 end break if _tmp self.pos = _save4 _save10 = self.pos while true # sequence _save11 = self.pos _tmp = apply(:_Ticks1) _tmp = _tmp ? nil : true self.pos = _save11 unless _tmp self.pos = _save10 break end _tmp = scan(/\A(?-mix:`+)/) unless _tmp self.pos = _save10 end break end # end sequence break if _tmp self.pos = _save4 _save12 = self.pos while true # sequence _save13 = self.pos _save14 = self.pos while true # sequence _tmp = _Sp() unless _tmp self.pos = _save14 break end _tmp = apply(:_Ticks1) unless _tmp self.pos = _save14 end break end # end sequence _tmp = _tmp ? nil : true self.pos = _save13 unless _tmp self.pos = _save12 break end _save15 = self.pos while true # choice _tmp = _Spacechar() break if _tmp self.pos = _save15 _save16 = self.pos while true # sequence _tmp = _Newline() unless _tmp self.pos = _save16 break end _save17 = self.pos _tmp = _BlankLine() _tmp = _tmp ? nil : true self.pos = _save17 unless _tmp self.pos = _save16 end break end # end sequence break if _tmp self.pos = _save15 break end # end choice unless _tmp self.pos = _save12 end break end # end sequence break if _tmp self.pos = _save4 break end # end choice if _tmp while true _save18 = self.pos while true # choice _save19 = self.pos _save20 = self.pos while true # sequence _save21 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save21 unless _tmp self.pos = _save20 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save20 end break end # end sequence if _tmp while true _save22 = self.pos while true # sequence _save23 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save23 unless _tmp self.pos = _save22 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save22 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save19 end break if _tmp self.pos = _save18 _save24 = self.pos while true # sequence _save25 = self.pos _tmp = apply(:_Ticks1) _tmp = _tmp ? nil : true self.pos = _save25 unless _tmp self.pos = _save24 break end _tmp = scan(/\A(?-mix:`+)/) unless _tmp self.pos = _save24 end break end # end sequence break if _tmp self.pos = _save18 _save26 = self.pos while true # sequence _save27 = self.pos _save28 = self.pos while true # sequence _tmp = _Sp() unless _tmp self.pos = _save28 break end _tmp = apply(:_Ticks1) unless _tmp self.pos = _save28 end break end # end sequence _tmp = _tmp ? nil : true self.pos = _save27 unless _tmp self.pos = _save26 break end _save29 = self.pos while true # choice _tmp = _Spacechar() break if _tmp self.pos = _save29 _save30 = self.pos while true # sequence _tmp = _Newline() unless _tmp self.pos = _save30 break end _save31 = self.pos _tmp = _BlankLine() _tmp = _tmp ? nil : true self.pos = _save31 unless _tmp self.pos = _save30 end break end # end sequence break if _tmp self.pos = _save29 break end # end choice unless _tmp self.pos = _save26 end break end # end sequence break if _tmp self.pos = _save18 break end # end choice break unless _tmp end _tmp = true else self.pos = _save3 end if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save2 break end _tmp = _Sp() unless _tmp self.pos = _save2 break end _tmp = apply(:_Ticks1) unless _tmp self.pos = _save2 end break end # end sequence break if _tmp self.pos = _save1 _save32 = self.pos while true # sequence _tmp = apply(:_Ticks2) unless _tmp self.pos = _save32 break end _tmp = _Sp() unless _tmp self.pos = _save32 break end _text_start = self.pos _save33 = self.pos _save34 = self.pos while true # choice _save35 = self.pos _save36 = self.pos while true # sequence _save37 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save37 unless _tmp self.pos = _save36 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save36 end break end # end sequence if _tmp while true _save38 = self.pos while true # sequence _save39 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save39 unless _tmp self.pos = _save38 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save38 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save35 end break if _tmp self.pos = _save34 _save40 = self.pos while true # sequence _save41 = self.pos _tmp = apply(:_Ticks2) _tmp = _tmp ? nil : true self.pos = _save41 unless _tmp self.pos = _save40 break end _tmp = scan(/\A(?-mix:`+)/) unless _tmp self.pos = _save40 end break end # end sequence break if _tmp self.pos = _save34 _save42 = self.pos while true # sequence _save43 = self.pos _save44 = self.pos while true # sequence _tmp = _Sp() unless _tmp self.pos = _save44 break end _tmp = apply(:_Ticks2) unless _tmp self.pos = _save44 end break end # end sequence _tmp = _tmp ? nil : true self.pos = _save43 unless _tmp self.pos = _save42 break end _save45 = self.pos while true # choice _tmp = _Spacechar() break if _tmp self.pos = _save45 _save46 = self.pos while true # sequence _tmp = _Newline() unless _tmp self.pos = _save46 break end _save47 = self.pos _tmp = _BlankLine() _tmp = _tmp ? nil : true self.pos = _save47 unless _tmp self.pos = _save46 end break end # end sequence break if _tmp self.pos = _save45 break end # end choice unless _tmp self.pos = _save42 end break end # end sequence break if _tmp self.pos = _save34 break end # end choice if _tmp while true _save48 = self.pos while true # choice _save49 = self.pos _save50 = self.pos while true # sequence _save51 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save51 unless _tmp self.pos = _save50 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save50 end break end # end sequence if _tmp while true _save52 = self.pos while true # sequence _save53 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save53 unless _tmp self.pos = _save52 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save52 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save49 end break if _tmp self.pos = _save48 _save54 = self.pos while true # sequence _save55 = self.pos _tmp = apply(:_Ticks2) _tmp = _tmp ? nil : true self.pos = _save55 unless _tmp self.pos = _save54 break end _tmp = scan(/\A(?-mix:`+)/) unless _tmp self.pos = _save54 end break end # end sequence break if _tmp self.pos = _save48 _save56 = self.pos while true # sequence _save57 = self.pos _save58 = self.pos while true # sequence _tmp = _Sp() unless _tmp self.pos = _save58 break end _tmp = apply(:_Ticks2) unless _tmp self.pos = _save58 end break end # end sequence _tmp = _tmp ? nil : true self.pos = _save57 unless _tmp self.pos = _save56 break end _save59 = self.pos while true # choice _tmp = _Spacechar() break if _tmp self.pos = _save59 _save60 = self.pos while true # sequence _tmp = _Newline() unless _tmp self.pos = _save60 break end _save61 = self.pos _tmp = _BlankLine() _tmp = _tmp ? nil : true self.pos = _save61 unless _tmp self.pos = _save60 end break end # end sequence break if _tmp self.pos = _save59 break end # end choice unless _tmp self.pos = _save56 end break end # end sequence break if _tmp self.pos = _save48 break end # end choice break unless _tmp end _tmp = true else self.pos = _save33 end if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save32 break end _tmp = _Sp() unless _tmp self.pos = _save32 break end _tmp = apply(:_Ticks2) unless _tmp self.pos = _save32 end break end # end sequence break if _tmp self.pos = _save1 _save62 = self.pos while true # sequence _tmp = apply(:_Ticks3) unless _tmp self.pos = _save62 break end _tmp = _Sp() unless _tmp self.pos = _save62 break end _text_start = self.pos _save63 = self.pos _save64 = self.pos while true # choice _save65 = self.pos _save66 = self.pos while true # sequence _save67 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save67 unless _tmp self.pos = _save66 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save66 end break end # end sequence if _tmp while true _save68 = self.pos while true # sequence _save69 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save69 unless _tmp self.pos = _save68 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save68 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save65 end break if _tmp self.pos = _save64 _save70 = self.pos while true # sequence _save71 = self.pos _tmp = apply(:_Ticks3) _tmp = _tmp ? nil : true self.pos = _save71 unless _tmp self.pos = _save70 break end _tmp = scan(/\A(?-mix:`+)/) unless _tmp self.pos = _save70 end break end # end sequence break if _tmp self.pos = _save64 _save72 = self.pos while true # sequence _save73 = self.pos _save74 = self.pos while true # sequence _tmp = _Sp() unless _tmp self.pos = _save74 break end _tmp = apply(:_Ticks3) unless _tmp self.pos = _save74 end break end # end sequence _tmp = _tmp ? nil : true self.pos = _save73 unless _tmp self.pos = _save72 break end _save75 = self.pos while true # choice _tmp = _Spacechar() break if _tmp self.pos = _save75 _save76 = self.pos while true # sequence _tmp = _Newline() unless _tmp self.pos = _save76 break end _save77 = self.pos _tmp = _BlankLine() _tmp = _tmp ? nil : true self.pos = _save77 unless _tmp self.pos = _save76 end break end # end sequence break if _tmp self.pos = _save75 break end # end choice unless _tmp self.pos = _save72 end break end # end sequence break if _tmp self.pos = _save64 break end # end choice if _tmp while true _save78 = self.pos while true # choice _save79 = self.pos _save80 = self.pos while true # sequence _save81 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save81 unless _tmp self.pos = _save80 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save80 end break end # end sequence if _tmp while true _save82 = self.pos while true # sequence _save83 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save83 unless _tmp self.pos = _save82 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save82 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save79 end break if _tmp self.pos = _save78 _save84 = self.pos while true # sequence _save85 = self.pos _tmp = apply(:_Ticks3) _tmp = _tmp ? nil : true self.pos = _save85 unless _tmp self.pos = _save84 break end _tmp = scan(/\A(?-mix:`+)/) unless _tmp self.pos = _save84 end break end # end sequence break if _tmp self.pos = _save78 _save86 = self.pos while true # sequence _save87 = self.pos _save88 = self.pos while true # sequence _tmp = _Sp() unless _tmp self.pos = _save88 break end _tmp = apply(:_Ticks3) unless _tmp self.pos = _save88 end break end # end sequence _tmp = _tmp ? nil : true self.pos = _save87 unless _tmp self.pos = _save86 break end _save89 = self.pos while true # choice _tmp = _Spacechar() break if _tmp self.pos = _save89 _save90 = self.pos while true # sequence _tmp = _Newline() unless _tmp self.pos = _save90 break end _save91 = self.pos _tmp = _BlankLine() _tmp = _tmp ? nil : true self.pos = _save91 unless _tmp self.pos = _save90 end break end # end sequence break if _tmp self.pos = _save89 break end # end choice unless _tmp self.pos = _save86 end break end # end sequence break if _tmp self.pos = _save78 break end # end choice break unless _tmp end _tmp = true else self.pos = _save63 end if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save62 break end _tmp = _Sp() unless _tmp self.pos = _save62 break end _tmp = apply(:_Ticks3) unless _tmp self.pos = _save62 end break end # end sequence break if _tmp self.pos = _save1 _save92 = self.pos while true # sequence _tmp = apply(:_Ticks4) unless _tmp self.pos = _save92 break end _tmp = _Sp() unless _tmp self.pos = _save92 break end _text_start = self.pos _save93 = self.pos _save94 = self.pos while true # choice _save95 = self.pos _save96 = self.pos while true # sequence _save97 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save97 unless _tmp self.pos = _save96 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save96 end break end # end sequence if _tmp while true _save98 = self.pos while true # sequence _save99 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save99 unless _tmp self.pos = _save98 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save98 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save95 end break if _tmp self.pos = _save94 _save100 = self.pos while true # sequence _save101 = self.pos _tmp = apply(:_Ticks4) _tmp = _tmp ? nil : true self.pos = _save101 unless _tmp self.pos = _save100 break end _tmp = scan(/\A(?-mix:`+)/) unless _tmp self.pos = _save100 end break end # end sequence break if _tmp self.pos = _save94 _save102 = self.pos while true # sequence _save103 = self.pos _save104 = self.pos while true # sequence _tmp = _Sp() unless _tmp self.pos = _save104 break end _tmp = apply(:_Ticks4) unless _tmp self.pos = _save104 end break end # end sequence _tmp = _tmp ? nil : true self.pos = _save103 unless _tmp self.pos = _save102 break end _save105 = self.pos while true # choice _tmp = _Spacechar() break if _tmp self.pos = _save105 _save106 = self.pos while true # sequence _tmp = _Newline() unless _tmp self.pos = _save106 break end _save107 = self.pos _tmp = _BlankLine() _tmp = _tmp ? nil : true self.pos = _save107 unless _tmp self.pos = _save106 end break end # end sequence break if _tmp self.pos = _save105 break end # end choice unless _tmp self.pos = _save102 end break end # end sequence break if _tmp self.pos = _save94 break end # end choice if _tmp while true _save108 = self.pos while true # choice _save109 = self.pos _save110 = self.pos while true # sequence _save111 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save111 unless _tmp self.pos = _save110 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save110 end break end # end sequence if _tmp while true _save112 = self.pos while true # sequence _save113 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save113 unless _tmp self.pos = _save112 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save112 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save109 end break if _tmp self.pos = _save108 _save114 = self.pos while true # sequence _save115 = self.pos _tmp = apply(:_Ticks4) _tmp = _tmp ? nil : true self.pos = _save115 unless _tmp self.pos = _save114 break end _tmp = scan(/\A(?-mix:`+)/) unless _tmp self.pos = _save114 end break end # end sequence break if _tmp self.pos = _save108 _save116 = self.pos while true # sequence _save117 = self.pos _save118 = self.pos while true # sequence _tmp = _Sp() unless _tmp self.pos = _save118 break end _tmp = apply(:_Ticks4) unless _tmp self.pos = _save118 end break end # end sequence _tmp = _tmp ? nil : true self.pos = _save117 unless _tmp self.pos = _save116 break end _save119 = self.pos while true # choice _tmp = _Spacechar() break if _tmp self.pos = _save119 _save120 = self.pos while true # sequence _tmp = _Newline() unless _tmp self.pos = _save120 break end _save121 = self.pos _tmp = _BlankLine() _tmp = _tmp ? nil : true self.pos = _save121 unless _tmp self.pos = _save120 end break end # end sequence break if _tmp self.pos = _save119 break end # end choice unless _tmp self.pos = _save116 end break end # end sequence break if _tmp self.pos = _save108 break end # end choice break unless _tmp end _tmp = true else self.pos = _save93 end if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save92 break end _tmp = _Sp() unless _tmp self.pos = _save92 break end _tmp = apply(:_Ticks4) unless _tmp self.pos = _save92 end break end # end sequence break if _tmp self.pos = _save1 _save122 = self.pos while true # sequence _tmp = apply(:_Ticks5) unless _tmp self.pos = _save122 break end _tmp = _Sp() unless _tmp self.pos = _save122 break end _text_start = self.pos _save123 = self.pos _save124 = self.pos while true # choice _save125 = self.pos _save126 = self.pos while true # sequence _save127 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save127 unless _tmp self.pos = _save126 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save126 end break end # end sequence if _tmp while true _save128 = self.pos while true # sequence _save129 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save129 unless _tmp self.pos = _save128 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save128 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save125 end break if _tmp self.pos = _save124 _save130 = self.pos while true # sequence _save131 = self.pos _tmp = apply(:_Ticks5) _tmp = _tmp ? nil : true self.pos = _save131 unless _tmp self.pos = _save130 break end _tmp = scan(/\A(?-mix:`+)/) unless _tmp self.pos = _save130 end break end # end sequence break if _tmp self.pos = _save124 _save132 = self.pos while true # sequence _save133 = self.pos _save134 = self.pos while true # sequence _tmp = _Sp() unless _tmp self.pos = _save134 break end _tmp = apply(:_Ticks5) unless _tmp self.pos = _save134 end break end # end sequence _tmp = _tmp ? nil : true self.pos = _save133 unless _tmp self.pos = _save132 break end _save135 = self.pos while true # choice _tmp = _Spacechar() break if _tmp self.pos = _save135 _save136 = self.pos while true # sequence _tmp = _Newline() unless _tmp self.pos = _save136 break end _save137 = self.pos _tmp = _BlankLine() _tmp = _tmp ? nil : true self.pos = _save137 unless _tmp self.pos = _save136 end break end # end sequence break if _tmp self.pos = _save135 break end # end choice unless _tmp self.pos = _save132 end break end # end sequence break if _tmp self.pos = _save124 break end # end choice if _tmp while true _save138 = self.pos while true # choice _save139 = self.pos _save140 = self.pos while true # sequence _save141 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save141 unless _tmp self.pos = _save140 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save140 end break end # end sequence if _tmp while true _save142 = self.pos while true # sequence _save143 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save143 unless _tmp self.pos = _save142 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save142 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save139 end break if _tmp self.pos = _save138 _save144 = self.pos while true # sequence _save145 = self.pos _tmp = apply(:_Ticks5) _tmp = _tmp ? nil : true self.pos = _save145 unless _tmp self.pos = _save144 break end _tmp = scan(/\A(?-mix:`+)/) unless _tmp self.pos = _save144 end break end # end sequence break if _tmp self.pos = _save138 _save146 = self.pos while true # sequence _save147 = self.pos _save148 = self.pos while true # sequence _tmp = _Sp() unless _tmp self.pos = _save148 break end _tmp = apply(:_Ticks5) unless _tmp self.pos = _save148 end break end # end sequence _tmp = _tmp ? nil : true self.pos = _save147 unless _tmp self.pos = _save146 break end _save149 = self.pos while true # choice _tmp = _Spacechar() break if _tmp self.pos = _save149 _save150 = self.pos while true # sequence _tmp = _Newline() unless _tmp self.pos = _save150 break end _save151 = self.pos _tmp = _BlankLine() _tmp = _tmp ? nil : true self.pos = _save151 unless _tmp self.pos = _save150 end break end # end sequence break if _tmp self.pos = _save149 break end # end choice unless _tmp self.pos = _save146 end break end # end sequence break if _tmp self.pos = _save138 break end # end choice break unless _tmp end _tmp = true else self.pos = _save123 end if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save122 break end _tmp = _Sp() unless _tmp self.pos = _save122 break end _tmp = apply(:_Ticks5) unless _tmp self.pos = _save122 end break end # end sequence break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end @result = begin; "#{text}" ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Code unless _tmp return _tmp end # RawHtml = < (HtmlComment | HtmlBlockScript | HtmlTag) > { if html? then text else '' end } def _RawHtml _save = self.pos while true # sequence _text_start = self.pos _save1 = self.pos while true # choice _tmp = apply(:_HtmlComment) break if _tmp self.pos = _save1 _tmp = apply(:_HtmlBlockScript) break if _tmp self.pos = _save1 _tmp = apply(:_HtmlTag) break if _tmp self.pos = _save1 break end # end choice if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end @result = begin; if html? then text else '' end ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_RawHtml unless _tmp return _tmp end # BlankLine = @Sp @Newline { "\n" } def _BlankLine _save = self.pos while true # sequence _tmp = _Sp() unless _tmp self.pos = _save break end _tmp = _Newline() unless _tmp self.pos = _save break end @result = begin; "\n" ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_BlankLine unless _tmp return _tmp end # Quoted = ("\"" (!"\"" .)* "\"" | "'" (!"'" .)* "'") def _Quoted _save = self.pos while true # choice _save1 = self.pos while true # sequence _tmp = match_string("\"") unless _tmp self.pos = _save1 break end while true _save3 = self.pos while true # sequence _save4 = self.pos _tmp = match_string("\"") _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save1 break end _tmp = match_string("\"") unless _tmp self.pos = _save1 end break end # end sequence break if _tmp self.pos = _save _save5 = self.pos while true # sequence _tmp = match_string("'") unless _tmp self.pos = _save5 break end while true _save7 = self.pos while true # sequence _save8 = self.pos _tmp = match_string("'") _tmp = _tmp ? nil : true self.pos = _save8 unless _tmp self.pos = _save7 break end _tmp = get_byte unless _tmp self.pos = _save7 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save5 break end _tmp = match_string("'") unless _tmp self.pos = _save5 end break end # end sequence break if _tmp self.pos = _save break end # end choice set_failed_rule :_Quoted unless _tmp return _tmp end # HtmlAttribute = (AlphanumericAscii | "-")+ Spnl ("=" Spnl (Quoted | (!">" Nonspacechar)+))? Spnl def _HtmlAttribute _save = self.pos while true # sequence _save1 = self.pos _save2 = self.pos while true # choice _tmp = apply(:_AlphanumericAscii) break if _tmp self.pos = _save2 _tmp = match_string("-") break if _tmp self.pos = _save2 break end # end choice if _tmp while true _save3 = self.pos while true # choice _tmp = apply(:_AlphanumericAscii) break if _tmp self.pos = _save3 _tmp = match_string("-") break if _tmp self.pos = _save3 break end # end choice break unless _tmp end _tmp = true else self.pos = _save1 end unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save4 = self.pos _save5 = self.pos while true # sequence _tmp = match_string("=") unless _tmp self.pos = _save5 break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save5 break end _save6 = self.pos while true # choice _tmp = apply(:_Quoted) break if _tmp self.pos = _save6 _save7 = self.pos _save8 = self.pos while true # sequence _save9 = self.pos _tmp = match_string(">") _tmp = _tmp ? nil : true self.pos = _save9 unless _tmp self.pos = _save8 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save8 end break end # end sequence if _tmp while true _save10 = self.pos while true # sequence _save11 = self.pos _tmp = match_string(">") _tmp = _tmp ? nil : true self.pos = _save11 unless _tmp self.pos = _save10 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save10 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save7 end break if _tmp self.pos = _save6 break end # end choice unless _tmp self.pos = _save5 end break end # end sequence unless _tmp _tmp = true self.pos = _save4 end unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlAttribute unless _tmp return _tmp end # HtmlComment = "" .)* "-->" def _HtmlComment _save = self.pos while true # sequence _tmp = match_string("") _tmp = _tmp ? nil : true self.pos = _save3 unless _tmp self.pos = _save2 break end _tmp = get_byte unless _tmp self.pos = _save2 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string("-->") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlComment unless _tmp return _tmp end # HtmlTag = "<" Spnl "/"? AlphanumericAscii+ Spnl HtmlAttribute* "/"? Spnl ">" def _HtmlTag _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos _tmp = match_string("/") unless _tmp _tmp = true self.pos = _save1 end unless _tmp self.pos = _save break end _save2 = self.pos _tmp = apply(:_AlphanumericAscii) if _tmp while true _tmp = apply(:_AlphanumericAscii) break unless _tmp end _tmp = true else self.pos = _save2 end unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _save4 = self.pos _tmp = match_string("/") unless _tmp _tmp = true self.pos = _save4 end unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlTag unless _tmp return _tmp end # Eof = !. def _Eof _save = self.pos _tmp = get_byte _tmp = _tmp ? nil : true self.pos = _save set_failed_rule :_Eof unless _tmp return _tmp end # Nonspacechar = !@Spacechar !@Newline . def _Nonspacechar _save = self.pos while true # sequence _save1 = self.pos _tmp = _Spacechar() _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save break end _save2 = self.pos _tmp = _Newline() _tmp = _tmp ? nil : true self.pos = _save2 unless _tmp self.pos = _save break end _tmp = get_byte unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Nonspacechar unless _tmp return _tmp end # Sp = @Spacechar* def _Sp while true _tmp = _Spacechar() break unless _tmp end _tmp = true set_failed_rule :_Sp unless _tmp return _tmp end # Spnl = @Sp (@Newline @Sp)? def _Spnl _save = self.pos while true # sequence _tmp = _Sp() unless _tmp self.pos = _save break end _save1 = self.pos _save2 = self.pos while true # sequence _tmp = _Newline() unless _tmp self.pos = _save2 break end _tmp = _Sp() unless _tmp self.pos = _save2 end break end # end sequence unless _tmp _tmp = true self.pos = _save1 end unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Spnl unless _tmp return _tmp end # SpecialChar = (/[*_`&\[\]()= 48 and _tmp <= 57 self.pos = _save _tmp = nil end end set_failed_rule :_Digit unless _tmp return _tmp end # Alphanumeric = %literals.Alphanumeric def _Alphanumeric _tmp = @_grammar_literals.external_invoke(self, :_Alphanumeric) set_failed_rule :_Alphanumeric unless _tmp return _tmp end # AlphanumericAscii = %literals.AlphanumericAscii def _AlphanumericAscii _tmp = @_grammar_literals.external_invoke(self, :_AlphanumericAscii) set_failed_rule :_AlphanumericAscii unless _tmp return _tmp end # BOM = %literals.BOM def _BOM _tmp = @_grammar_literals.external_invoke(self, :_BOM) set_failed_rule :_BOM unless _tmp return _tmp end # Newline = %literals.Newline def _Newline _tmp = @_grammar_literals.external_invoke(self, :_Newline) set_failed_rule :_Newline unless _tmp return _tmp end # NonAlphanumeric = %literals.NonAlphanumeric def _NonAlphanumeric _tmp = @_grammar_literals.external_invoke(self, :_NonAlphanumeric) set_failed_rule :_NonAlphanumeric unless _tmp return _tmp end # Spacechar = %literals.Spacechar def _Spacechar _tmp = @_grammar_literals.external_invoke(self, :_Spacechar) set_failed_rule :_Spacechar unless _tmp return _tmp end # HexEntity = /&#x/i < /[0-9a-fA-F]+/ > ";" { [text.to_i(16)].pack 'U' } def _HexEntity _save = self.pos while true # sequence _tmp = scan(/\A(?i-mx:&#x)/) unless _tmp self.pos = _save break end _text_start = self.pos _tmp = scan(/\A(?-mix:[0-9a-fA-F]+)/) if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end _tmp = match_string(";") unless _tmp self.pos = _save break end @result = begin; [text.to_i(16)].pack 'U' ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HexEntity unless _tmp return _tmp end # DecEntity = "&#" < /[0-9]+/ > ";" { [text.to_i].pack 'U' } def _DecEntity _save = self.pos while true # sequence _tmp = match_string("&#") unless _tmp self.pos = _save break end _text_start = self.pos _tmp = scan(/\A(?-mix:[0-9]+)/) if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end _tmp = match_string(";") unless _tmp self.pos = _save break end @result = begin; [text.to_i].pack 'U' ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_DecEntity unless _tmp return _tmp end # CharEntity = "&" < /[A-Za-z0-9]+/ > ";" { if entity = HTML_ENTITIES[text] then entity.pack 'U*' else "&#{text};" end } def _CharEntity _save = self.pos while true # sequence _tmp = match_string("&") unless _tmp self.pos = _save break end _text_start = self.pos _tmp = scan(/\A(?-mix:[A-Za-z0-9]+)/) if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end _tmp = match_string(";") unless _tmp self.pos = _save break end @result = begin; if entity = HTML_ENTITIES[text] then entity.pack 'U*' else "&#{text};" end ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_CharEntity unless _tmp return _tmp end # NonindentSpace = / {0,3}/ def _NonindentSpace _tmp = scan(/\A(?-mix: {0,3})/) set_failed_rule :_NonindentSpace unless _tmp return _tmp end # Indent = /\t| / def _Indent _tmp = scan(/\A(?-mix:\t| )/) set_failed_rule :_Indent unless _tmp return _tmp end # IndentedLine = Indent Line def _IndentedLine _save = self.pos while true # sequence _tmp = apply(:_Indent) unless _tmp self.pos = _save break end _tmp = apply(:_Line) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_IndentedLine unless _tmp return _tmp end # OptionallyIndentedLine = Indent? Line def _OptionallyIndentedLine _save = self.pos while true # sequence _save1 = self.pos _tmp = apply(:_Indent) unless _tmp _tmp = true self.pos = _save1 end unless _tmp self.pos = _save break end _tmp = apply(:_Line) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_OptionallyIndentedLine unless _tmp return _tmp end # StartList = &. { [] } def _StartList _save = self.pos while true # sequence _save1 = self.pos _tmp = get_byte self.pos = _save1 unless _tmp self.pos = _save break end @result = begin; [] ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_StartList unless _tmp return _tmp end # Line = @RawLine:a { a } def _Line _save = self.pos while true # sequence _tmp = _RawLine() a = @result unless _tmp self.pos = _save break end @result = begin; a ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Line unless _tmp return _tmp end # RawLine = (< (!"\r" !"\n" .)* @Newline > | < .+ > @Eof) { text } def _RawLine _save = self.pos while true # sequence _save1 = self.pos while true # choice _text_start = self.pos _save2 = self.pos while true # sequence while true _save4 = self.pos while true # sequence _save5 = self.pos _tmp = match_string("\r") _tmp = _tmp ? nil : true self.pos = _save5 unless _tmp self.pos = _save4 break end _save6 = self.pos _tmp = match_string("\n") _tmp = _tmp ? nil : true self.pos = _save6 unless _tmp self.pos = _save4 break end _tmp = get_byte unless _tmp self.pos = _save4 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save2 break end _tmp = _Newline() unless _tmp self.pos = _save2 end break end # end sequence if _tmp text = get_text(_text_start) end break if _tmp self.pos = _save1 _save7 = self.pos while true # sequence _text_start = self.pos _save8 = self.pos _tmp = get_byte if _tmp while true _tmp = get_byte break unless _tmp end _tmp = true else self.pos = _save8 end if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save7 break end _tmp = _Eof() unless _tmp self.pos = _save7 end break end # end sequence break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end @result = begin; text ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_RawLine unless _tmp return _tmp end # SkipBlock = (HtmlBlock | (!"#" !SetextBottom1 !SetextBottom2 !@BlankLine @RawLine)+ @BlankLine* | @BlankLine+ | @RawLine) def _SkipBlock _save = self.pos while true # choice _tmp = apply(:_HtmlBlock) break if _tmp self.pos = _save _save1 = self.pos while true # sequence _save2 = self.pos _save3 = self.pos while true # sequence _save4 = self.pos _tmp = match_string("#") _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _save5 = self.pos _tmp = apply(:_SetextBottom1) _tmp = _tmp ? nil : true self.pos = _save5 unless _tmp self.pos = _save3 break end _save6 = self.pos _tmp = apply(:_SetextBottom2) _tmp = _tmp ? nil : true self.pos = _save6 unless _tmp self.pos = _save3 break end _save7 = self.pos _tmp = _BlankLine() _tmp = _tmp ? nil : true self.pos = _save7 unless _tmp self.pos = _save3 break end _tmp = _RawLine() unless _tmp self.pos = _save3 end break end # end sequence if _tmp while true _save8 = self.pos while true # sequence _save9 = self.pos _tmp = match_string("#") _tmp = _tmp ? nil : true self.pos = _save9 unless _tmp self.pos = _save8 break end _save10 = self.pos _tmp = apply(:_SetextBottom1) _tmp = _tmp ? nil : true self.pos = _save10 unless _tmp self.pos = _save8 break end _save11 = self.pos _tmp = apply(:_SetextBottom2) _tmp = _tmp ? nil : true self.pos = _save11 unless _tmp self.pos = _save8 break end _save12 = self.pos _tmp = _BlankLine() _tmp = _tmp ? nil : true self.pos = _save12 unless _tmp self.pos = _save8 break end _tmp = _RawLine() unless _tmp self.pos = _save8 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save2 end unless _tmp self.pos = _save1 break end while true _tmp = _BlankLine() break unless _tmp end _tmp = true unless _tmp self.pos = _save1 end break end # end sequence break if _tmp self.pos = _save _save14 = self.pos _tmp = _BlankLine() if _tmp while true _tmp = _BlankLine() break unless _tmp end _tmp = true else self.pos = _save14 end break if _tmp self.pos = _save _tmp = _RawLine() break if _tmp self.pos = _save break end # end choice set_failed_rule :_SkipBlock unless _tmp return _tmp end # ExtendedSpecialChar = &{ notes? } "^" def _ExtendedSpecialChar _save = self.pos while true # sequence _save1 = self.pos _tmp = begin; notes? ; end self.pos = _save1 unless _tmp self.pos = _save break end _tmp = match_string("^") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_ExtendedSpecialChar unless _tmp return _tmp end # NoteReference = &{ notes? } RawNoteReference:ref { note_for ref } def _NoteReference _save = self.pos while true # sequence _save1 = self.pos _tmp = begin; notes? ; end self.pos = _save1 unless _tmp self.pos = _save break end _tmp = apply(:_RawNoteReference) ref = @result unless _tmp self.pos = _save break end @result = begin; note_for ref ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_NoteReference unless _tmp return _tmp end # RawNoteReference = "[^" < (!@Newline !"]" .)+ > "]" { text } def _RawNoteReference _save = self.pos while true # sequence _tmp = match_string("[^") unless _tmp self.pos = _save break end _text_start = self.pos _save1 = self.pos _save2 = self.pos while true # sequence _save3 = self.pos _tmp = _Newline() _tmp = _tmp ? nil : true self.pos = _save3 unless _tmp self.pos = _save2 break end _save4 = self.pos _tmp = match_string("]") _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save2 break end _tmp = get_byte unless _tmp self.pos = _save2 end break end # end sequence if _tmp while true _save5 = self.pos while true # sequence _save6 = self.pos _tmp = _Newline() _tmp = _tmp ? nil : true self.pos = _save6 unless _tmp self.pos = _save5 break end _save7 = self.pos _tmp = match_string("]") _tmp = _tmp ? nil : true self.pos = _save7 unless _tmp self.pos = _save5 break end _tmp = get_byte unless _tmp self.pos = _save5 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save1 end if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end _tmp = match_string("]") unless _tmp self.pos = _save break end @result = begin; text ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_RawNoteReference unless _tmp return _tmp end # Note = &{ notes? } @NonindentSpace RawNoteReference:ref ":" @Sp @StartList:a RawNoteBlock:i { a.concat i } (&Indent RawNoteBlock:i { a.concat i })* { @footnotes[ref] = paragraph a nil } def _Note _save = self.pos while true # sequence _save1 = self.pos _tmp = begin; notes? ; end self.pos = _save1 unless _tmp self.pos = _save break end _tmp = _NonindentSpace() unless _tmp self.pos = _save break end _tmp = apply(:_RawNoteReference) ref = @result unless _tmp self.pos = _save break end _tmp = match_string(":") unless _tmp self.pos = _save break end _tmp = _Sp() unless _tmp self.pos = _save break end _tmp = _StartList() a = @result unless _tmp self.pos = _save break end _tmp = apply(:_RawNoteBlock) i = @result unless _tmp self.pos = _save break end @result = begin; a.concat i ; end _tmp = true unless _tmp self.pos = _save break end while true _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_Indent) self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = apply(:_RawNoteBlock) i = @result unless _tmp self.pos = _save3 break end @result = begin; a.concat i ; end _tmp = true unless _tmp self.pos = _save3 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save break end @result = begin; @footnotes[ref] = paragraph a nil ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Note unless _tmp return _tmp end # InlineNote = &{ notes? } "^[" @StartList:a (!"]" Inline:l { a << l })+ "]" { ref = [:inline, @note_order.length] @footnotes[ref] = paragraph a note_for ref } def _InlineNote _save = self.pos while true # sequence _save1 = self.pos _tmp = begin; notes? ; end self.pos = _save1 unless _tmp self.pos = _save break end _tmp = match_string("^[") unless _tmp self.pos = _save break end _tmp = _StartList() a = @result unless _tmp self.pos = _save break end _save2 = self.pos _save3 = self.pos while true # sequence _save4 = self.pos _tmp = match_string("]") _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = apply(:_Inline) l = @result unless _tmp self.pos = _save3 break end @result = begin; a << l ; end _tmp = true unless _tmp self.pos = _save3 end break end # end sequence if _tmp while true _save5 = self.pos while true # sequence _save6 = self.pos _tmp = match_string("]") _tmp = _tmp ? nil : true self.pos = _save6 unless _tmp self.pos = _save5 break end _tmp = apply(:_Inline) l = @result unless _tmp self.pos = _save5 break end @result = begin; a << l ; end _tmp = true unless _tmp self.pos = _save5 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save2 end unless _tmp self.pos = _save break end _tmp = match_string("]") unless _tmp self.pos = _save break end @result = begin; ref = [:inline, @note_order.length] @footnotes[ref] = paragraph a note_for ref ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_InlineNote unless _tmp return _tmp end # Notes = (Note | SkipBlock)* def _Notes while true _save1 = self.pos while true # choice _tmp = apply(:_Note) break if _tmp self.pos = _save1 _tmp = apply(:_SkipBlock) break if _tmp self.pos = _save1 break end # end choice break unless _tmp end _tmp = true set_failed_rule :_Notes unless _tmp return _tmp end # RawNoteBlock = @StartList:a (!@BlankLine OptionallyIndentedLine:l { a << l })+ < @BlankLine* > { a << text } { a } def _RawNoteBlock _save = self.pos while true # sequence _tmp = _StartList() a = @result unless _tmp self.pos = _save break end _save1 = self.pos _save2 = self.pos while true # sequence _save3 = self.pos _tmp = _BlankLine() _tmp = _tmp ? nil : true self.pos = _save3 unless _tmp self.pos = _save2 break end _tmp = apply(:_OptionallyIndentedLine) l = @result unless _tmp self.pos = _save2 break end @result = begin; a << l ; end _tmp = true unless _tmp self.pos = _save2 end break end # end sequence if _tmp while true _save4 = self.pos while true # sequence _save5 = self.pos _tmp = _BlankLine() _tmp = _tmp ? nil : true self.pos = _save5 unless _tmp self.pos = _save4 break end _tmp = apply(:_OptionallyIndentedLine) l = @result unless _tmp self.pos = _save4 break end @result = begin; a << l ; end _tmp = true unless _tmp self.pos = _save4 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save1 end unless _tmp self.pos = _save break end _text_start = self.pos while true _tmp = _BlankLine() break unless _tmp end _tmp = true if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end @result = begin; a << text ; end _tmp = true unless _tmp self.pos = _save break end @result = begin; a ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_RawNoteBlock unless _tmp return _tmp end # CodeFence = &{ github? } Ticks3 (@Sp StrChunk:format)? Spnl < ((!"`" Nonspacechar)+ | !Ticks3 /`+/ | Spacechar | @Newline)+ > Ticks3 @Sp @Newline* { verbatim = RDoc::Markup::Verbatim.new text verbatim.format = format.intern if format verbatim } def _CodeFence _save = self.pos while true # sequence _save1 = self.pos _tmp = begin; github? ; end self.pos = _save1 unless _tmp self.pos = _save break end _tmp = apply(:_Ticks3) unless _tmp self.pos = _save break end _save2 = self.pos _save3 = self.pos while true # sequence _tmp = _Sp() unless _tmp self.pos = _save3 break end _tmp = apply(:_StrChunk) format = @result unless _tmp self.pos = _save3 end break end # end sequence unless _tmp _tmp = true self.pos = _save2 end unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _text_start = self.pos _save4 = self.pos _save5 = self.pos while true # choice _save6 = self.pos _save7 = self.pos while true # sequence _save8 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save8 unless _tmp self.pos = _save7 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save7 end break end # end sequence if _tmp while true _save9 = self.pos while true # sequence _save10 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save10 unless _tmp self.pos = _save9 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save9 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save6 end break if _tmp self.pos = _save5 _save11 = self.pos while true # sequence _save12 = self.pos _tmp = apply(:_Ticks3) _tmp = _tmp ? nil : true self.pos = _save12 unless _tmp self.pos = _save11 break end _tmp = scan(/\A(?-mix:`+)/) unless _tmp self.pos = _save11 end break end # end sequence break if _tmp self.pos = _save5 _tmp = apply(:_Spacechar) break if _tmp self.pos = _save5 _tmp = _Newline() break if _tmp self.pos = _save5 break end # end choice if _tmp while true _save13 = self.pos while true # choice _save14 = self.pos _save15 = self.pos while true # sequence _save16 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save16 unless _tmp self.pos = _save15 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save15 end break end # end sequence if _tmp while true _save17 = self.pos while true # sequence _save18 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save18 unless _tmp self.pos = _save17 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save17 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save14 end break if _tmp self.pos = _save13 _save19 = self.pos while true # sequence _save20 = self.pos _tmp = apply(:_Ticks3) _tmp = _tmp ? nil : true self.pos = _save20 unless _tmp self.pos = _save19 break end _tmp = scan(/\A(?-mix:`+)/) unless _tmp self.pos = _save19 end break end # end sequence break if _tmp self.pos = _save13 _tmp = apply(:_Spacechar) break if _tmp self.pos = _save13 _tmp = _Newline() break if _tmp self.pos = _save13 break end # end choice break unless _tmp end _tmp = true else self.pos = _save4 end if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end _tmp = apply(:_Ticks3) unless _tmp self.pos = _save break end _tmp = _Sp() unless _tmp self.pos = _save break end while true _tmp = _Newline() break unless _tmp end _tmp = true unless _tmp self.pos = _save break end @result = begin; verbatim = RDoc::Markup::Verbatim.new text verbatim.format = format.intern if format verbatim ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_CodeFence unless _tmp return _tmp end # DefinitionList = &{ definition_lists? } DefinitionListItem+:list { RDoc::Markup::List.new :NOTE, *list.flatten } def _DefinitionList _save = self.pos while true # sequence _save1 = self.pos _tmp = begin; definition_lists? ; end self.pos = _save1 unless _tmp self.pos = _save break end _save2 = self.pos _ary = [] _tmp = apply(:_DefinitionListItem) if _tmp _ary << @result while true _tmp = apply(:_DefinitionListItem) _ary << @result if _tmp break unless _tmp end _tmp = true @result = _ary else self.pos = _save2 end list = @result unless _tmp self.pos = _save break end @result = begin; RDoc::Markup::List.new :NOTE, *list.flatten ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_DefinitionList unless _tmp return _tmp end # DefinitionListItem = DefinitionListLabel+:label DefinitionListDefinition+:defns { list_items = [] list_items << RDoc::Markup::ListItem.new(label, defns.shift) list_items.concat defns.map { |defn| RDoc::Markup::ListItem.new nil, defn } unless list_items.empty? list_items } def _DefinitionListItem _save = self.pos while true # sequence _save1 = self.pos _ary = [] _tmp = apply(:_DefinitionListLabel) if _tmp _ary << @result while true _tmp = apply(:_DefinitionListLabel) _ary << @result if _tmp break unless _tmp end _tmp = true @result = _ary else self.pos = _save1 end label = @result unless _tmp self.pos = _save break end _save2 = self.pos _ary = [] _tmp = apply(:_DefinitionListDefinition) if _tmp _ary << @result while true _tmp = apply(:_DefinitionListDefinition) _ary << @result if _tmp break unless _tmp end _tmp = true @result = _ary else self.pos = _save2 end defns = @result unless _tmp self.pos = _save break end @result = begin; list_items = [] list_items << RDoc::Markup::ListItem.new(label, defns.shift) list_items.concat defns.map { |defn| RDoc::Markup::ListItem.new nil, defn } unless list_items.empty? list_items ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_DefinitionListItem unless _tmp return _tmp end # DefinitionListLabel = StrChunk:label @Sp @Newline { label } def _DefinitionListLabel _save = self.pos while true # sequence _tmp = apply(:_StrChunk) label = @result unless _tmp self.pos = _save break end _tmp = _Sp() unless _tmp self.pos = _save break end _tmp = _Newline() unless _tmp self.pos = _save break end @result = begin; label ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_DefinitionListLabel unless _tmp return _tmp end # DefinitionListDefinition = @NonindentSpace ":" @Space Inlines:a @BlankLine+ { paragraph a } def _DefinitionListDefinition _save = self.pos while true # sequence _tmp = _NonindentSpace() unless _tmp self.pos = _save break end _tmp = match_string(":") unless _tmp self.pos = _save break end _tmp = _Space() unless _tmp self.pos = _save break end _tmp = apply(:_Inlines) a = @result unless _tmp self.pos = _save break end _save1 = self.pos _tmp = _BlankLine() if _tmp while true _tmp = _BlankLine() break unless _tmp end _tmp = true else self.pos = _save1 end unless _tmp self.pos = _save break end @result = begin; paragraph a ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_DefinitionListDefinition unless _tmp return _tmp end Rules = {} Rules[:_root] = rule_info("root", "Doc") Rules[:_Doc] = rule_info("Doc", "BOM? Block*:a { RDoc::Markup::Document.new(*a.compact) }") Rules[:_Block] = rule_info("Block", "@BlankLine* (BlockQuote | Verbatim | CodeFence | Note | Reference | HorizontalRule | Heading | OrderedList | BulletList | DefinitionList | HtmlBlock | StyleBlock | Para | Plain)") Rules[:_Para] = rule_info("Para", "@NonindentSpace Inlines:a @BlankLine+ { paragraph a }") Rules[:_Plain] = rule_info("Plain", "Inlines:a { paragraph a }") Rules[:_AtxInline] = rule_info("AtxInline", "!@Newline !(@Sp? /\#*/ @Sp @Newline) Inline") Rules[:_AtxStart] = rule_info("AtxStart", "< /\\\#{1,6}/ > { text.length }") Rules[:_AtxHeading] = rule_info("AtxHeading", "AtxStart:s @Sp? AtxInline+:a (@Sp? /\#*/ @Sp)? @Newline { RDoc::Markup::Heading.new(s, a.join) }") Rules[:_SetextHeading] = rule_info("SetextHeading", "(SetextHeading1 | SetextHeading2)") Rules[:_SetextBottom1] = rule_info("SetextBottom1", "/={3,}/ @Newline") Rules[:_SetextBottom2] = rule_info("SetextBottom2", "/-{3,}/ @Newline") Rules[:_SetextHeading1] = rule_info("SetextHeading1", "&(@RawLine SetextBottom1) @StartList:a (!@Endline Inline:b { a << b })+ @Sp? @Newline SetextBottom1 { RDoc::Markup::Heading.new(1, a.join) }") Rules[:_SetextHeading2] = rule_info("SetextHeading2", "&(@RawLine SetextBottom2) @StartList:a (!@Endline Inline:b { a << b })+ @Sp? @Newline SetextBottom2 { RDoc::Markup::Heading.new(2, a.join) }") Rules[:_Heading] = rule_info("Heading", "(SetextHeading | AtxHeading)") Rules[:_BlockQuote] = rule_info("BlockQuote", "BlockQuoteRaw:a { RDoc::Markup::BlockQuote.new(*a) }") Rules[:_BlockQuoteRaw] = rule_info("BlockQuoteRaw", "@StartList:a (\">\" \" \"? Line:l { a << l } (!\">\" !@BlankLine Line:c { a << c })* (@BlankLine:n { a << n })*)+ { inner_parse a.join }") Rules[:_NonblankIndentedLine] = rule_info("NonblankIndentedLine", "!@BlankLine IndentedLine") Rules[:_VerbatimChunk] = rule_info("VerbatimChunk", "@BlankLine*:a NonblankIndentedLine+:b { a.concat b }") Rules[:_Verbatim] = rule_info("Verbatim", "VerbatimChunk+:a { RDoc::Markup::Verbatim.new(*a.flatten) }") Rules[:_HorizontalRule] = rule_info("HorizontalRule", "@NonindentSpace (\"*\" @Sp \"*\" @Sp \"*\" (@Sp \"*\")* | \"-\" @Sp \"-\" @Sp \"-\" (@Sp \"-\")* | \"_\" @Sp \"_\" @Sp \"_\" (@Sp \"_\")*) @Sp @Newline @BlankLine+ { RDoc::Markup::Rule.new 1 }") Rules[:_Bullet] = rule_info("Bullet", "!HorizontalRule @NonindentSpace /[+*-]/ @Spacechar+") Rules[:_BulletList] = rule_info("BulletList", "&Bullet (ListTight | ListLoose):a { RDoc::Markup::List.new(:BULLET, *a) }") Rules[:_ListTight] = rule_info("ListTight", "ListItemTight+:a @BlankLine* !(Bullet | Enumerator) { a }") Rules[:_ListLoose] = rule_info("ListLoose", "@StartList:a (ListItem:b @BlankLine* { a << b })+ { a }") Rules[:_ListItem] = rule_info("ListItem", "(Bullet | Enumerator) @StartList:a ListBlock:b { a << b } (ListContinuationBlock:c { a.push(*c) })* { list_item_from a }") Rules[:_ListItemTight] = rule_info("ListItemTight", "(Bullet | Enumerator) ListBlock:a (!@BlankLine ListContinuationBlock:b { a.push(*b) })* !ListContinuationBlock { list_item_from a }") Rules[:_ListBlock] = rule_info("ListBlock", "!@BlankLine Line:a ListBlockLine*:c { [a, *c] }") Rules[:_ListContinuationBlock] = rule_info("ListContinuationBlock", "@StartList:a @BlankLine* { a << \"\\n\" } (Indent ListBlock:b { a.concat b })+ { a }") Rules[:_Enumerator] = rule_info("Enumerator", "@NonindentSpace [0-9]+ \".\" @Spacechar+") Rules[:_OrderedList] = rule_info("OrderedList", "&Enumerator (ListTight | ListLoose):a { RDoc::Markup::List.new(:NUMBER, *a) }") Rules[:_ListBlockLine] = rule_info("ListBlockLine", "!@BlankLine !(Indent? (Bullet | Enumerator)) !HorizontalRule OptionallyIndentedLine") Rules[:_HtmlOpenAnchor] = rule_info("HtmlOpenAnchor", "\"<\" Spnl (\"a\" | \"A\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlCloseAnchor] = rule_info("HtmlCloseAnchor", "\"<\" Spnl \"/\" (\"a\" | \"A\") Spnl \">\"") Rules[:_HtmlAnchor] = rule_info("HtmlAnchor", "HtmlOpenAnchor (HtmlAnchor | !HtmlCloseAnchor .)* HtmlCloseAnchor") Rules[:_HtmlBlockOpenAddress] = rule_info("HtmlBlockOpenAddress", "\"<\" Spnl (\"address\" | \"ADDRESS\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseAddress] = rule_info("HtmlBlockCloseAddress", "\"<\" Spnl \"/\" (\"address\" | \"ADDRESS\") Spnl \">\"") Rules[:_HtmlBlockAddress] = rule_info("HtmlBlockAddress", "HtmlBlockOpenAddress (HtmlBlockAddress | !HtmlBlockCloseAddress .)* HtmlBlockCloseAddress") Rules[:_HtmlBlockOpenBlockquote] = rule_info("HtmlBlockOpenBlockquote", "\"<\" Spnl (\"blockquote\" | \"BLOCKQUOTE\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseBlockquote] = rule_info("HtmlBlockCloseBlockquote", "\"<\" Spnl \"/\" (\"blockquote\" | \"BLOCKQUOTE\") Spnl \">\"") Rules[:_HtmlBlockBlockquote] = rule_info("HtmlBlockBlockquote", "HtmlBlockOpenBlockquote (HtmlBlockBlockquote | !HtmlBlockCloseBlockquote .)* HtmlBlockCloseBlockquote") Rules[:_HtmlBlockOpenCenter] = rule_info("HtmlBlockOpenCenter", "\"<\" Spnl (\"center\" | \"CENTER\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseCenter] = rule_info("HtmlBlockCloseCenter", "\"<\" Spnl \"/\" (\"center\" | \"CENTER\") Spnl \">\"") Rules[:_HtmlBlockCenter] = rule_info("HtmlBlockCenter", "HtmlBlockOpenCenter (HtmlBlockCenter | !HtmlBlockCloseCenter .)* HtmlBlockCloseCenter") Rules[:_HtmlBlockOpenDir] = rule_info("HtmlBlockOpenDir", "\"<\" Spnl (\"dir\" | \"DIR\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseDir] = rule_info("HtmlBlockCloseDir", "\"<\" Spnl \"/\" (\"dir\" | \"DIR\") Spnl \">\"") Rules[:_HtmlBlockDir] = rule_info("HtmlBlockDir", "HtmlBlockOpenDir (HtmlBlockDir | !HtmlBlockCloseDir .)* HtmlBlockCloseDir") Rules[:_HtmlBlockOpenDiv] = rule_info("HtmlBlockOpenDiv", "\"<\" Spnl (\"div\" | \"DIV\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseDiv] = rule_info("HtmlBlockCloseDiv", "\"<\" Spnl \"/\" (\"div\" | \"DIV\") Spnl \">\"") Rules[:_HtmlBlockDiv] = rule_info("HtmlBlockDiv", "HtmlBlockOpenDiv (HtmlBlockDiv | !HtmlBlockCloseDiv .)* HtmlBlockCloseDiv") Rules[:_HtmlBlockOpenDl] = rule_info("HtmlBlockOpenDl", "\"<\" Spnl (\"dl\" | \"DL\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseDl] = rule_info("HtmlBlockCloseDl", "\"<\" Spnl \"/\" (\"dl\" | \"DL\") Spnl \">\"") Rules[:_HtmlBlockDl] = rule_info("HtmlBlockDl", "HtmlBlockOpenDl (HtmlBlockDl | !HtmlBlockCloseDl .)* HtmlBlockCloseDl") Rules[:_HtmlBlockOpenFieldset] = rule_info("HtmlBlockOpenFieldset", "\"<\" Spnl (\"fieldset\" | \"FIELDSET\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseFieldset] = rule_info("HtmlBlockCloseFieldset", "\"<\" Spnl \"/\" (\"fieldset\" | \"FIELDSET\") Spnl \">\"") Rules[:_HtmlBlockFieldset] = rule_info("HtmlBlockFieldset", "HtmlBlockOpenFieldset (HtmlBlockFieldset | !HtmlBlockCloseFieldset .)* HtmlBlockCloseFieldset") Rules[:_HtmlBlockOpenForm] = rule_info("HtmlBlockOpenForm", "\"<\" Spnl (\"form\" | \"FORM\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseForm] = rule_info("HtmlBlockCloseForm", "\"<\" Spnl \"/\" (\"form\" | \"FORM\") Spnl \">\"") Rules[:_HtmlBlockForm] = rule_info("HtmlBlockForm", "HtmlBlockOpenForm (HtmlBlockForm | !HtmlBlockCloseForm .)* HtmlBlockCloseForm") Rules[:_HtmlBlockOpenH1] = rule_info("HtmlBlockOpenH1", "\"<\" Spnl (\"h1\" | \"H1\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseH1] = rule_info("HtmlBlockCloseH1", "\"<\" Spnl \"/\" (\"h1\" | \"H1\") Spnl \">\"") Rules[:_HtmlBlockH1] = rule_info("HtmlBlockH1", "HtmlBlockOpenH1 (HtmlBlockH1 | !HtmlBlockCloseH1 .)* HtmlBlockCloseH1") Rules[:_HtmlBlockOpenH2] = rule_info("HtmlBlockOpenH2", "\"<\" Spnl (\"h2\" | \"H2\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseH2] = rule_info("HtmlBlockCloseH2", "\"<\" Spnl \"/\" (\"h2\" | \"H2\") Spnl \">\"") Rules[:_HtmlBlockH2] = rule_info("HtmlBlockH2", "HtmlBlockOpenH2 (HtmlBlockH2 | !HtmlBlockCloseH2 .)* HtmlBlockCloseH2") Rules[:_HtmlBlockOpenH3] = rule_info("HtmlBlockOpenH3", "\"<\" Spnl (\"h3\" | \"H3\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseH3] = rule_info("HtmlBlockCloseH3", "\"<\" Spnl \"/\" (\"h3\" | \"H3\") Spnl \">\"") Rules[:_HtmlBlockH3] = rule_info("HtmlBlockH3", "HtmlBlockOpenH3 (HtmlBlockH3 | !HtmlBlockCloseH3 .)* HtmlBlockCloseH3") Rules[:_HtmlBlockOpenH4] = rule_info("HtmlBlockOpenH4", "\"<\" Spnl (\"h4\" | \"H4\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseH4] = rule_info("HtmlBlockCloseH4", "\"<\" Spnl \"/\" (\"h4\" | \"H4\") Spnl \">\"") Rules[:_HtmlBlockH4] = rule_info("HtmlBlockH4", "HtmlBlockOpenH4 (HtmlBlockH4 | !HtmlBlockCloseH4 .)* HtmlBlockCloseH4") Rules[:_HtmlBlockOpenH5] = rule_info("HtmlBlockOpenH5", "\"<\" Spnl (\"h5\" | \"H5\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseH5] = rule_info("HtmlBlockCloseH5", "\"<\" Spnl \"/\" (\"h5\" | \"H5\") Spnl \">\"") Rules[:_HtmlBlockH5] = rule_info("HtmlBlockH5", "HtmlBlockOpenH5 (HtmlBlockH5 | !HtmlBlockCloseH5 .)* HtmlBlockCloseH5") Rules[:_HtmlBlockOpenH6] = rule_info("HtmlBlockOpenH6", "\"<\" Spnl (\"h6\" | \"H6\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseH6] = rule_info("HtmlBlockCloseH6", "\"<\" Spnl \"/\" (\"h6\" | \"H6\") Spnl \">\"") Rules[:_HtmlBlockH6] = rule_info("HtmlBlockH6", "HtmlBlockOpenH6 (HtmlBlockH6 | !HtmlBlockCloseH6 .)* HtmlBlockCloseH6") Rules[:_HtmlBlockOpenMenu] = rule_info("HtmlBlockOpenMenu", "\"<\" Spnl (\"menu\" | \"MENU\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseMenu] = rule_info("HtmlBlockCloseMenu", "\"<\" Spnl \"/\" (\"menu\" | \"MENU\") Spnl \">\"") Rules[:_HtmlBlockMenu] = rule_info("HtmlBlockMenu", "HtmlBlockOpenMenu (HtmlBlockMenu | !HtmlBlockCloseMenu .)* HtmlBlockCloseMenu") Rules[:_HtmlBlockOpenNoframes] = rule_info("HtmlBlockOpenNoframes", "\"<\" Spnl (\"noframes\" | \"NOFRAMES\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseNoframes] = rule_info("HtmlBlockCloseNoframes", "\"<\" Spnl \"/\" (\"noframes\" | \"NOFRAMES\") Spnl \">\"") Rules[:_HtmlBlockNoframes] = rule_info("HtmlBlockNoframes", "HtmlBlockOpenNoframes (HtmlBlockNoframes | !HtmlBlockCloseNoframes .)* HtmlBlockCloseNoframes") Rules[:_HtmlBlockOpenNoscript] = rule_info("HtmlBlockOpenNoscript", "\"<\" Spnl (\"noscript\" | \"NOSCRIPT\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseNoscript] = rule_info("HtmlBlockCloseNoscript", "\"<\" Spnl \"/\" (\"noscript\" | \"NOSCRIPT\") Spnl \">\"") Rules[:_HtmlBlockNoscript] = rule_info("HtmlBlockNoscript", "HtmlBlockOpenNoscript (HtmlBlockNoscript | !HtmlBlockCloseNoscript .)* HtmlBlockCloseNoscript") Rules[:_HtmlBlockOpenOl] = rule_info("HtmlBlockOpenOl", "\"<\" Spnl (\"ol\" | \"OL\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseOl] = rule_info("HtmlBlockCloseOl", "\"<\" Spnl \"/\" (\"ol\" | \"OL\") Spnl \">\"") Rules[:_HtmlBlockOl] = rule_info("HtmlBlockOl", "HtmlBlockOpenOl (HtmlBlockOl | !HtmlBlockCloseOl .)* HtmlBlockCloseOl") Rules[:_HtmlBlockOpenP] = rule_info("HtmlBlockOpenP", "\"<\" Spnl (\"p\" | \"P\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseP] = rule_info("HtmlBlockCloseP", "\"<\" Spnl \"/\" (\"p\" | \"P\") Spnl \">\"") Rules[:_HtmlBlockP] = rule_info("HtmlBlockP", "HtmlBlockOpenP (HtmlBlockP | !HtmlBlockCloseP .)* HtmlBlockCloseP") Rules[:_HtmlBlockOpenPre] = rule_info("HtmlBlockOpenPre", "\"<\" Spnl (\"pre\" | \"PRE\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockClosePre] = rule_info("HtmlBlockClosePre", "\"<\" Spnl \"/\" (\"pre\" | \"PRE\") Spnl \">\"") Rules[:_HtmlBlockPre] = rule_info("HtmlBlockPre", "HtmlBlockOpenPre (HtmlBlockPre | !HtmlBlockClosePre .)* HtmlBlockClosePre") Rules[:_HtmlBlockOpenTable] = rule_info("HtmlBlockOpenTable", "\"<\" Spnl (\"table\" | \"TABLE\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseTable] = rule_info("HtmlBlockCloseTable", "\"<\" Spnl \"/\" (\"table\" | \"TABLE\") Spnl \">\"") Rules[:_HtmlBlockTable] = rule_info("HtmlBlockTable", "HtmlBlockOpenTable (HtmlBlockTable | !HtmlBlockCloseTable .)* HtmlBlockCloseTable") Rules[:_HtmlBlockOpenUl] = rule_info("HtmlBlockOpenUl", "\"<\" Spnl (\"ul\" | \"UL\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseUl] = rule_info("HtmlBlockCloseUl", "\"<\" Spnl \"/\" (\"ul\" | \"UL\") Spnl \">\"") Rules[:_HtmlBlockUl] = rule_info("HtmlBlockUl", "HtmlBlockOpenUl (HtmlBlockUl | !HtmlBlockCloseUl .)* HtmlBlockCloseUl") Rules[:_HtmlBlockOpenDd] = rule_info("HtmlBlockOpenDd", "\"<\" Spnl (\"dd\" | \"DD\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseDd] = rule_info("HtmlBlockCloseDd", "\"<\" Spnl \"/\" (\"dd\" | \"DD\") Spnl \">\"") Rules[:_HtmlBlockDd] = rule_info("HtmlBlockDd", "HtmlBlockOpenDd (HtmlBlockDd | !HtmlBlockCloseDd .)* HtmlBlockCloseDd") Rules[:_HtmlBlockOpenDt] = rule_info("HtmlBlockOpenDt", "\"<\" Spnl (\"dt\" | \"DT\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseDt] = rule_info("HtmlBlockCloseDt", "\"<\" Spnl \"/\" (\"dt\" | \"DT\") Spnl \">\"") Rules[:_HtmlBlockDt] = rule_info("HtmlBlockDt", "HtmlBlockOpenDt (HtmlBlockDt | !HtmlBlockCloseDt .)* HtmlBlockCloseDt") Rules[:_HtmlBlockOpenFrameset] = rule_info("HtmlBlockOpenFrameset", "\"<\" Spnl (\"frameset\" | \"FRAMESET\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseFrameset] = rule_info("HtmlBlockCloseFrameset", "\"<\" Spnl \"/\" (\"frameset\" | \"FRAMESET\") Spnl \">\"") Rules[:_HtmlBlockFrameset] = rule_info("HtmlBlockFrameset", "HtmlBlockOpenFrameset (HtmlBlockFrameset | !HtmlBlockCloseFrameset .)* HtmlBlockCloseFrameset") Rules[:_HtmlBlockOpenLi] = rule_info("HtmlBlockOpenLi", "\"<\" Spnl (\"li\" | \"LI\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseLi] = rule_info("HtmlBlockCloseLi", "\"<\" Spnl \"/\" (\"li\" | \"LI\") Spnl \">\"") Rules[:_HtmlBlockLi] = rule_info("HtmlBlockLi", "HtmlBlockOpenLi (HtmlBlockLi | !HtmlBlockCloseLi .)* HtmlBlockCloseLi") Rules[:_HtmlBlockOpenTbody] = rule_info("HtmlBlockOpenTbody", "\"<\" Spnl (\"tbody\" | \"TBODY\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseTbody] = rule_info("HtmlBlockCloseTbody", "\"<\" Spnl \"/\" (\"tbody\" | \"TBODY\") Spnl \">\"") Rules[:_HtmlBlockTbody] = rule_info("HtmlBlockTbody", "HtmlBlockOpenTbody (HtmlBlockTbody | !HtmlBlockCloseTbody .)* HtmlBlockCloseTbody") Rules[:_HtmlBlockOpenTd] = rule_info("HtmlBlockOpenTd", "\"<\" Spnl (\"td\" | \"TD\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseTd] = rule_info("HtmlBlockCloseTd", "\"<\" Spnl \"/\" (\"td\" | \"TD\") Spnl \">\"") Rules[:_HtmlBlockTd] = rule_info("HtmlBlockTd", "HtmlBlockOpenTd (HtmlBlockTd | !HtmlBlockCloseTd .)* HtmlBlockCloseTd") Rules[:_HtmlBlockOpenTfoot] = rule_info("HtmlBlockOpenTfoot", "\"<\" Spnl (\"tfoot\" | \"TFOOT\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseTfoot] = rule_info("HtmlBlockCloseTfoot", "\"<\" Spnl \"/\" (\"tfoot\" | \"TFOOT\") Spnl \">\"") Rules[:_HtmlBlockTfoot] = rule_info("HtmlBlockTfoot", "HtmlBlockOpenTfoot (HtmlBlockTfoot | !HtmlBlockCloseTfoot .)* HtmlBlockCloseTfoot") Rules[:_HtmlBlockOpenTh] = rule_info("HtmlBlockOpenTh", "\"<\" Spnl (\"th\" | \"TH\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseTh] = rule_info("HtmlBlockCloseTh", "\"<\" Spnl \"/\" (\"th\" | \"TH\") Spnl \">\"") Rules[:_HtmlBlockTh] = rule_info("HtmlBlockTh", "HtmlBlockOpenTh (HtmlBlockTh | !HtmlBlockCloseTh .)* HtmlBlockCloseTh") Rules[:_HtmlBlockOpenThead] = rule_info("HtmlBlockOpenThead", "\"<\" Spnl (\"thead\" | \"THEAD\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseThead] = rule_info("HtmlBlockCloseThead", "\"<\" Spnl \"/\" (\"thead\" | \"THEAD\") Spnl \">\"") Rules[:_HtmlBlockThead] = rule_info("HtmlBlockThead", "HtmlBlockOpenThead (HtmlBlockThead | !HtmlBlockCloseThead .)* HtmlBlockCloseThead") Rules[:_HtmlBlockOpenTr] = rule_info("HtmlBlockOpenTr", "\"<\" Spnl (\"tr\" | \"TR\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseTr] = rule_info("HtmlBlockCloseTr", "\"<\" Spnl \"/\" (\"tr\" | \"TR\") Spnl \">\"") Rules[:_HtmlBlockTr] = rule_info("HtmlBlockTr", "HtmlBlockOpenTr (HtmlBlockTr | !HtmlBlockCloseTr .)* HtmlBlockCloseTr") Rules[:_HtmlBlockOpenScript] = rule_info("HtmlBlockOpenScript", "\"<\" Spnl (\"script\" | \"SCRIPT\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseScript] = rule_info("HtmlBlockCloseScript", "\"<\" Spnl \"/\" (\"script\" | \"SCRIPT\") Spnl \">\"") Rules[:_HtmlBlockScript] = rule_info("HtmlBlockScript", "HtmlBlockOpenScript (!HtmlBlockCloseScript .)* HtmlBlockCloseScript") Rules[:_HtmlBlockInTags] = rule_info("HtmlBlockInTags", "(HtmlAnchor | HtmlBlockAddress | HtmlBlockBlockquote | HtmlBlockCenter | HtmlBlockDir | HtmlBlockDiv | HtmlBlockDl | HtmlBlockFieldset | HtmlBlockForm | HtmlBlockH1 | HtmlBlockH2 | HtmlBlockH3 | HtmlBlockH4 | HtmlBlockH5 | HtmlBlockH6 | HtmlBlockMenu | HtmlBlockNoframes | HtmlBlockNoscript | HtmlBlockOl | HtmlBlockP | HtmlBlockPre | HtmlBlockTable | HtmlBlockUl | HtmlBlockDd | HtmlBlockDt | HtmlBlockFrameset | HtmlBlockLi | HtmlBlockTbody | HtmlBlockTd | HtmlBlockTfoot | HtmlBlockTh | HtmlBlockThead | HtmlBlockTr | HtmlBlockScript)") Rules[:_HtmlBlock] = rule_info("HtmlBlock", "< (HtmlBlockInTags | HtmlComment | HtmlBlockSelfClosing | HtmlUnclosed) > @BlankLine+ { if html? then RDoc::Markup::Raw.new text end }") Rules[:_HtmlUnclosed] = rule_info("HtmlUnclosed", "\"<\" Spnl HtmlUnclosedType Spnl HtmlAttribute* Spnl \">\"") Rules[:_HtmlUnclosedType] = rule_info("HtmlUnclosedType", "(\"HR\" | \"hr\")") Rules[:_HtmlBlockSelfClosing] = rule_info("HtmlBlockSelfClosing", "\"<\" Spnl HtmlBlockType Spnl HtmlAttribute* \"/\" Spnl \">\"") Rules[:_HtmlBlockType] = rule_info("HtmlBlockType", "(\"ADDRESS\" | \"BLOCKQUOTE\" | \"CENTER\" | \"DD\" | \"DIR\" | \"DIV\" | \"DL\" | \"DT\" | \"FIELDSET\" | \"FORM\" | \"FRAMESET\" | \"H1\" | \"H2\" | \"H3\" | \"H4\" | \"H5\" | \"H6\" | \"HR\" | \"ISINDEX\" | \"LI\" | \"MENU\" | \"NOFRAMES\" | \"NOSCRIPT\" | \"OL\" | \"P\" | \"PRE\" | \"SCRIPT\" | \"TABLE\" | \"TBODY\" | \"TD\" | \"TFOOT\" | \"TH\" | \"THEAD\" | \"TR\" | \"UL\" | \"address\" | \"blockquote\" | \"center\" | \"dd\" | \"dir\" | \"div\" | \"dl\" | \"dt\" | \"fieldset\" | \"form\" | \"frameset\" | \"h1\" | \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"h6\" | \"hr\" | \"isindex\" | \"li\" | \"menu\" | \"noframes\" | \"noscript\" | \"ol\" | \"p\" | \"pre\" | \"script\" | \"table\" | \"tbody\" | \"td\" | \"tfoot\" | \"th\" | \"thead\" | \"tr\" | \"ul\")") Rules[:_StyleOpen] = rule_info("StyleOpen", "\"<\" Spnl (\"style\" | \"STYLE\") Spnl HtmlAttribute* \">\"") Rules[:_StyleClose] = rule_info("StyleClose", "\"<\" Spnl \"/\" (\"style\" | \"STYLE\") Spnl \">\"") Rules[:_InStyleTags] = rule_info("InStyleTags", "StyleOpen (!StyleClose .)* StyleClose") Rules[:_StyleBlock] = rule_info("StyleBlock", "< InStyleTags > @BlankLine* { if css? then RDoc::Markup::Raw.new text end }") Rules[:_Inlines] = rule_info("Inlines", "(!@Endline Inline:i { i } | @Endline:c &Inline { c })+:chunks @Endline? { chunks }") Rules[:_Inline] = rule_info("Inline", "(Str | @Endline | UlOrStarLine | @Space | Strong | Emph | Image | Link | NoteReference | InlineNote | Code | RawHtml | Entity | EscapedChar | Symbol)") Rules[:_Space] = rule_info("Space", "@Spacechar+ { \" \" }") Rules[:_Str] = rule_info("Str", "@StartList:a < @NormalChar+ > { a = text } (StrChunk:c { a << c })* { a }") Rules[:_StrChunk] = rule_info("StrChunk", "< (@NormalChar | /_+/ &Alphanumeric)+ > { text }") Rules[:_EscapedChar] = rule_info("EscapedChar", "\"\\\\\" !@Newline < /[:\\\\`|*_{}\\[\\]()\#+.!><-]/ > { text }") Rules[:_Entity] = rule_info("Entity", "(HexEntity | DecEntity | CharEntity):a { a }") Rules[:_Endline] = rule_info("Endline", "(@LineBreak | @TerminalEndline | @NormalEndline)") Rules[:_NormalEndline] = rule_info("NormalEndline", "@Sp @Newline !@BlankLine !\">\" !AtxStart !(Line /={3,}|-{3,}=/ @Newline) { \"\\n\" }") Rules[:_TerminalEndline] = rule_info("TerminalEndline", "@Sp @Newline @Eof") Rules[:_LineBreak] = rule_info("LineBreak", "\" \" @NormalEndline { RDoc::Markup::HardBreak.new }") Rules[:_Symbol] = rule_info("Symbol", "< @SpecialChar > { text }") Rules[:_UlOrStarLine] = rule_info("UlOrStarLine", "(UlLine | StarLine):a { a }") Rules[:_StarLine] = rule_info("StarLine", "(< /\\*{4,}/ > { text } | < @Spacechar /\\*+/ &@Spacechar > { text })") Rules[:_UlLine] = rule_info("UlLine", "(< /_{4,}/ > { text } | < @Spacechar /_+/ &@Spacechar > { text })") Rules[:_Emph] = rule_info("Emph", "(EmphStar | EmphUl)") Rules[:_OneStarOpen] = rule_info("OneStarOpen", "!StarLine \"*\" !@Spacechar !@Newline") Rules[:_OneStarClose] = rule_info("OneStarClose", "!@Spacechar !@Newline Inline:a \"*\" { a }") Rules[:_EmphStar] = rule_info("EmphStar", "OneStarOpen @StartList:a (!OneStarClose Inline:l { a << l })* OneStarClose:l { a << l } { emphasis a.join }") Rules[:_OneUlOpen] = rule_info("OneUlOpen", "!UlLine \"_\" !@Spacechar !@Newline") Rules[:_OneUlClose] = rule_info("OneUlClose", "!@Spacechar !@Newline Inline:a \"_\" { a }") Rules[:_EmphUl] = rule_info("EmphUl", "OneUlOpen @StartList:a (!OneUlClose Inline:l { a << l })* OneUlClose:l { a << l } { emphasis a.join }") Rules[:_Strong] = rule_info("Strong", "(StrongStar | StrongUl)") Rules[:_TwoStarOpen] = rule_info("TwoStarOpen", "!StarLine \"**\" !@Spacechar !@Newline") Rules[:_TwoStarClose] = rule_info("TwoStarClose", "!@Spacechar !@Newline Inline:a \"**\" { a }") Rules[:_StrongStar] = rule_info("StrongStar", "TwoStarOpen @StartList:a (!TwoStarClose Inline:l { a << l })* TwoStarClose:l { a << l } { strong a.join }") Rules[:_TwoUlOpen] = rule_info("TwoUlOpen", "!UlLine \"__\" !@Spacechar !@Newline") Rules[:_TwoUlClose] = rule_info("TwoUlClose", "!@Spacechar !@Newline Inline:a \"__\" { a }") Rules[:_StrongUl] = rule_info("StrongUl", "TwoUlOpen @StartList:a (!TwoUlClose Inline:i { a << i })* TwoUlClose:l { a << l } { strong a.join }") Rules[:_Image] = rule_info("Image", "\"!\" (ExplicitLink | ReferenceLink):a { \"rdoc-image:\#{a[/\\[(.*)\\]/, 1]}\" }") Rules[:_Link] = rule_info("Link", "(ExplicitLink | ReferenceLink | AutoLink)") Rules[:_ReferenceLink] = rule_info("ReferenceLink", "(ReferenceLinkDouble | ReferenceLinkSingle)") Rules[:_ReferenceLinkDouble] = rule_info("ReferenceLinkDouble", "Label:content < Spnl > !\"[]\" Label:label { link_to content, label, text }") Rules[:_ReferenceLinkSingle] = rule_info("ReferenceLinkSingle", "Label:content < (Spnl \"[]\")? > { link_to content, content, text }") Rules[:_ExplicitLink] = rule_info("ExplicitLink", "Label:l Spnl \"(\" @Sp Source:s Spnl Title @Sp \")\" { \"{\#{l}}[\#{s}]\" }") Rules[:_Source] = rule_info("Source", "(\"<\" < SourceContents > \">\" | < SourceContents >) { text }") Rules[:_SourceContents] = rule_info("SourceContents", "(((!\"(\" !\")\" !\">\" Nonspacechar)+ | \"(\" SourceContents \")\")* | \"\")") Rules[:_Title] = rule_info("Title", "(TitleSingle | TitleDouble | \"\"):a { a }") Rules[:_TitleSingle] = rule_info("TitleSingle", "\"'\" (!(\"'\" @Sp (\")\" | @Newline)) .)* \"'\"") Rules[:_TitleDouble] = rule_info("TitleDouble", "\"\\\"\" (!(\"\\\"\" @Sp (\")\" | @Newline)) .)* \"\\\"\"") Rules[:_AutoLink] = rule_info("AutoLink", "(AutoLinkUrl | AutoLinkEmail)") Rules[:_AutoLinkUrl] = rule_info("AutoLinkUrl", "\"<\" < /[A-Za-z]+/ \"://\" (!@Newline !\">\" .)+ > \">\" { text }") Rules[:_AutoLinkEmail] = rule_info("AutoLinkEmail", "\"<\" \"mailto:\"? < /[\\w+.\\/!%~$-]+/i \"@\" (!@Newline !\">\" .)+ > \">\" { \"mailto:\#{text}\" }") Rules[:_Reference] = rule_info("Reference", "@NonindentSpace !\"[]\" Label:label \":\" Spnl RefSrc:link RefTitle @BlankLine+ { \# TODO use title reference label, link nil }") Rules[:_Label] = rule_info("Label", "\"[\" (!\"^\" &{ notes? } | &. &{ !notes? }) @StartList:a (!\"]\" Inline:l { a << l })* \"]\" { a.join.gsub(/\\s+/, ' ') }") Rules[:_RefSrc] = rule_info("RefSrc", "< Nonspacechar+ > { text }") Rules[:_RefTitle] = rule_info("RefTitle", "(RefTitleSingle | RefTitleDouble | RefTitleParens | EmptyTitle)") Rules[:_EmptyTitle] = rule_info("EmptyTitle", "\"\"") Rules[:_RefTitleSingle] = rule_info("RefTitleSingle", "Spnl \"'\" < (!(\"'\" @Sp @Newline | @Newline) .)* > \"'\" { text }") Rules[:_RefTitleDouble] = rule_info("RefTitleDouble", "Spnl \"\\\"\" < (!(\"\\\"\" @Sp @Newline | @Newline) .)* > \"\\\"\" { text }") Rules[:_RefTitleParens] = rule_info("RefTitleParens", "Spnl \"(\" < (!(\")\" @Sp @Newline | @Newline) .)* > \")\" { text }") Rules[:_References] = rule_info("References", "(Reference | SkipBlock)*") Rules[:_Ticks1] = rule_info("Ticks1", "\"`\" !\"`\"") Rules[:_Ticks2] = rule_info("Ticks2", "\"``\" !\"`\"") Rules[:_Ticks3] = rule_info("Ticks3", "\"```\" !\"`\"") Rules[:_Ticks4] = rule_info("Ticks4", "\"````\" !\"`\"") Rules[:_Ticks5] = rule_info("Ticks5", "\"`````\" !\"`\"") Rules[:_Code] = rule_info("Code", "(Ticks1 @Sp < ((!\"`\" Nonspacechar)+ | !Ticks1 /`+/ | !(@Sp Ticks1) (@Spacechar | @Newline !@BlankLine))+ > @Sp Ticks1 | Ticks2 @Sp < ((!\"`\" Nonspacechar)+ | !Ticks2 /`+/ | !(@Sp Ticks2) (@Spacechar | @Newline !@BlankLine))+ > @Sp Ticks2 | Ticks3 @Sp < ((!\"`\" Nonspacechar)+ | !Ticks3 /`+/ | !(@Sp Ticks3) (@Spacechar | @Newline !@BlankLine))+ > @Sp Ticks3 | Ticks4 @Sp < ((!\"`\" Nonspacechar)+ | !Ticks4 /`+/ | !(@Sp Ticks4) (@Spacechar | @Newline !@BlankLine))+ > @Sp Ticks4 | Ticks5 @Sp < ((!\"`\" Nonspacechar)+ | !Ticks5 /`+/ | !(@Sp Ticks5) (@Spacechar | @Newline !@BlankLine))+ > @Sp Ticks5) { \"\#{text}\" }") Rules[:_RawHtml] = rule_info("RawHtml", "< (HtmlComment | HtmlBlockScript | HtmlTag) > { if html? then text else '' end }") Rules[:_BlankLine] = rule_info("BlankLine", "@Sp @Newline { \"\\n\" }") Rules[:_Quoted] = rule_info("Quoted", "(\"\\\"\" (!\"\\\"\" .)* \"\\\"\" | \"'\" (!\"'\" .)* \"'\")") Rules[:_HtmlAttribute] = rule_info("HtmlAttribute", "(AlphanumericAscii | \"-\")+ Spnl (\"=\" Spnl (Quoted | (!\">\" Nonspacechar)+))? Spnl") Rules[:_HtmlComment] = rule_info("HtmlComment", "\"\" .)* \"-->\"") Rules[:_HtmlTag] = rule_info("HtmlTag", "\"<\" Spnl \"/\"? AlphanumericAscii+ Spnl HtmlAttribute* \"/\"? Spnl \">\"") Rules[:_Eof] = rule_info("Eof", "!.") Rules[:_Nonspacechar] = rule_info("Nonspacechar", "!@Spacechar !@Newline .") Rules[:_Sp] = rule_info("Sp", "@Spacechar*") Rules[:_Spnl] = rule_info("Spnl", "@Sp (@Newline @Sp)?") Rules[:_SpecialChar] = rule_info("SpecialChar", "(/[*_`&\\[\\]() \";\" { [text.to_i(16)].pack 'U' }") Rules[:_DecEntity] = rule_info("DecEntity", "\"&\#\" < /[0-9]+/ > \";\" { [text.to_i].pack 'U' }") Rules[:_CharEntity] = rule_info("CharEntity", "\"&\" < /[A-Za-z0-9]+/ > \";\" { if entity = HTML_ENTITIES[text] then entity.pack 'U*' else \"&\#{text};\" end }") Rules[:_NonindentSpace] = rule_info("NonindentSpace", "/ {0,3}/") Rules[:_Indent] = rule_info("Indent", "/\\t| /") Rules[:_IndentedLine] = rule_info("IndentedLine", "Indent Line") Rules[:_OptionallyIndentedLine] = rule_info("OptionallyIndentedLine", "Indent? Line") Rules[:_StartList] = rule_info("StartList", "&. { [] }") Rules[:_Line] = rule_info("Line", "@RawLine:a { a }") Rules[:_RawLine] = rule_info("RawLine", "(< (!\"\\r\" !\"\\n\" .)* @Newline > | < .+ > @Eof) { text }") Rules[:_SkipBlock] = rule_info("SkipBlock", "(HtmlBlock | (!\"\#\" !SetextBottom1 !SetextBottom2 !@BlankLine @RawLine)+ @BlankLine* | @BlankLine+ | @RawLine)") Rules[:_ExtendedSpecialChar] = rule_info("ExtendedSpecialChar", "&{ notes? } \"^\"") Rules[:_NoteReference] = rule_info("NoteReference", "&{ notes? } RawNoteReference:ref { note_for ref }") Rules[:_RawNoteReference] = rule_info("RawNoteReference", "\"[^\" < (!@Newline !\"]\" .)+ > \"]\" { text }") Rules[:_Note] = rule_info("Note", "&{ notes? } @NonindentSpace RawNoteReference:ref \":\" @Sp @StartList:a RawNoteBlock:i { a.concat i } (&Indent RawNoteBlock:i { a.concat i })* { @footnotes[ref] = paragraph a nil }") Rules[:_InlineNote] = rule_info("InlineNote", "&{ notes? } \"^[\" @StartList:a (!\"]\" Inline:l { a << l })+ \"]\" { ref = [:inline, @note_order.length] @footnotes[ref] = paragraph a note_for ref }") Rules[:_Notes] = rule_info("Notes", "(Note | SkipBlock)*") Rules[:_RawNoteBlock] = rule_info("RawNoteBlock", "@StartList:a (!@BlankLine OptionallyIndentedLine:l { a << l })+ < @BlankLine* > { a << text } { a }") Rules[:_CodeFence] = rule_info("CodeFence", "&{ github? } Ticks3 (@Sp StrChunk:format)? Spnl < ((!\"`\" Nonspacechar)+ | !Ticks3 /`+/ | Spacechar | @Newline)+ > Ticks3 @Sp @Newline* { verbatim = RDoc::Markup::Verbatim.new text verbatim.format = format.intern if format verbatim }") Rules[:_DefinitionList] = rule_info("DefinitionList", "&{ definition_lists? } DefinitionListItem+:list { RDoc::Markup::List.new :NOTE, *list.flatten }") Rules[:_DefinitionListItem] = rule_info("DefinitionListItem", "DefinitionListLabel+:label DefinitionListDefinition+:defns { list_items = [] list_items << RDoc::Markup::ListItem.new(label, defns.shift) list_items.concat defns.map { |defn| RDoc::Markup::ListItem.new nil, defn } unless list_items.empty? list_items }") Rules[:_DefinitionListLabel] = rule_info("DefinitionListLabel", "StrChunk:label @Sp @Newline { label }") Rules[:_DefinitionListDefinition] = rule_info("DefinitionListDefinition", "@NonindentSpace \":\" @Space Inlines:a @BlankLine+ { paragraph a }") # :startdoc: end PK!Zs׻ 2.2.0/rdoc/token_stream.rbnu[## # A TokenStream is a list of tokens, gathered during the parse of some entity # (say a method). Entities populate these streams by being registered with the # lexer. Any class can collect tokens by including TokenStream. From the # outside, you use such an object by calling the start_collecting_tokens # method, followed by calls to add_token and pop_token. module RDoc::TokenStream ## # Converts +token_stream+ to HTML wrapping various tokens with # elements. The following tokens types are wrapped in spans # with the given class names: # # TkCONSTANT :: 'ruby-constant' # TkKW :: 'ruby-keyword' # TkIVAR :: 'ruby-ivar' # TkOp :: 'ruby-operator' # TkId :: 'ruby-identifier' # TkNode :: 'ruby-node' # TkCOMMENT :: 'ruby-comment' # TkREGEXP :: 'ruby-regexp' # TkSTRING :: 'ruby-string' # TkVal :: 'ruby-value' # # Other token types are not wrapped in spans. def self.to_html token_stream token_stream.map do |t| next unless t style = case t when RDoc::RubyToken::TkCONSTANT then 'ruby-constant' when RDoc::RubyToken::TkKW then 'ruby-keyword' when RDoc::RubyToken::TkIVAR then 'ruby-ivar' when RDoc::RubyToken::TkOp then 'ruby-operator' when RDoc::RubyToken::TkId then 'ruby-identifier' when RDoc::RubyToken::TkNode then 'ruby-node' when RDoc::RubyToken::TkCOMMENT then 'ruby-comment' when RDoc::RubyToken::TkREGEXP then 'ruby-regexp' when RDoc::RubyToken::TkSTRING then 'ruby-string' when RDoc::RubyToken::TkVal then 'ruby-value' end text = CGI.escapeHTML t.text if style then "#{text}" else text end end.join end ## # Adds +tokens+ to the collected tokens def add_tokens(*tokens) tokens.flatten.each { |token| @token_stream << token } end alias add_token add_tokens ## # Starts collecting tokens def collect_tokens @token_stream = [] end alias start_collecting_tokens collect_tokens ## # Remove the last token from the collected tokens def pop_token @token_stream.pop end ## # Current token stream def token_stream @token_stream end ## # Returns a string representation of the token stream def tokens_to_s token_stream.compact.map { |token| token.text }.join '' end end PK! [h42.2.0/rdoc/top_level.rbnu[## # A TopLevel context is a representation of the contents of a single file class RDoc::TopLevel < RDoc::Context MARSHAL_VERSION = 0 # :nodoc: ## # This TopLevel's File::Stat struct attr_accessor :file_stat ## # Relative name of this file attr_accessor :relative_name ## # Absolute name of this file attr_accessor :absolute_name ## # All the classes or modules that were declared in # this file. These are assigned to either +#classes_hash+ # or +#modules_hash+ once we know what they really are. attr_reader :classes_or_modules attr_accessor :diagram # :nodoc: ## # The parser class that processed this file attr_accessor :parser ## # Creates a new TopLevel for the file at +absolute_name+. If documentation # is being generated outside the source dir +relative_name+ is relative to # the source directory. def initialize absolute_name, relative_name = absolute_name super() @name = nil @absolute_name = absolute_name @relative_name = relative_name @file_stat = File.stat(absolute_name) rescue nil # HACK for testing @diagram = nil @parser = nil @classes_or_modules = [] end ## # An RDoc::TopLevel is equal to another with the same relative_name def == other self.class === other and @relative_name == other.relative_name end alias eql? == ## # Adds +an_alias+ to +Object+ instead of +self+. def add_alias(an_alias) object_class.record_location self return an_alias unless @document_self object_class.add_alias an_alias end ## # Adds +constant+ to +Object+ instead of +self+. def add_constant constant object_class.record_location self return constant unless @document_self object_class.add_constant constant end ## # Adds +include+ to +Object+ instead of +self+. def add_include(include) object_class.record_location self return include unless @document_self object_class.add_include include end ## # Adds +method+ to +Object+ instead of +self+. def add_method(method) object_class.record_location self return method unless @document_self object_class.add_method method end ## # Adds class or module +mod+. Used in the building phase # by the Ruby parser. def add_to_classes_or_modules mod @classes_or_modules << mod end ## # Base name of this file def base_name File.basename @relative_name end alias name base_name ## # Only a TopLevel that contains text file) will be displayed. See also # RDoc::CodeObject#display? def display? text? and super end ## # See RDoc::TopLevel::find_class_or_module #-- # TODO Why do we search through all classes/modules found, not just the # ones of this instance? def find_class_or_module name @store.find_class_or_module name end ## # Finds a class or module named +symbol+ def find_local_symbol(symbol) find_class_or_module(symbol) || super end ## # Finds a module or class with +name+ def find_module_named(name) find_class_or_module(name) end ## # Returns the relative name of this file def full_name @relative_name end ## # An RDoc::TopLevel has the same hash as another with the same # relative_name def hash @relative_name.hash end ## # URL for this with a +prefix+ def http_url(prefix) path = [prefix, @relative_name.tr('.', '_')] File.join(*path.compact) + '.html' end def inspect # :nodoc: "#<%s:0x%x %p modules: %p classes: %p>" % [ self.class, object_id, base_name, @modules.map { |n,m| m }, @classes.map { |n,c| c } ] end ## # Time this file was last modified, if known def last_modified @file_stat ? file_stat.mtime : nil end ## # Dumps this TopLevel for use by ri. See also #marshal_load def marshal_dump [ MARSHAL_VERSION, @relative_name, @parser, parse(@comment), ] end ## # Loads this TopLevel from +array+. def marshal_load array # :nodoc: initialize array[1] @parser = array[2] @comment = array[3] @file_stat = nil end ## # Returns the NormalClass "Object", creating it if not found. # # Records +self+ as a location in "Object". def object_class @object_class ||= begin oc = @store.find_class_named('Object') || add_class(RDoc::NormalClass, 'Object') oc.record_location self oc end end ## # Base name of this file without the extension def page_name basename = File.basename @relative_name basename =~ /\.(rb|rdoc|txt|md)$/i $` || basename end ## # Path to this file for use with HTML generator output. def path http_url @store.rdoc.generator.file_dir end def pretty_print q # :nodoc: q.group 2, "[#{self.class}: ", "]" do q.text "base name: #{base_name.inspect}" q.breakable items = @modules.map { |n,m| m } items.concat @modules.map { |n,c| c } q.seplist items do |mod| q.pp mod end end end ## # Search record used by RDoc::Generator::JsonIndex def search_record return unless @parser < RDoc::Parser::Text [ page_name, '', page_name, '', path, '', snippet(@comment), ] end ## # Is this TopLevel from a text file instead of a source code file? def text? @parser and @parser.ancestors.include? RDoc::Parser::Text end def to_s # :nodoc: "file #{full_name}" end end PK!@@""2.2.0/rdoc/stats/quiet.rbnu[## # Stats printer that prints nothing class RDoc::Stats::Quiet ## # Creates a new Quiet that will print nothing def initialize num_files @num_files = num_files end ## # Prints a message at the beginning of parsing def begin_adding(*) end ## # Prints when an alias is added def print_alias(*) end ## # Prints when an attribute is added def print_attribute(*) end ## # Prints when a class is added def print_class(*) end ## # Prints when a constant is added def print_constant(*) end ## # Prints when a file is added def print_file(*) end ## # Prints when a method is added def print_method(*) end ## # Prints when a module is added def print_module(*) end ## # Prints when RDoc is done def done_adding(*) end end PK!Ά2.2.0/rdoc/stats/verbose.rbnu[## # Stats printer that prints everything documented, including the documented # status class RDoc::Stats::Verbose < RDoc::Stats::Normal ## # Returns a marker for RDoc::CodeObject +co+ being undocumented def nodoc co " (undocumented)" unless co.documented? end def print_alias as # :nodoc: puts " alias #{as.new_name} #{as.old_name}#{nodoc as}" end def print_attribute attribute # :nodoc: puts " #{attribute.definition} #{attribute.name}#{nodoc attribute}" end def print_class(klass) # :nodoc: puts " class #{klass.full_name}#{nodoc klass}" end def print_constant(constant) # :nodoc: puts " #{constant.name}#{nodoc constant}" end def print_file(files_so_far, file) # :nodoc: super puts end def print_method(method) # :nodoc: puts " #{method.singleton ? '::' : '#'}#{method.name}#{nodoc method}" end def print_module(mod) # :nodoc: puts " module #{mod.full_name}#{nodoc mod}" end end PK! MM2.2.0/rdoc/stats/normal.rbnu[begin require 'io/console/size' rescue LoadError end ## # Stats printer that prints just the files being documented with a progress # bar class RDoc::Stats::Normal < RDoc::Stats::Quiet def begin_adding # :nodoc: puts "Parsing sources..." @last_width = 0 end ## # Prints a file with a progress bar def print_file files_so_far, filename progress_bar = sprintf("%3d%% [%2d/%2d] ", 100 * files_so_far / @num_files, files_so_far, @num_files) # Print a progress bar, but make sure it fits on a single line. Filename # will be truncated if necessary. terminal_width = if defined?(IO) && IO.respond_to?(:console_size) IO.console_size[1].to_i.nonzero? || 80 else 80 end max_filename_size = terminal_width - progress_bar.size if filename.size > max_filename_size then # Turn "some_long_filename.rb" to "...ong_filename.rb" filename = filename[(filename.size - max_filename_size) .. -1] filename[0..2] = "..." end line = "#{progress_bar}#{filename}" if $stdout.tty? # Clean the line with whitespaces so that leftover output from the # previous line doesn't show up. $stdout.print("\r" << (" " * @last_width) << ("\b" * @last_width) << "\r") if @last_width && @last_width > 0 @last_width = line.size $stdout.print("#{line}\r") else $stdout.puts(line) end $stdout.flush end def done_adding # :nodoc: puts end end PK!8 992.2.0/rdoc/context/section.rbnu[## # A section of documentation like: # # # :section: The title # # The body # # Sections can be referenced multiple times and will be collapsed into a # single section. class RDoc::Context::Section include RDoc::Text MARSHAL_VERSION = 0 # :nodoc: ## # Section comment attr_reader :comment ## # Section comments attr_reader :comments ## # Context this Section lives in attr_reader :parent ## # Section title attr_reader :title @@sequence = "SEC00000" ## # Creates a new section with +title+ and +comment+ def initialize parent, title, comment @parent = parent @title = title ? title.strip : title @@sequence.succ! @sequence = @@sequence.dup @comments = [] add_comment comment end ## # Sections are equal when they have the same #title def == other self.class === other and @title == other.title end ## # Adds +comment+ to this section def add_comment comment comment = extract_comment comment return if comment.empty? case comment when RDoc::Comment then @comments << comment when RDoc::Markup::Document then @comments.concat comment.parts when Array then @comments.concat comment else raise TypeError, "unknown comment type: #{comment.inspect}" end end ## # Anchor reference for linking to this section def aref title = @title || '[untitled]' CGI.escape(title).gsub('%', '-').sub(/^-/, '') end ## # Extracts the comment for this section from the original comment block. # If the first line contains :section:, strip it and use the rest. # Otherwise remove lines up to the line containing :section:, and look # for those lines again at the end and remove them. This lets us write # # # :section: The title # # The body def extract_comment comment case comment when Array then comment.map do |c| extract_comment c end when nil RDoc::Comment.new '' when RDoc::Comment then if comment.text =~ /^#[ \t]*:section:.*\n/ then start = $` rest = $' comment.text = if start.empty? then rest else rest.sub(/#{start.chomp}\Z/, '') end end comment when RDoc::Markup::Document then comment else raise TypeError, "unknown comment #{comment.inspect}" end end def inspect # :nodoc: "#<%s:0x%x %p>" % [self.class, object_id, title] end ## # The files comments in this section come from def in_files return [] if @comments.empty? case @comments when Array then @comments.map do |comment| comment.file end when RDoc::Markup::Document then @comment.parts.map do |document| document.file end else raise RDoc::Error, "BUG: unknown comment class #{@comments.class}" end end ## # Serializes this Section. The title and parsed comment are saved, but not # the section parent which must be restored manually. def marshal_dump [ MARSHAL_VERSION, @title, parse, ] end ## # De-serializes this Section. The section parent must be restored manually. def marshal_load array @parent = nil @title = array[1] @comments = array[2] end ## # Parses +comment_location+ into an RDoc::Markup::Document composed of # multiple RDoc::Markup::Documents with their file set. def parse case @comments when String then super when Array then docs = @comments.map do |comment, location| doc = super comment doc.file = location if location doc end RDoc::Markup::Document.new(*docs) when RDoc::Comment then doc = super @comments.text, comments.format doc.file = @comments.location doc when RDoc::Markup::Document then return @comments else raise ArgumentError, "unknown comment class #{comments.class}" end end ## # The section's title, or 'Top Section' if the title is nil. # # This is used by the table of contents template so the name is silly. def plain_html @title || 'Top Section' end ## # Removes a comment from this section if it is from the same file as # +comment+ def remove_comment comment return if @comments.empty? case @comments when Array then @comments.delete_if do |my_comment| my_comment.file == comment.file end when RDoc::Markup::Document then @comments.parts.delete_if do |document| document.file == comment.file.name end else raise RDoc::Error, "BUG: unknown comment class #{@comments.class}" end end ## # Section sequence number (deprecated) def sequence warn "RDoc::Context::Section#sequence is deprecated, use #aref" @sequence end end PK!BsMyy2.2.0/rdoc/code_objects.rbnu[# This file was used to load all the RDoc::CodeObject subclasses at once. Now # autoload handles this. require 'rdoc' PK!@Cnn2.2.0/rdoc/ruby_lex.rbnu[# coding: US-ASCII #-- # irb/ruby-lex.rb - ruby lexcal analyzer # $Release Version: 0.9.5$ # $Revision: 17979 $ # $Date: 2008-07-09 10:17:05 -0700 (Wed, 09 Jul 2008) $ # by Keiju ISHITSUKA(keiju@ruby-lang.org) # #++ require "e2mmap" require "irb/slex" require "stringio" ## # Ruby lexer adapted from irb. # # The internals are not documented because they are scary. class RDoc::RubyLex ## # Raised upon invalid input class Error < RDoc::Error end # :stopdoc: extend Exception2MessageMapper def_exception(:AlreadyDefinedToken, "Already defined token(%s)") def_exception(:TkReading2TokenNoKey, "key nothing(key='%s')") def_exception(:TkSymbol2TokenNoKey, "key nothing(key='%s')") def_exception(:TkReading2TokenDuplicateError, "key duplicate(token_n='%s', key='%s')") def_exception(:SyntaxError, "%s") def_exception(:TerminateLineInput, "Terminate Line Input") include RDoc::RubyToken include IRB attr_accessor :continue attr_accessor :lex_state attr_reader :reader class << self attr_accessor :debug_level end def self.debug? @debug_level > 0 end self.debug_level = 0 # :startdoc: ## # Returns an Array of +ruby+ tokens. See ::new for a description of # +options+. def self.tokenize ruby, options tokens = [] scanner = RDoc::RubyLex.new ruby, options scanner.exception_on_syntax_error = true while token = scanner.token do tokens << token end tokens end ## # Creates a new lexer for +content+. +options+ is an RDoc::Options, only # +tab_width is used. def initialize(content, options) lex_init if /\t/ =~ content then tab_width = options.tab_width content = content.split(/\n/).map do |line| 1 while line.gsub!(/\t+/) { ' ' * (tab_width*$&.length - $`.length % tab_width) } && $~ line end.join("\n") end content << "\n" unless content[-1, 1] == "\n" set_input StringIO.new content @base_char_no = 0 @char_no = 0 @exp_line_no = @line_no = 1 @here_readed = [] @readed = [] @rests = [] @seek = 0 @here_header = false @indent = 0 @indent_stack = [] @lex_state = :EXPR_BEG @space_seen = false @continue = false @line = "" @skip_space = false @readed_auto_clean_up = false @exception_on_syntax_error = true @prompt = nil @prev_seek = nil @ltype = nil end # :stopdoc: def inspect # :nodoc: "#<%s:0x%x pos %d lex_state %p space_seen %p>" % [ self.class, object_id, @io.pos, @lex_state, @space_seen, ] end attr_accessor :skip_space attr_accessor :readed_auto_clean_up attr_accessor :exception_on_syntax_error attr_reader :seek attr_reader :char_no attr_reader :line_no attr_reader :indent # io functions def set_input(io, p = nil, &block) @io = io if p.respond_to?(:call) @input = p elsif block_given? @input = block else @input = Proc.new{@io.gets} end end def get_readed if idx = @readed.rindex("\n") @base_char_no = @readed.size - (idx + 1) else @base_char_no += @readed.size end readed = @readed.join("") @readed = [] readed end def getc while @rests.empty? # return nil unless buf_input @rests.push nil unless buf_input end c = @rests.shift if @here_header @here_readed.push c else @readed.push c end @seek += 1 if c == "\n" @line_no += 1 @char_no = 0 else @char_no += 1 end c end def gets l = "" while c = getc l.concat(c) break if c == "\n" end return nil if l == "" and c.nil? l end def eof? @io.eof? end def getc_of_rests if @rests.empty? nil else getc end end def ungetc(c = nil) if @here_readed.empty? c2 = @readed.pop else c2 = @here_readed.pop end c = c2 unless c @rests.unshift c #c = @seek -= 1 if c == "\n" @line_no -= 1 if idx = @readed.rindex("\n") @char_no = idx + 1 else @char_no = @base_char_no + @readed.size end else @char_no -= 1 end end def peek_equal?(str) chrs = str.split(//) until @rests.size >= chrs.size return false unless buf_input end @rests[0, chrs.size] == chrs end def peek_match?(regexp) while @rests.empty? return false unless buf_input end regexp =~ @rests.join("") end def peek(i = 0) while @rests.size <= i return nil unless buf_input end @rests[i] end def buf_input prompt line = @input.call return nil unless line @rests.concat line.split(//) true end private :buf_input def set_prompt(p = nil, &block) p = block if block_given? if p.respond_to?(:call) @prompt = p else @prompt = Proc.new{print p} end end def prompt if @prompt @prompt.call(@ltype, @indent, @continue, @line_no) end end def initialize_input @ltype = nil @quoted = nil @indent = 0 @indent_stack = [] @lex_state = :EXPR_BEG @space_seen = false @here_header = false @continue = false prompt @line = "" @exp_line_no = @line_no end def each_top_level_statement initialize_input catch(:TERM_INPUT) do loop do begin @continue = false prompt unless l = lex throw :TERM_INPUT if @line == '' else #p l @line.concat l if @ltype or @continue or @indent > 0 next end end if @line != "\n" yield @line, @exp_line_no end break unless l @line = '' @exp_line_no = @line_no @indent = 0 @indent_stack = [] prompt rescue TerminateLineInput initialize_input prompt get_readed end end end end def lex until (((tk = token).kind_of?(TkNL) || tk.kind_of?(TkEND_OF_SCRIPT)) && !@continue or tk.nil?) #p tk #p @lex_state #p self end line = get_readed # print self.inspect if line == "" and tk.kind_of?(TkEND_OF_SCRIPT) || tk.nil? nil else line end end def token # require "tracer" # Tracer.on @prev_seek = @seek @prev_line_no = @line_no @prev_char_no = @char_no begin begin tk = @OP.match(self) @space_seen = tk.kind_of?(TkSPACE) rescue SyntaxError => e raise Error, "syntax error: #{e.message}" if @exception_on_syntax_error tk = TkError.new(@seek, @line_no, @char_no) end end while @skip_space and tk.kind_of?(TkSPACE) if @readed_auto_clean_up get_readed end # Tracer.off tk end ENINDENT_CLAUSE = [ "case", "class", "def", "do", "for", "if", "module", "unless", "until", "while", "begin" #, "when" ] DEINDENT_CLAUSE = ["end" #, "when" ] PERCENT_LTYPE = { "q" => "\'", "Q" => "\"", "x" => "\`", "r" => "/", "w" => "]", "W" => "]", "s" => ":" } PERCENT_PAREN = { "{" => "}", "[" => "]", "<" => ">", "(" => ")" } PERCENT_PAREN_REV = PERCENT_PAREN.invert Ltype2Token = { "\'" => TkSTRING, "\"" => TkSTRING, "\`" => TkXSTRING, "/" => TkREGEXP, "]" => TkDSTRING, ":" => TkSYMBOL } DLtype2Token = { "\"" => TkDSTRING, "\`" => TkDXSTRING, "/" => TkDREGEXP, } def lex_init() @OP = IRB::SLex.new @OP.def_rules("\0", "\004", "\032") do |op, io| Token(TkEND_OF_SCRIPT, '') end @OP.def_rules(" ", "\t", "\f", "\r", "\13") do |op, io| @space_seen = true str = op while (ch = getc) =~ /[ \t\f\r\13]/ do str << ch end ungetc Token TkSPACE, str end @OP.def_rule("#") do |op, io| identify_comment end @OP.def_rule("=begin", proc{|op, io| @prev_char_no == 0 && peek(0) =~ /\s/}) do |op, io| @ltype = "=" res = '' nil until getc == "\n" until ( peek_equal?("=end") && peek(4) =~ /\s/ ) do (ch = getc) res << ch end gets # consume =end @ltype = nil Token(TkRD_COMMENT, res) end @OP.def_rule("\n") do |op, io| print "\\n\n" if RDoc::RubyLex.debug? case @lex_state when :EXPR_BEG, :EXPR_FNAME, :EXPR_DOT @continue = true else @continue = false @lex_state = :EXPR_BEG until (@indent_stack.empty? || [TkLPAREN, TkLBRACK, TkLBRACE, TkfLPAREN, TkfLBRACK, TkfLBRACE].include?(@indent_stack.last)) @indent_stack.pop end end @here_header = false @here_readed = [] Token(TkNL) end @OP.def_rules("*", "**", "=", "==", "===", "=~", "<=>", "<", "<=", ">", ">=", ">>") do |op, io| case @lex_state when :EXPR_FNAME, :EXPR_DOT @lex_state = :EXPR_ARG else @lex_state = :EXPR_BEG end Token(op) end @OP.def_rules("!", "!=", "!~") do |op, io| @lex_state = :EXPR_BEG Token(op) end @OP.def_rules("<<") do |op, io| tk = nil if @lex_state != :EXPR_END && @lex_state != :EXPR_CLASS && (@lex_state != :EXPR_ARG || @space_seen) c = peek(0) if /\S/ =~ c && (/["'`]/ =~ c || /\w/ =~ c || c == "-") tk = identify_here_document end end unless tk tk = Token(op) case @lex_state when :EXPR_FNAME, :EXPR_DOT @lex_state = :EXPR_ARG else @lex_state = :EXPR_BEG end end tk end @OP.def_rules("'", '"') do |op, io| identify_string(op) end @OP.def_rules("`") do |op, io| if @lex_state == :EXPR_FNAME @lex_state = :EXPR_END Token(op) else identify_string(op) end end @OP.def_rules('?') do |op, io| if @lex_state == :EXPR_END @lex_state = :EXPR_BEG Token(TkQUESTION) else ch = getc if @lex_state == :EXPR_ARG && ch =~ /\s/ ungetc @lex_state = :EXPR_BEG; Token(TkQUESTION) else @lex_state = :EXPR_END Token(TkCHAR, "?#{ch}") end end end @OP.def_rules("&", "&&", "|", "||") do |op, io| @lex_state = :EXPR_BEG Token(op) end @OP.def_rules("+=", "-=", "*=", "**=", "&=", "|=", "^=", "<<=", ">>=", "||=", "&&=") do |op, io| @lex_state = :EXPR_BEG op =~ /^(.*)=$/ Token(TkOPASGN, $1) end @OP.def_rule("+@", proc{|op, io| @lex_state == :EXPR_FNAME}) do |op, io| @lex_state = :EXPR_ARG Token(op) end @OP.def_rule("-@", proc{|op, io| @lex_state == :EXPR_FNAME}) do |op, io| @lex_state = :EXPR_ARG Token(op) end @OP.def_rules("+", "-") do |op, io| catch(:RET) do if @lex_state == :EXPR_ARG if @space_seen and peek(0) =~ /[0-9]/ throw :RET, identify_number(op) else @lex_state = :EXPR_BEG end elsif @lex_state != :EXPR_END and peek(0) =~ /[0-9]/ throw :RET, identify_number(op) else @lex_state = :EXPR_BEG end Token(op) end end @OP.def_rule(".") do |op, io| @lex_state = :EXPR_BEG if peek(0) =~ /[0-9]/ ungetc identify_number else # for "obj.if" etc. @lex_state = :EXPR_DOT Token(TkDOT) end end @OP.def_rules("..", "...") do |op, io| @lex_state = :EXPR_BEG Token(op) end lex_int2 end def lex_int2 @OP.def_rules("]", "}", ")") do |op, io| @lex_state = :EXPR_END @indent -= 1 @indent_stack.pop Token(op) end @OP.def_rule(":") do |op, io| if @lex_state == :EXPR_END || peek(0) =~ /\s/ @lex_state = :EXPR_BEG Token(TkCOLON) else @lex_state = :EXPR_FNAME; Token(TkSYMBEG) end end @OP.def_rule("::") do |op, io| # p @lex_state.id2name, @space_seen if @lex_state == :EXPR_BEG or @lex_state == :EXPR_ARG && @space_seen @lex_state = :EXPR_BEG Token(TkCOLON3) else @lex_state = :EXPR_DOT Token(TkCOLON2) end end @OP.def_rule("/") do |op, io| if @lex_state == :EXPR_BEG || @lex_state == :EXPR_MID identify_string(op) elsif peek(0) == '=' getc @lex_state = :EXPR_BEG Token(TkOPASGN, "/") #/) elsif @lex_state == :EXPR_ARG and @space_seen and peek(0) !~ /\s/ identify_string(op) else @lex_state = :EXPR_BEG Token("/") #/) end end @OP.def_rules("^") do |op, io| @lex_state = :EXPR_BEG Token("^") end # @OP.def_rules("^=") do # @lex_state = :EXPR_BEG # Token(OP_ASGN, :^) # end @OP.def_rules(",") do |op, io| @lex_state = :EXPR_BEG Token(op) end @OP.def_rules(";") do |op, io| @lex_state = :EXPR_BEG until (@indent_stack.empty? || [TkLPAREN, TkLBRACK, TkLBRACE, TkfLPAREN, TkfLBRACK, TkfLBRACE].include?(@indent_stack.last)) @indent_stack.pop end Token(op) end @OP.def_rule("~") do |op, io| @lex_state = :EXPR_BEG Token("~") end @OP.def_rule("~@", proc{|op, io| @lex_state == :EXPR_FNAME}) do |op, io| @lex_state = :EXPR_BEG Token("~") end @OP.def_rule("(") do |op, io| @indent += 1 if @lex_state == :EXPR_BEG || @lex_state == :EXPR_MID @lex_state = :EXPR_BEG tk_c = TkfLPAREN else @lex_state = :EXPR_BEG tk_c = TkLPAREN end @indent_stack.push tk_c Token tk_c end @OP.def_rule("[]", proc{|op, io| @lex_state == :EXPR_FNAME}) do |op, io| @lex_state = :EXPR_ARG Token("[]") end @OP.def_rule("[]=", proc{|op, io| @lex_state == :EXPR_FNAME}) do |op, io| @lex_state = :EXPR_ARG Token("[]=") end @OP.def_rule("[") do |op, io| @indent += 1 if @lex_state == :EXPR_FNAME tk_c = TkfLBRACK else if @lex_state == :EXPR_BEG || @lex_state == :EXPR_MID tk_c = TkLBRACK elsif @lex_state == :EXPR_ARG && @space_seen tk_c = TkLBRACK else tk_c = TkfLBRACK end @lex_state = :EXPR_BEG end @indent_stack.push tk_c Token(tk_c) end @OP.def_rule("{") do |op, io| @indent += 1 if @lex_state != :EXPR_END && @lex_state != :EXPR_ARG tk_c = TkLBRACE else tk_c = TkfLBRACE end @lex_state = :EXPR_BEG @indent_stack.push tk_c Token(tk_c) end @OP.def_rule('\\') do |op, io| if getc == "\n" @space_seen = true @continue = true Token(TkSPACE) else ungetc Token("\\") end end @OP.def_rule('%') do |op, io| if @lex_state == :EXPR_BEG || @lex_state == :EXPR_MID identify_quotation elsif peek(0) == '=' getc Token(TkOPASGN, :%) elsif @lex_state == :EXPR_ARG and @space_seen and peek(0) !~ /\s/ identify_quotation else @lex_state = :EXPR_BEG Token("%") #)) end end @OP.def_rule('$') do |op, io| identify_gvar end @OP.def_rule('@') do |op, io| if peek(0) =~ /[\w@]/ ungetc identify_identifier else Token("@") end end # @OP.def_rule("def", proc{|op, io| /\s/ =~ io.peek(0)}) do # |op, io| # @indent += 1 # @lex_state = :EXPR_FNAME # # @lex_state = :EXPR_END # # until @rests[0] == "\n" or @rests[0] == ";" # # rests.shift # # end # end @OP.def_rule("_") do if peek_match?(/_END__/) and @lex_state == :EXPR_BEG then 6.times { getc } Token(TkEND_OF_SCRIPT, '__END__') else ungetc identify_identifier end end @OP.def_rule("") do |op, io| printf "MATCH: start %s: %s\n", op, io.inspect if RDoc::RubyLex.debug? if peek(0) =~ /[0-9]/ t = identify_number else t = identify_identifier end printf "MATCH: end %s: %s\n", op, io.inspect if RDoc::RubyLex.debug? t end p @OP if RDoc::RubyLex.debug? end def identify_gvar @lex_state = :EXPR_END case ch = getc when /[~_*$?!@\/\\;,=:<>".]/ #" Token(TkGVAR, "$" + ch) when "-" Token(TkGVAR, "$-" + getc) when "&", "`", "'", "+" Token(TkBACK_REF, "$"+ch) when /[1-9]/ ref = ch while (ch = getc) =~ /[0-9]/ do ref << ch end ungetc Token(TkNTH_REF, "$#{ref}") when /\w/ ungetc ungetc identify_identifier else ungetc Token("$") end end IDENT_RE = if defined? Encoding then eval '/[\w\u{0080}-\u{FFFFF}]/u' # 1.8 can't parse \u{} else /[\w\x80-\xFF]/ end def identify_identifier token = "" if peek(0) =~ /[$@]/ token.concat(c = getc) if c == "@" and peek(0) == "@" token.concat getc end end while (ch = getc) =~ IDENT_RE do print " :#{ch}: " if RDoc::RubyLex.debug? token.concat ch end ungetc if (ch == "!" || ch == "?") && token[0,1] =~ /\w/ && peek(0) != "=" token.concat getc end # almost fix token case token when /^\$/ return Token(TkGVAR, token) when /^\@\@/ @lex_state = :EXPR_END # p Token(TkCVAR, token) return Token(TkCVAR, token) when /^\@/ @lex_state = :EXPR_END return Token(TkIVAR, token) end if @lex_state != :EXPR_DOT print token, "\n" if RDoc::RubyLex.debug? token_c, *trans = TkReading2Token[token] if token_c # reserved word? if (@lex_state != :EXPR_BEG && @lex_state != :EXPR_FNAME && trans[1]) # modifiers token_c = TkSymbol2Token[trans[1]] @lex_state = trans[0] else if @lex_state != :EXPR_FNAME if ENINDENT_CLAUSE.include?(token) valid = peek(0) != ':' # check for ``class = val'' etc. case token when "class" valid = false unless peek_match?(/^\s*(<<|\w|::)/) when "def" valid = false if peek_match?(/^\s*(([+-\/*&\|^]|<<|>>|\|\||\&\&)=|\&\&|\|\|)/) when "do" valid = false if peek_match?(/^\s*([+-\/*]?=|\*|<|>|\&)/) when *ENINDENT_CLAUSE valid = false if peek_match?(/^\s*([+-\/*]?=|\*|<|>|\&|\|)/) else # no nothing end if valid if valid if token == "do" if ![TkFOR, TkWHILE, TkUNTIL].include?(@indent_stack.last) @indent += 1 @indent_stack.push token_c end else @indent += 1 @indent_stack.push token_c end else token_c = TkIDENTIFIER end elsif DEINDENT_CLAUSE.include?(token) @indent -= 1 @indent_stack.pop end @lex_state = trans[0] else @lex_state = :EXPR_END end end return Token(token_c, token) end end if @lex_state == :EXPR_FNAME @lex_state = :EXPR_END if peek(0) == '=' token.concat getc end elsif @lex_state == :EXPR_BEG || @lex_state == :EXPR_DOT || @lex_state == :EXPR_ARG @lex_state = :EXPR_ARG else @lex_state = :EXPR_END end if token[0, 1] =~ /[A-Z]/ return Token(TkCONSTANT, token) elsif token[token.size - 1, 1] =~ /[!?]/ return Token(TkFID, token) else return Token(TkIDENTIFIER, token) end end def identify_here_document ch = getc # if lt = PERCENT_LTYPE[ch] if ch == "-" ch = getc indent = true end if /['"`]/ =~ ch user_quote = lt = ch quoted = "" while (c = getc) && c != lt quoted.concat c end else user_quote = nil lt = '"' quoted = ch.dup while (c = getc) && c =~ /\w/ quoted.concat c end ungetc end ltback, @ltype = @ltype, lt reserve = [] while ch = getc reserve.push ch if ch == "\\" reserve.push ch = getc elsif ch == "\n" break end end output_heredoc = reserve.join =~ /\A\r?\n\z/ if output_heredoc then doc = '<<' doc << '-' if indent doc << "#{user_quote}#{quoted}#{user_quote}\n" else doc = '"' end @here_header = false while l = gets l = l.sub(/(:?\r)?\n\z/, "\n") if (indent ? l.strip : l.chomp) == quoted break end doc << l end if output_heredoc then raise Error, "Missing terminating #{quoted} for string" unless l doc << l.chomp else doc << '"' end @here_header = true @here_readed.concat reserve while ch = reserve.pop ungetc ch end token_class = output_heredoc ? RDoc::RubyLex::TkHEREDOC : Ltype2Token[lt] @ltype = ltback @lex_state = :EXPR_END Token(token_class, doc) end def identify_quotation type = ch = getc if lt = PERCENT_LTYPE[type] ch = getc elsif type =~ /\W/ type = nil lt = "\"" else return Token(TkMOD, '%') end # if ch !~ /\W/ # ungetc # next # end #@ltype = lt @quoted = ch unless @quoted = PERCENT_PAREN[ch] identify_string(lt, @quoted, type) end def identify_number(op = "") @lex_state = :EXPR_END num = op if peek(0) == "0" && peek(1) !~ /[.eE]/ num << getc case peek(0) when /[xX]/ ch = getc match = /[0-9a-fA-F_]/ when /[bB]/ ch = getc match = /[01_]/ when /[oO]/ ch = getc match = /[0-7_]/ when /[dD]/ ch = getc match = /[0-9_]/ when /[0-7]/ match = /[0-7_]/ when /[89]/ raise Error, "Illegal octal digit" else return Token(TkINTEGER, num) end num << ch if ch len0 = true non_digit = false while ch = getc num << ch if match =~ ch if ch == "_" if non_digit raise Error, "trailing `#{ch}' in number" else non_digit = ch end else non_digit = false len0 = false end else ungetc num[-1, 1] = '' if len0 raise Error, "numeric literal without digits" end if non_digit raise Error, "trailing `#{non_digit}' in number" end break end end return Token(TkINTEGER, num) end type = TkINTEGER allow_point = true allow_e = true non_digit = false while ch = getc num << ch case ch when /[0-9]/ non_digit = false when "_" non_digit = ch when allow_point && "." if non_digit raise Error, "trailing `#{non_digit}' in number" end type = TkFLOAT if peek(0) !~ /[0-9]/ type = TkINTEGER ungetc num[-1, 1] = '' break end allow_point = false when allow_e && "e", allow_e && "E" if non_digit raise Error, "trailing `#{non_digit}' in number" end type = TkFLOAT if peek(0) =~ /[+-]/ num << getc end allow_e = false allow_point = false non_digit = ch else if non_digit raise Error, "trailing `#{non_digit}' in number" end ungetc num[-1, 1] = '' break end end Token(type, num) end def identify_string(ltype, quoted = ltype, type = nil) close = PERCENT_PAREN.values.include?(quoted) @ltype = ltype @quoted = quoted str = if ltype == quoted and %w[" ' /].include? ltype then ltype.dup elsif RUBY_VERSION > '1.9' then "%#{type or PERCENT_LTYPE.key ltype}#{PERCENT_PAREN_REV[quoted]||quoted}" else "%#{type or PERCENT_LTYPE.index ltype}#{PERCENT_PAREN_REV[quoted]||quoted}" end subtype = nil begin nest = 0 while ch = getc str << ch if @quoted == ch and nest <= 0 break elsif @ltype != "'" && @ltype != "]" && @ltype != ":" and ch == "#" ch = getc subtype = true if ch == "{" then str << ch << skip_inner_expression next else ungetc end elsif ch == '\\' if %w[' /].include? @ltype then case ch = getc when "\\", "\n", "'" when @ltype str << ch else ungetc end else str << read_escape end end if close then if PERCENT_PAREN[ch] == @quoted nest += 1 elsif ch == @quoted nest -= 1 end end end if @ltype == "/" while peek(0) =~ /i|m|x|o|e|s|u|n/ str << getc end end if subtype Token(DLtype2Token[ltype], str) else Token(Ltype2Token[ltype], str) end ensure @ltype = nil @quoted = nil @lex_state = :EXPR_END end end def skip_inner_expression res = "" nest = 0 while ch = getc res << ch if ch == '}' break if nest.zero? nest -= 1 elsif ch == '{' nest += 1 end end res end def identify_comment @ltype = "#" comment = '#' while ch = getc # if ch == "\\" #" # read_escape # end if ch == "\n" @ltype = nil ungetc break end comment << ch end return Token(TkCOMMENT, comment) end def read_escape escape = '' ch = getc case ch when "\n", "\r", "\f" escape << ch when "\\", "n", "t", "r", "f", "v", "a", "e", "b", "s" #" escape << ch when /[0-7]/ ungetc ch 3.times do ch = getc case ch when /[0-7]/ escape << ch when nil break else ungetc break end end when "x" escape << ch 2.times do ch = getc case ch when /[0-9a-fA-F]/ escape << ch when nil break else ungetc break end end when "M" escape << ch ch = getc if ch != '-' ungetc else escape << ch ch = getc if ch == "\\" #" ungetc escape << read_escape else escape << ch end end when "C", "c" #, "^" escape << ch if ch == "C" ch = getc if ch == "-" escape << ch ch = getc escape << ch escape << read_escape if ch == "\\" else ungetc end elsif (ch = getc) == "\\" #" escape << ch << read_escape end else escape << ch # other characters end escape end # :startdoc: end #RDoc::RubyLex.debug_level = 1 PK!${x 0 end ## # Method name # # If the method has no assigned name, it extracts it from #call_seq. def name return @name if @name @name = @call_seq[/^.*?\.(\w+)/, 1] || @call_seq[/^.*?(\w+)/, 1] || @call_seq if @call_seq end ## # A list of this method's method and yield parameters. +call-seq+ params # are preferred over parsed method and block params. def param_list if @call_seq then params = @call_seq.split("\n").last params = params.sub(/.*?\((.*)\)/, '\1') params = params.sub(/(\{|do)\s*\|([^|]*)\|.*/, ',\2') elsif @params then params = @params.sub(/\((.*)\)/, '\1') params << ",#{@block_params}" if @block_params elsif @block_params then params = @block_params else return [] end if @block_params then # If this method has explicit block parameters, remove any explicit # &block params.sub!(/,?\s*&\w+/, '') else params.sub!(/\&(\w+)/, '\1') end params = params.gsub(/\s+/, '').split(',').reject(&:empty?) params.map { |param| param.sub(/=.*/, '') } end ## # Pretty parameter list for this method. If the method's parameters were # given by +call-seq+ it is preferred over the parsed values. def param_seq if @call_seq then params = @call_seq.split("\n").last params = params.sub(/[^( ]+/, '') params = params.sub(/(\|[^|]+\|)\s*\.\.\.\s*(end|\})/, '\1 \2') elsif @params then params = @params.gsub(/\s*\#.*/, '') params = params.tr("\n", " ").squeeze(" ") params = "(#{params})" unless params[0] == ?( else params = '' end if @block_params then # If this method has explicit block parameters, remove any explicit # &block params.sub!(/,?\s*&\w+/, '') block = @block_params.gsub(/\s*\#.*/, '') block = block.tr("\n", " ").squeeze(" ") if block[0] == ?( block.sub!(/^\(/, '').sub!(/\)/, '') end params << " { |#{block}| ... }" end params end ## # Sets the store for this method and its referenced code objects. def store= store super @file = @store.add_file @file.full_name if @file end ## # For methods that +super+, find the superclass method that would be called. def superclass_method return unless @calls_super return @superclass_method if @superclass_method parent.each_ancestor do |ancestor| if method = ancestor.method_list.find { |m| m.name == @name } then @superclass_method = method break end end @superclass_method end end PK!9P))2.2.0/rdoc/comment.rbnu[## # A comment holds the text comment for a RDoc::CodeObject and provides a # unified way of cleaning it up and parsing it into an RDoc::Markup::Document. # # Each comment may have a different markup format set by #format=. By default # 'rdoc' is used. The :markup: directive tells RDoc which format to use. # # See RDoc::Markup@Other+directives for instructions on adding an alternate # format. class RDoc::Comment include RDoc::Text ## # The format of this comment. Defaults to RDoc::Markup attr_reader :format ## # The RDoc::TopLevel this comment was found in attr_accessor :location ## # For duck-typing when merging classes at load time alias file location # :nodoc: ## # The text for this comment attr_reader :text ## # Overrides the content returned by #parse. Use when there is no #text # source for this comment attr_writer :document ## # Creates a new comment with +text+ that is found in the RDoc::TopLevel # +location+. def initialize text = nil, location = nil @location = location @text = text @document = nil @format = 'rdoc' @normalized = false end ## #-- # TODO deep copy @document def initialize_copy copy # :nodoc: @text = copy.text.dup end def == other # :nodoc: self.class === other and other.text == @text and other.location == @location end ## # Look for a 'call-seq' in the comment to override the normal parameter # handling. The :call-seq: is indented from the baseline. All lines of the # same indentation level and prefix are consumed. # # For example, all of the following will be used as the :call-seq: # # # :call-seq: # # ARGF.readlines(sep=$/) -> array # # ARGF.readlines(limit) -> array # # ARGF.readlines(sep, limit) -> array # # # # ARGF.to_a(sep=$/) -> array # # ARGF.to_a(limit) -> array # # ARGF.to_a(sep, limit) -> array def extract_call_seq method # we must handle situations like the above followed by an unindented first # comment. The difficulty is to make sure not to match lines starting # with ARGF at the same indent, but that are after the first description # paragraph. if @text =~ /^\s*:?call-seq:(.*?(?:\S).*?)^\s*$/m then all_start, all_stop = $~.offset(0) seq_start, seq_stop = $~.offset(1) # we get the following lines that start with the leading word at the # same indent, even if they have blank lines before if $1 =~ /(^\s*\n)+^(\s*\w+)/m then leading = $2 # ' * ARGF' in the example above re = %r% \A( (^\s*\n)+ (^#{Regexp.escape leading}.*?\n)+ )+ ^\s*$ %xm if @text[seq_stop..-1] =~ re then all_stop = seq_stop + $~.offset(0).last seq_stop = seq_stop + $~.offset(1).last end end seq = @text[seq_start..seq_stop] seq.gsub!(/^\s*(\S|\n)/m, '\1') @text.slice! all_start...all_stop method.call_seq = seq.chomp elsif @text.sub!(/^\s*:?call-seq:(.*?)(^\s*$|\z)/m, '') then seq = $1 seq.gsub!(/^\s*/, '') method.call_seq = seq end method end ## # A comment is empty if its text String is empty. def empty? @text.empty? end ## # HACK dubious def force_encoding encoding @text.force_encoding encoding end ## # Sets the format of this comment and resets any parsed document def format= format @format = format @document = nil end def inspect # :nodoc: location = @location ? @location.relative_name : '(unknown)' "#<%s:%x %s %p>" % [self.class, object_id, location, @text] end ## # Normalizes the text. See RDoc::Text#normalize_comment for details def normalize return self unless @text return self if @normalized # TODO eliminate duplicate normalization @text = normalize_comment @text @normalized = true self end ## # Was this text normalized? def normalized? # :nodoc: @normalized end ## # Parses the comment into an RDoc::Markup::Document. The parsed document is # cached until the text is changed. def parse return @document if @document @document = super @text, @format @document.file = @location @document end ## # Removes private sections from this comment. Private sections are flush to # the comment marker and start with -- and end with ++. # For C-style comments, a private marker may not start at the opening of the # comment. # # /* # *-- # * private # *++ # * public # */ def remove_private # Workaround for gsub encoding for Ruby 1.9.2 and earlier empty = '' empty.force_encoding @text.encoding if Object.const_defined? :Encoding @text = @text.gsub(%r%^\s*([#*]?)--.*?^\s*(\1)\+\+\n?%m, empty) @text = @text.sub(%r%^\s*[#*]?--.*%m, '') end ## # Replaces this comment's text with +text+ and resets the parsed document. # # An error is raised if the comment contains a document but no text. def text= text raise RDoc::Error, 'replacing document-only comment is not allowed' if @text.nil? and @document @document = nil @text = text end ## # Returns true if this comment is in TomDoc format. def tomdoc? @format == 'tomdoc' end end PK!Nzz2.2.0/rdoc/single_class.rbnu[## # A singleton class class RDoc::SingleClass < RDoc::ClassModule ## # Adds the superclass to the included modules. def ancestors superclass ? super + [superclass] : super end def aref_prefix # :nodoc: 'sclass' end ## # The definition of this singleton class, class << MyClassName def definition "class << #{full_name}" end end PK!t\2.2.0/rdoc/markdown/entities.rbnu[## # HTML entity name map for RDoc::Markdown RDoc::Markdown::HTML_ENTITIES = { "AElig" => [0x000C6], "AMP" => [0x00026], "Aacute" => [0x000C1], "Abreve" => [0x00102], "Acirc" => [0x000C2], "Acy" => [0x00410], "Afr" => [0x1D504], "Agrave" => [0x000C0], "Alpha" => [0x00391], "Amacr" => [0x00100], "And" => [0x02A53], "Aogon" => [0x00104], "Aopf" => [0x1D538], "ApplyFunction" => [0x02061], "Aring" => [0x000C5], "Ascr" => [0x1D49C], "Assign" => [0x02254], "Atilde" => [0x000C3], "Auml" => [0x000C4], "Backslash" => [0x02216], "Barv" => [0x02AE7], "Barwed" => [0x02306], "Bcy" => [0x00411], "Because" => [0x02235], "Bernoullis" => [0x0212C], "Beta" => [0x00392], "Bfr" => [0x1D505], "Bopf" => [0x1D539], "Breve" => [0x002D8], "Bscr" => [0x0212C], "Bumpeq" => [0x0224E], "CHcy" => [0x00427], "COPY" => [0x000A9], "Cacute" => [0x00106], "Cap" => [0x022D2], "CapitalDifferentialD" => [0x02145], "Cayleys" => [0x0212D], "Ccaron" => [0x0010C], "Ccedil" => [0x000C7], "Ccirc" => [0x00108], "Cconint" => [0x02230], "Cdot" => [0x0010A], "Cedilla" => [0x000B8], "CenterDot" => [0x000B7], "Cfr" => [0x0212D], "Chi" => [0x003A7], "CircleDot" => [0x02299], "CircleMinus" => [0x02296], "CirclePlus" => [0x02295], "CircleTimes" => [0x02297], "ClockwiseContourIntegral" => [0x02232], "CloseCurlyDoubleQuote" => [0x0201D], "CloseCurlyQuote" => [0x02019], "Colon" => [0x02237], "Colone" => [0x02A74], "Congruent" => [0x02261], "Conint" => [0x0222F], "ContourIntegral" => [0x0222E], "Copf" => [0x02102], "Coproduct" => [0x02210], "CounterClockwiseContourIntegral" => [0x02233], "Cross" => [0x02A2F], "Cscr" => [0x1D49E], "Cup" => [0x022D3], "CupCap" => [0x0224D], "DD" => [0x02145], "DDotrahd" => [0x02911], "DJcy" => [0x00402], "DScy" => [0x00405], "DZcy" => [0x0040F], "Dagger" => [0x02021], "Darr" => [0x021A1], "Dashv" => [0x02AE4], "Dcaron" => [0x0010E], "Dcy" => [0x00414], "Del" => [0x02207], "Delta" => [0x00394], "Dfr" => [0x1D507], "DiacriticalAcute" => [0x000B4], "DiacriticalDot" => [0x002D9], "DiacriticalDoubleAcute" => [0x002DD], "DiacriticalGrave" => [0x00060], "DiacriticalTilde" => [0x002DC], "Diamond" => [0x022C4], "DifferentialD" => [0x02146], "Dopf" => [0x1D53B], "Dot" => [0x000A8], "DotDot" => [0x020DC], "DotEqual" => [0x02250], "DoubleContourIntegral" => [0x0222F], "DoubleDot" => [0x000A8], "DoubleDownArrow" => [0x021D3], "DoubleLeftArrow" => [0x021D0], "DoubleLeftRightArrow" => [0x021D4], "DoubleLeftTee" => [0x02AE4], "DoubleLongLeftArrow" => [0x027F8], "DoubleLongLeftRightArrow" => [0x027FA], "DoubleLongRightArrow" => [0x027F9], "DoubleRightArrow" => [0x021D2], "DoubleRightTee" => [0x022A8], "DoubleUpArrow" => [0x021D1], "DoubleUpDownArrow" => [0x021D5], "DoubleVerticalBar" => [0x02225], "DownArrow" => [0x02193], "DownArrowBar" => [0x02913], "DownArrowUpArrow" => [0x021F5], "DownBreve" => [0x00311], "DownLeftRightVector" => [0x02950], "DownLeftTeeVector" => [0x0295E], "DownLeftVector" => [0x021BD], "DownLeftVectorBar" => [0x02956], "DownRightTeeVector" => [0x0295F], "DownRightVector" => [0x021C1], "DownRightVectorBar" => [0x02957], "DownTee" => [0x022A4], "DownTeeArrow" => [0x021A7], "Downarrow" => [0x021D3], "Dscr" => [0x1D49F], "Dstrok" => [0x00110], "ENG" => [0x0014A], "ETH" => [0x000D0], "Eacute" => [0x000C9], "Ecaron" => [0x0011A], "Ecirc" => [0x000CA], "Ecy" => [0x0042D], "Edot" => [0x00116], "Efr" => [0x1D508], "Egrave" => [0x000C8], "Element" => [0x02208], "Emacr" => [0x00112], "EmptySmallSquare" => [0x025FB], "EmptyVerySmallSquare" => [0x025AB], "Eogon" => [0x00118], "Eopf" => [0x1D53C], "Epsilon" => [0x00395], "Equal" => [0x02A75], "EqualTilde" => [0x02242], "Equilibrium" => [0x021CC], "Escr" => [0x02130], "Esim" => [0x02A73], "Eta" => [0x00397], "Euml" => [0x000CB], "Exists" => [0x02203], "ExponentialE" => [0x02147], "Fcy" => [0x00424], "Ffr" => [0x1D509], "FilledSmallSquare" => [0x025FC], "FilledVerySmallSquare" => [0x025AA], "Fopf" => [0x1D53D], "ForAll" => [0x02200], "Fouriertrf" => [0x02131], "Fscr" => [0x02131], "GJcy" => [0x00403], "GT" => [0x0003E], "Gamma" => [0x00393], "Gammad" => [0x003DC], "Gbreve" => [0x0011E], "Gcedil" => [0x00122], "Gcirc" => [0x0011C], "Gcy" => [0x00413], "Gdot" => [0x00120], "Gfr" => [0x1D50A], "Gg" => [0x022D9], "Gopf" => [0x1D53E], "GreaterEqual" => [0x02265], "GreaterEqualLess" => [0x022DB], "GreaterFullEqual" => [0x02267], "GreaterGreater" => [0x02AA2], "GreaterLess" => [0x02277], "GreaterSlantEqual" => [0x02A7E], "GreaterTilde" => [0x02273], "Gscr" => [0x1D4A2], "Gt" => [0x0226B], "HARDcy" => [0x0042A], "Hacek" => [0x002C7], "Hat" => [0x0005E], "Hcirc" => [0x00124], "Hfr" => [0x0210C], "HilbertSpace" => [0x0210B], "Hopf" => [0x0210D], "HorizontalLine" => [0x02500], "Hscr" => [0x0210B], "Hstrok" => [0x00126], "HumpDownHump" => [0x0224E], "HumpEqual" => [0x0224F], "IEcy" => [0x00415], "IJlig" => [0x00132], "IOcy" => [0x00401], "Iacute" => [0x000CD], "Icirc" => [0x000CE], "Icy" => [0x00418], "Idot" => [0x00130], "Ifr" => [0x02111], "Igrave" => [0x000CC], "Im" => [0x02111], "Imacr" => [0x0012A], "ImaginaryI" => [0x02148], "Implies" => [0x021D2], "Int" => [0x0222C], "Integral" => [0x0222B], "Intersection" => [0x022C2], "InvisibleComma" => [0x02063], "InvisibleTimes" => [0x02062], "Iogon" => [0x0012E], "Iopf" => [0x1D540], "Iota" => [0x00399], "Iscr" => [0x02110], "Itilde" => [0x00128], "Iukcy" => [0x00406], "Iuml" => [0x000CF], "Jcirc" => [0x00134], "Jcy" => [0x00419], "Jfr" => [0x1D50D], "Jopf" => [0x1D541], "Jscr" => [0x1D4A5], "Jsercy" => [0x00408], "Jukcy" => [0x00404], "KHcy" => [0x00425], "KJcy" => [0x0040C], "Kappa" => [0x0039A], "Kcedil" => [0x00136], "Kcy" => [0x0041A], "Kfr" => [0x1D50E], "Kopf" => [0x1D542], "Kscr" => [0x1D4A6], "LJcy" => [0x00409], "LT" => [0x0003C], "Lacute" => [0x00139], "Lambda" => [0x0039B], "Lang" => [0x027EA], "Laplacetrf" => [0x02112], "Larr" => [0x0219E], "Lcaron" => [0x0013D], "Lcedil" => [0x0013B], "Lcy" => [0x0041B], "LeftAngleBracket" => [0x027E8], "LeftArrow" => [0x02190], "LeftArrowBar" => [0x021E4], "LeftArrowRightArrow" => [0x021C6], "LeftCeiling" => [0x02308], "LeftDoubleBracket" => [0x027E6], "LeftDownTeeVector" => [0x02961], "LeftDownVector" => [0x021C3], "LeftDownVectorBar" => [0x02959], "LeftFloor" => [0x0230A], "LeftRightArrow" => [0x02194], "LeftRightVector" => [0x0294E], "LeftTee" => [0x022A3], "LeftTeeArrow" => [0x021A4], "LeftTeeVector" => [0x0295A], "LeftTriangle" => [0x022B2], "LeftTriangleBar" => [0x029CF], "LeftTriangleEqual" => [0x022B4], "LeftUpDownVector" => [0x02951], "LeftUpTeeVector" => [0x02960], "LeftUpVector" => [0x021BF], "LeftUpVectorBar" => [0x02958], "LeftVector" => [0x021BC], "LeftVectorBar" => [0x02952], "Leftarrow" => [0x021D0], "Leftrightarrow" => [0x021D4], "LessEqualGreater" => [0x022DA], "LessFullEqual" => [0x02266], "LessGreater" => [0x02276], "LessLess" => [0x02AA1], "LessSlantEqual" => [0x02A7D], "LessTilde" => [0x02272], "Lfr" => [0x1D50F], "Ll" => [0x022D8], "Lleftarrow" => [0x021DA], "Lmidot" => [0x0013F], "LongLeftArrow" => [0x027F5], "LongLeftRightArrow" => [0x027F7], "LongRightArrow" => [0x027F6], "Longleftarrow" => [0x027F8], "Longleftrightarrow" => [0x027FA], "Longrightarrow" => [0x027F9], "Lopf" => [0x1D543], "LowerLeftArrow" => [0x02199], "LowerRightArrow" => [0x02198], "Lscr" => [0x02112], "Lsh" => [0x021B0], "Lstrok" => [0x00141], "Lt" => [0x0226A], "Map" => [0x02905], "Mcy" => [0x0041C], "MediumSpace" => [0x0205F], "Mellintrf" => [0x02133], "Mfr" => [0x1D510], "MinusPlus" => [0x02213], "Mopf" => [0x1D544], "Mscr" => [0x02133], "Mu" => [0x0039C], "NJcy" => [0x0040A], "Nacute" => [0x00143], "Ncaron" => [0x00147], "Ncedil" => [0x00145], "Ncy" => [0x0041D], "NegativeMediumSpace" => [0x0200B], "NegativeThickSpace" => [0x0200B], "NegativeThinSpace" => [0x0200B], "NegativeVeryThinSpace" => [0x0200B], "NestedGreaterGreater" => [0x0226B], "NestedLessLess" => [0x0226A], "NewLine" => [0x0000A], "Nfr" => [0x1D511], "NoBreak" => [0x02060], "NonBreakingSpace" => [0x000A0], "Nopf" => [0x02115], "Not" => [0x02AEC], "NotCongruent" => [0x02262], "NotCupCap" => [0x0226D], "NotDoubleVerticalBar" => [0x02226], "NotElement" => [0x02209], "NotEqual" => [0x02260], "NotEqualTilde" => [0x02242, 0x00338], "NotExists" => [0x02204], "NotGreater" => [0x0226F], "NotGreaterEqual" => [0x02271], "NotGreaterFullEqual" => [0x02267, 0x00338], "NotGreaterGreater" => [0x0226B, 0x00338], "NotGreaterLess" => [0x02279], "NotGreaterSlantEqual" => [0x02A7E, 0x00338], "NotGreaterTilde" => [0x02275], "NotHumpDownHump" => [0x0224E, 0x00338], "NotHumpEqual" => [0x0224F, 0x00338], "NotLeftTriangle" => [0x022EA], "NotLeftTriangleBar" => [0x029CF, 0x00338], "NotLeftTriangleEqual" => [0x022EC], "NotLess" => [0x0226E], "NotLessEqual" => [0x02270], "NotLessGreater" => [0x02278], "NotLessLess" => [0x0226A, 0x00338], "NotLessSlantEqual" => [0x02A7D, 0x00338], "NotLessTilde" => [0x02274], "NotNestedGreaterGreater" => [0x02AA2, 0x00338], "NotNestedLessLess" => [0x02AA1, 0x00338], "NotPrecedes" => [0x02280], "NotPrecedesEqual" => [0x02AAF, 0x00338], "NotPrecedesSlantEqual" => [0x022E0], "NotReverseElement" => [0x0220C], "NotRightTriangle" => [0x022EB], "NotRightTriangleBar" => [0x029D0, 0x00338], "NotRightTriangleEqual" => [0x022ED], "NotSquareSubset" => [0x0228F, 0x00338], "NotSquareSubsetEqual" => [0x022E2], "NotSquareSuperset" => [0x02290, 0x00338], "NotSquareSupersetEqual" => [0x022E3], "NotSubset" => [0x02282, 0x020D2], "NotSubsetEqual" => [0x02288], "NotSucceeds" => [0x02281], "NotSucceedsEqual" => [0x02AB0, 0x00338], "NotSucceedsSlantEqual" => [0x022E1], "NotSucceedsTilde" => [0x0227F, 0x00338], "NotSuperset" => [0x02283, 0x020D2], "NotSupersetEqual" => [0x02289], "NotTilde" => [0x02241], "NotTildeEqual" => [0x02244], "NotTildeFullEqual" => [0x02247], "NotTildeTilde" => [0x02249], "NotVerticalBar" => [0x02224], "Nscr" => [0x1D4A9], "Ntilde" => [0x000D1], "Nu" => [0x0039D], "OElig" => [0x00152], "Oacute" => [0x000D3], "Ocirc" => [0x000D4], "Ocy" => [0x0041E], "Odblac" => [0x00150], "Ofr" => [0x1D512], "Ograve" => [0x000D2], "Omacr" => [0x0014C], "Omega" => [0x003A9], "Omicron" => [0x0039F], "Oopf" => [0x1D546], "OpenCurlyDoubleQuote" => [0x0201C], "OpenCurlyQuote" => [0x02018], "Or" => [0x02A54], "Oscr" => [0x1D4AA], "Oslash" => [0x000D8], "Otilde" => [0x000D5], "Otimes" => [0x02A37], "Ouml" => [0x000D6], "OverBar" => [0x0203E], "OverBrace" => [0x023DE], "OverBracket" => [0x023B4], "OverParenthesis" => [0x023DC], "PartialD" => [0x02202], "Pcy" => [0x0041F], "Pfr" => [0x1D513], "Phi" => [0x003A6], "Pi" => [0x003A0], "PlusMinus" => [0x000B1], "Poincareplane" => [0x0210C], "Popf" => [0x02119], "Pr" => [0x02ABB], "Precedes" => [0x0227A], "PrecedesEqual" => [0x02AAF], "PrecedesSlantEqual" => [0x0227C], "PrecedesTilde" => [0x0227E], "Prime" => [0x02033], "Product" => [0x0220F], "Proportion" => [0x02237], "Proportional" => [0x0221D], "Pscr" => [0x1D4AB], "Psi" => [0x003A8], "QUOT" => [0x00022], "Qfr" => [0x1D514], "Qopf" => [0x0211A], "Qscr" => [0x1D4AC], "RBarr" => [0x02910], "REG" => [0x000AE], "Racute" => [0x00154], "Rang" => [0x027EB], "Rarr" => [0x021A0], "Rarrtl" => [0x02916], "Rcaron" => [0x00158], "Rcedil" => [0x00156], "Rcy" => [0x00420], "Re" => [0x0211C], "ReverseElement" => [0x0220B], "ReverseEquilibrium" => [0x021CB], "ReverseUpEquilibrium" => [0x0296F], "Rfr" => [0x0211C], "Rho" => [0x003A1], "RightAngleBracket" => [0x027E9], "RightArrow" => [0x02192], "RightArrowBar" => [0x021E5], "RightArrowLeftArrow" => [0x021C4], "RightCeiling" => [0x02309], "RightDoubleBracket" => [0x027E7], "RightDownTeeVector" => [0x0295D], "RightDownVector" => [0x021C2], "RightDownVectorBar" => [0x02955], "RightFloor" => [0x0230B], "RightTee" => [0x022A2], "RightTeeArrow" => [0x021A6], "RightTeeVector" => [0x0295B], "RightTriangle" => [0x022B3], "RightTriangleBar" => [0x029D0], "RightTriangleEqual" => [0x022B5], "RightUpDownVector" => [0x0294F], "RightUpTeeVector" => [0x0295C], "RightUpVector" => [0x021BE], "RightUpVectorBar" => [0x02954], "RightVector" => [0x021C0], "RightVectorBar" => [0x02953], "Rightarrow" => [0x021D2], "Ropf" => [0x0211D], "RoundImplies" => [0x02970], "Rrightarrow" => [0x021DB], "Rscr" => [0x0211B], "Rsh" => [0x021B1], "RuleDelayed" => [0x029F4], "SHCHcy" => [0x00429], "SHcy" => [0x00428], "SOFTcy" => [0x0042C], "Sacute" => [0x0015A], "Sc" => [0x02ABC], "Scaron" => [0x00160], "Scedil" => [0x0015E], "Scirc" => [0x0015C], "Scy" => [0x00421], "Sfr" => [0x1D516], "ShortDownArrow" => [0x02193], "ShortLeftArrow" => [0x02190], "ShortRightArrow" => [0x02192], "ShortUpArrow" => [0x02191], "Sigma" => [0x003A3], "SmallCircle" => [0x02218], "Sopf" => [0x1D54A], "Sqrt" => [0x0221A], "Square" => [0x025A1], "SquareIntersection" => [0x02293], "SquareSubset" => [0x0228F], "SquareSubsetEqual" => [0x02291], "SquareSuperset" => [0x02290], "SquareSupersetEqual" => [0x02292], "SquareUnion" => [0x02294], "Sscr" => [0x1D4AE], "Star" => [0x022C6], "Sub" => [0x022D0], "Subset" => [0x022D0], "SubsetEqual" => [0x02286], "Succeeds" => [0x0227B], "SucceedsEqual" => [0x02AB0], "SucceedsSlantEqual" => [0x0227D], "SucceedsTilde" => [0x0227F], "SuchThat" => [0x0220B], "Sum" => [0x02211], "Sup" => [0x022D1], "Superset" => [0x02283], "SupersetEqual" => [0x02287], "Supset" => [0x022D1], "THORN" => [0x000DE], "TRADE" => [0x02122], "TSHcy" => [0x0040B], "TScy" => [0x00426], "Tab" => [0x00009], "Tau" => [0x003A4], "Tcaron" => [0x00164], "Tcedil" => [0x00162], "Tcy" => [0x00422], "Tfr" => [0x1D517], "Therefore" => [0x02234], "Theta" => [0x00398], "ThickSpace" => [0x0205F, 0x0200A], "ThinSpace" => [0x02009], "Tilde" => [0x0223C], "TildeEqual" => [0x02243], "TildeFullEqual" => [0x02245], "TildeTilde" => [0x02248], "Topf" => [0x1D54B], "TripleDot" => [0x020DB], "Tscr" => [0x1D4AF], "Tstrok" => [0x00166], "Uacute" => [0x000DA], "Uarr" => [0x0219F], "Uarrocir" => [0x02949], "Ubrcy" => [0x0040E], "Ubreve" => [0x0016C], "Ucirc" => [0x000DB], "Ucy" => [0x00423], "Udblac" => [0x00170], "Ufr" => [0x1D518], "Ugrave" => [0x000D9], "Umacr" => [0x0016A], "UnderBar" => [0x0005F], "UnderBrace" => [0x023DF], "UnderBracket" => [0x023B5], "UnderParenthesis" => [0x023DD], "Union" => [0x022C3], "UnionPlus" => [0x0228E], "Uogon" => [0x00172], "Uopf" => [0x1D54C], "UpArrow" => [0x02191], "UpArrowBar" => [0x02912], "UpArrowDownArrow" => [0x021C5], "UpDownArrow" => [0x02195], "UpEquilibrium" => [0x0296E], "UpTee" => [0x022A5], "UpTeeArrow" => [0x021A5], "Uparrow" => [0x021D1], "Updownarrow" => [0x021D5], "UpperLeftArrow" => [0x02196], "UpperRightArrow" => [0x02197], "Upsi" => [0x003D2], "Upsilon" => [0x003A5], "Uring" => [0x0016E], "Uscr" => [0x1D4B0], "Utilde" => [0x00168], "Uuml" => [0x000DC], "VDash" => [0x022AB], "Vbar" => [0x02AEB], "Vcy" => [0x00412], "Vdash" => [0x022A9], "Vdashl" => [0x02AE6], "Vee" => [0x022C1], "Verbar" => [0x02016], "Vert" => [0x02016], "VerticalBar" => [0x02223], "VerticalLine" => [0x0007C], "VerticalSeparator" => [0x02758], "VerticalTilde" => [0x02240], "VeryThinSpace" => [0x0200A], "Vfr" => [0x1D519], "Vopf" => [0x1D54D], "Vscr" => [0x1D4B1], "Vvdash" => [0x022AA], "Wcirc" => [0x00174], "Wedge" => [0x022C0], "Wfr" => [0x1D51A], "Wopf" => [0x1D54E], "Wscr" => [0x1D4B2], "Xfr" => [0x1D51B], "Xi" => [0x0039E], "Xopf" => [0x1D54F], "Xscr" => [0x1D4B3], "YAcy" => [0x0042F], "YIcy" => [0x00407], "YUcy" => [0x0042E], "Yacute" => [0x000DD], "Ycirc" => [0x00176], "Ycy" => [0x0042B], "Yfr" => [0x1D51C], "Yopf" => [0x1D550], "Yscr" => [0x1D4B4], "Yuml" => [0x00178], "ZHcy" => [0x00416], "Zacute" => [0x00179], "Zcaron" => [0x0017D], "Zcy" => [0x00417], "Zdot" => [0x0017B], "ZeroWidthSpace" => [0x0200B], "Zeta" => [0x00396], "Zfr" => [0x02128], "Zopf" => [0x02124], "Zscr" => [0x1D4B5], "aacute" => [0x000E1], "abreve" => [0x00103], "ac" => [0x0223E], "acE" => [0x0223E, 0x00333], "acd" => [0x0223F], "acirc" => [0x000E2], "acute" => [0x000B4], "acy" => [0x00430], "aelig" => [0x000E6], "af" => [0x02061], "afr" => [0x1D51E], "agrave" => [0x000E0], "alefsym" => [0x02135], "aleph" => [0x02135], "alpha" => [0x003B1], "amacr" => [0x00101], "amalg" => [0x02A3F], "amp" => [0x00026], "and" => [0x02227], "andand" => [0x02A55], "andd" => [0x02A5C], "andslope" => [0x02A58], "andv" => [0x02A5A], "ang" => [0x02220], "ange" => [0x029A4], "angle" => [0x02220], "angmsd" => [0x02221], "angmsdaa" => [0x029A8], "angmsdab" => [0x029A9], "angmsdac" => [0x029AA], "angmsdad" => [0x029AB], "angmsdae" => [0x029AC], "angmsdaf" => [0x029AD], "angmsdag" => [0x029AE], "angmsdah" => [0x029AF], "angrt" => [0x0221F], "angrtvb" => [0x022BE], "angrtvbd" => [0x0299D], "angsph" => [0x02222], "angst" => [0x000C5], "angzarr" => [0x0237C], "aogon" => [0x00105], "aopf" => [0x1D552], "ap" => [0x02248], "apE" => [0x02A70], "apacir" => [0x02A6F], "ape" => [0x0224A], "apid" => [0x0224B], "apos" => [0x00027], "approx" => [0x02248], "approxeq" => [0x0224A], "aring" => [0x000E5], "ascr" => [0x1D4B6], "ast" => [0x0002A], "asymp" => [0x02248], "asympeq" => [0x0224D], "atilde" => [0x000E3], "auml" => [0x000E4], "awconint" => [0x02233], "awint" => [0x02A11], "bNot" => [0x02AED], "backcong" => [0x0224C], "backepsilon" => [0x003F6], "backprime" => [0x02035], "backsim" => [0x0223D], "backsimeq" => [0x022CD], "barvee" => [0x022BD], "barwed" => [0x02305], "barwedge" => [0x02305], "bbrk" => [0x023B5], "bbrktbrk" => [0x023B6], "bcong" => [0x0224C], "bcy" => [0x00431], "bdquo" => [0x0201E], "becaus" => [0x02235], "because" => [0x02235], "bemptyv" => [0x029B0], "bepsi" => [0x003F6], "bernou" => [0x0212C], "beta" => [0x003B2], "beth" => [0x02136], "between" => [0x0226C], "bfr" => [0x1D51F], "bigcap" => [0x022C2], "bigcirc" => [0x025EF], "bigcup" => [0x022C3], "bigodot" => [0x02A00], "bigoplus" => [0x02A01], "bigotimes" => [0x02A02], "bigsqcup" => [0x02A06], "bigstar" => [0x02605], "bigtriangledown" => [0x025BD], "bigtriangleup" => [0x025B3], "biguplus" => [0x02A04], "bigvee" => [0x022C1], "bigwedge" => [0x022C0], "bkarow" => [0x0290D], "blacklozenge" => [0x029EB], "blacksquare" => [0x025AA], "blacktriangle" => [0x025B4], "blacktriangledown" => [0x025BE], "blacktriangleleft" => [0x025C2], "blacktriangleright" => [0x025B8], "blank" => [0x02423], "blk12" => [0x02592], "blk14" => [0x02591], "blk34" => [0x02593], "block" => [0x02588], "bne" => [0x0003D, 0x020E5], "bnequiv" => [0x02261, 0x020E5], "bnot" => [0x02310], "bopf" => [0x1D553], "bot" => [0x022A5], "bottom" => [0x022A5], "bowtie" => [0x022C8], "boxDL" => [0x02557], "boxDR" => [0x02554], "boxDl" => [0x02556], "boxDr" => [0x02553], "boxH" => [0x02550], "boxHD" => [0x02566], "boxHU" => [0x02569], "boxHd" => [0x02564], "boxHu" => [0x02567], "boxUL" => [0x0255D], "boxUR" => [0x0255A], "boxUl" => [0x0255C], "boxUr" => [0x02559], "boxV" => [0x02551], "boxVH" => [0x0256C], "boxVL" => [0x02563], "boxVR" => [0x02560], "boxVh" => [0x0256B], "boxVl" => [0x02562], "boxVr" => [0x0255F], "boxbox" => [0x029C9], "boxdL" => [0x02555], "boxdR" => [0x02552], "boxdl" => [0x02510], "boxdr" => [0x0250C], "boxh" => [0x02500], "boxhD" => [0x02565], "boxhU" => [0x02568], "boxhd" => [0x0252C], "boxhu" => [0x02534], "boxminus" => [0x0229F], "boxplus" => [0x0229E], "boxtimes" => [0x022A0], "boxuL" => [0x0255B], "boxuR" => [0x02558], "boxul" => [0x02518], "boxur" => [0x02514], "boxv" => [0x02502], "boxvH" => [0x0256A], "boxvL" => [0x02561], "boxvR" => [0x0255E], "boxvh" => [0x0253C], "boxvl" => [0x02524], "boxvr" => [0x0251C], "bprime" => [0x02035], "breve" => [0x002D8], "brvbar" => [0x000A6], "bscr" => [0x1D4B7], "bsemi" => [0x0204F], "bsim" => [0x0223D], "bsime" => [0x022CD], "bsol" => [0x0005C], "bsolb" => [0x029C5], "bsolhsub" => [0x027C8], "bull" => [0x02022], "bullet" => [0x02022], "bump" => [0x0224E], "bumpE" => [0x02AAE], "bumpe" => [0x0224F], "bumpeq" => [0x0224F], "cacute" => [0x00107], "cap" => [0x02229], "capand" => [0x02A44], "capbrcup" => [0x02A49], "capcap" => [0x02A4B], "capcup" => [0x02A47], "capdot" => [0x02A40], "caps" => [0x02229, 0x0FE00], "caret" => [0x02041], "caron" => [0x002C7], "ccaps" => [0x02A4D], "ccaron" => [0x0010D], "ccedil" => [0x000E7], "ccirc" => [0x00109], "ccups" => [0x02A4C], "ccupssm" => [0x02A50], "cdot" => [0x0010B], "cedil" => [0x000B8], "cemptyv" => [0x029B2], "cent" => [0x000A2], "centerdot" => [0x000B7], "cfr" => [0x1D520], "chcy" => [0x00447], "check" => [0x02713], "checkmark" => [0x02713], "chi" => [0x003C7], "cir" => [0x025CB], "cirE" => [0x029C3], "circ" => [0x002C6], "circeq" => [0x02257], "circlearrowleft" => [0x021BA], "circlearrowright" => [0x021BB], "circledR" => [0x000AE], "circledS" => [0x024C8], "circledast" => [0x0229B], "circledcirc" => [0x0229A], "circleddash" => [0x0229D], "cire" => [0x02257], "cirfnint" => [0x02A10], "cirmid" => [0x02AEF], "cirscir" => [0x029C2], "clubs" => [0x02663], "clubsuit" => [0x02663], "colon" => [0x0003A], "colone" => [0x02254], "coloneq" => [0x02254], "comma" => [0x0002C], "commat" => [0x00040], "comp" => [0x02201], "compfn" => [0x02218], "complement" => [0x02201], "complexes" => [0x02102], "cong" => [0x02245], "congdot" => [0x02A6D], "conint" => [0x0222E], "copf" => [0x1D554], "coprod" => [0x02210], "copy" => [0x000A9], "copysr" => [0x02117], "crarr" => [0x021B5], "cross" => [0x02717], "cscr" => [0x1D4B8], "csub" => [0x02ACF], "csube" => [0x02AD1], "csup" => [0x02AD0], "csupe" => [0x02AD2], "ctdot" => [0x022EF], "cudarrl" => [0x02938], "cudarrr" => [0x02935], "cuepr" => [0x022DE], "cuesc" => [0x022DF], "cularr" => [0x021B6], "cularrp" => [0x0293D], "cup" => [0x0222A], "cupbrcap" => [0x02A48], "cupcap" => [0x02A46], "cupcup" => [0x02A4A], "cupdot" => [0x0228D], "cupor" => [0x02A45], "cups" => [0x0222A, 0x0FE00], "curarr" => [0x021B7], "curarrm" => [0x0293C], "curlyeqprec" => [0x022DE], "curlyeqsucc" => [0x022DF], "curlyvee" => [0x022CE], "curlywedge" => [0x022CF], "curren" => [0x000A4], "curvearrowleft" => [0x021B6], "curvearrowright" => [0x021B7], "cuvee" => [0x022CE], "cuwed" => [0x022CF], "cwconint" => [0x02232], "cwint" => [0x02231], "cylcty" => [0x0232D], "dArr" => [0x021D3], "dHar" => [0x02965], "dagger" => [0x02020], "daleth" => [0x02138], "darr" => [0x02193], "dash" => [0x02010], "dashv" => [0x022A3], "dbkarow" => [0x0290F], "dblac" => [0x002DD], "dcaron" => [0x0010F], "dcy" => [0x00434], "dd" => [0x02146], "ddagger" => [0x02021], "ddarr" => [0x021CA], "ddotseq" => [0x02A77], "deg" => [0x000B0], "delta" => [0x003B4], "demptyv" => [0x029B1], "dfisht" => [0x0297F], "dfr" => [0x1D521], "dharl" => [0x021C3], "dharr" => [0x021C2], "diam" => [0x022C4], "diamond" => [0x022C4], "diamondsuit" => [0x02666], "diams" => [0x02666], "die" => [0x000A8], "digamma" => [0x003DD], "disin" => [0x022F2], "div" => [0x000F7], "divide" => [0x000F7], "divideontimes" => [0x022C7], "divonx" => [0x022C7], "djcy" => [0x00452], "dlcorn" => [0x0231E], "dlcrop" => [0x0230D], "dollar" => [0x00024], "dopf" => [0x1D555], "dot" => [0x002D9], "doteq" => [0x02250], "doteqdot" => [0x02251], "dotminus" => [0x02238], "dotplus" => [0x02214], "dotsquare" => [0x022A1], "doublebarwedge" => [0x02306], "downarrow" => [0x02193], "downdownarrows" => [0x021CA], "downharpoonleft" => [0x021C3], "downharpoonright" => [0x021C2], "drbkarow" => [0x02910], "drcorn" => [0x0231F], "drcrop" => [0x0230C], "dscr" => [0x1D4B9], "dscy" => [0x00455], "dsol" => [0x029F6], "dstrok" => [0x00111], "dtdot" => [0x022F1], "dtri" => [0x025BF], "dtrif" => [0x025BE], "duarr" => [0x021F5], "duhar" => [0x0296F], "dwangle" => [0x029A6], "dzcy" => [0x0045F], "dzigrarr" => [0x027FF], "eDDot" => [0x02A77], "eDot" => [0x02251], "eacute" => [0x000E9], "easter" => [0x02A6E], "ecaron" => [0x0011B], "ecir" => [0x02256], "ecirc" => [0x000EA], "ecolon" => [0x02255], "ecy" => [0x0044D], "edot" => [0x00117], "ee" => [0x02147], "efDot" => [0x02252], "efr" => [0x1D522], "eg" => [0x02A9A], "egrave" => [0x000E8], "egs" => [0x02A96], "egsdot" => [0x02A98], "el" => [0x02A99], "elinters" => [0x023E7], "ell" => [0x02113], "els" => [0x02A95], "elsdot" => [0x02A97], "emacr" => [0x00113], "empty" => [0x02205], "emptyset" => [0x02205], "emptyv" => [0x02205], "emsp" => [0x02003], "emsp13" => [0x02004], "emsp14" => [0x02005], "eng" => [0x0014B], "ensp" => [0x02002], "eogon" => [0x00119], "eopf" => [0x1D556], "epar" => [0x022D5], "eparsl" => [0x029E3], "eplus" => [0x02A71], "epsi" => [0x003B5], "epsilon" => [0x003B5], "epsiv" => [0x003F5], "eqcirc" => [0x02256], "eqcolon" => [0x02255], "eqsim" => [0x02242], "eqslantgtr" => [0x02A96], "eqslantless" => [0x02A95], "equals" => [0x0003D], "equest" => [0x0225F], "equiv" => [0x02261], "equivDD" => [0x02A78], "eqvparsl" => [0x029E5], "erDot" => [0x02253], "erarr" => [0x02971], "escr" => [0x0212F], "esdot" => [0x02250], "esim" => [0x02242], "eta" => [0x003B7], "eth" => [0x000F0], "euml" => [0x000EB], "euro" => [0x020AC], "excl" => [0x00021], "exist" => [0x02203], "expectation" => [0x02130], "exponentiale" => [0x02147], "fallingdotseq" => [0x02252], "fcy" => [0x00444], "female" => [0x02640], "ffilig" => [0x0FB03], "fflig" => [0x0FB00], "ffllig" => [0x0FB04], "ffr" => [0x1D523], "filig" => [0x0FB01], "fjlig" => [0x00066, 0x0006A], "flat" => [0x0266D], "fllig" => [0x0FB02], "fltns" => [0x025B1], "fnof" => [0x00192], "fopf" => [0x1D557], "forall" => [0x02200], "fork" => [0x022D4], "forkv" => [0x02AD9], "fpartint" => [0x02A0D], "frac12" => [0x000BD], "frac13" => [0x02153], "frac14" => [0x000BC], "frac15" => [0x02155], "frac16" => [0x02159], "frac18" => [0x0215B], "frac23" => [0x02154], "frac25" => [0x02156], "frac34" => [0x000BE], "frac35" => [0x02157], "frac38" => [0x0215C], "frac45" => [0x02158], "frac56" => [0x0215A], "frac58" => [0x0215D], "frac78" => [0x0215E], "frasl" => [0x02044], "frown" => [0x02322], "fscr" => [0x1D4BB], "gE" => [0x02267], "gEl" => [0x02A8C], "gacute" => [0x001F5], "gamma" => [0x003B3], "gammad" => [0x003DD], "gap" => [0x02A86], "gbreve" => [0x0011F], "gcirc" => [0x0011D], "gcy" => [0x00433], "gdot" => [0x00121], "ge" => [0x02265], "gel" => [0x022DB], "geq" => [0x02265], "geqq" => [0x02267], "geqslant" => [0x02A7E], "ges" => [0x02A7E], "gescc" => [0x02AA9], "gesdot" => [0x02A80], "gesdoto" => [0x02A82], "gesdotol" => [0x02A84], "gesl" => [0x022DB, 0x0FE00], "gesles" => [0x02A94], "gfr" => [0x1D524], "gg" => [0x0226B], "ggg" => [0x022D9], "gimel" => [0x02137], "gjcy" => [0x00453], "gl" => [0x02277], "glE" => [0x02A92], "gla" => [0x02AA5], "glj" => [0x02AA4], "gnE" => [0x02269], "gnap" => [0x02A8A], "gnapprox" => [0x02A8A], "gne" => [0x02A88], "gneq" => [0x02A88], "gneqq" => [0x02269], "gnsim" => [0x022E7], "gopf" => [0x1D558], "grave" => [0x00060], "gscr" => [0x0210A], "gsim" => [0x02273], "gsime" => [0x02A8E], "gsiml" => [0x02A90], "gt" => [0x0003E], "gtcc" => [0x02AA7], "gtcir" => [0x02A7A], "gtdot" => [0x022D7], "gtlPar" => [0x02995], "gtquest" => [0x02A7C], "gtrapprox" => [0x02A86], "gtrarr" => [0x02978], "gtrdot" => [0x022D7], "gtreqless" => [0x022DB], "gtreqqless" => [0x02A8C], "gtrless" => [0x02277], "gtrsim" => [0x02273], "gvertneqq" => [0x02269, 0x0FE00], "gvnE" => [0x02269, 0x0FE00], "hArr" => [0x021D4], "hairsp" => [0x0200A], "half" => [0x000BD], "hamilt" => [0x0210B], "hardcy" => [0x0044A], "harr" => [0x02194], "harrcir" => [0x02948], "harrw" => [0x021AD], "hbar" => [0x0210F], "hcirc" => [0x00125], "hearts" => [0x02665], "heartsuit" => [0x02665], "hellip" => [0x02026], "hercon" => [0x022B9], "hfr" => [0x1D525], "hksearow" => [0x02925], "hkswarow" => [0x02926], "hoarr" => [0x021FF], "homtht" => [0x0223B], "hookleftarrow" => [0x021A9], "hookrightarrow" => [0x021AA], "hopf" => [0x1D559], "horbar" => [0x02015], "hscr" => [0x1D4BD], "hslash" => [0x0210F], "hstrok" => [0x00127], "hybull" => [0x02043], "hyphen" => [0x02010], "iacute" => [0x000ED], "ic" => [0x02063], "icirc" => [0x000EE], "icy" => [0x00438], "iecy" => [0x00435], "iexcl" => [0x000A1], "iff" => [0x021D4], "ifr" => [0x1D526], "igrave" => [0x000EC], "ii" => [0x02148], "iiiint" => [0x02A0C], "iiint" => [0x0222D], "iinfin" => [0x029DC], "iiota" => [0x02129], "ijlig" => [0x00133], "imacr" => [0x0012B], "image" => [0x02111], "imagline" => [0x02110], "imagpart" => [0x02111], "imath" => [0x00131], "imof" => [0x022B7], "imped" => [0x001B5], "in" => [0x02208], "incare" => [0x02105], "infin" => [0x0221E], "infintie" => [0x029DD], "inodot" => [0x00131], "int" => [0x0222B], "intcal" => [0x022BA], "integers" => [0x02124], "intercal" => [0x022BA], "intlarhk" => [0x02A17], "intprod" => [0x02A3C], "iocy" => [0x00451], "iogon" => [0x0012F], "iopf" => [0x1D55A], "iota" => [0x003B9], "iprod" => [0x02A3C], "iquest" => [0x000BF], "iscr" => [0x1D4BE], "isin" => [0x02208], "isinE" => [0x022F9], "isindot" => [0x022F5], "isins" => [0x022F4], "isinsv" => [0x022F3], "isinv" => [0x02208], "it" => [0x02062], "itilde" => [0x00129], "iukcy" => [0x00456], "iuml" => [0x000EF], "jcirc" => [0x00135], "jcy" => [0x00439], "jfr" => [0x1D527], "jmath" => [0x00237], "jopf" => [0x1D55B], "jscr" => [0x1D4BF], "jsercy" => [0x00458], "jukcy" => [0x00454], "kappa" => [0x003BA], "kappav" => [0x003F0], "kcedil" => [0x00137], "kcy" => [0x0043A], "kfr" => [0x1D528], "kgreen" => [0x00138], "khcy" => [0x00445], "kjcy" => [0x0045C], "kopf" => [0x1D55C], "kscr" => [0x1D4C0], "lAarr" => [0x021DA], "lArr" => [0x021D0], "lAtail" => [0x0291B], "lBarr" => [0x0290E], "lE" => [0x02266], "lEg" => [0x02A8B], "lHar" => [0x02962], "lacute" => [0x0013A], "laemptyv" => [0x029B4], "lagran" => [0x02112], "lambda" => [0x003BB], "lang" => [0x027E8], "langd" => [0x02991], "langle" => [0x027E8], "lap" => [0x02A85], "laquo" => [0x000AB], "larr" => [0x02190], "larrb" => [0x021E4], "larrbfs" => [0x0291F], "larrfs" => [0x0291D], "larrhk" => [0x021A9], "larrlp" => [0x021AB], "larrpl" => [0x02939], "larrsim" => [0x02973], "larrtl" => [0x021A2], "lat" => [0x02AAB], "latail" => [0x02919], "late" => [0x02AAD], "lates" => [0x02AAD, 0x0FE00], "lbarr" => [0x0290C], "lbbrk" => [0x02772], "lbrace" => [0x0007B], "lbrack" => [0x0005B], "lbrke" => [0x0298B], "lbrksld" => [0x0298F], "lbrkslu" => [0x0298D], "lcaron" => [0x0013E], "lcedil" => [0x0013C], "lceil" => [0x02308], "lcub" => [0x0007B], "lcy" => [0x0043B], "ldca" => [0x02936], "ldquo" => [0x0201C], "ldquor" => [0x0201E], "ldrdhar" => [0x02967], "ldrushar" => [0x0294B], "ldsh" => [0x021B2], "le" => [0x02264], "leftarrow" => [0x02190], "leftarrowtail" => [0x021A2], "leftharpoondown" => [0x021BD], "leftharpoonup" => [0x021BC], "leftleftarrows" => [0x021C7], "leftrightarrow" => [0x02194], "leftrightarrows" => [0x021C6], "leftrightharpoons" => [0x021CB], "leftrightsquigarrow" => [0x021AD], "leftthreetimes" => [0x022CB], "leg" => [0x022DA], "leq" => [0x02264], "leqq" => [0x02266], "leqslant" => [0x02A7D], "les" => [0x02A7D], "lescc" => [0x02AA8], "lesdot" => [0x02A7F], "lesdoto" => [0x02A81], "lesdotor" => [0x02A83], "lesg" => [0x022DA, 0x0FE00], "lesges" => [0x02A93], "lessapprox" => [0x02A85], "lessdot" => [0x022D6], "lesseqgtr" => [0x022DA], "lesseqqgtr" => [0x02A8B], "lessgtr" => [0x02276], "lesssim" => [0x02272], "lfisht" => [0x0297C], "lfloor" => [0x0230A], "lfr" => [0x1D529], "lg" => [0x02276], "lgE" => [0x02A91], "lhard" => [0x021BD], "lharu" => [0x021BC], "lharul" => [0x0296A], "lhblk" => [0x02584], "ljcy" => [0x00459], "ll" => [0x0226A], "llarr" => [0x021C7], "llcorner" => [0x0231E], "llhard" => [0x0296B], "lltri" => [0x025FA], "lmidot" => [0x00140], "lmoust" => [0x023B0], "lmoustache" => [0x023B0], "lnE" => [0x02268], "lnap" => [0x02A89], "lnapprox" => [0x02A89], "lne" => [0x02A87], "lneq" => [0x02A87], "lneqq" => [0x02268], "lnsim" => [0x022E6], "loang" => [0x027EC], "loarr" => [0x021FD], "lobrk" => [0x027E6], "longleftarrow" => [0x027F5], "longleftrightarrow" => [0x027F7], "longmapsto" => [0x027FC], "longrightarrow" => [0x027F6], "looparrowleft" => [0x021AB], "looparrowright" => [0x021AC], "lopar" => [0x02985], "lopf" => [0x1D55D], "loplus" => [0x02A2D], "lotimes" => [0x02A34], "lowast" => [0x02217], "lowbar" => [0x0005F], "loz" => [0x025CA], "lozenge" => [0x025CA], "lozf" => [0x029EB], "lpar" => [0x00028], "lparlt" => [0x02993], "lrarr" => [0x021C6], "lrcorner" => [0x0231F], "lrhar" => [0x021CB], "lrhard" => [0x0296D], "lrm" => [0x0200E], "lrtri" => [0x022BF], "lsaquo" => [0x02039], "lscr" => [0x1D4C1], "lsh" => [0x021B0], "lsim" => [0x02272], "lsime" => [0x02A8D], "lsimg" => [0x02A8F], "lsqb" => [0x0005B], "lsquo" => [0x02018], "lsquor" => [0x0201A], "lstrok" => [0x00142], "lt" => [0x0003C], "ltcc" => [0x02AA6], "ltcir" => [0x02A79], "ltdot" => [0x022D6], "lthree" => [0x022CB], "ltimes" => [0x022C9], "ltlarr" => [0x02976], "ltquest" => [0x02A7B], "ltrPar" => [0x02996], "ltri" => [0x025C3], "ltrie" => [0x022B4], "ltrif" => [0x025C2], "lurdshar" => [0x0294A], "luruhar" => [0x02966], "lvertneqq" => [0x02268, 0x0FE00], "lvnE" => [0x02268, 0x0FE00], "mDDot" => [0x0223A], "macr" => [0x000AF], "male" => [0x02642], "malt" => [0x02720], "maltese" => [0x02720], "map" => [0x021A6], "mapsto" => [0x021A6], "mapstodown" => [0x021A7], "mapstoleft" => [0x021A4], "mapstoup" => [0x021A5], "marker" => [0x025AE], "mcomma" => [0x02A29], "mcy" => [0x0043C], "mdash" => [0x02014], "measuredangle" => [0x02221], "mfr" => [0x1D52A], "mho" => [0x02127], "micro" => [0x000B5], "mid" => [0x02223], "midast" => [0x0002A], "midcir" => [0x02AF0], "middot" => [0x000B7], "minus" => [0x02212], "minusb" => [0x0229F], "minusd" => [0x02238], "minusdu" => [0x02A2A], "mlcp" => [0x02ADB], "mldr" => [0x02026], "mnplus" => [0x02213], "models" => [0x022A7], "mopf" => [0x1D55E], "mp" => [0x02213], "mscr" => [0x1D4C2], "mstpos" => [0x0223E], "mu" => [0x003BC], "multimap" => [0x022B8], "mumap" => [0x022B8], "nGg" => [0x022D9, 0x00338], "nGt" => [0x0226B, 0x020D2], "nGtv" => [0x0226B, 0x00338], "nLeftarrow" => [0x021CD], "nLeftrightarrow" => [0x021CE], "nLl" => [0x022D8, 0x00338], "nLt" => [0x0226A, 0x020D2], "nLtv" => [0x0226A, 0x00338], "nRightarrow" => [0x021CF], "nVDash" => [0x022AF], "nVdash" => [0x022AE], "nabla" => [0x02207], "nacute" => [0x00144], "nang" => [0x02220, 0x020D2], "nap" => [0x02249], "napE" => [0x02A70, 0x00338], "napid" => [0x0224B, 0x00338], "napos" => [0x00149], "napprox" => [0x02249], "natur" => [0x0266E], "natural" => [0x0266E], "naturals" => [0x02115], "nbsp" => [0x000A0], "nbump" => [0x0224E, 0x00338], "nbumpe" => [0x0224F, 0x00338], "ncap" => [0x02A43], "ncaron" => [0x00148], "ncedil" => [0x00146], "ncong" => [0x02247], "ncongdot" => [0x02A6D, 0x00338], "ncup" => [0x02A42], "ncy" => [0x0043D], "ndash" => [0x02013], "ne" => [0x02260], "neArr" => [0x021D7], "nearhk" => [0x02924], "nearr" => [0x02197], "nearrow" => [0x02197], "nedot" => [0x02250, 0x00338], "nequiv" => [0x02262], "nesear" => [0x02928], "nesim" => [0x02242, 0x00338], "nexist" => [0x02204], "nexists" => [0x02204], "nfr" => [0x1D52B], "ngE" => [0x02267, 0x00338], "nge" => [0x02271], "ngeq" => [0x02271], "ngeqq" => [0x02267, 0x00338], "ngeqslant" => [0x02A7E, 0x00338], "nges" => [0x02A7E, 0x00338], "ngsim" => [0x02275], "ngt" => [0x0226F], "ngtr" => [0x0226F], "nhArr" => [0x021CE], "nharr" => [0x021AE], "nhpar" => [0x02AF2], "ni" => [0x0220B], "nis" => [0x022FC], "nisd" => [0x022FA], "niv" => [0x0220B], "njcy" => [0x0045A], "nlArr" => [0x021CD], "nlE" => [0x02266, 0x00338], "nlarr" => [0x0219A], "nldr" => [0x02025], "nle" => [0x02270], "nleftarrow" => [0x0219A], "nleftrightarrow" => [0x021AE], "nleq" => [0x02270], "nleqq" => [0x02266, 0x00338], "nleqslant" => [0x02A7D, 0x00338], "nles" => [0x02A7D, 0x00338], "nless" => [0x0226E], "nlsim" => [0x02274], "nlt" => [0x0226E], "nltri" => [0x022EA], "nltrie" => [0x022EC], "nmid" => [0x02224], "nopf" => [0x1D55F], "not" => [0x000AC], "notin" => [0x02209], "notinE" => [0x022F9, 0x00338], "notindot" => [0x022F5, 0x00338], "notinva" => [0x02209], "notinvb" => [0x022F7], "notinvc" => [0x022F6], "notni" => [0x0220C], "notniva" => [0x0220C], "notnivb" => [0x022FE], "notnivc" => [0x022FD], "npar" => [0x02226], "nparallel" => [0x02226], "nparsl" => [0x02AFD, 0x020E5], "npart" => [0x02202, 0x00338], "npolint" => [0x02A14], "npr" => [0x02280], "nprcue" => [0x022E0], "npre" => [0x02AAF, 0x00338], "nprec" => [0x02280], "npreceq" => [0x02AAF, 0x00338], "nrArr" => [0x021CF], "nrarr" => [0x0219B], "nrarrc" => [0x02933, 0x00338], "nrarrw" => [0x0219D, 0x00338], "nrightarrow" => [0x0219B], "nrtri" => [0x022EB], "nrtrie" => [0x022ED], "nsc" => [0x02281], "nsccue" => [0x022E1], "nsce" => [0x02AB0, 0x00338], "nscr" => [0x1D4C3], "nshortmid" => [0x02224], "nshortparallel" => [0x02226], "nsim" => [0x02241], "nsime" => [0x02244], "nsimeq" => [0x02244], "nsmid" => [0x02224], "nspar" => [0x02226], "nsqsube" => [0x022E2], "nsqsupe" => [0x022E3], "nsub" => [0x02284], "nsubE" => [0x02AC5, 0x00338], "nsube" => [0x02288], "nsubset" => [0x02282, 0x020D2], "nsubseteq" => [0x02288], "nsubseteqq" => [0x02AC5, 0x00338], "nsucc" => [0x02281], "nsucceq" => [0x02AB0, 0x00338], "nsup" => [0x02285], "nsupE" => [0x02AC6, 0x00338], "nsupe" => [0x02289], "nsupset" => [0x02283, 0x020D2], "nsupseteq" => [0x02289], "nsupseteqq" => [0x02AC6, 0x00338], "ntgl" => [0x02279], "ntilde" => [0x000F1], "ntlg" => [0x02278], "ntriangleleft" => [0x022EA], "ntrianglelefteq" => [0x022EC], "ntriangleright" => [0x022EB], "ntrianglerighteq" => [0x022ED], "nu" => [0x003BD], "num" => [0x00023], "numero" => [0x02116], "numsp" => [0x02007], "nvDash" => [0x022AD], "nvHarr" => [0x02904], "nvap" => [0x0224D, 0x020D2], "nvdash" => [0x022AC], "nvge" => [0x02265, 0x020D2], "nvgt" => [0x0003E, 0x020D2], "nvinfin" => [0x029DE], "nvlArr" => [0x02902], "nvle" => [0x02264, 0x020D2], "nvlt" => [0x0003C, 0x020D2], "nvltrie" => [0x022B4, 0x020D2], "nvrArr" => [0x02903], "nvrtrie" => [0x022B5, 0x020D2], "nvsim" => [0x0223C, 0x020D2], "nwArr" => [0x021D6], "nwarhk" => [0x02923], "nwarr" => [0x02196], "nwarrow" => [0x02196], "nwnear" => [0x02927], "oS" => [0x024C8], "oacute" => [0x000F3], "oast" => [0x0229B], "ocir" => [0x0229A], "ocirc" => [0x000F4], "ocy" => [0x0043E], "odash" => [0x0229D], "odblac" => [0x00151], "odiv" => [0x02A38], "odot" => [0x02299], "odsold" => [0x029BC], "oelig" => [0x00153], "ofcir" => [0x029BF], "ofr" => [0x1D52C], "ogon" => [0x002DB], "ograve" => [0x000F2], "ogt" => [0x029C1], "ohbar" => [0x029B5], "ohm" => [0x003A9], "oint" => [0x0222E], "olarr" => [0x021BA], "olcir" => [0x029BE], "olcross" => [0x029BB], "oline" => [0x0203E], "olt" => [0x029C0], "omacr" => [0x0014D], "omega" => [0x003C9], "omicron" => [0x003BF], "omid" => [0x029B6], "ominus" => [0x02296], "oopf" => [0x1D560], "opar" => [0x029B7], "operp" => [0x029B9], "oplus" => [0x02295], "or" => [0x02228], "orarr" => [0x021BB], "ord" => [0x02A5D], "order" => [0x02134], "orderof" => [0x02134], "ordf" => [0x000AA], "ordm" => [0x000BA], "origof" => [0x022B6], "oror" => [0x02A56], "orslope" => [0x02A57], "orv" => [0x02A5B], "oscr" => [0x02134], "oslash" => [0x000F8], "osol" => [0x02298], "otilde" => [0x000F5], "otimes" => [0x02297], "otimesas" => [0x02A36], "ouml" => [0x000F6], "ovbar" => [0x0233D], "par" => [0x02225], "para" => [0x000B6], "parallel" => [0x02225], "parsim" => [0x02AF3], "parsl" => [0x02AFD], "part" => [0x02202], "pcy" => [0x0043F], "percnt" => [0x00025], "period" => [0x0002E], "permil" => [0x02030], "perp" => [0x022A5], "pertenk" => [0x02031], "pfr" => [0x1D52D], "phi" => [0x003C6], "phiv" => [0x003D5], "phmmat" => [0x02133], "phone" => [0x0260E], "pi" => [0x003C0], "pitchfork" => [0x022D4], "piv" => [0x003D6], "planck" => [0x0210F], "planckh" => [0x0210E], "plankv" => [0x0210F], "plus" => [0x0002B], "plusacir" => [0x02A23], "plusb" => [0x0229E], "pluscir" => [0x02A22], "plusdo" => [0x02214], "plusdu" => [0x02A25], "pluse" => [0x02A72], "plusmn" => [0x000B1], "plussim" => [0x02A26], "plustwo" => [0x02A27], "pm" => [0x000B1], "pointint" => [0x02A15], "popf" => [0x1D561], "pound" => [0x000A3], "pr" => [0x0227A], "prE" => [0x02AB3], "prap" => [0x02AB7], "prcue" => [0x0227C], "pre" => [0x02AAF], "prec" => [0x0227A], "precapprox" => [0x02AB7], "preccurlyeq" => [0x0227C], "preceq" => [0x02AAF], "precnapprox" => [0x02AB9], "precneqq" => [0x02AB5], "precnsim" => [0x022E8], "precsim" => [0x0227E], "prime" => [0x02032], "primes" => [0x02119], "prnE" => [0x02AB5], "prnap" => [0x02AB9], "prnsim" => [0x022E8], "prod" => [0x0220F], "profalar" => [0x0232E], "profline" => [0x02312], "profsurf" => [0x02313], "prop" => [0x0221D], "propto" => [0x0221D], "prsim" => [0x0227E], "prurel" => [0x022B0], "pscr" => [0x1D4C5], "psi" => [0x003C8], "puncsp" => [0x02008], "qfr" => [0x1D52E], "qint" => [0x02A0C], "qopf" => [0x1D562], "qprime" => [0x02057], "qscr" => [0x1D4C6], "quaternions" => [0x0210D], "quatint" => [0x02A16], "quest" => [0x0003F], "questeq" => [0x0225F], "quot" => [0x00022], "rAarr" => [0x021DB], "rArr" => [0x021D2], "rAtail" => [0x0291C], "rBarr" => [0x0290F], "rHar" => [0x02964], "race" => [0x0223D, 0x00331], "racute" => [0x00155], "radic" => [0x0221A], "raemptyv" => [0x029B3], "rang" => [0x027E9], "rangd" => [0x02992], "range" => [0x029A5], "rangle" => [0x027E9], "raquo" => [0x000BB], "rarr" => [0x02192], "rarrap" => [0x02975], "rarrb" => [0x021E5], "rarrbfs" => [0x02920], "rarrc" => [0x02933], "rarrfs" => [0x0291E], "rarrhk" => [0x021AA], "rarrlp" => [0x021AC], "rarrpl" => [0x02945], "rarrsim" => [0x02974], "rarrtl" => [0x021A3], "rarrw" => [0x0219D], "ratail" => [0x0291A], "ratio" => [0x02236], "rationals" => [0x0211A], "rbarr" => [0x0290D], "rbbrk" => [0x02773], "rbrace" => [0x0007D], "rbrack" => [0x0005D], "rbrke" => [0x0298C], "rbrksld" => [0x0298E], "rbrkslu" => [0x02990], "rcaron" => [0x00159], "rcedil" => [0x00157], "rceil" => [0x02309], "rcub" => [0x0007D], "rcy" => [0x00440], "rdca" => [0x02937], "rdldhar" => [0x02969], "rdquo" => [0x0201D], "rdquor" => [0x0201D], "rdsh" => [0x021B3], "real" => [0x0211C], "realine" => [0x0211B], "realpart" => [0x0211C], "reals" => [0x0211D], "rect" => [0x025AD], "reg" => [0x000AE], "rfisht" => [0x0297D], "rfloor" => [0x0230B], "rfr" => [0x1D52F], "rhard" => [0x021C1], "rharu" => [0x021C0], "rharul" => [0x0296C], "rho" => [0x003C1], "rhov" => [0x003F1], "rightarrow" => [0x02192], "rightarrowtail" => [0x021A3], "rightharpoondown" => [0x021C1], "rightharpoonup" => [0x021C0], "rightleftarrows" => [0x021C4], "rightleftharpoons" => [0x021CC], "rightrightarrows" => [0x021C9], "rightsquigarrow" => [0x0219D], "rightthreetimes" => [0x022CC], "ring" => [0x002DA], "risingdotseq" => [0x02253], "rlarr" => [0x021C4], "rlhar" => [0x021CC], "rlm" => [0x0200F], "rmoust" => [0x023B1], "rmoustache" => [0x023B1], "rnmid" => [0x02AEE], "roang" => [0x027ED], "roarr" => [0x021FE], "robrk" => [0x027E7], "ropar" => [0x02986], "ropf" => [0x1D563], "roplus" => [0x02A2E], "rotimes" => [0x02A35], "rpar" => [0x00029], "rpargt" => [0x02994], "rppolint" => [0x02A12], "rrarr" => [0x021C9], "rsaquo" => [0x0203A], "rscr" => [0x1D4C7], "rsh" => [0x021B1], "rsqb" => [0x0005D], "rsquo" => [0x02019], "rsquor" => [0x02019], "rthree" => [0x022CC], "rtimes" => [0x022CA], "rtri" => [0x025B9], "rtrie" => [0x022B5], "rtrif" => [0x025B8], "rtriltri" => [0x029CE], "ruluhar" => [0x02968], "rx" => [0x0211E], "sacute" => [0x0015B], "sbquo" => [0x0201A], "sc" => [0x0227B], "scE" => [0x02AB4], "scap" => [0x02AB8], "scaron" => [0x00161], "sccue" => [0x0227D], "sce" => [0x02AB0], "scedil" => [0x0015F], "scirc" => [0x0015D], "scnE" => [0x02AB6], "scnap" => [0x02ABA], "scnsim" => [0x022E9], "scpolint" => [0x02A13], "scsim" => [0x0227F], "scy" => [0x00441], "sdot" => [0x022C5], "sdotb" => [0x022A1], "sdote" => [0x02A66], "seArr" => [0x021D8], "searhk" => [0x02925], "searr" => [0x02198], "searrow" => [0x02198], "sect" => [0x000A7], "semi" => [0x0003B], "seswar" => [0x02929], "setminus" => [0x02216], "setmn" => [0x02216], "sext" => [0x02736], "sfr" => [0x1D530], "sfrown" => [0x02322], "sharp" => [0x0266F], "shchcy" => [0x00449], "shcy" => [0x00448], "shortmid" => [0x02223], "shortparallel" => [0x02225], "shy" => [0x000AD], "sigma" => [0x003C3], "sigmaf" => [0x003C2], "sigmav" => [0x003C2], "sim" => [0x0223C], "simdot" => [0x02A6A], "sime" => [0x02243], "simeq" => [0x02243], "simg" => [0x02A9E], "simgE" => [0x02AA0], "siml" => [0x02A9D], "simlE" => [0x02A9F], "simne" => [0x02246], "simplus" => [0x02A24], "simrarr" => [0x02972], "slarr" => [0x02190], "smallsetminus" => [0x02216], "smashp" => [0x02A33], "smeparsl" => [0x029E4], "smid" => [0x02223], "smile" => [0x02323], "smt" => [0x02AAA], "smte" => [0x02AAC], "smtes" => [0x02AAC, 0x0FE00], "softcy" => [0x0044C], "sol" => [0x0002F], "solb" => [0x029C4], "solbar" => [0x0233F], "sopf" => [0x1D564], "spades" => [0x02660], "spadesuit" => [0x02660], "spar" => [0x02225], "sqcap" => [0x02293], "sqcaps" => [0x02293, 0x0FE00], "sqcup" => [0x02294], "sqcups" => [0x02294, 0x0FE00], "sqsub" => [0x0228F], "sqsube" => [0x02291], "sqsubset" => [0x0228F], "sqsubseteq" => [0x02291], "sqsup" => [0x02290], "sqsupe" => [0x02292], "sqsupset" => [0x02290], "sqsupseteq" => [0x02292], "squ" => [0x025A1], "square" => [0x025A1], "squarf" => [0x025AA], "squf" => [0x025AA], "srarr" => [0x02192], "sscr" => [0x1D4C8], "ssetmn" => [0x02216], "ssmile" => [0x02323], "sstarf" => [0x022C6], "star" => [0x02606], "starf" => [0x02605], "straightepsilon" => [0x003F5], "straightphi" => [0x003D5], "strns" => [0x000AF], "sub" => [0x02282], "subE" => [0x02AC5], "subdot" => [0x02ABD], "sube" => [0x02286], "subedot" => [0x02AC3], "submult" => [0x02AC1], "subnE" => [0x02ACB], "subne" => [0x0228A], "subplus" => [0x02ABF], "subrarr" => [0x02979], "subset" => [0x02282], "subseteq" => [0x02286], "subseteqq" => [0x02AC5], "subsetneq" => [0x0228A], "subsetneqq" => [0x02ACB], "subsim" => [0x02AC7], "subsub" => [0x02AD5], "subsup" => [0x02AD3], "succ" => [0x0227B], "succapprox" => [0x02AB8], "succcurlyeq" => [0x0227D], "succeq" => [0x02AB0], "succnapprox" => [0x02ABA], "succneqq" => [0x02AB6], "succnsim" => [0x022E9], "succsim" => [0x0227F], "sum" => [0x02211], "sung" => [0x0266A], "sup" => [0x02283], "sup1" => [0x000B9], "sup2" => [0x000B2], "sup3" => [0x000B3], "supE" => [0x02AC6], "supdot" => [0x02ABE], "supdsub" => [0x02AD8], "supe" => [0x02287], "supedot" => [0x02AC4], "suphsol" => [0x027C9], "suphsub" => [0x02AD7], "suplarr" => [0x0297B], "supmult" => [0x02AC2], "supnE" => [0x02ACC], "supne" => [0x0228B], "supplus" => [0x02AC0], "supset" => [0x02283], "supseteq" => [0x02287], "supseteqq" => [0x02AC6], "supsetneq" => [0x0228B], "supsetneqq" => [0x02ACC], "supsim" => [0x02AC8], "supsub" => [0x02AD4], "supsup" => [0x02AD6], "swArr" => [0x021D9], "swarhk" => [0x02926], "swarr" => [0x02199], "swarrow" => [0x02199], "swnwar" => [0x0292A], "szlig" => [0x000DF], "target" => [0x02316], "tau" => [0x003C4], "tbrk" => [0x023B4], "tcaron" => [0x00165], "tcedil" => [0x00163], "tcy" => [0x00442], "tdot" => [0x020DB], "telrec" => [0x02315], "tfr" => [0x1D531], "there4" => [0x02234], "therefore" => [0x02234], "theta" => [0x003B8], "thetasym" => [0x003D1], "thetav" => [0x003D1], "thickapprox" => [0x02248], "thicksim" => [0x0223C], "thinsp" => [0x02009], "thkap" => [0x02248], "thksim" => [0x0223C], "thorn" => [0x000FE], "tilde" => [0x002DC], "times" => [0x000D7], "timesb" => [0x022A0], "timesbar" => [0x02A31], "timesd" => [0x02A30], "tint" => [0x0222D], "toea" => [0x02928], "top" => [0x022A4], "topbot" => [0x02336], "topcir" => [0x02AF1], "topf" => [0x1D565], "topfork" => [0x02ADA], "tosa" => [0x02929], "tprime" => [0x02034], "trade" => [0x02122], "triangle" => [0x025B5], "triangledown" => [0x025BF], "triangleleft" => [0x025C3], "trianglelefteq" => [0x022B4], "triangleq" => [0x0225C], "triangleright" => [0x025B9], "trianglerighteq" => [0x022B5], "tridot" => [0x025EC], "trie" => [0x0225C], "triminus" => [0x02A3A], "triplus" => [0x02A39], "trisb" => [0x029CD], "tritime" => [0x02A3B], "trpezium" => [0x023E2], "tscr" => [0x1D4C9], "tscy" => [0x00446], "tshcy" => [0x0045B], "tstrok" => [0x00167], "twixt" => [0x0226C], "twoheadleftarrow" => [0x0219E], "twoheadrightarrow" => [0x021A0], "uArr" => [0x021D1], "uHar" => [0x02963], "uacute" => [0x000FA], "uarr" => [0x02191], "ubrcy" => [0x0045E], "ubreve" => [0x0016D], "ucirc" => [0x000FB], "ucy" => [0x00443], "udarr" => [0x021C5], "udblac" => [0x00171], "udhar" => [0x0296E], "ufisht" => [0x0297E], "ufr" => [0x1D532], "ugrave" => [0x000F9], "uharl" => [0x021BF], "uharr" => [0x021BE], "uhblk" => [0x02580], "ulcorn" => [0x0231C], "ulcorner" => [0x0231C], "ulcrop" => [0x0230F], "ultri" => [0x025F8], "umacr" => [0x0016B], "uml" => [0x000A8], "uogon" => [0x00173], "uopf" => [0x1D566], "uparrow" => [0x02191], "updownarrow" => [0x02195], "upharpoonleft" => [0x021BF], "upharpoonright" => [0x021BE], "uplus" => [0x0228E], "upsi" => [0x003C5], "upsih" => [0x003D2], "upsilon" => [0x003C5], "upuparrows" => [0x021C8], "urcorn" => [0x0231D], "urcorner" => [0x0231D], "urcrop" => [0x0230E], "uring" => [0x0016F], "urtri" => [0x025F9], "uscr" => [0x1D4CA], "utdot" => [0x022F0], "utilde" => [0x00169], "utri" => [0x025B5], "utrif" => [0x025B4], "uuarr" => [0x021C8], "uuml" => [0x000FC], "uwangle" => [0x029A7], "vArr" => [0x021D5], "vBar" => [0x02AE8], "vBarv" => [0x02AE9], "vDash" => [0x022A8], "vangrt" => [0x0299C], "varepsilon" => [0x003F5], "varkappa" => [0x003F0], "varnothing" => [0x02205], "varphi" => [0x003D5], "varpi" => [0x003D6], "varpropto" => [0x0221D], "varr" => [0x02195], "varrho" => [0x003F1], "varsigma" => [0x003C2], "varsubsetneq" => [0x0228A, 0x0FE00], "varsubsetneqq" => [0x02ACB, 0x0FE00], "varsupsetneq" => [0x0228B, 0x0FE00], "varsupsetneqq" => [0x02ACC, 0x0FE00], "vartheta" => [0x003D1], "vartriangleleft" => [0x022B2], "vartriangleright" => [0x022B3], "vcy" => [0x00432], "vdash" => [0x022A2], "vee" => [0x02228], "veebar" => [0x022BB], "veeeq" => [0x0225A], "vellip" => [0x022EE], "verbar" => [0x0007C], "vert" => [0x0007C], "vfr" => [0x1D533], "vltri" => [0x022B2], "vnsub" => [0x02282, 0x020D2], "vnsup" => [0x02283, 0x020D2], "vopf" => [0x1D567], "vprop" => [0x0221D], "vrtri" => [0x022B3], "vscr" => [0x1D4CB], "vsubnE" => [0x02ACB, 0x0FE00], "vsubne" => [0x0228A, 0x0FE00], "vsupnE" => [0x02ACC, 0x0FE00], "vsupne" => [0x0228B, 0x0FE00], "vzigzag" => [0x0299A], "wcirc" => [0x00175], "wedbar" => [0x02A5F], "wedge" => [0x02227], "wedgeq" => [0x02259], "weierp" => [0x02118], "wfr" => [0x1D534], "wopf" => [0x1D568], "wp" => [0x02118], "wr" => [0x02240], "wreath" => [0x02240], "wscr" => [0x1D4CC], "xcap" => [0x022C2], "xcirc" => [0x025EF], "xcup" => [0x022C3], "xdtri" => [0x025BD], "xfr" => [0x1D535], "xhArr" => [0x027FA], "xharr" => [0x027F7], "xi" => [0x003BE], "xlArr" => [0x027F8], "xlarr" => [0x027F5], "xmap" => [0x027FC], "xnis" => [0x022FB], "xodot" => [0x02A00], "xopf" => [0x1D569], "xoplus" => [0x02A01], "xotime" => [0x02A02], "xrArr" => [0x027F9], "xrarr" => [0x027F6], "xscr" => [0x1D4CD], "xsqcup" => [0x02A06], "xuplus" => [0x02A04], "xutri" => [0x025B3], "xvee" => [0x022C1], "xwedge" => [0x022C0], "yacute" => [0x000FD], "yacy" => [0x0044F], "ycirc" => [0x00177], "ycy" => [0x0044B], "yen" => [0x000A5], "yfr" => [0x1D536], "yicy" => [0x00457], "yopf" => [0x1D56A], "yscr" => [0x1D4CE], "yucy" => [0x0044E], "yuml" => [0x000FF], "zacute" => [0x0017A], "zcaron" => [0x0017E], "zcy" => [0x00437], "zdot" => [0x0017C], "zeetrf" => [0x02128], "zeta" => [0x003B6], "zfr" => [0x1D537], "zhcy" => [0x00436], "zigrarr" => [0x021DD], "zopf" => [0x1D56B], "zscr" => [0x1D4CF], "zwj" => [0x0200D], "zwnj" => [0x0200C], } PK!yEr$r$#2.2.0/rdoc/markdown/literals_1_9.rbnu[# coding: UTF-8 # :markup: markdown ## #-- # This set of literals is for Ruby 1.9 regular expressions and gives full # unicode support. # # Unlike peg-markdown, this set of literals recognizes Unicode alphanumeric # characters, newlines and spaces. class RDoc::Markdown::Literals # :stopdoc: # This is distinct from setup_parser so that a standalone parser # can redefine #initialize and still have access to the proper # parser setup code. def initialize(str, debug=false) setup_parser(str, debug) end # Prepares for parsing +str+. If you define a custom initialize you must # call this method before #parse def setup_parser(str, debug=false) set_string str, 0 @memoizations = Hash.new { |h,k| h[k] = {} } @result = nil @failed_rule = nil @failing_rule_offset = -1 setup_foreign_grammar end attr_reader :string attr_reader :failing_rule_offset attr_accessor :result, :pos def current_column(target=pos) if c = string.rindex("\n", target-1) return target - c - 1 end target + 1 end def current_line(target=pos) cur_offset = 0 cur_line = 0 string.each_line do |line| cur_line += 1 cur_offset += line.size return cur_line if cur_offset >= target end -1 end def lines lines = [] string.each_line { |l| lines << l } lines end def get_text(start) @string[start..@pos-1] end # Sets the string and current parsing position for the parser. def set_string string, pos @string = string @string_size = string ? string.size : 0 @pos = pos end def show_pos width = 10 if @pos < width "#{@pos} (\"#{@string[0,@pos]}\" @ \"#{@string[@pos,width]}\")" else "#{@pos} (\"... #{@string[@pos - width, width]}\" @ \"#{@string[@pos,width]}\")" end end def failure_info l = current_line @failing_rule_offset c = current_column @failing_rule_offset if @failed_rule.kind_of? Symbol info = self.class::Rules[@failed_rule] "line #{l}, column #{c}: failed rule '#{info.name}' = '#{info.rendered}'" else "line #{l}, column #{c}: failed rule '#{@failed_rule}'" end end def failure_caret l = current_line @failing_rule_offset c = current_column @failing_rule_offset line = lines[l-1] "#{line}\n#{' ' * (c - 1)}^" end def failure_character l = current_line @failing_rule_offset c = current_column @failing_rule_offset lines[l-1][c-1, 1] end def failure_oneline l = current_line @failing_rule_offset c = current_column @failing_rule_offset char = lines[l-1][c-1, 1] if @failed_rule.kind_of? Symbol info = self.class::Rules[@failed_rule] "@#{l}:#{c} failed rule '#{info.name}', got '#{char}'" else "@#{l}:#{c} failed rule '#{@failed_rule}', got '#{char}'" end end class ParseError < RuntimeError end def raise_error raise ParseError, failure_oneline end def show_error(io=STDOUT) error_pos = @failing_rule_offset line_no = current_line(error_pos) col_no = current_column(error_pos) io.puts "On line #{line_no}, column #{col_no}:" if @failed_rule.kind_of? Symbol info = self.class::Rules[@failed_rule] io.puts "Failed to match '#{info.rendered}' (rule '#{info.name}')" else io.puts "Failed to match rule '#{@failed_rule}'" end io.puts "Got: #{string[error_pos,1].inspect}" line = lines[line_no-1] io.puts "=> #{line}" io.print(" " * (col_no + 3)) io.puts "^" end def set_failed_rule(name) if @pos > @failing_rule_offset @failed_rule = name @failing_rule_offset = @pos end end attr_reader :failed_rule def match_string(str) len = str.size if @string[pos,len] == str @pos += len return str end return nil end def scan(reg) if m = reg.match(@string[@pos..-1]) width = m.end(0) @pos += width return true end return nil end if "".respond_to? :ord def get_byte if @pos >= @string_size return nil end s = @string[@pos].ord @pos += 1 s end else def get_byte if @pos >= @string_size return nil end s = @string[@pos] @pos += 1 s end end def parse(rule=nil) # We invoke the rules indirectly via apply # instead of by just calling them as methods because # if the rules use left recursion, apply needs to # manage that. if !rule apply(:_root) else method = rule.gsub("-","_hyphen_") apply :"_#{method}" end end class MemoEntry def initialize(ans, pos) @ans = ans @pos = pos @result = nil @set = false @left_rec = false end attr_reader :ans, :pos, :result, :set attr_accessor :left_rec def move!(ans, pos, result) @ans = ans @pos = pos @result = result @set = true @left_rec = false end end def external_invoke(other, rule, *args) old_pos = @pos old_string = @string set_string other.string, other.pos begin if val = __send__(rule, *args) other.pos = @pos other.result = @result else other.set_failed_rule "#{self.class}##{rule}" end val ensure set_string old_string, old_pos end end def apply_with_args(rule, *args) memo_key = [rule, args] if m = @memoizations[memo_key][@pos] @pos = m.pos if !m.set m.left_rec = true return nil end @result = m.result return m.ans else m = MemoEntry.new(nil, @pos) @memoizations[memo_key][@pos] = m start_pos = @pos ans = __send__ rule, *args lr = m.left_rec m.move! ans, @pos, @result # Don't bother trying to grow the left recursion # if it's failing straight away (thus there is no seed) if ans and lr return grow_lr(rule, args, start_pos, m) else return ans end return ans end end def apply(rule) if m = @memoizations[rule][@pos] @pos = m.pos if !m.set m.left_rec = true return nil end @result = m.result return m.ans else m = MemoEntry.new(nil, @pos) @memoizations[rule][@pos] = m start_pos = @pos ans = __send__ rule lr = m.left_rec m.move! ans, @pos, @result # Don't bother trying to grow the left recursion # if it's failing straight away (thus there is no seed) if ans and lr return grow_lr(rule, nil, start_pos, m) else return ans end return ans end end def grow_lr(rule, args, start_pos, m) while true @pos = start_pos @result = m.result if args ans = __send__ rule, *args else ans = __send__ rule end return nil unless ans break if @pos <= m.pos m.move! ans, @pos, @result end @result = m.result @pos = m.pos return m.ans end class RuleInfo def initialize(name, rendered) @name = name @rendered = rendered end attr_reader :name, :rendered end def self.rule_info(name, rendered) RuleInfo.new(name, rendered) end # :startdoc: # :stopdoc: def setup_foreign_grammar; end # Alphanumeric = /\p{Word}/ def _Alphanumeric _tmp = scan(/\A(?-mix:\p{Word})/) set_failed_rule :_Alphanumeric unless _tmp return _tmp end # AlphanumericAscii = /[A-Za-z0-9]/ def _AlphanumericAscii _tmp = scan(/\A(?-mix:[A-Za-z0-9])/) set_failed_rule :_AlphanumericAscii unless _tmp return _tmp end # BOM = "uFEFF" def _BOM _tmp = match_string("uFEFF") set_failed_rule :_BOM unless _tmp return _tmp end # Newline = /\n|\r\n?|\p{Zl}|\p{Zp}/ def _Newline _tmp = scan(/\A(?-mix:\n|\r\n?|\p{Zl}|\p{Zp})/) set_failed_rule :_Newline unless _tmp return _tmp end # NonAlphanumeric = /\p{^Word}/ def _NonAlphanumeric _tmp = scan(/\A(?-mix:\p{^Word})/) set_failed_rule :_NonAlphanumeric unless _tmp return _tmp end # Spacechar = /\t|\p{Zs}/ def _Spacechar _tmp = scan(/\A(?-mix:\t|\p{Zs})/) set_failed_rule :_Spacechar unless _tmp return _tmp end Rules = {} Rules[:_Alphanumeric] = rule_info("Alphanumeric", "/\\p{Word}/") Rules[:_AlphanumericAscii] = rule_info("AlphanumericAscii", "/[A-Za-z0-9]/") Rules[:_BOM] = rule_info("BOM", "\"uFEFF\"") Rules[:_Newline] = rule_info("Newline", "/\\n|\\r\\n?|\\p{Zl}|\\p{Zp}/") Rules[:_NonAlphanumeric] = rule_info("NonAlphanumeric", "/\\p{^Word}/") Rules[:_Spacechar] = rule_info("Spacechar", "/\\t|\\p{Zs}/") # :startdoc: end PK!___2.2.0/rdoc/alias.rbnu[## # Represent an alias, which is an old_name/new_name pair associated with a # particular context #-- # TODO implement Alias as a proxy to a method/attribute, inheriting from # MethodAttr class RDoc::Alias < RDoc::CodeObject ## # Aliased method's name attr_reader :new_name alias name new_name ## # Aliasee method's name attr_reader :old_name ## # Is this an alias declared in a singleton context? attr_accessor :singleton ## # Source file token stream attr_reader :text ## # Creates a new Alias with a token stream of +text+ that aliases +old_name+ # to +new_name+, has +comment+ and is a +singleton+ context. def initialize(text, old_name, new_name, comment, singleton = false) super() @text = text @singleton = singleton @old_name = old_name @new_name = new_name self.comment = comment end ## # Order by #singleton then #new_name def <=>(other) [@singleton ? 0 : 1, new_name] <=> [other.singleton ? 0 : 1, other.new_name] end ## # HTML fragment reference for this alias def aref type = singleton ? 'c' : 'i' "#alias-#{type}-#{html_name}" end ## # Full old name including namespace def full_old_name @full_name || "#{parent.name}#{pretty_old_name}" end ## # HTML id-friendly version of +#new_name+. def html_name CGI.escape(@new_name.gsub('-', '-2D')).gsub('%','-').sub(/^-/, '') end def inspect # :nodoc: parent_name = parent ? parent.name : '(unknown)' "#<%s:0x%x %s.alias_method %s, %s>" % [ self.class, object_id, parent_name, @old_name, @new_name, ] end ## # '::' for the alias of a singleton method/attribute, '#' for instance-level. def name_prefix singleton ? '::' : '#' end ## # Old name with prefix '::' or '#'. def pretty_old_name "#{singleton ? '::' : '#'}#{@old_name}" end ## # New name with prefix '::' or '#'. def pretty_new_name "#{singleton ? '::' : '#'}#{@new_name}" end alias pretty_name pretty_new_name def to_s # :nodoc: "alias: #{self.new_name} -> #{self.pretty_old_name} in: #{parent}" end end PK!pcc2.2.0/rdoc/meta_method.rbnu[## # MetaMethod represents a meta-programmed method class RDoc::MetaMethod < RDoc::AnyMethod end PK!xkk2.2.0/rdoc/normal_class.rbnu[## # A normal class, neither singleton nor anonymous class RDoc::NormalClass < RDoc::ClassModule ## # The ancestors of this class including modules. Unlike Module#ancestors, # this class is not included in the result. The result will contain both # RDoc::ClassModules and Strings. def ancestors if String === superclass then super << superclass elsif superclass then ancestors = super ancestors << superclass ancestors.concat superclass.ancestors else super end end def aref_prefix # :nodoc: 'class' end ## # The definition of this class, class MyClassName def definition "class #{full_name}" end def direct_ancestors superclass ? super + [superclass] : super end def inspect # :nodoc: superclass = @superclass ? " < #{@superclass}" : nil "<%s:0x%x class %s%s includes: %p extends: %p attributes: %p methods: %p aliases: %p>" % [ self.class, object_id, full_name, superclass, @includes, @extends, @attributes, @method_list, @aliases ] end def to_s # :nodoc: display = "#{self.class.name} #{self.full_name}" if superclass display << ' < ' << (superclass.is_a?(String) ? superclass : superclass.full_name) end display << ' -> ' << is_alias_for.to_s if is_alias_for display end def pretty_print q # :nodoc: superclass = @superclass ? " < #{@superclass}" : nil q.group 2, "[class #{full_name}#{superclass} ", "]" do q.breakable q.text "includes:" q.breakable q.seplist @includes do |inc| q.pp inc end q.breakable q.text "constants:" q.breakable q.seplist @constants do |const| q.pp const end q.breakable q.text "attributes:" q.breakable q.seplist @attributes do |attr| q.pp attr end q.breakable q.text "methods:" q.breakable q.seplist @method_list do |meth| q.pp meth end q.breakable q.text "aliases:" q.breakable q.seplist @aliases do |aliaz| q.pp aliaz end q.breakable q.text "comment:" q.breakable q.pp comment end end end PK!Z>2.2.0/rdoc/rubygems_hook.rbnu[require 'rubygems' require 'rubygems/user_interaction' require 'fileutils' require 'rdoc' ## # Gem::RDoc provides methods to generate RDoc and ri data for installed gems # upon gem installation. # # This file is automatically required by RubyGems 1.9 and newer. class RDoc::RubygemsHook include Gem::UserInteraction extend Gem::UserInteraction @rdoc_version = nil @specs = [] ## # Force installation of documentation? attr_accessor :force ## # Generate rdoc? attr_accessor :generate_rdoc ## # Generate ri data? attr_accessor :generate_ri class << self ## # Loaded version of RDoc. Set by ::load_rdoc attr_reader :rdoc_version end ## # Post installs hook that generates documentation for each specification in # +specs+ def self.generation_hook installer, specs start = Time.now types = installer.document generate_rdoc = types.include? 'rdoc' generate_ri = types.include? 'ri' specs.each do |spec| new(spec, generate_rdoc, generate_ri).generate end return unless generate_rdoc or generate_ri duration = (Time.now - start).to_i names = specs.map(&:name).join ', ' say "Done installing documentation for #{names} after #{duration} seconds" end ## # Loads the RDoc generator def self.load_rdoc return if @rdoc_version require 'rdoc/rdoc' @rdoc_version = Gem::Version.new ::RDoc::VERSION end ## # Creates a new documentation generator for +spec+. RDoc and ri data # generation can be enabled or disabled through +generate_rdoc+ and # +generate_ri+ respectively. # # Only +generate_ri+ is enabled by default. def initialize spec, generate_rdoc = false, generate_ri = true @doc_dir = spec.doc_dir @force = false @rdoc = nil @spec = spec @generate_rdoc = generate_rdoc @generate_ri = generate_ri @rdoc_dir = spec.doc_dir 'rdoc' @ri_dir = spec.doc_dir 'ri' end ## # Removes legacy rdoc arguments from +args+ #-- # TODO move to RDoc::Options def delete_legacy_args args args.delete '--inline-source' args.delete '--promiscuous' args.delete '-p' args.delete '--one-file' end ## # Generates documentation using the named +generator+ ("darkfish" or "ri") # and following the given +options+. # # Documentation will be generated into +destination+ def document generator, options, destination generator_name = generator options = options.dup options.exclude ||= [] # TODO maybe move to RDoc::Options#finish options.setup_generator generator options.op_dir = destination options.finish generator = options.generator.new @rdoc.store, options @rdoc.options = options @rdoc.generator = generator say "Installing #{generator_name} documentation for #{@spec.full_name}" FileUtils.mkdir_p options.op_dir Dir.chdir options.op_dir do begin @rdoc.class.current = @rdoc @rdoc.generator.generate ensure @rdoc.class.current = nil end end end ## # Generates RDoc and ri data def generate return if @spec.default_gem? return unless @generate_ri or @generate_rdoc setup options = nil args = @spec.rdoc_options if @spec.respond_to? :source_paths then args.concat @spec.source_paths else args.concat @spec.require_paths end args.concat @spec.extra_rdoc_files case config_args = Gem.configuration[:rdoc] when String then args = args.concat config_args.split when Array then args = args.concat config_args end delete_legacy_args args Dir.chdir @spec.full_gem_path do options = ::RDoc::Options.new options.default_title = "#{@spec.full_name} Documentation" options.parse args end options.quiet = !Gem.configuration.really_verbose @rdoc = new_rdoc @rdoc.options = options store = RDoc::Store.new store.encoding = options.encoding if options.respond_to? :encoding store.dry_run = options.dry_run store.main = options.main_page store.title = options.title @rdoc.store = store say "Parsing documentation for #{@spec.full_name}" Dir.chdir @spec.full_gem_path do @rdoc.parse_files options.files end document 'ri', options, @ri_dir if @generate_ri and (@force or not File.exist? @ri_dir) document 'darkfish', options, @rdoc_dir if @generate_rdoc and (@force or not File.exist? @rdoc_dir) end ## # #new_rdoc creates a new RDoc instance. This method is provided only to # make testing easier. def new_rdoc # :nodoc: ::RDoc::RDoc.new end ## # Is rdoc documentation installed? def rdoc_installed? File.exist? @rdoc_dir end ## # Removes generated RDoc and ri data def remove base_dir = @spec.base_dir raise Gem::FilePermissionError, base_dir unless File.writable? base_dir FileUtils.rm_rf @rdoc_dir FileUtils.rm_rf @ri_dir end ## # Is ri data installed? def ri_installed? File.exist? @ri_dir end ## # Prepares the spec for documentation generation def setup self.class.load_rdoc raise Gem::FilePermissionError, @doc_dir if File.exist?(@doc_dir) and not File.writable?(@doc_dir) FileUtils.mkdir_p @doc_dir unless File.exist? @doc_dir end end PK!QC662.2.0/rdoc/rdoc.rbnu[require 'rdoc' require 'find' require 'fileutils' require 'pathname' require 'time' ## # This is the driver for generating RDoc output. It handles file parsing and # generation of output. # # To use this class to generate RDoc output via the API, the recommended way # is: # # rdoc = RDoc::RDoc.new # options = rdoc.load_options # returns an RDoc::Options instance # # set extra options # rdoc.document options # # You can also generate output like the +rdoc+ executable: # # rdoc = RDoc::RDoc.new # rdoc.document argv # # Where +argv+ is an array of strings, each corresponding to an argument you'd # give rdoc on the command line. See rdoc --help for details. class RDoc::RDoc @current = nil ## # This is the list of supported output generators GENERATORS = {} ## # File pattern to exclude attr_accessor :exclude ## # Generator instance used for creating output attr_accessor :generator ## # Hash of files and their last modified times. attr_reader :last_modified ## # RDoc options attr_accessor :options ## # Accessor for statistics. Available after each call to parse_files attr_reader :stats ## # The current documentation store attr_reader :store ## # Add +klass+ that can generate output after parsing def self.add_generator(klass) name = klass.name.sub(/^RDoc::Generator::/, '').downcase GENERATORS[name] = klass end ## # Active RDoc::RDoc instance def self.current @current end ## # Sets the active RDoc::RDoc instance def self.current= rdoc @current = rdoc end ## # Creates a new RDoc::RDoc instance. Call #document to parse files and # generate documentation. def initialize @current = nil @exclude = nil @generator = nil @last_modified = {} @old_siginfo = nil @options = nil @stats = nil @store = nil end ## # Report an error message and exit def error(msg) raise RDoc::Error, msg end ## # Gathers a set of parseable files from the files and directories listed in # +files+. def gather_files files files = ["."] if files.empty? file_list = normalized_file_list files, true, @exclude file_list = file_list.uniq file_list = remove_unparseable file_list file_list.sort end ## # Turns RDoc from stdin into HTML def handle_pipe @html = RDoc::Markup::ToHtml.new @options parser = RDoc::Text::MARKUP_FORMAT[@options.markup] document = parser.parse $stdin.read out = @html.convert document $stdout.write out end ## # Installs a siginfo handler that prints the current filename. def install_siginfo_handler return unless Signal.list.include? 'INFO' @old_siginfo = trap 'INFO' do puts @current if @current end end ## # Loads options from .rdoc_options if the file exists, otherwise creates a # new RDoc::Options instance. def load_options options_file = File.expand_path '.rdoc_options' return RDoc::Options.new unless File.exist? options_file RDoc.load_yaml parse_error = if Object.const_defined? :Psych then Psych::SyntaxError else ArgumentError end begin options = YAML.load_file '.rdoc_options' rescue *parse_error end raise RDoc::Error, "#{options_file} is not a valid rdoc options file" unless RDoc::Options === options options end ## # Create an output dir if it doesn't exist. If it does exist, but doesn't # contain the flag file created.rid then we refuse to use it, as # we may clobber some manually generated documentation def setup_output_dir(dir, force) flag_file = output_flag_file dir last = {} if @options.dry_run then # do nothing elsif File.exist? dir then error "#{dir} exists and is not a directory" unless File.directory? dir begin open flag_file do |io| unless force then Time.parse io.gets io.each do |line| file, time = line.split "\t", 2 time = Time.parse(time) rescue next last[file] = time end end end rescue SystemCallError, TypeError error <<-ERROR Directory #{dir} already exists, but it looks like it isn't an RDoc directory. Because RDoc doesn't want to risk destroying any of your existing files, you'll need to specify a different output directory name (using the --op option) ERROR end unless @options.force_output else FileUtils.mkdir_p dir FileUtils.touch flag_file end last end ## # Sets the current documentation tree to +store+ and sets the store's rdoc # driver to this instance. def store= store @store = store @store.rdoc = self end ## # Update the flag file in an output directory. def update_output_dir(op_dir, time, last = {}) return if @options.dry_run or not @options.update_output_dir open output_flag_file(op_dir), "w" do |f| f.puts time.rfc2822 last.each do |n, t| f.puts "#{n}\t#{t.rfc2822}" end end end ## # Return the path name of the flag file in an output directory. def output_flag_file(op_dir) File.join op_dir, "created.rid" end ## # The .document file contains a list of file and directory name patterns, # representing candidates for documentation. It may also contain comments # (starting with '#') def parse_dot_doc_file in_dir, filename # read and strip comments patterns = File.read(filename).gsub(/#.*/, '') result = [] patterns.split.each do |patt| candidates = Dir.glob(File.join(in_dir, patt)) result.concat normalized_file_list(candidates) end result end ## # Given a list of files and directories, create a list of all the Ruby # files they contain. # # If +force_doc+ is true we always add the given files, if false, only # add files that we guarantee we can parse. It is true when looking at # files given on the command line, false when recursing through # subdirectories. # # The effect of this is that if you want a file with a non-standard # extension parsed, you must name it explicitly. def normalized_file_list(relative_files, force_doc = false, exclude_pattern = nil) file_list = [] relative_files.each do |rel_file_name| next if rel_file_name.end_with? 'created.rid' next if exclude_pattern && exclude_pattern =~ rel_file_name stat = File.stat rel_file_name rescue next case type = stat.ftype when "file" then next if last_modified = @last_modified[rel_file_name] and stat.mtime.to_i <= last_modified.to_i if force_doc or RDoc::Parser.can_parse(rel_file_name) then file_list << rel_file_name.sub(/^\.\//, '') @last_modified[rel_file_name] = stat.mtime end when "directory" then next if rel_file_name == "CVS" || rel_file_name == ".svn" created_rid = File.join rel_file_name, "created.rid" next if File.file? created_rid dot_doc = File.join rel_file_name, RDoc::DOT_DOC_FILENAME if File.file? dot_doc then file_list << parse_dot_doc_file(rel_file_name, dot_doc) else file_list << list_files_in_directory(rel_file_name) end else warn "rdoc can't parse the #{type} #{rel_file_name}" end end file_list.flatten end ## # Return a list of the files to be processed in a directory. We know that # this directory doesn't have a .document file, so we're looking for real # files. However we may well contain subdirectories which must be tested # for .document files. def list_files_in_directory dir files = Dir.glob File.join(dir, "*") normalized_file_list files, false, @options.exclude end ## # Parses +filename+ and returns an RDoc::TopLevel def parse_file filename if Object.const_defined? :Encoding then encoding = @options.encoding filename = filename.encode encoding end @stats.add_file filename return if RDoc::Parser.binary? filename content = RDoc::Encoding.read_file filename, encoding return unless content filename_path = Pathname(filename).expand_path relative_path = filename_path.relative_path_from @options.root if @options.page_dir and relative_path.to_s.start_with? @options.page_dir.to_s then relative_path = relative_path.relative_path_from @options.page_dir end top_level = @store.add_file filename, relative_path.to_s parser = RDoc::Parser.for top_level, filename, content, @options, @stats return unless parser parser.scan # restart documentation for the classes & modules found top_level.classes_or_modules.each do |cm| cm.done_documenting = false end top_level rescue Errno::EACCES => e $stderr.puts <<-EOF Unable to read #{filename}, #{e.message} Please check the permissions for this file. Perhaps you do not have access to it or perhaps the original author's permissions are to restrictive. If the this is not your library please report a bug to the author. EOF rescue => e $stderr.puts <<-EOF Before reporting this, could you check that the file you're documenting has proper syntax: #{Gem.ruby} -c #{filename} RDoc is not a full Ruby parser and will fail when fed invalid ruby programs. The internal error was: \t(#{e.class}) #{e.message} EOF $stderr.puts e.backtrace.join("\n\t") if $DEBUG_RDOC raise e nil end ## # Parse each file on the command line, recursively entering directories. def parse_files files file_list = gather_files files @stats = RDoc::Stats.new @store, file_list.length, @options.verbosity return [] if file_list.empty? @stats.begin_adding file_info = file_list.map do |filename| @current = filename parse_file filename end.compact @stats.done_adding file_info end ## # Removes file extensions known to be unparseable from +files+ and TAGS # files for emacs and vim. def remove_unparseable files files.reject do |file| file =~ /\.(?:class|eps|erb|scpt\.txt|ttf|yml)$/i or (file =~ /tags$/i and open(file, 'rb') { |io| io.read(100) =~ /\A(\f\n[^,]+,\d+$|!_TAG_)/ }) end end ## # Generates documentation or a coverage report depending upon the settings # in +options+. # # +options+ can be either an RDoc::Options instance or an array of strings # equivalent to the strings that would be passed on the command line like # %w[-q -o doc -t My\ Doc\ Title]. #document will automatically # call RDoc::Options#finish if an options instance was given. # # For a list of options, see either RDoc::Options or rdoc --help. # # By default, output will be stored in a directory called "doc" below the # current directory, so make sure you're somewhere writable before invoking. def document options self.store = RDoc::Store.new if RDoc::Options === options then @options = options @options.finish else @options = load_options @options.parse options end if @options.pipe then handle_pipe exit end @exclude = @options.exclude unless @options.coverage_report then @last_modified = setup_output_dir @options.op_dir, @options.force_update end @store.encoding = @options.encoding if @options.respond_to? :encoding @store.dry_run = @options.dry_run @store.main = @options.main_page @store.title = @options.title @store.path = @options.op_dir @start_time = Time.now @store.load_cache file_info = parse_files @options.files @options.default_title = "RDoc Documentation" @store.complete @options.visibility @stats.coverage_level = @options.coverage_report if @options.coverage_report then puts puts @stats.report.accept RDoc::Markup::ToRdoc.new elsif file_info.empty? then $stderr.puts "\nNo newer files." unless @options.quiet else gen_klass = @options.generator @generator = gen_klass.new @store, @options generate end if @stats and (@options.coverage_report or not @options.quiet) then puts puts @stats.summary.accept RDoc::Markup::ToRdoc.new end exit @stats.fully_documented? if @options.coverage_report end ## # Generates documentation for +file_info+ (from #parse_files) into the # output dir using the generator selected # by the RDoc options def generate Dir.chdir @options.op_dir do unless @options.quiet then $stderr.puts "\nGenerating #{@generator.class.name.sub(/^.*::/, '')} format into #{Dir.pwd}..." end @generator.generate update_output_dir '.', @start_time, @last_modified end end ## # Removes a siginfo handler and replaces the previous def remove_siginfo_handler return unless Signal.list.key? 'INFO' handler = @old_siginfo || 'DEFAULT' trap 'INFO', handler end end begin require 'rubygems' if Gem.respond_to? :find_files then rdoc_extensions = Gem.find_files 'rdoc/discover' rdoc_extensions.each do |extension| begin load extension rescue => e warn "error loading #{extension.inspect}: #{e.message} (#{e.class})" warn "\t#{e.backtrace.join "\n\t"}" if $DEBUG end end end rescue LoadError end # require built-in generators after discovery in case they've been replaced require 'rdoc/generator/darkfish' require 'rdoc/generator/ri' require 'rdoc/generator/pot' PK!Wj\KK2.2.0/rdoc/cross_reference.rbnu[## # RDoc::CrossReference is a reusable way to create cross references for names. class RDoc::CrossReference ## # Regular expression to match class references # # 1. There can be a '\\' in front of text to suppress the cross-reference # 2. There can be a '::' in front of class names to reference from the # top-level namespace. # 3. The method can be followed by parenthesis (not recommended) CLASS_REGEXP_STR = '\\\\?((?:\:{2})?[A-Z]\w*(?:\:\:\w+)*)' ## # Regular expression to match method references. # # See CLASS_REGEXP_STR METHOD_REGEXP_STR = '([a-z]\w*[!?=]?|%|===|\[\]=?|<<|>>)(?:\([\w.+*/=<>-]*\))?' ## # Regular expressions matching text that should potentially have # cross-reference links generated are passed to add_special. Note that # these expressions are meant to pick up text for which cross-references # have been suppressed, since the suppression characters are removed by the # code that is triggered. CROSSREF_REGEXP = /(?:^|\s) ( (?: # A::B::C.meth #{CLASS_REGEXP_STR}(?:[.#]|::)#{METHOD_REGEXP_STR} # Stand-alone method (preceded by a #) | \\?\##{METHOD_REGEXP_STR} # Stand-alone method (preceded by ::) | ::#{METHOD_REGEXP_STR} # A::B::C # The stuff after CLASS_REGEXP_STR is a # nasty hack. CLASS_REGEXP_STR unfortunately matches # words like dog and cat (these are legal "class" # names in Fortran 95). When a word is flagged as a # potential cross-reference, limitations in the markup # engine suppress other processing, such as typesetting. # This is particularly noticeable for contractions. # In order that words like "can't" not # be flagged as potential cross-references, only # flag potential class cross-references if the character # after the cross-reference is a space, sentence # punctuation, tag start character, or attribute # marker. | #{CLASS_REGEXP_STR}(?=[@\s).?!,;<\000]|\z) # Things that look like filenames # The key thing is that there must be at least # one special character (period, slash, or # underscore). | (?:\.\.\/)*[-\/\w]+[_\/.][-\w\/.]+ # Things that have markup suppressed # Don't process things like '\<' in \, though. # TODO: including < is a hack, not very satisfying. | \\[^\s<] ) # labels for headings (?:@[\w+%-]+(?:\.[\w|%-]+)?)? )/x ## # Version of CROSSREF_REGEXP used when --hyperlink-all is specified. ALL_CROSSREF_REGEXP = / (?:^|\s) ( (?: # A::B::C.meth #{CLASS_REGEXP_STR}(?:[.#]|::)#{METHOD_REGEXP_STR} # Stand-alone method | \\?#{METHOD_REGEXP_STR} # A::B::C | #{CLASS_REGEXP_STR}(?=[@\s).?!,;<\000]|\z) # Things that look like filenames | (?:\.\.\/)*[-\/\w]+[_\/.][-\w\/.]+ # Things that have markup suppressed | \\[^\s<] ) # labels for headings (?:@[\w+%-]+)? )/x ## # Hash of references that have been looked-up to their replacements attr_accessor :seen ## # Allows cross-references to be created based on the given +context+ # (RDoc::Context). def initialize context @context = context @store = context.store @seen = {} end ## # Returns a reference to +name+. # # If the reference is found and +name+ is not documented +text+ will be # returned. If +name+ is escaped +name+ is returned. If +name+ is not # found +text+ is returned. def resolve name, text return @seen[name] if @seen.include? name if /#{CLASS_REGEXP_STR}([.#]|::)#{METHOD_REGEXP_STR}/o =~ name then type = $2 type = '' if type == '.' # will find either #method or ::method method = "#{type}#{$3}" container = @context.find_symbol_module($1) elsif /^([.#]|::)#{METHOD_REGEXP_STR}/o =~ name then type = $1 type = '' if type == '.' method = "#{type}#{$2}" container = @context else container = nil end if container then ref = container.find_local_symbol method unless ref || RDoc::TopLevel === container then ref = container.find_ancestor_local_symbol method end end ref = case name when /^\\(#{CLASS_REGEXP_STR})$/o then @context.find_symbol $1 else @context.find_symbol name end unless ref # Try a page name ref = @store.page name if not ref and name =~ /^\w+$/ ref = nil if RDoc::Alias === ref # external alias, can't link to it out = if name == '\\' then name elsif name =~ /^\\/ then # we remove the \ only in front of what we know: # other backslashes are treated later, only outside of ref ? $' : name elsif ref then if ref.display? then ref else text end else text end @seen[name] = out out end end PK!H.2.2.0/rdoc/normal_module.rbnu[## # A normal module, like NormalClass class RDoc::NormalModule < RDoc::ClassModule def aref_prefix # :nodoc: 'module' end def inspect # :nodoc: "#<%s:0x%x module %s includes: %p extends: %p attributes: %p methods: %p aliases: %p>" % [ self.class, object_id, full_name, @includes, @extends, @attributes, @method_list, @aliases ] end ## # The definition of this module, module MyModuleName def definition "module #{full_name}" end ## # This is a module, returns true def module? true end def pretty_print q # :nodoc: q.group 2, "[module #{full_name}: ", "]" do q.breakable q.text "includes:" q.breakable q.seplist @includes do |inc| q.pp inc end q.breakable q.breakable q.text "constants:" q.breakable q.seplist @constants do |const| q.pp const end q.text "attributes:" q.breakable q.seplist @attributes do |attr| q.pp attr end q.breakable q.text "methods:" q.breakable q.seplist @method_list do |meth| q.pp meth end q.breakable q.text "aliases:" q.breakable q.seplist @aliases do |aliaz| q.pp aliaz end q.breakable q.text "comment:" q.breakable q.pp comment end end ## # Modules don't have one, raises NoMethodError def superclass raise NoMethodError, "#{full_name} is a module" end end PK!T T 2.2.0/rdoc/encoding.rbnu[# coding: US-ASCII ## # This class is a wrapper around File IO and Encoding that helps RDoc load # files and convert them to the correct encoding. module RDoc::Encoding ## # Reads the contents of +filename+ and handles any encoding directives in # the file. # # The content will be converted to the +encoding+. If the file cannot be # converted a warning will be printed and nil will be returned. # # If +force_transcode+ is true the document will be transcoded and any # unknown character in the target encoding will be replaced with '?' def self.read_file filename, encoding, force_transcode = false content = open filename, "rb" do |f| f.read end content.gsub!("\r\n", "\n") if RUBY_PLATFORM =~ /mswin|mingw/ utf8 = content.sub!(/\A\xef\xbb\xbf/, '') RDoc::Encoding.set_encoding content if Object.const_defined? :Encoding then begin encoding ||= Encoding.default_external orig_encoding = content.encoding if not orig_encoding.ascii_compatible? then content.encode! encoding elsif utf8 then content.force_encoding Encoding::UTF_8 content.encode! encoding else # assume the content is in our output encoding content.force_encoding encoding end unless content.valid_encoding? then # revert and try to transcode content.force_encoding orig_encoding content.encode! encoding end unless content.valid_encoding? then warn "unable to convert #{filename} to #{encoding}, skipping" content = nil end rescue Encoding::InvalidByteSequenceError, Encoding::UndefinedConversionError => e if force_transcode then content.force_encoding orig_encoding content.encode!(encoding, :invalid => :replace, :undef => :replace, :replace => '?') return content else warn "unable to convert #{e.message} for #{filename}, skipping" return nil end end end content rescue ArgumentError => e raise unless e.message =~ /unknown encoding name - (.*)/ warn "unknown encoding name \"#{$1}\" for #{filename}, skipping" nil rescue Errno::EISDIR, Errno::ENOENT nil end ## # Sets the encoding of +string+ based on the magic comment def self.set_encoding string string =~ /\A(?:#!.*\n)?(.*\n)/ first_line = $1 name = case first_line when /^<\?xml[^?]*encoding=(["'])(.*?)\1/ then $2 when /\b(?:en)?coding[=:]\s*([^\s;]+)/i then $1 else return end string.sub! first_line, '' return unless Object.const_defined? :Encoding enc = Encoding.find name string.force_encoding enc if enc end end PK!=NS1002.2.0/rdoc/constant.rbnu[## # A constant class RDoc::Constant < RDoc::CodeObject MARSHAL_VERSION = 0 # :nodoc: ## # Sets the module or class this is constant is an alias for. attr_writer :is_alias_for ## # The constant's name attr_accessor :name ## # The constant's value attr_accessor :value ## # The constant's visibility attr_accessor :visibility ## # Creates a new constant with +name+, +value+ and +comment+ def initialize(name, value, comment) super() @name = name @value = value @is_alias_for = nil @visibility = nil self.comment = comment end ## # Constants are ordered by name def <=> other return unless self.class === other [parent_name, name] <=> [other.parent_name, other.name] end ## # Constants are equal when their #parent and #name is the same def == other self.class == other.class and @parent == other.parent and @name == other.name end ## # A constant is documented if it has a comment, or is an alias # for a documented class or module. def documented? return true if super return false unless @is_alias_for case @is_alias_for when String then found = @store.find_class_or_module @is_alias_for return false unless found @is_alias_for = found end @is_alias_for.documented? end ## # Full constant name including namespace def full_name @full_name ||= "#{parent_name}::#{@name}" end ## # The module or class this constant is an alias for def is_alias_for case @is_alias_for when String then found = @store.find_class_or_module @is_alias_for @is_alias_for = found if found @is_alias_for else @is_alias_for end end def inspect # :nodoc: "#<%s:0x%x %s::%s>" % [ self.class, object_id, parent_name, @name, ] end ## # Dumps this Constant for use by ri. See also #marshal_load def marshal_dump alias_name = case found = is_alias_for when RDoc::CodeObject then found.full_name else found end [ MARSHAL_VERSION, @name, full_name, @visibility, alias_name, parse(@comment), @file.relative_name, parent.name, parent.class, section.title, ] end ## # Loads this Constant from +array+. For a loaded Constant the following # methods will return cached values: # # * #full_name # * #parent_name def marshal_load array initialize array[1], nil, array[5] @full_name = array[2] @visibility = array[3] @is_alias_for = array[4] # 5 handled above # 6 handled below @parent_name = array[7] @parent_class = array[8] @section_title = array[9] @file = RDoc::TopLevel.new array[6] end ## # Path to this constant for use with HTML generator output. def path "#{@parent.path}##{@name}" end def pretty_print q # :nodoc: q.group 2, "[#{self.class.name} #{full_name}", "]" do unless comment.empty? then q.breakable q.text "comment:" q.breakable q.pp @comment end end end ## # Sets the store for this class or module and its contained code objects. def store= store super @file = @store.add_file @file.full_name if @file end def to_s # :nodoc: parent_name = parent ? parent.full_name : '(unknown)' if is_alias_for "constant #{parent_name}::#@name -> #{is_alias_for}" else "constant #{parent_name}::#@name" end end end PK!Yrr2.2.0/rdoc/erb_partial.rbnu[## # Allows an ERB template to be rendered in the context (binding) of an # existing ERB template evaluation. class RDoc::ERBPartial < ERB ## # Overrides +compiler+ startup to set the +eoutvar+ to an empty string only # if it isn't already set. def set_eoutvar compiler, eoutvar = '_erbout' super compiler.pre_cmd = ["#{eoutvar} ||= ''"] end end PK!c-2.2.0/rdoc/attr.rbnu[## # An attribute created by \#attr, \#attr_reader, \#attr_writer or # \#attr_accessor class RDoc::Attr < RDoc::MethodAttr ## # 3:: # RDoc 4 # Added parent name and class # Added section title MARSHAL_VERSION = 3 # :nodoc: ## # Is the attribute readable ('R'), writable ('W') or both ('RW')? attr_accessor :rw ## # Creates a new Attr with body +text+, +name+, read/write status +rw+ and # +comment+. +singleton+ marks this as a class attribute. def initialize(text, name, rw, comment, singleton = false) super text, name @rw = rw @singleton = singleton self.comment = comment end ## # Attributes are equal when their names, singleton and rw are identical def == other self.class == other.class and self.name == other.name and self.rw == other.rw and self.singleton == other.singleton end ## # Add +an_alias+ as an attribute in +context+. def add_alias(an_alias, context) new_attr = self.class.new(self.text, an_alias.new_name, self.rw, self.comment, self.singleton) new_attr.record_location an_alias.file new_attr.visibility = self.visibility new_attr.is_alias_for = self @aliases << new_attr context.add_attribute new_attr new_attr end ## # The #aref prefix for attributes def aref_prefix 'attribute' end ## # Attributes never call super. See RDoc::AnyMethod#calls_super # # An RDoc::Attr can show up in the method list in some situations (see # Gem::ConfigFile) def calls_super # :nodoc: false end ## # Returns attr_reader, attr_writer or attr_accessor as appropriate. def definition case @rw when 'RW' then 'attr_accessor' when 'R' then 'attr_reader' when 'W' then 'attr_writer' end end def inspect # :nodoc: alias_for = @is_alias_for ? " (alias for #{@is_alias_for.name})" : nil visibility = self.visibility visibility = "forced #{visibility}" if force_documentation "#<%s:0x%x %s %s (%s)%s>" % [ self.class, object_id, full_name, rw, visibility, alias_for, ] end ## # Dumps this Attr for use by ri. See also #marshal_load def marshal_dump [ MARSHAL_VERSION, @name, full_name, @rw, @visibility, parse(@comment), singleton, @file.relative_name, @parent.full_name, @parent.class, @section.title ] end ## # Loads this Attr from +array+. For a loaded Attr the following # methods will return cached values: # # * #full_name # * #parent_name def marshal_load array initialize_visibility @aliases = [] @parent = nil @parent_name = nil @parent_class = nil @section = nil @file = nil version = array[0] @name = array[1] @full_name = array[2] @rw = array[3] @visibility = array[4] @comment = array[5] @singleton = array[6] || false # MARSHAL_VERSION == 0 # 7 handled below @parent_name = array[8] @parent_class = array[9] @section_title = array[10] @file = RDoc::TopLevel.new array[7] if version > 1 @parent_name ||= @full_name.split('#', 2).first end def pretty_print q # :nodoc: q.group 2, "[#{self.class.name} #{full_name} #{rw} #{visibility}", "]" do unless comment.empty? then q.breakable q.text "comment:" q.breakable q.pp @comment end end end def to_s # :nodoc: "#{definition} #{name} in: #{parent}" end ## # Attributes do not have token streams. # # An RDoc::Attr can show up in the method list in some situations (see # Gem::ConfigFile) def token_stream # :nodoc: end end PK!>2.2.0/rdoc/parser/rd.rbnu[## # Parse a RD format file. The parsed RDoc::Markup::Document is attached as a # file comment. class RDoc::Parser::RD < RDoc::Parser include RDoc::Parser::Text parse_files_matching(/\.rd(?:\.[^.]+)?$/) ## # Creates an rd-format TopLevel for the given file. def scan comment = RDoc::Comment.new @content, @top_level comment.format = 'rd' @top_level.comment = comment end end PK! ..2.2.0/rdoc/parser/c.rbnu[require 'tsort' ## # RDoc::Parser::C attempts to parse C extension files. It looks for # the standard patterns that you find in extensions: rb_define_class, # rb_define_method and so on. It tries to find the corresponding # C source for the methods and extract comments, but if we fail # we don't worry too much. # # The comments associated with a Ruby method are extracted from the C # comment block associated with the routine that _implements_ that # method, that is to say the method whose name is given in the # rb_define_method call. For example, you might write: # # /* # * Returns a new array that is a one-dimensional flattening of this # * array (recursively). That is, for every element that is an array, # * extract its elements into the new array. # * # * s = [ 1, 2, 3 ] #=> [1, 2, 3] # * t = [ 4, 5, 6, [7, 8] ] #=> [4, 5, 6, [7, 8]] # * a = [ s, t, 9, 10 ] #=> [[1, 2, 3], [4, 5, 6, [7, 8]], 9, 10] # * a.flatten #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # */ # static VALUE # rb_ary_flatten(ary) # VALUE ary; # { # ary = rb_obj_dup(ary); # rb_ary_flatten_bang(ary); # return ary; # } # # ... # # void # Init_Array() # { # ... # rb_define_method(rb_cArray, "flatten", rb_ary_flatten, 0); # # Here RDoc will determine from the rb_define_method line that there's a # method called "flatten" in class Array, and will look for the implementation # in the method rb_ary_flatten. It will then use the comment from that # method in the HTML output. This method must be in the same source file # as the rb_define_method. # # The comment blocks may include special directives: # # [Document-class: +name+] # Documentation for the named class. # # [Document-module: +name+] # Documentation for the named module. # # [Document-const: +name+] # Documentation for the named +rb_define_const+. # # Constant values can be supplied on the first line of the comment like so: # # /* 300: The highest possible score in bowling */ # rb_define_const(cFoo, "PERFECT", INT2FIX(300)); # # The value can contain internal colons so long as they are escaped with a \ # # [Document-global: +name+] # Documentation for the named +rb_define_global_const+ # # [Document-variable: +name+] # Documentation for the named +rb_define_variable+ # # [Document-method: +method_name+] # Documentation for the named method. Use this when the method name is # unambiguous. # # [Document-method: ClassName::method_name] # Documentation for a singleton method in the given class. Use this when # the method name alone is ambiguous. # # [Document-method: ClassName#method_name] # Documentation for a instance method in the given class. Use this when the # method name alone is ambiguous. # # [Document-attr: +name+] # Documentation for the named attribute. # # [call-seq: text up to an empty line] # Because C source doesn't give descriptive names to Ruby-level parameters, # you need to document the calling sequence explicitly # # In addition, RDoc assumes by default that the C method implementing a # Ruby function is in the same source file as the rb_define_method call. # If this isn't the case, add the comment: # # rb_define_method(....); // in filename # # As an example, we might have an extension that defines multiple classes # in its Init_xxx method. We could document them using # # /* # * Document-class: MyClass # * # * Encapsulate the writing and reading of the configuration # * file. ... # */ # # /* # * Document-method: read_value # * # * call-seq: # * cfg.read_value(key) -> value # * cfg.read_value(key} { |key| } -> value # * # * Return the value corresponding to +key+ from the configuration. # * In the second form, if the key isn't found, invoke the # * block and return its value. # */ class RDoc::Parser::C < RDoc::Parser parse_files_matching(/\.(?:([CcHh])\1?|c([+xp])\2|y)\z/) include RDoc::Text ## # Maps C variable names to names of Ruby classes or modules attr_reader :classes ## # C file the parser is parsing attr_accessor :content ## # Dependencies from a missing enclosing class to the classes in # missing_dependencies that depend upon it. attr_reader :enclosure_dependencies ## # Maps C variable names to names of Ruby classes (and singleton classes) attr_reader :known_classes ## # Classes found while parsing the C file that were not yet registered due to # a missing enclosing class. These are processed by do_missing attr_reader :missing_dependencies ## # Maps C variable names to names of Ruby singleton classes attr_reader :singleton_classes ## # The TopLevel items in the parsed file belong to attr_reader :top_level ## # Prepares for parsing a C file. See RDoc::Parser#initialize for details on # the arguments. def initialize top_level, file_name, content, options, stats super @known_classes = RDoc::KNOWN_CLASSES.dup @content = handle_tab_width handle_ifdefs_in @content @file_dir = File.dirname @file_name @classes = load_variable_map :c_class_variables @singleton_classes = load_variable_map :c_singleton_class_variables # class_variable => { function => [method, ...] } @methods = Hash.new { |h, f| h[f] = Hash.new { |i, m| i[m] = [] } } # missing variable => [handle_class_module arguments] @missing_dependencies = {} # missing enclosure variable => [dependent handle_class_module arguments] @enclosure_dependencies = Hash.new { |h, k| h[k] = [] } @enclosure_dependencies.instance_variable_set :@missing_dependencies, @missing_dependencies @enclosure_dependencies.extend TSort def @enclosure_dependencies.tsort_each_node &block each_key(&block) rescue TSort::Cyclic => e cycle_vars = e.message.scan(/"(.*?)"/).flatten cycle = cycle_vars.sort.map do |var_name| delete var_name var_name, type, mod_name, = @missing_dependencies[var_name] "#{type} #{mod_name} (#{var_name})" end.join ', ' warn "Unable to create #{cycle} due to a cyclic class or module creation" retry end def @enclosure_dependencies.tsort_each_child node, &block fetch(node, []).each(&block) end end ## # Removes duplicate call-seq entries for methods using the same # implementation. def deduplicate_call_seq @methods.each do |var_name, functions| class_name = @known_classes[var_name] class_obj = find_class var_name, class_name functions.each_value do |method_names| next if method_names.length == 1 method_names.each do |method_name| deduplicate_method_name class_obj, method_name end end end end ## # If two ruby methods share a C implementation (and comment) this # deduplicates the examples in the call_seq for the method to reduce # confusion in the output. def deduplicate_method_name class_obj, method_name # :nodoc: return unless method = class_obj.method_list.find { |m| m.name == method_name } return unless call_seq = method.call_seq method_name = method_name[0, 1] if method_name =~ /\A\[/ entries = call_seq.split "\n" matching = entries.select do |entry| entry =~ /^\w*\.?#{Regexp.escape method_name}/ or entry =~ /\s#{Regexp.escape method_name}\s/ end method.call_seq = matching.join "\n" end ## # Scans #content for rb_define_alias def do_aliases @content.scan(/rb_define_alias\s*\( \s*(\w+), \s*"(.+?)", \s*"(.+?)" \s*\)/xm) do |var_name, new_name, old_name| class_name = @known_classes[var_name] unless class_name then @options.warn "Enclosing class or module %p for alias %s %s is not known" % [ var_name, new_name, old_name] next end class_obj = find_class var_name, class_name al = RDoc::Alias.new '', old_name, new_name, '' al.singleton = @singleton_classes.key? var_name comment = find_alias_comment var_name, new_name, old_name comment.normalize al.comment = comment al.record_location @top_level class_obj.add_alias al @stats.add_alias al end end ## # Scans #content for rb_attr and rb_define_attr def do_attrs @content.scan(/rb_attr\s*\( \s*(\w+), \s*([\w"()]+), \s*([01]), \s*([01]), \s*\w+\);/xm) do |var_name, attr_name, read, write| handle_attr var_name, attr_name, read, write end @content.scan(%r%rb_define_attr\( \s*([\w\.]+), \s*"([^"]+)", \s*(\d+), \s*(\d+)\s*\); %xm) do |var_name, attr_name, read, write| handle_attr var_name, attr_name, read, write end end ## # Scans #content for boot_defclass def do_boot_defclass @content.scan(/(\w+)\s*=\s*boot_defclass\s*\(\s*"(\w+?)",\s*(\w+?)\s*\)/) do |var_name, class_name, parent| parent = nil if parent == "0" handle_class_module(var_name, :class, class_name, parent, nil) end end ## # Scans #content for rb_define_class, boot_defclass, rb_define_class_under # and rb_singleton_class def do_classes do_boot_defclass do_define_class do_define_class_under do_singleton_class do_struct_define_without_accessor end ## # Scans #content for rb_define_variable, rb_define_readonly_variable, # rb_define_const and rb_define_global_const def do_constants @content.scan(%r%\Wrb_define_ ( variable | readonly_variable | const | global_const ) \s*\( (?:\s*(\w+),)? \s*"(\w+)", \s*(.*?)\s*\)\s*; %xm) do |type, var_name, const_name, definition| var_name = "rb_cObject" if !var_name or var_name == "rb_mKernel" handle_constants type, var_name, const_name, definition end @content.scan(%r% \Wrb_curses_define_const \s*\( \s* (\w+) \s* \) \s*;%xm) do |consts| const = consts.first handle_constants 'const', 'mCurses', const, "UINT2NUM(#{const})" end @content.scan(%r% \Wrb_file_const \s*\( \s* "([^"]+)", \s* (.*?) \s* \) \s*;%xm) do |name, value| handle_constants 'const', 'rb_mFConst', name, value end end ## # Scans #content for rb_define_class def do_define_class # The '.' lets us handle SWIG-generated files @content.scan(/([\w\.]+)\s* = \s*rb_define_class\s* \( \s*"(\w+)", \s*(\w+)\s* \)/mx) do |var_name, class_name, parent| handle_class_module(var_name, :class, class_name, parent, nil) end end ## # Scans #content for rb_define_class_under def do_define_class_under @content.scan(/([\w\.]+)\s* = # var_name \s*rb_define_class_under\s* \( \s* (\w+), # under \s* "(\w+)", # class_name \s* (?: ([\w\*\s\(\)\.\->]+) | # parent_name rb_path2class\("([\w:]+)"\) # path ) \s* \) /mx) do |var_name, under, class_name, parent_name, path| parent = path || parent_name handle_class_module var_name, :class, class_name, parent, under end end ## # Scans #content for rb_define_module def do_define_module @content.scan(/(\w+)\s* = \s*rb_define_module\s*\(\s*"(\w+)"\s*\)/mx) do |var_name, class_name| handle_class_module(var_name, :module, class_name, nil, nil) end end ## # Scans #content for rb_define_module_under def do_define_module_under @content.scan(/(\w+)\s* = \s*rb_define_module_under\s* \( \s*(\w+), \s*"(\w+)" \s*\)/mx) do |var_name, in_module, class_name| handle_class_module(var_name, :module, class_name, nil, in_module) end end ## # Scans #content for rb_include_module def do_includes @content.scan(/rb_include_module\s*\(\s*(\w+?),\s*(\w+?)\s*\)/) do |c,m| next unless cls = @classes[c] m = @known_classes[m] || m comment = RDoc::Comment.new '', @top_level incl = cls.add_include RDoc::Include.new(m, comment) incl.record_location @top_level end end ## # Scans #content for rb_define_method, rb_define_singleton_method, # rb_define_module_function, rb_define_private_method, # rb_define_global_function and define_filetest_function def do_methods @content.scan(%r%rb_define_ ( singleton_method | method | module_function | private_method ) \s*\(\s*([\w\.]+), \s*"([^"]+)", \s*(?:RUBY_METHOD_FUNC\(|VALUEFUNC\(|\(METHOD\))?(\w+)\)?, \s*(-?\w+)\s*\) (?:;\s*/[*/]\s+in\s+(\w+?\.(?:cpp|c|y)))? %xm) do |type, var_name, meth_name, function, param_count, source_file| # Ignore top-object and weird struct.c dynamic stuff next if var_name == "ruby_top_self" next if var_name == "nstr" var_name = "rb_cObject" if var_name == "rb_mKernel" handle_method(type, var_name, meth_name, function, param_count, source_file) end @content.scan(%r%rb_define_global_function\s*\( \s*"([^"]+)", \s*(?:RUBY_METHOD_FUNC\(|VALUEFUNC\()?(\w+)\)?, \s*(-?\w+)\s*\) (?:;\s*/[*/]\s+in\s+(\w+?\.[cy]))? %xm) do |meth_name, function, param_count, source_file| handle_method("method", "rb_mKernel", meth_name, function, param_count, source_file) end @content.scan(/define_filetest_function\s*\( \s*"([^"]+)", \s*(?:RUBY_METHOD_FUNC\(|VALUEFUNC\()?(\w+)\)?, \s*(-?\w+)\s*\)/xm) do |meth_name, function, param_count| handle_method("method", "rb_mFileTest", meth_name, function, param_count) handle_method("singleton_method", "rb_cFile", meth_name, function, param_count) end end ## # Creates classes and module that were missing were defined due to the file # order being different than the declaration order. def do_missing return if @missing_dependencies.empty? @enclosure_dependencies.tsort.each do |in_module| arguments = @missing_dependencies.delete in_module next unless arguments # dependency on existing class handle_class_module(*arguments) end end ## # Scans #content for rb_define_module and rb_define_module_under def do_modules do_define_module do_define_module_under end ## # Scans #content for rb_singleton_class def do_singleton_class @content.scan(/([\w\.]+)\s* = \s*rb_singleton_class\s* \( \s*(\w+) \s*\)/mx) do |sclass_var, class_var| handle_singleton sclass_var, class_var end end ## # Scans #content for struct_define_without_accessor def do_struct_define_without_accessor @content.scan(/([\w\.]+)\s* = \s*rb_struct_define_without_accessor\s* \( \s*"(\w+)", # Class name \s*(\w+), # Parent class \s*\w+, # Allocation function (\s*"\w+",)* # Attributes \s*NULL \)/mx) do |var_name, class_name, parent| handle_class_module(var_name, :class, class_name, parent, nil) end end ## # Finds the comment for an alias on +class_name+ from +new_name+ to # +old_name+ def find_alias_comment class_name, new_name, old_name content =~ %r%((?>/\*.*?\*/\s+)) rb_define_alias\(\s*#{Regexp.escape class_name}\s*, \s*"#{Regexp.escape new_name}"\s*, \s*"#{Regexp.escape old_name}"\s*\);%xm RDoc::Comment.new($1 || '', @top_level) end ## # Finds a comment for rb_define_attr, rb_attr or Document-attr. # # +var_name+ is the C class variable the attribute is defined on. # +attr_name+ is the attribute's name. # # +read+ and +write+ are the read/write flags ('1' or '0'). Either both or # neither must be provided. def find_attr_comment var_name, attr_name, read = nil, write = nil attr_name = Regexp.escape attr_name rw = if read and write then /\s*#{read}\s*,\s*#{write}\s*/xm else /.*?/m end comment = if @content =~ %r%((?>/\*.*?\*/\s+)) rb_define_attr\((?:\s*#{var_name},)?\s* "#{attr_name}"\s*, #{rw}\)\s*;%xm then $1 elsif @content =~ %r%((?>/\*.*?\*/\s+)) rb_attr\(\s*#{var_name}\s*, \s*#{attr_name}\s*, #{rw},.*?\)\s*;%xm then $1 elsif @content =~ %r%(/\*.*?(?:\s*\*\s*)?) Document-attr:\s#{attr_name}\s*?\n ((?>(.|\n)*?\*/))%x then "#{$1}\n#{$2}" else '' end RDoc::Comment.new comment, @top_level end ## # Find the C code corresponding to a Ruby method def find_body class_name, meth_name, meth_obj, file_content, quiet = false case file_content when %r%((?>/\*.*?\*/\s*)?) ((?:(?:\w+)\s+)? (?:intern\s+)?VALUE\s+#{meth_name} \s*(\([^)]*\))([^;]|$))%xm then comment = RDoc::Comment.new $1, @top_level body = $2 offset, = $~.offset(2) comment.remove_private if comment # try to find the whole body body = $& if /#{Regexp.escape body}[^(]*?\{.*?^\}/m =~ file_content # The comment block may have been overridden with a 'Document-method' # block. This happens in the interpreter when multiple methods are # vectored through to the same C method but those methods are logically # distinct (for example Kernel.hash and Kernel.object_id share the same # implementation override_comment = find_override_comment class_name, meth_obj comment = override_comment if override_comment comment.normalize find_modifiers comment, meth_obj if comment #meth_obj.params = params meth_obj.start_collecting_tokens tk = RDoc::RubyToken::Token.new nil, 1, 1 tk.set_text body meth_obj.add_token tk meth_obj.comment = comment meth_obj.offset = offset meth_obj.line = file_content[0, offset].count("\n") + 1 body when %r%((?>/\*.*?\*/\s*))^\s*(\#\s*define\s+#{meth_name}\s+(\w+))%m then comment = RDoc::Comment.new $1, @top_level body = $2 offset = $~.offset(2).first find_body class_name, $3, meth_obj, file_content, true comment.normalize find_modifiers comment, meth_obj meth_obj.start_collecting_tokens tk = RDoc::RubyToken::Token.new nil, 1, 1 tk.set_text body meth_obj.add_token tk meth_obj.comment = comment meth_obj.offset = offset meth_obj.line = file_content[0, offset].count("\n") + 1 body when %r%^\s*\#\s*define\s+#{meth_name}\s+(\w+)%m then # with no comment we hope the aliased definition has it and use it's # definition body = find_body(class_name, $1, meth_obj, file_content, true) return body if body @options.warn "No definition for #{meth_name}" false else # No body, but might still have an override comment comment = find_override_comment class_name, meth_obj if comment then comment.normalize find_modifiers comment, meth_obj meth_obj.comment = comment '' else @options.warn "No definition for #{meth_name}" false end end end ## # Finds a RDoc::NormalClass or RDoc::NormalModule for +raw_name+ def find_class(raw_name, name) unless @classes[raw_name] if raw_name =~ /^rb_m/ container = @top_level.add_module RDoc::NormalModule, name else container = @top_level.add_class RDoc::NormalClass, name end container.record_location @top_level @classes[raw_name] = container end @classes[raw_name] end ## # Look for class or module documentation above Init_+class_name+(void), # in a Document-class +class_name+ (or module) comment or above an # rb_define_class (or module). If a comment is supplied above a matching # Init_ and a rb_define_class the Init_ comment is used. # # /* # * This is a comment for Foo # */ # Init_Foo(void) { # VALUE cFoo = rb_define_class("Foo", rb_cObject); # } # # /* # * Document-class: Foo # * This is a comment for Foo # */ # Init_foo(void) { # VALUE cFoo = rb_define_class("Foo", rb_cObject); # } # # /* # * This is a comment for Foo # */ # VALUE cFoo = rb_define_class("Foo", rb_cObject); def find_class_comment class_name, class_mod comment = nil if @content =~ %r% ((?>/\*.*?\*/\s+)) (static\s+)? void\s+ Init_#{class_name}\s*(?:_\(\s*)?\(\s*(?:void\s*)?\)%xmi then comment = $1.sub(%r%Document-(?:class|module):\s+#{class_name}%, '') elsif @content =~ %r%Document-(?:class|module):\s+#{class_name}\s*? (?:<\s+[:,\w]+)?\n((?>.*?\*/))%xm then comment = "/*\n#{$1}" elsif @content =~ %r%((?>/\*.*?\*/\s+)) ([\w\.\s]+\s* = \s+)?rb_define_(class|module)[\t (]*?"(#{class_name})"%xm then comment = $1 elsif @content =~ %r%((?>/\*.*?\*/\s+)) ([\w\. \t]+ = \s+)?rb_define_(class|module)_under[\t\w, (]*?"(#{class_name.split('::').last})"%xm then comment = $1 else comment = '' end comment = RDoc::Comment.new comment, @top_level comment.normalize look_for_directives_in class_mod, comment class_mod.add_comment comment, @top_level end ## # Finds a comment matching +type+ and +const_name+ either above the # comment or in the matching Document- section. def find_const_comment(type, const_name, class_name = nil) comment = if @content =~ %r%((?>^\s*/\*.*?\*/\s+)) rb_define_#{type}\((?:\s*(\w+),)?\s* "#{const_name}"\s*, .*?\)\s*;%xmi then $1 elsif class_name and @content =~ %r%Document-(?:const|global|variable):\s #{class_name}::#{const_name} \s*?\n((?>.*?\*/))%xm then "/*\n#{$1}" elsif @content =~ %r%Document-(?:const|global|variable): \s#{const_name} \s*?\n((?>.*?\*/))%xm then "/*\n#{$1}" else '' end RDoc::Comment.new comment, @top_level end ## # Handles modifiers in +comment+ and updates +meth_obj+ as appropriate. def find_modifiers comment, meth_obj comment.normalize comment.extract_call_seq meth_obj look_for_directives_in meth_obj, comment end ## # Finds a Document-method override for +meth_obj+ on +class_name+ def find_override_comment class_name, meth_obj name = Regexp.escape meth_obj.name prefix = Regexp.escape meth_obj.name_prefix comment = if @content =~ %r%Document-method: \s+#{class_name}#{prefix}#{name} \s*?\n((?>.*?\*/))%xm then "/*#{$1}" elsif @content =~ %r%Document-method: \s#{name}\s*?\n((?>.*?\*/))%xm then "/*#{$1}" end return unless comment RDoc::Comment.new comment, @top_level end ## # Creates a new RDoc::Attr +attr_name+ on class +var_name+ that is either # +read+, +write+ or both def handle_attr(var_name, attr_name, read, write) rw = '' rw << 'R' if '1' == read rw << 'W' if '1' == write class_name = @known_classes[var_name] return unless class_name class_obj = find_class var_name, class_name return unless class_obj comment = find_attr_comment var_name, attr_name comment.normalize name = attr_name.gsub(/rb_intern\("([^"]+)"\)/, '\1') attr = RDoc::Attr.new '', name, rw, comment attr.record_location @top_level class_obj.add_attribute attr @stats.add_attribute attr end ## # Creates a new RDoc::NormalClass or RDoc::NormalModule based on +type+ # named +class_name+ in +parent+ which was assigned to the C +var_name+. def handle_class_module(var_name, type, class_name, parent, in_module) parent_name = @known_classes[parent] || parent if in_module then enclosure = @classes[in_module] || @store.find_c_enclosure(in_module) if enclosure.nil? and enclosure = @known_classes[in_module] then enc_type = /^rb_m/ =~ in_module ? :module : :class handle_class_module in_module, enc_type, enclosure, nil, nil enclosure = @classes[in_module] end unless enclosure then @enclosure_dependencies[in_module] << var_name @missing_dependencies[var_name] = [var_name, type, class_name, parent, in_module] return end else enclosure = @top_level end if type == :class then full_name = if RDoc::ClassModule === enclosure then enclosure.full_name + "::#{class_name}" else class_name end if @content =~ %r%Document-class:\s+#{full_name}\s*<\s+([:,\w]+)% then parent_name = $1 end cm = enclosure.add_class RDoc::NormalClass, class_name, parent_name else cm = enclosure.add_module RDoc::NormalModule, class_name end cm.record_location enclosure.top_level find_class_comment cm.full_name, cm case cm when RDoc::NormalClass @stats.add_class cm when RDoc::NormalModule @stats.add_module cm end @classes[var_name] = cm @known_classes[var_name] = cm.full_name @store.add_c_enclosure var_name, cm end ## # Adds constants. By providing some_value: at the start of the comment you # can override the C value of the comment to give a friendly definition. # # /* 300: The perfect score in bowling */ # rb_define_const(cFoo, "PERFECT", INT2FIX(300); # # Will override INT2FIX(300) with the value +300+ in the output # RDoc. Values may include quotes and escaped colons (\:). def handle_constants(type, var_name, const_name, definition) class_name = @known_classes[var_name] return unless class_name class_obj = find_class var_name, class_name unless class_obj then @options.warn 'Enclosing class or module %p is not known' % [const_name] return end comment = find_const_comment type, const_name, class_name comment.normalize # In the case of rb_define_const, the definition and comment are in # "/* definition: comment */" form. The literal ':' and '\' characters # can be escaped with a backslash. if type.downcase == 'const' then no_match, new_definition, new_comment = comment.text.split(/(\A.*):/) if no_match and no_match.empty? then if new_definition.empty? then # Default to literal C definition new_definition = definition else new_definition.gsub!("\:", ":") new_definition.gsub!("\\", '\\') end new_definition.sub!(/\A(\s+)/, '') new_comment = "#{$1}#{new_comment.lstrip}" new_comment = RDoc::Comment.new new_comment, @top_level con = RDoc::Constant.new const_name, new_definition, new_comment else con = RDoc::Constant.new const_name, definition, comment end else con = RDoc::Constant.new const_name, definition, comment end con.record_location @top_level @stats.add_constant con class_obj.add_constant con end ## # Removes #ifdefs that would otherwise confuse us def handle_ifdefs_in(body) body.gsub(/^#ifdef HAVE_PROTOTYPES.*?#else.*?\n(.*?)#endif.*?\n/m, '\1') end ## # Adds an RDoc::AnyMethod +meth_name+ defined on a class or module assigned # to +var_name+. +type+ is the type of method definition function used. # +singleton_method+ and +module_function+ create a singleton method. def handle_method(type, var_name, meth_name, function, param_count, source_file = nil) class_name = @known_classes[var_name] singleton = @singleton_classes.key? var_name @methods[var_name][function] << meth_name return unless class_name class_obj = find_class var_name, class_name if class_obj then if meth_name == 'initialize' then meth_name = 'new' singleton = true type = 'method' # force public end meth_obj = RDoc::AnyMethod.new '', meth_name meth_obj.c_function = function meth_obj.singleton = singleton || %w[singleton_method module_function].include?(type) p_count = Integer(param_count) rescue -1 if source_file then file_name = File.join @file_dir, source_file if File.exist? file_name then file_content = File.read file_name else @options.warn "unknown source #{source_file} for #{meth_name} in #{@file_name}" end else file_content = @content end body = find_body class_name, function, meth_obj, file_content if body and meth_obj.document_self then meth_obj.params = if p_count < -1 then # -2 is Array '(*args)' elsif p_count == -1 then # argc, argv rb_scan_args body else "(#{(1..p_count).map { |i| "p#{i}" }.join ', '})" end meth_obj.record_location @top_level class_obj.add_method meth_obj @stats.add_method meth_obj meth_obj.visibility = :private if 'private_method' == type end end end ## # Registers a singleton class +sclass_var+ as a singleton of +class_var+ def handle_singleton sclass_var, class_var class_name = @known_classes[class_var] @known_classes[sclass_var] = class_name @singleton_classes[sclass_var] = class_name end ## # Normalizes tabs in +body+ def handle_tab_width(body) if /\t/ =~ body tab_width = @options.tab_width body.split(/\n/).map do |line| 1 while line.gsub!(/\t+/) do ' ' * (tab_width * $&.length - $`.length % tab_width) end && $~ line end.join "\n" else body end end ## # Loads the variable map with the given +name+ from the RDoc::Store, if # present. def load_variable_map map_name return {} unless files = @store.cache[map_name] return {} unless name_map = files[@file_name] class_map = {} name_map.each do |variable, name| next unless mod = @store.find_class_or_module(name) class_map[variable] = if map_name == :c_class_variables then mod else name end @known_classes[variable] = name end class_map end ## # Look for directives in a normal comment block: # # /* # * :title: My Awesome Project # */ # # This method modifies the +comment+ def look_for_directives_in context, comment @preprocess.handle comment, context do |directive, param| case directive when 'main' then @options.main_page = param '' when 'title' then @options.default_title = param if @options.respond_to? :default_title= '' end end comment end ## # Extracts parameters from the +method_body+ and returns a method # parameter string. Follows 1.9.3dev's scan-arg-spec, see README.EXT def rb_scan_args method_body method_body =~ /rb_scan_args\((.*?)\)/m return '(*args)' unless $1 $1.split(/,/)[2] =~ /"(.*?)"/ # format argument format = $1.split(//) lead = opt = trail = 0 if format.first =~ /\d/ then lead = $&.to_i format.shift if format.first =~ /\d/ then opt = $&.to_i format.shift if format.first =~ /\d/ then trail = $&.to_i format.shift block_arg = true end end end if format.first == '*' and not block_arg then var = true format.shift if format.first =~ /\d/ then trail = $&.to_i format.shift end end if format.first == ':' then hash = true format.shift end if format.first == '&' then block = true format.shift end # if the format string is not empty there's a bug in the C code, ignore it args = [] position = 1 (1...(position + lead)).each do |index| args << "p#{index}" end position += lead (position...(position + opt)).each do |index| args << "p#{index} = v#{index}" end position += opt if var then args << '*args' position += 1 end (position...(position + trail)).each do |index| args << "p#{index}" end position += trail if hash then args << "p#{position} = {}" end args << '&block' if block "(#{args.join ', '})" end ## # Removes lines that are commented out that might otherwise get picked up # when scanning for classes and methods def remove_commented_out_lines @content.gsub!(%r%//.*rb_define_%, '//') end ## # Extracts the classes, modules, methods, attributes, constants and aliases # from a C file and returns an RDoc::TopLevel for this file def scan remove_commented_out_lines do_modules do_classes do_missing do_constants do_methods do_includes do_aliases do_attrs deduplicate_call_seq @store.add_c_variables self @top_level end end PK!0E2.2.0/rdoc/parser/text.rbnu[## # Indicates this parser is text and doesn't contain code constructs. # # Include this module in a RDoc::Parser subclass to make it show up as a file, # not as part of a class or module. #-- # This is not named File to avoid overriding ::File module RDoc::Parser::Text end PK!Q2.2.0/rdoc/parser/simple.rbnu[## # Parse a non-source file. We basically take the whole thing as one big # comment. class RDoc::Parser::Simple < RDoc::Parser include RDoc::Parser::Text parse_files_matching(//) attr_reader :content # :nodoc: ## # Prepare to parse a plain file def initialize(top_level, file_name, content, options, stats) super preprocess = RDoc::Markup::PreProcess.new @file_name, @options.rdoc_include preprocess.handle @content, @top_level end ## # Extract the file contents and attach them to the TopLevel as a comment def scan comment = remove_coding_comment @content comment = remove_private_comment comment comment = RDoc::Comment.new comment, @top_level @top_level.comment = comment @top_level end ## # Removes the encoding magic comment from +text+ def remove_coding_comment text text.sub(/\A# .*coding[=:].*$/, '') end ## # Removes private comments. # # Unlike RDoc::Comment#remove_private this implementation only looks for two # dashes at the beginning of the line. Three or more dashes are considered # to be a rule and ignored. def remove_private_comment comment # Workaround for gsub encoding for Ruby 1.9.2 and earlier empty = '' empty.force_encoding comment.encoding if Object.const_defined? :Encoding comment = comment.gsub(%r%^--\n.*?^\+\+\n?%m, empty) comment.sub(%r%^--\n.*%m, empty) end end PK!V 2.2.0/rdoc/parser/ruby_tools.rbnu[## # Collection of methods for writing parsers against RDoc::RubyLex and # RDoc::RubyToken module RDoc::Parser::RubyTools include RDoc::RubyToken ## # Adds a token listener +obj+, but you should probably use token_listener def add_token_listener(obj) @token_listeners ||= [] @token_listeners << obj end ## # Fetches the next token from the scanner def get_tk tk = nil if @tokens.empty? then tk = @scanner.token @read.push @scanner.get_readed puts "get_tk1 => #{tk.inspect}" if $TOKEN_DEBUG else @read.push @unget_read.shift tk = @tokens.shift puts "get_tk2 => #{tk.inspect}" if $TOKEN_DEBUG end tk = nil if TkEND_OF_SCRIPT === tk if TkSYMBEG === tk then set_token_position tk.line_no, tk.char_no case tk1 = get_tk when TkId, TkOp, TkSTRING, TkDSTRING, TkSTAR, TkAMPER then if tk1.respond_to?(:name) then tk = Token(TkSYMBOL).set_text(":" + tk1.name) else tk = Token(TkSYMBOL).set_text(":" + tk1.text) end # remove the identifier we just read to replace it with a symbol @token_listeners.each do |obj| obj.pop_token end if @token_listeners else tk = tk1 end end # inform any listeners of our shiny new token @token_listeners.each do |obj| obj.add_token(tk) end if @token_listeners tk end ## # Reads and returns all tokens up to one of +tokens+. Leaves the matched # token in the token list. def get_tk_until(*tokens) read = [] loop do tk = get_tk case tk when *tokens then unget_tk tk break end read << tk end read end ## # Retrieves a String representation of the read tokens def get_tkread read = @read.join("") @read = [] read end ## # Peek equivalent for get_tkread def peek_read @read.join('') end ## # Peek at the next token, but don't remove it from the stream def peek_tk unget_tk(tk = get_tk) tk end ## # Removes the token listener +obj+ def remove_token_listener(obj) @token_listeners.delete(obj) end ## # Resets the tools def reset @read = [] @tokens = [] @unget_read = [] @nest = 0 end ## # Skips whitespace tokens including newlines if +skip_nl+ is true def skip_tkspace(skip_nl = true) # HACK dup tokens = [] while TkSPACE === (tk = get_tk) or (skip_nl and TkNL === tk) do tokens.push tk end unget_tk tk tokens end ## # Has +obj+ listen to tokens def token_listener(obj) add_token_listener obj yield ensure remove_token_listener obj end ## # Returns +tk+ to the scanner def unget_tk(tk) @tokens.unshift tk @unget_read.unshift @read.pop # Remove this token from any listeners @token_listeners.each do |obj| obj.pop_token end if @token_listeners nil end end PK!k—2.2.0/rdoc/parser/markdown.rbnu[## # Parse a Markdown format file. The parsed RDoc::Markup::Document is attached # as a file comment. class RDoc::Parser::Markdown < RDoc::Parser include RDoc::Parser::Text parse_files_matching(/\.(md|markdown)(?:\.[^.]+)?$/) ## # Creates an Markdown-format TopLevel for the given file. def scan comment = RDoc::Comment.new @content, @top_level comment.format = 'markdown' @top_level.comment = comment end end PK!g2.2.0/rdoc/parser/ruby.rbnu[## # This file contains stuff stolen outright from: # # rtags.rb - # ruby-lex.rb - ruby lexcal analyzer # ruby-token.rb - ruby tokens # by Keiju ISHITSUKA (Nippon Rational Inc.) # $TOKEN_DEBUG ||= nil ## # Extracts code elements from a source file returning a TopLevel object # containing the constituent file elements. # # This file is based on rtags # # RubyParser understands how to document: # * classes # * modules # * methods # * constants # * aliases # * private, public, protected # * private_class_function, public_class_function # * module_function # * attr, attr_reader, attr_writer, attr_accessor # * extra accessors given on the command line # * metaprogrammed methods # * require # * include # # == Method Arguments # #-- # NOTE: I don't think this works, needs tests, remove the paragraph following # this block when known to work # # The parser extracts the arguments from the method definition. You can # override this with a custom argument definition using the :args: directive: # # ## # # This method tries over and over until it is tired # # def go_go_go(thing_to_try, tries = 10) # :args: thing_to_try # puts thing_to_try # go_go_go thing_to_try, tries - 1 # end # # If you have a more-complex set of overrides you can use the :call-seq: # directive: #++ # # The parser extracts the arguments from the method definition. You can # override this with a custom argument definition using the :call-seq: # directive: # # ## # # This method can be called with a range or an offset and length # # # # :call-seq: # # my_method(Range) # # my_method(offset, length) # # def my_method(*args) # end # # The parser extracts +yield+ expressions from method bodies to gather the # yielded argument names. If your method manually calls a block instead of # yielding or you want to override the discovered argument names use # the :yields: directive: # # ## # # My method is awesome # # def my_method(&block) # :yields: happy, times # block.call 1, 2 # end # # == Metaprogrammed Methods # # To pick up a metaprogrammed method, the parser looks for a comment starting # with '##' before an identifier: # # ## # # This is a meta-programmed method! # # add_my_method :meta_method, :arg1, :arg2 # # The parser looks at the token after the identifier to determine the name, in # this example, :meta_method. If a name cannot be found, a warning is printed # and 'unknown is used. # # You can force the name of a method using the :method: directive: # # ## # # :method: some_method! # # By default, meta-methods are instance methods. To indicate that a method is # a singleton method instead use the :singleton-method: directive: # # ## # # :singleton-method: # # You can also use the :singleton-method: directive with a name: # # ## # # :singleton-method: some_method! # # You can define arguments for metaprogrammed methods via either the # :call-seq:, :arg: or :args: directives. # # Additionally you can mark a method as an attribute by # using :attr:, :attr_reader:, :attr_writer: or :attr_accessor:. Just like # for :method:, the name is optional. # # ## # # :attr_reader: my_attr_name # # == Hidden methods and attributes # # You can provide documentation for methods that don't appear using # the :method:, :singleton-method: and :attr: directives: # # ## # # :attr_writer: ghost_writer # # There is an attribute here, but you can't see it! # # ## # # :method: ghost_method # # There is a method here, but you can't see it! # # ## # # this is a comment for a regular method # # def regular_method() end # # Note that by default, the :method: directive will be ignored if there is a # standard rdocable item following it. class RDoc::Parser::Ruby < RDoc::Parser parse_files_matching(/\.rbw?$/) include RDoc::RubyToken include RDoc::TokenStream include RDoc::Parser::RubyTools ## # RDoc::NormalClass type NORMAL = "::" ## # RDoc::SingleClass type SINGLE = "<<" ## # Creates a new Ruby parser. def initialize(top_level, file_name, content, options, stats) super @size = 0 @token_listeners = nil @scanner = RDoc::RubyLex.new content, @options @scanner.exception_on_syntax_error = false @prev_seek = nil @markup = @options.markup @track_visibility = :nodoc != @options.visibility @encoding = nil @encoding = @options.encoding if Object.const_defined? :Encoding reset end ## # Retrieves the read token stream and replaces +pattern+ with +replacement+ # using gsub. If the result is only a ";" returns an empty string. def get_tkread_clean pattern, replacement # :nodoc: read = get_tkread.gsub(pattern, replacement).strip return '' if read == ';' read end ## # Extracts the visibility information for the visibility token +tk+ # and +single+ class type identifier. # # Returns the visibility type (a string), the visibility (a symbol) and # +singleton+ if the methods following should be converted to singleton # methods. def get_visibility_information tk, single # :nodoc: vis_type = tk.name singleton = single == SINGLE vis = case vis_type when 'private' then :private when 'protected' then :protected when 'public' then :public when 'private_class_method' then singleton = true :private when 'public_class_method' then singleton = true :public when 'module_function' then singleton = true :public else raise RDoc::Error, "Invalid visibility: #{tk.name}" end return vis_type, vis, singleton end ## # Look for the first comment in a file that isn't a shebang line. def collect_first_comment skip_tkspace comment = '' comment.force_encoding @encoding if @encoding first_line = true first_comment_tk_class = nil tk = get_tk while TkCOMMENT === tk if first_line and tk.text =~ /\A#!/ then skip_tkspace tk = get_tk elsif first_line and tk.text =~ /\A#\s*-\*-/ then first_line = false skip_tkspace tk = get_tk else break if first_comment_tk_class and not first_comment_tk_class === tk first_comment_tk_class = tk.class first_line = false comment << tk.text << "\n" tk = get_tk if TkNL === tk then skip_tkspace false tk = get_tk end end end unget_tk tk new_comment comment end ## # Consumes trailing whitespace from the token stream def consume_trailing_spaces # :nodoc: get_tkread skip_tkspace false end ## # Creates a new attribute in +container+ with +name+. def create_attr container, single, name, rw, comment # :nodoc: att = RDoc::Attr.new get_tkread, name, rw, comment, single == SINGLE record_location att container.add_attribute att @stats.add_attribute att att end ## # Creates a module alias in +container+ at +rhs_name+ (or at the top-level # for "::") with the name from +constant+. def create_module_alias container, constant, rhs_name # :nodoc: mod = if rhs_name =~ /^::/ then @store.find_class_or_module rhs_name else container.find_module_named rhs_name end container.add_module_alias mod, constant.name, @top_level if mod end ## # Aborts with +msg+ def error(msg) msg = make_message msg abort msg end ## # Looks for a true or false token. Returns false if TkFALSE or TkNIL are # found. def get_bool skip_tkspace tk = get_tk case tk when TkTRUE true when TkFALSE, TkNIL false else unget_tk tk true end end ## # Look for the name of a class of module (optionally with a leading :: or # with :: separated named) and return the ultimate name, the associated # container, and the given name (with the ::). def get_class_or_module container, ignore_constants = false skip_tkspace name_t = get_tk given_name = '' # class ::A -> A is in the top level case name_t when TkCOLON2, TkCOLON3 then # bug name_t = get_tk container = @top_level given_name << '::' end skip_tkspace false given_name << name_t.name while TkCOLON2 === peek_tk do prev_container = container container = container.find_module_named name_t.name container ||= if ignore_constants then RDoc::Context.new else c = prev_container.add_module RDoc::NormalModule, name_t.name c.ignore unless prev_container.document_children @top_level.add_to_classes_or_modules c c end record_location container get_tk skip_tkspace false name_t = get_tk given_name << '::' << name_t.name end skip_tkspace false return [container, name_t, given_name] end ## # Return a superclass, which can be either a constant of an expression def get_class_specification case peek_tk when TkSELF then return 'self' when TkGVAR then return '' end res = get_constant skip_tkspace false get_tkread # empty out read buffer tk = get_tk case tk when TkNL, TkCOMMENT, TkSEMICOLON then unget_tk(tk) return res end res += parse_call_parameters(tk) res end ## # Parse a constant, which might be qualified by one or more class or module # names def get_constant res = "" skip_tkspace false tk = get_tk while TkCOLON2 === tk or TkCOLON3 === tk or TkCONSTANT === tk do res += tk.name tk = get_tk end unget_tk(tk) res end ## # Get a constant that may be surrounded by parens def get_constant_with_optional_parens skip_tkspace false nest = 0 while TkLPAREN === (tk = peek_tk) or TkfLPAREN === tk do get_tk skip_tkspace nest += 1 end name = get_constant while nest > 0 skip_tkspace tk = get_tk nest -= 1 if TkRPAREN === tk end name end ## # Little hack going on here. In the statement: # # f = 2*(1+yield) # # We see the RPAREN as the next token, so we need to exit early. This still # won't catch all cases (such as "a = yield + 1" def get_end_token tk # :nodoc: case tk when TkLPAREN, TkfLPAREN TkRPAREN when TkRPAREN nil else TkNL end end ## # Retrieves the method container for a singleton method. def get_method_container container, name_t # :nodoc: prev_container = container container = container.find_module_named(name_t.name) unless container then constant = prev_container.constants.find do |const| const.name == name_t.name end if constant then parse_method_dummy prev_container return end end unless container then # TODO seems broken, should starting at Object in @store obj = name_t.name.split("::").inject(Object) do |state, item| state.const_get(item) end rescue nil type = obj.class == Class ? RDoc::NormalClass : RDoc::NormalModule unless [Class, Module].include?(obj.class) then warn("Couldn't find #{name_t.name}. Assuming it's a module") end if type == RDoc::NormalClass then sclass = obj.superclass ? obj.superclass.name : nil container = prev_container.add_class type, name_t.name, sclass else container = prev_container.add_module type, name_t.name end record_location container end container end ## # Extracts a name or symbol from the token stream. def get_symbol_or_name tk = get_tk case tk when TkSYMBOL then text = tk.text.sub(/^:/, '') if TkASSIGN === peek_tk then get_tk text << '=' end text when TkId, TkOp then tk.name when TkAMPER, TkDSTRING, TkSTAR, TkSTRING then tk.text else raise RDoc::Error, "Name or symbol expected (got #{tk})" end end def stop_at_EXPR_END # :nodoc: @scanner.lex_state == :EXPR_END || !@scanner.continue end ## # Marks containers between +container+ and +ancestor+ as ignored def suppress_parents container, ancestor # :nodoc: while container and container != ancestor do container.suppress unless container.documented? container = container.parent end end ## # Look for directives in a normal comment block: # # # :stopdoc: # # Don't display comment from this point forward # # This routine modifies its +comment+ parameter. def look_for_directives_in context, comment @preprocess.handle comment, context do |directive, param| case directive when 'method', 'singleton-method', 'attr', 'attr_accessor', 'attr_reader', 'attr_writer' then false # handled elsewhere when 'section' then context.set_current_section param, comment.dup comment.text = '' break end end remove_private_comments comment end ## # Adds useful info about the parser to +message+ def make_message message prefix = "#{@file_name}:" prefix << "#{@scanner.line_no}:#{@scanner.char_no}:" if @scanner "#{prefix} #{message}" end ## # Creates a comment with the correct format def new_comment comment c = RDoc::Comment.new comment, @top_level c.format = @markup c end ## # Creates an RDoc::Attr for the name following +tk+, setting the comment to # +comment+. def parse_attr(context, single, tk, comment) offset = tk.seek line_no = tk.line_no args = parse_symbol_arg 1 if args.size > 0 then name = args[0] rw = "R" skip_tkspace false tk = get_tk if TkCOMMA === tk then rw = "RW" if get_bool else unget_tk tk end att = create_attr context, single, name, rw, comment att.offset = offset att.line = line_no read_documentation_modifiers att, RDoc::ATTR_MODIFIERS else warn "'attr' ignored - looks like a variable" end end ## # Creates an RDoc::Attr for each attribute listed after +tk+, setting the # comment for each to +comment+. def parse_attr_accessor(context, single, tk, comment) offset = tk.seek line_no = tk.line_no args = parse_symbol_arg rw = "?" tmp = RDoc::CodeObject.new read_documentation_modifiers tmp, RDoc::ATTR_MODIFIERS # TODO In most other places we let the context keep track of document_self # and add found items appropriately but here we do not. I'm not sure why. return if @track_visibility and not tmp.document_self case tk.name when "attr_reader" then rw = "R" when "attr_writer" then rw = "W" when "attr_accessor" then rw = "RW" else rw = '?' end for name in args att = create_attr context, single, name, rw, comment att.offset = offset att.line = line_no end end ## # Parses an +alias+ in +context+ with +comment+ def parse_alias(context, single, tk, comment) offset = tk.seek line_no = tk.line_no skip_tkspace if TkLPAREN === peek_tk then get_tk skip_tkspace end new_name = get_symbol_or_name @scanner.lex_state = :EXPR_FNAME skip_tkspace if TkCOMMA === peek_tk then get_tk skip_tkspace end begin old_name = get_symbol_or_name rescue RDoc::Error return end al = RDoc::Alias.new(get_tkread, old_name, new_name, comment, single == SINGLE) record_location al al.offset = offset al.line = line_no read_documentation_modifiers al, RDoc::ATTR_MODIFIERS context.add_alias al @stats.add_alias al al end ## # Extracts call parameters from the token stream. def parse_call_parameters(tk) end_token = case tk when TkLPAREN, TkfLPAREN TkRPAREN when TkRPAREN return "" else TkNL end nest = 0 loop do case tk when TkSEMICOLON break when TkLPAREN, TkfLPAREN nest += 1 when end_token if end_token == TkRPAREN nest -= 1 break if @scanner.lex_state == :EXPR_END and nest <= 0 else break unless @scanner.continue end when TkCOMMENT, TkASSIGN, TkOPASGN unget_tk(tk) break when nil then break end tk = get_tk end get_tkread_clean "\n", " " end ## # Parses a class in +context+ with +comment+ def parse_class container, single, tk, comment offset = tk.seek line_no = tk.line_no declaration_context = container container, name_t, given_name = get_class_or_module container cls = case name_t when TkCONSTANT parse_class_regular container, declaration_context, single, name_t, given_name, comment when TkLSHFT case name = get_class_specification when 'self', container.name parse_statements container, SINGLE return # don't update offset or line else parse_class_singleton container, name, comment end else warn "Expected class name or '<<'. Got #{name_t.class}: #{name_t.text.inspect}" return end cls.offset = offset cls.line = line_no cls end ## # Parses and creates a regular class def parse_class_regular container, declaration_context, single, # :nodoc: name_t, given_name, comment superclass = '::Object' if given_name =~ /^::/ then declaration_context = @top_level given_name = $' end if TkLT === peek_tk then get_tk skip_tkspace superclass = get_class_specification superclass = '(unknown)' if superclass.empty? end cls_type = single == SINGLE ? RDoc::SingleClass : RDoc::NormalClass cls = declaration_context.add_class cls_type, given_name, superclass cls.ignore unless container.document_children read_documentation_modifiers cls, RDoc::CLASS_MODIFIERS record_location cls cls.add_comment comment, @top_level @top_level.add_to_classes_or_modules cls @stats.add_class cls suppress_parents container, declaration_context unless cls.document_self parse_statements cls cls end ## # Parses a singleton class in +container+ with the given +name+ and # +comment+. def parse_class_singleton container, name, comment # :nodoc: other = @store.find_class_named name unless other then if name =~ /^::/ then name = $' container = @top_level end other = container.add_module RDoc::NormalModule, name record_location other # class << $gvar other.ignore if name.empty? other.add_comment comment, @top_level end # notify :nodoc: all if not a constant-named class/module # (and remove any comment) unless name =~ /\A(::)?[A-Z]/ then other.document_self = nil other.document_children = false other.clear_comment end @top_level.add_to_classes_or_modules other @stats.add_class other read_documentation_modifiers other, RDoc::CLASS_MODIFIERS parse_statements(other, SINGLE) other end ## # Parses a constant in +context+ with +comment+. If +ignore_constants+ is # true, no found constants will be added to RDoc. def parse_constant container, tk, comment, ignore_constants = false offset = tk.seek line_no = tk.line_no name = tk.name skip_tkspace false return unless name =~ /^\w+$/ eq_tk = get_tk if TkCOLON2 === eq_tk then unget_tk eq_tk unget_tk tk container, name_t, = get_class_or_module container, ignore_constants name = name_t.name eq_tk = get_tk end unless TkASSIGN === eq_tk then unget_tk eq_tk return false end if TkGT === peek_tk then unget_tk eq_tk return end value = '' con = RDoc::Constant.new name, value, comment body = parse_constant_body container, con return unless body value.replace body record_location con con.offset = offset con.line = line_no read_documentation_modifiers con, RDoc::CONSTANT_MODIFIERS @stats.add_constant con container.add_constant con true end def parse_constant_body container, constant # :nodoc: nest = 0 rhs_name = '' get_tkread tk = get_tk loop do case tk when TkSEMICOLON then break if nest <= 0 when TkLPAREN, TkfLPAREN, TkLBRACE, TkfLBRACE, TkLBRACK, TkfLBRACK, TkDO, TkIF, TkUNLESS, TkCASE, TkDEF, TkBEGIN then nest += 1 when TkRPAREN, TkRBRACE, TkRBRACK, TkEND then nest -= 1 when TkCOMMENT then if nest <= 0 and stop_at_EXPR_END then unget_tk tk break else unget_tk tk read_documentation_modifiers constant, RDoc::CONSTANT_MODIFIERS end when TkCONSTANT then rhs_name << tk.name if nest <= 0 and TkNL === peek_tk then create_module_alias container, constant, rhs_name break end when TkNL then if nest <= 0 and stop_at_EXPR_END then unget_tk tk break end when TkCOLON2, TkCOLON3 then rhs_name << '::' when nil then break end tk = get_tk end get_tkread_clean(/^[ \t]+/, '') end ## # Generates an RDoc::Method or RDoc::Attr from +comment+ by looking for # :method: or :attr: directives in +comment+. def parse_comment container, tk, comment return parse_comment_tomdoc container, tk, comment if @markup == 'tomdoc' column = tk.char_no offset = tk.seek line_no = tk.line_no text = comment.text singleton = !!text.sub!(/(^# +:?)(singleton-)(method:)/, '\1\3') co = if text.sub!(/^# +:?method: *(\S*).*?\n/i, '') then parse_comment_ghost container, text, $1, column, line_no, comment elsif text.sub!(/# +:?(attr(_reader|_writer|_accessor)?): *(\S*).*?\n/i, '') then parse_comment_attr container, $1, $3, comment end if co then co.singleton = singleton co.offset = offset co.line = line_no end true end ## # Parse a comment that is describing an attribute in +container+ with the # given +name+ and +comment+. def parse_comment_attr container, type, name, comment # :nodoc: return if name.empty? rw = case type when 'attr_reader' then 'R' when 'attr_writer' then 'W' else 'RW' end create_attr container, NORMAL, name, rw, comment end def parse_comment_ghost container, text, name, column, line_no, # :nodoc: comment name = nil if name.empty? meth = RDoc::GhostMethod.new get_tkread, name record_location meth meth.start_collecting_tokens indent = TkSPACE.new 0, 1, 1 indent.set_text " " * column position_comment = TkCOMMENT.new 0, line_no, 1 position_comment.set_text "# File #{@top_level.relative_name}, line #{line_no}" meth.add_tokens [position_comment, NEWLINE_TOKEN, indent] meth.params = if text.sub!(/^#\s+:?args?:\s*(.*?)\s*$/i, '') then $1 else '' end comment.normalize comment.extract_call_seq meth return unless meth.name container.add_method meth meth.comment = comment @stats.add_method meth meth end ## # Creates an RDoc::Method on +container+ from +comment+ if there is a # Signature section in the comment def parse_comment_tomdoc container, tk, comment return unless signature = RDoc::TomDoc.signature(comment) offset = tk.seek line_no = tk.line_no name, = signature.split %r%[ \(]%, 2 meth = RDoc::GhostMethod.new get_tkread, name record_location meth meth.offset = offset meth.line = line_no meth.start_collecting_tokens indent = TkSPACE.new 0, 1, 1 indent.set_text " " * offset position_comment = TkCOMMENT.new 0, line_no, 1 position_comment.set_text "# File #{@top_level.relative_name}, line #{line_no}" meth.add_tokens [position_comment, NEWLINE_TOKEN, indent] meth.call_seq = signature comment.normalize return unless meth.name container.add_method meth meth.comment = comment @stats.add_method meth end ## # Parses an +include+ or +extend+, indicated by the +klass+ and adds it to # +container+ # with +comment+ def parse_extend_or_include klass, container, comment # :nodoc: loop do skip_tkspace_comment name = get_constant_with_optional_parens unless name.empty? then obj = container.add klass, name, comment record_location obj end return unless TkCOMMA === peek_tk get_tk end end ## # Parses identifiers that can create new methods or change visibility. # # Returns true if the comment was not consumed. def parse_identifier container, single, tk, comment # :nodoc: case tk.name when 'private', 'protected', 'public', 'private_class_method', 'public_class_method', 'module_function' then parse_visibility container, single, tk return true when 'attr' then parse_attr container, single, tk, comment when /^attr_(reader|writer|accessor)$/ then parse_attr_accessor container, single, tk, comment when 'alias_method' then parse_alias container, single, tk, comment when 'require', 'include' then # ignore else if comment.text =~ /\A#\#$/ then case comment.text when /^# +:?attr(_reader|_writer|_accessor)?:/ then parse_meta_attr container, single, tk, comment else method = parse_meta_method container, single, tk, comment method.params = container.params if container.params method.block_params = container.block_params if container.block_params end end end false end ## # Parses a meta-programmed attribute and creates an RDoc::Attr. # # To create foo and bar attributes on class C with comment "My attributes": # # class C # # ## # # :attr: # # # # My attributes # # my_attr :foo, :bar # # end # # To create a foo attribute on class C with comment "My attribute": # # class C # # ## # # :attr: foo # # # # My attribute # # my_attr :foo, :bar # # end def parse_meta_attr(context, single, tk, comment) args = parse_symbol_arg rw = "?" # If nodoc is given, don't document any of them tmp = RDoc::CodeObject.new read_documentation_modifiers tmp, RDoc::ATTR_MODIFIERS if comment.text.sub!(/^# +:?(attr(_reader|_writer|_accessor)?): *(\S*).*?\n/i, '') then rw = case $1 when 'attr_reader' then 'R' when 'attr_writer' then 'W' else 'RW' end name = $3 unless $3.empty? end if name then att = create_attr context, single, name, rw, comment else args.each do |attr_name| att = create_attr context, single, attr_name, rw, comment end end att end ## # Parses a meta-programmed method def parse_meta_method(container, single, tk, comment) column = tk.char_no offset = tk.seek line_no = tk.line_no start_collecting_tokens add_token tk add_token_listener self skip_tkspace false singleton = !!comment.text.sub!(/(^# +:?)(singleton-)(method:)/, '\1\3') name = parse_meta_method_name comment, tk return unless name meth = RDoc::MetaMethod.new get_tkread, name record_location meth meth.offset = offset meth.line = line_no meth.singleton = singleton remove_token_listener self meth.start_collecting_tokens indent = TkSPACE.new 0, 1, 1 indent.set_text " " * column position_comment = TkCOMMENT.new 0, line_no, 1 position_comment.value = "# File #{@top_level.relative_name}, line #{line_no}" meth.add_tokens [position_comment, NEWLINE_TOKEN, indent] meth.add_tokens @token_stream parse_meta_method_params container, single, meth, tk, comment meth.comment = comment @stats.add_method meth meth end ## # Parses the name of a metaprogrammed method. +comment+ is used to # determine the name while +tk+ is used in an error message if the name # cannot be determined. def parse_meta_method_name comment, tk # :nodoc: if comment.text.sub!(/^# +:?method: *(\S*).*?\n/i, '') then return $1 unless $1.empty? end name_t = get_tk case name_t when TkSYMBOL then name_t.text[1..-1] when TkSTRING then name_t.value[1..-2] when TkASSIGN then # ignore remove_token_listener self nil else warn "unknown name token #{name_t.inspect} for meta-method '#{tk.name}'" 'unknown' end end ## # Parses the parameters and block for a meta-programmed method. def parse_meta_method_params container, single, meth, tk, comment # :nodoc: token_listener meth do meth.params = '' comment.normalize comment.extract_call_seq meth container.add_method meth last_tk = tk while tk = get_tk do case tk when TkSEMICOLON then break when TkNL then break unless last_tk and TkCOMMA === last_tk when TkSPACE then # expression continues when TkDO then parse_statements container, single, meth break else last_tk = tk end end end end ## # Parses a normal method defined by +def+ def parse_method(container, single, tk, comment) singleton = nil added_container = false name = nil column = tk.char_no offset = tk.seek line_no = tk.line_no start_collecting_tokens add_token tk token_listener self do prev_container = container name, container, singleton = parse_method_name container added_container = container != prev_container end return unless name meth = RDoc::AnyMethod.new get_tkread, name meth.singleton = single == SINGLE ? true : singleton record_location meth meth.offset = offset meth.line = line_no meth.start_collecting_tokens indent = TkSPACE.new 0, 1, 1 indent.set_text " " * column token = TkCOMMENT.new 0, line_no, 1 token.set_text "# File #{@top_level.relative_name}, line #{line_no}" meth.add_tokens [token, NEWLINE_TOKEN, indent] meth.add_tokens @token_stream parse_method_params_and_body container, single, meth, added_container comment.normalize comment.extract_call_seq meth meth.comment = comment @stats.add_method meth end ## # Parses the parameters and body of +meth+ def parse_method_params_and_body container, single, meth, added_container token_listener meth do @scanner.continue = false parse_method_parameters meth if meth.document_self or not @track_visibility then container.add_method meth elsif added_container then container.document_self = false end # Having now read the method parameters and documentation modifiers, we # now know whether we have to rename #initialize to ::new if meth.name == "initialize" && !meth.singleton then if meth.dont_rename_initialize then meth.visibility = :protected else meth.singleton = true meth.name = "new" meth.visibility = :public end end parse_statements container, single, meth end end ## # Parses a method that needs to be ignored. def parse_method_dummy container dummy = RDoc::Context.new dummy.parent = container dummy.store = container.store skip_method dummy end ## # Parses the name of a method in +container+. # # Returns the method name, the container it is in (for def Foo.name) and if # it is a singleton or regular method. def parse_method_name container # :nodoc: @scanner.lex_state = :EXPR_FNAME skip_tkspace name_t = get_tk back_tk = skip_tkspace singleton = false case dot = get_tk when TkDOT, TkCOLON2 then singleton = true name, container = parse_method_name_singleton container, name_t else unget_tk dot back_tk.reverse_each do |token| unget_tk token end name = parse_method_name_regular container, name_t end return name, container, singleton end ## # For the given +container+ and initial name token +name_t+ the method name # is parsed from the token stream for a regular method. def parse_method_name_regular container, name_t # :nodoc: case name_t when TkSTAR, TkAMPER then name_t.text else unless name_t.respond_to? :name then warn "expected method name token, . or ::, got #{name_t.inspect}" skip_method container return end name_t.name end end ## # For the given +container+ and initial name token +name_t+ the method name # and the new +container+ (if necessary) are parsed from the token stream # for a singleton method. def parse_method_name_singleton container, name_t # :nodoc: @scanner.lex_state = :EXPR_FNAME skip_tkspace name_t2 = get_tk name = case name_t when TkSELF, TkMOD then case name_t2 # NOTE: work around '[' being consumed early and not being re-tokenized # as a TkAREF when TkfLBRACK then get_tk '[]' else name_t2.name end when TkCONSTANT then name = name_t2.name container = get_method_container container, name_t return unless container name when TkIDENTIFIER, TkIVAR, TkGVAR then parse_method_dummy container nil when TkTRUE, TkFALSE, TkNIL then klass_name = "#{name_t.name.capitalize}Class" container = @store.find_class_named klass_name container ||= @top_level.add_class RDoc::NormalClass, klass_name name_t2.name else warn "unexpected method name token #{name_t.inspect}" # break skip_method container nil end return name, container end ## # Extracts +yield+ parameters from +method+ def parse_method_or_yield_parameters(method = nil, modifiers = RDoc::METHOD_MODIFIERS) skip_tkspace false tk = get_tk end_token = get_end_token tk return '' unless end_token nest = 0 loop do case tk when TkSEMICOLON then break if nest == 0 when TkLBRACE, TkfLBRACE then nest += 1 when TkRBRACE then nest -= 1 if nest <= 0 # we might have a.each { |i| yield i } unget_tk(tk) if nest < 0 break end when TkLPAREN, TkfLPAREN then nest += 1 when end_token then if end_token == TkRPAREN nest -= 1 break if nest <= 0 else break unless @scanner.continue end when TkRPAREN then nest -= 1 when method && method.block_params.nil? && TkCOMMENT then unget_tk tk read_documentation_modifiers method, modifiers @read.pop when TkCOMMENT then @read.pop when nil then break end tk = get_tk end get_tkread_clean(/\s+/, ' ') end ## # Capture the method's parameters. Along the way, look for a comment # containing: # # # yields: .... # # and add this as the block_params for the method def parse_method_parameters method res = parse_method_or_yield_parameters method res = "(#{res})" unless res =~ /\A\(/ method.params = res unless method.params return if method.block_params skip_tkspace false read_documentation_modifiers method, RDoc::METHOD_MODIFIERS end ## # Parses an RDoc::NormalModule in +container+ with +comment+ def parse_module container, single, tk, comment container, name_t, = get_class_or_module container name = name_t.name mod = container.add_module RDoc::NormalModule, name mod.ignore unless container.document_children record_location mod read_documentation_modifiers mod, RDoc::CLASS_MODIFIERS mod.add_comment comment, @top_level parse_statements mod @stats.add_module mod end ## # Parses an RDoc::Require in +context+ containing +comment+ def parse_require(context, comment) skip_tkspace_comment tk = get_tk if TkLPAREN === tk then skip_tkspace_comment tk = get_tk end name = tk.text if TkSTRING === tk if name then @top_level.add_require RDoc::Require.new(name, comment) else unget_tk tk end end ## # Parses a rescue def parse_rescue skip_tkspace false while tk = get_tk case tk when TkNL, TkSEMICOLON then break when TkCOMMA then skip_tkspace false get_tk if TkNL === peek_tk end skip_tkspace false end end ## # The core of the Ruby parser. def parse_statements(container, single = NORMAL, current_method = nil, comment = new_comment('')) raise 'no' unless RDoc::Comment === comment comment.force_encoding @encoding if @encoding nest = 1 save_visibility = container.visibility non_comment_seen = true while tk = get_tk do keep_comment = false try_parse_comment = false non_comment_seen = true unless TkCOMMENT === tk case tk when TkNL then skip_tkspace tk = get_tk if TkCOMMENT === tk then if non_comment_seen then # Look for RDoc in a comment about to be thrown away non_comment_seen = parse_comment container, tk, comment unless comment.empty? comment = '' comment.force_encoding @encoding if @encoding end while TkCOMMENT === tk do comment << tk.text << "\n" tk = get_tk if TkNL === tk then skip_tkspace false # leading spaces tk = get_tk end end comment = new_comment comment unless comment.empty? then look_for_directives_in container, comment if container.done_documenting then throw :eof if RDoc::TopLevel === container container.ongoing_visibility = save_visibility end end keep_comment = true else non_comment_seen = true end unget_tk tk keep_comment = true when TkCLASS then parse_class container, single, tk, comment when TkMODULE then parse_module container, single, tk, comment when TkDEF then parse_method container, single, tk, comment when TkCONSTANT then unless parse_constant container, tk, comment, current_method then try_parse_comment = true end when TkALIAS then parse_alias container, single, tk, comment unless current_method when TkYIELD then if current_method.nil? then warn "Warning: yield outside of method" if container.document_self else parse_yield container, single, tk, current_method end # Until and While can have a 'do', which shouldn't increase the nesting. # We can't solve the general case, but we can handle most occurrences by # ignoring a do at the end of a line. when TkUNTIL, TkWHILE then nest += 1 skip_optional_do_after_expression # 'for' is trickier when TkFOR then nest += 1 skip_for_variable skip_optional_do_after_expression when TkCASE, TkDO, TkIF, TkUNLESS, TkBEGIN then nest += 1 when TkSUPER then current_method.calls_super = true if current_method when TkRESCUE then parse_rescue when TkIDENTIFIER then if nest == 1 and current_method.nil? then keep_comment = parse_identifier container, single, tk, comment end case tk.name when "require" then parse_require container, comment when "include" then parse_extend_or_include RDoc::Include, container, comment when "extend" then parse_extend_or_include RDoc::Extend, container, comment end when TkEND then nest -= 1 if nest == 0 then read_documentation_modifiers container, RDoc::CLASS_MODIFIERS container.ongoing_visibility = save_visibility parse_comment container, tk, comment unless comment.empty? return end else try_parse_comment = nest == 1 end if try_parse_comment then non_comment_seen = parse_comment container, tk, comment unless comment.empty? keep_comment = false end unless keep_comment then comment = new_comment '' comment.force_encoding @encoding if @encoding container.params = nil container.block_params = nil end consume_trailing_spaces end container.params = nil container.block_params = nil end ## # Parse up to +no+ symbol arguments def parse_symbol_arg(no = nil) skip_tkspace_comment case tk = get_tk when TkLPAREN parse_symbol_arg_paren no else parse_symbol_arg_space no, tk end end ## # Parses up to +no+ symbol arguments surrounded by () and places them in # +args+. def parse_symbol_arg_paren no # :nodoc: args = [] loop do skip_tkspace_comment if tk1 = parse_symbol_in_arg args.push tk1 break if no and args.size >= no end skip_tkspace_comment case tk2 = get_tk when TkRPAREN break when TkCOMMA else warn("unexpected token: '#{tk2.inspect}'") if $DEBUG_RDOC break end end args end ## # Parses up to +no+ symbol arguments separated by spaces and places them in # +args+. def parse_symbol_arg_space no, tk # :nodoc: args = [] unget_tk tk if tk = parse_symbol_in_arg args.push tk return args if no and args.size >= no end loop do skip_tkspace false tk1 = get_tk unless TkCOMMA === tk1 then unget_tk tk1 break end skip_tkspace_comment if tk = parse_symbol_in_arg args.push tk break if no and args.size >= no end end args end ## # Returns symbol text from the next token def parse_symbol_in_arg case tk = get_tk when TkSYMBOL tk.text.sub(/^:/, '') when TkSTRING eval @read[-1] when TkDSTRING, TkIDENTIFIER then nil # ignore else warn("Expected symbol or string, got #{tk.inspect}") if $DEBUG_RDOC nil end end ## # Parses statements in the top-level +container+ def parse_top_level_statements container comment = collect_first_comment look_for_directives_in container, comment throw :eof if container.done_documenting @markup = comment.format # HACK move if to RDoc::Context#comment= container.comment = comment if container.document_self unless comment.empty? parse_statements container, NORMAL, nil, comment end ## # Determines the visibility in +container+ from +tk+ def parse_visibility(container, single, tk) vis_type, vis, singleton = get_visibility_information tk, single skip_tkspace_comment false case peek_tk # Ryan Davis suggested the extension to ignore modifiers, because he # often writes # # protected unless $TESTING # when TkNL, TkUNLESS_MOD, TkIF_MOD, TkSEMICOLON then container.ongoing_visibility = vis else update_visibility container, vis_type, vis, singleton end end ## # Determines the block parameter for +context+ def parse_yield(context, single, tk, method) return if method.block_params get_tkread @scanner.continue = false method.block_params = parse_method_or_yield_parameters end ## # Directives are modifier comments that can appear after class, module, or # method names. For example: # # def fred # :yields: a, b # # or: # # class MyClass # :nodoc: # # We return the directive name and any parameters as a two element array if # the name is in +allowed+. A directive can be found anywhere up to the end # of the current line. def read_directive allowed tokens = [] while tk = get_tk do tokens << tk case tk when TkNL, TkDEF then return when TkCOMMENT then return unless tk.text =~ /\s*:?([\w-]+):\s*(.*)/ directive = $1.downcase return [directive, $2] if allowed.include? directive return end end ensure unless tokens.length == 1 and TkCOMMENT === tokens.first then tokens.reverse_each do |token| unget_tk token end end end ## # Handles directives following the definition for +context+ (any # RDoc::CodeObject) if the directives are +allowed+ at this point. # # See also RDoc::Markup::PreProcess#handle_directive def read_documentation_modifiers context, allowed directive, value = read_directive allowed return unless directive @preprocess.handle_directive '', directive, value, context do |dir, param| if %w[notnew not_new not-new].include? dir then context.dont_rename_initialize = true true end end end ## # Records the location of this +container+ in the file for this parser and # adds it to the list of classes and modules in the file. def record_location container # :nodoc: case container when RDoc::ClassModule then @top_level.add_to_classes_or_modules container end container.record_location @top_level end ## # Removes private comments from +comment+ #-- # TODO remove def remove_private_comments comment comment.remove_private end ## # Scans this Ruby file for Ruby constructs def scan reset catch :eof do begin parse_top_level_statements @top_level rescue StandardError => e bytes = '' 20.times do @scanner.ungetc end count = 0 60.times do |i| count = i byte = @scanner.getc break unless byte bytes << byte end count -= 20 count.times do @scanner.ungetc end $stderr.puts <<-EOF #{self.class} failure around line #{@scanner.line_no} of #{@file_name} EOF unless bytes.empty? then $stderr.puts $stderr.puts bytes.inspect end raise e end end @top_level end ## # while, until, and for have an optional do def skip_optional_do_after_expression skip_tkspace false tk = get_tk end_token = get_end_token tk b_nest = 0 nest = 0 @scanner.continue = false loop do case tk when TkSEMICOLON then break if b_nest.zero? when TkLPAREN, TkfLPAREN then nest += 1 when TkBEGIN then b_nest += 1 when TkEND then b_nest -= 1 when TkDO break if nest.zero? when end_token then if end_token == TkRPAREN nest -= 1 break if @scanner.lex_state == :EXPR_END and nest.zero? else break unless @scanner.continue end when nil then break end tk = get_tk end skip_tkspace false get_tk if TkDO === peek_tk end ## # skip the var [in] part of a 'for' statement def skip_for_variable skip_tkspace false get_tk skip_tkspace false tk = get_tk unget_tk(tk) unless TkIN === tk end ## # Skips the next method in +container+ def skip_method container meth = RDoc::AnyMethod.new "", "anon" parse_method_parameters meth parse_statements container, false, meth end ## # Skip spaces until a comment is found def skip_tkspace_comment(skip_nl = true) loop do skip_tkspace skip_nl return unless TkCOMMENT === peek_tk get_tk end end ## # Updates visibility in +container+ from +vis_type+ and +vis+. def update_visibility container, vis_type, vis, singleton # :nodoc: new_methods = [] case vis_type when 'module_function' then args = parse_symbol_arg container.set_visibility_for args, :private, false container.methods_matching args do |m| s_m = m.dup record_location s_m s_m.singleton = true new_methods << s_m end when 'public_class_method', 'private_class_method' then args = parse_symbol_arg container.methods_matching args, true do |m| if m.parent != container then m = m.dup record_location m new_methods << m end m.visibility = vis end else args = parse_symbol_arg container.set_visibility_for args, vis, singleton end new_methods.each do |method| case method when RDoc::AnyMethod then container.add_method method when RDoc::Attr then container.add_attribute method end method.visibility = vis end end ## # Prints +message+ to +$stderr+ unless we're being quiet def warn message @options.warn make_message message end end PK!ob2.2.0/rdoc/parser/changelog.rbnu[require 'time' ## # A ChangeLog file parser. # # This parser converts a ChangeLog into an RDoc::Markup::Document. When # viewed as HTML a ChangeLog page will have an entry for each day's entries in # the sidebar table of contents. # # This parser is meant to parse the MRI ChangeLog, but can be used to parse any # {GNU style Change # Log}[http://www.gnu.org/prep/standards/html_node/Style-of-Change-Logs.html]. class RDoc::Parser::ChangeLog < RDoc::Parser include RDoc::Parser::Text parse_files_matching(/(\/|\\|\A)ChangeLog[^\/\\]*\z/) ## # Attaches the +continuation+ of the previous line to the +entry_body+. # # Continued function listings are joined together as a single entry. # Continued descriptions are joined to make a single paragraph. def continue_entry_body entry_body, continuation return unless last = entry_body.last if last =~ /\)\s*\z/ and continuation =~ /\A\(/ then last.sub!(/\)\s*\z/, ',') continuation.sub!(/\A\(/, '') end if last =~ /\s\z/ then last << continuation else last << ' ' << continuation end end ## # Creates an RDoc::Markup::Document given the +groups+ of ChangeLog entries. def create_document groups doc = RDoc::Markup::Document.new doc.omit_headings_below = 2 doc.file = @top_level doc << RDoc::Markup::Heading.new(1, File.basename(@file_name)) doc << RDoc::Markup::BlankLine.new groups.sort_by do |day,| day end.reverse_each do |day, entries| doc << RDoc::Markup::Heading.new(2, day.dup) doc << RDoc::Markup::BlankLine.new doc.concat create_entries entries end doc end ## # Returns a list of ChangeLog entries an RDoc::Markup nodes for the given # +entries+. def create_entries entries out = [] entries.each do |entry, items| out << RDoc::Markup::Heading.new(3, entry) out << RDoc::Markup::BlankLine.new out << create_items(items) end out end ## # Returns an RDoc::Markup::List containing the given +items+ in the # ChangeLog def create_items items list = RDoc::Markup::List.new :NOTE items.each do |item| item =~ /\A(.*?(?:\([^)]+\))?):\s*/ title = $1 body = $' paragraph = RDoc::Markup::Paragraph.new body list_item = RDoc::Markup::ListItem.new title, paragraph list << list_item end list end ## # Groups +entries+ by date. def group_entries entries entries.group_by do |title, _| begin Time.parse(title).strftime '%Y-%m-%d' rescue NoMethodError, ArgumentError time, = title.split ' ', 2 Time.parse(time).strftime '%Y-%m-%d' end end end ## # Parses the entries in the ChangeLog. # # Returns an Array of each ChangeLog entry in order of parsing. # # A ChangeLog entry is an Array containing the ChangeLog title (date and # committer) and an Array of ChangeLog items (file and function changed with # description). # # An example result would be: # # [ 'Tue Dec 4 08:33:46 2012 Eric Hodel ', # [ 'README.EXT: Converted to RDoc format', # 'README.EXT.ja: ditto']] def parse_entries entries = [] entry_name = nil entry_body = [] @content.each_line do |line| case line when /^\s*$/ then next when /^\w.*/ then entries << [entry_name, entry_body] if entry_name entry_name = $& begin time = Time.parse entry_name # HACK Ruby 1.8 does not raise ArgumentError for Time.parse "Other" entry_name = nil unless entry_name =~ /#{time.year}/ rescue NoMethodError # HACK Ruby 2.1.2 and earlier raises NoMethodError if time part is absent entry_name.split ' ', 2 rescue ArgumentError if /out of range/ =~ $!.message Time.parse(entry_name.split(' ', 2)[0]) rescue entry_name = nil else entry_name = nil end end entry_body = [] when /^(\t| {8})?\*\s*(.*)/ then # "\t* file.c (func): ..." entry_body << $2 when /^(\t| {8})?\s*(\(.*)/ then # "\t(func): ..." entry = $2 if entry_body.last =~ /:/ then entry_body << entry else continue_entry_body entry_body, entry end when /^(\t| {8})?\s*(.*)/ then continue_entry_body entry_body, $2 end end entries << [entry_name, entry_body] if entry_name entries.reject! do |(entry,_)| entry == nil end entries end ## # Converts the ChangeLog into an RDoc::Markup::Document def scan entries = parse_entries grouped_entries = group_entries entries doc = create_document grouped_entries @top_level.comment = doc @top_level end end PK! Y/Y/2.2.0/rdoc/servlet.rbnu[require 'rdoc' require 'time' require 'webrick' ## # This is a WEBrick servlet that allows you to browse ri documentation. # # You can show documentation through either `ri --server` or, with RubyGems # 2.0 or newer, `gem server`. For ri, the server runs on port 8214 by # default. For RubyGems the server runs on port 8808 by default. # # You can use this servlet in your own project by mounting it on a WEBrick # server: # # require 'webrick' # # server = WEBrick::HTTPServer.new Port: 8000 # # server.mount '/', RDoc::Servlet # # If you want to mount the servlet some other place than the root, provide the # base path when mounting: # # server.mount '/rdoc', RDoc::Servlet, '/rdoc' class RDoc::Servlet < WEBrick::HTTPServlet::AbstractServlet @server_stores = Hash.new { |hash, server| hash[server] = {} } @cache = Hash.new { |hash, store| hash[store] = {} } ## # Maps an asset type to its path on the filesystem attr_reader :asset_dirs ## # An RDoc::Options instance used for rendering options attr_reader :options ## # Creates an instance of this servlet that shares cached data between # requests. def self.get_instance server, *options # :nodoc: stores = @server_stores[server] new server, stores, @cache, *options end ## # Creates a new WEBrick servlet. # # Use +mount_path+ when mounting the servlet somewhere other than /. # # Use +extra_doc_dirs+ for additional documentation directories. # # +server+ is provided automatically by WEBrick when mounting. +stores+ and # +cache+ are provided automatically by the servlet. def initialize server, stores, cache, mount_path = nil, extra_doc_dirs = [] super server @cache = cache @mount_path = mount_path @extra_doc_dirs = extra_doc_dirs @stores = stores @options = RDoc::Options.new @options.op_dir = '.' darkfish_dir = nil # HACK dup $LOAD_PATH.each do |path| darkfish_dir = File.join path, 'rdoc/generator/template/darkfish/' next unless File.directory? darkfish_dir @options.template_dir = darkfish_dir break end @asset_dirs = { :darkfish => darkfish_dir, :json_index => File.expand_path('../generator/template/json_index/', __FILE__), } end ## # Serves the asset at the path in +req+ for +generator_name+ via +res+. def asset generator_name, req, res asset_dir = @asset_dirs[generator_name] asset_path = File.join asset_dir, req.path if_modified_since req, res, asset_path res.body = File.read asset_path res.content_type = case req.path when /css$/ then 'text/css' when /js$/ then 'application/javascript' else 'application/octet-stream' end end ## # GET request entry point. Fills in +res+ for the path, etc. in +req+. def do_GET req, res req.path.sub!(/^#{Regexp.escape @mount_path}/o, '') if @mount_path case req.path when '/' then root req, res when '/rdoc.css', '/js/darkfish.js', '/js/jquery.js', '/js/search.js', %r%^/images/% then asset :darkfish, req, res when '/js/navigation.js', '/js/searcher.js' then asset :json_index, req, res when '/js/search_index.js' then root_search req, res else show_documentation req, res end rescue WEBrick::HTTPStatus::NotFound => e generator = generator_for RDoc::Store.new not_found generator, req, res, e.message rescue WEBrick::HTTPStatus::Status raise rescue => e error e, req, res end ## # Fills in +res+ with the class, module or page for +req+ from +store+. # # +path+ is relative to the mount_path and is used to determine the class, # module or page name (/RDoc/Servlet.html becomes RDoc::Servlet). # +generator+ is used to create the page. def documentation_page store, generator, path, req, res name = path.sub(/.html$/, '').gsub '/', '::' if klass = store.find_class_or_module(name) then res.body = generator.generate_class klass elsif page = store.find_text_page(name.sub(/_([^_]*)$/, '.\1')) then res.body = generator.generate_page page else not_found generator, req, res end end ## # Creates the JSON search index on +res+ for the given +store+. +generator+ # must respond to \#json_index to build. +req+ is ignored. def documentation_search store, generator, req, res json_index = @cache[store].fetch :json_index do @cache[store][:json_index] = JSON.dump generator.json_index.build_index end res.content_type = 'application/javascript' res.body = "var search_data = #{json_index}" end ## # Returns the RDoc::Store and path relative to +mount_path+ for # documentation at +path+. def documentation_source path _, source_name, path = path.split '/', 3 store = @stores[source_name] return store, path if store store = store_for source_name store.load_all @stores[source_name] = store return store, path end ## # Generates an error page for the +exception+ while handling +req+ on +res+. def error exception, req, res backtrace = exception.backtrace.join "\n" res.content_type = 'text/html' res.status = 500 res.body = <<-BODY Error - #{ERB::Util.html_escape exception.class}

    Error

    While processing #{ERB::Util.html_escape req.request_uri} the RDoc (#{ERB::Util.html_escape RDoc::VERSION}) server has encountered a #{ERB::Util.html_escape exception.class} exception:

    #{ERB::Util.html_escape exception.message}

    Please report this to the RDoc issues tracker. Please include the RDoc version, the URI above and exception class, message and backtrace. If you're viewing a gem's documentation, include the gem name and version. If you're viewing Ruby's documentation, include the version of ruby.

    Backtrace:

    #{ERB::Util.html_escape backtrace}
    BODY end ## # Instantiates a Darkfish generator for +store+ def generator_for store generator = RDoc::Generator::Darkfish.new store, @options generator.file_output = false generator.asset_rel_path = '..' rdoc = RDoc::RDoc.new rdoc.store = store rdoc.generator = generator rdoc.options = @options @options.main_page = store.main @options.title = store.title generator end ## # Handles the If-Modified-Since HTTP header on +req+ for +path+. If the # file has not been modified a Not Modified response is returned. If the # file has been modified a Last-Modified header is added to +res+. def if_modified_since req, res, path = nil last_modified = File.stat(path).mtime if path res['last-modified'] = last_modified.httpdate return unless ims = req['if-modified-since'] ims = Time.parse ims unless ims < last_modified then res.body = '' raise WEBrick::HTTPStatus::NotModified end end ## # Returns an Array of installed documentation. # # Each entry contains the documentation name (gem name, 'Ruby # Documentation', etc.), the path relative to the mount point, whether the # documentation exists, the type of documentation (See RDoc::RI::Paths#each) # and the filesystem to the RDoc::Store for the documentation. def installed_docs extra_counter = 0 ri_paths.map do |path, type| store = RDoc::Store.new path, type exists = File.exist? store.cache_path case type when :gem then gem_path = path[%r%/([^/]*)/ri$%, 1] [gem_path, "#{gem_path}/", exists, type, path] when :system then ['Ruby Documentation', 'ruby/', exists, type, path] when :site then ['Site Documentation', 'site/', exists, type, path] when :home then ['Home Documentation', 'home/', exists, type, path] when :extra then extra_counter += 1 store.load_cache if exists title = store.title || "Extra Documentation" [title, "extra-#{extra_counter}/", exists, type, path] end end end ## # Returns a 404 page built by +generator+ for +req+ on +res+. def not_found generator, req, res, message = nil message ||= "The page #{ERB::Util.h req.path} was not found" res.body = generator.generate_servlet_not_found message res.status = 404 end ## # Enumerates the ri paths. See RDoc::RI::Paths#each def ri_paths &block RDoc::RI::Paths.each true, true, true, :all, *@extra_doc_dirs, &block #TODO: pass extra_dirs end ## # Generates the root page on +res+. +req+ is ignored. def root req, res generator = RDoc::Generator::Darkfish.new nil, @options res.body = generator.generate_servlet_root installed_docs res.content_type = 'text/html' end ## # Generates a search index for the root page on +res+. +req+ is ignored. def root_search req, res search_index = [] info = [] installed_docs.map do |name, href, exists, type, path| next unless exists search_index << name case type when :gem gemspec = path.gsub(%r%/doc/([^/]*?)/ri$%, '/specifications/\1.gemspec') spec = Gem::Specification.load gemspec path = spec.full_name comment = spec.summary when :system then path = 'ruby' comment = 'Documentation for the Ruby standard library' when :site then path = 'site' comment = 'Documentation for non-gem libraries' when :home then path = 'home' comment = 'Documentation from your home directory' when :extra comment = name end info << [name, '', path, '', comment] end index = { :index => { :searchIndex => search_index, :longSearchIndex => search_index, :info => info, } } res.body = "var search_data = #{JSON.dump index};" res.content_type = 'application/javascript' end ## # Displays documentation for +req+ on +res+, whether that be HTML or some # asset. def show_documentation req, res store, path = documentation_source req.path if_modified_since req, res, store.cache_path generator = generator_for store case path when nil, '', 'index.html' then res.body = generator.generate_index when 'table_of_contents.html' then res.body = generator.generate_table_of_contents when 'js/search_index.js' then documentation_search store, generator, req, res else documentation_page store, generator, path, req, res end ensure res.content_type ||= 'text/html' end ## # Returns an RDoc::Store for the given +source_name+ ('ruby' or a gem name). def store_for source_name case source_name when 'home' then RDoc::Store.new RDoc::RI::Paths.home_dir, :home when 'ruby' then RDoc::Store.new RDoc::RI::Paths.system_dir, :system when 'site' then RDoc::Store.new RDoc::RI::Paths.site_dir, :site when /^extra-(\d+)$/ then index = $1.to_i - 1 ri_dir = installed_docs[index][4] RDoc::Store.new ri_dir, :extra else ri_dir, type = ri_paths.find do |dir, dir_type| next unless dir_type == :gem source_name == dir[%r%/([^/]*)/ri$%, 1] end raise WEBrick::HTTPStatus::NotFound, "Could not find gem \"#{source_name}\". Are you sure you installed it?" unless ri_dir store = RDoc::Store.new ri_dir, type return store if File.exist? store.cache_path raise WEBrick::HTTPStatus::NotFound, "Could not find documentation for \"#{source_name}\". Please run `gem rdoc --ri gem_name`" end end end PK!;;2.2.0/rdoc/ri.rbnu[require 'rdoc' ## # Namespace for the ri command line tool's implementation. # # See ri --help for details. module RDoc::RI ## # Base RI error class class Error < RDoc::Error; end autoload :Driver, 'rdoc/ri/driver' autoload :Paths, 'rdoc/ri/paths' autoload :Store, 'rdoc/ri/store' end PK!ui}i}2.2.0/rdoc/rd/inline_parser.rbnu[# # DO NOT MODIFY!!!! # This file is automatically generated by Racc 1.4.12 # from Racc grammer file "". # require 'racc/parser.rb' require 'strscan' class RDoc::RD ## # RD format parser for inline markup such as emphasis, links, footnotes, etc. class InlineParser < Racc::Parser # :stopdoc: EM_OPEN = '((*' EM_OPEN_RE = /\A#{Regexp.quote(EM_OPEN)}/ EM_CLOSE = '*))' EM_CLOSE_RE = /\A#{Regexp.quote(EM_CLOSE)}/ CODE_OPEN = '(({' CODE_OPEN_RE = /\A#{Regexp.quote(CODE_OPEN)}/ CODE_CLOSE = '}))' CODE_CLOSE_RE = /\A#{Regexp.quote(CODE_CLOSE)}/ VAR_OPEN = '((|' VAR_OPEN_RE = /\A#{Regexp.quote(VAR_OPEN)}/ VAR_CLOSE = '|))' VAR_CLOSE_RE = /\A#{Regexp.quote(VAR_CLOSE)}/ KBD_OPEN = '((%' KBD_OPEN_RE = /\A#{Regexp.quote(KBD_OPEN)}/ KBD_CLOSE = '%))' KBD_CLOSE_RE = /\A#{Regexp.quote(KBD_CLOSE)}/ INDEX_OPEN = '((:' INDEX_OPEN_RE = /\A#{Regexp.quote(INDEX_OPEN)}/ INDEX_CLOSE = ':))' INDEX_CLOSE_RE = /\A#{Regexp.quote(INDEX_CLOSE)}/ REF_OPEN = '((<' REF_OPEN_RE = /\A#{Regexp.quote(REF_OPEN)}/ REF_CLOSE = '>))' REF_CLOSE_RE = /\A#{Regexp.quote(REF_CLOSE)}/ FOOTNOTE_OPEN = '((-' FOOTNOTE_OPEN_RE = /\A#{Regexp.quote(FOOTNOTE_OPEN)}/ FOOTNOTE_CLOSE = '-))' FOOTNOTE_CLOSE_RE = /\A#{Regexp.quote(FOOTNOTE_CLOSE)}/ VERB_OPEN = "(('" VERB_OPEN_RE = /\A#{Regexp.quote(VERB_OPEN)}/ VERB_CLOSE = "'))" VERB_CLOSE_RE = /\A#{Regexp.quote(VERB_CLOSE)}/ BAR = "|" BAR_RE = /\A#{Regexp.quote(BAR)}/ QUOTE = '"' QUOTE_RE = /\A#{Regexp.quote(QUOTE)}/ SLASH = "/" SLASH_RE = /\A#{Regexp.quote(SLASH)}/ BACK_SLASH = "\\" BACK_SLASH_RE = /\A#{Regexp.quote(BACK_SLASH)}/ URL = "URL:" URL_RE = /\A#{Regexp.quote(URL)}/ other_re_mode = Regexp::EXTENDED other_re_mode |= Regexp::MULTILINE OTHER_RE = Regexp.new( "\\A.+?(?=#{Regexp.quote(EM_OPEN)}|#{Regexp.quote(EM_CLOSE)}| #{Regexp.quote(CODE_OPEN)}|#{Regexp.quote(CODE_CLOSE)}| #{Regexp.quote(VAR_OPEN)}|#{Regexp.quote(VAR_CLOSE)}| #{Regexp.quote(KBD_OPEN)}|#{Regexp.quote(KBD_CLOSE)}| #{Regexp.quote(INDEX_OPEN)}|#{Regexp.quote(INDEX_CLOSE)}| #{Regexp.quote(REF_OPEN)}|#{Regexp.quote(REF_CLOSE)}| #{Regexp.quote(FOOTNOTE_OPEN)}|#{Regexp.quote(FOOTNOTE_CLOSE)}| #{Regexp.quote(VERB_OPEN)}|#{Regexp.quote(VERB_CLOSE)}| #{Regexp.quote(BAR)}| #{Regexp.quote(QUOTE)}| #{Regexp.quote(SLASH)}| #{Regexp.quote(BACK_SLASH)}| #{Regexp.quote(URL)})", other_re_mode) # :startdoc: ## # Creates a new parser for inline markup in the rd format. The +block_parser+ # is used to for footnotes and labels in the inline text. def initialize block_parser @block_parser = block_parser end ## # Parses the +inline+ text from RD format into RDoc format. def parse inline @inline = inline @src = StringScanner.new inline @pre = "" @yydebug = true do_parse.to_s end ## # Returns the next token from the inline text def next_token return [false, false] if @src.eos? # p @src.rest if @yydebug if ret = @src.scan(EM_OPEN_RE) @pre << ret [:EM_OPEN, ret] elsif ret = @src.scan(EM_CLOSE_RE) @pre << ret [:EM_CLOSE, ret] elsif ret = @src.scan(CODE_OPEN_RE) @pre << ret [:CODE_OPEN, ret] elsif ret = @src.scan(CODE_CLOSE_RE) @pre << ret [:CODE_CLOSE, ret] elsif ret = @src.scan(VAR_OPEN_RE) @pre << ret [:VAR_OPEN, ret] elsif ret = @src.scan(VAR_CLOSE_RE) @pre << ret [:VAR_CLOSE, ret] elsif ret = @src.scan(KBD_OPEN_RE) @pre << ret [:KBD_OPEN, ret] elsif ret = @src.scan(KBD_CLOSE_RE) @pre << ret [:KBD_CLOSE, ret] elsif ret = @src.scan(INDEX_OPEN_RE) @pre << ret [:INDEX_OPEN, ret] elsif ret = @src.scan(INDEX_CLOSE_RE) @pre << ret [:INDEX_CLOSE, ret] elsif ret = @src.scan(REF_OPEN_RE) @pre << ret [:REF_OPEN, ret] elsif ret = @src.scan(REF_CLOSE_RE) @pre << ret [:REF_CLOSE, ret] elsif ret = @src.scan(FOOTNOTE_OPEN_RE) @pre << ret [:FOOTNOTE_OPEN, ret] elsif ret = @src.scan(FOOTNOTE_CLOSE_RE) @pre << ret [:FOOTNOTE_CLOSE, ret] elsif ret = @src.scan(VERB_OPEN_RE) @pre << ret [:VERB_OPEN, ret] elsif ret = @src.scan(VERB_CLOSE_RE) @pre << ret [:VERB_CLOSE, ret] elsif ret = @src.scan(BAR_RE) @pre << ret [:BAR, ret] elsif ret = @src.scan(QUOTE_RE) @pre << ret [:QUOTE, ret] elsif ret = @src.scan(SLASH_RE) @pre << ret [:SLASH, ret] elsif ret = @src.scan(BACK_SLASH_RE) @pre << ret [:BACK_SLASH, ret] elsif ret = @src.scan(URL_RE) @pre << ret [:URL, ret] elsif ret = @src.scan(OTHER_RE) @pre << ret [:OTHER, ret] else ret = @src.rest @pre << ret @src.terminate [:OTHER, ret] end end ## # Raises a ParseError when invalid formatting is found def on_error(et, ev, values) lines_of_rest = @src.rest.lines.to_a.length prev_words = prev_words_on_error(ev) at = 4 + prev_words.length message = <<-MSG RD syntax error: line #{@block_parser.line_index - lines_of_rest}: ...#{prev_words} #{(ev||'')} #{next_words_on_error()} ... MSG message << " " * at + "^" * (ev ? ev.length : 0) + "\n" raise ParseError, message end ## # Returns words before the error def prev_words_on_error(ev) pre = @pre if ev and /#{Regexp.quote(ev)}$/ =~ pre pre = $` end last_line(pre) end ## # Returns the last line of +src+ def last_line(src) if n = src.rindex("\n") src[(n+1) .. -1] else src end end private :last_line ## # Returns words following an error def next_words_on_error if n = @src.rest.index("\n") @src.rest[0 .. (n-1)] else @src.rest end end ## # Creates a new RDoc::RD::Inline for the +rdoc+ markup and the raw +reference+ def inline rdoc, reference = rdoc RDoc::RD::Inline.new rdoc, reference end # :stopdoc: ##### State transition tables begin ### racc_action_table = [ 63, 64, 65, 153, 81, 62, 76, 78, 79, 87, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 77, 80, 152, 63, 64, 65, 61, 81, 62, 76, 78, 79, 124, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 77, 80, 149, 104, 103, 102, 100, 101, 99, 115, 116, 117, 164, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 96, 118, 119, 104, 103, 102, 100, 101, 99, 115, 116, 117, 89, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 88, 118, 119, 104, 103, 102, 100, 101, 99, 115, 116, 117, 161, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 86, 118, 119, 104, 103, 102, 100, 101, 99, 115, 116, 117, 85, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 137, 118, 119, 63, 64, 65, 61, 81, 62, 76, 78, 79, 84, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 77, 80, 22, 23, 24, 25, 26, 21, 18, 19, 176, 177, 13, 173, 14, 154, 15, 175, 16, 137, 17, 42, 148, 20, 54, 38, 53, 55, 56, 57, 29, 13, 177, 14, nil, 15, nil, 16, nil, 17, nil, nil, 20, 22, 23, 24, 25, 26, 21, 18, 19, nil, nil, 13, nil, 14, nil, 15, nil, 16, nil, 17, nil, nil, 20, 22, 23, 24, 25, 26, 21, 18, 19, nil, nil, 13, nil, 14, nil, 15, nil, 16, nil, 17, nil, nil, 20, 22, 23, 24, 25, 26, 21, 18, 19, nil, nil, 13, nil, 14, nil, 15, nil, 16, nil, 17, 145, nil, 20, 54, 133, 53, 55, 56, 57, nil, 13, nil, 14, nil, 15, nil, 16, nil, 17, nil, nil, 20, 22, 23, 24, 25, 26, 21, 18, 19, nil, nil, 13, nil, 14, nil, 15, nil, 16, nil, 17, 145, nil, 20, 54, 133, 53, 55, 56, 57, nil, 13, nil, 14, nil, 15, nil, 16, nil, 17, nil, nil, 20, 22, 23, 24, 25, 26, 21, 18, 19, nil, nil, 13, nil, 14, nil, 15, nil, 16, nil, 17, 145, nil, 20, 54, 133, 53, 55, 56, 57, nil, 13, nil, 14, nil, 15, nil, 16, nil, 17, 145, nil, 20, 54, 133, 53, 55, 56, 57, nil, 13, nil, 14, nil, 15, nil, 16, nil, 17, nil, nil, 20, 22, 23, 24, 25, 26, 21, 18, 19, nil, nil, 13, nil, 14, nil, 15, nil, 16, 122, 17, nil, 54, 20, 53, 55, 56, 57, nil, 13, nil, 14, nil, 15, nil, 16, nil, 17, nil, nil, 20, 22, 23, 24, 25, 26, 21, 18, 19, nil, nil, 13, nil, 14, nil, 15, nil, 16, nil, 17, nil, nil, 20, 135, 136, 54, 133, 53, 55, 56, 57, nil, 13, nil, 14, nil, 15, nil, 16, nil, 17, nil, nil, 20, 135, 136, 54, 133, 53, 55, 56, 57, nil, 13, nil, 14, nil, 15, nil, 16, nil, 17, nil, nil, 20, 135, 136, 54, 133, 53, 55, 56, 57, nil, 13, nil, 14, nil, 15, nil, 16, nil, 17, nil, nil, 20, 172, 135, 136, 54, 133, 53, 55, 56, 57, 165, 135, 136, 54, 133, 53, 55, 56, 57, 95, nil, nil, 54, 91, 53, 55, 56, 57, 174, 135, 136, 54, 133, 53, 55, 56, 57, 158, nil, nil, 54, nil, 53, 55, 56, 57, 178, 135, 136, 54, 133, 53, 55, 56, 57, 145, nil, nil, 54, 133, 53, 55, 56, 57, 145, nil, nil, 54, 133, 53, 55, 56, 57, 135, 136, 54, 133, 53, 55, 56, 57, 135, 136, 54, 133, 53, 55, 56, 57, 135, 136, 54, 133, 53, 55, 56, 57, 22, 23, 24, 25, 26, 21 ] racc_action_check = [ 61, 61, 61, 61, 61, 61, 61, 61, 61, 33, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 41, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 97, 97, 97, 97, 97, 97, 97, 97, 97, 125, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 37, 97, 97, 38, 38, 38, 38, 38, 38, 38, 38, 38, 35, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 34, 38, 38, 155, 155, 155, 155, 155, 155, 155, 155, 155, 100, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 32, 155, 155, 91, 91, 91, 91, 91, 91, 91, 91, 91, 31, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 43, 91, 91, 20, 20, 20, 20, 20, 20, 20, 20, 20, 29, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 17, 17, 17, 17, 17, 17, 17, 17, 165, 165, 17, 162, 17, 90, 17, 164, 17, 94, 17, 18, 58, 17, 18, 18, 18, 18, 18, 18, 1, 18, 172, 18, nil, 18, nil, 18, nil, 18, nil, nil, 18, 19, 19, 19, 19, 19, 19, 19, 19, nil, nil, 19, nil, 19, nil, 19, nil, 19, nil, 19, nil, nil, 19, 16, 16, 16, 16, 16, 16, 16, 16, nil, nil, 16, nil, 16, nil, 16, nil, 16, nil, 16, nil, nil, 16, 15, 15, 15, 15, 15, 15, 15, 15, nil, nil, 15, nil, 15, nil, 15, nil, 15, nil, 15, 45, nil, 15, 45, 45, 45, 45, 45, 45, nil, 45, nil, 45, nil, 45, nil, 45, nil, 45, nil, nil, 45, 14, 14, 14, 14, 14, 14, 14, 14, nil, nil, 14, nil, 14, nil, 14, nil, 14, nil, 14, 146, nil, 14, 146, 146, 146, 146, 146, 146, nil, 146, nil, 146, nil, 146, nil, 146, nil, 146, nil, nil, 146, 13, 13, 13, 13, 13, 13, 13, 13, nil, nil, 13, nil, 13, nil, 13, nil, 13, nil, 13, 138, nil, 13, 138, 138, 138, 138, 138, 138, nil, 138, nil, 138, nil, 138, nil, 138, nil, 138, 44, nil, 138, 44, 44, 44, 44, 44, 44, nil, 44, nil, 44, nil, 44, nil, 44, nil, 44, nil, nil, 44, 2, 2, 2, 2, 2, 2, 2, 2, nil, nil, 2, nil, 2, nil, 2, nil, 2, 39, 2, nil, 39, 2, 39, 39, 39, 39, nil, 39, nil, 39, nil, 39, nil, 39, nil, 39, nil, nil, 39, 0, 0, 0, 0, 0, 0, 0, 0, nil, nil, 0, nil, 0, nil, 0, nil, 0, nil, 0, nil, nil, 0, 122, 122, 122, 122, 122, 122, 122, 122, nil, 122, nil, 122, nil, 122, nil, 122, nil, 122, nil, nil, 122, 127, 127, 127, 127, 127, 127, 127, 127, nil, 127, nil, 127, nil, 127, nil, 127, nil, 127, nil, nil, 127, 42, 42, 42, 42, 42, 42, 42, 42, nil, 42, nil, 42, nil, 42, nil, 42, nil, 42, nil, nil, 42, 159, 159, 159, 159, 159, 159, 159, 159, 159, 126, 126, 126, 126, 126, 126, 126, 126, 126, 36, nil, nil, 36, 36, 36, 36, 36, 36, 163, 163, 163, 163, 163, 163, 163, 163, 163, 92, nil, nil, 92, nil, 92, 92, 92, 92, 171, 171, 171, 171, 171, 171, 171, 171, 171, 142, nil, nil, 142, 142, 142, 142, 142, 142, 52, nil, nil, 52, 52, 52, 52, 52, 52, 95, 95, 95, 95, 95, 95, 95, 95, 168, 168, 168, 168, 168, 168, 168, 168, 158, 158, 158, 158, 158, 158, 158, 158, 27, 27, 27, 27, 27, 27 ] racc_action_pointer = [ 423, 188, 384, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 324, 283, 242, 220, 157, 176, 198, 135, nil, nil, nil, nil, nil, nil, 604, nil, 147, nil, 110, 96, -9, 69, 56, 526, 43, 66, 401, nil, 28, 486, 130, 362, 261, nil, nil, nil, nil, nil, nil, 571, nil, nil, nil, nil, nil, 169, 20, nil, -3, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 150, 112, 544, nil, 172, 579, nil, 43, nil, nil, 95, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 444, nil, nil, 52, 517, 465, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 343, nil, nil, nil, 562, nil, nil, nil, 302, nil, nil, nil, nil, nil, nil, nil, nil, 89, nil, nil, 595, 508, nil, nil, 168, 535, 171, 164, nil, nil, 587, nil, nil, 553, 185, nil, nil, nil, nil, nil, nil ] racc_action_default = [ -138, -138, -1, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12, -138, -138, -138, -138, -138, -138, -138, -138, -103, -104, -105, -106, -107, -108, -111, -110, -138, -2, -138, -138, -138, -138, -138, -138, -138, -138, -27, -26, -35, -138, -58, -41, -40, -47, -48, -49, -50, -51, -52, -63, -66, -67, -68, -69, -70, -138, -138, -112, -138, -116, -117, -118, -119, -120, -121, -122, -123, -124, -125, -126, -127, -128, -129, -130, -131, -132, -133, -134, -135, -137, -109, 179, -13, -14, -15, -16, -17, -138, -138, -23, -22, -33, -138, -19, -24, -79, -80, -138, -82, -83, -84, -85, -86, -87, -88, -89, -90, -91, -92, -93, -94, -95, -96, -97, -98, -99, -100, -25, -35, -138, -58, -28, -138, -59, -42, -46, -55, -56, -65, -71, -72, -75, -76, -77, -31, -38, -44, -53, -54, -57, -61, -73, -74, -39, -62, -101, -102, -136, -113, -114, -115, -18, -20, -21, -33, -138, -138, -78, -81, -138, -59, -36, -37, -64, -45, -59, -43, -60, -138, -34, -36, -37, -29, -30, -32, -34 ] racc_goto_table = [ 126, 44, 125, 43, 144, 144, 160, 93, 97, 52, 166, 82, 144, 41, 40, 39, 138, 146, 169, 147, 167, 94, 44, 1, 123, 129, 169, 52, 36, 37, 52, 90, 59, 92, 121, 120, 31, 32, 33, 34, 35, 170, 58, 166, 83, 30, 170, 166, 151, nil, 150, nil, 166, 159, 8, 166, 8, nil, nil, nil, nil, 155, nil, 156, 160, nil, nil, 8, 8, 8, 8, 8, nil, 8, 4, nil, 4, 157, nil, nil, 163, nil, 162, 52, nil, 168, nil, 4, 4, 4, 4, 4, nil, 4, nil, nil, nil, nil, 144, nil, nil, nil, 144, nil, nil, 129, 144, 144, nil, 5, 129, 5, nil, nil, nil, nil, 171, 6, nil, 6, nil, nil, 5, 5, 5, 5, 5, 11, 5, 11, 6, 6, 6, 6, 6, 7, 6, 7, nil, nil, 11, 11, 11, 11, 11, nil, 11, nil, 7, 7, 7, 7, 7, nil, 7 ] racc_goto_check = [ 22, 24, 21, 23, 36, 36, 37, 18, 16, 34, 35, 41, 36, 20, 19, 17, 25, 25, 28, 32, 29, 23, 24, 1, 23, 24, 28, 34, 13, 15, 34, 14, 38, 17, 20, 19, 1, 1, 1, 1, 1, 33, 1, 35, 39, 3, 33, 35, 42, nil, 41, nil, 35, 22, 8, 35, 8, nil, nil, nil, nil, 16, nil, 18, 37, nil, nil, 8, 8, 8, 8, 8, nil, 8, 4, nil, 4, 23, nil, nil, 22, nil, 21, 34, nil, 22, nil, 4, 4, 4, 4, 4, nil, 4, nil, nil, nil, nil, 36, nil, nil, nil, 36, nil, nil, 24, 36, 36, nil, 5, 24, 5, nil, nil, nil, nil, 22, 6, nil, 6, nil, nil, 5, 5, 5, 5, 5, 11, 5, 11, 6, 6, 6, 6, 6, 7, 6, 7, nil, nil, 11, 11, 11, 11, 11, nil, 11, nil, 7, 7, 7, 7, 7, nil, 7 ] racc_goto_pointer = [ nil, 23, nil, 43, 74, 109, 117, 135, 54, nil, nil, 127, nil, 10, -5, 11, -30, -3, -29, -4, -5, -40, -42, -15, -17, -28, nil, nil, -120, -107, nil, nil, -33, -101, -9, -116, -40, -91, 12, 17, nil, -9, -13 ] racc_goto_default = [ nil, nil, 2, 3, 46, 47, 48, 49, 50, 9, 10, 51, 12, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 140, nil, 45, 127, 139, 128, 141, 130, 142, 143, 132, 131, 134, 98, nil, 28, 27, nil, 60 ] racc_reduce_table = [ 0, 0, :racc_error, 1, 27, :_reduce_none, 2, 28, :_reduce_2, 1, 28, :_reduce_3, 1, 29, :_reduce_none, 1, 29, :_reduce_none, 1, 29, :_reduce_none, 1, 29, :_reduce_none, 1, 29, :_reduce_none, 1, 29, :_reduce_none, 1, 29, :_reduce_none, 1, 29, :_reduce_none, 1, 29, :_reduce_none, 3, 30, :_reduce_13, 3, 31, :_reduce_14, 3, 32, :_reduce_15, 3, 33, :_reduce_16, 3, 34, :_reduce_17, 4, 35, :_reduce_18, 3, 35, :_reduce_19, 2, 40, :_reduce_20, 2, 40, :_reduce_21, 1, 40, :_reduce_22, 1, 40, :_reduce_23, 2, 41, :_reduce_24, 2, 41, :_reduce_25, 1, 41, :_reduce_26, 1, 41, :_reduce_27, 2, 39, :_reduce_none, 4, 39, :_reduce_29, 4, 39, :_reduce_30, 2, 43, :_reduce_31, 4, 43, :_reduce_32, 1, 44, :_reduce_33, 3, 44, :_reduce_34, 1, 45, :_reduce_none, 3, 45, :_reduce_36, 3, 45, :_reduce_37, 2, 46, :_reduce_38, 2, 46, :_reduce_39, 1, 46, :_reduce_40, 1, 46, :_reduce_41, 1, 47, :_reduce_none, 2, 51, :_reduce_43, 1, 51, :_reduce_44, 2, 53, :_reduce_45, 1, 53, :_reduce_46, 1, 50, :_reduce_none, 1, 50, :_reduce_none, 1, 50, :_reduce_none, 1, 50, :_reduce_none, 1, 50, :_reduce_none, 1, 50, :_reduce_none, 1, 54, :_reduce_none, 1, 54, :_reduce_none, 1, 55, :_reduce_none, 1, 55, :_reduce_none, 1, 56, :_reduce_57, 1, 52, :_reduce_58, 1, 57, :_reduce_59, 2, 58, :_reduce_60, 1, 58, :_reduce_none, 2, 49, :_reduce_62, 1, 49, :_reduce_none, 2, 48, :_reduce_64, 1, 48, :_reduce_none, 1, 60, :_reduce_none, 1, 60, :_reduce_none, 1, 60, :_reduce_none, 1, 60, :_reduce_none, 1, 60, :_reduce_none, 1, 62, :_reduce_none, 1, 62, :_reduce_none, 1, 59, :_reduce_none, 1, 59, :_reduce_none, 1, 61, :_reduce_none, 1, 61, :_reduce_none, 1, 61, :_reduce_none, 2, 42, :_reduce_78, 1, 42, :_reduce_none, 1, 63, :_reduce_none, 2, 63, :_reduce_none, 1, 63, :_reduce_none, 1, 63, :_reduce_none, 1, 63, :_reduce_none, 1, 63, :_reduce_none, 1, 63, :_reduce_none, 1, 63, :_reduce_none, 1, 63, :_reduce_none, 1, 63, :_reduce_none, 1, 63, :_reduce_none, 1, 63, :_reduce_none, 1, 63, :_reduce_none, 1, 63, :_reduce_none, 1, 63, :_reduce_none, 1, 63, :_reduce_none, 1, 63, :_reduce_none, 1, 63, :_reduce_none, 1, 63, :_reduce_none, 1, 63, :_reduce_none, 1, 63, :_reduce_none, 3, 36, :_reduce_101, 3, 37, :_reduce_102, 1, 65, :_reduce_none, 1, 65, :_reduce_none, 1, 65, :_reduce_none, 1, 65, :_reduce_none, 1, 65, :_reduce_none, 1, 65, :_reduce_none, 2, 66, :_reduce_109, 1, 66, :_reduce_none, 1, 38, :_reduce_111, 1, 67, :_reduce_none, 2, 67, :_reduce_113, 2, 67, :_reduce_114, 2, 67, :_reduce_115, 1, 68, :_reduce_none, 1, 68, :_reduce_none, 1, 68, :_reduce_none, 1, 68, :_reduce_none, 1, 68, :_reduce_none, 1, 68, :_reduce_none, 1, 68, :_reduce_none, 1, 68, :_reduce_none, 1, 68, :_reduce_none, 1, 68, :_reduce_none, 1, 68, :_reduce_none, 1, 68, :_reduce_none, 1, 68, :_reduce_none, 1, 68, :_reduce_none, 1, 68, :_reduce_none, 1, 68, :_reduce_none, 1, 68, :_reduce_none, 1, 68, :_reduce_none, 1, 68, :_reduce_none, 1, 68, :_reduce_none, 2, 64, :_reduce_136, 1, 64, :_reduce_none ] racc_reduce_n = 138 racc_shift_n = 179 racc_token_table = { false => 0, :error => 1, :EX_LOW => 2, :QUOTE => 3, :BAR => 4, :SLASH => 5, :BACK_SLASH => 6, :URL => 7, :OTHER => 8, :REF_OPEN => 9, :FOOTNOTE_OPEN => 10, :FOOTNOTE_CLOSE => 11, :EX_HIGH => 12, :EM_OPEN => 13, :EM_CLOSE => 14, :CODE_OPEN => 15, :CODE_CLOSE => 16, :VAR_OPEN => 17, :VAR_CLOSE => 18, :KBD_OPEN => 19, :KBD_CLOSE => 20, :INDEX_OPEN => 21, :INDEX_CLOSE => 22, :REF_CLOSE => 23, :VERB_OPEN => 24, :VERB_CLOSE => 25 } racc_nt_base = 26 racc_use_result_var = true Racc_arg = [ racc_action_table, racc_action_check, racc_action_default, racc_action_pointer, racc_goto_table, racc_goto_check, racc_goto_default, racc_goto_pointer, racc_nt_base, racc_reduce_table, racc_token_table, racc_shift_n, racc_reduce_n, racc_use_result_var ] Racc_token_to_s_table = [ "$end", "error", "EX_LOW", "QUOTE", "BAR", "SLASH", "BACK_SLASH", "URL", "OTHER", "REF_OPEN", "FOOTNOTE_OPEN", "FOOTNOTE_CLOSE", "EX_HIGH", "EM_OPEN", "EM_CLOSE", "CODE_OPEN", "CODE_CLOSE", "VAR_OPEN", "VAR_CLOSE", "KBD_OPEN", "KBD_CLOSE", "INDEX_OPEN", "INDEX_CLOSE", "REF_CLOSE", "VERB_OPEN", "VERB_CLOSE", "$start", "content", "elements", "element", "emphasis", "code", "var", "keyboard", "index", "reference", "footnote", "verb", "normal_str_ele", "substitute", "ref_label", "ref_label2", "ref_url_strings", "filename", "element_label", "element_label2", "ref_subst_content", "ref_subst_content_q", "ref_subst_strings_q", "ref_subst_strings_first", "ref_subst_ele2", "ref_subst_eles", "ref_subst_str_ele_first", "ref_subst_eles_q", "ref_subst_ele", "ref_subst_ele_q", "ref_subst_str_ele", "ref_subst_str_ele_q", "ref_subst_strings", "ref_subst_string3", "ref_subst_string", "ref_subst_string_q", "ref_subst_string2", "ref_url_string", "verb_strings", "normal_string", "normal_strings", "verb_string", "verb_normal_string" ] Racc_debug_parser = false ##### State transition tables end ##### # reduce 0 omitted # reduce 1 omitted def _reduce_2(val, _values, result) result.append val[1] result end def _reduce_3(val, _values, result) result = val[0] result end # reduce 4 omitted # reduce 5 omitted # reduce 6 omitted # reduce 7 omitted # reduce 8 omitted # reduce 9 omitted # reduce 10 omitted # reduce 11 omitted # reduce 12 omitted def _reduce_13(val, _values, result) content = val[1] result = inline "#{content}", content result end def _reduce_14(val, _values, result) content = val[1] result = inline "#{content}", content result end def _reduce_15(val, _values, result) content = val[1] result = inline "+#{content}+", content result end def _reduce_16(val, _values, result) content = val[1] result = inline "#{content}", content result end def _reduce_17(val, _values, result) label = val[1] @block_parser.add_label label.reference result = "#{label}" result end def _reduce_18(val, _values, result) result = "{#{val[1]}}[#{val[2].join}]" result end def _reduce_19(val, _values, result) scheme, inline = val[1] result = "{#{inline}}[#{scheme}#{inline.reference}]" result end def _reduce_20(val, _values, result) result = [nil, inline(val[1])] result end def _reduce_21(val, _values, result) result = [ 'rdoc-label:', inline("#{val[0].reference}/#{val[1].reference}") ] result end def _reduce_22(val, _values, result) result = ['rdoc-label:', val[0].reference] result end def _reduce_23(val, _values, result) result = ['rdoc-label:', "#{val[0].reference}/"] result end def _reduce_24(val, _values, result) result = [nil, inline(val[1])] result end def _reduce_25(val, _values, result) result = [ 'rdoc-label:', inline("#{val[0].reference}/#{val[1].reference}") ] result end def _reduce_26(val, _values, result) result = ['rdoc-label:', val[0]] result end def _reduce_27(val, _values, result) ref = val[0].reference result = ['rdoc-label:', inline(ref, "#{ref}/")] result end # reduce 28 omitted def _reduce_29(val, _values, result) result = val[1] result end def _reduce_30(val, _values, result) result = val[1] result end def _reduce_31(val, _values, result) result = inline val[0] result end def _reduce_32(val, _values, result) result = inline "\"#{val[1]}\"" result end def _reduce_33(val, _values, result) result = inline val[0] result end def _reduce_34(val, _values, result) result = inline "\"#{val[1]}\"" result end # reduce 35 omitted def _reduce_36(val, _values, result) result = val[1] result end def _reduce_37(val, _values, result) result = inline val[1] result end def _reduce_38(val, _values, result) result = val[0].append val[1] result end def _reduce_39(val, _values, result) result = val[0].append val[1] result end def _reduce_40(val, _values, result) result = val[0] result end def _reduce_41(val, _values, result) result = inline val[0] result end # reduce 42 omitted def _reduce_43(val, _values, result) result = val[0].append val[1] result end def _reduce_44(val, _values, result) result = inline val[0] result end def _reduce_45(val, _values, result) result = val[0].append val[1] result end def _reduce_46(val, _values, result) result = val[0] result end # reduce 47 omitted # reduce 48 omitted # reduce 49 omitted # reduce 50 omitted # reduce 51 omitted # reduce 52 omitted # reduce 53 omitted # reduce 54 omitted # reduce 55 omitted # reduce 56 omitted def _reduce_57(val, _values, result) result = val[0] result end def _reduce_58(val, _values, result) result = inline val[0] result end def _reduce_59(val, _values, result) result = inline val[0] result end def _reduce_60(val, _values, result) result << val[1] result end # reduce 61 omitted def _reduce_62(val, _values, result) result << val[1] result end # reduce 63 omitted def _reduce_64(val, _values, result) result << val[1] result end # reduce 65 omitted # reduce 66 omitted # reduce 67 omitted # reduce 68 omitted # reduce 69 omitted # reduce 70 omitted # reduce 71 omitted # reduce 72 omitted # reduce 73 omitted # reduce 74 omitted # reduce 75 omitted # reduce 76 omitted # reduce 77 omitted def _reduce_78(val, _values, result) result << val[1] result end # reduce 79 omitted # reduce 80 omitted # reduce 81 omitted # reduce 82 omitted # reduce 83 omitted # reduce 84 omitted # reduce 85 omitted # reduce 86 omitted # reduce 87 omitted # reduce 88 omitted # reduce 89 omitted # reduce 90 omitted # reduce 91 omitted # reduce 92 omitted # reduce 93 omitted # reduce 94 omitted # reduce 95 omitted # reduce 96 omitted # reduce 97 omitted # reduce 98 omitted # reduce 99 omitted # reduce 100 omitted def _reduce_101(val, _values, result) index = @block_parser.add_footnote val[1].rdoc result = "{*#{index}}[rdoc-label:foottext-#{index}:footmark-#{index}]" result end def _reduce_102(val, _values, result) result = inline "#{val[1]}", val[1] result end # reduce 103 omitted # reduce 104 omitted # reduce 105 omitted # reduce 106 omitted # reduce 107 omitted # reduce 108 omitted def _reduce_109(val, _values, result) result << val[1] result end # reduce 110 omitted def _reduce_111(val, _values, result) result = inline val[0] result end # reduce 112 omitted def _reduce_113(val, _values, result) result = val[1] result end def _reduce_114(val, _values, result) result = val[1] result end def _reduce_115(val, _values, result) result = val[1] result end # reduce 116 omitted # reduce 117 omitted # reduce 118 omitted # reduce 119 omitted # reduce 120 omitted # reduce 121 omitted # reduce 122 omitted # reduce 123 omitted # reduce 124 omitted # reduce 125 omitted # reduce 126 omitted # reduce 127 omitted # reduce 128 omitted # reduce 129 omitted # reduce 130 omitted # reduce 131 omitted # reduce 132 omitted # reduce 133 omitted # reduce 134 omitted # reduce 135 omitted def _reduce_136(val, _values, result) result << val[1] result end # reduce 137 omitted def _reduce_none(val, _values, result) val[0] end end # class InlineParser end PK!|mm2.2.0/rdoc/rd/inline.rbnu[## # Inline keeps track of markup and labels to create proper links. class RDoc::RD::Inline ## # The text of the reference attr_reader :reference ## # The markup of this reference in RDoc format attr_reader :rdoc ## # Creates a new Inline for +rdoc+ and +reference+. # # +rdoc+ may be another Inline or a String. If +reference+ is not given it # will use the text from +rdoc+. def self.new rdoc, reference = rdoc if self === rdoc and reference.equal? rdoc then rdoc else super end end ## # Initializes the Inline with +rdoc+ and +inline+ def initialize rdoc, reference # :not-new: @reference = reference.equal?(rdoc) ? reference.dup : reference # unpack @reference = @reference.reference if self.class === @reference @rdoc = rdoc end def == other # :nodoc: self.class === other and @reference == other.reference and @rdoc == other.rdoc end ## # Appends +more+ to this inline. +more+ may be a String or another Inline. def append more case more when String then @reference << more @rdoc << more when RDoc::RD::Inline then @reference << more.reference @rdoc << more.rdoc else raise "unknown thingy #{more}" end self end def inspect # :nodoc: "(inline: #{self})" end alias to_s rdoc # :nodoc: end PK!kXX2.2.0/rdoc/rd/block_parser.rbnu[# # DO NOT MODIFY!!!! # This file is automatically generated by Racc 1.4.12 # from Racc grammer file "". # require 'racc/parser.rb' class RDoc::RD ## # RD format parser for headings, paragraphs, lists, verbatim sections that # exist as blocks. class BlockParser < Racc::Parser # :stopdoc: TMPFILE = ["rdtmp", $$, 0] MARK_TO_LEVEL = { '=' => 1, '==' => 2, '===' => 3, '====' => 4, '+' => 5, '++' => 6, } # :startdoc: ## # Footnotes for this document attr_reader :footnotes ## # Labels for items in this document attr_reader :labels ## # Path to find included files in attr_accessor :include_path ## # Creates a new RDoc::RD::BlockParser. Use #parse to parse an rd-format # document. def initialize @inline_parser = RDoc::RD::InlineParser.new self @include_path = [] # for testing @footnotes = [] @labels = {} end ## # Parses +src+ and returns an RDoc::Markup::Document. def parse src @src = src @src.push false @footnotes = [] @labels = {} # @i: index(line no.) of src @i = 0 # stack for current indentation @indent_stack = [] # how indented. @current_indent = @indent_stack.join("") # RDoc::RD::BlockParser for tmp src @subparser = nil # which part is in now @in_part = nil @part_content = [] @in_verbatim = false @yydebug = true document = do_parse unless @footnotes.empty? then blankline = document.parts.pop document.parts << RDoc::Markup::Rule.new(1) document.parts.concat @footnotes document.parts.push blankline end document end ## # Returns the next token from the document def next_token # :nodoc: # preprocessing # if it is not in RD part # => method while @in_part != "rd" line = @src[@i] @i += 1 # next line case line # src end when false return [false, false] # RD part begin when /^=begin\s*(?:\bRD\b.*)?\s*$/ if @in_part # if in non-RD part @part_content.push(line) else @in_part = "rd" return [:WHITELINE, "=begin\n"] # <= for textblockand end # non-RD part begin when /^=begin\s+(\w+)/ part = $1 if @in_part # if in non-RD part @part_content.push(line) else @in_part = part if @tree.filter[part] # if filter exists # p "BEGIN_PART: #{@in_part}" # DEBUG end # non-RD part end when /^=end/ if @in_part # if in non-RD part # p "END_PART: #{@in_part}" # DEBUG # make Part-in object part = RDoc::RD::Part.new(@part_content.join(""), @tree, "r") @part_content.clear # call filter, part_out is output(Part object) part_out = @tree.filter[@in_part].call(part) if @tree.filter[@in_part].mode == :rd # if output is RD formatted subtree = parse_subtree(part_out.to_a) else # if output is target formatted basename = TMPFILE.join('.') TMPFILE[-1] += 1 tmpfile = open(@tree.tmp_dir + "/" + basename + ".#{@in_part}", "w") tmpfile.print(part_out) tmpfile.close subtree = parse_subtree(["=begin\n", "<<< #{basename}\n", "=end\n"]) end @in_part = nil return [:SUBTREE, subtree] end else if @in_part # if in non-RD part @part_content.push(line) end end end @current_indent = @indent_stack.join("") line = @src[@i] case line when false if_current_indent_equal("") do [false, false] end when /^=end/ if_current_indent_equal("") do @in_part = nil [:WHITELINE, "=end"] # MUST CHANGE?? end when /^\s*$/ @i += 1 # next line return [:WHITELINE, ':WHITELINE'] when /^\#/ # comment line @i += 1 # next line self.next_token() when /^(={1,4})(?!=)\s*(?=\S)/, /^(\+{1,2})(?!\+)\s*(?=\S)/ rest = $' # ' rest.strip! mark = $1 if_current_indent_equal("") do return [:HEADLINE, [MARK_TO_LEVEL[mark], rest]] end when /^<<<\s*(\S+)/ file = $1 if_current_indent_equal("") do suffix = file[-3 .. -1] if suffix == ".rd" or suffix == ".rb" subtree = parse_subtree(get_included(file)) [:SUBTREE, subtree] else [:INCLUDE, file] end end when /^(\s*)\*(\s*)/ rest = $' # ' newIndent = $2 if_current_indent_equal($1) do if @in_verbatim [:STRINGLINE, line] else @indent_stack.push("\s" << newIndent) [:ITEMLISTLINE, rest] end end when /^(\s*)(\(\d+\))(\s*)/ rest = $' # ' mark = $2 newIndent = $3 if_current_indent_equal($1) do if @in_verbatim [:STRINGLINE, line] else @indent_stack.push("\s" * mark.size << newIndent) [:ENUMLISTLINE, rest] end end when /^(\s*):(\s*)/ rest = $' # ' newIndent = $2 if_current_indent_equal($1) do if @in_verbatim [:STRINGLINE, line] else @indent_stack.push("\s#{$2}") [:DESCLISTLINE, rest] end end when /^(\s*)---(?!-|\s*$)/ indent = $1 rest = $' /\s*/ === rest term = $' new_indent = $& if_current_indent_equal(indent) do if @in_verbatim [:STRINGLINE, line] else @indent_stack.push("\s\s\s" + new_indent) [:METHODLISTLINE, term] end end when /^(\s*)/ if_current_indent_equal($1) do [:STRINGLINE, line] end else raise "[BUG] parsing error may occured." end end ## # Yields to the given block if +indent+ matches the current indent, otherwise # an indentation token is processed. def if_current_indent_equal(indent) indent = indent.sub(/\t/, "\s" * 8) if @current_indent == indent @i += 1 # next line yield elsif indent.index(@current_indent) == 0 @indent_stack.push(indent[@current_indent.size .. -1]) [:INDENT, ":INDENT"] else @indent_stack.pop [:DEDENT, ":DEDENT"] end end private :if_current_indent_equal ## # Cuts off excess whitespace in +src+ def cut_off(src) ret = [] whiteline_buf = [] line = src.shift /^\s*/ =~ line indent = Regexp.quote($&) ret.push($') while line = src.shift if /^(\s*)$/ =~ line whiteline_buf.push(line) elsif /^#{indent}/ =~ line unless whiteline_buf.empty? ret.concat(whiteline_buf) whiteline_buf.clear end ret.push($') else raise "[BUG]: probably Parser Error while cutting off.\n" end end ret end private :cut_off def set_term_to_element(parent, term) # parent.set_term_under_document_struct(term, @tree.document_struct) parent.set_term_without_document_struct(term) end private :set_term_to_element ## # Raises a ParseError when invalid formatting is found def on_error(et, ev, _values) prv, cur, nxt = format_line_num(@i, @i+1, @i+2) raise ParseError, <|#{@src[@i].chomp} #{nxt} |#{@src[@i+1].chomp} Msg end ## # Current line number def line_index @i end ## # Parses subtree +src+ def parse_subtree src @subparser ||= RDoc::RD::BlockParser.new @subparser.parse src end private :parse_subtree ## # Retrieves the content for +file+ from the include_path def get_included(file) included = [] @include_path.each do |dir| file_name = File.join dir, file if File.exist? file_name then included = IO.readlines file_name break end end included end private :get_included ## # Formats line numbers +line_numbers+ prettily def format_line_num(*line_numbers) width = line_numbers.collect{|i| i.to_s.length }.max line_numbers.collect{|i| sprintf("%#{width}d", i) } end private :format_line_num ## # Retrieves the content of +values+ as a single String def content values values.map { |value| value.content }.join end ## # Creates a paragraph for +value+ def paragraph value content = cut_off(value).join(' ').rstrip contents = @inline_parser.parse content RDoc::Markup::Paragraph.new(*contents) end ## # Adds footnote +content+ to the document def add_footnote content index = @footnotes.length / 2 + 1 footmark_link = "{^#{index}}[rdoc-label:footmark-#{index}:foottext-#{index}]" @footnotes << RDoc::Markup::Paragraph.new(footmark_link, ' ', *content) @footnotes << RDoc::Markup::BlankLine.new index end ## # Adds label +label+ to the document def add_label label @labels[label] = true label end # :stopdoc: ##### State transition tables begin ### racc_action_table = [ 34, 35, 30, 33, 14, 73, 38, 33, 76, 15, 88, 34, 35, 30, 33, 40, 34, 35, 30, 33, 40, 65, 34, 35, 30, 33, 14, 73, 77, 14, 54, 15, 34, 35, 30, 33, 14, 9, 10, 11, 12, 15, 34, 35, 30, 33, 14, 73, 81, 54, 38, 15, 34, 35, 30, 33, 14, 73, 40, 67, 83, 15, 34, 35, 30, 33, 14, 73, 54, 30, 35, 15, 34, 35, 30, 33, 34, 47, 36, 14, 59, 15, 34, 35, 30, 33, 14, 73, 38, nil, nil, 15, 34, 35, 30, 33, nil, 47, nil, nil, nil, 15, 34, 35, 30, 33, 14, 73, nil, nil, nil, 15, 34, 35, 30, 33, 14, 73, nil, nil, nil, 15, 34, 35, 30, 33, 14, 9, 10, 11, 12, 15, 34, 35, 30, 33, 14, 73, nil, nil, nil, 15, 34, 35, 30, 33, 14, 73, 61, 63, nil, 15, nil, 62, 60, 61, 63, 61, 63, 14, 62, 87, 62, nil, 79, 34, 35, 30, 33 ] racc_action_check = [ 86, 86, 86, 86, 86, 86, 57, 31, 49, 86, 86, 41, 41, 41, 41, 41, 15, 15, 15, 15, 15, 41, 45, 45, 45, 45, 45, 45, 51, 34, 54, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 85, 85, 85, 85, 56, 33, 58, 85, 79, 79, 79, 79, 79, 79, 62, 44, 66, 79, 78, 78, 78, 78, 78, 78, 30, 28, 25, 78, 24, 24, 24, 24, 22, 24, 1, 35, 36, 24, 75, 75, 75, 75, 75, 75, 13, nil, nil, 75, 27, 27, 27, 27, nil, 27, nil, nil, nil, 27, 74, 74, 74, 74, 74, 74, nil, nil, nil, 74, 68, 68, 68, 68, 68, 68, nil, nil, nil, 68, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 46, 46, 46, 46, 46, 46, nil, nil, nil, 46, 47, 47, 47, 47, 47, 47, 39, 39, nil, 47, nil, 39, 39, 82, 82, 64, 64, 52, 82, 82, 64, nil, 52, 20, 20, 20, 20 ] racc_action_pointer = [ 29, 78, 119, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 81, nil, 13, nil, nil, nil, nil, 162, nil, 73, nil, 69, 66, nil, 89, 64, nil, 60, 1, nil, 41, 22, 72, 80, nil, nil, 141, nil, 8, nil, nil, 46, 19, 129, 139, nil, -5, nil, 15, 152, nil, 22, nil, 35, -1, 43, nil, nil, nil, 51, nil, 150, nil, 47, nil, 109, nil, nil, nil, nil, nil, 99, 79, nil, nil, 59, 49, nil, nil, 148, nil, nil, 39, -3, nil, nil ] racc_action_default = [ -2, -73, -1, -4, -5, -6, -7, -8, -9, -10, -11, -12, -13, -14, -16, -73, -23, -24, -25, -26, -27, -31, -32, -34, -72, -36, -38, -72, -40, -42, -59, -44, -46, -59, -63, -65, -73, -3, -15, -73, -22, -73, -30, -33, -73, -69, -70, -71, -37, -73, -41, -73, -51, -58, -61, -45, -73, -62, -64, 89, -17, -19, -73, -21, -18, -28, -73, -35, -66, -53, -54, -55, -56, -57, -67, -68, -39, -43, -49, -73, -60, -47, -73, -29, -52, -48, -73, -20, -50 ] racc_goto_table = [ 4, 39, 4, 68, 74, 75, 5, 6, 5, 6, 51, 42, 44, 56, 3, 49, 37, 57, 58, 41, 43, 48, 84, 50, 66, 55, 1, 64, 84, 84, 45, 46, 42, 45, 46, 2, 85, 86, 80, 84, 84, nil, nil, nil, nil, nil, nil, nil, 82, nil, nil, nil, 78 ] racc_goto_check = [ 4, 10, 4, 31, 31, 31, 5, 6, 5, 6, 27, 12, 21, 27, 3, 21, 3, 9, 9, 17, 19, 23, 32, 26, 11, 29, 1, 10, 32, 32, 5, 6, 12, 5, 6, 2, 31, 31, 33, 32, 32, nil, nil, nil, nil, nil, nil, nil, 10, nil, nil, nil, 4 ] racc_goto_pointer = [ nil, 26, 35, 14, 0, 6, 7, nil, nil, -17, -14, -17, -9, nil, nil, nil, nil, 4, nil, -2, nil, -12, nil, -4, nil, nil, -5, -20, nil, -6, nil, -42, -46, -16 ] racc_goto_default = [ nil, nil, nil, nil, 70, 71, 72, 7, 8, 13, nil, nil, 21, 16, 17, 18, 19, 20, 22, 23, 24, nil, 25, 26, 27, 28, 29, nil, 31, 32, 52, nil, 69, 53 ] racc_reduce_table = [ 0, 0, :racc_error, 1, 15, :_reduce_1, 0, 15, :_reduce_2, 2, 16, :_reduce_3, 1, 16, :_reduce_4, 1, 17, :_reduce_5, 1, 17, :_reduce_6, 1, 17, :_reduce_none, 1, 17, :_reduce_8, 1, 17, :_reduce_9, 1, 17, :_reduce_10, 1, 17, :_reduce_11, 1, 21, :_reduce_12, 1, 22, :_reduce_13, 1, 18, :_reduce_14, 2, 23, :_reduce_15, 1, 23, :_reduce_16, 3, 19, :_reduce_17, 1, 25, :_reduce_18, 2, 24, :_reduce_19, 4, 24, :_reduce_20, 2, 24, :_reduce_21, 1, 24, :_reduce_22, 1, 26, :_reduce_none, 1, 26, :_reduce_none, 1, 26, :_reduce_none, 1, 26, :_reduce_none, 1, 20, :_reduce_27, 3, 20, :_reduce_28, 4, 20, :_reduce_29, 2, 31, :_reduce_30, 1, 31, :_reduce_31, 1, 27, :_reduce_32, 2, 32, :_reduce_33, 1, 32, :_reduce_34, 3, 33, :_reduce_35, 1, 28, :_reduce_36, 2, 36, :_reduce_37, 1, 36, :_reduce_38, 3, 37, :_reduce_39, 1, 29, :_reduce_40, 2, 39, :_reduce_41, 1, 39, :_reduce_42, 3, 40, :_reduce_43, 1, 30, :_reduce_44, 2, 42, :_reduce_45, 1, 42, :_reduce_46, 3, 43, :_reduce_47, 3, 41, :_reduce_48, 2, 41, :_reduce_49, 4, 41, :_reduce_50, 1, 41, :_reduce_51, 2, 45, :_reduce_52, 1, 45, :_reduce_none, 1, 46, :_reduce_54, 1, 46, :_reduce_55, 1, 46, :_reduce_none, 1, 46, :_reduce_57, 1, 44, :_reduce_none, 0, 44, :_reduce_none, 2, 47, :_reduce_none, 1, 47, :_reduce_none, 2, 34, :_reduce_62, 1, 34, :_reduce_63, 2, 38, :_reduce_64, 1, 38, :_reduce_65, 2, 35, :_reduce_66, 2, 35, :_reduce_67, 2, 35, :_reduce_68, 1, 35, :_reduce_69, 1, 35, :_reduce_none, 1, 35, :_reduce_71, 0, 35, :_reduce_72 ] racc_reduce_n = 73 racc_shift_n = 89 racc_token_table = { false => 0, :error => 1, :DUMMY => 2, :ITEMLISTLINE => 3, :ENUMLISTLINE => 4, :DESCLISTLINE => 5, :METHODLISTLINE => 6, :STRINGLINE => 7, :WHITELINE => 8, :SUBTREE => 9, :HEADLINE => 10, :INCLUDE => 11, :INDENT => 12, :DEDENT => 13 } racc_nt_base = 14 racc_use_result_var = true Racc_arg = [ racc_action_table, racc_action_check, racc_action_default, racc_action_pointer, racc_goto_table, racc_goto_check, racc_goto_default, racc_goto_pointer, racc_nt_base, racc_reduce_table, racc_token_table, racc_shift_n, racc_reduce_n, racc_use_result_var ] Racc_token_to_s_table = [ "$end", "error", "DUMMY", "ITEMLISTLINE", "ENUMLISTLINE", "DESCLISTLINE", "METHODLISTLINE", "STRINGLINE", "WHITELINE", "SUBTREE", "HEADLINE", "INCLUDE", "INDENT", "DEDENT", "$start", "document", "blocks", "block", "textblock", "verbatim", "lists", "headline", "include", "textblockcontent", "verbatimcontent", "verbatim_after_lists", "list", "itemlist", "enumlist", "desclist", "methodlist", "lists2", "itemlistitems", "itemlistitem", "first_textblock_in_itemlist", "other_blocks_in_list", "enumlistitems", "enumlistitem", "first_textblock_in_enumlist", "desclistitems", "desclistitem", "description_part", "methodlistitems", "methodlistitem", "whitelines", "blocks_in_list", "block_in_list", "whitelines2" ] Racc_debug_parser = false ##### State transition tables end ##### # reduce 0 omitted def _reduce_1(val, _values, result) result = RDoc::Markup::Document.new(*val[0]) result end def _reduce_2(val, _values, result) raise ParseError, "file empty" result end def _reduce_3(val, _values, result) result = val[0].concat val[1] result end def _reduce_4(val, _values, result) result = val[0] result end def _reduce_5(val, _values, result) result = val result end def _reduce_6(val, _values, result) result = val result end # reduce 7 omitted def _reduce_8(val, _values, result) result = val result end def _reduce_9(val, _values, result) result = val result end def _reduce_10(val, _values, result) result = [RDoc::Markup::BlankLine.new] result end def _reduce_11(val, _values, result) result = val[0].parts result end def _reduce_12(val, _values, result) # val[0] is like [level, title] title = @inline_parser.parse(val[0][1]) result = RDoc::Markup::Heading.new(val[0][0], title) result end def _reduce_13(val, _values, result) result = RDoc::Markup::Include.new val[0], @include_path result end def _reduce_14(val, _values, result) # val[0] is Array of String result = paragraph val[0] result end def _reduce_15(val, _values, result) result << val[1].rstrip result end def _reduce_16(val, _values, result) result = [val[0].rstrip] result end def _reduce_17(val, _values, result) # val[1] is Array of String content = cut_off val[1] result = RDoc::Markup::Verbatim.new(*content) # imform to lexer. @in_verbatim = false result end def _reduce_18(val, _values, result) # val[0] is Array of String content = cut_off val[0] result = RDoc::Markup::Verbatim.new(*content) # imform to lexer. @in_verbatim = false result end def _reduce_19(val, _values, result) result << val[1] result end def _reduce_20(val, _values, result) result.concat val[2] result end def _reduce_21(val, _values, result) result << "\n" result end def _reduce_22(val, _values, result) result = val # inform to lexer. @in_verbatim = true result end # reduce 23 omitted # reduce 24 omitted # reduce 25 omitted # reduce 26 omitted def _reduce_27(val, _values, result) result = val[0] result end def _reduce_28(val, _values, result) result = val[1] result end def _reduce_29(val, _values, result) result = val[1].push(val[2]) result end def _reduce_30(val, _values, result) result = val[0] << val[1] result end def _reduce_31(val, _values, result) result = [val[0]] result end def _reduce_32(val, _values, result) result = RDoc::Markup::List.new :BULLET, *val[0] result end def _reduce_33(val, _values, result) result.push(val[1]) result end def _reduce_34(val, _values, result) result = val result end def _reduce_35(val, _values, result) result = RDoc::Markup::ListItem.new nil, val[0], *val[1] result end def _reduce_36(val, _values, result) result = RDoc::Markup::List.new :NUMBER, *val[0] result end def _reduce_37(val, _values, result) result.push(val[1]) result end def _reduce_38(val, _values, result) result = val result end def _reduce_39(val, _values, result) result = RDoc::Markup::ListItem.new nil, val[0], *val[1] result end def _reduce_40(val, _values, result) result = RDoc::Markup::List.new :NOTE, *val[0] result end def _reduce_41(val, _values, result) result.push(val[1]) result end def _reduce_42(val, _values, result) result = val result end def _reduce_43(val, _values, result) term = @inline_parser.parse val[0].strip result = RDoc::Markup::ListItem.new term, *val[1] result end def _reduce_44(val, _values, result) result = RDoc::Markup::List.new :LABEL, *val[0] result end def _reduce_45(val, _values, result) result.push(val[1]) result end def _reduce_46(val, _values, result) result = val result end def _reduce_47(val, _values, result) result = RDoc::Markup::ListItem.new "#{val[0].strip}", *val[1] result end def _reduce_48(val, _values, result) result = [val[1]].concat(val[2]) result end def _reduce_49(val, _values, result) result = [val[1]] result end def _reduce_50(val, _values, result) result = val[2] result end def _reduce_51(val, _values, result) result = [] result end def _reduce_52(val, _values, result) result.concat val[1] result end # reduce 53 omitted def _reduce_54(val, _values, result) result = val result end def _reduce_55(val, _values, result) result = val result end # reduce 56 omitted def _reduce_57(val, _values, result) result = [] result end # reduce 58 omitted # reduce 59 omitted # reduce 60 omitted # reduce 61 omitted def _reduce_62(val, _values, result) result = paragraph [val[0]].concat(val[1]) result end def _reduce_63(val, _values, result) result = paragraph [val[0]] result end def _reduce_64(val, _values, result) result = paragraph [val[0]].concat(val[1]) result end def _reduce_65(val, _values, result) result = paragraph [val[0]] result end def _reduce_66(val, _values, result) result = [val[0]].concat(val[1]) result end def _reduce_67(val, _values, result) result.concat val[1] result end def _reduce_68(val, _values, result) result = val[1] result end def _reduce_69(val, _values, result) result = val result end # reduce 70 omitted def _reduce_71(val, _values, result) result = [] result end def _reduce_72(val, _values, result) result = [] result end def _reduce_none(val, _values, result) val[0] end end # class BlockParser end PK!Z_ _ 2.2.0/rdoc/known_classes.rbnu[module RDoc ## # Ruby's built-in classes, modules and exceptions KNOWN_CLASSES = { "rb_cArray" => "Array", "rb_cBasicObject" => "BasicObject", "rb_cBignum" => "Bignum", "rb_cClass" => "Class", "rb_cData" => "Data", "rb_cDir" => "Dir", "rb_cEncoding" => "Encoding", "rb_cFalseClass" => "FalseClass", "rb_cFile" => "File", "rb_cFixnum" => "Fixnum", "rb_cFloat" => "Float", "rb_cHash" => "Hash", "rb_cIO" => "IO", "rb_cInteger" => "Integer", "rb_cModule" => "Module", "rb_cNilClass" => "NilClass", "rb_cNumeric" => "Numeric", "rb_cObject" => "Object", "rb_cProc" => "Proc", "rb_cRange" => "Range", "rb_cRegexp" => "Regexp", "rb_cRubyVM" => "RubyVM", "rb_cSocket" => "Socket", "rb_cString" => "String", "rb_cStruct" => "Struct", "rb_cSymbol" => "Symbol", "rb_cThread" => "Thread", "rb_cTime" => "Time", "rb_cTrueClass" => "TrueClass", "rb_eArgError" => "ArgError", "rb_eEOFError" => "EOFError", "rb_eException" => "Exception", "rb_eFatal" => "fatal", "rb_eFloatDomainError" => "FloatDomainError", "rb_eIOError" => "IOError", "rb_eIndexError" => "IndexError", "rb_eInterrupt" => "Interrupt", "rb_eLoadError" => "LoadError", "rb_eNameError" => "NameError", "rb_eNoMemError" => "NoMemError", "rb_eNotImpError" => "NotImpError", "rb_eRangeError" => "RangeError", "rb_eRuntimeError" => "RuntimeError", "rb_eScriptError" => "ScriptError", "rb_eSecurityError" => "SecurityError", "rb_eSignal" => "SignalException", "rb_eStandardError" => "StandardError", "rb_eSyntaxError" => "SyntaxError", "rb_eSystemCallError" => "SystemCallError", "rb_eSystemExit" => "SystemExit", "rb_eTypeError" => "TypeError", "rb_eZeroDivError" => "ZeroDivError", "rb_mComparable" => "Comparable", "rb_mEnumerable" => "Enumerable", "rb_mErrno" => "Errno", "rb_mFConst" => "File::Constants", "rb_mFileTest" => "FileTest", "rb_mGC" => "GC", "rb_mKernel" => "Kernel", "rb_mMath" => "Math", "rb_mProcess" => "Process" } end PK!p++2.2.0/rdoc/ri/task.rbnu[require 'rubygems' begin gem 'rdoc' rescue Gem::LoadError end unless defined?(RDoc) require 'rdoc/task' ## # RDoc::RI::Task creates ri data in ./.rdoc for your project. # # It contains the following tasks: # # [ri] # Build ri data # # [clobber_ri] # Delete ri data files. This target is automatically added to the main # clobber target. # # [reri] # Rebuild the ri data from scratch even if they are not out of date. # # Simple example: # # require 'rdoc/ri/task' # # RDoc::RI::Task.new do |ri| # ri.main = 'README.rdoc' # ri.rdoc_files.include 'README.rdoc', 'lib/**/*.rb' # end # # For further configuration details see RDoc::Task. class RDoc::RI::Task < RDoc::Task DEFAULT_NAMES = { # :nodoc: :clobber_rdoc => :clobber_ri, :rdoc => :ri, :rerdoc => :reri, } ## # Create an ri task with the given name. See RDoc::Task for documentation on # setting names. def initialize name = DEFAULT_NAMES # :yield: self super end def clobber_task_description # :nodoc: "Remove RI data files" end ## # Sets default task values def defaults super @rdoc_dir = '.rdoc' end def rdoc_task_description # :nodoc: 'Build RI data files' end def rerdoc_task_description # :nodoc: 'Rebuild RI data files' end end PK!?g772.2.0/rdoc/ri/store.rbnu[module RDoc::RI Store = RDoc::Store # :nodoc: end PK!('TT2.2.0/rdoc/ri/formatter.rbnu[## # For RubyGems backwards compatibility module RDoc::RI::Formatter # :nodoc: end PK!w"2.2.0/rdoc/ri/paths.rbnu[require 'rdoc/ri' ## # The directories where ri data lives. Paths can be enumerated via ::each, or # queried individually via ::system_dir, ::site_dir, ::home_dir and ::gem_dir. module RDoc::RI::Paths #:stopdoc: require 'rbconfig' version = RbConfig::CONFIG['ruby_version'] BASE = if RbConfig::CONFIG.key? 'ridir' then File.join RbConfig::CONFIG['ridir'], version else File.join RbConfig::CONFIG['datadir'], 'ri', version end homedir = begin File.expand_path('~') rescue ArgumentError end homedir ||= ENV['HOME'] || ENV['USERPROFILE'] || ENV['HOMEPATH'] # for 1.8 compatibility HOMEDIR = if homedir then File.join homedir, ".rdoc" end #:startdoc: ## # Iterates over each selected path yielding the directory and type. # # Yielded types: # :system:: Where Ruby's ri data is stored. Yielded when +system+ is # true # :site:: Where ri for installed libraries are stored. Yielded when # +site+ is true. Normally no ri data is stored here. # :home:: ~/.rdoc. Yielded when +home+ is true. # :gem:: ri data for an installed gem. Yielded when +gems+ is true. # :extra:: ri data directory from the command line. Yielded for each # entry in +extra_dirs+ def self.each system = true, site = true, home = true, gems = :latest, *extra_dirs # :yields: directory, type return enum_for __method__, system, site, home, gems, *extra_dirs unless block_given? extra_dirs.each do |dir| yield dir, :extra end yield system_dir, :system if system yield site_dir, :site if site yield home_dir, :home if home and HOMEDIR gemdirs(gems).each do |dir| yield dir, :gem end if gems nil end ## # The ri directory for the gem with +gem_name+. def self.gem_dir name, version req = Gem::Requirement.new "= #{version}" spec = Gem::Specification.find_by_name name, req File.join spec.doc_dir, 'ri' end ## # The latest installed gems' ri directories. +filter+ can be :all or # :latest. # # A +filter+ :all includes all versions of gems and includes gems without # ri documentation. def self.gemdirs filter = :latest require 'rubygems' unless defined?(Gem) ri_paths = {} all = Gem::Specification.map do |spec| [File.join(spec.doc_dir, 'ri'), spec.name, spec.version] end if filter == :all then gemdirs = [] all.group_by do |_, name, _| name end.sort_by do |group, _| group end.map do |group, items| items.sort_by do |_, _, version| version end.reverse_each do |dir,| gemdirs << dir end end return gemdirs end all.each do |dir, name, ver| next unless File.exist? dir if ri_paths[name].nil? or ver > ri_paths[name].first then ri_paths[name] = [ver, name, dir] end end ri_paths.sort_by { |_, (_, name, _)| name }.map { |k, v| v.last } rescue LoadError [] end ## # The location of the rdoc data in the user's home directory. # # Like ::system, ri data in the user's home directory is rare and predates # libraries distributed via RubyGems. ri data is rarely generated into this # directory. def self.home_dir HOMEDIR end ## # Returns existing directories from the selected documentation directories # as an Array. # # See also ::each def self.path(system = true, site = true, home = true, gems = :latest, *extra_dirs) path = raw_path system, site, home, gems, *extra_dirs path.select { |directory| File.directory? directory } end ## # Returns selected documentation directories including nonexistent # directories. # # See also ::each def self.raw_path(system, site, home, gems, *extra_dirs) path = [] each(system, site, home, gems, *extra_dirs) do |dir, type| path << dir end path.compact end ## # The location of ri data installed into the site dir. # # Historically this was available for documentation installed by Ruby # libraries predating RubyGems. It is unlikely to contain any content for # modern Ruby installations. def self.site_dir File.join BASE, 'site' end ## # The location of the built-in ri data. # # This data is built automatically when `make` is run when Ruby is # installed. If you did not install Ruby by hand you may need to install # the documentation yourself. Please consult the documentation for your # package manager or Ruby installer for details. You can also use the # rdoc-data gem to install system ri data for common versions of Ruby. def self.system_dir File.join BASE, 'system' end end PK!c҉҉2.2.0/rdoc/ri/driver.rbnu[require 'abbrev' require 'optparse' begin require 'readline' rescue LoadError end begin require 'win32console' rescue LoadError end require 'rdoc' ## # For RubyGems backwards compatibility require 'rdoc/ri/formatter' ## # The RI driver implements the command-line ri tool. # # The driver supports: # * loading RI data from: # * Ruby's standard library # * RubyGems # * ~/.rdoc # * A user-supplied directory # * Paging output (uses RI_PAGER environment variable, PAGER environment # variable or the less, more and pager programs) # * Interactive mode with tab-completion # * Abbreviated names (ri Zl shows Zlib documentation) # * Colorized output # * Merging output from multiple RI data sources class RDoc::RI::Driver ## # Base Driver error class class Error < RDoc::RI::Error; end ## # Raised when a name isn't found in the ri data stores class NotFoundError < Error ## # Name that wasn't found alias name message def message # :nodoc: "Nothing known about #{super}" end end ## # Show all method documentation following a class or module attr_accessor :show_all ## # An RDoc::RI::Store for each entry in the RI path attr_accessor :stores ## # Controls the user of the pager vs $stdout attr_accessor :use_stdout ## # Default options for ri def self.default_options options = {} options[:interactive] = false options[:profile] = false options[:show_all] = false options[:use_cache] = true options[:use_stdout] = !$stdout.tty? options[:width] = 72 # By default all standard paths are used. options[:use_system] = true options[:use_site] = true options[:use_home] = true options[:use_gems] = true options[:extra_doc_dirs] = [] return options end ## # Dump +data_path+ using pp def self.dump data_path require 'pp' open data_path, 'rb' do |io| pp Marshal.load(io.read) end end ## # Parses +argv+ and returns a Hash of options def self.process_args argv options = default_options opts = OptionParser.new do |opt| opt.accept File do |file,| File.readable?(file) and not File.directory?(file) and file end opt.program_name = File.basename $0 opt.version = RDoc::VERSION opt.release = nil opt.summary_indent = ' ' * 4 opt.banner = <<-EOT Usage: #{opt.program_name} [options] [names...] Where name can be: Class | Module | Module::Class Class::method | Class#method | Class.method | method gem_name: | gem_name:README | gem_name:History All class names may be abbreviated to their minimum unambiguous form. If a name is ambiguous, all valid options will be listed. A '.' matches either class or instance methods, while #method matches only instance and ::method matches only class methods. README and other files may be displayed by prefixing them with the gem name they're contained in. If the gem name is followed by a ':' all files in the gem will be shown. The file name extension may be omitted where it is unambiguous. For example: #{opt.program_name} Fil #{opt.program_name} File #{opt.program_name} File.new #{opt.program_name} zip #{opt.program_name} rdoc:README Note that shell quoting or escaping may be required for method names containing punctuation: #{opt.program_name} 'Array.[]' #{opt.program_name} compact\\! To see the default directories ri will search, run: #{opt.program_name} --list-doc-dirs Specifying the --system, --site, --home, --gems or --doc-dir options will limit ri to searching only the specified directories. ri options may be set in the 'RI' environment variable. The ri pager can be set with the 'RI_PAGER' environment variable or the 'PAGER' environment variable. EOT opt.separator nil opt.separator "Options:" opt.separator nil opt.on("--[no-]interactive", "-i", "In interactive mode you can repeatedly", "look up methods with autocomplete.") do |interactive| options[:interactive] = interactive end opt.separator nil opt.on("--[no-]all", "-a", "Show all documentation for a class or", "module.") do |show_all| options[:show_all] = show_all end opt.separator nil opt.on("--[no-]list", "-l", "List classes ri knows about.") do |list| options[:list] = list end opt.separator nil opt.on("--[no-]pager", "Send output directly to stdout,", "rather than to a pager.") do |use_pager| options[:use_stdout] = !use_pager end opt.separator nil opt.on("-T", "Synonym for --no-pager") do options[:use_stdout] = true end opt.separator nil opt.on("--width=WIDTH", "-w", OptionParser::DecimalInteger, "Set the width of the output.") do |width| options[:width] = width end opt.separator nil opt.on("--server [PORT]", Integer, "Run RDoc server on the given port.", "The default port is 8214.") do |port| options[:server] = port || 8214 end opt.separator nil formatters = RDoc::Markup.constants.grep(/^To[A-Z][a-z]+$/).sort formatters = formatters.sort.map do |formatter| formatter.to_s.sub('To', '').downcase end formatters -= %w[html label test] # remove useless output formats opt.on("--format=NAME", "-f", "Uses the selected formatter. The default", "formatter is bs for paged output and ansi", "otherwise. Valid formatters are:", formatters.join(' '), formatters) do |value| options[:formatter] = RDoc::Markup.const_get "To#{value.capitalize}" end opt.separator nil opt.separator "Data source options:" opt.separator nil opt.on("--[no-]list-doc-dirs", "List the directories from which ri will", "source documentation on stdout and exit.") do |list_doc_dirs| options[:list_doc_dirs] = list_doc_dirs end opt.separator nil opt.on("--doc-dir=DIRNAME", "-d", Array, "List of directories from which to source", "documentation in addition to the standard", "directories. May be repeated.") do |value| value.each do |dir| unless File.directory? dir then raise OptionParser::InvalidArgument, "#{dir} is not a directory" end options[:extra_doc_dirs] << File.expand_path(dir) end end opt.separator nil opt.on("--no-standard-docs", "Do not include documentation from", "the Ruby standard library, site_lib,", "installed gems, or ~/.rdoc.", "Use with --doc-dir") do options[:use_system] = false options[:use_site] = false options[:use_gems] = false options[:use_home] = false end opt.separator nil opt.on("--[no-]system", "Include documentation from Ruby's standard", "library. Defaults to true.") do |value| options[:use_system] = value end opt.separator nil opt.on("--[no-]site", "Include documentation from libraries", "installed in site_lib.", "Defaults to true.") do |value| options[:use_site] = value end opt.separator nil opt.on("--[no-]gems", "Include documentation from RubyGems.", "Defaults to true.") do |value| options[:use_gems] = value end opt.separator nil opt.on("--[no-]home", "Include documentation stored in ~/.rdoc.", "Defaults to true.") do |value| options[:use_home] = value end opt.separator nil opt.separator "Debug options:" opt.separator nil opt.on("--[no-]profile", "Run with the ruby profiler") do |value| options[:profile] = value end opt.separator nil opt.on("--dump=CACHE", File, "Dumps data from an ri cache or data file") do |value| options[:dump_path] = value end end argv = ENV['RI'].to_s.split.concat argv opts.parse! argv options[:names] = argv options[:use_stdout] ||= !$stdout.tty? options[:use_stdout] ||= options[:interactive] options[:width] ||= 72 options rescue OptionParser::InvalidArgument, OptionParser::InvalidOption => e puts opts puts puts e exit 1 end ## # Runs the ri command line executable using +argv+ def self.run argv = ARGV options = process_args argv if options[:dump_path] then dump options[:dump_path] return end ri = new options ri.run end ## # Creates a new driver using +initial_options+ from ::process_args def initialize initial_options = {} @paging = false @classes = nil options = self.class.default_options.update(initial_options) @formatter_klass = options[:formatter] require 'profile' if options[:profile] @names = options[:names] @list = options[:list] @doc_dirs = [] @stores = [] RDoc::RI::Paths.each(options[:use_system], options[:use_site], options[:use_home], options[:use_gems], *options[:extra_doc_dirs]) do |path, type| @doc_dirs << path store = RDoc::RI::Store.new path, type store.load_cache @stores << store end @list_doc_dirs = options[:list_doc_dirs] @interactive = options[:interactive] @server = options[:server] @use_stdout = options[:use_stdout] @show_all = options[:show_all] # pager process for jruby @jruby_pager_process = nil end ## # Adds paths for undocumented classes +also_in+ to +out+ def add_also_in out, also_in return if also_in.empty? out << RDoc::Markup::Rule.new(1) out << RDoc::Markup::Paragraph.new("Also found in:") paths = RDoc::Markup::Verbatim.new also_in.each do |store| paths.parts.push store.friendly_path, "\n" end out << paths end ## # Adds a class header to +out+ for class +name+ which is described in # +classes+. def add_class out, name, classes heading = if classes.all? { |klass| klass.module? } then name else superclass = classes.map do |klass| klass.superclass unless klass.module? end.compact.shift || 'Object' superclass = superclass.full_name unless String === superclass "#{name} < #{superclass}" end out << RDoc::Markup::Heading.new(1, heading) out << RDoc::Markup::BlankLine.new end ## # Adds "(from ...)" to +out+ for +store+ def add_from out, store out << RDoc::Markup::Paragraph.new("(from #{store.friendly_path})") end ## # Adds +extends+ to +out+ def add_extends out, extends add_extension_modules out, 'Extended by', extends end ## # Adds a list of +extensions+ to this module of the given +type+ to +out+. # add_includes and add_extends call this, so you should use those directly. def add_extension_modules out, type, extensions return if extensions.empty? out << RDoc::Markup::Rule.new(1) out << RDoc::Markup::Heading.new(1, "#{type}:") extensions.each do |modules, store| if modules.length == 1 then add_extension_modules_single out, store, modules.first else add_extension_modules_multiple out, store, modules end end end ## # Renders multiple included +modules+ from +store+ to +out+. def add_extension_modules_multiple out, store, modules # :nodoc: out << RDoc::Markup::Paragraph.new("(from #{store.friendly_path})") wout, with = modules.partition { |incl| incl.comment.empty? } out << RDoc::Markup::BlankLine.new unless with.empty? with.each do |incl| out << RDoc::Markup::Paragraph.new(incl.name) out << RDoc::Markup::BlankLine.new out << incl.comment end unless wout.empty? then verb = RDoc::Markup::Verbatim.new wout.each do |incl| verb.push incl.name, "\n" end out << verb end end ## # Adds a single extension module +include+ from +store+ to +out+ def add_extension_modules_single out, store, include # :nodoc: name = include.name path = store.friendly_path out << RDoc::Markup::Paragraph.new("#{name} (from #{path})") if include.comment then out << RDoc::Markup::BlankLine.new out << include.comment end end ## # Adds +includes+ to +out+ def add_includes out, includes add_extension_modules out, 'Includes', includes end ## # Looks up the method +name+ and adds it to +out+ def add_method out, name filtered = lookup_method name method_out = method_document name, filtered out.concat method_out.parts end ## # Adds documentation for all methods in +klass+ to +out+ def add_method_documentation out, klass klass.method_list.each do |method| begin add_method out, method.full_name rescue NotFoundError next end end end ## # Adds a list of +methods+ to +out+ with a heading of +name+ def add_method_list out, methods, name return if methods.empty? out << RDoc::Markup::Heading.new(1, "#{name}:") out << RDoc::Markup::BlankLine.new if @use_stdout and !@interactive then out.concat methods.map { |method| RDoc::Markup::Verbatim.new method } else out << RDoc::Markup::IndentedParagraph.new(2, methods.join(', ')) end out << RDoc::Markup::BlankLine.new end ## # Returns ancestor classes of +klass+ def ancestors_of klass ancestors = [] unexamined = [klass] seen = [] loop do break if unexamined.empty? current = unexamined.shift seen << current stores = classes[current] break unless stores and not stores.empty? klasses = stores.map do |store| store.ancestors[current] end.flatten.uniq klasses = klasses - seen ancestors.concat klasses unexamined.concat klasses end ancestors.reverse end ## # For RubyGems backwards compatibility def class_cache # :nodoc: end ## # Builds a RDoc::Markup::Document from +found+, +klasess+ and +includes+ def class_document name, found, klasses, includes, extends also_in = [] out = RDoc::Markup::Document.new add_class out, name, klasses add_includes out, includes add_extends out, extends found.each do |store, klass| render_class out, store, klass, also_in end add_also_in out, also_in out end ## # Adds the class +comment+ to +out+. def class_document_comment out, comment # :nodoc: unless comment.empty? then out << RDoc::Markup::Rule.new(1) if comment.merged? then parts = comment.parts parts = parts.zip [RDoc::Markup::BlankLine.new] * parts.length parts.flatten! parts.pop out.concat parts else out << comment end end end ## # Adds the constants from +klass+ to the Document +out+. def class_document_constants out, klass # :nodoc: return if klass.constants.empty? out << RDoc::Markup::Heading.new(1, "Constants:") out << RDoc::Markup::BlankLine.new list = RDoc::Markup::List.new :NOTE constants = klass.constants.sort_by { |constant| constant.name } list.items.concat constants.map { |constant| parts = constant.comment.parts if constant.comment parts << RDoc::Markup::Paragraph.new('[not documented]') if parts.empty? RDoc::Markup::ListItem.new(constant.name, *parts) } out << list out << RDoc::Markup::BlankLine.new end ## # Hash mapping a known class or module to the stores it can be loaded from def classes return @classes if @classes @classes = {} @stores.each do |store| store.cache[:modules].each do |mod| # using default block causes searched-for modules to be added @classes[mod] ||= [] @classes[mod] << store end end @classes end ## # Returns the stores wherein +name+ is found along with the classes, # extends and includes that match it def classes_and_includes_and_extends_for name klasses = [] extends = [] includes = [] found = @stores.map do |store| begin klass = store.load_class name klasses << klass extends << [klass.extends, store] if klass.extends includes << [klass.includes, store] if klass.includes [store, klass] rescue RDoc::Store::MissingFileError end end.compact extends.reject! do |modules,| modules.empty? end includes.reject! do |modules,| modules.empty? end [found, klasses, includes, extends] end ## # Completes +name+ based on the caches. For Readline def complete name completions = [] klass, selector, method = parse_name name complete_klass name, klass, selector, method, completions complete_method name, klass, selector, completions completions.sort.uniq end def complete_klass name, klass, selector, method, completions # :nodoc: klasses = classes.keys # may need to include Foo when given Foo:: klass_name = method ? name : klass if name !~ /#|\./ then completions.replace klasses.grep(/^#{Regexp.escape klass_name}[^:]*$/) completions.concat klasses.grep(/^#{Regexp.escape name}[^:]*$/) if name =~ /::$/ completions << klass if classes.key? klass # to complete a method name elsif selector then completions << klass if classes.key? klass elsif classes.key? klass_name then completions << klass_name end end def complete_method name, klass, selector, completions # :nodoc: if completions.include? klass and name =~ /#|\.|::/ then methods = list_methods_matching name if not methods.empty? then # remove Foo if given Foo:: and a method was found completions.delete klass elsif selector then # replace Foo with Foo:: as given completions.delete klass completions << "#{klass}#{selector}" end completions.concat methods end end ## # Converts +document+ to text and writes it to the pager def display document page do |io| text = document.accept formatter(io) io.write text end end ## # Outputs formatted RI data for class +name+. Groups undocumented classes def display_class name return if name =~ /#|\./ found, klasses, includes, extends = classes_and_includes_and_extends_for name return if found.empty? out = class_document name, found, klasses, includes, extends display out end ## # Outputs formatted RI data for method +name+ def display_method name out = RDoc::Markup::Document.new add_method out, name display out end ## # Outputs formatted RI data for the class or method +name+. # # Returns true if +name+ was found, false if it was not an alternative could # be guessed, raises an error if +name+ couldn't be guessed. def display_name name if name =~ /\w:(\w|$)/ then display_page name return true end return true if display_class name display_method name if name =~ /::|#|\./ true rescue NotFoundError matches = list_methods_matching name if name =~ /::|#|\./ matches = classes.keys.grep(/^#{Regexp.escape name}/) if matches.empty? raise if matches.empty? page do |io| io.puts "#{name} not found, maybe you meant:" io.puts io.puts matches.sort.join("\n") end false end ## # Displays each name in +name+ def display_names names names.each do |name| name = expand_name name display_name name end end ## # Outputs formatted RI data for page +name+. def display_page name store_name, page_name = name.split ':', 2 store = @stores.find { |s| s.source == store_name } return display_page_list store if page_name.empty? pages = store.cache[:pages] unless pages.include? page_name then found_names = pages.select do |n| n =~ /#{Regexp.escape page_name}\.[^.]+$/ end if found_names.length.zero? then return display_page_list store, pages elsif found_names.length > 1 then return display_page_list store, found_names, page_name end page_name = found_names.first end page = store.load_page page_name display page.comment end ## # Outputs a formatted RI page list for the pages in +store+. def display_page_list store, pages = store.cache[:pages], search = nil out = RDoc::Markup::Document.new title = if search then "#{search} pages" else 'Pages' end out << RDoc::Markup::Heading.new(1, "#{title} in #{store.friendly_path}") out << RDoc::Markup::BlankLine.new list = RDoc::Markup::List.new(:BULLET) pages.each do |page| list << RDoc::Markup::Paragraph.new(page) end out << list display out end ## # Expands abbreviated klass +klass+ into a fully-qualified class. "Zl::Da" # will be expanded to Zlib::DataError. def expand_class klass klass.split('::').inject '' do |expanded, klass_part| expanded << '::' unless expanded.empty? short = expanded << klass_part subset = classes.keys.select do |klass_name| klass_name =~ /^#{expanded}[^:]*$/ end abbrevs = Abbrev.abbrev subset expanded = abbrevs[short] raise NotFoundError, short unless expanded expanded.dup end end ## # Expands the class portion of +name+ into a fully-qualified class. See # #expand_class. def expand_name name klass, selector, method = parse_name name return [selector, method].join if klass.empty? case selector when ':' then [find_store(klass), selector, method] else [expand_class(klass), selector, method] end.join end ## # Filters the methods in +found+ trying to find a match for +name+. def filter_methods found, name regexp = name_regexp name filtered = found.find_all do |store, methods| methods.any? { |method| method.full_name =~ regexp } end return filtered unless filtered.empty? found end ## # Yields items matching +name+ including the store they were found in, the # class being searched for, the class they were found in (an ancestor) the # types of methods to look up (from #method_type), and the method name being # searched for def find_methods name klass, selector, method = parse_name name types = method_type selector klasses = nil ambiguous = klass.empty? if ambiguous then klasses = classes.keys else klasses = ancestors_of klass klasses.unshift klass end methods = [] klasses.each do |ancestor| ancestors = classes[ancestor] next unless ancestors klass = ancestor if ambiguous ancestors.each do |store| methods << [store, klass, ancestor, types, method] end end methods = methods.sort_by do |_, k, a, _, m| [k, a, m].compact end methods.each do |item| yield(*item) # :yields: store, klass, ancestor, types, method end self end ## # Finds the given +pager+ for jruby. Returns an IO if +pager+ was found. # # Returns false if +pager+ does not exist. # # Returns nil if the jruby JVM doesn't support ProcessBuilder redirection # (1.6 and older). def find_pager_jruby pager require 'java' require 'shellwords' return nil unless java.lang.ProcessBuilder.constants.include? :Redirect pager = Shellwords.split pager pb = java.lang.ProcessBuilder.new(*pager) pb = pb.redirect_output java.lang.ProcessBuilder::Redirect::INHERIT @jruby_pager_process = pb.start input = @jruby_pager_process.output_stream io = input.to_io io.sync = true io rescue java.io.IOException false end ## # Finds a store that matches +name+ which can be the name of a gem, "ruby", # "home" or "site". # # See also RDoc::Store#source def find_store name @stores.each do |store| source = store.source return source if source == name return source if store.type == :gem and source =~ /^#{Regexp.escape name}-\d/ end raise RDoc::RI::Driver::NotFoundError, name end ## # Creates a new RDoc::Markup::Formatter. If a formatter is given with -f, # use it. If we're outputting to a pager, use bs, otherwise ansi. def formatter(io) if @formatter_klass then @formatter_klass.new elsif paging? or !io.tty? then RDoc::Markup::ToBs.new else RDoc::Markup::ToAnsi.new end end ## # Runs ri interactively using Readline if it is available. def interactive puts "\nEnter the method name you want to look up." if defined? Readline then Readline.completion_proc = method :complete puts "You can use tab to autocomplete." end puts "Enter a blank line to exit.\n\n" loop do name = if defined? Readline then Readline.readline ">> " else print ">> " $stdin.gets end return if name.nil? or name.empty? name = expand_name name.strip begin display_name name rescue NotFoundError => e puts e.message end end rescue Interrupt exit end ## # Is +file+ in ENV['PATH']? def in_path? file return true if file =~ %r%\A/% and File.exist? file ENV['PATH'].split(File::PATH_SEPARATOR).any? do |path| File.exist? File.join(path, file) end end ## # Lists classes known to ri starting with +names+. If +names+ is empty all # known classes are shown. def list_known_classes names = [] classes = [] stores.each do |store| classes << store.module_names end classes = classes.flatten.uniq.sort unless names.empty? then filter = Regexp.union names.map { |name| /^#{name}/ } classes = classes.grep filter end page do |io| if paging? or io.tty? then if names.empty? then io.puts "Classes and Modules known to ri:" else io.puts "Classes and Modules starting with #{names.join ', '}:" end io.puts end io.puts classes.join("\n") end end ## # Returns an Array of methods matching +name+ def list_methods_matching name found = [] find_methods name do |store, klass, ancestor, types, method| if types == :instance or types == :both then methods = store.instance_methods[ancestor] if methods then matches = methods.grep(/^#{Regexp.escape method.to_s}/) matches = matches.map do |match| "#{klass}##{match}" end found.concat matches end end if types == :class or types == :both then methods = store.class_methods[ancestor] next unless methods matches = methods.grep(/^#{Regexp.escape method.to_s}/) matches = matches.map do |match| "#{klass}::#{match}" end found.concat matches end end found.uniq end ## # Loads RI data for method +name+ on +klass+ from +store+. +type+ and # +cache+ indicate if it is a class or instance method. def load_method store, cache, klass, type, name methods = store.send(cache)[klass] return unless methods method = methods.find do |method_name| method_name == name end return unless method store.load_method klass, "#{type}#{method}" rescue RDoc::Store::MissingFileError => e comment = RDoc::Comment.new("missing documentation at #{e.file}").parse method = RDoc::AnyMethod.new nil, name method.comment = comment method end ## # Returns an Array of RI data for methods matching +name+ def load_methods_matching name found = [] find_methods name do |store, klass, ancestor, types, method| methods = [] methods << load_method(store, :class_methods, ancestor, '::', method) if [:class, :both].include? types methods << load_method(store, :instance_methods, ancestor, '#', method) if [:instance, :both].include? types found << [store, methods.compact] end found.reject do |path, methods| methods.empty? end end ## # Returns a filtered list of methods matching +name+ def lookup_method name found = load_methods_matching name raise NotFoundError, name if found.empty? filter_methods found, name end ## # Builds a RDoc::Markup::Document from +found+, +klasses+ and +includes+ def method_document name, filtered out = RDoc::Markup::Document.new out << RDoc::Markup::Heading.new(1, name) out << RDoc::Markup::BlankLine.new filtered.each do |store, methods| methods.each do |method| render_method out, store, method, name end end out end ## # Returns the type of method (:both, :instance, :class) for +selector+ def method_type selector case selector when '.', nil then :both when '#' then :instance else :class end end ## # Returns a regular expression for +name+ that will match an # RDoc::AnyMethod's name. def name_regexp name klass, type, name = parse_name name case type when '#', '::' then /^#{klass}#{type}#{Regexp.escape name}$/ else /^#{klass}(#|::)#{Regexp.escape name}$/ end end ## # Paginates output through a pager program. def page if pager = setup_pager then begin yield pager ensure pager.close @jruby_pager_process.wait_for if @jruby_pager_process end else yield $stdout end rescue Errno::EPIPE ensure @paging = false end ## # Are we using a pager? def paging? @paging end ## # Extracts the class, selector and method name parts from +name+ like # Foo::Bar#baz. # # NOTE: Given Foo::Bar, Bar is considered a class even though it may be a # method def parse_name name parts = name.split(/(::?|#|\.)/) if parts.length == 1 then if parts.first =~ /^[a-z]|^([%&*+\/<>^`|~-]|\+@|-@|<<|<=>?|===?|=>|=~|>>|\[\]=?|~@)$/ then type = '.' meth = parts.pop else type = nil meth = nil end elsif parts.length == 2 or parts.last =~ /::|#|\./ then type = parts.pop meth = nil elsif parts[1] == ':' then klass = parts.shift type = parts.shift meth = parts.join elsif parts[-2] != '::' or parts.last !~ /^[A-Z]/ then meth = parts.pop type = parts.pop end klass ||= parts.join [klass, type, meth] end ## # Renders the +klass+ from +store+ to +out+. If the klass has no # documentable items the class is added to +also_in+ instead. def render_class out, store, klass, also_in # :nodoc: comment = klass.comment # TODO the store's cache should always return an empty Array class_methods = store.class_methods[klass.full_name] || [] instance_methods = store.instance_methods[klass.full_name] || [] attributes = store.attributes[klass.full_name] || [] if comment.empty? and instance_methods.empty? and class_methods.empty? then also_in << store return end add_from out, store class_document_comment out, comment if class_methods or instance_methods or not klass.constants.empty? then out << RDoc::Markup::Rule.new(1) end class_document_constants out, klass add_method_list out, class_methods, 'Class methods' add_method_list out, instance_methods, 'Instance methods' add_method_list out, attributes, 'Attributes' add_method_documentation out, klass if @show_all end def render_method out, store, method, name # :nodoc: out << RDoc::Markup::Paragraph.new("(from #{store.friendly_path})") unless name =~ /^#{Regexp.escape method.parent_name}/ then out << RDoc::Markup::Heading.new(3, "Implementation from #{method.parent_name}") end out << RDoc::Markup::Rule.new(1) render_method_arguments out, method.arglists render_method_superclass out, method render_method_comment out, method end def render_method_arguments out, arglists # :nodoc: return unless arglists arglists = arglists.chomp.split "\n" arglists = arglists.map { |line| line + "\n" } out << RDoc::Markup::Verbatim.new(*arglists) out << RDoc::Markup::Rule.new(1) end def render_method_comment out, method # :nodoc: out << RDoc::Markup::BlankLine.new out << method.comment out << RDoc::Markup::BlankLine.new end def render_method_superclass out, method # :nodoc: return unless method.respond_to?(:superclass_method) and method.superclass_method out << RDoc::Markup::BlankLine.new out << RDoc::Markup::Heading.new(4, "(Uses superclass method #{method.superclass_method})") out << RDoc::Markup::Rule.new(1) end ## # Looks up and displays ri data according to the options given. def run if @list_doc_dirs then puts @doc_dirs elsif @list then list_known_classes @names elsif @server then start_server elsif @interactive or @names.empty? then interactive else display_names @names end rescue NotFoundError => e abort e.message end ## # Sets up a pager program to pass output through. Tries the RI_PAGER and # PAGER environment variables followed by pager, less then more. def setup_pager return if @use_stdout jruby = Object.const_defined?(:RUBY_ENGINE) && RUBY_ENGINE == 'jruby' pagers = [ENV['RI_PAGER'], ENV['PAGER'], 'pager', 'less', 'more'] pagers.compact.uniq.each do |pager| next unless pager pager_cmd = pager.split.first next unless in_path? pager_cmd if jruby then case io = find_pager_jruby(pager) when nil then break when false then next else io end else io = IO.popen(pager, 'w') rescue next end next if $? and $?.pid == io.pid and $?.exited? # pager didn't work @paging = true return io end @use_stdout = true nil end ## # Starts a WEBrick server for ri. def start_server require 'webrick' server = WEBrick::HTTPServer.new :Port => @server extra_doc_dirs = @stores.map {|s| s.type == :extra ? s.path : nil}.compact server.mount '/', RDoc::Servlet, nil, extra_doc_dirs trap 'INT' do server.shutdown end trap 'TERM' do server.shutdown end server.start end end PK!`= = 2.2.0/rdoc/parser.rbnu[# -*- coding: us-ascii -*- ## # A parser is simple a class that subclasses RDoc::Parser and implements #scan # to fill in an RDoc::TopLevel with parsed data. # # The initialize method takes an RDoc::TopLevel to fill with parsed content, # the name of the file to be parsed, the content of the file, an RDoc::Options # object and an RDoc::Stats object to inform the user of parsed items. The # scan method is then called to parse the file and must return the # RDoc::TopLevel object. By calling super these items will be set for you. # # In order to be used by RDoc the parser needs to register the file extensions # it can parse. Use ::parse_files_matching to register extensions. # # require 'rdoc' # # class RDoc::Parser::Xyz < RDoc::Parser # parse_files_matching /\.xyz$/ # # def initialize top_level, file_name, content, options, stats # super # # # extra initialization if needed # end # # def scan # # parse file and fill in @top_level # end # end class RDoc::Parser @parsers = [] class << self ## # An Array of arrays that maps file extension (or name) regular # expressions to parser classes that will parse matching filenames. # # Use parse_files_matching to register a parser's file extensions. attr_reader :parsers end ## # The name of the file being parsed attr_reader :file_name ## # Alias an extension to another extension. After this call, files ending # "new_ext" will be parsed using the same parser as "old_ext" def self.alias_extension(old_ext, new_ext) old_ext = old_ext.sub(/^\.(.*)/, '\1') new_ext = new_ext.sub(/^\.(.*)/, '\1') parser = can_parse_by_name "xxx.#{old_ext}" return false unless parser RDoc::Parser.parsers.unshift [/\.#{new_ext}$/, parser] true end ## # Determines if the file is a "binary" file which basically means it has # content that an RDoc parser shouldn't try to consume. def self.binary?(file) return false if file =~ /\.(rdoc|txt)$/ s = File.read(file, 1024) or return false have_encoding = s.respond_to? :encoding return true if s[0, 2] == Marshal.dump('')[0, 2] or s.index("\x00") if have_encoding then mode = "r" s.sub!(/\A#!.*\n/, '') # assume shebang line isn't longer than 1024. encoding = s[/^\s*\#\s*(?:-\*-\s*)?(?:en)?coding:\s*([^\s;]+?)(?:-\*-|[\s;])/, 1] mode = "rb:#{encoding}" if encoding s = File.open(file, mode) {|f| f.gets(nil, 1024)} not s.valid_encoding? else if 0.respond_to? :fdiv then s.count("\x00-\x7F", "^ -~\t\r\n").fdiv(s.size) > 0.3 else # HACK 1.8.6 (s.count("\x00-\x7F", "^ -~\t\r\n").to_f / s.size) > 0.3 end end end ## # Processes common directives for CodeObjects for the C and Ruby parsers. # # Applies +directive+'s +value+ to +code_object+, if appropriate def self.process_directive code_object, directive, value warn "RDoc::Parser::process_directive is deprecated and wil be removed in RDoc 4. Use RDoc::Markup::PreProcess#handle_directive instead" if $-w case directive when 'nodoc' then code_object.document_self = nil # notify nodoc code_object.document_children = value.downcase != 'all' when 'doc' then code_object.document_self = true code_object.force_documentation = true when 'yield', 'yields' then # remove parameter &block code_object.params.sub!(/,?\s*&\w+/, '') if code_object.params code_object.block_params = value when 'arg', 'args' then code_object.params = value end end ## # Checks if +file+ is a zip file in disguise. Signatures from # http://www.garykessler.net/library/file_sigs.html def self.zip? file zip_signature = File.read file, 4 zip_signature == "PK\x03\x04" or zip_signature == "PK\x05\x06" or zip_signature == "PK\x07\x08" rescue false end ## # Return a parser that can handle a particular extension def self.can_parse file_name parser = can_parse_by_name file_name # HACK Selenium hides a jar file using a .txt extension return if parser == RDoc::Parser::Simple and zip? file_name parser end ## # Returns a parser that can handle the extension for +file_name+. This does # not depend upon the file being readable. def self.can_parse_by_name file_name _, parser = RDoc::Parser.parsers.find { |regexp,| regexp =~ file_name } # The default parser must not parse binary files ext_name = File.extname file_name return parser if ext_name.empty? if parser == RDoc::Parser::Simple and ext_name !~ /txt|rdoc/ then case check_modeline file_name when nil, 'rdoc' then # continue else return nil end end parser rescue Errno::EACCES end ## # Returns the file type from the modeline in +file_name+ def self.check_modeline file_name line = open file_name do |io| io.gets end /-\*-\s*(.*?\S)\s*-\*-/ =~ line return nil unless type = $1 if /;/ =~ type then return nil unless /(?:\s|\A)mode:\s*([^\s;]+)/i =~ type type = $1 end return nil if /coding:/i =~ type type.downcase rescue ArgumentError # invalid byte sequence, etc. end ## # Finds and instantiates the correct parser for the given +file_name+ and # +content+. def self.for top_level, file_name, content, options, stats return if binary? file_name parser = use_markup content unless parser then parse_name = file_name # If no extension, look for shebang if file_name !~ /\.\w+$/ && content =~ %r{\A#!(.+)} then shebang = $1 case shebang when %r{env\s+ruby}, %r{/ruby} parse_name = 'dummy.rb' end end parser = can_parse parse_name end return unless parser content = remove_modeline content parser.new top_level, file_name, content, options, stats rescue SystemCallError nil end ## # Record which file types this parser can understand. # # It is ok to call this multiple times. def self.parse_files_matching(regexp) RDoc::Parser.parsers.unshift [regexp, self] end ## # Removes an emacs-style modeline from the first line of the document def self.remove_modeline content content.sub(/\A.*-\*-\s*(.*?\S)\s*-\*-.*\r?\n/, '') end ## # If there is a markup: parser_name comment at the front of the # file, use it to determine the parser. For example: # # # markup: rdoc # # Class comment can go here # # class C # end # # The comment should appear as the first line of the +content+. # # If the content contains a shebang or editor modeline the comment may # appear on the second or third line. # # Any comment style may be used to hide the markup comment. def self.use_markup content markup = content.lines.first(3).grep(/markup:\s+(\w+)/) { $1 }.first return unless markup # TODO Ruby should be returned only when the filename is correct return RDoc::Parser::Ruby if %w[tomdoc markdown].include? markup markup = Regexp.escape markup _, selected = RDoc::Parser.parsers.find do |_, parser| /^#{markup}$/i =~ parser.name.sub(/.*:/, '') end selected end ## # Creates a new Parser storing +top_level+, +file_name+, +content+, # +options+ and +stats+ in instance variables. In +@preprocess+ an # RDoc::Markup::PreProcess object is created which allows processing of # directives. def initialize top_level, file_name, content, options, stats @top_level = top_level @top_level.parser = self.class @store = @top_level.store @file_name = file_name @content = content @options = options @stats = stats @preprocess = RDoc::Markup::PreProcess.new @file_name, @options.rdoc_include @preprocess.options = @options end autoload :RubyTools, 'rdoc/parser/ruby_tools' autoload :Text, 'rdoc/parser/text' end # simple must come first in order to show up last in the parsers list require 'rdoc/parser/simple' require 'rdoc/parser/c' require 'rdoc/parser/changelog' require 'rdoc/parser/markdown' require 'rdoc/parser/rd' require 'rdoc/parser/ruby' PK!XSw' ' 2.2.0/digest.rbnu[require 'digest.so' module Digest # A mutex for Digest(). REQUIRE_MUTEX = Mutex.new def self.const_missing(name) # :nodoc: case name when :SHA256, :SHA384, :SHA512 lib = 'digest/sha2.so' else lib = File.join('digest', name.to_s.downcase) end begin require lib rescue LoadError raise LoadError, "library not found for class Digest::#{name} -- #{lib}", caller(1) end unless Digest.const_defined?(name) raise NameError, "uninitialized constant Digest::#{name}", caller(1) end Digest.const_get(name) end class ::Digest::Class # Creates a digest object and reads a given file, _name_. # Optional arguments are passed to the constructor of the digest # class. # # p Digest::SHA256.file("X11R6.8.2-src.tar.bz2").hexdigest # # => "f02e3c85572dc9ad7cb77c2a638e3be24cc1b5bea9fdbb0b0299c9668475c534" def self.file(name, *args) new(*args).file(name) end # Returns the base64 encoded hash value of a given _string_. The # return value is properly padded with '=' and contains no line # feeds. def self.base64digest(str, *args) [digest(str, *args)].pack('m0') end end module Instance # Updates the digest with the contents of a given file _name_ and # returns self. def file(name) File.open(name, "rb") {|f| buf = "" while f.read(16384, buf) update buf end } self end # If none is given, returns the resulting hash value of the digest # in a base64 encoded form, keeping the digest's state. # # If a +string+ is given, returns the hash value for the given # +string+ in a base64 encoded form, resetting the digest to the # initial state before and after the process. # # In either case, the return value is properly padded with '=' and # contains no line feeds. def base64digest(str = nil) [str ? digest(str) : digest].pack('m0') end # Returns the resulting hash value and resets the digest to the # initial state. def base64digest! [digest!].pack('m0') end end end # call-seq: # Digest(name) -> digest_subclass # # Returns a Digest subclass by +name+ in a thread-safe manner even # when on-demand loading is involved. # # require 'digest' # # Digest("MD5") # # => Digest::MD5 # # Digest(:SHA256) # # => Digest::SHA256 # # Digest(:Foo) # # => LoadError: library not found for class Digest::Foo -- digest/foo def Digest(name) const = name.to_sym Digest::REQUIRE_MUTEX.synchronize { # Ignore autoload's because it is void when we have #const_missing Digest.const_missing(const) } rescue LoadError # Constants do not necessarily rely on digest/*. if Digest.const_defined?(const) Digest.const_get(const) else raise end end PK!X2.2.0/monitor.rbnu[# = monitor.rb # # Copyright (C) 2001 Shugo Maeda # # This library is distributed under the terms of the Ruby license. # You can freely distribute/modify this library. # require 'thread' # # In concurrent programming, a monitor is an object or module intended to be # used safely by more than one thread. The defining characteristic of a # monitor is that its methods are executed with mutual exclusion. That is, at # each point in time, at most one thread may be executing any of its methods. # This mutual exclusion greatly simplifies reasoning about the implementation # of monitors compared to reasoning about parallel code that updates a data # structure. # # You can read more about the general principles on the Wikipedia page for # Monitors[http://en.wikipedia.org/wiki/Monitor_%28synchronization%29] # # == Examples # # === Simple object.extend # # require 'monitor.rb' # # buf = [] # buf.extend(MonitorMixin) # empty_cond = buf.new_cond # # # consumer # Thread.start do # loop do # buf.synchronize do # empty_cond.wait_while { buf.empty? } # print buf.shift # end # end # end # # # producer # while line = ARGF.gets # buf.synchronize do # buf.push(line) # empty_cond.signal # end # end # # The consumer thread waits for the producer thread to push a line to buf # while buf.empty?. The producer thread (main thread) reads a # line from ARGF and pushes it into buf then calls empty_cond.signal # to notify the consumer thread of new data. # # === Simple Class include # # require 'monitor' # # class SynchronizedArray < Array # # include MonitorMixin # # def initialize(*args) # super(*args) # end # # alias :old_shift :shift # alias :old_unshift :unshift # # def shift(n=1) # self.synchronize do # self.old_shift(n) # end # end # # def unshift(item) # self.synchronize do # self.old_unshift(item) # end # end # # # other methods ... # end # # +SynchronizedArray+ implements an Array with synchronized access to items. # This Class is implemented as subclass of Array which includes the # MonitorMixin module. # module MonitorMixin # # FIXME: This isn't documented in Nutshell. # # Since MonitorMixin.new_cond returns a ConditionVariable, and the example # above calls while_wait and signal, this class should be documented. # class ConditionVariable class Timeout < Exception; end # # Releases the lock held in the associated monitor and waits; reacquires the lock on wakeup. # # If +timeout+ is given, this method returns after +timeout+ seconds passed, # even if no other thread doesn't signal. # def wait(timeout = nil) @monitor.__send__(:mon_check_owner) count = @monitor.__send__(:mon_exit_for_cond) begin @cond.wait(@monitor.instance_variable_get(:@mon_mutex), timeout) return true ensure @monitor.__send__(:mon_enter_for_cond, count) end end # # Calls wait repeatedly while the given block yields a truthy value. # def wait_while while yield wait end end # # Calls wait repeatedly until the given block yields a truthy value. # def wait_until until yield wait end end # # Wakes up the first thread in line waiting for this lock. # def signal @monitor.__send__(:mon_check_owner) @cond.signal end # # Wakes up all threads waiting for this lock. # def broadcast @monitor.__send__(:mon_check_owner) @cond.broadcast end private def initialize(monitor) @monitor = monitor @cond = ::ConditionVariable.new end end def self.extend_object(obj) super(obj) obj.__send__(:mon_initialize) end # # Attempts to enter exclusive section. Returns +false+ if lock fails. # def mon_try_enter if @mon_owner != Thread.current unless @mon_mutex.try_lock return false end @mon_owner = Thread.current end @mon_count += 1 return true end # For backward compatibility alias try_mon_enter mon_try_enter # # Enters exclusive section. # def mon_enter if @mon_owner != Thread.current @mon_mutex.lock @mon_owner = Thread.current end @mon_count += 1 end # # Leaves exclusive section. # def mon_exit mon_check_owner @mon_count -=1 if @mon_count == 0 @mon_owner = nil @mon_mutex.unlock end end # # Enters exclusive section and executes the block. Leaves the exclusive # section automatically when the block exits. See example under # +MonitorMixin+. # def mon_synchronize mon_enter begin yield ensure mon_exit end end alias synchronize mon_synchronize # # Creates a new MonitorMixin::ConditionVariable associated with the # receiver. # def new_cond return ConditionVariable.new(self) end private # Use extend MonitorMixin or include MonitorMixin instead # of this constructor. Have look at the examples above to understand how to # use this module. def initialize(*args) super mon_initialize end # Initializes the MonitorMixin after being included in a class or when an # object has been extended with the MonitorMixin def mon_initialize @mon_owner = nil @mon_count = 0 @mon_mutex = Mutex.new end def mon_check_owner if @mon_owner != Thread.current raise ThreadError, "current thread not owner" end end def mon_enter_for_cond(count) @mon_owner = Thread.current @mon_count = count end def mon_exit_for_cond count = @mon_count @mon_owner = nil @mon_count = 0 return count end end # Use the Monitor class when you want to have a lock object for blocks with # mutual exclusion. # # require 'monitor' # # lock = Monitor.new # lock.synchronize do # # exclusive access # end # class Monitor include MonitorMixin alias try_enter try_mon_enter alias enter mon_enter alias exit mon_exit end # Documentation comments: # - All documentation comes from Nutshell. # - MonitorMixin.new_cond appears in the example, but is not documented in # Nutshell. # - All the internals (internal modules Accessible and Initializable, class # ConditionVariable) appear in RDoc. It might be good to hide them, by # making them private, or marking them :nodoc:, etc. # - RDoc doesn't recognise aliases, so we have mon_synchronize documented, but # not synchronize. # - mon_owner is in Nutshell, but appears as an accessor in a separate module # here, so is hard/impossible to RDoc. Some other useful accessors # (mon_count and some queue stuff) are also in this module, and don't appear # directly in the RDoc output. # - in short, it may be worth changing the code layout in this file to make the # documentation easier # Local variables: # mode: Ruby # tab-width: 8 # End: PK!%DOtOt2.2.0/debug.rbnu[# Copyright (C) 2000 Network Applied Communication Laboratory, Inc. # Copyright (C) 2000 Information-technology Promotion Agency, Japan # Copyright (C) 2000-2003 NAKAMURA, Hiroshi require 'continuation' if $SAFE > 0 STDERR.print "-r debug.rb is not available in safe mode\n" exit 1 end require 'tracer' require 'pp' class Tracer # :nodoc: def Tracer.trace_func(*vars) Single.trace_func(*vars) end end SCRIPT_LINES__ = {} unless defined? SCRIPT_LINES__ # :nodoc: ## # This library provides debugging functionality to Ruby. # # To add a debugger to your code, start by requiring +debug+ in your # program: # # def say(word) # require 'debug' # puts word # end # # This will cause Ruby to interrupt execution and show a prompt when the +say+ # method is run. # # Once you're inside the prompt, you can start debugging your program. # # (rdb:1) p word # "hello" # # == Getting help # # You can get help at any time by pressing +h+. # # (rdb:1) h # Debugger help v.-0.002b # Commands # b[reak] [file:|class:] # b[reak] [class.] # set breakpoint to some position # wat[ch] set watchpoint to some expression # cat[ch] (|off) set catchpoint to an exception # b[reak] list breakpoints # cat[ch] show catchpoint # del[ete][ nnn] delete some or all breakpoints # disp[lay] add expression into display expression list # undisp[lay][ nnn] delete one particular or all display expressions # c[ont] run until program ends or hit breakpoint # s[tep][ nnn] step (into methods) one line or till line nnn # n[ext][ nnn] go over one line or till line nnn # w[here] display frames # f[rame] alias for where # l[ist][ (-|nn-mm)] list program, - lists backwards # nn-mm lists given lines # up[ nn] move to higher frame # down[ nn] move to lower frame # fin[ish] return to outer frame # tr[ace] (on|off) set trace mode of current thread # tr[ace] (on|off) all set trace mode of all threads # q[uit] exit from debugger # v[ar] g[lobal] show global variables # v[ar] l[ocal] show local variables # v[ar] i[nstance] show instance variables of object # v[ar] c[onst] show constants of object # m[ethod] i[nstance] show methods of object # m[ethod] show instance methods of class or module # th[read] l[ist] list all threads # th[read] c[ur[rent]] show current thread # th[read] [sw[itch]] switch thread context to nnn # th[read] stop stop thread nnn # th[read] resume resume thread nnn # p expression evaluate expression and print its value # h[elp] print this help # evaluate # # == Usage # # The following is a list of common functionalities that the debugger # provides. # # === Navigating through your code # # In general, a debugger is used to find bugs in your program, which # often means pausing execution and inspecting variables at some point # in time. # # Let's look at an example: # # def my_method(foo) # require 'debug' # foo = get_foo if foo.nil? # raise if foo.nil? # end # # When you run this program, the debugger will kick in just before the # +foo+ assignment. # # (rdb:1) p foo # nil # # In this example, it'd be interesting to move to the next line and # inspect the value of +foo+ again. You can do that by pressing +n+: # # (rdb:1) n # goes to next line # (rdb:1) p foo # nil # # You now know that the original value of +foo+ was nil, and that it # still was nil after calling +get_foo+. # # Other useful commands for navigating through your code are: # # +c+:: # Runs the program until it either exists or encounters another breakpoint. # You usually press +c+ when you are finished debugging your program and # want to resume its execution. # +s+:: # Steps into method definition. In the previous example, +s+ would take you # inside the method definition of +get_foo+. # +r+:: # Restart the program. # +q+:: # Quit the program. # # === Inspecting variables # # You can use the debugger to easily inspect both local and global variables. # We've seen how to inspect local variables before: # # (rdb:1) p my_arg # 42 # # You can also pretty print the result of variables or expressions: # # (rdb:1) pp %w{a very long long array containing many words} # ["a", # "very", # "long", # ... # ] # # You can list all local variables with +v l+: # # (rdb:1) v l # foo => "hello" # # Similarly, you can show all global variables with +v g+: # # (rdb:1) v g # all global variables # # Finally, you can omit +p+ if you simply want to evaluate a variable or # expression # # (rdb:1) 5**2 # 25 # # === Going beyond basics # # Ruby Debug provides more advanced functionalities like switching # between threads, setting breakpoints and watch expressions, and more. # The full list of commands is available at any time by pressing +h+. # # == Staying out of trouble # # Make sure you remove every instance of +require 'debug'+ before # shipping your code. Failing to do so may result in your program # hanging unpredictably. # # Debug is not available in safe mode. class DEBUGGER__ MUTEX = Mutex.new # :nodoc: class Context # :nodoc: DEBUG_LAST_CMD = [] begin require 'readline' def readline(prompt, hist) Readline::readline(prompt, hist) end rescue LoadError def readline(prompt, hist) STDOUT.print prompt STDOUT.flush line = STDIN.gets exit unless line line.chomp! line end USE_READLINE = false end def initialize if Thread.current == Thread.main @stop_next = 1 else @stop_next = 0 end @last_file = nil @file = nil @line = nil @no_step = nil @frames = [] @finish_pos = 0 @trace = false @catch = "StandardError" @suspend_next = false end def stop_next(n=1) @stop_next = n end def set_suspend @suspend_next = true end def clear_suspend @suspend_next = false end def suspend_all DEBUGGER__.suspend end def resume_all DEBUGGER__.resume end def check_suspend while MUTEX.synchronize { if @suspend_next DEBUGGER__.waiting.push Thread.current @suspend_next = false true end } end end def trace? @trace end def set_trace(arg) @trace = arg end def stdout DEBUGGER__.stdout end def break_points DEBUGGER__.break_points end def display DEBUGGER__.display end def context(th) DEBUGGER__.context(th) end def set_trace_all(arg) DEBUGGER__.set_trace(arg) end def set_last_thread(th) DEBUGGER__.set_last_thread(th) end def debug_eval(str, binding) begin eval(str, binding) rescue StandardError, ScriptError => e at = eval("caller(1)", binding) stdout.printf "%s:%s\n", at.shift, e.to_s.sub(/\(eval\):1:(in `.*?':)?/, '') for i in at stdout.printf "\tfrom %s\n", i end throw :debug_error end end def debug_silent_eval(str, binding) begin eval(str, binding) rescue StandardError, ScriptError nil end end def var_list(ary, binding) ary.sort! for v in ary stdout.printf " %s => %s\n", v, eval(v.to_s, binding).inspect end end def debug_variable_info(input, binding) case input when /^\s*g(?:lobal)?\s*$/ var_list(global_variables, binding) when /^\s*l(?:ocal)?\s*$/ var_list(eval("local_variables", binding), binding) when /^\s*i(?:nstance)?\s+/ obj = debug_eval($', binding) var_list(obj.instance_variables, obj.instance_eval{binding()}) when /^\s*c(?:onst(?:ant)?)?\s+/ obj = debug_eval($', binding) unless obj.kind_of? Module stdout.print "Should be Class/Module: ", $', "\n" else var_list(obj.constants, obj.module_eval{binding()}) end end end def debug_method_info(input, binding) case input when /^i(:?nstance)?\s+/ obj = debug_eval($', binding) len = 0 for v in obj.methods.sort len += v.size + 1 if len > 70 len = v.size + 1 stdout.print "\n" end stdout.print v, " " end stdout.print "\n" else obj = debug_eval(input, binding) unless obj.kind_of? Module stdout.print "Should be Class/Module: ", input, "\n" else len = 0 for v in obj.instance_methods(false).sort len += v.size + 1 if len > 70 len = v.size + 1 stdout.print "\n" end stdout.print v, " " end stdout.print "\n" end end end def thnum num = DEBUGGER__.instance_eval{@thread_list[Thread.current]} unless num DEBUGGER__.make_thread_list num = DEBUGGER__.instance_eval{@thread_list[Thread.current]} end num end def debug_command(file, line, id, binding) MUTEX.lock unless defined?($debugger_restart) and $debugger_restart callcc{|c| $debugger_restart = c} end set_last_thread(Thread.current) frame_pos = 0 binding_file = file binding_line = line previous_line = nil if ENV['EMACS'] stdout.printf "\032\032%s:%d:\n", binding_file, binding_line else stdout.printf "%s:%d:%s", binding_file, binding_line, line_at(binding_file, binding_line) end @frames[0] = [binding, file, line, id] display_expressions(binding) prompt = true while prompt and input = readline("(rdb:%d) "%thnum(), true) catch(:debug_error) do if input == "" next unless DEBUG_LAST_CMD[0] input = DEBUG_LAST_CMD[0] stdout.print input, "\n" else DEBUG_LAST_CMD[0] = input end case input when /^\s*tr(?:ace)?(?:\s+(on|off))?(?:\s+(all))?$/ if defined?( $2 ) if $1 == 'on' set_trace_all true else set_trace_all false end elsif defined?( $1 ) if $1 == 'on' set_trace true else set_trace false end end if trace? stdout.print "Trace on.\n" else stdout.print "Trace off.\n" end when /^\s*b(?:reak)?\s+(?:(.+):)?([^.:]+)$/ pos = $2 if $1 klass = debug_silent_eval($1, binding) file = $1 end if pos =~ /^\d+$/ pname = pos pos = pos.to_i else pname = pos = pos.intern.id2name end break_points.push [true, 0, klass || file, pos] stdout.printf "Set breakpoint %d at %s:%s\n", break_points.size, klass || file, pname when /^\s*b(?:reak)?\s+(.+)[#.]([^.:]+)$/ pos = $2.intern.id2name klass = debug_eval($1, binding) break_points.push [true, 0, klass, pos] stdout.printf "Set breakpoint %d at %s.%s\n", break_points.size, klass, pos when /^\s*wat(?:ch)?\s+(.+)$/ exp = $1 break_points.push [true, 1, exp] stdout.printf "Set watchpoint %d:%s\n", break_points.size, exp when /^\s*b(?:reak)?$/ if break_points.find{|b| b[1] == 0} n = 1 stdout.print "Breakpoints:\n" break_points.each do |b| if b[0] and b[1] == 0 stdout.printf " %d %s:%s\n", n, b[2], b[3] end n += 1 end end if break_points.find{|b| b[1] == 1} n = 1 stdout.print "\n" stdout.print "Watchpoints:\n" for b in break_points if b[0] and b[1] == 1 stdout.printf " %d %s\n", n, b[2] end n += 1 end end if break_points.size == 0 stdout.print "No breakpoints\n" else stdout.print "\n" end when /^\s*del(?:ete)?(?:\s+(\d+))?$/ pos = $1 unless pos input = readline("Clear all breakpoints? (y/n) ", false) if input == "y" for b in break_points b[0] = false end end else pos = pos.to_i if break_points[pos-1] break_points[pos-1][0] = false else stdout.printf "Breakpoint %d is not defined\n", pos end end when /^\s*disp(?:lay)?\s+(.+)$/ exp = $1 display.push [true, exp] stdout.printf "%d: ", display.size display_expression(exp, binding) when /^\s*disp(?:lay)?$/ display_expressions(binding) when /^\s*undisp(?:lay)?(?:\s+(\d+))?$/ pos = $1 unless pos input = readline("Clear all expressions? (y/n) ", false) if input == "y" for d in display d[0] = false end end else pos = pos.to_i if display[pos-1] display[pos-1][0] = false else stdout.printf "Display expression %d is not defined\n", pos end end when /^\s*c(?:ont)?$/ prompt = false when /^\s*s(?:tep)?(?:\s+(\d+))?$/ if $1 lev = $1.to_i else lev = 1 end @stop_next = lev prompt = false when /^\s*n(?:ext)?(?:\s+(\d+))?$/ if $1 lev = $1.to_i else lev = 1 end @stop_next = lev @no_step = @frames.size - frame_pos prompt = false when /^\s*w(?:here)?$/, /^\s*f(?:rame)?$/ display_frames(frame_pos) when /^\s*l(?:ist)?(?:\s+(.+))?$/ if not $1 b = previous_line ? previous_line + 10 : binding_line - 5 e = b + 9 elsif $1 == '-' b = previous_line ? previous_line - 10 : binding_line - 5 e = b + 9 else b, e = $1.split(/[-,]/) if e b = b.to_i e = e.to_i else b = b.to_i - 5 e = b + 9 end end previous_line = b display_list(b, e, binding_file, binding_line) when /^\s*up(?:\s+(\d+))?$/ previous_line = nil if $1 lev = $1.to_i else lev = 1 end frame_pos += lev if frame_pos >= @frames.size frame_pos = @frames.size - 1 stdout.print "At toplevel\n" end binding, binding_file, binding_line = @frames[frame_pos] stdout.print format_frame(frame_pos) when /^\s*down(?:\s+(\d+))?$/ previous_line = nil if $1 lev = $1.to_i else lev = 1 end frame_pos -= lev if frame_pos < 0 frame_pos = 0 stdout.print "At stack bottom\n" end binding, binding_file, binding_line = @frames[frame_pos] stdout.print format_frame(frame_pos) when /^\s*fin(?:ish)?$/ if frame_pos == @frames.size stdout.print "\"finish\" not meaningful in the outermost frame.\n" else @finish_pos = @frames.size - frame_pos frame_pos = 0 prompt = false end when /^\s*cat(?:ch)?(?:\s+(.+))?$/ if $1 excn = $1 if excn == 'off' @catch = nil stdout.print "Clear catchpoint.\n" else @catch = excn stdout.printf "Set catchpoint %s.\n", @catch end else if @catch stdout.printf "Catchpoint %s.\n", @catch else stdout.print "No catchpoint.\n" end end when /^\s*q(?:uit)?$/ input = readline("Really quit? (y/n) ", false) if input == "y" exit! # exit -> exit!: No graceful way to stop threads... end when /^\s*v(?:ar)?\s+/ debug_variable_info($', binding) when /^\s*m(?:ethod)?\s+/ debug_method_info($', binding) when /^\s*th(?:read)?\s+/ if DEBUGGER__.debug_thread_info($', binding) == :cont prompt = false end when /^\s*pp\s+/ PP.pp(debug_eval($', binding), stdout) when /^\s*p\s+/ stdout.printf "%s\n", debug_eval($', binding).inspect when /^\s*r(?:estart)?$/ $debugger_restart.call when /^\s*h(?:elp)?$/ debug_print_help() else v = debug_eval(input, binding) stdout.printf "%s\n", v.inspect end end end MUTEX.unlock resume_all end def debug_print_help stdout.print < b[reak] [class.] set breakpoint to some position wat[ch] set watchpoint to some expression cat[ch] (|off) set catchpoint to an exception b[reak] list breakpoints cat[ch] show catchpoint del[ete][ nnn] delete some or all breakpoints disp[lay] add expression into display expression list undisp[lay][ nnn] delete one particular or all display expressions c[ont] run until program ends or hit breakpoint s[tep][ nnn] step (into methods) one line or till line nnn n[ext][ nnn] go over one line or till line nnn w[here] display frames f[rame] alias for where l[ist][ (-|nn-mm)] list program, - lists backwards nn-mm lists given lines up[ nn] move to higher frame down[ nn] move to lower frame fin[ish] return to outer frame tr[ace] (on|off) set trace mode of current thread tr[ace] (on|off) all set trace mode of all threads q[uit] exit from debugger v[ar] g[lobal] show global variables v[ar] l[ocal] show local variables v[ar] i[nstance] show instance variables of object v[ar] c[onst] show constants of object m[ethod] i[nstance] show methods of object m[ethod] show instance methods of class or module th[read] l[ist] list all threads th[read] c[ur[rent]] show current thread th[read] [sw[itch]] switch thread context to nnn th[read] stop stop thread nnn th[read] resume resume thread nnn pp expression evaluate expression and pretty_print its value p expression evaluate expression and print its value r[estart] restart program h[elp] print this help evaluate EOHELP end def display_expressions(binding) n = 1 for d in display if d[0] stdout.printf "%d: ", n display_expression(d[1], binding) end n += 1 end end def display_expression(exp, binding) stdout.printf "%s = %s\n", exp, debug_silent_eval(exp, binding).to_s end def frame_set_pos(file, line) if @frames[0] @frames[0][1] = file @frames[0][2] = line end end def display_frames(pos) 0.upto(@frames.size - 1) do |n| if n == pos stdout.print "--> " else stdout.print " " end stdout.print format_frame(n) end end def format_frame(pos) _, file, line, id = @frames[pos] sprintf "#%d %s:%s%s\n", pos + 1, file, line, (id ? ":in `#{id.id2name}'" : "") end def script_lines(file, line) unless (lines = SCRIPT_LINES__[file]) and lines != true Tracer::Single.get_line(file, line) if File.exist?(file) lines = SCRIPT_LINES__[file] lines = nil if lines == true end lines end def display_list(b, e, file, line) if lines = script_lines(file, line) stdout.printf "[%d, %d] in %s\n", b, e, file b.upto(e) do |n| if n > 0 && lines[n-1] if n == line stdout.printf "=> %d %s\n", n, lines[n-1].chomp else stdout.printf " %d %s\n", n, lines[n-1].chomp end end end else stdout.printf "No sourcefile available for %s\n", file end end def line_at(file, line) lines = script_lines(file, line) if lines and line = lines[line-1] return line end return "\n" end def debug_funcname(id) if id.nil? "toplevel" else id.id2name end end def check_break_points(file, klass, pos, binding, id) return false if break_points.empty? n = 1 for b in break_points if b[0] # valid if b[1] == 0 # breakpoint if (b[2] == file and b[3] == pos) or (klass and b[2] == klass and b[3] == pos) stdout.printf "Breakpoint %d, %s at %s:%s\n", n, debug_funcname(id), file, pos return true end elsif b[1] == 1 # watchpoint if debug_silent_eval(b[2], binding) stdout.printf "Watchpoint %d, %s at %s:%s\n", n, debug_funcname(id), file, pos return true end end end n += 1 end return false end def excn_handle(file, line, id, binding) if $!.class <= SystemExit set_trace_func nil exit end if @catch and ($!.class.ancestors.find { |e| e.to_s == @catch }) stdout.printf "%s:%d: `%s' (%s)\n", file, line, $!, $!.class fs = @frames.size tb = caller(0)[-fs..-1] if tb for i in tb stdout.printf "\tfrom %s\n", i end end suspend_all debug_command(file, line, id, binding) end end def trace_func(event, file, line, id, binding, klass) Tracer.trace_func(event, file, line, id, binding, klass) if trace? context(Thread.current).check_suspend @file = file @line = line case event when 'line' frame_set_pos(file, line) if !@no_step or @frames.size == @no_step @stop_next -= 1 @stop_next = -1 if @stop_next < 0 elsif @frames.size < @no_step @stop_next = 0 # break here before leaving... else # nothing to do. skipped. end if @stop_next == 0 or check_break_points(file, nil, line, binding, id) @no_step = nil suspend_all debug_command(file, line, id, binding) end when 'call' @frames.unshift [binding, file, line, id] if check_break_points(file, klass, id.id2name, binding, id) suspend_all debug_command(file, line, id, binding) end when 'c-call' frame_set_pos(file, line) when 'class' @frames.unshift [binding, file, line, id] when 'return', 'end' if @frames.size == @finish_pos @stop_next = 1 @finish_pos = 0 end @frames.shift when 'raise' excn_handle(file, line, id, binding) end @last_file = file end end trap("INT") { DEBUGGER__.interrupt } @last_thread = Thread::main @max_thread = 1 @thread_list = {Thread::main => 1} @break_points = [] @display = [] @waiting = [] @stdout = STDOUT class << DEBUGGER__ # Returns the IO used as stdout. Defaults to STDOUT def stdout @stdout end # Sets the IO used as stdout. Defaults to STDOUT def stdout=(s) @stdout = s end # Returns the display expression list # # See DEBUGGER__ for more usage def display @display end # Returns the list of break points where execution will be stopped. # # See DEBUGGER__ for more usage def break_points @break_points end # Returns the list of waiting threads. # # When stepping through the traces of a function, thread gets suspended, to # be resumed later. def waiting @waiting end def set_trace( arg ) MUTEX.synchronize do make_thread_list for th, in @thread_list context(th).set_trace arg end end arg end def set_last_thread(th) @last_thread = th end def suspend MUTEX.synchronize do make_thread_list for th, in @thread_list next if th == Thread.current context(th).set_suspend end end # Schedule other threads to suspend as soon as possible. Thread.pass end def resume MUTEX.synchronize do make_thread_list @thread_list.each do |th,| next if th == Thread.current context(th).clear_suspend end waiting.each do |th| th.run end waiting.clear end # Schedule other threads to restart as soon as possible. Thread.pass end def context(thread=Thread.current) c = thread[:__debugger_data__] unless c thread[:__debugger_data__] = c = Context.new end c end def interrupt context(@last_thread).stop_next end def get_thread(num) th = @thread_list.key(num) unless th @stdout.print "No thread ##{num}\n" throw :debug_error end th end def thread_list(num) th = get_thread(num) if th == Thread.current @stdout.print "+" else @stdout.print " " end @stdout.printf "%d ", num @stdout.print th.inspect, "\t" file = context(th).instance_eval{@file} if file @stdout.print file,":",context(th).instance_eval{@line} end @stdout.print "\n" end def thread_list_all for th in @thread_list.values.sort thread_list(th) end end def make_thread_list hash = {} for th in Thread::list if @thread_list.key? th hash[th] = @thread_list[th] else @max_thread += 1 hash[th] = @max_thread end end @thread_list = hash end def debug_thread_info(input, binding) case input when /^l(?:ist)?/ make_thread_list thread_list_all when /^c(?:ur(?:rent)?)?$/ make_thread_list thread_list(@thread_list[Thread.current]) when /^(?:sw(?:itch)?\s+)?(\d+)/ make_thread_list th = get_thread($1.to_i) if th == Thread.current @stdout.print "It's the current thread.\n" else thread_list(@thread_list[th]) context(th).stop_next th.run return :cont end when /^stop\s+(\d+)/ make_thread_list th = get_thread($1.to_i) if th == Thread.current @stdout.print "It's the current thread.\n" elsif th.stop? @stdout.print "Already stopped.\n" else thread_list(@thread_list[th]) context(th).suspend end when /^resume\s+(\d+)/ make_thread_list th = get_thread($1.to_i) if th == Thread.current @stdout.print "It's the current thread.\n" elsif !th.stop? @stdout.print "Already running." else thread_list(@thread_list[th]) th.run end end end end stdout.printf "Debug.rb\n" stdout.printf "Emacs support available.\n\n" RubyVM::InstructionSequence.compile_option = { trace_instruction: true } set_trace_func proc { |event, file, line, id, binding, klass, *rest| DEBUGGER__.context.trace_func event, file, line, id, binding, klass } end PK!:޾@ @ 2.2.0/thwait.rbnu[# # thwait.rb - thread synchronization class # $Release Version: 0.9 $ # $Revision: 1.3 $ # by Keiju ISHITSUKA(Nihon Rational Software Co.,Ltd.) require "thread.rb" require "e2mmap.rb" # # This class watches for termination of multiple threads. Basic functionality # (wait until specified threads have terminated) can be accessed through the # class method ThreadsWait::all_waits. Finer control can be gained using # instance methods. # # Example: # # ThreadsWait.all_waits(thr1, thr2, ...) do |t| # STDERR.puts "Thread #{t} has terminated." # end # # # th = ThreadsWait.new(thread1,...) # th.next_wait # next one to be done # # class ThreadsWait extend Exception2MessageMapper def_exception("ErrNoWaitingThread", "No threads for waiting.") def_exception("ErrNoFinishedThread", "No finished threads.") # # Waits until all specified threads have terminated. If a block is provided, # it is executed for each thread as they terminate. # def ThreadsWait.all_waits(*threads) # :yield: thread tw = ThreadsWait.new(*threads) if block_given? tw.all_waits do |th| yield th end else tw.all_waits end end # # Creates a ThreadsWait object, specifying the threads to wait on. # Non-blocking. # def initialize(*threads) @threads = [] @wait_queue = Queue.new join_nowait(*threads) unless threads.empty? end # Returns the array of threads that have not terminated yet. attr_reader :threads # # Returns +true+ if there are no threads in the pool still running. # def empty? @threads.empty? end # # Returns +true+ if any thread has terminated and is ready to be collected. # def finished? !@wait_queue.empty? end # # Waits for specified threads to terminate, and returns when one of # the threads terminated. # def join(*threads) join_nowait(*threads) next_wait end # # Specifies the threads that this object will wait for, but does not actually # wait. # def join_nowait(*threads) threads.flatten! @threads.concat threads for th in threads Thread.start(th) do |t| begin t.join ensure @wait_queue.push t end end end end # # Waits until any of the specified threads has terminated, and returns the one # that does. # # If there is no thread to wait, raises +ErrNoWaitingThread+. If +nonblock+ # is true, and there is no terminated thread, raises +ErrNoFinishedThread+. # def next_wait(nonblock = nil) ThreadsWait.fail ErrNoWaitingThread if @threads.empty? begin @threads.delete(th = @wait_queue.pop(nonblock)) th rescue ThreadError ThreadsWait.fail ErrNoFinishedThread end end # # Waits until all of the specified threads are terminated. If a block is # supplied for the method, it is executed for each thread termination. # # Raises exceptions in the same manner as +next_wait+. # def all_waits until @threads.empty? th = next_wait yield th if block_given? end end end ## # An alias for ThreadsWait from thwait.rb ThWait = ThreadsWait # Documentation comments: # - Source of documentation is evenly split between Nutshell, existing # comments, and my own rephrasing. # - I'm not particularly confident that the comments are all exactly correct. PK!;թ 2.2.0/weakref.rbnu[require "delegate" # Weak Reference class that allows a referenced object to be # garbage-collected. # # A WeakRef may be used exactly like the object it references. # # Usage: # # foo = Object.new # create a new object instance # p foo.to_s # original's class # foo = WeakRef.new(foo) # reassign foo with WeakRef instance # p foo.to_s # should be same class # GC.start # start the garbage collector # p foo.to_s # should raise exception (recycled) # # == Example # # With help from WeakRef, we can implement our own rudimentary WeakHash class. # # We will call it WeakHash, since it's really just a Hash except all of it's # keys and values can be garbage collected. # # require 'weakref' # # class WeakHash < Hash # def []= key, obj # super WeakRef.new(key), WeakRef.new(obj) # end # end # # This is just a simple implementation, we've opened the Hash class and changed # Hash#store to create a new WeakRef object with +key+ and +obj+ parameters # before passing them as our key-value pair to the hash. # # With this you will have to limit your self to String keys, otherwise you # will get an ArgumentError because WeakRef cannot create a finalizer for a # Symbol. Symbols are immutable and cannot be garbage collected. # # Let's see it in action: # # omg = "lol" # c = WeakHash.new # c['foo'] = "bar" # c['baz'] = Object.new # c['qux'] = omg # puts c.inspect # #=> {"foo"=>"bar", "baz"=>#, "qux"=>"lol"} # # # Now run the garbage collector # GC.start # c['foo'] #=> nil # c['baz'] #=> nil # c['qux'] #=> nil # omg #=> "lol" # # puts c.inspect # #=> WeakRef::RefError: Invalid Reference - probably recycled # # You can see the local variable +omg+ stayed, although its reference in our # hash object was garbage collected, along with the rest of the keys and # values. Also, when we tried to inspect our hash, we got a WeakRef::RefError. # This is because these objects were also garbage collected. class WeakRef < Delegator ## # RefError is raised when a referenced object has been recycled by the # garbage collector class RefError < StandardError end @@__map = ::ObjectSpace::WeakMap.new ## # Creates a weak reference to +orig+ # # Raises an ArgumentError if the given +orig+ is immutable, such as Symbol, # Fixnum, or Float. def initialize(orig) case orig when true, false, nil @delegate_sd_obj = orig else @@__map[self] = orig end super end def __getobj__ # :nodoc: @@__map[self] or defined?(@delegate_sd_obj) ? @delegate_sd_obj : Kernel::raise(RefError, "Invalid Reference - probably recycled", Kernel::caller(2)) end def __setobj__(obj) # :nodoc: end ## # Returns true if the referenced object is still alive. def weakref_alive? @@__map.key?(self) or defined?(@delegate_sd_obj) end end PK!6˺''2.2.0/openssl/ssl.rbnu[=begin = $RCSfile$ -- Ruby-space definitions that completes C-space funcs for SSL = Info 'OpenSSL for Ruby 2' project Copyright (C) 2001 GOTOU YUUZOU All rights reserved. = Licence This program is licenced under the same licence as Ruby. (See the file 'LICENCE'.) = Version $Id: ssl.rb 51554 2015-08-12 15:16:42Z nagachika $ =end require "openssl/buffering" require "fcntl" module OpenSSL module SSL class SSLContext DEFAULT_PARAMS = { :ssl_version => "SSLv23", :verify_mode => OpenSSL::SSL::VERIFY_PEER, :ciphers => %w{ ECDHE-ECDSA-AES128-GCM-SHA256 ECDHE-RSA-AES128-GCM-SHA256 ECDHE-ECDSA-AES256-GCM-SHA384 ECDHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES128-GCM-SHA256 DHE-DSS-AES128-GCM-SHA256 DHE-RSA-AES256-GCM-SHA384 DHE-DSS-AES256-GCM-SHA384 ECDHE-ECDSA-AES128-SHA256 ECDHE-RSA-AES128-SHA256 ECDHE-ECDSA-AES128-SHA ECDHE-RSA-AES128-SHA ECDHE-ECDSA-AES256-SHA384 ECDHE-RSA-AES256-SHA384 ECDHE-ECDSA-AES256-SHA ECDHE-RSA-AES256-SHA DHE-RSA-AES128-SHA256 DHE-RSA-AES256-SHA256 DHE-RSA-AES128-SHA DHE-RSA-AES256-SHA DHE-DSS-AES128-SHA256 DHE-DSS-AES256-SHA256 DHE-DSS-AES128-SHA DHE-DSS-AES256-SHA AES128-GCM-SHA256 AES256-GCM-SHA384 AES128-SHA256 AES256-SHA256 AES128-SHA AES256-SHA ECDHE-ECDSA-RC4-SHA ECDHE-RSA-RC4-SHA RC4-SHA }.join(":"), :options => -> { opts = OpenSSL::SSL::OP_ALL opts &= ~OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS if defined?(OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS) opts |= OpenSSL::SSL::OP_NO_COMPRESSION if defined?(OpenSSL::SSL::OP_NO_COMPRESSION) opts |= OpenSSL::SSL::OP_NO_SSLv2 if defined?(OpenSSL::SSL::OP_NO_SSLv2) opts |= OpenSSL::SSL::OP_NO_SSLv3 if defined?(OpenSSL::SSL::OP_NO_SSLv3) opts }.call } DEFAULT_CERT_STORE = OpenSSL::X509::Store.new DEFAULT_CERT_STORE.set_default_paths if defined?(OpenSSL::X509::V_FLAG_CRL_CHECK_ALL) DEFAULT_CERT_STORE.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL end ## # Sets the parameters for this SSL context to the values in +params+. # The keys in +params+ must be assignment methods on SSLContext. # # If the verify_mode is not VERIFY_NONE and ca_file, ca_path and # cert_store are not set then the system default certificate store is # used. def set_params(params={}) params = DEFAULT_PARAMS.merge(params) params.each{|name, value| self.__send__("#{name}=", value) } if self.verify_mode != OpenSSL::SSL::VERIFY_NONE unless self.ca_file or self.ca_path or self.cert_store self.cert_store = DEFAULT_CERT_STORE end end return params end end module SocketForwarder def addr to_io.addr end def peeraddr to_io.peeraddr end def setsockopt(level, optname, optval) to_io.setsockopt(level, optname, optval) end def getsockopt(level, optname) to_io.getsockopt(level, optname) end def fcntl(*args) to_io.fcntl(*args) end def closed? to_io.closed? end def do_not_reverse_lookup=(flag) to_io.do_not_reverse_lookup = flag end end module Nonblock def initialize(*args) flag = File::NONBLOCK flag |= @io.fcntl(Fcntl::F_GETFL) if defined?(Fcntl::F_GETFL) @io.fcntl(Fcntl::F_SETFL, flag) super end end def verify_certificate_identity(cert, hostname) should_verify_common_name = true cert.extensions.each{|ext| next if ext.oid != "subjectAltName" ostr = OpenSSL::ASN1.decode(ext.to_der).value.last sequence = OpenSSL::ASN1.decode(ostr.value) sequence.value.each{|san| case san.tag when 2 # dNSName in GeneralName (RFC5280) should_verify_common_name = false return true if verify_hostname(hostname, san.value) when 7 # iPAddress in GeneralName (RFC5280) should_verify_common_name = false # follows GENERAL_NAME_print() in x509v3/v3_alt.c if san.value.size == 4 return true if san.value.unpack('C*').join('.') == hostname elsif san.value.size == 16 return true if san.value.unpack('n*').map { |e| sprintf("%X", e) }.join(':') == hostname end end } } if should_verify_common_name cert.subject.to_a.each{|oid, value| if oid == "CN" return true if verify_hostname(hostname, value) end } end return false end module_function :verify_certificate_identity def verify_hostname(hostname, san) # :nodoc: # RFC 5280, IA5String is limited to the set of ASCII characters return false unless san.ascii_only? return false unless hostname.ascii_only? # See RFC 6125, section 6.4.1 # Matching is case-insensitive. san_parts = san.downcase.split(".") # TODO: this behavior should probably be more strict return san == hostname if san_parts.size < 2 # Matching is case-insensitive. host_parts = hostname.downcase.split(".") # RFC 6125, section 6.4.3, subitem 2. # If the wildcard character is the only character of the left-most # label in the presented identifier, the client SHOULD NOT compare # against anything but the left-most label of the reference # identifier (e.g., *.example.com would match foo.example.com but # not bar.foo.example.com or example.com). return false unless san_parts.size == host_parts.size # RFC 6125, section 6.4.3, subitem 1. # The client SHOULD NOT attempt to match a presented identifier in # which the wildcard character comprises a label other than the # left-most label (e.g., do not match bar.*.example.net). return false unless verify_wildcard(host_parts.shift, san_parts.shift) san_parts.join(".") == host_parts.join(".") end module_function :verify_hostname def verify_wildcard(domain_component, san_component) # :nodoc: parts = san_component.split("*", -1) return false if parts.size > 2 return san_component == domain_component if parts.size == 1 # RFC 6125, section 6.4.3, subitem 3. # The client SHOULD NOT attempt to match a presented identifier # where the wildcard character is embedded within an A-label or # U-label of an internationalized domain name. return false if domain_component.start_with?("xn--") && san_component != "*" parts[0].length + parts[1].length < domain_component.length && domain_component.start_with?(parts[0]) && domain_component.end_with?(parts[1]) end module_function :verify_wildcard class SSLSocket include Buffering include SocketForwarder include Nonblock ## # Perform hostname verification after an SSL connection is established # # This method MUST be called after calling #connect to ensure that the # hostname of a remote peer has been verified. def post_connection_check(hostname) if peer_cert.nil? msg = "Peer verification enabled, but no certificate received." if using_anon_cipher? msg += " Anonymous cipher suite #{cipher[0]} was negotiated. Anonymous suites must be disabled to use peer verification." end raise SSLError, msg end unless OpenSSL::SSL.verify_certificate_identity(peer_cert, hostname) raise SSLError, "hostname \"#{hostname}\" does not match the server certificate" end return true end def session SSL::Session.new(self) rescue SSL::Session::SessionError nil end private def using_anon_cipher? ctx = OpenSSL::SSL::SSLContext.new ctx.ciphers = "aNULL" ctx.ciphers.include?(cipher) end end ## # SSLServer represents a TCP/IP server socket with Secure Sockets Layer. class SSLServer include SocketForwarder # When true then #accept works exactly the same as TCPServer#accept attr_accessor :start_immediately # Creates a new instance of SSLServer. # * +srv+ is an instance of TCPServer. # * +ctx+ is an instance of OpenSSL::SSL::SSLContext. def initialize(svr, ctx) @svr = svr @ctx = ctx unless ctx.session_id_context # see #6137 - session id may not exceed 32 bytes prng = ::Random.new($0.hash) session_id = prng.bytes(16).unpack('H*')[0] @ctx.session_id_context = session_id end @start_immediately = true end # Returns the TCPServer passed to the SSLServer when initialized. def to_io @svr end # See TCPServer#listen for details. def listen(backlog=5) @svr.listen(backlog) end # See BasicSocket#shutdown for details. def shutdown(how=Socket::SHUT_RDWR) @svr.shutdown(how) end # Works similar to TCPServer#accept. def accept # Socket#accept returns [socket, addrinfo]. # TCPServer#accept returns a socket. # The following comma strips addrinfo. sock, = @svr.accept begin ssl = OpenSSL::SSL::SSLSocket.new(sock, @ctx) ssl.sync_close = true ssl.accept if @start_immediately ssl rescue Exception => ex if ssl ssl.close else sock.close end raise ex end end # See IO#close for details. def close @svr.close end end end end PK!s~2.2.0/openssl/digest.rbnu[#-- # # $RCSfile$ # # = Ruby-space predefined Digest subclasses # # = Info # 'OpenSSL for Ruby 2' project # Copyright (C) 2002 Michal Rokos # All rights reserved. # # = Licence # This program is licenced under the same licence as Ruby. # (See the file 'LICENCE'.) # # = Version # $Id: digest.rb 44116 2013-12-10 07:16:03Z nobu $ # #++ module OpenSSL class Digest alg = %w(DSS DSS1 MD2 MD4 MD5 MDC2 RIPEMD160 SHA SHA1) if OPENSSL_VERSION_NUMBER > 0x00908000 alg += %w(SHA224 SHA256 SHA384 SHA512) end # Return the +data+ hash computed with +name+ Digest. +name+ is either the # long name or short name of a supported digest algorithm. # # === Examples # # OpenSSL::Digest.digest("SHA256", "abc") # # which is equivalent to: # # OpenSSL::Digest::SHA256.digest("abc") def self.digest(name, data) super(data, name) end alg.each{|name| klass = Class.new(self) { define_method(:initialize, ->(data = nil) {super(name, data)}) } singleton = (class << klass; self; end) singleton.class_eval{ define_method(:digest){|data| new.digest(data) } define_method(:hexdigest){|data| new.hexdigest(data) } } const_set(name, klass) } # Deprecated. # # This class is only provided for backwards compatibility. class Digest < Digest # :nodoc: # Deprecated. # # See OpenSSL::Digest.new def initialize(*args) warn('Digest::Digest is deprecated; use Digest') super(*args) end end end # Digest # Returns a Digest subclass by +name+. # # require 'openssl' # # OpenSSL::Digest("MD5") # # => OpenSSL::Digest::MD5 # # Digest("Foo") # # => NameError: wrong constant name Foo def Digest(name) OpenSSL::Digest.const_get(name) end module_function :Digest end # OpenSSL PK!QQ2.2.0/openssl/cipher.rbnu[#-- # # $RCSfile$ # # = Ruby-space predefined Cipher subclasses # # = Info # 'OpenSSL for Ruby 2' project # Copyright (C) 2002 Michal Rokos # All rights reserved. # # = Licence # This program is licenced under the same licence as Ruby. # (See the file 'LICENCE'.) # # = Version # $Id: cipher.rb 36895 2012-09-04 00:57:31Z nobu $ # #++ module OpenSSL class Cipher %w(AES CAST5 BF DES IDEA RC2 RC4 RC5).each{|name| klass = Class.new(Cipher){ define_method(:initialize){|*args| cipher_name = args.inject(name){|n, arg| "#{n}-#{arg}" } super(cipher_name) } } const_set(name, klass) } %w(128 192 256).each{|keylen| klass = Class.new(Cipher){ define_method(:initialize){|mode| mode ||= "CBC" cipher_name = "AES-#{keylen}-#{mode}" super(cipher_name) } } const_set("AES#{keylen}", klass) } # Generate, set, and return a random key. # You must call cipher.encrypt or cipher.decrypt before calling this method. def random_key str = OpenSSL::Random.random_bytes(self.key_len) self.key = str return str end # Generate, set, and return a random iv. # You must call cipher.encrypt or cipher.decrypt before calling this method. def random_iv str = OpenSSL::Random.random_bytes(self.iv_len) self.iv = str return str end # This class is only provided for backwards compatibility. Use OpenSSL::Cipher in the future. class Cipher < Cipher # add warning end end # Cipher end # OpenSSL PK!ޢ==2.2.0/openssl/x509.rbnu[#-- # # $RCSfile$ # # = Ruby-space definitions that completes C-space funcs for X509 and subclasses # # = Info # 'OpenSSL for Ruby 2' project # Copyright (C) 2002 Michal Rokos # All rights reserved. # # = Licence # This program is licenced under the same licence as Ruby. # (See the file 'LICENCE'.) # # = Version # $Id: x509.rb 48521 2014-11-20 15:39:03Z usa $ # #++ module OpenSSL module X509 class ExtensionFactory def create_extension(*arg) if arg.size > 1 create_ext(*arg) else send("create_ext_from_"+arg[0].class.name.downcase, arg[0]) end end def create_ext_from_array(ary) raise ExtensionError, "unexpected array form" if ary.size > 3 create_ext(ary[0], ary[1], ary[2]) end def create_ext_from_string(str) # "oid = critical, value" oid, value = str.split(/=/, 2) oid.strip! value.strip! create_ext(oid, value) end def create_ext_from_hash(hash) create_ext(hash["oid"], hash["value"], hash["critical"]) end end class Extension def to_s # "oid = critical, value" str = self.oid str << " = " str << "critical, " if self.critical? str << self.value.gsub(/\n/, ", ") end def to_h # {"oid"=>sn|ln, "value"=>value, "critical"=>true|false} {"oid"=>self.oid,"value"=>self.value,"critical"=>self.critical?} end def to_a [ self.oid, self.value, self.critical? ] end end class Name module RFC2253DN Special = ',=+<>#;' HexChar = /[0-9a-fA-F]/ HexPair = /#{HexChar}#{HexChar}/ HexString = /#{HexPair}+/ Pair = /\\(?:[#{Special}]|\\|"|#{HexPair})/ StringChar = /[^\\"#{Special}]/ QuoteChar = /[^\\"]/ AttributeType = /[a-zA-Z][0-9a-zA-Z]*|[0-9]+(?:\.[0-9]+)*/ AttributeValue = / (?!["#])((?:#{StringChar}|#{Pair})*)| \#(#{HexString})| "((?:#{QuoteChar}|#{Pair})*)" /x TypeAndValue = /\A(#{AttributeType})=#{AttributeValue}/ module_function def expand_pair(str) return nil unless str return str.gsub(Pair){ pair = $& case pair.size when 2 then pair[1,1] when 3 then Integer("0x#{pair[1,2]}").chr else raise OpenSSL::X509::NameError, "invalid pair: #{str}" end } end def expand_hexstring(str) return nil unless str der = str.gsub(HexPair){$&.to_i(16).chr } a1 = OpenSSL::ASN1.decode(der) return a1.value, a1.tag end def expand_value(str1, str2, str3) value = expand_pair(str1) value, tag = expand_hexstring(str2) unless value value = expand_pair(str3) unless value return value, tag end def scan(dn) str = dn ary = [] while true if md = TypeAndValue.match(str) remain = md.post_match type = md[1] value, tag = expand_value(md[2], md[3], md[4]) rescue nil if value type_and_value = [type, value] type_and_value.push(tag) if tag ary.unshift(type_and_value) if remain.length > 2 && remain[0] == ?, str = remain[1..-1] next elsif remain.length > 2 && remain[0] == ?+ raise OpenSSL::X509::NameError, "multi-valued RDN is not supported: #{dn}" elsif remain.empty? break end end end msg_dn = dn[0, dn.length - str.length] + " =>" + str raise OpenSSL::X509::NameError, "malformed RDN: #{msg_dn}" end return ary end end class << self def parse_rfc2253(str, template=OBJECT_TYPE_TEMPLATE) ary = OpenSSL::X509::Name::RFC2253DN.scan(str) self.new(ary, template) end def parse_openssl(str, template=OBJECT_TYPE_TEMPLATE) ary = str.scan(/\s*([^\/,]+)\s*/).collect{|i| i[0].split("=", 2) } self.new(ary, template) end alias parse parse_openssl end def pretty_print(q) q.object_group(self) { q.text ' ' q.text to_s(OpenSSL::X509::Name::RFC2253) } end end class StoreContext def cleanup warn "(#{caller.first}) OpenSSL::X509::StoreContext#cleanup is deprecated with no replacement" if $VERBOSE end end class Certificate def pretty_print(q) q.object_group(self) { q.breakable q.text 'subject='; q.pp self.subject; q.text ','; q.breakable q.text 'issuer='; q.pp self.issuer; q.text ','; q.breakable q.text 'serial='; q.pp self.serial; q.text ','; q.breakable q.text 'not_before='; q.pp self.not_before; q.text ','; q.breakable q.text 'not_after='; q.pp self.not_after } end end end end PK!H%%2.2.0/openssl/buffering.rbnu[# coding: binary #-- #= $RCSfile$ -- Buffering mix-in module. # #= Info # 'OpenSSL for Ruby 2' project # Copyright (C) 2001 GOTOU YUUZOU # All rights reserved. # #= Licence # This program is licenced under the same licence as Ruby. # (See the file 'LICENCE'.) # #= Version # $Id: buffering.rb 43964 2013-12-03 01:44:41Z drbrain $ #++ ## # OpenSSL IO buffering mix-in module. # # This module allows an OpenSSL::SSL::SSLSocket to behave like an IO. # # You typically won't use this module directly, you can see it implemented in # OpenSSL::SSL::SSLSocket. module OpenSSL::Buffering include Enumerable ## # The "sync mode" of the SSLSocket. # # See IO#sync for full details. attr_accessor :sync ## # Default size to read from or write to the SSLSocket for buffer operations. BLOCK_SIZE = 1024*16 ## # Creates an instance of OpenSSL's buffering IO module. def initialize(*) super @eof = false @rbuffer = "" @sync = @io.sync end # # for reading. # private ## # Fills the buffer from the underlying SSLSocket def fill_rbuff begin @rbuffer << self.sysread(BLOCK_SIZE) rescue Errno::EAGAIN retry rescue EOFError @eof = true end end ## # Consumes +size+ bytes from the buffer def consume_rbuff(size=nil) if @rbuffer.empty? nil else size = @rbuffer.size unless size ret = @rbuffer[0, size] @rbuffer[0, size] = "" ret end end public ## # Reads +size+ bytes from the stream. If +buf+ is provided it must # reference a string which will receive the data. # # See IO#read for full details. def read(size=nil, buf=nil) if size == 0 if buf buf.clear return buf else return "" end end until @eof break if size && size <= @rbuffer.size fill_rbuff end ret = consume_rbuff(size) || "" if buf buf.replace(ret) ret = buf end (size && ret.empty?) ? nil : ret end ## # Reads at most +maxlen+ bytes from the stream. If +buf+ is provided it # must reference a string which will receive the data. # # See IO#readpartial for full details. def readpartial(maxlen, buf=nil) if maxlen == 0 if buf buf.clear return buf else return "" end end if @rbuffer.empty? begin return sysread(maxlen, buf) rescue Errno::EAGAIN retry end end ret = consume_rbuff(maxlen) if buf buf.replace(ret) ret = buf end raise EOFError if ret.empty? ret end ## # Reads at most +maxlen+ bytes in the non-blocking manner. # # When no data can be read without blocking it raises # OpenSSL::SSL::SSLError extended by IO::WaitReadable or IO::WaitWritable. # # IO::WaitReadable means SSL needs to read internally so read_nonblock # should be called again when the underlying IO is readable. # # IO::WaitWritable means SSL needs to write internally so read_nonblock # should be called again after the underlying IO is writable. # # OpenSSL::Buffering#read_nonblock needs two rescue clause as follows: # # # emulates blocking read (readpartial). # begin # result = ssl.read_nonblock(maxlen) # rescue IO::WaitReadable # IO.select([io]) # retry # rescue IO::WaitWritable # IO.select(nil, [io]) # retry # end # # Note that one reason that read_nonblock writes to the underlying IO is # when the peer requests a new TLS/SSL handshake. See openssl the FAQ for # more details. http://www.openssl.org/support/faq.html def read_nonblock(maxlen, buf=nil, exception: true) if maxlen == 0 if buf buf.clear return buf else return "" end end if @rbuffer.empty? return sysread_nonblock(maxlen, buf, exception: exception) end ret = consume_rbuff(maxlen) if buf buf.replace(ret) ret = buf end raise EOFError if ret.empty? ret end ## # Reads the next "line+ from the stream. Lines are separated by +eol+. If # +limit+ is provided the result will not be longer than the given number of # bytes. # # +eol+ may be a String or Regexp. # # Unlike IO#gets the line read will not be assigned to +$_+. # # Unlike IO#gets the separator must be provided if a limit is provided. def gets(eol=$/, limit=nil) idx = @rbuffer.index(eol) until @eof break if idx fill_rbuff idx = @rbuffer.index(eol) end if eol.is_a?(Regexp) size = idx ? idx+$&.size : nil else size = idx ? idx+eol.size : nil end if limit and limit >= 0 size = [size, limit].min end consume_rbuff(size) end ## # Executes the block for every line in the stream where lines are separated # by +eol+. # # See also #gets def each(eol=$/) while line = self.gets(eol) yield line end end alias each_line each ## # Reads lines from the stream which are separated by +eol+. # # See also #gets def readlines(eol=$/) ary = [] while line = self.gets(eol) ary << line end ary end ## # Reads a line from the stream which is separated by +eol+. # # Raises EOFError if at end of file. def readline(eol=$/) raise EOFError if eof? gets(eol) end ## # Reads one character from the stream. Returns nil if called at end of # file. def getc read(1) end ## # Calls the given block once for each byte in the stream. def each_byte # :yields: byte while c = getc yield(c.ord) end end ## # Reads a one-character string from the stream. Raises an EOFError at end # of file. def readchar raise EOFError if eof? getc end ## # Pushes character +c+ back onto the stream such that a subsequent buffered # character read will return it. # # Unlike IO#getc multiple bytes may be pushed back onto the stream. # # Has no effect on unbuffered reads (such as #sysread). def ungetc(c) @rbuffer[0,0] = c.chr end ## # Returns true if the stream is at file which means there is no more data to # be read. def eof? fill_rbuff if !@eof && @rbuffer.empty? @eof && @rbuffer.empty? end alias eof eof? # # for writing. # private ## # Writes +s+ to the buffer. When the buffer is full or #sync is true the # buffer is flushed to the underlying socket. def do_write(s) @wbuffer = "" unless defined? @wbuffer @wbuffer << s @wbuffer.force_encoding(Encoding::BINARY) @sync ||= false if @sync or @wbuffer.size > BLOCK_SIZE or idx = @wbuffer.rindex($/) remain = idx ? idx + $/.size : @wbuffer.length nwritten = 0 while remain > 0 str = @wbuffer[nwritten,remain] begin nwrote = syswrite(str) rescue Errno::EAGAIN retry end remain -= nwrote nwritten += nwrote end @wbuffer[0,nwritten] = "" end end public ## # Writes +s+ to the stream. If the argument is not a string it will be # converted using String#to_s. Returns the number of bytes written. def write(s) do_write(s) s.bytesize end ## # Writes +str+ in the non-blocking manner. # # If there is buffered data, it is flushed first. This may block. # # write_nonblock returns number of bytes written to the SSL connection. # # When no data can be written without blocking it raises # OpenSSL::SSL::SSLError extended by IO::WaitReadable or IO::WaitWritable. # # IO::WaitReadable means SSL needs to read internally so write_nonblock # should be called again after the underlying IO is readable. # # IO::WaitWritable means SSL needs to write internally so write_nonblock # should be called again after underlying IO is writable. # # So OpenSSL::Buffering#write_nonblock needs two rescue clause as follows. # # # emulates blocking write. # begin # result = ssl.write_nonblock(str) # rescue IO::WaitReadable # IO.select([io]) # retry # rescue IO::WaitWritable # IO.select(nil, [io]) # retry # end # # Note that one reason that write_nonblock reads from the underlying IO # is when the peer requests a new TLS/SSL handshake. See the openssl FAQ # for more details. http://www.openssl.org/support/faq.html def write_nonblock(s, exception: true) flush syswrite_nonblock(s, exception: exception) end ## # Writes +s+ to the stream. +s+ will be converted to a String using # String#to_s. def << (s) do_write(s) self end ## # Writes +args+ to the stream along with a record separator. # # See IO#puts for full details. def puts(*args) s = "" if args.empty? s << "\n" end args.each{|arg| s << arg.to_s if $/ && /\n\z/ !~ s s << "\n" end } do_write(s) nil end ## # Writes +args+ to the stream. # # See IO#print for full details. def print(*args) s = "" args.each{ |arg| s << arg.to_s } do_write(s) nil end ## # Formats and writes to the stream converting parameters under control of # the format string. # # See Kernel#sprintf for format string details. def printf(s, *args) do_write(s % args) nil end ## # Flushes buffered data to the SSLSocket. def flush osync = @sync @sync = true do_write "" return self ensure @sync = osync end ## # Closes the SSLSocket and flushes any unwritten data. def close flush rescue nil sysclose end end PK!//2.2.0/openssl/config.rbnu[=begin = Ruby-space definitions that completes C-space funcs for Config = Info Copyright (C) 2010 Hiroshi Nakamura = Licence This program is licenced under the same licence as Ruby. (See the file 'LICENCE'.) =end require 'stringio' module OpenSSL ## # = OpenSSL::Config # # Configuration for the openssl library. # # Many system's installation of openssl library will depend on your system # configuration. See the value of OpenSSL::Config::DEFAULT_CONFIG_FILE for # the location of the file for your host. # # See also http://www.openssl.org/docs/apps/config.html class Config include Enumerable class << self ## # Parses a given +string+ as a blob that contains configuration for openssl. # # If the source of the IO is a file, then consider using #parse_config. def parse(string) c = new() parse_config(StringIO.new(string)).each do |section, hash| c[section] = hash end c end ## # load is an alias to ::new alias load new ## # Parses the configuration data read from +io+, see also #parse. # # Raises a ConfigError on invalid configuration data. def parse_config(io) begin parse_config_lines(io) rescue ConfigError => e e.message.replace("error in line #{io.lineno}: " + e.message) raise end end def get_key_string(data, section, key) # :nodoc: if v = data[section] && data[section][key] return v elsif section == 'ENV' if v = ENV[key] return v end end if v = data['default'] && data['default'][key] return v end end private def parse_config_lines(io) section = 'default' data = {section => {}} while definition = get_definition(io) definition = clear_comments(definition) next if definition.empty? if definition[0] == ?[ if /\[([^\]]*)\]/ =~ definition section = $1.strip data[section] ||= {} else raise ConfigError, "missing close square bracket" end else if /\A([^:\s]*)(?:::([^:\s]*))?\s*=(.*)\z/ =~ definition if $2 section = $1 key = $2 else key = $1 end value = unescape_value(data, section, $3) (data[section] ||= {})[key] = value.strip else raise ConfigError, "missing equal sign" end end end data end # escape with backslash QUOTE_REGEXP_SQ = /\A([^'\\]*(?:\\.[^'\\]*)*)'/ # escape with backslash and doubled dq QUOTE_REGEXP_DQ = /\A([^"\\]*(?:""[^"\\]*|\\.[^"\\]*)*)"/ # escaped char map ESCAPE_MAP = { "r" => "\r", "n" => "\n", "b" => "\b", "t" => "\t", } def unescape_value(data, section, value) scanned = [] while m = value.match(/['"\\$]/) scanned << m.pre_match c = m[0] value = m.post_match case c when "'" if m = value.match(QUOTE_REGEXP_SQ) scanned << m[1].gsub(/\\(.)/, '\\1') value = m.post_match else break end when '"' if m = value.match(QUOTE_REGEXP_DQ) scanned << m[1].gsub(/""/, '').gsub(/\\(.)/, '\\1') value = m.post_match else break end when "\\" c = value.slice!(0, 1) scanned << (ESCAPE_MAP[c] || c) when "$" ref, value = extract_reference(value) refsec = section if ref.index('::') refsec, ref = ref.split('::', 2) end if v = get_key_string(data, refsec, ref) scanned << v else raise ConfigError, "variable has no value" end else raise 'must not reaced' end end scanned << value scanned.join end def extract_reference(value) rest = '' if m = value.match(/\(([^)]*)\)|\{([^}]*)\}/) value = m[1] || m[2] rest = m.post_match elsif [?(, ?{].include?(value[0]) raise ConfigError, "no close brace" end if m = value.match(/[a-zA-Z0-9_]*(?:::[a-zA-Z0-9_]*)?/) return m[0], m.post_match + rest else raise end end def clear_comments(line) # FCOMMENT if m = line.match(/\A([\t\n\f ]*);.*\z/) return m[1] end # COMMENT scanned = [] while m = line.match(/[#'"\\]/) scanned << m.pre_match c = m[0] line = m.post_match case c when '#' line = nil break when "'", '"' regexp = (c == "'") ? QUOTE_REGEXP_SQ : QUOTE_REGEXP_DQ scanned << c if m = line.match(regexp) scanned << m[0] line = m.post_match else scanned << line line = nil break end when "\\" scanned << c scanned << line.slice!(0, 1) else raise 'must not reaced' end end scanned << line scanned.join end def get_definition(io) if line = get_line(io) while /[^\\]\\\z/ =~ line if extra = get_line(io) line += extra else break end end return line.strip end end def get_line(io) if line = io.gets line.gsub(/[\r\n]*/, '') end end end ## # Creates an instance of OpenSSL's configuration class. # # This can be used in contexts like OpenSSL::X509::ExtensionFactory.config= # # If the optional +filename+ parameter is provided, then it is read in and # parsed via #parse_config. # # This can raise IO exceptions based on the access, or availability of the # file. A ConfigError exception may be raised depending on the validity of # the data being configured. # def initialize(filename = nil) @data = {} if filename File.open(filename.to_s) do |file| Config.parse_config(file).each do |section, hash| self[section] = hash end end end end ## # Gets the value of +key+ from the given +section+ # # Given the following configurating file being loaded: # # config = OpenSSL::Config.load('foo.cnf') # #=> # # puts config.to_s # #=> [ default ] # # foo=bar # # You can get a specific value from the config if you know the +section+ # and +key+ like so: # # config.get_value('default','foo') # #=> "bar" # def get_value(section, key) if section.nil? raise TypeError.new('nil not allowed') end section = 'default' if section.empty? get_key_string(section, key) end ## # # *Deprecated* # # Use #get_value instead def value(arg1, arg2 = nil) # :nodoc: warn('Config#value is deprecated; use Config#get_value') if arg2.nil? section, key = 'default', arg1 else section, key = arg1, arg2 end section ||= 'default' section = 'default' if section.empty? get_key_string(section, key) end ## # Set the target +key+ with a given +value+ under a specific +section+. # # Given the following configurating file being loaded: # # config = OpenSSL::Config.load('foo.cnf') # #=> # # puts config.to_s # #=> [ default ] # # foo=bar # # You can set the value of +foo+ under the +default+ section to a new # value: # # config.add_value('default', 'foo', 'buzz') # #=> "buzz" # puts config.to_s # #=> [ default ] # # foo=buzz # def add_value(section, key, value) check_modify (@data[section] ||= {})[key] = value end ## # Get a specific +section+ from the current configuration # # Given the following configurating file being loaded: # # config = OpenSSL::Config.load('foo.cnf') # #=> # # puts config.to_s # #=> [ default ] # # foo=bar # # You can get a hash of the specific section like so: # # config['default'] # #=> {"foo"=>"bar"} # def [](section) @data[section] || {} end ## # Deprecated # # Use #[] instead def section(name) # :nodoc: warn('Config#section is deprecated; use Config#[]') @data[name] || {} end ## # Sets a specific +section+ name with a Hash +pairs+ # # Given the following configuration being created: # # config = OpenSSL::Config.new # #=> # # config['default'] = {"foo"=>"bar","baz"=>"buz"} # #=> {"foo"=>"bar", "baz"=>"buz"} # puts config.to_s # #=> [ default ] # # foo=bar # # baz=buz # # It's important to note that this will essentially merge any of the keys # in +pairs+ with the existing +section+. For example: # # config['default'] # #=> {"foo"=>"bar", "baz"=>"buz"} # config['default'] = {"foo" => "changed"} # #=> {"foo"=>"changed"} # config['default'] # #=> {"foo"=>"changed", "baz"=>"buz"} # def []=(section, pairs) check_modify @data[section] ||= {} pairs.each do |key, value| self.add_value(section, key, value) end end ## # Get the names of all sections in the current configuration def sections @data.keys end ## # Get the parsable form of the current configuration # # Given the following configuration being created: # # config = OpenSSL::Config.new # #=> # # config['default'] = {"foo"=>"bar","baz"=>"buz"} # #=> {"foo"=>"bar", "baz"=>"buz"} # puts config.to_s # #=> [ default ] # # foo=bar # # baz=buz # # You can parse get the serialized configuration using #to_s and then parse # it later: # # serialized_config = config.to_s # # much later... # new_config = OpenSSL::Config.parse(serialized_config) # #=> # # puts new_config # #=> [ default ] # foo=bar # baz=buz # def to_s ary = [] @data.keys.sort.each do |section| ary << "[ #{section} ]\n" @data[section].keys.each do |key| ary << "#{key}=#{@data[section][key]}\n" end ary << "\n" end ary.join end ## # For a block. # # Receive the section and its pairs for the current configuration. # # config.each do |section, key, value| # # ... # end # def each @data.each do |section, hash| hash.each do |key, value| yield [section, key, value] end end end ## # String representation of this configuration object, including the class # name and its sections. def inspect "#<#{self.class.name} sections=#{sections.inspect}>" end protected def data # :nodoc: @data end private def initialize_copy(other) @data = other.data.dup end def check_modify raise TypeError.new("Insecure: can't modify OpenSSL config") if frozen? end def get_key_string(section, key) Config.get_key_string(@data, section, key) end end end PK!2.2.0/openssl/bn.rbnu[#-- # # $RCSfile$ # # = Ruby-space definitions that completes C-space funcs for BN # # = Info # 'OpenSSL for Ruby 2' project # Copyright (C) 2002 Michal Rokos # All rights reserved. # # = Licence # This program is licenced under the same licence as Ruby. # (See the file 'LICENCE'.) # # = Version # $Id: bn.rb 47647 2014-09-20 01:17:05Z akr $ # #++ module OpenSSL class BN include Comparable def pretty_print(q) q.object_group(self) { q.text ' ' q.text to_i.to_s } end end # BN end # OpenSSL ## # Add double dispatch to Integer # class Integer # Casts an Integer as an OpenSSL::BN # # See `man bn` for more info. def to_bn OpenSSL::BN::new(self) end end # Integer PK!Ho] ] 2.2.0/rss.rbnu[## # = RSS reading and writing # # Really Simple Syndication (RSS) is a family of formats that describe 'feeds,' # specially constructed XML documents that allow an interested person to # subscribe and receive updates from a particular web service. This portion of # the standard library provides tooling to read and create these feeds. # # The standard library supports RSS 0.91, 1.0, 2.0, and Atom, a related format. # Here are some links to the standards documents for these formats: # # * RSS # * 0.9.1[http://www.rssboard.org/rss-0-9-1-netscape] # * 1.0[http://web.resource.org/rss/1.0/] # * 2.0[http://www.rssboard.org/rss-specification] # * Atom[http://tools.ietf.org/html/rfc4287] # # == Consuming RSS # # If you'd like to read someone's RSS feed with your Ruby code, you've come to # the right place. It's really easy to do this, but we'll need the help of # open-uri: # # require 'rss' # require 'open-uri' # # url = 'http://www.ruby-lang.org/en/feeds/news.rss' # open(url) do |rss| # feed = RSS::Parser.parse(rss) # puts "Title: #{feed.channel.title}" # feed.items.each do |item| # puts "Item: #{item.title}" # end # end # # As you can see, the workhorse is RSS::Parser#parse, which takes the source of # the feed and a parameter that performs validation on the feed. We get back an # object that has all of the data from our feed, accessible through methods. # This example shows getting the title out of the channel element, and looping # through the list of items. # # == Producing RSS # # Producing our own RSS feeds is easy as well. Let's make a very basic feed: # # require "rss" # # rss = RSS::Maker.make("atom") do |maker| # maker.channel.author = "matz" # maker.channel.updated = Time.now.to_s # maker.channel.about = "http://www.ruby-lang.org/en/feeds/news.rss" # maker.channel.title = "Example Feed" # # maker.items.new_item do |item| # item.link = "http://www.ruby-lang.org/en/news/2010/12/25/ruby-1-9-2-p136-is-released/" # item.title = "Ruby 1.9.2-p136 is released" # item.updated = Time.now.to_s # end # end # # puts rss # # As you can see, this is a very Builder-like DSL. This code will spit out an # Atom feed with one item. If we needed a second item, we'd make another block # with maker.items.new_item and build a second one. # # == Copyright # # Copyright (c) 2003-2007 Kouhei Sutou # # You can redistribute it and/or modify it under the same terms as Ruby. # # There is an additional tutorial by the author of RSS at: # http://www.cozmixng.org/~rwiki/?cmd=view;name=RSS+Parser%3A%3ATutorial.en module RSS end require 'rss/1.0' require 'rss/2.0' require 'rss/atom' require 'rss/content' require 'rss/dublincore' require 'rss/image' require 'rss/itunes' require 'rss/slash' require 'rss/syndication' require 'rss/taxonomy' require 'rss/trackback' require "rss/maker" PK!?d2.2.0/timeout.rbnu[# Timeout long-running blocks # # == Synopsis # # require 'timeout' # status = Timeout::timeout(5) { # # Something that should be interrupted if it takes more than 5 seconds... # } # # == Description # # Timeout provides a way to auto-terminate a potentially long-running # operation if it hasn't finished in a fixed amount of time. # # Previous versions didn't use a module for namespacing, however # #timeout is provided for backwards compatibility. You # should prefer Timeout#timeout instead. # # == Copyright # # Copyright:: (C) 2000 Network Applied Communication Laboratory, Inc. # Copyright:: (C) 2000 Information-technology Promotion Agency, Japan module Timeout # Raised by Timeout#timeout when the block times out. class Error < RuntimeError attr_reader :thread def self.catch(*args) exc = new(*args) exc.instance_variable_set(:@thread, Thread.current) ::Kernel.catch(exc) {yield exc} end def exception(*) # TODO: use Fiber.current to see if self can be thrown if self.thread == Thread.current bt = caller begin throw(self, bt) rescue UncaughtThrowError end end self end end ExitException = Error # :stopdoc: THIS_FILE = /\A#{Regexp.quote(__FILE__)}:/o CALLER_OFFSET = ((c = caller[0]) && THIS_FILE =~ c) ? 1 : 0 # :startdoc: # Perform an operation in a block, raising an error if it takes longer than # +sec+ seconds to complete. # # +sec+:: Number of seconds to wait for the block to terminate. Any number # may be used, including Floats to specify fractional seconds. A # value of 0 or +nil+ will execute the block without any timeout. # +klass+:: Exception Class to raise if the block fails to terminate # in +sec+ seconds. Omitting will use the default, Timeout::Error # # Returns the result of the block *if* the block completed before # +sec+ seconds, otherwise throws an exception, based on the value of +klass+. # # The exception thrown to terminate the given block cannot be rescued inside # the block unless +klass+ is given explicitly. # # Note that this is both a method of module Timeout, so you can include # Timeout into your classes so they have a #timeout method, as well as # a module method, so you can call it directly as Timeout.timeout(). def timeout(sec, klass = nil) #:yield: +sec+ return yield(sec) if sec == nil or sec.zero? message = "execution expired" e = Error bl = proc do |exception| begin x = Thread.current y = Thread.start { begin sleep sec rescue => e x.raise e else x.raise exception, message end } return yield(sec) ensure if y y.kill y.join # make sure y is dead. end end end if klass begin bl.call(klass) rescue klass => e bt = e.backtrace end else bt = Error.catch(message, &bl) end rej = /\A#{Regexp.quote(__FILE__)}:#{__LINE__-4}\z/o bt.reject! {|m| rej =~ m} level = -caller(CALLER_OFFSET).size while THIS_FILE =~ bt[level] bt.delete_at(level) end raise(e, message, bt) end module_function :timeout end # Identical to: # # Timeout::timeout(n, e, &block). # # This method is deprecated and provided only for backwards compatibility. # You should use Timeout#timeout instead. def timeout(n, e = nil, &block) Timeout::timeout(n, e, &block) end # Another name for Timeout::Error, defined for backwards compatibility with # earlier versions of timeout.rb. TimeoutError = Timeout::Error PK!; bfbf2.2.0/socket.rbnu[require 'socket.so' class Addrinfo # creates an Addrinfo object from the arguments. # # The arguments are interpreted as similar to self. # # Addrinfo.tcp("0.0.0.0", 4649).family_addrinfo("www.ruby-lang.org", 80) # #=> # # # Addrinfo.unix("/tmp/sock").family_addrinfo("/tmp/sock2") # #=> # # def family_addrinfo(*args) if args.empty? raise ArgumentError, "no address specified" elsif Addrinfo === args.first raise ArgumentError, "too many arguments" if args.length != 1 addrinfo = args.first if (self.pfamily != addrinfo.pfamily) || (self.socktype != addrinfo.socktype) raise ArgumentError, "Addrinfo type mismatch" end addrinfo elsif self.ip? raise ArgumentError, "IP address needs host and port but #{args.length} arguments given" if args.length != 2 host, port = args Addrinfo.getaddrinfo(host, port, self.pfamily, self.socktype, self.protocol)[0] elsif self.unix? raise ArgumentError, "UNIX socket needs single path argument but #{args.length} arguments given" if args.length != 1 path, = args Addrinfo.unix(path) else raise ArgumentError, "unexpected family" end end # creates a new Socket connected to the address of +local_addrinfo+. # # If _local_addrinfo_ is nil, the address of the socket is not bound. # # The _timeout_ specify the seconds for timeout. # Errno::ETIMEDOUT is raised when timeout occur. # # If a block is given the created socket is yielded for each address. # def connect_internal(local_addrinfo, timeout=nil) # :yields: socket sock = Socket.new(self.pfamily, self.socktype, self.protocol) begin sock.ipv6only! if self.ipv6? sock.bind local_addrinfo if local_addrinfo if timeout begin sock.connect_nonblock(self) rescue IO::WaitWritable if !IO.select(nil, [sock], nil, timeout) raise Errno::ETIMEDOUT, 'user specified timeout' end begin sock.connect_nonblock(self) # check connection failure rescue Errno::EISCONN end end else sock.connect(self) end rescue Exception sock.close raise end if block_given? begin yield sock ensure sock.close if !sock.closed? end else sock end end private :connect_internal # :call-seq: # addrinfo.connect_from([local_addr_args], [opts]) {|socket| ... } # addrinfo.connect_from([local_addr_args], [opts]) # # creates a socket connected to the address of self. # # If one or more arguments given as _local_addr_args_, # it is used as the local address of the socket. # _local_addr_args_ is given for family_addrinfo to obtain actual address. # # If _local_addr_args_ is not given, the local address of the socket is not bound. # # The optional last argument _opts_ is options represented by a hash. # _opts_ may have following options: # # [:timeout] specify the timeout in seconds. # # If a block is given, it is called with the socket and the value of the block is returned. # The socket is returned otherwise. # # Addrinfo.tcp("www.ruby-lang.org", 80).connect_from("0.0.0.0", 4649) {|s| # s.print "GET / HTTP/1.0\r\nHost: www.ruby-lang.org\r\n\r\n" # puts s.read # } # # # Addrinfo object can be taken for the argument. # Addrinfo.tcp("www.ruby-lang.org", 80).connect_from(Addrinfo.tcp("0.0.0.0", 4649)) {|s| # s.print "GET / HTTP/1.0\r\nHost: www.ruby-lang.org\r\n\r\n" # puts s.read # } # def connect_from(*args, &block) opts = Hash === args.last ? args.pop : {} local_addr_args = args connect_internal(family_addrinfo(*local_addr_args), opts[:timeout], &block) end # :call-seq: # addrinfo.connect([opts]) {|socket| ... } # addrinfo.connect([opts]) # # creates a socket connected to the address of self. # # The optional argument _opts_ is options represented by a hash. # _opts_ may have following options: # # [:timeout] specify the timeout in seconds. # # If a block is given, it is called with the socket and the value of the block is returned. # The socket is returned otherwise. # # Addrinfo.tcp("www.ruby-lang.org", 80).connect {|s| # s.print "GET / HTTP/1.0\r\nHost: www.ruby-lang.org\r\n\r\n" # puts s.read # } # def connect(opts={}, &block) connect_internal(nil, opts[:timeout], &block) end # :call-seq: # addrinfo.connect_to([remote_addr_args], [opts]) {|socket| ... } # addrinfo.connect_to([remote_addr_args], [opts]) # # creates a socket connected to _remote_addr_args_ and bound to self. # # The optional last argument _opts_ is options represented by a hash. # _opts_ may have following options: # # [:timeout] specify the timeout in seconds. # # If a block is given, it is called with the socket and the value of the block is returned. # The socket is returned otherwise. # # Addrinfo.tcp("0.0.0.0", 4649).connect_to("www.ruby-lang.org", 80) {|s| # s.print "GET / HTTP/1.0\r\nHost: www.ruby-lang.org\r\n\r\n" # puts s.read # } # def connect_to(*args, &block) opts = Hash === args.last ? args.pop : {} remote_addr_args = args remote_addrinfo = family_addrinfo(*remote_addr_args) remote_addrinfo.send(:connect_internal, self, opts[:timeout], &block) end # creates a socket bound to self. # # If a block is given, it is called with the socket and the value of the block is returned. # The socket is returned otherwise. # # Addrinfo.udp("0.0.0.0", 9981).bind {|s| # s.local_address.connect {|s| s.send "hello", 0 } # p s.recv(10) #=> "hello" # } # def bind sock = Socket.new(self.pfamily, self.socktype, self.protocol) begin sock.ipv6only! if self.ipv6? sock.setsockopt(:SOCKET, :REUSEADDR, 1) sock.bind(self) rescue Exception sock.close raise end if block_given? begin yield sock ensure sock.close if !sock.closed? end else sock end end # creates a listening socket bound to self. def listen(backlog=Socket::SOMAXCONN) sock = Socket.new(self.pfamily, self.socktype, self.protocol) begin sock.ipv6only! if self.ipv6? sock.setsockopt(:SOCKET, :REUSEADDR, 1) sock.bind(self) sock.listen(backlog) rescue Exception sock.close raise end if block_given? begin yield sock ensure sock.close if !sock.closed? end else sock end end # iterates over the list of Addrinfo objects obtained by Addrinfo.getaddrinfo. # # Addrinfo.foreach(nil, 80) {|x| p x } # #=> # # # # # # # # # # # def self.foreach(nodename, service, family=nil, socktype=nil, protocol=nil, flags=nil, &block) Addrinfo.getaddrinfo(nodename, service, family, socktype, protocol, flags).each(&block) end end class BasicSocket < IO # Returns an address of the socket suitable for connect in the local machine. # # This method returns _self_.local_address, except following condition. # # - IPv4 unspecified address (0.0.0.0) is replaced by IPv4 loopback address (127.0.0.1). # - IPv6 unspecified address (::) is replaced by IPv6 loopback address (::1). # # If the local address is not suitable for connect, SocketError is raised. # IPv4 and IPv6 address which port is 0 is not suitable for connect. # Unix domain socket which has no path is not suitable for connect. # # Addrinfo.tcp("0.0.0.0", 0).listen {|serv| # p serv.connect_address #=> # # serv.connect_address.connect {|c| # s, _ = serv.accept # p [c, s] #=> [#, #] # } # } # def connect_address addr = local_address afamily = addr.afamily if afamily == Socket::AF_INET raise SocketError, "unbound IPv4 socket" if addr.ip_port == 0 if addr.ip_address == "0.0.0.0" addr = Addrinfo.new(["AF_INET", addr.ip_port, nil, "127.0.0.1"], addr.pfamily, addr.socktype, addr.protocol) end elsif defined?(Socket::AF_INET6) && afamily == Socket::AF_INET6 raise SocketError, "unbound IPv6 socket" if addr.ip_port == 0 if addr.ip_address == "::" addr = Addrinfo.new(["AF_INET6", addr.ip_port, nil, "::1"], addr.pfamily, addr.socktype, addr.protocol) elsif addr.ip_address == "0.0.0.0" # MacOS X 10.4 returns "a.b.c.d" for IPv4-mapped IPv6 address. addr = Addrinfo.new(["AF_INET6", addr.ip_port, nil, "::1"], addr.pfamily, addr.socktype, addr.protocol) elsif addr.ip_address == "::ffff:0.0.0.0" # MacOS X 10.6 returns "::ffff:a.b.c.d" for IPv4-mapped IPv6 address. addr = Addrinfo.new(["AF_INET6", addr.ip_port, nil, "::1"], addr.pfamily, addr.socktype, addr.protocol) end elsif defined?(Socket::AF_UNIX) && afamily == Socket::AF_UNIX raise SocketError, "unbound Unix socket" if addr.unix_path == "" end addr end end class Socket < BasicSocket # enable the socket option IPV6_V6ONLY if IPV6_V6ONLY is available. def ipv6only! if defined? Socket::IPV6_V6ONLY self.setsockopt(:IPV6, :V6ONLY, 1) end end # :call-seq: # Socket.tcp(host, port, local_host=nil, local_port=nil, [opts]) {|socket| ... } # Socket.tcp(host, port, local_host=nil, local_port=nil, [opts]) # # creates a new socket object connected to host:port using TCP/IP. # # If local_host:local_port is given, # the socket is bound to it. # # The optional last argument _opts_ is options represented by a hash. # _opts_ may have following options: # # [:connect_timeout] specify the timeout in seconds. # # If a block is given, the block is called with the socket. # The value of the block is returned. # The socket is closed when this method returns. # # If no block is given, the socket is returned. # # Socket.tcp("www.ruby-lang.org", 80) {|sock| # sock.print "GET / HTTP/1.0\r\nHost: www.ruby-lang.org\r\n\r\n" # sock.close_write # puts sock.read # } # def self.tcp(host, port, *rest) # :yield: socket opts = Hash === rest.last ? rest.pop : {} raise ArgumentError, "wrong number of arguments (#{rest.length} for 2)" if 2 < rest.length local_host, local_port = rest last_error = nil ret = nil connect_timeout = opts[:connect_timeout] local_addr_list = nil if local_host != nil || local_port != nil local_addr_list = Addrinfo.getaddrinfo(local_host, local_port, nil, :STREAM, nil) end Addrinfo.foreach(host, port, nil, :STREAM) {|ai| if local_addr_list local_addr = local_addr_list.find {|local_ai| local_ai.afamily == ai.afamily } next if !local_addr else local_addr = nil end begin sock = local_addr ? ai.connect_from(local_addr, :timeout => connect_timeout) : ai.connect(:timeout => connect_timeout) rescue SystemCallError last_error = $! next end ret = sock break } if !ret if last_error raise last_error else raise SocketError, "no appropriate local address" end end if block_given? begin yield ret ensure ret.close if !ret.closed? end else ret end end # :stopdoc: def self.ip_sockets_port0(ai_list, reuseaddr) sockets = [] begin sockets.clear port = nil ai_list.each {|ai| begin s = Socket.new(ai.pfamily, ai.socktype, ai.protocol) rescue SystemCallError next end sockets << s s.ipv6only! if ai.ipv6? if reuseaddr s.setsockopt(:SOCKET, :REUSEADDR, 1) end if !port s.bind(ai) port = s.local_address.ip_port else s.bind(ai.family_addrinfo(ai.ip_address, port)) end } rescue Errno::EADDRINUSE sockets.each {|s| s.close } retry rescue Exception sockets.each {|s| s.close } raise end sockets end class << self private :ip_sockets_port0 end def self.tcp_server_sockets_port0(host) ai_list = Addrinfo.getaddrinfo(host, 0, nil, :STREAM, nil, Socket::AI_PASSIVE) sockets = ip_sockets_port0(ai_list, true) begin sockets.each {|s| s.listen(Socket::SOMAXCONN) } rescue Exception sockets.each {|s| s.close } raise end sockets end class << self private :tcp_server_sockets_port0 end # :startdoc: # creates TCP/IP server sockets for _host_ and _port_. # _host_ is optional. # # If no block given, # it returns an array of listening sockets. # # If a block is given, the block is called with the sockets. # The value of the block is returned. # The socket is closed when this method returns. # # If _port_ is 0, actual port number is chosen dynamically. # However all sockets in the result has same port number. # # # tcp_server_sockets returns two sockets. # sockets = Socket.tcp_server_sockets(1296) # p sockets #=> [#, #] # # # The sockets contains IPv6 and IPv4 sockets. # sockets.each {|s| p s.local_address } # #=> # # # # # # # IPv6 and IPv4 socket has same port number, 53114, even if it is chosen dynamically. # sockets = Socket.tcp_server_sockets(0) # sockets.each {|s| p s.local_address } # #=> # # # # # # # The block is called with the sockets. # Socket.tcp_server_sockets(0) {|sockets| # p sockets #=> [#, #] # } # def self.tcp_server_sockets(host=nil, port) if port == 0 sockets = tcp_server_sockets_port0(host) else last_error = nil sockets = [] begin Addrinfo.foreach(host, port, nil, :STREAM, nil, Socket::AI_PASSIVE) {|ai| begin s = ai.listen rescue SystemCallError last_error = $! next end sockets << s } if sockets.empty? raise last_error end rescue Exception sockets.each {|s| s.close } raise end end if block_given? begin yield sockets ensure sockets.each {|s| s.close if !s.closed? } end else sockets end end # yield socket and client address for each a connection accepted via given sockets. # # The arguments are a list of sockets. # The individual argument should be a socket or an array of sockets. # # This method yields the block sequentially. # It means that the next connection is not accepted until the block returns. # So concurrent mechanism, thread for example, should be used to service multiple clients at a time. # def self.accept_loop(*sockets) # :yield: socket, client_addrinfo sockets.flatten!(1) if sockets.empty? raise ArgumentError, "no sockets" end loop { readable, _, _ = IO.select(sockets) readable.each {|r| begin sock, addr = r.accept_nonblock rescue IO::WaitReadable next end yield sock, addr } } end # creates a TCP/IP server on _port_ and calls the block for each connection accepted. # The block is called with a socket and a client_address as an Addrinfo object. # # If _host_ is specified, it is used with _port_ to determine the server addresses. # # The socket is *not* closed when the block returns. # So application should close it explicitly. # # This method calls the block sequentially. # It means that the next connection is not accepted until the block returns. # So concurrent mechanism, thread for example, should be used to service multiple clients at a time. # # Note that Addrinfo.getaddrinfo is used to determine the server socket addresses. # When Addrinfo.getaddrinfo returns two or more addresses, # IPv4 and IPv6 address for example, # all of them are used. # Socket.tcp_server_loop succeeds if one socket can be used at least. # # # Sequential echo server. # # It services only one client at a time. # Socket.tcp_server_loop(16807) {|sock, client_addrinfo| # begin # IO.copy_stream(sock, sock) # ensure # sock.close # end # } # # # Threaded echo server # # It services multiple clients at a time. # # Note that it may accept connections too much. # Socket.tcp_server_loop(16807) {|sock, client_addrinfo| # Thread.new { # begin # IO.copy_stream(sock, sock) # ensure # sock.close # end # } # } # def self.tcp_server_loop(host=nil, port, &b) # :yield: socket, client_addrinfo tcp_server_sockets(host, port) {|sockets| accept_loop(sockets, &b) } end # :call-seq: # Socket.udp_server_sockets([host, ] port) # # Creates UDP/IP sockets for a UDP server. # # If no block given, it returns an array of sockets. # # If a block is given, the block is called with the sockets. # The value of the block is returned. # The sockets are closed when this method returns. # # If _port_ is zero, some port is chosen. # But the chosen port is used for the all sockets. # # # UDP/IP echo server # Socket.udp_server_sockets(0) {|sockets| # p sockets.first.local_address.ip_port #=> 32963 # Socket.udp_server_loop_on(sockets) {|msg, msg_src| # msg_src.reply msg # } # } # def self.udp_server_sockets(host=nil, port) last_error = nil sockets = [] ipv6_recvpktinfo = nil if defined? Socket::AncillaryData if defined? Socket::IPV6_RECVPKTINFO # RFC 3542 ipv6_recvpktinfo = Socket::IPV6_RECVPKTINFO elsif defined? Socket::IPV6_PKTINFO # RFC 2292 ipv6_recvpktinfo = Socket::IPV6_PKTINFO end end local_addrs = Socket.ip_address_list ip_list = [] Addrinfo.foreach(host, port, nil, :DGRAM, nil, Socket::AI_PASSIVE) {|ai| if ai.ipv4? && ai.ip_address == "0.0.0.0" local_addrs.each {|a| next if !a.ipv4? ip_list << Addrinfo.new(a.to_sockaddr, :INET, :DGRAM, 0); } elsif ai.ipv6? && ai.ip_address == "::" && !ipv6_recvpktinfo local_addrs.each {|a| next if !a.ipv6? ip_list << Addrinfo.new(a.to_sockaddr, :INET6, :DGRAM, 0); } else ip_list << ai end } if port == 0 sockets = ip_sockets_port0(ip_list, false) else ip_list.each {|ip| ai = Addrinfo.udp(ip.ip_address, port) begin s = ai.bind rescue SystemCallError last_error = $! next end sockets << s } if sockets.empty? raise last_error end end sockets.each {|s| ai = s.local_address if ipv6_recvpktinfo && ai.ipv6? && ai.ip_address == "::" s.setsockopt(:IPV6, ipv6_recvpktinfo, 1) end } if block_given? begin yield sockets ensure sockets.each {|s| s.close if !s.closed? } if sockets end else sockets end end # :call-seq: # Socket.udp_server_recv(sockets) {|msg, msg_src| ... } # # Receive UDP/IP packets from the given _sockets_. # For each packet received, the block is called. # # The block receives _msg_ and _msg_src_. # _msg_ is a string which is the payload of the received packet. # _msg_src_ is a Socket::UDPSource object which is used for reply. # # Socket.udp_server_loop can be implemented using this method as follows. # # udp_server_sockets(host, port) {|sockets| # loop { # readable, _, _ = IO.select(sockets) # udp_server_recv(readable) {|msg, msg_src| ... } # } # } # def self.udp_server_recv(sockets) sockets.each {|r| begin msg, sender_addrinfo, _, *controls = r.recvmsg_nonblock rescue IO::WaitReadable next end ai = r.local_address if ai.ipv6? and pktinfo = controls.find {|c| c.cmsg_is?(:IPV6, :PKTINFO) } ai = Addrinfo.udp(pktinfo.ipv6_pktinfo_addr.ip_address, ai.ip_port) yield msg, UDPSource.new(sender_addrinfo, ai) {|reply_msg| r.sendmsg reply_msg, 0, sender_addrinfo, pktinfo } else yield msg, UDPSource.new(sender_addrinfo, ai) {|reply_msg| r.send reply_msg, 0, sender_addrinfo } end } end # :call-seq: # Socket.udp_server_loop_on(sockets) {|msg, msg_src| ... } # # Run UDP/IP server loop on the given sockets. # # The return value of Socket.udp_server_sockets is appropriate for the argument. # # It calls the block for each message received. # def self.udp_server_loop_on(sockets, &b) # :yield: msg, msg_src loop { readable, _, _ = IO.select(sockets) udp_server_recv(readable, &b) } end # :call-seq: # Socket.udp_server_loop(port) {|msg, msg_src| ... } # Socket.udp_server_loop(host, port) {|msg, msg_src| ... } # # creates a UDP/IP server on _port_ and calls the block for each message arrived. # The block is called with the message and its source information. # # This method allocates sockets internally using _port_. # If _host_ is specified, it is used conjunction with _port_ to determine the server addresses. # # The _msg_ is a string. # # The _msg_src_ is a Socket::UDPSource object. # It is used for reply. # # # UDP/IP echo server. # Socket.udp_server_loop(9261) {|msg, msg_src| # msg_src.reply msg # } # def self.udp_server_loop(host=nil, port, &b) # :yield: message, message_source udp_server_sockets(host, port) {|sockets| udp_server_loop_on(sockets, &b) } end # UDP/IP address information used by Socket.udp_server_loop. class UDPSource # +remote_address+ is an Addrinfo object. # # +local_address+ is an Addrinfo object. # # +reply_proc+ is a Proc used to send reply back to the source. def initialize(remote_address, local_address, &reply_proc) @remote_address = remote_address @local_address = local_address @reply_proc = reply_proc end # Address of the source attr_reader :remote_address # Local address attr_reader :local_address def inspect # :nodoc: "\#<#{self.class}: #{@remote_address.inspect_sockaddr} to #{@local_address.inspect_sockaddr}>" end # Sends the String +msg+ to the source def reply(msg) @reply_proc.call msg end end # creates a new socket connected to path using UNIX socket socket. # # If a block is given, the block is called with the socket. # The value of the block is returned. # The socket is closed when this method returns. # # If no block is given, the socket is returned. # # # talk to /tmp/sock socket. # Socket.unix("/tmp/sock") {|sock| # t = Thread.new { IO.copy_stream(sock, STDOUT) } # IO.copy_stream(STDIN, sock) # t.join # } # def self.unix(path) # :yield: socket addr = Addrinfo.unix(path) sock = addr.connect if block_given? begin yield sock ensure sock.close if !sock.closed? end else sock end end # creates a UNIX server socket on _path_ # # If no block given, it returns a listening socket. # # If a block is given, it is called with the socket and the block value is returned. # When the block exits, the socket is closed and the socket file is removed. # # socket = Socket.unix_server_socket("/tmp/s") # p socket #=> # # p socket.local_address #=> # # # Socket.unix_server_socket("/tmp/sock") {|s| # p s #=> # # p s.local_address #=> # # # } # def self.unix_server_socket(path) if !unix_socket_abstract_name?(path) begin st = File.lstat(path) rescue Errno::ENOENT end if st && st.socket? && st.owned? File.unlink path end end s = Addrinfo.unix(path).listen if block_given? begin yield s ensure s.close if !s.closed? if !unix_socket_abstract_name?(path) File.unlink path end end else s end end class << self private def unix_socket_abstract_name?(path) /linux/ =~ RUBY_PLATFORM && /\A(\0|\z)/ =~ path end end # creates a UNIX socket server on _path_. # It calls the block for each socket accepted. # # If _host_ is specified, it is used with _port_ to determine the server ports. # # The socket is *not* closed when the block returns. # So application should close it. # # This method deletes the socket file pointed by _path_ at first if # the file is a socket file and it is owned by the user of the application. # This is safe only if the directory of _path_ is not changed by a malicious user. # So don't use /tmp/malicious-users-directory/socket. # Note that /tmp/socket and /tmp/your-private-directory/socket is safe assuming that /tmp has sticky bit. # # # Sequential echo server. # # It services only one client at a time. # Socket.unix_server_loop("/tmp/sock") {|sock, client_addrinfo| # begin # IO.copy_stream(sock, sock) # ensure # sock.close # end # } # def self.unix_server_loop(path, &b) # :yield: socket, client_addrinfo unix_server_socket(path) {|serv| accept_loop(serv, &b) } end end PK!x2.2.0/tmpdir.rbnu[# # tmpdir - retrieve temporary directory path # # $Id: tmpdir.rb 63017 2018-03-28 14:34:14Z usa $ # require 'fileutils' begin require 'etc.so' rescue LoadError # rescue LoadError for miniruby end class Dir @@systmpdir ||= defined?(Etc.systmpdir) ? Etc.systmpdir : '/tmp' ## # Returns the operating system's temporary file path. def self.tmpdir if $SAFE > 0 @@systmpdir else tmp = nil [ENV['TMPDIR'], ENV['TMP'], ENV['TEMP'], @@systmpdir, '/tmp', '.'].each do |dir| next if !dir dir = File.expand_path(dir) if stat = File.stat(dir) and stat.directory? and stat.writable? and (!stat.world_writable? or stat.sticky?) tmp = dir break end rescue nil end raise ArgumentError, "could not find a temporary directory" unless tmp tmp end end # Dir.mktmpdir creates a temporary directory. # # The directory is created with 0700 permission. # Application should not change the permission to make the temporary directory accessible from other users. # # The prefix and suffix of the name of the directory is specified by # the optional first argument, prefix_suffix. # - If it is not specified or nil, "d" is used as the prefix and no suffix is used. # - If it is a string, it is used as the prefix and no suffix is used. # - If it is an array, first element is used as the prefix and second element is used as a suffix. # # Dir.mktmpdir {|dir| dir is ".../d..." } # Dir.mktmpdir("foo") {|dir| dir is ".../foo..." } # Dir.mktmpdir(["foo", "bar"]) {|dir| dir is ".../foo...bar" } # # The directory is created under Dir.tmpdir or # the optional second argument tmpdir if non-nil value is given. # # Dir.mktmpdir {|dir| dir is "#{Dir.tmpdir}/d..." } # Dir.mktmpdir(nil, "/var/tmp") {|dir| dir is "/var/tmp/d..." } # # If a block is given, # it is yielded with the path of the directory. # The directory and its contents are removed # using FileUtils.remove_entry before Dir.mktmpdir returns. # The value of the block is returned. # # Dir.mktmpdir {|dir| # # use the directory... # open("#{dir}/foo", "w") { ... } # } # # If a block is not given, # The path of the directory is returned. # In this case, Dir.mktmpdir doesn't remove the directory. # # dir = Dir.mktmpdir # begin # # use the directory... # open("#{dir}/foo", "w") { ... } # ensure # # remove the directory. # FileUtils.remove_entry dir # end # def Dir.mktmpdir(prefix_suffix=nil, *rest) path = Tmpname.create(prefix_suffix || "d", *rest) {|n| mkdir(n, 0700)} if block_given? begin yield path ensure stat = File.stat(File.dirname(path)) if stat.world_writable? and !stat.sticky? raise ArgumentError, "parent directory is world writable but not sticky" end FileUtils.remove_entry path end else path end end module Tmpname # :nodoc: module_function def tmpdir Dir.tmpdir end def make_tmpname((prefix, suffix), n) prefix = (String.try_convert(prefix) or raise ArgumentError, "unexpected prefix: #{prefix.inspect}") prefix = prefix.delete("#{File::SEPARATOR}#{File::ALT_SEPARATOR}") suffix &&= (String.try_convert(suffix) or raise ArgumentError, "unexpected suffix: #{suffix.inspect}") suffix &&= suffix.delete("#{File::SEPARATOR}#{File::ALT_SEPARATOR}") t = Time.now.strftime("%Y%m%d") path = "#{prefix}#{t}-#{$$}-#{rand(0x100000000).to_s(36)}" path << "-#{n}" if n path << suffix if suffix path end def create(basename, tmpdir=nil, max_try: nil, **opts) if $SAFE > 0 and tmpdir.tainted? tmpdir = '/tmp' else tmpdir ||= tmpdir() end n = nil begin path = File.join(tmpdir, make_tmpname(basename, n)) yield(path, n, opts) rescue Errno::EEXIST n ||= 0 n += 1 retry if !max_try or n < max_try raise "cannot generate temporary name using `#{basename}' under `#{tmpdir}'" end path end end end PK!jY 2.2.0/date.rbnu[# date.rb: Written by Tadayoshi Funaba 1998-2011 require 'date_core' class Date class Infinity < Numeric # :nodoc: include Comparable def initialize(d=1) @d = d <=> 0 end def d() @d end protected :d def zero? () false end def finite? () false end def infinite? () d.nonzero? end def nan? () d.zero? end def abs() self.class.new end def -@ () self.class.new(-d) end def +@ () self.class.new(+d) end def <=> (other) case other when Infinity; return d <=> other.d when Numeric; return d else begin l, r = other.coerce(self) return l <=> r rescue NoMethodError end end nil end def coerce(other) case other when Numeric; return -d, d else super end end def to_f return 0 if @d == 0 if @d > 0 Float::INFINITY else -Float::INFINITY end end end end PK!e  2.2.0/profiler.rbnu[# Profile provides a way to Profile your Ruby application. # # Profiling your program is a way of determining which methods are called and # how long each method takes to complete. This way you can detect which # methods are possible bottlenecks. # # Profiling your program will slow down your execution time considerably, # so activate it only when you need it. Don't confuse benchmarking with # profiling. # # There are two ways to activate Profiling: # # == Command line # # Run your Ruby script with -rprofile: # # ruby -rprofile example.rb # # If you're profiling an executable in your $PATH you can use # ruby -S: # # ruby -rprofile -S some_executable # # == From code # # Just require 'profile': # # require 'profile' # # def slow_method # 5000.times do # 9999999999999999*999999999 # end # end # # def fast_method # 5000.times do # 9999999999999999+999999999 # end # end # # slow_method # fast_method # # The output in both cases is a report when the execution is over: # # ruby -rprofile example.rb # # % cumulative self self total # time seconds seconds calls ms/call ms/call name # 68.42 0.13 0.13 2 65.00 95.00 Integer#times # 15.79 0.16 0.03 5000 0.01 0.01 Fixnum#* # 15.79 0.19 0.03 5000 0.01 0.01 Fixnum#+ # 0.00 0.19 0.00 2 0.00 0.00 IO#set_encoding # 0.00 0.19 0.00 1 0.00 100.00 Object#slow_method # 0.00 0.19 0.00 2 0.00 0.00 Module#method_added # 0.00 0.19 0.00 1 0.00 90.00 Object#fast_method # 0.00 0.19 0.00 1 0.00 190.00 #toplevel module Profiler__ class Wrapper < Struct.new(:defined_class, :method_id, :hash) # :nodoc: private :defined_class=, :method_id=, :hash= def initialize(klass, mid) super(klass, mid, nil) self.hash = Struct.instance_method(:hash).bind(self).call end def to_s "#{defined_class.inspect}#".sub(/\A\##\z/, '\1.') << method_id.to_s end alias inspect to_s end # internal values @@start = nil # the start time that profiling began @@stacks = nil # the map of stacks keyed by thread @@maps = nil # the map of call data keyed by thread, class and id. Call data contains the call count, total time, PROFILE_CALL_PROC = TracePoint.new(*%i[call c_call b_call]) {|tp| # :nodoc: now = Process.times[0] stack = (@@stacks[Thread.current] ||= []) stack.push [now, 0.0] } PROFILE_RETURN_PROC = TracePoint.new(*%i[return c_return b_return]) {|tp| # :nodoc: now = Process.times[0] key = Wrapper.new(tp.defined_class, tp.method_id) stack = (@@stacks[Thread.current] ||= []) if tick = stack.pop threadmap = (@@maps[Thread.current] ||= {}) data = (threadmap[key] ||= [0, 0.0, 0.0, key]) data[0] += 1 cost = now - tick[0] data[1] += cost data[2] += cost - tick[1] stack[-1][1] += cost if stack[-1] end } module_function # Starts the profiler. # # See Profiler__ for more information. def start_profile @@start = Process.times[0] @@stacks = {} @@maps = {} PROFILE_CALL_PROC.enable PROFILE_RETURN_PROC.enable end # Stops the profiler. # # See Profiler__ for more information. def stop_profile PROFILE_CALL_PROC.disable PROFILE_RETURN_PROC.disable end # Outputs the results from the profiler. # # See Profiler__ for more information. def print_profile(f) stop_profile total = Process.times[0] - @@start if total == 0 then total = 0.01 end totals = {} @@maps.values.each do |threadmap| threadmap.each do |key, data| total_data = (totals[key] ||= [0, 0.0, 0.0, key]) total_data[0] += data[0] total_data[1] += data[1] total_data[2] += data[2] end end # Maybe we should show a per thread output and a totals view? data = totals.values data = data.sort_by{|x| -x[2]} sum = 0 f.printf " %% cumulative self self total\n" f.printf " time seconds seconds calls ms/call ms/call name\n" for d in data sum += d[2] f.printf "%6.2f %8.2f %8.2f %8d ", d[2]/total*100, sum, d[2], d[0] f.printf "%8.2f %8.2f %s\n", d[2]*1000/d[0], d[1]*1000/d[0], d[3] end f.printf "%6.2f %8.2f %8.2f %8d ", 0.0, total, 0.0, 1 # ??? f.printf "%8.2f %8.2f %s\n", 0.0, total*1000, "#toplevel" # ??? end end PK!gg2.2.0/rubygems.rbnu[# -*- ruby -*- #-- # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. # All rights reserved. # See LICENSE.txt for permissions. #++ require 'rbconfig' require 'thread' module Gem VERSION = '2.4.5.5' end # Must be first since it unloads the prelude from 1.9.2 require 'rubygems/compatibility' require 'rubygems/defaults' require 'rubygems/deprecate' require 'rubygems/errors' ## # RubyGems is the Ruby standard for publishing and managing third party # libraries. # # For user documentation, see: # # * gem help and gem help [command] # * {RubyGems User Guide}[http://docs.rubygems.org/read/book/1] # * {Frequently Asked Questions}[http://docs.rubygems.org/read/book/3] # # For gem developer documentation see: # # * {Creating Gems}[http://docs.rubygems.org/read/chapter/5] # * Gem::Specification # * Gem::Version for version dependency notes # # Further RubyGems documentation can be found at: # # * {RubyGems Guides}[http://guides.rubygems.org] # * {RubyGems API}[http://rubygems.rubyforge.org/rdoc] (also available from # gem server) # # == RubyGems Plugins # # As of RubyGems 1.3.2, RubyGems will load plugins installed in gems or # $LOAD_PATH. Plugins must be named 'rubygems_plugin' (.rb, .so, etc) and # placed at the root of your gem's #require_path. Plugins are discovered via # Gem::find_files then loaded. Take care when implementing a plugin as your # plugin file may be loaded multiple times if multiple versions of your gem # are installed. # # For an example plugin, see the graph gem which adds a `gem graph` command. # # == RubyGems Defaults, Packaging # # RubyGems defaults are stored in rubygems/defaults.rb. If you're packaging # RubyGems or implementing Ruby you can change RubyGems' defaults. # # For RubyGems packagers, provide lib/rubygems/defaults/operating_system.rb # and override any defaults from lib/rubygems/defaults.rb. # # For Ruby implementers, provide lib/rubygems/defaults/#{RUBY_ENGINE}.rb and # override any defaults from lib/rubygems/defaults.rb. # # If you need RubyGems to perform extra work on install or uninstall, your # defaults override file can set pre and post install and uninstall hooks. # See Gem::pre_install, Gem::pre_uninstall, Gem::post_install, # Gem::post_uninstall. # # == Bugs # # You can submit bugs to the # {RubyGems bug tracker}[https://github.com/rubygems/rubygems/issues] # on GitHub # # == Credits # # RubyGems is currently maintained by Eric Hodel. # # RubyGems was originally developed at RubyConf 2003 by: # # * Rich Kilmer -- rich(at)infoether.com # * Chad Fowler -- chad(at)chadfowler.com # * David Black -- dblack(at)wobblini.net # * Paul Brannan -- paul(at)atdesk.com # * Jim Weirich -- jim(at)weirichhouse.org # # Contributors: # # * Gavin Sinclair -- gsinclair(at)soyabean.com.au # * George Marrows -- george.marrows(at)ntlworld.com # * Dick Davies -- rasputnik(at)hellooperator.net # * Mauricio Fernandez -- batsman.geo(at)yahoo.com # * Simon Strandgaard -- neoneye(at)adslhome.dk # * Dave Glasser -- glasser(at)mit.edu # * Paul Duncan -- pabs(at)pablotron.org # * Ville Aine -- vaine(at)cs.helsinki.fi # * Eric Hodel -- drbrain(at)segment7.net # * Daniel Berger -- djberg96(at)gmail.com # * Phil Hagelberg -- technomancy(at)gmail.com # * Ryan Davis -- ryand-ruby(at)zenspider.com # * Evan Phoenix -- evan(at)fallingsnow.net # * Steve Klabnik -- steve(at)steveklabnik.com # # (If your name is missing, PLEASE let us know!) # # See {LICENSE.txt}[rdoc-ref:lib/rubygems/LICENSE.txt] for permissions. # # Thanks! # # -The RubyGems Team module Gem RUBYGEMS_DIR = File.dirname File.expand_path(__FILE__) ## # An Array of Regexps that match windows Ruby platforms. WIN_PATTERNS = [ /bccwin/i, /cygwin/i, /djgpp/i, /mingw/i, /mswin/i, /wince/i, ] GEM_DEP_FILES = %w[ gem.deps.rb Gemfile Isolate ] ## # Subdirectories in a gem repository REPOSITORY_SUBDIRECTORIES = %w[ build_info cache doc extensions gems specifications ] ## # Subdirectories in a gem repository for default gems REPOSITORY_DEFAULT_GEM_SUBDIRECTORIES = %w[ gems specifications/default ] @@win_platform = nil @configuration = nil @loaded_specs = {} LOADED_SPECS_MUTEX = Mutex.new @path_to_default_spec_map = {} @platforms = [] @ruby = nil @ruby_api_version = nil @sources = nil @post_build_hooks ||= [] @post_install_hooks ||= [] @post_uninstall_hooks ||= [] @pre_uninstall_hooks ||= [] @pre_install_hooks ||= [] @pre_reset_hooks ||= [] @post_reset_hooks ||= [] ## # Try to activate a gem containing +path+. Returns true if # activation succeeded or wasn't needed because it was already # activated. Returns false if it can't find the path in a gem. def self.try_activate path # finds the _latest_ version... regardless of loaded specs and their deps # if another gem had a requirement that would mean we shouldn't # activate the latest version, then either it would already be activated # or if it was ambiguous (and thus unresolved) the code in our custom # require will try to activate the more specific version. spec = Gem::Specification.find_inactive_by_path path unless spec spec = Gem::Specification.find_by_path path return true if spec && spec.activated? return false end begin spec.activate rescue Gem::LoadError # this could fail due to gem dep collisions, go lax Gem::Specification.find_by_name(spec.name).activate end return true end def self.needs rs = Gem::RequestSet.new yield rs finish_resolve rs end def self.finish_resolve(request_set=Gem::RequestSet.new) request_set.import Gem::Specification.unresolved_deps.values request_set.resolve_current.each do |s| s.full_spec.activate end end ## # Find the full path to the executable for gem +name+. If the +exec_name+ # is not given, the gem's default_executable is chosen, otherwise the # specified executable's path is returned. +requirements+ allows # you to specify specific gem versions. def self.bin_path(name, exec_name = nil, *requirements) # TODO: fails test_self_bin_path_bin_file_gone_in_latest # Gem::Specification.find_by_name(name, *requirements).bin_file exec_name raise ArgumentError, "you must supply exec_name" unless exec_name requirements = Gem::Requirement.default if requirements.empty? dep = Gem::Dependency.new name, requirements loaded = Gem.loaded_specs[name] return loaded.bin_file exec_name if loaded && dep.matches_spec?(loaded) specs = dep.matching_specs(true) raise Gem::GemNotFoundException, "can't find gem #{name} (#{requirements})" if specs.empty? specs = specs.find_all { |spec| spec.executables.include? exec_name } if exec_name unless spec = specs.last msg = "can't find gem #{name} (#{requirements}) with executable #{exec_name}" raise Gem::GemNotFoundException, msg end spec.bin_file exec_name end ## # The mode needed to read a file as straight binary. def self.binary_mode 'rb' end ## # The path where gem executables are to be installed. def self.bindir(install_dir=Gem.dir) return File.join install_dir, 'bin' unless install_dir.to_s == Gem.default_dir.to_s Gem.default_bindir end ## # Reset the +dir+ and +path+ values. The next time +dir+ or +path+ # is requested, the values will be calculated from scratch. This is # mainly used by the unit tests to provide test isolation. def self.clear_paths @paths = nil @user_home = nil Gem::Specification.reset Gem::Security.reset if defined?(Gem::Security) end ## # The path to standard location of the user's .gemrc file. def self.config_file @config_file ||= File.join Gem.user_home, '.gemrc' end ## # The standard configuration object for gems. def self.configuration @configuration ||= Gem::ConfigFile.new [] end ## # Use the given configuration object (which implements the ConfigFile # protocol) as the standard configuration object. def self.configuration=(config) @configuration = config end ## # The path to the data directory specified by the gem name. If the # package is not available as a gem, return nil. def self.datadir(gem_name) # TODO: deprecate and move to Gem::Specification # and drop the extra ", gem_name" which is uselessly redundant spec = @loaded_specs[gem_name] return nil if spec.nil? File.join spec.full_gem_path, "data", gem_name end ## # A Zlib::Deflate.deflate wrapper def self.deflate(data) require 'zlib' Zlib::Deflate.deflate data end # Retrieve the PathSupport object that RubyGems uses to # lookup files. def self.paths @paths ||= Gem::PathSupport.new end # Initialize the filesystem paths to use from +env+. # +env+ is a hash-like object (typically ENV) that # is queried for 'GEM_HOME', 'GEM_PATH', and 'GEM_SPEC_CACHE' def self.paths=(env) clear_paths @paths = Gem::PathSupport.new env Gem::Specification.dirs = @paths.path end ## # The path where gems are to be installed. #-- # FIXME deprecate these once everything else has been done -ebh def self.dir paths.home end def self.path paths.path end def self.spec_cache_dir paths.spec_cache_dir end ## # Quietly ensure the Gem directory +dir+ contains all the proper # subdirectories. If we can't create a directory due to a permission # problem, then we will silently continue. # # If +mode+ is given, missing directories are created with this mode. # # World-writable directories will never be created. def self.ensure_gem_subdirectories dir = Gem.dir, mode = nil ensure_subdirectories(dir, mode, REPOSITORY_SUBDIRECTORIES) end ## # Quietly ensure the Gem directory +dir+ contains all the proper # subdirectories for handling default gems. If we can't create a # directory due to a permission problem, then we will silently continue. # # If +mode+ is given, missing directories are created with this mode. # # World-writable directories will never be created. def self.ensure_default_gem_subdirectories dir = Gem.dir, mode = nil ensure_subdirectories(dir, mode, REPOSITORY_DEFAULT_GEM_SUBDIRECTORIES) end def self.ensure_subdirectories dir, mode, subdirs # :nodoc: old_umask = File.umask File.umask old_umask | 002 require 'fileutils' options = {} options[:mode] = mode if mode subdirs.each do |name| subdir = File.join dir, name next if File.exist? subdir FileUtils.mkdir_p subdir, options rescue nil end ensure File.umask old_umask end ## # The extension API version of ruby. This includes the static vs non-static # distinction as extensions cannot be shared between the two. def self.extension_api_version # :nodoc: if 'no' == RbConfig::CONFIG['ENABLE_SHARED'] then "#{ruby_api_version}-static" else ruby_api_version end end ## # Returns a list of paths matching +glob+ that can be used by a gem to pick # up features from other gems. For example: # # Gem.find_files('rdoc/discover').each do |path| load path end # # if +check_load_path+ is true (the default), then find_files also searches # $LOAD_PATH for files as well as gems. # # Note that find_files will return all files even if they are from different # versions of the same gem. See also find_latest_files def self.find_files(glob, check_load_path=true) files = [] files = find_files_from_load_path glob if check_load_path files.concat Gem::Specification.map { |spec| spec.matches_for_glob("#{glob}#{Gem.suffix_pattern}") }.flatten # $LOAD_PATH might contain duplicate entries or reference # the spec dirs directly, so we prune. files.uniq! if check_load_path return files end def self.find_files_from_load_path glob # :nodoc: $LOAD_PATH.map { |load_path| Dir["#{File.expand_path glob, load_path}#{Gem.suffix_pattern}"] }.flatten.select { |file| File.file? file.untaint } end ## # Returns a list of paths matching +glob+ from the latest gems that can be # used by a gem to pick up features from other gems. For example: # # Gem.find_latest_files('rdoc/discover').each do |path| load path end # # if +check_load_path+ is true (the default), then find_latest_files also # searches $LOAD_PATH for files as well as gems. # # Unlike find_files, find_latest_files will return only files from the # latest version of a gem. def self.find_latest_files(glob, check_load_path=true) files = [] files = find_files_from_load_path glob if check_load_path files.concat Gem::Specification.latest_specs(true).map { |spec| spec.matches_for_glob("#{glob}#{Gem.suffix_pattern}") }.flatten # $LOAD_PATH might contain duplicate entries or reference # the spec dirs directly, so we prune. files.uniq! if check_load_path return files end ## # Finds the user's home directory. #-- # Some comments from the ruby-talk list regarding finding the home # directory: # # I have HOME, USERPROFILE and HOMEDRIVE + HOMEPATH. Ruby seems # to be depending on HOME in those code samples. I propose that # it should fallback to USERPROFILE and HOMEDRIVE + HOMEPATH (at # least on Win32). #++ #-- # # FIXME move to pathsupport # #++ def self.find_home windows = File::ALT_SEPARATOR if not windows or RUBY_VERSION >= '1.9' then File.expand_path "~" else ['HOME', 'USERPROFILE'].each do |key| return File.expand_path ENV[key] if ENV[key] end if ENV['HOMEDRIVE'] && ENV['HOMEPATH'] then File.expand_path "#{ENV['HOMEDRIVE']}#{ENV['HOMEPATH']}" end end rescue if windows then File.expand_path File.join(ENV['HOMEDRIVE'] || ENV['SystemDrive'], '/') else File.expand_path "/" end end private_class_method :find_home # FIXME deprecate these in 3.0 ## # Zlib::GzipReader wrapper that unzips +data+. def self.gunzip(data) require 'rubygems/util' Gem::Util.gunzip data end ## # Zlib::GzipWriter wrapper that zips +data+. def self.gzip(data) require 'rubygems/util' Gem::Util.gzip data end ## # A Zlib::Inflate#inflate wrapper def self.inflate(data) require 'rubygems/util' Gem::Util.inflate data end ## # Top level install helper method. Allows you to install gems interactively: # # % irb # >> Gem.install "minitest" # Fetching: minitest-3.0.1.gem (100%) # => [#] def self.install name, version = Gem::Requirement.default, *options require "rubygems/dependency_installer" inst = Gem::DependencyInstaller.new(*options) inst.install name, version inst.installed_gems end ## # Get the default RubyGems API host. This is normally # https://rubygems.org. def self.host # TODO: move to utils @host ||= Gem::DEFAULT_HOST end ## Set the default RubyGems API host. def self.host= host # TODO: move to utils @host = host end ## # The index to insert activated gem paths into the $LOAD_PATH. The activated # gem's paths are inserted before site lib directory by default. def self.load_path_insert_index index = $LOAD_PATH.index RbConfig::CONFIG['sitelibdir'] index end @yaml_loaded = false ## # Loads YAML, preferring Psych def self.load_yaml return if @yaml_loaded return unless defined?(gem) test_syck = ENV['TEST_SYCK'] unless test_syck begin gem 'psych', '~> 2.0.0' rescue Gem::LoadError # It's OK if the user does not have the psych gem installed. We will # attempt to require the stdlib version end begin # Try requiring the gem version *or* stdlib version of psych. require 'psych' rescue ::LoadError # If we can't load psych, thats fine, go on. else # If 'yaml' has already been required, then we have to # be sure to switch it over to the newly loaded psych. if defined?(YAML::ENGINE) && YAML::ENGINE.yamler != "psych" YAML::ENGINE.yamler = "psych" end require 'rubygems/psych_additions' require 'rubygems/psych_tree' end end require 'yaml' require 'rubygems/safe_yaml' # If we're supposed to be using syck, then we may have to force # activate it via the YAML::ENGINE API. if test_syck and defined?(YAML::ENGINE) YAML::ENGINE.yamler = "syck" unless YAML::ENGINE.syck? end # Now that we're sure some kind of yaml library is loaded, pull # in our hack to deal with Syck's DefaultKey ugliness. require 'rubygems/syck_hack' @yaml_loaded = true end ## # The file name and line number of the caller of the caller of this method. def self.location_of_caller caller[1] =~ /(.*?):(\d+).*?$/i file = $1 lineno = $2.to_i [file, lineno] end ## # The version of the Marshal format for your Ruby. def self.marshal_version "#{Marshal::MAJOR_VERSION}.#{Marshal::MINOR_VERSION}" end ## # Set array of platforms this RubyGems supports (primarily for testing). def self.platforms=(platforms) @platforms = platforms end ## # Array of platforms this RubyGems supports. def self.platforms @platforms ||= [] if @platforms.empty? @platforms = [Gem::Platform::RUBY, Gem::Platform.local] end @platforms end ## # Adds a post-build hook that will be passed an Gem::Installer instance # when Gem::Installer#install is called. The hook is called after the gem # has been extracted and extensions have been built but before the # executables or gemspec has been written. If the hook returns +false+ then # the gem's files will be removed and the install will be aborted. def self.post_build(&hook) @post_build_hooks << hook end ## # Adds a post-install hook that will be passed an Gem::Installer instance # when Gem::Installer#install is called def self.post_install(&hook) @post_install_hooks << hook end ## # Adds a post-installs hook that will be passed a Gem::DependencyInstaller # and a list of installed specifications when # Gem::DependencyInstaller#install is complete def self.done_installing(&hook) @done_installing_hooks << hook end ## # Adds a hook that will get run after Gem::Specification.reset is # run. def self.post_reset(&hook) @post_reset_hooks << hook end ## # Adds a post-uninstall hook that will be passed a Gem::Uninstaller instance # and the spec that was uninstalled when Gem::Uninstaller#uninstall is # called def self.post_uninstall(&hook) @post_uninstall_hooks << hook end ## # Adds a pre-install hook that will be passed an Gem::Installer instance # when Gem::Installer#install is called. If the hook returns +false+ then # the install will be aborted. def self.pre_install(&hook) @pre_install_hooks << hook end ## # Adds a hook that will get run before Gem::Specification.reset is # run. def self.pre_reset(&hook) @pre_reset_hooks << hook end ## # Adds a pre-uninstall hook that will be passed an Gem::Uninstaller instance # and the spec that will be uninstalled when Gem::Uninstaller#uninstall is # called def self.pre_uninstall(&hook) @pre_uninstall_hooks << hook end ## # The directory prefix this RubyGems was installed at. If your # prefix is in a standard location (ie, rubygems is installed where # you'd expect it to be), then prefix returns nil. def self.prefix prefix = File.dirname RUBYGEMS_DIR if prefix != File.expand_path(RbConfig::CONFIG['sitelibdir']) and prefix != File.expand_path(RbConfig::CONFIG['libdir']) and 'lib' == File.basename(RUBYGEMS_DIR) then prefix end end ## # Refresh available gems from disk. def self.refresh Gem::Specification.reset end ## # Safely read a file in binary mode on all platforms. def self.read_binary(path) open path, 'rb+' do |f| f.flock(File::LOCK_EX) f.read end rescue Errno::EACCES open path, 'rb' do |f| f.read end end ## # The path to the running Ruby interpreter. def self.ruby if @ruby.nil? then @ruby = File.join(RbConfig::CONFIG['bindir'], "#{RbConfig::CONFIG['ruby_install_name']}#{RbConfig::CONFIG['EXEEXT']}") @ruby = "\"#{@ruby}\"" if @ruby =~ /\s/ end @ruby end ## # Returns a String containing the API compatibility version of Ruby def self.ruby_api_version @ruby_api_version ||= RbConfig::CONFIG['ruby_version'].dup end ## # Returns the latest release-version specification for the gem +name+. def self.latest_spec_for name dependency = Gem::Dependency.new name fetcher = Gem::SpecFetcher.fetcher spec_tuples, = fetcher.spec_for_dependency dependency spec, = spec_tuples.first spec end ## # Returns the latest release version of RubyGems. def self.latest_rubygems_version latest_version_for('rubygems-update') or raise "Can't find 'rubygems-update' in any repo. Check `gem source list`." end ## # Returns the version of the latest release-version of gem +name+ def self.latest_version_for name spec = latest_spec_for name spec and spec.version end ## # A Gem::Version for the currently running Ruby. def self.ruby_version return @ruby_version if defined? @ruby_version version = RUBY_VERSION.dup if defined?(RUBY_PATCHLEVEL) && RUBY_PATCHLEVEL != -1 then version << ".#{RUBY_PATCHLEVEL}" elsif defined?(RUBY_REVISION) then version << ".dev.#{RUBY_REVISION}" end @ruby_version = Gem::Version.new version end ## # A Gem::Version for the currently running RubyGems def self.rubygems_version return @rubygems_version if defined? @rubygems_version @rubygems_version = Gem::Version.new Gem::VERSION end ## # Returns an Array of sources to fetch remote gems from. Uses # default_sources if the sources list is empty. def self.sources @sources ||= Gem::SourceList.from(default_sources) end ## # Need to be able to set the sources without calling # Gem.sources.replace since that would cause an infinite loop. # # DOC: This comment is not documentation about the method itself, it's # more of a code comment about the implementation. def self.sources= new_sources if !new_sources @sources = nil else @sources = Gem::SourceList.from(new_sources) end end ## # Glob pattern for require-able path suffixes. def self.suffix_pattern @suffix_pattern ||= "{#{suffixes.join(',')}}" end ## # Suffixes for require-able paths. def self.suffixes @suffixes ||= ['', '.rb', *%w(DLEXT DLEXT2).map { |key| val = RbConfig::CONFIG[key] next unless val and not val.empty? ".#{val}" } ].compact.uniq end ## # Prints the amount of time the supplied block takes to run using the debug # UI output. def self.time(msg, width = 0, display = Gem.configuration.verbose) now = Time.now value = yield elapsed = Time.now - now ui.say "%2$*1$s: %3$3.3fs" % [-width, msg, elapsed] if display value end ## # Lazily loads DefaultUserInteraction and returns the default UI. def self.ui require 'rubygems/user_interaction' Gem::DefaultUserInteraction.ui end ## # Use the +home+ and +paths+ values for Gem.dir and Gem.path. Used mainly # by the unit tests to provide environment isolation. def self.use_paths(home, *paths) paths = nil if paths == [nil] paths = paths.first if Array === Array(paths).first self.paths = { "GEM_HOME" => home, "GEM_PATH" => paths } end ## # The home directory for the user. def self.user_home @user_home ||= find_home.untaint end ## # Is this a windows platform? def self.win_platform? if @@win_platform.nil? then ruby_platform = RbConfig::CONFIG['host_os'] @@win_platform = !!WIN_PATTERNS.find { |r| ruby_platform =~ r } end @@win_platform end ## # Load +plugins+ as Ruby files def self.load_plugin_files plugins # :nodoc: plugins.each do |plugin| # Skip older versions of the GemCutter plugin: Its commands are in # RubyGems proper now. next if plugin =~ /gemcutter-0\.[0-3]/ begin load plugin rescue ::Exception => e details = "#{plugin.inspect}: #{e.message} (#{e.class})" warn "Error loading RubyGems plugin #{details}" end end end ## # Find the 'rubygems_plugin' files in the latest installed gems and load # them def self.load_plugins # Remove this env var by at least 3.0 if ENV['RUBYGEMS_LOAD_ALL_PLUGINS'] load_plugin_files find_files('rubygems_plugin', false) else load_plugin_files find_latest_files('rubygems_plugin', false) end end ## # Find all 'rubygems_plugin' files in $LOAD_PATH and load them def self.load_env_plugins path = "rubygems_plugin" files = [] $LOAD_PATH.each do |load_path| globbed = Dir["#{File.expand_path path, load_path}#{Gem.suffix_pattern}"] globbed.each do |load_path_file| files << load_path_file if File.file?(load_path_file.untaint) end end load_plugin_files files end ## # Looks for a gem dependency file at +path+ and activates the gems in the # file if found. If the file is not found an ArgumentError is raised. # # If +path+ is not given the RUBYGEMS_GEMDEPS environment variable is used, # but if no file is found no exception is raised. # # If '-' is given for +path+ RubyGems searches up from the current working # directory for gem dependency files (gem.deps.rb, Gemfile, Isolate) and # activates the gems in the first one found. # # You can run this automatically when rubygems starts. To enable, set # the RUBYGEMS_GEMDEPS environment variable to either the path # of your gem dependencies file or "-" to auto-discover in parent # directories. # # NOTE: Enabling automatic discovery on multiuser systems can lead to # execution of arbitrary code when used from directories outside your # control. def self.use_gemdeps path = nil raise_exception = path path ||= ENV['RUBYGEMS_GEMDEPS'] return unless path path = path.dup if path == "-" then require 'rubygems/util' Gem::Util.traverse_parents Dir.pwd do |directory| dep_file = GEM_DEP_FILES.find { |f| File.file?(f) } next unless dep_file path = File.join directory, dep_file break end end path.untaint unless File.file? path then return unless raise_exception raise ArgumentError, "Unable to find gem dependencies file at #{path}" end rs = Gem::RequestSet.new rs.load_gemdeps path rs.resolve_current.map do |s| sp = s.full_spec sp.activate sp end rescue Gem::LoadError, Gem::UnsatisfiableDependencyError => e warn e.message warn "You may need to `gem install -g` to install missing gems" warn "" end class << self ## # TODO remove with RubyGems 3.0 alias detect_gemdeps use_gemdeps # :nodoc: end # FIX: Almost everywhere else we use the `def self.` way of defining class # methods, and then we switch over to `class << self` here. Pick one or the # other. class << self ## # Hash of loaded Gem::Specification keyed by name attr_reader :loaded_specs ## # Register a Gem::Specification for default gem. # # Two formats for the specification are supported: # # * MRI 2.0 style, where spec.files contains unprefixed require names. # The spec's filenames will be registered as-is. # * New style, where spec.files contains files prefixed with paths # from spec.require_paths. The prefixes are stripped before # registering the spec's filenames. Unprefixed files are omitted. # def register_default_spec(spec) new_format = Gem.default_gems_use_full_paths? || spec.require_paths.any? {|path| spec.files.any? {|f| f.start_with? path } } if new_format prefix_group = spec.require_paths.map {|f| f + "/"}.join("|") prefix_pattern = /^(#{prefix_group})/ end spec.files.each do |file| if new_format file = file.sub(prefix_pattern, "") next unless $~ end @path_to_default_spec_map[file] = spec end end ## # Find a Gem::Specification of default gem from +path+ def find_unresolved_default_spec(path) Gem.suffixes.each do |suffix| spec = @path_to_default_spec_map["#{path}#{suffix}"] return spec if spec end nil end ## # Remove needless Gem::Specification of default gem from # unresolved default gem list def remove_unresolved_default_spec(spec) spec.files.each do |file| @path_to_default_spec_map.delete(file) end end ## # Clear default gem related variables. It is for test def clear_default_specs @path_to_default_spec_map.clear end ## # The list of hooks to be run after Gem::Installer#install extracts files # and builds extensions attr_reader :post_build_hooks ## # The list of hooks to be run after Gem::Installer#install completes # installation attr_reader :post_install_hooks ## # The list of hooks to be run after Gem::DependencyInstaller installs a # set of gems attr_reader :done_installing_hooks ## # The list of hooks to be run after Gem::Specification.reset is run. attr_reader :post_reset_hooks ## # The list of hooks to be run after Gem::Uninstaller#uninstall completes # installation attr_reader :post_uninstall_hooks ## # The list of hooks to be run before Gem::Installer#install does any work attr_reader :pre_install_hooks ## # The list of hooks to be run before Gem::Specification.reset is run. attr_reader :pre_reset_hooks ## # The list of hooks to be run before Gem::Uninstaller#uninstall does any # work attr_reader :pre_uninstall_hooks end ## # Location of Marshal quick gemspecs on remote repositories MARSHAL_SPEC_DIR = "quick/Marshal.#{Gem.marshal_version}/" autoload :ConfigFile, 'rubygems/config_file' autoload :Dependency, 'rubygems/dependency' autoload :DependencyList, 'rubygems/dependency_list' autoload :DependencyResolver, 'rubygems/resolver' autoload :Installer, 'rubygems/installer' autoload :PathSupport, 'rubygems/path_support' autoload :Platform, 'rubygems/platform' autoload :RequestSet, 'rubygems/request_set' autoload :Requirement, 'rubygems/requirement' autoload :Resolver, 'rubygems/resolver' autoload :Source, 'rubygems/source' autoload :SourceList, 'rubygems/source_list' autoload :SpecFetcher, 'rubygems/spec_fetcher' autoload :Specification, 'rubygems/specification' autoload :Version, 'rubygems/version' require "rubygems/specification" end require 'rubygems/exceptions' # REFACTOR: This should be pulled out into some kind of hacks file. gem_preluded = Gem::GEM_PRELUDE_SUCKAGE and defined? Gem unless gem_preluded then # TODO: remove guard after 1.9.2 dropped begin ## # Defaults the operating system (or packager) wants to provide for RubyGems. require 'rubygems/defaults/operating_system' rescue LoadError end if defined?(RUBY_ENGINE) then begin ## # Defaults the Ruby implementation wants to provide for RubyGems require "rubygems/defaults/#{RUBY_ENGINE}" rescue LoadError end end end ## # Loads the default specs. Gem::Specification.load_defaults require 'rubygems/core_ext/kernel_gem' require 'rubygems/core_ext/kernel_require' Gem.use_gemdeps PK!.H%%2.2.0/rubygems/request_set.rbnu[require 'tsort' ## # A RequestSet groups a request to activate a set of dependencies. # # nokogiri = Gem::Dependency.new 'nokogiri', '~> 1.6' # pg = Gem::Dependency.new 'pg', '~> 0.14' # # set = Gem::RequestSet.new nokogiri, pg # # requests = set.resolve # # p requests.map { |r| r.full_name } # #=> ["nokogiri-1.6.0", "mini_portile-0.5.1", "pg-0.17.0"] class Gem::RequestSet include TSort ## # Array of gems to install even if already installed attr_accessor :always_install attr_reader :dependencies attr_accessor :development ## # Errors fetching gems during resolution. attr_reader :errors ## # Set to true if you want to install only direct development dependencies. attr_accessor :development_shallow ## # The set of git gems imported via load_gemdeps. attr_reader :git_set # :nodoc: ## # When true, dependency resolution is not performed, only the requested gems # are installed. attr_accessor :ignore_dependencies attr_reader :install_dir # :nodoc: ## # If true, allow dependencies to match prerelease gems. attr_accessor :prerelease ## # When false no remote sets are used for resolving gems. attr_accessor :remote attr_reader :resolver # :nodoc: ## # Sets used for resolution attr_reader :sets # :nodoc: ## # Treat missing dependencies as silent errors attr_accessor :soft_missing ## # The set of vendor gems imported via load_gemdeps. attr_reader :vendor_set # :nodoc: ## # Creates a RequestSet for a list of Gem::Dependency objects, +deps+. You # can then #resolve and #install the resolved list of dependencies. # # nokogiri = Gem::Dependency.new 'nokogiri', '~> 1.6' # pg = Gem::Dependency.new 'pg', '~> 0.14' # # set = Gem::RequestSet.new nokogiri, pg def initialize *deps @dependencies = deps @always_install = [] @conservative = false @dependency_names = {} @development = false @development_shallow = false @errors = [] @git_set = nil @ignore_dependencies = false @install_dir = Gem.dir @prerelease = false @remote = true @requests = [] @sets = [] @soft_missing = false @sorted = nil @specs = nil @vendor_set = nil yield self if block_given? end ## # Declare that a gem of name +name+ with +reqs+ requirements is needed. def gem name, *reqs if dep = @dependency_names[name] then dep.requirement.concat reqs else dep = Gem::Dependency.new name, reqs @dependency_names[name] = dep @dependencies << dep end end ## # Add +deps+ Gem::Dependency objects to the set. def import deps @dependencies.concat deps end ## # Installs gems for this RequestSet using the Gem::Installer +options+. # # If a +block+ is given an activation +request+ and +installer+ are yielded. # The +installer+ will be +nil+ if a gem matching the request was already # installed. def install options, &block # :yields: request, installer if dir = options[:install_dir] requests = install_into dir, false, options, &block return requests end cache_dir = options[:cache_dir] || Gem.dir @prerelease = options[:prerelease] requests = [] sorted_requests.each do |req| if req.installed? then req.spec.spec.build_extensions if @always_install.none? { |spec| spec == req.spec.spec } then yield req, nil if block_given? next end end path = req.download cache_dir inst = Gem::Installer.new path, options yield req, inst if block_given? requests << inst.install end requests ensure raise if $! return requests if options[:gemdeps] specs = requests.map do |request| case request when Gem::Resolver::ActivationRequest then request.spec.spec else request end end require 'rubygems/dependency_installer' inst = Gem::DependencyInstaller.new options inst.installed_gems.replace specs Gem.done_installing_hooks.each do |hook| hook.call inst, specs end unless Gem.done_installing_hooks.empty? end ## # Installs from the gem dependencies files in the +:gemdeps+ option in # +options+, yielding to the +block+ as in #install. # # If +:without_groups+ is given in the +options+, those groups in the gem # dependencies file are not used. See Gem::Installer for other +options+. def install_from_gemdeps options, &block gemdeps = options[:gemdeps] @install_dir = options[:install_dir] || Gem.dir @prerelease = options[:prerelease] @remote = options[:domain] != :local @conservative = true if options[:conservative] gem_deps_api = load_gemdeps gemdeps, options[:without_groups], true resolve if options[:explain] puts "Gems to install:" sorted_requests.each do |spec| puts " #{spec.full_name}" end if Gem.configuration.really_verbose @resolver.stats.display end else installed = install options, &block if options.fetch :lock, true then lockfile = Gem::RequestSet::Lockfile.new self, gemdeps, gem_deps_api.dependencies lockfile.write end installed end end def install_into dir, force = true, options = {} gem_home, ENV['GEM_HOME'] = ENV['GEM_HOME'], dir existing = force ? [] : specs_in(dir) existing.delete_if { |s| @always_install.include? s } dir = File.expand_path dir installed = [] options[:development] = false options[:install_dir] = dir options[:only_install_dir] = true @prerelease = options[:prerelease] sorted_requests.each do |request| spec = request.spec if existing.find { |s| s.full_name == spec.full_name } then yield request, nil if block_given? next end spec.install options do |installer| yield request, installer if block_given? end installed << request end installed ensure ENV['GEM_HOME'] = gem_home end ## # Load a dependency management file. def load_gemdeps path, without_groups = [], installing = false @git_set = Gem::Resolver::GitSet.new @vendor_set = Gem::Resolver::VendorSet.new @git_set.root_dir = @install_dir lockfile = Gem::RequestSet::Lockfile.new self, path lockfile.parse gf = Gem::RequestSet::GemDependencyAPI.new self, path gf.installing = installing gf.without_groups = without_groups if without_groups gf.load end def pretty_print q # :nodoc: q.group 2, '[RequestSet:', ']' do q.breakable if @remote then q.text 'remote' q.breakable end if @prerelease then q.text 'prerelease' q.breakable end if @development_shallow then q.text 'shallow development' q.breakable elsif @development then q.text 'development' q.breakable end if @soft_missing then q.text 'soft missing' end q.group 2, '[dependencies:', ']' do q.breakable @dependencies.map do |dep| q.text dep.to_s q.breakable end end q.breakable q.text 'sets:' q.breakable q.pp @sets.map { |set| set.class } end end ## # Resolve the requested dependencies and return an Array of Specification # objects to be activated. def resolve set = Gem::Resolver::BestSet.new @sets << set @sets << @git_set @sets << @vendor_set set = Gem::Resolver.compose_sets(*@sets) set.remote = @remote set.prerelease = @prerelease resolver = Gem::Resolver.new @dependencies, set resolver.development = @development resolver.development_shallow = @development_shallow resolver.ignore_dependencies = @ignore_dependencies resolver.soft_missing = @soft_missing if @conservative installed_gems = {} Gem::Specification.find_all do |spec| (installed_gems[spec.name] ||= []) << spec end resolver.skip_gems = installed_gems end @resolver = resolver @requests = resolver.resolve @errors = set.errors @requests end ## # Resolve the requested dependencies against the gems available via Gem.path # and return an Array of Specification objects to be activated. def resolve_current resolve Gem::Resolver::CurrentSet.new end def sorted_requests @sorted ||= strongly_connected_components.flatten end def specs @specs ||= @requests.map { |r| r.full_spec } end def specs_in dir Dir["#{dir}/specifications/*.gemspec"].map do |g| Gem::Specification.load g end end def tsort_each_node &block # :nodoc: @requests.each(&block) end def tsort_each_child node # :nodoc: node.spec.dependencies.each do |dep| next if dep.type == :development and not @development match = @requests.find { |r| dep.match? r.spec.name, r.spec.version, @prerelease } unless match then next if dep.type == :development and @development_shallow next if @soft_missing raise Gem::DependencyError, "Unresolved dependency found during sorting - #{dep} (requested by #{node.spec.full_name})" end yield match end end end require 'rubygems/request_set/gem_dependency_api' require 'rubygems/request_set/lockfile' PK!(++2.2.0/rubygems/version.rbnu[## # The Version class processes string versions into comparable # values. A version string should normally be a series of numbers # separated by periods. Each part (digits separated by periods) is # considered its own number, and these are used for sorting. So for # instance, 3.10 sorts higher than 3.2 because ten is greater than # two. # # If any part contains letters (currently only a-z are supported) then # that version is considered prerelease. Versions with a prerelease # part in the Nth part sort less than versions with N-1 # parts. Prerelease parts are sorted alphabetically using the normal # Ruby string sorting rules. If a prerelease part contains both # letters and numbers, it will be broken into multiple parts to # provide expected sort behavior (1.0.a10 becomes 1.0.a.10, and is # greater than 1.0.a9). # # Prereleases sort between real releases (newest to oldest): # # 1. 1.0 # 2. 1.0.b1 # 3. 1.0.a.2 # 4. 0.9 # # If you want to specify a version restriction that includes both prereleases # and regular releases of the 1.x series this is the best way: # # s.add_dependency 'example', '>= 1.0.0.a', '< 2.0.0' # # == How Software Changes # # Users expect to be able to specify a version constraint that gives them # some reasonable expectation that new versions of a library will work with # their software if the version constraint is true, and not work with their # software if the version constraint is false. In other words, the perfect # system will accept all compatible versions of the library and reject all # incompatible versions. # # Libraries change in 3 ways (well, more than 3, but stay focused here!). # # 1. The change may be an implementation detail only and have no effect on # the client software. # 2. The change may add new features, but do so in a way that client software # written to an earlier version is still compatible. # 3. The change may change the public interface of the library in such a way # that old software is no longer compatible. # # Some examples are appropriate at this point. Suppose I have a Stack class # that supports a push and a pop method. # # === Examples of Category 1 changes: # # * Switch from an array based implementation to a linked-list based # implementation. # * Provide an automatic (and transparent) backing store for large stacks. # # === Examples of Category 2 changes might be: # # * Add a depth method to return the current depth of the stack. # * Add a top method that returns the current top of stack (without # changing the stack). # * Change push so that it returns the item pushed (previously it # had no usable return value). # # === Examples of Category 3 changes might be: # # * Changes pop so that it no longer returns a value (you must use # top to get the top of the stack). # * Rename the methods to push_item and pop_item. # # == RubyGems Rational Versioning # # * Versions shall be represented by three non-negative integers, separated # by periods (e.g. 3.1.4). The first integers is the "major" version # number, the second integer is the "minor" version number, and the third # integer is the "build" number. # # * A category 1 change (implementation detail) will increment the build # number. # # * A category 2 change (backwards compatible) will increment the minor # version number and reset the build number. # # * A category 3 change (incompatible) will increment the major build number # and reset the minor and build numbers. # # * Any "public" release of a gem should have a different version. Normally # that means incrementing the build number. This means a developer can # generate builds all day long, but as soon as they make a public release, # the version must be updated. # # === Examples # # Let's work through a project lifecycle using our Stack example from above. # # Version 0.0.1:: The initial Stack class is release. # Version 0.0.2:: Switched to a linked=list implementation because it is # cooler. # Version 0.1.0:: Added a depth method. # Version 1.0.0:: Added top and made pop return nil # (pop used to return the old top item). # Version 1.1.0:: push now returns the value pushed (it used it # return nil). # Version 1.1.1:: Fixed a bug in the linked list implementation. # Version 1.1.2:: Fixed a bug introduced in the last fix. # # Client A needs a stack with basic push/pop capability. They write to the # original interface (no top), so their version constraint looks like: # # gem 'stack', '~> 0.0' # # Essentially, any version is OK with Client A. An incompatible change to # the library will cause them grief, but they are willing to take the chance # (we call Client A optimistic). # # Client B is just like Client A except for two things: (1) They use the # depth method and (2) they are worried about future # incompatibilities, so they write their version constraint like this: # # gem 'stack', '~> 0.1' # # The depth method was introduced in version 0.1.0, so that version # or anything later is fine, as long as the version stays below version 1.0 # where incompatibilities are introduced. We call Client B pessimistic # because they are worried about incompatible future changes (it is OK to be # pessimistic!). # # == Preventing Version Catastrophe: # # From: http://blog.zenspider.com/2008/10/rubygems-howto-preventing-cata.html # # Let's say you're depending on the fnord gem version 2.y.z. If you # specify your dependency as ">= 2.0.0" then, you're good, right? What # happens if fnord 3.0 comes out and it isn't backwards compatible # with 2.y.z? Your stuff will break as a result of using ">=". The # better route is to specify your dependency with an "approximate" version # specifier ("~>"). They're a tad confusing, so here is how the dependency # specifiers work: # # Specification From ... To (exclusive) # ">= 3.0" 3.0 ... ∞ # "~> 3.0" 3.0 ... 4.0 # "~> 3.0.0" 3.0.0 ... 3.1 # "~> 3.5" 3.5 ... 4.0 # "~> 3.5.0" 3.5.0 ... 3.6 # "~> 3" 3.0 ... 4.0 # # For the last example, single-digit versions are automatically extended with # a zero to give a sensible result. class Gem::Version autoload :Requirement, 'rubygems/requirement' include Comparable VERSION_PATTERN = '[0-9]+(?>\.[0-9a-zA-Z]+)*(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?' # :nodoc: ANCHORED_VERSION_PATTERN = /\A\s*(#{VERSION_PATTERN})?\s*\z/ # :nodoc: ## # A string representation of this Version. def version @version.dup end alias to_s version ## # True if the +version+ string matches RubyGems' requirements. def self.correct? version version.to_s =~ ANCHORED_VERSION_PATTERN end ## # Factory method to create a Version object. Input may be a Version # or a String. Intended to simplify client code. # # ver1 = Version.create('1.3.17') # -> (Version object) # ver2 = Version.create(ver1) # -> (ver1) # ver3 = Version.create(nil) # -> nil def self.create input if self === input then # check yourself before you wreck yourself input elsif input.nil? then nil else new input end end @@all = {} def self.new version # :nodoc: return super unless Gem::Version == self @@all[version] ||= super end ## # Constructs a Version from the +version+ string. A version string is a # series of digits or ASCII letters separated by dots. def initialize version raise ArgumentError, "Malformed version number string #{version}" unless self.class.correct?(version) @version = version.to_s.strip.gsub("-",".pre.") @segments = nil end ## # Return a new version object where the next to the last revision # number is one greater (e.g., 5.3.1 => 5.4). # # Pre-release (alpha) parts, e.g, 5.3.1.b.2 => 5.4, are ignored. def bump segments = self.segments.dup segments.pop while segments.any? { |s| String === s } segments.pop if segments.size > 1 segments[-1] = segments[-1].succ self.class.new segments.join(".") end ## # A Version is only eql? to another version if it's specified to the # same precision. Version "1.0" is not the same as version "1". def eql? other self.class === other and @version == other.version end def hash # :nodoc: @hash ||= segments.hash end def init_with coder # :nodoc: yaml_initialize coder.tag, coder.map end def inspect # :nodoc: "#<#{self.class} #{version.inspect}>" end ## # Dump only the raw version string, not the complete object. It's a # string for backwards (RubyGems 1.3.5 and earlier) compatibility. def marshal_dump [version] end ## # Load custom marshal format. It's a string for backwards (RubyGems # 1.3.5 and earlier) compatibility. def marshal_load array initialize array[0] end def yaml_initialize(tag, map) # :nodoc: @version = map['version'] @segments = nil @hash = nil end def to_yaml_properties # :nodoc: ["@version"] end def encode_with coder # :nodoc: coder.add 'version', @version end ## # A version is considered a prerelease if it contains a letter. def prerelease? @prerelease ||= !!(@version =~ /[a-zA-Z]/) end def pretty_print q # :nodoc: q.text "Gem::Version.new(#{version.inspect})" end ## # The release for this version (e.g. 1.2.0.a -> 1.2.0). # Non-prerelease versions return themselves. def release return self unless prerelease? segments = self.segments.dup segments.pop while segments.any? { |s| String === s } self.class.new segments.join('.') end def segments # :nodoc: # segments is lazy so it can pick up version values that come from # old marshaled versions, which don't go through marshal_load. @segments ||= @version.scan(/[0-9]+|[a-z]+/i).map do |s| /^\d+$/ =~ s ? s.to_i : s end end ## # A recommended version for use with a ~> Requirement. def approximate_recommendation segments = self.segments.dup segments.pop while segments.any? { |s| String === s } segments.pop while segments.size > 2 segments.push 0 while segments.size < 2 "~> #{segments.join(".")}" end ## # Compares this version with +other+ returning -1, 0, or 1 if the # other version is larger, the same, or smaller than this # one. Attempts to compare to something that's not a # Gem::Version return +nil+. def <=> other return unless Gem::Version === other return 0 if @version == other.version lhsegments = segments rhsegments = other.segments lhsize = lhsegments.size rhsize = rhsegments.size limit = (lhsize > rhsize ? lhsize : rhsize) - 1 i = 0 while i <= limit lhs, rhs = lhsegments[i] || 0, rhsegments[i] || 0 i += 1 next if lhs == rhs return -1 if String === lhs && Numeric === rhs return 1 if Numeric === lhs && String === rhs return lhs <=> rhs end return 0 end end PK!]-2.2.0/rubygems/ssl_certs/GlobalSignRootCA.pemnu[-----BEGIN CERTIFICATE----- MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp 1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8 9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE 38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== -----END CERTIFICATE----- PK!*W{2.2.0/rubygems/text.rbnu[require 'rubygems' ## # A collection of text-wrangling methods module Gem::Text ## # Remove any non-printable characters and make the text suitable for # printing. def clean_text(text) text.gsub(/[\000-\b\v-\f\016-\037\177]/, ".".freeze) end def truncate_text(text, description, max_length = 100_000) raise ArgumentError, "max_length must be positive" unless max_length > 0 return text if text.size <= max_length "Truncating #{description} to #{max_length.to_s.reverse.gsub(/...(?=.)/,'\&,').reverse} characters:\n" + text[0, max_length] end ## # Wraps +text+ to +wrap+ characters and optionally indents by +indent+ # characters def format_text(text, wrap, indent=0) result = [] work = clean_text(text) while work.length > wrap do if work =~ /^(.{0,#{wrap}})[ \n]/ then result << $1.rstrip work.slice!(0, $&.length) else result << work.slice!(0, wrap) end end result << work if work.length.nonzero? result.join("\n").gsub(/^/, " " * indent) end def min3 a, b, c # :nodoc: if a < b && a < c then a elsif b < c then b else c end end # This code is based directly on the Text gem implementation # Returns a value representing the "cost" of transforming str1 into str2 def levenshtein_distance str1, str2 s = str1 t = str2 n = s.length m = t.length max = n/2 return m if (0 == n) return n if (0 == m) return n if (n - m).abs > max d = (0..m).to_a x = nil str1.each_char.each_with_index do |char1,i| e = i+1 str2.each_char.each_with_index do |char2,j| cost = (char1 == char2) ? 0 : 1 x = min3( d[j+1] + 1, # insertion e + 1, # deletion d[j] + cost # substitution ) d[j] = e e = x end d[m] = x end return x end end PK!**2.2.0/rubygems/request/connection_pools.rbnu[require 'thread' class Gem::Request::ConnectionPools # :nodoc: @client = Net::HTTP class << self attr_accessor :client end def initialize proxy_uri, cert_files @proxy_uri = proxy_uri @cert_files = cert_files @pools = {} @pool_mutex = Mutex.new end def pool_for uri http_args = net_http_args(uri, @proxy_uri) key = http_args + [https?(uri)] @pool_mutex.synchronize do @pools[key] ||= if https? uri then Gem::Request::HTTPSPool.new(http_args, @cert_files, @proxy_uri) else Gem::Request::HTTPPool.new(http_args, @cert_files, @proxy_uri) end end end def close_all @pools.each_value {|pool| pool.close_all} end private ## # Returns list of no_proxy entries (if any) from the environment def get_no_proxy_from_env env_no_proxy = ENV['no_proxy'] || ENV['NO_PROXY'] return [] if env_no_proxy.nil? or env_no_proxy.empty? env_no_proxy.split(/\s*,\s*/) end def https? uri uri.scheme.downcase == 'https' end def no_proxy? host, env_no_proxy host = host.downcase env_no_proxy.any? do |pattern| pattern = pattern.downcase host[-pattern.length, pattern.length] == pattern or (pattern.start_with? '.' and pattern[1..-1] == host) end end def net_http_args uri, proxy_uri net_http_args = [uri.host, uri.port] no_proxy = get_no_proxy_from_env if proxy_uri and not no_proxy?(uri.host, no_proxy) then net_http_args + [ proxy_uri.host, proxy_uri.port, Gem::UriFormatter.new(proxy_uri.user).unescape, Gem::UriFormatter.new(proxy_uri.password).unescape, ] elsif no_proxy? uri.host, no_proxy then net_http_args + [nil, nil] else net_http_args end end end PK!(4s>$2.2.0/rubygems/request/https_pool.rbnu[class Gem::Request::HTTPSPool < Gem::Request::HTTPPool # :nodoc: private def setup_connection connection Gem::Request.configure_connection_for_https(connection, @cert_files) super end end PK!!#2.2.0/rubygems/request/http_pool.rbnu[## # A connection "pool" that only manages one connection for now. Provides # thread safe `checkout` and `checkin` methods. The pool consists of one # connection that corresponds to `http_args`. This class is private, do not # use it. class Gem::Request::HTTPPool # :nodoc: attr_reader :cert_files, :proxy_uri def initialize http_args, cert_files, proxy_uri @http_args = http_args @cert_files = cert_files @proxy_uri = proxy_uri @queue = SizedQueue.new 1 @queue << nil end def checkout @queue.pop || make_connection end def checkin connection @queue.push connection end def close_all until @queue.empty? if connection = @queue.pop(true) and connection.started? connection.finish end end @queue.push(nil) end private def make_connection setup_connection Gem::Request::ConnectionPools.client.new(*@http_args) end def setup_connection connection connection.start connection end end PK!qZ2.2.0/rubygems/platform.rbnu[require "rubygems/deprecate" ## # Available list of platforms for targeting Gem installations. # # See `gem help platform` for information on platform matching. class Gem::Platform @local = nil attr_accessor :cpu attr_accessor :os attr_accessor :version def self.local arch = RbConfig::CONFIG['arch'] arch = "#{arch}_60" if arch =~ /mswin(?:32|64)$/ @local ||= new(arch) end def self.match(platform) Gem.platforms.any? do |local_platform| platform.nil? or local_platform == platform or (local_platform != Gem::Platform::RUBY and local_platform =~ platform) end end def self.installable?(spec) if spec.respond_to? :installable_platform? spec.installable_platform? else match spec.platform end end def self.new(arch) # :nodoc: case arch when Gem::Platform::CURRENT then Gem::Platform.local when Gem::Platform::RUBY, nil, '' then Gem::Platform::RUBY else super end end def initialize(arch) case arch when Array then @cpu, @os, @version = arch when String then arch = arch.split '-' if arch.length > 2 and arch.last !~ /\d/ then # reassemble x86-linux-gnu extra = arch.pop arch.last << "-#{extra}" end cpu = arch.shift @cpu = case cpu when /i\d86/ then 'x86' else cpu end if arch.length == 2 and arch.last =~ /^\d+(\.\d+)?$/ then # for command-line @os, @version = arch return end os, = arch @cpu, os = nil, cpu if os.nil? # legacy jruby @os, @version = case os when /aix(\d+)?/ then [ 'aix', $1 ] when /cygwin/ then [ 'cygwin', nil ] when /darwin(\d+)?/ then [ 'darwin', $1 ] when /^macruby$/ then [ 'macruby', nil ] when /freebsd(\d+)?/ then [ 'freebsd', $1 ] when /hpux(\d+)?/ then [ 'hpux', $1 ] when /^java$/, /^jruby$/ then [ 'java', nil ] when /^java([\d.]*)/ then [ 'java', $1 ] when /^dalvik(\d+)?$/ then [ 'dalvik', $1 ] when /^dotnet$/ then [ 'dotnet', nil ] when /^dotnet([\d.]*)/ then [ 'dotnet', $1 ] when /linux/ then [ 'linux', $1 ] when /mingw32/ then [ 'mingw32', nil ] when /(mswin\d+)(\_(\d+))?/ then os, version = $1, $3 @cpu = 'x86' if @cpu.nil? and os =~ /32$/ [os, version] when /netbsdelf/ then [ 'netbsdelf', nil ] when /openbsd(\d+\.\d+)?/ then [ 'openbsd', $1 ] when /solaris(\d+\.\d+)?/ then [ 'solaris', $1 ] # test when /^(\w+_platform)(\d+)?/ then [ $1, $2 ] else [ 'unknown', nil ] end when Gem::Platform then @cpu = arch.cpu @os = arch.os @version = arch.version else raise ArgumentError, "invalid argument #{arch.inspect}" end end def inspect "#<%s:0x%x @cpu=%p, @os=%p, @version=%p>" % [self.class, object_id, *to_a] end def to_a [@cpu, @os, @version] end def to_s to_a.compact.join '-' end ## # Is +other+ equal to this platform? Two platforms are equal if they have # the same CPU, OS and version. def ==(other) self.class === other and to_a == other.to_a end alias :eql? :== def hash # :nodoc: to_a.hash end ## # Does +other+ match this platform? Two platforms match if they have the # same CPU, or either has a CPU of 'universal', they have the same OS, and # they have the same version, or either has no version. # # Additionally, the platform will match if the local CPU is 'arm' and the # other CPU starts with "arm" (for generic ARM family support). def ===(other) return nil unless Gem::Platform === other # cpu (@cpu == 'universal' or other.cpu == 'universal' or @cpu == other.cpu or (@cpu == 'arm' and other.cpu =~ /\Aarm/)) and # os @os == other.os and # version (@version.nil? or other.version.nil? or @version == other.version) end ## # Does +other+ match this platform? If +other+ is a String it will be # converted to a Gem::Platform first. See #=== for matching rules. def =~(other) case other when Gem::Platform then # nop when String then # This data is from http://gems.rubyforge.org/gems/yaml on 19 Aug 2007 other = case other when /^i686-darwin(\d)/ then ['x86', 'darwin', $1 ] when /^i\d86-linux/ then ['x86', 'linux', nil ] when 'java', 'jruby' then [nil, 'java', nil ] when /^dalvik(\d+)?$/ then [nil, 'dalvik', $1 ] when /dotnet(\-(\d+\.\d+))?/ then ['universal','dotnet', $2 ] when /mswin32(\_(\d+))?/ then ['x86', 'mswin32', $2 ] when /mswin64(\_(\d+))?/ then ['x64', 'mswin64', $2 ] when 'powerpc-darwin' then ['powerpc', 'darwin', nil ] when /powerpc-darwin(\d)/ then ['powerpc', 'darwin', $1 ] when /sparc-solaris2.8/ then ['sparc', 'solaris', '2.8' ] when /universal-darwin(\d)/ then ['universal', 'darwin', $1 ] else other end other = Gem::Platform.new other else return nil end self === other end ## # A pure-Ruby gem that may use Gem::Specification#extensions to build # binary files. RUBY = 'ruby' ## # A platform-specific gem that is built for the packaging Ruby's platform. # This will be replaced with Gem::Platform::local. CURRENT = 'current' end PK! | | 2.2.0/rubygems/errors.rbnu[#-- # This file contains all the various exceptions and other errors that are used # inside of RubyGems. # # DOC: Confirm _all_ #++ module Gem ## # Raised when RubyGems is unable to load or activate a gem. Contains the # name and version requirements of the gem that either conflicts with # already activated gems or that RubyGems is otherwise unable to activate. class LoadError < ::LoadError # Name of gem attr_accessor :name # Version requirement of gem attr_accessor :requirement end # Raised when there are conflicting gem specs loaded class ConflictError < LoadError ## # A Hash mapping conflicting specifications to the dependencies that # caused the conflict attr_reader :conflicts ## # The specification that had the conflict attr_reader :target def initialize target, conflicts @target = target @conflicts = conflicts @name = target.name reason = conflicts.map { |act, dependencies| "#{act.full_name} conflicts with #{dependencies.join(", ")}" }.join ", " # TODO: improve message by saying who activated `con` super("Unable to activate #{target.full_name}, because #{reason}") end end class ErrorReason; end # Generated when trying to lookup a gem to indicate that the gem # was found, but that it isn't usable on the current platform. # # fetch and install read these and report them to the user to aid # in figuring out why a gem couldn't be installed. # class PlatformMismatch < ErrorReason ## # the name of the gem attr_reader :name ## # the version attr_reader :version ## # The platforms that are mismatched attr_reader :platforms def initialize(name, version) @name = name @version = version @platforms = [] end ## # append a platform to the list of mismatched platforms. # # Platforms are added via this instead of injected via the constructor # so that we can loop over a list of mismatches and just add them rather # than perform some kind of calculation mismatch summary before creation. def add_platform(platform) @platforms << platform end ## # A wordy description of the error. def wordy "Found %s (%s), but was for platform%s %s" % [@name, @version, @platforms.size == 1 ? '' : 's', @platforms.join(' ,')] end end ## # An error that indicates we weren't able to fetch some # data from a source class SourceFetchProblem < ErrorReason ## # Creates a new SourceFetchProblem for the given +source+ and +error+. def initialize(source, error) @source = source @error = error end ## # The source that had the fetch problem. attr_reader :source ## # The fetch error which is an Exception subclass. attr_reader :error ## # An English description of the error. def wordy "Unable to download data from #{@source.uri} - #{@error.message}" end ## # The "exception" alias allows you to call raise on a SourceFetchProblem. alias exception error end end PK!%2.2.0/rubygems/gemcutter_utilities.rbnu[require 'rubygems/remote_fetcher' ## # Utility methods for using the RubyGems API. module Gem::GemcutterUtilities # TODO: move to Gem::Command OptionParser.accept Symbol do |value| value.to_sym end attr_writer :host ## # Add the --key option def add_key_option add_option('-k', '--key KEYNAME', Symbol, 'Use the given API key', 'from ~/.gem/credentials') do |value,options| options[:key] = value end end ## # The API key from the command options or from the user's configuration. def api_key if options[:key] then verify_api_key options[:key] elsif Gem.configuration.api_keys.key?(host) Gem.configuration.api_keys[host] else Gem.configuration.rubygems_api_key end end ## # The host to connect to either from the RUBYGEMS_HOST environment variable # or from the user's configuration def host configured_host = Gem.host unless Gem.configuration.disable_default_gem_server @host ||= begin env_rubygems_host = ENV['RUBYGEMS_HOST'] env_rubygems_host = nil if env_rubygems_host and env_rubygems_host.empty? env_rubygems_host|| configured_host end end ## # Creates an RubyGems API to +host+ and +path+ with the given HTTP +method+. # # If +allowed_push_host+ metadata is present, then it will only allow that host. def rubygems_api_request(method, path, host = nil, allowed_push_host = nil, &block) require 'net/http' self.host = host if host unless self.host alert_error "You must specify a gem server" terminate_interaction 1 # TODO: question this end if allowed_push_host and self.host != allowed_push_host alert_error "#{self.host.inspect} is not allowed by the gemspec, which only allows #{allowed_push_host.inspect}" terminate_interaction 1 end uri = URI.parse "#{self.host}/#{path}" request_method = Net::HTTP.const_get method.to_s.capitalize Gem::RemoteFetcher.fetcher.request(uri, request_method, &block) end ## # Signs in with the RubyGems API at +sign_in_host+ and sets the rubygems API # key. def sign_in sign_in_host = nil sign_in_host ||= self.host return if api_key pretty_host = if Gem::DEFAULT_HOST == sign_in_host then 'RubyGems.org' else sign_in_host end say "Enter your #{pretty_host} credentials." say "Don't have an account yet? " + "Create one at #{sign_in_host}/sign_up" email = ask " Email: " password = ask_for_password "Password: " say "\n" response = rubygems_api_request(:get, "api/v1/api_key", sign_in_host) do |request| request.basic_auth email, password end with_response response do |resp| say "Signed in." Gem.configuration.rubygems_api_key = resp.body end end ## # Retrieves the pre-configured API key +key+ or terminates interaction with # an error. def verify_api_key(key) if Gem.configuration.api_keys.key? key then Gem.configuration.api_keys[key] else alert_error "No such API key. Please add it to your configuration (done automatically on initial `gem push`)." terminate_interaction 1 # TODO: question this end end ## # If +response+ is an HTTP Success (2XX) response, yields the response if a # block was given or shows the response body to the user. # # If the response was not successful, shows an error to the user including # the +error_prefix+ and the response body. def with_response response, error_prefix = nil case response when Net::HTTPSuccess then if block_given? then yield response else say response.body end else message = response.body message = "#{error_prefix}: #{message}" if error_prefix say message terminate_interaction 1 # TODO: question this end end end PK!F ?7?7&2.2.0/rubygems/dependency_installer.rbnu[require 'rubygems' require 'rubygems/dependency_list' require 'rubygems/package' require 'rubygems/installer' require 'rubygems/spec_fetcher' require 'rubygems/user_interaction' require 'rubygems/source' require 'rubygems/available_set' ## # Installs a gem along with all its dependencies from local and remote gems. class Gem::DependencyInstaller include Gem::UserInteraction DEFAULT_OPTIONS = { # :nodoc: :env_shebang => false, :document => %w[ri], :domain => :both, # HACK dup :force => false, :format_executable => false, # HACK dup :ignore_dependencies => false, :prerelease => false, :security_policy => nil, # HACK NoSecurity requires OpenSSL. AlmostNo? Low? :wrappers => true, :build_args => nil, :build_docs_in_background => false, :install_as_default => false }.freeze ## # Documentation types. For use by the Gem.done_installing hook attr_reader :document ## # Errors from SpecFetcher while searching for remote specifications attr_reader :errors ## #-- # TODO remove, no longer used attr_reader :gems_to_install # :nodoc: ## # List of gems installed by #install in alphabetic order attr_reader :installed_gems ## # Creates a new installer instance. # # Options are: # :cache_dir:: Alternate repository path to store .gem files in. # :domain:: :local, :remote, or :both. :local only searches gems in the # current directory. :remote searches only gems in Gem::sources. # :both searches both. # :env_shebang:: See Gem::Installer::new. # :force:: See Gem::Installer#install. # :format_executable:: See Gem::Installer#initialize. # :ignore_dependencies:: Don't install any dependencies. # :install_dir:: See Gem::Installer#install. # :prerelease:: Allow prerelease versions. See #install. # :security_policy:: See Gem::Installer::new and Gem::Security. # :user_install:: See Gem::Installer.new # :wrappers:: See Gem::Installer::new # :build_args:: See Gem::Installer::new def initialize options = {} @only_install_dir = !!options[:install_dir] @install_dir = options[:install_dir] || Gem.dir @build_root = options[:build_root] options = DEFAULT_OPTIONS.merge options @bin_dir = options[:bin_dir] @dev_shallow = options[:dev_shallow] @development = options[:development] @document = options[:document] @domain = options[:domain] @env_shebang = options[:env_shebang] @force = options[:force] @format_executable = options[:format_executable] @ignore_dependencies = options[:ignore_dependencies] @prerelease = options[:prerelease] @security_policy = options[:security_policy] @user_install = options[:user_install] @wrappers = options[:wrappers] @build_args = options[:build_args] @build_docs_in_background = options[:build_docs_in_background] @install_as_default = options[:install_as_default] # Indicates that we should not try to update any deps unless # we absolutely must. @minimal_deps = options[:minimal_deps] @available = nil @installed_gems = [] @toplevel_specs = nil @cache_dir = options[:cache_dir] || @install_dir @errors = [] end ## #-- # TODO remove, no longer used def add_found_dependencies to_do, dependency_list # :nodoc: seen = {} dependencies = Hash.new { |h, name| h[name] = Gem::Dependency.new name } until to_do.empty? do spec = to_do.shift # HACK why is spec nil? next if spec.nil? or seen[spec.name] seen[spec.name] = true deps = spec.runtime_dependencies if @development if @dev_shallow if @toplevel_specs.include? spec.full_name deps |= spec.development_dependencies end else deps |= spec.development_dependencies end end deps.each do |dep| dependencies[dep.name] = dependencies[dep.name].merge dep if @minimal_deps next if Gem::Specification.any? do |installed_spec| dep.name == installed_spec.name and dep.requirement.satisfied_by? installed_spec.version end end results = find_gems_with_sources(dep) results.sorted.each do |t| to_do.push t.spec end results.remove_installed! dep @available << results results.inject_into_list dependency_list end end dependency_list.remove_specs_unsatisfied_by dependencies end ## # Creates an AvailableSet to install from based on +dep_or_name+ and # +version+ def available_set_for dep_or_name, version # :nodoc: if String === dep_or_name then find_spec_by_name_and_version dep_or_name, version, @prerelease else dep = dep_or_name.dup dep.prerelease = @prerelease @available = find_gems_with_sources dep end @available.pick_best! end ## # Indicated, based on the requested domain, if local # gems should be considered. def consider_local? @domain == :both or @domain == :local end ## # Indicated, based on the requested domain, if remote # gems should be considered. def consider_remote? @domain == :both or @domain == :remote end ## # Returns a list of pairs of gemspecs and source_uris that match # Gem::Dependency +dep+ from both local (Dir.pwd) and remote (Gem.sources) # sources. Gems are sorted with newer gems preferred over older gems, and # local gems preferred over remote gems. def find_gems_with_sources dep, best_only=false # :nodoc: set = Gem::AvailableSet.new if consider_local? sl = Gem::Source::Local.new if spec = sl.find_gem(dep.name) if dep.matches_spec? spec set.add spec, sl end end end if consider_remote? begin # TODO this is pulled from #spec_for_dependency to allow # us to filter tuples before fetching specs. # tuples, errors = Gem::SpecFetcher.fetcher.search_for_dependency dep if best_only && !tuples.empty? tuples.sort! { |a,b| b[0].version <=> a[0].version } tuples = [tuples.first] end specs = [] tuples.each do |tup, source| begin spec = source.fetch_spec(tup) rescue Gem::RemoteFetcher::FetchError => e errors << Gem::SourceFetchProblem.new(source, e) else specs << [spec, source] end end if @errors @errors += errors else @errors = errors end set << specs rescue Gem::RemoteFetcher::FetchError => e # FIX if there is a problem talking to the network, we either need to always tell # the user (no really_verbose) or fail hard, not silently tell them that we just # couldn't find their requested gem. verbose do "Error fetching remote data:\t\t#{e.message}\n" \ "Falling back to local-only install" end @domain = :local end end set end ## # Finds a spec and the source_uri it came from for gem +gem_name+ and # +version+. Returns an Array of specs and sources required for # installation of the gem. def find_spec_by_name_and_version gem_name, version = Gem::Requirement.default, prerelease = false set = Gem::AvailableSet.new if consider_local? if gem_name =~ /\.gem$/ and File.file? gem_name then src = Gem::Source::SpecificFile.new(gem_name) set.add src.spec, src elsif gem_name =~ /\.gem$/ then Dir[gem_name].each do |name| begin src = Gem::Source::SpecificFile.new name set.add src.spec, src rescue Gem::Package::FormatError end end else local = Gem::Source::Local.new if s = local.find_gem(gem_name, version) set.add s, local end end end if set.empty? dep = Gem::Dependency.new gem_name, version dep.prerelease = true if prerelease set = find_gems_with_sources(dep, true) set.match_platform! end if set.empty? raise Gem::SpecificGemNotFoundException.new(gem_name, version, @errors) end @available = set end ## # Gathers all dependencies necessary for the installation from local and # remote sources unless the ignore_dependencies was given. #-- # TODO remove at RubyGems 3 def gather_dependencies # :nodoc: specs = @available.all_specs # these gems were listed by the user, always install them keep_names = specs.map { |spec| spec.full_name } if @dev_shallow @toplevel_specs = keep_names end dependency_list = Gem::DependencyList.new @development dependency_list.add(*specs) to_do = specs.dup add_found_dependencies to_do, dependency_list unless @ignore_dependencies # REFACTOR maybe abstract away using Gem::Specification.include? so # that this isn't dependent only on the currently installed gems dependency_list.specs.reject! { |spec| not keep_names.include?(spec.full_name) and Gem::Specification.include?(spec) } unless dependency_list.ok? or @ignore_dependencies or @force then reason = dependency_list.why_not_ok?.map { |k,v| "#{k} requires #{v.join(", ")}" }.join("; ") raise Gem::DependencyError, "Unable to resolve dependencies: #{reason}" end @gems_to_install = dependency_list.dependency_order.reverse end def in_background what # :nodoc: fork_happened = false if @build_docs_in_background and Process.respond_to?(:fork) begin Process.fork do yield end fork_happened = true say "#{what} in a background process." rescue NotImplementedError end end yield unless fork_happened end ## # Installs the gem +dep_or_name+ and all its dependencies. Returns an Array # of installed gem specifications. # # If the +:prerelease+ option is set and there is a prerelease for # +dep_or_name+ the prerelease version will be installed. # # Unless explicitly specified as a prerelease dependency, prerelease gems # that +dep_or_name+ depend on will not be installed. # # If c-1.a depends on b-1 and a-1.a and there is a gem b-1.a available then # c-1.a, b-1 and a-1.a will be installed. b-1.a will need to be installed # separately. def install dep_or_name, version = Gem::Requirement.default request_set = resolve_dependencies dep_or_name, version @installed_gems = [] options = { :bin_dir => @bin_dir, :build_args => @build_args, :document => @document, :env_shebang => @env_shebang, :force => @force, :format_executable => @format_executable, :ignore_dependencies => @ignore_dependencies, :prerelease => @prerelease, :security_policy => @security_policy, :user_install => @user_install, :wrappers => @wrappers, :build_root => @build_root, :install_as_default => @install_as_default } options[:install_dir] = @install_dir if @only_install_dir request_set.install options do |_, installer| @installed_gems << installer.spec if installer end @installed_gems.sort! # Since this is currently only called for docs, we can be lazy and just say # it's documentation. Ideally the hook adder could decide whether to be in # the background or not, and what to call it. in_background "Installing documentation" do Gem.done_installing_hooks.each do |hook| hook.call self, @installed_gems end end unless Gem.done_installing_hooks.empty? @installed_gems end def install_development_deps # :nodoc: if @development and @dev_shallow then :shallow elsif @development then :all else :none end end def resolve_dependencies dep_or_name, version # :nodoc: request_set = Gem::RequestSet.new request_set.development = @development request_set.development_shallow = @dev_shallow request_set.soft_missing = @force request_set.prerelease = @prerelease request_set.remote = false unless consider_remote? installer_set = Gem::Resolver::InstallerSet.new @domain installer_set.ignore_installed = @only_install_dir if consider_local? if dep_or_name =~ /\.gem$/ and File.file? dep_or_name then src = Gem::Source::SpecificFile.new dep_or_name installer_set.add_local dep_or_name, src.spec, src version = src.spec.version if version == Gem::Requirement.default elsif dep_or_name =~ /\.gem$/ then Dir[dep_or_name].each do |name| begin src = Gem::Source::SpecificFile.new name installer_set.add_local dep_or_name, src.spec, src rescue Gem::Package::FormatError end end # else This is a dependency. InstallerSet handles this case end end dependency = if spec = installer_set.local?(dep_or_name) then Gem::Dependency.new spec.name, version elsif String === dep_or_name then Gem::Dependency.new dep_or_name, version else dep_or_name end dependency.prerelease = @prerelease request_set.import [dependency] installer_set.add_always_install dependency request_set.always_install = installer_set.always_install if @ignore_dependencies then installer_set.ignore_dependencies = true request_set.ignore_dependencies = true request_set.soft_missing = true end request_set.resolve installer_set @errors.concat request_set.errors request_set end end PK!v!2.2.0/rubygems/command_manager.rbnu[#-- # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. # All rights reserved. # See LICENSE.txt for permissions. #++ require 'rubygems/command' require 'rubygems/user_interaction' ## # The command manager registers and installs all the individual sub-commands # supported by the gem command. # # Extra commands can be provided by writing a rubygems_plugin.rb # file in an installed gem. You should register your command against the # Gem::CommandManager instance, like this: # # # file rubygems_plugin.rb # require 'rubygems/command_manager' # # Gem::CommandManager.instance.register_command :edit # # You should put the implementation of your command in rubygems/commands. # # # file rubygems/commands/edit_command.rb # class Gem::Commands::EditCommand < Gem::Command # # ... # end # # See Gem::Command for instructions on writing gem commands. class Gem::CommandManager include Gem::UserInteraction BUILTIN_COMMANDS = [ # :nodoc: :build, :cert, :check, :cleanup, :contents, :dependency, :environment, :fetch, :generate_index, :help, :install, :list, :lock, :mirror, :open, :outdated, :owner, :pristine, :push, :query, :rdoc, :search, :server, :sources, :specification, :stale, :uninstall, :unpack, :update, :which, :yank, ] ## # Return the authoritative instance of the command manager. def self.instance @command_manager ||= new end ## # Returns self. Allows a CommandManager instance to stand # in for the class itself. def instance self end ## # Reset the authoritative instance of the command manager. def self.reset @command_manager = nil end ## # Register all the subcommands supported by the gem command. def initialize require 'timeout' @commands = {} BUILTIN_COMMANDS.each do |name| register_command name end end ## # Register the Symbol +command+ as a gem command. def register_command(command, obj=false) @commands[command] = obj end ## # Unregister the Symbol +command+ as a gem command. def unregister_command(command) @commands.delete command end ## # Returns a Command instance for +command_name+ def [](command_name) command_name = command_name.intern return nil if @commands[command_name].nil? @commands[command_name] ||= load_and_instantiate(command_name) end ## # Return a sorted list of all command names as strings. def command_names @commands.keys.collect {|key| key.to_s}.sort end ## # Run the command specified by +args+. def run(args, build_args=nil) process_args(args, build_args) rescue StandardError, Timeout::Error => ex alert_error "While executing gem ... (#{ex.class})\n #{ex}" ui.backtrace ex terminate_interaction(1) rescue Interrupt alert_error "Interrupted" terminate_interaction(1) end def process_args(args, build_args=nil) if args.empty? then say Gem::Command::HELP terminate_interaction 1 end case args.first when '-h', '--help' then say Gem::Command::HELP terminate_interaction 0 when '-v', '--version' then say Gem::VERSION terminate_interaction 0 when /^-/ then alert_error "Invalid option: #{args.first}. See 'gem --help'." terminate_interaction 1 else cmd_name = args.shift.downcase cmd = find_command cmd_name cmd.invoke_with_build_args args, build_args end end def find_command(cmd_name) possibilities = find_command_possibilities cmd_name if possibilities.size > 1 then raise Gem::CommandLineError, "Ambiguous command #{cmd_name} matches [#{possibilities.join(', ')}]" elsif possibilities.empty? then raise Gem::CommandLineError, "Unknown command #{cmd_name}" end self[possibilities.first] end def find_command_possibilities(cmd_name) len = cmd_name.length found = command_names.select { |name| cmd_name == name[0, len] } exact = found.find { |name| name == cmd_name } exact ? [exact] : found end private def load_and_instantiate(command_name) command_name = command_name.to_s const_name = command_name.capitalize.gsub(/_(.)/) { $1.upcase } << "Command" load_error = nil begin begin require "rubygems/commands/#{command_name}_command" rescue LoadError => e load_error = e end Gem::Commands.const_get(const_name).new rescue Exception => e e = load_error if load_error alert_error "Loading command: #{command_name} (#{e.class})\n\t#{e}" ui.backtrace e end end end PK!P!2.2.0/rubygems/install_message.rbnu[require 'rubygems' require 'rubygems/user_interaction' ## # A default post-install hook that displays "Successfully installed # some_gem-1.0" Gem.post_install do |installer| ui = Gem::DefaultUserInteraction.ui ui.say "Successfully installed #{installer.spec.full_name}" end PK!jNW02.2.0/rubygems/gem_runner.rbnu[#-- # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. # All rights reserved. # See LICENSE.txt for permissions. #++ require 'rubygems' require 'rubygems/command_manager' require 'rubygems/config_file' ## # Load additional plugins from $LOAD_PATH Gem.load_env_plugins rescue nil ## # Run an instance of the gem program. # # Gem::GemRunner is only intended for internal use by RubyGems itself. It # does not form any public API and may change at any time for any reason. # # If you would like to duplicate functionality of `gem` commands, use the # classes they call directly. class Gem::GemRunner def initialize(options={}) # TODO: nuke these options @command_manager_class = options[:command_manager] || Gem::CommandManager @config_file_class = options[:config_file] || Gem::ConfigFile end ## # Run the gem command with the following arguments. def run args build_args = extract_build_args args do_configuration args cmd = @command_manager_class.instance cmd.command_names.each do |command_name| config_args = Gem.configuration[command_name] config_args = case config_args when String config_args.split ' ' else Array(config_args) end Gem::Command.add_specific_extra_args command_name, config_args end cmd.run Gem.configuration.args, build_args end ## # Separates the build arguments (those following --) from the # other arguments in the list. def extract_build_args args # :nodoc: return [] unless offset = args.index('--') build_args = args.slice!(offset...args.length) build_args.shift build_args end private def do_configuration(args) Gem.configuration = @config_file_class.new(args) Gem.use_paths Gem.configuration[:gemhome], Gem.configuration[:gempath] Gem::Command.extra_args = Gem.configuration[:gem] end end Gem.load_plugins PK!+fHH2.2.0/rubygems/path_support.rbnu[## # # Gem::PathSupport facilitates the GEM_HOME and GEM_PATH environment settings # to the rest of RubyGems. # class Gem::PathSupport ## # The default system path for managing Gems. attr_reader :home ## # Array of paths to search for Gems. attr_reader :path ## # Directory with spec cache attr_reader :spec_cache_dir # :nodoc: ## # # Constructor. Takes a single argument which is to be treated like a # hashtable, or defaults to ENV, the system environment. # def initialize(env=ENV) @env = env # note 'env' vs 'ENV'... @home = env["GEM_HOME"] || ENV["GEM_HOME"] || Gem.default_dir if File::ALT_SEPARATOR then @home = @home.gsub(File::ALT_SEPARATOR, File::SEPARATOR) end self.path = env["GEM_PATH"] || ENV["GEM_PATH"] @spec_cache_dir = env["GEM_SPEC_CACHE"] || ENV["GEM_SPEC_CACHE"] || Gem.default_spec_cache_dir @spec_cache_dir = @spec_cache_dir.dup.untaint end private ## # Set the Gem home directory (as reported by Gem.dir). def home=(home) @home = home.to_s end ## # Set the Gem search path (as reported by Gem.path). def path=(gpaths) # FIX: it should be [home, *path], not [*path, home] gem_path = [] # FIX: I can't tell wtf this is doing. gpaths ||= (ENV['GEM_PATH'] || "").empty? ? nil : ENV["GEM_PATH"] if gpaths if gpaths.kind_of?(Array) gem_path = gpaths.dup else gem_path = gpaths.split(Gem.path_separator) end if File::ALT_SEPARATOR then gem_path.map! do |this_path| this_path.gsub File::ALT_SEPARATOR, File::SEPARATOR end end gem_path << @home else gem_path = Gem.default_path + [@home] if defined?(APPLE_GEM_HOME) gem_path << APPLE_GEM_HOME end end @path = gem_path.uniq end end PK!'N2.2.0/rubygems/request.rbnu[require 'net/http' require 'thread' require 'time' require 'rubygems/user_interaction' class Gem::Request include Gem::UserInteraction ### # Legacy. This is used in tests. def self.create_with_proxy uri, request_class, last_modified, proxy # :nodoc: cert_files = get_cert_files proxy ||= get_proxy_from_env(uri.scheme) pool = ConnectionPools.new proxy_uri(proxy), cert_files new(uri, request_class, last_modified, pool.pool_for(uri)) end def self.proxy_uri proxy # :nodoc: case proxy when :no_proxy then nil when URI::HTTP then proxy else URI.parse(proxy) end end def initialize(uri, request_class, last_modified, pool) @uri = uri @request_class = request_class @last_modified = last_modified @requests = Hash.new 0 @user_agent = user_agent @connection_pool = pool end def proxy_uri; @connection_pool.proxy_uri; end def cert_files; @connection_pool.cert_files; end def self.get_cert_files pattern = File.expand_path("./ssl_certs/*.pem", File.dirname(__FILE__)) Dir.glob(pattern) end def self.configure_connection_for_https(connection, cert_files) require 'net/https' connection.use_ssl = true connection.verify_mode = Gem.configuration.ssl_verify_mode || OpenSSL::SSL::VERIFY_PEER store = OpenSSL::X509::Store.new if Gem.configuration.ssl_client_cert then pem = File.read Gem.configuration.ssl_client_cert connection.cert = OpenSSL::X509::Certificate.new pem connection.key = OpenSSL::PKey::RSA.new pem end store.set_default_paths cert_files.each do |ssl_cert_file| store.add_file ssl_cert_file end if Gem.configuration.ssl_ca_cert if File.directory? Gem.configuration.ssl_ca_cert store.add_path Gem.configuration.ssl_ca_cert else store.add_file Gem.configuration.ssl_ca_cert end end connection.cert_store = store connection rescue LoadError => e raise unless (e.respond_to?(:path) && e.path == 'openssl') || e.message =~ / -- openssl$/ raise Gem::Exception.new( 'Unable to require openssl, install OpenSSL and rebuild ruby (preferred) or use non-HTTPS sources') end ## # Creates or an HTTP connection based on +uri+, or retrieves an existing # connection, using a proxy if needed. def connection_for(uri) @connection_pool.checkout rescue defined?(OpenSSL::SSL) ? OpenSSL::SSL::SSLError : Errno::EHOSTDOWN, Errno::EHOSTDOWN => e raise Gem::RemoteFetcher::FetchError.new(e.message, uri) end def fetch request = @request_class.new @uri.request_uri unless @uri.nil? || @uri.user.nil? || @uri.user.empty? then request.basic_auth Gem::UriFormatter.new(@uri.user).unescape, Gem::UriFormatter.new(@uri.password).unescape end request.add_field 'User-Agent', @user_agent request.add_field 'Connection', 'keep-alive' request.add_field 'Keep-Alive', '30' if @last_modified then request.add_field 'If-Modified-Since', @last_modified.httpdate end yield request if block_given? perform_request request end ## # Returns a proxy URI for the given +scheme+ if one is set in the # environment variables. def self.get_proxy_from_env scheme = 'http' _scheme = scheme.downcase _SCHEME = scheme.upcase env_proxy = ENV["#{_scheme}_proxy"] || ENV["#{_SCHEME}_PROXY"] no_env_proxy = env_proxy.nil? || env_proxy.empty? return get_proxy_from_env 'http' if no_env_proxy and _scheme != 'http' return :no_proxy if no_env_proxy uri = URI(Gem::UriFormatter.new(env_proxy).normalize) if uri and uri.user.nil? and uri.password.nil? then user = ENV["#{_scheme}_proxy_user"] || ENV["#{_SCHEME}_PROXY_USER"] password = ENV["#{_scheme}_proxy_pass"] || ENV["#{_SCHEME}_PROXY_PASS"] uri.user = Gem::UriFormatter.new(user).escape uri.password = Gem::UriFormatter.new(password).escape end uri end def perform_request request # :nodoc: connection = connection_for @uri retried = false bad_response = false begin @requests[connection.object_id] += 1 verbose "#{request.method} #{@uri}" file_name = File.basename(@uri.path) # perform download progress reporter only for gems if request.response_body_permitted? && file_name =~ /\.gem$/ reporter = ui.download_reporter response = connection.request(request) do |incomplete_response| if Net::HTTPOK === incomplete_response reporter.fetch(file_name, incomplete_response.content_length) downloaded = 0 data = '' incomplete_response.read_body do |segment| data << segment downloaded += segment.length reporter.update(downloaded) end reporter.done if incomplete_response.respond_to? :body= incomplete_response.body = data else incomplete_response.instance_variable_set(:@body, data) end end end else response = connection.request request end verbose "#{response.code} #{response.message}" rescue Net::HTTPBadResponse verbose "bad response" reset connection raise Gem::RemoteFetcher::FetchError.new('too many bad responses', @uri) if bad_response bad_response = true retry # HACK work around EOFError bug in Net::HTTP # NOTE Errno::ECONNABORTED raised a lot on Windows, and make impossible # to install gems. rescue EOFError, Timeout::Error, Errno::ECONNABORTED, Errno::ECONNRESET, Errno::EPIPE requests = @requests[connection.object_id] verbose "connection reset after #{requests} requests, retrying" raise Gem::RemoteFetcher::FetchError.new('too many connection resets', @uri) if retried reset connection retried = true retry end response ensure @connection_pool.checkin connection end ## # Resets HTTP connection +connection+. def reset(connection) @requests.delete connection.object_id connection.finish connection.start end def user_agent ua = "RubyGems/#{Gem::VERSION} #{Gem::Platform.local}" ruby_version = RUBY_VERSION ruby_version += 'dev' if RUBY_PATCHLEVEL == -1 ua << " Ruby/#{ruby_version} (#{RUBY_RELEASE_DATE}" if RUBY_PATCHLEVEL >= 0 then ua << " patchlevel #{RUBY_PATCHLEVEL}" elsif defined?(RUBY_REVISION) then ua << " revision #{RUBY_REVISION}" end ua << ")" ua << " #{RUBY_ENGINE}" if defined?(RUBY_ENGINE) and RUBY_ENGINE != 'ruby' ua end end require 'rubygems/request/http_pool' require 'rubygems/request/https_pool' require 'rubygems/request/connection_pools' PK!{;;2.2.0/rubygems/package.rbnu[# -*- coding: utf-8 -*- #-- # Copyright (C) 2004 Mauricio Julio Fernández Pradier # See LICENSE.txt for additional licensing information. #++ # # Example using a Gem::Package # # Builds a .gem file given a Gem::Specification. A .gem file is a tarball # which contains a data.tar.gz and metadata.gz, and possibly signatures. # # require 'rubygems' # require 'rubygems/package' # # spec = Gem::Specification.new do |s| # s.summary = "Ruby based make-like utility." # s.name = 'rake' # s.version = PKG_VERSION # s.requirements << 'none' # s.files = PKG_FILES # s.description = <<-EOF # Rake is a Make-like program implemented in Ruby. Tasks # and dependencies are specified in standard Ruby syntax. # EOF # end # # Gem::Package.build spec # # Reads a .gem file. # # require 'rubygems' # require 'rubygems/package' # # the_gem = Gem::Package.new(path_to_dot_gem) # the_gem.contents # get the files in the gem # the_gem.extract_files destination_directory # extract the gem into a directory # the_gem.spec # get the spec out of the gem # the_gem.verify # check the gem is OK (contains valid gem specification, contains a not corrupt contents archive) # # #files are the files in the .gem tar file, not the Ruby files in the gem # #extract_files and #contents automatically call #verify require 'rubygems/security' require 'rubygems/specification' require 'rubygems/user_interaction' require 'zlib' class Gem::Package include Gem::UserInteraction class Error < Gem::Exception; end class FormatError < Error attr_reader :path def initialize message, source = nil if source @path = source.path message << " in #{path}" if path end super message end end class PathError < Error def initialize destination, destination_dir super "installing into parent path %s of %s is not allowed" % [destination, destination_dir] end end class NonSeekableIO < Error; end class TooLongFileName < Error; end ## # Raised when a tar file is corrupt class TarInvalidError < Error; end attr_accessor :build_time # :nodoc: ## # Checksums for the contents of the package attr_reader :checksums ## # The files in this package. This is not the contents of the gem, just the # files in the top-level container. attr_reader :files ## # The security policy used for verifying the contents of this package. attr_accessor :security_policy ## # Sets the Gem::Specification to use to build this package. attr_writer :spec def self.build spec, skip_validation=false gem_file = spec.file_name package = new gem_file package.spec = spec package.build skip_validation gem_file end ## # Creates a new Gem::Package for the file at +gem+. +gem+ can also be # provided as an IO object. # # If +gem+ is an existing file in the old format a Gem::Package::Old will be # returned. def self.new gem gem = if gem.is_a?(Gem::Package::Source) gem elsif gem.respond_to? :read Gem::Package::IOSource.new gem else Gem::Package::FileSource.new gem end return super(gem) unless Gem::Package == self return super unless gem.present? return super unless gem.start return super unless gem.start.include? 'MD5SUM =' Gem::Package::Old.new gem end ## # Creates a new package that will read or write to the file +gem+. def initialize gem # :notnew: @gem = gem @build_time = Time.now @checksums = {} @contents = nil @digests = Hash.new { |h, algorithm| h[algorithm] = {} } @files = nil @security_policy = nil @signatures = {} @signer = nil @spec = nil end ## # Adds a checksum for each entry in the gem to checksums.yaml.gz. def add_checksums tar Gem.load_yaml checksums_by_algorithm = Hash.new { |h, algorithm| h[algorithm] = {} } @checksums.each do |name, digests| digests.each do |algorithm, digest| checksums_by_algorithm[algorithm][name] = digest.hexdigest end end tar.add_file_signed 'checksums.yaml.gz', 0444, @signer do |io| gzip_to io do |gz_io| YAML.dump checksums_by_algorithm, gz_io end end end ## # Adds the files listed in the packages's Gem::Specification to data.tar.gz # and adds this file to the +tar+. def add_contents tar # :nodoc: digests = tar.add_file_signed 'data.tar.gz', 0444, @signer do |io| gzip_to io do |gz_io| Gem::Package::TarWriter.new gz_io do |data_tar| add_files data_tar end end end @checksums['data.tar.gz'] = digests end ## # Adds files included the package's Gem::Specification to the +tar+ file def add_files tar # :nodoc: @spec.files.each do |file| stat = File.stat file next unless stat.file? tar.add_file_simple file, stat.mode, stat.size do |dst_io| open file, 'rb' do |src_io| dst_io.write src_io.read 16384 until src_io.eof? end end end end ## # Adds the package's Gem::Specification to the +tar+ file def add_metadata tar # :nodoc: digests = tar.add_file_signed 'metadata.gz', 0444, @signer do |io| gzip_to io do |gz_io| gz_io.write @spec.to_yaml end end @checksums['metadata.gz'] = digests end ## # Builds this package based on the specification set by #spec= def build skip_validation = false Gem.load_yaml require 'rubygems/security' @spec.mark_version @spec.validate unless skip_validation setup_signer @gem.with_write_io do |gem_io| Gem::Package::TarWriter.new gem_io do |gem| add_metadata gem add_contents gem add_checksums gem end end say <<-EOM Successfully built RubyGem Name: #{@spec.name} Version: #{@spec.version} File: #{File.basename @spec.cache_file} EOM ensure @signer = nil end ## # A list of file names contained in this gem def contents return @contents if @contents verify unless @spec @contents = [] @gem.with_read_io do |io| gem_tar = Gem::Package::TarReader.new io gem_tar.each do |entry| next unless entry.full_name == 'data.tar.gz' open_tar_gz entry do |pkg_tar| pkg_tar.each do |contents_entry| @contents << contents_entry.full_name end end return @contents end end end ## # Creates a digest of the TarEntry +entry+ from the digest algorithm set by # the security policy. def digest entry # :nodoc: algorithms = if @checksums then @checksums.keys else [Gem::Security::DIGEST_NAME].compact end algorithms.each do |algorithm| digester = if defined?(OpenSSL::Digest) then OpenSSL::Digest.new algorithm else Digest.const_get(algorithm).new end digester << entry.read(16384) until entry.eof? entry.rewind @digests[algorithm][entry.full_name] = digester end @digests end ## # Extracts the files in this package into +destination_dir+ # # If +pattern+ is specified, only entries matching that glob will be # extracted. def extract_files destination_dir, pattern = "*" verify unless @spec FileUtils.mkdir_p destination_dir @gem.with_read_io do |io| reader = Gem::Package::TarReader.new io reader.each do |entry| next unless entry.full_name == 'data.tar.gz' extract_tar_gz entry, destination_dir, pattern return # ignore further entries end end end ## # Extracts all the files in the gzipped tar archive +io+ into # +destination_dir+. # # If an entry in the archive contains a relative path above # +destination_dir+ or an absolute path is encountered an exception is # raised. # # If +pattern+ is specified, only entries matching that glob will be # extracted. def extract_tar_gz io, destination_dir, pattern = "*" # :nodoc: open_tar_gz io do |tar| tar.each do |entry| next unless File.fnmatch pattern, entry.full_name, File::FNM_DOTMATCH destination = install_location entry.full_name, destination_dir FileUtils.rm_rf destination mkdir_options = {} mkdir_options[:mode] = entry.header.mode if entry.directory? mkdir = if entry.directory? then destination else File.dirname destination end FileUtils.mkdir_p mkdir, mkdir_options open destination, 'wb' do |out| out.write entry.read FileUtils.chmod entry.header.mode, destination end if entry.file? verbose destination end end end ## # Gzips content written to +gz_io+ to +io+. #-- # Also sets the gzip modification time to the package build time to ease # testing. def gzip_to io # :yields: gz_io gz_io = Zlib::GzipWriter.new io, Zlib::BEST_COMPRESSION gz_io.mtime = @build_time yield gz_io ensure gz_io.close end ## # Returns the full path for installing +filename+. # # If +filename+ is not inside +destination_dir+ an exception is raised. def install_location filename, destination_dir # :nodoc: raise Gem::Package::PathError.new(filename, destination_dir) if filename.start_with? '/' destination_dir = File.realpath destination_dir if File.respond_to? :realpath destination_dir = File.expand_path destination_dir destination = File.join destination_dir, filename destination = File.expand_path destination raise Gem::Package::PathError.new(destination, destination_dir) unless destination.start_with? destination_dir + '/' destination.untaint destination end ## # Loads a Gem::Specification from the TarEntry +entry+ def load_spec entry # :nodoc: case entry.full_name when 'metadata' then @spec = Gem::Specification.from_yaml entry.read when 'metadata.gz' then args = [entry] args << { :external_encoding => Encoding::UTF_8 } if Object.const_defined?(:Encoding) && Zlib::GzipReader.method(:wrap).arity != 1 Zlib::GzipReader.wrap(*args) do |gzio| @spec = Gem::Specification.from_yaml gzio.read end end end ## # Opens +io+ as a gzipped tar archive def open_tar_gz io # :nodoc: Zlib::GzipReader.wrap io do |gzio| tar = Gem::Package::TarReader.new gzio yield tar end end ## # Reads and loads checksums.yaml.gz from the tar file +gem+ def read_checksums gem Gem.load_yaml @checksums = gem.seek 'checksums.yaml.gz' do |entry| Zlib::GzipReader.wrap entry do |gz_io| Gem::SafeYAML.safe_load gz_io.read end end end ## # Prepares the gem for signing and checksum generation. If a signing # certificate and key are not present only checksum generation is set up. def setup_signer passphrase = ENV['GEM_PRIVATE_KEY_PASSPHRASE'] if @spec.signing_key then @signer = Gem::Security::Signer.new @spec.signing_key, @spec.cert_chain, passphrase @spec.signing_key = nil @spec.cert_chain = @signer.cert_chain.map { |cert| cert.to_s } else @signer = Gem::Security::Signer.new nil, nil, passphrase @spec.cert_chain = @signer.cert_chain.map { |cert| cert.to_pem } if @signer.cert_chain end end ## # The spec for this gem. # # If this is a package for a built gem the spec is loaded from the # gem and returned. If this is a package for a gem being built the provided # spec is returned. def spec verify unless @spec @spec end ## # Verifies that this gem: # # * Contains a valid gem specification # * Contains a contents archive # * The contents archive is not corrupt # # After verification the gem specification from the gem is available from # #spec def verify @files = [] @spec = nil @gem.with_read_io do |io| Gem::Package::TarReader.new io do |reader| read_checksums reader verify_files reader end end verify_checksums @digests, @checksums @security_policy.verify_signatures @spec, @digests, @signatures if @security_policy true rescue Gem::Security::Exception @spec = nil @files = [] raise rescue Errno::ENOENT => e raise Gem::Package::FormatError.new e.message rescue Gem::Package::TarInvalidError => e raise Gem::Package::FormatError.new e.message, @gem end ## # Verifies the +checksums+ against the +digests+. This check is not # cryptographically secure. Missing checksums are ignored. def verify_checksums digests, checksums # :nodoc: return unless checksums checksums.sort.each do |algorithm, gem_digests| gem_digests.sort.each do |file_name, gem_hexdigest| computed_digest = digests[algorithm][file_name] unless computed_digest.hexdigest == gem_hexdigest then raise Gem::Package::FormatError.new \ "#{algorithm} checksum mismatch for #{file_name}", @gem end end end end ## # Verifies +entry+ in a .gem file. def verify_entry entry file_name = entry.full_name @files << file_name case file_name when /\.sig$/ then @signatures[$`] = entry.read if @security_policy return else digest entry end case file_name when /^metadata(.gz)?$/ then load_spec entry when 'data.tar.gz' then verify_gz entry end rescue => e message = "package is corrupt, exception while verifying: " + "#{e.message} (#{e.class})" raise Gem::Package::FormatError.new message, @gem end ## # Verifies the files of the +gem+ def verify_files gem gem.each do |entry| verify_entry entry end unless @spec then raise Gem::Package::FormatError.new 'package metadata is missing', @gem end unless @files.include? 'data.tar.gz' then raise Gem::Package::FormatError.new \ 'package content (data.tar.gz) is missing', @gem end if duplicates = @files.group_by {|f| f }.select {|k,v| v.size > 1 }.map(&:first) and duplicates.any? raise Gem::Security::Exception, "duplicate files in the package: (#{duplicates.map(&:inspect).join(', ')})" end end ## # Verifies that +entry+ is a valid gzipped file. def verify_gz entry # :nodoc: Zlib::GzipReader.wrap entry do |gzio| gzio.read 16384 until gzio.eof? # gzip checksum verification end rescue Zlib::GzipFile::Error => e raise Gem::Package::FormatError.new(e.message, entry.full_name) end end require 'rubygems/package/digest_io' require 'rubygems/package/source' require 'rubygems/package/file_source' require 'rubygems/package/io_source' require 'rubygems/package/old' require 'rubygems/package/tar_header' require 'rubygems/package/tar_reader' require 'rubygems/package/tar_reader/entry' require 'rubygems/package/tar_writer' PK!OO 2.2.0/rubygems/version_option.rbnu[#-- # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. # All rights reserved. # See LICENSE.txt for permissions. #++ require 'rubygems' ## # Mixin methods for --version and --platform Gem::Command options. module Gem::VersionOption ## # Add the --platform option to the option parser. def add_platform_option(task = command, *wrap) OptionParser.accept Gem::Platform do |value| if value == Gem::Platform::RUBY then value else Gem::Platform.new value end end add_option('--platform PLATFORM', Gem::Platform, "Specify the platform of gem to #{task}", *wrap) do |value, options| unless options[:added_platform] then Gem.platforms = [Gem::Platform::RUBY] options[:added_platform] = true end Gem.platforms << value unless Gem.platforms.include? value end end ## # Add the --prerelease option to the option parser. def add_prerelease_option(*wrap) add_option("--[no-]prerelease", "Allow prerelease versions of a gem", *wrap) do |value, options| options[:prerelease] = value options[:explicit_prerelease] = true end end ## # Add the --version option to the option parser. def add_version_option(task = command, *wrap) OptionParser.accept Gem::Requirement do |value| Gem::Requirement.new(*value.split(/\s*,\s*/)) end add_option('-v', '--version VERSION', Gem::Requirement, "Specify version of gem to #{task}", *wrap) do |value, options| options[:version] = value explicit_prerelease_set = !options[:explicit_prerelease].nil? options[:explicit_prerelease] = false unless explicit_prerelease_set options[:prerelease] = value.prerelease? unless options[:explicit_prerelease] end end end PK!e 2.2.0/rubygems/deprecate.rbnu[## # Provides a single method +deprecate+ to be used to declare when # something is going away. # # class Legacy # def self.klass_method # # ... # end # # def instance_method # # ... # end # # extend Gem::Deprecate # deprecate :instance_method, "X.z", 2011, 4 # # class << self # extend Gem::Deprecate # deprecate :klass_method, :none, 2011, 4 # end # end module Gem::Deprecate def self.skip # :nodoc: @skip ||= false end def self.skip= v # :nodoc: @skip = v end ## # Temporarily turn off warnings. Intended for tests only. def skip_during Gem::Deprecate.skip, original = true, Gem::Deprecate.skip yield ensure Gem::Deprecate.skip = original end ## # Simple deprecation method that deprecates +name+ by wrapping it up # in a dummy method. It warns on each call to the dummy method # telling the user of +repl+ (unless +repl+ is :none) and the # year/month that it is planned to go away. def deprecate name, repl, year, month class_eval { old = "_deprecated_#{name}" alias_method old, name define_method name do |*args, &block| klass = self.kind_of? Module target = klass ? "#{self}." : "#{self.class}#" msg = [ "NOTE: #{target}#{name} is deprecated", repl == :none ? " with no replacement" : "; use #{repl} instead", ". It will be removed on or after %4d-%02d-01." % [year, month], "\n#{target}#{name} called from #{Gem.location_of_caller.join(":")}", ] warn "#{msg.join}." unless Gem::Deprecate.skip send old, *args, &block end } end module_function :deprecate, :skip_during end PK!PQ!!!2.2.0/rubygems/security/signer.rbnu[## # Basic OpenSSL-based package signing class. class Gem::Security::Signer ## # The chain of certificates for signing including the signing certificate attr_accessor :cert_chain ## # The private key for the signing certificate attr_accessor :key ## # The digest algorithm used to create the signature attr_reader :digest_algorithm ## # The name of the digest algorithm, used to pull digests out of the hash by # name. attr_reader :digest_name # :nodoc: ## # Creates a new signer with an RSA +key+ or path to a key, and a certificate # +chain+ containing X509 certificates, encoding certificates or paths to # certificates. def initialize key, cert_chain, passphrase = nil @cert_chain = cert_chain @key = key unless @key then default_key = File.join Gem.default_key_path @key = default_key if File.exist? default_key end unless @cert_chain then default_cert = File.join Gem.default_cert_path @cert_chain = [default_cert] if File.exist? default_cert end @digest_algorithm = Gem::Security::DIGEST_ALGORITHM @digest_name = Gem::Security::DIGEST_NAME @key = OpenSSL::PKey::RSA.new File.read(@key), passphrase if @key and not OpenSSL::PKey::RSA === @key if @cert_chain then @cert_chain = @cert_chain.compact.map do |cert| next cert if OpenSSL::X509::Certificate === cert cert = File.read cert if File.exist? cert OpenSSL::X509::Certificate.new cert end load_cert_chain end end ## # Extracts the full name of +cert+. If the certificate has a subjectAltName # this value is preferred, otherwise the subject is used. def extract_name cert # :nodoc: subject_alt_name = cert.extensions.find { |e| 'subjectAltName' == e.oid } if subject_alt_name then /\Aemail:/ =~ subject_alt_name.value $' || subject_alt_name.value else cert.subject end end ## # Loads any missing issuers in the cert chain from the trusted certificates. # # If the issuer does not exist it is ignored as it will be checked later. def load_cert_chain # :nodoc: return if @cert_chain.empty? while @cert_chain.first.issuer.to_s != @cert_chain.first.subject.to_s do issuer = Gem::Security.trust_dir.issuer_of @cert_chain.first break unless issuer # cert chain is verified later @cert_chain.unshift issuer end end ## # Sign data with given digest algorithm def sign data return unless @key if @cert_chain.length == 1 and @cert_chain.last.not_after < Time.now then re_sign_key end full_name = extract_name @cert_chain.last Gem::Security::SigningPolicy.verify @cert_chain, @key, {}, {}, full_name @key.sign @digest_algorithm.new, data end ## # Attempts to re-sign the private key if the signing certificate is expired. # # The key will be re-signed if: # * The expired certificate is self-signed # * The expired certificate is saved at ~/.gem/gem-public_cert.pem # * There is no file matching the expiry date at # ~/.gem/gem-public_cert.pem.expired.%Y%m%d%H%M%S # # If the signing certificate can be re-signed the expired certificate will # be saved as ~/.gem/gem-pubilc_cert.pem.expired.%Y%m%d%H%M%S where the # expiry time (not after) is used for the timestamp. def re_sign_key # :nodoc: old_cert = @cert_chain.last disk_cert_path = File.join Gem.default_cert_path disk_cert = File.read disk_cert_path rescue nil disk_key = File.read File.join(Gem.default_key_path) rescue nil if disk_key == @key.to_pem and disk_cert == old_cert.to_pem then expiry = old_cert.not_after.strftime '%Y%m%d%H%M%S' old_cert_file = "gem-public_cert.pem.expired.#{expiry}" old_cert_path = File.join Gem.user_home, ".gem", old_cert_file unless File.exist? old_cert_path then Gem::Security.write old_cert, old_cert_path cert = Gem::Security.re_sign old_cert, @key Gem::Security.write cert, disk_cert_path @cert_chain = [cert] end end end end PK!36/ $2.2.0/rubygems/security/trust_dir.rbnu[## # The TrustDir manages the trusted certificates for gem signature # verification. class Gem::Security::TrustDir ## # Default permissions for the trust directory and its contents DEFAULT_PERMISSIONS = { :trust_dir => 0700, :trusted_cert => 0600, } ## # The directory where trusted certificates will be stored. attr_reader :dir ## # Creates a new TrustDir using +dir+ where the directory and file # permissions will be checked according to +permissions+ def initialize dir, permissions = DEFAULT_PERMISSIONS @dir = dir @permissions = permissions @digester = Gem::Security::DIGEST_ALGORITHM end ## # Returns the path to the trusted +certificate+ def cert_path certificate name_path certificate.subject end ## # Enumerates trusted certificates. def each_certificate return enum_for __method__ unless block_given? glob = File.join @dir, '*.pem' Dir[glob].each do |certificate_file| begin certificate = load_certificate certificate_file yield certificate, certificate_file rescue OpenSSL::X509::CertificateError next # HACK warn end end end ## # Returns the issuer certificate of the given +certificate+ if it exists in # the trust directory. def issuer_of certificate path = name_path certificate.issuer return unless File.exist? path load_certificate path end ## # Returns the path to the trusted certificate with the given ASN.1 +name+ def name_path name digest = @digester.hexdigest name.to_s File.join @dir, "cert-#{digest}.pem" end ## # Loads the given +certificate_file+ def load_certificate certificate_file pem = File.read certificate_file OpenSSL::X509::Certificate.new pem end ## # Add a certificate to trusted certificate list. def trust_cert certificate verify destination = cert_path certificate open destination, 'wb', @permissions[:trusted_cert] do |io| io.write certificate.to_pem end end ## # Make sure the trust directory exists. If it does exist, make sure it's # actually a directory. If not, then create it with the appropriate # permissions. def verify if File.exist? @dir then raise Gem::Security::Exception, "trust directory #{@dir} is not a directory" unless File.directory? @dir FileUtils.chmod 0700, @dir else FileUtils.mkdir_p @dir, :mode => @permissions[:trust_dir] end end end PK!6Pl!2.2.0/rubygems/security/policy.rbnu[require 'rubygems/user_interaction' ## # A Gem::Security::Policy object encapsulates the settings for verifying # signed gem files. This is the base class. You can either declare an # instance of this or use one of the preset security policies in # Gem::Security::Policies. class Gem::Security::Policy include Gem::UserInteraction attr_reader :name attr_accessor :only_signed attr_accessor :only_trusted attr_accessor :verify_chain attr_accessor :verify_data attr_accessor :verify_root attr_accessor :verify_signer ## # Create a new Gem::Security::Policy object with the given mode and # options. def initialize name, policy = {}, opt = {} require 'openssl' @name = name @opt = opt # Default to security @only_signed = true @only_trusted = true @verify_chain = true @verify_data = true @verify_root = true @verify_signer = true policy.each_pair do |key, val| case key when :verify_data then @verify_data = val when :verify_signer then @verify_signer = val when :verify_chain then @verify_chain = val when :verify_root then @verify_root = val when :only_trusted then @only_trusted = val when :only_signed then @only_signed = val end end end ## # Verifies each certificate in +chain+ has signed the following certificate # and is valid for the given +time+. def check_chain chain, time raise Gem::Security::Exception, 'missing signing chain' unless chain raise Gem::Security::Exception, 'empty signing chain' if chain.empty? begin chain.each_cons 2 do |issuer, cert| check_cert cert, issuer, time end true rescue Gem::Security::Exception => e raise Gem::Security::Exception, "invalid signing chain: #{e.message}" end end ## # Verifies that +data+ matches the +signature+ created by +public_key+ and # the +digest+ algorithm. def check_data public_key, digest, signature, data raise Gem::Security::Exception, "invalid signature" unless public_key.verify digest.new, signature, data.digest true end ## # Ensures that +signer+ is valid for +time+ and was signed by the +issuer+. # If the +issuer+ is +nil+ no verification is performed. def check_cert signer, issuer, time raise Gem::Security::Exception, 'missing signing certificate' unless signer message = "certificate #{signer.subject}" if not_before = signer.not_before and not_before > time then raise Gem::Security::Exception, "#{message} not valid before #{not_before}" end if not_after = signer.not_after and not_after < time then raise Gem::Security::Exception, "#{message} not valid after #{not_after}" end if issuer and not signer.verify issuer.public_key then raise Gem::Security::Exception, "#{message} was not issued by #{issuer.subject}" end true end ## # Ensures the public key of +key+ matches the public key in +signer+ def check_key signer, key unless signer and key then return true unless @only_signed raise Gem::Security::Exception, 'missing key or signature' end raise Gem::Security::Exception, "certificate #{signer.subject} does not match the signing key" unless signer.public_key.to_pem == key.public_key.to_pem true end ## # Ensures the root certificate in +chain+ is self-signed and valid for # +time+. def check_root chain, time raise Gem::Security::Exception, 'missing signing chain' unless chain root = chain.first raise Gem::Security::Exception, 'missing root certificate' unless root raise Gem::Security::Exception, "root certificate #{root.subject} is not self-signed " + "(issuer #{root.issuer})" if root.issuer.to_s != root.subject.to_s # HACK to_s is for ruby 1.8 check_cert root, root, time end ## # Ensures the root of +chain+ has a trusted certificate in +trust_dir+ and # the digests of the two certificates match according to +digester+ def check_trust chain, digester, trust_dir raise Gem::Security::Exception, 'missing signing chain' unless chain root = chain.first raise Gem::Security::Exception, 'missing root certificate' unless root path = Gem::Security.trust_dir.cert_path root unless File.exist? path then message = "root cert #{root.subject} is not trusted" message << " (root of signing cert #{chain.last.subject})" if chain.length > 1 raise Gem::Security::Exception, message end save_cert = OpenSSL::X509::Certificate.new File.read path save_dgst = digester.digest save_cert.public_key.to_s pkey_str = root.public_key.to_s cert_dgst = digester.digest pkey_str raise Gem::Security::Exception, "trusted root certificate #{root.subject} checksum " + "does not match signing root certificate checksum" unless save_dgst == cert_dgst true end ## # Extracts the email or subject from +certificate+ def subject certificate # :nodoc: certificate.extensions.each do |extension| next unless extension.oid == 'subjectAltName' return extension.value end certificate.subject.to_s end def inspect # :nodoc: ("[Policy: %s - data: %p signer: %p chain: %p root: %p " + "signed-only: %p trusted-only: %p]") % [ @name, @verify_chain, @verify_data, @verify_root, @verify_signer, @only_signed, @only_trusted, ] end ## # For +full_name+, verifies the certificate +chain+ is valid, the +digests+ # match the signatures +signatures+ created by the signer depending on the # +policy+ settings. # # If +key+ is given it is used to validate the signing certificate. def verify chain, key = nil, digests = {}, signatures = {}, full_name = '(unknown)' if signatures.empty? then if @only_signed then raise Gem::Security::Exception, "unsigned gems are not allowed by the #{name} policy" elsif digests.empty? then # lack of signatures is irrelevant if there is nothing to check # against else alert_warning "#{full_name} is not signed" return end end opt = @opt digester = Gem::Security::DIGEST_ALGORITHM trust_dir = opt[:trust_dir] time = Time.now _, signer_digests = digests.find do |algorithm, file_digests| file_digests.values.first.name == Gem::Security::DIGEST_NAME end if @verify_data then raise Gem::Security::Exception, 'no digests provided (probable bug)' if signer_digests.nil? or signer_digests.empty? else signer_digests = {} end signer = chain.last check_key signer, key if key check_cert signer, nil, time if @verify_signer check_chain chain, time if @verify_chain check_root chain, time if @verify_root if @only_trusted then check_trust chain, digester, trust_dir elsif signatures.empty? and digests.empty? then # trust is irrelevant if there's no signatures to verify else alert_warning "#{subject signer} is not trusted for #{full_name}" end signatures.each do |file, _| digest = signer_digests[file] raise Gem::Security::Exception, "missing digest for #{file}" unless digest end signer_digests.each do |file, digest| signature = signatures[file] raise Gem::Security::Exception, "missing signature for #{file}" unless signature check_data signer.public_key, digester, signature, digest if @verify_data end true end ## # Extracts the certificate chain from the +spec+ and calls #verify to ensure # the signatures and certificate chain is valid according to the policy.. def verify_signatures spec, digests, signatures chain = spec.cert_chain.map do |cert_pem| OpenSSL::X509::Certificate.new cert_pem end verify chain, nil, digests, signatures, spec.full_name true end alias to_s name # :nodoc: end PK!(a5 5 #2.2.0/rubygems/security/policies.rbnu[module Gem::Security ## # No security policy: all package signature checks are disabled. NoSecurity = Policy.new( 'No Security', :verify_data => false, :verify_signer => false, :verify_chain => false, :verify_root => false, :only_trusted => false, :only_signed => false ) ## # AlmostNo security policy: only verify that the signing certificate is the # one that actually signed the data. Make no attempt to verify the signing # certificate chain. # # This policy is basically useless. better than nothing, but can still be # easily spoofed, and is not recommended. AlmostNoSecurity = Policy.new( 'Almost No Security', :verify_data => true, :verify_signer => false, :verify_chain => false, :verify_root => false, :only_trusted => false, :only_signed => false ) ## # Low security policy: only verify that the signing certificate is actually # the gem signer, and that the signing certificate is valid. # # This policy is better than nothing, but can still be easily spoofed, and # is not recommended. LowSecurity = Policy.new( 'Low Security', :verify_data => true, :verify_signer => true, :verify_chain => false, :verify_root => false, :only_trusted => false, :only_signed => false ) ## # Medium security policy: verify the signing certificate, verify the signing # certificate chain all the way to the root certificate, and only trust root # certificates that we have explicitly allowed trust for. # # This security policy is reasonable, but it allows unsigned packages, so a # malicious person could simply delete the package signature and pass the # gem off as unsigned. MediumSecurity = Policy.new( 'Medium Security', :verify_data => true, :verify_signer => true, :verify_chain => true, :verify_root => true, :only_trusted => true, :only_signed => false ) ## # High security policy: only allow signed gems to be installed, verify the # signing certificate, verify the signing certificate chain all the way to # the root certificate, and only trust root certificates that we have # explicitly allowed trust for. # # This security policy is significantly more difficult to bypass, and offers # a reasonable guarantee that the contents of the gem have not been altered. HighSecurity = Policy.new( 'High Security', :verify_data => true, :verify_signer => true, :verify_chain => true, :verify_root => true, :only_trusted => true, :only_signed => true ) ## # Policy used to verify a certificate and key when signing a gem SigningPolicy = Policy.new( 'Signing Policy', :verify_data => false, :verify_signer => true, :verify_chain => true, :verify_root => true, :only_trusted => false, :only_signed => false ) ## # Hash of configured security policies Policies = { 'NoSecurity' => NoSecurity, 'AlmostNoSecurity' => AlmostNoSecurity, 'LowSecurity' => LowSecurity, 'MediumSecurity' => MediumSecurity, 'HighSecurity' => HighSecurity, # SigningPolicy is not intended for use by `gem -P` so do not list it } end PK!ЂĽ2.2.0/rubygems/validator.rbnu[#-- # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. # All rights reserved. # See LICENSE.txt for permissions. #++ require 'rubygems/package' require 'rubygems/installer' ## # Validator performs various gem file and gem database validation class Gem::Validator include Gem::UserInteraction def initialize # :nodoc: require 'find' end ## # Given a gem file's contents, validates against its own MD5 checksum # gem_data:: [String] Contents of the gem file def verify_gem(gem_data) # TODO remove me? The code here only validate an MD5SUM that was # in some old formatted gems, but hasn't been for a long time. end ## # Given the path to a gem file, validates against its own MD5 checksum # # gem_path:: [String] Path to gem file def verify_gem_file(gem_path) open gem_path, Gem.binary_mode do |file| gem_data = file.read verify_gem gem_data end rescue Errno::ENOENT, Errno::EINVAL raise Gem::VerificationError, "missing gem file #{gem_path}" end private def find_files_for_gem(gem_directory) installed_files = [] Find.find gem_directory do |file_name| fn = file_name[gem_directory.size..file_name.size-1].sub(/^\//, "") installed_files << fn unless fn =~ /CVS/ || fn.empty? || File.directory?(file_name) end installed_files end public ## # Describes a problem with a file in a gem. ErrorData = Struct.new :path, :problem do def <=> other # :nodoc: return nil unless self.class === other [path, problem] <=> [other.path, other.problem] end end ## # Checks the gem directory for the following potential # inconsistencies/problems: # # * Checksum gem itself # * For each file in each gem, check consistency of installed versions # * Check for files that aren't part of the gem but are in the gems directory # * 1 cache - 1 spec - 1 directory. # # returns a hash of ErrorData objects, keyed on the problem gem's name. #-- # TODO needs further cleanup def alien(gems=[]) errors = Hash.new { |h,k| h[k] = {} } Gem::Specification.each do |spec| next unless gems.include? spec.name unless gems.empty? next if spec.default_gem? gem_name = spec.file_name gem_path = spec.cache_file spec_path = spec.spec_file gem_directory = spec.full_gem_path unless File.directory? gem_directory then errors[gem_name][spec.full_name] = "Gem registered but doesn't exist at #{gem_directory}" next end unless File.exist? spec_path then errors[gem_name][spec_path] = "Spec file missing for installed gem" end begin verify_gem_file(gem_path) good, gone, unreadable = nil, nil, nil, nil open gem_path, Gem.binary_mode do |file| package = Gem::Package.new gem_path good, gone = package.contents.partition { |file_name| File.exist? File.join(gem_directory, file_name) } gone.sort.each do |path| errors[gem_name][path] = "Missing file" end good, unreadable = good.partition { |file_name| File.readable? File.join(gem_directory, file_name) } unreadable.sort.each do |path| errors[gem_name][path] = "Unreadable file" end good.each do |entry, data| begin next unless data # HACK `gem check -a mkrf` source = File.join gem_directory, entry['path'] open source, Gem.binary_mode do |f| unless f.read == data then errors[gem_name][entry['path']] = "Modified from original" end end end end end installed_files = find_files_for_gem(gem_directory) extras = installed_files - good - unreadable extras.each do |extra| errors[gem_name][extra] = "Extra file" end rescue Gem::VerificationError => e errors[gem_name][gem_path] = e.message end end errors.each do |name, subhash| errors[name] = subhash.map do |path, msg| ErrorData.new path, msg end.sort end errors end end PK!z2.2.0/rubygems/ext.rbnu[#-- # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. # All rights reserved. # See LICENSE.txt for permissions. #++ ## # Classes for building C extensions live here. module Gem::Ext; end require 'rubygems/ext/build_error' require 'rubygems/ext/builder' require 'rubygems/ext/configure_builder' require 'rubygems/ext/ext_conf_builder' require 'rubygems/ext/rake_builder' require 'rubygems/ext/cmake_builder' PK!i!2.2.0/rubygems/dependency_list.rbnu[#-- # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. # All rights reserved. # See LICENSE.txt for permissions. #++ require 'tsort' require 'rubygems/deprecate' ## # Gem::DependencyList is used for installing and uninstalling gems in the # correct order to avoid conflicts. #-- # TODO: It appears that all but topo-sort functionality is being duplicated # (or is planned to be duplicated) elsewhere in rubygems. Is the majority of # this class necessary anymore? Especially #ok?, #why_not_ok? class Gem::DependencyList attr_reader :specs include Enumerable include TSort ## # Allows enabling/disabling use of development dependencies attr_accessor :development ## # Creates a DependencyList from the current specs. def self.from_specs list = new list.add(*Gem::Specification.to_a) list end ## # Creates a new DependencyList. If +development+ is true, development # dependencies will be included. def initialize development = false @specs = [] @development = development end ## # Adds +gemspecs+ to the dependency list. def add(*gemspecs) @specs.concat gemspecs end def clear @specs.clear end ## # Return a list of the gem specifications in the dependency list, sorted in # order so that no gemspec in the list depends on a gemspec earlier in the # list. # # This is useful when removing gems from a set of installed gems. By # removing them in the returned order, you don't get into as many dependency # issues. # # If there are circular dependencies (yuck!), then gems will be returned in # order until only the circular dependents and anything they reference are # left. Then arbitrary gemspecs will be returned until the circular # dependency is broken, after which gems will be returned in dependency # order again. def dependency_order sorted = strongly_connected_components.flatten result = [] seen = {} sorted.each do |spec| if index = seen[spec.name] then if result[index].version < spec.version then result[index] = spec end else seen[spec.name] = result.length result << spec end end result.reverse end ## # Iterator over dependency_order def each(&block) dependency_order.each(&block) end def find_name(full_name) @specs.find { |spec| spec.full_name == full_name } end def inspect # :nodoc: "#<%s:0x%x %p>" % [self.class, object_id, map { |s| s.full_name }] end ## # Are all the dependencies in the list satisfied? def ok? why_not_ok?(:quick).empty? end def why_not_ok? quick = false unsatisfied = Hash.new { |h,k| h[k] = [] } each do |spec| spec.runtime_dependencies.each do |dep| inst = Gem::Specification.any? { |installed_spec| dep.name == installed_spec.name and dep.requirement.satisfied_by? installed_spec.version } unless inst or @specs.find { |s| s.satisfies_requirement? dep } then unsatisfied[spec.name] << dep return unsatisfied if quick end end end unsatisfied end ## # Is is ok to remove a gemspec from the dependency list? # # If removing the gemspec creates breaks a currently ok dependency, then it # is NOT ok to remove the gemspec. def ok_to_remove?(full_name, check_dev=true) gem_to_remove = find_name full_name siblings = @specs.find_all { |s| s.name == gem_to_remove.name && s.full_name != gem_to_remove.full_name } deps = [] @specs.each do |spec| check = check_dev ? spec.dependencies : spec.runtime_dependencies check.each do |dep| deps << dep if gem_to_remove.satisfies_requirement?(dep) end end deps.all? { |dep| siblings.any? { |s| s.satisfies_requirement? dep } } end ## # Remove everything in the DependencyList that matches but doesn't # satisfy items in +dependencies+ (a hash of gem names to arrays of # dependencies). def remove_specs_unsatisfied_by dependencies specs.reject! { |spec| dep = dependencies[spec.name] dep and not dep.requirement.satisfied_by? spec.version } end ## # Removes the gemspec matching +full_name+ from the dependency list def remove_by_name(full_name) @specs.delete_if { |spec| spec.full_name == full_name } end ## # Return a hash of predecessors. result[spec] is an Array of # gemspecs that have a dependency satisfied by the named gemspec. def spec_predecessors result = Hash.new { |h,k| h[k] = [] } specs = @specs.sort.reverse specs.each do |spec| specs.each do |other| next if spec == other other.dependencies.each do |dep| if spec.satisfies_requirement? dep then result[spec] << other end end end end result end def tsort_each_node(&block) @specs.each(&block) end def tsort_each_child(node) specs = @specs.sort.reverse dependencies = node.runtime_dependencies dependencies.push(*node.development_dependencies) if @development dependencies.each do |dep| specs.each do |spec| if spec.satisfies_requirement? dep then yield spec break end end end end private ## # Count the number of gemspecs in the list +specs+ that are not in # +ignored+. def active_count(specs, ignored) specs.count { |spec| ignored[spec.full_name].nil? } end end PK!BB2.2.0/rubygems/spec_fetcher.rbnu[require 'rubygems/remote_fetcher' require 'rubygems/user_interaction' require 'rubygems/errors' require 'rubygems/text' require 'rubygems/name_tuple' ## # SpecFetcher handles metadata updates from remote gem repositories. class Gem::SpecFetcher include Gem::UserInteraction include Gem::Text ## # Cache of latest specs attr_reader :latest_specs # :nodoc: ## # Sources for this SpecFetcher attr_reader :sources # :nodoc: ## # Cache of all released specs attr_reader :specs # :nodoc: ## # Cache of prerelease specs attr_reader :prerelease_specs # :nodoc: @fetcher = nil ## # Default fetcher instance. Use this instead of ::new to reduce object # allocation. def self.fetcher @fetcher ||= new end def self.fetcher=(fetcher) # :nodoc: @fetcher = fetcher end ## # Creates a new SpecFetcher. Ordinarily you want to use the default fetcher # from Gem::SpecFetcher::fetcher which uses the Gem.sources. # # If you need to retrieve specifications from a different +source+, you can # send it as an argument. def initialize sources = nil @sources = sources || Gem.sources @update_cache = begin File.stat(Gem.user_home).uid == Process.uid rescue Errno::EACCES, Errno::ENOENT false end @specs = {} @latest_specs = {} @prerelease_specs = {} @caches = { :latest => @latest_specs, :prerelease => @prerelease_specs, :released => @specs, } @fetcher = Gem::RemoteFetcher.fetcher end ## # # Find and fetch gem name tuples that match +dependency+. # # If +matching_platform+ is false, gems for all platforms are returned. def search_for_dependency(dependency, matching_platform=true) found = {} rejected_specs = {} if dependency.prerelease? if dependency.specific? type = :complete else type = :abs_latest end elsif dependency.latest_version? type = :latest else type = :released end list, errors = available_specs(type) list.each do |source, specs| if dependency.name.is_a?(String) && specs.respond_to?(:bsearch) start_index = (0 ... specs.length).bsearch{ |i| specs[i].name >= dependency.name } end_index = (0 ... specs.length).bsearch{ |i| specs[i].name > dependency.name } specs = specs[start_index ... end_index] if start_index && end_index end found[source] = specs.select do |tup| if dependency.match?(tup) if matching_platform and !Gem::Platform.match(tup.platform) pm = ( rejected_specs[dependency] ||= \ Gem::PlatformMismatch.new(tup.name, tup.version)) pm.add_platform tup.platform false else true end end end end errors += rejected_specs.values tuples = [] found.each do |source, specs| specs.each do |s| tuples << [s, source] end end tuples = tuples.sort_by { |x| x[0] } return [tuples, errors] end ## # Return all gem name tuples who's names match +obj+ def detect(type=:complete) tuples = [] list, _ = available_specs(type) list.each do |source, specs| specs.each do |tup| if yield(tup) tuples << [tup, source] end end end tuples end ## # Find and fetch specs that match +dependency+. # # If +matching_platform+ is false, gems for all platforms are returned. def spec_for_dependency(dependency, matching_platform=true) tuples, errors = search_for_dependency(dependency, matching_platform) specs = [] tuples.each do |tup, source| begin spec = source.fetch_spec(tup) rescue Gem::RemoteFetcher::FetchError => e errors << Gem::SourceFetchProblem.new(source, e) else specs << [spec, source] end end return [specs, errors] end ## # Suggests gems based on the supplied +gem_name+. Returns an array of # alternative gem names. def suggest_gems_from_name gem_name gem_name = gem_name.downcase.tr('_-', '') max = gem_name.size / 2 names = available_specs(:latest).first.values.flatten(1) matches = names.map { |n| next unless n.match_platform? distance = levenshtein_distance gem_name, n.name.downcase.tr('_-', '') next if distance >= max return [n.name] if distance == 0 [n.name, distance] }.compact matches = matches.uniq.sort_by { |name, dist| dist } matches.first(5).map { |name, dist| name } end ## # Returns a list of gems available for each source in Gem::sources. # # +type+ can be one of 3 values: # :released => Return the list of all released specs # :complete => Return the list of all specs # :latest => Return the list of only the highest version of each gem # :prerelease => Return the list of all prerelease only specs # def available_specs(type) errors = [] list = {} @sources.each_source do |source| begin names = case type when :latest tuples_for source, :latest when :released tuples_for source, :released when :complete names = tuples_for(source, :prerelease, true) + tuples_for(source, :released) names.sort when :abs_latest names = tuples_for(source, :prerelease, true) + tuples_for(source, :latest) names.sort when :prerelease tuples_for(source, :prerelease) else raise Gem::Exception, "Unknown type - :#{type}" end rescue Gem::RemoteFetcher::FetchError => e errors << Gem::SourceFetchProblem.new(source, e) else list[source] = names end end [list, errors] end ## # Retrieves NameTuples from +source+ of the given +type+ (:prerelease, # etc.). If +gracefully_ignore+ is true, errors are ignored. def tuples_for(source, type, gracefully_ignore=false) # :nodoc: @caches[type][source.uri] ||= source.load_specs(type).sort_by { |tup| tup.name } rescue Gem::RemoteFetcher::FetchError raise unless gracefully_ignore [] end end PK!ܰ#2.2.0/rubygems/resolver/lock_set.rbnu[## # A set of gems from a gem dependencies lockfile. class Gem::Resolver::LockSet < Gem::Resolver::Set attr_reader :specs # :nodoc: ## # Creates a new LockSet from the given +sources+ def initialize sources super() @sources = sources.map do |source| Gem::Source::Lock.new source end @specs = [] end ## # Creates a new IndexSpecification in this set using the given +name+, # +version+ and +platform+. # # The specification's set will be the current set, and the source will be # the current set's source. def add name, version, platform # :nodoc: version = Gem::Version.new version specs = @sources.map do |source| Gem::Resolver::LockSpecification.new self, name, version, source, platform end @specs.concat specs specs end ## # Returns an Array of IndexSpecification objects matching the # DependencyRequest +req+. def find_all req @specs.select do |spec| req.match? spec end end ## # Loads a Gem::Specification with the given +name+, +version+ and # +platform+. +source+ is ignored. def load_spec name, version, platform, source # :nodoc: dep = Gem::Dependency.new name, version found = @specs.find do |spec| dep.matches_spec? spec and spec.platform == platform end tuple = Gem::NameTuple.new found.name, found.version, found.platform found.source.fetch_spec tuple end def pretty_print q # :nodoc: q.group 2, '[LockSet', ']' do q.breakable q.text 'source:' q.breakable q.pp @source q.breakable q.text 'specs:' q.breakable q.pp @specs.map { |spec| spec.full_name } end end end PK!޷Q-2.2.0/rubygems/resolver/dependency_request.rbnu[## # Used Internally. Wraps a Dependency object to also track which spec # contained the Dependency. class Gem::Resolver::DependencyRequest ## # The wrapped Gem::Dependency attr_reader :dependency ## # The request for this dependency. attr_reader :requester ## # Creates a new DependencyRequest for +dependency+ from +requester+. # +requester may be nil if the request came from a user. def initialize dependency, requester @dependency = dependency @requester = requester end def == other # :nodoc: case other when Gem::Dependency @dependency == other when Gem::Resolver::DependencyRequest @dependency == other.dependency && @requester == other.requester else false end end ## # Is this dependency a development dependency? def development? @dependency.type == :development end ## # Does this dependency request match +spec+? # # NOTE: #match? only matches prerelease versions when #dependency is a # prerelease dependency. def match? spec, allow_prerelease = false @dependency.match? spec, nil, allow_prerelease end ## # Does this dependency request match +spec+? # # NOTE: #matches_spec? matches prerelease versions. See also #match? def matches_spec?(spec) @dependency.matches_spec? spec end ## # The name of the gem this dependency request is requesting. def name @dependency.name end ## # Indicate that the request is for a gem explicitly requested by the user def explicit? @requester.nil? end ## # Indicate that the request is for a gem requested as a dependency of # another gem def implicit? !explicit? end ## # Return a String indicating who caused this request to be added (only # valid for implicit requests) def request_context @requester ? @requester.request : "(unknown)" end def pretty_print q # :nodoc: q.group 2, '[Dependency request ', ']' do q.breakable q.text @dependency.to_s q.breakable q.text ' requested by ' q.pp @requester end end ## # The version requirement for this dependency request def requirement @dependency.requirement end def to_s # :nodoc: @dependency.to_s end end PK!cӝG  .2.2.0/rubygems/resolver/local_specification.rbnu[## # A LocalSpecification comes from a .gem file on the local filesystem. class Gem::Resolver::LocalSpecification < Gem::Resolver::SpecSpecification ## # Returns +true+ if this gem is installable for the current platform. def installable_platform? return true if @source.kind_of? Gem::Source::SpecificFile super end def local? # :nodoc: true end def pretty_print q # :nodoc: q.group 2, '[LocalSpecification', ']' do q.breakable q.text "name: #{name}" q.breakable q.text "version: #{version}" q.breakable q.text "platform: #{platform}" q.breakable q.text 'dependencies:' q.breakable q.pp dependencies q.breakable q.text "source: #{@source.path}" end end end PK!{@,2.2.0/rubygems/resolver/api_specification.rbnu[## # Represents a specification retrieved via the rubygems.org API. # # This is used to avoid loading the full Specification object when all we need # is the name, version, and dependencies. class Gem::Resolver::APISpecification < Gem::Resolver::Specification ## # Creates an APISpecification for the given +set+ from the rubygems.org # +api_data+. # # See http://guides.rubygems.org/rubygems-org-api/#misc_methods for the # format of the +api_data+. def initialize(set, api_data) super() @set = set @name = api_data[:name] @version = Gem::Version.new api_data[:number] @platform = Gem::Platform.new api_data[:platform] @dependencies = api_data[:dependencies].map do |name, ver| Gem::Dependency.new name, ver.split(/\s*,\s*/) end end def == other # :nodoc: self.class === other and @set == other.set and @name == other.name and @version == other.version and @platform == other.platform and @dependencies == other.dependencies end def fetch_development_dependencies # :nodoc: spec = source.fetch_spec Gem::NameTuple.new @name, @version, @platform @dependencies = spec.dependencies end def installable_platform? # :nodoc: Gem::Platform.match @platform end def pretty_print q # :nodoc: q.group 2, '[APISpecification', ']' do q.breakable q.text "name: #{name}" q.breakable q.text "version: #{version}" q.breakable q.text "platform: #{platform}" q.breakable q.text 'dependencies:' q.breakable q.pp @dependencies q.breakable q.text "set uri: #{@set.dep_uri}" end end ## # Fetches a Gem::Specification for this APISpecification. def spec # :nodoc: @spec ||= begin tuple = Gem::NameTuple.new @name, @version, @platform source.fetch_spec tuple end end def source # :nodoc: @set.source end end PK!po 2.2.0/rubygems/resolver/stats.rbnu[class Gem::Resolver::Stats def initialize @max_depth = 0 @max_requirements = 0 @requirements = 0 @backtracking = 0 @iterations = 0 end def record_depth(stack) if stack.size > @max_depth @max_depth = stack.size end end def record_requirements(reqs) if reqs.size > @max_requirements @max_requirements = reqs.size end end def requirement! @requirements += 1 end def backtracking! @backtracking += 1 end def iteration! @iterations += 1 end PATTERN = "%20s: %d\n" def display $stdout.puts "=== Resolver Statistics ===" $stdout.printf PATTERN, "Max Depth", @max_depth $stdout.printf PATTERN, "Total Requirements", @requirements $stdout.printf PATTERN, "Max Requirements", @max_requirements $stdout.printf PATTERN, "Backtracking #", @backtracking $stdout.printf PATTERN, "Iteration #", @iterations end end PK!]2.2.0/rubygems/resolver/set.rbnu[## # Resolver sets are used to look up specifications (and their # dependencies) used in resolution. This set is abstract. class Gem::Resolver::Set ## # Set to true to disable network access for this set attr_accessor :remote ## # Errors encountered when resolving gems attr_accessor :errors ## # When true, allows matching of requests to prerelease gems. attr_accessor :prerelease def initialize # :nodoc: @prerelease = false @remote = true @errors = [] end ## # The find_all method must be implemented. It returns all Resolver # Specification objects matching the given DependencyRequest +req+. def find_all req raise NotImplementedError end ## # The #prefetch method may be overridden, but this is not necessary. This # default implementation does nothing, which is suitable for sets where # looking up a specification is cheap (such as installed gems). # # When overridden, the #prefetch method should look up specifications # matching +reqs+. def prefetch reqs end ## # When true, this set is allowed to access the network when looking up # specifications or dependencies. def remote? # :nodoc: @remote end end PK!R.2.2.0/rubygems/resolver/index_specification.rbnu[## # Represents a possible Specification object returned from IndexSet. Used to # delay needed to download full Specification objects when only the +name+ # and +version+ are needed. class Gem::Resolver::IndexSpecification < Gem::Resolver::Specification ## # An IndexSpecification is created from the index format described in `gem # help generate_index`. # # The +set+ contains other specifications for this (URL) +source+. # # The +name+, +version+ and +platform+ are the name, version and platform of # the gem. def initialize set, name, version, source, platform super() @set = set @name = name @version = version @source = source @platform = platform.to_s @spec = nil end ## # The dependencies of the gem for this specification def dependencies spec.dependencies end def inspect # :nodoc: '#<%s %s source %s>' % [self.class, full_name, @source] end def pretty_print q # :nodoc: q.group 2, '[Index specification', ']' do q.breakable q.text full_name unless Gem::Platform::RUBY == @platform then q.breakable q.text @platform.to_s end q.breakable q.text 'source ' q.pp @source end end ## # Fetches a Gem::Specification for this IndexSpecification from the #source. def spec # :nodoc: @spec ||= begin tuple = Gem::NameTuple.new @name, @version, @platform @source.fetch_spec tuple end end end PK!A8T$2.2.0/rubygems/resolver/index_set.rbnu[## # The global rubygems pool represented via the traditional # source index. class Gem::Resolver::IndexSet < Gem::Resolver::Set def initialize source = nil # :nodoc: super() @f = if source then sources = Gem::SourceList.from [source] Gem::SpecFetcher.new sources else Gem::SpecFetcher.fetcher end @all = Hash.new { |h,k| h[k] = [] } list, errors = @f.available_specs :complete @errors.concat errors list.each do |uri, specs| specs.each do |n| @all[n.name] << [uri, n] end end @specs = {} end ## # Return an array of IndexSpecification objects matching # DependencyRequest +req+. def find_all req res = [] return res unless @remote name = req.dependency.name @all[name].each do |uri, n| if req.match? n, @prerelease then res << Gem::Resolver::IndexSpecification.new( self, n.name, n.version, uri, n.platform) end end res end def pretty_print q # :nodoc: q.group 2, '[IndexSet', ']' do q.breakable q.text 'sources:' q.breakable q.pp @f.sources q.breakable q.text 'specs:' q.breakable names = @all.values.map do |tuples| tuples.map do |_, tuple| tuple.full_name end end.flatten q.seplist names do |name| q.text name end end end end PK!d: -2.2.0/rubygems/resolver/activation_request.rbnu[## # Specifies a Specification object that should be activated. Also contains a # dependency that was used to introduce this activation. class Gem::Resolver::ActivationRequest ## # The parent request for this activation request. attr_reader :request ## # The specification to be activated. attr_reader :spec ## # Creates a new ActivationRequest that will activate +spec+. The parent # +request+ is used to provide diagnostics in case of conflicts. # # +others_possible+ indicates that other specifications may also match this # activation request. def initialize spec, request, others_possible = true @spec = spec @request = request @others_possible = others_possible end def == other # :nodoc: case other when Gem::Specification @spec == other when Gem::Resolver::ActivationRequest @spec == other.spec && @request == other.request else false end end ## # Is this activation request for a development dependency? def development? @request.development? end ## # Downloads a gem at +path+ and returns the file path. def download path if @spec.respond_to? :source source = @spec.source else source = Gem.sources.first end Gem.ensure_gem_subdirectories path source.download full_spec, path end ## # The full name of the specification to be activated. def full_name @spec.full_name end ## # The Gem::Specification for this activation request. def full_spec Gem::Specification === @spec ? @spec : @spec.spec end def inspect # :nodoc: others = case @others_possible when true then # TODO remove at RubyGems 3 ' (others possible)' when false then # TODO remove at RubyGems 3 nil else unless @others_possible.empty? then others = @others_possible.map { |s| s.full_name } " (others possible: #{others.join ', '})" end end '#<%s for %p from %s%s>' % [ self.class, @spec, @request, others ] end ## # True if the requested gem has already been installed. def installed? case @spec when Gem::Resolver::VendorSpecification then true else this_spec = full_spec Gem::Specification.any? do |s| s == this_spec end end end ## # The name of this activation request's specification def name @spec.name end ## # Indicate if this activation is one of a set of possible # requests for the same Dependency request. def others_possible? case @others_possible when true, false then @others_possible else not @others_possible.empty? end end ## # Return the ActivationRequest that contained the dependency # that we were activated for. def parent @request.requester end def pretty_print q # :nodoc: q.group 2, '[Activation request', ']' do q.breakable q.pp @spec q.breakable q.text ' for ' q.pp @request case @others_possible when false then when true then q.breakable q.text 'others possible' else unless @others_possible.empty? then q.breakable q.text 'others ' q.pp @others_possible.map { |s| s.full_name } end end end end ## # The version of this activation request's specification def version @spec.version end end PK!.-2.2.0/rubygems/resolver/lock_specification.rbnu[## # The LockSpecification comes from a lockfile (Gem::RequestSet::Lockfile). # # A LockSpecification's dependency information is pre-filled from the # lockfile. class Gem::Resolver::LockSpecification < Gem::Resolver::Specification def initialize set, name, version, source, platform super() @name = name @platform = platform @set = set @source = source @version = version @dependencies = [] @spec = nil end ## # This is a null install as a locked specification is considered installed. # +options+ are ignored. def install options = {} destination = options[:install_dir] || Gem.dir if File.exist? File.join(destination, 'specifications', spec.spec_name) then yield nil return end super end ## # Adds +dependency+ from the lockfile to this specification def add_dependency dependency # :nodoc: @dependencies << dependency end def pretty_print q # :nodoc: q.group 2, '[LockSpecification', ']' do q.breakable q.text "name: #{@name}" q.breakable q.text "version: #{@version}" unless @platform == Gem::Platform::RUBY then q.breakable q.text "platform: #{@platform}" end unless @dependencies.empty? then q.breakable q.text 'dependencies:' q.breakable q.pp @dependencies end end end ## # A specification constructed from the lockfile is returned def spec @spec ||= Gem::Specification.find { |spec| spec.name == @name and spec.version == @version } @spec ||= Gem::Specification.new do |s| s.name = @name s.version = @version s.platform = @platform s.dependencies.concat @dependencies end end end PK!{?h h "2.2.0/rubygems/resolver/git_set.rbnu[## # A GitSet represents gems that are sourced from git repositories. # # This is used for gem dependency file support. # # Example: # # set = Gem::Resolver::GitSet.new # set.add_git_gem 'rake', 'git://example/rake.git', tag: 'rake-10.1.0' class Gem::Resolver::GitSet < Gem::Resolver::Set ## # The root directory for git gems in this set. This is usually Gem.dir, the # installation directory for regular gems. attr_accessor :root_dir ## # Contains repositories needing submodules attr_reader :need_submodules # :nodoc: ## # A Hash containing git gem names for keys and a Hash of repository and # git commit reference as values. attr_reader :repositories # :nodoc: ## # A hash of gem names to Gem::Resolver::GitSpecifications attr_reader :specs # :nodoc: def initialize # :nodoc: super() @git = ENV['git'] || 'git' @need_submodules = {} @repositories = {} @root_dir = Gem.dir @specs = {} end def add_git_gem name, repository, reference, submodules # :nodoc: @repositories[name] = [repository, reference] @need_submodules[repository] = submodules end ## # Adds and returns a GitSpecification with the given +name+ and +version+ # which came from a +repository+ at the given +reference+. If +submodules+ # is true they are checked out along with the repository. # # This fills in the prefetch information as enough information about the gem # is present in the arguments. def add_git_spec name, version, repository, reference, submodules # :nodoc: add_git_gem name, repository, reference, submodules source = Gem::Source::Git.new name, repository, reference source.root_dir = @root_dir spec = Gem::Specification.new do |s| s.name = name s.version = version end git_spec = Gem::Resolver::GitSpecification.new self, spec, source @specs[spec.name] = git_spec git_spec end ## # Finds all git gems matching +req+ def find_all req prefetch nil specs.values.select do |spec| req.match? spec end end ## # Prefetches specifications from the git repositories in this set. def prefetch reqs return unless @specs.empty? @repositories.each do |name, (repository, reference)| source = Gem::Source::Git.new name, repository, reference source.root_dir = @root_dir source.remote = @remote source.specs.each do |spec| git_spec = Gem::Resolver::GitSpecification.new self, spec, source @specs[spec.name] = git_spec end end end def pretty_print q # :nodoc: q.group 2, '[GitSet', ']' do next if @repositories.empty? q.breakable repos = @repositories.map do |name, (repository, reference)| "#{name}: #{repository}@#{reference}" end q.seplist repos do |repo| q.text repo end end end end PK!h$ '2.2.0/rubygems/resolver/composed_set.rbnu[## # A ComposedSet allows multiple sets to be queried like a single set. # # To create a composed set with any number of sets use: # # Gem::Resolver.compose_sets set1, set2 # # This method will eliminate nesting of composed sets. class Gem::Resolver::ComposedSet < Gem::Resolver::Set attr_reader :sets # :nodoc: ## # Creates a new ComposedSet containing +sets+. Use # Gem::Resolver::compose_sets instead. def initialize *sets super() @sets = sets end ## # When +allow_prerelease+ is set to +true+ prereleases gems are allowed to # match dependencies. def prerelease= allow_prerelease super sets.each do |set| set.prerelease = allow_prerelease end end ## # Sets the remote network access for all composed sets. def remote= remote super @sets.each { |set| set.remote = remote } end def errors @errors + @sets.map { |set| set.errors }.flatten end ## # Finds all specs matching +req+ in all sets. def find_all req @sets.map do |s| s.find_all req end.flatten end ## # Prefetches +reqs+ in all sets. def prefetch reqs @sets.each { |s| s.prefetch(reqs) } end end PK!OO#2.2.0/rubygems/resolver/best_set.rbnu[## # The BestSet chooses the best available method to query a remote index. # # It combines IndexSet and APISet class Gem::Resolver::BestSet < Gem::Resolver::ComposedSet ## # Creates a BestSet for the given +sources+ or Gem::sources if none are # specified. +sources+ must be a Gem::SourceList. def initialize sources = Gem.sources super() @sources = sources end ## # Picks which sets to use for the configured sources. def pick_sets # :nodoc: @sources.each_source do |source| @sets << source.dependency_resolver_set end end def find_all req # :nodoc: pick_sets if @remote and @sets.empty? super rescue Gem::RemoteFetcher::FetchError => e replace_failed_api_set e retry end def prefetch reqs # :nodoc: pick_sets if @remote and @sets.empty? super end def pretty_print q # :nodoc: q.group 2, '[BestSet', ']' do q.breakable q.text 'sets:' q.breakable q.pp @sets end end ## # Replaces a failed APISet for the URI in +error+ with an IndexSet. # # If no matching APISet can be found the original +error+ is raised. # # The calling method must retry the exception to repeat the lookup. def replace_failed_api_set error # :nodoc: uri = error.uri uri = URI uri unless URI === uri uri.query = nil raise error unless api_set = @sets.find { |set| Gem::Resolver::APISet === set and set.dep_uri == uri } index_set = Gem::Resolver::IndexSet.new api_set.source @sets.map! do |set| next set unless set == api_set index_set end end end PK!,2.2.0/rubygems/resolver/git_specification.rbnu[## # A GitSpecification represents a gem that is sourced from a git repository # and is being loaded through a gem dependencies file through the +git:+ # option. class Gem::Resolver::GitSpecification < Gem::Resolver::SpecSpecification def == other # :nodoc: self.class === other and @set == other.set and @spec == other.spec and @source == other.source end def add_dependency dependency # :nodoc: spec.dependencies << dependency end ## # Installing a git gem only involves building the extensions and generating # the executables. def install options = {} require 'rubygems/installer' installer = Gem::Installer.new '', options installer.spec = spec yield installer if block_given? installer.run_pre_install_hooks installer.build_extensions installer.run_post_build_hooks installer.generate_bin installer.run_post_install_hooks end def pretty_print q # :nodoc: q.group 2, '[GitSpecification', ']' do q.breakable q.text "name: #{name}" q.breakable q.text "version: #{version}" q.breakable q.text 'dependencies:' q.breakable q.pp dependencies q.breakable q.text "source:" q.breakable q.pp @source end end end PK!1 "2.2.0/rubygems/resolver/api_set.rbnu[## # The global rubygems pool, available via the rubygems.org API. # Returns instances of APISpecification. class Gem::Resolver::APISet < Gem::Resolver::Set ## # The URI for the dependency API this APISet uses. attr_reader :dep_uri # :nodoc: ## # The Gem::Source that gems are fetched from attr_reader :source ## # The corresponding place to fetch gems. attr_reader :uri ## # Creates a new APISet that will retrieve gems from +uri+ using the RubyGems # API URL +dep_uri+ which is described at # http://guides.rubygems.org/rubygems-org-api def initialize dep_uri = 'https://rubygems.org/api/v1/dependencies' super() dep_uri = URI dep_uri unless URI === dep_uri # for ruby 1.8 @dep_uri = dep_uri @uri = dep_uri + '../..' @data = Hash.new { |h,k| h[k] = [] } @source = Gem::Source.new @uri @to_fetch = [] end ## # Return an array of APISpecification objects matching # DependencyRequest +req+. def find_all req res = [] return res unless @remote if @to_fetch.include?(req.name) prefetch_now end versions(req.name).each do |ver| if req.dependency.match? req.name, ver[:number] res << Gem::Resolver::APISpecification.new(self, ver) end end res end ## # A hint run by the resolver to allow the Set to fetch # data for DependencyRequests +reqs+. def prefetch reqs return unless @remote names = reqs.map { |r| r.dependency.name } needed = names - @data.keys - @to_fetch @to_fetch += needed end def prefetch_now # :nodoc: needed, @to_fetch = @to_fetch, [] uri = @dep_uri + "?gems=#{needed.sort.join ','}" str = Gem::RemoteFetcher.fetcher.fetch_path uri loaded = [] Marshal.load(str).each do |ver| name = ver[:name] @data[name] << ver loaded << name end (needed - loaded).each do |missing| @data[missing] = [] end end def pretty_print q # :nodoc: q.group 2, '[APISet', ']' do q.breakable q.text "URI: #{@dep_uri}" q.breakable q.text 'gem names:' q.pp @data.keys end end ## # Return data for all versions of the gem +name+. def versions name # :nodoc: if @data.key?(name) return @data[name] end uri = @dep_uri + "?gems=#{name}" str = Gem::RemoteFetcher.fetcher.fetch_path uri Marshal.load(str).each do |ver| @data[ver[:name]] << ver end @data[name] end end PK!%t&&/2.2.0/rubygems/resolver/vendor_specification.rbnu[## # A VendorSpecification represents a gem that has been unpacked into a project # and is being loaded through a gem dependencies file through the +path:+ # option. class Gem::Resolver::VendorSpecification < Gem::Resolver::SpecSpecification def == other # :nodoc: self.class === other and @set == other.set and @spec == other.spec and @source == other.source end ## # This is a null install as this gem was unpacked into a directory. # +options+ are ignored. def install options = {} yield nil end end PK!99+2.2.0/rubygems/resolver/requirement_list.rbnu[## # The RequirementList is used to hold the requirements being considered # while resolving a set of gems. # # The RequirementList acts like a queue where the oldest items are removed # first. class Gem::Resolver::RequirementList include Enumerable ## # Creates a new RequirementList. def initialize @exact = [] @list = [] end def initialize_copy other # :nodoc: @exact = @exact.dup @list = @list.dup end ## # Adds Resolver::DependencyRequest +req+ to this requirements list. def add(req) if req.requirement.exact? @exact.push req else @list.push req end req end ## # Enumerates requirements in the list def each # :nodoc: return enum_for __method__ unless block_given? @exact.each do |requirement| yield requirement end @list.each do |requirement| yield requirement end end ## # How many elements are in the list def size @exact.size + @list.size end ## # Is the list empty? def empty? @exact.empty? && @list.empty? end ## # Remove the oldest DependencyRequest from the list. def remove return @exact.shift unless @exact.empty? @list.shift end ## # Returns the oldest five entries from the list. def next5 x = @exact[0,5] x + @list[0,5 - x.size] end end PK!iLuV%2.2.0/rubygems/resolver/vendor_set.rbnu[## # A VendorSet represents gems that have been unpacked into a specific # directory that contains a gemspec. # # This is used for gem dependency file support. # # Example: # # set = Gem::Resolver::VendorSet.new # # set.add_vendor_gem 'rake', 'vendor/rake' # # The directory vendor/rake must contain an unpacked rake gem along with a # rake.gemspec (watching the given name). class Gem::Resolver::VendorSet < Gem::Resolver::Set ## # The specifications for this set. attr_reader :specs # :nodoc: def initialize # :nodoc: super() @directories = {} @specs = {} end ## # Adds a specification to the set with the given +name+ which has been # unpacked into the given +directory+. def add_vendor_gem name, directory # :nodoc: gemspec = File.join directory, "#{name}.gemspec" spec = Gem::Specification.load gemspec raise Gem::GemNotFoundException, "unable to find #{gemspec} for gem #{name}" unless spec spec.full_gem_path = File.expand_path directory @specs[spec.name] = spec @directories[spec] = directory spec end ## # Returns an Array of VendorSpecification objects matching the # DependencyRequest +req+. def find_all req @specs.values.select do |spec| req.match? spec end.map do |spec| source = Gem::Source::Vendor.new @directories[spec] Gem::Resolver::VendorSpecification.new self, spec, source end end ## # Loads a spec with the given +name+. +version+, +platform+ and +source+ are # ignored. def load_spec name, version, platform, source # :nodoc: @specs.fetch name end def pretty_print q # :nodoc: q.group 2, '[VendorSet', ']' do next if @directories.empty? q.breakable dirs = @directories.map do |spec, directory| "#{spec.full_name}: #{directory}" end q.seplist dirs do |dir| q.text dir end end end end PK!C-  (2.2.0/rubygems/resolver/specification.rbnu[## # A Resolver::Specification contains a subset of the information # contained in a Gem::Specification. Only the information necessary for # dependency resolution in the resolver is included. class Gem::Resolver::Specification ## # The dependencies of the gem for this specification attr_reader :dependencies ## # The name of the gem for this specification attr_reader :name ## # The platform this gem works on. attr_reader :platform ## # The set this specification came from. attr_reader :set ## # The source for this specification attr_reader :source ## # The Gem::Specification for this Resolver::Specification. # # Implementers, note that #install updates @spec, so be sure to cache the # Gem::Specification in @spec when overriding. attr_reader :spec ## # The version of the gem for this specification. attr_reader :version ## # Sets default instance variables for the specification. def initialize @dependencies = nil @name = nil @platform = nil @set = nil @source = nil @version = nil end ## # Fetches development dependencies if the source does not provide them by # default (see APISpecification). def fetch_development_dependencies # :nodoc: end ## # The name and version of the specification. # # Unlike Gem::Specification#full_name, the platform is not included. def full_name "#{@name}-#{@version}" end ## # Installs this specification using the Gem::Installer +options+. The # install method yields a Gem::Installer instance, which indicates the # gem will be installed, or +nil+, which indicates the gem is already # installed. # # After installation #spec is updated to point to the just-installed # specification. def install options = {} require 'rubygems/installer' destination = options[:install_dir] || Gem.dir Gem.ensure_gem_subdirectories destination gem = source.download spec, destination installer = Gem::Installer.new gem, options yield installer if block_given? @spec = installer.install end ## # Returns true if this specification is installable on this platform. def installable_platform? Gem::Platform.match spec.platform end def local? # :nodoc: false end end PK!"vO-2.2.0/rubygems/resolver/spec_specification.rbnu[## # The Resolver::SpecSpecification contains common functionality for # Resolver specifications that are backed by a Gem::Specification. class Gem::Resolver::SpecSpecification < Gem::Resolver::Specification ## # A SpecSpecification is created for a +set+ for a Gem::Specification in # +spec+. The +source+ is either where the +spec+ came from, or should be # loaded from. def initialize set, spec, source = nil @set = set @source = source @spec = spec end ## # The dependencies of the gem for this specification def dependencies spec.dependencies end ## # The name and version of the specification. # # Unlike Gem::Specification#full_name, the platform is not included. def full_name "#{spec.name}-#{spec.version}" end ## # The name of the gem for this specification def name spec.name end ## # The platform this gem works on. def platform spec.platform end ## # The version of the gem for this specification. def version spec.version end end PK!&22.2.0/rubygems/resolver/installed_specification.rbnu[## # An InstalledSpecification represents a gem that is already installed # locally. class Gem::Resolver::InstalledSpecification < Gem::Resolver::SpecSpecification def == other # :nodoc: self.class === other and @set == other.set and @spec == other.spec end ## # This is a null install as this specification is already installed. # +options+ are ignored. def install options = {} yield nil end ## # Returns +true+ if this gem is installable for the current platform. def installable_platform? # BACKCOMPAT If the file is coming out of a specified file, then we # ignore the platform. This code can be removed in RG 3.0. return true if @source.kind_of? Gem::Source::SpecificFile super end def pretty_print q # :nodoc: q.group 2, '[InstalledSpecification', ']' do q.breakable q.text "name: #{name}" q.breakable q.text "version: #{version}" q.breakable q.text "platform: #{platform}" q.breakable q.text 'dependencies:' q.breakable q.pp spec.dependencies end end ## # The source for this specification def source @source ||= Gem::Source::Installed.new end end PK!}+(2.2.0/rubygems/resolver/installer_set.rbnu[## # A set of gems for installation sourced from remote sources and local .gem # files class Gem::Resolver::InstallerSet < Gem::Resolver::Set ## # List of Gem::Specification objects that must always be installed. attr_reader :always_install # :nodoc: ## # Only install gems in the always_install list attr_accessor :ignore_dependencies # :nodoc: ## # Do not look in the installed set when finding specifications. This is # used by the --install-dir option to `gem install` attr_accessor :ignore_installed # :nodoc: ## # The remote_set looks up remote gems for installation. attr_reader :remote_set # :nodoc: ## # Creates a new InstallerSet that will look for gems in +domain+. def initialize domain super() @domain = domain @remote = consider_remote? @f = Gem::SpecFetcher.fetcher @always_install = [] @ignore_dependencies = false @ignore_installed = false @local = {} @remote_set = Gem::Resolver::BestSet.new @specs = {} end ## # Looks up the latest specification for +dependency+ and adds it to the # always_install list. def add_always_install dependency request = Gem::Resolver::DependencyRequest.new dependency, nil found = find_all request found.delete_if { |s| s.version.prerelease? and not s.local? } unless dependency.prerelease? found = found.select do |s| Gem::Source::SpecificFile === s.source or Gem::Platform::RUBY == s.platform or Gem::Platform.local === s.platform end if found.empty? then exc = Gem::UnsatisfiableDependencyError.new request exc.errors = errors raise exc end newest = found.max_by do |s| [s.version, s.platform == Gem::Platform::RUBY ? -1 : 1] end @always_install << newest.spec end ## # Adds a local gem requested using +dep_name+ with the given +spec+ that can # be loaded and installed using the +source+. def add_local dep_name, spec, source @local[dep_name] = [spec, source] end ## # Should local gems should be considered? def consider_local? # :nodoc: @domain == :both or @domain == :local end ## # Should remote gems should be considered? def consider_remote? # :nodoc: @domain == :both or @domain == :remote end ## # Errors encountered while resolving gems def errors @errors + @remote_set.errors end ## # Returns an array of IndexSpecification objects matching DependencyRequest # +req+. def find_all req res = [] dep = req.dependency return res if @ignore_dependencies and @always_install.none? { |spec| dep.match? spec } name = dep.name dep.matching_specs.each do |gemspec| next if @always_install.any? { |spec| spec.name == gemspec.name } res << Gem::Resolver::InstalledSpecification.new(self, gemspec) end unless @ignore_installed if consider_local? then matching_local = @local.values.select do |spec, _| req.match? spec end.map do |spec, source| Gem::Resolver::LocalSpecification.new self, spec, source end res.concat matching_local local_source = Gem::Source::Local.new if local_spec = local_source.find_gem(name, dep.requirement) then res << Gem::Resolver::IndexSpecification.new( self, local_spec.name, local_spec.version, local_source, local_spec.platform) end end res.delete_if do |spec| spec.version.prerelease? and not dep.prerelease? end res.concat @remote_set.find_all req if consider_remote? res end def prefetch(reqs) @remote_set.prefetch(reqs) if consider_remote? end def prerelease= allow_prerelease super @remote_set.prerelease = allow_prerelease end def inspect # :nodoc: always_install = @always_install.map { |s| s.full_name } '#<%s domain: %s specs: %p always install: %p>' % [ self.class, @domain, @specs.keys, always_install, ] end ## # Called from IndexSpecification to get a true Specification # object. def load_spec name, ver, platform, source # :nodoc: key = "#{name}-#{ver}-#{platform}" @specs.fetch key do tuple = Gem::NameTuple.new name, ver, platform @specs[key] = source.fetch_spec tuple end end ## # Has a local gem for +dep_name+ been added to this set? def local? dep_name # :nodoc: spec, = @local[dep_name] spec end def pretty_print q # :nodoc: q.group 2, '[InstallerSet', ']' do q.breakable q.text "domain: #{@domain}" q.breakable q.text 'specs: ' q.pp @specs.keys q.breakable q.text 'always install: ' q.pp @always_install end end def remote= remote # :nodoc: case @domain when :local then @domain = :both if remote when :remote then @domain = nil unless remote when :both then @domain = :local unless remote end end end PK!<7U U #2.2.0/rubygems/resolver/conflict.rbnu[## # Used internally to indicate that a dependency conflicted # with a spec that would be activated. class Gem::Resolver::Conflict ## # The specification that was activated prior to the conflict attr_reader :activated ## # The dependency that is in conflict with the activated gem. attr_reader :dependency attr_reader :failed_dep # :nodoc: ## # Creates a new resolver conflict when +dependency+ is in conflict with an # already +activated+ specification. def initialize(dependency, activated, failed_dep=dependency) @dependency = dependency @activated = activated @failed_dep = failed_dep end def == other # :nodoc: self.class === other and @dependency == other.dependency and @activated == other.activated and @failed_dep == other.failed_dep end ## # A string explanation of the conflict. def explain "" end ## # Return the 2 dependency objects that conflicted def conflicting_dependencies [@failed_dep.dependency, @activated.request.dependency] end ## # Explanation of the conflict used by exceptions to print useful messages def explanation activated = @activated.spec.full_name dependency = @failed_dep.dependency requirement = dependency.requirement alternates = dependency.matching_specs.map { |spec| spec.full_name } unless alternates.empty? then matching = <<-MATCHING.chomp Gems matching %s: %s MATCHING matching = matching % [ dependency, alternates.join(', '), ] end explanation = <<-EXPLANATION Activated %s which does not match conflicting dependency (%s) Conflicting dependency chains: %s versus: %s %s EXPLANATION explanation % [ activated, requirement, request_path(@activated).reverse.join(", depends on\n "), request_path(@failed_dep).reverse.join(", depends on\n "), matching, ] end ## # Returns true if the conflicting dependency's name matches +spec+. def for_spec?(spec) @dependency.name == spec.name end def pretty_print q # :nodoc: q.group 2, '[Dependency conflict: ', ']' do q.breakable q.text 'activated ' q.pp @activated q.breakable q.text ' dependency ' q.pp @dependency q.breakable if @dependency == @failed_dep then q.text ' failed' else q.text ' failed dependency ' q.pp @failed_dep end end end ## # Path of activations from the +current+ list. def request_path current path = [] while current do case current when Gem::Resolver::ActivationRequest then path << "#{current.request.dependency}, #{current.spec.version} activated" current = current.parent when Gem::Resolver::DependencyRequest then path << "#{current.dependency}" current = current.requester else raise Gem::Exception, "[BUG] unknown request class #{current.class}" end end path = ['user request (gem command or Gemfile)'] if path.empty? path end ## # Return the Specification that listed the dependency def requester @failed_dep.requester end end ## # TODO: Remove in RubyGems 3 Gem::Resolver::DependencyConflict = Gem::Resolver::Conflict # :nodoc: PK!ې&2.2.0/rubygems/resolver/current_set.rbnu[## # A set which represents the installed gems. Respects # all the normal settings that control where to look # for installed gems. class Gem::Resolver::CurrentSet < Gem::Resolver::Set def find_all req req.dependency.matching_specs end end PK!1 ss!2.2.0/rubygems/ext/build_error.rbnu[## # Raised when there is an error while building extensions. class Gem::Ext::BuildError < Gem::InstallError end PK!y?#2.2.0/rubygems/ext/cmake_builder.rbnu[require 'rubygems/command' class Gem::Ext::CmakeBuilder < Gem::Ext::Builder def self.build(extension, directory, dest_path, results, args=[], lib_dir=nil) unless File.exist?('Makefile') then cmd = "cmake . -DCMAKE_INSTALL_PREFIX=#{dest_path}" cmd << " #{Gem::Command.build_args.join ' '}" unless Gem::Command.build_args.empty? run cmd, results end make dest_path, results results end end PK!sN"2.2.0/rubygems/ext/rake_builder.rbnu[#-- # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. # All rights reserved. # See LICENSE.txt for permissions. #++ class Gem::Ext::RakeBuilder < Gem::Ext::Builder def self.build(extension, directory, dest_path, results, args=[], lib_dir=nil) if File.basename(extension) =~ /mkrf_conf/i then cmd = "#{Gem.ruby} #{File.basename extension}" cmd << " #{args.join " "}" unless args.empty? run cmd, results end # Deal with possible spaces in the path, e.g. C:/Program Files dest_path = '"' + dest_path.to_s + '"' if dest_path.to_s.include?(' ') rake = ENV['rake'] rake ||= begin "#{Gem.ruby} -rubygems #{Gem.bin_path('rake', 'rake')}" rescue Gem::Exception end rake ||= Gem.default_exec_format % 'rake' cmd = "#{rake} RUBYARCHDIR=#{dest_path} RUBYLIBDIR=#{dest_path}" # ENV is frozen run cmd, results results end end PK!!..2.2.0/rubygems/ext/builder.rbnu[#-- # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. # All rights reserved. # See LICENSE.txt for permissions. #++ require 'rubygems/user_interaction' require 'thread' class Gem::Ext::Builder include Gem::UserInteraction ## # The builder shells-out to run various commands after changing the # directory. This means multiple installations cannot be allowed to build # extensions in parallel as they may change each other's directories leading # to broken extensions or failed installations. CHDIR_MUTEX = Mutex.new # :nodoc: attr_accessor :build_args # :nodoc: def self.class_name name =~ /Ext::(.*)Builder/ $1.downcase end def self.make(dest_path, results) unless File.exist? 'Makefile' then raise Gem::InstallError, 'Makefile not found' end # try to find make program from Ruby configure arguments first RbConfig::CONFIG['configure_args'] =~ /with-make-prog\=(\w+)/ make_program = ENV['MAKE'] || ENV['make'] || $1 unless make_program then make_program = (/mswin/ =~ RUBY_PLATFORM) ? 'nmake' : 'make' end destdir = '"DESTDIR=%s"' % ENV['DESTDIR'] if RUBY_VERSION > '2.0' ['clean', '', 'install'].each do |target| # Pass DESTDIR via command line to override what's in MAKEFLAGS cmd = [ make_program, destdir, target ].join(' ').rstrip begin run(cmd, results, "make #{target}".rstrip) rescue Gem::InstallError raise unless target == 'clean' # ignore clean failure end end end def self.redirector '2>&1' end def self.run(command, results, command_name = nil) verbose = Gem.configuration.really_verbose begin # TODO use Process.spawn when ruby 1.8 support is dropped. rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], nil if verbose puts(command) system(command) else results << command results << `#{command} #{redirector}` end ensure ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps end unless $?.success? then results << "Building has failed. See above output for more information on the failure." if verbose exit_reason = if $?.exited? then ", exit code #{$?.exitstatus}" elsif $?.signaled? then ", uncaught signal #{$?.termsig}" end raise Gem::InstallError, "#{command_name || class_name} failed#{exit_reason}" end end ## # Creates a new extension builder for +spec+. If the +spec+ does not yet # have build arguments, saved, set +build_args+ which is an ARGV-style # array. def initialize spec, build_args = spec.build_args @spec = spec @build_args = build_args @gem_dir = spec.full_gem_path @ran_rake = nil end ## # Chooses the extension builder class for +extension+ def builder_for extension # :nodoc: case extension when /extconf/ then Gem::Ext::ExtConfBuilder when /configure/ then Gem::Ext::ConfigureBuilder when /rakefile/i, /mkrf_conf/i then @ran_rake = true Gem::Ext::RakeBuilder when /CMakeLists.txt/ then Gem::Ext::CmakeBuilder else extension_dir = File.join @gem_dir, File.dirname(extension) message = "No builder for extension '#{extension}'" build_error extension_dir, message end end ## # Logs the build +output+ in +build_dir+, then raises Gem::Ext::BuildError. def build_error build_dir, output, backtrace = nil # :nodoc: gem_make_out = write_gem_make_out output message = <<-EOF ERROR: Failed to build gem native extension. #{output} Gem files will remain installed in #{@gem_dir} for inspection. Results logged to #{gem_make_out} EOF raise Gem::Ext::BuildError, message, backtrace end def build_extension extension, dest_path # :nodoc: results = [] extension ||= '' # I wish I knew why this line existed extension_dir = File.expand_path File.join @gem_dir, File.dirname(extension) lib_dir = File.join @spec.full_gem_path, @spec.raw_require_paths.first builder = builder_for extension begin FileUtils.mkdir_p dest_path CHDIR_MUTEX.synchronize do Dir.chdir extension_dir do results = builder.build(extension, @gem_dir, dest_path, results, @build_args, lib_dir) verbose { results.join("\n") } end end write_gem_make_out results.join "\n" rescue => e results << e.message build_error extension_dir, results.join("\n"), $@ end end ## # Builds extensions. Valid types of extensions are extconf.rb files, # configure scripts and rakefiles or mkrf_conf files. def build_extensions return if @spec.extensions.empty? if @build_args.empty? say "Building native extensions. This could take a while..." else say "Building native extensions with: '#{@build_args.join ' '}'" say "This could take a while..." end dest_path = @spec.extension_dir FileUtils.rm_f @spec.gem_build_complete_path @ran_rake = false # only run rake once @spec.extensions.each do |extension| break if @ran_rake build_extension extension, dest_path end FileUtils.touch @spec.gem_build_complete_path end ## # Writes +output+ to gem_make.out in the extension install directory. def write_gem_make_out output # :nodoc: destination = File.join @spec.extension_dir, 'gem_make.out' FileUtils.mkdir_p @spec.extension_dir open destination, 'wb' do |io| io.puts output end destination end end PK!F}}'2.2.0/rubygems/ext/configure_builder.rbnu[#-- # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. # All rights reserved. # See LICENSE.txt for permissions. #++ class Gem::Ext::ConfigureBuilder < Gem::Ext::Builder def self.build(extension, directory, dest_path, results, args=[], lib_dir=nil) unless File.exist?('Makefile') then cmd = "sh ./configure --prefix=#{dest_path}" cmd << " #{args.join ' '}" unless args.empty? run cmd, results end make dest_path, results results end end PK!P:&2.2.0/rubygems/ext/ext_conf_builder.rbnu[#-- # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. # All rights reserved. # See LICENSE.txt for permissions. #++ require 'fileutils' require 'tempfile' class Gem::Ext::ExtConfBuilder < Gem::Ext::Builder FileEntry = FileUtils::Entry_ # :nodoc: def self.build(extension, directory, dest_path, results, args=[], lib_dir=nil) # relative path required as some versions of mktmpdir return an absolute # path which breaks make if it includes a space in the name tmp_dest = get_relative_path(Dir.mktmpdir(".gem.", ".")) t = nil Tempfile.open %w"siteconf .rb", "." do |siteconf| t = siteconf siteconf.puts "require 'rbconfig'" siteconf.puts "dest_path = #{tmp_dest.dump}" %w[sitearchdir sitelibdir].each do |dir| siteconf.puts "RbConfig::MAKEFILE_CONFIG['#{dir}'] = dest_path" siteconf.puts "RbConfig::CONFIG['#{dir}'] = dest_path" end siteconf.flush destdir = ENV["DESTDIR"] begin cmd = [Gem.ruby, "-r", get_relative_path(siteconf.path), File.basename(extension), *args].join ' ' begin run cmd, results ensure FileUtils.mv 'mkmf.log', dest_path if File.exist? 'mkmf.log' siteconf.unlink end ENV["DESTDIR"] = nil make dest_path, results if tmp_dest # TODO remove in RubyGems 3 if Gem.install_extension_in_lib and lib_dir then FileUtils.mkdir_p lib_dir entries = Dir.entries(tmp_dest) - %w[. ..] entries = entries.map { |entry| File.join tmp_dest, entry } FileUtils.cp_r entries, lib_dir, :remove_destination => true end FileEntry.new(tmp_dest).traverse do |ent| destent = ent.class.new(dest_path, ent.rel) destent.exist? or FileUtils.mv(ent.path, destent.path) end end ensure ENV["DESTDIR"] = destdir end end t.unlink if t and t.path results ensure FileUtils.rm_rf tmp_dest if tmp_dest end private def self.get_relative_path(path) path[0..Dir.pwd.length-1] = '.' if path.start_with?(Dir.pwd) path end end PK!]T  )2.2.0/rubygems/commands/unpack_command.rbnu[require 'rubygems/command' require 'rubygems/installer' require 'rubygems/version_option' require 'rubygems/remote_fetcher' class Gem::Commands::UnpackCommand < Gem::Command include Gem::VersionOption def initialize require 'fileutils' super 'unpack', 'Unpack an installed gem to the current directory', :version => Gem::Requirement.default, :target => Dir.pwd add_option('--target=DIR', 'target directory for unpacking') do |value, options| options[:target] = value end add_option('--spec', 'unpack the gem specification') do |value, options| options[:spec] = true end add_version_option end def arguments # :nodoc: "GEMNAME name of gem to unpack" end def defaults_str # :nodoc: "--version '#{Gem::Requirement.default}'" end def description <<-EOF The unpack command allows you to examine the contents of a gem or modify them to help diagnose a bug. You can add the contents of the unpacked gem to the load path using the RUBYLIB environment variable or -I: $ gem unpack my_gem Unpacked gem: '.../my_gem-1.0' [edit my_gem-1.0/lib/my_gem.rb] $ ruby -Imy_gem-1.0/lib -S other_program You can repackage an unpacked gem using the build command. See the build command help for an example. EOF end def usage # :nodoc: "#{program_name} GEMNAME" end #-- # TODO: allow, e.g., 'gem unpack rake-0.3.1'. Find a general solution for # this, so that it works for uninstall as well. (And check other commands # at the same time.) def execute get_all_gem_names.each do |name| dependency = Gem::Dependency.new name, options[:version] path = get_path dependency unless path then alert_error "Gem '#{name}' not installed nor fetchable." next end if @options[:spec] then spec, metadata = get_metadata path if metadata.nil? then alert_error "--spec is unsupported on '#{name}' (old format gem)" next end spec_file = File.basename spec.spec_file open spec_file, 'w' do |io| io.write metadata end else basename = File.basename path, '.gem' target_dir = File.expand_path basename, options[:target] package = Gem::Package.new path package.extract_files target_dir say "Unpacked gem: '#{target_dir}'" end end end ## # # Find cached filename in Gem.path. Returns nil if the file cannot be found. # #-- # TODO: see comments in get_path() about general service. def find_in_cache(filename) Gem.path.each do |path| this_path = File.join(path, "cache", filename) return this_path if File.exist? this_path end return nil end ## # Return the full path to the cached gem file matching the given # name and version requirement. Returns 'nil' if no match. # # Example: # # get_path 'rake', '> 0.4' # "/usr/lib/ruby/gems/1.8/cache/rake-0.4.2.gem" # get_path 'rake', '< 0.1' # nil # get_path 'rak' # nil (exact name required) #-- # TODO: This should be refactored so that it's a general service. I don't # think any of our existing classes are the right place though. Just maybe # 'Cache'? # # TODO: It just uses Gem.dir for now. What's an easy way to get the list of # source directories? def get_path dependency return dependency.name if dependency.name =~ /\.gem$/i specs = dependency.matching_specs selected = specs.max_by { |s| s.version } return Gem::RemoteFetcher.fetcher.download_to_cache(dependency) unless selected return unless dependency.name =~ /^#{selected.name}$/i # We expect to find (basename).gem in the 'cache' directory. Furthermore, # the name match must be exact (ignoring case). path = find_in_cache File.basename selected.cache_file return Gem::RemoteFetcher.fetcher.download_to_cache(dependency) unless path path end ## # Extracts the Gem::Specification and raw metadata from the .gem file at # +path+. #-- # TODO move to Gem::Package as #raw_spec or something def get_metadata path format = Gem::Package.new path spec = format.spec metadata = nil open path, Gem.binary_mode do |io| tar = Gem::Package::TarReader.new io tar.each_entry do |entry| case entry.full_name when 'metadata' then metadata = entry.read when 'metadata.gz' then metadata = Gem.gunzip entry.read end end end return spec, metadata end end PK!(2.2.0/rubygems/commands/stale_command.rbnu[require 'rubygems/command' class Gem::Commands::StaleCommand < Gem::Command def initialize super('stale', 'List gems along with access times') end def description # :nodoc: <<-EOF The stale command lists the latest access time for all the files in your installed gems. You can use this command to discover gems and gem versions you are no longer using. EOF end def usage # :nodoc: "#{program_name}" end def execute gem_to_atime = {} Gem::Specification.each do |spec| name = spec.full_name Dir["#{spec.full_gem_path}/**/*.*"].each do |file| next if File.directory?(file) stat = File.stat(file) gem_to_atime[name] ||= stat.atime gem_to_atime[name] = stat.atime if gem_to_atime[name] < stat.atime end end gem_to_atime.sort_by { |_, atime| atime }.each do |name, atime| say "#{name} at #{atime.strftime '%c'}" end end end PK!ڏ,2.2.0/rubygems/commands/uninstall_command.rbnu[require 'rubygems/command' require 'rubygems/version_option' require 'rubygems/uninstaller' require 'fileutils' ## # Gem uninstaller command line tool # # See `gem help uninstall` class Gem::Commands::UninstallCommand < Gem::Command include Gem::VersionOption def initialize super 'uninstall', 'Uninstall gems from the local repository', :version => Gem::Requirement.default, :user_install => true, :check_dev => false, :vendor => false add_option('-a', '--[no-]all', 'Uninstall all matching versions' ) do |value, options| options[:all] = value end add_option('-I', '--[no-]ignore-dependencies', 'Ignore dependency requirements while', 'uninstalling') do |value, options| options[:ignore] = value end add_option('-D', '--[no-]-check-development', 'Check development dependencies while uninstalling', '(default: false)') do |value, options| options[:check_dev] = value end add_option('-x', '--[no-]executables', 'Uninstall applicable executables without', 'confirmation') do |value, options| options[:executables] = value end add_option('-i', '--install-dir DIR', 'Directory to uninstall gem from') do |value, options| options[:install_dir] = File.expand_path(value) end add_option('-n', '--bindir DIR', 'Directory to remove binaries from') do |value, options| options[:bin_dir] = File.expand_path(value) end add_option('--[no-]user-install', 'Uninstall from user\'s home directory', 'in addition to GEM_HOME.') do |value, options| options[:user_install] = value end add_option('--[no-]format-executable', 'Assume executable names match Ruby\'s prefix and suffix.') do |value, options| options[:format_executable] = value end add_option('--[no-]force', 'Uninstall all versions of the named gems', 'ignoring dependencies') do |value, options| options[:force] = value end add_option('--[no-]abort-on-dependent', 'Prevent uninstalling gems that are', 'depended on by other gems.') do |value, options| options[:abort_on_dependent] = value end add_version_option add_platform_option add_option('--vendor', 'Uninstall gem from the vendor directory.', 'Only for use by gem repackagers.') do |value, options| unless Gem.vendor_dir then raise OptionParser::InvalidOption.new 'your platform is not supported' end alert_warning 'Use your OS package manager to uninstall vendor gems' options[:vendor] = true options[:install_dir] = Gem.vendor_dir end end def arguments # :nodoc: "GEMNAME name of gem to uninstall" end def defaults_str # :nodoc: "--version '#{Gem::Requirement.default}' --no-force " + "--user-install" end def description # :nodoc: <<-EOF The uninstall command removes a previously installed gem. RubyGems will ask for confirmation if you are attempting to uninstall a gem that is a dependency of an existing gem. You can use the --ignore-dependencies option to skip this check. EOF end def usage # :nodoc: "#{program_name} GEMNAME [GEMNAME ...]" end def execute if options[:all] and not options[:args].empty? then uninstall_specific elsif options[:all] then uninstall_all else uninstall_specific end end def uninstall_all specs = Gem::Specification.reject { |spec| spec.default_gem? } specs.each do |spec| options[:version] = spec.version begin Gem::Uninstaller.new(spec.name, options).uninstall rescue Gem::InstallError end end alert "Uninstalled all gems in #{options[:install_dir]}" end def uninstall_specific deplist = Gem::DependencyList.new get_all_gem_names.uniq.each do |name| Gem::Specification.find_all_by_name(name).each do |spec| deplist.add spec end end deps = deplist.strongly_connected_components.flatten.reverse deps.map(&:name).uniq.each do |gem_name| begin Gem::Uninstaller.new(gem_name, options).uninstall rescue Gem::GemNotInHomeException => e spec = e.spec alert("In order to remove #{spec.name}, please execute:\n" + "\tgem uninstall #{spec.name} --install-dir=#{spec.installation_path}") end end end end PK!7 '2.2.0/rubygems/commands/rdoc_command.rbnu[require 'rubygems/command' require 'rubygems/version_option' require 'rubygems/rdoc' require 'fileutils' class Gem::Commands::RdocCommand < Gem::Command include Gem::VersionOption def initialize super 'rdoc', 'Generates RDoc for pre-installed gems', :version => Gem::Requirement.default, :include_rdoc => false, :include_ri => true, :overwrite => false add_option('--all', 'Generate RDoc/RI documentation for all', 'installed gems') do |value, options| options[:all] = value end add_option('--[no-]rdoc', 'Generate RDoc HTML') do |value, options| options[:include_rdoc] = value end add_option('--[no-]ri', 'Generate RI data') do |value, options| options[:include_ri] = value end add_option('--[no-]overwrite', 'Overwrite installed documents') do |value, options| options[:overwrite] = value end add_version_option end def arguments # :nodoc: "GEMNAME gem to generate documentation for (unless --all)" end def defaults_str # :nodoc: "--version '#{Gem::Requirement.default}' --ri --no-overwrite" end def description # :nodoc: <<-DESC The rdoc command builds documentation for installed gems. By default only documentation is built using rdoc, but additional types of documentation may be built through rubygems plugins and the Gem.post_installs hook. Use --overwrite to force rebuilding of documentation. DESC end def usage # :nodoc: "#{program_name} [args]" end def execute specs = if options[:all] then Gem::Specification.to_a else get_all_gem_names.map do |name| Gem::Specification.find_by_name name, options[:version] end.flatten.uniq end if specs.empty? then alert_error 'No matching gems found' terminate_interaction 1 end specs.each do |spec| doc = Gem::RDoc.new spec, options[:include_rdoc], options[:include_ri] doc.force = options[:overwrite] if options[:overwrite] then FileUtils.rm_rf File.join(spec.doc_dir, 'ri') FileUtils.rm_rf File.join(spec.doc_dir, 'rdoc') end begin doc.generate rescue Errno::ENOENT => e e.message =~ / - / alert_error "Unable to document #{spec.full_name}, #{$'} is missing, skipping" terminate_interaction 1 if specs.length == 1 end end end end PK!paa(2.2.0/rubygems/commands/build_command.rbnu[require 'rubygems/command' require 'rubygems/package' class Gem::Commands::BuildCommand < Gem::Command def initialize super 'build', 'Build a gem from a gemspec' add_option '--force', 'skip validation of the spec' do |value, options| options[:force] = true end end def arguments # :nodoc: "GEMSPEC_FILE gemspec file name to build a gem for" end def description # :nodoc: <<-EOF The build command allows you to create a gem from a ruby gemspec. The best way to build a gem is to use a Rakefile and the Gem::PackageTask which ships with RubyGems. The gemspec can either be created by hand or extracted from an existing gem with gem spec: $ gem unpack my_gem-1.0.gem Unpacked gem: '.../my_gem-1.0' $ gem spec my_gem-1.0.gem --ruby > my_gem-1.0/my_gem-1.0.gemspec $ cd my_gem-1.0 [edit gem contents] $ gem build my_gem-1.0.gemspec EOF end def usage # :nodoc: "#{program_name} GEMSPEC_FILE" end def execute gemspec = get_one_gem_name if File.exist? gemspec then spec = Gem::Specification.load gemspec if spec then Gem::Package.build spec, options[:force] else alert_error "Error loading gemspec. Aborting." terminate_interaction 1 end else alert_error "Gemspec file not found: #{gemspec}" terminate_interaction 1 end end end PK!6(2.2.0/rubygems/commands/fetch_command.rbnu[require 'rubygems/command' require 'rubygems/local_remote_options' require 'rubygems/version_option' class Gem::Commands::FetchCommand < Gem::Command include Gem::LocalRemoteOptions include Gem::VersionOption def initialize super 'fetch', 'Download a gem and place it in the current directory' add_bulk_threshold_option add_proxy_option add_source_option add_clear_sources_option add_version_option add_platform_option add_prerelease_option end def arguments # :nodoc: 'GEMNAME name of gem to download' end def defaults_str # :nodoc: "--version '#{Gem::Requirement.default}'" end def description # :nodoc: <<-EOF The fetch command fetches gem files that can be stored for later use or unpacked to examine their contents. See the build command help for an example of unpacking a gem, modifying it, then repackaging it. EOF end def usage # :nodoc: "#{program_name} GEMNAME [GEMNAME ...]" end def execute version = options[:version] || Gem::Requirement.default platform = Gem.platforms.last gem_names = get_all_gem_names gem_names.each do |gem_name| dep = Gem::Dependency.new gem_name, version dep.prerelease = options[:prerelease] specs_and_sources, errors = Gem::SpecFetcher.fetcher.spec_for_dependency dep if platform then filtered = specs_and_sources.select { |s,| s.platform == platform } specs_and_sources = filtered unless filtered.empty? end spec, source = specs_and_sources.max_by { |s,| s.version } if spec.nil? then show_lookup_failure gem_name, version, errors, options[:domain] next end source.download spec say "Downloaded #{spec.full_name}" end end end PK!J&&*2.2.0/rubygems/commands/install_command.rbnu[require 'rubygems/command' require 'rubygems/install_update_options' require 'rubygems/dependency_installer' require 'rubygems/local_remote_options' require 'rubygems/validator' require 'rubygems/version_option' ## # Gem installer command line tool # # See `gem help install` class Gem::Commands::InstallCommand < Gem::Command attr_reader :installed_specs # :nodoc: include Gem::VersionOption include Gem::LocalRemoteOptions include Gem::InstallUpdateOptions def initialize defaults = Gem::DependencyInstaller::DEFAULT_OPTIONS.merge({ :format_executable => false, :lock => true, :suggest_alternate => true, :version => Gem::Requirement.default, :without_groups => [], }) super 'install', 'Install a gem into the local repository', defaults add_install_update_options add_local_remote_options add_platform_option add_version_option add_prerelease_option "to be installed. (Only for listed gems)" add_option(:"Install/Update", '-g', '--file [FILE]', 'Read from a gem dependencies API file and', 'install the listed gems') do |v,o| v = Gem::GEM_DEP_FILES.find do |file| File.exist? file end unless v unless v then message = v ? v : "(tried #{Gem::GEM_DEP_FILES.join ', '})" raise OptionParser::InvalidArgument, "cannot find gem dependencies file #{message}" end o[:gemdeps] = v end add_option(:"Install/Update", '--without GROUPS', Array, 'Omit the named groups (comma separated)', 'when installing from a gem dependencies', 'file') do |v,o| o[:without_groups].concat v.map { |without| without.intern } end add_option(:"Install/Update", '--default', 'Add the gem\'s full specification to', 'specifications/default and extract only its bin') do |v,o| o[:install_as_default] = v end add_option(:"Install/Update", '--explain', 'Rather than install the gems, indicate which would', 'be installed') do |v,o| o[:explain] = v end add_option(:"Install/Update", '--[no-]lock', 'Create a lock file (when used with -g/--file)') do |v,o| o[:lock] = v end add_option(:"Install/Update", '--[no-]suggestions', 'Suggest alternates when gems are not found') do |v,o| o[:suggest_alternate] = v end @installed_specs = [] end def arguments # :nodoc: "GEMNAME name of gem to install" end def defaults_str # :nodoc: "--both --version '#{Gem::Requirement.default}' --document --no-force\n" + "--install-dir #{Gem.dir} --lock" end def description # :nodoc: <<-EOF The install command installs local or remote gem into a gem repository. For gems with executables ruby installs a wrapper file into the executable directory by default. This can be overridden with the --no-wrappers option. The wrapper allows you to choose among alternate gem versions using _version_. For example `rake _0.7.3_ --version` will run rake version 0.7.3 if a newer version is also installed. Gem Dependency Files ==================== RubyGems can install a consistent set of gems across multiple environments using `gem install -g` when a gem dependencies file (gem.deps.rb, Gemfile or Isolate) is present. If no explicit file is given RubyGems attempts to find one in the current directory. When the RUBYGEMS_GEMDEPS environment variable is set to a gem dependencies file the gems from that file will be activated at startup time. Set it to a specific filename or to "-" to have RubyGems automatically discover the gem dependencies file by walking up from the current directory. NOTE: Enabling automatic discovery on multiuser systems can lead to execution of arbitrary code when used from directories outside your control. Extension Install Failures ========================== If an extension fails to compile during gem installation the gem specification is not written out, but the gem remains unpacked in the repository. You may need to specify the path to the library's headers and libraries to continue. You can do this by adding a -- between RubyGems' options and the extension's build options: $ gem install some_extension_gem [build fails] Gem files will remain installed in \\ /path/to/gems/some_extension_gem-1.0 for inspection. Results logged to /path/to/gems/some_extension_gem-1.0/gem_make.out $ gem install some_extension_gem -- --with-extension-lib=/path/to/lib [build succeeds] $ gem list some_extension_gem *** LOCAL GEMS *** some_extension_gem (1.0) $ If you correct the compilation errors by editing the gem files you will need to write the specification by hand. For example: $ gem install some_extension_gem [build fails] Gem files will remain installed in \\ /path/to/gems/some_extension_gem-1.0 for inspection. Results logged to /path/to/gems/some_extension_gem-1.0/gem_make.out $ [cd /path/to/gems/some_extension_gem-1.0] $ [edit files or what-have-you and run make] $ gem spec ../../cache/some_extension_gem-1.0.gem --ruby > \\ ../../specifications/some_extension_gem-1.0.gemspec $ gem list some_extension_gem *** LOCAL GEMS *** some_extension_gem (1.0) $ EOF end def usage # :nodoc: "#{program_name} GEMNAME [GEMNAME ...] [options] -- --build-flags" end def check_install_dir # :nodoc: if options[:install_dir] and options[:user_install] then alert_error "Use --install-dir or --user-install but not both" terminate_interaction 1 end end def check_version # :nodoc: if options[:version] != Gem::Requirement.default and get_all_gem_names.size > 1 then alert_error "Can't use --version w/ multiple gems. Use name:ver instead." terminate_interaction 1 end end def execute if options.include? :gemdeps then install_from_gemdeps return # not reached end @installed_specs = [] ENV.delete 'GEM_PATH' if options[:install_dir].nil? and RUBY_VERSION > '1.9' check_install_dir check_version load_hooks exit_code = install_gems show_installed terminate_interaction exit_code end def install_from_gemdeps # :nodoc: require 'rubygems/request_set' rs = Gem::RequestSet.new specs = rs.install_from_gemdeps options do |req, inst| s = req.full_spec if inst say "Installing #{s.name} (#{s.version})" else say "Using #{s.name} (#{s.version})" end end @installed_specs = specs terminate_interaction end def install_gem name, version # :nodoc: return if options[:conservative] and not Gem::Dependency.new(name, version).matching_specs.empty? req = Gem::Requirement.create(version) if options[:ignore_dependencies] then install_gem_without_dependencies name, req else inst = Gem::DependencyInstaller.new options request_set = inst.resolve_dependencies name, req if options[:explain] puts "Gems to install:" request_set.sorted_requests.each do |s| puts " #{s.full_name}" end return else @installed_specs.concat request_set.install options end show_install_errors inst.errors end end def install_gem_without_dependencies name, req # :nodoc: gem = nil if local? then if name =~ /\.gem$/ and File.file? name then source = Gem::Source::SpecificFile.new name spec = source.spec else source = Gem::Source::Local.new spec = source.find_gem name, req end gem = source.download spec if spec end if remote? and not gem then dependency = Gem::Dependency.new name, req dependency.prerelease = options[:prerelease] fetcher = Gem::RemoteFetcher.fetcher gem = fetcher.download_to_cache dependency end inst = Gem::Installer.new gem, options inst.install require 'rubygems/dependency_installer' dinst = Gem::DependencyInstaller.new options dinst.installed_gems.replace [inst.spec] Gem.done_installing_hooks.each do |hook| hook.call dinst, [inst.spec] end unless Gem.done_installing_hooks.empty? @installed_specs.push(inst.spec) end def install_gems # :nodoc: exit_code = 0 get_all_gem_names_and_versions.each do |gem_name, gem_version| gem_version ||= options[:version] begin install_gem gem_name, gem_version rescue Gem::InstallError => e alert_error "Error installing #{gem_name}:\n\t#{e.message}" exit_code |= 1 rescue Gem::GemNotFoundException, Gem::UnsatisfiableDependencyError => e domain = options[:domain] domain = :local unless options[:suggest_alternate] show_lookup_failure e.name, e.version, e.errors, domain exit_code |= 2 end end exit_code end ## # Loads post-install hooks def load_hooks # :nodoc: if options[:install_as_default] require 'rubygems/install_default_message' else require 'rubygems/install_message' end require 'rubygems/rdoc' end def show_install_errors errors # :nodoc: return unless errors errors.each do |x| return unless Gem::SourceFetchProblem === x msg = "Unable to pull data from '#{x.source.uri}': #{x.error.message}" alert_warning msg end end def show_installed # :nodoc: return if @installed_specs.empty? gems = @installed_specs.length == 1 ? 'gem' : 'gems' say "#{@installed_specs.length} #{gems} installed" end end PK!TtrCC+2.2.0/rubygems/commands/contents_command.rbnu[require 'English' require 'rubygems/command' require 'rubygems/version_option' class Gem::Commands::ContentsCommand < Gem::Command include Gem::VersionOption def initialize super 'contents', 'Display the contents of the installed gems', :specdirs => [], :lib_only => false, :prefix => true, :show_install_dir => false add_version_option add_option( '--all', "Contents for all gems") do |all, options| options[:all] = all end add_option('-s', '--spec-dir a,b,c', Array, "Search for gems under specific paths") do |spec_dirs, options| options[:specdirs] = spec_dirs end add_option('-l', '--[no-]lib-only', "Only return files in the Gem's lib_dirs") do |lib_only, options| options[:lib_only] = lib_only end add_option( '--[no-]prefix', "Don't include installed path prefix") do |prefix, options| options[:prefix] = prefix end add_option( '--[no-]show-install-dir', 'Show only the gem install dir') do |show, options| options[:show_install_dir] = show end @path_kind = nil @spec_dirs = nil @version = nil end def arguments # :nodoc: "GEMNAME name of gem to list contents for" end def defaults_str # :nodoc: "--no-lib-only --prefix" end def description # :nodoc: <<-EOF The contents command lists the files in an installed gem. The listing can be given as full file names, file names without the installed directory prefix or only the files that are requireable. EOF end def usage # :nodoc: "#{program_name} GEMNAME [GEMNAME ...]" end def execute @version = options[:version] || Gem::Requirement.default @spec_dirs = specification_directories @path_kind = path_description @spec_dirs names = gem_names names.each do |name| found = if options[:show_install_dir] then gem_install_dir name else gem_contents name end terminate_interaction 1 unless found or names.length > 1 end end def files_in spec if spec.default_gem? then files_in_default_gem spec else files_in_gem spec end end def files_in_gem spec gem_path = spec.full_gem_path extra = "/{#{spec.require_paths.join ','}}" if options[:lib_only] glob = "#{gem_path}#{extra}/**/*" prefix_re = /#{Regexp.escape(gem_path)}\// Dir[glob].map do |file| [gem_path, file.sub(prefix_re, "")] end end def files_in_default_gem spec spec.files.map do |file| case file when /\A#{spec.bindir}\// [RbConfig::CONFIG['bindir'], $POSTMATCH] when /\.so\z/ [RbConfig::CONFIG['archdir'], file] else [RbConfig::CONFIG['rubylibdir'], file] end end end def gem_contents name spec = spec_for name return false unless spec files = files_in spec show_files files true end def gem_install_dir name spec = spec_for name return false unless spec say spec.gem_dir true end def gem_names # :nodoc: if options[:all] then Gem::Specification.map(&:name) else get_all_gem_names end end def path_description spec_dirs # :nodoc: if spec_dirs.empty? then "default gem paths" else "specified path" end end def show_files files files.sort.each do |prefix, basename| absolute_path = File.join(prefix, basename) next if File.directory? absolute_path if options[:prefix] then say absolute_path else say basename end end end def spec_for name spec = Gem::Specification.find_all_by_name(name, @version).last return spec if spec say "Unable to find gem '#{name}' in #{@path_kind}" if Gem.configuration.verbose then say "\nDirectories searched:" @spec_dirs.sort.each { |dir| say dir } end return nil end def specification_directories # :nodoc: options[:specdirs].map do |i| [i, File.join(i, "specifications")] end.flatten end end PK!=gg*2.2.0/rubygems/commands/cleanup_command.rbnu[require 'rubygems/command' require 'rubygems/dependency_list' require 'rubygems/uninstaller' class Gem::Commands::CleanupCommand < Gem::Command def initialize super 'cleanup', 'Clean up old versions of installed gems', :force => false, :install_dir => Gem.dir add_option('-n', '-d', '--dryrun', 'Do not uninstall gems') do |value, options| options[:dryrun] = true end @candidate_gems = nil @default_gems = [] @full = nil @gems_to_cleanup = nil @original_home = nil @original_path = nil @primary_gems = nil end def arguments # :nodoc: "GEMNAME name of gem to cleanup" end def defaults_str # :nodoc: "--no-dryrun" end def description # :nodoc: <<-EOF The cleanup command removes old versions of gems from GEM_HOME that are not required to meet a dependency. If a gem is installed elsewhere in GEM_PATH the cleanup command won't delete it. If no gems are named all gems in GEM_HOME are cleaned. EOF end def usage # :nodoc: "#{program_name} [GEMNAME ...]" end def execute say "Cleaning up installed gems..." if options[:args].empty? then done = false last_set = nil until done do clean_gems this_set = @gems_to_cleanup.map { |spec| spec.full_name }.sort done = this_set.empty? || last_set == this_set last_set = this_set end else clean_gems end say "Clean Up Complete" verbose do skipped = @default_gems.map { |spec| spec.full_name } "Skipped default gems: #{skipped.join ', '}" end end def clean_gems get_primary_gems get_candidate_gems get_gems_to_cleanup @full = Gem::DependencyList.from_specs deplist = Gem::DependencyList.new @gems_to_cleanup.each do |spec| deplist.add spec end deps = deplist.strongly_connected_components.flatten @original_home = Gem.dir @original_path = Gem.path deps.reverse_each do |spec| uninstall_dep spec end Gem::Specification.reset end def get_candidate_gems @candidate_gems = unless options[:args].empty? then options[:args].map do |gem_name| Gem::Specification.find_all_by_name gem_name end.flatten else Gem::Specification.to_a end end def get_gems_to_cleanup gems_to_cleanup = @candidate_gems.select { |spec| @primary_gems[spec.name].version != spec.version } default_gems, gems_to_cleanup = gems_to_cleanup.partition { |spec| spec.default_gem? } @default_gems += default_gems @default_gems.uniq! @gems_to_cleanup = gems_to_cleanup.uniq end def get_primary_gems @primary_gems = {} Gem::Specification.each do |spec| if @primary_gems[spec.name].nil? or @primary_gems[spec.name].version < spec.version then @primary_gems[spec.name] = spec end end end def uninstall_dep spec return unless @full.ok_to_remove?(spec.full_name) if options[:dryrun] then say "Dry Run Mode: Would uninstall #{spec.full_name}" return end say "Attempting to uninstall #{spec.full_name}" uninstall_options = { :executables => false, :version => "= #{spec.version}", } uninstall_options[:user_install] = Gem.user_dir == spec.base_dir uninstaller = Gem::Uninstaller.new spec.name, uninstall_options begin uninstaller.uninstall rescue Gem::DependencyRemovalException, Gem::InstallError, Gem::GemNotInHomeException, Gem::FilePermissionError => e say "Unable to uninstall #{spec.full_name}:" say "\t#{e.class}: #{e.message}" end ensure # Restore path Gem::Uninstaller may have changed Gem.use_paths @original_home, *@original_path end end PK!!m'2.2.0/rubygems/commands/cert_command.rbnu[require 'rubygems/command' require 'rubygems/security' begin require 'openssl' rescue LoadError => e raise unless (e.respond_to?(:path) && e.path == 'openssl') || e.message =~ / -- openssl$/ end class Gem::Commands::CertCommand < Gem::Command def initialize super 'cert', 'Manage RubyGems certificates and signing settings', :add => [], :remove => [], :list => [], :build => [], :sign => [] OptionParser.accept OpenSSL::X509::Certificate do |certificate| begin OpenSSL::X509::Certificate.new File.read certificate rescue Errno::ENOENT raise OptionParser::InvalidArgument, "#{certificate}: does not exist" rescue OpenSSL::X509::CertificateError raise OptionParser::InvalidArgument, "#{certificate}: invalid X509 certificate" end end OptionParser.accept OpenSSL::PKey::RSA do |key_file| begin passphrase = ENV['GEM_PRIVATE_KEY_PASSPHRASE'] key = OpenSSL::PKey::RSA.new File.read(key_file), passphrase rescue Errno::ENOENT raise OptionParser::InvalidArgument, "#{key_file}: does not exist" rescue OpenSSL::PKey::RSAError raise OptionParser::InvalidArgument, "#{key_file}: invalid RSA key" end raise OptionParser::InvalidArgument, "#{key_file}: private key not found" unless key.private? key end add_option('-a', '--add CERT', OpenSSL::X509::Certificate, 'Add a trusted certificate.') do |cert, options| options[:add] << cert end add_option('-l', '--list [FILTER]', 'List trusted certificates where the', 'subject contains FILTER') do |filter, options| filter ||= '' options[:list] << filter end add_option('-r', '--remove FILTER', 'Remove trusted certificates where the', 'subject contains FILTER') do |filter, options| options[:remove] << filter end add_option('-b', '--build EMAIL_ADDR', 'Build private key and self-signed', 'certificate for EMAIL_ADDR') do |email_address, options| options[:build] << email_address end add_option('-C', '--certificate CERT', OpenSSL::X509::Certificate, 'Signing certificate for --sign') do |cert, options| options[:issuer_cert] = cert end add_option('-K', '--private-key KEY', OpenSSL::PKey::RSA, 'Key for --sign or --build') do |key, options| options[:key] = key end add_option('-s', '--sign CERT', 'Signs CERT with the key from -K', 'and the certificate from -C') do |cert_file, options| raise OptionParser::InvalidArgument, "#{cert_file}: does not exist" unless File.file? cert_file options[:sign] << cert_file end end def add_certificate certificate # :nodoc: Gem::Security.trust_dir.trust_cert certificate say "Added '#{certificate.subject}'" end def execute options[:add].each do |certificate| add_certificate certificate end options[:remove].each do |filter| remove_certificates_matching filter end options[:list].each do |filter| list_certificates_matching filter end options[:build].each do |name| build name end sign_certificates unless options[:sign].empty? end def build name key, key_path = build_key cert_path = build_cert name, key say "Certificate: #{cert_path}" if key_path say "Private Key: #{key_path}" say "Don't forget to move the key file to somewhere private!" end end def build_cert name, key # :nodoc: cert = Gem::Security.create_cert_email name, key Gem::Security.write cert, "gem-public_cert.pem" end def build_key # :nodoc: return options[:key] if options[:key] passphrase = ask_for_password 'Passphrase for your Private Key:' say "\n" passphrase_confirmation = ask_for_password 'Please repeat the passphrase for your Private Key:' say "\n" raise Gem::CommandLineError, "Passphrase and passphrase confirmation don't match" unless passphrase == passphrase_confirmation key = Gem::Security.create_key key_path = Gem::Security.write key, "gem-private_key.pem", 0600, passphrase return key, key_path end def certificates_matching filter return enum_for __method__, filter unless block_given? Gem::Security.trusted_certificates.select do |certificate, _| subject = certificate.subject.to_s subject.downcase.index filter end.sort_by do |certificate, _| certificate.subject.to_a.map { |name, data,| [name, data] } end.each do |certificate, path| yield certificate, path end end def description # :nodoc: <<-EOF The cert command manages signing keys and certificates for creating signed gems. Your signing certificate and private key are typically stored in ~/.gem/gem-public_cert.pem and ~/.gem/gem-private_key.pem respectively. To build a certificate for signing gems: gem cert --build you@example If you already have an RSA key, or are creating a new certificate for an existing key: gem cert --build you@example --private-key /path/to/key.pem If you wish to trust a certificate you can add it to the trust list with: gem cert --add /path/to/cert.pem You can list trusted certificates with: gem cert --list or: gem cert --list cert_subject_substring If you wish to remove a previously trusted certificate: gem cert --remove cert_subject_substring To sign another gem author's certificate: gem cert --sign /path/to/other_cert.pem For further reading on signing gems see `ri Gem::Security`. EOF end def list_certificates_matching filter # :nodoc: certificates_matching filter do |certificate, _| # this could probably be formatted more gracefully say certificate.subject.to_s end end def load_default_cert cert_file = File.join Gem.default_cert_path cert = File.read cert_file options[:issuer_cert] = OpenSSL::X509::Certificate.new cert rescue Errno::ENOENT alert_error \ "--certificate not specified and ~/.gem/gem-public_cert.pem does not exist" terminate_interaction 1 rescue OpenSSL::X509::CertificateError alert_error \ "--certificate not specified and ~/.gem/gem-public_cert.pem is not valid" terminate_interaction 1 end def load_default_key key_file = File.join Gem.default_key_path key = File.read key_file passphrase = ENV['GEM_PRIVATE_KEY_PASSPHRASE'] options[:key] = OpenSSL::PKey::RSA.new key, passphrase rescue Errno::ENOENT alert_error \ "--private-key not specified and ~/.gem/gem-private_key.pem does not exist" terminate_interaction 1 rescue OpenSSL::PKey::RSAError alert_error \ "--private-key not specified and ~/.gem/gem-private_key.pem is not valid" terminate_interaction 1 end def load_defaults # :nodoc: load_default_cert unless options[:issuer_cert] load_default_key unless options[:key] end def remove_certificates_matching filter # :nodoc: certificates_matching filter do |certificate, path| FileUtils.rm path say "Removed '#{certificate.subject}'" end end def sign cert_file cert = File.read cert_file cert = OpenSSL::X509::Certificate.new cert permissions = File.stat(cert_file).mode & 0777 issuer_cert = options[:issuer_cert] issuer_key = options[:key] cert = Gem::Security.sign cert, issuer_key, issuer_cert Gem::Security.write cert, cert_file, permissions end def sign_certificates # :nodoc: load_defaults unless options[:sign].empty? options[:sign].each do |cert_file| sign cert_file end end end if defined?(OpenSSL::SSL) PK!jP9))'2.2.0/rubygems/commands/help_command.rbnu[require 'rubygems/command' class Gem::Commands::HelpCommand < Gem::Command # :stopdoc: EXAMPLES = <<-EOF Some examples of 'gem' usage. * Install 'rake', either from local directory or remote server: gem install rake * Install 'rake', only from remote server: gem install rake --remote * Install 'rake', but only version 0.3.1, even if dependencies are not met, and into a user-specific directory: gem install rake --version 0.3.1 --force --user-install * List local gems whose name begins with 'D': gem list D * List local and remote gems whose name contains 'log': gem search log --both * List only remote gems whose name contains 'log': gem search log --remote * Uninstall 'rake': gem uninstall rake * Create a gem: See http://guides.rubygems.org/make-your-own-gem/ * See information about RubyGems: gem environment * Update all gems on your system: gem update * Update your local version of RubyGems gem update --system EOF GEM_DEPENDENCIES = <<-EOF A gem dependencies file allows installation of a consistent set of gems across multiple environments. The RubyGems implementation is designed to be compatible with Bundler's Gemfile format. You can see additional documentation on the format at: http://bundler.io RubyGems automatically looks for these gem dependencies files: * gem.deps.rb * Gemfile * Isolate These files are looked up automatically using `gem install -g`, or you can specify a custom file. When the RUBYGEMS_GEMDEPS environment variable is set to a gem dependencies file the gems from that file will be activated at startup time. Set it to a specific filename or to "-" to have RubyGems automatically discover the gem dependencies file by walking up from the current directory. You can also activate gem dependencies at program startup using Gem.use_gemdeps. NOTE: Enabling automatic discovery on multiuser systems can lead to execution of arbitrary code when used from directories outside your control. Gem Dependencies ================ Use #gem to declare which gems you directly depend upon: gem 'rake' To depend on a specific set of versions: gem 'rake', '~> 10.3', '>= 10.3.2' RubyGems will require the gem name when activating the gem using the RUBYGEMS_GEMDEPS environment variable or Gem::use_gemdeps. Use the require: option to override this behavior if the gem does not have a file of that name or you don't want to require those files: gem 'my_gem', require: 'other_file' To prevent RubyGems from requiring any files use: gem 'my_gem', require: false To load dependencies from a .gemspec file: gemspec RubyGems looks for the first .gemspec file in the current directory. To override this use the name: option: gemspec name: 'specific_gem' To look in a different directory use the path: option: gemspec name: 'specific_gem', path: 'gemspecs' To depend on a gem unpacked into a local directory: gem 'modified_gem', path: 'vendor/modified_gem' To depend on a gem from git: gem 'private_gem', git: 'git@my.company.example:private_gem.git' To depend on a gem from github: gem 'private_gem', github: 'my_company/private_gem' To depend on a gem from a github gist: gem 'bang', gist: '1232884' Git, github and gist support the ref:, branch: and tag: options to specify a commit reference or hash, branch or tag respectively to use for the gem. Setting the submodules: option to true for git, github and gist dependencies causes fetching of submodules when fetching the repository. You can depend on multiple gems from a single repository with the git method: git 'https://github.com/rails/rails.git' do gem 'activesupport' gem 'activerecord' end Gem Sources =========== RubyGems uses the default sources for regular `gem install` for gem dependencies files. Unlike bundler, you do need to specify a source. You can override the sources used for downloading gems with: source 'https://gem_server.example' You may specify multiple sources. Unlike bundler the prepend: option is not supported. Sources are used in-order, to prepend a source place it at the front of the list. Gem Platform ============ You can restrict gem dependencies to specific platforms with the #platform and #platforms methods: platform :ruby_21 do gem 'debugger' end See the bundler Gemfile manual page for a list of platforms supported in a gem dependencies file.: http://bundler.io/v1.6/man/gemfile.5.html Ruby Version and Engine Dependency ================================== You can specifiy the version, engine and engine version of ruby to use with your gem dependencies file. If you are not running the specified version RubyGems will raise an exception. To depend on a specific version of ruby: ruby '2.1.2' To depend on a specific ruby engine: ruby '1.9.3', engine: 'jruby' To depend on a specific ruby engine version: ruby '1.9.3', engine: 'jruby', engine_version: '1.7.11' Grouping Dependencies ===================== Gem dependencies may be placed in groups that can be excluded from install. Dependencies required for development or testing of your code may be excluded when installed in a production environment. A #gem dependency may be placed in a group using the group: option: gem 'minitest', group: :test To install dependencies from a gemfile without specific groups use the `--without` option for `gem install -g`: $ gem install -g --without test The group: option also accepts multiple groups if the gem fits in multiple categories. Multiple groups may be excluded during install by comma-separating the groups for `--without` or by specifying `--without` multiple times. The #group method can also be used to place gems in groups: group :test do gem 'minitest' gem 'minitest-emoji' end The #group method allows multiple groups. The #gemspec development dependencies are placed in the :development group by default. This may be overriden with the :development_group option: gemspec development_group: :other EOF PLATFORMS = <<-'EOF' RubyGems platforms are composed of three parts, a CPU, an OS, and a version. These values are taken from values in rbconfig.rb. You can view your current platform by running `gem environment`. RubyGems matches platforms as follows: * The CPU must match exactly unless one of the platforms has "universal" as the CPU or the local CPU starts with "arm" and the gem's CPU is exactly "arm" (for gems that support generic ARM architecture). * The OS must match exactly. * The versions must match exactly unless one of the versions is nil. For commands that install, uninstall and list gems, you can override what RubyGems thinks your platform is with the --platform option. The platform you pass must match "#{cpu}-#{os}" or "#{cpu}-#{os}-#{version}". On mswin platforms, the version is the compiler version, not the OS version. (Ruby compiled with VC6 uses "60" as the compiler version, VC8 uses "80".) For the ARM architecture, gems with a platform of "arm-linux" should run on a reasonable set of ARM CPUs and not depend on instructions present on a limited subset of the architecture. For example, the binary should run on platforms armv5, armv6hf, armv6l, armv7, etc. If you use the "arm-linux" platform please test your gem on a variety of ARM hardware before release to ensure it functions correctly. Example platforms: x86-freebsd # Any FreeBSD version on an x86 CPU universal-darwin-8 # Darwin 8 only gems that run on any CPU x86-mswin32-80 # Windows gems compiled with VC8 armv7-linux # Gem complied for an ARMv7 CPU running linux arm-linux # Gem compiled for any ARM CPU running linux When building platform gems, set the platform in the gem specification to Gem::Platform::CURRENT. This will correctly mark the gem with your ruby's platform. EOF # NOTE when updating also update Gem::Command::HELP SUBCOMMANDS = [ ["commands", :show_commands], ["options", Gem::Command::HELP], ["examples", EXAMPLES], ["gem_dependencies", GEM_DEPENDENCIES], ["platforms", PLATFORMS], ] # :startdoc: def initialize super 'help', "Provide help on the 'gem' command" @command_manager = Gem::CommandManager.instance end def usage # :nodoc: "#{program_name} ARGUMENT" end def execute arg = options[:args][0] _, help = SUBCOMMANDS.find do |command,| begins? command, arg end if help then if Symbol === help then send help else say help end return end if options[:help] then show_help elsif arg then show_command_help arg else say Gem::Command::HELP end end def show_commands # :nodoc: out = [] out << "GEM commands are:" out << nil margin_width = 4 desc_width = @command_manager.command_names.map { |n| n.size }.max + 4 summary_width = 80 - margin_width - desc_width wrap_indent = ' ' * (margin_width + desc_width) format = "#{' ' * margin_width}%-#{desc_width}s%s" @command_manager.command_names.each do |cmd_name| command = @command_manager[cmd_name] summary = if command then command.summary else "[No command found for #{cmd_name}]" end summary = wrap(summary, summary_width).split "\n" out << sprintf(format, cmd_name, summary.shift) until summary.empty? do out << "#{wrap_indent}#{summary.shift}" end end out << nil out << "For help on a particular command, use 'gem help COMMAND'." out << nil out << "Commands may be abbreviated, so long as they are unambiguous." out << "e.g. 'gem i rake' is short for 'gem install rake'." say out.join("\n") end def show_command_help command_name # :nodoc: command_name = command_name.downcase possibilities = @command_manager.find_command_possibilities command_name if possibilities.size == 1 then command = @command_manager[possibilities.first] command.invoke("--help") elsif possibilities.size > 1 then alert_warning "Ambiguous command #{command_name} (#{possibilities.join(', ')})" else alert_warning "Unknown command #{command_name}. Try: gem help commands" end end def show_help # :nodoc: command = @command_manager[options[:help]] if command then # help with provided command command.invoke("--help") else alert_error "Unknown command #{options[:help]}. Try 'gem help commands'" end end end PK!.-2.2.0/rubygems/commands/dependency_command.rbnu[require 'rubygems/command' require 'rubygems/local_remote_options' require 'rubygems/version_option' class Gem::Commands::DependencyCommand < Gem::Command include Gem::LocalRemoteOptions include Gem::VersionOption def initialize super 'dependency', 'Show the dependencies of an installed gem', :version => Gem::Requirement.default, :domain => :local add_version_option add_platform_option add_prerelease_option add_option('-R', '--[no-]reverse-dependencies', 'Include reverse dependencies in the output') do |value, options| options[:reverse_dependencies] = value end add_option('-p', '--pipe', "Pipe Format (name --version ver)") do |value, options| options[:pipe_format] = value end add_local_remote_options end def arguments # :nodoc: "REGEXP show dependencies for gems whose names start with REGEXP" end def defaults_str # :nodoc: "--local --version '#{Gem::Requirement.default}' --no-reverse-dependencies" end def description # :nodoc: <<-EOF The dependency commands lists which other gems a given gem depends on. For local gems only the reverse dependencies can be shown (which gems depend on the named gem). The dependency list can be displayed in a format suitable for piping for use with other commands. EOF end def usage # :nodoc: "#{program_name} REGEXP" end def fetch_remote_specs dependency # :nodoc: fetcher = Gem::SpecFetcher.fetcher ss, = fetcher.spec_for_dependency dependency ss.map { |spec, _| spec } end def fetch_specs dependency # :nodoc: specs = [] specs.concat dependency.matching_specs if local? specs.concat fetch_remote_specs dependency if remote? ensure_specs specs specs.uniq.sort end def gem_dependency args, version, prerelease # :nodoc: args << '' if args.empty? pattern = if args.length == 1 and args.first =~ /\A\/(.*)\/(i)?\z/m then flags = $2 ? Regexp::IGNORECASE : nil Regexp.new $1, flags else /\A#{Regexp.union(*args)}/ end dependency = Gem::Deprecate.skip_during { Gem::Dependency.new pattern, version } dependency.prerelease = prerelease dependency end def display_pipe specs # :nodoc: specs.each do |spec| unless spec.dependencies.empty? then spec.dependencies.sort_by { |dep| dep.name }.each do |dep| say "#{dep.name} --version '#{dep.requirement}'" end end end end def display_readable specs, reverse # :nodoc: response = '' specs.each do |spec| response << print_dependencies(spec) unless reverse[spec.full_name].empty? then response << " Used by\n" reverse[spec.full_name].each do |sp, dep| response << " #{sp} (#{dep})\n" end end response << "\n" end say response end def execute ensure_local_only_reverse_dependencies dependency = gem_dependency options[:args], options[:version], options[:prerelease] specs = fetch_specs dependency reverse = reverse_dependencies specs if options[:pipe_format] then display_pipe specs else display_readable specs, reverse end end def ensure_local_only_reverse_dependencies # :nodoc: if options[:reverse_dependencies] and remote? and not local? then alert_error 'Only reverse dependencies for local gems are supported.' terminate_interaction 1 end end def ensure_specs specs # :nodoc: return unless specs.empty? patterns = options[:args].join ',' say "No gems found matching #{patterns} (#{options[:version]})" if Gem.configuration.verbose terminate_interaction 1 end def print_dependencies(spec, level = 0) # :nodoc: response = '' response << ' ' * level + "Gem #{spec.full_name}\n" unless spec.dependencies.empty? then spec.dependencies.sort_by { |dep| dep.name }.each do |dep| response << ' ' * level + " #{dep}\n" end end response end def remote_specs dependency # :nodoc: fetcher = Gem::SpecFetcher.fetcher ss, _ = fetcher.spec_for_dependency dependency ss.map { |s,o| s } end def reverse_dependencies specs # :nodoc: reverse = Hash.new { |h, k| h[k] = [] } return reverse unless options[:reverse_dependencies] specs.each do |spec| reverse[spec.full_name] = find_reverse_dependencies spec end reverse end ## # Returns an Array of [specification, dep] that are satisfied by +spec+. def find_reverse_dependencies spec # :nodoc: result = [] Gem::Specification.each do |sp| sp.dependencies.each do |dep| dep = Gem::Dependency.new(*dep) unless Gem::Dependency === dep if spec.name == dep.name and dep.requirement.satisfied_by?(spec.version) then result << [sp.full_name, dep] end end end result end end PK!?]]+2.2.0/rubygems/commands/pristine_command.rbnu[require 'rubygems/command' require 'rubygems/package' require 'rubygems/installer' require 'rubygems/version_option' class Gem::Commands::PristineCommand < Gem::Command include Gem::VersionOption def initialize super 'pristine', 'Restores installed gems to pristine condition from files located in the gem cache', :version => Gem::Requirement.default, :extensions => true, :extensions_set => false, :all => false add_option('--all', 'Restore all installed gems to pristine', 'condition') do |value, options| options[:all] = value end add_option('--[no-]extensions', 'Restore gems with extensions', 'in addition to regular gems') do |value, options| options[:extensions_set] = true options[:extensions] = value end add_option('--only-executables', 'Only restore executables') do |value, options| options[:only_executables] = value end add_option('-E', '--[no-]env-shebang', 'Rewrite executables with a shebang', 'of /usr/bin/env') do |value, options| options[:env_shebang] = value end add_version_option('restore to', 'pristine condition') end def arguments # :nodoc: "GEMNAME gem to restore to pristine condition (unless --all)" end def defaults_str # :nodoc: '--extensions' end def description # :nodoc: <<-EOF The pristine command compares an installed gem with the contents of its cached .gem file and restores any files that don't match the cached .gem's copy. If you have made modifications to an installed gem, the pristine command will revert them. All extensions are rebuilt and all bin stubs for the gem are regenerated after checking for modifications. If the cached gem cannot be found it will be downloaded. If --no-extensions is provided pristine will not attempt to restore a gem with an extension. If --extensions is given (but not --all or gem names) only gems with extensions will be restored. EOF end def usage # :nodoc: "#{program_name} [GEMNAME ...]" end def execute specs = if options[:all] then Gem::Specification.map # `--extensions` must be explicitly given to pristine only gems # with extensions. elsif options[:extensions_set] and options[:extensions] and options[:args].empty? then Gem::Specification.select do |spec| spec.extensions and not spec.extensions.empty? end else get_all_gem_names.map do |gem_name| Gem::Specification.find_all_by_name gem_name, options[:version] end.flatten end if specs.to_a.empty? then raise Gem::Exception, "Failed to find gems #{options[:args]} #{options[:version]}" end install_dir = Gem.dir # TODO use installer option raise Gem::FilePermissionError.new(install_dir) unless File.writable?(install_dir) say "Restoring gems to pristine condition..." specs.each do |spec| if spec.default_gem? say "Skipped #{spec.full_name}, it is a default gem" next end if spec.bundled_gem_in_old_ruby? say "Skipped #{spec.full_name}, it is bundled with old Ruby" next end unless spec.extensions.empty? or options[:extensions] then say "Skipped #{spec.full_name}, it needs to compile an extension" next end gem = spec.cache_file unless File.exist? gem then require 'rubygems/remote_fetcher' say "Cached gem for #{spec.full_name} not found, attempting to fetch..." dep = Gem::Dependency.new spec.name, spec.version found, _ = Gem::SpecFetcher.fetcher.spec_for_dependency dep if found.empty? say "Skipped #{spec.full_name}, it was not found from cache and remote sources" next end spec_candidate, source = found.first Gem::RemoteFetcher.fetcher.download spec_candidate, source.uri.to_s, spec.base_dir end env_shebang = if options.include? :env_shebang then options[:env_shebang] else install_defaults = Gem::ConfigFile::PLATFORM_DEFAULTS['install'] install_defaults.to_s['--env-shebang'] end installer = Gem::Installer.new(gem, :wrappers => true, :force => true, :install_dir => spec.base_dir, :env_shebang => env_shebang, :build_args => spec.build_args) if options[:only_executables] then installer.generate_bin else installer.install end say "Restored #{spec.full_name}" end end end PK!.2.2.0/rubygems/commands/environment_command.rbnu[require 'rubygems/command' class Gem::Commands::EnvironmentCommand < Gem::Command def initialize super 'environment', 'Display information about the RubyGems environment' end def arguments # :nodoc: args = <<-EOF packageversion display the package version gemdir display the path where gems are installed gempath display path used to search for gems version display the gem format version remotesources display the remote gem servers platform display the supported gem platforms display everything EOF return args.gsub(/^\s+/, '') end def description # :nodoc: <<-EOF The environment command lets you query rubygems for its configuration for use in shell scripts or as a debugging aid. The RubyGems environment can be controlled through command line arguments, gemrc files, environment variables and built-in defaults. Command line argument defaults and some RubyGems defaults can be set in a ~/.gemrc file for individual users and a gemrc in the SYSTEM CONFIGURATION DIRECTORY for all users. These files are YAML files with the following YAML keys: :sources: A YAML array of remote gem repositories to install gems from :verbose: Verbosity of the gem command. false, true, and :really are the levels :update_sources: Enable/disable automatic updating of repository metadata :backtrace: Print backtrace when RubyGems encounters an error :gempath: The paths in which to look for gems :disable_default_gem_server: Force specification of gem server host on push : A string containing arguments for the specified gem command Example: :verbose: false install: --no-wrappers update: --no-wrappers :disable_default_gem_server: true RubyGems' default local repository can be overridden with the GEM_PATH and GEM_HOME environment variables. GEM_HOME sets the default repository to install into. GEM_PATH allows multiple local repositories to be searched for gems. If you are behind a proxy server, RubyGems uses the HTTP_PROXY, HTTP_PROXY_USER and HTTP_PROXY_PASS environment variables to discover the proxy server. If you would like to push gems to a private gem server the RUBYGEMS_HOST environment variable can be set to the URI for that server. If you are packaging RubyGems all of RubyGems' defaults are in lib/rubygems/defaults.rb. You may override these in lib/rubygems/defaults/operating_system.rb EOF end def usage # :nodoc: "#{program_name} [arg]" end def execute out = '' arg = options[:args][0] out << case arg when /^packageversion/ then Gem::RubyGemsPackageVersion when /^version/ then Gem::VERSION when /^gemdir/, /^gemhome/, /^home/, /^GEM_HOME/ then Gem.dir when /^gempath/, /^path/, /^GEM_PATH/ then Gem.path.join(File::PATH_SEPARATOR) when /^remotesources/ then Gem.sources.to_a.join("\n") when /^platform/ then Gem.platforms.join(File::PATH_SEPARATOR) when nil then show_environment else raise Gem::CommandLineError, "Unknown environment option [#{arg}]" end say out true end def add_path out, path path.each do |component| out << " - #{component}\n" end end def show_environment # :nodoc: out = "RubyGems Environment:\n" out << " - RUBYGEMS VERSION: #{Gem::VERSION}\n" out << " - RUBY VERSION: #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}" out << " patchlevel #{RUBY_PATCHLEVEL}" if defined? RUBY_PATCHLEVEL out << ") [#{RUBY_PLATFORM}]\n" out << " - INSTALLATION DIRECTORY: #{Gem.dir}\n" out << " - RUBYGEMS PREFIX: #{Gem.prefix}\n" unless Gem.prefix.nil? out << " - RUBY EXECUTABLE: #{Gem.ruby}\n" out << " - EXECUTABLE DIRECTORY: #{Gem.bindir}\n" out << " - SPEC CACHE DIRECTORY: #{Gem.spec_cache_dir}\n" out << " - SYSTEM CONFIGURATION DIRECTORY: #{Gem::ConfigFile::SYSTEM_CONFIG_PATH}\n" out << " - RUBYGEMS PLATFORMS:\n" Gem.platforms.each do |platform| out << " - #{platform}\n" end out << " - GEM PATHS:\n" out << " - #{Gem.dir}\n" gem_path = Gem.path.dup gem_path.delete Gem.dir add_path out, gem_path out << " - GEM CONFIGURATION:\n" Gem.configuration.each do |name, value| value = value.gsub(/./, '*') if name == 'gemcutter_key' out << " - #{name.inspect} => #{value.inspect}\n" end out << " - REMOTE SOURCES:\n" Gem.sources.each do |s| out << " - #{s}\n" end out << " - SHELL PATH:\n" shell_path = ENV['PATH'].split(File::PATH_SEPARATOR) add_path out, shell_path out end end PK!##(2.2.0/rubygems/commands/query_command.rbnu[require 'rubygems/command' require 'rubygems/local_remote_options' require 'rubygems/spec_fetcher' require 'rubygems/version_option' require 'rubygems/text' class Gem::Commands::QueryCommand < Gem::Command include Gem::Text include Gem::LocalRemoteOptions include Gem::VersionOption def initialize(name = 'query', summary = 'Query gem information in local or remote repositories') super name, summary, :name => //, :domain => :local, :details => false, :versions => true, :installed => nil, :version => Gem::Requirement.default add_option('-i', '--[no-]installed', 'Check for installed gem') do |value, options| options[:installed] = value end add_option('-I', 'Equivalent to --no-installed') do |value, options| options[:installed] = false end add_version_option command, "for use with --installed" add_option('-n', '--name-matches REGEXP', 'Name of gem(s) to query on matches the', 'provided REGEXP') do |value, options| options[:name] = /#{value}/i end add_option('-d', '--[no-]details', 'Display detailed information of gem(s)') do |value, options| options[:details] = value end add_option( '--[no-]versions', 'Display only gem names') do |value, options| options[:versions] = value options[:details] = false unless value end add_option('-a', '--all', 'Display all gem versions') do |value, options| options[:all] = value end add_option( '--[no-]prerelease', 'Display prerelease versions') do |value, options| options[:prerelease] = value end add_local_remote_options end def defaults_str # :nodoc: "--local --name-matches // --no-details --versions --no-installed" end def description # :nodoc: <<-EOF The query command is the basis for the list and search commands. You should really use the list and search commands instead. This command is too hard to use. EOF end def execute exit_code = 0 if options[:args].to_a.empty? and options[:name].source.empty? name = options[:name] no_name = true elsif !options[:name].source.empty? name = Array(options[:name]) else name = options[:args].to_a.map{|arg| /#{arg}/i } end prerelease = options[:prerelease] unless options[:installed].nil? then if no_name then alert_error "You must specify a gem name" exit_code |= 4 elsif name.count > 1 alert_error "You must specify only ONE gem!" exit_code |= 4 else installed = installed? name.first, options[:version] installed = !installed unless options[:installed] if installed then say "true" else say "false" exit_code |= 1 end end terminate_interaction exit_code end names = Array(name) names.each { |n| show_gems n, prerelease } end private def display_header type if (ui.outs.tty? and Gem.configuration.verbose) or both? then say say "*** #{type} GEMS ***" say end end #Guts of original execute def show_gems name, prerelease req = Gem::Requirement.default # TODO: deprecate for real dep = Gem::Deprecate.skip_during { Gem::Dependency.new name, req } dep.prerelease = prerelease if local? then if prerelease and not both? then alert_warning "prereleases are always shown locally" end display_header 'LOCAL' specs = Gem::Specification.find_all { |s| s.name =~ name and req =~ s.version } spec_tuples = specs.map do |spec| [spec.name_tuple, spec] end output_query_results spec_tuples end if remote? then display_header 'REMOTE' fetcher = Gem::SpecFetcher.fetcher type = if options[:all] if options[:prerelease] :complete else :released end elsif options[:prerelease] :prerelease else :latest end if name.source.empty? spec_tuples = fetcher.detect(type) { true } else spec_tuples = fetcher.detect(type) do |name_tuple| name === name_tuple.name end end output_query_results spec_tuples end end ## # Check if gem +name+ version +version+ is installed. def installed?(name, req = Gem::Requirement.default) Gem::Specification.any? { |s| s.name =~ name and req =~ s.version } end def output_query_results(spec_tuples) output = [] versions = Hash.new { |h,name| h[name] = [] } spec_tuples.each do |spec_tuple, source| versions[spec_tuple.name] << [spec_tuple, source] end versions = versions.sort_by do |(n,_),_| n.downcase end output_versions output, versions say output.join(options[:details] ? "\n\n" : "\n") end def output_versions output, versions versions.each do |gem_name, matching_tuples| matching_tuples = matching_tuples.sort_by { |n,_| n.version }.reverse platforms = Hash.new { |h,version| h[version] = [] } matching_tuples.each do |n, _| platforms[n.version] << n.platform if n.platform end seen = {} matching_tuples.delete_if do |n,_| if seen[n.version] then true else seen[n.version] = true false end end output << clean_text(make_entry(matching_tuples, platforms)) end end def entry_details entry, detail_tuple, specs, platforms return unless options[:details] name_tuple, spec = detail_tuple spec = spec.fetch_spec name_tuple unless Gem::Specification === spec entry << "\n" spec_platforms entry, platforms spec_authors entry, spec spec_homepage entry, spec spec_license entry, spec spec_loaded_from entry, spec, specs spec_summary entry, spec end def entry_versions entry, name_tuples, platforms return unless options[:versions] list = if platforms.empty? or options[:details] then name_tuples.map { |n| n.version }.uniq else platforms.sort.reverse.map do |version, pls| if pls == [Gem::Platform::RUBY] then version else ruby = pls.delete Gem::Platform::RUBY platform_list = [ruby, *pls.sort].compact "#{version} #{platform_list.join ' '}" end end end entry << " (#{list.join ', '})" end def make_entry entry_tuples, platforms detail_tuple = entry_tuples.first name_tuples, specs = entry_tuples.flatten.partition do |item| Gem::NameTuple === item end entry = [name_tuples.first.name] entry_versions entry, name_tuples, platforms entry_details entry, detail_tuple, specs, platforms entry.join end def spec_authors entry, spec authors = "Author#{spec.authors.length > 1 ? 's' : ''}: " authors << spec.authors.join(', ') entry << format_text(authors, 68, 4) end def spec_homepage entry, spec return if spec.homepage.nil? or spec.homepage.empty? entry << "\n" << format_text("Homepage: #{spec.homepage}", 68, 4) end def spec_license entry, spec return if spec.license.nil? or spec.license.empty? licenses = "License#{spec.licenses.length > 1 ? 's' : ''}: " licenses << spec.licenses.join(', ') entry << "\n" << format_text(licenses, 68, 4) end def spec_loaded_from entry, spec, specs return unless spec.loaded_from if specs.length == 1 then default = spec.default_gem? ? ' (default)' : nil entry << "\n" << " Installed at#{default}: #{spec.base_dir}" else label = 'Installed at' specs.each do |s| version = s.version.to_s version << ', default' if s.default_gem? entry << "\n" << " #{label} (#{version}): #{s.base_dir}" label = ' ' * label.length end end end def spec_platforms entry, platforms non_ruby = platforms.any? do |_, pls| pls.any? { |pl| pl != Gem::Platform::RUBY } end return unless non_ruby if platforms.length == 1 then title = platforms.values.length == 1 ? 'Platform' : 'Platforms' entry << " #{title}: #{platforms.values.sort.join ', '}\n" else entry << " Platforms:\n" platforms.sort_by do |version,| version end.each do |version, pls| label = " #{version}: " data = format_text pls.sort.join(', '), 68, label.length data[0, label.length] = label entry << data << "\n" end end end def spec_summary entry, spec summary = truncate_text(spec.summary, "the summary for #{spec.full_name}") entry << "\n\n" << format_text(summary, 68, 4) end end PK!8  02.2.0/rubygems/commands/specification_command.rbnu[require 'rubygems/command' require 'rubygems/local_remote_options' require 'rubygems/version_option' require 'rubygems/package' class Gem::Commands::SpecificationCommand < Gem::Command include Gem::LocalRemoteOptions include Gem::VersionOption def initialize Gem.load_yaml super 'specification', 'Display gem specification (in yaml)', :domain => :local, :version => Gem::Requirement.default, :format => :yaml add_version_option('examine') add_platform_option add_prerelease_option add_option('--all', 'Output specifications for all versions of', 'the gem') do |value, options| options[:all] = true end add_option('--ruby', 'Output ruby format') do |value, options| options[:format] = :ruby end add_option('--yaml', 'Output YAML format') do |value, options| options[:format] = :yaml end add_option('--marshal', 'Output Marshal format') do |value, options| options[:format] = :marshal end add_local_remote_options end def arguments # :nodoc: <<-ARGS GEMFILE name of gem to show the gemspec for FIELD name of gemspec field to show ARGS end def defaults_str # :nodoc: "--local --version '#{Gem::Requirement.default}' --yaml" end def description # :nodoc: <<-EOF The specification command allows you to extract the specification from a gem for examination. The specification can be output in YAML, ruby or Marshal formats. Specific fields in the specification can be extracted in YAML format: $ gem spec rake summary --- Ruby based make-like utility. ... EOF end def usage # :nodoc: "#{program_name} [GEMFILE] [FIELD]" end def execute specs = [] gem = options[:args].shift unless gem then raise Gem::CommandLineError, "Please specify a gem name or file on the command line" end case v = options[:version] when String req = Gem::Requirement.create v when Gem::Requirement req = v else raise Gem::CommandLineError, "Unsupported version type: '#{v}'" end if !req.none? and options[:all] alert_error "Specify --all or -v, not both" terminate_interaction 1 end if options[:all] dep = Gem::Dependency.new gem else dep = Gem::Dependency.new gem, req end field = get_one_optional_argument raise Gem::CommandLineError, "--ruby and FIELD are mutually exclusive" if field and options[:format] == :ruby if local? then if File.exist? gem then specs << Gem::Package.new(gem).spec rescue nil end if specs.empty? then specs.push(*dep.matching_specs) end end if remote? then dep.prerelease = options[:prerelease] found, _ = Gem::SpecFetcher.fetcher.spec_for_dependency dep specs.push(*found.map { |spec,| spec }) end if specs.empty? then alert_error "No gem matching '#{dep}' found" terminate_interaction 1 end unless options[:all] then specs = [specs.max_by { |s| s.version }] end specs.each do |s| s = s.send field if field say case options[:format] when :ruby then s.to_ruby when :marshal then Marshal.dump s else s.to_yaml end say "\n" end end end PK!k^ ^ (2.2.0/rubygems/commands/owner_command.rbnu[require 'rubygems/command' require 'rubygems/local_remote_options' require 'rubygems/gemcutter_utilities' class Gem::Commands::OwnerCommand < Gem::Command include Gem::LocalRemoteOptions include Gem::GemcutterUtilities def description # :nodoc: <<-EOF The owner command lets you add and remove owners of a gem on a push server (the default is https://rubygems.org). The owner of a gem has the permission to push new versions, yank existing versions or edit the HTML page of the gem. Be careful of who you give push permission to. EOF end def arguments # :nodoc: "GEM gem to manage owners for" end def usage # :nodoc: "#{program_name} GEM" end def initialize super 'owner', 'Manage gem owners of a gem on the push server' add_proxy_option add_key_option defaults.merge! :add => [], :remove => [] add_option '-a', '--add EMAIL', 'Add an owner' do |value, options| options[:add] << value end add_option '-r', '--remove EMAIL', 'Remove an owner' do |value, options| options[:remove] << value end add_option '-h', '--host HOST', 'Use another gemcutter-compatible host' do |value, options| options[:host] = value end end def execute @host = options[:host] sign_in name = get_one_gem_name add_owners name, options[:add] remove_owners name, options[:remove] show_owners name end def show_owners name response = rubygems_api_request :get, "api/v1/gems/#{name}/owners.yaml" do |request| request.add_field "Authorization", api_key end with_response response do |resp| owners = YAML.load resp.body say "Owners for gem: #{name}" owners.each do |owner| say "- #{owner['email']}" end end end def add_owners name, owners manage_owners :post, name, owners end def remove_owners name, owners manage_owners :delete, name, owners end def manage_owners method, name, owners owners.each do |owner| begin response = rubygems_api_request method, "api/v1/gems/#{name}/owners" do |request| request.set_form_data 'email' => owner request.add_field "Authorization", api_key end action = method == :delete ? "Removing" : "Adding" with_response response, "#{action} #{owner}" rescue # ignore end end end end PK!/WW)2.2.0/rubygems/commands/search_command.rbnu[require 'rubygems/command' require 'rubygems/commands/query_command' class Gem::Commands::SearchCommand < Gem::Commands::QueryCommand def initialize super 'search', 'Display remote gems whose name matches REGEXP' remove_option '--name-matches' defaults[:domain] = :remote end def arguments # :nodoc: "REGEXP regexp to search for in gem name" end def defaults_str # :nodoc: "--remote --no-details" end def description # :nodoc: <<-EOF The search command displays remote gems whose name matches the given regexp. The --details option displays additional details from the gem but will take a little longer to complete as it must download the information individually from the index. To list local gems use the list command. EOF end def usage # :nodoc: "#{program_name} [REGEXP]" end end PK!Uo(2.2.0/rubygems/commands/which_command.rbnu[require 'rubygems/command' class Gem::Commands::WhichCommand < Gem::Command def initialize super 'which', 'Find the location of a library file you can require', :search_gems_first => false, :show_all => false add_option '-a', '--[no-]all', 'show all matching files' do |show_all, options| options[:show_all] = show_all end add_option '-g', '--[no-]gems-first', 'search gems before non-gems' do |gems_first, options| options[:search_gems_first] = gems_first end end def arguments # :nodoc: "FILE name of file to find" end def defaults_str # :nodoc: "--no-gems-first --no-all" end def description # :nodoc: <<-EOF The which command is like the shell which command and shows you where the file you wish to require lives. You can use the which command to help determine why you are requiring a version you did not expect or to look at the content of a file you are requiring to see why it does not behave as you expect. EOF end def execute found = true options[:args].each do |arg| arg = arg.sub(/#{Regexp.union(*Gem.suffixes)}$/, '') dirs = $LOAD_PATH spec = Gem::Specification.find_by_path arg if spec then if options[:search_gems_first] then dirs = spec.full_require_paths + $LOAD_PATH else dirs = $LOAD_PATH + spec.full_require_paths end end # TODO: this is totally redundant and stupid paths = find_paths arg, dirs if paths.empty? then alert_error "Can't find ruby library file or shared library #{arg}" found &&= false else say paths end end terminate_interaction 1 unless found end def find_paths(package_name, dirs) result = [] dirs.each do |dir| Gem.suffixes.each do |ext| full_path = File.join dir, "#{package_name}#{ext}" if File.exist? full_path and not File.directory? full_path then result << full_path return result unless options[:show_all] end end end result end def usage # :nodoc: "#{program_name} FILE [FILE ...]" end end PK!ǜڥ '2.2.0/rubygems/commands/yank_command.rbnu[require 'rubygems/command' require 'rubygems/local_remote_options' require 'rubygems/version_option' require 'rubygems/gemcutter_utilities' class Gem::Commands::YankCommand < Gem::Command include Gem::LocalRemoteOptions include Gem::VersionOption include Gem::GemcutterUtilities def description # :nodoc: <<-EOF The yank command removes a gem you pushed to a server from the server's index. Note that if you push a gem to rubygems.org the yank command does not prevent other people from downloading the gem via the download link. Once you have pushed a gem several downloads will happen automatically via the webhooks. If you accidentally pushed passwords or other sensitive data you will need to change them immediately and yank your gem. If you are yanking a gem due to intellectual property reasons contact http://help.rubygems.org for permanant removal. Be sure to mention this as the reason for the removal request. EOF end def arguments # :nodoc: "GEM name of gem" end def usage # :nodoc: "#{program_name} GEM -v VERSION [-p PLATFORM] [--undo] [--key KEY_NAME]" end def initialize super 'yank', 'Remove a pushed gem from the index' add_version_option("remove") add_platform_option("remove") add_option('--undo') do |value, options| options[:undo] = true end add_key_option end def execute sign_in version = get_version_from_requirements(options[:version]) platform = get_platform_from_requirements(options) if version then if options[:undo] then unyank_gem(version, platform) else yank_gem(version, platform) end else say "A version argument is required: #{usage}" terminate_interaction end end def yank_gem(version, platform) say "Yanking gem from #{self.host}..." yank_api_request(:delete, version, platform, "api/v1/gems/yank") end def unyank_gem(version, platform) say "Unyanking gem from #{host}..." yank_api_request(:put, version, platform, "api/v1/gems/unyank") end private def yank_api_request(method, version, platform, api) name = get_one_gem_name response = rubygems_api_request(method, api) do |request| request.add_field("Authorization", api_key) data = { 'gem_name' => name, 'version' => version, } data['platform'] = platform if platform request.set_form_data data end say response.body end def get_version_from_requirements(requirements) requirements.requirements.first[1].version rescue nil end def get_platform_from_requirements(requirements) Gem.platforms[1].to_s if requirements.key? :added_platform end end PK!ݳ '2.2.0/rubygems/commands/lock_command.rbnu[require 'rubygems/command' class Gem::Commands::LockCommand < Gem::Command def initialize super 'lock', 'Generate a lockdown list of gems', :strict => false add_option '-s', '--[no-]strict', 'fail if unable to satisfy a dependency' do |strict, options| options[:strict] = strict end end def arguments # :nodoc: "GEMNAME name of gem to lock\nVERSION version of gem to lock" end def defaults_str # :nodoc: "--no-strict" end def description # :nodoc: <<-EOF The lock command will generate a list of +gem+ statements that will lock down the versions for the gem given in the command line. It will specify exact versions in the requirements list to ensure that the gems loaded will always be consistent. A full recursive search of all effected gems will be generated. Example: gem lock rails-1.0.0 > lockdown.rb will produce in lockdown.rb: require "rubygems" gem 'rails', '= 1.0.0' gem 'rake', '= 0.7.0.1' gem 'activesupport', '= 1.2.5' gem 'activerecord', '= 1.13.2' gem 'actionpack', '= 1.11.2' gem 'actionmailer', '= 1.1.5' gem 'actionwebservice', '= 1.0.0' Just load lockdown.rb from your application to ensure that the current versions are loaded. Make sure that lockdown.rb is loaded *before* any other require statements. Notice that rails 1.0.0 only requires that rake 0.6.2 or better be used. Rake-0.7.0.1 is the most recent version installed that satisfies that, so we lock it down to the exact version. EOF end def usage # :nodoc: "#{program_name} GEMNAME-VERSION [GEMNAME-VERSION ...]" end def complain(message) if options[:strict] then raise Gem::Exception, message else say "# #{message}" end end def execute say "require 'rubygems'" locked = {} pending = options[:args] until pending.empty? do full_name = pending.shift spec = Gem::Specification.load spec_path(full_name) if spec.nil? then complain "Could not find gem #{full_name}, try using the full name" next end say "gem '#{spec.name}', '= #{spec.version}'" unless locked[spec.name] locked[spec.name] = true spec.runtime_dependencies.each do |dep| next if locked[dep.name] candidates = dep.matching_specs if candidates.empty? then complain "Unable to satisfy '#{dep}' from currently installed gems" else pending << candidates.last.full_name end end end end def spec_path(gem_full_name) gemspecs = Gem.path.map { |path| File.join path, "specifications", "#{gem_full_name}.gemspec" } gemspecs.find { |path| File.exist? path } end end PK! '2.2.0/rubygems/commands/list_command.rbnu[require 'rubygems/command' require 'rubygems/commands/query_command' ## # An alternate to Gem::Commands::QueryCommand that searches for gems starting # with the the supplied argument. class Gem::Commands::ListCommand < Gem::Commands::QueryCommand def initialize super 'list', 'Display local gems whose name matches REGEXP' remove_option('--name-matches') end def arguments # :nodoc: "REGEXP regexp to look for in gem name" end def defaults_str # :nodoc: "--local --no-details" end def description # :nodoc: <<-EOF The list command is used to view the gems you have installed locally. The --details option displays additional details including the summary, the homepage, the author, the locations of different versions of the gem. To search for remote gems use the search command. EOF end def usage # :nodoc: "#{program_name} [STRING ...]" end end PK!KZ  12.2.0/rubygems/commands/generate_index_command.rbnu[require 'rubygems/command' require 'rubygems/indexer' ## # Generates a index files for use as a gem server. # # See `gem help generate_index` class Gem::Commands::GenerateIndexCommand < Gem::Command def initialize super 'generate_index', 'Generates the index files for a gem server directory', :directory => '.', :build_modern => true add_option '-d', '--directory=DIRNAME', 'repository base dir containing gems subdir' do |dir, options| options[:directory] = File.expand_path dir end add_option '--[no-]modern', 'Generate indexes for RubyGems', '(always true)' do |value, options| options[:build_modern] = value end add_option '--update', 'Update modern indexes with gems added', 'since the last update' do |value, options| options[:update] = value end end def defaults_str # :nodoc: "--directory . --modern" end def description # :nodoc: <<-EOF The generate_index command creates a set of indexes for serving gems statically. The command expects a 'gems' directory under the path given to the --directory option. The given directory will be the directory you serve as the gem repository. For `gem generate_index --directory /path/to/repo`, expose /path/to/repo via your HTTP server configuration (not /path/to/repo/gems). When done, it will generate a set of files like this: gems/*.gem # .gem files you want to # index specs..gz # specs index latest_specs..gz # latest specs index prerelease_specs..gz # prerelease specs index quick/Marshal./.gemspec.rz # Marshal quick index file The .rz extension files are compressed with the inflate algorithm. The Marshal version number comes from ruby's Marshal::MAJOR_VERSION and Marshal::MINOR_VERSION constants. It is used to ensure compatibility. EOF end def execute # This is always true because it's the only way now. options[:build_modern] = true if not File.exist?(options[:directory]) or not File.directory?(options[:directory]) then alert_error "unknown directory name #{directory}." terminate_interaction 1 else indexer = Gem::Indexer.new options.delete(:directory), options if options[:update] then indexer.update_index else indexer.generate_index end end end end PK!̳5RR)2.2.0/rubygems/commands/mirror_command.rbnu[require 'rubygems/command' unless defined? Gem::Commands::MirrorCommand class Gem::Commands::MirrorCommand < Gem::Command def initialize super('mirror', 'Mirror all gem files (requires rubygems-mirror)') begin Gem::Specification.find_by_name('rubygems-mirror').activate rescue Gem::LoadError # no-op end end def description # :nodoc: <<-EOF The mirror command has been moved to the rubygems-mirror gem. EOF end def execute alert_error "Install the rubygems-mirror gem for the mirror command" end end end PK!h(2.2.0/rubygems/commands/check_command.rbnu[require 'rubygems/command' require 'rubygems/version_option' require 'rubygems/validator' require 'rubygems/doctor' class Gem::Commands::CheckCommand < Gem::Command include Gem::VersionOption def initialize super 'check', 'Check a gem repository for added or missing files', :alien => true, :doctor => false, :dry_run => false, :gems => true add_option('-a', '--[no-]alien', 'Report "unmanaged" or rogue files in the', 'gem repository') do |value, options| options[:alien] = value end add_option('--[no-]doctor', 'Clean up uninstalled gems and broken', 'specifications') do |value, options| options[:doctor] = value end add_option('--[no-]dry-run', 'Do not remove files, only report what', 'would be removed') do |value, options| options[:dry_run] = value end add_option('--[no-]gems', 'Check installed gems for problems') do |value, options| options[:gems] = value end add_version_option 'check' end def check_gems say 'Checking gems...' say gems = get_all_gem_names rescue [] Gem::Validator.new.alien(gems).sort.each do |key, val| unless val.empty? then say "#{key} has #{val.size} problems" val.each do |error_entry| say " #{error_entry.path}:" say " #{error_entry.problem}" end else say "#{key} is error-free" if Gem.configuration.verbose end say end end def doctor say 'Checking for files from uninstalled gems...' say Gem.path.each do |gem_repo| doctor = Gem::Doctor.new gem_repo, options[:dry_run] doctor.doctor end end def execute check_gems if options[:gems] doctor if options[:doctor] end def arguments # :nodoc: 'GEMNAME name of gem to check' end def defaults_str # :nodoc: '--gems --alien' end def description # :nodoc: <<-EOF The check command can list and repair problems with installed gems and specifications and will clean up gems that have been partially uninstalled. EOF end def usage # :nodoc: "#{program_name} [OPTIONS] [GEMNAME ...]" end end PK!"WZ66+2.2.0/rubygems/commands/outdated_command.rbnu[require 'rubygems/command' require 'rubygems/local_remote_options' require 'rubygems/spec_fetcher' require 'rubygems/version_option' class Gem::Commands::OutdatedCommand < Gem::Command include Gem::LocalRemoteOptions include Gem::VersionOption def initialize super 'outdated', 'Display all gems that need updates' add_local_remote_options add_platform_option end def description # :nodoc: <<-EOF The outdated command lists gems you may wish to upgrade to a newer version. You can check for dependency mismatches using the dependency command and update the gems with the update or install commands. EOF end def execute Gem::Specification.outdated_and_latest_version.each do |spec, remote_version| say "#{spec.name} (#{spec.version} < #{remote_version})" end end end PK!c33(2.2.0/rubygems/commands/setup_command.rbnu[require 'rubygems/command' ## # Installs RubyGems itself. This command is ordinarily only available from a # RubyGems checkout or tarball. class Gem::Commands::SetupCommand < Gem::Command HISTORY_HEADER = /^===\s*[\d.]+\s*\/\s*\d{4}-\d{2}-\d{2}\s*$/ VERSION_MATCHER = /^===\s*([\d.]+)\s*\/\s*\d{4}-\d{2}-\d{2}\s*$/ def initialize require 'tmpdir' super 'setup', 'Install RubyGems', :format_executable => true, :document => %w[ri], :site_or_vendor => 'sitelibdir', :destdir => '', :prefix => '', :previous_version => '' add_option '--previous-version=VERSION', 'Previous version of rubygems', 'Used for changelog processing' do |version, options| options[:previous_version] = version end add_option '--prefix=PREFIX', 'Prefix path for installing RubyGems', 'Will not affect gem repository location' do |prefix, options| options[:prefix] = File.expand_path prefix end add_option '--destdir=DESTDIR', 'Root directory to install RubyGems into', 'Mainly used for packaging RubyGems' do |destdir, options| options[:destdir] = File.expand_path destdir end add_option '--[no-]vendor', 'Install into vendorlibdir not sitelibdir' do |vendor, options| options[:site_or_vendor] = vendor ? 'vendorlibdir' : 'sitelibdir' end add_option '--[no-]format-executable', 'Makes `gem` match ruby', 'If ruby is ruby18, gem will be gem18' do |value, options| options[:format_executable] = value end add_option '--[no-]document [TYPES]', Array, 'Generate documentation for RubyGems.', 'List the documentation types you wish to', 'generate. For example: rdoc,ri' do |value, options| options[:document] = case value when nil then %w[rdoc ri] when false then [] else value end end add_option '--[no-]rdoc', 'Generate RDoc documentation for RubyGems' do |value, options| if value then options[:document] << 'rdoc' else options[:document].delete 'rdoc' end options[:document].uniq! end add_option '--[no-]ri', 'Generate RI documentation for RubyGems' do |value, options| if value then options[:document] << 'ri' else options[:document].delete 'ri' end options[:document].uniq! end @verbose = nil end def check_ruby_version required_version = Gem::Requirement.new '>= 1.8.7' unless required_version.satisfied_by? Gem.ruby_version then alert_error "Expected Ruby version #{required_version}, is #{Gem.ruby_version}" terminate_interaction 1 end end def defaults_str # :nodoc: "--format-executable --document ri" end def description # :nodoc: <<-EOF Installs RubyGems itself. RubyGems installs RDoc for itself in GEM_HOME. By default this is: #{Gem.dir} If you prefer a different directory, set the GEM_HOME environment variable. RubyGems will install the gem command with a name matching ruby's prefix and suffix. If ruby was installed as `ruby18`, gem will be installed as `gem18`. By default, this RubyGems will install gem as: #{Gem.default_exec_format % 'gem'} EOF end def execute @verbose = Gem.configuration.really_verbose install_destdir = options[:destdir] unless install_destdir.empty? then ENV['GEM_HOME'] ||= File.join(install_destdir, Gem.default_dir.gsub(/^[a-zA-Z]:/, '')) end check_ruby_version require 'fileutils' if Gem.configuration.really_verbose then extend FileUtils::Verbose else extend FileUtils end lib_dir, bin_dir = make_destination_dirs install_destdir install_lib lib_dir install_executables bin_dir remove_old_bin_files bin_dir remove_old_lib_files lib_dir say "RubyGems #{Gem::VERSION} installed" uninstall_old_gemcutter documentation_success = install_rdoc say if @verbose then say "-" * 78 say end if options[:previous_version].empty? options[:previous_version] = Gem::VERSION.sub(/[0-9]+$/, '0') end options[:previous_version] = Gem::Version.new(options[:previous_version]) show_release_notes say say "-" * 78 say say "RubyGems installed the following executables:" say @bin_file_names.map { |name| "\t#{name}\n" } say unless @bin_file_names.grep(/#{File::SEPARATOR}gem$/) then say "If `gem` was installed by a previous RubyGems installation, you may need" say "to remove it by hand." say end if documentation_success if options[:document].include? 'rdoc' then say "Rdoc documentation was installed. You may now invoke:" say " gem server" say "and then peruse beautifully formatted documentation for your gems" say "with your web browser." say "If you do not wish to install this documentation in the future, use the" say "--no-document flag, or set it as the default in your ~/.gemrc file. See" say "'gem help env' for details." say end if options[:document].include? 'ri' then say "Ruby Interactive (ri) documentation was installed. ri is kind of like man " say "pages for ruby libraries. You may access it like this:" say " ri Classname" say " ri Classname.class_method" say " ri Classname#instance_method" say "If you do not wish to install this documentation in the future, use the" say "--no-document flag, or set it as the default in your ~/.gemrc file. See" say "'gem help env' for details." say end end end def install_executables(bin_dir) say "Installing gem executable" if @verbose @bin_file_names = [] Dir.chdir 'bin' do bin_files = Dir['*'] bin_files.delete 'update_rubygems' bin_files.each do |bin_file| bin_file_formatted = if options[:format_executable] then Gem.default_exec_format % bin_file else bin_file end dest_file = File.join bin_dir, bin_file_formatted bin_tmp_file = File.join Dir.tmpdir, "#{bin_file}.#{$$}" begin bin = File.readlines bin_file bin[0] = "#!#{Gem.ruby}\n" File.open bin_tmp_file, 'w' do |fp| fp.puts bin.join end install bin_tmp_file, dest_file, :mode => 0755 @bin_file_names << dest_file ensure rm bin_tmp_file end next unless Gem.win_platform? begin bin_cmd_file = File.join Dir.tmpdir, "#{bin_file}.bat" File.open bin_cmd_file, 'w' do |file| file.puts <<-TEXT @ECHO OFF IF NOT "%~f0" == "~f0" GOTO :WinNT @"#{File.basename(Gem.ruby).chomp('"')}" "#{dest_file}" %1 %2 %3 %4 %5 %6 %7 %8 %9 GOTO :EOF :WinNT @"#{File.basename(Gem.ruby).chomp('"')}" "%~dpn0" %* TEXT end install bin_cmd_file, "#{dest_file}.bat", :mode => 0755 ensure rm bin_cmd_file end end end end def install_file file, dest_dir dest_file = File.join dest_dir, file dest_dir = File.dirname dest_file mkdir_p dest_dir unless File.directory? dest_dir install file, dest_file, :mode => 0644 end def install_lib(lib_dir) say "Installing RubyGems" if @verbose lib_files = rb_files_in 'lib' pem_files = pem_files_in 'lib' Dir.chdir 'lib' do lib_files.each do |lib_file| install_file lib_file, lib_dir end pem_files.each do |pem_file| install_file pem_file, lib_dir end end end def install_rdoc gem_doc_dir = File.join Gem.dir, 'doc' rubygems_name = "rubygems-#{Gem::VERSION}" rubygems_doc_dir = File.join gem_doc_dir, rubygems_name begin Gem.ensure_gem_subdirectories Gem.dir rescue SystemCallError # ignore end if File.writable? gem_doc_dir and (not File.exist? rubygems_doc_dir or File.writable? rubygems_doc_dir) then say "Removing old RubyGems RDoc and ri" if @verbose Dir[File.join(Gem.dir, 'doc', 'rubygems-[0-9]*')].each do |dir| rm_rf dir end require 'rubygems/rdoc' fake_spec = Gem::Specification.new 'rubygems', Gem::VERSION def fake_spec.full_gem_path File.expand_path '../../../..', __FILE__ end generate_ri = options[:document].include? 'ri' generate_rdoc = options[:document].include? 'rdoc' rdoc = Gem::RDoc.new fake_spec, generate_rdoc, generate_ri rdoc.generate return true elsif @verbose then say "Skipping RDoc generation, #{gem_doc_dir} not writable" say "Set the GEM_HOME environment variable if you want RDoc generated" end return false end def make_destination_dirs(install_destdir) lib_dir, bin_dir = Gem.default_rubygems_dirs unless lib_dir lib_dir, bin_dir = generate_default_dirs(install_destdir) end mkdir_p lib_dir mkdir_p bin_dir return lib_dir, bin_dir end def generate_default_dirs(install_destdir) prefix = options[:prefix] site_or_vendor = options[:site_or_vendor] if prefix.empty? then lib_dir = RbConfig::CONFIG[site_or_vendor] bin_dir = RbConfig::CONFIG['bindir'] else # Apple installed RubyGems into libdir, and RubyGems <= 1.1.0 gets # confused about installation location, so switch back to # sitelibdir/vendorlibdir. if defined?(APPLE_GEM_HOME) and # just in case Apple and RubyGems don't get this patched up proper. (prefix == RbConfig::CONFIG['libdir'] or # this one is important prefix == File.join(RbConfig::CONFIG['libdir'], 'ruby')) then lib_dir = RbConfig::CONFIG[site_or_vendor] bin_dir = RbConfig::CONFIG['bindir'] else lib_dir = File.join prefix, 'lib' bin_dir = File.join prefix, 'bin' end end unless install_destdir.empty? then lib_dir = File.join install_destdir, lib_dir.gsub(/^[a-zA-Z]:/, '') bin_dir = File.join install_destdir, bin_dir.gsub(/^[a-zA-Z]:/, '') end [lib_dir, bin_dir] end def pem_files_in dir Dir.chdir dir do Dir[File.join('**', '*pem')] end end def rb_files_in dir Dir.chdir dir do Dir[File.join('**', '*rb')] end end def remove_old_bin_files(bin_dir) old_bin_files = { 'gem_mirror' => 'gem mirror', 'gem_server' => 'gem server', 'gemlock' => 'gem lock', 'gemri' => 'ri', 'gemwhich' => 'gem which', 'index_gem_repository.rb' => 'gem generate_index', } old_bin_files.each do |old_bin_file, new_name| old_bin_path = File.join bin_dir, old_bin_file next unless File.exist? old_bin_path deprecation_message = "`#{old_bin_file}` has been deprecated. Use `#{new_name}` instead." File.open old_bin_path, 'w' do |fp| fp.write <<-EOF #!#{Gem.ruby} abort "#{deprecation_message}" EOF end next unless Gem.win_platform? File.open "#{old_bin_path}.bat", 'w' do |fp| fp.puts %{@ECHO.#{deprecation_message}} end end end def remove_old_lib_files lib_dir rubygems_dir = File.join lib_dir, 'rubygems' lib_files = rb_files_in 'lib/rubygems' old_lib_files = rb_files_in rubygems_dir to_remove = old_lib_files - lib_files to_remove.delete_if do |file| file.start_with? 'defaults' end Dir.chdir rubygems_dir do to_remove.each do |file| FileUtils.rm_f file warn "unable to remove old file #{file} please remove it by hand" if File.exist? file end end end def show_release_notes release_notes = File.join Dir.pwd, 'History.txt' release_notes = if File.exist? release_notes then history = File.read release_notes history.force_encoding Encoding::UTF_8 if Object.const_defined? :Encoding history = history.sub(/^# coding:.*?(?=^=)/m, '') text = history.split(HISTORY_HEADER) text.shift # correct an off-by-one generated by split version_lines = history.scan(HISTORY_HEADER) versions = history.scan(VERSION_MATCHER).flatten.map do |x| Gem::Version.new(x) end history_string = "" until versions.length == 0 or versions.shift < options[:previous_version] do history_string += version_lines.shift + text.shift end history_string else "Oh-no! Unable to find release notes!" end say release_notes end def uninstall_old_gemcutter require 'rubygems/uninstaller' ui = Gem::Uninstaller.new('gemcutter', :all => true, :ignore => true, :version => '< 0.4') ui.uninstall rescue Gem::InstallError end end PK!s5Fj j )2.2.0/rubygems/commands/server_command.rbnu[require 'rubygems/command' require 'rubygems/server' class Gem::Commands::ServerCommand < Gem::Command def initialize super 'server', 'Documentation and gem repository HTTP server', :port => 8808, :gemdir => [], :daemon => false OptionParser.accept :Port do |port| if port =~ /\A\d+\z/ then port = Integer port raise OptionParser::InvalidArgument, "#{port}: not a port number" if port > 65535 port else begin Socket.getservbyname port rescue SocketError raise OptionParser::InvalidArgument, "#{port}: no such named service" end end end add_option '-p', '--port=PORT', :Port, 'port to listen on' do |port, options| options[:port] = port end add_option '-d', '--dir=GEMDIR', 'directories from which to serve gems', 'multiple directories may be provided' do |gemdir, options| options[:gemdir] << File.expand_path(gemdir) end add_option '--[no-]daemon', 'run as a daemon' do |daemon, options| options[:daemon] = daemon end add_option '-b', '--bind=HOST,HOST', 'addresses to bind', Array do |address, options| options[:addresses] ||= [] options[:addresses].push(*address) end add_option '-l', '--launch[=COMMAND]', 'launches a browser window', "COMMAND defaults to 'start' on Windows", "and 'open' on all other platforms" do |launch, options| launch ||= Gem.win_platform? ? 'start' : 'open' options[:launch] = launch end end def defaults_str # :nodoc: "--port 8808 --dir #{Gem.dir} --no-daemon" end def description # :nodoc: <<-EOF The server command starts up a web server that hosts the RDoc for your installed gems and can operate as a server for installation of gems on other machines. The cache files for installed gems must exist to use the server as a source for gem installation. To install gems from a running server, use `gem install GEMNAME --source http://gem_server_host:8808` You can set up a shortcut to gem server documentation using the URL: http://localhost:8808/rdoc?q=%s - Firefox http://localhost:8808/rdoc?q=* - LaunchBar EOF end def execute options[:gemdir] = Gem.path if options[:gemdir].empty? Gem::Server.run options end end PK!2 )2.2.0/rubygems/commands/update_command.rbnu[require 'rubygems/command' require 'rubygems/command_manager' require 'rubygems/dependency_installer' require 'rubygems/install_update_options' require 'rubygems/local_remote_options' require 'rubygems/spec_fetcher' require 'rubygems/version_option' require 'rubygems/install_message' # must come before rdoc for messaging require 'rubygems/rdoc' class Gem::Commands::UpdateCommand < Gem::Command include Gem::InstallUpdateOptions include Gem::LocalRemoteOptions include Gem::VersionOption attr_reader :installer # :nodoc: attr_reader :updated # :nodoc: def initialize super 'update', 'Update installed gems to the latest version', :document => %w[rdoc ri], :force => false add_install_update_options OptionParser.accept Gem::Version do |value| Gem::Version.new value value end add_option('--system [VERSION]', Gem::Version, 'Update the RubyGems system software') do |value, options| value = true unless value options[:system] = value end add_local_remote_options add_platform_option add_prerelease_option "as update targets" @updated = [] @installer = nil end def arguments # :nodoc: "REGEXP regexp to search for in gem name" end def defaults_str # :nodoc: "--document --no-force --install-dir #{Gem.dir}" end def description # :nodoc: <<-EOF The update command will update your gems to the latest version. The update command does not remove the previous version. Use the cleanup command to remove old versions. EOF end def usage # :nodoc: "#{program_name} REGEXP [REGEXP ...]" end def check_latest_rubygems version # :nodoc: if Gem.rubygems_version == version then say "Latest version currently installed. Aborting." terminate_interaction end options[:user_install] = false end def check_update_arguments # :nodoc: unless options[:args].empty? then alert_error "Gem names are not allowed with the --system option" terminate_interaction 1 end end def execute if options[:system] then update_rubygems return end say "Updating installed gems" hig = highest_installed_gems gems_to_update = which_to_update hig, options[:args].uniq updated = update_gems gems_to_update updated_names = updated.map { |spec| spec.name } not_updated_names = options[:args].uniq - updated_names if updated.empty? then say "Nothing to update" else say "Gems updated: #{updated_names.join(' ')}" say "Gems already up-to-date: #{not_updated_names.join(' ')}" unless not_updated_names.empty? end end def fetch_remote_gems spec # :nodoc: dependency = Gem::Dependency.new spec.name, "> #{spec.version}" dependency.prerelease = options[:prerelease] fetcher = Gem::SpecFetcher.fetcher spec_tuples, errors = fetcher.search_for_dependency dependency error = errors.find { |e| e.respond_to? :exception } raise error if error spec_tuples end def highest_installed_gems # :nodoc: hig = {} # highest installed gems Gem::Specification.each do |spec| if hig[spec.name].nil? or hig[spec.name].version < spec.version then hig[spec.name] = spec end end hig end def highest_remote_version spec # :nodoc: spec_tuples = fetch_remote_gems spec matching_gems = spec_tuples.select do |g,_| g.name == spec.name and g.match_platform? end highest_remote_gem = matching_gems.max_by { |g,_| g.version } highest_remote_gem ||= [Gem::NameTuple.null] highest_remote_gem.first.version end def install_rubygems version # :nodoc: args = update_rubygems_arguments update_dir = File.join Gem.dir, 'gems', "rubygems-update-#{version}" Dir.chdir update_dir do say "Installing RubyGems #{version}" # Make sure old rubygems isn't loaded old = ENV["RUBYOPT"] ENV.delete("RUBYOPT") if old installed = system Gem.ruby, 'setup.rb', *args say "RubyGems system software updated" if installed ENV["RUBYOPT"] = old if old end end def rubygems_target_version version = options[:system] update_latest = version == true if update_latest then version = Gem::Version.new Gem::VERSION requirement = Gem::Requirement.new ">= #{Gem::VERSION}" else version = Gem::Version.new version requirement = Gem::Requirement.new version end rubygems_update = Gem::Specification.new rubygems_update.name = 'rubygems-update' rubygems_update.version = version hig = { 'rubygems-update' => rubygems_update } gems_to_update = which_to_update hig, options[:args], :system _, up_ver = gems_to_update.first target = if update_latest then up_ver else version end return target, requirement end def update_gem name, version = Gem::Requirement.default return if @updated.any? { |spec| spec.name == name } update_options = options.dup update_options[:prerelease] = version.prerelease? @installer = Gem::DependencyInstaller.new update_options say "Updating #{name}" begin @installer.install name, Gem::Requirement.new(version) rescue Gem::InstallError, Gem::DependencyError => e alert_error "Error installing #{name}:\n\t#{e.message}" end @installer.installed_gems.each do |spec| @updated << spec end end def update_gems gems_to_update gems_to_update.uniq.sort.each do |(name, version)| update_gem name, version end @updated end ## # Update RubyGems software to the latest version. def update_rubygems check_update_arguments version, requirement = rubygems_target_version check_latest_rubygems version update_gem 'rubygems-update', version installed_gems = Gem::Specification.find_all_by_name 'rubygems-update', requirement version = installed_gems.last.version install_rubygems version end def update_rubygems_arguments # :nodoc: args = [] args << '--prefix' << Gem.prefix if Gem.prefix # TODO use --document for >= 1.9 , --no-rdoc --no-ri < 1.9 args << '--no-rdoc' unless options[:document].include? 'rdoc' args << '--no-ri' unless options[:document].include? 'ri' args << '--no-format-executable' if options[:no_format_executable] args << '--previous-version' << Gem::VERSION if options[:system] == true or Gem::Version.new(options[:system]) >= Gem::Version.new(2) args end def which_to_update highest_installed_gems, gem_names, system = false result = [] highest_installed_gems.each do |l_name, l_spec| next if not gem_names.empty? and gem_names.none? { |name| name == l_spec.name } highest_remote_ver = highest_remote_version l_spec if system or (l_spec.version < highest_remote_ver) then result << [l_spec.name, [l_spec.version, highest_remote_ver].max] end end result end end PK!zZ? '2.2.0/rubygems/commands/push_command.rbnu[require 'rubygems/command' require 'rubygems/local_remote_options' require 'rubygems/gemcutter_utilities' require 'rubygems/package' class Gem::Commands::PushCommand < Gem::Command include Gem::LocalRemoteOptions include Gem::GemcutterUtilities def description # :nodoc: <<-EOF The push command uploads a gem to the push server (the default is https://rubygems.org) and adds it to the index. The gem can be removed from the index (but only the index) using the yank command. For further discussion see the help for the yank command. EOF end def arguments # :nodoc: "GEM built gem to push up" end def usage # :nodoc: "#{program_name} GEM" end def initialize super 'push', 'Push a gem up to the gem server', :host => self.host add_proxy_option add_key_option add_option('--host HOST', 'Push to another gemcutter-compatible host') do |value, options| options[:host] = value end @host = nil end def execute @host = options[:host] sign_in @host send_gem get_one_gem_name end def send_gem name args = [:post, "api/v1/gems"] latest_rubygems_version = Gem.latest_rubygems_version if latest_rubygems_version < Gem.rubygems_version and Gem.rubygems_version.prerelease? and Gem::Version.new('2.0.0.rc.2') != Gem.rubygems_version then alert_error <<-ERROR You are using a beta release of RubyGems (#{Gem::VERSION}) which is not allowed to push gems. Please downgrade or upgrade to a release version. The latest released RubyGems version is #{latest_rubygems_version} You can upgrade or downgrade to the latest release version with: gem update --system=#{latest_rubygems_version} ERROR terminate_interaction 1 end gem_data = Gem::Package.new(name) unless @host then @host = gem_data.spec.metadata['default_gem_server'] end # Always include this, even if it's nil args << @host if gem_data.spec.metadata.has_key?('allowed_push_host') args << gem_data.spec.metadata['allowed_push_host'] end say "Pushing gem to #{@host || Gem.host}..." response = rubygems_api_request(*args) do |request| request.body = Gem.read_binary name request.add_field "Content-Length", request.body.size request.add_field "Content-Type", "application/octet-stream" request.add_field "Authorization", api_key end with_response response end end PK!XWW'2.2.0/rubygems/commands/open_command.rbnu[require 'English' require 'rubygems/command' require 'rubygems/version_option' require 'rubygems/util' class Gem::Commands::OpenCommand < Gem::Command include Gem::VersionOption def initialize super 'open', 'Open gem sources in editor' add_option('-e', '--editor EDITOR', String, "Opens gem sources in EDITOR") do |editor, options| options[:editor] = editor || get_env_editor end end def arguments # :nodoc: "GEMNAME name of gem to open in editor" end def defaults_str # :nodoc: "-e #{get_env_editor}" end def description # :nodoc: <<-EOF The open command opens gem in editor and changes current path to gem's source directory. Editor can be specified with -e option, otherwise rubygems will look for editor in $EDITOR, $VISUAL and $GEM_EDITOR variables. EOF end def usage # :nodoc: "#{program_name} GEMNAME [-e EDITOR]" end def get_env_editor ENV['GEM_EDITOR'] || ENV['VISUAL'] || ENV['EDITOR'] || 'vi' end def execute @version = options[:version] || Gem::Requirement.default @editor = options[:editor] || get_env_editor found = open_gem(get_one_gem_name) terminate_interaction 1 unless found end def open_gem name spec = spec_for name return false unless spec open_editor(spec.full_gem_path) end def open_editor path system(*@editor.split(/\s+/) + [path]) end def spec_for name spec = Gem::Specification.find_all_by_name(name, @version).last return spec if spec say "Unable to find gem '#{name}'" end end PK!@ő[*2.2.0/rubygems/commands/sources_command.rbnu[require 'rubygems/command' require 'rubygems/remote_fetcher' require 'rubygems/spec_fetcher' require 'rubygems/local_remote_options' class Gem::Commands::SourcesCommand < Gem::Command include Gem::LocalRemoteOptions def initialize require 'fileutils' super 'sources', 'Manage the sources and cache file RubyGems uses to search for gems' add_option '-a', '--add SOURCE_URI', 'Add source' do |value, options| options[:add] = value end add_option '-l', '--list', 'List sources' do |value, options| options[:list] = value end add_option '-r', '--remove SOURCE_URI', 'Remove source' do |value, options| options[:remove] = value end add_option '-c', '--clear-all', 'Remove all sources (clear the cache)' do |value, options| options[:clear_all] = value end add_option '-u', '--update', 'Update source cache' do |value, options| options[:update] = value end add_proxy_option end def add_source source_uri # :nodoc: check_rubygems_https source_uri source = Gem::Source.new source_uri begin if Gem.sources.include? source_uri then say "source #{source_uri} already present in the cache" else source.load_specs :released Gem.sources << source Gem.configuration.write say "#{source_uri} added to sources" end rescue URI::Error, ArgumentError say "#{source_uri} is not a URI" terminate_interaction 1 rescue Gem::RemoteFetcher::FetchError => e say "Error fetching #{source_uri}:\n\t#{e.message}" terminate_interaction 1 end end def check_rubygems_https source_uri # :nodoc: uri = URI source_uri if uri.scheme and uri.scheme.downcase == 'http' and uri.host.downcase == 'rubygems.org' then question = <<-QUESTION.chomp https://rubygems.org is recommended for security over #{uri} Do you want to add this insecure source? QUESTION terminate_interaction 1 unless ask_yes_no question end end def clear_all # :nodoc: path = Gem.spec_cache_dir FileUtils.rm_rf path unless File.exist? path then say "*** Removed specs cache ***" else unless File.writable? path then say "*** Unable to remove source cache (write protected) ***" else say "*** Unable to remove source cache ***" end terminate_interaction 1 end end def defaults_str # :nodoc: '--list' end def description # :nodoc: <<-EOF RubyGems fetches gems from the sources you have configured (stored in your ~/.gemrc). The default source is https://rubygems.org, but you may have older sources configured. This guide will help you update your sources or configure yourself to use your own gem server. Without any arguments the sources lists your currently configured sources: $ gem sources *** CURRENT SOURCES *** https://rubygems.org This may list multiple sources or non-rubygems sources. You probably configured them before or have an old `~/.gemrc`. If you have sources you do not recognize you should remove them. RubyGems has been configured to serve gems via the following URLs through its history: * http://gems.rubyforge.org (RubyGems 1.3.6 and earlier) * http://rubygems.org (RubyGems 1.3.7 through 1.8.25) * https://rubygems.org (RubyGems 2.0.1 and newer) Since all of these sources point to the same set of gems you only need one of them in your list. https://rubygems.org is recommended as it brings the protections of an SSL connection to gem downloads. To add a source use the --add argument: $ gem sources --add https://rubygems.org https://rubygems.org added to sources RubyGems will check to see if gems can be installed from the source given before it is added. To remove a source use the --remove argument: $ gem sources --remove http://rubygems.org http://rubygems.org removed from sources EOF end def list # :nodoc: say "*** CURRENT SOURCES ***" say Gem.sources.each do |src| say src end end def list? # :nodoc: !(options[:add] || options[:clear_all] || options[:remove] || options[:update]) end def execute clear_all if options[:clear_all] source_uri = options[:add] add_source source_uri if source_uri source_uri = options[:remove] remove_source source_uri if source_uri update if options[:update] list if list? end def remove_source source_uri # :nodoc: unless Gem.sources.include? source_uri then say "source #{source_uri} not present in cache" else Gem.sources.delete source_uri Gem.configuration.write say "#{source_uri} removed from sources" end end def update # :nodoc: Gem.sources.each_source do |src| src.load_specs :released src.load_specs :latest end say "source cache successfully updated" end def remove_cache_file desc, path # :nodoc: FileUtils.rm_rf path if not File.exist?(path) then say "*** Removed #{desc} source cache ***" elsif not File.writable?(path) then say "*** Unable to remove #{desc} source cache (write protected) ***" else say "*** Unable to remove #{desc} source cache ***" end end end PK!442.2.0/rubygems/indexer.rbnu[require 'rubygems' require 'rubygems/package' require 'time' begin gem 'builder' require 'builder/xchar' rescue LoadError end ## # Top level class for building the gem repository index. class Gem::Indexer include Gem::UserInteraction ## # Build indexes for RubyGems 1.2.0 and newer when true attr_accessor :build_modern ## # Index install location attr_reader :dest_directory ## # Specs index install location attr_reader :dest_specs_index ## # Latest specs index install location attr_reader :dest_latest_specs_index ## # Prerelease specs index install location attr_reader :dest_prerelease_specs_index ## # Index build directory attr_reader :directory ## # Create an indexer that will index the gems in +directory+. def initialize(directory, options = {}) require 'fileutils' require 'tmpdir' require 'zlib' unless defined?(Builder::XChar) then raise "Gem::Indexer requires that the XML Builder library be installed:" + "\n\tgem install builder" end options = { :build_modern => true }.merge options @build_modern = options[:build_modern] @dest_directory = directory @directory = File.join(Dir.tmpdir, "gem_generate_index_#{$$}") marshal_name = "Marshal.#{Gem.marshal_version}" @master_index = File.join @directory, 'yaml' @marshal_index = File.join @directory, marshal_name @quick_dir = File.join @directory, 'quick' @quick_marshal_dir = File.join @quick_dir, marshal_name @quick_marshal_dir_base = File.join "quick", marshal_name # FIX: UGH @quick_index = File.join @quick_dir, 'index' @latest_index = File.join @quick_dir, 'latest_index' @specs_index = File.join @directory, "specs.#{Gem.marshal_version}" @latest_specs_index = File.join(@directory, "latest_specs.#{Gem.marshal_version}") @prerelease_specs_index = File.join(@directory, "prerelease_specs.#{Gem.marshal_version}") @dest_specs_index = File.join(@dest_directory, "specs.#{Gem.marshal_version}") @dest_latest_specs_index = File.join(@dest_directory, "latest_specs.#{Gem.marshal_version}") @dest_prerelease_specs_index = File.join(@dest_directory, "prerelease_specs.#{Gem.marshal_version}") @files = [] end ## # Abbreviate the spec for downloading. Abbreviated specs are only used for # searching, downloading and related activities and do not need deployment # specific information (e.g. list of files). So we abbreviate the spec, # making it much smaller for quicker downloads. #-- # TODO move to Gem::Specification def abbreviate(spec) spec.files = [] spec.test_files = [] spec.rdoc_options = [] spec.extra_rdoc_files = [] spec.cert_chain = [] spec end ## # Build various indicies def build_indicies Gem::Specification.dirs = [] Gem::Specification.add_specs(*map_gems_to_specs(gem_file_list)) build_marshal_gemspecs build_modern_indicies if @build_modern compress_indicies end ## # Builds Marshal quick index gemspecs. def build_marshal_gemspecs count = Gem::Specification.count { |s| not s.default_gem? } progress = ui.progress_reporter count, "Generating Marshal quick index gemspecs for #{count} gems", "Complete" files = [] Gem.time 'Generated Marshal quick index gemspecs' do Gem::Specification.each do |spec| next if spec.default_gem? spec_file_name = "#{spec.original_name}.gemspec.rz" marshal_name = File.join @quick_marshal_dir, spec_file_name marshal_zipped = Gem.deflate Marshal.dump(spec) open marshal_name, 'wb' do |io| io.write marshal_zipped end files << marshal_name progress.updated spec.original_name end progress.done end @files << @quick_marshal_dir files end ## # Build a single index for RubyGems 1.2 and newer def build_modern_index(index, file, name) say "Generating #{name} index" Gem.time "Generated #{name} index" do open(file, 'wb') do |io| specs = index.map do |*spec| # We have to splat here because latest_specs is an array, while the # others are hashes. spec = spec.flatten.last platform = spec.original_platform # win32-api-1.0.4-x86-mswin32-60 unless String === platform then alert_warning "Skipping invalid platform in gem: #{spec.full_name}" next end platform = Gem::Platform::RUBY if platform.nil? or platform.empty? [spec.name, spec.version, platform] end specs = compact_specs(specs) Marshal.dump(specs, io) end end end ## # Builds indicies for RubyGems 1.2 and newer. Handles full, latest, prerelease def build_modern_indicies specs = Gem::Specification.reject { |s| s.default_gem? } prerelease, released = specs.partition { |s| s.version.prerelease? } latest_specs = Gem::Specification.latest_specs.reject { |s| s.default_gem? } build_modern_index(released.sort, @specs_index, 'specs') build_modern_index(latest_specs.sort, @latest_specs_index, 'latest specs') build_modern_index(prerelease.sort, @prerelease_specs_index, 'prerelease specs') @files += [@specs_index, "#{@specs_index}.gz", @latest_specs_index, "#{@latest_specs_index}.gz", @prerelease_specs_index, "#{@prerelease_specs_index}.gz"] end def map_gems_to_specs gems gems.map { |gemfile| if File.size(gemfile) == 0 then alert_warning "Skipping zero-length gem: #{gemfile}" next end begin spec = Gem::Package.new(gemfile).spec spec.loaded_from = gemfile # HACK: fuck this shit - borks all tests that use pl1 # if File.basename(gemfile, ".gem") != spec.original_name then # exp = spec.full_name # exp << " (#{spec.original_name})" if # spec.original_name != spec.full_name # msg = "Skipping misnamed gem: #{gemfile} should be named #{exp}" # alert_warning msg # next # end abbreviate spec sanitize spec spec rescue SignalException alert_error "Received signal, exiting" raise rescue Exception => e msg = ["Unable to process #{gemfile}", "#{e.message} (#{e.class})", "\t#{e.backtrace.join "\n\t"}"].join("\n") alert_error msg end }.compact end ## # Compresses indicies on disk #-- # All future files should be compressed using gzip, not deflate def compress_indicies say "Compressing indicies" Gem.time 'Compressed indicies' do if @build_modern then gzip @specs_index gzip @latest_specs_index gzip @prerelease_specs_index end end end ## # Compacts Marshal output for the specs index data source by using identical # objects as much as possible. def compact_specs(specs) names = {} versions = {} platforms = {} specs.map do |(name, version, platform)| names[name] = name unless names.include? name versions[version] = version unless versions.include? version platforms[platform] = platform unless platforms.include? platform [names[name], versions[version], platforms[platform]] end end ## # Compress +filename+ with +extension+. def compress(filename, extension) data = Gem.read_binary filename zipped = Gem.deflate data open "#{filename}.#{extension}", 'wb' do |io| io.write zipped end end ## # List of gem file names to index. def gem_file_list Dir[File.join(@dest_directory, "gems", '*.gem')] end ## # Builds and installs indicies. def generate_index make_temp_directories build_indicies install_indicies rescue SignalException ensure FileUtils.rm_rf @directory end ## # Zlib::GzipWriter wrapper that gzips +filename+ on disk. def gzip(filename) Zlib::GzipWriter.open "#{filename}.gz" do |io| io.write Gem.read_binary(filename) end end ## # Install generated indicies into the destination directory. def install_indicies verbose = Gem.configuration.really_verbose say "Moving index into production dir #{@dest_directory}" if verbose files = @files files.delete @quick_marshal_dir if files.include? @quick_dir if files.include? @quick_marshal_dir and not files.include? @quick_dir then files.delete @quick_marshal_dir dst_name = File.join(@dest_directory, @quick_marshal_dir_base) FileUtils.mkdir_p File.dirname(dst_name), :verbose => verbose FileUtils.rm_rf dst_name, :verbose => verbose FileUtils.mv(@quick_marshal_dir, dst_name, :verbose => verbose, :force => true) end files = files.map do |path| path.sub(/^#{Regexp.escape @directory}\/?/, '') # HACK? end files.each do |file| src_name = File.join @directory, file dst_name = File.join @dest_directory, file FileUtils.rm_rf dst_name, :verbose => verbose FileUtils.mv(src_name, @dest_directory, :verbose => verbose, :force => true) end end ## # Make directories for index generation def make_temp_directories FileUtils.rm_rf @directory FileUtils.mkdir_p @directory, :mode => 0700 FileUtils.mkdir_p @quick_marshal_dir end ## # Ensure +path+ and path with +extension+ are identical. def paranoid(path, extension) data = Gem.read_binary path compressed_data = Gem.read_binary "#{path}.#{extension}" unless data == Gem.inflate(compressed_data) then raise "Compressed file #{compressed_path} does not match uncompressed file #{path}" end end ## # Sanitize the descriptive fields in the spec. Sometimes non-ASCII # characters will garble the site index. Non-ASCII characters will # be replaced by their XML entity equivalent. def sanitize(spec) spec.summary = sanitize_string(spec.summary) spec.description = sanitize_string(spec.description) spec.post_install_message = sanitize_string(spec.post_install_message) spec.authors = spec.authors.collect { |a| sanitize_string(a) } spec end ## # Sanitize a single string. def sanitize_string(string) return string unless string # HACK the #to_s is in here because RSpec has an Array of Arrays of # Strings for authors. Need a way to disallow bad values on gemspec # generation. (Probably won't happen.) string = string.to_s begin Builder::XChar.encode string rescue NameError, NoMethodError string.to_xs end end ## # Perform an in-place update of the repository from newly added gems. def update_index make_temp_directories specs_mtime = File.stat(@dest_specs_index).mtime newest_mtime = Time.at 0 updated_gems = gem_file_list.select do |gem| gem_mtime = File.stat(gem).mtime newest_mtime = gem_mtime if gem_mtime > newest_mtime gem_mtime >= specs_mtime end if updated_gems.empty? then say 'No new gems' terminate_interaction 0 end specs = map_gems_to_specs updated_gems prerelease, released = specs.partition { |s| s.version.prerelease? } Gem::Specification.dirs = [] Gem::Specification.add_specs(*specs) files = build_marshal_gemspecs Gem.time 'Updated indexes' do update_specs_index released, @dest_specs_index, @specs_index update_specs_index released, @dest_latest_specs_index, @latest_specs_index update_specs_index(prerelease, @dest_prerelease_specs_index, @prerelease_specs_index) end compress_indicies verbose = Gem.configuration.really_verbose say "Updating production dir #{@dest_directory}" if verbose files << @specs_index files << "#{@specs_index}.gz" files << @latest_specs_index files << "#{@latest_specs_index}.gz" files << @prerelease_specs_index files << "#{@prerelease_specs_index}.gz" files = files.map do |path| path.sub(/^#{Regexp.escape @directory}\/?/, '') # HACK? end files.each do |file| src_name = File.join @directory, file dst_name = File.join @dest_directory, file # REFACTOR: duped above FileUtils.mv src_name, dst_name, :verbose => verbose, :force => true File.utime newest_mtime, newest_mtime, dst_name end end ## # Combines specs in +index+ and +source+ then writes out a new copy to # +dest+. For a latest index, does not ensure the new file is minimal. def update_specs_index(index, source, dest) specs_index = Marshal.load Gem.read_binary(source) index.each do |spec| platform = spec.original_platform platform = Gem::Platform::RUBY if platform.nil? or platform.empty? specs_index << [spec.name, spec.version, platform] end specs_index = compact_specs specs_index.uniq.sort open dest, 'wb' do |io| Marshal.dump specs_index, io end end end PK!V$ $ 2.2.0/rubygems/doctor.rbnu[require 'rubygems' require 'rubygems/user_interaction' ## # Cleans up after a partially-failed uninstall or for an invalid # Gem::Specification. # # If a specification was removed by hand this will remove any remaining files. # # If a corrupt specification was installed this will clean up warnings by # removing the bogus specification. class Gem::Doctor include Gem::UserInteraction ## # Maps a gem subdirectory to the files that are expected to exist in the # subdirectory. REPOSITORY_EXTENSION_MAP = [ # :nodoc: ['specifications', '.gemspec'], ['build_info', '.info'], ['cache', '.gem'], ['doc', ''], ['extensions', ''], ['gems', ''], ] missing = Gem::REPOSITORY_SUBDIRECTORIES.sort - REPOSITORY_EXTENSION_MAP.map { |(k,_)| k }.sort raise "Update REPOSITORY_EXTENSION_MAP, missing: #{missing.join ', '}" unless missing.empty? ## # Creates a new Gem::Doctor that will clean up +gem_repository+. Only one # gem repository may be cleaned at a time. # # If +dry_run+ is true no files or directories will be removed. def initialize gem_repository, dry_run = false @gem_repository = gem_repository @dry_run = dry_run @installed_specs = nil end ## # Specs installed in this gem repository def installed_specs # :nodoc: @installed_specs ||= Gem::Specification.map { |s| s.full_name } end ## # Are we doctoring a gem repository? def gem_repository? not installed_specs.empty? end ## # Cleans up uninstalled files and invalid gem specifications def doctor @orig_home = Gem.dir @orig_path = Gem.path say "Checking #{@gem_repository}" Gem.use_paths @gem_repository.to_s unless gem_repository? then say 'This directory does not appear to be a RubyGems repository, ' + 'skipping' say return end doctor_children say ensure Gem.use_paths @orig_home, *@orig_path end ## # Cleans up children of this gem repository def doctor_children # :nodoc: REPOSITORY_EXTENSION_MAP.each do |sub_directory, extension| doctor_child sub_directory, extension end end ## # Removes files in +sub_directory+ with +extension+ def doctor_child sub_directory, extension # :nodoc: directory = File.join(@gem_repository, sub_directory) Dir.entries(directory).sort.each do |ent| next if ent == "." || ent == ".." child = File.join(directory, ent) next unless File.exist?(child) basename = File.basename(child, extension) next if installed_specs.include? basename next if /^rubygems-\d/ =~ basename next if 'specifications' == sub_directory and 'default' == basename type = File.directory?(child) ? 'directory' : 'file' action = if @dry_run then 'Extra' else FileUtils.rm_r(child) 'Removed' end say "#{action} #{type} #{sub_directory}/#{File.basename(child)}" end rescue Errno::ENOENT # ignore end end PK!^2.2.0/rubygems/package_task.rbnu[# Copyright (c) 2003, 2004 Jim Weirich, 2009 Eric Hodel # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. require 'rubygems' require 'rubygems/package' begin gem 'rake' rescue Gem::LoadError end require 'rake/packagetask' ## # Create a package based upon a Gem::Specification. Gem packages, as well as # zip files and tar/gzipped packages can be produced by this task. # # In addition to the Rake targets generated by Rake::PackageTask, a # Gem::PackageTask will also generate the following tasks: # # ["package_dir/name-version.gem"] # Create a RubyGems package with the given name and version. # # Example using a Gem::Specification: # # require 'rubygems' # require 'rubygems/package_task' # # spec = Gem::Specification.new do |s| # s.summary = "Ruby based make-like utility." # s.name = 'rake' # s.version = PKG_VERSION # s.requirements << 'none' # s.files = PKG_FILES # s.description = <<-EOF # Rake is a Make-like program implemented in Ruby. Tasks # and dependencies are specified in standard Ruby syntax. # EOF # end # # Gem::PackageTask.new(spec) do |pkg| # pkg.need_zip = true # pkg.need_tar = true # end class Gem::PackageTask < Rake::PackageTask ## # Ruby Gem::Specification containing the metadata for this package. The # name, version and package_files are automatically determined from the # gemspec and don't need to be explicitly provided. attr_accessor :gem_spec ## # Create a Gem Package task library. Automatically define the gem if a # block is given. If no block is supplied, then #define needs to be called # to define the task. def initialize(gem_spec) init gem_spec yield self if block_given? define if block_given? end ## # Initialization tasks without the "yield self" or define operations. def init(gem) super gem.full_name, :noversion @gem_spec = gem @package_files += gem_spec.files if gem_spec.files end ## # Create the Rake tasks and actions specified by this Gem::PackageTask. # (+define+ is automatically called if a block is given to +new+). def define super gem_file = File.basename gem_spec.cache_file gem_path = File.join package_dir, gem_file gem_dir = File.join package_dir, gem_spec.full_name task :package => [:gem] directory package_dir directory gem_dir desc "Build the gem file #{gem_file}" task :gem => [gem_path] trace = Rake.application.options.trace Gem.configuration.verbose = trace file gem_path => [package_dir, gem_dir] + @gem_spec.files do chdir(gem_dir) do when_writing "Creating #{gem_spec.file_name}" do Gem::Package.build gem_spec verbose trace do mv gem_file, '..' end end end end end end PK!.O2.2.0/rubygems/test_case.rbnu[# TODO: $SAFE = 1 begin gem 'minitest', '~> 4.0' rescue NoMethodError, Gem::LoadError # for ruby tests end if defined? Gem::QuickLoader Gem::QuickLoader.load_full_rubygems_library else require 'rubygems' end begin gem 'minitest' rescue Gem::LoadError end # We have to load these up front because otherwise we'll try to load # them while we're testing rubygems, and thus we can't actually load them. unless Gem::Dependency.new('rdoc', '>= 3.10').matching_specs.empty? gem 'rdoc' gem 'json' end require 'minitest/autorun' require 'rubygems/deprecate' require 'fileutils' require 'pathname' require 'pp' require 'rubygems/package' require 'shellwords' require 'tmpdir' require 'uri' require 'zlib' Gem.load_yaml require 'rubygems/mock_gem_ui' module Gem ## # Allows setting the gem path searcher. This method is available when # requiring 'rubygems/test_case' def self.searcher=(searcher) @searcher = searcher end ## # Allows toggling Windows behavior. This method is available when requiring # 'rubygems/test_case' def self.win_platform=(val) @@win_platform = val end ## # Allows setting path to Ruby. This method is available when requiring # 'rubygems/test_case' def self.ruby= ruby @ruby = ruby end ## # When rubygems/test_case is required the default user interaction is a # MockGemUi. module DefaultUserInteraction @ui = Gem::MockGemUi.new end end ## # RubyGemTestCase provides a variety of methods for testing rubygems and # gem-related behavior in a sandbox. Through RubyGemTestCase you can install # and uninstall gems, fetch remote gems through a stub fetcher and be assured # your normal set of gems is not affected. # # Tests are always run at a safe level of 1. class Gem::TestCase < MiniTest::Unit::TestCase attr_accessor :fetcher # :nodoc: attr_accessor :gem_repo # :nodoc: attr_accessor :uri # :nodoc: def assert_activate expected, *specs specs.each do |spec| case spec when String then Gem::Specification.find_by_name(spec).activate when Gem::Specification then spec.activate else flunk spec.inspect end end loaded = Gem.loaded_specs.values.map(&:full_name) assert_equal expected.sort, loaded.sort if expected end # TODO: move to minitest def assert_path_exists path, msg = nil msg = message(msg) { "Expected path '#{path}' to exist" } assert File.exist?(path), msg end ## # Sets the ENABLE_SHARED entry in RbConfig::CONFIG to +value+ and restores # the original value when the block ends def enable_shared value enable_shared = RbConfig::CONFIG['ENABLE_SHARED'] RbConfig::CONFIG['ENABLE_SHARED'] = value yield ensure if enable_shared then RbConfig::CONFIG['enable_shared'] = enable_shared else RbConfig::CONFIG.delete 'enable_shared' end end # TODO: move to minitest def refute_path_exists path, msg = nil msg = message(msg) { "Expected path '#{path}' to not exist" } refute File.exist?(path), msg end def scan_make_command_lines(output) output.scan(/^#{Regexp.escape make_command}(?:[[:blank:]].*)?$/) end def parse_make_command_line(line) command, *args = line.shellsplit targets = [] macros = {} args.each do |arg| case arg when /\A(\w+)=/ macros[$1] = $' else targets << arg end end targets << '' if targets.empty? { :command => command, :targets => targets, :macros => macros, } end def assert_contains_make_command(target, output, msg = nil) if output.match(/\n/) msg = message(msg) { 'Expected output containing make command "%s": %s' % [ ('%s %s' % [make_command, target]).rstrip, output.inspect ] } else msg = message(msg) { 'Expected make command "%s": %s' % [ ('%s %s' % [make_command, target]).rstrip, output.inspect ] } end assert scan_make_command_lines(output).any? { |line| make = parse_make_command_line(line) if make[:targets].include?(target) yield make, line if block_given? true else false end }, msg end include Gem::DefaultUserInteraction undef_method :default_test if instance_methods.include? 'default_test' or instance_methods.include? :default_test @@project_dir = Dir.pwd.untaint unless defined?(@@project_dir) @@initial_reset = false ## # #setup prepares a sandboxed location to install gems. All installs are # directed to a temporary directory. All install plugins are removed. # # If the +RUBY+ environment variable is set the given path is used for # Gem::ruby. The local platform is set to i386-mswin32 for Windows # or i686-darwin8.10.1 otherwise. # # If the +KEEP_FILES+ environment variable is set the files will not be # removed from /tmp/test_rubygems_#{$$}.#{Time.now.to_i}. def setup super @orig_gem_home = ENV['GEM_HOME'] @orig_gem_path = ENV['GEM_PATH'] @orig_gem_vendor = ENV['GEM_VENDOR'] ENV['GEM_VENDOR'] = nil @current_dir = Dir.pwd @fetcher = nil @ui = Gem::MockGemUi.new tmpdir = File.expand_path Dir.tmpdir tmpdir.untaint if ENV['KEEP_FILES'] then @tempdir = File.join(tmpdir, "test_rubygems_#{$$}.#{Time.now.to_i}") else @tempdir = File.join(tmpdir, "test_rubygems_#{$$}") end @tempdir.untaint FileUtils.mkdir_p @tempdir # This makes the tempdir consistent on OS X. # File.expand_path Dir.tmpdir #=> "/var/..." # Dir.chdir Dir.tmpdir do File.expand_path '.' end #=> "/private/var/..." # TODO use File#realpath above instead of #expand_path once 1.8 support is # dropped. Dir.chdir @tempdir do @tempdir = File.expand_path '.' @tempdir.untaint end # This makes the tempdir consistent on Windows. # Dir.tmpdir may return short path name, but Dir[Dir.tmpdir] returns long # path name. https://bugs.ruby-lang.org/issues/10819 # File.expand_path or File.realpath doesn't convert path name to long path # name. Only Dir[] (= Dir.glob) works. # Short and long path name is specific to Windows filesystem. if win_platform? @tempdir = Dir[@tempdir][0] @tempdir.untaint end @gemhome = File.join @tempdir, 'gemhome' @userhome = File.join @tempdir, 'userhome' ENV["GEM_SPEC_CACHE"] = File.join @tempdir, 'spec_cache' @orig_ruby = if ENV['RUBY'] then ruby = Gem.ruby Gem.ruby = ENV['RUBY'] ruby end @git = ENV['GIT'] || 'git' Gem.ensure_gem_subdirectories @gemhome @orig_LOAD_PATH = $LOAD_PATH.dup $LOAD_PATH.map! { |s| File.expand_path(s).untaint } Dir.chdir @tempdir @orig_ENV_HOME = ENV['HOME'] ENV['HOME'] = @userhome Gem.instance_variable_set :@user_home, nil Gem.send :remove_instance_variable, :@ruby_version if Gem.instance_variables.include? :@ruby_version FileUtils.mkdir_p @gemhome FileUtils.mkdir_p @userhome @orig_gem_private_key_passphrase = ENV['GEM_PRIVATE_KEY_PASSPHRASE'] ENV['GEM_PRIVATE_KEY_PASSPHRASE'] = PRIVATE_KEY_PASSPHRASE @default_dir = File.join @tempdir, 'default' @default_spec_dir = File.join @default_dir, "specifications", "default" Gem.instance_variable_set :@default_dir, @default_dir FileUtils.mkdir_p @default_spec_dir # We use Gem::Specification.reset the first time only so that if there # are unresolved deps that leak into the whole test suite, they're at least # reported once. if @@initial_reset Gem::Specification.unresolved_deps.clear # done to avoid cross-test warnings else @@initial_reset = true Gem::Specification.reset end Gem.use_paths(@gemhome) Gem::Security.reset Gem.loaded_specs.clear Gem.clear_default_specs Gem::Specification.unresolved_deps.clear Gem.configuration.verbose = true Gem.configuration.update_sources = true Gem::RemoteFetcher.fetcher = Gem::FakeFetcher.new @gem_repo = "http://gems.example.com/" @uri = URI.parse @gem_repo Gem.sources.replace [@gem_repo] Gem.searcher = nil Gem::SpecFetcher.fetcher = nil @orig_BASERUBY = RbConfig::CONFIG['BASERUBY'] RbConfig::CONFIG['BASERUBY'] = RbConfig::CONFIG['ruby_install_name'] @orig_arch = RbConfig::CONFIG['arch'] if win_platform? util_set_arch 'i386-mswin32' else util_set_arch 'i686-darwin8.10.1' end @marshal_version = "#{Marshal::MAJOR_VERSION}.#{Marshal::MINOR_VERSION}" end ## # #teardown restores the process to its original state and removes the # tempdir unless the +KEEP_FILES+ environment variable was set. def teardown $LOAD_PATH.replace @orig_LOAD_PATH if @orig_LOAD_PATH if @orig_BASERUBY RbConfig::CONFIG['BASERUBY'] = @orig_BASERUBY else RbConfig::CONFIG.delete('BASERUBY') end RbConfig::CONFIG['arch'] = @orig_arch if defined? Gem::RemoteFetcher then Gem::RemoteFetcher.fetcher = nil end Dir.chdir @current_dir FileUtils.rm_rf @tempdir unless ENV['KEEP_FILES'] ENV['GEM_HOME'] = @orig_gem_home ENV['GEM_PATH'] = @orig_gem_path ENV['GEM_VENDOR'] = @orig_gem_vendor Gem.ruby = @orig_ruby if @orig_ruby if @orig_ENV_HOME then ENV['HOME'] = @orig_ENV_HOME else ENV.delete 'HOME' end Gem.instance_variable_set :@default_dir, nil ENV['GEM_PRIVATE_KEY_PASSPHRASE'] = @orig_gem_private_key_passphrase Gem::Specification._clear_load_cache end def common_installer_setup common_installer_teardown Gem.post_build do |installer| @post_build_hook_arg = installer true end Gem.post_install do |installer| @post_install_hook_arg = installer end Gem.post_uninstall do |uninstaller| @post_uninstall_hook_arg = uninstaller end Gem.pre_install do |installer| @pre_install_hook_arg = installer true end Gem.pre_uninstall do |uninstaller| @pre_uninstall_hook_arg = uninstaller end end def common_installer_teardown Gem.post_build_hooks.clear Gem.post_install_hooks.clear Gem.done_installing_hooks.clear Gem.post_reset_hooks.clear Gem.post_uninstall_hooks.clear Gem.pre_install_hooks.clear Gem.pre_reset_hooks.clear Gem.pre_uninstall_hooks.clear end ## # A git_gem is used with a gem dependencies file. The gem created here # has no files, just a gem specification for the given +name+ and +version+. # # Yields the +specification+ to the block, if given def git_gem name = 'a', version = 1 have_git? directory = File.join 'git', name directory = File.expand_path directory git_spec = Gem::Specification.new name, version do |specification| yield specification if block_given? end FileUtils.mkdir_p directory gemspec = "#{name}.gemspec" open File.join(directory, gemspec), 'w' do |io| io.write git_spec.to_ruby end head = nil Dir.chdir directory do unless File.exist? '.git' then system @git, 'init', '--quiet' system @git, 'config', 'user.name', 'RubyGems Tests' system @git, 'config', 'user.email', 'rubygems@example' end system @git, 'add', gemspec system @git, 'commit', '-a', '-m', 'a non-empty commit message', '--quiet' head = Gem::Util.popen('git', 'rev-parse', 'master').strip end return name, git_spec.version, directory, head end ## # Skips this test unless you have a git executable def have_git? return if in_path? @git skip 'cannot find git executable, use GIT environment variable to set' end def in_path? executable # :nodoc: return true if %r%\A([A-Z]:|/)% =~ executable and File.exist? executable ENV['PATH'].split(File::PATH_SEPARATOR).any? do |directory| File.exist? File.join directory, executable end end ## # Builds and installs the Gem::Specification +spec+ def install_gem spec, options = {} require 'rubygems/installer' gem = File.join @tempdir, "gems", "#{spec.full_name}.gem" unless File.exist? gem then use_ui Gem::MockGemUi.new do Dir.chdir @tempdir do Gem::Package.build spec end end gem = File.join(@tempdir, File.basename(spec.cache_file)).untaint end Gem::Installer.new(gem, options.merge({:wrappers => true})).install end ## # Builds and installs the Gem::Specification +spec+ into the user dir def install_gem_user spec install_gem spec, :user_install => true end ## # Uninstalls the Gem::Specification +spec+ def uninstall_gem spec require 'rubygems/uninstaller' Gem::Uninstaller.new(spec.name, :executables => true, :user_install => true).uninstall end ## # creates a temporary directory with hax # TODO: deprecate and remove def create_tmpdir tmpdir = nil Dir.chdir Dir.tmpdir do tmpdir = Dir.pwd end # HACK OSX /private/tmp tmpdir = File.join tmpdir, "test_rubygems_#{$$}" FileUtils.mkdir_p tmpdir return tmpdir end ## # Enables pretty-print for all tests def mu_pp(obj) s = '' s = PP.pp obj, s s = s.force_encoding(Encoding.default_external) if defined? Encoding s.chomp end ## # Reads a Marshal file at +path+ def read_cache(path) open path.dup.untaint, 'rb' do |io| Marshal.load io.read end end ## # Reads a binary file at +path+ def read_binary(path) Gem.read_binary path end ## # Writes a binary file to +path+ which is relative to +@gemhome+ def write_file(path) path = File.join @gemhome, path unless Pathname.new(path).absolute? dir = File.dirname path FileUtils.mkdir_p dir open path, 'wb' do |io| yield io if block_given? end path end def all_spec_names Gem::Specification.map(&:full_name) end ## # Creates a Gem::Specification with a minimum of extra work. +name+ and # +version+ are the gem's name and version, platform, author, email, # homepage, summary and description are defaulted. The specification is # yielded for customization. # # The gem is added to the installed gems in +@gemhome+ and the runtime. # # Use this with #write_file to build an installed gem. def quick_gem(name, version='2') require 'rubygems/specification' spec = Gem::Specification.new do |s| s.platform = Gem::Platform::RUBY s.name = name s.version = version s.author = 'A User' s.email = 'example@example.com' s.homepage = 'http://example.com' s.summary = "this is a summary" s.description = "This is a test description" yield(s) if block_given? end Gem::Specification.map # HACK: force specs to (re-)load before we write written_path = write_file spec.spec_file do |io| io.write spec.to_ruby_for_cache end spec.loaded_from = spec.loaded_from = written_path Gem::Specification.add_spec spec.for_cache return spec end ## # TODO: remove in RubyGems 3.0 def quick_spec name, version = '2' # :nodoc: util_spec name, version end ## # Builds a gem from +spec+ and places it in File.join @gemhome, # 'cache'. Automatically creates files based on +spec.files+ def util_build_gem(spec) dir = spec.gem_dir FileUtils.mkdir_p dir Dir.chdir dir do spec.files.each do |file| next if File.exist? file FileUtils.mkdir_p File.dirname(file) File.open file, 'w' do |fp| fp.puts "# #{file}" end end use_ui Gem::MockGemUi.new do Gem::Package.build spec end cache = spec.cache_file FileUtils.mv File.basename(cache), cache end end def util_remove_gem(spec) FileUtils.rm_rf spec.cache_file FileUtils.rm_rf spec.spec_file end ## # Removes all installed gems from +@gemhome+. def util_clear_gems FileUtils.rm_rf File.join(@gemhome, "gems") # TODO: use Gem::Dirs FileUtils.mkdir File.join(@gemhome, "gems") FileUtils.rm_rf File.join(@gemhome, "specifications") FileUtils.mkdir File.join(@gemhome, "specifications") Gem::Specification.reset end ## # Install the provided specs def install_specs(*specs) Gem::Specification.add_specs(*specs) Gem.searcher = nil end ## # Installs the provided default specs including writing the spec file def install_default_gems(*specs) install_default_specs(*specs) specs.each do |spec| open spec.loaded_from, 'w' do |io| io.write spec.to_ruby_for_cache end end end ## # Install the provided default specs def install_default_specs(*specs) install_specs(*specs) specs.each do |spec| Gem.register_default_spec(spec) end end def loaded_spec_names Gem.loaded_specs.values.map(&:full_name).sort end def unresolved_names Gem::Specification.unresolved_deps.values.map(&:to_s).sort end def save_loaded_features old_loaded_features = $LOADED_FEATURES.dup yield ensure $LOADED_FEATURES.replace old_loaded_features end ## # new_spec is deprecated as it is never used. # # TODO: remove in RubyGems 3.0 def new_spec name, version, deps = nil, *files # :nodoc: require 'rubygems/specification' spec = Gem::Specification.new do |s| s.platform = Gem::Platform::RUBY s.name = name s.version = version s.author = 'A User' s.email = 'example@example.com' s.homepage = 'http://example.com' s.summary = "this is a summary" s.description = "This is a test description" Array(deps).each do |n, req| s.add_dependency n, (req || '>= 0') end s.files.push(*files) unless files.empty? yield s if block_given? end spec.loaded_from = spec.spec_file unless files.empty? then write_file spec.spec_file do |io| io.write spec.to_ruby_for_cache end util_build_gem spec cache_file = File.join @tempdir, 'gems', "#{spec.full_name}.gem" FileUtils.mkdir_p File.dirname cache_file FileUtils.mv spec.cache_file, cache_file FileUtils.rm spec.spec_file end spec end def new_default_spec(name, version, deps = nil, *files) spec = util_spec name, version, deps spec.loaded_from = File.join(@default_spec_dir, spec.spec_name) spec.files = files lib_dir = File.join(@tempdir, "default_gems", "lib") $LOAD_PATH.unshift(lib_dir) files.each do |file| rb_path = File.join(lib_dir, file) FileUtils.mkdir_p(File.dirname(rb_path)) File.open(rb_path, "w") do |rb| rb << "# #{file}" end end spec end ## # Creates a spec with +name+, +version+. +deps+ can specify the dependency # or a +block+ can be given for full customization of the specification. def util_spec name, version = 2, deps = nil # :yields: specification raise "deps or block, not both" if deps and block_given? spec = Gem::Specification.new do |s| s.platform = Gem::Platform::RUBY s.name = name s.version = version s.author = 'A User' s.email = 'example@example.com' s.homepage = 'http://example.com' s.summary = "this is a summary" s.description = "This is a test description" yield s if block_given? end if deps then # Since Hash#each is unordered in 1.8, sort the keys and iterate that # way so the tests are deterministic on all implementations. deps.keys.sort.each do |n| spec.add_dependency n, (deps[n] || '>= 0') end end spec.loaded_from = spec.spec_file Gem::Specification.add_spec spec return spec end ## # Creates a gem with +name+, +version+ and +deps+. The specification will # be yielded before gem creation for customization. The gem will be placed # in File.join @tempdir, 'gems'. The specification and .gem file # location are returned. def util_gem(name, version, deps = nil, &block) # TODO: deprecate raise "deps or block, not both" if deps and block if deps then block = proc do |s| # Since Hash#each is unordered in 1.8, sort # the keys and iterate that way so the tests are # deterministic on all implementations. deps.keys.sort.each do |n| s.add_dependency n, (deps[n] || '>= 0') end end end spec = quick_gem(name, version, &block) util_build_gem spec cache_file = File.join @tempdir, 'gems', "#{spec.original_name}.gem" FileUtils.mkdir_p File.dirname cache_file FileUtils.mv spec.cache_file, cache_file FileUtils.rm spec.spec_file spec.loaded_from = nil [spec, cache_file] end ## # Gzips +data+. def util_gzip(data) out = StringIO.new Zlib::GzipWriter.wrap out do |io| io.write data end out.string end ## # Creates several default gems which all have a lib/code.rb file. The gems # are not installed but are available in the cache dir. # # +@a1+:: gem a version 1, this is the best-described gem. # +@a2+:: gem a version 2 # +@a3a:: gem a version 3.a # +@a_evil9+:: gem a_evil version 9, use this to ensure similarly-named gems # don't collide with a. # +@b2+:: gem b version 2 # +@c1_2+:: gem c version 1.2 # +@pl1+:: gem pl version 1, this gem has a legacy platform of i386-linux. # # Additional +prerelease+ gems may also be created: # # +@a2_pre+:: gem a version 2.a # TODO: nuke this and fix tests. this should speed up a lot def util_make_gems(prerelease = false) @a1 = quick_gem 'a', '1' do |s| s.files = %w[lib/code.rb] s.require_paths = %w[lib] s.date = Gem::Specification::TODAY - 86400 s.homepage = 'http://a.example.com' s.email = %w[example@example.com example2@example.com] s.authors = %w[Example Example2] s.description = <<-DESC This line is really, really long. So long, in fact, that it is more than eighty characters long! The purpose of this line is for testing wrapping behavior because sometimes people don't wrap their text to eighty characters. Without the wrapping, the text might not look good in the RSS feed. Also, a list: * An entry that\'s actually kind of sort * an entry that\'s really long, which will probably get wrapped funny. That's ok, somebody wasn't thinking straight when they made it more than eighty characters. DESC end init = proc do |s| s.files = %w[lib/code.rb] s.require_paths = %w[lib] end @a2 = quick_gem('a', '2', &init) @a3a = quick_gem('a', '3.a', &init) @a_evil9 = quick_gem('a_evil', '9', &init) @b2 = quick_gem('b', '2', &init) @c1_2 = quick_gem('c', '1.2', &init) @x = quick_gem('x', '1', &init) @dep_x = quick_gem('dep_x', '1') do |s| s.files = %w[lib/code.rb] s.require_paths = %w[lib] s.add_dependency 'x', '>= 1' end @pl1 = quick_gem 'pl', '1' do |s| # l for legacy s.files = %w[lib/code.rb] s.require_paths = %w[lib] s.platform = Gem::Platform.new 'i386-linux' s.instance_variable_set :@original_platform, 'i386-linux' end if prerelease @a2_pre = quick_gem('a', '2.a', &init) write_file File.join(*%W[gems #{@a2_pre.original_name} lib code.rb]) util_build_gem @a2_pre end write_file File.join(*%W[gems #{@a1.original_name} lib code.rb]) write_file File.join(*%W[gems #{@a2.original_name} lib code.rb]) write_file File.join(*%W[gems #{@a3a.original_name} lib code.rb]) write_file File.join(*%W[gems #{@a_evil9.original_name} lib code.rb]) write_file File.join(*%W[gems #{@b2.original_name} lib code.rb]) write_file File.join(*%W[gems #{@c1_2.original_name} lib code.rb]) write_file File.join(*%W[gems #{@pl1.original_name} lib code.rb]) write_file File.join(*%W[gems #{@x.original_name} lib code.rb]) write_file File.join(*%W[gems #{@dep_x.original_name} lib code.rb]) [@a1, @a2, @a3a, @a_evil9, @b2, @c1_2, @pl1, @x, @dep_x].each do |spec| util_build_gem spec end FileUtils.rm_r File.join(@gemhome, "gems", @pl1.original_name) end ## # Set the platform to +arch+ def util_set_arch(arch) RbConfig::CONFIG['arch'] = arch platform = Gem::Platform.new arch Gem.instance_variable_set :@platforms, nil Gem::Platform.instance_variable_set :@local, nil platform end ## # Sets up a fake fetcher using the gems from #util_make_gems. Optionally # additional +prerelease+ gems may be included. # # Gems created by this method may be fetched using Gem::RemoteFetcher. def util_setup_fake_fetcher(prerelease = false) require 'zlib' require 'socket' require 'rubygems/remote_fetcher' @fetcher = Gem::FakeFetcher.new util_make_gems(prerelease) Gem::Specification.reset @all_gems = [@a1, @a2, @a3a, @a_evil9, @b2, @c1_2].sort @all_gem_names = @all_gems.map { |gem| gem.full_name } gem_names = [@a1.full_name, @a2.full_name, @a3a.full_name, @b2.full_name] @gem_names = gem_names.sort.join("\n") Gem::RemoteFetcher.fetcher = @fetcher end ## # Add +spec+ to +@fetcher+ serving the data in the file +path+. # +repo+ indicates which repo to make +spec+ appear to be in. def add_to_fetcher(spec, path=nil, repo=@gem_repo) path ||= spec.cache_file @fetcher.data["#{@gem_repo}gems/#{spec.file_name}"] = read_binary(path) end ## # Sets up Gem::SpecFetcher to return information from the gems in +specs+. # Best used with +@all_gems+ from #util_setup_fake_fetcher. def util_setup_spec_fetcher(*specs) specs -= Gem::Specification._all Gem::Specification.add_specs(*specs) spec_fetcher = Gem::SpecFetcher.fetcher prerelease, all = Gem::Specification.partition { |spec| spec.version.prerelease? } spec_fetcher.specs[@uri] = [] all.each do |spec| spec_fetcher.specs[@uri] << spec.name_tuple end spec_fetcher.latest_specs[@uri] = [] Gem::Specification.latest_specs.each do |spec| spec_fetcher.latest_specs[@uri] << spec.name_tuple end spec_fetcher.prerelease_specs[@uri] = [] prerelease.each do |spec| spec_fetcher.prerelease_specs[@uri] << spec.name_tuple end # HACK for test_download_to_cache unless Gem::RemoteFetcher === @fetcher then v = Gem.marshal_version specs = all.map { |spec| spec.name_tuple } s_zip = util_gzip Marshal.dump Gem::NameTuple.to_basic specs latest_specs = Gem::Specification.latest_specs.map do |spec| spec.name_tuple end l_zip = util_gzip Marshal.dump Gem::NameTuple.to_basic latest_specs prerelease_specs = prerelease.map { |spec| spec.name_tuple } p_zip = util_gzip Marshal.dump Gem::NameTuple.to_basic prerelease_specs @fetcher.data["#{@gem_repo}specs.#{v}.gz"] = s_zip @fetcher.data["#{@gem_repo}latest_specs.#{v}.gz"] = l_zip @fetcher.data["#{@gem_repo}prerelease_specs.#{v}.gz"] = p_zip v = Gem.marshal_version Gem::Specification.each do |spec| path = "#{@gem_repo}quick/Marshal.#{v}/#{spec.original_name}.gemspec.rz" data = Marshal.dump spec data_deflate = Zlib::Deflate.deflate data @fetcher.data[path] = data_deflate end end nil # force errors end ## # Deflates +data+ def util_zip(data) Zlib::Deflate.deflate data end def util_set_RUBY_VERSION(version, patchlevel = nil, revision = nil) if Gem.instance_variables.include? :@ruby_version or Gem.instance_variables.include? '@ruby_version' then Gem.send :remove_instance_variable, :@ruby_version end @RUBY_VERSION = RUBY_VERSION @RUBY_PATCHLEVEL = RUBY_PATCHLEVEL if defined?(RUBY_PATCHLEVEL) @RUBY_REVISION = RUBY_REVISION if defined?(RUBY_REVISION) Object.send :remove_const, :RUBY_VERSION Object.send :remove_const, :RUBY_PATCHLEVEL if defined?(RUBY_PATCHLEVEL) Object.send :remove_const, :RUBY_REVISION if defined?(RUBY_REVISION) Object.const_set :RUBY_VERSION, version Object.const_set :RUBY_PATCHLEVEL, patchlevel if patchlevel Object.const_set :RUBY_REVISION, revision if revision end def util_restore_RUBY_VERSION Object.send :remove_const, :RUBY_VERSION Object.send :remove_const, :RUBY_PATCHLEVEL if defined?(RUBY_PATCHLEVEL) Object.send :remove_const, :RUBY_REVISION if defined?(RUBY_REVISION) Object.const_set :RUBY_VERSION, @RUBY_VERSION Object.const_set :RUBY_PATCHLEVEL, @RUBY_PATCHLEVEL if defined?(@RUBY_PATCHLEVEL) Object.const_set :RUBY_REVISION, @RUBY_REVISION if defined?(@RUBY_REVISION) end ## # Is this test being run on a Windows platform? def self.win_platform? Gem.win_platform? end ## # Is this test being run on a Windows platform? def win_platform? Gem.win_platform? end ## # Returns whether or not we're on a version of Ruby built with VC++ (or # Borland) versus Cygwin, Mingw, etc. def self.vc_windows? RUBY_PLATFORM.match('mswin') end ## # Returns whether or not we're on a version of Ruby built with VC++ (or # Borland) versus Cygwin, Mingw, etc. def vc_windows? RUBY_PLATFORM.match('mswin') end ## # Returns the make command for the current platform. For versions of Ruby # built on MS Windows with VC++ or Borland it will return 'nmake'. On all # other platforms, including Cygwin, it will return 'make'. def self.make_command ENV["make"] || (vc_windows? ? 'nmake' : 'make') end ## # Returns the make command for the current platform. For versions of Ruby # built on MS Windows with VC++ or Borland it will return 'nmake'. On all # other platforms, including Cygwin, it will return 'make'. def make_command ENV["make"] || (vc_windows? ? 'nmake' : 'make') end ## # Returns whether or not the nmake command could be found. def nmake_found? system('nmake /? 1>NUL 2>&1') end # In case we're building docs in a background process, this method waits for # that process to exit (or if it's already been reaped, or never happened, # swallows the Errno::ECHILD error). def wait_for_child_process_to_exit Process.wait if Process.respond_to?(:fork) rescue Errno::ECHILD end ## # Allows tests to use a random (but controlled) port number instead of # a hardcoded one. This helps CI tools when running parallels builds on # the same builder slave. def self.process_based_port @@process_based_port ||= 8000 + $$ % 1000 end ## # See ::process_based_port def process_based_port self.class.process_based_port end ## # Allows the proper version of +rake+ to be used for the test. def build_rake_in(good=true) gem_ruby = Gem.ruby Gem.ruby = @@ruby env_rake = ENV["rake"] rake = (good ? @@good_rake : @@bad_rake) ENV["rake"] = rake yield rake ensure Gem.ruby = gem_ruby if env_rake ENV["rake"] = env_rake else ENV.delete("rake") end end ## # Finds the path to the Ruby executable def self.rubybin ruby = ENV["RUBY"] return ruby if ruby ruby = "ruby" rubyexe = "#{ruby}.exe" 3.times do if File.exist? ruby and File.executable? ruby and !File.directory? ruby return File.expand_path(ruby) end if File.exist? rubyexe and File.executable? rubyexe return File.expand_path(rubyexe) end ruby = File.join("..", ruby) end begin require "rbconfig" File.join(RbConfig::CONFIG["bindir"], RbConfig::CONFIG["ruby_install_name"] + RbConfig::CONFIG["EXEEXT"]) rescue LoadError "ruby" end end @@ruby = rubybin @@good_rake = "#{rubybin} #{File.expand_path('../../../test/rubygems/good_rake.rb', __FILE__)}" @@bad_rake = "#{rubybin} #{File.expand_path('../../../test/rubygems/bad_rake.rb', __FILE__)}" ## # Construct a new Gem::Dependency. def dep name, *requirements Gem::Dependency.new name, *requirements end ## # Constructs a Gem::Resolver::DependencyRequest from a # Gem::Dependency +dep+, a +from_name+ and +from_version+ requesting the # dependency and a +parent+ DependencyRequest def dependency_request dep, from_name, from_version, parent = nil remote = Gem::Source.new @uri unless parent then parent_dep = dep from_name, from_version parent = Gem::Resolver::DependencyRequest.new parent_dep, nil end spec = Gem::Resolver::IndexSpecification.new \ nil, from_name, from_version, remote, Gem::Platform::RUBY activation = Gem::Resolver::ActivationRequest.new spec, parent Gem::Resolver::DependencyRequest.new dep, activation end ## # Constructs a new Gem::Requirement. def req *requirements return requirements.first if Gem::Requirement === requirements.first Gem::Requirement.create requirements end ## # Constructs a new Gem::Specification. def spec name, version, &block Gem::Specification.new name, v(version), &block end ## # Creates a SpecFetcher pre-filled with the gems or specs defined in the # block. # # Yields a +fetcher+ object that responds to +spec+ and +gem+. +spec+ adds # a specification to the SpecFetcher while +gem+ adds both a specification # and the gem data to the RemoteFetcher so the built gem can be downloaded. # # If only the a-3 gem is supposed to be downloaded you can save setup # time by creating only specs for the other versions: # # spec_fetcher do |fetcher| # fetcher.spec 'a', 1 # fetcher.spec 'a', 2, 'b' => 3 # dependency on b = 3 # fetcher.gem 'a', 3 do |spec| # # spec is a Gem::Specification # # ... # end # end def spec_fetcher repository = @gem_repo Gem::TestCase::SpecFetcherSetup.declare self, repository do |spec_fetcher_setup| yield spec_fetcher_setup if block_given? end end ## # Construct a new Gem::Version. def v string Gem::Version.create string end ## # A vendor_gem is used with a gem dependencies file. The gem created here # has no files, just a gem specification for the given +name+ and +version+. # # Yields the +specification+ to the block, if given def vendor_gem name = 'a', version = 1 directory = File.join 'vendor', name vendor_spec = Gem::Specification.new name, version do |specification| yield specification if block_given? end FileUtils.mkdir_p directory open File.join(directory, "#{name}.gemspec"), 'w' do |io| io.write vendor_spec.to_ruby end return name, vendor_spec.version, directory end ## # The StaticSet is a static set of gem specifications used for testing only. # It is available by requiring Gem::TestCase. class StaticSet < Gem::Resolver::Set ## # A StaticSet ignores remote because it has a fixed set of gems. attr_accessor :remote ## # Creates a new StaticSet for the given +specs+ def initialize(specs) super() @specs = specs @remote = true end ## # Adds +spec+ to this set. def add spec @specs << spec end ## # Finds +dep+ in this set. def find_spec(dep) @specs.reverse_each do |s| return s if dep.matches_spec? s end end ## # Finds all gems matching +dep+ in this set. def find_all(dep) @specs.find_all { |s| dep.match? s, @prerelease } end ## # Loads a Gem::Specification from this set which has the given +name+, # version +ver+, +platform+. The +source+ is ignored. def load_spec name, ver, platform, source dep = Gem::Dependency.new name, ver spec = find_spec dep Gem::Specification.new spec.name, spec.version do |s| s.platform = spec.platform end end def prefetch reqs # :nodoc: end end ## # Loads certificate named +cert_name+ from test/rubygems/. def self.load_cert cert_name cert_file = cert_path cert_name cert = File.read cert_file OpenSSL::X509::Certificate.new cert end ## # Returns the path to the certificate named +cert_name+ from # test/rubygems/. def self.cert_path cert_name if 32 == (Time.at(2**32) rescue 32) then cert_file = File.expand_path "../../../test/rubygems/#{cert_name}_cert_32.pem", __FILE__ return cert_file if File.exist? cert_file end File.expand_path "../../../test/rubygems/#{cert_name}_cert.pem", __FILE__ end ## # Loads an RSA private key named +key_name+ with +passphrase+ in test/rubygems/ def self.load_key key_name, passphrase = nil key_file = key_path key_name key = File.read key_file OpenSSL::PKey::RSA.new key, passphrase end ## # Returns the path to the key named +key_name+ from test/rubygems def self.key_path key_name File.expand_path "../../../test/rubygems/#{key_name}_key.pem", __FILE__ end # :stopdoc: # only available in RubyGems tests PRIVATE_KEY_PASSPHRASE = 'Foo bar' begin PRIVATE_KEY = load_key 'private' PRIVATE_KEY_PATH = key_path 'private' # ENCRYPTED_PRIVATE_KEY is PRIVATE_KEY encrypted with PRIVATE_KEY_PASSPHRASE ENCRYPTED_PRIVATE_KEY = load_key 'encrypted_private', PRIVATE_KEY_PASSPHRASE ENCRYPTED_PRIVATE_KEY_PATH = key_path 'encrypted_private' PUBLIC_KEY = PRIVATE_KEY.public_key PUBLIC_CERT = load_cert 'public' PUBLIC_CERT_PATH = cert_path 'public' rescue Errno::ENOENT PRIVATE_KEY = nil PUBLIC_KEY = nil PUBLIC_CERT = nil end if defined?(OpenSSL::SSL) end require 'rubygems/test_utilities' PK!Vcjj(2.2.0/rubygems/install_update_options.rbnu[#-- # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. # All rights reserved. # See LICENSE.txt for permissions. #++ require 'rubygems' # forward-declare module Gem::Security # :nodoc: class Policy # :nodoc: end end ## # Mixin methods for install and update options for Gem::Commands module Gem::InstallUpdateOptions ## # Add the install/update options to the option parser. def add_install_update_options # TODO: use @parser.accept OptionParser.accept Gem::Security::Policy do |value| require 'rubygems/security' raise OptionParser::InvalidArgument, 'OpenSSL not installed' unless defined?(Gem::Security::HighSecurity) value = Gem::Security::Policies[value] valid = Gem::Security::Policies.keys.sort message = "#{value} (#{valid.join ', '} are valid)" raise OptionParser::InvalidArgument, message if value.nil? value end add_option(:"Install/Update", '-i', '--install-dir DIR', 'Gem repository directory to get installed', 'gems') do |value, options| options[:install_dir] = File.expand_path(value) end add_option(:"Install/Update", '-n', '--bindir DIR', 'Directory where binary files are', 'located') do |value, options| options[:bin_dir] = File.expand_path(value) end add_option(:"Install/Update", '--[no-]document [TYPES]', Array, 'Generate documentation for installed gems', 'List the documentation types you wish to', 'generate. For example: rdoc,ri') do |value, options| options[:document] = case value when nil then %w[ri] when false then [] else value end end add_option(:"Install/Update", '--build-root DIR', 'Temporary installation root. Useful for building', 'packages. Do not use this when installing remote gems.') do |value, options| options[:build_root] = File.expand_path(value) end add_option(:"Install/Update", '--vendor', 'Install gem into the vendor directory.', 'Only for use by gem repackagers.') do |value, options| unless Gem.vendor_dir then raise OptionParser::InvalidOption.new 'your platform is not supported' end options[:vendor] = true options[:install_dir] = Gem.vendor_dir end add_option(:"Install/Update", '-N', '--no-document', 'Disable documentation generation') do |value, options| options[:document] = [] end add_option(:Deprecated, '--[no-]rdoc', 'Generate RDoc for installed gems', 'Use --document instead') do |value, options| if value then options[:document] << 'rdoc' else options[:document].delete 'rdoc' end options[:document].uniq! end add_option(:Deprecated, '--[no-]ri', 'Generate ri data for installed gems.', 'Use --document instead') do |value, options| if value then options[:document] << 'ri' else options[:document].delete 'ri' end options[:document].uniq! end add_option(:"Install/Update", '-E', '--[no-]env-shebang', "Rewrite the shebang line on installed", "scripts to use /usr/bin/env") do |value, options| options[:env_shebang] = value end add_option(:"Install/Update", '-f', '--[no-]force', 'Force gem to install, bypassing dependency', 'checks') do |value, options| options[:force] = value end add_option(:"Install/Update", '-w', '--[no-]wrappers', 'Use bin wrappers for executables', 'Not available on dosish platforms') do |value, options| options[:wrappers] = value end add_option(:"Install/Update", '-P', '--trust-policy POLICY', Gem::Security::Policy, 'Specify gem trust policy') do |value, options| options[:security_policy] = value end add_option(:"Install/Update", '--ignore-dependencies', 'Do not install any required dependent gems') do |value, options| options[:ignore_dependencies] = value end add_option(:"Install/Update", '--[no-]format-executable', 'Make installed executable names match ruby.', 'If ruby is ruby18, foo_exec will be', 'foo_exec18') do |value, options| options[:format_executable] = value end add_option(:"Install/Update", '--[no-]user-install', 'Install in user\'s home directory instead', 'of GEM_HOME.') do |value, options| options[:user_install] = value end add_option(:"Install/Update", "--development", "Install additional development", "dependencies") do |value, options| options[:development] = true options[:dev_shallow] = true end add_option(:"Install/Update", "--development-all", "Install development dependencies for all", "gems (including dev deps themselves)") do |value, options| options[:development] = true options[:dev_shallow] = false end add_option(:"Install/Update", "--conservative", "Don't attempt to upgrade gems already", "meeting version requirement") do |value, options| options[:conservative] = true options[:minimal_deps] = true end add_option(:"Install/Update", "--minimal-deps", "Don't upgrade any dependencies that already", "meet version requirements") do |value, options| options[:minimal_deps] = true end end ## # Default options for the gem install command. def install_update_defaults_str '--document=rdoc,ri --wrappers' end end PK!B` ` 2.2.0/rubygems/util.rbnu[## # This module contains various utility methods as module methods. module Gem::Util @silent_mutex = nil ## # Zlib::GzipReader wrapper that unzips +data+. def self.gunzip(data) require 'zlib' require 'rubygems/util/stringio' data = Gem::StringSource.new data unzipped = Zlib::GzipReader.new(data).read unzipped.force_encoding Encoding::BINARY if Object.const_defined? :Encoding unzipped end ## # Zlib::GzipWriter wrapper that zips +data+. def self.gzip(data) require 'zlib' require 'rubygems/util/stringio' zipped = Gem::StringSink.new zipped.set_encoding Encoding::BINARY if Object.const_defined? :Encoding Zlib::GzipWriter.wrap zipped do |io| io.write data end zipped.string end ## # A Zlib::Inflate#inflate wrapper def self.inflate(data) require 'zlib' Zlib::Inflate.inflate data end ## # This calls IO.popen where it accepts an array for a +command+ (Ruby 1.9+) # and implements an IO.popen-like behavior where it does not accept an array # for a command. def self.popen *command IO.popen command, &:read rescue TypeError # ruby 1.8 only supports string command r, w = IO.pipe pid = fork do STDIN.close STDOUT.reopen w exec(*command) end w.close begin return r.read ensure Process.wait pid end end NULL_DEVICE = defined?(IO::NULL) ? IO::NULL : Gem.win_platform? ? 'NUL' : '/dev/null' ## # Invokes system, but silences all output. def self.silent_system *command opt = {:out => NULL_DEVICE, :err => [:child, :out]} if Hash === command.last opt.update(command.last) cmds = command[0...-1] else cmds = command.dup end return system(*(cmds << opt)) rescue TypeError require 'thread' @silent_mutex ||= Mutex.new null_device = NULL_DEVICE @silent_mutex.synchronize do begin stdout = STDOUT.dup stderr = STDERR.dup STDOUT.reopen null_device, 'w' STDERR.reopen null_device, 'w' return system(*command) ensure STDOUT.reopen stdout STDERR.reopen stderr stdout.close stderr.close end end end ## # Enumerates the parents of +directory+. def self.traverse_parents directory return enum_for __method__, directory unless block_given? here = File.expand_path directory start = here Dir.chdir start begin loop do yield here Dir.chdir '..' return if Dir.pwd == here # toplevel here = Dir.pwd end ensure Dir.chdir start end end end PK!Ԑ [[2.2.0/rubygems/server.rbnu[require 'webrick' require 'zlib' require 'erb' require 'rubygems' require 'rubygems/rdoc' ## # Gem::Server and allows users to serve gems for consumption by # `gem --remote-install`. # # gem_server starts an HTTP server on the given port and serves the following: # * "/" - Browsing of gem spec files for installed gems # * "/specs.#{Gem.marshal_version}.gz" - specs name/version/platform index # * "/latest_specs.#{Gem.marshal_version}.gz" - latest specs # name/version/platform index # * "/quick/" - Individual gemspecs # * "/gems" - Direct access to download the installable gems # * "/rdoc?q=" - Search for installed rdoc documentation # # == Usage # # gem_server = Gem::Server.new Gem.dir, 8089, false # gem_server.run # #-- # TODO Refactor into a real WEBrick servlet to remove code duplication. class Gem::Server attr_reader :spec_dirs include ERB::Util include Gem::UserInteraction SEARCH = <<-SEARCH
    SEARCH DOC_TEMPLATE = <<-'DOC_TEMPLATE' RubyGems Documentation Index
    <%= SEARCH %>

    RubyGems Documentation Index

    Summary

    There are <%=values["gem_count"]%> gems installed:

    <%= values["specs"].map { |v| "#{v["name"]}" }.join ', ' %>.

    Gems

    <% values["specs"].each do |spec| %>
    <% if spec["first_name_entry"] then %> "> <% end %> <%=spec["name"]%> <%=spec["version"]%> <% if spec["ri_installed"] then %> ">[rdoc] <% elsif spec["rdoc_installed"] then %> ">[rdoc] <% else %> [rdoc] <% end %> <% if spec["homepage"] then %> " title="<%=spec["homepage"]%>">[www] <% else %> [www] <% end %> <% if spec["has_deps"] then %> - depends on <%= spec["dependencies"].map { |v| "#{v["name"]}" }.join ', ' %>. <% end %>
    <%=spec["summary"]%> <% if spec["executables"] then %>
    <% if spec["only_one_executable"] then %> Executable is <% else %> Executables are <%end%> <%= spec["executables"].map { |v| "#{v["executable"]}"}.join ', ' %>. <%end%>

    <% end %>
    DOC_TEMPLATE # CSS is copy & paste from rdoc-style.css, RDoc V1.0.1 - 20041108 RDOC_CSS = <<-RDOC_CSS body { font-family: Verdana,Arial,Helvetica,sans-serif; font-size: 90%; margin: 0; margin-left: 40px; padding: 0; background: white; } h1,h2,h3,h4 { margin: 0; color: #efefef; background: transparent; } h1 { font-size: 150%; } h2,h3,h4 { margin-top: 1em; } a { background: #eef; color: #039; text-decoration: none; } a:hover { background: #039; color: #eef; } /* Override the base stylesheets Anchor inside a table cell */ td > a { background: transparent; color: #039; text-decoration: none; } /* and inside a section title */ .section-title > a { background: transparent; color: #eee; text-decoration: none; } /* === Structural elements =================================== */ div#index { margin: 0; margin-left: -40px; padding: 0; font-size: 90%; } div#index a { margin-left: 0.7em; } div#index .section-bar { margin-left: 0px; padding-left: 0.7em; background: #ccc; font-size: small; } div#classHeader, div#fileHeader { width: auto; color: white; padding: 0.5em 1.5em 0.5em 1.5em; margin: 0; margin-left: -40px; border-bottom: 3px solid #006; } div#classHeader a, div#fileHeader a { background: inherit; color: white; } div#classHeader td, div#fileHeader td { background: inherit; color: white; } div#fileHeader { background: #057; } div#classHeader { background: #048; } .class-name-in-header { font-size: 180%; font-weight: bold; } div#bodyContent { padding: 0 1.5em 0 1.5em; } div#description { padding: 0.5em 1.5em; background: #efefef; border: 1px dotted #999; } div#description h1,h2,h3,h4,h5,h6 { color: #125;; background: transparent; } div#validator-badges { text-align: center; } div#validator-badges img { border: 0; } div#copyright { color: #333; background: #efefef; font: 0.75em sans-serif; margin-top: 5em; margin-bottom: 0; padding: 0.5em 2em; } /* === Classes =================================== */ table.header-table { color: white; font-size: small; } .type-note { font-size: small; color: #DEDEDE; } .xxsection-bar { background: #eee; color: #333; padding: 3px; } .section-bar { color: #333; border-bottom: 1px solid #999; margin-left: -20px; } .section-title { background: #79a; color: #eee; padding: 3px; margin-top: 2em; margin-left: -30px; border: 1px solid #999; } .top-aligned-row { vertical-align: top } .bottom-aligned-row { vertical-align: bottom } /* --- Context section classes ----------------------- */ .context-row { } .context-item-name { font-family: monospace; font-weight: bold; color: black; } .context-item-value { font-size: small; color: #448; } .context-item-desc { color: #333; padding-left: 2em; } /* --- Method classes -------------------------- */ .method-detail { background: #efefef; padding: 0; margin-top: 0.5em; margin-bottom: 1em; border: 1px dotted #ccc; } .method-heading { color: black; background: #ccc; border-bottom: 1px solid #666; padding: 0.2em 0.5em 0 0.5em; } .method-signature { color: black; background: inherit; } .method-name { font-weight: bold; } .method-args { font-style: italic; } .method-description { padding: 0 0.5em 0 0.5em; } /* --- Source code sections -------------------- */ a.source-toggle { font-size: 90%; } div.method-source-code { background: #262626; color: #ffdead; margin: 1em; padding: 0.5em; border: 1px dashed #999; overflow: hidden; } div.method-source-code pre { color: #ffdead; overflow: hidden; } /* --- Ruby keyword styles --------------------- */ .standalone-code { background: #221111; color: #ffdead; overflow: hidden; } .ruby-constant { color: #7fffd4; background: transparent; } .ruby-keyword { color: #00ffff; background: transparent; } .ruby-ivar { color: #eedd82; background: transparent; } .ruby-operator { color: #00ffee; background: transparent; } .ruby-identifier { color: #ffdead; background: transparent; } .ruby-node { color: #ffa07a; background: transparent; } .ruby-comment { color: #b22222; font-weight: bold; background: transparent; } .ruby-regexp { color: #ffa07a; background: transparent; } .ruby-value { color: #7fffd4; background: transparent; } RDOC_CSS RDOC_NO_DOCUMENTATION = <<-'NO_DOC' Found documentation
    <%= SEARCH %>

    No documentation found

    No gems matched <%= h query.inspect %>

    Back to complete gem index

    NO_DOC RDOC_SEARCH_TEMPLATE = <<-'RDOC_SEARCH' Found documentation
    <%= SEARCH %>

    Found documentation

    Summary

    <%=doc_items.length%> documentation topics found.

    Topics

    <% doc_items.each do |doc_item| %>
    <%=doc_item[:name]%> [rdoc]
    <%=doc_item[:summary]%>

    <% end %>

    Back to complete gem index

    RDOC_SEARCH def self.run(options) new(options[:gemdir], options[:port], options[:daemon], options[:launch], options[:addresses]).run end def initialize(gem_dirs, port, daemon, launch = nil, addresses = nil) Gem::RDoc.load_rdoc Socket.do_not_reverse_lookup = true @gem_dirs = Array gem_dirs @port = port @daemon = daemon @launch = launch @addresses = addresses logger = WEBrick::Log.new nil, WEBrick::BasicLog::FATAL @server = WEBrick::HTTPServer.new :DoNotListen => true, :Logger => logger @spec_dirs = @gem_dirs.map { |gem_dir| File.join gem_dir, 'specifications' } @spec_dirs.reject! { |spec_dir| !File.directory? spec_dir } reset_gems @have_rdoc_4_plus = nil end def add_date res res['date'] = @spec_dirs.map do |spec_dir| File.stat(spec_dir).mtime end.max end def doc_root gem_name if have_rdoc_4_plus? then "/doc_root/#{gem_name}/" else "/doc_root/#{gem_name}/rdoc/index.html" end end def have_rdoc_4_plus? @have_rdoc_4_plus ||= Gem::Requirement.new('>= 4.0.0.preview2').satisfied_by? Gem::RDoc.rdoc_version end def latest_specs(req, res) reset_gems res['content-type'] = 'application/x-gzip' add_date res latest_specs = Gem::Specification.latest_specs specs = latest_specs.sort.map do |spec| platform = spec.original_platform || Gem::Platform::RUBY [spec.name, spec.version, platform] end specs = Marshal.dump specs if req.path =~ /\.gz$/ then specs = Gem.gzip specs res['content-type'] = 'application/x-gzip' else res['content-type'] = 'application/octet-stream' end if req.request_method == 'HEAD' then res['content-length'] = specs.length else res.body << specs end end ## # Creates server sockets based on the addresses option. If no addresses # were given a server socket for all interfaces is created. def listen addresses = @addresses addresses = [nil] unless addresses listeners = 0 addresses.each do |address| begin @server.listen address, @port @server.listeners[listeners..-1].each do |listener| host, port = listener.addr.values_at 2, 1 host = "[#{host}]" if host =~ /:/ # we don't reverse lookup say "Server started at http://#{host}:#{port}" end listeners = @server.listeners.length rescue SystemCallError next end end if @server.listeners.empty? then say "Unable to start a server." say "Check for running servers or your --bind and --port arguments" terminate_interaction 1 end end def prerelease_specs req, res reset_gems res['content-type'] = 'application/x-gzip' add_date res specs = Gem::Specification.select do |spec| spec.version.prerelease? end.sort.map do |spec| platform = spec.original_platform || Gem::Platform::RUBY [spec.name, spec.version, platform] end specs = Marshal.dump specs if req.path =~ /\.gz$/ then specs = Gem.gzip specs res['content-type'] = 'application/x-gzip' else res['content-type'] = 'application/octet-stream' end if req.request_method == 'HEAD' then res['content-length'] = specs.length else res.body << specs end end def quick(req, res) reset_gems res['content-type'] = 'text/plain' add_date res case req.request_uri.path when %r|^/quick/(Marshal.#{Regexp.escape Gem.marshal_version}/)?(.*?)-([0-9.]+[^-]*?)(-.*?)?\.gemspec\.rz$| then marshal_format, name, version, platform = $1, $2, $3, $4 specs = Gem::Specification.find_all_by_name name, version selector = [name, version, platform].map(&:inspect).join ' ' platform = if platform then Gem::Platform.new platform.sub(/^-/, '') else Gem::Platform::RUBY end specs = specs.select { |s| s.platform == platform } if specs.empty? then res.status = 404 res.body = "No gems found matching #{selector}" elsif specs.length > 1 then res.status = 500 res.body = "Multiple gems found matching #{selector}" elsif marshal_format then res['content-type'] = 'application/x-deflate' res.body << Gem.deflate(Marshal.dump(specs.first)) end else raise WEBrick::HTTPStatus::NotFound, "`#{req.path}' not found." end end def root(req, res) reset_gems add_date res raise WEBrick::HTTPStatus::NotFound, "`#{req.path}' not found." unless req.path == '/' specs = [] total_file_count = 0 Gem::Specification.each do |spec| total_file_count += spec.files.size deps = spec.dependencies.map { |dep| { "name" => dep.name, "type" => dep.type, "version" => dep.requirement.to_s, } } deps = deps.sort_by { |dep| [dep["name"].downcase, dep["version"]] } deps.last["is_last"] = true unless deps.empty? # executables executables = spec.executables.sort.collect { |exec| {"executable" => exec} } executables = nil if executables.empty? executables.last["is_last"] = true if executables # Pre-process spec homepage for safety reasons begin homepage_uri = URI.parse(spec.homepage) if [URI::HTTP, URI::HTTPS].member? homepage_uri.class homepage_uri = spec.homepage else homepage_uri = "." end rescue URI::InvalidURIError homepage_uri = "." end specs << { "authors" => spec.authors.sort.join(", "), "date" => spec.date.to_s, "dependencies" => deps, "doc_path" => doc_root(spec.full_name), "executables" => executables, "only_one_executable" => (executables && executables.size == 1), "full_name" => spec.full_name, "has_deps" => !deps.empty?, "homepage" => homepage_uri, "name" => spec.name, "rdoc_installed" => Gem::RDoc.new(spec).rdoc_installed?, "ri_installed" => Gem::RDoc.new(spec).ri_installed?, "summary" => spec.summary, "version" => spec.version.to_s, } end specs << { "authors" => "Chad Fowler, Rich Kilmer, Jim Weirich, Eric Hodel and others", "dependencies" => [], "doc_path" => doc_root("rubygems-#{Gem::VERSION}"), "executables" => [{"executable" => 'gem', "is_last" => true}], "only_one_executable" => true, "full_name" => "rubygems-#{Gem::VERSION}", "has_deps" => false, "homepage" => "http://docs.rubygems.org/", "name" => 'rubygems', "ri_installed" => true, "summary" => "RubyGems itself", "version" => Gem::VERSION, } specs = specs.sort_by { |spec| [spec["name"].downcase, spec["version"]] } specs.last["is_last"] = true # tag all specs with first_name_entry last_spec = nil specs.each do |spec| is_first = last_spec.nil? || (last_spec["name"].downcase != spec["name"].downcase) spec["first_name_entry"] = is_first last_spec = spec end # create page from template template = ERB.new(DOC_TEMPLATE) res['content-type'] = 'text/html' values = { "gem_count" => specs.size.to_s, "specs" => specs, "total_file_count" => total_file_count.to_s } # suppress 1.9.3dev warning about unused variable values = values result = template.result binding res.body = result end ## # Can be used for quick navigation to the rdoc documentation. You can then # define a search shortcut for your browser. E.g. in Firefox connect # 'shortcut:rdoc' to http://localhost:8808/rdoc?q=%s template. Then you can # directly open the ActionPack documentation by typing 'rdoc actionp'. If # there are multiple hits for the search term, they are presented as a list # with links. # # Search algorithm aims for an intuitive search: # 1. first try to find the gems and documentation folders which name # starts with the search term # 2. search for entries, that *contain* the search term # 3. show all the gems # # If there is only one search hit, user is immediately redirected to the # documentation for the particular gem, otherwise a list with results is # shown. # # === Additional trick - install documentation for Ruby core # # Note: please adjust paths accordingly use for example 'locate yaml.rb' and # 'gem environment' to identify directories, that are specific for your # local installation # # 1. install Ruby sources # cd /usr/src # sudo apt-get source ruby # # 2. generate documentation # rdoc -o /usr/lib/ruby/gems/1.8/doc/core/rdoc \ # /usr/lib/ruby/1.8 ruby1.8-1.8.7.72 # # By typing 'rdoc core' you can now access the core documentation def rdoc(req, res) query = req.query['q'] show_rdoc_for_pattern("#{query}*", res) && return show_rdoc_for_pattern("*#{query}*", res) && return template = ERB.new RDOC_NO_DOCUMENTATION res['content-type'] = 'text/html' res.body = template.result binding end ## # Updates the server to use the latest installed gems. def reset_gems # :nodoc: Gem::Specification.dirs = @gem_dirs end ## # Returns true and prepares http response, if rdoc for the requested gem # name pattern was found. # # The search is based on the file system content, not on the gems metadata. # This allows additional documentation folders like 'core' for the Ruby core # documentation - just put it underneath the main doc folder. def show_rdoc_for_pattern(pattern, res) found_gems = Dir.glob("{#{@gem_dirs.join ','}}/doc/#{pattern}").select {|path| File.exist? File.join(path, 'rdoc/index.html') } case found_gems.length when 0 return false when 1 new_path = File.basename(found_gems[0]) res.status = 302 res['Location'] = doc_root new_path return true else doc_items = [] found_gems.each do |file_name| base_name = File.basename(file_name) doc_items << { :name => base_name, :url => doc_root(new_path), :summary => '' } end template = ERB.new(RDOC_SEARCH_TEMPLATE) res['content-type'] = 'text/html' result = template.result binding res.body = result return true end end def run listen WEBrick::Daemon.start if @daemon @server.mount_proc "/specs.#{Gem.marshal_version}", method(:specs) @server.mount_proc "/specs.#{Gem.marshal_version}.gz", method(:specs) @server.mount_proc "/latest_specs.#{Gem.marshal_version}", method(:latest_specs) @server.mount_proc "/latest_specs.#{Gem.marshal_version}.gz", method(:latest_specs) @server.mount_proc "/prerelease_specs.#{Gem.marshal_version}", method(:prerelease_specs) @server.mount_proc "/prerelease_specs.#{Gem.marshal_version}.gz", method(:prerelease_specs) @server.mount_proc "/quick/", method(:quick) @server.mount_proc("/gem-server-rdoc-style.css") do |req, res| res['content-type'] = 'text/css' add_date res res.body << RDOC_CSS end @server.mount_proc "/", method(:root) @server.mount_proc "/rdoc", method(:rdoc) file_handlers = { '/gems' => '/cache/', } if have_rdoc_4_plus? then @server.mount '/doc_root', RDoc::Servlet, '/doc_root' else file_handlers['/doc_root'] = '/doc/' end @gem_dirs.each do |gem_dir| file_handlers.each do |mount_point, mount_dir| @server.mount(mount_point, WEBrick::HTTPServlet::FileHandler, File.join(gem_dir, mount_dir), true) end end trap("INT") { @server.shutdown; exit! } trap("TERM") { @server.shutdown; exit! } launch if @launch @server.start end def specs(req, res) reset_gems add_date res specs = Gem::Specification.sort_by(&:sort_obj).map do |spec| platform = spec.original_platform || Gem::Platform::RUBY [spec.name, spec.version, platform] end specs = Marshal.dump specs if req.path =~ /\.gz$/ then specs = Gem.gzip specs res['content-type'] = 'application/x-gzip' else res['content-type'] = 'application/octet-stream' end if req.request_method == 'HEAD' then res['content-length'] = specs.length else res.body << specs end end def launch listeners = @server.listeners.map{|l| l.addr[2] } # TODO: 0.0.0.0 == any, not localhost. host = listeners.any?{|l| l == '0.0.0.0'} ? 'localhost' : listeners.first say "Launching browser to http://#{host}:#{@port}" system("#{@launch} http://#{host}:#{@port}") end end PK!o%2.2.0/rubygems/basic_specification.rbnu[## # BasicSpecification is an abstract class which implements some common code # used by both Specification and StubSpecification. class Gem::BasicSpecification ## # Allows installation of extensions for git: gems. attr_writer :base_dir # :nodoc: ## # Sets the directory where extensions for this gem will be installed. attr_writer :extension_dir # :nodoc: ## # Is this specification ignored for activation purposes? attr_writer :ignored # :nodoc: ## # The path this gemspec was loaded from. This attribute is not persisted. attr_reader :loaded_from ## # Allows correct activation of git: and path: gems. attr_writer :full_gem_path # :nodoc: def self.default_specifications_dir File.join(Gem.default_dir, "specifications", "default") end ## # True when the gem has been activated def activated? raise NotImplementedError end ## # Returns the full path to the base gem directory. # # eg: /usr/local/lib/ruby/gems/1.8 def base_dir return Gem.dir unless loaded_from @base_dir ||= if default_gem? then File.dirname File.dirname File.dirname loaded_from else File.dirname File.dirname loaded_from end end ## # Return true if this spec can require +file+. def contains_requirable_file? file @contains_requirable_file ||= {} @contains_requirable_file[file] ||= begin if instance_variable_defined?(:@ignored) or instance_variable_defined?('@ignored') then return false elsif missing_extensions? then @ignored = true warn "Ignoring #{full_name} because its extensions are not built. " + "Try: gem pristine #{name} --version #{version}" return false end suffixes = Gem.suffixes full_require_paths.any? do |dir| base = "#{dir}/#{file}" suffixes.any? { |suf| File.file? "#{base}#{suf}" } end end ? :yes : :no @contains_requirable_file[file] == :yes end def default_gem? loaded_from && File.dirname(loaded_from) == self.class.default_specifications_dir end ## # Returns full path to the directory where gem's extensions are installed. def extension_dir @extension_dir ||= File.expand_path File.join(extensions_dir, full_name) end ## # Returns path to the extensions directory. def extensions_dir @extensions_dir ||= Gem.default_ext_dir_for(base_dir) || File.join(base_dir, 'extensions', Gem::Platform.local.to_s, Gem.extension_api_version) end def find_full_gem_path # :nodoc: # TODO: also, shouldn't it default to full_name if it hasn't been written? path = File.expand_path File.join(gems_dir, full_name) path.untaint path if File.directory? path end private :find_full_gem_path ## # The full path to the gem (install path + full name). def full_gem_path # TODO: This is a heavily used method by gems, so we'll need # to aleast just alias it to #gem_dir rather than remove it. @full_gem_path ||= find_full_gem_path end ## # Returns the full name (name-version) of this Gem. Platform information # is included (name-version-platform) if it is specified and not the # default Ruby platform. def full_name if platform == Gem::Platform::RUBY or platform.nil? then "#{name}-#{version}".untaint else "#{name}-#{version}-#{platform}".untaint end end ## # Full paths in the gem to add to $LOAD_PATH when this gem is # activated. def full_require_paths @full_require_paths ||= begin full_paths = raw_require_paths.map do |path| File.join full_gem_path, path end full_paths.unshift extension_dir unless @extensions.nil? || @extensions.empty? full_paths end end ## # Full path of the target library file. # If the file is not in this gem, return nil. def to_fullpath path if activated? then @paths_map ||= {} @paths_map[path] ||= begin fullpath = nil suffixes = Gem.suffixes full_require_paths.find do |dir| suffixes.find do |suf| File.file?(fullpath = "#{dir}/#{path}#{suf}") end end ? fullpath : nil end else nil end end ## # Returns the full path to this spec's gem directory. # eg: /usr/local/lib/ruby/1.8/gems/mygem-1.0 def gem_dir @gem_dir ||= File.expand_path File.join(gems_dir, full_name) end ## # Returns the full path to the gems directory containing this spec's # gem directory. eg: /usr/local/lib/ruby/1.8/gems def gems_dir # TODO: this logic seems terribly broken, but tests fail if just base_dir @gems_dir ||= File.join(loaded_from && base_dir || Gem.dir, "gems") end ## # Set the path the Specification was loaded from. +path+ is converted to a # String. def loaded_from= path @loaded_from = path && path.to_s @extension_dir = nil @extensions_dir = nil @full_gem_path = nil @gem_dir = nil @gems_dir = nil @base_dir = nil end ## # Name of the gem def name raise NotImplementedError end ## # Platform of the gem def platform raise NotImplementedError end def raw_require_paths # :nodoc: Array(@require_paths) end ## # Paths in the gem to add to $LOAD_PATH when this gem is # activated. # # See also #require_paths= # # If you have an extension you do not need to add "ext" to the # require path, the extension build process will copy the extension files # into "lib" for you. # # The default value is "lib" # # Usage: # # # If all library files are in the root directory... # spec.require_path = '.' def require_paths return raw_require_paths if @extensions.nil? || @extensions.empty? [extension_dir].concat raw_require_paths end ## # Returns the paths to the source files for use with analysis and # documentation tools. These paths are relative to full_gem_path. def source_paths paths = raw_require_paths.dup if @extensions then ext_dirs = @extensions.map do |extension| extension.split(File::SEPARATOR, 2).first end.uniq paths.concat ext_dirs end paths.uniq end ## # Return a Gem::Specification from this gem def to_spec raise NotImplementedError end ## # Version of the gem def version raise NotImplementedError end ## # Whether this specification is stubbed - i.e. we have information # about the gem from a stub line, without having to evaluate the # entire gemspec file. def stubbed? raise NotImplementedError end end PK!Pܡ2.2.0/rubygems/util/list.rbnu[module Gem List = Struct.new(:value, :tail) class List def each n = self while n yield n.value n = n.tail end end def to_a ary = [] n = self while n ary.unshift n.value n = n.tail end ary end def find n = self while n v = n.value return v if yield(v) n = n.tail end nil end def prepend(value) List.new value, self end def pretty_print q # :nodoc: q.pp to_a end def self.prepend(list, value) return List.new(value) unless list List.new value, list end end end PK!2.2.0/rubygems/util/stringio.rbnu[class Gem::StringSink def initialize @string = "" end attr_reader :string def write(s) @string += s s.size end def set_encoding(enc) @string.force_encoding enc end end class Gem::StringSource def initialize(str) @string = str.dup end def read(count=nil) if count @string.slice!(0,count) else s = @string @string = "" s end end alias_method :readpartial, :read end PK!sz z &2.2.0/rubygems/local_remote_options.rbnu[#-- # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. # All rights reserved. # See LICENSE.txt for permissions. #++ require 'uri' require 'rubygems' ## # Mixin methods for local and remote Gem::Command options. module Gem::LocalRemoteOptions ## # Allows OptionParser to handle HTTP URIs. def accept_uri_http OptionParser.accept URI::HTTP do |value| begin uri = URI.parse value rescue URI::InvalidURIError raise OptionParser::InvalidArgument, value end unless ['http', 'https', 'file'].include?(uri.scheme) raise OptionParser::InvalidArgument, value end value end end ## # Add local/remote options to the command line parser. def add_local_remote_options add_option(:"Local/Remote", '-l', '--local', 'Restrict operations to the LOCAL domain') do |value, options| options[:domain] = :local end add_option(:"Local/Remote", '-r', '--remote', 'Restrict operations to the REMOTE domain') do |value, options| options[:domain] = :remote end add_option(:"Local/Remote", '-b', '--both', 'Allow LOCAL and REMOTE operations') do |value, options| options[:domain] = :both end add_bulk_threshold_option add_clear_sources_option add_source_option add_proxy_option add_update_sources_option end ## # Add the --bulk-threshold option def add_bulk_threshold_option add_option(:"Local/Remote", '-B', '--bulk-threshold COUNT', "Threshold for switching to bulk", "synchronization (default #{Gem.configuration.bulk_threshold})") do |value, options| Gem.configuration.bulk_threshold = value.to_i end end ## # Add the --clear-sources option def add_clear_sources_option add_option(:"Local/Remote", '--clear-sources', 'Clear the gem sources') do |value, options| Gem.sources = nil options[:sources_cleared] = true end end ## # Add the --http-proxy option def add_proxy_option accept_uri_http add_option(:"Local/Remote", '-p', '--[no-]http-proxy [URL]', URI::HTTP, 'Use HTTP proxy for remote operations') do |value, options| options[:http_proxy] = (value == false) ? :no_proxy : value Gem.configuration[:http_proxy] = options[:http_proxy] end end ## # Add the --source option def add_source_option accept_uri_http add_option(:"Local/Remote", '-s', '--source URL', URI::HTTP, 'Append URL to list of remote gem sources') do |source, options| source << '/' if source !~ /\/\z/ if options.delete :sources_cleared then Gem.sources = [source] else Gem.sources << source unless Gem.sources.include?(source) end end end ## # Add the --update-sources option def add_update_sources_option add_option(:Deprecated, '-u', '--[no-]update-sources', 'Update local source cache') do |value, options| Gem.configuration.update_sources = value end end ## # Is fetching of local and remote information enabled? def both? options[:domain] == :both end ## # Is local fetching enabled? def local? options[:domain] == :local || options[:domain] == :both end ## # Is remote fetching enabled? def remote? options[:domain] == :remote || options[:domain] == :both end end PK!(  !2.2.0/rubygems/psych_additions.rbnu[# This exists just to satify bugs in marshal'd gemspecs that # contain a reference to YAML::PrivateType. We prune these out # in Specification._load, but if we don't have the constant, Marshal # blows up. module Psych # :nodoc: class PrivateType # :nodoc: end end PK!W""2.2.0/rubygems/uninstaller.rbnu[#-- # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. # All rights reserved. # See LICENSE.txt for permissions. #++ require 'fileutils' require 'rubygems' require 'rubygems/dependency_list' require 'rubygems/rdoc' require 'rubygems/user_interaction' ## # An Uninstaller. # # The uninstaller fires pre and post uninstall hooks. Hooks can be added # either through a rubygems_plugin.rb file in an installed gem or via a # rubygems/defaults/#{RUBY_ENGINE}.rb or rubygems/defaults/operating_system.rb # file. See Gem.pre_uninstall and Gem.post_uninstall for details. class Gem::Uninstaller include Gem::UserInteraction ## # The directory a gem's executables will be installed into attr_reader :bin_dir ## # The gem repository the gem will be installed into attr_reader :gem_home ## # The Gem::Specification for the gem being uninstalled, only set during # #uninstall_gem attr_reader :spec ## # Constructs an uninstaller that will uninstall +gem+ def initialize(gem, options = {}) # TODO document the valid options @gem = gem @version = options[:version] || Gem::Requirement.default @gem_home = File.expand_path(options[:install_dir] || Gem.dir) @force_executables = options[:executables] @force_all = options[:all] @force_ignore = options[:ignore] @bin_dir = options[:bin_dir] @format_executable = options[:format_executable] @abort_on_dependent = options[:abort_on_dependent] # Indicate if development dependencies should be checked when # uninstalling. (default: false) # @check_dev = options[:check_dev] if options[:force] @force_all = true @force_ignore = true end # only add user directory if install_dir is not set @user_install = false @user_install = options[:user_install] unless options[:install_dir] end ## # Performs the uninstall of the gem. This removes the spec, the Gem # directory, and the cached .gem file. def uninstall dependency = Gem::Dependency.new @gem, @version list = [] dirs = Gem::Specification.dirs + [Gem::Specification.default_specifications_dir] Gem::Specification.each_spec dirs do |spec| next unless dependency.matches_spec? spec list << spec end default_specs, list = list.partition do |spec| spec.default_gem? end list, other_repo_specs = list.partition do |spec| @gem_home == spec.base_dir or (@user_install and spec.base_dir == Gem.user_dir) end list.sort! if list.empty? then if other_repo_specs.empty? if default_specs.empty? raise Gem::InstallError, "gem #{@gem.inspect} is not installed" else message = "gem #{@gem.inspect} cannot be uninstalled " + "because it is a default gem" raise Gem::InstallError, message end end other_repos = other_repo_specs.map { |spec| spec.base_dir }.uniq message = ["#{@gem} is not installed in GEM_HOME, try:"] message.concat other_repos.map { |repo| "\tgem uninstall -i #{repo} #{@gem}" } raise Gem::InstallError, message.join("\n") elsif @force_all then remove_all list elsif list.size > 1 then gem_names = list.map { |gem| gem.full_name } gem_names << "All versions" say _, index = choose_from_list "Select gem to uninstall:", gem_names if index == list.size then remove_all list elsif index >= 0 && index < list.size then uninstall_gem list[index] else say "Error: must enter a number [1-#{list.size+1}]" end else uninstall_gem list.first end end ## # Uninstalls gem +spec+ def uninstall_gem(spec) @spec = spec unless dependencies_ok? spec if abort_on_dependent? || !ask_if_ok(spec) raise Gem::DependencyRemovalException, "Uninstallation aborted due to dependent gem(s)" end end Gem.pre_uninstall_hooks.each do |hook| hook.call self end remove_executables @spec remove @spec Gem.post_uninstall_hooks.each do |hook| hook.call self end @spec = nil end ## # Removes installed executables and batch files (windows only) for # +gemspec+. def remove_executables(spec) return if spec.nil? or spec.executables.empty? executables = spec.executables.clone # Leave any executables created by other installed versions # of this gem installed. list = Gem::Specification.find_all { |s| s.name == spec.name && s.version != spec.version } list.each do |s| s.executables.each do |exe_name| executables.delete exe_name end end return if executables.empty? executables = executables.map { |exec| formatted_program_filename exec } remove = if @force_executables.nil? then ask_yes_no("Remove executables:\n" + "\t#{executables.join ', '}\n\n" + "in addition to the gem?", true) else @force_executables end if remove then bin_dir = @bin_dir || Gem.bindir(spec.base_dir) raise Gem::FilePermissionError, bin_dir unless File.writable? bin_dir executables.each do |exe_name| say "Removing #{exe_name}" exe_file = File.join bin_dir, exe_name FileUtils.rm_f exe_file FileUtils.rm_f "#{exe_file}.bat" end else say "Executables and scripts will remain installed." end end ## # Removes all gems in +list+. # # NOTE: removes uninstalled gems from +list+. def remove_all(list) list.each { |spec| uninstall_gem spec } end ## # spec:: the spec of the gem to be uninstalled # list:: the list of all such gems # # Warning: this method modifies the +list+ parameter. Once it has # uninstalled a gem, it is removed from that list. def remove(spec) unless path_ok?(@gem_home, spec) or (@user_install and path_ok?(Gem.user_dir, spec)) then e = Gem::GemNotInHomeException.new \ "Gem '#{spec.full_name}' is not installed in directory #{@gem_home}" e.spec = spec raise e end raise Gem::FilePermissionError, spec.base_dir unless File.writable?(spec.base_dir) FileUtils.rm_rf spec.full_gem_path FileUtils.rm_rf spec.extension_dir old_platform_name = spec.original_name gemspec = spec.spec_file unless File.exist? gemspec then gemspec = File.join(File.dirname(gemspec), "#{old_platform_name}.gemspec") end FileUtils.rm_rf gemspec gem = spec.cache_file gem = File.join(spec.cache_dir, "#{old_platform_name}.gem") unless File.exist? gem FileUtils.rm_rf gem Gem::RDoc.new(spec).remove say "Successfully uninstalled #{spec.full_name}" Gem::Specification.remove_spec spec end ## # Is +spec+ in +gem_dir+? def path_ok?(gem_dir, spec) full_path = File.join gem_dir, 'gems', spec.full_name original_path = File.join gem_dir, 'gems', spec.original_name full_path == spec.full_gem_path || original_path == spec.full_gem_path end ## # Returns true if it is OK to remove +spec+ or this is a forced # uninstallation. def dependencies_ok? spec # :nodoc: return true if @force_ignore deplist = Gem::DependencyList.from_specs deplist.ok_to_remove?(spec.full_name, @check_dev) end ## # Should the uninstallation abort if a dependency will go unsatisfied? # # See ::new. def abort_on_dependent? # :nodoc: @abort_on_dependent end ## # Asks if it is OK to remove +spec+. Returns true if it is OK. def ask_if_ok spec # :nodoc: msg = [''] msg << 'You have requested to uninstall the gem:' msg << "\t#{spec.full_name}" msg << '' siblings = Gem::Specification.select do |s| s.name == spec.name && s.full_name != spec.full_name end spec.dependent_gems.each do |dep_spec, dep, satlist| unless siblings.any? { |s| s.satisfies_requirement? dep } msg << "#{dep_spec.name}-#{dep_spec.version} depends on #{dep}" end end msg << 'If you remove this gem, these dependencies will not be met.' msg << 'Continue with Uninstall?' return ask_yes_no(msg.join("\n"), false) end ## # Returns the formatted version of the executable +filename+ def formatted_program_filename filename # :nodoc: # TODO perhaps the installer should leave a small manifest # of what it did for us to find rather than trying to recreate # it again. if @format_executable then require 'rubygems/installer' Gem::Installer.exec_format % File.basename(filename) else filename end end end PK! 'http://example.com' class Gem::UriFormatter ## # The URI to be formatted. attr_reader :uri ## # Creates a new URI formatter for +uri+. def initialize uri @uri = uri end ## # Escapes the #uri for use as a CGI parameter def escape return unless @uri CGI.escape @uri end ## # Normalize the URI by adding "http://" if it is missing. def normalize (@uri =~ /^(https?|ftp|file):/i) ? @uri : "http://#{@uri}" end ## # Unescapes the #uri which came from a CGI parameter def unescape return unless @uri CGI.unescape @uri end end PK!*2.2.0/rubygems/package/tar_reader/entry.rbnu[# -*- coding: utf-8 -*- #++ # Copyright (C) 2004 Mauricio Julio Fernández Pradier # See LICENSE.txt for additional licensing information. #-- ## # Class for reading entries out of a tar file class Gem::Package::TarReader::Entry ## # Header for this tar entry attr_reader :header ## # Creates a new tar entry for +header+ that will be read from +io+ def initialize(header, io) @closed = false @header = header @io = io @orig_pos = @io.pos @read = 0 end def check_closed # :nodoc: raise IOError, "closed #{self.class}" if closed? end ## # Number of bytes read out of the tar entry def bytes_read @read end ## # Closes the tar entry def close @closed = true end ## # Is the tar entry closed? def closed? @closed end ## # Are we at the end of the tar entry? def eof? check_closed @read >= @header.size end ## # Full name of the tar entry def full_name if @header.prefix != "" then File.join @header.prefix, @header.name else @header.name end rescue ArgumentError => e raise unless e.message == 'string contains null byte' raise Gem::Package::TarInvalidError, 'tar is corrupt, name contains null byte' end ## # Read one byte from the tar entry def getc check_closed return nil if @read >= @header.size ret = @io.getc @read += 1 if ret ret end ## # Is this tar entry a directory? def directory? @header.typeflag == "5" end ## # Is this tar entry a file? def file? @header.typeflag == "0" end ## # The position in the tar entry def pos check_closed bytes_read end ## # Reads +len+ bytes from the tar file entry, or the rest of the entry if # nil def read(len = nil) check_closed return nil if @read >= @header.size len ||= @header.size - @read max_read = [len, @header.size - @read].min ret = @io.read max_read @read += ret.size ret end alias readpartial read # :nodoc: ## # Rewinds to the beginning of the tar file entry def rewind check_closed raise Gem::Package::NonSeekableIO unless @io.respond_to? :pos= @io.pos = @orig_pos @read = 0 end end PK!FsF '2.2.0/rubygems/package/tar_test_case.rbnu[require 'rubygems/test_case' require 'rubygems/package' ## # A test case for Gem::Package::Tar* classes class Gem::Package::TarTestCase < Gem::TestCase def ASCIIZ(str, length) str + "\0" * (length - str.length) end def SP(s) s + " " end def SP_Z(s) s + " \0" end def Z(s) s + "\0" end def assert_headers_equal(expected, actual) expected = expected.to_s unless String === expected actual = actual.to_s unless String === actual fields = %w[ name 100 mode 8 uid 8 gid 8 size 12 mtime 12 checksum 8 typeflag 1 linkname 100 magic 6 version 2 uname 32 gname 32 devmajor 8 devminor 8 prefix 155 ] offset = 0 until fields.empty? do name = fields.shift length = fields.shift.to_i if name == "checksum" then chksum_off = offset offset += length next end assert_equal expected[offset, length], actual[offset, length], "Field #{name} of the tar header differs." offset += length end assert_equal expected[chksum_off, 8], actual[chksum_off, 8] end def calc_checksum(header) sum = header.unpack("C*").inject{|s,a| s + a} SP(Z(to_oct(sum, 6))) end def header(type, fname, dname, length, mode, mtime, checksum = nil) checksum ||= " " * 8 arr = [ # struct tarfile_entry_posix ASCIIZ(fname, 100), # char name[100]; ASCII + (Z unless filled) Z(to_oct(mode, 7)), # char mode[8]; 0 padded, octal null Z(to_oct(0, 7)), # char uid[8]; ditto Z(to_oct(0, 7)), # char gid[8]; ditto Z(to_oct(length, 11)), # char size[12]; 0 padded, octal, null Z(to_oct(mtime, 11)), # char mtime[12]; 0 padded, octal, null checksum, # char checksum[8]; 0 padded, octal, null, space type, # char typeflag[1]; file: "0" dir: "5" "\0" * 100, # char linkname[100]; ASCII + (Z unless filled) "ustar\0", # char magic[6]; "ustar\0" "00", # char version[2]; "00" ASCIIZ("wheel", 32), # char uname[32]; ASCIIZ ASCIIZ("wheel", 32), # char gname[32]; ASCIIZ Z(to_oct(0, 7)), # char devmajor[8]; 0 padded, octal, null Z(to_oct(0, 7)), # char devminor[8]; 0 padded, octal, null ASCIIZ(dname, 155) # char prefix[155]; ASCII + (Z unless filled) ] format = "C100C8C8C8C12C12C8CC100C6C2C32C32C8C8C155" h = if RUBY_VERSION >= "1.9" then arr.join else arr = arr.join("").split(//).map{|x| x[0]} arr.pack format end ret = h + "\0" * (512 - h.size) assert_equal(512, ret.size) ret end def tar_dir_header(name, prefix, mode, mtime) h = header("5", name, prefix, 0, mode, mtime) checksum = calc_checksum(h) header("5", name, prefix, 0, mode, mtime, checksum) end def tar_file_header(fname, dname, mode, length, mtime) h = header("0", fname, dname, length, mode, mtime) checksum = calc_checksum(h) header("0", fname, dname, length, mode, mtime, checksum) end def to_oct(n, pad_size) "%0#{pad_size}o" % n end def util_entry(tar) io = TempIO.new tar header = Gem::Package::TarHeader.from io Gem::Package::TarReader::Entry.new header, io end def util_dir_entry util_entry tar_dir_header("foo", "bar", 0, Time.now) end end PK!}2v v $2.2.0/rubygems/package/tar_reader.rbnu[# -*- coding: utf-8 -*- #-- # Copyright (C) 2004 Mauricio Julio Fernández Pradier # See LICENSE.txt for additional licensing information. #++ ## # TarReader reads tar files and allows iteration over their items class Gem::Package::TarReader include Enumerable ## # Raised if the tar IO is not seekable class UnexpectedEOF < StandardError; end ## # Creates a new TarReader on +io+ and yields it to the block, if given. def self.new(io) reader = super return reader unless block_given? begin yield reader ensure reader.close end nil end ## # Creates a new tar file reader on +io+ which needs to respond to #pos, # #eof?, #read, #getc and #pos= def initialize(io) @io = io @init_pos = io.pos end ## # Close the tar file def close end ## # Iterates over files in the tarball yielding each entry def each return enum_for __method__ unless block_given? until @io.eof? do header = Gem::Package::TarHeader.from @io return if header.empty? entry = Gem::Package::TarReader::Entry.new header, @io size = entry.header.size yield entry skip = (512 - (size % 512)) % 512 pending = size - entry.bytes_read begin # avoid reading... @io.seek pending, IO::SEEK_CUR pending = 0 rescue Errno::EINVAL, NameError while pending > 0 do bytes_read = @io.read([pending, 4096].min).size raise UnexpectedEOF if @io.eof? pending -= bytes_read end end @io.read skip # discard trailing zeros # make sure nobody can use #read, #getc or #rewind anymore entry.close end end alias each_entry each ## # NOTE: Do not call #rewind during #each def rewind if @init_pos == 0 then raise Gem::Package::NonSeekableIO unless @io.respond_to? :rewind @io.rewind else raise Gem::Package::NonSeekableIO unless @io.respond_to? :pos= @io.pos = @init_pos end end ## # Seeks through the tar file until it finds the +entry+ with +name+ and # yields it. Rewinds the tar file to the beginning when the block # terminates. def seek name # :yields: entry found = find do |entry| entry.full_name == name end return unless found return yield found ensure rewind end end require 'rubygems/package/tar_reader/entry' PK!A)$2.2.0/rubygems/package/tar_writer.rbnu[# -*- coding: utf-8 -*- #-- # Copyright (C) 2004 Mauricio Julio Fernández Pradier # See LICENSE.txt for additional licensing information. #++ require 'digest' ## # Allows writing of tar files class Gem::Package::TarWriter class FileOverflow < StandardError; end ## # IO wrapper that allows writing a limited amount of data class BoundedStream ## # Maximum number of bytes that can be written attr_reader :limit ## # Number of bytes written attr_reader :written ## # Wraps +io+ and allows up to +limit+ bytes to be written def initialize(io, limit) @io = io @limit = limit @written = 0 end ## # Writes +data+ onto the IO, raising a FileOverflow exception if the # number of bytes will be more than #limit def write(data) if data.bytesize + @written > @limit raise FileOverflow, "You tried to feed more data than fits in the file." end @io.write data @written += data.bytesize data.bytesize end end ## # IO wrapper that provides only #write class RestrictedStream ## # Creates a new RestrictedStream wrapping +io+ def initialize(io) @io = io end ## # Writes +data+ onto the IO def write(data) @io.write data end end ## # Creates a new TarWriter, yielding it if a block is given def self.new(io) writer = super return writer unless block_given? begin yield writer ensure writer.close end nil end ## # Creates a new TarWriter that will write to +io+ def initialize(io) @io = io @closed = false end ## # Adds file +name+ with permissions +mode+, and yields an IO for writing the # file to def add_file(name, mode) # :yields: io check_closed raise Gem::Package::NonSeekableIO unless @io.respond_to? :pos= name, prefix = split_name name init_pos = @io.pos @io.write "\0" * 512 # placeholder for the header yield RestrictedStream.new(@io) if block_given? size = @io.pos - init_pos - 512 remainder = (512 - (size % 512)) % 512 @io.write "\0" * remainder final_pos = @io.pos @io.pos = init_pos header = Gem::Package::TarHeader.new :name => name, :mode => mode, :size => size, :prefix => prefix, :mtime => Time.now @io.write header @io.pos = final_pos self end ## # Adds +name+ with permissions +mode+ to the tar, yielding +io+ for writing # the file. The +digest_algorithm+ is written to a read-only +name+.sum # file following the given file contents containing the digest name and # hexdigest separated by a tab. # # The created digest object is returned. def add_file_digest name, mode, digest_algorithms # :yields: io digests = digest_algorithms.map do |digest_algorithm| digest = digest_algorithm.new digest_name = if digest.respond_to? :name then digest.name else /::([^:]+)$/ =~ digest_algorithm.name $1 end [digest_name, digest] end digests = Hash[*digests.flatten] add_file name, mode do |io| Gem::Package::DigestIO.wrap io, digests do |digest_io| yield digest_io end end digests end ## # Adds +name+ with permissions +mode+ to the tar, yielding +io+ for writing # the file. The +signer+ is used to add a digest file using its # digest_algorithm per add_file_digest and a cryptographic signature in # +name+.sig. If the signer has no key only the checksum file is added. # # Returns the digest. def add_file_signed name, mode, signer digest_algorithms = [ signer.digest_algorithm, Digest::SHA512, ].compact.uniq digests = add_file_digest name, mode, digest_algorithms do |io| yield io end signature_digest = digests.values.compact.find do |digest| digest_name = if digest.respond_to? :name then digest.name else /::([^:]+)$/ =~ digest.class.name $1 end digest_name == signer.digest_name end raise "no #{signer.digest_name} in #{digests.values.compact}" unless signature_digest if signer.key then signature = signer.sign signature_digest.digest add_file_simple "#{name}.sig", 0444, signature.length do |io| io.write signature end end digests end ## # Add file +name+ with permissions +mode+ +size+ bytes long. Yields an IO # to write the file to. def add_file_simple(name, mode, size) # :yields: io check_closed name, prefix = split_name name header = Gem::Package::TarHeader.new(:name => name, :mode => mode, :size => size, :prefix => prefix, :mtime => Time.now).to_s @io.write header os = BoundedStream.new @io, size yield os if block_given? min_padding = size - os.written @io.write("\0" * min_padding) remainder = (512 - (size % 512)) % 512 @io.write("\0" * remainder) self end ## # Raises IOError if the TarWriter is closed def check_closed raise IOError, "closed #{self.class}" if closed? end ## # Closes the TarWriter def close check_closed @io.write "\0" * 1024 flush @closed = true end ## # Is the TarWriter closed? def closed? @closed end ## # Flushes the TarWriter's IO def flush check_closed @io.flush if @io.respond_to? :flush end ## # Creates a new directory in the tar file +name+ with +mode+ def mkdir(name, mode) check_closed name, prefix = split_name(name) header = Gem::Package::TarHeader.new :name => name, :mode => mode, :typeflag => "5", :size => 0, :prefix => prefix, :mtime => Time.now @io.write header self end ## # Splits +name+ into a name and prefix that can fit in the TarHeader def split_name(name) # :nodoc: if name.bytesize > 256 raise Gem::Package::TooLongFileName.new("File \"#{name}\" has a too long path (should be 256 or less)") end if name.bytesize <= 100 then prefix = "" else parts = name.split(/\//) newname = parts.pop nxt = "" loop do nxt = parts.pop break if newname.bytesize + 1 + nxt.bytesize > 100 newname = nxt + "/" + newname end prefix = (parts + [nxt]).join "/" name = newname if name.bytesize > 100 raise Gem::Package::TooLongFileName.new("File \"#{prefix}/#{name}\" has a too long name (should be 100 or less)") end if prefix.bytesize > 155 then raise Gem::Package::TooLongFileName.new("File \"#{prefix}/#{name}\" has a too long base path (should be 155 or less)") end end return name, prefix end end PK!J<;>** 2.2.0/rubygems/package/source.rbnu[class Gem::Package::Source # :nodoc: end PK!\99%2.2.0/rubygems/package/file_source.rbnu[## # The primary source of gems is a file on disk, including all usages # internal to rubygems. # # This is a private class, do not depend on it directly. Instead, pass a path # object to `Gem::Package.new`. class Gem::Package::FileSource < Gem::Package::Source # :nodoc: all attr_reader :path def initialize path @path = path end def start @start ||= File.read path, 20 end def present? File.exist? path end def with_write_io &block open path, 'wb', &block end def with_read_io &block open path, 'rb', &block end end PK!!/$2.2.0/rubygems/package/tar_header.rbnu[# -*- coding: utf-8 -*- #-- # Copyright (C) 2004 Mauricio Julio Fernández Pradier # See LICENSE.txt for additional licensing information. #++ ## #-- # struct tarfile_entry_posix { # char name[100]; # ASCII + (Z unless filled) # char mode[8]; # 0 padded, octal, null # char uid[8]; # ditto # char gid[8]; # ditto # char size[12]; # 0 padded, octal, null # char mtime[12]; # 0 padded, octal, null # char checksum[8]; # 0 padded, octal, null, space # char typeflag[1]; # file: "0" dir: "5" # char linkname[100]; # ASCII + (Z unless filled) # char magic[6]; # "ustar\0" # char version[2]; # "00" # char uname[32]; # ASCIIZ # char gname[32]; # ASCIIZ # char devmajor[8]; # 0 padded, octal, null # char devminor[8]; # o padded, octal, null # char prefix[155]; # ASCII + (Z unless filled) # }; #++ # A header for a tar file class Gem::Package::TarHeader ## # Fields in the tar header FIELDS = [ :checksum, :devmajor, :devminor, :gid, :gname, :linkname, :magic, :mode, :mtime, :name, :prefix, :size, :typeflag, :uid, :uname, :version, ] ## # Pack format for a tar header PACK_FORMAT = 'a100' + # name 'a8' + # mode 'a8' + # uid 'a8' + # gid 'a12' + # size 'a12' + # mtime 'a7a' + # chksum 'a' + # typeflag 'a100' + # linkname 'a6' + # magic 'a2' + # version 'a32' + # uname 'a32' + # gname 'a8' + # devmajor 'a8' + # devminor 'a155' # prefix ## # Unpack format for a tar header UNPACK_FORMAT = 'A100' + # name 'A8' + # mode 'A8' + # uid 'A8' + # gid 'A12' + # size 'A12' + # mtime 'A8' + # checksum 'A' + # typeflag 'A100' + # linkname 'A6' + # magic 'A2' + # version 'A32' + # uname 'A32' + # gname 'A8' + # devmajor 'A8' + # devminor 'A155' # prefix attr_reader(*FIELDS) ## # Creates a tar header from IO +stream+ def self.from(stream) header = stream.read 512 empty = (header == "\0" * 512) fields = header.unpack UNPACK_FORMAT new :name => fields.shift, :mode => strict_oct(fields.shift), :uid => strict_oct(fields.shift), :gid => strict_oct(fields.shift), :size => strict_oct(fields.shift), :mtime => strict_oct(fields.shift), :checksum => strict_oct(fields.shift), :typeflag => fields.shift, :linkname => fields.shift, :magic => fields.shift, :version => strict_oct(fields.shift), :uname => fields.shift, :gname => fields.shift, :devmajor => strict_oct(fields.shift), :devminor => strict_oct(fields.shift), :prefix => fields.shift, :empty => empty end def self.strict_oct(str) return str.oct if str =~ /\A[0-7]*\z/ raise ArgumentError, "#{str.inspect} is not an octal string" end ## # Creates a new TarHeader using +vals+ def initialize(vals) unless vals[:name] && vals[:size] && vals[:prefix] && vals[:mode] then raise ArgumentError, ":name, :size, :prefix and :mode required" end vals[:uid] ||= 0 vals[:gid] ||= 0 vals[:mtime] ||= 0 vals[:checksum] ||= "" vals[:typeflag] = "0" if vals[:typeflag].nil? || vals[:typeflag].empty? vals[:magic] ||= "ustar" vals[:version] ||= "00" vals[:uname] ||= "wheel" vals[:gname] ||= "wheel" vals[:devmajor] ||= 0 vals[:devminor] ||= 0 FIELDS.each do |name| instance_variable_set "@#{name}", vals[name] end @empty = vals[:empty] end ## # Is the tar entry empty? def empty? @empty end def ==(other) # :nodoc: self.class === other and @checksum == other.checksum and @devmajor == other.devmajor and @devminor == other.devminor and @gid == other.gid and @gname == other.gname and @linkname == other.linkname and @magic == other.magic and @mode == other.mode and @mtime == other.mtime and @name == other.name and @prefix == other.prefix and @size == other.size and @typeflag == other.typeflag and @uid == other.uid and @uname == other.uname and @version == other.version end def to_s # :nodoc: update_checksum header end ## # Updates the TarHeader's checksum def update_checksum header = header " " * 8 @checksum = oct calculate_checksum(header), 6 end private def calculate_checksum(header) header.unpack("C*").inject { |a, b| a + b } end def header(checksum = @checksum) header = [ name, oct(mode, 7), oct(uid, 7), oct(gid, 7), oct(size, 11), oct(mtime, 11), checksum, " ", typeflag, linkname, magic, oct(version, 2), uname, gname, oct(devmajor, 7), oct(devminor, 7), prefix ] header = header.pack PACK_FORMAT header << ("\0" * ((512 - header.size) % 512)) end def oct(num, len) "%0#{len}o" % num end end PK!eM 2.2.0/rubygems/package/old.rbnu[#-- # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. # All rights reserved. # See LICENSE.txt for permissions. #++ ## # The format class knows the guts of the ancient .gem file format and provides # the capability to read such ancient gems. # # Please pretend this doesn't exist. class Gem::Package::Old < Gem::Package undef_method :spec= ## # Creates a new old-format package reader for +gem+. Old-format packages # cannot be written. def initialize gem require 'fileutils' require 'zlib' Gem.load_yaml @contents = nil @gem = gem @security_policy = nil @spec = nil end ## # A list of file names contained in this gem def contents verify return @contents if @contents @gem.with_read_io do |io| read_until_dashes io # spec header = file_list io @contents = header.map { |file| file['path'] } end end ## # Extracts the files in this package into +destination_dir+ def extract_files destination_dir verify errstr = "Error reading files from gem" @gem.with_read_io do |io| read_until_dashes io # spec header = file_list io raise Gem::Exception, errstr unless header header.each do |entry| full_name = entry['path'] destination = install_location full_name, destination_dir file_data = '' read_until_dashes io do |line| file_data << line end file_data = file_data.strip.unpack("m")[0] file_data = Zlib::Inflate.inflate file_data raise Gem::Package::FormatError, "#{full_name} in #{@gem} is corrupt" if file_data.length != entry['size'].to_i FileUtils.rm_rf destination FileUtils.mkdir_p File.dirname destination open destination, 'wb', entry['mode'] do |out| out.write file_data end verbose destination end end rescue Zlib::DataError raise Gem::Exception, errstr end ## # Reads the file list section from the old-format gem +io+ def file_list io # :nodoc: header = '' read_until_dashes io do |line| header << line end Gem::SafeYAML.safe_load header end ## # Reads lines until a "---" separator is found def read_until_dashes io # :nodoc: while (line = io.gets) && line.chomp.strip != "---" do yield line if block_given? end end ## # Skips the Ruby self-install header in +io+. def skip_ruby io # :nodoc: loop do line = io.gets return if line.chomp == '__END__' break unless line end raise Gem::Exception, "Failed to find end of ruby script while reading gem" end ## # The specification for this gem def spec verify return @spec if @spec yaml = '' @gem.with_read_io do |io| skip_ruby io read_until_dashes io do |line| yaml << line end end yaml_error = if RUBY_VERSION < '1.9' then YAML::ParseError elsif YAML.const_defined?(:ENGINE) && YAML::ENGINE.yamler == 'syck' then YAML::ParseError else YAML::SyntaxError end begin @spec = Gem::Specification.from_yaml yaml rescue yaml_error raise Gem::Exception, "Failed to parse gem specification out of gem file" end rescue ArgumentError raise Gem::Exception, "Failed to parse gem specification out of gem file" end ## # Raises an exception if a security policy that verifies data is active. # Old format gems cannot be verified as signed. def verify return true unless @security_policy raise Gem::Security::Exception, 'old format gems do not contain signatures and cannot be verified' if @security_policy.verify_data true end end PK!R#2.2.0/rubygems/package/io_source.rbnu[## # Supports reading and writing gems from/to a generic IO object. This is # useful for other applications built on top of rubygems, such as # rubygems.org. # # This is a private class, do not depend on it directly. Instead, pass an IO # object to `Gem::Package.new`. class Gem::Package::IOSource < Gem::Package::Source # :nodoc: all attr_reader :io def initialize io @io = io end def start @start ||= begin if io.pos > 0 raise Gem::Package::Error, "Cannot read start unless IO is at start" end value = io.read 20 io.rewind value end end def present? true end def with_read_io yield io end def with_write_io yield io end def path end end PK! 55#2.2.0/rubygems/package/digest_io.rbnu[## # IO wrapper that creates digests of contents written to the IO it wraps. class Gem::Package::DigestIO ## # Collected digests for wrapped writes. # # { # 'SHA1' => #, # 'SHA512' => #, # } attr_reader :digests ## # Wraps +io+ and updates digest for each of the digest algorithms in # the +digests+ Hash. Returns the digests hash. Example: # # io = StringIO.new # digests = { # 'SHA1' => OpenSSL::Digest.new('SHA1'), # 'SHA512' => OpenSSL::Digest.new('SHA512'), # } # # Gem::Package::DigestIO.wrap io, digests do |digest_io| # digest_io.write "hello" # end # # digests['SHA1'].hexdigest #=> "aaf4c61d[...]" # digests['SHA512'].hexdigest #=> "9b71d224[...]" def self.wrap io, digests digest_io = new io, digests yield digest_io return digests end ## # Creates a new DigestIO instance. Using ::wrap is recommended, see the # ::wrap documentation for documentation of +io+ and +digests+. def initialize io, digests @io = io @digests = digests end ## # Writes +data+ to the underlying IO and updates the digests def write data result = @io.write data @digests.each do |_, digest| digest << data end result end end PK!)cc2.2.0/rubygems/mock_gem_ui.rbnu[require 'stringio' require 'rubygems/user_interaction' ## # This Gem::StreamUI subclass records input and output to StringIO for # retrieval during tests. class Gem::MockGemUi < Gem::StreamUI ## # Raised when you haven't provided enough input to your MockGemUi class InputEOFError < RuntimeError def initialize question super "Out of input for MockGemUi on #{question.inspect}" end end class TermError < RuntimeError attr_reader :exit_code def initialize exit_code super @exit_code = exit_code end end class SystemExitException < RuntimeError; end module TTY attr_accessor :tty def tty?() @tty = true unless defined?(@tty) @tty end def noecho yield self end end def initialize(input = "") ins = StringIO.new input outs = StringIO.new errs = StringIO.new ins.extend TTY outs.extend TTY errs.extend TTY super ins, outs, errs, true @terminated = false end def ask question raise InputEOFError, question if @ins.eof? super end def input @ins.string end def output @outs.string end def error @errs.string end def terminated? @terminated end def terminate_interaction(status=0) @terminated = true raise TermError, status if status != 0 raise SystemExitException end end PK!m2.2.0/rubygems/defaults.rbnu[module Gem DEFAULT_HOST = "https://rubygems.org" @post_install_hooks ||= [] @done_installing_hooks ||= [] @post_uninstall_hooks ||= [] @pre_uninstall_hooks ||= [] @pre_install_hooks ||= [] ## # An Array of the default sources that come with RubyGems def self.default_sources %w[https://rubygems.org/] end ## # Default spec directory path to be used if an alternate value is not # specified in the environment def self.default_spec_cache_dir File.join Gem.user_home, '.gem', 'specs' end ## # Default home directory path to be used if an alternate value is not # specified in the environment def self.default_dir path = if defined? RUBY_FRAMEWORK_VERSION then [ File.dirname(RbConfig::CONFIG['sitedir']), 'Gems', RbConfig::CONFIG['ruby_version'] ] elsif RbConfig::CONFIG['rubylibprefix'] then [ RbConfig::CONFIG['rubylibprefix'], 'gems', RbConfig::CONFIG['ruby_version'] ] else [ RbConfig::CONFIG['libdir'], ruby_engine, 'gems', RbConfig::CONFIG['ruby_version'] ] end @default_dir ||= File.join(*path) end ## # Returns binary extensions dir for specified RubyGems base dir or nil # if such directory cannot be determined. # # By default, the binary extensions are located side by side with their # Ruby counterparts, therefore nil is returned def self.default_ext_dir_for base_dir nil end ## # Paths where RubyGems' .rb files and bin files are installed def self.default_rubygems_dirs nil # default to standard layout end ## # Path for gems in the user's home directory def self.user_dir parts = [Gem.user_home, '.gem', ruby_engine] parts << RbConfig::CONFIG['ruby_version'] unless RbConfig::CONFIG['ruby_version'].empty? File.join parts end ## # How String Gem paths should be split. Overridable for esoteric platforms. def self.path_separator File::PATH_SEPARATOR end ## # Default gem load path def self.default_path path = [] path << user_dir if user_home && File.exist?(user_home) path << default_dir path << vendor_dir if vendor_dir and File.directory? vendor_dir path end ## # Deduce Ruby's --program-prefix and --program-suffix from its install name def self.default_exec_format exec_format = RbConfig::CONFIG['ruby_install_name'].sub('ruby', '%s') rescue '%s' unless exec_format =~ /%s/ then raise Gem::Exception, "[BUG] invalid exec_format #{exec_format.inspect}, no %s" end exec_format end ## # The default directory for binaries def self.default_bindir if defined? RUBY_FRAMEWORK_VERSION then # mac framework support '/usr/bin' else # generic install RbConfig::CONFIG['bindir'] end end ## # A wrapper around RUBY_ENGINE const that may not be defined def self.ruby_engine if defined? RUBY_ENGINE then RUBY_ENGINE else 'ruby' end end ## # The default signing key path def self.default_key_path File.join Gem.user_home, ".gem", "gem-private_key.pem" end ## # The default signing certificate chain path def self.default_cert_path File.join Gem.user_home, ".gem", "gem-public_cert.pem" end ## # Whether to expect full paths in default gems - true for non-MRI # ruby implementations def self.default_gems_use_full_paths? ruby_engine != 'ruby' end ## # Install extensions into lib as well as into the extension directory. def self.install_extension_in_lib # :nodoc: true end ## # Directory where vendor gems are installed. def self.vendor_dir # :nodoc: if vendor_dir = ENV['GEM_VENDOR'] then return vendor_dir.dup end return nil unless RbConfig::CONFIG.key? 'vendordir' File.join RbConfig::CONFIG['vendordir'], 'gems', RbConfig::CONFIG['ruby_version'] end end PK!̌t99&2.2.0/rubygems/request_set/lockfile.rbnu[require 'strscan' ## # Parses a gem.deps.rb.lock file and constructs a LockSet containing the # dependencies found inside. If the lock file is missing no LockSet is # constructed. class Gem::RequestSet::Lockfile ## # Raised when a lockfile cannot be parsed class ParseError < Gem::Exception ## # The column where the error was encountered attr_reader :column ## # The line where the error was encountered attr_reader :line ## # The location of the lock file attr_reader :path ## # Raises a ParseError with the given +message+ which was encountered at a # +line+ and +column+ while parsing. def initialize message, column, line, path @line = line @column = column @path = path super "#{message} (at line #{line} column #{column})" end end ## # The platforms for this Lockfile attr_reader :platforms ## # Creates a new Lockfile for the given +request_set+ and +gem_deps_file+ # location. def initialize request_set, gem_deps_file, dependencies = nil @set = request_set @dependencies = dependencies @gem_deps_file = File.expand_path(gem_deps_file) @gem_deps_dir = File.dirname(@gem_deps_file) @gem_deps_file.untaint unless gem_deps_file.tainted? @current_token = nil @line = 0 @line_pos = 0 @platforms = [] @tokens = [] end def add_DEPENDENCIES out # :nodoc: out << "DEPENDENCIES" dependencies = if @dependencies then @dependencies.sort_by { |name,| name }.map do |name, requirement| requirement_string = if '!' == requirement then requirement else Gem::Requirement.new(requirement).for_lockfile end [name, requirement_string] end else @requests.sort_by { |r| r.name }.map do |request| spec = request.spec name = request.name requirement = request.request.dependency.requirement requirement_string = if [Gem::Resolver::VendorSpecification, Gem::Resolver::GitSpecification].include? spec.class then "!" else requirement.for_lockfile end [name, requirement_string] end end dependencies = dependencies.map do |name, requirement_string| " #{name}#{requirement_string}" end out.concat dependencies out << nil end def add_GEM out # :nodoc: return if @spec_groups.empty? source_groups = @spec_groups.values.flatten.group_by do |request| request.spec.source.uri end source_groups.sort_by { |group,| group.to_s }.map do |group, requests| out << "GEM" out << " remote: #{group}" out << " specs:" requests.sort_by { |request| request.name }.each do |request| next if request.spec.name == 'bundler' platform = "-#{request.spec.platform}" unless Gem::Platform::RUBY == request.spec.platform out << " #{request.name} (#{request.version}#{platform})" request.full_spec.dependencies.sort.each do |dependency| next if dependency.type == :development requirement = dependency.requirement out << " #{dependency.name}#{requirement.for_lockfile}" end end out << nil end end def add_GIT out return unless git_requests = @spec_groups.delete(Gem::Resolver::GitSpecification) by_repository_revision = git_requests.group_by do |request| source = request.spec.source [source.repository, source.rev_parse] end out << "GIT" by_repository_revision.each do |(repository, revision), requests| out << " remote: #{repository}" out << " revision: #{revision}" out << " specs:" requests.sort_by { |request| request.name }.each do |request| out << " #{request.name} (#{request.version})" dependencies = request.spec.dependencies.sort_by { |dep| dep.name } dependencies.each do |dep| out << " #{dep.name}#{dep.requirement.for_lockfile}" end end end out << nil end def relative_path_from dest, base # :nodoc: dest = File.expand_path(dest) base = File.expand_path(base) if dest.index(base) == 0 then offset = dest[base.size+1..-1] return '.' unless offset offset else dest end end def add_PATH out # :nodoc: return unless path_requests = @spec_groups.delete(Gem::Resolver::VendorSpecification) out << "PATH" path_requests.each do |request| directory = File.expand_path(request.spec.source.uri) out << " remote: #{relative_path_from directory, @gem_deps_dir}" out << " specs:" out << " #{request.name} (#{request.version})" end out << nil end def add_PLATFORMS out # :nodoc: out << "PLATFORMS" platforms = @requests.map { |request| request.spec.platform }.uniq platforms = platforms.sort_by { |platform| platform.to_s } platforms.sort.each do |platform| out << " #{platform}" end out << nil end ## # Gets the next token for a Lockfile def get expected_types = nil, expected_value = nil # :nodoc: @current_token = @tokens.shift type, value, column, line = @current_token if expected_types and not Array(expected_types).include? type then unget message = "unexpected token [#{type.inspect}, #{value.inspect}], " + "expected #{expected_types.inspect}" raise ParseError.new message, column, line, "#{@gem_deps_file}.lock" end if expected_value and expected_value != value then unget message = "unexpected token [#{type.inspect}, #{value.inspect}], " + "expected [#{expected_types.inspect}, " + "#{expected_value.inspect}]" raise ParseError.new message, column, line, "#{@gem_deps_file}.lock" end @current_token end def parse # :nodoc: tokenize until @tokens.empty? do type, data, column, line = get case type when :section then skip :newline case data when 'DEPENDENCIES' then parse_DEPENDENCIES when 'GIT' then parse_GIT when 'GEM' then parse_GEM when 'PATH' then parse_PATH when 'PLATFORMS' then parse_PLATFORMS else type, = get until @tokens.empty? or peek.first == :section end else raise "BUG: unhandled token #{type} (#{data.inspect}) at line #{line} column #{column}" end end end def parse_DEPENDENCIES # :nodoc: while not @tokens.empty? and :text == peek.first do _, name, = get :text requirements = [] case peek[0] when :bang then get :bang requirements << pinned_requirement(name) when :l_paren then get :l_paren loop do _, op, = get :requirement _, version, = get :text requirements << "#{op} #{version}" break unless peek[0] == :comma get :comma end get :r_paren if peek[0] == :bang then requirements.clear requirements << pinned_requirement(name) get :bang end end @set.gem name, *requirements skip :newline end end def parse_GEM # :nodoc: sources = [] while [:entry, 'remote'] == peek.first(2) do get :entry, 'remote' _, data, = get :text skip :newline sources << Gem::Source.new(data) end sources << Gem::Source.new(Gem::DEFAULT_HOST) if sources.empty? get :entry, 'specs' skip :newline set = Gem::Resolver::LockSet.new sources last_specs = nil while not @tokens.empty? and :text == peek.first do _, name, column, = get :text case peek[0] when :newline then last_specs.each do |spec| spec.add_dependency Gem::Dependency.new name if column == 6 end when :l_paren then get :l_paren type, data, = get [:text, :requirement] if type == :text and column == 4 then version, platform = data.split '-', 2 platform = platform ? Gem::Platform.new(platform) : Gem::Platform::RUBY last_specs = set.add name, version, platform else dependency = parse_dependency name, data last_specs.each do |spec| spec.add_dependency dependency end end get :r_paren else raise "BUG: unknown token #{peek}" end skip :newline end @set.sets << set end def parse_GIT # :nodoc: get :entry, 'remote' _, repository, = get :text skip :newline get :entry, 'revision' _, revision, = get :text skip :newline type, value = peek.first 2 if type == :entry and %w[branch ref tag].include? value then get get :text skip :newline end get :entry, 'specs' skip :newline set = Gem::Resolver::GitSet.new set.root_dir = @set.install_dir last_spec = nil while not @tokens.empty? and :text == peek.first do _, name, column, = get :text case peek[0] when :newline then last_spec.add_dependency Gem::Dependency.new name if column == 6 when :l_paren then get :l_paren type, data, = get [:text, :requirement] if type == :text and column == 4 then last_spec = set.add_git_spec name, data, repository, revision, true else dependency = parse_dependency name, data last_spec.add_dependency dependency end get :r_paren else raise "BUG: unknown token #{peek}" end skip :newline end @set.sets << set end def parse_PATH # :nodoc: get :entry, 'remote' _, directory, = get :text skip :newline get :entry, 'specs' skip :newline set = Gem::Resolver::VendorSet.new last_spec = nil while not @tokens.empty? and :text == peek.first do _, name, column, = get :text case peek[0] when :newline then last_spec.add_dependency Gem::Dependency.new name if column == 6 when :l_paren then get :l_paren type, data, = get [:text, :requirement] if type == :text and column == 4 then last_spec = set.add_vendor_gem name, directory else dependency = parse_dependency name, data last_spec.dependencies << dependency end get :r_paren else raise "BUG: unknown token #{peek}" end skip :newline end @set.sets << set end def parse_PLATFORMS # :nodoc: while not @tokens.empty? and :text == peek.first do _, name, = get :text @platforms << name skip :newline end end ## # Parses the requirements following the dependency +name+ and the +op+ for # the first token of the requirements and returns a Gem::Dependency object. def parse_dependency name, op # :nodoc: return Gem::Dependency.new name, op unless peek[0] == :text _, version, = get :text requirements = ["#{op} #{version}"] while peek[0] == :comma do get :comma _, op, = get :requirement _, version, = get :text requirements << "#{op} #{version}" end Gem::Dependency.new name, requirements end ## # Peeks at the next token for Lockfile def peek # :nodoc: @tokens.first || [:EOF] end def pinned_requirement name # :nodoc: spec = @set.sets.select { |set| Gem::Resolver::GitSet === set or Gem::Resolver::VendorSet === set }.map { |set| set.specs[name] }.compact.first spec.version end def skip type # :nodoc: get while not @tokens.empty? and peek.first == type end ## # The contents of the lock file. def to_s @set.resolve out = [] @requests = @set.sorted_requests @spec_groups = @requests.group_by do |request| request.spec.class end add_PATH out add_GIT out add_GEM out add_PLATFORMS out add_DEPENDENCIES out out.join "\n" end ## # Calculates the column (by byte) and the line of the current token based on # +byte_offset+. def token_pos byte_offset # :nodoc: [byte_offset - @line_pos, @line] end ## # Converts a lock file into an Array of tokens. If the lock file is missing # an empty Array is returned. def tokenize # :nodoc: @line = 0 @line_pos = 0 @platforms = [] @tokens = [] @current_token = nil lock_file = "#{@gem_deps_file}.lock" @input = File.read lock_file s = StringScanner.new @input until s.eos? do pos = s.pos pos = s.pos if leading_whitespace = s.scan(/ +/) if s.scan(/[<|=>]{7}/) then message = "your #{lock_file} contains merge conflict markers" column, line = token_pos pos raise ParseError.new message, column, line, lock_file end @tokens << case when s.scan(/\r?\n/) then token = [:newline, nil, *token_pos(pos)] @line_pos = s.pos @line += 1 token when s.scan(/[A-Z]+/) then if leading_whitespace then text = s.matched text += s.scan(/[^\s)]*/).to_s # in case of no match [:text, text, *token_pos(pos)] else [:section, s.matched, *token_pos(pos)] end when s.scan(/([a-z]+):\s/) then s.pos -= 1 # rewind for possible newline [:entry, s[1], *token_pos(pos)] when s.scan(/\(/) then [:l_paren, nil, *token_pos(pos)] when s.scan(/\)/) then [:r_paren, nil, *token_pos(pos)] when s.scan(/<=|>=|=|~>|<|>|!=/) then [:requirement, s.matched, *token_pos(pos)] when s.scan(/,/) then [:comma, nil, *token_pos(pos)] when s.scan(/!/) then [:bang, nil, *token_pos(pos)] when s.scan(/[^\s),!]*/) then [:text, s.matched, *token_pos(pos)] else raise "BUG: can't create token for: #{s.string[s.pos..-1].inspect}" end end @tokens rescue Errno::ENOENT @tokens end ## # Ungets the last token retrieved by #get def unget # :nodoc: @tokens.unshift @current_token end ## # Writes the lock file alongside the gem dependencies file def write content = to_s open "#{@gem_deps_file}.lock", 'w' do |io| io.write content end end end PK!UU02.2.0/rubygems/request_set/gem_dependency_api.rbnu[## # A semi-compatible DSL for the Bundler Gemfile and Isolate gem dependencies # files. # # To work with both the Bundler Gemfile and Isolate formats this # implementation takes some liberties to allow compatibility with each, most # notably in #source. # # A basic gem dependencies file will look like the following: # # source 'https://rubygems.org' # # gem 'rails', '3.2.14a # gem 'devise', '~> 2.1', '>= 2.1.3' # gem 'cancan' # gem 'airbrake' # gem 'pg' # # RubyGems recommends saving this as gem.deps.rb over Gemfile or Isolate. # # To install the gems in this Gemfile use `gem install -g` to install it and # create a lockfile. The lockfile will ensure that when you make changes to # your gem dependencies file a minimum amount of change is made to the # dependencies of your gems. # # RubyGems can activate all the gems in your dependencies file at startup # using the RUBYGEMS_GEMDEPS environment variable or through Gem.use_gemdeps. # See Gem.use_gemdeps for details and warnings. # # See `gem help install` and `gem help gem_dependencies` for further details. class Gem::RequestSet::GemDependencyAPI ENGINE_MAP = { # :nodoc: :jruby => %w[jruby], :jruby_18 => %w[jruby], :jruby_19 => %w[jruby], :maglev => %w[maglev], :mri => %w[ruby], :mri_18 => %w[ruby], :mri_19 => %w[ruby], :mri_20 => %w[ruby], :mri_21 => %w[ruby], :rbx => %w[rbx], :ruby => %w[ruby rbx maglev], :ruby_18 => %w[ruby rbx maglev], :ruby_19 => %w[ruby rbx maglev], :ruby_20 => %w[ruby rbx maglev], :ruby_21 => %w[ruby rbx maglev], } mswin = Gem::Platform.new 'x86-mswin32' mswin64 = Gem::Platform.new 'x64-mswin64' x86_mingw = Gem::Platform.new 'x86-mingw32' x64_mingw = Gem::Platform.new 'x64-mingw32' PLATFORM_MAP = { # :nodoc: :jruby => Gem::Platform::RUBY, :jruby_18 => Gem::Platform::RUBY, :jruby_19 => Gem::Platform::RUBY, :maglev => Gem::Platform::RUBY, :mingw => x86_mingw, :mingw_18 => x86_mingw, :mingw_19 => x86_mingw, :mingw_20 => x86_mingw, :mingw_21 => x86_mingw, :mri => Gem::Platform::RUBY, :mri_18 => Gem::Platform::RUBY, :mri_19 => Gem::Platform::RUBY, :mri_20 => Gem::Platform::RUBY, :mri_21 => Gem::Platform::RUBY, :mswin => mswin, :mswin_18 => mswin, :mswin_19 => mswin, :mswin_20 => mswin, :mswin_21 => mswin, :mswin64 => mswin64, :mswin64_19 => mswin64, :mswin64_20 => mswin64, :mswin64_21 => mswin64, :rbx => Gem::Platform::RUBY, :ruby => Gem::Platform::RUBY, :ruby_18 => Gem::Platform::RUBY, :ruby_19 => Gem::Platform::RUBY, :ruby_20 => Gem::Platform::RUBY, :ruby_21 => Gem::Platform::RUBY, :x64_mingw => x64_mingw, :x64_mingw_20 => x64_mingw, :x64_mingw_21 => x64_mingw } gt_eq_0 = Gem::Requirement.new '>= 0' tilde_gt_1_8_0 = Gem::Requirement.new '~> 1.8.0' tilde_gt_1_9_0 = Gem::Requirement.new '~> 1.9.0' tilde_gt_2_0_0 = Gem::Requirement.new '~> 2.0.0' tilde_gt_2_1_0 = Gem::Requirement.new '~> 2.1.0' VERSION_MAP = { # :nodoc: :jruby => gt_eq_0, :jruby_18 => tilde_gt_1_8_0, :jruby_19 => tilde_gt_1_9_0, :maglev => gt_eq_0, :mingw => gt_eq_0, :mingw_18 => tilde_gt_1_8_0, :mingw_19 => tilde_gt_1_9_0, :mingw_20 => tilde_gt_2_0_0, :mingw_21 => tilde_gt_2_1_0, :mri => gt_eq_0, :mri_18 => tilde_gt_1_8_0, :mri_19 => tilde_gt_1_9_0, :mri_20 => tilde_gt_2_0_0, :mri_21 => tilde_gt_2_1_0, :mswin => gt_eq_0, :mswin_18 => tilde_gt_1_8_0, :mswin_19 => tilde_gt_1_9_0, :mswin_20 => tilde_gt_2_0_0, :mswin_21 => tilde_gt_2_1_0, :mswin64 => gt_eq_0, :mswin64_19 => tilde_gt_1_9_0, :mswin64_20 => tilde_gt_2_0_0, :mswin64_21 => tilde_gt_2_1_0, :rbx => gt_eq_0, :ruby => gt_eq_0, :ruby_18 => tilde_gt_1_8_0, :ruby_19 => tilde_gt_1_9_0, :ruby_20 => tilde_gt_2_0_0, :ruby_21 => tilde_gt_2_1_0, :x64_mingw => gt_eq_0, :x64_mingw_20 => tilde_gt_2_0_0, :x64_mingw_21 => tilde_gt_2_1_0, } WINDOWS = { # :nodoc: :mingw => :only, :mingw_18 => :only, :mingw_19 => :only, :mingw_20 => :only, :mingw_21 => :only, :mri => :never, :mri_18 => :never, :mri_19 => :never, :mri_20 => :never, :mri_21 => :never, :mswin => :only, :mswin_18 => :only, :mswin_19 => :only, :mswin_20 => :only, :mswin_21 => :only, :mswin64 => :only, :mswin64_19 => :only, :mswin64_20 => :only, :mswin64_21 => :only, :rbx => :never, :ruby => :never, :ruby_18 => :never, :ruby_19 => :never, :ruby_20 => :never, :ruby_21 => :never, :x64_mingw => :only, :x64_mingw_20 => :only, :x64_mingw_21 => :only, } ## # The gems required by #gem statements in the gem.deps.rb file attr_reader :dependencies ## # A set of gems that are loaded via the +:git+ option to #gem attr_reader :git_set # :nodoc: ## # A Hash containing gem names and files to require from those gems. attr_reader :requires # :nodoc: ## # A set of gems that are loaded via the +:path+ option to #gem attr_reader :vendor_set # :nodoc: ## # The groups of gems to exclude from installation attr_accessor :without_groups # :nodoc: ## # Creates a new GemDependencyAPI that will add dependencies to the # Gem::RequestSet +set+ based on the dependency API description in +path+. def initialize set, path @set = set @path = path @current_groups = nil @current_platforms = nil @current_repository = nil @dependencies = {} @default_sources = true @git_set = @set.git_set @git_sources = {} @installing = false @requires = Hash.new { |h, name| h[name] = [] } @vendor_set = @set.vendor_set @gem_sources = {} @without_groups = [] git_source :github do |repo_name| repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include? "/" "git://github.com/#{repo_name}.git" end git_source :bitbucket do |repo_name| repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include? "/" user, = repo_name.split "/", 2 "https://#{user}@bitbucket.org/#{repo_name}.git" end end ## # Adds +dependencies+ to the request set if any of the +groups+ are allowed. # This is used for gemspec dependencies. def add_dependencies groups, dependencies # :nodoc: return unless (groups & @without_groups).empty? dependencies.each do |dep| @set.gem dep.name, *dep.requirement end end private :add_dependencies ## # Finds a gemspec with the given +name+ that lives at +path+. def find_gemspec name, path # :nodoc: glob = File.join path, "#{name}.gemspec" spec_files = Dir[glob] case spec_files.length when 1 then spec_file = spec_files.first spec = Gem::Specification.load spec_file return spec if spec raise ArgumentError, "invalid gemspec #{spec_file}" when 0 then raise ArgumentError, "no gemspecs found at #{Dir.pwd}" else raise ArgumentError, "found multiple gemspecs at #{Dir.pwd}, " + "use the name: option to specify the one you want" end end ## # Changes the behavior of gem dependency file loading to installing mode. # In installing mode certain restrictions are ignored such as ruby version # mismatch checks. def installing= installing # :nodoc: @installing = installing end ## # Loads the gem dependency file and returns self. def load instance_eval File.read(@path).untaint, @path, 1 self end ## # :category: Gem Dependencies DSL # # :call-seq: # gem(name) # gem(name, *requirements) # gem(name, *requirements, options) # # Specifies a gem dependency with the given +name+ and +requirements+. You # may also supply +options+ following the +requirements+ # # +options+ include: # # require: :: # RubyGems does not provide any autorequire features so requires in a gem # dependencies file are recorded but ignored. # # In bundler the require: option overrides the file to require during # Bundler.require. By default the name of the dependency is required in # Bundler. A single file or an Array of files may be given. # # To disable requiring any file give +false+: # # gem 'rake', require: false # # group: :: # Place the dependencies in the given dependency group. A single group or # an Array of groups may be given. # # See also #group # # platform: :: # Only install the dependency on the given platform. A single platform or # an Array of platforms may be given. # # See #platform for a list of platforms available. # # path: :: # Install this dependency from an unpacked gem in the given directory. # # gem 'modified_gem', path: 'vendor/modified_gem' # # git: :: # Install this dependency from a git repository: # # gem 'private_gem', git: git@my.company.example:private_gem.git' # # gist: :: # Install this dependency from the gist ID: # # gem 'bang', gist: '1232884' # # github: :: # Install this dependency from a github git repository: # # gem 'private_gem', github: 'my_company/private_gem' # # submodules: :: # Set to +true+ to include submodules when fetching the git repository for # git:, gist: and github: dependencies. # # ref: :: # Use the given commit name or SHA for git:, gist: and github: # dependencies. # # branch: :: # Use the given branch for git:, gist: and github: dependencies. # # tag: :: # Use the given tag for git:, gist: and github: dependencies. def gem name, *requirements options = requirements.pop if requirements.last.kind_of?(Hash) options ||= {} options[:git] = @current_repository if @current_repository source_set = false source_set ||= gem_path name, options source_set ||= gem_git name, options source_set ||= gem_git_source name, options duplicate = @dependencies.include? name @dependencies[name] = if requirements.empty? and not source_set then nil elsif source_set then '!' else requirements end return unless gem_platforms options groups = gem_group name, options return unless (groups & @without_groups).empty? pin_gem_source name, :default unless source_set gem_requires name, options if duplicate then warn <<-WARNING Gem dependencies file #{@path} requires #{name} more than once. WARNING end @set.gem name, *requirements end ## # Handles the git: option from +options+ for gem +name+. # # Returns +true+ if the path option was handled. def gem_git name, options # :nodoc: if gist = options.delete(:gist) then options[:git] = "https://gist.github.com/#{gist}.git" end return unless repository = options.delete(:git) pin_gem_source name, :git, repository reference = nil reference ||= options.delete :ref reference ||= options.delete :branch reference ||= options.delete :tag reference ||= 'master' submodules = options.delete :submodules @git_set.add_git_gem name, repository, reference, submodules true end private :gem_git ## # Handles a git gem option from +options+ for gem +name+ for a git source # registered through git_source. # # Returns +true+ if the custom source option was handled. def gem_git_source name, options # :nodoc: return unless git_source = (@git_sources.keys & options.keys).last source_callback = @git_sources[git_source] source_param = options.delete git_source git_url = source_callback.call source_param options[:git] = git_url gem_git name, options true end private :gem_git_source ## # Handles the :group and :groups +options+ for the gem with the given # +name+. def gem_group name, options # :nodoc: g = options.delete :group all_groups = g ? Array(g) : [] groups = options.delete :groups all_groups |= groups if groups all_groups |= @current_groups if @current_groups all_groups end private :gem_group ## # Handles the path: option from +options+ for gem +name+. # # Returns +true+ if the path option was handled. def gem_path name, options # :nodoc: return unless directory = options.delete(:path) pin_gem_source name, :path, directory @vendor_set.add_vendor_gem name, directory true end private :gem_path ## # Handles the platforms: option from +options+. Returns true if the # platform matches the current platform. def gem_platforms options # :nodoc: platform_names = Array(options.delete :platform) platform_names.concat Array(options.delete :platforms) platform_names.concat @current_platforms if @current_platforms return true if platform_names.empty? platform_names.any? do |platform_name| raise ArgumentError, "unknown platform #{platform_name.inspect}" unless platform = PLATFORM_MAP[platform_name] next false unless Gem::Platform.match platform if engines = ENGINE_MAP[platform_name] then next false unless engines.include? Gem.ruby_engine end case WINDOWS[platform_name] when :only then next false unless Gem.win_platform? when :never then next false if Gem.win_platform? end VERSION_MAP[platform_name].satisfied_by? Gem.ruby_version end end private :gem_platforms ## # Records the require: option from +options+ and adds those files, or the # default file to the require list for +name+. def gem_requires name, options # :nodoc: if options.include? :require then if requires = options.delete(:require) then @requires[name].concat Array requires end else @requires[name] << name end end private :gem_requires ## # :category: Gem Dependencies DSL # # Block form for specifying gems from a git +repository+. # # git 'https://github.com/rails/rails.git' do # gem 'activesupport' # gem 'activerecord' # end def git repository @current_repository = repository yield ensure @current_repository = nil end ## # Defines a custom git source that uses +name+ to expand git repositories # for use in gems built from git repositories. You must provide a block # that accepts a git repository name for expansion. def git_source name, &callback @git_sources[name] = callback end ## # Returns the basename of the file the dependencies were loaded from def gem_deps_file # :nodoc: File.basename @path end ## # :category: Gem Dependencies DSL # # Loads dependencies from a gemspec file. # # +options+ include: # # name: :: # The name portion of the gemspec file. Defaults to searching for any # gemspec file in the current directory. # # gemspec name: 'my_gem' # # path: :: # The path the gemspec lives in. Defaults to the current directory: # # gemspec 'my_gem', path: 'gemspecs', name: 'my_gem' # # development_group: :: # The group to add development dependencies to. By default this is # :development. Only one group may be specified. def gemspec options = {} name = options.delete(:name) || '{,*}' path = options.delete(:path) || '.' development_group = options.delete(:development_group) || :development spec = find_gemspec name, path groups = gem_group spec.name, {} self_dep = Gem::Dependency.new spec.name, spec.version add_dependencies groups, [self_dep] add_dependencies groups, spec.runtime_dependencies @dependencies[spec.name] = '!' spec.dependencies.each do |dep| @dependencies[dep.name] = dep.requirement end groups << development_group add_dependencies groups, spec.development_dependencies gem_requires spec.name, options end ## # :category: Gem Dependencies DSL # # Block form for placing a dependency in the given +groups+. # # group :development do # gem 'debugger' # end # # group :development, :test do # gem 'minitest' # end # # Groups can be excluded at install time using `gem install -g --without # development`. See `gem help install` and `gem help gem_dependencies` for # further details. def group *groups @current_groups = groups yield ensure @current_groups = nil end ## # Pins the gem +name+ to the given +source+. Adding a gem with the same # name from a different +source+ will raise an exception. def pin_gem_source name, type = :default, source = nil source_description = case type when :default then '(default)' when :path then "path: #{source}" when :git then "git: #{source}" else '(unknown)' end raise ArgumentError, "duplicate source #{source_description} for gem #{name}" if @gem_sources.fetch(name, source) != source @gem_sources[name] = source end private :pin_gem_source ## # :category: Gem Dependencies DSL # # Block form for restricting gems to a set of platforms. # # The gem dependencies platform is different from Gem::Platform. A platform # gem.deps.rb platform matches on the ruby engine, the ruby version and # whether or not windows is allowed. # # :ruby, :ruby_XY :: # Matches non-windows, non-jruby implementations where X and Y can be used # to match releases in the 1.8, 1.9, 2.0 or 2.1 series. # # :mri, :mri_XY :: # Matches non-windows C Ruby (Matz Ruby) or only the 1.8, 1.9, 2.0 or # 2.1 series. # # :mingw, :mingw_XY :: # Matches 32 bit C Ruby on MinGW or only the 1.8, 1.9, 2.0 or 2.1 series. # # :x64_mingw, :x64_mingw_XY :: # Matches 64 bit C Ruby on MinGW or only the 1.8, 1.9, 2.0 or 2.1 series. # # :mswin, :mswin_XY :: # Matches 32 bit C Ruby on Microsoft Windows or only the 1.8, 1.9, 2.0 or # 2.1 series. # # :mswin64, :mswin64_XY :: # Matches 64 bit C Ruby on Microsoft Windows or only the 1.8, 1.9, 2.0 or # 2.1 series. # # :jruby, :jruby_XY :: # Matches JRuby or JRuby in 1.8 or 1.9 mode. # # :maglev :: # Matches Maglev # # :rbx :: # Matches non-windows Rubinius # # NOTE: There is inconsistency in what environment a platform matches. You # may need to read the source to know the exact details. def platform *platforms @current_platforms = platforms yield ensure @current_platforms = nil end ## # :category: Gem Dependencies DSL # # Block form for restricting gems to a particular set of platforms. See # #platform. alias :platforms :platform ## # :category: Gem Dependencies DSL # # Restricts this gem dependencies file to the given ruby +version+. # # You may also provide +engine:+ and +engine_version:+ options to restrict # this gem dependencies file to a particular ruby engine and its engine # version. This matching is performed by using the RUBY_ENGINE and # engine_specific VERSION constants. (For JRuby, JRUBY_VERSION). def ruby version, options = {} engine = options[:engine] engine_version = options[:engine_version] raise ArgumentError, 'you must specify engine_version along with the ruby engine' if engine and not engine_version return true if @installing unless RUBY_VERSION == version then message = "Your Ruby version is #{RUBY_VERSION}, " + "but your #{gem_deps_file} requires #{version}" raise Gem::RubyVersionMismatch, message end if engine and engine != Gem.ruby_engine then message = "Your ruby engine is #{Gem.ruby_engine}, " + "but your #{gem_deps_file} requires #{engine}" raise Gem::RubyVersionMismatch, message end if engine_version then my_engine_version = Object.const_get "#{Gem.ruby_engine.upcase}_VERSION" if engine_version != my_engine_version then message = "Your ruby engine version is #{Gem.ruby_engine} #{my_engine_version}, " + "but your #{gem_deps_file} requires #{engine} #{engine_version}" raise Gem::RubyVersionMismatch, message end end return true end ## # :category: Gem Dependencies DSL # # Sets +url+ as a source for gems for this dependency API. RubyGems uses # the default configured sources if no source was given. If a source is set # only that source is used. # # This method differs in behavior from Bundler: # # * The +:gemcutter+, # +:rubygems+ and +:rubyforge+ sources are not # supported as they are deprecated in bundler. # * The +prepend:+ option is not supported. If you wish to order sources # then list them in your preferred order. def source url Gem.sources.clear if @default_sources @default_sources = false Gem.sources << url end # TODO: remove this typo name at RubyGems 3.0 Gem::RequestSet::GemDepedencyAPI = self # :nodoc: end PK!8 2.2.0/rubygems/source.rbnu[require 'uri' require 'fileutils' ## # A Source knows how to list and fetch gems from a RubyGems marshal index. # # There are other Source subclasses for installed gems, local gems, the # bundler dependency API and so-forth. class Gem::Source include Comparable FILES = { # :nodoc: :released => 'specs', :latest => 'latest_specs', :prerelease => 'prerelease_specs', } ## # The URI this source will fetch gems from. attr_reader :uri ## # Creates a new Source which will use the index located at +uri+. def initialize(uri) begin unless uri.kind_of? URI uri = URI.parse(uri.to_s) end rescue URI::InvalidURIError raise if Gem::Source == self.class end @uri = uri @api_uri = nil end ## # Use an SRV record on the host to look up the true endpoint for the index. def api_uri # :nodoc: require 'rubygems/remote_fetcher' @api_uri ||= Gem::RemoteFetcher.fetcher.api_endpoint uri end ## # Sources are ordered by installation preference. def <=>(other) case other when Gem::Source::Installed, Gem::Source::Local, Gem::Source::Lock, Gem::Source::SpecificFile, Gem::Source::Git, Gem::Source::Vendor then -1 when Gem::Source then if !@uri return 0 unless other.uri return 1 end return -1 if !other.uri @uri.to_s <=> other.uri.to_s else nil end end def == other # :nodoc: self.class === other and @uri == other.uri end alias_method :eql?, :== # :nodoc: ## # Returns a Set that can fetch specifications from this source. def dependency_resolver_set # :nodoc: return Gem::Resolver::IndexSet.new self if 'file' == api_uri.scheme bundler_api_uri = api_uri + './api/v1/dependencies' begin fetcher = Gem::RemoteFetcher.fetcher response = fetcher.fetch_path bundler_api_uri, nil, true rescue Gem::RemoteFetcher::FetchError Gem::Resolver::IndexSet.new self else if response.respond_to? :uri then Gem::Resolver::APISet.new response.uri else Gem::Resolver::APISet.new bundler_api_uri end end end def hash # :nodoc: @uri.hash end ## # Returns the local directory to write +uri+ to. def cache_dir(uri) # Correct for windows paths escaped_path = uri.path.sub(/^\/([a-z]):\//i, '/\\1-/') escaped_path.untaint File.join Gem.spec_cache_dir, "#{uri.host}%#{uri.port}", File.dirname(escaped_path) end ## # Returns true when it is possible and safe to update the cache directory. def update_cache? @update_cache ||= begin File.stat(Gem.user_home).uid == Process.uid rescue Errno::ENOENT false end end ## # Fetches a specification for the given +name_tuple+. def fetch_spec name_tuple fetcher = Gem::RemoteFetcher.fetcher spec_file_name = name_tuple.spec_name uri = api_uri + "#{Gem::MARSHAL_SPEC_DIR}#{spec_file_name}" cache_dir = cache_dir uri local_spec = File.join cache_dir, spec_file_name if File.exist? local_spec then spec = Gem.read_binary local_spec spec = Marshal.load(spec) rescue nil return spec if spec end uri.path << '.rz' spec = fetcher.fetch_path uri spec = Gem.inflate spec if update_cache? then FileUtils.mkdir_p cache_dir open local_spec, 'wb' do |io| io.write spec end end # TODO: Investigate setting Gem::Specification#loaded_from to a URI Marshal.load spec end ## # Loads +type+ kind of specs fetching from +@uri+ if the on-disk cache is # out of date. # # +type+ is one of the following: # # :released => Return the list of all released specs # :latest => Return the list of only the highest version of each gem # :prerelease => Return the list of all prerelease only specs # def load_specs(type) file = FILES[type] fetcher = Gem::RemoteFetcher.fetcher file_name = "#{file}.#{Gem.marshal_version}" spec_path = api_uri + "#{file_name}.gz" cache_dir = cache_dir spec_path local_file = File.join(cache_dir, file_name) retried = false FileUtils.mkdir_p cache_dir if update_cache? spec_dump = fetcher.cache_update_path spec_path, local_file, update_cache? begin Gem::NameTuple.from_list Marshal.load(spec_dump) rescue ArgumentError if update_cache? && !retried FileUtils.rm local_file retried = true retry else raise Gem::Exception.new("Invalid spec cache file in #{local_file}") end end end ## # Downloads +spec+ and writes it to +dir+. See also # Gem::RemoteFetcher#download. def download(spec, dir=Dir.pwd) fetcher = Gem::RemoteFetcher.fetcher fetcher.download spec, api_uri.to_s, dir end def pretty_print q # :nodoc: q.group 2, '[Remote:', ']' do q.breakable q.text @uri.to_s if api = api_uri q.breakable q.text 'API URI: ' q.text api.to_s end end end end require 'rubygems/source/git' require 'rubygems/source/installed' require 'rubygems/source/specific_file' require 'rubygems/source/local' require 'rubygems/source/lock' require 'rubygems/source/vendor' PK!O 2.2.0/rubygems/source_list.rbnu[require 'rubygems/source' ## # The SourceList represents the sources rubygems has been configured to use. # A source may be created from an array of sources: # # Gem::SourceList.from %w[https://rubygems.example https://internal.example] # # Or by adding them: # # sources = Gem::SourceList.new # sources.add 'https://rubygems.example' # # The most common way to get a SourceList is Gem.sources. class Gem::SourceList include Enumerable ## # Creates a new SourceList def initialize @sources = [] end ## # The sources in this list attr_reader :sources ## # Creates a new SourceList from an array of sources. def self.from(ary) list = new list.replace ary return list end def initialize_copy(other) # :nodoc: @sources = @sources.dup end ## # Appends +obj+ to the source list which may be a Gem::Source, URI or URI # String. def <<(obj) src = case obj when URI Gem::Source.new(obj) when Gem::Source obj else Gem::Source.new(URI.parse(obj)) end @sources << src src end ## # Replaces this SourceList with the sources in +other+ See #<< for # acceptable items in +other+. def replace(other) clear other.each do |x| self << x end self end ## # Removes all sources from the SourceList. def clear @sources.clear end ## # Yields each source URI in the list. def each @sources.each { |s| yield s.uri.to_s } end ## # Yields each source in the list. def each_source(&b) @sources.each(&b) end ## # Returns true if there are no sources in this SourceList. def empty? @sources.empty? end def == other # :nodoc: to_a == other end ## # Returns an Array of source URI Strings. def to_a @sources.map { |x| x.uri.to_s } end alias_method :to_ary, :to_a ## # Returns the first source in the list. def first @sources.first end ## # Returns true if this source list includes +other+ which may be a # Gem::Source or a source URI. def include?(other) if other.kind_of? Gem::Source @sources.include? other else @sources.find { |x| x.uri.to_s == other.to_s } end end ## # Deletes +source+ from the source list which may be a Gem::Source or a URI. def delete source if source.kind_of? Gem::Source @sources.delete source else @sources.delete_if { |x| x.uri.to_s == source.to_s } end end end PK!m?d5d52.2.0/rubygems/resolver.rbnu[require 'rubygems/dependency' require 'rubygems/exceptions' require 'rubygems/util/list' require 'uri' require 'net/http' ## # Given a set of Gem::Dependency objects as +needed+ and a way to query the # set of available specs via +set+, calculates a set of ActivationRequest # objects which indicate all the specs that should be activated to meet the # all the requirements. class Gem::Resolver ## # If the DEBUG_RESOLVER environment variable is set then debugging mode is # enabled for the resolver. This will display information about the state # of the resolver while a set of dependencies is being resolved. DEBUG_RESOLVER = !ENV['DEBUG_RESOLVER'].nil? require 'pp' if DEBUG_RESOLVER ## # Contains all the conflicts encountered while doing resolution attr_reader :conflicts ## # Set to true if all development dependencies should be considered. attr_accessor :development ## # Set to true if immediate development dependencies should be considered. attr_accessor :development_shallow ## # When true, no dependencies are looked up for requested gems. attr_accessor :ignore_dependencies ## # List of dependencies that could not be found in the configured sources. attr_reader :missing attr_reader :stats ## # Hash of gems to skip resolution. Keyed by gem name, with arrays of # gem specifications as values. attr_accessor :skip_gems ## # When a missing dependency, don't stop. Just go on and record what was # missing. attr_accessor :soft_missing ## # Combines +sets+ into a ComposedSet that allows specification lookup in a # uniform manner. If one of the +sets+ is itself a ComposedSet its sets are # flattened into the result ComposedSet. def self.compose_sets *sets sets.compact! sets = sets.map do |set| case set when Gem::Resolver::BestSet then set when Gem::Resolver::ComposedSet then set.sets else set end end.flatten case sets.length when 0 then raise ArgumentError, 'one set in the composition must be non-nil' when 1 then sets.first else Gem::Resolver::ComposedSet.new(*sets) end end ## # Creates a Resolver that queries only against the already installed gems # for the +needed+ dependencies. def self.for_current_gems needed new needed, Gem::Resolver::CurrentSet.new end ## # Create Resolver object which will resolve the tree starting # with +needed+ Dependency objects. # # +set+ is an object that provides where to look for specifications to # satisfy the Dependencies. This defaults to IndexSet, which will query # rubygems.org. def initialize needed, set = nil @set = set || Gem::Resolver::IndexSet.new @needed = needed @conflicts = [] @development = false @development_shallow = false @ignore_dependencies = false @missing = [] @skip_gems = {} @soft_missing = false @stats = Gem::Resolver::Stats.new end def explain stage, *data # :nodoc: return unless DEBUG_RESOLVER d = data.map { |x| x.pretty_inspect }.join(", ") $stderr.printf "%10s %s\n", stage.to_s.upcase, d end def explain_list stage # :nodoc: return unless DEBUG_RESOLVER data = yield $stderr.printf "%10s (%d entries)\n", stage.to_s.upcase, data.size PP.pp data, $stderr unless data.empty? end ## # Creates an ActivationRequest for the given +dep+ and the last +possible+ # specification. # # Returns the Specification and the ActivationRequest def activation_request dep, possible # :nodoc: spec = possible.pop explain :activate, [spec.full_name, possible.size] explain :possible, possible activation_request = Gem::Resolver::ActivationRequest.new spec, dep, possible return spec, activation_request end def requests s, act, reqs=nil # :nodoc: return reqs if @ignore_dependencies s.fetch_development_dependencies if @development s.dependencies.reverse_each do |d| next if d.type == :development and not @development next if d.type == :development and @development_shallow and act.development? next if d.type == :development and @development_shallow and act.parent reqs.add Gem::Resolver::DependencyRequest.new(d, act) @stats.requirement! end @set.prefetch reqs @stats.record_requirements reqs reqs end ## # Proceed with resolution! Returns an array of ActivationRequest objects. def resolve @conflicts = [] needed = Gem::Resolver::RequirementList.new @needed.reverse_each do |n| request = Gem::Resolver::DependencyRequest.new n, nil needed.add request @stats.requirement! end @stats.record_requirements needed res = resolve_for needed, nil raise Gem::DependencyResolutionError, res if res.kind_of? Gem::Resolver::Conflict res.to_a end ## # Extracts the specifications that may be able to fulfill +dependency+ and # returns those that match the local platform and all those that match. def find_possible dependency # :nodoc: all = @set.find_all dependency if (skip_dep_gems = skip_gems[dependency.name]) && !skip_dep_gems.empty? matching = all.select do |api_spec| skip_dep_gems.any? { |s| api_spec.version == s.version } end all = matching unless matching.empty? end matching_platform = select_local_platforms all return matching_platform, all end def handle_conflict(dep, existing) # :nodoc: # There is a conflict! We return the conflict object which will be seen by # the caller and be handled at the right level. # If the existing activation indicates that there are other possibles for # it, then issue the conflict on the dependency for the activation itself. # Otherwise, if there was a requester, issue it on the requester's # request itself. # Finally, if the existing request has no requester (toplevel) unwind to # it anyway. if existing.others_possible? conflict = Gem::Resolver::Conflict.new dep, existing elsif dep.requester depreq = dep.requester.request conflict = Gem::Resolver::Conflict.new depreq, existing, dep elsif existing.request.requester.nil? conflict = Gem::Resolver::Conflict.new dep, existing else raise Gem::DependencyError, "Unable to figure out how to unwind conflict" end @conflicts << conflict unless @conflicts.include? conflict return conflict end # Contains the state for attempting activation of a set of possible specs. # +needed+ is a Gem::List of DependencyRequest objects that, well, need # to be satisfied. # +specs+ is the List of ActivationRequest that are being tested. # +dep+ is the DependencyRequest that was used to generate this state. # +spec+ is the Specification for this state. # +possible+ is List of DependencyRequest objects that can be tried to # find a complete set. # +conflicts+ is a [DependencyRequest, Conflict] hit tried to # activate the state. # State = Struct.new(:needed, :specs, :dep, :spec, :possibles, :conflicts) do def summary # :nodoc: nd = needed.map { |s| s.to_s }.sort if nd if specs then ss = specs.map { |s| s.full_name }.sort ss.unshift ss.length end d = dep.to_s d << " from #{dep.requester.full_name}" if dep.requester ps = possibles.map { |p| p.full_name }.sort ps.unshift ps.length cs = conflicts.map do |(s, c)| [s.full_name, c.conflicting_dependencies.map { |cd| cd.to_s }] end { :needed => nd, :specs => ss, :dep => d, :spec => spec.full_name, :possibles => ps, :conflicts => cs } end end ## # The meat of the algorithm. Given +needed+ DependencyRequest objects and # +specs+ being a list to ActivationRequest, calculate a new list of # ActivationRequest objects. def resolve_for needed, specs # :nodoc: # The State objects that are used to attempt the activation tree. states = [] while !needed.empty? @stats.iteration! dep = needed.remove explain :try, [dep, dep.requester ? dep.requester.request : :toplevel] explain_list(:next5) { needed.next5 } explain_list(:specs) { Array(specs).map { |x| x.full_name }.sort } # If there is already a spec activated for the requested name... if specs && existing = specs.find { |s| dep.name == s.name } # then we're done since this new dep matches the existing spec. next if dep.matches_spec? existing conflict = handle_conflict dep, existing return conflict unless dep.requester explain :conflict, dep, :existing, existing.full_name depreq = dep.requester.request state = nil until states.empty? x = states.pop i = existing.request.requester explain :consider, x.spec.full_name, [depreq.name, dep.name, i ? i.name : :top] if x.spec.name == depreq.name or x.spec.name == dep.name or (i && (i.name == x.spec.name)) explain :found, x.spec.full_name state = x break end end return conflict unless state @stats.backtracking! needed, specs = resolve_for_conflict needed, specs, state states << state unless state.possibles.empty? next end matching, all = find_possible dep case matching.size when 0 resolve_for_zero dep, all when 1 needed, specs = resolve_for_single needed, specs, dep, matching else needed, specs = resolve_for_multiple needed, specs, states, dep, matching end end specs end ## # Rewinds +needed+ and +specs+ to a previous state in +state+ for a conflict # between +dep+ and +existing+. def resolve_for_conflict needed, specs, state # :nodoc: # We exhausted the possibles so it's definitely not going to work out, # bail out. raise Gem::ImpossibleDependenciesError.new state.dep, state.conflicts if state.possibles.empty? # Retry resolution with this spec and add it's dependencies spec, act = activation_request state.dep, state.possibles needed = requests spec, act, state.needed.dup specs = Gem::List.prepend state.specs, act return needed, specs end ## # There are multiple +possible+ specifications for this +dep+. Updates # +needed+, +specs+ and +states+ for further resolution of the +possible+ # choices. def resolve_for_multiple needed, specs, states, dep, possible # :nodoc: # Sort them so that we try the highest versions first. possible = possible.sort_by do |s| [s.source, s.version, s.platform == Gem::Platform::RUBY ? -1 : 1] end spec, act = activation_request dep, possible # We may need to try all of +possible+, so we setup state to unwind back # to current +needed+ and +specs+ so we can try another. This is code is # what makes conflict resolution possible. states << State.new(needed.dup, specs, dep, spec, possible, []) @stats.record_depth states explain :states, states.map { |s| s.dep } needed = requests spec, act, needed specs = Gem::List.prepend specs, act return needed, specs end ## # Add the spec from the +possible+ list to +specs+ and process the spec's # dependencies by adding them to +needed+. def resolve_for_single needed, specs, dep, possible # :nodoc: spec, act = activation_request dep, possible specs = Gem::List.prepend specs, act # Put the deps for at the beginning of needed # rather than the end to match the depth first # searching done by the multiple case code below. # # This keeps the error messages consistent. needed = requests spec, act, needed return needed, specs end ## # When there are no possible specifications for +dep+ our work is done. def resolve_for_zero dep, platform_mismatch # :nodoc: @missing << dep unless @soft_missing exc = Gem::UnsatisfiableDependencyError.new dep, platform_mismatch exc.errors = @set.errors raise exc end end ## # Returns the gems in +specs+ that match the local platform. def select_local_platforms specs # :nodoc: specs.select do |spec| Gem::Platform.installable? spec end end end ## # TODO remove in RubyGems 3 Gem::DependencyResolver = Gem::Resolver # :nodoc: require 'rubygems/resolver/activation_request' require 'rubygems/resolver/conflict' require 'rubygems/resolver/dependency_request' require 'rubygems/resolver/requirement_list' require 'rubygems/resolver/stats' require 'rubygems/resolver/set' require 'rubygems/resolver/api_set' require 'rubygems/resolver/composed_set' require 'rubygems/resolver/best_set' require 'rubygems/resolver/current_set' require 'rubygems/resolver/git_set' require 'rubygems/resolver/index_set' require 'rubygems/resolver/installer_set' require 'rubygems/resolver/lock_set' require 'rubygems/resolver/vendor_set' require 'rubygems/resolver/specification' require 'rubygems/resolver/spec_specification' require 'rubygems/resolver/api_specification' require 'rubygems/resolver/git_specification' require 'rubygems/resolver/index_specification' require 'rubygems/resolver/installed_specification' require 'rubygems/resolver/local_specification' require 'rubygems/resolver/lock_specification' require 'rubygems/resolver/vendor_specification' PK!L_)2.2.0/rubygems/core_ext/kernel_require.rbnu[#-- # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. # All rights reserved. # See LICENSE.txt for permissions. #++ require 'monitor' module Kernel RUBYGEMS_ACTIVATION_MONITOR = Monitor.new # :nodoc: if defined?(gem_original_require) then # Ruby ships with a custom_require, override its require remove_method :require else ## # The Kernel#require from before RubyGems was loaded. alias gem_original_require require private :gem_original_require end ## # When RubyGems is required, Kernel#require is replaced with our own which # is capable of loading gems on demand. # # When you call require 'x', this is what happens: # * If the file can be loaded from the existing Ruby loadpath, it # is. # * Otherwise, installed gems are searched for a file that matches. # If it's found in gem 'y', that gem is activated (added to the # loadpath). # # The normal require functionality of returning false if # that file has already been loaded is preserved. def require path RUBYGEMS_ACTIVATION_MONITOR.enter path = path.to_path if path.respond_to? :to_path spec = Gem.find_unresolved_default_spec(path) if spec Gem.remove_unresolved_default_spec(spec) gem(spec.name) end # If there are no unresolved deps, then we can use just try # normal require handle loading a gem from the rescue below. if Gem::Specification.unresolved_deps.empty? then RUBYGEMS_ACTIVATION_MONITOR.exit return gem_original_require(path) end # If +path+ is for a gem that has already been loaded, don't # bother trying to find it in an unresolved gem, just go straight # to normal require. #-- # TODO request access to the C implementation of this to speed up RubyGems spec = Gem::Specification.stubs.find { |s| s.activated? and s.contains_requirable_file? path } begin RUBYGEMS_ACTIVATION_MONITOR.exit return gem_original_require(spec.to_fullpath(path) || path) end if spec # Attempt to find +path+ in any unresolved gems... found_specs = Gem::Specification.find_in_unresolved path # If there are no directly unresolved gems, then try and find +path+ # in any gems that are available via the currently unresolved gems. # For example, given: # # a => b => c => d # # If a and b are currently active with c being unresolved and d.rb is # requested, then find_in_unresolved_tree will find d.rb in d because # it's a dependency of c. # if found_specs.empty? then found_specs = Gem::Specification.find_in_unresolved_tree path found_specs.each do |found_spec| found_spec.activate end # We found +path+ directly in an unresolved gem. Now we figure out, of # the possible found specs, which one we should activate. else # Check that all the found specs are just different # versions of the same gem names = found_specs.map(&:name).uniq if names.size > 1 then RUBYGEMS_ACTIVATION_MONITOR.exit raise Gem::LoadError, "#{path} found in multiple gems: #{names.join ', '}" end # Ok, now find a gem that has no conflicts, starting # at the highest version. valid = found_specs.select { |s| s.conflicts.empty? }.last unless valid then le = Gem::LoadError.new "unable to find a version of '#{names.first}' to activate" le.name = names.first RUBYGEMS_ACTIVATION_MONITOR.exit raise le end valid.activate end RUBYGEMS_ACTIVATION_MONITOR.exit return gem_original_require(path) rescue LoadError => load_error RUBYGEMS_ACTIVATION_MONITOR.enter if load_error.message.start_with?("Could not find") or (load_error.message.end_with?(path) and Gem.try_activate(path)) then RUBYGEMS_ACTIVATION_MONITOR.exit return gem_original_require(path) else RUBYGEMS_ACTIVATION_MONITOR.exit end raise load_error end private :require end PK!gפ1 %2.2.0/rubygems/core_ext/kernel_gem.rbnu[## # RubyGems adds the #gem method to allow activation of specific gem versions # and overrides the #require method on Kernel to make gems appear as if they # live on the $LOAD_PATH. See the documentation of these methods # for further detail. module Kernel # REFACTOR: This should be pulled out into some kind of hacks file. remove_method :gem if 'method' == defined? gem # from gem_prelude.rb on 1.9 ## # Use Kernel#gem to activate a specific version of +gem_name+. # # +requirements+ is a list of version requirements that the # specified gem must match, most commonly "= example.version.number". See # Gem::Requirement for how to specify a version requirement. # # If you will be activating the latest version of a gem, there is no need to # call Kernel#gem, Kernel#require will do the right thing for you. # # Kernel#gem returns true if the gem was activated, otherwise false. If the # gem could not be found, didn't match the version requirements, or a # different version was already activated, an exception will be raised. # # Kernel#gem should be called *before* any require statements (otherwise # RubyGems may load a conflicting library version). # # Kernel#gem only loads prerelease versions when prerelease +requirements+ # are given: # # gem 'rake', '>= 1.1.a', '< 2' # # In older RubyGems versions, the environment variable GEM_SKIP could be # used to skip activation of specified gems, for example to test out changes # that haven't been installed yet. Now RubyGems defers to -I and the # RUBYLIB environment variable to skip activation of a gem. # # Example: # # GEM_SKIP=libA:libB ruby -I../libA -I../libB ./mycode.rb def gem(gem_name, *requirements) # :doc: skip_list = (ENV['GEM_SKIP'] || "").split(/:/) raise Gem::LoadError, "skipping #{gem_name}" if skip_list.include? gem_name if gem_name.kind_of? Gem::Dependency unless Gem::Deprecate.skip warn "#{Gem.location_of_caller.join ':'}:Warning: Kernel.gem no longer "\ "accepts a Gem::Dependency object, please pass the name "\ "and requirements directly" end requirements = gem_name.requirement gem_name = gem_name.name end dep = Gem::Dependency.new(gem_name, *requirements) loaded = Gem.loaded_specs[gem_name] return false if loaded && dep.matches_spec?(loaded) spec = dep.to_spec Gem::LOADED_SPECS_MUTEX.synchronize { spec.activate } if spec end private :gem end PK! p&2.2.0/rubygems/source/specific_file.rbnu[## # A source representing a single .gem file. This is used for installation of # local gems. class Gem::Source::SpecificFile < Gem::Source ## # The path to the gem for this specific file. attr_reader :path ## # Creates a new SpecificFile for the gem in +file+ def initialize(file) @uri = nil @path = ::File.expand_path(file) @package = Gem::Package.new @path @spec = @package.spec @name = @spec.name_tuple end ## # The Gem::Specification extracted from this .gem. attr_reader :spec def load_specs *a # :nodoc: [@name] end def fetch_spec name # :nodoc: return @spec if name == @name raise Gem::Exception, "Unable to find '#{name}'" @spec end def download spec, dir = nil # :nodoc: return @path if spec == @spec raise Gem::Exception, "Unable to download '#{spec.full_name}'" end def pretty_print q # :nodoc: q.group 2, '[SpecificFile:', ']' do q.breakable q.text @path end end ## # Orders this source against +other+. # # If +other+ is a SpecificFile from a different gem name +nil+ is returned. # # If +other+ is a SpecificFile from the same gem name the versions are # compared using Gem::Version#<=> # # Otherwise Gem::Source#<=> is used. def <=> other case other when Gem::Source::SpecificFile then return nil if @spec.name != other.spec.name @spec.version <=> other.spec.version else super end end end PK!̻2.2.0/rubygems/source/git.rbnu[require 'digest' require 'rubygems/util' ## # A git gem for use in a gem dependencies file. # # Example: # # source = # Gem::Source::Git.new 'rake', 'git@example:rake.git', 'rake-10.1.0', false # # source.specs class Gem::Source::Git < Gem::Source ## # The name of the gem created by this git gem. attr_reader :name ## # The commit reference used for checking out this git gem. attr_reader :reference ## # When false the cache for this repository will not be updated. attr_accessor :remote ## # The git repository this gem is sourced from. attr_reader :repository ## # The directory for cache and git gem installation attr_accessor :root_dir ## # Does this repository need submodules checked out too? attr_reader :need_submodules ## # Creates a new git gem source for a gems from loaded from +repository+ at # the given +reference+. The +name+ is only used to track the repository # back to a gem dependencies file, it has no real significance as a git # repository may contain multiple gems. If +submodules+ is true, submodules # will be checked out when the gem is installed. def initialize name, repository, reference, submodules = false super repository @name = name @repository = repository @reference = reference @need_submodules = submodules @remote = true @root_dir = Gem.dir @git = ENV['git'] || 'git' end def <=> other case other when Gem::Source::Git then 0 when Gem::Source::Vendor, Gem::Source::Lock then -1 when Gem::Source then 1 else nil end end def == other # :nodoc: super and @name == other.name and @repository == other.repository and @reference == other.reference and @need_submodules == other.need_submodules end ## # Checks out the files for the repository into the install_dir. def checkout # :nodoc: cache return false unless File.exist? repo_cache_dir unless File.exist? install_dir then system @git, 'clone', '--quiet', '--no-checkout', repo_cache_dir, install_dir end Dir.chdir install_dir do system @git, 'fetch', '--quiet', '--force', '--tags', install_dir success = system @git, 'reset', '--quiet', '--hard', rev_parse success &&= Gem::Util.silent_system @git, 'submodule', 'update', '--quiet', '--init', '--recursive' if @need_submodules success end end ## # Creates a local cache repository for the git gem. def cache # :nodoc: return unless @remote if File.exist? repo_cache_dir then Dir.chdir repo_cache_dir do system @git, 'fetch', '--quiet', '--force', '--tags', @repository, 'refs/heads/*:refs/heads/*' end else system @git, 'clone', '--quiet', '--bare', '--no-hardlinks', @repository, repo_cache_dir end end ## # Directory where git gems get unpacked and so-forth. def base_dir # :nodoc: File.join @root_dir, 'bundler' end ## # A short reference for use in git gem directories def dir_shortref # :nodoc: rev_parse[0..11] end ## # Nothing to download for git gems def download full_spec, path # :nodoc: end ## # The directory where the git gem will be installed. def install_dir # :nodoc: return unless File.exist? repo_cache_dir File.join base_dir, 'gems', "#{@name}-#{dir_shortref}" end def pretty_print q # :nodoc: q.group 2, '[Git: ', ']' do q.breakable q.text @repository q.breakable q.text @reference end end ## # The directory where the git gem's repository will be cached. def repo_cache_dir # :nodoc: File.join @root_dir, 'cache', 'bundler', 'git', "#{@name}-#{uri_hash}" end ## # Converts the git reference for the repository into a commit hash. def rev_parse # :nodoc: hash = nil Dir.chdir repo_cache_dir do hash = Gem::Util.popen(@git, 'rev-parse', @reference).strip end raise Gem::Exception, "unable to find reference #{@reference} in #{@repository}" unless $?.success? hash end ## # Loads all gemspecs in the repository def specs checkout return [] unless install_dir Dir.chdir install_dir do Dir['{,*,*/*}.gemspec'].map do |spec_file| directory = File.dirname spec_file file = File.basename spec_file Dir.chdir directory do spec = Gem::Specification.load file if spec then spec.base_dir = base_dir spec.extension_dir = File.join base_dir, 'extensions', Gem::Platform.local.to_s, Gem.extension_api_version, "#{name}-#{dir_shortref}" spec.full_gem_path = File.dirname spec.loaded_from if spec end spec end end.compact end end ## # A hash for the git gem based on the git repository URI. def uri_hash # :nodoc: normalized = if @repository =~ %r%^\w+://(\w+@)?% then uri = URI(@repository).normalize.to_s.sub %r%/$%,'' uri.sub(/\A(\w+)/) { $1.downcase } else @repository end Digest::SHA1.hexdigest normalized end end PK!Zk k 2.2.0/rubygems/source/local.rbnu[## # The local source finds gems in the current directory for fulfilling # dependencies. class Gem::Source::Local < Gem::Source def initialize # :nodoc: @specs = nil @api_uri = nil @uri = nil end ## # Local sorts before Gem::Source and after Gem::Source::Installed def <=> other case other when Gem::Source::Installed, Gem::Source::Lock then -1 when Gem::Source::Local then 0 when Gem::Source then 1 else nil end end def inspect # :nodoc: keys = @specs ? @specs.keys.sort : 'NOT LOADED' "#<%s specs: %p>" % [self.class, keys] end def load_specs type # :nodoc: names = [] @specs = {} Dir["*.gem"].each do |file| begin pkg = Gem::Package.new(file) rescue SystemCallError, Gem::Package::FormatError # ignore else tup = pkg.spec.name_tuple @specs[tup] = [File.expand_path(file), pkg] case type when :released unless pkg.spec.version.prerelease? names << pkg.spec.name_tuple end when :prerelease if pkg.spec.version.prerelease? names << pkg.spec.name_tuple end when :latest tup = pkg.spec.name_tuple cur = names.find { |x| x.name == tup.name } if !cur names << tup elsif cur.version < tup.version names.delete cur names << tup end else names << pkg.spec.name_tuple end end end names end def find_gem gem_name, version = Gem::Requirement.default, # :nodoc: prerelease = false load_specs :complete found = [] @specs.each do |n, data| if n.name == gem_name s = data[1].spec if version.satisfied_by?(s.version) if prerelease found << s elsif !s.version.prerelease? found << s end end end end found.max_by { |s| s.version } end def fetch_spec name # :nodoc: load_specs :complete if data = @specs[name] data.last.spec else raise Gem::Exception, "Unable to find spec for #{name.inspect}" end end def download spec, cache_dir = nil # :nodoc: load_specs :complete @specs.each do |name, data| return data[0] if data[1].spec == spec end raise Gem::Exception, "Unable to find file for '#{spec.full_name}'" end def pretty_print q # :nodoc: q.group 2, '[Local gems:', ']' do q.breakable q.seplist @specs.keys do |v| q.text v.full_name end end end end PK!2.2.0/rubygems/source/vendor.rbnu[## # This represents a vendored source that is similar to an installed gem. class Gem::Source::Vendor < Gem::Source::Installed ## # Creates a new Vendor source for a gem that was unpacked at +path+. def initialize path @uri = path end def <=> other case other when Gem::Source::Lock then -1 when Gem::Source::Vendor then 0 when Gem::Source then 1 else nil end end end PK!02ww"2.2.0/rubygems/source/installed.rbnu[## # Represents an installed gem. This is used for dependency resolution. class Gem::Source::Installed < Gem::Source def initialize # :nodoc: @uri = nil end ## # Installed sources sort before all other sources def <=> other case other when Gem::Source::Git, Gem::Source::Lock, Gem::Source::Vendor then -1 when Gem::Source::Installed then 0 when Gem::Source then 1 else nil end end ## # We don't need to download an installed gem def download spec, path nil end def pretty_print q # :nodoc: q.text '[Installed]' end end PK!ʥ MM2.2.0/rubygems/source/lock.rbnu[## # A Lock source wraps an installed gem's source and sorts before other sources # during dependency resolution. This allows RubyGems to prefer gems from # dependency lock files. class Gem::Source::Lock < Gem::Source ## # The wrapped Gem::Source attr_reader :wrapped ## # Creates a new Lock source that wraps +source+ and moves it earlier in the # sort list. def initialize source @wrapped = source end def <=> other # :nodoc: case other when Gem::Source::Lock then @wrapped <=> other.wrapped when Gem::Source then 1 else nil end end def == other # :nodoc: 0 == (self <=> other) end ## # Delegates to the wrapped source's fetch_spec method. def fetch_spec name_tuple @wrapped.fetch_spec name_tuple end def uri # :nodoc: @wrapped.uri end end PK!mlK2K22.2.0/rubygems/config_file.rbnu[#-- # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. # All rights reserved. # See LICENSE.txt for permissions. #++ require 'rubygems/user_interaction' require 'rbconfig' ## # Gem::ConfigFile RubyGems options and gem command options from gemrc. # # gemrc is a YAML file that uses strings to match gem command arguments and # symbols to match RubyGems options. # # Gem command arguments use a String key that matches the command name and # allow you to specify default arguments: # # install: --no-rdoc --no-ri # update: --no-rdoc --no-ri # # You can use gem: to set default arguments for all commands. # # RubyGems options use symbol keys. Valid options are: # # +:backtrace+:: See #backtrace # +:sources+:: Sets Gem::sources # +:verbose+:: See #verbose # # gemrc files may exist in various locations and are read and merged in # the following order: # # - system wide (/etc/gemrc) # - per user (~/.gemrc) # - per environment (gemrc files listed in the GEMRC environment variable) class Gem::ConfigFile include Gem::UserInteraction DEFAULT_BACKTRACE = false DEFAULT_BULK_THRESHOLD = 1000 DEFAULT_VERBOSITY = true DEFAULT_UPDATE_SOURCES = true ## # For Ruby packagers to set configuration defaults. Set in # rubygems/defaults/operating_system.rb OPERATING_SYSTEM_DEFAULTS = {} ## # For Ruby implementers to set configuration defaults. Set in # rubygems/defaults/#{RUBY_ENGINE}.rb PLATFORM_DEFAULTS = {} # :stopdoc: SYSTEM_CONFIG_PATH = begin require "etc" Etc.sysconfdir rescue LoadError, NoMethodError begin # TODO: remove after we drop 1.8.7 and 1.9.1 require 'Win32API' CSIDL_COMMON_APPDATA = 0x0023 path = 0.chr * 260 if RUBY_VERSION > '1.9' then SHGetFolderPath = Win32API.new 'shell32', 'SHGetFolderPath', 'PLPLP', 'L', :stdcall SHGetFolderPath.call nil, CSIDL_COMMON_APPDATA, nil, 1, path else SHGetFolderPath = Win32API.new 'shell32', 'SHGetFolderPath', 'LLLLP', 'L' SHGetFolderPath.call 0, CSIDL_COMMON_APPDATA, 0, 1, path end path.strip rescue LoadError RbConfig::CONFIG["sysconfdir"] || "/etc" end end # :startdoc: SYSTEM_WIDE_CONFIG_FILE = File.join SYSTEM_CONFIG_PATH, 'gemrc' ## # List of arguments supplied to the config file object. attr_reader :args ## # Where to look for gems (deprecated) attr_accessor :path ## # Where to install gems (deprecated) attr_accessor :home ## # True if we print backtraces on errors. attr_writer :backtrace ## # Bulk threshold value. If the number of missing gems are above this # threshold value, then a bulk download technique is used. (deprecated) attr_accessor :bulk_threshold ## # Verbose level of output: # * false -- No output # * true -- Normal output # * :loud -- Extra output attr_accessor :verbose ## # True if we want to update the SourceInfoCache every time, false otherwise attr_accessor :update_sources ## # True if we want to force specification of gem server when pushing a gem attr_accessor :disable_default_gem_server # openssl verify mode value, used for remote https connection attr_reader :ssl_verify_mode ## # Path name of directory or file of openssl CA certificate, used for remote # https connection attr_accessor :ssl_ca_cert ## # Path name of directory or file of openssl client certificate, used for remote https connection with client authentication attr_reader :ssl_client_cert ## # Create the config file object. +args+ is the list of arguments # from the command line. # # The following command line options are handled early here rather # than later at the time most command options are processed. # # --config-file, --config-file==NAME:: # Obviously these need to be handled by the ConfigFile object to ensure we # get the right config file. # # --backtrace:: # Backtrace needs to be turned on early so that errors before normal # option parsing can be properly handled. # # --debug:: # Enable Ruby level debug messages. Handled early for the same reason as # --backtrace. #-- # TODO: parse options upstream, pass in options directly def initialize(args) @config_file_name = nil need_config_file_name = false arg_list = [] args.each do |arg| if need_config_file_name then @config_file_name = arg need_config_file_name = false elsif arg =~ /^--config-file=(.*)/ then @config_file_name = $1 elsif arg =~ /^--config-file$/ then need_config_file_name = true else arg_list << arg end end @backtrace = DEFAULT_BACKTRACE @bulk_threshold = DEFAULT_BULK_THRESHOLD @verbose = DEFAULT_VERBOSITY @update_sources = DEFAULT_UPDATE_SOURCES operating_system_config = Marshal.load Marshal.dump(OPERATING_SYSTEM_DEFAULTS) platform_config = Marshal.load Marshal.dump(PLATFORM_DEFAULTS) system_config = load_file SYSTEM_WIDE_CONFIG_FILE user_config = load_file config_file_name.dup.untaint environment_config = (ENV['GEMRC'] || '').split(/[:;]/).inject({}) do |result, file| result.merge load_file file end @hash = operating_system_config.merge platform_config @hash = @hash.merge system_config @hash = @hash.merge user_config @hash = @hash.merge environment_config # HACK these override command-line args, which is bad @backtrace = @hash[:backtrace] if @hash.key? :backtrace @bulk_threshold = @hash[:bulk_threshold] if @hash.key? :bulk_threshold @home = @hash[:gemhome] if @hash.key? :gemhome @path = @hash[:gempath] if @hash.key? :gempath @update_sources = @hash[:update_sources] if @hash.key? :update_sources @verbose = @hash[:verbose] if @hash.key? :verbose @disable_default_gem_server = @hash[:disable_default_gem_server] if @hash.key? :disable_default_gem_server @ssl_verify_mode = @hash[:ssl_verify_mode] if @hash.key? :ssl_verify_mode @ssl_ca_cert = @hash[:ssl_ca_cert] if @hash.key? :ssl_ca_cert @ssl_client_cert = @hash[:ssl_client_cert] if @hash.key? :ssl_client_cert @api_keys = nil @rubygems_api_key = nil Gem.sources = @hash[:sources] if @hash.key? :sources handle_arguments arg_list end ## # Hash of RubyGems.org and alternate API keys def api_keys load_api_keys unless @api_keys @api_keys end ## # Checks the permissions of the credentials file. If they are not 0600 an # error message is displayed and RubyGems aborts. def check_credentials_permissions return if Gem.win_platform? # windows doesn't write 0600 as 0600 return unless File.exist? credentials_path existing_permissions = File.stat(credentials_path).mode & 0777 return if existing_permissions == 0600 alert_error <<-ERROR Your gem push credentials file located at: \t#{credentials_path} has file permissions of 0#{existing_permissions.to_s 8} but 0600 is required. To fix this error run: \tchmod 0600 #{credentials_path} You should reset your credentials at: \thttps://rubygems.org/profile/edit if you believe they were disclosed to a third party. ERROR terminate_interaction 1 end ## # Location of RubyGems.org credentials def credentials_path File.join Gem.user_home, '.gem', 'credentials' end def load_api_keys check_credentials_permissions @api_keys = if File.exist? credentials_path then load_file(credentials_path) else @hash end if @api_keys.key? :rubygems_api_key then @rubygems_api_key = @api_keys[:rubygems_api_key] @api_keys[:rubygems] = @api_keys.delete :rubygems_api_key unless @api_keys.key? :rubygems end end ## # Returns the RubyGems.org API key def rubygems_api_key load_api_keys unless @rubygems_api_key @rubygems_api_key end ## # Sets the RubyGems.org API key to +api_key+ def rubygems_api_key= api_key check_credentials_permissions config = load_file(credentials_path).merge(:rubygems_api_key => api_key) dirname = File.dirname credentials_path Dir.mkdir(dirname) unless File.exist? dirname Gem.load_yaml permissions = 0600 & (~File.umask) File.open(credentials_path, 'w', permissions) do |f| f.write config.to_yaml end @rubygems_api_key = api_key end YAMLErrors = [ArgumentError] YAMLErrors << Psych::SyntaxError if defined?(Psych::SyntaxError) def load_file(filename) Gem.load_yaml return {} unless filename and File.exist? filename begin content = Gem::SafeYAML.load(File.read(filename)) unless content.kind_of? Hash warn "Failed to load #{filename} because it doesn't contain valid YAML hash" return {} end return content rescue *YAMLErrors => e warn "Failed to load #{filename}, #{e}" rescue Errno::EACCES warn "Failed to load #{filename} due to permissions problem." end {} end # True if the backtrace option has been specified, or debug is on. def backtrace @backtrace or $DEBUG end # The name of the configuration file. def config_file_name @config_file_name || Gem.config_file end # Delegates to @hash def each(&block) hash = @hash.dup hash.delete :update_sources hash.delete :verbose hash.delete :backtrace hash.delete :bulk_threshold yield :update_sources, @update_sources yield :verbose, @verbose yield :backtrace, @backtrace yield :bulk_threshold, @bulk_threshold yield 'config_file_name', @config_file_name if @config_file_name hash.each(&block) end # Handle the command arguments. def handle_arguments(arg_list) @args = [] arg_list.each do |arg| case arg when /^--(backtrace|traceback)$/ then @backtrace = true when /^--debug$/ then $DEBUG = true warn 'NOTE: Debugging mode prints all exceptions even when rescued' else @args << arg end end end # Really verbose mode gives you extra output. def really_verbose case verbose when true, false, nil then false else true end end # to_yaml only overwrites things you can't override on the command line. def to_yaml # :nodoc: yaml_hash = {} yaml_hash[:backtrace] = if @hash.key?(:backtrace) @hash[:backtrace] else DEFAULT_BACKTRACE end yaml_hash[:bulk_threshold] = if @hash.key?(:bulk_threshold) @hash[:bulk_threshold] else DEFAULT_BULK_THRESHOLD end yaml_hash[:sources] = Gem.sources.to_a yaml_hash[:update_sources] = if @hash.key?(:update_sources) @hash[:update_sources] else DEFAULT_UPDATE_SOURCES end yaml_hash[:verbose] = if @hash.key?(:verbose) @hash[:verbose] else DEFAULT_VERBOSITY end yaml_hash[:ssl_verify_mode] = @hash[:ssl_verify_mode] if @hash.key? :ssl_verify_mode yaml_hash[:ssl_ca_cert] = @hash[:ssl_ca_cert] if @hash.key? :ssl_ca_cert yaml_hash[:ssl_client_cert] = @hash[:ssl_client_cert] if @hash.key? :ssl_client_cert keys = yaml_hash.keys.map { |key| key.to_s } keys << 'debug' re = Regexp.union(*keys) @hash.each do |key, value| key = key.to_s next if key =~ re yaml_hash[key.to_s] = value end yaml_hash.to_yaml end # Writes out this config file, replacing its source. def write open config_file_name, 'w' do |io| io.write to_yaml end end # Return the configuration information for +key+. def [](key) @hash[key.to_s] end # Set configuration option +key+ to +value+. def []=(key, value) @hash[key.to_s] = value end def ==(other) # :nodoc: self.class === other and @backtrace == other.backtrace and @bulk_threshold == other.bulk_threshold and @verbose == other.verbose and @update_sources == other.update_sources and @hash == other.hash end attr_reader :hash protected :hash end PK!%2.2.0/rubygems/installer_test_case.rbnu[require 'rubygems/test_case' require 'rubygems/installer' class Gem::Installer ## # Available through requiring rubygems/installer_test_case attr_writer :bin_dir ## # Available through requiring rubygems/installer_test_case attr_writer :build_args ## # Available through requiring rubygems/installer_test_case attr_writer :gem_dir ## # Available through requiring rubygems/installer_test_case attr_writer :force ## # Available through requiring rubygems/installer_test_case attr_writer :format ## # Available through requiring rubygems/installer_test_case attr_writer :gem_home ## # Available through requiring rubygems/installer_test_case attr_writer :env_shebang ## # Available through requiring rubygems/installer_test_case attr_writer :ignore_dependencies ## # Available through requiring rubygems/installer_test_case attr_writer :format_executable ## # Available through requiring rubygems/installer_test_case attr_writer :security_policy ## # Available through requiring rubygems/installer_test_case attr_writer :wrappers end ## # A test case for Gem::Installer. class Gem::InstallerTestCase < Gem::TestCase ## # Creates the following instance variables: # # @spec:: # a spec named 'a', intended for regular installs # @user_spec:: # a spec named 'b', intended for user installs # @gem:: # the path to a built gem from @spec # @user_spec:: # the path to a built gem from @user_spec # # @installer:: # a Gem::Installer for the @spec that installs into @gemhome # @user_installer:: # a Gem::Installer for the @user_spec that installs into Gem.user_dir def setup super @spec = quick_gem 'a' do |spec| util_make_exec spec end @user_spec = quick_gem 'b' do |spec| util_make_exec spec end util_build_gem @spec util_build_gem @user_spec @gem = @spec.cache_file @user_gem = @user_spec.cache_file @installer = util_installer @spec, @gemhome @user_installer = util_installer @user_spec, Gem.user_dir, :user Gem::Installer.path_warning = false end def util_gem_bindir spec = @spec # :nodoc: # TODO: deprecate spec.bin_dir end def util_gem_dir spec = @spec # :nodoc: # TODO: deprecate spec.gem_dir end ## # The path where installed executables live def util_inst_bindir File.join @gemhome, "bin" end ## # Adds an executable named "executable" to +spec+ with the given +shebang+. # # The executable is also written to the bin dir in @tmpdir and the installed # gem directory for +spec+. def util_make_exec(spec = @spec, shebang = "#!/usr/bin/ruby") spec.executables = %w[executable] spec.files << 'bin/executable' exec_path = spec.bin_file "executable" write_file exec_path do |io| io.puts shebang end bin_path = File.join @tempdir, "bin", "executable" write_file bin_path do |io| io.puts shebang end end ## # Builds the @spec gem and returns an installer for it. The built gem # includes: # # bin/executable # lib/code.rb # ext/a/mkrf_conf.rb def util_setup_gem(ui = @ui) # HACK fix use_ui to make this automatic @spec.files << File.join('lib', 'code.rb') @spec.extensions << File.join('ext', 'a', 'mkrf_conf.rb') Dir.chdir @tempdir do FileUtils.mkdir_p 'bin' FileUtils.mkdir_p 'lib' FileUtils.mkdir_p File.join('ext', 'a') File.open File.join('bin', 'executable'), 'w' do |f| f.puts "raise 'ran executable'" end File.open File.join('lib', 'code.rb'), 'w' do |f| f.puts '1' end File.open File.join('ext', 'a', 'mkrf_conf.rb'), 'w' do |f| f << <<-EOF File.open 'Rakefile', 'w' do |rf| rf.puts "task :default" end EOF end use_ui ui do FileUtils.rm_f @gem @gem = Gem::Package.build @spec end end @installer = Gem::Installer.new @gem end ## # Creates an installer for +spec+ that will install into +gem_home+. If # +user+ is true a user-install will be performed. def util_installer(spec, gem_home, user=false) Gem::Installer.new(spec.cache_file, :install_dir => gem_home, :user_install => user) end end PK!)N],], 2.2.0/rubygems/remote_fetcher.rbnu[require 'rubygems' require 'rubygems/request' require 'rubygems/uri_formatter' require 'rubygems/user_interaction' require 'rubygems/request/connection_pools' require 'resolv' ## # RemoteFetcher handles the details of fetching gems and gem information from # a remote source. class Gem::RemoteFetcher include Gem::UserInteraction ## # A FetchError exception wraps up the various possible IO and HTTP failures # that could happen while downloading from the internet. class FetchError < Gem::Exception ## # The URI which was being accessed when the exception happened. attr_accessor :uri def initialize(message, uri) super message @uri = uri end def to_s # :nodoc: "#{super} (#{uri})" end end ## # A FetchError that indicates that the reason for not being # able to fetch data was that the host could not be contacted class UnknownHostError < FetchError end @fetcher = nil ## # Cached RemoteFetcher instance. def self.fetcher @fetcher ||= self.new Gem.configuration[:http_proxy] end ## # Initialize a remote fetcher using the source URI and possible proxy # information. # # +proxy+ # * [String]: explicit specification of proxy; overrides any environment # variable setting # * nil: respect environment variables (HTTP_PROXY, HTTP_PROXY_USER, # HTTP_PROXY_PASS) # * :no_proxy: ignore environment variables and _don't_ use a proxy # # +dns+: An object to use for DNS resolution of the API endpoint. # By default, use Resolv::DNS. def initialize(proxy=nil, dns=Resolv::DNS.new) require 'net/http' require 'stringio' require 'time' require 'uri' Socket.do_not_reverse_lookup = true @proxy = proxy @pools = {} @pool_lock = Mutex.new @cert_files = Gem::Request.get_cert_files @dns = dns end ## # Given a source at +uri+, calculate what hostname to actually # connect to query the data for it. def api_endpoint(uri) host = uri.host begin res = @dns.getresource "_rubygems._tcp.#{host}", Resolv::DNS::Resource::IN::SRV rescue Resolv::ResolvError uri else target = res.target.to_s.strip if URI("http://" + target).host.end_with?(".#{host}") return URI.parse "#{uri.scheme}://#{target}#{uri.path}" end uri end end ## # Given a name and requirement, downloads this gem into cache and returns the # filename. Returns nil if the gem cannot be located. #-- # Should probably be integrated with #download below, but that will be a # larger, more emcompassing effort. -erikh def download_to_cache dependency found, _ = Gem::SpecFetcher.fetcher.spec_for_dependency dependency return if found.empty? spec, source = found.max_by { |(s,_)| s.version } download spec, source.uri.to_s end ## # Moves the gem +spec+ from +source_uri+ to the cache dir unless it is # already there. If the source_uri is local the gem cache dir copy is # always replaced. def download(spec, source_uri, install_dir = Gem.dir) cache_dir = if Dir.pwd == install_dir then # see fetch_command install_dir elsif File.writable? install_dir then File.join install_dir, "cache" else File.join Gem.user_dir, "cache" end gem_file_name = File.basename spec.cache_file local_gem_path = File.join cache_dir, gem_file_name FileUtils.mkdir_p cache_dir rescue nil unless File.exist? cache_dir # Always escape URI's to deal with potential spaces and such # It should also be considered that source_uri may already be # a valid URI with escaped characters. e.g. "{DESede}" is encoded # as "%7BDESede%7D". If this is escaped again the percentage # symbols will be escaped. unless source_uri.is_a?(URI::Generic) begin source_uri = URI.parse(source_uri) rescue source_uri = URI.parse(URI.const_defined?(:DEFAULT_PARSER) ? URI::DEFAULT_PARSER.escape(source_uri.to_s) : URI.escape(source_uri.to_s)) end end scheme = source_uri.scheme # URI.parse gets confused by MS Windows paths with forward slashes. scheme = nil if scheme =~ /^[a-z]$/i # REFACTOR: split this up and dispatch on scheme (eg download_http) # REFACTOR: be sure to clean up fake fetcher when you do this... cleaner case scheme when 'http', 'https', 's3' then unless File.exist? local_gem_path then begin verbose "Downloading gem #{gem_file_name}" remote_gem_path = source_uri + "gems/#{gem_file_name}" self.cache_update_path remote_gem_path, local_gem_path rescue Gem::RemoteFetcher::FetchError raise if spec.original_platform == spec.platform alternate_name = "#{spec.original_name}.gem" verbose "Failed, downloading gem #{alternate_name}" remote_gem_path = source_uri + "gems/#{alternate_name}" self.cache_update_path remote_gem_path, local_gem_path end end when 'file' then begin path = source_uri.path path = File.dirname(path) if File.extname(path) == '.gem' remote_gem_path = correct_for_windows_path(File.join(path, 'gems', gem_file_name)) FileUtils.cp(remote_gem_path, local_gem_path) rescue Errno::EACCES local_gem_path = source_uri.to_s end verbose "Using local gem #{local_gem_path}" when nil then # TODO test for local overriding cache source_path = if Gem.win_platform? && source_uri.scheme && !source_uri.path.include?(':') then "#{source_uri.scheme}:#{source_uri.path}" else source_uri.path end source_path = Gem::UriFormatter.new(source_path).unescape begin FileUtils.cp source_path, local_gem_path unless File.identical?(source_path, local_gem_path) rescue Errno::EACCES local_gem_path = source_uri.to_s end verbose "Using local gem #{local_gem_path}" else raise ArgumentError, "unsupported URI scheme #{source_uri.scheme}" end local_gem_path end ## # File Fetcher. Dispatched by +fetch_path+. Use it instead. def fetch_file uri, *_ Gem.read_binary correct_for_windows_path uri.path end ## # HTTP Fetcher. Dispatched by +fetch_path+. Use it instead. def fetch_http uri, last_modified = nil, head = false, depth = 0 fetch_type = head ? Net::HTTP::Head : Net::HTTP::Get response = request uri, fetch_type, last_modified case response when Net::HTTPOK, Net::HTTPNotModified then response.uri = uri if response.respond_to? :uri head ? response : response.body when Net::HTTPMovedPermanently, Net::HTTPFound, Net::HTTPSeeOther, Net::HTTPTemporaryRedirect then raise FetchError.new('too many redirects', uri) if depth > 10 location = URI.parse response['Location'] if https?(uri) && !https?(location) raise FetchError.new("redirecting to non-https resource: #{location}", uri) end fetch_http(location, last_modified, head, depth + 1) else raise FetchError.new("bad response #{response.message} #{response.code}", uri) end end alias :fetch_https :fetch_http ## # Downloads +uri+ and returns it as a String. def fetch_path(uri, mtime = nil, head = false) uri = URI.parse uri unless URI::Generic === uri raise ArgumentError, "bad uri: #{uri}" unless uri unless uri.scheme raise ArgumentError, "uri scheme is invalid: #{uri.scheme.inspect}" end data = send "fetch_#{uri.scheme}", uri, mtime, head if data and !head and uri.to_s =~ /\.gz$/ begin data = Gem.gunzip data rescue Zlib::GzipFile::Error raise FetchError.new("server did not return a valid file", uri.to_s) end end data rescue FetchError raise rescue Timeout::Error raise UnknownHostError.new('timed out', uri.to_s) rescue IOError, SocketError, SystemCallError => e if e.message =~ /getaddrinfo/ raise UnknownHostError.new('no such name', uri.to_s) else raise FetchError.new("#{e.class}: #{e}", uri.to_s) end end def fetch_s3(uri, mtime = nil, head = false) public_uri = sign_s3_url(uri) fetch_https public_uri, mtime, head end ## # Downloads +uri+ to +path+ if necessary. If no path is given, it just # passes the data. def cache_update_path uri, path = nil, update = true mtime = path && File.stat(path).mtime rescue nil data = fetch_path(uri, mtime) if data == nil # indicates the server returned 304 Not Modified return Gem.read_binary(path) end if update and path open(path, 'wb') do |io| io.flock(File::LOCK_EX) io.write data end end data end ## # Returns the size of +uri+ in bytes. def fetch_size(uri) # TODO: phase this out response = fetch_path(uri, nil, true) response['content-length'].to_i end def correct_for_windows_path(path) if path[0].chr == '/' && path[1].chr =~ /[a-z]/i && path[2].chr == ':' path[1..-1] else path end end ## # Performs a Net::HTTP request of type +request_class+ on +uri+ returning # a Net::HTTP response object. request maintains a table of persistent # connections to reduce connect overhead. def request(uri, request_class, last_modified = nil) proxy = proxy_for @proxy, uri pool = pools_for(proxy).pool_for uri request = Gem::Request.new uri, request_class, last_modified, pool request.fetch do |req| yield req if block_given? end end def https?(uri) uri.scheme.downcase == 'https' end def close_all @pools.each_value {|pool| pool.close_all} end protected # we have our own signing code here to avoid a dependency on the aws-sdk gem # fortunately, a simple GET request isn't too complex to sign properly def sign_s3_url(uri, expiration = nil) require 'base64' require 'openssl' unless uri.user && uri.password raise FetchError.new("credentials needed in s3 source, like s3://key:secret@bucket-name/", uri.to_s) end expiration ||= s3_expiration canonical_path = "/#{uri.host}#{uri.path}" payload = "GET\n\n\n#{expiration}\n#{canonical_path}" digest = OpenSSL::HMAC.digest('sha1', uri.password, payload) # URI.escape is deprecated, and there isn't yet a replacement that does quite what we want signature = Base64.encode64(digest).gsub("\n", '').gsub(/[\+\/=]/) { |c| BASE64_URI_TRANSLATE[c] } URI.parse("https://#{uri.host}.s3.amazonaws.com#{uri.path}?AWSAccessKeyId=#{uri.user}&Expires=#{expiration}&Signature=#{signature}") end def s3_expiration (Time.now + 3600).to_i # one hour from now end BASE64_URI_TRANSLATE = { '+' => '%2B', '/' => '%2F', '=' => '%3D' }.freeze private def proxy_for proxy, uri Gem::Request.proxy_uri(proxy || Gem::Request.get_proxy_from_env(uri.scheme)) end def pools_for proxy @pool_lock.synchronize do @pools[proxy] ||= Gem::Request::ConnectionPools.new proxy, @cert_files end end end PK!w2.2.0/rubygems/requirement.rbnu[require "rubygems/version" require "rubygems/deprecate" # If we're being loaded after yaml was already required, then # load our yaml + workarounds now. Gem.load_yaml if defined? ::YAML ## # A Requirement is a set of one or more version restrictions. It supports a # few (=, !=, >, <, >=, <=, ~>) different restriction operators. # # See Gem::Version for a description on how versions and requirements work # together in RubyGems. class Gem::Requirement OPS = { #:nodoc: "=" => lambda { |v, r| v == r }, "!=" => lambda { |v, r| v != r }, ">" => lambda { |v, r| v > r }, "<" => lambda { |v, r| v < r }, ">=" => lambda { |v, r| v >= r }, "<=" => lambda { |v, r| v <= r }, "~>" => lambda { |v, r| v >= r && v.release < r.bump } } quoted = OPS.keys.map { |k| Regexp.quote k }.join "|" PATTERN_RAW = "\\s*(#{quoted})?\\s*(#{Gem::Version::VERSION_PATTERN})\\s*" # :nodoc: ## # A regular expression that matches a requirement PATTERN = /\A#{PATTERN_RAW}\z/ ## # The default requirement matches any version DefaultRequirement = [">=", Gem::Version.new(0)] ## # Raised when a bad requirement is encountered class BadRequirementError < ArgumentError; end ## # Factory method to create a Gem::Requirement object. Input may be # a Version, a String, or nil. Intended to simplify client code. # # If the input is "weird", the default version requirement is # returned. def self.create input case input when Gem::Requirement then input when Gem::Version, Array then new input else if input.respond_to? :to_str then new [input.to_str] else default end end end ## # A default "version requirement" can surely _only_ be '>= 0'. def self.default new '>= 0' end ## # Parse +obj+, returning an [op, version] pair. +obj+ can # be a String or a Gem::Version. # # If +obj+ is a String, it can be either a full requirement # specification, like ">= 1.2", or a simple version number, # like "1.2". # # parse("> 1.0") # => [">", "1.0"] # parse("1.0") # => ["=", "1.0"] # parse(Gem::Version.new("1.0")) # => ["=, "1.0"] def self.parse obj return ["=", obj] if Gem::Version === obj unless PATTERN =~ obj.to_s raise BadRequirementError, "Illformed requirement [#{obj.inspect}]" end if $1 == ">=" && $2 == "0" DefaultRequirement else [$1 || "=", Gem::Version.new($2)] end end ## # An array of requirement pairs. The first element of the pair is # the op, and the second is the Gem::Version. attr_reader :requirements #:nodoc: ## # Constructs a requirement from +requirements+. Requirements can be # Strings, Gem::Versions, or Arrays of those. +nil+ and duplicate # requirements are ignored. An empty set of +requirements+ is the # same as ">= 0". def initialize *requirements requirements = requirements.flatten requirements.compact! requirements.uniq! if requirements.empty? @requirements = [DefaultRequirement] else @requirements = requirements.map! { |r| self.class.parse r } end end ## # Concatenates the +new+ requirements onto this requirement. def concat new new = new.flatten new.compact! new.uniq! new = new.map { |r| self.class.parse r } @requirements.concat new end ## # Formats this requirement for use in a Gem::RequestSet::Lockfile. def for_lockfile # :nodoc: return if [DefaultRequirement] == @requirements list = requirements.sort_by { |_, version| version }.map { |op, version| "#{op} #{version}" }.uniq " (#{list.join ', '})" end ## # true if this gem has no requirements. def none? if @requirements.size == 1 @requirements[0] == DefaultRequirement else false end end ## # true if the requirement is for only an exact version def exact? return false unless @requirements.size == 1 @requirements[0][0] == "=" end def as_list # :nodoc: requirements.map { |op, version| "#{op} #{version}" }.sort end def hash # :nodoc: requirements.hash end def marshal_dump # :nodoc: fix_syck_default_key_in_requirements [@requirements] end def marshal_load array # :nodoc: @requirements = array[0] fix_syck_default_key_in_requirements end def yaml_initialize(tag, vals) # :nodoc: vals.each do |ivar, val| instance_variable_set "@#{ivar}", val end Gem.load_yaml fix_syck_default_key_in_requirements end def init_with coder # :nodoc: yaml_initialize coder.tag, coder.map end def to_yaml_properties # :nodoc: ["@requirements"] end def encode_with coder # :nodoc: coder.add 'requirements', @requirements end ## # A requirement is a prerelease if any of the versions inside of it # are prereleases def prerelease? requirements.any? { |r| r.last.prerelease? } end def pretty_print q # :nodoc: q.group 1, 'Gem::Requirement.new(', ')' do q.pp as_list end end ## # True if +version+ satisfies this Requirement. def satisfied_by? version raise ArgumentError, "Need a Gem::Version: #{version.inspect}" unless Gem::Version === version # #28965: syck has a bug with unquoted '=' YAML.loading as YAML::DefaultKey requirements.all? { |op, rv| (OPS[op] || OPS["="]).call version, rv } end alias :=== :satisfied_by? alias :=~ :satisfied_by? ## # True if the requirement will not always match the latest version. def specific? return true if @requirements.length > 1 # GIGO, > 1, > 2 is silly not %w[> >=].include? @requirements.first.first # grab the operator end def to_s # :nodoc: as_list.join ", " end def == other # :nodoc: Gem::Requirement === other and to_s == other.to_s end private def fix_syck_default_key_in_requirements # :nodoc: Gem.load_yaml # Fixup the Syck DefaultKey bug @requirements.each do |r| if r[0].kind_of? Gem::SyckDefaultKey r[0] = "=" end end end end class Gem::Version # This is needed for compatibility with older yaml # gemspecs. Requirement = Gem::Requirement # :nodoc: end PK!HG2.2.0/rubygems/rdoc.rbnu[require 'rubygems' require 'rubygems/user_interaction' require 'fileutils' begin gem 'rdoc' rescue Gem::LoadError # swallow else # This will force any deps that 'rdoc' might have # (such as json) that are ambiguous to be activated, which # is important because we end up using Specification.reset # and we don't want the warning it pops out. Gem.finish_resolve end loaded_hook = false begin require 'rdoc/rubygems_hook' loaded_hook = true module Gem RDoc = RDoc::RubygemsHook end rescue LoadError end ## # Gem::RDoc provides methods to generate RDoc and ri data for installed gems. # It works for RDoc 1.0.1 (in Ruby 1.8) up to RDoc 3.6. # # This implementation is considered obsolete. The RDoc project is the # appropriate location to find this functionality. This file provides the # hooks to load RDoc generation code from the "rdoc" gem and a fallback in # case the installed version of RDoc does not have them. class Gem::RDoc # :nodoc: all include Gem::UserInteraction extend Gem::UserInteraction @rdoc_version = nil @specs = [] ## # Force installation of documentation? attr_accessor :force ## # Generate rdoc? attr_accessor :generate_rdoc ## # Generate ri data? attr_accessor :generate_ri class << self ## # Loaded version of RDoc. Set by ::load_rdoc attr_reader :rdoc_version end ## # Post installs hook that generates documentation for each specification in # +specs+ def self.generation_hook installer, specs start = Time.now types = installer.document generate_rdoc = types.include? 'rdoc' generate_ri = types.include? 'ri' specs.each do |spec| new(spec, generate_rdoc, generate_ri).generate end return unless generate_rdoc or generate_ri duration = (Time.now - start).to_i names = specs.map(&:name).join ', ' say "Done installing documentation for #{names} after #{duration} seconds" end ## # Loads the RDoc generator def self.load_rdoc return if @rdoc_version require 'rdoc/rdoc' @rdoc_version = if ::RDoc.const_defined? :VERSION then Gem::Version.new ::RDoc::VERSION else Gem::Version.new '1.0.1' end rescue LoadError => e raise Gem::DocumentError, "RDoc is not installed: #{e}" end ## # Creates a new documentation generator for +spec+. RDoc and ri data # generation can be enabled or disabled through +generate_rdoc+ and # +generate_ri+ respectively. # # Only +generate_ri+ is enabled by default. def initialize spec, generate_rdoc = true, generate_ri = true @doc_dir = spec.doc_dir @file_info = nil @force = false @rdoc = nil @spec = spec @generate_rdoc = generate_rdoc @generate_ri = generate_ri @rdoc_dir = spec.doc_dir 'rdoc' @ri_dir = spec.doc_dir 'ri' end ## # Removes legacy rdoc arguments from +args+ #-- # TODO move to RDoc::Options def delete_legacy_args args args.delete '--inline-source' args.delete '--promiscuous' args.delete '-p' args.delete '--one-file' end ## # Generates documentation using the named +generator+ ("darkfish" or "ri") # and following the given +options+. # # Documentation will be generated into +destination+ def document generator, options, destination generator_name = generator options = options.dup options.exclude ||= [] # TODO maybe move to RDoc::Options#finish options.setup_generator generator options.op_dir = destination options.finish generator = options.generator.new @rdoc.store, options @rdoc.options = options @rdoc.generator = generator say "Installing #{generator_name} documentation for #{@spec.full_name}" FileUtils.mkdir_p options.op_dir Dir.chdir options.op_dir do begin @rdoc.class.current = @rdoc @rdoc.generator.generate @file_info ensure @rdoc.class.current = nil end end end ## # Generates RDoc and ri data def generate return unless @generate_ri or @generate_rdoc setup options = nil if Gem::Requirement.new('< 3').satisfied_by? self.class.rdoc_version then generate_legacy return end ::RDoc::TopLevel.reset # TODO ::RDoc::RDoc.reset ::RDoc::Parser::C.reset args = @spec.rdoc_options args.concat @spec.source_paths args.concat @spec.extra_rdoc_files case config_args = Gem.configuration[:rdoc] when String then args = args.concat config_args.split when Array then args = args.concat config_args end delete_legacy_args args Dir.chdir @spec.full_gem_path do options = ::RDoc::Options.new options.default_title = "#{@spec.full_name} Documentation" options.parse args end options.quiet = !Gem.configuration.really_verbose @rdoc = new_rdoc @rdoc.options = options say "Parsing documentation for #{@spec.full_name}" Dir.chdir @spec.full_gem_path do @file_info = @rdoc.parse_files options.files end document 'ri', options, @ri_dir if @generate_ri and (@force or not File.exist? @ri_dir) document 'darkfish', options, @rdoc_dir if @generate_rdoc and (@force or not File.exist? @rdoc_dir) end ## # Generates RDoc and ri data for legacy RDoc versions. This method will not # exist in future versions. def generate_legacy if @generate_rdoc then FileUtils.rm_rf @rdoc_dir say "Installing RDoc documentation for #{@spec.full_name}" legacy_rdoc '--op', @rdoc_dir end if @generate_ri then FileUtils.rm_rf @ri_dir say "Installing ri documentation for #{@spec.full_name}" legacy_rdoc '--ri', '--op', @ri_dir end end ## # Generates RDoc using a legacy version of RDoc from the ARGV-like +args+. # This method will not exist in future versions. def legacy_rdoc *args args << @spec.rdoc_options args << '--quiet' args << @spec.require_paths.clone args << @spec.extra_rdoc_files args << '--title' << "#{@spec.full_name} Documentation" args = args.flatten.map do |arg| arg.to_s end delete_legacy_args args if Gem::Requirement.new('>= 2.4.0') =~ self.class.rdoc_version r = new_rdoc verbose { "rdoc #{args.join ' '}" } Dir.chdir @spec.full_gem_path do begin r.document args rescue Errno::EACCES => e dirname = File.dirname e.message.split("-")[1].strip raise Gem::FilePermissionError, dirname rescue Interrupt => e raise e rescue Exception => ex alert_error "While generating documentation for #{@spec.full_name}" ui.errs.puts "... MESSAGE: #{ex}" ui.errs.puts "... RDOC args: #{args.join(' ')}" ui.backtrace ex ui.errs.puts "(continuing with the rest of the installation)" end end end ## # #new_rdoc creates a new RDoc instance. This method is provided only to # make testing easier. def new_rdoc # :nodoc: ::RDoc::RDoc.new end ## # Is rdoc documentation installed? def rdoc_installed? File.exist? @rdoc_dir end ## # Removes generated RDoc and ri data def remove base_dir = @spec.base_dir raise Gem::FilePermissionError, base_dir unless File.writable? base_dir FileUtils.rm_rf @rdoc_dir FileUtils.rm_rf @ri_dir end ## # Is ri data installed? def ri_installed? File.exist? @ri_dir end ## # Prepares the spec for documentation generation def setup self.class.load_rdoc raise Gem::FilePermissionError, @doc_dir if File.exist?(@doc_dir) and not File.writable?(@doc_dir) FileUtils.mkdir_p @doc_dir unless File.exist? @doc_dir end end unless loaded_hook Gem.done_installing(&Gem::RDoc.method(:generation_hook)) PK!]C 2.2.0/rubygems/available_set.rbnu[class Gem::AvailableSet include Enumerable Tuple = Struct.new(:spec, :source) attr_accessor :remote # :nodoc: def initialize @set = [] @sorted = nil @remote = true end attr_reader :set def add(spec, source) @set << Tuple.new(spec, source) @sorted = nil self end def <<(o) case o when Gem::AvailableSet s = o.set when Array s = o.map do |sp,so| if !sp.kind_of?(Gem::Specification) or !so.kind_of?(Gem::Source) raise TypeError, "Array must be in [[spec, source], ...] form" end Tuple.new(sp,so) end else raise TypeError, "must be a Gem::AvailableSet" end @set += s @sorted = nil self end ## # Yields each Tuple in this AvailableSet def each return enum_for __method__ unless block_given? @set.each do |tuple| yield tuple end end ## # Yields the Gem::Specification for each Tuple in this AvailableSet def each_spec return enum_for __method__ unless block_given? each do |tuple| yield tuple.spec end end def empty? @set.empty? end def all_specs @set.map { |t| t.spec } end def match_platform! @set.reject! { |t| !Gem::Platform.match(t.spec.platform) } @sorted = nil self end def sorted @sorted ||= @set.sort do |a,b| i = b.spec <=> a.spec i != 0 ? i : (a.source <=> b.source) end end def size @set.size end def source_for(spec) f = @set.find { |t| t.spec == spec } f.source end ## # Converts this AvailableSet into a RequestSet that can be used to install # gems. # # If +development+ is :none then no development dependencies are installed. # Other options are :shallow for only direct development dependencies of the # gems in this set or :all for all development dependencies. def to_request_set development = :none request_set = Gem::RequestSet.new request_set.development = :all == development each_spec do |spec| request_set.always_install << spec request_set.gem spec.name, spec.version request_set.import spec.development_dependencies if :shallow == development end request_set end ## # # Used by the Resolver, the protocol to use a AvailableSet as a # search Set. def find_all(req) dep = req.dependency match = @set.find_all do |t| dep.match? t.spec end match.map do |t| Gem::Resolver::LocalSpecification.new(self, t.spec, t.source) end end def prefetch(reqs) end def pick_best! return self if empty? @set = [sorted.first] @sorted = nil self end def remove_installed!(dep) @set.reject! do |t| # already locally installed Gem::Specification.any? do |installed_spec| dep.name == installed_spec.name and dep.requirement.satisfied_by? installed_spec.version end end @sorted = nil self end def inject_into_list(dep_list) @set.each { |t| dep_list.add t.spec } end end PK!ZZ2.2.0/rubygems/syck_hack.rbnu[# :stopdoc: # Hack to handle syck's DefaultKey bug # # This file is always loaded AFTER either syck or psych are already # loaded. It then looks at what constants are available and creates # a consistent view on all rubys. # # All this is so that there is always a YAML::Syck::DefaultKey # class no matter if the full yaml library has loaded or not. # module YAML # :nodoc: # In newer 1.9.2, there is a Syck toplevel constant instead of it # being underneath YAML. If so, reference it back under YAML as # well. if defined? ::Syck # for tests that change YAML::ENGINE # 1.8 does not support the second argument to const_defined? remove_const :Syck rescue nil Syck = ::Syck # JRuby's "Syck" is called "Yecht" elsif defined? YAML::Yecht Syck = YAML::Yecht # Otherwise, if there is no YAML::Syck, then we've got just psych # loaded, so lets define a stub for DefaultKey. elsif !defined? YAML::Syck module Syck class DefaultKey # :nodoc: end end end # Now that we've got something that is always here, define #to_s # so when code tries to use this, it at least just shows up like it # should. module Syck class DefaultKey remove_method :to_s rescue nil def to_s '=' end end end SyntaxError = Error unless defined? SyntaxError end # Sometime in the 1.9 dev cycle, the Syck constant was moved from under YAML # to be a toplevel constant. So gemspecs created under these versions of Syck # will have references to Syck::DefaultKey. # # So we need to be sure that we reference Syck at the toplevel too so that # we can always load these kind of gemspecs. # if !defined?(Syck) Syck = YAML::Syck end # Now that we've got Syck setup in all the right places, store # a reference to the DefaultKey class inside Gem. We do this so that # if later on YAML, etc are redefined, we've still got a consistent # place to find the DefaultKey class for comparison. module Gem # for tests that change YAML::ENGINE remove_const :SyckDefaultKey if const_defined? :SyckDefaultKey SyckDefaultKey = YAML::Syck::DefaultKey end # :startdoc: PK!52.2.0/rubygems/exceptions.rbnu[# TODO: the documentation in here is terrible. # # Each exception needs a brief description and the scenarios where it is # likely to be raised ## # Base exception class for RubyGems. All exception raised by RubyGems are a # subclass of this one. class Gem::Exception < RuntimeError ## #-- # TODO: remove in RubyGems 3, nobody sets this attr_accessor :source_exception # :nodoc: end class Gem::CommandLineError < Gem::Exception; end class Gem::DependencyError < Gem::Exception; end class Gem::DependencyRemovalException < Gem::Exception; end ## # Raised by Gem::Resolver when a Gem::Dependency::Conflict reaches the # toplevel. Indicates which dependencies were incompatible through #conflict # and #conflicting_dependencies class Gem::DependencyResolutionError < Gem::DependencyError attr_reader :conflict def initialize conflict @conflict = conflict a, b = conflicting_dependencies super "conflicting dependencies #{a} and #{b}\n#{@conflict.explanation}" end def conflicting_dependencies @conflict.conflicting_dependencies end end ## # Raised when attempting to uninstall a gem that isn't in GEM_HOME. class Gem::GemNotInHomeException < Gem::Exception attr_accessor :spec end class Gem::DocumentError < Gem::Exception; end ## # Potentially raised when a specification is validated. class Gem::EndOfYAMLException < Gem::Exception; end ## # Signals that a file permission error is preventing the user from # operating on the given directory. class Gem::FilePermissionError < Gem::Exception attr_reader :directory def initialize directory @directory = directory super "You don't have write permissions for the #{directory} directory." end end ## # Used to raise parsing and loading errors class Gem::FormatException < Gem::Exception attr_accessor :file_path end class Gem::GemNotFoundException < Gem::Exception; end ## # Raised by the DependencyInstaller when a specific gem cannot be found class Gem::SpecificGemNotFoundException < Gem::GemNotFoundException ## # Creates a new SpecificGemNotFoundException for a gem with the given +name+ # and +version+. Any +errors+ encountered when attempting to find the gem # are also stored. def initialize(name, version, errors=nil) super "Could not find a valid gem '#{name}' (#{version}) locally or in a repository" @name = name @version = version @errors = errors end ## # The name of the gem that could not be found. attr_reader :name ## # The version of the gem that could not be found. attr_reader :version ## # Errors encountered attempting to find the gem. attr_reader :errors end ## # Raised by Gem::Resolver when dependencies conflict and create the # inability to find a valid possible spec for a request. class Gem::ImpossibleDependenciesError < Gem::Exception attr_reader :conflicts attr_reader :request def initialize request, conflicts @request = request @conflicts = conflicts super build_message end def build_message # :nodoc: requester = @request.requester requester = requester ? requester.spec.full_name : 'The user' dependency = @request.dependency message = "#{requester} requires #{dependency} but it conflicted:\n" @conflicts.each do |_, conflict| message << conflict.explanation end message end def dependency @request.dependency end end class Gem::InstallError < Gem::Exception; end ## # Potentially raised when a specification is validated. class Gem::InvalidSpecificationException < Gem::Exception; end class Gem::OperationNotSupportedError < Gem::Exception; end ## # Signals that a remote operation cannot be conducted, probably due to not # being connected (or just not finding host). #-- # TODO: create a method that tests connection to the preferred gems server. # All code dealing with remote operations will want this. Failure in that # method should raise this error. class Gem::RemoteError < Gem::Exception; end class Gem::RemoteInstallationCancelled < Gem::Exception; end class Gem::RemoteInstallationSkipped < Gem::Exception; end ## # Represents an error communicating via HTTP. class Gem::RemoteSourceException < Gem::Exception; end ## # Raised when a gem dependencies file specifies a ruby version that does not # match the current version. class Gem::RubyVersionMismatch < Gem::Exception; end ## # Raised by Gem::Validator when something is not right in a gem. class Gem::VerificationError < Gem::Exception; end ## # Raised to indicate that a system exit should occur with the specified # exit_code class Gem::SystemExitException < SystemExit ## # The exit code for the process attr_accessor :exit_code ## # Creates a new SystemExitException with the given +exit_code+ def initialize(exit_code) @exit_code = exit_code super "Exiting RubyGems with exit_code #{exit_code}" end end ## # Raised by Resolver when a dependency requests a gem for which # there is no spec. class Gem::UnsatisfiableDependencyError < Gem::DependencyError ## # The unsatisfiable dependency. This is a # Gem::Resolver::DependencyRequest, not a Gem::Dependency attr_reader :dependency ## # Errors encountered which may have contributed to this exception attr_accessor :errors ## # Creates a new UnsatisfiableDependencyError for the unsatisfiable # Gem::Resolver::DependencyRequest +dep+ def initialize dep, platform_mismatch=nil if platform_mismatch and !platform_mismatch.empty? plats = platform_mismatch.map { |x| x.platform.to_s }.sort.uniq super "Unable to resolve dependency: No match for '#{dep}' on this platform. Found: #{plats.join(', ')}" else if dep.explicit? super "Unable to resolve dependency: user requested '#{dep}'" else super "Unable to resolve dependency: '#{dep.request_context}' requires '#{dep}'" end end @dependency = dep @errors = [] end ## # The name of the unresolved dependency def name @dependency.name end ## # The Requirement of the unresolved dependency (not Version). def version @dependency.requirement end end ## # Backwards compatible typo'd exception class for early RubyGems 2.0.x Gem::UnsatisfiableDepedencyError = Gem::UnsatisfiableDependencyError # :nodoc: PK!YYY2.2.0/rubygems/installer.rbnu[#-- # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. # All rights reserved. # See LICENSE.txt for permissions. #++ require 'rubygems/command' require 'rubygems/exceptions' require 'rubygems/package' require 'rubygems/ext' require 'rubygems/user_interaction' require 'fileutils' ## # The installer installs the files contained in the .gem into the Gem.home. # # Gem::Installer does the work of putting files in all the right places on the # filesystem including unpacking the gem into its gem dir, installing the # gemspec in the specifications dir, storing the cached gem in the cache dir, # and installing either wrappers or symlinks for executables. # # The installer invokes pre and post install hooks. Hooks can be added either # through a rubygems_plugin.rb file in an installed gem or via a # rubygems/defaults/#{RUBY_ENGINE}.rb or rubygems/defaults/operating_system.rb # file. See Gem.pre_install and Gem.post_install for details. class Gem::Installer ## # Paths where env(1) might live. Some systems are broken and have it in # /bin ENV_PATHS = %w[/usr/bin/env /bin/env] ## # Deprecated in favor of Gem::Ext::BuildError ExtensionBuildError = Gem::Ext::BuildError # :nodoc: include Gem::UserInteraction ## # Filename of the gem being installed. attr_reader :gem ## # The directory a gem's executables will be installed into attr_reader :bin_dir attr_reader :build_root # :nodoc: ## # The gem repository the gem will be installed into attr_reader :gem_home ## # The options passed when the Gem::Installer was instantiated. attr_reader :options ## # Sets the specification for .gem-less installs. attr_writer :spec @path_warning = false @install_lock = Mutex.new class << self ## # True if we've warned about PATH not including Gem.bindir attr_accessor :path_warning ## # Certain aspects of the install process are not thread-safe. This lock is # used to allow multiple threads to install Gems at the same time. attr_reader :install_lock ## # Overrides the executable format. # # This is a sprintf format with a "%s" which will be replaced with the # executable name. It is based off the ruby executable name's difference # from "ruby". attr_writer :exec_format # Defaults to use Ruby's program prefix and suffix. def exec_format @exec_format ||= Gem.default_exec_format end end ## # Constructs an Installer instance that will install the gem located at # +gem+. +options+ is a Hash with the following keys: # # :bin_dir:: Where to put a bin wrapper if needed. # :development:: Whether or not development dependencies should be installed. # :env_shebang:: Use /usr/bin/env in bin wrappers. # :force:: Overrides all version checks and security policy checks, except # for a signed-gems-only policy. # :format_executable:: Format the executable the same as the Ruby executable. # If your Ruby is ruby18, foo_exec will be installed as # foo_exec18. # :ignore_dependencies:: Don't raise if a dependency is missing. # :install_dir:: The directory to install the gem into. # :security_policy:: Use the specified security policy. See Gem::Security # :user_install:: Indicate that the gem should be unpacked into the users # personal gem directory. # :only_install_dir:: Only validate dependencies against what is in the # install_dir # :wrappers:: Install wrappers if true, symlinks if false. # :build_args:: An Array of arguments to pass to the extension builder # process. If not set, then Gem::Command.build_args is used def initialize(gem, options={}) require 'fileutils' @gem = gem @options = options @package = Gem::Package.new @gem process_options @package.security_policy = @security_policy if options[:user_install] and not options[:unpack] then @gem_home = Gem.user_dir @bin_dir = Gem.bindir gem_home unless options[:bin_dir] check_that_user_bin_dir_is_in_path end end ## # Checks if +filename+ exists in +@bin_dir+. # # If +@force+ is set +filename+ is overwritten. # # If +filename+ exists and is a RubyGems wrapper for different gem the user # is consulted. # # If +filename+ exists and +@bin_dir+ is Gem.default_bindir (/usr/local) the # user is consulted. # # Otherwise +filename+ is overwritten. def check_executable_overwrite filename # :nodoc: return if @force generated_bin = File.join @bin_dir, formatted_program_filename(filename) return unless File.exist? generated_bin ruby_executable = false existing = nil open generated_bin, 'rb' do |io| next unless io.gets =~ /^#!/ # shebang io.gets # blankline # TODO detect a specially formatted comment instead of trying # to run a regexp against Ruby code. next unless io.gets =~ /This file was generated by RubyGems/ ruby_executable = true existing = io.read.slice(/^gem (['"])(.*?)(\1),/, 2) end return if spec.name == existing # somebody has written to RubyGems' directory, overwrite, too bad return if Gem.default_bindir != @bin_dir and not ruby_executable question = "#{spec.name}'s executable \"#{filename}\" conflicts with " if ruby_executable then question << existing return if ask_yes_no "#{question}\nOverwrite the executable?", false conflict = "installed executable from #{existing}" else question << generated_bin return if ask_yes_no "#{question}\nOverwrite the executable?", false conflict = generated_bin end raise Gem::InstallError, "\"#{filename}\" from #{spec.name} conflicts with #{conflict}" end ## # Lazy accessor for the spec's gem directory. def gem_dir @gem_dir ||= File.join(gem_home, "gems", spec.full_name) end ## # Lazy accessor for the installer's spec. def spec @spec ||= @package.spec rescue Gem::Package::Error => e raise Gem::InstallError, "invalid gem: #{e.message}" end ## # Installs the gem and returns a loaded Gem::Specification for the installed # gem. # # The gem will be installed with the following structure: # # @gem_home/ # cache/.gem #=> a cached copy of the installed gem # gems//... #=> extracted files # specifications/.gemspec #=> the Gem::Specification def install pre_install_checks FileUtils.rm_f File.join gem_home, 'specifications', @spec.spec_name run_pre_install_hooks # Completely remove any previous gem files FileUtils.rm_rf gem_dir FileUtils.mkdir_p gem_dir spec.loaded_from = spec_file if @options[:install_as_default] extract_bin write_default_spec else extract_files build_extensions write_build_info_file run_post_build_hooks generate_bin write_spec write_cache_file end say spec.post_install_message unless spec.post_install_message.nil? Gem::Installer.install_lock.synchronize { Gem::Specification.add_spec spec } run_post_install_hooks spec # TODO This rescue is in the wrong place. What is raising this exception? # move this rescue to around the code that actually might raise it. rescue Zlib::GzipFile::Error raise Gem::InstallError, "gzip error installing #{gem}" end def run_pre_install_hooks # :nodoc: Gem.pre_install_hooks.each do |hook| if hook.call(self) == false then location = " at #{$1}" if hook.inspect =~ /@(.*:\d+)/ message = "pre-install hook#{location} failed for #{spec.full_name}" raise Gem::InstallError, message end end end def run_post_build_hooks # :nodoc: Gem.post_build_hooks.each do |hook| if hook.call(self) == false then FileUtils.rm_rf gem_dir location = " at #{$1}" if hook.inspect =~ /@(.*:\d+)/ message = "post-build hook#{location} failed for #{spec.full_name}" raise Gem::InstallError, message end end end def run_post_install_hooks # :nodoc: Gem.post_install_hooks.each do |hook| hook.call self end end ## # # Return an Array of Specifications contained within the gem_home # we'll be installing into. def installed_specs @specs ||= begin specs = [] Dir[File.join(gem_home, "specifications", "*.gemspec")].each do |path| spec = Gem::Specification.load path.untaint specs << spec if spec end specs end end ## # Ensure that the dependency is satisfied by the current installation of # gem. If it is not an exception is raised. # # spec :: Gem::Specification # dependency :: Gem::Dependency def ensure_dependency(spec, dependency) unless installation_satisfies_dependency? dependency then raise Gem::InstallError, "#{spec.name} requires #{dependency}" end true end ## # True if the gems in the system satisfy +dependency+. def installation_satisfies_dependency?(dependency) return true if @options[:development] and dependency.type == :development return true if installed_specs.detect { |s| dependency.matches_spec? s } return false if @only_install_dir not dependency.matching_specs.empty? end ## # Unpacks the gem into the given directory. def unpack(directory) @gem_dir = directory extract_files end ## # The location of of the spec file that is installed. # def spec_file File.join gem_home, "specifications", "#{spec.full_name}.gemspec" end ## # The location of of the default spec file for default gems. # def default_spec_file File.join gem_home, "specifications/default", "#{spec.full_name}.gemspec" end ## # Writes the .gemspec specification (in Ruby) to the gem home's # specifications directory. def write_spec open spec_file, 'w' do |file| spec.installed_by_version = Gem.rubygems_version file.puts spec.to_ruby_for_cache file.fsync rescue nil # for filesystems without fsync(2) end end ## # Writes the full .gemspec specification (in Ruby) to the gem home's # specifications/default directory. def write_default_spec File.open(default_spec_file, "w") do |file| file.puts spec.to_ruby end end ## # Creates windows .bat files for easy running of commands def generate_windows_script(filename, bindir) if Gem.win_platform? then script_name = filename + ".bat" script_path = File.join bindir, File.basename(script_name) File.open script_path, 'w' do |file| file.puts windows_stub_script(bindir, filename) end verbose script_path end end def generate_bin # :nodoc: return if spec.executables.nil? or spec.executables.empty? Dir.mkdir @bin_dir unless File.exist? @bin_dir raise Gem::FilePermissionError.new(@bin_dir) unless File.writable? @bin_dir spec.executables.each do |filename| filename.untaint bin_path = File.join gem_dir, spec.bindir, filename unless File.exist? bin_path then # TODO change this to a more useful warning warn "#{bin_path} maybe `gem pristine #{spec.name}` will fix it?" next end mode = File.stat(bin_path).mode FileUtils.chmod mode | 0111, bin_path unless (mode | 0111) == mode check_executable_overwrite filename if @wrappers then generate_bin_script filename, @bin_dir else generate_bin_symlink filename, @bin_dir end end end ## # Creates the scripts to run the applications in the gem. #-- # The Windows script is generated in addition to the regular one due to a # bug or misfeature in the Windows shell's pipe. See # http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/193379 def generate_bin_script(filename, bindir) bin_script_path = File.join bindir, formatted_program_filename(filename) FileUtils.rm_f bin_script_path # prior install may have been --no-wrappers File.open bin_script_path, 'wb', 0755 do |file| file.print app_script_text(filename) end verbose bin_script_path generate_windows_script filename, bindir end ## # Creates the symlinks to run the applications in the gem. Moves # the symlink if the gem being installed has a newer version. def generate_bin_symlink(filename, bindir) if Gem.win_platform? then alert_warning "Unable to use symlinks on Windows, installing wrapper" generate_bin_script filename, bindir return end src = File.join gem_dir, spec.bindir, filename dst = File.join bindir, formatted_program_filename(filename) if File.exist? dst then if File.symlink? dst then link = File.readlink(dst).split File::SEPARATOR cur_version = Gem::Version.create(link[-3].sub(/^.*-/, '')) return if spec.version < cur_version end File.unlink dst end FileUtils.symlink src, dst, :verbose => Gem.configuration.really_verbose end ## # Generates a #! line for +bin_file_name+'s wrapper copying arguments if # necessary. # # If the :custom_shebang config is set, then it is used as a template # for how to create the shebang used for to run a gem's executables. # # The template supports 4 expansions: # # $env the path to the unix env utility # $ruby the path to the currently running ruby interpreter # $exec the path to the gem's executable # $name the name of the gem the executable is for # def shebang(bin_file_name) ruby_name = RbConfig::CONFIG['ruby_install_name'] if @env_shebang path = File.join gem_dir, spec.bindir, bin_file_name first_line = File.open(path, "rb") {|file| file.gets} if /\A#!/ =~ first_line then # Preserve extra words on shebang line, like "-w". Thanks RPA. shebang = first_line.sub(/\A\#!.*?ruby\S*((\s+\S+)+)/, "#!#{Gem.ruby}") opts = $1 shebang.strip! # Avoid nasty ^M issues. end if which = Gem.configuration[:custom_shebang] # replace bin_file_name with "ruby" to avoid endless loops which = which.gsub(/ #{bin_file_name}$/," #{RbConfig::CONFIG['ruby_install_name']}") which = which.gsub(/\$(\w+)/) do case $1 when "env" @env_path ||= ENV_PATHS.find {|env_path| File.executable? env_path } when "ruby" "#{Gem.ruby}#{opts}" when "exec" bin_file_name when "name" spec.name end end "#!#{which}" elsif not ruby_name then "#!#{Gem.ruby}#{opts}" elsif opts then "#!/bin/sh\n'exec' #{ruby_name.dump} '-x' \"$0\" \"$@\"\n#{shebang}" else # Create a plain shebang line. @env_path ||= ENV_PATHS.find {|env_path| File.executable? env_path } "#!#{@env_path} #{ruby_name}" end end ## # Ensures the Gem::Specification written out for this gem is loadable upon # installation. def ensure_loadable_spec ruby = spec.to_ruby_for_cache ruby.untaint begin eval ruby rescue StandardError, SyntaxError => e raise Gem::InstallError, "The specification for #{spec.full_name} is corrupt (#{e.class})" end end def ensure_required_ruby_version_met # :nodoc: if rrv = spec.required_ruby_version then unless rrv.satisfied_by? Gem.ruby_version then raise Gem::InstallError, "#{spec.name} requires Ruby version #{rrv}." end end end def ensure_required_rubygems_version_met # :nodoc: if rrgv = spec.required_rubygems_version then unless rrgv.satisfied_by? Gem.rubygems_version then raise Gem::InstallError, "#{spec.name} requires RubyGems version #{rrgv}. " + "Try 'gem update --system' to update RubyGems itself." end end end def ensure_dependencies_met # :nodoc: deps = spec.runtime_dependencies deps |= spec.development_dependencies if @development deps.each do |dep_gem| ensure_dependency spec, dep_gem end end def process_options # :nodoc: @options = { :bin_dir => nil, :env_shebang => false, :force => false, :only_install_dir => false }.merge options @env_shebang = options[:env_shebang] @force = options[:force] @install_dir = options[:install_dir] @gem_home = options[:install_dir] || Gem.dir @ignore_dependencies = options[:ignore_dependencies] @format_executable = options[:format_executable] @security_policy = options[:security_policy] @wrappers = options[:wrappers] @only_install_dir = options[:only_install_dir] # If the user has asked for the gem to be installed in a directory that is # the system gem directory, then use the system bin directory, else create # (or use) a new bin dir under the gem_home. @bin_dir = options[:bin_dir] || Gem.bindir(gem_home) @development = options[:development] @build_root = options[:build_root] @build_args = options[:build_args] || Gem::Command.build_args unless @build_root.nil? require 'pathname' @build_root = Pathname.new(@build_root).expand_path @bin_dir = File.join(@build_root, options[:bin_dir] || Gem.bindir(@gem_home)) @gem_home = File.join(@build_root, @gem_home) alert_warning "You build with buildroot.\n Build root: #{@build_root}\n Bin dir: #{@bin_dir}\n Gem home: #{@gem_home}" end end def check_that_user_bin_dir_is_in_path # :nodoc: user_bin_dir = @bin_dir || Gem.bindir(gem_home) user_bin_dir = user_bin_dir.gsub(File::SEPARATOR, File::ALT_SEPARATOR) if File::ALT_SEPARATOR path = ENV['PATH'] if Gem.win_platform? then path = path.downcase user_bin_dir = user_bin_dir.downcase end path = path.split(File::PATH_SEPARATOR) unless path.include? user_bin_dir then unless !Gem.win_platform? && (path.include? user_bin_dir.sub(ENV['HOME'], '~')) unless self.class.path_warning then alert_warning "You don't have #{user_bin_dir} in your PATH,\n\t gem executables will not run." self.class.path_warning = true end end end end def verify_gem_home(unpack = false) # :nodoc: FileUtils.mkdir_p gem_home raise Gem::FilePermissionError, gem_home unless unpack or File.writable?(gem_home) end def verify_spec_name return if spec.name =~ Gem::Specification::VALID_NAME_PATTERN raise Gem::InstallError, "#{spec} has an invalid name" end ## # Return the text for an application file. def app_script_text(bin_file_name) return <<-TEXT #{shebang bin_file_name} # # This file was generated by RubyGems. # # The application '#{spec.name}' is installed as part of a gem, and # this file is here to facilitate running it. # require 'rubygems' version = "#{Gem::Requirement.default}" if ARGV.first str = ARGV.first str = str.dup.force_encoding("BINARY") if str.respond_to? :force_encoding if str =~ /\\A_(.*)_\\z/ and Gem::Version.correct?($1) then version = $1 ARGV.shift end end gem '#{spec.name}', version load Gem.bin_path('#{spec.name}', '#{bin_file_name}', version) TEXT end ## # return the stub script text used to launch the true Ruby script def windows_stub_script(bindir, bin_file_name) ruby = Gem.ruby.gsub(/^\"|\"$/, "").tr(File::SEPARATOR, "\\") return <<-TEXT @ECHO OFF IF NOT "%~f0" == "~f0" GOTO :WinNT @"#{ruby}" "#{File.join(bindir, bin_file_name)}" %1 %2 %3 %4 %5 %6 %7 %8 %9 GOTO :EOF :WinNT @"#{ruby}" "%~dpn0" %* TEXT end ## # Builds extensions. Valid types of extensions are extconf.rb files, # configure scripts and rakefiles or mkrf_conf files. def build_extensions builder = Gem::Ext::Builder.new spec, @build_args builder.build_extensions end ## # Logs the build +output+ in +build_dir+, then raises Gem::Ext::BuildError. # # TODO: Delete this for RubyGems 3. It remains for API compatibility def extension_build_error(build_dir, output, backtrace = nil) # :nodoc: builder = Gem::Ext::Builder.new spec, @build_args builder.build_error build_dir, output, backtrace end ## # Reads the file index and extracts each file into the gem directory. # # Ensures that files can't be installed outside the gem directory. def extract_files @package.extract_files gem_dir end ## # Extracts only the bin/ files from the gem into the gem directory. # This is used by default gems to allow a gem-aware stub to function # without the full gem installed. def extract_bin @package.extract_files gem_dir, "bin/*" end ## # Prefix and suffix the program filename the same as ruby. def formatted_program_filename(filename) if @format_executable then self.class.exec_format % File.basename(filename) else filename end end ## # # Return the target directory where the gem is to be installed. This # directory is not guaranteed to be populated. # def dir gem_dir.to_s end ## # Performs various checks before installing the gem such as the install # repository is writable and its directories exist, required Ruby and # rubygems versions are met and that dependencies are installed. # # Version and dependency checks are skipped if this install is forced. # # The dependent check will be skipped this install is ignoring dependencies. def pre_install_checks verify_gem_home options[:unpack] # If we're forcing the install then disable security unless the security # policy says that we only install signed gems. @security_policy = nil if @force and @security_policy and not @security_policy.only_signed ensure_loadable_spec verify_spec_name if options[:install_as_default] Gem.ensure_default_gem_subdirectories gem_home else Gem.ensure_gem_subdirectories gem_home end return true if @force ensure_required_ruby_version_met ensure_required_rubygems_version_met ensure_dependencies_met unless @ignore_dependencies true end ## # Writes the file containing the arguments for building this gem's # extensions. def write_build_info_file return if @build_args.empty? build_info_dir = File.join gem_home, 'build_info' FileUtils.mkdir_p build_info_dir build_info_file = File.join build_info_dir, "#{spec.full_name}.info" open build_info_file, 'w' do |io| @build_args.each do |arg| io.puts arg end end end ## # Writes the .gem file to the cache directory def write_cache_file cache_file = File.join gem_home, 'cache', spec.file_name FileUtils.cp @gem, cache_file unless File.exist? cache_file end end PK!Sg]]&2.2.0/rubygems/source_specific_file.rbnu[require 'rubygems/source/specific_file' # TODO warn upon require, this file is deprecated. PK!O33)2.2.0/rubygems/install_default_message.rbnu[require 'rubygems' require 'rubygems/user_interaction' ## # A post-install hook that displays "Successfully installed # some_gem-1.0 as a default gem" Gem.post_install do |installer| ui = Gem::DefaultUserInteraction.ui ui.say "Successfully installed #{installer.spec.full_name} as a default gem" end PK!MXMSS2.2.0/rubygems/security.rbnu[#-- # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. # All rights reserved. # See LICENSE.txt for permissions. #++ require 'rubygems/exceptions' require 'fileutils' begin require 'openssl' rescue LoadError => e raise unless (e.respond_to?(:path) && e.path == 'openssl') || e.message =~ / -- openssl$/ end ## # = Signing gems # # The Gem::Security implements cryptographic signatures for gems. The section # below is a step-by-step guide to using signed gems and generating your own. # # == Walkthrough # # === Building your certificate # # In order to start signing your gems, you'll need to build a private key and # a self-signed certificate. Here's how: # # # build a private key and certificate for yourself: # $ gem cert --build you@example.com # # This could take anywhere from a few seconds to a minute or two, depending on # the speed of your computer (public key algorithms aren't exactly the # speediest crypto algorithms in the world). When it's finished, you'll see # the files "gem-private_key.pem" and "gem-public_cert.pem" in the current # directory. # # First things first: Move both files to ~/.gem if you don't already have a # key and certificate in that directory. Ensure the file permissions make the # key unreadable by others (by default the file is saved securely). # # Keep your private key hidden; if it's compromised, someone can sign packages # as you (note: PKI has ways of mitigating the risk of stolen keys; more on # that later). # # === Signing Gems # # In RubyGems 2 and newer there is no extra work to sign a gem. RubyGems will # automatically find your key and certificate in your home directory and use # them to sign newly packaged gems. # # If your certificate is not self-signed (signed by a third party) RubyGems # will attempt to load the certificate chain from the trusted certificates. # Use gem cert --add signing_cert.pem to add your signers as # trusted certificates. See below for further information on certificate # chains. # # If you build your gem it will automatically be signed. If you peek inside # your gem file, you'll see a couple of new files have been added: # # $ tar tf your-gem-1.0.gem # metadata.gz # metadata.gz.sum # metadata.gz.sig # metadata signature # data.tar.gz # data.tar.gz.sum # data.tar.gz.sig # data signature # # === Manually signing gems # # If you wish to store your key in a separate secure location you'll need to # set your gems up for signing by hand. To do this, set the # signing_key and cert_chain in the gemspec before # packaging your gem: # # s.signing_key = '/secure/path/to/gem-private_key.pem' # s.cert_chain = %w[/secure/path/to/gem-public_cert.pem] # # When you package your gem with these options set RubyGems will automatically # load your key and certificate from the secure paths. # # === Signed gems and security policies # # Now let's verify the signature. Go ahead and install the gem, but add the # following options: -P HighSecurity, like this: # # # install the gem with using the security policy "HighSecurity" # $ sudo gem install your.gem -P HighSecurity # # The -P option sets your security policy -- we'll talk about # that in just a minute. Eh, what's this? # # $ gem install -P HighSecurity your-gem-1.0.gem # ERROR: While executing gem ... (Gem::Security::Exception) # root cert /CN=you/DC=example is not trusted # # The culprit here is the security policy. RubyGems has several different # security policies. Let's take a short break and go over the security # policies. Here's a list of the available security policies, and a brief # description of each one: # # * NoSecurity - Well, no security at all. Signed packages are treated like # unsigned packages. # * LowSecurity - Pretty much no security. If a package is signed then # RubyGems will make sure the signature matches the signing # certificate, and that the signing certificate hasn't expired, but # that's it. A malicious user could easily circumvent this kind of # security. # * MediumSecurity - Better than LowSecurity and NoSecurity, but still # fallible. Package contents are verified against the signing # certificate, and the signing certificate is checked for validity, # and checked against the rest of the certificate chain (if you don't # know what a certificate chain is, stay tuned, we'll get to that). # The biggest improvement over LowSecurity is that MediumSecurity # won't install packages that are signed by untrusted sources. # Unfortunately, MediumSecurity still isn't totally secure -- a # malicious user can still unpack the gem, strip the signatures, and # distribute the gem unsigned. # * HighSecurity - Here's the bugger that got us into this mess. # The HighSecurity policy is identical to the MediumSecurity policy, # except that it does not allow unsigned gems. A malicious user # doesn't have a whole lot of options here; they can't modify the # package contents without invalidating the signature, and they can't # modify or remove signature or the signing certificate chain, or # RubyGems will simply refuse to install the package. Oh well, maybe # they'll have better luck causing problems for CPAN users instead :). # # The reason RubyGems refused to install your shiny new signed gem was because # it was from an untrusted source. Well, your code is infallible (naturally), # so you need to add yourself as a trusted source: # # # add trusted certificate # gem cert --add ~/.gem/gem-public_cert.pem # # You've now added your public certificate as a trusted source. Now you can # install packages signed by your private key without any hassle. Let's try # the install command above again: # # # install the gem with using the HighSecurity policy (and this time # # without any shenanigans) # $ gem install -P HighSecurity your-gem-1.0.gem # Successfully installed your-gem-1.0 # 1 gem installed # # This time RubyGems will accept your signed package and begin installing. # # While you're waiting for RubyGems to work it's magic, have a look at some of # the other security commands by running gem help cert: # # Options: # -a, --add CERT Add a trusted certificate. # -l, --list [FILTER] List trusted certificates where the # subject contains FILTER # -r, --remove FILTER Remove trusted certificates where the # subject contains FILTER # -b, --build EMAIL_ADDR Build private key and self-signed # certificate for EMAIL_ADDR # -C, --certificate CERT Signing certificate for --sign # -K, --private-key KEY Key for --sign or --build # -s, --sign CERT Signs CERT with the key from -K # and the certificate from -C # # We've already covered the --build option, and the # --add, --list, and --remove commands # seem fairly straightforward; they allow you to add, list, and remove the # certificates in your trusted certificate list. But what's with this # --sign option? # # === Certificate chains # # To answer that question, let's take a look at "certificate chains", a # concept I mentioned earlier. There are a couple of problems with # self-signed certificates: first of all, self-signed certificates don't offer # a whole lot of security. Sure, the certificate says Yukihiro Matsumoto, but # how do I know it was actually generated and signed by matz himself unless he # gave me the certificate in person? # # The second problem is scalability. Sure, if there are 50 gem authors, then # I have 50 trusted certificates, no problem. What if there are 500 gem # authors? 1000? Having to constantly add new trusted certificates is a # pain, and it actually makes the trust system less secure by encouraging # RubyGems users to blindly trust new certificates. # # Here's where certificate chains come in. A certificate chain establishes an # arbitrarily long chain of trust between an issuing certificate and a child # certificate. So instead of trusting certificates on a per-developer basis, # we use the PKI concept of certificate chains to build a logical hierarchy of # trust. Here's a hypothetical example of a trust hierarchy based (roughly) # on geography: # # -------------------------- # | rubygems@rubygems.org | # -------------------------- # | # ----------------------------------- # | | # ---------------------------- ----------------------------- # | seattlerb@seattlerb.org | | dcrubyists@richkilmer.com | # ---------------------------- ----------------------------- # | | | | # --------------- ---------------- ----------- -------------- # | drbrain | | zenspider | | pabs@dc | | tomcope@dc | # --------------- ---------------- ----------- -------------- # # # Now, rather than having 4 trusted certificates (one for drbrain, zenspider, # pabs@dc, and tomecope@dc), a user could actually get by with one # certificate, the "rubygems@rubygems.org" certificate. # # Here's how it works: # # I install "rdoc-3.12.gem", a package signed by "drbrain". I've never heard # of "drbrain", but his certificate has a valid signature from the # "seattle.rb@seattlerb.org" certificate, which in turn has a valid signature # from the "rubygems@rubygems.org" certificate. Voila! At this point, it's # much more reasonable for me to trust a package signed by "drbrain", because # I can establish a chain to "rubygems@rubygems.org", which I do trust. # # === Signing certificates # # The --sign option allows all this to happen. A developer # creates their build certificate with the --build option, then # has their certificate signed by taking it with them to their next regional # Ruby meetup (in our hypothetical example), and it's signed there by the # person holding the regional RubyGems signing certificate, which is signed at # the next RubyConf by the holder of the top-level RubyGems certificate. At # each point the issuer runs the same command: # # # sign a certificate with the specified key and certificate # # (note that this modifies client_cert.pem!) # $ gem cert -K /mnt/floppy/issuer-priv_key.pem -C issuer-pub_cert.pem # --sign client_cert.pem # # Then the holder of issued certificate (in this case, your buddy "drbrain"), # can start using this signed certificate to sign RubyGems. By the way, in # order to let everyone else know about his new fancy signed certificate, # "drbrain" would save his newly signed certificate as # ~/.gem/gem-public_cert.pem # # Obviously this RubyGems trust infrastructure doesn't exist yet. Also, in # the "real world", issuers actually generate the child certificate from a # certificate request, rather than sign an existing certificate. And our # hypothetical infrastructure is missing a certificate revocation system. # These are that can be fixed in the future... # # At this point you should know how to do all of these new and interesting # things: # # * build a gem signing key and certificate # * adjust your security policy # * modify your trusted certificate list # * sign a certificate # # == Manually verifying signatures # # In case you don't trust RubyGems you can verify gem signatures manually: # # 1. Fetch and unpack the gem # # gem fetch some_signed_gem # tar -xf some_signed_gem-1.0.gem # # 2. Grab the public key from the gemspec # # gem spec some_signed_gem-1.0.gem cert_chain | \ # ruby -ryaml -e 'puts YAML.load_documents($stdin)' > public_key.crt # # 3. Generate a SHA1 hash of the data.tar.gz # # openssl dgst -sha1 < data.tar.gz > my.hash # # 4. Verify the signature # # openssl rsautl -verify -inkey public_key.crt -certin \ # -in data.tar.gz.sig > verified.hash # # 5. Compare your hash to the verified hash # # diff -s verified.hash my.hash # # 6. Repeat 5 and 6 with metadata.gz # # == OpenSSL Reference # # The .pem files generated by --build and --sign are PEM files. Here's a # couple of useful OpenSSL commands for manipulating them: # # # convert a PEM format X509 certificate into DER format: # # (note: Windows .cer files are X509 certificates in DER format) # $ openssl x509 -in input.pem -outform der -out output.der # # # print out the certificate in a human-readable format: # $ openssl x509 -in input.pem -noout -text # # And you can do the same thing with the private key file as well: # # # convert a PEM format RSA key into DER format: # $ openssl rsa -in input_key.pem -outform der -out output_key.der # # # print out the key in a human readable format: # $ openssl rsa -in input_key.pem -noout -text # # == Bugs/TODO # # * There's no way to define a system-wide trust list. # * custom security policies (from a YAML file, etc) # * Simple method to generate a signed certificate request # * Support for OCSP, SCVP, CRLs, or some other form of cert status check # (list is in order of preference) # * Support for encrypted private keys # * Some sort of semi-formal trust hierarchy (see long-winded explanation # above) # * Path discovery (for gem certificate chains that don't have a self-signed # root) -- by the way, since we don't have this, THE ROOT OF THE CERTIFICATE # CHAIN MUST BE SELF SIGNED if Policy#verify_root is true (and it is for the # MediumSecurity and HighSecurity policies) # * Better explanation of X509 naming (ie, we don't have to use email # addresses) # * Honor AIA field (see note about OCSP above) # * Honor extension restrictions # * Might be better to store the certificate chain as a PKCS#7 or PKCS#12 # file, instead of an array embedded in the metadata. # * Flexible signature and key algorithms, not hard-coded to RSA and SHA1. # # == Original author # # Paul Duncan # http://pablotron.org/ module Gem::Security ## # Gem::Security default exception type class Exception < Gem::Exception; end ## # Digest algorithm used to sign gems DIGEST_ALGORITHM = if defined?(OpenSSL::Digest) then OpenSSL::Digest::SHA1 end ## # Used internally to select the signing digest from all computed digests DIGEST_NAME = # :nodoc: if DIGEST_ALGORITHM then DIGEST_ALGORITHM.new.name end ## # Algorithm for creating the key pair used to sign gems KEY_ALGORITHM = if defined?(OpenSSL::PKey) then OpenSSL::PKey::RSA end ## # Length of keys created by KEY_ALGORITHM KEY_LENGTH = 2048 ## # Cipher used to encrypt the key pair used to sign gems. # Must be in the list returned by OpenSSL::Cipher.ciphers KEY_CIPHER = OpenSSL::Cipher.new('AES-256-CBC') if defined?(OpenSSL::Cipher) ## # One year in seconds ONE_YEAR = 86400 * 365 ## # The default set of extensions are: # # * The certificate is not a certificate authority # * The key for the certificate may be used for key and data encipherment # and digital signatures # * The certificate contains a subject key identifier EXTENSIONS = { 'basicConstraints' => 'CA:FALSE', 'keyUsage' => 'keyEncipherment,dataEncipherment,digitalSignature', 'subjectKeyIdentifier' => 'hash', } def self.alt_name_or_x509_entry certificate, x509_entry alt_name = certificate.extensions.find do |extension| extension.oid == "#{x509_entry}AltName" end return alt_name.value if alt_name certificate.send x509_entry end ## # Creates an unsigned certificate for +subject+ and +key+. The lifetime of # the key is from the current time to +age+ which defaults to one year. # # The +extensions+ restrict the key to the indicated uses. def self.create_cert subject, key, age = ONE_YEAR, extensions = EXTENSIONS, serial = 1 cert = OpenSSL::X509::Certificate.new cert.public_key = key.public_key cert.version = 2 cert.serial = serial cert.not_before = Time.now cert.not_after = Time.now + age cert.subject = subject ef = OpenSSL::X509::ExtensionFactory.new nil, cert cert.extensions = extensions.map do |ext_name, value| ef.create_extension ext_name, value end cert end ## # Creates a self-signed certificate with an issuer and subject from +email+, # a subject alternative name of +email+ and the given +extensions+ for the # +key+. def self.create_cert_email email, key, age = ONE_YEAR, extensions = EXTENSIONS subject = email_to_name email extensions = extensions.merge "subjectAltName" => "email:#{email}" create_cert_self_signed subject, key, age, extensions end ## # Creates a self-signed certificate with an issuer and subject of +subject+ # and the given +extensions+ for the +key+. def self.create_cert_self_signed subject, key, age = ONE_YEAR, extensions = EXTENSIONS, serial = 1 certificate = create_cert subject, key, age, extensions sign certificate, key, certificate, age, extensions, serial end ## # Creates a new key pair of the specified +length+ and +algorithm+. The # default is a 2048 bit RSA key. def self.create_key length = KEY_LENGTH, algorithm = KEY_ALGORITHM algorithm.new length end ## # Turns +email_address+ into an OpenSSL::X509::Name def self.email_to_name email_address email_address = email_address.gsub(/[^\w@.-]+/i, '_') cn, dcs = email_address.split '@' dcs = dcs.split '.' name = "CN=#{cn}/#{dcs.map { |dc| "DC=#{dc}" }.join '/'}" OpenSSL::X509::Name.parse name end ## # Signs +expired_certificate+ with +private_key+ if the keys match and the # expired certificate was self-signed. #-- # TODO increment serial def self.re_sign expired_certificate, private_key, age = ONE_YEAR, extensions = EXTENSIONS raise Gem::Security::Exception, "incorrect signing key for re-signing " + "#{expired_certificate.subject}" unless expired_certificate.public_key.to_pem == private_key.public_key.to_pem unless expired_certificate.subject.to_s == expired_certificate.issuer.to_s then subject = alt_name_or_x509_entry expired_certificate, :subject issuer = alt_name_or_x509_entry expired_certificate, :issuer raise Gem::Security::Exception, "#{subject} is not self-signed, contact #{issuer} " + "to obtain a valid certificate" end serial = expired_certificate.serial + 1 create_cert_self_signed(expired_certificate.subject, private_key, age, extensions, serial) end ## # Resets the trust directory for verifying gems. def self.reset @trust_dir = nil end ## # Sign the public key from +certificate+ with the +signing_key+ and # +signing_cert+, using the Gem::Security::DIGEST_ALGORITHM. Uses the # default certificate validity range and extensions. # # Returns the newly signed certificate. def self.sign certificate, signing_key, signing_cert, age = ONE_YEAR, extensions = EXTENSIONS, serial = 1 signee_subject = certificate.subject signee_key = certificate.public_key alt_name = certificate.extensions.find do |extension| extension.oid == 'subjectAltName' end extensions = extensions.merge 'subjectAltName' => alt_name.value if alt_name issuer_alt_name = signing_cert.extensions.find do |extension| extension.oid == 'subjectAltName' end extensions = extensions.merge 'issuerAltName' => issuer_alt_name.value if issuer_alt_name signed = create_cert signee_subject, signee_key, age, extensions, serial signed.issuer = signing_cert.subject signed.sign signing_key, Gem::Security::DIGEST_ALGORITHM.new end ## # Returns a Gem::Security::TrustDir which wraps the directory where trusted # certificates live. def self.trust_dir return @trust_dir if @trust_dir dir = File.join Gem.user_home, '.gem', 'trust' @trust_dir ||= Gem::Security::TrustDir.new dir end ## # Enumerates the trusted certificates via Gem::Security::TrustDir. def self.trusted_certificates &block trust_dir.each_certificate(&block) end ## # Writes +pemmable+, which must respond to +to_pem+ to +path+ with the given # +permissions+. If passed +cipher+ and +passphrase+ those arguments will be # passed to +to_pem+. def self.write pemmable, path, permissions = 0600, passphrase = nil, cipher = KEY_CIPHER path = File.expand_path path open path, 'wb', permissions do |io| if passphrase and cipher io.write pemmable.to_pem cipher, passphrase else io.write pemmable.to_pem end end path end reset end if defined?(OpenSSL::SSL) then require 'rubygems/security/policy' require 'rubygems/security/policies' require 'rubygems/security/trust_dir' end require 'rubygems/security/signer' PK!!(99$2.2.0/rubygems/stub_specification.rbnu[## # Gem::StubSpecification reads the stub: line from the gemspec. This prevents # us having to eval the entire gemspec in order to find out certain # information. class Gem::StubSpecification < Gem::BasicSpecification # :nodoc: PREFIX = "# stub: " OPEN_MODE = # :nodoc: if Object.const_defined? :Encoding then 'r:UTF-8:-' else 'r' end class StubLine # :nodoc: all attr_reader :parts def initialize(data) @parts = data[PREFIX.length..-1].split(" ") end def name @parts[0] end def version Gem::Version.new @parts[1] end def platform Gem::Platform.new @parts[2] end def require_paths @parts[3..-1].join(" ").split("\0") end end def initialize(filename) self.loaded_from = filename @data = nil @extensions = nil @name = nil @spec = nil end ## # True when this gem has been activated def activated? @activated ||= begin loaded = Gem.loaded_specs[name] loaded && loaded.version == version end end def build_extensions # :nodoc: return if default_gem? return if extensions.empty? to_spec.build_extensions end ## # If the gemspec contains a stubline, returns a StubLine instance. Otherwise # returns the full Gem::Specification. def data unless @data @extensions = [] open loaded_from, OPEN_MODE do |file| begin file.readline # discard encoding line stubline = file.readline.chomp if stubline.start_with?(PREFIX) then @data = StubLine.new stubline @extensions = $'.split "\0" if /\A#{PREFIX}/ =~ file.readline.chomp end rescue EOFError end end end @data ||= to_spec end private :data ## # Extensions for this gem def extensions return @extensions if @extensions data # load @extensions end ## # If a gem has a stub specification it doesn't need to bother with # compatibility with original_name gems. It was installed with the # normalized name. def find_full_gem_path # :nodoc: path = File.expand_path File.join gems_dir, full_name path.untaint path end ## # Full paths in the gem to add to $LOAD_PATH when this gem is # activated. def full_require_paths @require_paths ||= data.require_paths super end def missing_extensions? return false if default_gem? return false if extensions.empty? to_spec.missing_extensions? end ## # Name of the gem def name @name ||= data.name end ## # Platform of the gem def platform @platform ||= data.platform end ## # Require paths of the gem def require_paths @require_paths ||= data.require_paths super end ## # The full Gem::Specification for this gem, loaded from evalling its gemspec def to_spec @spec ||= if @data then Gem.loaded_specs.values.find { |spec| spec.name == name and spec.version == version } end @spec ||= Gem::Specification.load(loaded_from) @spec.ignored = @ignored if instance_variable_defined? :@ignored @spec end ## # Is this StubSpecification valid? i.e. have we found a stub line, OR does # the filename contain a valid gemspec? def valid? data end ## # Version of the gem def version @version ||= data.version end ## # Is there a stub line present for this StubSpecification? def stubbed? data.is_a? StubLine end end PK!GiGa##2.2.0/rubygems/specification.rbnu[# -*- coding: utf-8 -*- #-- # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. # All rights reserved. # See LICENSE.txt for permissions. #++ require 'rubygems/version' require 'rubygems/requirement' require 'rubygems/platform' require 'rubygems/deprecate' require 'rubygems/basic_specification' require 'rubygems/stub_specification' require 'rubygems/util/stringio' require 'uri' ## # The Specification class contains the information for a Gem. Typically # defined in a .gemspec file or a Rakefile, and looks like this: # # Gem::Specification.new do |s| # s.name = 'example' # s.version = '0.1.0' # s.licenses = ['MIT'] # s.summary = "This is an example!" # s.description = "Much longer explanation of the example!" # s.authors = ["Ruby Coder"] # s.email = 'rubycoder@example.com' # s.files = ["lib/example.rb"] # s.homepage = 'https://rubygems.org/gems/example' # end # # Starting in RubyGems 2.0, a Specification can hold arbitrary # metadata. See #metadata for restrictions on the format and size of metadata # items you may add to a specification. class Gem::Specification < Gem::BasicSpecification # REFACTOR: Consider breaking out this version stuff into a separate # module. There's enough special stuff around it that it may justify # a separate class. ## # The version number of a specification that does not specify one # (i.e. RubyGems 0.7 or earlier). NONEXISTENT_SPECIFICATION_VERSION = -1 ## # The specification version applied to any new Specification instances # created. This should be bumped whenever something in the spec format # changes. # # Specification Version History: # # spec ruby # ver ver yyyy-mm-dd description # -1 <0.8.0 pre-spec-version-history # 1 0.8.0 2004-08-01 Deprecated "test_suite_file" for "test_files" # "test_file=x" is a shortcut for "test_files=[x]" # 2 0.9.5 2007-10-01 Added "required_rubygems_version" # Now forward-compatible with future versions # 3 1.3.2 2009-01-03 Added Fixnum validation to specification_version # 4 1.9.0 2011-06-07 Added metadata #-- # When updating this number, be sure to also update #to_ruby. # # NOTE RubyGems < 1.2 cannot load specification versions > 2. CURRENT_SPECIFICATION_VERSION = 4 # :nodoc: ## # An informal list of changes to the specification. The highest-valued # key should be equal to the CURRENT_SPECIFICATION_VERSION. SPECIFICATION_VERSION_HISTORY = { # :nodoc: -1 => ['(RubyGems versions up to and including 0.7 did not have versioned specifications)'], 1 => [ 'Deprecated "test_suite_file" in favor of the new, but equivalent, "test_files"', '"test_file=x" is a shortcut for "test_files=[x]"' ], 2 => [ 'Added "required_rubygems_version"', 'Now forward-compatible with future versions', ], 3 => [ 'Added Fixnum validation to the specification_version' ], 4 => [ 'Added sandboxed freeform metadata to the specification version.' ] } MARSHAL_FIELDS = { # :nodoc: -1 => 16, 1 => 16, 2 => 16, 3 => 17, 4 => 18, } today = Time.now.utc TODAY = Time.utc(today.year, today.month, today.day) # :nodoc: LOAD_CACHE = {} # :nodoc: private_constant :LOAD_CACHE if defined? private_constant VALID_NAME_PATTERN = /\A[a-zA-Z0-9\.\-\_]+\z/ # :nodoc: # :startdoc: ## # List of attribute names: [:name, :version, ...] @@required_attributes = [:rubygems_version, :specification_version, :name, :version, :date, :summary, :require_paths] ## # Map of attribute names to default values. @@default_value = { :authors => [], :autorequire => nil, :bindir => 'bin', :cert_chain => [], :date => TODAY, :dependencies => [], :description => nil, :email => nil, :executables => [], :extensions => [], :extra_rdoc_files => [], :files => [], :homepage => nil, :licenses => [], :metadata => {}, :name => nil, :platform => Gem::Platform::RUBY, :post_install_message => nil, :rdoc_options => [], :require_paths => ['lib'], :required_ruby_version => Gem::Requirement.default, :required_rubygems_version => Gem::Requirement.default, :requirements => [], :rubyforge_project => nil, :rubygems_version => Gem::VERSION, :signing_key => nil, :specification_version => CURRENT_SPECIFICATION_VERSION, :summary => nil, :test_files => [], :version => nil, } Dupable = { } # :nodoc: @@default_value.each do |k,v| case v when Time, Numeric, Symbol, true, false, nil Dupable[k] = false else Dupable[k] = true end end @@attributes = @@default_value.keys.sort_by { |s| s.to_s } @@array_attributes = @@default_value.reject { |k,v| v != [] }.keys @@nil_attributes, @@non_nil_attributes = @@default_value.keys.partition { |k| @@default_value[k].nil? } ###################################################################### # :section: Required gemspec attributes ## # This gem's name. # # Usage: # # spec.name = 'rake' attr_accessor :name ## # This gem's version. # # The version string can contain numbers and periods, such as +1.0.0+. # A gem is a 'prerelease' gem if the version has a letter in it, such as # +1.0.0.pre+. # # Usage: # # spec.version = '0.4.1' attr_reader :version ## # Paths in the gem to add to $LOAD_PATH when this gem is # activated. # # See also #require_paths # # If you have an extension you do not need to add "ext" to the # require path, the extension build process will copy the extension files # into "lib" for you. # # The default value is "lib" # # Usage: # # # If all library files are in the root directory... # spec.require_paths = ['.'] def require_paths=(val) @require_paths = Array(val) end ## # The version of RubyGems used to create this gem. # # Do not set this, it is set automatically when the gem is packaged. attr_accessor :rubygems_version ## # A short summary of this gem's description. Displayed in `gem list -d`. # # The #description should be more detailed than the summary. # # Usage: # # spec.summary = "This is a small summary of my gem" attr_reader :summary ## # Singular writer for #authors # # Usage: # # spec.author = 'John Jones' def author= o self.authors = [o] end ## # Sets the list of authors, ensuring it is an array. # # Usage: # # spec.authors = ['John Jones', 'Mary Smith'] def authors= value @authors = Array(value).flatten.grep(String) end ## # The platform this gem runs on. # # This is usually Gem::Platform::RUBY or Gem::Platform::CURRENT. # # Most gems contain pure Ruby code; they should simply leave the default # value in place. Some gems contain C (or other) code to be compiled into a # Ruby "extension". The gem should leave the default value in place unless # the code will only compile on a certain type of system. Some gems consist # of pre-compiled code ("binary gems"). It's especially important that they # set the platform attribute appropriately. A shortcut is to set the # platform to Gem::Platform::CURRENT, which will cause the gem builder to set # the platform to the appropriate value for the system on which the build is # being performed. # # If this attribute is set to a non-default value, it will be included in # the filename of the gem when it is built such as: # nokogiri-1.6.0-x86-mingw32.gem # # Usage: # # spec.platform = Gem::Platform.local def platform= platform if @original_platform.nil? or @original_platform == Gem::Platform::RUBY then @original_platform = platform end case platform when Gem::Platform::CURRENT then @new_platform = Gem::Platform.local @original_platform = @new_platform.to_s when Gem::Platform then @new_platform = platform # legacy constants when nil, Gem::Platform::RUBY then @new_platform = Gem::Platform::RUBY when 'mswin32' then # was Gem::Platform::WIN32 @new_platform = Gem::Platform.new 'x86-mswin32' when 'i586-linux' then # was Gem::Platform::LINUX_586 @new_platform = Gem::Platform.new 'x86-linux' when 'powerpc-darwin' then # was Gem::Platform::DARWIN @new_platform = Gem::Platform.new 'ppc-darwin' else @new_platform = Gem::Platform.new platform end @platform = @new_platform.to_s invalidate_memoized_attributes @new_platform end ## # Files included in this gem. You cannot append to this accessor, you must # assign to it. # # Only add files you can require to this list, not directories, etc. # # Directories are automatically stripped from this list when building a gem, # other non-files cause an error. # # Usage: # # require 'rake' # spec.files = FileList['lib/**/*.rb', # 'bin/*', # '[A-Z]*', # 'test/**/*'].to_a # # # or without Rake... # spec.files = Dir['lib/**/*.rb'] + Dir['bin/*'] # spec.files += Dir['[A-Z]*'] + Dir['test/**/*'] # spec.files.reject! { |fn| fn.include? "CVS" } def files # DO NOT CHANGE TO ||= ! This is not a normal accessor. (yes, it sucks) # DOC: Why isn't it normal? Why does it suck? How can we fix this? @files = [@files, @test_files, add_bindir(@executables), @extra_rdoc_files, @extensions, ].flatten.uniq.compact.sort end ###################################################################### # :section: Optional gemspec attributes ## # The path in the gem for executable scripts. Usually 'bin' # # Usage: # # spec.bindir = 'bin' attr_accessor :bindir ## # The certificate chain used to sign this gem. See Gem::Security for # details. attr_accessor :cert_chain ## # A long description of this gem # # The description should be more detailed than the summary but not # excessively long. A few paragraphs is a recommended length with no # examples or formatting. # # Usage: # # spec.description = <<-EOF # Rake is a Make-like program implemented in Ruby. Tasks and # dependencies are specified in standard Ruby syntax. # EOF attr_reader :description ## # A contact email address (or addresses) for this gem # # Usage: # # spec.email = 'john.jones@example.com' # spec.email = ['jack@example.com', 'jill@example.com'] attr_accessor :email ## # The URL of this gem's home page # # Usage: # # spec.homepage = 'http://rake.rubyforge.org' attr_accessor :homepage ## # A message that gets displayed after the gem is installed. # # Usage: # # spec.post_install_message = "Thanks for installing!" attr_accessor :post_install_message ## # The version of Ruby required by this gem attr_reader :required_ruby_version ## # The RubyGems version required by this gem attr_reader :required_rubygems_version ## # The key used to sign this gem. See Gem::Security for details. attr_accessor :signing_key ## # :attr_accessor: metadata # # The metadata holds extra data for this gem that may be useful to other # consumers and is settable by gem authors without requiring an update to # the rubygems software. # # Metadata items have the following restrictions: # # * The metadata must be a Hash object # * All keys and values must be Strings # * Keys can be a maximum of 128 bytes and values can be a maximum of 1024 # bytes # * All strings must be UTF-8, no binary data is allowed # # To add metadata for the location of a issue tracker: # # s.metadata = { "issue_tracker" => "https://example/issues" } attr_accessor :metadata ## # Adds a development dependency named +gem+ with +requirements+ to this # gem. # # Usage: # # spec.add_development_dependency 'example', '~> 1.1', '>= 1.1.4' # # Development dependencies aren't installed by default and aren't # activated when a gem is required. def add_development_dependency(gem, *requirements) add_dependency_with_type(gem, :development, *requirements) end ## # Adds a runtime dependency named +gem+ with +requirements+ to this gem. # # Usage: # # spec.add_runtime_dependency 'example', '~> 1.1', '>= 1.1.4' def add_runtime_dependency(gem, *requirements) add_dependency_with_type(gem, :runtime, *requirements) end ## # Executables included in the gem. # # For example, the rake gem has rake as an executable. You don’t specify the # full path (as in bin/rake); all application-style files are expected to be # found in bindir. These files must be executable Ruby files. Files that # use bash or other interpreters will not work. # # Executables included may only be ruby scripts, not scripts for other # languages or compiled binaries. # # Usage: # # spec.executables << 'rake' def executables @executables ||= [] end ## # Extensions to build when installing the gem, specifically the paths to # extconf.rb-style files used to compile extensions. # # These files will be run when the gem is installed, causing the C (or # whatever) code to be compiled on the user’s machine. # # Usage: # # spec.extensions << 'ext/rmagic/extconf.rb' # # See Gem::Ext::Builder for information about writing extensions for gems. def extensions @extensions ||= [] end ## # Extra files to add to RDoc such as README or doc/examples.txt # # When the user elects to generate the RDoc documentation for a gem (typically # at install time), all the library files are sent to RDoc for processing. # This option allows you to have some non-code files included for a more # complete set of documentation. # # Usage: # # spec.extra_rdoc_files = ['README', 'doc/user-guide.txt'] def extra_rdoc_files @extra_rdoc_files ||= [] end ## # The version of RubyGems that installed this gem. Returns # Gem::Version.new(0) for gems installed by versions earlier # than RubyGems 2.2.0. def installed_by_version # :nodoc: @installed_by_version ||= Gem::Version.new(0) end ## # Sets the version of RubyGems that installed this gem. See also # #installed_by_version. def installed_by_version= version # :nodoc: @installed_by_version = Gem::Version.new version end ## # :category: Recommended gemspec attributes # # The license for this gem. # # The license must be no more than 64 characters. # # This should just be the name of your license. The full text of the license # should be inside of the gem (at the top level) when you build it. # # The simplest way, is to specify the standard SPDX ID # https://spdx.org/licenses/ for the license. # Ideally you should pick one that is OSI (Open Source Initiative) # http://opensource.org/licenses/alphabetical approved. # # The most commonly used OSI approved licenses are BSD-3-Clause and MIT. # GitHub also provides a license picker at http://choosealicense.com/. # # You should specify a license for your gem so that people know how they are # permitted to use it, and any restrictions you're placing on it. Not # specifying a license means all rights are reserved; others have no rights # to use the code for any purpose. # # You can set multiple licenses with #licenses= # # Usage: # spec.license = 'MIT' def license=o self.licenses = [o] end ## # :category: Recommended gemspec attributes # The license(s) for the library. # # Each license must be a short name, no more than 64 characters. # # This should just be the name of your license. The full # text of the license should be inside of the gem when you build it. # # See #license= for more discussion # # Usage: # spec.licenses = ['MIT', 'GPL-2'] def licenses= licenses @licenses = Array licenses end ## # Specifies the rdoc options to be used when generating API documentation. # # Usage: # # spec.rdoc_options << '--title' << 'Rake -- Ruby Make' << # '--main' << 'README' << # '--line-numbers' def rdoc_options @rdoc_options ||= [] end ## # The version of Ruby required by this gem. The ruby version can be # specified to the patch-level: # # $ ruby -v -e 'p Gem.ruby_version' # ruby 2.0.0p247 (2013-06-27 revision 41674) [x86_64-darwin12.4.0] # # # # Usage: # # # This gem will work with 1.8.6 or greater... # spec.required_ruby_version = '>= 1.8.6' # # # Only with ruby 2.0.x # spec.required_ruby_version = '~> 2.0' def required_ruby_version= req @required_ruby_version = Gem::Requirement.create req end ## # The RubyGems version required by this gem def required_rubygems_version= req @required_rubygems_version = Gem::Requirement.create req end ## # Lists the external (to RubyGems) requirements that must be met for this gem # to work. It's simply information for the user. # # Usage: # # spec.requirements << 'libmagick, v6.0' # spec.requirements << 'A good graphics card' def requirements @requirements ||= [] end ## # A collection of unit test files. They will be loaded as unit tests when # the user requests a gem to be unit tested. # # Usage: # spec.test_files = Dir.glob('test/tc_*.rb') # spec.test_files = ['tests/test-suite.rb'] def test_files= files # :nodoc: @test_files = Array files end ###################################################################### # :section: Specification internals ## # True when this gemspec has been activated. This attribute is not persisted. attr_accessor :activated alias :activated? :activated ## # Autorequire was used by old RubyGems to automatically require a file. # # Deprecated: It is neither supported nor functional. attr_accessor :autorequire # :nodoc: ## # Sets the default executable for this gem. # # Deprecated: You must now specify the executable name to Gem.bin_path. attr_writer :default_executable ## # Allows deinstallation of gems with legacy platforms. attr_writer :original_platform # :nodoc: ## # The rubyforge project this gem lives under. i.e. RubyGems' # rubyforge_project is "rubygems". # # This option is deprecated. attr_accessor :rubyforge_project ## # The Gem::Specification version of this gemspec. # # Do not set this, it is set automatically when the gem is packaged. attr_accessor :specification_version def self._all # :nodoc: unless defined?(@@all) && @@all then @@all = stubs.map(&:to_spec) # After a reset, make sure already loaded specs # are still marked as activated. specs = {} Gem.loaded_specs.each_value{|s| specs[s] = true} @@all.each{|s| s.activated = true if specs[s]} end @@all end def self._clear_load_cache # :nodoc: LOAD_CACHE.clear end def self.each_gemspec(dirs) # :nodoc: dirs.each do |dir| Dir[File.join(dir, "*.gemspec")].each do |path| yield path.untaint end end end def self.each_stub(dirs) # :nodoc: each_gemspec(dirs) do |path| stub = Gem::StubSpecification.new(path) yield stub if stub.valid? end end def self.each_spec(dirs) # :nodoc: each_gemspec(dirs) do |path| spec = self.load path yield spec if spec end end ## # Returns a Gem::StubSpecification for every installed gem def self.stubs @@stubs ||= begin stubs = {} each_stub([default_specifications_dir] + dirs) do |stub| stubs[stub.full_name] ||= stub end stubs = stubs.values _resort!(stubs) stubs end end def self._resort!(specs) # :nodoc: specs.sort! { |a, b| names = a.name <=> b.name next names if names.nonzero? b.version <=> a.version } end ## # Loads the default specifications. It should be called only once. def self.load_defaults each_spec([default_specifications_dir]) do |spec| # #load returns nil if the spec is bad, so we just ignore # it at this stage Gem.register_default_spec(spec) end end ## # Adds +spec+ to the known specifications, keeping the collection # properly sorted. def self.add_spec spec # TODO: find all extraneous adds # puts # p :add_spec => [spec.full_name, caller.reject { |s| s =~ /minitest/ }] # TODO: flush the rest of the crap from the tests # raise "no dupes #{spec.full_name} in #{all_names.inspect}" if # _all.include? spec raise "nil spec!" unless spec # TODO: remove once we're happy with tests return if _all.include? spec _all << spec stubs << spec _resort!(_all) _resort!(stubs) end ## # Adds multiple specs to the known specifications. def self.add_specs *specs raise "nil spec!" if specs.any?(&:nil?) # TODO: remove once we're happy # TODO: this is much more efficient, but we need the extra checks for now # _all.concat specs # _resort! specs.each do |spec| # TODO: slow add_spec spec end end ## # Returns all specifications. This method is discouraged from use. # You probably want to use one of the Enumerable methods instead. def self.all warn "NOTE: Specification.all called from #{caller.first}" unless Gem::Deprecate.skip _all end ## # Sets the known specs to +specs+. Not guaranteed to work for you in # the future. Use at your own risk. Caveat emptor. Doomy doom doom. # Etc etc. # #-- # Makes +specs+ the known specs # Listen, time is a river # Winter comes, code breaks # # -- wilsonb def self.all= specs @@all = @@stubs = specs end ## # Return full names of all specs in sorted order. def self.all_names self._all.map(&:full_name) end ## # Return the list of all array-oriented instance variables. #-- # Not sure why we need to use so much stupid reflection in here... def self.array_attributes @@array_attributes.dup end ## # Return the list of all instance variables. #-- # Not sure why we need to use so much stupid reflection in here... def self.attribute_names @@attributes.dup end ## # Return the directories that Specification uses to find specs. def self.dirs @@dirs ||= Gem.path.collect { |dir| File.join dir.dup.untaint, "specifications" } end ## # Set the directories that Specification uses to find specs. Setting # this resets the list of known specs. def self.dirs= dirs self.reset @@dirs = Array(dirs).map { |dir| File.join dir, "specifications" } end extend Enumerable ## # Enumerate every known spec. See ::dirs= and ::add_spec to set the list of # specs. def self.each return enum_for(:each) unless block_given? self._all.each do |x| yield x end end ## # Returns every spec that matches +name+ and optional +requirements+. def self.find_all_by_name name, *requirements requirements = Gem::Requirement.default if requirements.empty? # TODO: maybe try: find_all { |s| spec === dep } Gem::Dependency.new(name, *requirements).matching_specs end ## # Find the best specification matching a +name+ and +requirements+. Raises # if the dependency doesn't resolve to a valid specification. def self.find_by_name name, *requirements requirements = Gem::Requirement.default if requirements.empty? # TODO: maybe try: find { |s| spec === dep } Gem::Dependency.new(name, *requirements).to_spec end ## # Return the best specification that contains the file matching +path+. def self.find_by_path path self.find { |spec| spec.contains_requirable_file? path } end ## # Return the best specification that contains the file matching +path+ # amongst the specs that are not activated. def self.find_inactive_by_path path stub = stubs.find { |s| s.contains_requirable_file? path unless s.activated? } stub && stub.to_spec end ## # Return currently unresolved specs that contain the file matching +path+. def self.find_in_unresolved path # TODO: do we need these?? Kill it specs = unresolved_deps.values.map { |dep| dep.to_specs }.flatten specs.find_all { |spec| spec.contains_requirable_file? path } end ## # Search through all unresolved deps and sub-dependencies and return # specs that contain the file matching +path+. def self.find_in_unresolved_tree path specs = unresolved_deps.values.map { |dep| dep.to_specs }.flatten specs.reverse_each do |spec| trails = [] spec.traverse do |from_spec, dep, to_spec, trail| next unless to_spec.conflicts.empty? trails << trail if to_spec.contains_requirable_file? path end next if trails.empty? return trails.map(&:reverse).sort.first.reverse end [] end ## # Special loader for YAML files. When a Specification object is loaded # from a YAML file, it bypasses the normal Ruby object initialization # routine (#initialize). This method makes up for that and deals with # gems of different ages. # # +input+ can be anything that YAML.load() accepts: String or IO. def self.from_yaml(input) Gem.load_yaml input = normalize_yaml_input input spec = Gem::SafeYAML.safe_load input if spec && spec.class == FalseClass then raise Gem::EndOfYAMLException end unless Gem::Specification === spec then raise Gem::Exception, "YAML data doesn't evaluate to gem specification" end spec.specification_version ||= NONEXISTENT_SPECIFICATION_VERSION spec.reset_nil_attributes_to_default spec end ## # Return the latest specs, optionally including prerelease specs if # +prerelease+ is true. def self.latest_specs prerelease = false result = Hash.new { |h,k| h[k] = {} } native = {} Gem::Specification.reverse_each do |spec| next if spec.version.prerelease? unless prerelease native[spec.name] = spec.version if spec.platform == Gem::Platform::RUBY result[spec.name][spec.platform] = spec end result.map(&:last).map(&:values).flatten.reject { |spec| minimum = native[spec.name] minimum && spec.version < minimum }.sort_by{ |tup| tup.name } end ## # Loads Ruby format gemspec from +file+. def self.load file return unless file file = file.dup.untaint return unless File.file?(file) spec = LOAD_CACHE[file] return spec if spec code = if defined? Encoding File.read file, :mode => 'r:UTF-8:-' else File.read file end code.untaint begin spec = eval code, binding, file if Gem::Specification === spec spec.loaded_from = File.expand_path file.to_s LOAD_CACHE[file] = spec return spec end warn "[#{file}] isn't a Gem::Specification (#{spec.class} instead)." rescue SignalException, SystemExit raise rescue SyntaxError, Exception => e warn "Invalid gemspec in [#{file}]: #{e}" end nil end ## # Specification attributes that must be non-nil def self.non_nil_attributes @@non_nil_attributes.dup end ## # Make sure the YAML specification is properly formatted with dashes def self.normalize_yaml_input(input) result = input.respond_to?(:read) ? input.read : input result = "--- " + result unless result =~ /\A--- / result.gsub!(/ !!null \n/, " \n") # date: 2011-04-26 00:00:00.000000000Z # date: 2011-04-26 00:00:00.000000000 Z result.gsub!(/^(date: \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+?)Z/, '\1 Z') result end ## # Return a list of all outdated local gem names. This method is HEAVY # as it must go fetch specifications from the server. # # Use outdated_and_latest_version if you wish to retrieve the latest remote # version as well. def self.outdated outdated_and_latest_version.map { |local, _| local.name } end ## # Enumerates the outdated local gems yielding the local specification and # the latest remote version. # # This method may take some time to return as it must check each local gem # against the server's index. def self.outdated_and_latest_version return enum_for __method__ unless block_given? # TODO: maybe we should switch to rubygems' version service? fetcher = Gem::SpecFetcher.fetcher latest_specs(true).each do |local_spec| dependency = Gem::Dependency.new local_spec.name, ">= #{local_spec.version}" remotes, = fetcher.search_for_dependency dependency remotes = remotes.map { |n, _| n.version } latest_remote = remotes.sort.last yield [local_spec, latest_remote] if latest_remote and local_spec.version < latest_remote end nil end ## # Removes +spec+ from the known specs. def self.remove_spec spec _all.delete spec stubs.delete_if { |s| s.full_name == spec.full_name } end ## # Is +name+ a required attribute? def self.required_attribute?(name) @@required_attributes.include? name.to_sym end ## # Required specification attributes def self.required_attributes @@required_attributes.dup end ## # Reset the list of known specs, running pre and post reset hooks # registered in Gem. def self.reset @@dirs = nil Gem.pre_reset_hooks.each { |hook| hook.call } @@all = nil @@stubs = nil _clear_load_cache unresolved = unresolved_deps unless unresolved.empty? then w = "W" + "ARN" warn "#{w}: Unresolved specs during Gem::Specification.reset:" unresolved.values.each do |dep| warn " #{dep}" end warn "#{w}: Clearing out unresolved specs." warn "Please report a bug if this causes problems." unresolved.clear end Gem.post_reset_hooks.each { |hook| hook.call } end # DOC: This method needs documented or nodoc'd def self.unresolved_deps @unresolved_deps ||= Hash.new { |h, n| h[n] = Gem::Dependency.new n } end ## # Load custom marshal format, re-initializing defaults as needed def self._load(str) array = Marshal.load str spec = Gem::Specification.new spec.instance_variable_set :@specification_version, array[1] current_version = CURRENT_SPECIFICATION_VERSION field_count = if spec.specification_version > current_version then spec.instance_variable_set :@specification_version, current_version MARSHAL_FIELDS[current_version] else MARSHAL_FIELDS[spec.specification_version] end if array.size < field_count then raise TypeError, "invalid Gem::Specification format #{array.inspect}" end # Cleanup any YAML::PrivateType. They only show up for an old bug # where nil => null, so just convert them to nil based on the type. array.map! { |e| e.kind_of?(YAML::PrivateType) ? nil : e } spec.instance_variable_set :@rubygems_version, array[0] # spec version spec.instance_variable_set :@name, array[2] spec.instance_variable_set :@version, array[3] spec.date = array[4] spec.instance_variable_set :@summary, array[5] spec.instance_variable_set :@required_ruby_version, array[6] spec.instance_variable_set :@required_rubygems_version, array[7] spec.instance_variable_set :@original_platform, array[8] spec.instance_variable_set :@dependencies, array[9] spec.instance_variable_set :@rubyforge_project, array[10] spec.instance_variable_set :@email, array[11] spec.instance_variable_set :@authors, array[12] spec.instance_variable_set :@description, array[13] spec.instance_variable_set :@homepage, array[14] spec.instance_variable_set :@has_rdoc, array[15] spec.instance_variable_set :@new_platform, array[16] spec.instance_variable_set :@platform, array[16].to_s spec.instance_variable_set :@license, array[17] spec.instance_variable_set :@metadata, array[18] spec.instance_variable_set :@loaded, false spec.instance_variable_set :@activated, false spec end def <=>(other) # :nodoc: sort_obj <=> other.sort_obj end def == other # :nodoc: self.class === other && name == other.name && version == other.version && platform == other.platform end ## # Dump only crucial instance variables. #-- # MAINTAIN ORDER! # (down with the man) def _dump(limit) Marshal.dump [ @rubygems_version, @specification_version, @name, @version, date, @summary, @required_ruby_version, @required_rubygems_version, @original_platform, @dependencies, @rubyforge_project, @email, @authors, @description, @homepage, true, # has_rdoc @new_platform, @licenses, @metadata ] end ## # Activate this spec, registering it as a loaded spec and adding # it's lib paths to $LOAD_PATH. Returns true if the spec was # activated, false if it was previously activated. Freaks out if # there are conflicts upon activation. def activate other = Gem.loaded_specs[self.name] if other then check_version_conflict other return false end raise_if_conflicts activate_dependencies add_self_to_load_path Gem.loaded_specs[self.name] = self @activated = true @loaded = true return true end ## # Activate all unambiguously resolved runtime dependencies of this # spec. Add any ambiguous dependencies to the unresolved list to be # resolved later, as needed. def activate_dependencies unresolved = Gem::Specification.unresolved_deps self.runtime_dependencies.each do |spec_dep| if loaded = Gem.loaded_specs[spec_dep.name] next if spec_dep.matches_spec? loaded msg = "can't satisfy '#{spec_dep}', already activated '#{loaded.full_name}'" e = Gem::LoadError.new msg e.name = spec_dep.name raise e end specs = spec_dep.to_specs if specs.size == 1 then specs.first.activate else name = spec_dep.name unresolved[name] = unresolved[name].merge spec_dep end end unresolved.delete self.name end ## # Returns an array with bindir attached to each executable in the # +executables+ list def add_bindir(executables) return nil if executables.nil? if @bindir then Array(executables).map { |e| File.join(@bindir, e) } else executables end rescue return nil end ## # Adds a dependency on gem +dependency+ with type +type+ that requires # +requirements+. Valid types are currently :runtime and # :development. def add_dependency_with_type(dependency, type, *requirements) requirements = if requirements.empty? then Gem::Requirement.default else requirements.flatten end unless dependency.respond_to?(:name) && dependency.respond_to?(:version_requirements) dependency = Gem::Dependency.new(dependency.to_s, requirements, type) end dependencies << dependency end private :add_dependency_with_type alias add_dependency add_runtime_dependency ## # Adds this spec's require paths to LOAD_PATH, in the proper location. def add_self_to_load_path return if default_gem? paths = full_require_paths # gem directories must come after -I and ENV['RUBYLIB'] insert_index = Gem.load_path_insert_index if insert_index then # gem directories must come after -I and ENV['RUBYLIB'] $LOAD_PATH.insert(insert_index, *paths) else # we are probably testing in core, -I and RUBYLIB don't apply $LOAD_PATH.unshift(*paths) end end ## # Singular reader for #authors. Returns the first author in the list def author val = authors and val.first end ## # The list of author names who wrote this gem. # # spec.authors = ['Chad Fowler', 'Jim Weirich', 'Rich Kilmer'] def authors @authors ||= [] end ## # Returns the full path to installed gem's bin directory. # # NOTE: do not confuse this with +bindir+, which is just 'bin', not # a full path. def bin_dir @bin_dir ||= File.join gem_dir, bindir # TODO: this is unfortunate end ## # Returns the full path to an executable named +name+ in this gem. def bin_file name File.join bin_dir, name end ## # Returns the build_args used to install the gem def build_args if File.exist? build_info_file build_info = File.readlines build_info_file build_info = build_info.map { |x| x.strip } build_info.delete "" build_info else [] end end ## # Builds extensions for this platform if the gem has extensions listed and # the gem.build_complete file is missing. def build_extensions # :nodoc: return if default_gem? return if extensions.empty? return if installed_by_version < Gem::Version.new('2.2.0.preview.2') return if File.exist? gem_build_complete_path return if !File.writable?(base_dir) return if !File.exist?(File.join(base_dir, 'extensions')) begin # We need to require things in $LOAD_PATH without looking for the # extension we are about to build. unresolved_deps = Gem::Specification.unresolved_deps.dup Gem::Specification.unresolved_deps.clear require 'rubygems/config_file' require 'rubygems/ext' require 'rubygems/user_interaction' ui = Gem::SilentUI.new Gem::DefaultUserInteraction.use_ui ui do builder = Gem::Ext::Builder.new self builder.build_extensions end ensure ui.close if ui Gem::Specification.unresolved_deps.replace unresolved_deps end end ## # Returns the full path to the build info directory def build_info_dir File.join base_dir, "build_info" end ## # Returns the full path to the file containing the build # information generated when the gem was installed def build_info_file File.join build_info_dir, "#{full_name}.info" end ## # Used to detect if the gem is bundled in older version of Ruby, but not # detectable as default gem (see BasicSpecification#default_gem?). def bundled_gem_in_old_ruby? !default_gem? && RUBY_VERSION < "2.0.0" && summary == "This #{name} is bundled with Ruby" end ## # Returns the full path to the cache directory containing this # spec's cached gem. def cache_dir @cache_dir ||= File.join base_dir, "cache" end ## # Returns the full path to the cached gem for this spec. def cache_file @cache_file ||= File.join cache_dir, "#{full_name}.gem" end ## # Return any possible conflicts against the currently loaded specs. def conflicts conflicts = {} self.runtime_dependencies.each { |dep| spec = Gem.loaded_specs[dep.name] if spec and not spec.satisfies_requirement? dep (conflicts[spec] ||= []) << dep end } conflicts end ## # The date this gem was created. Lazily defaults to the current UTC date. # # There is no need to set this in your gem specification. def date @date ||= TODAY end DateLike = Object.new # :nodoc: def DateLike.===(obj) # :nodoc: defined?(::Date) and Date === obj end DateTimeFormat = # :nodoc: /\A (\d{4})-(\d{2})-(\d{2}) (\s+ \d{2}:\d{2}:\d{2}\.\d+ \s* (Z | [-+]\d\d:\d\d) )? \Z/x ## # The date this gem was created # # DO NOT set this, it is set automatically when the gem is packaged. def date= date # We want to end up with a Time object with one-day resolution. # This is the cleanest, most-readable, faster-than-using-Date # way to do it. @date = case date when String then if DateTimeFormat =~ date then Time.utc($1.to_i, $2.to_i, $3.to_i) # Workaround for where the date format output from psych isn't # parsed as a Time object by syck and thus comes through as a # string. elsif /\A(\d{4})-(\d{2})-(\d{2}) \d{2}:\d{2}:\d{2}\.\d+?Z\z/ =~ date then Time.utc($1.to_i, $2.to_i, $3.to_i) else raise(Gem::InvalidSpecificationException, "invalid date format in specification: #{date.inspect}") end when Time, DateLike then Time.utc(date.year, date.month, date.day) else TODAY end end ## # The default executable for this gem. # # Deprecated: The name of the gem is assumed to be the name of the # executable now. See Gem.bin_path. def default_executable # :nodoc: if defined?(@default_executable) and @default_executable result = @default_executable elsif @executables and @executables.size == 1 result = Array(@executables).first else result = nil end result end ## # The default value for specification attribute +name+ def default_value name @@default_value[name] end ## # A list of Gem::Dependency objects this gem depends on. # # Use #add_dependency or #add_development_dependency to add dependencies to # a gem. def dependencies @dependencies ||= [] end ## # Return a list of all gems that have a dependency on this gemspec. The # list is structured with entries that conform to: # # [depending_gem, dependency, [list_of_gems_that_satisfy_dependency]] def dependent_gems out = [] Gem::Specification.each do |spec| spec.dependencies.each do |dep| if self.satisfies_requirement?(dep) then sats = [] find_all_satisfiers(dep) do |sat| sats << sat end out << [spec, dep, sats] end end end out end ## # Returns all specs that matches this spec's runtime dependencies. def dependent_specs runtime_dependencies.map { |dep| dep.to_specs }.flatten end ## # A detailed description of this gem. See also #summary def description= str @description = str.to_s end ## # List of dependencies that are used for development def development_dependencies dependencies.select { |d| d.type == :development } end ## # Returns the full path to this spec's documentation directory. If +type+ # is given it will be appended to the end. For example: # # spec.doc_dir # => "/path/to/gem_repo/doc/a-1" # # spec.doc_dir 'ri' # => "/path/to/gem_repo/doc/a-1/ri" def doc_dir type = nil @doc_dir ||= File.join base_dir, 'doc', full_name if type then File.join @doc_dir, type else @doc_dir end end def encode_with coder # :nodoc: mark_version coder.add 'name', @name coder.add 'version', @version platform = case @original_platform when nil, '' then 'ruby' when String then @original_platform else @original_platform.to_s end coder.add 'platform', platform attributes = @@attributes.map(&:to_s) - %w[name version platform] attributes.each do |name| coder.add name, instance_variable_get("@#{name}") end end def eql? other # :nodoc: self.class === other && same_attributes?(other) end ## # Singular accessor for #executables def executable val = executables and val.first end ## # Singular accessor for #executables def executable=o self.executables = [o] end ## # Sets executables to +value+, ensuring it is an array. Don't # use this, push onto the array instead. def executables= value # TODO: warn about setting instead of pushing @executables = Array(value) end ## # Sets extensions to +extensions+, ensuring it is an array. Don't # use this, push onto the array instead. def extensions= extensions # TODO: warn about setting instead of pushing @extensions = Array extensions end ## # Sets extra_rdoc_files to +files+, ensuring it is an array. Don't # use this, push onto the array instead. def extra_rdoc_files= files # TODO: warn about setting instead of pushing @extra_rdoc_files = Array files end ## # The default (generated) file name of the gem. See also #spec_name. # # spec.file_name # => "example-1.0.gem" def file_name "#{full_name}.gem" end ## # Sets files to +files+, ensuring it is an array. def files= files @files = Array files end ## # Finds all gems that satisfy +dep+ def find_all_satisfiers dep Gem::Specification.each do |spec| yield spec if spec.satisfies_requirement? dep end end private :find_all_satisfiers ## # Creates a duplicate spec without large blobs that aren't used at runtime. def for_cache spec = dup spec.files = nil spec.test_files = nil spec end def find_full_gem_path # :nodoc: super || File.expand_path(File.join(gems_dir, original_name)) end private :find_full_gem_path def full_name @full_name ||= super end ## # The path to the gem.build_complete file within the extension install # directory. def gem_build_complete_path # :nodoc: File.join extension_dir, 'gem.build_complete' end ## # Work around bundler removing my methods def gem_dir # :nodoc: super end ## # Deprecated and ignored, defaults to true. # # Formerly used to indicate this gem was RDoc-capable. def has_rdoc # :nodoc: true end ## # Deprecated and ignored. # # Formerly used to indicate this gem was RDoc-capable. def has_rdoc= ignored # :nodoc: @has_rdoc = true end alias :has_rdoc? :has_rdoc # :nodoc: ## # True if this gem has files in test_files def has_unit_tests? # :nodoc: not test_files.empty? end # :stopdoc: alias has_test_suite? has_unit_tests? # :startdoc: def hash # :nodoc: name.hash ^ version.hash end def init_with coder # :nodoc: @installed_by_version ||= nil yaml_initialize coder.tag, coder.map end ## # Specification constructor. Assigns the default values to the attributes # and yields itself for further initialization. Optionally takes +name+ and # +version+. def initialize name = nil, version = nil @loaded = false @activated = false self.loaded_from = nil @original_platform = nil @installed_by_version = nil @@nil_attributes.each do |key| instance_variable_set "@#{key}", nil end @@non_nil_attributes.each do |key| default = default_value(key) value = Dupable[key] ? default.dup : default instance_variable_set "@#{key}", value end @new_platform = Gem::Platform::RUBY self.name = name if name self.version = version if version yield self if block_given? end ## # Duplicates array_attributes from +other_spec+ so state isn't shared. def initialize_copy other_spec self.class.array_attributes.each do |name| name = :"@#{name}" next unless other_spec.instance_variable_defined? name begin val = other_spec.instance_variable_get(name) if val then instance_variable_set name, val.dup elsif Gem.configuration.really_verbose warn "WARNING: #{full_name} has an invalid nil value for #{name}" end rescue TypeError e = Gem::FormatException.new \ "#{full_name} has an invalid value for #{name}" e.file_path = loaded_from raise e end end end ## # Expire memoized instance variables that can incorrectly generate, replace # or miss files due changes in certain attributes used to compute them. def invalidate_memoized_attributes @full_name = nil @cache_file = nil end private :invalidate_memoized_attributes def inspect # :nodoc: if $DEBUG super else "#<#{self.class}:0x#{__id__.to_s(16)} #{full_name}>" end end ## # Returns a string usable in Dir.glob to match all requirable paths # for this spec. def lib_dirs_glob dirs = if self.require_paths.size > 1 then "{#{self.require_paths.join(',')}}" else self.require_paths.first end "#{self.full_gem_path}/#{dirs}" end ## # Files in the Gem under one of the require_paths def lib_files @files.select do |file| require_paths.any? do |path| file.start_with? path end end end ## # Singular accessor for #licenses def license val = licenses and val.first end ## # Plural accessor for setting licenses # # See #license= for details def licenses @licenses ||= [] end def loaded_from= path # :nodoc: super @bin_dir = nil @cache_dir = nil @cache_file = nil @doc_dir = nil @ri_dir = nil @spec_dir = nil @spec_file = nil end ## # Sets the rubygems_version to the current RubyGems version. def mark_version @rubygems_version = Gem::VERSION end ## # Return all files in this gem that match for +glob+. def matches_for_glob glob # TODO: rename? # TODO: do we need these?? Kill it glob = File.join(self.lib_dirs_glob, glob) Dir[glob].map { |f| f.untaint } # FIX our tests are broken, run w/ SAFE=1 end ## # Warn about unknown attributes while loading a spec. def method_missing(sym, *a, &b) # :nodoc: if @specification_version > CURRENT_SPECIFICATION_VERSION and sym.to_s =~ /=$/ then warn "ignoring #{sym} loading #{full_name}" if $DEBUG else super end end ## # Is this specification missing its extensions? When this returns true you # probably want to build_extensions def missing_extensions? return false if default_gem? return false if extensions.empty? return false if installed_by_version < Gem::Version.new('2.2.0.preview.2') return false if File.exist? gem_build_complete_path true end ## # Normalize the list of files so that: # * All file lists have redundancies removed. # * Files referenced in the extra_rdoc_files are included in the package # file list. def normalize if defined?(@extra_rdoc_files) and @extra_rdoc_files then @extra_rdoc_files.uniq! @files ||= [] @files.concat(@extra_rdoc_files) end @files = @files.uniq if @files @extensions = @extensions.uniq if @extensions @test_files = @test_files.uniq if @test_files @executables = @executables.uniq if @executables @extra_rdoc_files = @extra_rdoc_files.uniq if @extra_rdoc_files end ## # Return a NameTuple that represents this Specification def name_tuple Gem::NameTuple.new name, version, original_platform end ## # Returns the full name (name-version) of this gemspec using the original # platform. For use with legacy gems. def original_name # :nodoc: if platform == Gem::Platform::RUBY or platform.nil? then "#{@name}-#{@version}" else "#{@name}-#{@version}-#{@original_platform}" end end ## # Cruft. Use +platform+. def original_platform # :nodoc: @original_platform ||= platform end ## # The platform this gem runs on. See Gem::Platform for details. def platform @new_platform ||= Gem::Platform::RUBY end def pretty_print(q) # :nodoc: q.group 2, 'Gem::Specification.new do |s|', 'end' do q.breakable attributes = @@attributes - [:name, :version] attributes.unshift :installed_by_version attributes.unshift :version attributes.unshift :name attributes.each do |attr_name| current_value = self.send attr_name if current_value != default_value(attr_name) or self.class.required_attribute? attr_name then q.text "s.#{attr_name} = " if attr_name == :date then current_value = current_value.utc q.text "Time.utc(#{current_value.year}, #{current_value.month}, #{current_value.day})" else q.pp current_value end q.breakable end end end end ## # Raise an exception if the version of this spec conflicts with the one # that is already loaded (+other+) def check_version_conflict other # :nodoc: return if self.version == other.version # This gem is already loaded. If the currently loaded gem is not in the # list of candidate gems, then we have a version conflict. msg = "can't activate #{full_name}, already activated #{other.full_name}" e = Gem::LoadError.new msg e.name = self.name # TODO: e.requirement = dep.requirement raise e end private :check_version_conflict ## # Check the spec for possible conflicts and freak out if there are any. def raise_if_conflicts # :nodoc: conf = self.conflicts unless conf.empty? then raise Gem::ConflictError.new self, conf end end ## # Sets rdoc_options to +value+, ensuring it is an array. Don't # use this, push onto the array instead. def rdoc_options= options # TODO: warn about setting instead of pushing @rdoc_options = Array options end ## # Singular accessor for #require_paths def require_path val = require_paths and val.first end ## # Singular accessor for #require_paths def require_path= path self.require_paths = Array(path) end ## # Set requirements to +req+, ensuring it is an array. Don't # use this, push onto the array instead. def requirements= req # TODO: warn about setting instead of pushing @requirements = Array req end def respond_to_missing? m, include_private = false # :nodoc: false end ## # Returns the full path to this spec's ri directory. def ri_dir @ri_dir ||= File.join base_dir, 'ri', full_name end ## # Return a string containing a Ruby code representation of the given # object. def ruby_code(obj) case obj when String then obj.dump when Array then '[' + obj.map { |x| ruby_code x }.join(", ") + ']' when Hash then seg = obj.keys.sort.map { |k| "#{k.to_s.dump} => #{obj[k].to_s.dump}" } "{ #{seg.join(', ')} }" when Gem::Version then obj.to_s.dump when DateLike then obj.strftime('%Y-%m-%d').dump when Time then obj.strftime('%Y-%m-%d').dump when Numeric then obj.inspect when true, false, nil then obj.inspect when Gem::Platform then "Gem::Platform.new(#{obj.to_a.inspect})" when Gem::Requirement then list = obj.as_list "Gem::Requirement.new(#{ruby_code(list.size == 1 ? obj.to_s : list)})" else raise Gem::Exception, "ruby_code case not handled: #{obj.class}" end end private :ruby_code ## # List of dependencies that will automatically be activated at runtime. def runtime_dependencies dependencies.select { |d| d.type == :runtime } end ## # True if this gem has the same attributes as +other+. def same_attributes? spec @@attributes.all? { |name, default| self.send(name) == spec.send(name) } end private :same_attributes? ## # Checks if this specification meets the requirement of +dependency+. def satisfies_requirement? dependency return @name == dependency.name && dependency.requirement.satisfied_by?(@version) end ## # Returns an object you can use to sort specifications in #sort_by. def sort_obj [@name, @version, @new_platform == Gem::Platform::RUBY ? -1 : 1] end ## # Used by Gem::Resolver to order Gem::Specification objects def source # :nodoc: Gem::Source::Installed.new end ## # Returns the full path to the directory containing this spec's # gemspec file. eg: /usr/local/lib/ruby/gems/1.8/specifications def spec_dir @spec_dir ||= File.join base_dir, "specifications" end ## # Returns the full path to this spec's gemspec file. # eg: /usr/local/lib/ruby/gems/1.8/specifications/mygem-1.0.gemspec def spec_file @spec_file ||= File.join spec_dir, "#{full_name}.gemspec" end ## # The default name of the gemspec. See also #file_name # # spec.spec_name # => "example-1.0.gemspec" def spec_name "#{full_name}.gemspec" end ## # A short summary of this gem's description. def summary= str @summary = str.to_s.strip. gsub(/(\w-)\n[ \t]*(\w)/, '\1\2').gsub(/\n[ \t]*/, " ") # so. weird. end ## # Singular accessor for #test_files def test_file # :nodoc: val = test_files and val.first end ## # Singular mutator for #test_files def test_file= file # :nodoc: self.test_files = [file] end ## # Test files included in this gem. You cannot append to this accessor, you # must assign to it. def test_files # :nodoc: # Handle the possibility that we have @test_suite_file but not # @test_files. This will happen when an old gem is loaded via # YAML. if defined? @test_suite_file then @test_files = [@test_suite_file].flatten @test_suite_file = nil end if defined?(@test_files) and @test_files then @test_files else @test_files = [] end end ## # Returns a Ruby code representation of this specification, such that it can # be eval'ed and reconstruct the same specification later. Attributes that # still have their default values are omitted. def to_ruby mark_version result = [] result << "# -*- encoding: utf-8 -*-" result << "#{Gem::StubSpecification::PREFIX}#{name} #{version} #{platform} #{raw_require_paths.join("\0")}" result << "#{Gem::StubSpecification::PREFIX}#{extensions.join "\0"}" unless extensions.empty? result << nil result << "Gem::Specification.new do |s|" result << " s.name = #{ruby_code name}" result << " s.version = #{ruby_code version}" unless platform.nil? or platform == Gem::Platform::RUBY then result << " s.platform = #{ruby_code original_platform}" end result << "" result << " s.required_rubygems_version = #{ruby_code required_rubygems_version} if s.respond_to? :required_rubygems_version=" if metadata and !metadata.empty? result << " s.metadata = #{ruby_code metadata} if s.respond_to? :metadata=" end result << " s.require_paths = #{ruby_code raw_require_paths}" handled = [ :dependencies, :name, :platform, :require_paths, :required_rubygems_version, :specification_version, :version, :has_rdoc, :default_executable, :metadata ] @@attributes.each do |attr_name| next if handled.include? attr_name current_value = self.send(attr_name) if current_value != default_value(attr_name) or self.class.required_attribute? attr_name then result << " s.#{attr_name} = #{ruby_code current_value}" end end if @installed_by_version then result << nil result << " s.installed_by_version = \"#{Gem::VERSION}\" if s.respond_to? :installed_by_version" end unless dependencies.empty? then result << nil result << " if s.respond_to? :specification_version then" result << " s.specification_version = #{specification_version}" result << nil result << " if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then" dependencies.each do |dep| req = dep.requirements_list.inspect dep.instance_variable_set :@type, :runtime if dep.type.nil? # HACK result << " s.add_#{dep.type}_dependency(%q<#{dep.name}>, #{req})" end result << " else" dependencies.each do |dep| version_reqs_param = dep.requirements_list.inspect result << " s.add_dependency(%q<#{dep.name}>, #{version_reqs_param})" end result << ' end' result << " else" dependencies.each do |dep| version_reqs_param = dep.requirements_list.inspect result << " s.add_dependency(%q<#{dep.name}>, #{version_reqs_param})" end result << " end" end result << "end" result << nil result.join "\n" end ## # Returns a Ruby lighter-weight code representation of this specification, # used for indexing only. # # See #to_ruby. def to_ruby_for_cache for_cache.to_ruby end def to_s # :nodoc: "#" end ## # Returns self def to_spec self end def to_yaml(opts = {}) # :nodoc: if (YAML.const_defined?(:ENGINE) && !YAML::ENGINE.syck?) || (defined?(Psych) && YAML == Psych) then # Because the user can switch the YAML engine behind our # back, we have to check again here to make sure that our # psych code was properly loaded, and load it if not. unless Gem.const_defined?(:NoAliasYAMLTree) require 'rubygems/psych_tree' end builder = Gem::NoAliasYAMLTree.create builder << self ast = builder.tree io = Gem::StringSink.new io.set_encoding Encoding::UTF_8 if Object.const_defined? :Encoding Psych::Visitors::Emitter.new(io).accept(ast) io.string.gsub(/ !!null \n/, " \n") else YAML.quick_emit object_id, opts do |out| out.map taguri, to_yaml_style do |map| encode_with map end end end end ## # Recursively walk dependencies of this spec, executing the +block+ for each # hop. def traverse trail = [], &block trail = trail + [self] runtime_dependencies.each do |dep| dep.to_specs.each do |dep_spec| block[self, dep, dep_spec, trail + [dep_spec]] dep_spec.traverse(trail, &block) unless trail.map(&:name).include? dep_spec.name end end end ## # Checks that the specification contains all required fields, and does a # very basic sanity check. # # Raises InvalidSpecificationException if the spec does not pass the # checks.. def validate packaging = true @warnings = 0 require 'rubygems/user_interaction' extend Gem::UserInteraction normalize nil_attributes = self.class.non_nil_attributes.find_all do |attrname| instance_variable_get("@#{attrname}").nil? end unless nil_attributes.empty? then raise Gem::InvalidSpecificationException, "#{nil_attributes.join ', '} must not be nil" end if packaging and rubygems_version != Gem::VERSION then raise Gem::InvalidSpecificationException, "expected RubyGems version #{Gem::VERSION}, was #{rubygems_version}" end @@required_attributes.each do |symbol| unless self.send symbol then raise Gem::InvalidSpecificationException, "missing value for attribute #{symbol}" end end if !name.is_a?(String) then raise Gem::InvalidSpecificationException, "invalid value for attribute name: \"#{name.inspect}\" must be a string" elsif name !~ /[a-zA-Z]/ then raise Gem::InvalidSpecificationException, "invalid value for attribute name: #{name.dump} must include at least one letter" elsif name !~ VALID_NAME_PATTERN then raise Gem::InvalidSpecificationException, "invalid value for attribute name: #{name.dump} can only include letters, numbers, dashes, and underscores" end if raw_require_paths.empty? then raise Gem::InvalidSpecificationException, 'specification must have at least one require_path' end @files.delete_if { |x| File.directory?(x) } @test_files.delete_if { |x| File.directory?(x) } @executables.delete_if { |x| File.directory?(File.join(@bindir, x)) } @extra_rdoc_files.delete_if { |x| File.directory?(x) } @extensions.delete_if { |x| File.directory?(x) } non_files = files.reject { |x| File.file?(x) } unless not packaging or non_files.empty? then raise Gem::InvalidSpecificationException, "[\"#{non_files.join "\", \""}\"] are not files" end if files.include? file_name then raise Gem::InvalidSpecificationException, "#{full_name} contains itself (#{file_name}), check your files list" end unless specification_version.is_a?(Fixnum) raise Gem::InvalidSpecificationException, 'specification_version must be a Fixnum (did you mean version?)' end case platform when Gem::Platform, Gem::Platform::RUBY then # ok else raise Gem::InvalidSpecificationException, "invalid platform #{platform.inspect}, see Gem::Platform" end self.class.array_attributes.each do |field| val = self.send field klass = case field when :dependencies Gem::Dependency else String end unless Array === val and val.all? { |x| x.kind_of?(klass) } then raise(Gem::InvalidSpecificationException, "#{field} must be an Array of #{klass}") end end [:authors].each do |field| val = self.send field raise Gem::InvalidSpecificationException, "#{field} may not be empty" if val.empty? end unless Hash === metadata raise Gem::InvalidSpecificationException, 'metadata must be a hash' end metadata.keys.each do |k| if !k.kind_of?(String) raise Gem::InvalidSpecificationException, 'metadata keys must be a String' end if k.size > 128 raise Gem::InvalidSpecificationException, "metadata key too large (#{k.size} > 128)" end end metadata.values.each do |k| if !k.kind_of?(String) raise Gem::InvalidSpecificationException, 'metadata values must be a String' end if k.size > 1024 raise Gem::InvalidSpecificationException, "metadata value too large (#{k.size} > 1024)" end end licenses.each { |license| if license.length > 64 raise Gem::InvalidSpecificationException, "each license must be 64 characters or less" end } warning <<-warning if licenses.empty? licenses is empty, but is recommended. Use a license abbreviation from: http://opensource.org/licenses/alphabetical warning validate_permissions # reject lazy developers: lazy = '"FIxxxXME" or "TOxxxDO"'.gsub(/xxx/, '') unless authors.grep(/FI XME|TO DO/x).empty? then raise Gem::InvalidSpecificationException, "#{lazy} is not an author" end unless Array(email).grep(/FI XME|TO DO/x).empty? then raise Gem::InvalidSpecificationException, "#{lazy} is not an email" end if description =~ /FI XME|TO DO/x then raise Gem::InvalidSpecificationException, "#{lazy} is not a description" end if summary =~ /FI XME|TO DO/x then raise Gem::InvalidSpecificationException, "#{lazy} is not a summary" end # Make sure a homepage is valid HTTP/HTTPS URI if homepage and not homepage.empty? begin homepage_uri = URI.parse(homepage) unless [URI::HTTP, URI::HTTPS].member? homepage_uri.class raise Gem::InvalidSpecificationException, "\"#{homepage}\" is not a valid HTTP URI" end rescue URI::InvalidURIError raise Gem::InvalidSpecificationException, "\"#{homepage}\" is not a valid HTTP URI" end end # Warnings %w[author description email homepage summary].each do |attribute| value = self.send attribute warning "no #{attribute} specified" if value.nil? or value.empty? end if description == summary then warning 'description and summary are identical' end # TODO: raise at some given date warning "deprecated autorequire specified" if autorequire executables.each do |executable| executable_path = File.join(bindir, executable) shebang = File.read(executable_path, 2) == '#!' warning "#{executable_path} is missing #! line" unless shebang end validate_dependencies true ensure if $! or @warnings > 0 then alert_warning "See http://guides.rubygems.org/specification-reference/ for help" end end ## # Checks that dependencies use requirements as we recommend. Warnings are # issued when dependencies are open-ended or overly strict for semantic # versioning. def validate_dependencies # :nodoc: seen = {} dependencies.each do |dep| if prev = seen[dep.name] then raise Gem::InvalidSpecificationException, <<-MESSAGE duplicate dependency on #{dep}, (#{prev.requirement}) use: add_runtime_dependency '#{dep.name}', '#{dep.requirement}', '#{prev.requirement}' MESSAGE end seen[dep.name] = dep prerelease_dep = dep.requirements_list.any? do |req| Gem::Requirement.new(req).prerelease? end warning "prerelease dependency on #{dep} is not recommended" if prerelease_dep overly_strict = dep.requirement.requirements.length == 1 && dep.requirement.requirements.any? do |op, version| op == '~>' and not version.prerelease? and version.segments.length > 2 and version.segments.first != 0 end if overly_strict then _, dep_version = dep.requirement.requirements.first base = dep_version.segments.first 2 warning <<-WARNING pessimistic dependency on #{dep} may be overly strict if #{dep.name} is semantically versioned, use: add_#{dep.type}_dependency '#{dep.name}', '~> #{base.join '.'}', '>= #{dep_version}' WARNING end open_ended = dep.requirement.requirements.all? do |op, version| not version.prerelease? and (op == '>' or op == '>=') end if open_ended then op, dep_version = dep.requirement.requirements.first base = dep_version.segments.first 2 bugfix = if op == '>' then ", '> #{dep_version}'" elsif op == '>=' and base != dep_version.segments then ", '>= #{dep_version}'" end warning <<-WARNING open-ended dependency on #{dep} is not recommended if #{dep.name} is semantically versioned, use: add_#{dep.type}_dependency '#{dep.name}', '~> #{base.join '.'}'#{bugfix} WARNING end end end ## # Checks to see if the files to be packaged are world-readable. def validate_permissions return if Gem.win_platform? files.each do |file| next if File.stat(file).mode & 0444 == 0444 warning "#{file} is not world-readable" end executables.each do |name| exec = File.join @bindir, name next if File.stat(exec).executable? warning "#{exec} is not executable" end end ## # Set the version to +version+, potentially also setting # required_rubygems_version if +version+ indicates it is a # prerelease. def version= version @version = Gem::Version.create(version) self.required_rubygems_version = '> 1.3.1' if @version.prerelease? invalidate_memoized_attributes return @version end def stubbed? false end def yaml_initialize(tag, vals) # :nodoc: vals.each do |ivar, val| case ivar when "date" # Force Date to go through the extra coerce logic in date= self.date = val.untaint else instance_variable_set "@#{ivar}", val.untaint end end @original_platform = @platform # for backwards compatibility self.platform = Gem::Platform.new @platform end ## # Reset nil attributes to their default values to make the spec valid def reset_nil_attributes_to_default nil_attributes = self.class.non_nil_attributes.find_all do |name| !instance_variable_defined?("@#{name}") || instance_variable_get("@#{name}").nil? end nil_attributes.each do |attribute| default = self.default_value attribute value = case default when Time, Numeric, Symbol, true, false, nil then default else default.dup end instance_variable_set "@#{attribute}", value end @installed_by_version ||= nil end def warning statement # :nodoc: @warnings += 1 alert_warning statement end extend Gem::Deprecate # TODO: # deprecate :has_rdoc, :none, 2011, 10 # deprecate :has_rdoc?, :none, 2011, 10 # deprecate :has_rdoc=, :none, 2011, 10 # deprecate :default_executable, :none, 2011, 10 # deprecate :default_executable=, :none, 2011, 10 # deprecate :file_name, :cache_file, 2011, 10 # deprecate :full_gem_path, :cache_file, 2011, 10 end # DOC: What is this and why is it here, randomly, at the end of this file? Gem.clear_paths PK!I2.2.0/rubygems/psych_tree.rbnu[module Gem if defined? ::Psych::Visitors class NoAliasYAMLTree < Psych::Visitors::YAMLTree def self.create new({}) end unless respond_to? :create def visit_String(str) return super unless str == '=' # or whatever you want quote = Psych::Nodes::Scalar::SINGLE_QUOTED @emitter.scalar str, nil, nil, false, true, quote end # Noop this out so there are no anchors def register(target, obj) end # This is ported over from the yaml_tree in 1.9.3 def format_time time if time.utc? time.strftime("%Y-%m-%d %H:%M:%S.%9N Z") else time.strftime("%Y-%m-%d %H:%M:%S.%9N %:z") end end private :format_time end end end PK![8oo2.2.0/rubygems/safe_yaml.rbnu[module Gem ### # This module is used for safely loading YAML specs from a gem. The # `safe_load` method defined on this module is specifically designed for # loading Gem specifications. For loading other YAML safely, please see # Psych.safe_load module SafeYAML WHITELISTED_CLASSES = %w( Symbol Time Date Gem::Dependency Gem::Platform Gem::Requirement Gem::Specification Gem::Version Gem::Version::Requirement YAML::Syck::DefaultKey Syck::DefaultKey ) WHITELISTED_SYMBOLS = %w( development runtime ) if ::YAML.respond_to? :safe_load def self.safe_load input ::YAML.safe_load(input, WHITELISTED_CLASSES, WHITELISTED_SYMBOLS, true) end def self.load input ::YAML.safe_load(input, [::Symbol]) end else warn "YAML safe loading is not available. Please upgrade psych to a version that supports safe loading (>= 2.0)." def self.safe_load input, *args ::YAML.load input end def self.load input ::YAML.load input end end end end PK!巹2.2.0/rubygems/compatibility.rbnu[# :stopdoc: #-- # This file contains all sorts of little compatibility hacks that we've # had to introduce over the years. Quarantining them into one file helps # us know when we can get rid of them. # # Ruby 1.9.x has introduced some things that are awkward, and we need to # support them, so we define some constants to use later. #++ module Gem # Only MRI 1.9.2 has the custom prelude. GEM_PRELUDE_SUCKAGE = RUBY_VERSION =~ /^1\.9\.2/ and RUBY_ENGINE == "ruby" end # Gem::QuickLoader exists in the gem prelude code in ruby 1.9.2 itself. # We gotta get rid of it if it's there, before we do anything else. if Gem::GEM_PRELUDE_SUCKAGE and defined?(Gem::QuickLoader) then Gem::QuickLoader.remove $LOADED_FEATURES.delete Gem::QuickLoader.path_to_full_rubygems_library if path = $LOADED_FEATURES.find {|n| n.end_with? '/rubygems.rb'} then raise LoadError, "another rubygems is already loaded from #{path}" end class << Gem remove_method :try_activate if Gem.respond_to?(:try_activate, true) end end module Gem RubyGemsVersion = VERSION # TODO remove at RubyGems 3 RbConfigPriorities = %w[ MAJOR MINOR TEENY EXEEXT RUBY_SO_NAME arch bindir datadir libdir ruby_install_name ruby_version rubylibprefix sitedir sitelibdir vendordir vendorlibdir rubylibdir ] unless defined?(ConfigMap) ## # Configuration settings from ::RbConfig ConfigMap = Hash.new do |cm, key| # TODO remove at RubyGems 3 cm[key] = RbConfig::CONFIG[key.to_s] end else RbConfigPriorities.each do |key| ConfigMap[key.to_sym] = RbConfig::CONFIG[key] end end RubyGemsPackageVersion = VERSION end PK!)8~ ~ 2.2.0/rubygems/name_tuple.rbnu[## # # Represents a gem of name +name+ at +version+ of +platform+. These # wrap the data returned from the indexes. require 'rubygems/platform' class Gem::NameTuple def initialize(name, version, platform="ruby") @name = name @version = version unless platform.kind_of? Gem::Platform platform = "ruby" if !platform or platform.empty? end @platform = platform end attr_reader :name, :version, :platform ## # Turn an array of [name, version, platform] into an array of # NameTuple objects. def self.from_list list list.map { |t| new(*t) } end ## # Turn an array of NameTuple objects back into an array of # [name, version, platform] tuples. def self.to_basic list list.map { |t| t.to_a } end ## # A null NameTuple, ie name=nil, version=0 def self.null new nil, Gem::Version.new(0), nil end ## # Returns the full name (name-version) of this Gem. Platform information is # included if it is not the default Ruby platform. This mimics the behavior # of Gem::Specification#full_name. def full_name case @platform when nil, 'ruby', '' "#{@name}-#{@version}" else "#{@name}-#{@version}-#{@platform}" end.untaint end ## # Indicate if this NameTuple matches the current platform. def match_platform? Gem::Platform.match @platform end ## # Indicate if this NameTuple is for a prerelease version. def prerelease? @version.prerelease? end ## # Return the name that the gemspec file would be def spec_name "#{full_name}.gemspec" end ## # Convert back to the [name, version, platform] tuple def to_a [@name, @version, @platform] end def inspect # :nodoc: "#" end alias to_s inspect # :nodoc: def <=> other [@name, @version, @platform == Gem::Platform::RUBY ? -1 : 1] <=> [other.name, other.version, other.platform == Gem::Platform::RUBY ? -1 : 1] end include Comparable ## # Compare with +other+. Supports another NameTuple or an Array # in the [name, version, platform] format. def == other case other when self.class @name == other.name and @version == other.version and @platform == other.platform when Array to_a == other else false end end alias_method :eql?, :== def hash to_a.hash end end PK!O(Q56562.2.0/rubygems/command.rbnu[#-- # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. # All rights reserved. # See LICENSE.txt for permissions. #++ require 'optparse' require 'rubygems/requirement' require 'rubygems/user_interaction' ## # Base class for all Gem commands. When creating a new gem command, define # #initialize, #execute, #arguments, #defaults_str, #description and #usage # (as appropriate). See the above mentioned methods for details. # # A very good example to look at is Gem::Commands::ContentsCommand class Gem::Command include Gem::UserInteraction ## # The name of the command. attr_reader :command ## # The options for the command. attr_reader :options ## # The default options for the command. attr_accessor :defaults ## # The name of the command for command-line invocation. attr_accessor :program_name ## # A short description of the command. attr_accessor :summary ## # Arguments used when building gems def self.build_args @build_args ||= [] end def self.build_args=(value) @build_args = value end def self.common_options @common_options ||= [] end def self.add_common_option(*args, &handler) Gem::Command.common_options << [args, handler] end def self.extra_args @extra_args ||= [] end def self.extra_args=(value) case value when Array @extra_args = value when String @extra_args = value.split end end ## # Return an array of extra arguments for the command. The extra arguments # come from the gem configuration file read at program startup. def self.specific_extra_args(cmd) specific_extra_args_hash[cmd] end ## # Add a list of extra arguments for the given command. +args+ may be an # array or a string to be split on white space. def self.add_specific_extra_args(cmd,args) args = args.split(/\s+/) if args.kind_of? String specific_extra_args_hash[cmd] = args end ## # Accessor for the specific extra args hash (self initializing). def self.specific_extra_args_hash @specific_extra_args_hash ||= Hash.new do |h,k| h[k] = Array.new end end ## # Initializes a generic gem command named +command+. +summary+ is a short # description displayed in `gem help commands`. +defaults+ are the default # options. Defaults should be mirrored in #defaults_str, unless there are # none. # # When defining a new command subclass, use add_option to add command-line # switches. # # Unhandled arguments (gem names, files, etc.) are left in # options[:args]. def initialize(command, summary=nil, defaults={}) @command = command @summary = summary @program_name = "gem #{command}" @defaults = defaults @options = defaults.dup @option_groups = Hash.new { |h,k| h[k] = [] } @parser = nil @when_invoked = nil end ## # True if +long+ begins with the characters from +short+. def begins?(long, short) return false if short.nil? long[0, short.length] == short end ## # Override to provide command handling. # # #options will be filled in with your parsed options, unparsed options will # be left in options[:args]. # # See also: #get_all_gem_names, #get_one_gem_name, # #get_one_optional_argument def execute raise Gem::Exception, "generic command has no actions" end ## # Display to the user that a gem couldn't be found and reasons why #-- # TODO: replace +domain+ with a parameter to suppress suggestions def show_lookup_failure(gem_name, version, errors, domain) if errors and !errors.empty? msg = "Could not find a valid gem '#{gem_name}' (#{version}), here is why:\n" errors.each { |x| msg << " #{x.wordy}\n" } alert_error msg else alert_error "Could not find a valid gem '#{gem_name}' (#{version}) in any repository" end unless domain == :local then # HACK suggestions = Gem::SpecFetcher.fetcher.suggest_gems_from_name gem_name unless suggestions.empty? alert_error "Possible alternatives: #{suggestions.join(", ")}" end end end ## # Get all gem names from the command line. def get_all_gem_names args = options[:args] if args.nil? or args.empty? then raise Gem::CommandLineError, "Please specify at least one gem name (e.g. gem build GEMNAME)" end args.select { |arg| arg !~ /^-/ } end ## # Get all [gem, version] from the command line. # # An argument in the form gem:ver is pull apart into the gen name and version, # respectively. def get_all_gem_names_and_versions get_all_gem_names.map do |name| if /\A(.*):(#{Gem::Requirement::PATTERN_RAW})\z/ =~ name [$1, $2] else [name] end end end ## # Get a single gem name from the command line. Fail if there is no gem name # or if there is more than one gem name given. def get_one_gem_name args = options[:args] if args.nil? or args.empty? then raise Gem::CommandLineError, "Please specify a gem name on the command line (e.g. gem build GEMNAME)" end if args.size > 1 then raise Gem::CommandLineError, "Too many gem names (#{args.join(', ')}); please specify only one" end args.first end ## # Get a single optional argument from the command line. If more than one # argument is given, return only the first. Return nil if none are given. def get_one_optional_argument args = options[:args] || [] args.first end ## # Override to provide details of the arguments a command takes. It should # return a left-justified string, one argument per line. # # For example: # # def usage # "#{program_name} FILE [FILE ...]" # end # # def arguments # "FILE name of file to find" # end def arguments "" end ## # Override to display the default values of the command options. (similar to # +arguments+, but displays the default values). # # For example: # # def defaults_str # --no-gems-first --no-all # end def defaults_str "" end ## # Override to display a longer description of what this command does. def description nil end ## # Override to display the usage for an individual gem command. # # The text "[options]" is automatically appended to the usage text. def usage program_name end ## # Display the help message for the command. def show_help parser.program_name = usage say parser end ## # Invoke the command with the given list of arguments. def invoke(*args) invoke_with_build_args args, nil end ## # Invoke the command with the given list of normal arguments # and additional build arguments. def invoke_with_build_args(args, build_args) handle_options args options[:build_args] = build_args if options[:help] then show_help elsif @when_invoked then @when_invoked.call options else execute end end ## # Call the given block when invoked. # # Normal command invocations just executes the +execute+ method of the # command. Specifying an invocation block allows the test methods to # override the normal action of a command to determine that it has been # invoked correctly. def when_invoked(&block) @when_invoked = block end ## # Add a command-line option and handler to the command. # # See OptionParser#make_switch for an explanation of +opts+. # # +handler+ will be called with two values, the value of the argument and # the options hash. # # If the first argument of add_option is a Symbol, it's used to group # options in output. See `gem help list` for an example. def add_option(*opts, &handler) # :yields: value, options group_name = Symbol === opts.first ? opts.shift : :options @option_groups[group_name] << [opts, handler] end ## # Remove previously defined command-line argument +name+. def remove_option(name) @option_groups.each do |_, option_list| option_list.reject! { |args, _| args.any? { |x| x =~ /^#{name}/ } } end end ## # Merge a set of command options with the set of default options (without # modifying the default option hash). def merge_options(new_options) @options = @defaults.clone new_options.each do |k,v| @options[k] = v end end ## # True if the command handles the given argument list. def handles?(args) begin parser.parse!(args.dup) return true rescue return false end end ## # Handle the given list of arguments by parsing them and recording the # results. def handle_options(args) args = add_extra_args(args) @options = Marshal.load Marshal.dump @defaults # deep copy parser.parse!(args) @options[:args] = args end ## # Adds extra args from ~/.gemrc def add_extra_args(args) result = [] s_extra = Gem::Command.specific_extra_args(@command) extra = Gem::Command.extra_args + s_extra until extra.empty? do ex = [] ex << extra.shift ex << extra.shift if extra.first.to_s =~ /^[^-]/ result << ex if handles?(ex) end result.flatten! result.concat(args) result end private def add_parser_description # :nodoc: return unless description formatted = description.split("\n\n").map do |chunk| wrap chunk, 80 - 4 end.join "\n" @parser.separator nil @parser.separator " Description:" formatted.split("\n").each do |line| @parser.separator " #{line.rstrip}" end end def add_parser_options # :nodoc: @parser.separator nil regular_options = @option_groups.delete :options configure_options "", regular_options @option_groups.sort_by { |n,_| n.to_s }.each do |group_name, option_list| @parser.separator nil configure_options group_name, option_list end end ## # Adds a section with +title+ and +content+ to the parser help view. Used # for adding command arguments and default arguments. def add_parser_run_info title, content return if content.empty? @parser.separator nil @parser.separator " #{title}:" content.split(/\n/).each do |line| @parser.separator " #{line}" end end def add_parser_summary # :nodoc: return unless @summary @parser.separator nil @parser.separator " Summary:" wrap(@summary, 80 - 4).split("\n").each do |line| @parser.separator " #{line.strip}" end end ## # Create on demand parser. def parser create_option_parser if @parser.nil? @parser end ## # Creates an option parser and fills it in with the help info for the # command. def create_option_parser @parser = OptionParser.new add_parser_options @parser.separator nil configure_options "Common", Gem::Command.common_options add_parser_run_info "Arguments", arguments add_parser_summary add_parser_description add_parser_run_info "Defaults", defaults_str end def configure_options(header, option_list) return if option_list.nil? or option_list.empty? header = header.to_s.empty? ? '' : "#{header} " @parser.separator " #{header}Options:" option_list.each do |args, handler| args.select { |arg| arg =~ /^-/ } @parser.on(*args) do |value| handler.call(value, @options) end end @parser.separator '' end ## # Wraps +text+ to +width+ def wrap(text, width) # :doc: text.gsub(/(.{1,#{width}})( +|$\n?)|(.{1,#{width}})/, "\\1\\3\n") end # ---------------------------------------------------------------- # Add the options common to all commands. add_common_option('-h', '--help', 'Get help on this command') do |value, options| options[:help] = true end add_common_option('-V', '--[no-]verbose', 'Set the verbose level of output') do |value, options| # Set us to "really verbose" so the progress meter works if Gem.configuration.verbose and value then Gem.configuration.verbose = 1 else Gem.configuration.verbose = value end end add_common_option('-q', '--quiet', 'Silence commands') do |value, options| Gem.configuration.verbose = false end # Backtrace and config-file are added so they show up in the help # commands. Both options are actually handled before the other # options get parsed. add_common_option('--config-file FILE', 'Use this config file instead of default') do end add_common_option('--backtrace', 'Show stack backtrace on errors') do end add_common_option('--debug', 'Turn on Ruby debugging') do end # :stopdoc: HELP = <<-HELP RubyGems is a sophisticated package manager for Ruby. This is a basic help message containing pointers to more information. Usage: gem -h/--help gem -v/--version gem command [arguments...] [options...] Examples: gem install rake gem list --local gem build package.gemspec gem help install Further help: gem help commands list all 'gem' commands gem help examples show some examples of usage gem help gem_dependencies gem dependencies file guide gem help platforms gem platforms guide gem help show help on COMMAND (e.g. 'gem help install') gem server present a web page at http://localhost:8808/ with info about installed gems Further information: http://guides.rubygems.org HELP # :startdoc: end ## # \Commands will be placed in this namespace module Gem::Commands end PK!"oo2.2.0/rubygems/source_local.rbnu[require 'rubygems/source' require 'rubygems/source_local' # TODO warn upon require, this file is deprecated. PK!gm*!!!2.2.0/rubygems/dependency.rbnu[## # The Dependency class holds a Gem name and a Gem::Requirement. require "rubygems/requirement" class Gem::Dependency ## # Valid dependency types. #-- # When this list is updated, be sure to change # Gem::Specification::CURRENT_SPECIFICATION_VERSION as well. # # REFACTOR: This type of constant, TYPES, indicates we might want # two classes, used via inheritance or duck typing. TYPES = [ :development, :runtime, ] ## # Dependency name or regular expression. attr_accessor :name ## # Allows you to force this dependency to be a prerelease. attr_writer :prerelease ## # Constructs a dependency with +name+ and +requirements+. The last # argument can optionally be the dependency type, which defaults to # :runtime. def initialize name, *requirements case name when String then # ok when Regexp then msg = ["NOTE: Dependency.new w/ a regexp is deprecated.", "Dependency.new called from #{Gem.location_of_caller.join(":")}"] warn msg.join("\n") unless Gem::Deprecate.skip else raise ArgumentError, "dependency name must be a String, was #{name.inspect}" end type = Symbol === requirements.last ? requirements.pop : :runtime requirements = requirements.first if 1 == requirements.length # unpack unless TYPES.include? type raise ArgumentError, "Valid types are #{TYPES.inspect}, " + "not #{type.inspect}" end @name = name @requirement = Gem::Requirement.create requirements @type = type @prerelease = false # This is for Marshal backwards compatibility. See the comments in # +requirement+ for the dirty details. @version_requirements = @requirement end ## # A dependency's hash is the XOR of the hashes of +name+, +type+, # and +requirement+. def hash # :nodoc: name.hash ^ type.hash ^ requirement.hash end def inspect # :nodoc: if prerelease? then "<%s type=%p name=%p requirements=%p prerelease=ok>" % [self.class, self.type, self.name, requirement.to_s] else "<%s type=%p name=%p requirements=%p>" % [self.class, self.type, self.name, requirement.to_s] end end ## # Does this dependency require a prerelease? def prerelease? @prerelease || requirement.prerelease? end ## # Is this dependency simply asking for the latest version # of a gem? def latest_version? @requirement.none? end def pretty_print q # :nodoc: q.group 1, 'Gem::Dependency.new(', ')' do q.pp name q.text ',' q.breakable q.pp requirement q.text ',' q.breakable q.pp type end end ## # What does this dependency require? def requirement return @requirement if defined?(@requirement) and @requirement # @version_requirements and @version_requirement are legacy ivar # names, and supported here because older gems need to keep # working and Dependency doesn't implement marshal_dump and # marshal_load. In a happier world, this would be an # attr_accessor. The horrifying instance_variable_get you see # below is also the legacy of some old restructurings. # # Note also that because of backwards compatibility (loading new # gems in an old RubyGems installation), we can't add explicit # marshaling to this class until we want to make a big # break. Maybe 2.0. # # Children, define explicit marshal and unmarshal behavior for # public classes. Marshal formats are part of your public API. # REFACTOR: See above if defined?(@version_requirement) && @version_requirement version = @version_requirement.instance_variable_get :@version @version_requirement = nil @version_requirements = Gem::Requirement.new version end @requirement = @version_requirements if defined?(@version_requirements) end def requirements_list requirement.as_list end def to_s # :nodoc: if type != :runtime then "#{name} (#{requirement}, #{type})" else "#{name} (#{requirement})" end end ## # Dependency type. def type @type ||= :runtime end def == other # :nodoc: Gem::Dependency === other && self.name == other.name && self.type == other.type && self.requirement == other.requirement end ## # Dependencies are ordered by name. def <=> other self.name <=> other.name end ## # Uses this dependency as a pattern to compare to +other+. This # dependency will match if the name matches the other's name, and # other has only an equal version requirement that satisfies this # dependency. def =~ other unless Gem::Dependency === other return unless other.respond_to?(:name) && other.respond_to?(:version) other = Gem::Dependency.new other.name, other.version end return false unless name === other.name reqs = other.requirement.requirements return false unless reqs.length == 1 return false unless reqs.first.first == '=' version = reqs.first.last requirement.satisfied_by? version end alias === =~ ## # :call-seq: # dep.match? name => true or false # dep.match? name, version => true or false # dep.match? spec => true or false # # Does this dependency match the specification described by +name+ and # +version+ or match +spec+? # # NOTE: Unlike #matches_spec? this method does not return true when the # version is a prerelease version unless this is a prerelease dependency. def match? obj, version=nil, allow_prerelease=false if !version name = obj.name version = obj.version else name = obj end return false unless self.name === name version = Gem::Version.new version return true if requirement.none? and not version.prerelease? return false if version.prerelease? and not allow_prerelease and not prerelease? requirement.satisfied_by? version end ## # Does this dependency match +spec+? # # NOTE: This is not a convenience method. Unlike #match? this method # returns true when +spec+ is a prerelease version even if this dependency # is not a prerelease dependency. def matches_spec? spec return false unless name === spec.name return true if requirement.none? requirement.satisfied_by?(spec.version) end ## # Merges the requirements of +other+ into this dependency def merge other unless name == other.name then raise ArgumentError, "#{self} and #{other} have different names" end default = Gem::Requirement.default self_req = self.requirement other_req = other.requirement return self.class.new name, self_req if other_req == default return self.class.new name, other_req if self_req == default self.class.new name, self_req.as_list.concat(other_req.as_list) end def matching_specs platform_only = false matches = Gem::Specification.stubs.find_all { |spec| self.name === spec.name and # TODO: == instead of === requirement.satisfied_by? spec.version }.map(&:to_spec) if platform_only matches.reject! { |spec| not Gem::Platform.match spec.platform } end matches.sort_by { |s| s.sort_obj } # HACK: shouldn't be needed end ## # True if the dependency will not always match the latest version. def specific? @requirement.specific? end def to_specs matches = matching_specs true # TODO: check Gem.activated_spec[self.name] in case matches falls outside if matches.empty? then specs = Gem::Specification.find_all { |s| s.name == name }.map { |x| x.full_name } if specs.empty? total = Gem::Specification.to_a.size msg = "Could not find '#{name}' (#{requirement}) among #{total} total gem(s)\n" else msg = "Could not find '#{name}' (#{requirement}) - did find: [#{specs.join ','}]\n" end msg << "Checked in 'GEM_PATH=#{Gem.path.join(File::PATH_SEPARATOR)}', execute `gem env` for more information" error = Gem::LoadError.new(msg) error.name = self.name error.requirement = self.requirement raise error end # TODO: any other resolver validations should go here matches end def to_spec matches = self.to_specs active = matches.find { |spec| spec.activated? } return active if active matches.delete_if { |spec| spec.version.prerelease? } unless prerelease? matches.last end end PK!F::"2.2.0/rubygems/user_interaction.rbnu[#-- # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. # All rights reserved. # See LICENSE.txt for permissions. #++ begin require 'io/console' rescue LoadError end ## # Module that defines the default UserInteraction. Any class including this # module will have access to the +ui+ method that returns the default UI. module Gem::DefaultUserInteraction ## # The default UI is a class variable of the singleton class for this # module. @ui = nil ## # Return the default UI. def self.ui @ui ||= Gem::ConsoleUI.new end ## # Set the default UI. If the default UI is never explicitly set, a simple # console based UserInteraction will be used automatically. def self.ui=(new_ui) @ui = new_ui end ## # Use +new_ui+ for the duration of +block+. def self.use_ui(new_ui) old_ui = @ui @ui = new_ui yield ensure @ui = old_ui end ## # See DefaultUserInteraction::ui def ui Gem::DefaultUserInteraction.ui end ## # See DefaultUserInteraction::ui= def ui=(new_ui) Gem::DefaultUserInteraction.ui = new_ui end ## # See DefaultUserInteraction::use_ui def use_ui(new_ui, &block) Gem::DefaultUserInteraction.use_ui(new_ui, &block) end end ## # UserInteraction allows RubyGems to interact with the user through standard # methods that can be replaced with more-specific UI methods for different # displays. # # Since UserInteraction dispatches to a concrete UI class you may need to # reference other classes for specific behavior such as Gem::ConsoleUI or # Gem::SilentUI. # # Example: # # class X # include Gem::UserInteraction # # def get_answer # n = ask("What is the meaning of life?") # end # end module Gem::UserInteraction include Gem::DefaultUserInteraction ## # Displays an alert +statement+. Asks a +question+ if given. def alert statement, question = nil ui.alert statement, question end ## # Displays an error +statement+ to the error output location. Asks a # +question+ if given. def alert_error statement, question = nil ui.alert_error statement, question end ## # Displays a warning +statement+ to the warning output location. Asks a # +question+ if given. def alert_warning statement, question = nil ui.alert_warning statement, question end ## # Asks a +question+ and returns the answer. def ask question ui.ask question end ## # Asks for a password with a +prompt+ def ask_for_password prompt ui.ask_for_password prompt end ## # Asks a yes or no +question+. Returns true for yes, false for no. def ask_yes_no question, default = nil ui.ask_yes_no question, default end ## # Asks the user to answer +question+ with an answer from the given +list+. def choose_from_list question, list ui.choose_from_list question, list end ## # Displays the given +statement+ on the standard output (or equivalent). def say statement = '' ui.say statement end ## # Terminates the RubyGems process with the given +exit_code+ def terminate_interaction exit_code = 0 ui.terminate_interaction exit_code end ## # Calls +say+ with +msg+ or the results of the block if really_verbose # is true. def verbose msg = nil say(msg || yield) if Gem.configuration.really_verbose end end ## # Gem::StreamUI implements a simple stream based user interface. class Gem::StreamUI ## # The input stream attr_reader :ins ## # The output stream attr_reader :outs ## # The error stream attr_reader :errs ## # Creates a new StreamUI wrapping +in_stream+ for user input, +out_stream+ # for standard output, +err_stream+ for error output. If +usetty+ is true # then special operations (like asking for passwords) will use the TTY # commands to disable character echo. def initialize(in_stream, out_stream, err_stream=STDERR, usetty=true) @ins = in_stream @outs = out_stream @errs = err_stream @usetty = usetty end ## # Returns true if TTY methods should be used on this StreamUI. def tty? if RUBY_VERSION < '1.9.3' and RUBY_PLATFORM =~ /mingw|mswin/ then @usetty else @usetty && @ins.tty? end end ## # Prints a formatted backtrace to the errors stream if backtraces are # enabled. def backtrace exception return unless Gem.configuration.backtrace @errs.puts "\t#{exception.backtrace.join "\n\t"}" end ## # Choose from a list of options. +question+ is a prompt displayed above # the list. +list+ is a list of option strings. Returns the pair # [option_name, option_index]. def choose_from_list(question, list) @outs.puts question list.each_with_index do |item, index| @outs.puts " #{index+1}. #{item}" end @outs.print "> " @outs.flush result = @ins.gets return nil, nil unless result result = result.strip.to_i - 1 return list[result], result end ## # Ask a question. Returns a true for yes, false for no. If not connected # to a tty, raises an exception if default is nil, otherwise returns # default. def ask_yes_no(question, default=nil) unless tty? then if default.nil? then raise Gem::OperationNotSupportedError, "Not connected to a tty and no default specified" else return default end end default_answer = case default when nil 'yn' when true 'Yn' else 'yN' end result = nil while result.nil? do result = case ask "#{question} [#{default_answer}]" when /^y/i then true when /^n/i then false when /^$/ then default else nil end end return result end ## # Ask a question. Returns an answer if connected to a tty, nil otherwise. def ask(question) return nil if not tty? @outs.print(question + " ") @outs.flush result = @ins.gets result.chomp! if result result end ## # Ask for a password. Does not echo response to terminal. def ask_for_password(question) return nil if not tty? @outs.print(question, " ") @outs.flush password = _gets_noecho @outs.puts password.chomp! if password password end if IO.method_defined?(:noecho) then def _gets_noecho @ins.noecho {@ins.gets} end elsif Gem.win_platform? def _gets_noecho require "Win32API" password = '' while char = Win32API.new("crtdll", "_getch", [ ], "L").Call do break if char == 10 || char == 13 # received carriage return or newline if char == 127 || char == 8 # backspace and delete password.slice!(-1, 1) else password << char.chr end end password end else def _gets_noecho system "stty -echo" begin @ins.gets ensure system "stty echo" end end end ## # Display a statement. def say(statement="") @outs.puts statement end ## # Display an informational alert. Will ask +question+ if it is not nil. def alert(statement, question=nil) @outs.puts "INFO: #{statement}" ask(question) if question end ## # Display a warning on stderr. Will ask +question+ if it is not nil. def alert_warning(statement, question=nil) @errs.puts "WARNING: #{statement}" ask(question) if question end ## # Display an error message in a location expected to get error messages. # Will ask +question+ if it is not nil. def alert_error(statement, question=nil) @errs.puts "ERROR: #{statement}" ask(question) if question end ## # Display a debug message on the same location as error messages. def debug(statement) @errs.puts statement end ## # Terminate the application with exit code +status+, running any exit # handlers that might have been defined. def terminate_interaction(status = 0) close raise Gem::SystemExitException, status end def close end ## # Return a progress reporter object chosen from the current verbosity. def progress_reporter(*args) if self.kind_of?(Gem::SilentUI) return SilentProgressReporter.new(@outs, *args) end case Gem.configuration.verbose when nil, false SilentProgressReporter.new(@outs, *args) when true SimpleProgressReporter.new(@outs, *args) else VerboseProgressReporter.new(@outs, *args) end end ## # An absolutely silent progress reporter. class SilentProgressReporter ## # The count of items is never updated for the silent progress reporter. attr_reader :count ## # Creates a silent progress reporter that ignores all input arguments. def initialize(out_stream, size, initial_message, terminal_message = nil) end ## # Does not print +message+ when updated as this object has taken a vow of # silence. def updated(message) end ## # Does not print anything when complete as this object has taken a vow of # silence. def done end end ## # A basic dotted progress reporter. class SimpleProgressReporter include Gem::DefaultUserInteraction ## # The number of progress items counted so far. attr_reader :count ## # Creates a new progress reporter that will write to +out_stream+ for # +size+ items. Shows the given +initial_message+ when progress starts # and the +terminal_message+ when it is complete. def initialize(out_stream, size, initial_message, terminal_message = "complete") @out = out_stream @total = size @count = 0 @terminal_message = terminal_message @out.puts initial_message end ## # Prints out a dot and ignores +message+. def updated(message) @count += 1 @out.print "." @out.flush end ## # Prints out the terminal message. def done @out.puts "\n#{@terminal_message}" end end ## # A progress reporter that prints out messages about the current progress. class VerboseProgressReporter include Gem::DefaultUserInteraction ## # The number of progress items counted so far. attr_reader :count ## # Creates a new progress reporter that will write to +out_stream+ for # +size+ items. Shows the given +initial_message+ when progress starts # and the +terminal_message+ when it is complete. def initialize(out_stream, size, initial_message, terminal_message = 'complete') @out = out_stream @total = size @count = 0 @terminal_message = terminal_message @out.puts initial_message end ## # Prints out the position relative to the total and the +message+. def updated(message) @count += 1 @out.puts "#{@count}/#{@total}: #{message}" end ## # Prints out the terminal message. def done @out.puts @terminal_message end end ## # Return a download reporter object chosen from the current verbosity def download_reporter(*args) if self.kind_of?(Gem::SilentUI) return SilentDownloadReporter.new(@outs, *args) end case Gem.configuration.verbose when nil, false SilentDownloadReporter.new(@outs, *args) else VerboseDownloadReporter.new(@outs, *args) end end ## # An absolutely silent download reporter. class SilentDownloadReporter ## # The silent download reporter ignores all arguments def initialize(out_stream, *args) end ## # The silent download reporter does not display +filename+ or care about # +filesize+ because it is silent. def fetch(filename, filesize) end ## # Nothing can update the silent download reporter. def update(current) end ## # The silent download reporter won't tell you when the download is done. # Because it is silent. def done end end ## # A progress reporter that prints out messages about the current progress. class VerboseDownloadReporter ## # The current file name being displayed attr_reader :file_name ## # The total bytes in the file attr_reader :total_bytes ## # The current progress (0 to 100) attr_reader :progress ## # Creates a new verbose download reporter that will display on # +out_stream+. The other arguments are ignored. def initialize(out_stream, *args) @out = out_stream @progress = 0 end ## # Tells the download reporter that the +file_name+ is being fetched and # contains +total_bytes+. def fetch(file_name, total_bytes) @file_name = file_name @total_bytes = total_bytes.to_i @units = @total_bytes.zero? ? 'B' : '%' update_display(false) end ## # Updates the verbose download reporter for the given number of +bytes+. def update(bytes) new_progress = if @units == 'B' then bytes else ((bytes.to_f * 100) / total_bytes.to_f).ceil end return if new_progress == @progress @progress = new_progress update_display end ## # Indicates the download is complete. def done @progress = 100 if @units == '%' update_display(true, true) end private def update_display(show_progress = true, new_line = false) # :nodoc: return unless @out.tty? if show_progress then @out.print "\rFetching: %s (%3d%s)" % [@file_name, @progress, @units] else @out.print "Fetching: %s" % @file_name end @out.puts if new_line end end end ## # Subclass of StreamUI that instantiates the user interaction using STDIN, # STDOUT, and STDERR. class Gem::ConsoleUI < Gem::StreamUI ## # The Console UI has no arguments as it defaults to reading input from # stdin, output to stdout and warnings or errors to stderr. def initialize super STDIN, STDOUT, STDERR, true end end ## # SilentUI is a UI choice that is absolutely silent. class Gem::SilentUI < Gem::StreamUI ## # The SilentUI has no arguments as it does not use any stream. def initialize reader, writer = nil, nil begin reader = File.open('/dev/null', 'r') writer = File.open('/dev/null', 'w') rescue Errno::ENOENT reader = File.open('nul', 'r') writer = File.open('nul', 'w') end super reader, writer, writer, false end def close super @ins.close @outs.close end def download_reporter(*args) # :nodoc: SilentDownloadReporter.new(@outs, *args) end def progress_reporter(*args) # :nodoc: SilentProgressReporter.new(@outs, *args) end end PK!`!! 2.2.0/rubygems/test_utilities.rbnu[require 'tempfile' require 'rubygems' require 'rubygems/remote_fetcher' ## # A fake Gem::RemoteFetcher for use in tests or to avoid real live HTTP # requests when testing code that uses RubyGems. # # Example: # # @fetcher = Gem::FakeFetcher.new # @fetcher.data['http://gems.example.com/yaml'] = source_index.to_yaml # Gem::RemoteFetcher.fetcher = @fetcher # # # invoke RubyGems code # # paths = @fetcher.paths # assert_equal 'http://gems.example.com/yaml', paths.shift # assert paths.empty?, paths.join(', ') # # See RubyGems' tests for more examples of FakeFetcher. class Gem::FakeFetcher attr_reader :data attr_reader :last_request attr_reader :api_endpoints attr_accessor :paths def initialize @data = {} @paths = [] @api_endpoints = {} end def api_endpoint(uri) @api_endpoints[uri] || uri end def find_data(path) return File.read path.path if URI === path and 'file' == path.scheme if URI === path and "URI::#{path.scheme.upcase}" != path.class.name then raise ArgumentError, "mismatch for scheme #{path.scheme} and class #{path.class}" end path = path.to_s @paths << path raise ArgumentError, 'need full URI' unless path =~ %r'^https?://' unless @data.key? path then raise Gem::RemoteFetcher::FetchError.new("no data for #{path}", path) end @data[path] end def fetch_path path, mtime = nil, head = false data = find_data(path) if data.respond_to?(:call) then data.call else if path.to_s =~ /gz$/ and not data.nil? and not data.empty? then data = Gem.gunzip data end data end end def cache_update_path uri, path = nil, update = true if data = fetch_path(uri) open(path, 'wb') { |io| io.write data } if path and update data else Gem.read_binary(path) if path end end # Thanks, FakeWeb! def open_uri_or_path(path) data = find_data(path) body, code, msg = data response = Net::HTTPResponse.send(:response_class, code.to_s).new("1.0", code.to_s, msg) response.instance_variable_set(:@body, body) response.instance_variable_set(:@read, true) response end def request(uri, request_class, last_modified = nil) data = find_data(uri) body, code, msg = data @last_request = request_class.new uri.request_uri yield @last_request if block_given? response = Net::HTTPResponse.send(:response_class, code.to_s).new("1.0", code.to_s, msg) response.instance_variable_set(:@body, body) response.instance_variable_set(:@read, true) response end def pretty_print q # :nodoc: q.group 2, '[FakeFetcher', ']' do q.breakable q.text 'URIs:' q.breakable q.pp @data.keys unless @api_endpoints.empty? then q.breakable q.text 'API endpoints:' q.breakable q.pp @api_endpoints.keys end end end def fetch_size(path) path = path.to_s @paths << path raise ArgumentError, 'need full URI' unless path =~ %r'^http://' unless @data.key? path then raise Gem::RemoteFetcher::FetchError.new("no data for #{path}", path) end data = @data[path] data.respond_to?(:call) ? data.call : data.length end def download spec, source_uri, install_dir = Gem.dir name = File.basename spec.cache_file path = if Dir.pwd == install_dir then # see fetch_command install_dir else File.join install_dir, "cache" end path = File.join path, name if source_uri =~ /^http/ then File.open(path, "wb") do |f| f.write fetch_path(File.join(source_uri, "gems", name)) end else FileUtils.cp source_uri, path end path end def download_to_cache dependency found, _ = Gem::SpecFetcher.fetcher.spec_for_dependency dependency return if found.empty? spec, source = found.first download spec, source.uri.to_s end end # :stopdoc: class Gem::RemoteFetcher def self.fetcher=(fetcher) @fetcher = fetcher end end # :startdoc: ## # The SpecFetcherSetup allows easy setup of a remote source in RubyGems tests: # # spec_fetcher do |f| # f.gem 'a', 1 # f.spec 'a', 2 # f.gem 'b', 1' 'a' => '~> 1.0' # f.clear # end # # The above declaration creates two gems, a-1 and b-1, with a dependency from # b to a. The declaration creates an additional spec a-2, but no gem for it # (so it cannot be installed). # # After the gems are created they are removed from Gem.dir. class Gem::TestCase::SpecFetcherSetup ## # Executes a SpecFetcher setup block. Yields an instance then creates the # gems and specifications defined in the instance. def self.declare test, repository setup = new test, repository yield setup setup.execute end def initialize test, repository # :nodoc: @test = test @repository = repository @gems = {} @installed = [] @operations = [] end ## # Removes any created gems or specifications from Gem.dir (the default # install location). def clear @operations << [:clear] end ## # Returns a Hash of created Specification full names and the corresponding # Specification. def created_specs created = {} @gems.keys.each do |spec| created[spec.full_name] = spec end created end ## # Creates any defined gems or specifications def execute # :nodoc: execute_operations setup_fetcher created_specs end def execute_operations # :nodoc: @operations.each do |operation, *arguments| case operation when :clear then @test.util_clear_gems @installed.clear when :gem then spec, gem = @test.util_gem(*arguments, &arguments.pop) write_spec spec @gems[spec] = gem @installed << spec when :spec then spec = @test.util_spec(*arguments, &arguments.pop) write_spec spec @gems[spec] = nil @installed << spec end end end ## # Creates a gem with +name+, +version+ and +deps+. The created gem can be # downloaded and installed. # # The specification will be yielded before gem creation for customization, # but only the block or the dependencies may be set, not both. def gem name, version, dependencies = nil, &block @operations << [:gem, name, version, dependencies, block] end ## # Creates a legacy platform spec with the name 'pl' and version 1 def legacy_platform spec 'pl', 1 do |s| s.platform = Gem::Platform.new 'i386-linux' s.instance_variable_set :@original_platform, 'i386-linux' end end def setup_fetcher # :nodoc: require 'zlib' require 'socket' require 'rubygems/remote_fetcher' unless @test.fetcher then @test.fetcher = Gem::FakeFetcher.new Gem::RemoteFetcher.fetcher = @test.fetcher end Gem::Specification.reset begin gem_repo, @test.gem_repo = @test.gem_repo, @repository @test.uri = URI @repository @test.util_setup_spec_fetcher(*@gems.keys) ensure @test.gem_repo = gem_repo @test.uri = URI gem_repo end # This works around util_setup_spec_fetcher adding all created gems to the # installed set. Gem::Specification.reset Gem::Specification.add_specs(*@installed) @gems.each do |spec, gem| next unless gem @test.fetcher.data["#{@repository}gems/#{spec.file_name}"] = Gem.read_binary(gem) FileUtils.cp gem, spec.cache_file end end ## # Creates a spec with +name+, +version+ and +deps+. The created gem can be # downloaded and installed. # # The specification will be yielded before creation for customization, # but only the block or the dependencies may be set, not both. def spec name, version, dependencies = nil, &block @operations << [:spec, name, version, dependencies, block] end def write_spec spec # :nodoc: open spec.spec_file, 'w' do |io| io.write spec.to_ruby_for_cache end end end ## # A StringIO duck-typed class that uses Tempfile instead of String as the # backing store. # # This is available when rubygems/test_utilities is required. #-- # This class was added to flush out problems in Rubinius' IO implementation. class TempIO < Tempfile ## # Creates a new TempIO that will be initialized to contain +string+. def initialize(string = '') super "TempIO" binmode write string rewind end ## # The content of the TempIO as a String. def string flush Gem.read_binary path end end PK! YY 2.2.0/time.rbnu[require 'date' # = time.rb # # When 'time' is required, Time is extended with additional methods for parsing # and converting Times. # # == Features # # This library extends the Time class with the following conversions between # date strings and Time objects: # # * date-time defined by {RFC 2822}[http://www.ietf.org/rfc/rfc2822.txt] # * HTTP-date defined by {RFC 2616}[http://www.ietf.org/rfc/rfc2616.txt] # * dateTime defined by XML Schema Part 2: Datatypes ({ISO # 8601}[http://www.iso.org/iso/date_and_time_format]) # * various formats handled by Date._parse # * custom formats handled by Date._strptime # # == Examples # # All examples assume you have loaded Time with: # # require 'time' # # All of these examples were done using the EST timezone which is GMT-5. # # === Converting to a String # # t = Time.now # t.iso8601 # => "2011-10-05T22:26:12-04:00" # t.rfc2822 # => "Wed, 05 Oct 2011 22:26:12 -0400" # t.httpdate # => "Thu, 06 Oct 2011 02:26:12 GMT" # # === Time.parse # # #parse takes a string representation of a Time and attempts to parse it # using a heuristic. # # Date.parse("2010-10-31") #=> 2010-10-31 00:00:00 -0500 # # Any missing pieces of the date are inferred based on the current date. # # # assuming the current date is "2011-10-31" # Time.parse("12:00") #=> 2011-10-31 12:00:00 -0500 # # We can change the date used to infer our missing elements by passing a second # object that responds to #mon, #day and #year, such as Date, Time or DateTime. # We can also use our own object. # # class MyDate # attr_reader :mon, :day, :year # # def initialize(mon, day, year) # @mon, @day, @year = mon, day, year # end # end # # d = Date.parse("2010-10-28") # t = Time.parse("2010-10-29") # dt = DateTime.parse("2010-10-30") # md = MyDate.new(10,31,2010) # # Time.parse("12:00", d) #=> 2010-10-28 12:00:00 -0500 # Time.parse("12:00", t) #=> 2010-10-29 12:00:00 -0500 # Time.parse("12:00", dt) #=> 2010-10-30 12:00:00 -0500 # Time.parse("12:00", md) #=> 2010-10-31 12:00:00 -0500 # # #parse also accepts an optional block. You can use this block to specify how # to handle the year component of the date. This is specifically designed for # handling two digit years. For example, if you wanted to treat all two digit # years prior to 70 as the year 2000+ you could write this: # # Time.parse("01-10-31") {|year| year + (year < 70 ? 2000 : 1900)} # #=> 2001-10-31 00:00:00 -0500 # Time.parse("70-10-31") {|year| year + (year < 70 ? 2000 : 1900)} # #=> 1970-10-31 00:00:00 -0500 # # === Time.strptime # # #strptime works similar to +parse+ except that instead of using a heuristic # to detect the format of the input string, you provide a second argument that # describes the format of the string. For example: # # Time.strptime("2000-10-31", "%Y-%m-%d") #=> 2000-10-31 00:00:00 -0500 class Time class << Time # # A hash of timezones mapped to hour differences from UTC. The # set of time zones corresponds to the ones specified by RFC 2822 # and ISO 8601. # ZoneOffset = { # :nodoc: 'UTC' => 0, # ISO 8601 'Z' => 0, # RFC 822 'UT' => 0, 'GMT' => 0, 'EST' => -5, 'EDT' => -4, 'CST' => -6, 'CDT' => -5, 'MST' => -7, 'MDT' => -6, 'PST' => -8, 'PDT' => -7, # Following definition of military zones is original one. # See RFC 1123 and RFC 2822 for the error in RFC 822. 'A' => +1, 'B' => +2, 'C' => +3, 'D' => +4, 'E' => +5, 'F' => +6, 'G' => +7, 'H' => +8, 'I' => +9, 'K' => +10, 'L' => +11, 'M' => +12, 'N' => -1, 'O' => -2, 'P' => -3, 'Q' => -4, 'R' => -5, 'S' => -6, 'T' => -7, 'U' => -8, 'V' => -9, 'W' => -10, 'X' => -11, 'Y' => -12, } # # Return the number of seconds the specified time zone differs # from UTC. # # Numeric time zones that include minutes, such as # -10:00 or +1330 will work, as will # simpler hour-only time zones like -10 or # +13. # # Textual time zones listed in ZoneOffset are also supported. # # If the time zone does not match any of the above, +zone_offset+ # will check if the local time zone (both with and without # potential Daylight Saving \Time changes being in effect) matches # +zone+. Specifying a value for +year+ will change the year used # to find the local time zone. # # If +zone_offset+ is unable to determine the offset, nil will be # returned. def zone_offset(zone, year=self.now.year) off = nil zone = zone.upcase if /\A([+-])(\d\d):?(\d\d)\z/ =~ zone off = ($1 == '-' ? -1 : 1) * ($2.to_i * 60 + $3.to_i) * 60 elsif /\A[+-]\d\d\z/ =~ zone off = zone.to_i * 3600 elsif ZoneOffset.include?(zone) off = ZoneOffset[zone] * 3600 elsif ((t = self.local(year, 1, 1)).zone.upcase == zone rescue false) off = t.utc_offset elsif ((t = self.local(year, 7, 1)).zone.upcase == zone rescue false) off = t.utc_offset end off end def zone_utc?(zone) # * +0000 # In RFC 2822, +0000 indicate a time zone at Universal Time. # Europe/Lisbon is "a time zone at Universal Time" in Winter. # Atlantic/Reykjavik is "a time zone at Universal Time". # Africa/Dakar is "a time zone at Universal Time". # So +0000 is a local time such as Europe/London, etc. # * GMT # GMT is used as a time zone abbreviation in Europe/London, # Africa/Dakar, etc. # So it is a local time. # # * -0000, -00:00 # In RFC 2822, -0000 the date-time contains no information about the # local time zone. # In RFC 3339, -00:00 is used for the time in UTC is known, # but the offset to local time is unknown. # They are not appropriate for specific time zone such as # Europe/London because time zone neutral, # So -00:00 and -0000 are treated as UTC. if /\A(?:-00:00|-0000|-00|UTC|Z|UT)\z/i =~ zone true else false end end private :zone_utc? def force_zone!(t, zone, offset=nil) if zone_utc?(zone) t.utc elsif offset ||= zone_offset(zone) # Prefer the local timezone over the fixed offset timezone because # the former is a real timezone and latter is an artificial timezone. t.localtime if t.utc_offset != offset # Use the fixed offset timezone only if the local timezone cannot # represent the given offset. t.localtime(offset) end else t.localtime end end private :force_zone! LeapYearMonthDays = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] # :nodoc: CommonYearMonthDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] # :nodoc: def month_days(y, m) if ((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0) LeapYearMonthDays[m-1] else CommonYearMonthDays[m-1] end end private :month_days def apply_offset(year, mon, day, hour, min, sec, off) if off < 0 off = -off off, o = off.divmod(60) if o != 0 then sec += o; o, sec = sec.divmod(60); off += o end off, o = off.divmod(60) if o != 0 then min += o; o, min = min.divmod(60); off += o end off, o = off.divmod(24) if o != 0 then hour += o; o, hour = hour.divmod(24); off += o end if off != 0 day += off days = month_days(year, mon) if days and days < day mon += 1 if 12 < mon mon = 1 year += 1 end day = 1 end end elsif 0 < off off, o = off.divmod(60) if o != 0 then sec -= o; o, sec = sec.divmod(60); off -= o end off, o = off.divmod(60) if o != 0 then min -= o; o, min = min.divmod(60); off -= o end off, o = off.divmod(24) if o != 0 then hour -= o; o, hour = hour.divmod(24); off -= o end if off != 0 then day -= off if day < 1 mon -= 1 if mon < 1 year -= 1 mon = 12 end day = month_days(year, mon) end end end return year, mon, day, hour, min, sec end private :apply_offset def make_time(date, year, mon, day, hour, min, sec, sec_fraction, zone, now) if !year && !mon && !day && !hour && !min && !sec && !sec_fraction raise ArgumentError, "no time information in #{date.inspect}" end off_year = year || now.year off = nil off = zone_offset(zone, off_year) if zone if off now = now.getlocal(off) if now.utc_offset != off else now = now.getlocal end usec = nil usec = sec_fraction * 1000000 if sec_fraction if now begin break if year; year = now.year break if mon; mon = now.mon break if day; day = now.day break if hour; hour = now.hour break if min; min = now.min break if sec; sec = now.sec break if sec_fraction; usec = now.tv_usec end until true end year ||= 1970 mon ||= 1 day ||= 1 hour ||= 0 min ||= 0 sec ||= 0 usec ||= 0 if year != off_year off = nil off = zone_offset(zone, year) if zone end if off year, mon, day, hour, min, sec = apply_offset(year, mon, day, hour, min, sec, off) t = self.utc(year, mon, day, hour, min, sec, usec) force_zone!(t, zone, off) t else self.local(year, mon, day, hour, min, sec, usec) end end private :make_time # # Parses +date+ using Date._parse and converts it to a Time object. # # If a block is given, the year described in +date+ is converted by the # block. For example: # # Time.parse(...) {|y| 0 <= y && y < 100 ? (y >= 69 ? y + 1900 : y + 2000) : y} # # If the upper components of the given time are broken or missing, they are # supplied with those of +now+. For the lower components, the minimum # values (1 or 0) are assumed if broken or missing. For example: # # # Suppose it is "Thu Nov 29 14:33:20 2001" now and # # your time zone is EST which is GMT-5. # now = Time.parse("Thu Nov 29 14:33:20 2001") # Time.parse("16:30", now) #=> 2001-11-29 16:30:00 -0500 # Time.parse("7/23", now) #=> 2001-07-23 00:00:00 -0500 # Time.parse("Aug 31", now) #=> 2001-08-31 00:00:00 -0500 # Time.parse("Aug 2000", now) #=> 2000-08-01 00:00:00 -0500 # # Since there are numerous conflicts among locally defined time zone # abbreviations all over the world, this method is not intended to # understand all of them. For example, the abbreviation "CST" is # used variously as: # # -06:00 in America/Chicago, # -05:00 in America/Havana, # +08:00 in Asia/Harbin, # +09:30 in Australia/Darwin, # +10:30 in Australia/Adelaide, # etc. # # Based on this fact, this method only understands the time zone # abbreviations described in RFC 822 and the system time zone, in the # order named. (i.e. a definition in RFC 822 overrides the system # time zone definition.) The system time zone is taken from # Time.local(year, 1, 1).zone and # Time.local(year, 7, 1).zone. # If the extracted time zone abbreviation does not match any of them, # it is ignored and the given time is regarded as a local time. # # ArgumentError is raised if Date._parse cannot extract information from # +date+ or if the Time class cannot represent specified date. # # This method can be used as a fail-safe for other parsing methods as: # # Time.rfc2822(date) rescue Time.parse(date) # Time.httpdate(date) rescue Time.parse(date) # Time.xmlschema(date) rescue Time.parse(date) # # A failure of Time.parse should be checked, though. # # You must require 'time' to use this method. # def parse(date, now=self.now) comp = !block_given? d = Date._parse(date, comp) year = d[:year] year = yield(year) if year && !comp make_time(date, year, d[:mon], d[:mday], d[:hour], d[:min], d[:sec], d[:sec_fraction], d[:zone], now) end # # Parses +date+ using Date._strptime and converts it to a Time object. # # If a block is given, the year described in +date+ is converted by the # block. For example: # # Time.strptime(...) {|y| y < 100 ? (y >= 69 ? y + 1900 : y + 2000) : y} # # Below is a list of the formatting options: # # %a :: The abbreviated weekday name ("Sun") # %A :: The full weekday name ("Sunday") # %b :: The abbreviated month name ("Jan") # %B :: The full month name ("January") # %c :: The preferred local date and time representation # %C :: Century (20 in 2009) # %d :: Day of the month (01..31) # %D :: Date (%m/%d/%y) # %e :: Day of the month, blank-padded ( 1..31) # %F :: Equivalent to %Y-%m-%d (the ISO 8601 date format) # %h :: Equivalent to %b # %H :: Hour of the day, 24-hour clock (00..23) # %I :: Hour of the day, 12-hour clock (01..12) # %j :: Day of the year (001..366) # %k :: hour, 24-hour clock, blank-padded ( 0..23) # %l :: hour, 12-hour clock, blank-padded ( 0..12) # %L :: Millisecond of the second (000..999) # %m :: Month of the year (01..12) # %M :: Minute of the hour (00..59) # %n :: Newline (\n) # %N :: Fractional seconds digits, default is 9 digits (nanosecond) # %3N :: millisecond (3 digits) # %6N :: microsecond (6 digits) # %9N :: nanosecond (9 digits) # %p :: Meridian indicator ("AM" or "PM") # %P :: Meridian indicator ("am" or "pm") # %r :: time, 12-hour (same as %I:%M:%S %p) # %R :: time, 24-hour (%H:%M) # %s :: Number of seconds since 1970-01-01 00:00:00 UTC. # %S :: Second of the minute (00..60) # %t :: Tab character (\t) # %T :: time, 24-hour (%H:%M:%S) # %u :: Day of the week as a decimal, Monday being 1. (1..7) # %U :: Week number of the current year, starting with the first Sunday as # the first day of the first week (00..53) # %v :: VMS date (%e-%b-%Y) # %V :: Week number of year according to ISO 8601 (01..53) # %W :: Week number of the current year, starting with the first Monday # as the first day of the first week (00..53) # %w :: Day of the week (Sunday is 0, 0..6) # %x :: Preferred representation for the date alone, no time # %X :: Preferred representation for the time alone, no date # %y :: Year without a century (00..99) # %Y :: Year which may include century, if provided # %z :: Time zone as hour offset from UTC (e.g. +0900) # %Z :: Time zone name # %% :: Literal "%" character def strptime(date, format, now=self.now) d = Date._strptime(date, format) raise ArgumentError, "invalid strptime format - `#{format}'" unless d if seconds = d[:seconds] if sec_fraction = d[:sec_fraction] usec = sec_fraction * 1000000 usec *= -1 if seconds < 0 else usec = 0 end t = Time.at(seconds, usec) if zone = d[:zone] force_zone!(t, zone) end else year = d[:year] year = yield(year) if year && block_given? t = make_time(date, year, d[:mon], d[:mday], d[:hour], d[:min], d[:sec], d[:sec_fraction], d[:zone], now) end t end MonthValue = { # :nodoc: 'JAN' => 1, 'FEB' => 2, 'MAR' => 3, 'APR' => 4, 'MAY' => 5, 'JUN' => 6, 'JUL' => 7, 'AUG' => 8, 'SEP' => 9, 'OCT' =>10, 'NOV' =>11, 'DEC' =>12 } # # Parses +date+ as date-time defined by RFC 2822 and converts it to a Time # object. The format is identical to the date format defined by RFC 822 and # updated by RFC 1123. # # ArgumentError is raised if +date+ is not compliant with RFC 2822 # or if the Time class cannot represent specified date. # # See #rfc2822 for more information on this format. # # You must require 'time' to use this method. # def rfc2822(date) if /\A\s* (?:(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun)\s*,\s*)? (\d{1,2})\s+ (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s+ (\d{2,})\s+ (\d{2})\s* :\s*(\d{2})\s* (?::\s*(\d{2}))?\s+ ([+-]\d{4}| UT|GMT|EST|EDT|CST|CDT|MST|MDT|PST|PDT|[A-IK-Z])/ix =~ date # Since RFC 2822 permit comments, the regexp has no right anchor. day = $1.to_i mon = MonthValue[$2.upcase] year = $3.to_i short_year_p = $3.length <= 3 hour = $4.to_i min = $5.to_i sec = $6 ? $6.to_i : 0 zone = $7 if short_year_p # following year completion is compliant with RFC 2822. year = if year < 50 2000 + year else 1900 + year end end off = zone_offset(zone) year, mon, day, hour, min, sec = apply_offset(year, mon, day, hour, min, sec, off) t = self.utc(year, mon, day, hour, min, sec) force_zone!(t, zone, off) t else raise ArgumentError.new("not RFC 2822 compliant date: #{date.inspect}") end end alias rfc822 rfc2822 # # Parses +date+ as an HTTP-date defined by RFC 2616 and converts it to a # Time object. # # ArgumentError is raised if +date+ is not compliant with RFC 2616 or if # the Time class cannot represent specified date. # # See #httpdate for more information on this format. # # You must require 'time' to use this method. # def httpdate(date) if /\A\s* (?:Mon|Tue|Wed|Thu|Fri|Sat|Sun),\x20 (\d{2})\x20 (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\x20 (\d{4})\x20 (\d{2}):(\d{2}):(\d{2})\x20 GMT \s*\z/ix =~ date self.rfc2822(date).utc elsif /\A\s* (?:Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday),\x20 (\d\d)-(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)-(\d\d)\x20 (\d\d):(\d\d):(\d\d)\x20 GMT \s*\z/ix =~ date year = $3.to_i if year < 50 year += 2000 else year += 1900 end self.utc(year, $2, $1.to_i, $4.to_i, $5.to_i, $6.to_i) elsif /\A\s* (?:Mon|Tue|Wed|Thu|Fri|Sat|Sun)\x20 (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\x20 (\d\d|\x20\d)\x20 (\d\d):(\d\d):(\d\d)\x20 (\d{4}) \s*\z/ix =~ date self.utc($6.to_i, MonthValue[$1.upcase], $2.to_i, $3.to_i, $4.to_i, $5.to_i) else raise ArgumentError.new("not RFC 2616 compliant date: #{date.inspect}") end end # # Parses +date+ as a dateTime defined by the XML Schema and converts it to # a Time object. The format is a restricted version of the format defined # by ISO 8601. # # ArgumentError is raised if +date+ is not compliant with the format or if # the Time class cannot represent specified date. # # See #xmlschema for more information on this format. # # You must require 'time' to use this method. # def xmlschema(date) if /\A\s* (-?\d+)-(\d\d)-(\d\d) T (\d\d):(\d\d):(\d\d) (\.\d+)? (Z|[+-]\d\d:\d\d)? \s*\z/ix =~ date year = $1.to_i mon = $2.to_i day = $3.to_i hour = $4.to_i min = $5.to_i sec = $6.to_i usec = 0 if $7 usec = Rational($7) * 1000000 end if $8 zone = $8 off = zone_offset(zone) year, mon, day, hour, min, sec = apply_offset(year, mon, day, hour, min, sec, off) t = self.utc(year, mon, day, hour, min, sec, usec) force_zone!(t, zone, off) t else self.local(year, mon, day, hour, min, sec, usec) end else raise ArgumentError.new("invalid date: #{date.inspect}") end end alias iso8601 xmlschema end # class << self # # Returns a string which represents the time as date-time defined by RFC 2822: # # day-of-week, DD month-name CCYY hh:mm:ss zone # # where zone is [+-]hhmm. # # If +self+ is a UTC time, -0000 is used as zone. # # You must require 'time' to use this method. # def rfc2822 sprintf('%s, %02d %s %0*d %02d:%02d:%02d ', RFC2822_DAY_NAME[wday], day, RFC2822_MONTH_NAME[mon-1], year < 0 ? 5 : 4, year, hour, min, sec) + if utc? '-0000' else off = utc_offset sign = off < 0 ? '-' : '+' sprintf('%s%02d%02d', sign, *(off.abs / 60).divmod(60)) end end alias rfc822 rfc2822 RFC2822_DAY_NAME = [ # :nodoc: 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ] RFC2822_MONTH_NAME = [ # :nodoc: 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ] # # Returns a string which represents the time as RFC 1123 date of HTTP-date # defined by RFC 2616: # # day-of-week, DD month-name CCYY hh:mm:ss GMT # # Note that the result is always UTC (GMT). # # You must require 'time' to use this method. # def httpdate t = dup.utc sprintf('%s, %02d %s %0*d %02d:%02d:%02d GMT', RFC2822_DAY_NAME[t.wday], t.day, RFC2822_MONTH_NAME[t.mon-1], t.year < 0 ? 5 : 4, t.year, t.hour, t.min, t.sec) end # # Returns a string which represents the time as a dateTime defined by XML # Schema: # # CCYY-MM-DDThh:mm:ssTZD # CCYY-MM-DDThh:mm:ss.sssTZD # # where TZD is Z or [+-]hh:mm. # # If self is a UTC time, Z is used as TZD. [+-]hh:mm is used otherwise. # # +fractional_digits+ specifies a number of digits to use for fractional # seconds. Its default value is 0. # # You must require 'time' to use this method. # def xmlschema(fraction_digits=0) fraction_digits = fraction_digits.to_i s = strftime("%FT%T") if fraction_digits > 0 s << strftime(".%#{fraction_digits}N") end s << (utc? ? 'Z' : strftime("%:z")) end alias iso8601 xmlschema end PK!׉;;2.2.0/psych.rbnu[require 'psych.so' require 'psych/nodes' require 'psych/streaming' require 'psych/visitors' require 'psych/handler' require 'psych/tree_builder' require 'psych/parser' require 'psych/omap' require 'psych/set' require 'psych/coder' require 'psych/core_ext' require 'psych/deprecated' require 'psych/stream' require 'psych/json/tree_builder' require 'psych/json/stream' require 'psych/handlers/document_stream' require 'psych/class_loader' ### # = Overview # # Psych is a YAML parser and emitter. # Psych leverages libyaml [Home page: http://pyyaml.org/wiki/LibYAML] # or [HG repo: https://bitbucket.org/xi/libyaml] for its YAML parsing # and emitting capabilities. In addition to wrapping libyaml, Psych also # knows how to serialize and de-serialize most Ruby objects to and from # the YAML format. # # = I NEED TO PARSE OR EMIT YAML RIGHT NOW! # # # Parse some YAML # Psych.load("--- foo") # => "foo" # # # Emit some YAML # Psych.dump("foo") # => "--- foo\n...\n" # { :a => 'b'}.to_yaml # => "---\n:a: b\n" # # Got more time on your hands? Keep on reading! # # == YAML Parsing # # Psych provides a range of interfaces for parsing a YAML document ranging from # low level to high level, depending on your parsing needs. At the lowest # level, is an event based parser. Mid level is access to the raw YAML AST, # and at the highest level is the ability to unmarshal YAML to Ruby objects. # # == YAML Emitting # # Psych provides a range of interfaces ranging from low to high level for # producing YAML documents. Very similar to the YAML parsing interfaces, Psych # provides at the lowest level, an event based system, mid-level is building # a YAML AST, and the highest level is converting a Ruby object straight to # a YAML document. # # == High-level API # # === Parsing # # The high level YAML parser provided by Psych simply takes YAML as input and # returns a Ruby data structure. For information on using the high level parser # see Psych.load # # ==== Reading from a string # # Psych.load("--- a") # => 'a' # Psych.load("---\n - a\n - b") # => ['a', 'b'] # # ==== Reading from a file # # Psych.load_file("database.yml") # # ==== Exception handling # # begin # # The second argument changes only the exception contents # Psych.parse("--- `", "file.txt") # rescue Psych::SyntaxError => ex # ex.file # => 'file.txt' # ex.message # => "(file.txt): found character that cannot start any token" # end # # === Emitting # # The high level emitter has the easiest interface. Psych simply takes a Ruby # data structure and converts it to a YAML document. See Psych.dump for more # information on dumping a Ruby data structure. # # ==== Writing to a string # # # Dump an array, get back a YAML string # Psych.dump(['a', 'b']) # => "---\n- a\n- b\n" # # # Dump an array to an IO object # Psych.dump(['a', 'b'], StringIO.new) # => # # # # Dump an array with indentation set # Psych.dump(['a', ['b']], :indentation => 3) # => "---\n- a\n- - b\n" # # # Dump an array to an IO with indentation set # Psych.dump(['a', ['b']], StringIO.new, :indentation => 3) # # ==== Writing to a file # # Currently there is no direct API for dumping Ruby structure to file: # # File.open('database.yml', 'w') do |file| # file.write(Psych.dump(['a', 'b'])) # end # # == Mid-level API # # === Parsing # # Psych provides access to an AST produced from parsing a YAML document. This # tree is built using the Psych::Parser and Psych::TreeBuilder. The AST can # be examined and manipulated freely. Please see Psych::parse_stream, # Psych::Nodes, and Psych::Nodes::Node for more information on dealing with # YAML syntax trees. # # ==== Reading from a string # # # Returns Psych::Nodes::Stream # Psych.parse_stream("---\n - a\n - b") # # # Returns Psych::Nodes::Document # Psych.parse("---\n - a\n - b") # # ==== Reading from a file # # # Returns Psych::Nodes::Stream # Psych.parse_stream(File.read('database.yml')) # # # Returns Psych::Nodes::Document # Psych.parse_file('database.yml') # # ==== Exception handling # # begin # # The second argument changes only the exception contents # Psych.parse("--- `", "file.txt") # rescue Psych::SyntaxError => ex # ex.file # => 'file.txt' # ex.message # => "(file.txt): found character that cannot start any token" # end # # === Emitting # # At the mid level is building an AST. This AST is exactly the same as the AST # used when parsing a YAML document. Users can build an AST by hand and the # AST knows how to emit itself as a YAML document. See Psych::Nodes, # Psych::Nodes::Node, and Psych::TreeBuilder for more information on building # a YAML AST. # # ==== Writing to a string # # # We need Psych::Nodes::Stream (not Psych::Nodes::Document) # stream = Psych.parse_stream("---\n - a\n - b") # # stream.to_yaml # => "---\n- a\n- b\n" # # ==== Writing to a file # # # We need Psych::Nodes::Stream (not Psych::Nodes::Document) # stream = Psych.parse_stream(File.read('database.yml')) # # File.open('database.yml', 'w') do |file| # file.write(stream.to_yaml) # end # # == Low-level API # # === Parsing # # The lowest level parser should be used when the YAML input is already known, # and the developer does not want to pay the price of building an AST or # automatic detection and conversion to Ruby objects. See Psych::Parser for # more information on using the event based parser. # # ==== Reading to Psych::Nodes::Stream structure # # parser = Psych::Parser.new(TreeBuilder.new) # => # # parser = Psych.parser # it's an alias for the above # # parser.parse("---\n - a\n - b") # => # # parser.handler # => # # parser.handler.root # => # # # ==== Receiving an events stream # # parser = Psych::Parser.new(Psych::Handlers::Recorder.new) # # parser.parse("---\n - a\n - b") # parser.events # => [list of [event, args] lists] # # event is one of: Psych::Handler::EVENTS # # args are the arguments passed to the event # # === Emitting # # The lowest level emitter is an event based system. Events are sent to a # Psych::Emitter object. That object knows how to convert the events to a YAML # document. This interface should be used when document format is known in # advance or speed is a concern. See Psych::Emitter for more information. # # ==== Writing to a Ruby structure # # Psych.parser.parse("--- a") # => # # # parser.handler.first # => # # parser.handler.first.to_ruby # => ["a"] # # parser.handler.root.first # => # # parser.handler.root.first.to_ruby # => "a" # # # You can instantiate an Emitter manually # Psych::Visitors::ToRuby.new.accept(parser.handler.root.first) # # => "a" module Psych # The version is Psych you're using VERSION = '2.0.8' # The version of libyaml Psych is using LIBYAML_VERSION = Psych.libyaml_version.join '.' ### # Load +yaml+ in to a Ruby data structure. If multiple documents are # provided, the object contained in the first document will be returned. # +filename+ will be used in the exception message if any exception is raised # while parsing. # # Raises a Psych::SyntaxError when a YAML syntax error is detected. # # Example: # # Psych.load("--- a") # => 'a' # Psych.load("---\n - a\n - b") # => ['a', 'b'] # # begin # Psych.load("--- `", "file.txt") # rescue Psych::SyntaxError => ex # ex.file # => 'file.txt' # ex.message # => "(file.txt): found character that cannot start any token" # end def self.load yaml, filename = nil result = parse(yaml, filename) result ? result.to_ruby : result end ### # Safely load the yaml string in +yaml+. By default, only the following # classes are allowed to be deserialized: # # * TrueClass # * FalseClass # * NilClass # * Numeric # * String # * Array # * Hash # # Recursive data structures are not allowed by default. Arbitrary classes # can be allowed by adding those classes to the +whitelist+. They are # additive. For example, to allow Date deserialization: # # Psych.safe_load(yaml, [Date]) # # Now the Date class can be loaded in addition to the classes listed above. # # Aliases can be explicitly allowed by changing the +aliases+ parameter. # For example: # # x = [] # x << x # yaml = Psych.dump x # Psych.safe_load yaml # => raises an exception # Psych.safe_load yaml, [], [], true # => loads the aliases # # A Psych::DisallowedClass exception will be raised if the yaml contains a # class that isn't in the whitelist. # # A Psych::BadAlias exception will be raised if the yaml contains aliases # but the +aliases+ parameter is set to false. def self.safe_load yaml, whitelist_classes = [], whitelist_symbols = [], aliases = false, filename = nil result = parse(yaml, filename) return unless result class_loader = ClassLoader::Restricted.new(whitelist_classes.map(&:to_s), whitelist_symbols.map(&:to_s)) scanner = ScalarScanner.new class_loader if aliases visitor = Visitors::ToRuby.new scanner, class_loader else visitor = Visitors::NoAliasRuby.new scanner, class_loader end visitor.accept result end ### # Parse a YAML string in +yaml+. Returns the Psych::Nodes::Document. # +filename+ is used in the exception message if a Psych::SyntaxError is # raised. # # Raises a Psych::SyntaxError when a YAML syntax error is detected. # # Example: # # Psych.parse("---\n - a\n - b") # => # # # begin # Psych.parse("--- `", "file.txt") # rescue Psych::SyntaxError => ex # ex.file # => 'file.txt' # ex.message # => "(file.txt): found character that cannot start any token" # end # # See Psych::Nodes for more information about YAML AST. def self.parse yaml, filename = nil parse_stream(yaml, filename) do |node| return node end false end ### # Parse a file at +filename+. Returns the Psych::Nodes::Document. # # Raises a Psych::SyntaxError when a YAML syntax error is detected. def self.parse_file filename File.open filename, 'r:bom|utf-8' do |f| parse f, filename end end ### # Returns a default parser def self.parser Psych::Parser.new(TreeBuilder.new) end ### # Parse a YAML string in +yaml+. Returns the Psych::Nodes::Stream. # This method can handle multiple YAML documents contained in +yaml+. # +filename+ is used in the exception message if a Psych::SyntaxError is # raised. # # If a block is given, a Psych::Nodes::Document node will be yielded to the # block as it's being parsed. # # Raises a Psych::SyntaxError when a YAML syntax error is detected. # # Example: # # Psych.parse_stream("---\n - a\n - b") # => # # # Psych.parse_stream("--- a\n--- b") do |node| # node # => # # end # # begin # Psych.parse_stream("--- `", "file.txt") # rescue Psych::SyntaxError => ex # ex.file # => 'file.txt' # ex.message # => "(file.txt): found character that cannot start any token" # end # # See Psych::Nodes for more information about YAML AST. def self.parse_stream yaml, filename = nil, &block if block_given? parser = Psych::Parser.new(Handlers::DocumentStream.new(&block)) parser.parse yaml, filename else parser = self.parser parser.parse yaml, filename parser.handler.root end end ### # call-seq: # Psych.dump(o) -> string of yaml # Psych.dump(o, options) -> string of yaml # Psych.dump(o, io) -> io object passed in # Psych.dump(o, io, options) -> io object passed in # # Dump Ruby object +o+ to a YAML string. Optional +options+ may be passed in # to control the output format. If an IO object is passed in, the YAML will # be dumped to that IO object. # # Example: # # # Dump an array, get back a YAML string # Psych.dump(['a', 'b']) # => "---\n- a\n- b\n" # # # Dump an array to an IO object # Psych.dump(['a', 'b'], StringIO.new) # => # # # # Dump an array with indentation set # Psych.dump(['a', ['b']], :indentation => 3) # => "---\n- a\n- - b\n" # # # Dump an array to an IO with indentation set # Psych.dump(['a', ['b']], StringIO.new, :indentation => 3) def self.dump o, io = nil, options = {} if Hash === io options = io io = nil end visitor = Psych::Visitors::YAMLTree.create options visitor << o visitor.tree.yaml io, options end ### # Dump a list of objects as separate documents to a document stream. # # Example: # # Psych.dump_stream("foo\n ", {}) # => "--- ! \"foo\\n \"\n--- {}\n" def self.dump_stream *objects visitor = Psych::Visitors::YAMLTree.create({}) objects.each do |o| visitor << o end visitor.tree.yaml end ### # Dump Ruby +object+ to a JSON string. def self.to_json object visitor = Psych::Visitors::JSONTree.create visitor << object visitor.tree.yaml end ### # Load multiple documents given in +yaml+. Returns the parsed documents # as a list. If a block is given, each document will be converted to Ruby # and passed to the block during parsing # # Example: # # Psych.load_stream("--- foo\n...\n--- bar\n...") # => ['foo', 'bar'] # # list = [] # Psych.load_stream("--- foo\n...\n--- bar\n...") do |ruby| # list << ruby # end # list # => ['foo', 'bar'] # def self.load_stream yaml, filename = nil if block_given? parse_stream(yaml, filename) do |node| yield node.to_ruby end else parse_stream(yaml, filename).children.map { |child| child.to_ruby } end end ### # Load the document contained in +filename+. Returns the yaml contained in # +filename+ as a Ruby object def self.load_file filename File.open(filename, 'r:bom|utf-8') { |f| self.load f, filename } end # :stopdoc: @domain_types = {} def self.add_domain_type domain, type_tag, &block key = ['tag', domain, type_tag].join ':' @domain_types[key] = [key, block] @domain_types["tag:#{type_tag}"] = [key, block] end def self.add_builtin_type type_tag, &block domain = 'yaml.org,2002' key = ['tag', domain, type_tag].join ':' @domain_types[key] = [key, block] end def self.remove_type type_tag @domain_types.delete type_tag end @load_tags = {} @dump_tags = {} def self.add_tag tag, klass @load_tags[tag] = klass.name @dump_tags[klass] = tag end class << self attr_accessor :load_tags attr_accessor :dump_tags attr_accessor :domain_types end # :startdoc: end PK! t,t,2.2.0/tempfile.rbnu[# # tempfile - manipulates temporary files # # $Id: tempfile.rb 47656 2014-09-21 01:40:21Z nobu $ # require 'delegate' require 'tmpdir' # A utility class for managing temporary files. When you create a Tempfile # object, it will create a temporary file with a unique filename. A Tempfile # objects behaves just like a File object, and you can perform all the usual # file operations on it: reading data, writing data, changing its permissions, # etc. So although this class does not explicitly document all instance methods # supported by File, you can in fact call any File instance method on a # Tempfile object. # # == Synopsis # # require 'tempfile' # # file = Tempfile.new('foo') # file.path # => A unique filename in the OS's temp directory, # # e.g.: "/tmp/foo.24722.0" # # This filename contains 'foo' in its basename. # file.write("hello world") # file.rewind # file.read # => "hello world" # file.close # file.unlink # deletes the temp file # # == Good practices # # === Explicit close # # When a Tempfile object is garbage collected, or when the Ruby interpreter # exits, its associated temporary file is automatically deleted. This means # that's it's unnecessary to explicitly delete a Tempfile after use, though # it's good practice to do so: not explicitly deleting unused Tempfiles can # potentially leave behind large amounts of tempfiles on the filesystem # until they're garbage collected. The existence of these temp files can make # it harder to determine a new Tempfile filename. # # Therefore, one should always call #unlink or close in an ensure block, like # this: # # file = Tempfile.new('foo') # begin # ...do something with file... # ensure # file.close # file.unlink # deletes the temp file # end # # === Unlink after creation # # On POSIX systems, it's possible to unlink a file right after creating it, # and before closing it. This removes the filesystem entry without closing # the file handle, so it ensures that only the processes that already had # the file handle open can access the file's contents. It's strongly # recommended that you do this if you do not want any other processes to # be able to read from or write to the Tempfile, and you do not need to # know the Tempfile's filename either. # # For example, a practical use case for unlink-after-creation would be this: # you need a large byte buffer that's too large to comfortably fit in RAM, # e.g. when you're writing a web server and you want to buffer the client's # file upload data. # # Please refer to #unlink for more information and a code example. # # == Minor notes # # Tempfile's filename picking method is both thread-safe and inter-process-safe: # it guarantees that no other threads or processes will pick the same filename. # # Tempfile itself however may not be entirely thread-safe. If you access the # same Tempfile object from multiple threads then you should protect it with a # mutex. class Tempfile < DelegateClass(File) # call-seq: # new(basename, [tmpdir = Dir.tmpdir], [options]) # # Creates a temporary file with permissions 0600 (= only readable and # writable by the owner) and opens it with mode "w+". # # The +basename+ parameter is used to determine the name of the # temporary file. You can either pass a String or an Array with # 2 String elements. In the former form, the temporary file's base # name will begin with the given string. In the latter form, # the temporary file's base name will begin with the array's first # element, and end with the second element. For example: # # file = Tempfile.new('hello') # file.path # => something like: "/tmp/hello2843-8392-92849382--0" # # # Use the Array form to enforce an extension in the filename: # file = Tempfile.new(['hello', '.jpg']) # file.path # => something like: "/tmp/hello2843-8392-92849382--0.jpg" # # The temporary file will be placed in the directory as specified # by the +tmpdir+ parameter. By default, this is +Dir.tmpdir+. # When $SAFE > 0 and the given +tmpdir+ is tainted, it uses # '/tmp' as the temporary directory. Please note that ENV values # are tainted by default, and +Dir.tmpdir+'s return value might # come from environment variables (e.g. $TMPDIR). # # file = Tempfile.new('hello', '/home/aisaka') # file.path # => something like: "/home/aisaka/hello2843-8392-92849382--0" # # You can also pass an options hash. Under the hood, Tempfile creates # the temporary file using +File.open+. These options will be passed to # +File.open+. This is mostly useful for specifying encoding # options, e.g.: # # Tempfile.new('hello', '/home/aisaka', :encoding => 'ascii-8bit') # # # You can also omit the 'tmpdir' parameter: # Tempfile.new('hello', :encoding => 'ascii-8bit') # # === Exceptions # # If Tempfile.new cannot find a unique filename within a limited # number of tries, then it will raise an exception. def initialize(basename, tmpdir=nil, mode: 0, **options) if block_given? warn "Tempfile.new doesn't call the given block." end @data = [] @clean_proc = Remover.new(@data) ObjectSpace.define_finalizer(self, @clean_proc) ::Dir::Tmpname.create(basename, tmpdir, options) do |tmpname, n, opts| mode |= File::RDWR|File::CREAT|File::EXCL opts[:perm] = 0600 @data[1] = @tmpfile = File.open(tmpname, mode, opts) @data[0] = @tmpname = tmpname @mode = mode & ~(File::CREAT|File::EXCL) opts.freeze @opts = opts end super(@tmpfile) end # Opens or reopens the file with mode "r+". def open @tmpfile.close if @tmpfile @tmpfile = File.open(@tmpname, @mode, @opts) @data[1] = @tmpfile __setobj__(@tmpfile) end def _close # :nodoc: begin @tmpfile.close if @tmpfile ensure @tmpfile = nil @data[1] = nil if @data end end protected :_close # Closes the file. If +unlink_now+ is true, then the file will be unlinked # (deleted) after closing. Of course, you can choose to later call #unlink # if you do not unlink it now. # # If you don't explicitly unlink the temporary file, the removal # will be delayed until the object is finalized. def close(unlink_now=false) if unlink_now close! else _close end end # Closes and unlinks (deletes) the file. Has the same effect as called # close(true). def close! _close unlink end # Unlinks (deletes) the file from the filesystem. One should always unlink # the file after using it, as is explained in the "Explicit close" good # practice section in the Tempfile overview: # # file = Tempfile.new('foo') # begin # ...do something with file... # ensure # file.close # file.unlink # deletes the temp file # end # # === Unlink-before-close # # On POSIX systems it's possible to unlink a file before closing it. This # practice is explained in detail in the Tempfile overview (section # "Unlink after creation"); please refer there for more information. # # However, unlink-before-close may not be supported on non-POSIX operating # systems. Microsoft Windows is the most notable case: unlinking a non-closed # file will result in an error, which this method will silently ignore. If # you want to practice unlink-before-close whenever possible, then you should # write code like this: # # file = Tempfile.new('foo') # file.unlink # On Windows this silently fails. # begin # ... do something with file ... # ensure # file.close! # Closes the file handle. If the file wasn't unlinked # # because #unlink failed, then this method will attempt # # to do so again. # end def unlink return unless @tmpname begin File.unlink(@tmpname) rescue Errno::ENOENT rescue Errno::EACCES # may not be able to unlink on Windows; just ignore return end # remove tmpname from remover @data[0] = @data[1] = nil @tmpname = nil ObjectSpace.undefine_finalizer(self) end alias delete unlink # Returns the full path name of the temporary file. # This will be nil if #unlink has been called. def path @tmpname end # Returns the size of the temporary file. As a side effect, the IO # buffer is flushed before determining the size. def size if @tmpfile @tmpfile.flush @tmpfile.stat.size elsif @tmpname File.size(@tmpname) else 0 end end alias length size # :stopdoc: def inspect if closed? "#<#{self.class}:#{path} (closed)>" else "#<#{self.class}:#{path}>" end end class Remover def initialize(data) @pid = $$ @data = data end def call(*args) return if @pid != $$ path, tmpfile = @data STDERR.print "removing ", path, "..." if $DEBUG tmpfile.close if tmpfile if path begin File.unlink(path) rescue Errno::ENOENT end end STDERR.print "done\n" if $DEBUG end end class << self # :startdoc: # Creates a new Tempfile. # # If no block is given, this is a synonym for Tempfile.new. # # If a block is given, then a Tempfile object will be constructed, # and the block is run with said object as argument. The Tempfile # object will be automatically closed after the block terminates. # The call returns the value of the block. # # In any case, all arguments (+*args+) will be passed to Tempfile.new. # # Tempfile.open('foo', '/home/temp') do |f| # ... do something with f ... # end # # # Equivalent: # f = Tempfile.open('foo', '/home/temp') # begin # ... do something with f ... # ensure # f.close # end def open(*args) tempfile = new(*args) if block_given? begin yield(tempfile) ensure tempfile.close end else tempfile end end end end # Creates a temporally file as usual File object (not Tempfile). # It don't use finalizer and delegation. # # If no block is given, this is similar to Tempfile.new except # creating File instead of Tempfile. # The created file is not removed automatically. # You should use File.unlink to remove it. # # If a block is given, then a File object will be constructed, # and the block is invoked with the object as the argument. # The File object will be automatically closed and # the temporally file is removed after the block terminates. # The call returns the value of the block. # # In any case, all arguments (+*args+) will be treated as Tempfile.new. # # Tempfile.create('foo', '/home/temp') do |f| # ... do something with f ... # end # def Tempfile.create(basename, tmpdir=nil, mode: 0, **options) tmpfile = nil Dir::Tmpname.create(basename, tmpdir, options) do |tmpname, n, opts| mode |= File::RDWR|File::CREAT|File::EXCL opts[:perm] = 0600 tmpfile = File.open(tmpname, mode, opts) end if block_given? begin yield tmpfile ensure tmpfile.close if !tmpfile.closed? File.unlink tmpfile end else tmpfile end end PK!V;II 2.2.0/csv.rbnu[# encoding: US-ASCII # = csv.rb -- CSV Reading and Writing # # Created by James Edward Gray II on 2005-10-31. # Copyright 2005 James Edward Gray II. You can redistribute or modify this code # under the terms of Ruby's license. # # See CSV for documentation. # # == Description # # Welcome to the new and improved CSV. # # This version of the CSV library began its life as FasterCSV. FasterCSV was # intended as a replacement to Ruby's then standard CSV library. It was # designed to address concerns users of that library had and it had three # primary goals: # # 1. Be significantly faster than CSV while remaining a pure Ruby library. # 2. Use a smaller and easier to maintain code base. (FasterCSV eventually # grew larger, was also but considerably richer in features. The parsing # core remains quite small.) # 3. Improve on the CSV interface. # # Obviously, the last one is subjective. I did try to defer to the original # interface whenever I didn't have a compelling reason to change it though, so # hopefully this won't be too radically different. # # We must have met our goals because FasterCSV was renamed to CSV and replaced # the original library as of Ruby 1.9. If you are migrating code from 1.8 or # earlier, you may have to change your code to comply with the new interface. # # == What's Different From the Old CSV? # # I'm sure I'll miss something, but I'll try to mention most of the major # differences I am aware of, to help others quickly get up to speed: # # === CSV Parsing # # * This parser is m17n aware. See CSV for full details. # * This library has a stricter parser and will throw MalformedCSVErrors on # problematic data. # * This library has a less liberal idea of a line ending than CSV. What you # set as the :row_sep is law. It can auto-detect your line endings # though. # * The old library returned empty lines as [nil]. This library calls # them []. # * This library has a much faster parser. # # === Interface # # * CSV now uses Hash-style parameters to set options. # * CSV no longer has generate_row() or parse_row(). # * The old CSV's Reader and Writer classes have been dropped. # * CSV::open() is now more like Ruby's open(). # * CSV objects now support most standard IO methods. # * CSV now has a new() method used to wrap objects like String and IO for # reading and writing. # * CSV::generate() is different from the old method. # * CSV no longer supports partial reads. It works line-by-line. # * CSV no longer allows the instance methods to override the separators for # performance reasons. They must be set in the constructor. # # If you use this library and find yourself missing any functionality I have # trimmed, please {let me know}[mailto:james@grayproductions.net]. # # == Documentation # # See CSV for documentation. # # == What is CSV, really? # # CSV maintains a pretty strict definition of CSV taken directly from # {the RFC}[http://www.ietf.org/rfc/rfc4180.txt]. I relax the rules in only one # place and that is to make using this library easier. CSV will parse all valid # CSV. # # What you don't want to do is feed CSV invalid data. Because of the way the # CSV format works, it's common for a parser to need to read until the end of # the file to be sure a field is invalid. This eats a lot of time and memory. # # Luckily, when working with invalid CSV, Ruby's built-in methods will almost # always be superior in every way. For example, parsing non-quoted fields is as # easy as: # # data.split(",") # # == Questions and/or Comments # # Feel free to email {James Edward Gray II}[mailto:james@grayproductions.net] # with any questions. require "forwardable" require "English" require "date" require "stringio" # # This class provides a complete interface to CSV files and data. It offers # tools to enable you to read and write to and from Strings or IO objects, as # needed. # # == Reading # # === From a File # # ==== A Line at a Time # # CSV.foreach("path/to/file.csv") do |row| # # use row here... # end # # ==== All at Once # # arr_of_arrs = CSV.read("path/to/file.csv") # # === From a String # # ==== A Line at a Time # # CSV.parse("CSV,data,String") do |row| # # use row here... # end # # ==== All at Once # # arr_of_arrs = CSV.parse("CSV,data,String") # # == Writing # # === To a File # # CSV.open("path/to/file.csv", "wb") do |csv| # csv << ["row", "of", "CSV", "data"] # csv << ["another", "row"] # # ... # end # # === To a String # # csv_string = CSV.generate do |csv| # csv << ["row", "of", "CSV", "data"] # csv << ["another", "row"] # # ... # end # # == Convert a Single Line # # csv_string = ["CSV", "data"].to_csv # to CSV # csv_array = "CSV,String".parse_csv # from CSV # # == Shortcut Interface # # CSV { |csv_out| csv_out << %w{my data here} } # to $stdout # CSV(csv = "") { |csv_str| csv_str << %w{my data here} } # to a String # CSV($stderr) { |csv_err| csv_err << %w{my data here} } # to $stderr # CSV($stdin) { |csv_in| csv_in.each { |row| p row } } # from $stdin # # == Advanced Usage # # === Wrap an IO Object # # csv = CSV.new(io, options) # # ... read (with gets() or each()) from and write (with <<) to csv here ... # # == CSV and Character Encodings (M17n or Multilingualization) # # This new CSV parser is m17n savvy. The parser works in the Encoding of the IO # or String object being read from or written to. Your data is never transcoded # (unless you ask Ruby to transcode it for you) and will literally be parsed in # the Encoding it is in. Thus CSV will return Arrays or Rows of Strings in the # Encoding of your data. This is accomplished by transcoding the parser itself # into your Encoding. # # Some transcoding must take place, of course, to accomplish this multiencoding # support. For example, :col_sep, :row_sep, and # :quote_char must be transcoded to match your data. Hopefully this # makes the entire process feel transparent, since CSV's defaults should just # magically work for you data. However, you can set these values manually in # the target Encoding to avoid the translation. # # It's also important to note that while all of CSV's core parser is now # Encoding agnostic, some features are not. For example, the built-in # converters will try to transcode data to UTF-8 before making conversions. # Again, you can provide custom converters that are aware of your Encodings to # avoid this translation. It's just too hard for me to support native # conversions in all of Ruby's Encodings. # # Anyway, the practical side of this is simple: make sure IO and String objects # passed into CSV have the proper Encoding set and everything should just work. # CSV methods that allow you to open IO objects (CSV::foreach(), CSV::open(), # CSV::read(), and CSV::readlines()) do allow you to specify the Encoding. # # One minor exception comes when generating CSV into a String with an Encoding # that is not ASCII compatible. There's no existing data for CSV to use to # prepare itself and thus you will probably need to manually specify the desired # Encoding for most of those cases. It will try to guess using the fields in a # row of output though, when using CSV::generate_line() or Array#to_csv(). # # I try to point out any other Encoding issues in the documentation of methods # as they come up. # # This has been tested to the best of my ability with all non-"dummy" Encodings # Ruby ships with. However, it is brave new code and may have some bugs. # Please feel free to {report}[mailto:james@grayproductions.net] any issues you # find with it. # class CSV # The version of the installed library. VERSION = "2.4.8".freeze # # A CSV::Row is part Array and part Hash. It retains an order for the fields # and allows duplicates just as an Array would, but also allows you to access # fields by name just as you could if they were in a Hash. # # All rows returned by CSV will be constructed from this class, if header row # processing is activated. # class Row # # Construct a new CSV::Row from +headers+ and +fields+, which are expected # to be Arrays. If one Array is shorter than the other, it will be padded # with +nil+ objects. # # The optional +header_row+ parameter can be set to +true+ to indicate, via # CSV::Row.header_row?() and CSV::Row.field_row?(), that this is a header # row. Otherwise, the row is assumes to be a field row. # # A CSV::Row object supports the following Array methods through delegation: # # * empty?() # * length() # * size() # def initialize(headers, fields, header_row = false) @header_row = header_row headers.each { |h| h.freeze if h.is_a? String } # handle extra headers or fields @row = if headers.size >= fields.size headers.zip(fields) else fields.zip(headers).map { |pair| pair.reverse! } end end # Internal data format used to compare equality. attr_reader :row protected :row ### Array Delegation ### extend Forwardable def_delegators :@row, :empty?, :length, :size # Returns +true+ if this is a header row. def header_row? @header_row end # Returns +true+ if this is a field row. def field_row? not header_row? end # Returns the headers of this row. def headers @row.map { |pair| pair.first } end # # :call-seq: # field( header ) # field( header, offset ) # field( index ) # # This method will return the field value by +header+ or +index+. If a field # is not found, +nil+ is returned. # # When provided, +offset+ ensures that a header match occurs on or later # than the +offset+ index. You can use this to find duplicate headers, # without resorting to hard-coding exact indices. # def field(header_or_index, minimum_index = 0) # locate the pair finder = header_or_index.is_a?(Integer) ? :[] : :assoc pair = @row[minimum_index..-1].send(finder, header_or_index) # return the field if we have a pair pair.nil? ? nil : pair.last end alias_method :[], :field # # :call-seq: # fetch( header ) # fetch( header ) { |row| ... } # fetch( header, default ) # # This method will fetch the field value by +header+. It has the same # behavior as Hash#fetch: if there is a field with the given +header+, its # value is returned. Otherwise, if a block is given, it is yielded the # +header+ and its result is returned; if a +default+ is given as the # second argument, it is returned; otherwise a KeyError is raised. # def fetch(header, *varargs) raise ArgumentError, "Too many arguments" if varargs.length > 1 pair = @row.assoc(header) if pair pair.last else if block_given? yield header elsif varargs.empty? raise KeyError, "key not found: #{header}" else varargs.first end end end # Returns +true+ if there is a field with the given +header+. def has_key?(header) !!@row.assoc(header) end alias_method :include?, :has_key? alias_method :key?, :has_key? alias_method :member?, :has_key? # # :call-seq: # []=( header, value ) # []=( header, offset, value ) # []=( index, value ) # # Looks up the field by the semantics described in CSV::Row.field() and # assigns the +value+. # # Assigning past the end of the row with an index will set all pairs between # to [nil, nil]. Assigning to an unused header appends the new # pair. # def []=(*args) value = args.pop if args.first.is_a? Integer if @row[args.first].nil? # extending past the end with index @row[args.first] = [nil, value] @row.map! { |pair| pair.nil? ? [nil, nil] : pair } else # normal index assignment @row[args.first][1] = value end else index = index(*args) if index.nil? # appending a field self << [args.first, value] else # normal header assignment @row[index][1] = value end end end # # :call-seq: # <<( field ) # <<( header_and_field_array ) # <<( header_and_field_hash ) # # If a two-element Array is provided, it is assumed to be a header and field # and the pair is appended. A Hash works the same way with the key being # the header and the value being the field. Anything else is assumed to be # a lone field which is appended with a +nil+ header. # # This method returns the row for chaining. # def <<(arg) if arg.is_a?(Array) and arg.size == 2 # appending a header and name @row << arg elsif arg.is_a?(Hash) # append header and name pairs arg.each { |pair| @row << pair } else # append field value @row << [nil, arg] end self # for chaining end # # A shortcut for appending multiple fields. Equivalent to: # # args.each { |arg| csv_row << arg } # # This method returns the row for chaining. # def push(*args) args.each { |arg| self << arg } self # for chaining end # # :call-seq: # delete( header ) # delete( header, offset ) # delete( index ) # # Used to remove a pair from the row by +header+ or +index+. The pair is # located as described in CSV::Row.field(). The deleted pair is returned, # or +nil+ if a pair could not be found. # def delete(header_or_index, minimum_index = 0) if header_or_index.is_a? Integer # by index @row.delete_at(header_or_index) elsif i = index(header_or_index, minimum_index) # by header @row.delete_at(i) else [ ] end end # # The provided +block+ is passed a header and field for each pair in the row # and expected to return +true+ or +false+, depending on whether the pair # should be deleted. # # This method returns the row for chaining. # def delete_if(&block) @row.delete_if(&block) self # for chaining end # # This method accepts any number of arguments which can be headers, indices, # Ranges of either, or two-element Arrays containing a header and offset. # Each argument will be replaced with a field lookup as described in # CSV::Row.field(). # # If called with no arguments, all fields are returned. # def fields(*headers_and_or_indices) if headers_and_or_indices.empty? # return all fields--no arguments @row.map { |pair| pair.last } else # or work like values_at() headers_and_or_indices.inject(Array.new) do |all, h_or_i| all + if h_or_i.is_a? Range index_begin = h_or_i.begin.is_a?(Integer) ? h_or_i.begin : index(h_or_i.begin) index_end = h_or_i.end.is_a?(Integer) ? h_or_i.end : index(h_or_i.end) new_range = h_or_i.exclude_end? ? (index_begin...index_end) : (index_begin..index_end) fields.values_at(new_range) else [field(*Array(h_or_i))] end end end end alias_method :values_at, :fields # # :call-seq: # index( header ) # index( header, offset ) # # This method will return the index of a field with the provided +header+. # The +offset+ can be used to locate duplicate header names, as described in # CSV::Row.field(). # def index(header, minimum_index = 0) # find the pair index = headers[minimum_index..-1].index(header) # return the index at the right offset, if we found one index.nil? ? nil : index + minimum_index end # Returns +true+ if +name+ is a header for this row, and +false+ otherwise. def header?(name) headers.include? name end alias_method :include?, :header? # # Returns +true+ if +data+ matches a field in this row, and +false+ # otherwise. # def field?(data) fields.include? data end include Enumerable # # Yields each pair of the row as header and field tuples (much like # iterating over a Hash). # # Support for Enumerable. # # This method returns the row for chaining. # def each(&block) @row.each(&block) self # for chaining end # # Returns +true+ if this row contains the same headers and fields in the # same order as +other+. # def ==(other) return @row == other.row if other.is_a? CSV::Row @row == other end # # Collapses the row into a simple Hash. Be warning that this discards field # order and clobbers duplicate fields. # def to_hash # flatten just one level of the internal Array Hash[*@row.inject(Array.new) { |ary, pair| ary.push(*pair) }] end # # Returns the row as a CSV String. Headers are not used. Equivalent to: # # csv_row.fields.to_csv( options ) # def to_csv(options = Hash.new) fields.to_csv(options) end alias_method :to_s, :to_csv # A summary of fields, by header, in an ASCII compatible String. def inspect str = ["#<", self.class.to_s] each do |header, field| str << " " << (header.is_a?(Symbol) ? header.to_s : header.inspect) << ":" << field.inspect end str << ">" begin str.join('') rescue # any encoding error str.map do |s| e = Encoding::Converter.asciicompat_encoding(s.encoding) e ? s.encode(e) : s.force_encoding("ASCII-8BIT") end.join('') end end end # # A CSV::Table is a two-dimensional data structure for representing CSV # documents. Tables allow you to work with the data by row or column, # manipulate the data, and even convert the results back to CSV, if needed. # # All tables returned by CSV will be constructed from this class, if header # row processing is activated. # class Table # # Construct a new CSV::Table from +array_of_rows+, which are expected # to be CSV::Row objects. All rows are assumed to have the same headers. # # A CSV::Table object supports the following Array methods through # delegation: # # * empty?() # * length() # * size() # def initialize(array_of_rows) @table = array_of_rows @mode = :col_or_row end # The current access mode for indexing and iteration. attr_reader :mode # Internal data format used to compare equality. attr_reader :table protected :table ### Array Delegation ### extend Forwardable def_delegators :@table, :empty?, :length, :size # # Returns a duplicate table object, in column mode. This is handy for # chaining in a single call without changing the table mode, but be aware # that this method can consume a fair amount of memory for bigger data sets. # # This method returns the duplicate table for chaining. Don't chain # destructive methods (like []=()) this way though, since you are working # with a duplicate. # def by_col self.class.new(@table.dup).by_col! end # # Switches the mode of this table to column mode. All calls to indexing and # iteration methods will work with columns until the mode is changed again. # # This method returns the table and is safe to chain. # def by_col! @mode = :col self end # # Returns a duplicate table object, in mixed mode. This is handy for # chaining in a single call without changing the table mode, but be aware # that this method can consume a fair amount of memory for bigger data sets. # # This method returns the duplicate table for chaining. Don't chain # destructive methods (like []=()) this way though, since you are working # with a duplicate. # def by_col_or_row self.class.new(@table.dup).by_col_or_row! end # # Switches the mode of this table to mixed mode. All calls to indexing and # iteration methods will use the default intelligent indexing system until # the mode is changed again. In mixed mode an index is assumed to be a row # reference while anything else is assumed to be column access by headers. # # This method returns the table and is safe to chain. # def by_col_or_row! @mode = :col_or_row self end # # Returns a duplicate table object, in row mode. This is handy for chaining # in a single call without changing the table mode, but be aware that this # method can consume a fair amount of memory for bigger data sets. # # This method returns the duplicate table for chaining. Don't chain # destructive methods (like []=()) this way though, since you are working # with a duplicate. # def by_row self.class.new(@table.dup).by_row! end # # Switches the mode of this table to row mode. All calls to indexing and # iteration methods will work with rows until the mode is changed again. # # This method returns the table and is safe to chain. # def by_row! @mode = :row self end # # Returns the headers for the first row of this table (assumed to match all # other rows). An empty Array is returned for empty tables. # def headers if @table.empty? Array.new else @table.first.headers end end # # In the default mixed mode, this method returns rows for index access and # columns for header access. You can force the index association by first # calling by_col!() or by_row!(). # # Columns are returned as an Array of values. Altering that Array has no # effect on the table. # def [](index_or_header) if @mode == :row or # by index (@mode == :col_or_row and index_or_header.is_a? Integer) @table[index_or_header] else # by header @table.map { |row| row[index_or_header] } end end # # In the default mixed mode, this method assigns rows for index access and # columns for header access. You can force the index association by first # calling by_col!() or by_row!(). # # Rows may be set to an Array of values (which will inherit the table's # headers()) or a CSV::Row. # # Columns may be set to a single value, which is copied to each row of the # column, or an Array of values. Arrays of values are assigned to rows top # to bottom in row major order. Excess values are ignored and if the Array # does not have a value for each row the extra rows will receive a +nil+. # # Assigning to an existing column or row clobbers the data. Assigning to # new columns creates them at the right end of the table. # def []=(index_or_header, value) if @mode == :row or # by index (@mode == :col_or_row and index_or_header.is_a? Integer) if value.is_a? Array @table[index_or_header] = Row.new(headers, value) else @table[index_or_header] = value end else # set column if value.is_a? Array # multiple values @table.each_with_index do |row, i| if row.header_row? row[index_or_header] = index_or_header else row[index_or_header] = value[i] end end else # repeated value @table.each do |row| if row.header_row? row[index_or_header] = index_or_header else row[index_or_header] = value end end end end end # # The mixed mode default is to treat a list of indices as row access, # returning the rows indicated. Anything else is considered columnar # access. For columnar access, the return set has an Array for each row # with the values indicated by the headers in each Array. You can force # column or row mode using by_col!() or by_row!(). # # You cannot mix column and row access. # def values_at(*indices_or_headers) if @mode == :row or # by indices ( @mode == :col_or_row and indices_or_headers.all? do |index| index.is_a?(Integer) or ( index.is_a?(Range) and index.first.is_a?(Integer) and index.last.is_a?(Integer) ) end ) @table.values_at(*indices_or_headers) else # by headers @table.map { |row| row.values_at(*indices_or_headers) } end end # # Adds a new row to the bottom end of this table. You can provide an Array, # which will be converted to a CSV::Row (inheriting the table's headers()), # or a CSV::Row. # # This method returns the table for chaining. # def <<(row_or_array) if row_or_array.is_a? Array # append Array @table << Row.new(headers, row_or_array) else # append Row @table << row_or_array end self # for chaining end # # A shortcut for appending multiple rows. Equivalent to: # # rows.each { |row| self << row } # # This method returns the table for chaining. # def push(*rows) rows.each { |row| self << row } self # for chaining end # # Removes and returns the indicated column or row. In the default mixed # mode indices refer to rows and everything else is assumed to be a column # header. Use by_col!() or by_row!() to force the lookup. # def delete(index_or_header) if @mode == :row or # by index (@mode == :col_or_row and index_or_header.is_a? Integer) @table.delete_at(index_or_header) else # by header @table.map { |row| row.delete(index_or_header).last } end end # # Removes any column or row for which the block returns +true+. In the # default mixed mode or row mode, iteration is the standard row major # walking of rows. In column mode, iteration will +yield+ two element # tuples containing the column name and an Array of values for that column. # # This method returns the table for chaining. # def delete_if(&block) if @mode == :row or @mode == :col_or_row # by index @table.delete_if(&block) else # by header to_delete = Array.new headers.each_with_index do |header, i| to_delete << header if block[[header, self[header]]] end to_delete.map { |header| delete(header) } end self # for chaining end include Enumerable # # In the default mixed mode or row mode, iteration is the standard row major # walking of rows. In column mode, iteration will +yield+ two element # tuples containing the column name and an Array of values for that column. # # This method returns the table for chaining. # def each(&block) if @mode == :col headers.each { |header| block[[header, self[header]]] } else @table.each(&block) end self # for chaining end # Returns +true+ if all rows of this table ==() +other+'s rows. def ==(other) @table == other.table end # # Returns the table as an Array of Arrays. Headers will be the first row, # then all of the field rows will follow. # def to_a @table.inject([headers]) do |array, row| if row.header_row? array else array + [row.fields] end end end # # Returns the table as a complete CSV String. Headers will be listed first, # then all of the field rows. # # This method assumes you want the Table.headers(), unless you explicitly # pass :write_headers => false. # def to_csv(options = Hash.new) wh = options.fetch(:write_headers, true) @table.inject(wh ? [headers.to_csv(options)] : [ ]) do |rows, row| if row.header_row? rows else rows + [row.fields.to_csv(options)] end end.join('') end alias_method :to_s, :to_csv # Shows the mode and size of this table in a US-ASCII String. def inspect "#<#{self.class} mode:#{@mode} row_count:#{to_a.size}>".encode("US-ASCII") end end # The error thrown when the parser encounters illegal CSV formatting. class MalformedCSVError < RuntimeError; end # # A FieldInfo Struct contains details about a field's position in the data # source it was read from. CSV will pass this Struct to some blocks that make # decisions based on field structure. See CSV.convert_fields() for an # example. # # index:: The zero-based index of the field in its row. # line:: The line of the data source this row is from. # header:: The header for the column, when available. # FieldInfo = Struct.new(:index, :line, :header) # A Regexp used to find and convert some common Date formats. DateMatcher = / \A(?: (\w+,?\s+)?\w+\s+\d{1,2},?\s+\d{2,4} | \d{4}-\d{2}-\d{2} )\z /x # A Regexp used to find and convert some common DateTime formats. DateTimeMatcher = / \A(?: (\w+,?\s+)?\w+\s+\d{1,2}\s+\d{1,2}:\d{1,2}:\d{1,2},?\s+\d{2,4} | \d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2} )\z /x # The encoding used by all converters. ConverterEncoding = Encoding.find("UTF-8") # # This Hash holds the built-in converters of CSV that can be accessed by name. # You can select Converters with CSV.convert() or through the +options+ Hash # passed to CSV::new(). # # :integer:: Converts any field Integer() accepts. # :float:: Converts any field Float() accepts. # :numeric:: A combination of :integer # and :float. # :date:: Converts any field Date::parse() accepts. # :date_time:: Converts any field DateTime::parse() accepts. # :all:: All built-in converters. A combination of # :date_time and :numeric. # # All built-in converters transcode field data to UTF-8 before attempting a # conversion. If your data cannot be transcoded to UTF-8 the conversion will # fail and the field will remain unchanged. # # This Hash is intentionally left unfrozen and users should feel free to add # values to it that can be accessed by all CSV objects. # # To add a combo field, the value should be an Array of names. Combo fields # can be nested with other combo fields. # Converters = { integer: lambda { |f| Integer(f.encode(ConverterEncoding)) rescue f }, float: lambda { |f| Float(f.encode(ConverterEncoding)) rescue f }, numeric: [:integer, :float], date: lambda { |f| begin e = f.encode(ConverterEncoding) e =~ DateMatcher ? Date.parse(e) : f rescue # encoding conversion or date parse errors f end }, date_time: lambda { |f| begin e = f.encode(ConverterEncoding) e =~ DateTimeMatcher ? DateTime.parse(e) : f rescue # encoding conversion or date parse errors f end }, all: [:date_time, :numeric] } # # This Hash holds the built-in header converters of CSV that can be accessed # by name. You can select HeaderConverters with CSV.header_convert() or # through the +options+ Hash passed to CSV::new(). # # :downcase:: Calls downcase() on the header String. # :symbol:: The header String is downcased, spaces are # replaced with underscores, non-word characters # are dropped, and finally to_sym() is called. # # All built-in header converters transcode header data to UTF-8 before # attempting a conversion. If your data cannot be transcoded to UTF-8 the # conversion will fail and the header will remain unchanged. # # This Hash is intentionally left unfrozen and users should feel free to add # values to it that can be accessed by all CSV objects. # # To add a combo field, the value should be an Array of names. Combo fields # can be nested with other combo fields. # HeaderConverters = { downcase: lambda { |h| h.encode(ConverterEncoding).downcase }, symbol: lambda { |h| h.encode(ConverterEncoding).downcase.strip.gsub(/\s+/, "_"). gsub(/\W+/, "").to_sym } } # # The options used when no overrides are given by calling code. They are: # # :col_sep:: "," # :row_sep:: :auto # :quote_char:: '"' # :field_size_limit:: +nil+ # :converters:: +nil+ # :unconverted_fields:: +nil+ # :headers:: +false+ # :return_headers:: +false+ # :header_converters:: +nil+ # :skip_blanks:: +false+ # :force_quotes:: +false+ # :skip_lines:: +nil+ # DEFAULT_OPTIONS = { col_sep: ",", row_sep: :auto, quote_char: '"', field_size_limit: nil, converters: nil, unconverted_fields: nil, headers: false, return_headers: false, header_converters: nil, skip_blanks: false, force_quotes: false, skip_lines: nil }.freeze # # This method will return a CSV instance, just like CSV::new(), but the # instance will be cached and returned for all future calls to this method for # the same +data+ object (tested by Object#object_id()) with the same # +options+. # # If a block is given, the instance is passed to the block and the return # value becomes the return value of the block. # def self.instance(data = $stdout, options = Hash.new) # create a _signature_ for this method call, data object and options sig = [data.object_id] + options.values_at(*DEFAULT_OPTIONS.keys.sort_by { |sym| sym.to_s }) # fetch or create the instance for this signature @@instances ||= Hash.new instance = (@@instances[sig] ||= new(data, options)) if block_given? yield instance # run block, if given, returning result else instance # or return the instance end end # # :call-seq: # filter( options = Hash.new ) { |row| ... } # filter( input, options = Hash.new ) { |row| ... } # filter( input, output, options = Hash.new ) { |row| ... } # # This method is a convenience for building Unix-like filters for CSV data. # Each row is yielded to the provided block which can alter it as needed. # After the block returns, the row is appended to +output+ altered or not. # # The +input+ and +output+ arguments can be anything CSV::new() accepts # (generally String or IO objects). If not given, they default to # ARGF and $stdout. # # The +options+ parameter is also filtered down to CSV::new() after some # clever key parsing. Any key beginning with :in_ or # :input_ will have that leading identifier stripped and will only # be used in the +options+ Hash for the +input+ object. Keys starting with # :out_ or :output_ affect only +output+. All other keys # are assigned to both objects. # # The :output_row_sep +option+ defaults to # $INPUT_RECORD_SEPARATOR ($/). # def self.filter(*args) # parse options for input, output, or both in_options, out_options = Hash.new, {row_sep: $INPUT_RECORD_SEPARATOR} if args.last.is_a? Hash args.pop.each do |key, value| case key.to_s when /\Ain(?:put)?_(.+)\Z/ in_options[$1.to_sym] = value when /\Aout(?:put)?_(.+)\Z/ out_options[$1.to_sym] = value else in_options[key] = value out_options[key] = value end end end # build input and output wrappers input = new(args.shift || ARGF, in_options) output = new(args.shift || $stdout, out_options) # read, yield, write input.each do |row| yield row output << row end end # # This method is intended as the primary interface for reading CSV files. You # pass a +path+ and any +options+ you wish to set for the read. Each row of # file will be passed to the provided +block+ in turn. # # The +options+ parameter can be anything CSV::new() understands. This method # also understands an additional :encoding parameter that you can use # to specify the Encoding of the data in the file to be read. You must provide # this unless your data is in Encoding::default_external(). CSV will use this # to determine how to parse the data. You may provide a second Encoding to # have the data transcoded as it is read. For example, # encoding: "UTF-32BE:UTF-8" would read UTF-32BE data from the file # but transcode it to UTF-8 before CSV parses it. # def self.foreach(path, options = Hash.new, &block) return to_enum(__method__, path, options) unless block open(path, options) do |csv| csv.each(&block) end end # # :call-seq: # generate( str, options = Hash.new ) { |csv| ... } # generate( options = Hash.new ) { |csv| ... } # # This method wraps a String you provide, or an empty default String, in a # CSV object which is passed to the provided block. You can use the block to # append CSV rows to the String and when the block exits, the final String # will be returned. # # Note that a passed String *is* modified by this method. Call dup() before # passing if you need a new String. # # The +options+ parameter can be anything CSV::new() understands. This method # understands an additional :encoding parameter when not passed a # String to set the base Encoding for the output. CSV needs this hint if you # plan to output non-ASCII compatible data. # def self.generate(*args) # add a default empty String, if none was given if args.first.is_a? String io = StringIO.new(args.shift) io.seek(0, IO::SEEK_END) args.unshift(io) else encoding = args[-1][:encoding] if args.last.is_a?(Hash) str = "" str.force_encoding(encoding) if encoding args.unshift(str) end csv = new(*args) # wrap yield csv # yield for appending csv.string # return final String end # # This method is a shortcut for converting a single row (Array) into a CSV # String. # # The +options+ parameter can be anything CSV::new() understands. This method # understands an additional :encoding parameter to set the base # Encoding for the output. This method will try to guess your Encoding from # the first non-+nil+ field in +row+, if possible, but you may need to use # this parameter as a backup plan. # # The :row_sep +option+ defaults to $INPUT_RECORD_SEPARATOR # ($/) when calling this method. # def self.generate_line(row, options = Hash.new) options = {row_sep: $INPUT_RECORD_SEPARATOR}.merge(options) encoding = options.delete(:encoding) str = "" if encoding str.force_encoding(encoding) elsif field = row.find { |f| not f.nil? } str.force_encoding(String(field).encoding) end (new(str, options) << row).string end # # :call-seq: # open( filename, mode = "rb", options = Hash.new ) { |faster_csv| ... } # open( filename, options = Hash.new ) { |faster_csv| ... } # open( filename, mode = "rb", options = Hash.new ) # open( filename, options = Hash.new ) # # This method opens an IO object, and wraps that with CSV. This is intended # as the primary interface for writing a CSV file. # # You must pass a +filename+ and may optionally add a +mode+ for Ruby's # open(). You may also pass an optional Hash containing any +options+ # CSV::new() understands as the final argument. # # This method works like Ruby's open() call, in that it will pass a CSV object # to a provided block and close it when the block terminates, or it will # return the CSV object when no block is provided. (*Note*: This is different # from the Ruby 1.8 CSV library which passed rows to the block. Use # CSV::foreach() for that behavior.) # # You must provide a +mode+ with an embedded Encoding designator unless your # data is in Encoding::default_external(). CSV will check the Encoding of the # underlying IO object (set by the +mode+ you pass) to determine how to parse # the data. You may provide a second Encoding to have the data transcoded as # it is read just as you can with a normal call to IO::open(). For example, # "rb:UTF-32BE:UTF-8" would read UTF-32BE data from the file but # transcode it to UTF-8 before CSV parses it. # # An opened CSV object will delegate to many IO methods for convenience. You # may call: # # * binmode() # * binmode?() # * close() # * close_read() # * close_write() # * closed?() # * eof() # * eof?() # * external_encoding() # * fcntl() # * fileno() # * flock() # * flush() # * fsync() # * internal_encoding() # * ioctl() # * isatty() # * path() # * pid() # * pos() # * pos=() # * reopen() # * seek() # * stat() # * sync() # * sync=() # * tell() # * to_i() # * to_io() # * truncate() # * tty?() # def self.open(*args) # find the +options+ Hash options = if args.last.is_a? Hash then args.pop else Hash.new end # wrap a File opened with the remaining +args+ with no newline # decorator file_opts = {universal_newline: false}.merge(options) begin f = File.open(*args, file_opts) rescue ArgumentError => e raise unless /needs binmode/ =~ e.message and args.size == 1 args << "rb" file_opts = {encoding: Encoding.default_external}.merge(file_opts) retry end begin csv = new(f, options) rescue Exception f.close raise end # handle blocks like Ruby's open(), not like the CSV library if block_given? begin yield csv ensure csv.close end else csv end end # # :call-seq: # parse( str, options = Hash.new ) { |row| ... } # parse( str, options = Hash.new ) # # This method can be used to easily parse CSV out of a String. You may either # provide a +block+ which will be called with each row of the String in turn, # or just use the returned Array of Arrays (when no +block+ is given). # # You pass your +str+ to read from, and an optional +options+ Hash containing # anything CSV::new() understands. # def self.parse(*args, &block) csv = new(*args) if block.nil? # slurp contents, if no block is given begin csv.read ensure csv.close end else # or pass each row to a provided block csv.each(&block) end end # # This method is a shortcut for converting a single line of a CSV String into # an Array. Note that if +line+ contains multiple rows, anything beyond the # first row is ignored. # # The +options+ parameter can be anything CSV::new() understands. # def self.parse_line(line, options = Hash.new) new(line, options).shift end # # Use to slurp a CSV file into an Array of Arrays. Pass the +path+ to the # file and any +options+ CSV::new() understands. This method also understands # an additional :encoding parameter that you can use to specify the # Encoding of the data in the file to be read. You must provide this unless # your data is in Encoding::default_external(). CSV will use this to determine # how to parse the data. You may provide a second Encoding to have the data # transcoded as it is read. For example, # encoding: "UTF-32BE:UTF-8" would read UTF-32BE data from the file # but transcode it to UTF-8 before CSV parses it. # def self.read(path, *options) open(path, *options) { |csv| csv.read } end # Alias for CSV::read(). def self.readlines(*args) read(*args) end # # A shortcut for: # # CSV.read( path, { headers: true, # converters: :numeric, # header_converters: :symbol }.merge(options) ) # def self.table(path, options = Hash.new) read( path, { headers: true, converters: :numeric, header_converters: :symbol }.merge(options) ) end # # This constructor will wrap either a String or IO object passed in +data+ for # reading and/or writing. In addition to the CSV instance methods, several IO # methods are delegated. (See CSV::open() for a complete list.) If you pass # a String for +data+, you can later retrieve it (after writing to it, for # example) with CSV.string(). # # Note that a wrapped String will be positioned at at the beginning (for # reading). If you want it at the end (for writing), use CSV::generate(). # If you want any other positioning, pass a preset StringIO object instead. # # You may set any reading and/or writing preferences in the +options+ Hash. # Available options are: # # :col_sep:: The String placed between each field. # This String will be transcoded into # the data's Encoding before parsing. # :row_sep:: The String appended to the end of each # row. This can be set to the special # :auto setting, which requests # that CSV automatically discover this # from the data. Auto-discovery reads # ahead in the data looking for the next # "\r\n", "\n", or # "\r" sequence. A sequence # will be selected even if it occurs in # a quoted field, assuming that you # would have the same line endings # there. If none of those sequences is # found, +data+ is ARGF, # STDIN, STDOUT, or # STDERR, or the stream is only # available for output, the default # $INPUT_RECORD_SEPARATOR # ($/) is used. Obviously, # discovery takes a little time. Set # manually if speed is important. Also # note that IO objects should be opened # in binary mode on Windows if this # feature will be used as the # line-ending translation can cause # problems with resetting the document # position to where it was before the # read ahead. This String will be # transcoded into the data's Encoding # before parsing. # :quote_char:: The character used to quote fields. # This has to be a single character # String. This is useful for # application that incorrectly use # ' as the quote character # instead of the correct ". # CSV will always consider a double # sequence of this character to be an # escaped quote. This String will be # transcoded into the data's Encoding # before parsing. # :field_size_limit:: This is a maximum size CSV will read # ahead looking for the closing quote # for a field. (In truth, it reads to # the first line ending beyond this # size.) If a quote cannot be found # within the limit CSV will raise a # MalformedCSVError, assuming the data # is faulty. You can use this limit to # prevent what are effectively DoS # attacks on the parser. However, this # limit can cause a legitimate parse to # fail and thus is set to +nil+, or off, # by default. # :converters:: An Array of names from the Converters # Hash and/or lambdas that handle custom # conversion. A single converter # doesn't have to be in an Array. All # built-in converters try to transcode # fields to UTF-8 before converting. # The conversion will fail if the data # cannot be transcoded, leaving the # field unchanged. # :unconverted_fields:: If set to +true+, an # unconverted_fields() method will be # added to all returned rows (Array or # CSV::Row) that will return the fields # as they were before conversion. Note # that :headers supplied by # Array or String were not fields of the # document and thus will have an empty # Array attached. # :headers:: If set to :first_row or # +true+, the initial row of the CSV # file will be treated as a row of # headers. If set to an Array, the # contents will be used as the headers. # If set to a String, the String is run # through a call of CSV::parse_line() # with the same :col_sep, # :row_sep, and # :quote_char as this instance # to produce an Array of headers. This # setting causes CSV#shift() to return # rows as CSV::Row objects instead of # Arrays and CSV#read() to return # CSV::Table objects instead of an Array # of Arrays. # :return_headers:: When +false+, header rows are silently # swallowed. If set to +true+, header # rows are returned in a CSV::Row object # with identical headers and # fields (save that the fields do not go # through the converters). # :write_headers:: When +true+ and :headers is # set, a header row will be added to the # output. # :header_converters:: Identical in functionality to # :converters save that the # conversions are only made to header # rows. All built-in converters try to # transcode headers to UTF-8 before # converting. The conversion will fail # if the data cannot be transcoded, # leaving the header unchanged. # :skip_blanks:: When set to a +true+ value, CSV will # skip over any empty rows. Note that # this setting will not skip rows that # contain column separators, even if # the rows contain no actual data. If # you want to skip rows that contain # separators but no content, consider # using :skip_lines, or # inspecting fields.compact.empty? on # each row. # :force_quotes:: When set to a +true+ value, CSV will # quote all CSV fields it creates. # :skip_lines:: When set to an object responding to # match, every line matching # it is considered a comment and ignored # during parsing. When set to a String, # it is first converted to a Regexp. # When set to +nil+ no line is considered # a comment. If the passed object does # not respond to match, # ArgumentError is thrown. # # See CSV::DEFAULT_OPTIONS for the default settings. # # Options cannot be overridden in the instance methods for performance reasons, # so be sure to set what you want here. # def initialize(data, options = Hash.new) if data.nil? raise ArgumentError.new("Cannot parse nil as CSV") end # build the options for this read/write options = DEFAULT_OPTIONS.merge(options) # create the IO object we will read from @io = data.is_a?(String) ? StringIO.new(data) : data # honor the IO encoding if we can, otherwise default to ASCII-8BIT @encoding = raw_encoding(nil) || ( if encoding = options.delete(:internal_encoding) case encoding when Encoding; encoding else Encoding.find(encoding) end end ) || ( case encoding = options.delete(:encoding) when Encoding; encoding when /\A[^:]+/; Encoding.find($&) end ) || Encoding.default_internal || Encoding.default_external # # prepare for building safe regular expressions in the target encoding, # if we can transcode the needed characters # @re_esc = "\\".encode(@encoding) rescue "" @re_chars = /#{%"[-\\]\\[\\.^$?*+{}()|# \r\n\t\f\v]".encode(@encoding)}/ init_separators(options) init_parsers(options) init_converters(options) init_headers(options) init_comments(options) @force_encoding = !!(encoding || options.delete(:encoding)) options.delete(:internal_encoding) options.delete(:external_encoding) unless options.empty? raise ArgumentError, "Unknown options: #{options.keys.join(', ')}." end # track our own lineno since IO gets confused about line-ends is CSV fields @lineno = 0 end # # The encoded :col_sep used in parsing and writing. See CSV::new # for details. # attr_reader :col_sep # # The encoded :row_sep used in parsing and writing. See CSV::new # for details. # attr_reader :row_sep # # The encoded :quote_char used in parsing and writing. See CSV::new # for details. # attr_reader :quote_char # The limit for field size, if any. See CSV::new for details. attr_reader :field_size_limit # The regex marking a line as a comment. See CSV::new for details attr_reader :skip_lines # # Returns the current list of converters in effect. See CSV::new for details. # Built-in converters will be returned by name, while others will be returned # as is. # def converters @converters.map do |converter| name = Converters.rassoc(converter) name ? name.first : converter end end # # Returns +true+ if unconverted_fields() to parsed results. See CSV::new # for details. # def unconverted_fields?() @unconverted_fields end # # Returns +nil+ if headers will not be used, +true+ if they will but have not # yet been read, or the actual headers after they have been read. See # CSV::new for details. # def headers @headers || true if @use_headers end # # Returns +true+ if headers will be returned as a row of results. # See CSV::new for details. # def return_headers?() @return_headers end # Returns +true+ if headers are written in output. See CSV::new for details. def write_headers?() @write_headers end # # Returns the current list of converters in effect for headers. See CSV::new # for details. Built-in converters will be returned by name, while others # will be returned as is. # def header_converters @header_converters.map do |converter| name = HeaderConverters.rassoc(converter) name ? name.first : converter end end # # Returns +true+ blank lines are skipped by the parser. See CSV::new # for details. # def skip_blanks?() @skip_blanks end # Returns +true+ if all output fields are quoted. See CSV::new for details. def force_quotes?() @force_quotes end # # The Encoding CSV is parsing or writing in. This will be the Encoding you # receive parsed data in and/or the Encoding data will be written in. # attr_reader :encoding # # The line number of the last row read from this file. Fields with nested # line-end characters will not affect this count. # attr_reader :lineno ### IO and StringIO Delegation ### extend Forwardable def_delegators :@io, :binmode, :binmode?, :close, :close_read, :close_write, :closed?, :eof, :eof?, :external_encoding, :fcntl, :fileno, :flock, :flush, :fsync, :internal_encoding, :ioctl, :isatty, :path, :pid, :pos, :pos=, :reopen, :seek, :stat, :string, :sync, :sync=, :tell, :to_i, :to_io, :truncate, :tty? # Rewinds the underlying IO object and resets CSV's lineno() counter. def rewind @headers = nil @lineno = 0 @io.rewind end ### End Delegation ### # # The primary write method for wrapped Strings and IOs, +row+ (an Array or # CSV::Row) is converted to CSV and appended to the data source. When a # CSV::Row is passed, only the row's fields() are appended to the output. # # The data source must be open for writing. # def <<(row) # make sure headers have been assigned if header_row? and [Array, String].include? @use_headers.class parse_headers # won't read data for Array or String self << @headers if @write_headers end # handle CSV::Row objects and Hashes row = case row when self.class::Row then row.fields when Hash then @headers.map { |header| row[header] } else row end @headers = row if header_row? @lineno += 1 output = row.map(&@quote).join(@col_sep) + @row_sep # quote and separate if @io.is_a?(StringIO) and output.encoding != (encoding = raw_encoding) if @force_encoding output = output.encode(encoding) elsif (compatible_encoding = Encoding.compatible?(@io.string, output)) @io.set_encoding(compatible_encoding) @io.seek(0, IO::SEEK_END) end end @io << output self # for chaining end alias_method :add_row, :<< alias_method :puts, :<< # # :call-seq: # convert( name ) # convert { |field| ... } # convert { |field, field_info| ... } # # You can use this method to install a CSV::Converters built-in, or provide a # block that handles a custom conversion. # # If you provide a block that takes one argument, it will be passed the field # and is expected to return the converted value or the field itself. If your # block takes two arguments, it will also be passed a CSV::FieldInfo Struct, # containing details about the field. Again, the block should return a # converted field or the field itself. # def convert(name = nil, &converter) add_converter(:converters, self.class::Converters, name, &converter) end # # :call-seq: # header_convert( name ) # header_convert { |field| ... } # header_convert { |field, field_info| ... } # # Identical to CSV#convert(), but for header rows. # # Note that this method must be called before header rows are read to have any # effect. # def header_convert(name = nil, &converter) add_converter( :header_converters, self.class::HeaderConverters, name, &converter ) end include Enumerable # # Yields each row of the data source in turn. # # Support for Enumerable. # # The data source must be open for reading. # def each if block_given? while row = shift yield row end else to_enum end end # # Slurps the remaining rows and returns an Array of Arrays. # # The data source must be open for reading. # def read rows = to_a if @use_headers Table.new(rows) else rows end end alias_method :readlines, :read # Returns +true+ if the next row read will be a header row. def header_row? @use_headers and @headers.nil? end # # The primary read method for wrapped Strings and IOs, a single row is pulled # from the data source, parsed and returned as an Array of fields (if header # rows are not used) or a CSV::Row (when header rows are used). # # The data source must be open for reading. # def shift ######################################################################### ### This method is purposefully kept a bit long as simple conditional ### ### checks are faster than numerous (expensive) method calls. ### ######################################################################### # handle headers not based on document content if header_row? and @return_headers and [Array, String].include? @use_headers.class if @unconverted_fields return add_unconverted_fields(parse_headers, Array.new) else return parse_headers end end # # it can take multiple calls to @io.gets() to get a full line, # because of \r and/or \n characters embedded in quoted fields # in_extended_col = false csv = Array.new loop do # add another read to the line unless parse = @io.gets(@row_sep) return nil end parse.sub!(@parsers[:line_end], "") if csv.empty? # # I believe a blank line should be an Array.new, not Ruby 1.8 # CSV's [nil] # if parse.empty? @lineno += 1 if @skip_blanks next elsif @unconverted_fields return add_unconverted_fields(Array.new, Array.new) elsif @use_headers return self.class::Row.new(Array.new, Array.new) else return Array.new end end end next if @skip_lines and @skip_lines.match parse parts = parse.split(@col_sep, -1) if parts.empty? if in_extended_col csv[-1] << @col_sep # will be replaced with a @row_sep after the parts.each loop else csv << nil end end # This loop is the hot path of csv parsing. Some things may be non-dry # for a reason. Make sure to benchmark when refactoring. parts.each do |part| if in_extended_col # If we are continuing a previous column if part[-1] == @quote_char && part.count(@quote_char) % 2 != 0 # extended column ends csv.last << part[0..-2] if csv.last =~ @parsers[:stray_quote] raise MalformedCSVError, "Missing or stray quote in line #{lineno + 1}" end csv.last.gsub!(@quote_char * 2, @quote_char) in_extended_col = false else csv.last << part csv.last << @col_sep end elsif part[0] == @quote_char # If we are staring a new quoted column if part[-1] != @quote_char || part.count(@quote_char) % 2 != 0 # start an extended column csv << part[1..-1] csv.last << @col_sep in_extended_col = true else # regular quoted column csv << part[1..-2] if csv.last =~ @parsers[:stray_quote] raise MalformedCSVError, "Missing or stray quote in line #{lineno + 1}" end csv.last.gsub!(@quote_char * 2, @quote_char) end elsif part =~ @parsers[:quote_or_nl] # Unquoted field with bad characters. if part =~ @parsers[:nl_or_lf] raise MalformedCSVError, "Unquoted fields do not allow " + "\\r or \\n (line #{lineno + 1})." else raise MalformedCSVError, "Illegal quoting in line #{lineno + 1}." end else # Regular ole unquoted field. csv << (part.empty? ? nil : part) end end # Replace tacked on @col_sep with @row_sep if we are still in an extended # column. csv[-1][-1] = @row_sep if in_extended_col if in_extended_col # if we're at eof?(), a quoted field wasn't closed... if @io.eof? raise MalformedCSVError, "Unclosed quoted field on line #{lineno + 1}." elsif @field_size_limit and csv.last.size >= @field_size_limit raise MalformedCSVError, "Field size exceeded on line #{lineno + 1}." end # otherwise, we need to loop and pull some more data to complete the row else @lineno += 1 # save fields unconverted fields, if needed... unconverted = csv.dup if @unconverted_fields # convert fields, if needed... csv = convert_fields(csv) unless @use_headers or @converters.empty? # parse out header rows and handle CSV::Row conversions... csv = parse_headers(csv) if @use_headers # inject unconverted fields and accessor, if requested... if @unconverted_fields and not csv.respond_to? :unconverted_fields add_unconverted_fields(csv, unconverted) end # return the results break csv end end end alias_method :gets, :shift alias_method :readline, :shift # # Returns a simplified description of the key CSV attributes in an # ASCII compatible String. # def inspect str = ["<#", self.class.to_s, " io_type:"] # show type of wrapped IO if @io == $stdout then str << "$stdout" elsif @io == $stdin then str << "$stdin" elsif @io == $stderr then str << "$stderr" else str << @io.class.to_s end # show IO.path(), if available if @io.respond_to?(:path) and (p = @io.path) str << " io_path:" << p.inspect end # show encoding str << " encoding:" << @encoding.name # show other attributes %w[ lineno col_sep row_sep quote_char skip_blanks ].each do |attr_name| if a = instance_variable_get("@#{attr_name}") str << " " << attr_name << ":" << a.inspect end end if @use_headers str << " headers:" << headers.inspect end str << ">" begin str.join('') rescue # any encoding error str.map do |s| e = Encoding::Converter.asciicompat_encoding(s.encoding) e ? s.encode(e) : s.force_encoding("ASCII-8BIT") end.join('') end end private # # Stores the indicated separators for later use. # # If auto-discovery was requested for @row_sep, this method will read # ahead in the @io and try to find one. +ARGF+, +STDIN+, +STDOUT+, # +STDERR+ and any stream open for output only with a default # @row_sep of $INPUT_RECORD_SEPARATOR ($/). # # This method also establishes the quoting rules used for CSV output. # def init_separators(options) # store the selected separators @col_sep = options.delete(:col_sep).to_s.encode(@encoding) @row_sep = options.delete(:row_sep) # encode after resolving :auto @quote_char = options.delete(:quote_char).to_s.encode(@encoding) if @quote_char.length != 1 raise ArgumentError, ":quote_char has to be a single character String" end # # automatically discover row separator when requested # (not fully encoding safe) # if @row_sep == :auto if [ARGF, STDIN, STDOUT, STDERR].include?(@io) or (defined?(Zlib) and @io.class == Zlib::GzipWriter) @row_sep = $INPUT_RECORD_SEPARATOR else begin # # remember where we were (pos() will raise an exception if @io is pipe # or not opened for reading) # saved_pos = @io.pos while @row_sep == :auto # # if we run out of data, it's probably a single line # (ensure will set default value) # break unless sample = @io.gets(nil, 1024) # extend sample if we're unsure of the line ending if sample.end_with? encode_str("\r") sample << (@io.gets(nil, 1) || "") end # try to find a standard separator if sample =~ encode_re("\r\n?|\n") @row_sep = $& break end end # tricky seek() clone to work around GzipReader's lack of seek() @io.rewind # reset back to the remembered position while saved_pos > 1024 # avoid loading a lot of data into memory @io.read(1024) saved_pos -= 1024 end @io.read(saved_pos) if saved_pos.nonzero? rescue IOError # not opened for reading # do nothing: ensure will set default rescue NoMethodError # Zlib::GzipWriter doesn't have some IO methods # do nothing: ensure will set default rescue SystemCallError # pipe # do nothing: ensure will set default ensure # # set default if we failed to detect # (stream not opened for reading, a pipe, or a single line of data) # @row_sep = $INPUT_RECORD_SEPARATOR if @row_sep == :auto end end end @row_sep = @row_sep.to_s.encode(@encoding) # establish quoting rules @force_quotes = options.delete(:force_quotes) do_quote = lambda do |field| field = String(field) encoded_quote = @quote_char.encode(field.encoding) encoded_quote + field.gsub(encoded_quote, encoded_quote * 2) + encoded_quote end quotable_chars = encode_str("\r\n", @col_sep, @quote_char) @quote = if @force_quotes do_quote else lambda do |field| if field.nil? # represent +nil+ fields as empty unquoted fields "" else field = String(field) # Stringify fields # represent empty fields as empty quoted fields if field.empty? or field.count(quotable_chars).nonzero? do_quote.call(field) else field # unquoted field end end end end end # Pre-compiles parsers and stores them by name for access during reads. def init_parsers(options) # store the parser behaviors @skip_blanks = options.delete(:skip_blanks) @field_size_limit = options.delete(:field_size_limit) # prebuild Regexps for faster parsing esc_row_sep = escape_re(@row_sep) esc_quote = escape_re(@quote_char) @parsers = { # for detecting parse errors quote_or_nl: encode_re("[", esc_quote, "\r\n]"), nl_or_lf: encode_re("[\r\n]"), stray_quote: encode_re( "[^", esc_quote, "]", esc_quote, "[^", esc_quote, "]" ), # safer than chomp!() line_end: encode_re(esc_row_sep, "\\z"), # illegal unquoted characters return_newline: encode_str("\r\n") } end # # Loads any converters requested during construction. # # If +field_name+ is set :converters (the default) field converters # are set. When +field_name+ is :header_converters header converters # are added instead. # # The :unconverted_fields option is also actived for # :converters calls, if requested. # def init_converters(options, field_name = :converters) if field_name == :converters @unconverted_fields = options.delete(:unconverted_fields) end instance_variable_set("@#{field_name}", Array.new) # find the correct method to add the converters convert = method(field_name.to_s.sub(/ers\Z/, "")) # load converters unless options[field_name].nil? # allow a single converter not wrapped in an Array unless options[field_name].is_a? Array options[field_name] = [options[field_name]] end # load each converter... options[field_name].each do |converter| if converter.is_a? Proc # custom code block convert.call(&converter) else # by name convert.call(converter) end end end options.delete(field_name) end # Stores header row settings and loads header converters, if needed. def init_headers(options) @use_headers = options.delete(:headers) @return_headers = options.delete(:return_headers) @write_headers = options.delete(:write_headers) # headers must be delayed until shift(), in case they need a row of content @headers = nil init_converters(options, :header_converters) end # Stores the pattern of comments to skip from the provided options. # # The pattern must respond to +.match+, else ArgumentError is raised. # Strings are converted to a Regexp. # # See also CSV.new def init_comments(options) @skip_lines = options.delete(:skip_lines) @skip_lines = Regexp.new(@skip_lines) if @skip_lines.is_a? String if @skip_lines and not @skip_lines.respond_to?(:match) raise ArgumentError, ":skip_lines has to respond to matches" end end # # The actual work method for adding converters, used by both CSV.convert() and # CSV.header_convert(). # # This method requires the +var_name+ of the instance variable to place the # converters in, the +const+ Hash to lookup named converters in, and the # normal parameters of the CSV.convert() and CSV.header_convert() methods. # def add_converter(var_name, const, name = nil, &converter) if name.nil? # custom converter instance_variable_get("@#{var_name}") << converter else # named converter combo = const[name] case combo when Array # combo converter combo.each do |converter_name| add_converter(var_name, const, converter_name) end else # individual named converter instance_variable_get("@#{var_name}") << combo end end end # # Processes +fields+ with @converters, or @header_converters # if +headers+ is passed as +true+, returning the converted field set. Any # converter that changes the field into something other than a String halts # the pipeline of conversion for that field. This is primarily an efficiency # shortcut. # def convert_fields(fields, headers = false) # see if we are converting headers or fields converters = headers ? @header_converters : @converters fields.map.with_index do |field, index| converters.each do |converter| break if field.nil? field = if converter.arity == 1 # straight field converter converter[field] else # FieldInfo converter header = @use_headers && !headers ? @headers[index] : nil converter[field, FieldInfo.new(index, lineno, header)] end break unless field.is_a? String # short-circuit pipeline for speed end field # final state of each field, converted or original end end # # This method is used to turn a finished +row+ into a CSV::Row. Header rows # are also dealt with here, either by returning a CSV::Row with identical # headers and fields (save that the fields do not go through the converters) # or by reading past them to return a field row. Headers are also saved in # @headers for use in future rows. # # When +nil+, +row+ is assumed to be a header row not based on an actual row # of the stream. # def parse_headers(row = nil) if @headers.nil? # header row @headers = case @use_headers # save headers # Array of headers when Array then @use_headers # CSV header String when String self.class.parse_line( @use_headers, col_sep: @col_sep, row_sep: @row_sep, quote_char: @quote_char ) # first row is headers else row end # prepare converted and unconverted copies row = @headers if row.nil? @headers = convert_fields(@headers, true) @headers.each { |h| h.freeze if h.is_a? String } if @return_headers # return headers return self.class::Row.new(@headers, row, true) elsif not [Array, String].include? @use_headers.class # skip to field row return shift end end self.class::Row.new(@headers, convert_fields(row)) # field row end # # This method injects an instance variable unconverted_fields into # +row+ and an accessor method for +row+ called unconverted_fields(). The # variable is set to the contents of +fields+. # def add_unconverted_fields(row, fields) class << row attr_reader :unconverted_fields end row.instance_eval { @unconverted_fields = fields } row end # # This method is an encoding safe version of Regexp::escape(). It will escape # any characters that would change the meaning of a regular expression in the # encoding of +str+. Regular expression characters that cannot be transcoded # to the target encoding will be skipped and no escaping will be performed if # a backslash cannot be transcoded. # def escape_re(str) str.gsub(@re_chars) {|c| @re_esc + c} end # # Builds a regular expression in @encoding. All +chunks+ will be # transcoded to that encoding. # def encode_re(*chunks) Regexp.new(encode_str(*chunks)) end # # Builds a String in @encoding. All +chunks+ will be transcoded to # that encoding. # def encode_str(*chunks) chunks.map { |chunk| chunk.encode(@encoding.name) }.join('') end private # # Returns the encoding of the internal IO object or the +default+ if the # encoding cannot be determined. # def raw_encoding(default = Encoding::ASCII_8BIT) if @io.respond_to? :internal_encoding @io.internal_encoding || @io.external_encoding elsif @io.is_a? StringIO @io.string.encoding elsif @io.respond_to? :encoding @io.encoding else default end end end # Passes +args+ to CSV::instance. # # CSV("CSV,data").read # #=> [["CSV", "data"]] # # If a block is given, the instance is passed the block and the return value # becomes the return value of the block. # # CSV("CSV,data") { |c| # c.read.any? { |a| a.include?("data") } # } #=> true # # CSV("CSV,data") { |c| # c.read.any? { |a| a.include?("zombies") } # } #=> false # def CSV(*args, &block) CSV.instance(*args, &block) end class Array # :nodoc: # Equivalent to CSV::generate_line(self, options) # # ["CSV", "data"].to_csv # #=> "CSV,data\n" def to_csv(options = Hash.new) CSV.generate_line(self, options) end end class String # :nodoc: # Equivalent to CSV::parse_line(self, options) # # "CSV,data".parse_csv # #=> ["CSV", "data"] def parse_csv(options = Hash.new) CSV.parse_line(self, options) end end PK!O8a 2.2.0/rake.rbnu[#-- # Copyright 2003-2010 by Jim Weirich (jim.weirich@gmail.com) # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. #++ module Rake VERSION = '10.4.2' end require 'rake/version' # :stopdoc: # TODO: Remove in Rake 11 RAKEVERSION = Rake::VERSION # :startdoc: require 'rbconfig' require 'fileutils' require 'singleton' require 'monitor' require 'optparse' require 'ostruct' require 'rake/ext/module' require 'rake/ext/string' require 'rake/ext/time' require 'rake/win32' require 'rake/linked_list' require 'rake/cpu_counter' require 'rake/scope' require 'rake/task_argument_error' require 'rake/rule_recursion_overflow_error' require 'rake/rake_module' require 'rake/trace_output' require 'rake/pseudo_status' require 'rake/task_arguments' require 'rake/invocation_chain' require 'rake/task' require 'rake/file_task' require 'rake/file_creation_task' require 'rake/multi_task' require 'rake/dsl_definition' require 'rake/file_utils_ext' require 'rake/file_list' require 'rake/default_loader' require 'rake/early_time' require 'rake/late_time' require 'rake/name_space' require 'rake/task_manager' require 'rake/application' require 'rake/backtrace' $trace = false # :stopdoc: # # Some top level Constants. FileList = Rake::FileList RakeFileUtils = Rake::FileUtilsExt PK!wJ9E'' 2.2.0/cgi.rbnu[# # cgi.rb - cgi support library # # Copyright (C) 2000 Network Applied Communication Laboratory, Inc. # # Copyright (C) 2000 Information-technology Promotion Agency, Japan # # Author: Wakou Aoyama # # Documentation: Wakou Aoyama (RDoc'd and embellished by William Webber) # # == Overview # # The Common Gateway Interface (CGI) is a simple protocol for passing an HTTP # request from a web server to a standalone program, and returning the output # to the web browser. Basically, a CGI program is called with the parameters # of the request passed in either in the environment (GET) or via $stdin # (POST), and everything it prints to $stdout is returned to the client. # # This file holds the CGI class. This class provides functionality for # retrieving HTTP request parameters, managing cookies, and generating HTML # output. # # The file CGI::Session provides session management functionality; see that # class for more details. # # See http://www.w3.org/CGI/ for more information on the CGI protocol. # # == Introduction # # CGI is a large class, providing several categories of methods, many of which # are mixed in from other modules. Some of the documentation is in this class, # some in the modules CGI::QueryExtension and CGI::HtmlExtension. See # CGI::Cookie for specific information on handling cookies, and cgi/session.rb # (CGI::Session) for information on sessions. # # For queries, CGI provides methods to get at environmental variables, # parameters, cookies, and multipart request data. For responses, CGI provides # methods for writing output and generating HTML. # # Read on for more details. Examples are provided at the bottom. # # == Queries # # The CGI class dynamically mixes in parameter and cookie-parsing # functionality, environmental variable access, and support for # parsing multipart requests (including uploaded files) from the # CGI::QueryExtension module. # # === Environmental Variables # # The standard CGI environmental variables are available as read-only # attributes of a CGI object. The following is a list of these variables: # # # AUTH_TYPE HTTP_HOST REMOTE_IDENT # CONTENT_LENGTH HTTP_NEGOTIATE REMOTE_USER # CONTENT_TYPE HTTP_PRAGMA REQUEST_METHOD # GATEWAY_INTERFACE HTTP_REFERER SCRIPT_NAME # HTTP_ACCEPT HTTP_USER_AGENT SERVER_NAME # HTTP_ACCEPT_CHARSET PATH_INFO SERVER_PORT # HTTP_ACCEPT_ENCODING PATH_TRANSLATED SERVER_PROTOCOL # HTTP_ACCEPT_LANGUAGE QUERY_STRING SERVER_SOFTWARE # HTTP_CACHE_CONTROL REMOTE_ADDR # HTTP_FROM REMOTE_HOST # # # For each of these variables, there is a corresponding attribute with the # same name, except all lower case and without a preceding HTTP_. # +content_length+ and +server_port+ are integers; the rest are strings. # # === Parameters # # The method #params() returns a hash of all parameters in the request as # name/value-list pairs, where the value-list is an Array of one or more # values. The CGI object itself also behaves as a hash of parameter names # to values, but only returns a single value (as a String) for each # parameter name. # # For instance, suppose the request contains the parameter # "favourite_colours" with the multiple values "blue" and "green". The # following behaviour would occur: # # cgi.params["favourite_colours"] # => ["blue", "green"] # cgi["favourite_colours"] # => "blue" # # If a parameter does not exist, the former method will return an empty # array, the latter an empty string. The simplest way to test for existence # of a parameter is by the #has_key? method. # # === Cookies # # HTTP Cookies are automatically parsed from the request. They are available # from the #cookies() accessor, which returns a hash from cookie name to # CGI::Cookie object. # # === Multipart requests # # If a request's method is POST and its content type is multipart/form-data, # then it may contain uploaded files. These are stored by the QueryExtension # module in the parameters of the request. The parameter name is the name # attribute of the file input field, as usual. However, the value is not # a string, but an IO object, either an IOString for small files, or a # Tempfile for larger ones. This object also has the additional singleton # methods: # # #local_path():: the path of the uploaded file on the local filesystem # #original_filename():: the name of the file on the client computer # #content_type():: the content type of the file # # == Responses # # The CGI class provides methods for sending header and content output to # the HTTP client, and mixes in methods for programmatic HTML generation # from CGI::HtmlExtension and CGI::TagMaker modules. The precise version of HTML # to use for HTML generation is specified at object creation time. # # === Writing output # # The simplest way to send output to the HTTP client is using the #out() method. # This takes the HTTP headers as a hash parameter, and the body content # via a block. The headers can be generated as a string using the #http_header() # method. The output stream can be written directly to using the #print() # method. # # === Generating HTML # # Each HTML element has a corresponding method for generating that # element as a String. The name of this method is the same as that # of the element, all lowercase. The attributes of the element are # passed in as a hash, and the body as a no-argument block that evaluates # to a String. The HTML generation module knows which elements are # always empty, and silently drops any passed-in body. It also knows # which elements require matching closing tags and which don't. However, # it does not know what attributes are legal for which elements. # # There are also some additional HTML generation methods mixed in from # the CGI::HtmlExtension module. These include individual methods for the # different types of form inputs, and methods for elements that commonly # take particular attributes where the attributes can be directly specified # as arguments, rather than via a hash. # # === Utility HTML escape and other methods like a function. # # There are some utility tool defined in cgi/util.rb . # And when include, you can use utility methods like a function. # # == Examples of use # # === Get form values # # require "cgi" # cgi = CGI.new # value = cgi['field_name'] # <== value string for 'field_name' # # if not 'field_name' included, then return "". # fields = cgi.keys # <== array of field names # # # returns true if form has 'field_name' # cgi.has_key?('field_name') # cgi.has_key?('field_name') # cgi.include?('field_name') # # CAUTION! cgi['field_name'] returned an Array with the old # cgi.rb(included in Ruby 1.6) # # === Get form values as hash # # require "cgi" # cgi = CGI.new # params = cgi.params # # cgi.params is a hash. # # cgi.params['new_field_name'] = ["value"] # add new param # cgi.params['field_name'] = ["new_value"] # change value # cgi.params.delete('field_name') # delete param # cgi.params.clear # delete all params # # # === Save form values to file # # require "pstore" # db = PStore.new("query.db") # db.transaction do # db["params"] = cgi.params # end # # # === Restore form values from file # # require "pstore" # db = PStore.new("query.db") # db.transaction do # cgi.params = db["params"] # end # # # === Get multipart form values # # require "cgi" # cgi = CGI.new # value = cgi['field_name'] # <== value string for 'field_name' # value.read # <== body of value # value.local_path # <== path to local file of value # value.original_filename # <== original filename of value # value.content_type # <== content_type of value # # and value has StringIO or Tempfile class methods. # # === Get cookie values # # require "cgi" # cgi = CGI.new # values = cgi.cookies['name'] # <== array of 'name' # # if not 'name' included, then return []. # names = cgi.cookies.keys # <== array of cookie names # # and cgi.cookies is a hash. # # === Get cookie objects # # require "cgi" # cgi = CGI.new # for name, cookie in cgi.cookies # cookie.expires = Time.now + 30 # end # cgi.out("cookie" => cgi.cookies) {"string"} # # cgi.cookies # { "name1" => cookie1, "name2" => cookie2, ... } # # require "cgi" # cgi = CGI.new # cgi.cookies['name'].expires = Time.now + 30 # cgi.out("cookie" => cgi.cookies['name']) {"string"} # # === Print http header and html string to $DEFAULT_OUTPUT ($>) # # require "cgi" # cgi = CGI.new("html4") # add HTML generation methods # cgi.out do # cgi.html do # cgi.head do # cgi.title { "TITLE" } # end + # cgi.body do # cgi.form("ACTION" => "uri") do # cgi.p do # cgi.textarea("get_text") + # cgi.br + # cgi.submit # end # end + # cgi.pre do # CGI::escapeHTML( # "params: #{cgi.params.inspect}\n" + # "cookies: #{cgi.cookies.inspect}\n" + # ENV.collect do |key, value| # "#{key} --> #{value}\n" # end.join("") # ) # end # end # end # end # # # add HTML generation methods # CGI.new("html3") # html3.2 # CGI.new("html4") # html4.01 (Strict) # CGI.new("html4Tr") # html4.01 Transitional # CGI.new("html4Fr") # html4.01 Frameset # CGI.new("html5") # html5 # # === Some utility methods # # require 'cgi/util' # CGI.escapeHTML('Usage: foo "bar" ') # # # === Some utility methods like a function # # require 'cgi/util' # include CGI::Util # escapeHTML('Usage: foo "bar" ') # h('Usage: foo "bar" ') # alias # # class CGI end require 'cgi/core' require 'cgi/cookie' require 'cgi/util' CGI.autoload(:HtmlExtension, 'cgi/html') PK!% 2.2.0/ripper/sexp.rbnu[# # $Id: sexp.rb 48144 2014-10-26 03:24:18Z nobu $ # # Copyright (c) 2004,2005 Minero Aoki # # This program is free software. # You can distribute and/or modify this program under the Ruby License. # For details of Ruby License, see ruby/COPYING. # require 'ripper/core' class Ripper # [EXPERIMENTAL] # Parses +src+ and create S-exp tree. # Returns more readable tree rather than Ripper.sexp_raw. # This method is mainly for developer use. # # require 'ripper' # require 'pp' # # pp Ripper.sexp("def m(a) nil end") # #=> [:program, # [[:def, # [:@ident, "m", [1, 4]], # [:paren, [:params, [[:@ident, "a", [1, 6]]], nil, nil, nil, nil]], # [:bodystmt, [[:var_ref, [:@kw, "nil", [1, 9]]]], nil, nil, nil]]]] # def Ripper.sexp(src, filename = '-', lineno = 1) builder = SexpBuilderPP.new(src, filename, lineno) sexp = builder.parse sexp unless builder.error? end # [EXPERIMENTAL] # Parses +src+ and create S-exp tree. # This method is mainly for developer use. # # require 'ripper' # require 'pp' # # pp Ripper.sexp_raw("def m(a) nil end") # #=> [:program, # [:stmts_add, # [:stmts_new], # [:def, # [:@ident, "m", [1, 4]], # [:paren, [:params, [[:@ident, "a", [1, 6]]], nil, nil, nil]], # [:bodystmt, # [:stmts_add, [:stmts_new], [:var_ref, [:@kw, "nil", [1, 9]]]], # nil, # nil, # nil]]]] # def Ripper.sexp_raw(src, filename = '-', lineno = 1) builder = SexpBuilder.new(src, filename, lineno) sexp = builder.parse sexp unless builder.error? end class SexpBuilderPP < ::Ripper #:nodoc: private PARSER_EVENT_TABLE.each do |event, arity| if /_new\z/ =~ event.to_s and arity == 0 module_eval(<<-End, __FILE__, __LINE__ + 1) def on_#{event} [] end End elsif /_add\z/ =~ event.to_s module_eval(<<-End, __FILE__, __LINE__ + 1) def on_#{event}(list, item) list.push item list end End else module_eval(<<-End, __FILE__, __LINE__ + 1) def on_#{event}(*args) [:#{event}, *args] end End end end SCANNER_EVENTS.each do |event| module_eval(<<-End, __FILE__, __LINE__ + 1) def on_#{event}(tok) [:@#{event}, tok, [lineno(), column()]] end End end end class SexpBuilder < ::Ripper #:nodoc: private PARSER_EVENTS.each do |event| module_eval(<<-End, __FILE__, __LINE__ + 1) def on_#{event}(*args) args.unshift :#{event} args end End end SCANNER_EVENTS.each do |event| module_eval(<<-End, __FILE__, __LINE__ + 1) def on_#{event}(tok) [:@#{event}, tok, [lineno(), column()]] end End end end end PK!2.2.0/ripper/lexer.rbnu[# # $Id: lexer.rb 44878 2014-02-07 12:57:44Z zzak $ # # Copyright (c) 2004,2005 Minero Aoki # # This program is free software. # You can distribute and/or modify this program under the Ruby License. # For details of Ruby License, see ruby/COPYING. # require 'ripper/core' class Ripper # Tokenizes the Ruby program and returns an array of strings. # # p Ripper.tokenize("def m(a) nil end") # # => ["def", " ", "m", "(", "a", ")", " ", "nil", " ", "end"] # def Ripper.tokenize(src, filename = '-', lineno = 1) Lexer.new(src, filename, lineno).tokenize end # Tokenizes the Ruby program and returns an array of an array, # which is formatted like [[lineno, column], type, token]. # # require 'ripper' # require 'pp' # # pp Ripper.lex("def m(a) nil end") # #=> [[[1, 0], :on_kw, "def"], # [[1, 3], :on_sp, " " ], # [[1, 4], :on_ident, "m" ], # [[1, 5], :on_lparen, "(" ], # [[1, 6], :on_ident, "a" ], # [[1, 7], :on_rparen, ")" ], # [[1, 8], :on_sp, " " ], # [[1, 9], :on_kw, "nil"], # [[1, 12], :on_sp, " " ], # [[1, 13], :on_kw, "end"]] # def Ripper.lex(src, filename = '-', lineno = 1) Lexer.new(src, filename, lineno).lex end class Lexer < ::Ripper #:nodoc: internal use only def tokenize lex().map {|pos, event, tok| tok } end def lex parse().sort_by {|pos, event, tok| pos } end def parse @buf = [] super @buf end private SCANNER_EVENTS.each do |event| module_eval(<<-End, __FILE__+'/module_eval', __LINE__ + 1) def on_#{event}(tok) @buf.push [[lineno(), column()], :on_#{event}, tok] end End end end # [EXPERIMENTAL] # Parses +src+ and return a string which was matched to +pattern+. # +pattern+ should be described as Regexp. # # require 'ripper' # # p Ripper.slice('def m(a) nil end', 'ident') #=> "m" # p Ripper.slice('def m(a) nil end', '[ident lparen rparen]+') #=> "m(a)" # p Ripper.slice("< "string\n" # def Ripper.slice(src, pattern, n = 0) if m = token_match(src, pattern) then m.string(n) else nil end end def Ripper.token_match(src, pattern) #:nodoc: TokenPattern.compile(pattern).match(src) end class TokenPattern #:nodoc: class Error < ::StandardError # :nodoc: end class CompileError < Error # :nodoc: end class MatchError < Error # :nodoc: end class << self alias compile new end def initialize(pattern) @source = pattern @re = compile(pattern) end def match(str) match_list(::Ripper.lex(str)) end def match_list(tokens) if m = @re.match(map_tokens(tokens)) then MatchData.new(tokens, m) else nil end end private def compile(pattern) if m = /[^\w\s$()\[\]{}?*+\.]/.match(pattern) raise CompileError, "invalid char in pattern: #{m[0].inspect}" end buf = '' pattern.scan(/(?:\w+|\$\(|[()\[\]\{\}?*+\.]+)/) do |tok| case tok when /\w/ buf.concat map_token(tok) when '$(' buf.concat '(' when '(' buf.concat '(?:' when /[?*\[\])\.]/ buf.concat tok else raise 'must not happen' end end Regexp.compile(buf) rescue RegexpError => err raise CompileError, err.message end def map_tokens(tokens) tokens.map {|pos,type,str| map_token(type.to_s.sub(/\Aon_/,'')) }.join end MAP = {} seed = ('a'..'z').to_a + ('A'..'Z').to_a + ('0'..'9').to_a SCANNER_EVENT_TABLE.each do |ev, | raise CompileError, "[RIPPER FATAL] too many system token" if seed.empty? MAP[ev.to_s.sub(/\Aon_/,'')] = seed.shift end def map_token(tok) MAP[tok] or raise CompileError, "unknown token: #{tok}" end class MatchData # :nodoc: def initialize(tokens, match) @tokens = tokens @match = match end def string(n = 0) return nil unless @match match(n).join end private def match(n = 0) return [] unless @match @tokens[@match.begin(n)...@match.end(n)].map {|pos,type,str| str } end end end end PK!2.2.0/ripper/filter.rbnu[# # $Id: filter.rb 36954 2012-09-12 23:04:41Z zzak $ # # Copyright (c) 2004,2005 Minero Aoki # # This program is free software. # You can distribute and/or modify this program under the Ruby License. # For details of Ruby License, see ruby/COPYING. # require 'ripper/lexer' class Ripper # This class handles only scanner events, # which are dispatched in the 'right' order (same with input). class Filter # Creates a new Ripper::Filter instance, passes parameters +src+, # +filename+, and +lineno+ to Ripper::Lexer.new # # The lexer is for internal use only. def initialize(src, filename = '-', lineno = 1) @__lexer = Lexer.new(src, filename, lineno) @__line = nil @__col = nil end # The file name of the input. def filename @__lexer.filename end # The line number of the current token. # This value starts from 1. # This method is valid only in event handlers. def lineno @__line end # The column number of the current token. # This value starts from 0. # This method is valid only in event handlers. def column @__col end # Starts the parser. # +init+ is a data accumulator and is passed to the next event handler (as # of Enumerable#inject). def parse(init = nil) data = init @__lexer.lex.each do |pos, event, tok| @__line, @__col = *pos data = if respond_to?(event, true) then __send__(event, tok, data) else on_default(event, tok, data) end end data end private # This method is called when some event handler is undefined. # +event+ is :on_XXX, +token+ is the scanned token, and +data+ is a data # accumulator. # # The return value of this method is passed to the next event handler (as # of Enumerable#inject). def on_default(event, token, data) data end end end PK!6332.2.0/ripper/core.rbnu[# # $Id: core.rb 36954 2012-09-12 23:04:41Z zzak $ # # Copyright (c) 2003-2005 Minero Aoki # # This program is free software. # You can distribute and/or modify this program under the Ruby License. # For details of Ruby License, see ruby/COPYING. # require 'ripper.so' class Ripper # Parses the given Ruby program read from +src+. # +src+ must be a String or an IO or a object with a #gets method. def Ripper.parse(src, filename = '(ripper)', lineno = 1) new(src, filename, lineno).parse end # This array contains name of parser events. PARSER_EVENTS = PARSER_EVENT_TABLE.keys # This array contains name of scanner events. SCANNER_EVENTS = SCANNER_EVENT_TABLE.keys # This array contains name of all ripper events. EVENTS = PARSER_EVENTS + SCANNER_EVENTS private # # Parser Events # PARSER_EVENT_TABLE.each do |id, arity| module_eval(<<-End, __FILE__, __LINE__ + 1) def on_#{id}(#{ ('a'..'z').to_a[0, arity].join(', ') }) #{arity == 0 ? 'nil' : 'a'} end End end # This method is called when weak warning is produced by the parser. # +fmt+ and +args+ is printf style. def warn(fmt, *args) end # This method is called when strong warning is produced by the parser. # +fmt+ and +args+ is printf style. def warning(fmt, *args) end # This method is called when the parser found syntax error. def compile_error(msg) end # # Scanner Events # SCANNER_EVENTS.each do |id| module_eval(<<-End, __FILE__, __LINE__ + 1) def on_#{id}(token) token end End end end PK!sPP 2.2.0/irb.rbnu[# # irb.rb - irb main module # $Release Version: 0.9.6 $ # $Revision: 54322 $ # by Keiju ISHITSUKA(keiju@ruby-lang.org) # # -- # # # require "e2mmap" require "irb/init" require "irb/context" require "irb/extend-command" require "irb/ruby-lex" require "irb/input-method" require "irb/locale" STDOUT.sync = true # IRB stands for "interactive Ruby" and is a tool to interactively execute Ruby # expressions read from the standard input. # # The +irb+ command from your shell will start the interpreter. # # == Usage # # Use of irb is easy if you know Ruby. # # When executing irb, prompts are displayed as follows. Then, enter the Ruby # expression. An input is executed when it is syntactically complete. # # $ irb # irb(main):001:0> 1+2 # #=> 3 # irb(main):002:0> class Foo # irb(main):003:1> def foo # irb(main):004:2> print 1 # irb(main):005:2> end # irb(main):006:1> end # #=> nil # # The Readline extension module can be used with irb. Use of Readline is # default if it's installed. # # == Command line options # # Usage: irb.rb [options] [programfile] [arguments] # -f Suppress read of ~/.irbrc # -m Bc mode (load mathn, fraction or matrix are available) # -d Set $DEBUG to true (same as `ruby -d') # -r load-module Same as `ruby -r' # -I path Specify $LOAD_PATH directory # -U Same as `ruby -U` # -E enc Same as `ruby -E` # -w Same as `ruby -w` # -W[level=2] Same as `ruby -W` # --inspect Use `inspect' for output (default except for bc mode) # --noinspect Don't use inspect for output # --readline Use Readline extension module # --noreadline Don't use Readline extension module # --prompt prompt-mode # --prompt-mode prompt-mode # Switch prompt mode. Pre-defined prompt modes are # `default', `simple', `xmp' and `inf-ruby' # --inf-ruby-mode Use prompt appropriate for inf-ruby-mode on emacs. # Suppresses --readline. # --simple-prompt Simple prompt mode # --noprompt No prompt mode # --tracer Display trace for each execution of commands. # --back-trace-limit n # Display backtrace top n and tail n. The default # value is 16. # --irb_debug n Set internal debug level to n (not for popular use) # -v, --version Print the version of irb # # == Configuration # # IRB reads from ~/.irbrc when it's invoked. # # If ~/.irbrc doesn't exist, +irb+ will try to read in the following order: # # * +.irbrc+ # * +irb.rc+ # * +_irbrc+ # * $irbrc # # The following are alternatives to the command line options. To use them type # as follows in an +irb+ session: # # IRB.conf[:IRB_NAME]="irb" # IRB.conf[:MATH_MODE]=false # IRB.conf[:INSPECT_MODE]=nil # IRB.conf[:IRB_RC] = nil # IRB.conf[:BACK_TRACE_LIMIT]=16 # IRB.conf[:USE_LOADER] = false # IRB.conf[:USE_READLINE] = nil # IRB.conf[:USE_TRACER] = false # IRB.conf[:IGNORE_SIGINT] = true # IRB.conf[:IGNORE_EOF] = false # IRB.conf[:PROMPT_MODE] = :DEFAULT # IRB.conf[:PROMPT] = {...} # IRB.conf[:DEBUG_LEVEL]=0 # # === Auto indentation # # To enable auto-indent mode in irb, add the following to your +.irbrc+: # # IRB.conf[:AUTO_INDENT] = true # # === Autocompletion # # To enable autocompletion for irb, add the following to your +.irbrc+: # # require 'irb/completion' # # === History # # By default, irb disables history and will not store any commands you used. # # If you want to enable history, add the following to your +.irbrc+: # # IRB.conf[:SAVE_HISTORY] = 1000 # # This will now store the last 1000 commands in ~/.irb_history. # # See IRB::Context#save_history= for more information. # # == Customizing the IRB Prompt # # In order to customize the prompt, you can change the following Hash: # # IRB.conf[:PROMPT] # # This example can be used in your +.irbrc+ # # IRB.conf[:PROMPT][:MY_PROMPT] = { # name of prompt mode # :AUTO_INDENT => true, # enables auto-indent mode # :PROMPT_I => ">> ", # simple prompt # :PROMPT_S => nil, # prompt for continuated strings # :PROMPT_C => nil, # prompt for continuated statement # :RETURN => " ==>%s\n" # format to return value # } # # IRB.conf[:PROMPT_MODE] = :MY_PROMPT # # Or, invoke irb with the above prompt mode by: # # irb --prompt my-prompt # # Constants +PROMPT_I+, +PROMPT_S+ and +PROMPT_C+ specify the format. In the # prompt specification, some special strings are available: # # %N # command name which is running # %m # to_s of main object (self) # %M # inspect of main object (self) # %l # type of string(", ', /, ]), `]' is inner %w[...] # %NNi # indent level. NN is digits and means as same as printf("%NNd"). # # It can be ommited # %NNn # line number. # %% # % # # For instance, the default prompt mode is defined as follows: # # IRB.conf[:PROMPT_MODE][:DEFAULT] = { # :PROMPT_I => "%N(%m):%03n:%i> ", # :PROMPT_S => "%N(%m):%03n:%i%l ", # :PROMPT_C => "%N(%m):%03n:%i* ", # :RETURN => "%s\n" # used to printf # } # # irb comes with a number of available modes: # # # :NULL: # # :PROMPT_I: # # :PROMPT_N: # # :PROMPT_S: # # :PROMPT_C: # # :RETURN: | # # %s # # :DEFAULT: # # :PROMPT_I: ! '%N(%m):%03n:%i> ' # # :PROMPT_N: ! '%N(%m):%03n:%i> ' # # :PROMPT_S: ! '%N(%m):%03n:%i%l ' # # :PROMPT_C: ! '%N(%m):%03n:%i* ' # # :RETURN: | # # => %s # # :CLASSIC: # # :PROMPT_I: ! '%N(%m):%03n:%i> ' # # :PROMPT_N: ! '%N(%m):%03n:%i> ' # # :PROMPT_S: ! '%N(%m):%03n:%i%l ' # # :PROMPT_C: ! '%N(%m):%03n:%i* ' # # :RETURN: | # # %s # # :SIMPLE: # # :PROMPT_I: ! '>> ' # # :PROMPT_N: ! '>> ' # # :PROMPT_S: # # :PROMPT_C: ! '?> ' # # :RETURN: | # # => %s # # :INF_RUBY: # # :PROMPT_I: ! '%N(%m):%03n:%i> ' # # :PROMPT_N: # # :PROMPT_S: # # :PROMPT_C: # # :RETURN: | # # %s # # :AUTO_INDENT: true # # :XMP: # # :PROMPT_I: # # :PROMPT_N: # # :PROMPT_S: # # :PROMPT_C: # # :RETURN: |2 # # ==>%s # # == Restrictions # # Because irb evaluates input immediately after it is syntactically complete, # the results may be slightly different than directly using Ruby. # # == IRB Sessions # # IRB has a special feature, that allows you to manage many sessions at once. # # You can create new sessions with Irb.irb, and get a list of current sessions # with the +jobs+ command in the prompt. # # === Commands # # JobManager provides commands to handle the current sessions: # # jobs # List of current sessions # fg # Switches to the session of the given number # kill # Kills the session with the given number # # The +exit+ command, or ::irb_exit, will quit the current session and call any # exit hooks with IRB.irb_at_exit. # # A few commands for loading files within the session are also available: # # +source+:: # Loads a given file in the current session and displays the source lines, # see IrbLoader#source_file # +irb_load+:: # Loads the given file similarly to Kernel#load, see IrbLoader#irb_load # +irb_require+:: # Loads the given file similarly to Kernel#require # # === Configuration # # The command line options, or IRB.conf, specify the default behavior of # Irb.irb. # # On the other hand, each conf in IRB@Command+line+options is used to # individually configure IRB.irb. # # If a proc is set for IRB.conf[:IRB_RC], its will be invoked after execution # of that proc with the context of the current session as its argument. Each # session can be configured using this mechanism. # # === Session variables # # There are a few variables in every Irb session that can come in handy: # # _:: # The value command executed, as a local variable # __:: # The history of evaluated commands # __[line_no]:: # Returns the evaluation value at the given line number, +line_no+. # If +line_no+ is a negative, the return value +line_no+ many lines before # the most recent return value. # # === Example using IRB Sessions # # # invoke a new session # irb(main):001:0> irb # # list open sessions # irb.1(main):001:0> jobs # #0->irb on main (# : stop) # #1->irb#1 on main (# : running) # # # change the active session # irb.1(main):002:0> fg 0 # # define class Foo in top-level session # irb(main):002:0> class Foo;end # # invoke a new session with the context of Foo # irb(main):003:0> irb Foo # # define Foo#foo # irb.2(Foo):001:0> def foo # irb.2(Foo):002:1> print 1 # irb.2(Foo):003:1> end # # # change the active session # irb.2(Foo):004:0> fg 0 # # list open sessions # irb(main):004:0> jobs # #0->irb on main (# : running) # #1->irb#1 on main (# : stop) # #2->irb#2 on Foo (# : stop) # # check if Foo#foo is available # irb(main):005:0> Foo.instance_methods #=> [:foo, ...] # # # change the active sesssion # irb(main):006:0> fg 2 # # define Foo#bar in the context of Foo # irb.2(Foo):005:0> def bar # irb.2(Foo):006:1> print "bar" # irb.2(Foo):007:1> end # irb.2(Foo):010:0> Foo.instance_methods #=> [:bar, :foo, ...] # # # change the active session # irb.2(Foo):011:0> fg 0 # irb(main):007:0> f = Foo.new #=> # # # invoke a new session with the context of f (instance of Foo) # irb(main):008:0> irb f # # list open sessions # irb.3():001:0> jobs # #0->irb on main (# : stop) # #1->irb#1 on main (# : stop) # #2->irb#2 on Foo (# : stop) # #3->irb#3 on # (# : running) # # evaluate f.foo # irb.3():002:0> foo #=> 1 => nil # # evaluate f.bar # irb.3():003:0> bar #=> bar => nil # # kill jobs 1, 2, and 3 # irb.3():004:0> kill 1, 2, 3 # # list open sesssions, should only include main session # irb(main):009:0> jobs # #0->irb on main (# : running) # # quit irb # irb(main):010:0> exit module IRB # An exception raised by IRB.irb_abort class Abort < Exception;end @CONF = {} # Displays current configuration. # # Modifing the configuration is achieved by sending a message to IRB.conf. # # See IRB@Configuration for more information. def IRB.conf @CONF end # Returns the current version of IRB, including release version and last # updated date. def IRB.version if v = @CONF[:VERSION] then return v end require "irb/version" rv = @RELEASE_VERSION.sub(/\.0/, "") @CONF[:VERSION] = format("irb %s(%s)", rv, @LAST_UPDATE_DATE) end # The current IRB::Context of the session, see IRB.conf # # irb # irb(main):001:0> IRB.CurrentContext.irb_name = "foo" # foo(main):002:0> IRB.conf[:MAIN_CONTEXT].irb_name #=> "foo" def IRB.CurrentContext IRB.conf[:MAIN_CONTEXT] end # Initializes IRB and creates a new Irb.irb object at the +TOPLEVEL_BINDING+ def IRB.start(ap_path = nil) $0 = File::basename(ap_path, ".rb") if ap_path IRB.setup(ap_path) if @CONF[:SCRIPT] irb = Irb.new(nil, @CONF[:SCRIPT]) else irb = Irb.new end @CONF[:IRB_RC].call(irb.context) if @CONF[:IRB_RC] @CONF[:MAIN_CONTEXT] = irb.context trap("SIGINT") do irb.signal_handle end begin catch(:IRB_EXIT) do irb.eval_input end ensure irb_at_exit end end # Calls each event hook of IRB.conf[:AT_EXIT] when the current session quits. def IRB.irb_at_exit @CONF[:AT_EXIT].each{|hook| hook.call} end # Quits irb def IRB.irb_exit(irb, ret) throw :IRB_EXIT, ret end # Aborts then interrupts irb. # # Will raise an Abort exception, or the given +exception+. def IRB.irb_abort(irb, exception = Abort) if defined? Thread irb.context.thread.raise exception, "abort then interrupt!" else raise exception, "abort then interrupt!" end end class Irb # Creates a new irb session def initialize(workspace = nil, input_method = nil, output_method = nil) @context = Context.new(self, workspace, input_method, output_method) @context.main.extend ExtendCommandBundle @signal_status = :IN_IRB @scanner = RubyLex.new @scanner.exception_on_syntax_error = false end # Returns the current context of this irb session attr_reader :context # The lexer used by this irb session attr_accessor :scanner # Evaluates input for this session. def eval_input @scanner.set_prompt do |ltype, indent, continue, line_no| if ltype f = @context.prompt_s elsif continue f = @context.prompt_c elsif indent > 0 f = @context.prompt_n else f = @context.prompt_i end f = "" unless f if @context.prompting? @context.io.prompt = p = prompt(f, ltype, indent, line_no) else @context.io.prompt = p = "" end if @context.auto_indent_mode unless ltype ind = prompt(@context.prompt_i, ltype, indent, line_no)[/.*\z/].size + indent * 2 - p.size ind += 2 if continue @context.io.prompt = p + " " * ind if ind > 0 end end end @scanner.set_input(@context.io) do signal_status(:IN_INPUT) do if l = @context.io.gets print l if @context.verbose? else if @context.ignore_eof? and @context.io.readable_after_eof? l = "\n" if @context.verbose? printf "Use \"exit\" to leave %s\n", @context.ap_name end else print "\n" end end l end end @scanner.each_top_level_statement do |line, line_no| signal_status(:IN_EVAL) do begin line.untaint @context.evaluate(line, line_no) output_value if @context.echo? exc = nil rescue Interrupt => exc rescue SystemExit, SignalException raise rescue Exception => exc end if exc print exc.class, ": ", exc, "\n" if exc.backtrace && exc.backtrace[0] =~ /irb(2)?(\/.*|-.*|\.rb)?:/ && exc.class.to_s !~ /^IRB/ && !(SyntaxError === exc) irb_bug = true else irb_bug = false end messages = [] lasts = [] levels = 0 if exc.backtrace for m in exc.backtrace m = @context.workspace.filter_backtrace(m) unless irb_bug if m if messages.size < @context.back_trace_limit messages.push "\tfrom "+m else lasts.push "\tfrom "+m if lasts.size > @context.back_trace_limit lasts.shift levels += 1 end end end end end print messages.join("\n"), "\n" unless lasts.empty? printf "... %d levels...\n", levels if levels > 0 print lasts.join("\n"), "\n" end print "Maybe IRB bug!\n" if irb_bug end if $SAFE > 2 abort "Error: irb does not work for $SAFE level higher than 2" end end end end # Evaluates the given block using the given +path+ as the Context#irb_path # and +name+ as the Context#irb_name. # # Used by the irb command +source+, see IRB@IRB+Sessions for more # information. def suspend_name(path = nil, name = nil) @context.irb_path, back_path = path, @context.irb_path if path @context.irb_name, back_name = name, @context.irb_name if name begin yield back_path, back_name ensure @context.irb_path = back_path if path @context.irb_name = back_name if name end end # Evaluates the given block using the given +workspace+ as the # Context#workspace. # # Used by the irb command +irb_load+, see IRB@IRB+Sessions for more # information. def suspend_workspace(workspace) @context.workspace, back_workspace = workspace, @context.workspace begin yield back_workspace ensure @context.workspace = back_workspace end end # Evaluates the given block using the given +input_method+ as the # Context#io. # # Used by the irb commands +source+ and +irb_load+, see IRB@IRB+Sessions # for more information. def suspend_input_method(input_method) back_io = @context.io @context.instance_eval{@io = input_method} begin yield back_io ensure @context.instance_eval{@io = back_io} end end # Evaluates the given block using the given +context+ as the Context. def suspend_context(context) @context, back_context = context, @context begin yield back_context ensure @context = back_context end end # Handler for the signal SIGINT, see Kernel#trap for more information. def signal_handle unless @context.ignore_sigint? print "\nabort!\n" if @context.verbose? exit end case @signal_status when :IN_INPUT print "^C\n" raise RubyLex::TerminateLineInput when :IN_EVAL IRB.irb_abort(self) when :IN_LOAD IRB.irb_abort(self, LoadAbort) when :IN_IRB # ignore else # ignore other cases as well end end # Evaluates the given block using the given +status+. def signal_status(status) return yield if @signal_status == :IN_LOAD signal_status_back = @signal_status @signal_status = status begin yield ensure @signal_status = signal_status_back end end def prompt(prompt, ltype, indent, line_no) # :nodoc: p = prompt.dup p.gsub!(/%([0-9]+)?([a-zA-Z])/) do case $2 when "N" @context.irb_name when "m" @context.main.to_s when "M" @context.main.inspect when "l" ltype when "i" if $1 format("%" + $1 + "d", indent) else indent.to_s end when "n" if $1 format("%" + $1 + "d", line_no) else line_no.to_s end when "%" "%" end end p end def output_value # :nodoc: printf @context.return_format, @context.inspect_last_value end # Outputs the local variables to this current session, including # #signal_status and #context, using IRB::Locale. def inspect ary = [] for iv in instance_variables case (iv = iv.to_s) when "@signal_status" ary.push format("%s=:%s", iv, @signal_status.id2name) when "@context" ary.push format("%s=%s", iv, eval(iv).__to_s__) else ary.push format("%s=%s", iv, eval(iv)) end end format("#<%s: %s>", self.class, ary.join(", ")) end end def @CONF.inspect IRB.version unless self[:VERSION] array = [] for k, v in sort{|a1, a2| a1[0].id2name <=> a2[0].id2name} case k when :MAIN_CONTEXT, :__TMP__EHV__ array.push format("CONF[:%s]=...myself...", k.id2name) when :PROMPT s = v.collect{ |kk, vv| ss = vv.collect{|kkk, vvv| ":#{kkk.id2name}=>#{vvv.inspect}"} format(":%s=>{%s}", kk.id2name, ss.join(", ")) } array.push format("CONF[:%s]={%s}", k.id2name, s.join(", ")) else array.push format("CONF[:%s]=%s", k.id2name, v.inspect) end end array.join("\n") end end PK!/&2.2.0/resolv-replace.rbnu[require 'socket' require 'resolv' class << IPSocket # :stopdoc: alias original_resolv_getaddress getaddress # :startdoc: def getaddress(host) begin return Resolv.getaddress(host).to_s rescue Resolv::ResolvError raise SocketError, "Hostname not known: #{host}" end end end class TCPSocket < IPSocket # :stopdoc: alias original_resolv_initialize initialize # :startdoc: def initialize(host, serv, *rest) rest[0] = IPSocket.getaddress(rest[0]) if rest[0] original_resolv_initialize(IPSocket.getaddress(host), serv, *rest) end end class UDPSocket < IPSocket # :stopdoc: alias original_resolv_bind bind # :startdoc: def bind(host, port) host = IPSocket.getaddress(host) if host != "" original_resolv_bind(host, port) end # :stopdoc: alias original_resolv_connect connect # :startdoc: def connect(host, port) original_resolv_connect(IPSocket.getaddress(host), port) end # :stopdoc: alias original_resolv_send send # :startdoc: def send(mesg, flags, *rest) if rest.length == 2 host, port = rest begin addrs = Resolv.getaddresses(host) rescue Resolv::ResolvError raise SocketError, "Hostname not known: #{host}" end addrs[0...-1].each {|addr| begin return original_resolv_send(mesg, flags, addr, port) rescue SystemCallError end } original_resolv_send(mesg, flags, addrs[-1], port) else original_resolv_send(mesg, flags, *rest) end end end class SOCKSSocket < TCPSocket # :stopdoc: alias original_resolv_initialize initialize # :startdoc: def initialize(host, serv) original_resolv_initialize(IPSocket.getaddress(host), port) end end if defined? SOCKSSocket PK!2.2.0/mutex_m.rbnu[# # mutex_m.rb - # $Release Version: 3.0$ # $Revision: 1.7 $ # Original from mutex.rb # by Keiju ISHITSUKA(keiju@ishitsuka.com) # modified by matz # patched by akira yamada # # -- require 'thread' # = mutex_m.rb # # When 'mutex_m' is required, any object that extends or includes Mutex_m will # be treated like a Mutex. # # Start by requiring the standard library Mutex_m: # # require "mutex_m.rb" # # From here you can extend an object with Mutex instance methods: # # obj = Object.new # obj.extend Mutex_m # # Or mixin Mutex_m into your module to your class inherit Mutex instance # methods. # # class Foo # include Mutex_m # # ... # end # obj = Foo.new # # this obj can be handled like Mutex # module Mutex_m def Mutex_m.define_aliases(cl) # :nodoc: cl.module_eval %q{ alias locked? mu_locked? alias lock mu_lock alias unlock mu_unlock alias try_lock mu_try_lock alias synchronize mu_synchronize } end def Mutex_m.append_features(cl) # :nodoc: super define_aliases(cl) unless cl.instance_of?(Module) end def Mutex_m.extend_object(obj) # :nodoc: super obj.mu_extended end def mu_extended # :nodoc: unless (defined? locked? and defined? lock and defined? unlock and defined? try_lock and defined? synchronize) Mutex_m.define_aliases(singleton_class) end mu_initialize end # See Mutex#synchronize def mu_synchronize(&block) @_mutex.synchronize(&block) end # See Mutex#locked? def mu_locked? @_mutex.locked? end # See Mutex#try_lock def mu_try_lock @_mutex.try_lock end # See Mutex#lock def mu_lock @_mutex.lock end # See Mutex#unlock def mu_unlock @_mutex.unlock end # See Mutex#sleep def sleep(timeout = nil) @_mutex.sleep(timeout) end private def mu_initialize # :nodoc: @_mutex = Mutex.new end def initialize(*args) # :nodoc: mu_initialize super end end PK!2.2.0/rss/dublincore.rbnu[require "rss/rss" module RSS # The prefix for the Dublin Core XML namespace. DC_PREFIX = 'dc' # The URI of the Dublin Core specification. DC_URI = "http://purl.org/dc/elements/1.1/" module BaseDublinCoreModel def append_features(klass) super return if klass.instance_of?(Module) DublinCoreModel::ELEMENT_NAME_INFOS.each do |name, plural_name| plural = plural_name || "#{name}s" full_name = "#{DC_PREFIX}_#{name}" full_plural_name = "#{DC_PREFIX}_#{plural}" klass_name = "DublinCore#{Utils.to_class_name(name)}" klass.install_must_call_validator(DC_PREFIX, DC_URI) klass.install_have_children_element(name, DC_URI, "*", full_name, full_plural_name) klass.module_eval(<<-EOC, *get_file_and_line_from_caller(0)) remove_method :#{full_name} remove_method :#{full_name}= remove_method :set_#{full_name} def #{full_name} @#{full_name}.first and @#{full_name}.first.value end def #{full_name}=(new_value) @#{full_name}[0] = Utils.new_with_value_if_need(#{klass_name}, new_value) end alias set_#{full_name} #{full_name}= EOC end klass.module_eval(<<-EOC, *get_file_and_line_from_caller(0)) if method_defined?(:date) alias date_without_#{DC_PREFIX}_date= date= def date=(value) self.date_without_#{DC_PREFIX}_date = value self.#{DC_PREFIX}_date = value end else alias date #{DC_PREFIX}_date alias date= #{DC_PREFIX}_date= end # For backward compatibility alias #{DC_PREFIX}_rightses #{DC_PREFIX}_rights_list EOC end end module DublinCoreModel extend BaseModel extend BaseDublinCoreModel TEXT_ELEMENTS = { "title" => nil, "description" => nil, "creator" => nil, "subject" => nil, "publisher" => nil, "contributor" => nil, "type" => nil, "format" => nil, "identifier" => nil, "source" => nil, "language" => nil, "relation" => nil, "coverage" => nil, "rights" => "rights_list" } DATE_ELEMENTS = { "date" => "w3cdtf", } ELEMENT_NAME_INFOS = DublinCoreModel::TEXT_ELEMENTS.to_a DublinCoreModel::DATE_ELEMENTS.each do |name, | ELEMENT_NAME_INFOS << [name, nil] end ELEMENTS = TEXT_ELEMENTS.keys + DATE_ELEMENTS.keys ELEMENTS.each do |name, plural_name| module_eval(<<-EOC, *get_file_and_line_from_caller(0)) class DublinCore#{Utils.to_class_name(name)} < Element include RSS10 content_setup class << self def required_prefix DC_PREFIX end def required_uri DC_URI end end @tag_name = #{name.dump} alias_method(:value, :content) alias_method(:value=, :content=) def initialize(*args) if Utils.element_initialize_arguments?(args) super else super() self.content = args[0] end end def full_name tag_name_with_prefix(DC_PREFIX) end def maker_target(target) target.new_#{name} end def setup_maker_attributes(#{name}) #{name}.content = content end end EOC end DATE_ELEMENTS.each do |name, type| tag_name = "#{DC_PREFIX}:#{name}" module_eval(<<-EOC, *get_file_and_line_from_caller(0)) class DublinCore#{Utils.to_class_name(name)} < Element remove_method(:content=) remove_method(:value=) date_writer("content", #{type.dump}, #{tag_name.dump}) alias_method(:value=, :content=) end EOC end end # For backward compatibility DublincoreModel = DublinCoreModel DublinCoreModel::ELEMENTS.each do |name| class_name = Utils.to_class_name(name) BaseListener.install_class_name(DC_URI, name, "DublinCore#{class_name}") end DublinCoreModel::ELEMENTS.collect! {|name| "#{DC_PREFIX}_#{name}"} end require 'rss/dublincore/1.0' require 'rss/dublincore/2.0' require 'rss/dublincore/atom' PK!c  2.2.0/rss/image.rbnu[require 'rss/1.0' require 'rss/dublincore' module RSS # The prefix for the Image XML namespace. IMAGE_PREFIX = 'image' # The URI for the Image specification. IMAGE_URI = 'http://purl.org/rss/1.0/modules/image/' RDF.install_ns(IMAGE_PREFIX, IMAGE_URI) # This constant holds strings which contain the names of # image elements, with the appropriate prefix. IMAGE_ELEMENTS = [] %w(item favicon).each do |name| class_name = Utils.to_class_name(name) BaseListener.install_class_name(IMAGE_URI, name, "Image#{class_name}") IMAGE_ELEMENTS << "#{IMAGE_PREFIX}_#{name}" end module ImageModelUtils def validate_one_tag_name(ignore_unknown_element, name, tags) if !ignore_unknown_element invalid = tags.find {|tag| tag != name} raise UnknownTagError.new(invalid, IMAGE_URI) if invalid end raise TooMuchTagError.new(name, tag_name) if tags.size > 1 end end module ImageItemModel include ImageModelUtils extend BaseModel def self.append_features(klass) super klass.install_have_child_element("item", IMAGE_URI, "?", "#{IMAGE_PREFIX}_item") klass.install_must_call_validator(IMAGE_PREFIX, IMAGE_URI) end class ImageItem < Element include RSS10 include DublinCoreModel @tag_name = "item" class << self def required_prefix IMAGE_PREFIX end def required_uri IMAGE_URI end end install_must_call_validator(IMAGE_PREFIX, IMAGE_URI) [ ["about", ::RSS::RDF::URI, true], ["resource", ::RSS::RDF::URI, false], ].each do |name, uri, required| install_get_attribute(name, uri, required, nil, nil, "#{::RSS::RDF::PREFIX}:#{name}") end %w(width height).each do |tag| full_name = "#{IMAGE_PREFIX}_#{tag}" disp_name = "#{IMAGE_PREFIX}:#{tag}" install_text_element(tag, IMAGE_URI, "?", full_name, :integer, disp_name) BaseListener.install_get_text_element(IMAGE_URI, tag, full_name) end alias width= image_width= alias width image_width alias height= image_height= alias height image_height def initialize(*args) if Utils.element_initialize_arguments?(args) super else super() self.about = args[0] self.resource = args[1] end end def full_name tag_name_with_prefix(IMAGE_PREFIX) end private def maker_target(target) target.image_item end def setup_maker_attributes(item) item.about = self.about item.resource = self.resource end end end module ImageFaviconModel include ImageModelUtils extend BaseModel def self.append_features(klass) super unless klass.class == Module klass.install_have_child_element("favicon", IMAGE_URI, "?", "#{IMAGE_PREFIX}_favicon") klass.install_must_call_validator(IMAGE_PREFIX, IMAGE_URI) end end class ImageFavicon < Element include RSS10 include DublinCoreModel @tag_name = "favicon" class << self def required_prefix IMAGE_PREFIX end def required_uri IMAGE_URI end end [ ["about", ::RSS::RDF::URI, true, ::RSS::RDF::PREFIX], ["size", IMAGE_URI, true, IMAGE_PREFIX], ].each do |name, uri, required, prefix| install_get_attribute(name, uri, required, nil, nil, "#{prefix}:#{name}") end AVAILABLE_SIZES = %w(small medium large) alias_method :set_size, :size= private :set_size def size=(new_value) if @do_validate and !new_value.nil? new_value = new_value.strip unless AVAILABLE_SIZES.include?(new_value) attr_name = "#{IMAGE_PREFIX}:size" raise NotAvailableValueError.new(full_name, new_value, attr_name) end end set_size(new_value) end alias image_size= size= alias image_size size def initialize(*args) if Utils.element_initialize_arguments?(args) super else super() self.about = args[0] self.size = args[1] end end def full_name tag_name_with_prefix(IMAGE_PREFIX) end private def maker_target(target) target.image_favicon end def setup_maker_attributes(favicon) favicon.about = self.about favicon.size = self.size end end end class RDF class Channel; include ImageFaviconModel; end class Item; include ImageItemModel; end end end PK!Ye2.2.0/rss/xml.rbnu[require "rss/utils" module RSS module XML class Element include Enumerable attr_reader :name, :prefix, :uri, :attributes, :children def initialize(name, prefix=nil, uri=nil, attributes={}, children=[]) @name = name @prefix = prefix @uri = uri @attributes = attributes if children.is_a?(String) or !children.respond_to?(:each) @children = [children] else @children = children end end def [](name) @attributes[name] end def []=(name, value) @attributes[name] = value end def <<(child) @children << child end def each(&block) @children.each(&block) end def ==(other) other.kind_of?(self.class) and @name == other.name and @uri == other.uri and @attributes == other.attributes and @children == other.children end def to_s rv = "<#{full_name}" attributes.each do |key, value| rv << " #{Utils.html_escape(key)}=\"#{Utils.html_escape(value)}\"" end if children.empty? rv << "/>" else rv << ">" children.each do |child| rv << child.to_s end rv << "" end rv end def full_name if @prefix "#{@prefix}:#{@name}" else @name end end end end end PK!?w 2.2.0/rss/taxonomy.rbnu[require "rss/1.0" require "rss/dublincore" module RSS # The prefix for the Taxonomy XML namespace. TAXO_PREFIX = "taxo" # The URI for the specification of the Taxonomy XML namespace. TAXO_URI = "http://purl.org/rss/1.0/modules/taxonomy/" RDF.install_ns(TAXO_PREFIX, TAXO_URI) # The listing of all the taxonomy elements, with the appropriate namespace. TAXO_ELEMENTS = [] %w(link).each do |name| full_name = "#{TAXO_PREFIX}_#{name}" BaseListener.install_get_text_element(TAXO_URI, name, full_name) TAXO_ELEMENTS << "#{TAXO_PREFIX}_#{name}" end %w(topic topics).each do |name| class_name = Utils.to_class_name(name) BaseListener.install_class_name(TAXO_URI, name, "Taxonomy#{class_name}") TAXO_ELEMENTS << "#{TAXO_PREFIX}_#{name}" end module TaxonomyTopicsModel extend BaseModel def self.append_features(klass) super klass.install_must_call_validator(TAXO_PREFIX, TAXO_URI) %w(topics).each do |name| klass.install_have_child_element(name, TAXO_URI, "?", "#{TAXO_PREFIX}_#{name}") end end class TaxonomyTopics < Element include RSS10 Bag = ::RSS::RDF::Bag class << self def required_prefix TAXO_PREFIX end def required_uri TAXO_URI end end @tag_name = "topics" install_have_child_element("Bag", RDF::URI, nil) install_must_call_validator('rdf', RDF::URI) def initialize(*args) if Utils.element_initialize_arguments?(args) super else super() self.Bag = args[0] end self.Bag ||= Bag.new end def full_name tag_name_with_prefix(TAXO_PREFIX) end def maker_target(target) target.taxo_topics end def resources if @Bag @Bag.lis.collect do |li| li.resource end else [] end end end end module TaxonomyTopicModel extend BaseModel def self.append_features(klass) super var_name = "#{TAXO_PREFIX}_topic" klass.install_have_children_element("topic", TAXO_URI, "*", var_name) end class TaxonomyTopic < Element include RSS10 include DublinCoreModel include TaxonomyTopicsModel class << self def required_prefix TAXO_PREFIX end def required_uri TAXO_URI end end @tag_name = "topic" install_get_attribute("about", ::RSS::RDF::URI, true, nil, nil, "#{RDF::PREFIX}:about") install_text_element("link", TAXO_URI, "?", "#{TAXO_PREFIX}_link") def initialize(*args) if Utils.element_initialize_arguments?(args) super else super() self.about = args[0] end end def full_name tag_name_with_prefix(TAXO_PREFIX) end def maker_target(target) target.new_taxo_topic end end end class RDF include TaxonomyTopicModel class Channel include TaxonomyTopicsModel end class Item; include TaxonomyTopicsModel; end end end PK!<2.2.0/rss/maker.rbnu[require "rss/rss" module RSS ## # # Provides a set of builders for various RSS objects # # * Feeds # * RSS 0.91 # * RSS 1.0 # * RSS 2.0 # * Atom 1.0 # # * Elements # * Atom::Entry module Maker # Collection of supported makers MAKERS = {} class << self # Builder for an RSS object # Creates an object of the type passed in +args+ # # Executes the +block+ to populate elements of the created RSS object def make(version, &block) self[version].make(&block) end # Returns the maker for the +version+ def [](version) maker_info = maker(version) raise UnsupportedMakerVersionError.new(version) if maker_info.nil? maker_info[:maker] end # Adds a maker to the set of supported makers def add_maker(version, normalized_version, maker) MAKERS[version] = {:maker => maker, :version => normalized_version} end # Returns collection of supported maker versions def versions MAKERS.keys.uniq.sort end # Returns collection of supported makers def makers MAKERS.values.collect { |info| info[:maker] }.uniq end # Returns true if the version is supported def supported?(version) versions.include?(version) end private # Can I remove this method? def maker(version) MAKERS[version] end end end end require "rss/maker/1.0" require "rss/maker/2.0" require "rss/maker/feed" require "rss/maker/entry" require "rss/maker/content" require "rss/maker/dublincore" require "rss/maker/slash" require "rss/maker/syndication" require "rss/maker/taxonomy" require "rss/maker/trackback" require "rss/maker/image" require "rss/maker/itunes" PK!\^{{2.2.0/rss/xmlparser.rbnu[begin require "xml/parser" rescue LoadError require "xmlparser" end begin require "xml/encoding-ja" rescue LoadError require "xmlencoding-ja" if defined?(Kconv) module XMLEncoding_ja class SJISHandler include Kconv end end end end module XML class Parser unless defined?(Error) # This error is legacy, so we just set it to the new one Error = ::XMLParserError # :nodoc: end end end module RSS class REXMLLikeXMLParser < ::XML::Parser include ::XML::Encoding_ja def listener=(listener) @listener = listener end def startElement(name, attrs) @listener.tag_start(name, attrs) end def endElement(name) @listener.tag_end(name) end def character(data) @listener.text(data) end def xmlDecl(version, encoding, standalone) @listener.xmldecl(version, encoding, standalone == 1) end def processingInstruction(target, content) @listener.instruction(target, content) end end class XMLParserParser < BaseParser class << self def listener XMLParserListener end end private def _parse begin parser = REXMLLikeXMLParser.new parser.listener = @listener parser.parse(@rss) rescue ::XML::Parser::Error => e raise NotWellFormedError.new(parser.line){e.message} end end end class XMLParserListener < BaseListener include ListenerMixin def xmldecl(version, encoding, standalone) super # Encoding is converted to UTF-8 when XMLParser parses XML. @encoding = 'UTF-8' end end end PK!snQENN2.2.0/rss/utils.rbnu[module RSS ## # RSS::Utils is a module that holds various utility functions that are used # across many parts of the rest of the RSS library. Like most modules named # some variant of 'util', its methods are probably not particularly useful # to those who aren't developing the library itself. module Utils module_function # Given a +name+ in a name_with_underscores or a name-with-dashes format, # returns the CamelCase version of +name+. # # If the +name+ is already CamelCased, nothing happens. # # Examples: # # require 'rss/utils' # # RSS::Utils.to_class_name("sample_name") # # => "SampleName" # RSS::Utils.to_class_name("with-dashes") # # => "WithDashes" # RSS::Utils.to_class_name("CamelCase") # # => "CamelCase" def to_class_name(name) name.split(/[_\-]/).collect do |part| "#{part[0, 1].upcase}#{part[1..-1]}" end.join("") end # Returns an array of two elements: the filename where the calling method # is located, and the line number where it is defined. # # Takes an optional argument +i+, which specifies how many callers up the # stack to look. # # Examples: # # require 'rss/utils' # # def foo # p RSS::Utils.get_file_and_line_from_caller # p RSS::Utils.get_file_and_line_from_caller(1) # end # # def bar # foo # end # # def baz # bar # end # # baz # # => ["test.rb", 5] # # => ["test.rb", 9] # # If +i+ is not given, or is the default value of 0, it attempts to figure # out the correct value. This is useful when in combination with # instance_eval. For example: # # require 'rss/utils' # # def foo # p RSS::Utils.get_file_and_line_from_caller(1) # end # # def bar # foo # end # # instance_eval <<-RUBY, *RSS::Utils.get_file_and_line_from_caller # def baz # bar # end # RUBY # # baz # # # => ["test.rb", 8] def get_file_and_line_from_caller(i=0) file, line, = caller[i].split(':') line = line.to_i line += 1 if i.zero? [file, line] end # Takes a string +s+ with some HTML in it, and escapes '&', '"', '<' and '>', by # replacing them with the appropriate entities. # # This method is also aliased to h, for convenience. # # Examples: # # require 'rss/utils' # # RSS::Utils.html_escape("Dungeons & Dragons") # # => "Dungeons & Dragons" # RSS::Utils.h(">_>") # # => ">_>" def html_escape(s) s.to_s.gsub(/&/, "&").gsub(/\"/, """).gsub(/>/, ">").gsub(/ 3 components.unshift("00") until components.size == 3 components.collect do |component| component.to_i end end def construct(hour, minute, second) components = [minute, second] if components.include?(nil) nil else components.unshift(hour) if hour and hour > 0 components.collect do |component| "%02d" % component end.join(":") end end end content_setup alias_method(:value, :content) remove_method(:content=) attr_reader :hour, :minute, :second def initialize(*args) if Utils.element_initialize_arguments?(args) super else super() args = args[0] if args.size == 1 and args[0].is_a?(Array) if args.size == 1 self.content = args[0] elsif args.size > 3 raise ArgumentError, "must be (do_validate, params), (content), " + "(minute, second), ([minute, second]), " + "(hour, minute, second) or ([hour, minute, second]): " + args.inspect else @second, @minute, @hour = args.reverse update_content end end end def content=(value) if value.nil? @content = nil elsif value.is_a?(self.class) self.content = value.content else begin @hour, @minute, @second = self.class.parse(value, @do_validate) rescue ArgumentError raise NotAvailableValueError.new(tag_name, value) end @content = value end end alias_method(:value=, :content=) def hour=(hour) @hour = @do_validate ? Integer(hour) : hour.to_i update_content hour end def minute=(minute) @minute = @do_validate ? Integer(minute) : minute.to_i update_content minute end def second=(second) @second = @do_validate ? Integer(second) : second.to_i update_content second end def full_name tag_name_with_prefix(ITUNES_PREFIX) end private def update_content @content = self.class.construct(hour, minute, second) end def maker_target(target) if @content target.itunes_duration {|duration| duration} else nil end end def setup_maker_element(duration) super(duration) duration.content = @content end end end class Rss class Channel include ITunesChannelModel class Item; include ITunesItemModel; end end end element_infos = ITunesChannelModel::ELEMENT_INFOS + ITunesItemModel::ELEMENT_INFOS element_infos.each do |name, type| case type when :element, :elements, :attribute class_name = Utils.to_class_name(name) BaseListener.install_class_name(ITUNES_URI, name, "ITunes#{class_name}") else accessor_base = "#{ITUNES_PREFIX}_#{name.gsub(/-/, '_')}" BaseListener.install_get_text_element(ITUNES_URI, name, accessor_base) end end end PK!\{72.2.0/rss/maker/dublincore.rbnu[require 'rss/dublincore' require 'rss/maker/1.0' module RSS module Maker module DublinCoreModel def self.append_features(klass) super ::RSS::DublinCoreModel::ELEMENT_NAME_INFOS.each do |name, plural_name| plural_name ||= "#{name}s" full_name = "#{RSS::DC_PREFIX}_#{name}" full_plural_name = "#{RSS::DC_PREFIX}_#{plural_name}" plural_klass_name = "DublinCore#{Utils.to_class_name(plural_name)}" klass.def_classed_elements(full_name, "value", plural_klass_name, full_plural_name, name) klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1) def new_#{full_name}(value=nil) _#{full_name} = #{full_plural_name}.new_#{name} _#{full_name}.value = value if block_given? yield _#{full_name} else _#{full_name} end end EOC end klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1) # For backward compatibility alias #{DC_PREFIX}_rightses #{DC_PREFIX}_rights_list EOC end ::RSS::DublinCoreModel::ELEMENT_NAME_INFOS.each do |name, plural_name| plural_name ||= "#{name}s" full_name ||= "#{DC_PREFIX}_#{name}" full_plural_name ||= "#{DC_PREFIX}_#{plural_name}" klass_name = Utils.to_class_name(name) full_klass_name = "DublinCore#{klass_name}" plural_klass_name = "DublinCore#{Utils.to_class_name(plural_name)}" module_eval(<<-EOC, __FILE__, __LINE__ + 1) class #{plural_klass_name}Base < Base def_array_element(#{name.dump}, #{full_plural_name.dump}, #{full_klass_name.dump}) class #{full_klass_name}Base < Base attr_accessor :value add_need_initialize_variable("value") alias_method(:content, :value) alias_method(:content=, :value=) def have_required_values? @value end def to_feed(feed, current) if value and current.respond_to?(:#{full_name}) new_item = current.class::#{full_klass_name}.new(value) current.#{full_plural_name} << new_item end end end #{klass_name}Base = #{full_klass_name}Base end EOC end def self.install_dublin_core(klass) ::RSS::DublinCoreModel::ELEMENT_NAME_INFOS.each do |name, plural_name| plural_name ||= "#{name}s" klass_name = Utils.to_class_name(name) full_klass_name = "DublinCore#{klass_name}" plural_klass_name = "DublinCore#{Utils.to_class_name(plural_name)}" klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1) class #{plural_klass_name} < #{plural_klass_name}Base class #{full_klass_name} < #{full_klass_name}Base end #{klass_name} = #{full_klass_name} end EOC end end end class ChannelBase include DublinCoreModel end class ImageBase; include DublinCoreModel; end class ItemsBase class ItemBase include DublinCoreModel end end class TextinputBase; include DublinCoreModel; end makers.each do |maker| maker.module_eval(<<-EOC, __FILE__, __LINE__ + 1) class Channel DublinCoreModel.install_dublin_core(self) end class Image DublinCoreModel.install_dublin_core(self) end class Items class Item DublinCoreModel.install_dublin_core(self) end end class Textinput DublinCoreModel.install_dublin_core(self) end EOC end end end PK!Np p 2.2.0/rss/maker/image.rbnu[require 'rss/image' require 'rss/maker/1.0' require 'rss/maker/dublincore' module RSS module Maker module ImageItemModel def self.append_features(klass) super name = "#{RSS::IMAGE_PREFIX}_item" klass.def_classed_element(name) end def self.install_image_item(klass) klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1) class ImageItem < ImageItemBase DublinCoreModel.install_dublin_core(self) end EOC end class ImageItemBase < Base include Maker::DublinCoreModel attr_accessor :about, :resource, :image_width, :image_height add_need_initialize_variable("about") add_need_initialize_variable("resource") add_need_initialize_variable("image_width") add_need_initialize_variable("image_height") alias width= image_width= alias width image_width alias height= image_height= alias height image_height def have_required_values? @about end def to_feed(feed, current) if current.respond_to?(:image_item=) and have_required_values? item = current.class::ImageItem.new setup_values(item) setup_other_elements(item) current.image_item = item end end end end module ImageFaviconModel def self.append_features(klass) super name = "#{RSS::IMAGE_PREFIX}_favicon" klass.def_classed_element(name) end def self.install_image_favicon(klass) klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1) class ImageFavicon < ImageFaviconBase DublinCoreModel.install_dublin_core(self) end EOC end class ImageFaviconBase < Base include Maker::DublinCoreModel attr_accessor :about, :image_size add_need_initialize_variable("about") add_need_initialize_variable("image_size") alias size image_size alias size= image_size= def have_required_values? @about and @image_size end def to_feed(feed, current) if current.respond_to?(:image_favicon=) and have_required_values? favicon = current.class::ImageFavicon.new setup_values(favicon) setup_other_elements(favicon) current.image_favicon = favicon end end end end class ChannelBase; include Maker::ImageFaviconModel; end class ItemsBase class ItemBase; include Maker::ImageItemModel; end end makers.each do |maker| maker.module_eval(<<-EOC, __FILE__, __LINE__ + 1) class Channel ImageFaviconModel.install_image_favicon(self) end class Items class Item ImageItemModel.install_image_item(self) end end EOC end end end PK!9fl l 2.2.0/rss/maker/taxonomy.rbnu[require 'rss/taxonomy' require 'rss/maker/1.0' require 'rss/maker/dublincore' module RSS module Maker module TaxonomyTopicsModel def self.append_features(klass) super klass.def_classed_element("#{RSS::TAXO_PREFIX}_topics", "TaxonomyTopics") end def self.install_taxo_topics(klass) klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1) class TaxonomyTopics < TaxonomyTopicsBase def to_feed(feed, current) if current.respond_to?(:taxo_topics) topics = current.class::TaxonomyTopics.new bag = topics.Bag @resources.each do |resource| bag.lis << RDF::Bag::Li.new(resource) end current.taxo_topics = topics end end end EOC end class TaxonomyTopicsBase < Base attr_reader :resources def_array_element("resource") remove_method :new_resource end end module TaxonomyTopicModel def self.append_features(klass) super class_name = "TaxonomyTopics" klass.def_classed_elements("#{TAXO_PREFIX}_topic", "value", class_name) end def self.install_taxo_topic(klass) klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1) class TaxonomyTopics < TaxonomyTopicsBase class TaxonomyTopic < TaxonomyTopicBase DublinCoreModel.install_dublin_core(self) TaxonomyTopicsModel.install_taxo_topics(self) def to_feed(feed, current) if current.respond_to?(:taxo_topics) topic = current.class::TaxonomyTopic.new(value) topic.taxo_link = value taxo_topics.to_feed(feed, topic) if taxo_topics current.taxo_topics << topic setup_other_elements(feed, topic) end end end end EOC end class TaxonomyTopicsBase < Base def_array_element("topic", nil, "TaxonomyTopic") alias_method(:new_taxo_topic, :new_topic) # For backward compatibility class TaxonomyTopicBase < Base include DublinCoreModel include TaxonomyTopicsModel attr_accessor :value add_need_initialize_variable("value") alias_method(:taxo_link, :value) alias_method(:taxo_link=, :value=) def have_required_values? @value end end end end class RSSBase include TaxonomyTopicModel end class ChannelBase include TaxonomyTopicsModel end class ItemsBase class ItemBase include TaxonomyTopicsModel end end makers.each do |maker| maker.module_eval(<<-EOC, __FILE__, __LINE__ + 1) TaxonomyTopicModel.install_taxo_topic(self) class Channel TaxonomyTopicsModel.install_taxo_topics(self) end class Items class Item TaxonomyTopicsModel.install_taxo_topics(self) end end EOC end end end PK!!dw112.2.0/rss/maker/feed.rbnu[require "rss/maker/atom" module RSS module Maker module Atom class Feed < RSSBase def initialize(feed_version="1.0") super @feed_type = "atom" @feed_subtype = "feed" end private def make_feed ::RSS::Atom::Feed.new(@version, @encoding, @standalone) end def setup_elements(feed) setup_channel(feed) setup_image(feed) setup_items(feed) end class Channel < ChannelBase include SetupDefaultLanguage def to_feed(feed) set_default_values do setup_values(feed) feed.dc_dates.clear setup_other_elements(feed) if image_favicon.about icon = feed.class::Icon.new icon.content = image_favicon.about feed.icon = icon end unless have_required_values? raise NotSetError.new("maker.channel", not_set_required_variables) end end end def have_required_values? super and (!authors.empty? or @maker.items.any? {|item| !item.authors.empty?}) end private def required_variable_names %w(id updated) end def variables super + %w(id updated) end def variable_is_set? super or !authors.empty? end def not_set_required_variables vars = super if authors.empty? and @maker.items.all? {|item| item.author.to_s.empty?} vars << "author" end vars << "title" unless title {|t| t.have_required_values?} vars end def _set_default_values(&block) keep = { :id => id, } self.id ||= about super(&block) ensure self.id = keep[:id] end class SkipDays < SkipDaysBase def to_feed(*args) end class Day < DayBase end end class SkipHours < SkipHoursBase def to_feed(*args) end class Hour < HourBase end end class Cloud < CloudBase def to_feed(*args) end end class Categories < CategoriesBase class Category < CategoryBase include AtomCategory def self.not_set_name "maker.channel.category" end end end class Links < LinksBase class Link < LinkBase include AtomLink def self.not_set_name "maker.channel.link" end end end AtomPersons.def_atom_persons(self, "author", "maker.channel.author") AtomPersons.def_atom_persons(self, "contributor", "maker.channel.contributor") class Generator < GeneratorBase include AtomGenerator def self.not_set_name "maker.channel.generator" end end AtomTextConstruct.def_atom_text_construct(self, "rights", "maker.channel.copyright", "Copyright") AtomTextConstruct.def_atom_text_construct(self, "subtitle", "maker.channel.description", "Description") AtomTextConstruct.def_atom_text_construct(self, "title", "maker.channel.title") end class Image < ImageBase def to_feed(feed) logo = feed.class::Logo.new class << logo alias_method(:url=, :content=) end set = setup_values(logo) class << logo remove_method(:url=) end if set feed.logo = logo set_parent(logo, feed) setup_other_elements(feed, logo) elsif variable_is_set? raise NotSetError.new("maker.image", not_set_required_variables) end end private def required_variable_names %w(url) end end class Items < ItemsBase def to_feed(feed) normalize.each do |item| item.to_feed(feed) end setup_other_elements(feed, feed.entries) end class Item < ItemBase def to_feed(feed) set_default_values do entry = feed.class::Entry.new set = setup_values(entry) entry.dc_dates.clear setup_other_elements(feed, entry) if set feed.entries << entry set_parent(entry, feed) elsif variable_is_set? raise NotSetError.new("maker.item", not_set_required_variables) end end end def have_required_values? set_default_values do super and title {|t| t.have_required_values?} end end private def required_variable_names %w(id updated) end def variables super + ["updated"] end def not_set_required_variables vars = super vars << "title" unless title {|t| t.have_required_values?} vars end def _set_default_values(&block) keep = { :id => id, } self.id ||= link super(&block) ensure self.id = keep[:id] end class Guid < GuidBase def to_feed(feed, current) end end class Enclosure < EnclosureBase def to_feed(feed, current) end end class Source < SourceBase def to_feed(feed, current) source = current.class::Source.new setup_values(source) current.source = source set_parent(source, current) setup_other_elements(feed, source) current.source = nil if source.to_s == "" end private def required_variable_names [] end def variables super + ["updated"] end AtomPersons.def_atom_persons(self, "author", "maker.item.source.author") AtomPersons.def_atom_persons(self, "contributor", "maker.item.source.contributor") class Categories < CategoriesBase class Category < CategoryBase include AtomCategory def self.not_set_name "maker.item.source.category" end end end class Generator < GeneratorBase include AtomGenerator def self.not_set_name "maker.item.source.generator" end end class Icon < IconBase def to_feed(feed, current) icon = current.class::Icon.new class << icon alias_method(:url=, :content=) end set = setup_values(icon) class << icon remove_method(:url=) end if set current.icon = icon set_parent(icon, current) setup_other_elements(feed, icon) elsif variable_is_set? raise NotSetError.new("maker.item.source.icon", not_set_required_variables) end end private def required_variable_names %w(url) end end class Links < LinksBase class Link < LinkBase include AtomLink def self.not_set_name "maker.item.source.link" end end end class Logo < LogoBase include AtomLogo def self.not_set_name "maker.item.source.logo" end end maker_name_base = "maker.item.source." maker_name = "#{maker_name_base}rights" AtomTextConstruct.def_atom_text_construct(self, "rights", maker_name) maker_name = "#{maker_name_base}subtitle" AtomTextConstruct.def_atom_text_construct(self, "subtitle", maker_name) maker_name = "#{maker_name_base}title" AtomTextConstruct.def_atom_text_construct(self, "title", maker_name) end class Categories < CategoriesBase class Category < CategoryBase include AtomCategory def self.not_set_name "maker.item.category" end end end AtomPersons.def_atom_persons(self, "author", "maker.item.author") AtomPersons.def_atom_persons(self, "contributor", "maker.item.contributor") class Links < LinksBase class Link < LinkBase include AtomLink def self.not_set_name "maker.item.link" end end end AtomTextConstruct.def_atom_text_construct(self, "rights", "maker.item.rights") AtomTextConstruct.def_atom_text_construct(self, "summary", "maker.item.description", "Description") AtomTextConstruct.def_atom_text_construct(self, "title", "maker.item.title") class Content < ContentBase def to_feed(feed, current) content = current.class::Content.new if setup_values(content) content.src = nil if content.src and content.content current.content = content set_parent(content, current) setup_other_elements(feed, content) elsif variable_is_set? raise NotSetError.new("maker.item.content", not_set_required_variables) end end alias_method(:xml, :xml_content) private def required_variable_names if out_of_line? %w(type) elsif xml_type? %w(xml_content) else %w(content) end end def variables if out_of_line? super elsif xml_type? super + %w(xml) else super end end def xml_type? _type = type return false if _type.nil? _type == "xhtml" or /(?:\+xml|\/xml)$/i =~ _type or %w(text/xml-external-parsed-entity application/xml-external-parsed-entity application/xml-dtd).include?(_type.downcase) end end end end class Textinput < TextinputBase end end end add_maker("atom", "1.0", Atom::Feed) add_maker("atom:feed", "1.0", Atom::Feed) add_maker("atom1.0", "1.0", Atom::Feed) add_maker("atom1.0:feed", "1.0", Atom::Feed) end end PK!=o\+/+/2.2.0/rss/maker/0.9.rbnu[require "rss/0.9" require "rss/maker/base" module RSS module Maker class RSS09 < RSSBase def initialize(feed_version) super @feed_type = "rss" end private def make_feed Rss.new(@feed_version, @version, @encoding, @standalone) end def setup_elements(rss) setup_channel(rss) end class Channel < ChannelBase def to_feed(rss) channel = Rss::Channel.new setup_values(channel) _not_set_required_variables = not_set_required_variables if _not_set_required_variables.empty? rss.channel = channel set_parent(channel, rss) setup_items(rss) setup_image(rss) setup_textinput(rss) setup_other_elements(rss, channel) rss else raise NotSetError.new("maker.channel", _not_set_required_variables) end end private def setup_items(rss) @maker.items.to_feed(rss) end def setup_image(rss) @maker.image.to_feed(rss) end def setup_textinput(rss) @maker.textinput.to_feed(rss) end def variables super + ["pubDate"] end def required_variable_names %w(link language) end def not_set_required_variables vars = super vars << "description" unless description {|d| d.have_required_values?} vars << "title" unless title {|t| t.have_required_values?} vars end class SkipDays < SkipDaysBase def to_feed(rss, channel) unless @days.empty? skipDays = Rss::Channel::SkipDays.new channel.skipDays = skipDays set_parent(skipDays, channel) @days.each do |day| day.to_feed(rss, skipDays.days) end end end class Day < DayBase def to_feed(rss, days) day = Rss::Channel::SkipDays::Day.new set = setup_values(day) if set days << day set_parent(day, days) setup_other_elements(rss, day) end end private def required_variable_names %w(content) end end end class SkipHours < SkipHoursBase def to_feed(rss, channel) unless @hours.empty? skipHours = Rss::Channel::SkipHours.new channel.skipHours = skipHours set_parent(skipHours, channel) @hours.each do |hour| hour.to_feed(rss, skipHours.hours) end end end class Hour < HourBase def to_feed(rss, hours) hour = Rss::Channel::SkipHours::Hour.new set = setup_values(hour) if set hours << hour set_parent(hour, hours) setup_other_elements(rss, hour) end end private def required_variable_names %w(content) end end end class Cloud < CloudBase def to_feed(*args) end end class Categories < CategoriesBase def to_feed(*args) end class Category < CategoryBase end end class Links < LinksBase def to_feed(rss, channel) return if @links.empty? @links.first.to_feed(rss, channel) end class Link < LinkBase def to_feed(rss, channel) if have_required_values? channel.link = href else raise NotSetError.new("maker.channel.link", not_set_required_variables) end end private def required_variable_names %w(href) end end end class Authors < AuthorsBase def to_feed(rss, channel) end class Author < AuthorBase def to_feed(rss, channel) end end end class Contributors < ContributorsBase def to_feed(rss, channel) end class Contributor < ContributorBase end end class Generator < GeneratorBase def to_feed(rss, channel) end end class Copyright < CopyrightBase def to_feed(rss, channel) channel.copyright = content if have_required_values? end private def required_variable_names %w(content) end end class Description < DescriptionBase def to_feed(rss, channel) channel.description = content if have_required_values? end private def required_variable_names %w(content) end end class Title < TitleBase def to_feed(rss, channel) channel.title = content if have_required_values? end private def required_variable_names %w(content) end end end class Image < ImageBase def to_feed(rss) image = Rss::Channel::Image.new set = setup_values(image) if set image.link = link rss.channel.image = image set_parent(image, rss.channel) setup_other_elements(rss, image) elsif required_element? raise NotSetError.new("maker.image", not_set_required_variables) end end private def required_variable_names %w(url title link) end def required_element? true end end class Items < ItemsBase def to_feed(rss) if rss.channel normalize.each do |item| item.to_feed(rss) end setup_other_elements(rss, rss.items) end end class Item < ItemBase def to_feed(rss) item = Rss::Channel::Item.new setup_values(item) _not_set_required_variables = not_set_required_variables if _not_set_required_variables.empty? rss.items << item set_parent(item, rss.channel) setup_other_elements(rss, item) elsif variable_is_set? raise NotSetError.new("maker.items", _not_set_required_variables) end end private def required_variable_names [] end def not_set_required_variables vars = super if @maker.feed_version == "0.91" vars << "title" unless title {|t| t.have_required_values?} vars << "link" unless link {|l| l.have_required_values?} end vars end class Guid < GuidBase def to_feed(*args) end end class Enclosure < EnclosureBase def to_feed(*args) end end class Source < SourceBase def to_feed(*args) end class Authors < AuthorsBase def to_feed(*args) end class Author < AuthorBase end end class Categories < CategoriesBase def to_feed(*args) end class Category < CategoryBase end end class Contributors < ContributorsBase def to_feed(*args) end class Contributor < ContributorBase end end class Generator < GeneratorBase def to_feed(*args) end end class Icon < IconBase def to_feed(*args) end end class Links < LinksBase def to_feed(*args) end class Link < LinkBase end end class Logo < LogoBase def to_feed(*args) end end class Rights < RightsBase def to_feed(*args) end end class Subtitle < SubtitleBase def to_feed(*args) end end class Title < TitleBase def to_feed(*args) end end end class Categories < CategoriesBase def to_feed(*args) end class Category < CategoryBase end end class Authors < AuthorsBase def to_feed(*args) end class Author < AuthorBase end end class Links < LinksBase def to_feed(rss, item) return if @links.empty? @links.first.to_feed(rss, item) end class Link < LinkBase def to_feed(rss, item) if have_required_values? item.link = href else raise NotSetError.new("maker.link", not_set_required_variables) end end private def required_variable_names %w(href) end end end class Contributors < ContributorsBase def to_feed(rss, item) end class Contributor < ContributorBase end end class Rights < RightsBase def to_feed(rss, item) end end class Description < DescriptionBase def to_feed(rss, item) item.description = content if have_required_values? end private def required_variable_names %w(content) end end class Content < ContentBase def to_feed(rss, item) end end class Title < TitleBase def to_feed(rss, item) item.title = content if have_required_values? end private def required_variable_names %w(content) end end end end class Textinput < TextinputBase def to_feed(rss) textInput = Rss::Channel::TextInput.new set = setup_values(textInput) if set rss.channel.textInput = textInput set_parent(textInput, rss.channel) setup_other_elements(rss, textInput) end end private def required_variable_names %w(title description name link) end end end class RSS091 < RSS09 def initialize(feed_version="0.91") super end class Channel < RSS09::Channel end class Items < RSS09::Items class Item < RSS09::Items::Item end end class Image < RSS09::Image end class Textinput < RSS09::Textinput end end class RSS092 < RSS09 def initialize(feed_version="0.92") super end class Channel < RSS09::Channel end class Items < RSS09::Items class Item < RSS09::Items::Item end end class Image < RSS09::Image end class Textinput < RSS09::Textinput end end add_maker("0.9", "0.92", RSS092) add_maker("0.91", "0.91", RSS091) add_maker("0.92", "0.92", RSS092) add_maker("rss0.9", "0.92", RSS092) add_maker("rss0.91", "0.91", RSS091) add_maker("rss0.92", "0.92", RSS092) end end PK!r]]2.2.0/rss/maker/syndication.rbnu[require 'rss/syndication' require 'rss/maker/1.0' module RSS module Maker module SyndicationModel def self.append_features(klass) super ::RSS::SyndicationModel::ELEMENTS.each do |name| klass.def_other_element(name) end end end class ChannelBase; include SyndicationModel; end end end PK!٢  2.2.0/rss/maker/itunes.rbnu[require 'rss/itunes' require 'rss/maker/2.0' module RSS module Maker module ITunesBaseModel def def_class_accessor(klass, name, type, *args) name = name.gsub(/-/, "_").gsub(/^itunes_/, '') full_name = "#{RSS::ITUNES_PREFIX}_#{name}" case type when nil klass.def_other_element(full_name) when :yes_other def_yes_other_accessor(klass, full_name) when :yes_clean_other def_yes_clean_other_accessor(klass, full_name) when :csv def_csv_accessor(klass, full_name) when :element, :attribute recommended_attribute_name, = *args klass_name = "ITunes#{Utils.to_class_name(name)}" klass.def_classed_element(full_name, klass_name, recommended_attribute_name) when :elements plural_name, recommended_attribute_name = args plural_name ||= "#{name}s" full_plural_name = "#{RSS::ITUNES_PREFIX}_#{plural_name}" klass_name = "ITunes#{Utils.to_class_name(name)}" plural_klass_name = "ITunes#{Utils.to_class_name(plural_name)}" def_elements_class_accessor(klass, name, full_name, full_plural_name, klass_name, plural_klass_name, recommended_attribute_name) end end def def_yes_other_accessor(klass, full_name) klass.def_other_element(full_name) klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1) def #{full_name}? Utils::YesOther.parse(@#{full_name}) end EOC end def def_yes_clean_other_accessor(klass, full_name) klass.def_other_element(full_name) klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1) def #{full_name}? Utils::YesCleanOther.parse(#{full_name}) end EOC end def def_csv_accessor(klass, full_name) klass.def_csv_element(full_name) end def def_elements_class_accessor(klass, name, full_name, full_plural_name, klass_name, plural_klass_name, recommended_attribute_name=nil) if recommended_attribute_name klass.def_classed_elements(full_name, recommended_attribute_name, plural_klass_name, full_plural_name) else klass.def_classed_element(full_plural_name, plural_klass_name) end klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1) def new_#{full_name}(text=nil) #{full_name} = @#{full_plural_name}.new_#{name} #{full_name}.text = text if block_given? yield #{full_name} else #{full_name} end end EOC end end module ITunesChannelModel extend ITunesBaseModel class << self def append_features(klass) super ::RSS::ITunesChannelModel::ELEMENT_INFOS.each do |name, type, *args| def_class_accessor(klass, name, type, *args) end end end class ITunesCategoriesBase < Base def_array_element("category", "itunes_categories", "ITunesCategory") class ITunesCategoryBase < Base attr_accessor :text add_need_initialize_variable("text") def_array_element("category", "itunes_categories", "ITunesCategory") def have_required_values? text end alias_method :to_feed_for_categories, :to_feed def to_feed(feed, current) if text and current.respond_to?(:itunes_category) new_item = current.class::ITunesCategory.new(text) to_feed_for_categories(feed, new_item) current.itunes_categories << new_item end end end end class ITunesImageBase < Base add_need_initialize_variable("href") attr_accessor("href") def to_feed(feed, current) if @href and current.respond_to?(:itunes_image) current.itunes_image ||= current.class::ITunesImage.new current.itunes_image.href = @href end end end class ITunesOwnerBase < Base %w(itunes_name itunes_email).each do |name| add_need_initialize_variable(name) attr_accessor(name) end def to_feed(feed, current) if current.respond_to?(:itunes_owner=) _not_set_required_variables = not_set_required_variables if (required_variable_names - _not_set_required_variables).empty? return end unless have_required_values? raise NotSetError.new("maker.channel.itunes_owner", _not_set_required_variables) end current.itunes_owner ||= current.class::ITunesOwner.new current.itunes_owner.itunes_name = @itunes_name current.itunes_owner.itunes_email = @itunes_email end end private def required_variable_names %w(itunes_name itunes_email) end end end module ITunesItemModel extend ITunesBaseModel class << self def append_features(klass) super ::RSS::ITunesItemModel::ELEMENT_INFOS.each do |name, type, *args| def_class_accessor(klass, name, type, *args) end end end class ITunesDurationBase < Base attr_reader :content add_need_initialize_variable("content") %w(hour minute second).each do |name| attr_reader(name) add_need_initialize_variable(name, 0) end def content=(content) if content.nil? @hour, @minute, @second, @content = nil else @hour, @minute, @second = ::RSS::ITunesItemModel::ITunesDuration.parse(content) @content = content end end def hour=(hour) @hour = Integer(hour) update_content end def minute=(minute) @minute = Integer(minute) update_content end def second=(second) @second = Integer(second) update_content end def to_feed(feed, current) if @content and current.respond_to?(:itunes_duration=) current.itunes_duration ||= current.class::ITunesDuration.new current.itunes_duration.content = @content end end private def update_content components = [@hour, @minute, @second] @content = ::RSS::ITunesItemModel::ITunesDuration.construct(*components) end end end class ChannelBase include Maker::ITunesChannelModel class ITunesCategories < ITunesCategoriesBase class ITunesCategory < ITunesCategoryBase ITunesCategory = self end end class ITunesImage < ITunesImageBase; end class ITunesOwner < ITunesOwnerBase; end end class ItemsBase class ItemBase include Maker::ITunesItemModel class ITunesDuration < ITunesDurationBase; end end end end end PK!7]<`<`2.2.0/rss/maker/base.rbnu[require 'forwardable' require 'rss/rss' module RSS module Maker class Base extend Utils::InheritedReader OTHER_ELEMENTS = [] NEED_INITIALIZE_VARIABLES = [] class << self def other_elements inherited_array_reader("OTHER_ELEMENTS") end def need_initialize_variables inherited_array_reader("NEED_INITIALIZE_VARIABLES") end def inherited_base ::RSS::Maker::Base end def inherited(subclass) subclass.const_set(:OTHER_ELEMENTS, []) subclass.const_set(:NEED_INITIALIZE_VARIABLES, []) end def add_other_element(variable_name) self::OTHER_ELEMENTS << variable_name end def add_need_initialize_variable(variable_name, init_value=nil, &init_block) init_value ||= init_block self::NEED_INITIALIZE_VARIABLES << [variable_name, init_value] end def def_array_element(name, plural=nil, klass_name=nil) include Enumerable extend Forwardable plural ||= "#{name}s" klass_name ||= Utils.to_class_name(name) def_delegators("@#{plural}", :<<, :[], :[]=, :first, :last) def_delegators("@#{plural}", :push, :pop, :shift, :unshift) def_delegators("@#{plural}", :each, :size, :empty?, :clear) add_need_initialize_variable(plural) {[]} module_eval(<<-EOC, __FILE__, __LINE__ + 1) def new_#{name} #{name} = self.class::#{klass_name}.new(@maker) @#{plural} << #{name} if block_given? yield #{name} else #{name} end end alias new_child new_#{name} def to_feed(*args) @#{plural}.each do |#{name}| #{name}.to_feed(*args) end end def replace(elements) @#{plural}.replace(elements.to_a) end EOC end def def_classed_element_without_accessor(name, class_name=nil) class_name ||= Utils.to_class_name(name) add_other_element(name) add_need_initialize_variable(name) do |object| object.send("make_#{name}") end module_eval(<<-EOC, __FILE__, __LINE__ + 1) private def setup_#{name}(feed, current) @#{name}.to_feed(feed, current) end def make_#{name} self.class::#{class_name}.new(@maker) end EOC end def def_classed_element(name, class_name=nil, attribute_name=nil) def_classed_element_without_accessor(name, class_name) if attribute_name module_eval(<<-EOC, __FILE__, __LINE__ + 1) def #{name} if block_given? yield(@#{name}) else @#{name}.#{attribute_name} end end def #{name}=(new_value) @#{name}.#{attribute_name} = new_value end EOC else attr_reader name end end def def_classed_elements(name, attribute, plural_class_name=nil, plural_name=nil, new_name=nil) plural_name ||= "#{name}s" new_name ||= name def_classed_element(plural_name, plural_class_name) local_variable_name = "_#{name}" new_value_variable_name = "new_value" additional_setup_code = nil if block_given? additional_setup_code = yield(local_variable_name, new_value_variable_name) end module_eval(<<-EOC, __FILE__, __LINE__ + 1) def #{name} #{local_variable_name} = #{plural_name}.first #{local_variable_name} ? #{local_variable_name}.#{attribute} : nil end def #{name}=(#{new_value_variable_name}) #{local_variable_name} = #{plural_name}.first || #{plural_name}.new_#{new_name} #{additional_setup_code} #{local_variable_name}.#{attribute} = #{new_value_variable_name} end EOC end def def_other_element(name) attr_accessor name def_other_element_without_accessor(name) end def def_other_element_without_accessor(name) add_need_initialize_variable(name) add_other_element(name) module_eval(<<-EOC, __FILE__, __LINE__ + 1) def setup_#{name}(feed, current) if !@#{name}.nil? and current.respond_to?(:#{name}=) current.#{name} = @#{name} end end EOC end def def_csv_element(name, type=nil) def_other_element_without_accessor(name) attr_reader(name) converter = "" if type == :integer converter = "{|v| Integer(v)}" end module_eval(<<-EOC, __FILE__, __LINE__ + 1) def #{name}=(value) @#{name} = Utils::CSV.parse(value)#{converter} end EOC end end attr_reader :maker def initialize(maker) @maker = maker @default_values_are_set = false initialize_variables end def have_required_values? not_set_required_variables.empty? end def variable_is_set? variables.any? {|var| not __send__(var).nil?} end private def initialize_variables self.class.need_initialize_variables.each do |variable_name, init_value| if init_value.nil? value = nil else if init_value.respond_to?(:call) value = init_value.call(self) elsif init_value.is_a?(String) # just for backward compatibility value = instance_eval(init_value, __FILE__, __LINE__) else value = init_value end end instance_variable_set("@#{variable_name}", value) end end def setup_other_elements(feed, current=nil) current ||= current_element(feed) self.class.other_elements.each do |element| __send__("setup_#{element}", feed, current) end end def current_element(feed) feed end def set_default_values(&block) return yield if @default_values_are_set begin @default_values_are_set = true _set_default_values(&block) ensure @default_values_are_set = false end end def _set_default_values(&block) yield end def setup_values(target) set = false if have_required_values? variables.each do |var| setter = "#{var}=" if target.respond_to?(setter) value = __send__(var) unless value.nil? target.__send__(setter, value) set = true end end end end set end def set_parent(target, parent) target.parent = parent if target.class.need_parent? end def variables self.class.need_initialize_variables.find_all do |name, init| # init == "nil" is just for backward compatibility init.nil? or init == "nil" end.collect do |name, init| name end end def not_set_required_variables required_variable_names.find_all do |var| __send__(var).nil? end end def required_variables_are_set? required_variable_names.each do |var| return false if __send__(var).nil? end true end end module AtomPersonConstructBase def self.append_features(klass) super klass.class_eval(<<-EOC, __FILE__, __LINE__ + 1) %w(name uri email).each do |element| attr_accessor element add_need_initialize_variable(element) end EOC end end module AtomTextConstructBase module EnsureXMLContent class << self def included(base) super base.class_eval do %w(type content xml_content).each do |element| attr_reader element attr_writer element if element != "xml_content" add_need_initialize_variable(element) end alias_method(:xhtml, :xml_content) end end end def ensure_xml_content(content) xhtml_uri = ::RSS::Atom::XHTML_URI unless content.is_a?(RSS::XML::Element) and ["div", xhtml_uri] == [content.name, content.uri] children = content children = [children] unless content.is_a?(Array) children = set_xhtml_uri_as_default_uri(children) content = RSS::XML::Element.new("div", nil, xhtml_uri, {"xmlns" => xhtml_uri}, children) end content end def xml_content=(content) @xml_content = ensure_xml_content(content) end def xhtml=(content) self.xml_content = content end private def set_xhtml_uri_as_default_uri(children) children.collect do |child| if child.is_a?(RSS::XML::Element) and child.prefix.nil? and child.uri.nil? RSS::XML::Element.new(child.name, nil, ::RSS::Atom::XHTML_URI, child.attributes.dup, set_xhtml_uri_as_default_uri(child.children)) else child end end end end def self.append_features(klass) super klass.class_eval do include EnsureXMLContent end end end module SetupDefaultDate private def _set_default_values keep = { :date => date, :dc_dates => dc_dates.to_a.dup, } _date = _parse_date_if_needed(date) if _date and !dc_dates.any? {|dc_date| dc_date.value == _date} dc_date = self.class::DublinCoreDates::DublinCoreDate.new(self) dc_date.value = _date.dup dc_dates.unshift(dc_date) end self.date ||= self.dc_date super ensure self.date = keep[:date] dc_dates.replace(keep[:dc_dates]) end def _parse_date_if_needed(date_value) date_value = Time.parse(date_value) if date_value.is_a?(String) date_value end end module SetupDefaultLanguage private def _set_default_values keep = { :dc_languages => dc_languages.to_a.dup, } _language = language if _language and !dc_languages.any? {|dc_language| dc_language.value == _language} dc_language = self.class::DublinCoreLanguages::DublinCoreLanguage.new(self) dc_language.value = _language.dup dc_languages.unshift(dc_language) end super ensure dc_languages.replace(keep[:dc_languages]) end end class RSSBase < Base class << self def make(*args, &block) new(*args).make(&block) end end %w(xml_stylesheets channel image items textinput).each do |element| attr_reader element add_need_initialize_variable(element) do |object| object.send("make_#{element}") end module_eval(<<-EOC, __FILE__, __LINE__ + 1) private def setup_#{element}(feed) @#{element}.to_feed(feed) end def make_#{element} self.class::#{Utils.to_class_name(element)}.new(self) end EOC end attr_reader :feed_version alias_method(:rss_version, :feed_version) attr_accessor :version, :encoding, :standalone def initialize(feed_version) super(self) @feed_type = nil @feed_subtype = nil @feed_version = feed_version @version = "1.0" @encoding = "UTF-8" @standalone = nil end def make yield(self) to_feed end def to_feed feed = make_feed setup_xml_stylesheets(feed) setup_elements(feed) setup_other_elements(feed) feed.validate feed end private remove_method :make_xml_stylesheets def make_xml_stylesheets XMLStyleSheets.new(self) end end class XMLStyleSheets < Base def_array_element("xml_stylesheet", nil, "XMLStyleSheet") class XMLStyleSheet < Base ::RSS::XMLStyleSheet::ATTRIBUTES.each do |attribute| attr_accessor attribute add_need_initialize_variable(attribute) end def to_feed(feed) xss = ::RSS::XMLStyleSheet.new guess_type_if_need(xss) set = setup_values(xss) if set feed.xml_stylesheets << xss end end private def guess_type_if_need(xss) if @type.nil? xss.href = @href @type = xss.type end end def required_variable_names %w(href type) end end end class ChannelBase < Base include SetupDefaultDate %w(cloud categories skipDays skipHours).each do |name| def_classed_element(name) end %w(generator copyright description title).each do |name| def_classed_element(name, nil, "content") end [ ["link", "href", Proc.new {|target,| "#{target}.href = 'self'"}], ["author", "name"], ["contributor", "name"], ].each do |name, attribute, additional_setup_maker| def_classed_elements(name, attribute, &additional_setup_maker) end %w(id about language managingEditor webMaster rating docs ttl).each do |element| attr_accessor element add_need_initialize_variable(element) end %w(date lastBuildDate).each do |date_element| attr_reader date_element add_need_initialize_variable(date_element) end def date=(_date) @date = _parse_date_if_needed(_date) end def lastBuildDate=(_date) @lastBuildDate = _parse_date_if_needed(_date) end def pubDate date end def pubDate=(date) self.date = date end def updated date end def updated=(date) self.date = date end alias_method(:rights, :copyright) alias_method(:rights=, :copyright=) alias_method(:subtitle, :description) alias_method(:subtitle=, :description=) def icon image_favicon.about end def icon=(url) image_favicon.about = url end def logo maker.image.url end def logo=(url) maker.image.url = url end class SkipDaysBase < Base def_array_element("day") class DayBase < Base %w(content).each do |element| attr_accessor element add_need_initialize_variable(element) end end end class SkipHoursBase < Base def_array_element("hour") class HourBase < Base %w(content).each do |element| attr_accessor element add_need_initialize_variable(element) end end end class CloudBase < Base %w(domain port path registerProcedure protocol).each do |element| attr_accessor element add_need_initialize_variable(element) end end class CategoriesBase < Base def_array_element("category", "categories") class CategoryBase < Base %w(domain content label).each do |element| attr_accessor element add_need_initialize_variable(element) end alias_method(:term, :domain) alias_method(:term=, :domain=) alias_method(:scheme, :content) alias_method(:scheme=, :content=) end end class LinksBase < Base def_array_element("link") class LinkBase < Base %w(href rel type hreflang title length).each do |element| attr_accessor element add_need_initialize_variable(element) end end end class AuthorsBase < Base def_array_element("author") class AuthorBase < Base include AtomPersonConstructBase end end class ContributorsBase < Base def_array_element("contributor") class ContributorBase < Base include AtomPersonConstructBase end end class GeneratorBase < Base %w(uri version content).each do |element| attr_accessor element add_need_initialize_variable(element) end end class CopyrightBase < Base include AtomTextConstructBase end class DescriptionBase < Base include AtomTextConstructBase end class TitleBase < Base include AtomTextConstructBase end end class ImageBase < Base %w(title url width height description).each do |element| attr_accessor element add_need_initialize_variable(element) end def link @maker.channel.link end end class ItemsBase < Base def_array_element("item") attr_accessor :do_sort, :max_size def initialize(maker) super @do_sort = false @max_size = -1 end def normalize if @max_size >= 0 sort_if_need[0...@max_size] else sort_if_need[0..@max_size] end end private def sort_if_need if @do_sort.respond_to?(:call) @items.sort do |x, y| @do_sort.call(x, y) end elsif @do_sort @items.sort do |x, y| y <=> x end else @items end end class ItemBase < Base include SetupDefaultDate %w(guid enclosure source categories content).each do |name| def_classed_element(name) end %w(rights description title).each do |name| def_classed_element(name, nil, "content") end [ ["author", "name"], ["link", "href", Proc.new {|target,| "#{target}.href = 'alternate'"}], ["contributor", "name"], ].each do |name, attribute| def_classed_elements(name, attribute) end %w(comments id published).each do |element| attr_accessor element add_need_initialize_variable(element) end %w(date).each do |date_element| attr_reader date_element add_need_initialize_variable(date_element) end def date=(_date) @date = _parse_date_if_needed(_date) end def pubDate date end def pubDate=(date) self.date = date end def updated date end def updated=(date) self.date = date end alias_method(:summary, :description) alias_method(:summary=, :description=) def <=>(other) _date = date || dc_date _other_date = other.date || other.dc_date if _date and _other_date _date <=> _other_date elsif _date 1 elsif _other_date -1 else 0 end end class GuidBase < Base %w(isPermaLink content).each do |element| attr_accessor element add_need_initialize_variable(element) end def permanent_link? isPermaLink end def permanent_link=(bool) self.isPermaLink = bool end end class EnclosureBase < Base %w(url length type).each do |element| attr_accessor element add_need_initialize_variable(element) end end class SourceBase < Base include SetupDefaultDate %w(authors categories contributors generator icon logo rights subtitle title).each do |name| def_classed_element(name) end [ ["link", "href"], ].each do |name, attribute| def_classed_elements(name, attribute) end %w(id content).each do |element| attr_accessor element add_need_initialize_variable(element) end alias_method(:url, :link) alias_method(:url=, :link=) %w(date).each do |date_element| attr_reader date_element add_need_initialize_variable(date_element) end def date=(_date) @date = _parse_date_if_needed(_date) end def updated date end def updated=(date) self.date = date end private AuthorsBase = ChannelBase::AuthorsBase CategoriesBase = ChannelBase::CategoriesBase ContributorsBase = ChannelBase::ContributorsBase GeneratorBase = ChannelBase::GeneratorBase class IconBase < Base %w(url).each do |element| attr_accessor element add_need_initialize_variable(element) end end LinksBase = ChannelBase::LinksBase class LogoBase < Base %w(uri).each do |element| attr_accessor element add_need_initialize_variable(element) end end class RightsBase < Base include AtomTextConstructBase end class SubtitleBase < Base include AtomTextConstructBase end class TitleBase < Base include AtomTextConstructBase end end CategoriesBase = ChannelBase::CategoriesBase AuthorsBase = ChannelBase::AuthorsBase LinksBase = ChannelBase::LinksBase ContributorsBase = ChannelBase::ContributorsBase class RightsBase < Base include AtomTextConstructBase end class DescriptionBase < Base include AtomTextConstructBase end class ContentBase < Base include AtomTextConstructBase::EnsureXMLContent %w(src).each do |element| attr_accessor(element) add_need_initialize_variable(element) end def xml_content=(content) content = ensure_xml_content(content) if inline_xhtml? @xml_content = content end alias_method(:xml, :xml_content) alias_method(:xml=, :xml_content=) def inline_text? [nil, "text", "html"].include?(@type) end def inline_html? @type == "html" end def inline_xhtml? @type == "xhtml" end def inline_other? !out_of_line? and ![nil, "text", "html", "xhtml"].include?(@type) end def inline_other_text? return false if @type.nil? or out_of_line? /\Atext\//i.match(@type) ? true : false end def inline_other_xml? return false if @type.nil? or out_of_line? /[\+\/]xml\z/i.match(@type) ? true : false end def inline_other_base64? return false if @type.nil? or out_of_line? @type.include?("/") and !inline_other_text? and !inline_other_xml? end def out_of_line? not @src.nil? and @content.nil? end end class TitleBase < Base include AtomTextConstructBase end end end class TextinputBase < Base %w(title description name link).each do |element| attr_accessor element add_need_initialize_variable(element) end end end end PK!0((2.2.0/rss/maker/1.0.rbnu[require "rss/1.0" require "rss/maker/base" module RSS module Maker class RSS10 < RSSBase def initialize(feed_version="1.0") super @feed_type = "rss" end private def make_feed RDF.new(@version, @encoding, @standalone) end def setup_elements(rss) setup_channel(rss) setup_image(rss) setup_items(rss) setup_textinput(rss) end class Channel < ChannelBase include SetupDefaultLanguage def to_feed(rss) set_default_values do _not_set_required_variables = not_set_required_variables if _not_set_required_variables.empty? channel = RDF::Channel.new(@about) setup_values(channel) channel.dc_dates.clear rss.channel = channel set_parent(channel, rss) setup_items(rss) setup_image(rss) setup_textinput(rss) setup_other_elements(rss, channel) else raise NotSetError.new("maker.channel", _not_set_required_variables) end end end private def setup_items(rss) items = RDF::Channel::Items.new seq = items.Seq set_parent(items, seq) target_items = @maker.items.normalize raise NotSetError.new("maker", ["items"]) if target_items.empty? target_items.each do |item| li = RDF::Channel::Items::Seq::Li.new(item.link) seq.lis << li set_parent(li, seq) end rss.channel.items = items set_parent(rss.channel, items) end def setup_image(rss) if @maker.image.have_required_values? image = RDF::Channel::Image.new(@maker.image.url) rss.channel.image = image set_parent(image, rss.channel) end end def setup_textinput(rss) if @maker.textinput.have_required_values? textinput = RDF::Channel::Textinput.new(@maker.textinput.link) rss.channel.textinput = textinput set_parent(textinput, rss.channel) end end def required_variable_names %w(about link) end def not_set_required_variables vars = super vars << "description" unless description {|d| d.have_required_values?} vars << "title" unless title {|t| t.have_required_values?} vars end class SkipDays < SkipDaysBase def to_feed(*args) end class Day < DayBase end end class SkipHours < SkipHoursBase def to_feed(*args) end class Hour < HourBase end end class Cloud < CloudBase def to_feed(*args) end end class Categories < CategoriesBase def to_feed(*args) end class Category < CategoryBase end end class Links < LinksBase def to_feed(rss, channel) return if @links.empty? @links.first.to_feed(rss, channel) end class Link < LinkBase def to_feed(rss, channel) if have_required_values? channel.link = href else raise NotSetError.new("maker.channel.link", not_set_required_variables) end end private def required_variable_names %w(href) end end end class Authors < AuthorsBase def to_feed(rss, channel) end class Author < AuthorBase def to_feed(rss, channel) end end end class Contributors < ContributorsBase def to_feed(rss, channel) end class Contributor < ContributorBase end end class Generator < GeneratorBase def to_feed(rss, channel) end end class Copyright < CopyrightBase def to_feed(rss, channel) end end class Description < DescriptionBase def to_feed(rss, channel) channel.description = content if have_required_values? end private def required_variable_names %w(content) end end class Title < TitleBase def to_feed(rss, channel) channel.title = content if have_required_values? end private def required_variable_names %w(content) end end end class Image < ImageBase def to_feed(rss) if @url image = RDF::Image.new(@url) set = setup_values(image) if set rss.image = image set_parent(image, rss) setup_other_elements(rss, image) end end end def have_required_values? super and @maker.channel.have_required_values? end private def variables super + ["link"] end def required_variable_names %w(url title link) end end class Items < ItemsBase def to_feed(rss) if rss.channel normalize.each do |item| item.to_feed(rss) end setup_other_elements(rss, rss.items) end end class Item < ItemBase def to_feed(rss) set_default_values do item = RDF::Item.new(link) set = setup_values(item) if set item.dc_dates.clear rss.items << item set_parent(item, rss) setup_other_elements(rss, item) elsif !have_required_values? raise NotSetError.new("maker.item", not_set_required_variables) end end end private def required_variable_names %w(link) end def variables super + %w(link) end def not_set_required_variables set_default_values do vars = super vars << "title" unless title {|t| t.have_required_values?} vars end end class Guid < GuidBase def to_feed(*args) end end class Enclosure < EnclosureBase def to_feed(*args) end end class Source < SourceBase def to_feed(*args) end class Authors < AuthorsBase def to_feed(*args) end class Author < AuthorBase end end class Categories < CategoriesBase def to_feed(*args) end class Category < CategoryBase end end class Contributors < ContributorsBase def to_feed(*args) end class Contributor < ContributorBase end end class Generator < GeneratorBase def to_feed(*args) end end class Icon < IconBase def to_feed(*args) end end class Links < LinksBase def to_feed(*args) end class Link < LinkBase end end class Logo < LogoBase def to_feed(*args) end end class Rights < RightsBase def to_feed(*args) end end class Subtitle < SubtitleBase def to_feed(*args) end end class Title < TitleBase def to_feed(*args) end end end class Categories < CategoriesBase def to_feed(*args) end class Category < CategoryBase end end class Authors < AuthorsBase def to_feed(*args) end class Author < AuthorBase end end class Links < LinksBase def to_feed(*args) end class Link < LinkBase end end class Contributors < ContributorsBase def to_feed(rss, item) end class Contributor < ContributorBase end end class Rights < RightsBase def to_feed(rss, item) end end class Description < DescriptionBase def to_feed(rss, item) item.description = content if have_required_values? end private def required_variable_names %w(content) end end class Content < ContentBase def to_feed(rss, item) end end class Title < TitleBase def to_feed(rss, item) item.title = content if have_required_values? end private def required_variable_names %w(content) end end end end class Textinput < TextinputBase def to_feed(rss) if @link textinput = RDF::Textinput.new(@link) set = setup_values(textinput) if set rss.textinput = textinput set_parent(textinput, rss) setup_other_elements(rss, textinput) end end end def have_required_values? super and @maker.channel.have_required_values? end private def required_variable_names %w(title description name link) end end end add_maker("1.0", "1.0", RSS10) add_maker("rss1.0", "1.0", RSS10) end end PK!2.2.0/rss/maker/slash.rbnu[require 'rss/slash' require 'rss/maker/1.0' module RSS module Maker module SlashModel def self.append_features(klass) super ::RSS::SlashModel::ELEMENT_INFOS.each do |name, type| full_name = "#{RSS::SLASH_PREFIX}_#{name}" case type when :csv_integer klass.def_csv_element(full_name, :integer) else klass.def_other_element(full_name) end end klass.module_eval do alias_method(:slash_hit_parades, :slash_hit_parade) alias_method(:slash_hit_parades=, :slash_hit_parade=) end end end class ItemsBase class ItemBase include SlashModel end end end end PK!FF2.2.0/rss/maker/trackback.rbnu[require 'rss/trackback' require 'rss/maker/1.0' require 'rss/maker/2.0' module RSS module Maker module TrackBackModel def self.append_features(klass) super klass.def_other_element("#{RSS::TRACKBACK_PREFIX}_ping") klass.def_classed_elements("#{RSS::TRACKBACK_PREFIX}_about", "value", "TrackBackAbouts") end class TrackBackAboutsBase < Base def_array_element("about", nil, "TrackBackAbout") class TrackBackAboutBase < Base attr_accessor :value add_need_initialize_variable("value") alias_method(:resource, :value) alias_method(:resource=, :value=) alias_method(:content, :value) alias_method(:content=, :value=) def have_required_values? @value end def to_feed(feed, current) if current.respond_to?(:trackback_abouts) and have_required_values? about = current.class::TrackBackAbout.new setup_values(about) setup_other_elements(about) current.trackback_abouts << about end end end end end class ItemsBase class ItemBase; include TrackBackModel; end end makers.each do |maker| maker.module_eval(<<-EOC, __FILE__, __LINE__ + 1) class Items class Item class TrackBackAbouts < TrackBackAboutsBase class TrackBackAbout < TrackBackAboutBase end end end end EOC end end end PK!_2.2.0/rss/maker/entry.rbnu[require "rss/maker/atom" require "rss/maker/feed" module RSS module Maker module Atom class Entry < RSSBase def initialize(feed_version="1.0") super @feed_type = "atom" @feed_subtype = "entry" end private def make_feed ::RSS::Atom::Entry.new(@version, @encoding, @standalone) end def setup_elements(entry) setup_items(entry) end class Channel < ChannelBase class SkipDays < SkipDaysBase class Day < DayBase end end class SkipHours < SkipHoursBase class Hour < HourBase end end class Cloud < CloudBase end Categories = Feed::Channel::Categories Links = Feed::Channel::Links Authors = Feed::Channel::Authors Contributors = Feed::Channel::Contributors class Generator < GeneratorBase include AtomGenerator def self.not_set_name "maker.channel.generator" end end Copyright = Feed::Channel::Copyright class Description < DescriptionBase end Title = Feed::Channel::Title end class Image < ImageBase end class Items < ItemsBase def to_feed(entry) (normalize.first || Item.new(@maker)).to_feed(entry) end class Item < ItemBase def to_feed(entry) set_default_values do setup_values(entry) entry.dc_dates.clear setup_other_elements(entry) unless have_required_values? raise NotSetError.new("maker.item", not_set_required_variables) end end end private def required_variable_names %w(id updated) end def variables super + ["updated"] end def variable_is_set? super or !authors.empty? end def not_set_required_variables set_default_values do vars = super if authors.all? {|author| !author.have_required_values?} vars << "author" end vars << "title" unless title {|t| t.have_required_values?} vars end end def _set_default_values keep = { :authors => authors.to_a.dup, :contributors => contributors.to_a.dup, :categories => categories.to_a.dup, :id => id, :links => links.to_a.dup, :rights => @rights, :title => @title, :updated => updated, } authors.replace(@maker.channel.authors) if keep[:authors].empty? if keep[:contributors].empty? contributors.replace(@maker.channel.contributors) end if keep[:categories].empty? categories.replace(@maker.channel.categories) end self.id ||= link || @maker.channel.id links.replace(@maker.channel.links) if keep[:links].empty? unless keep[:rights].variable_is_set? @maker.channel.rights {|r| @rights = r} end unless keep[:title].variable_is_set? @maker.channel.title {|t| @title = t} end self.updated ||= @maker.channel.updated super ensure authors.replace(keep[:authors]) contributors.replace(keep[:contributors]) categories.replace(keep[:categories]) links.replace(keep[:links]) self.id = keep[:id] @rights = keep[:rights] @title = keep[:title] self.updated = keep[:updated] end Guid = Feed::Items::Item::Guid Enclosure = Feed::Items::Item::Enclosure Source = Feed::Items::Item::Source Categories = Feed::Items::Item::Categories Authors = Feed::Items::Item::Authors Contributors = Feed::Items::Item::Contributors Links = Feed::Items::Item::Links Rights = Feed::Items::Item::Rights Description = Feed::Items::Item::Description Title = Feed::Items::Item::Title Content = Feed::Items::Item::Content end end class Textinput < TextinputBase end end end add_maker("atom:entry", "1.0", Atom::Entry) add_maker("atom1.0:entry", "1.0", Atom::Entry) end end PK!ë2.2.0/rss/maker/content.rbnu[require 'rss/content' require 'rss/maker/1.0' require 'rss/maker/2.0' module RSS module Maker module ContentModel def self.append_features(klass) super ::RSS::ContentModel::ELEMENTS.each do |name| klass.def_other_element(name) end end end class ItemsBase class ItemBase; include ContentModel; end end end end PK!DG`2.2.0/rss/maker/atom.rbnu[require "rss/atom" require "rss/maker/base" module RSS module Maker module AtomPersons module_function def def_atom_persons(klass, name, maker_name, plural=nil) plural ||= "#{name}s" klass_name = Utils.to_class_name(name) plural_klass_name = Utils.to_class_name(plural) klass.class_eval(<<-EOC, __FILE__, __LINE__ + 1) class #{plural_klass_name} < #{plural_klass_name}Base class #{klass_name} < #{klass_name}Base def to_feed(feed, current) #{name} = feed.class::#{klass_name}.new set = setup_values(#{name}) unless set raise NotSetError.new(#{maker_name.dump}, not_set_required_variables) end current.#{plural} << #{name} set_parent(#{name}, current) setup_other_elements(#{name}) end private def required_variable_names %w(name) end end end EOC end end module AtomTextConstruct class << self def def_atom_text_construct(klass, name, maker_name, klass_name=nil, atom_klass_name=nil) klass_name ||= Utils.to_class_name(name) atom_klass_name ||= Utils.to_class_name(name) klass.class_eval(<<-EOC, __FILE__, __LINE__ + 1) class #{klass_name} < #{klass_name}Base include #{self.name} def to_feed(feed, current) #{name} = current.class::#{atom_klass_name}.new if setup_values(#{name}) current.#{name} = #{name} set_parent(#{name}, current) setup_other_elements(feed) elsif variable_is_set? raise NotSetError.new(#{maker_name.dump}, not_set_required_variables) end end end EOC end end private def required_variable_names if type == "xhtml" %w(xml_content) else %w(content) end end def variables if type == "xhtml" super + %w(xhtml) else super end end end module AtomCategory def to_feed(feed, current) category = feed.class::Category.new set = setup_values(category) if set current.categories << category set_parent(category, current) setup_other_elements(feed) else raise NotSetError.new(self.class.not_set_name, not_set_required_variables) end end private def required_variable_names %w(term) end def variables super + ["term", "scheme"] end end module AtomLink def to_feed(feed, current) link = feed.class::Link.new set = setup_values(link) if set current.links << link set_parent(link, current) setup_other_elements(feed) else raise NotSetError.new(self.class.not_set_name, not_set_required_variables) end end private def required_variable_names %w(href) end end module AtomGenerator def to_feed(feed, current) generator = current.class::Generator.new if setup_values(generator) current.generator = generator set_parent(generator, current) setup_other_elements(feed) elsif variable_is_set? raise NotSetError.new(self.class.not_set_name, not_set_required_variables) end end private def required_variable_names %w(content) end end module AtomLogo def to_feed(feed, current) logo = current.class::Logo.new class << logo alias_method(:uri=, :content=) end set = setup_values(logo) class << logo remove_method(:uri=) end if set current.logo = logo set_parent(logo, current) setup_other_elements(feed) elsif variable_is_set? raise NotSetError.new(self.class.not_set_name, not_set_required_variables) end end private def required_variable_names %w(uri) end end end end PK!^s2.2.0/rss/maker/2.0.rbnu[require "rss/2.0" require "rss/maker/0.9" module RSS module Maker class RSS20 < RSS09 def initialize(feed_version="2.0") super end class Channel < RSS09::Channel private def required_variable_names %w(link) end class SkipDays < RSS09::Channel::SkipDays class Day < RSS09::Channel::SkipDays::Day end end class SkipHours < RSS09::Channel::SkipHours class Hour < RSS09::Channel::SkipHours::Hour end end class Cloud < RSS09::Channel::Cloud def to_feed(rss, channel) cloud = Rss::Channel::Cloud.new set = setup_values(cloud) if set channel.cloud = cloud set_parent(cloud, channel) setup_other_elements(rss, cloud) end end private def required_variable_names %w(domain port path registerProcedure protocol) end end class Categories < RSS09::Channel::Categories def to_feed(rss, channel) @categories.each do |category| category.to_feed(rss, channel) end end class Category < RSS09::Channel::Categories::Category def to_feed(rss, channel) category = Rss::Channel::Category.new set = setup_values(category) if set channel.categories << category set_parent(category, channel) setup_other_elements(rss, category) end end private def required_variable_names %w(content) end end end class Generator < GeneratorBase def to_feed(rss, channel) channel.generator = content end private def required_variable_names %w(content) end end end class Image < RSS09::Image private def required_element? false end end class Items < RSS09::Items class Item < RSS09::Items::Item private def required_variable_names [] end def not_set_required_variables vars = super if !title {|t| t.have_required_values?} and !description {|d| d.have_required_values?} vars << "title or description" end vars end def variables super + ["pubDate"] end class Guid < RSS09::Items::Item::Guid def to_feed(rss, item) guid = Rss::Channel::Item::Guid.new set = setup_values(guid) if set item.guid = guid set_parent(guid, item) setup_other_elements(rss, guid) end end private def required_variable_names %w(content) end end class Enclosure < RSS09::Items::Item::Enclosure def to_feed(rss, item) enclosure = Rss::Channel::Item::Enclosure.new set = setup_values(enclosure) if set item.enclosure = enclosure set_parent(enclosure, item) setup_other_elements(rss, enclosure) end end private def required_variable_names %w(url length type) end end class Source < RSS09::Items::Item::Source def to_feed(rss, item) source = Rss::Channel::Item::Source.new set = setup_values(source) if set item.source = source set_parent(source, item) setup_other_elements(rss, source) end end private def required_variable_names %w(url content) end class Links < RSS09::Items::Item::Source::Links def to_feed(rss, source) return if @links.empty? @links.first.to_feed(rss, source) end class Link < RSS09::Items::Item::Source::Links::Link def to_feed(rss, source) source.url = href end end end end class Categories < RSS09::Items::Item::Categories def to_feed(rss, item) @categories.each do |category| category.to_feed(rss, item) end end class Category < RSS09::Items::Item::Categories::Category def to_feed(rss, item) category = Rss::Channel::Item::Category.new set = setup_values(category) if set item.categories << category set_parent(category, item) setup_other_elements(rss) end end private def required_variable_names %w(content) end end end class Authors < RSS09::Items::Item::Authors def to_feed(rss, item) return if @authors.empty? @authors.first.to_feed(rss, item) end class Author < RSS09::Items::Item::Authors::Author def to_feed(rss, item) item.author = name end end end end end class Textinput < RSS09::Textinput end end add_maker("2.0", "2.0", RSS20) add_maker("rss2.0", "2.0", RSS20) end end PK!`l&l&2.2.0/rss/1.0.rbnu[require "rss/parser" module RSS ## # = RSS 1.0 support # # RSS has three different versions. This module contains support for version # 1.0[http://web.resource.org/rss/1.0/] # # == Producing RSS 1.0 # # Producing our own RSS feeds is easy as well. Let's make a very basic feed: # # require "rss" # # rss = RSS::Maker.make("1.0") do |maker| # maker.channel.language = "en" # maker.channel.author = "matz" # maker.channel.about = "About my feed." # maker.channel.updated = Time.now.to_s # maker.channel.link = "http://www.ruby-lang.org/en/feeds/news.rss" # maker.channel.title = "Example Feed" # maker.channel.description = "A longer description of my feed." # maker.items.new_item do |item| # item.link = "http://www.ruby-lang.org/en/news/2010/12/25/ruby-1-9-2-p136-is-released/" # item.title = "Ruby 1.9.2-p136 is released" # item.updated = Time.now.to_s # end # end # # puts rss # # As you can see, this is a very Builder-like DSL. This code will spit out an # RSS 1.0 feed with one item. If we needed a second item, we'd make another # block with maker.items.new_item and build a second one. module RSS10 NSPOOL = {} ELEMENTS = [] def self.append_features(klass) super klass.install_must_call_validator('', ::RSS::URI) end end class RDF < Element include RSS10 include RootElementMixin class << self def required_uri URI end end @tag_name = 'RDF' PREFIX = 'rdf' URI = "http://www.w3.org/1999/02/22-rdf-syntax-ns#" install_ns('', ::RSS::URI) install_ns(PREFIX, URI) [ ["channel", nil], ["image", "?"], ["item", "+", :children], ["textinput", "?"], ].each do |tag, occurs, type| type ||= :child __send__("install_have_#{type}_element", tag, ::RSS::URI, occurs) end alias_method(:rss_version, :feed_version) def initialize(version=nil, encoding=nil, standalone=nil) super('1.0', version, encoding, standalone) @feed_type = "rss" end def full_name tag_name_with_prefix(PREFIX) end class Li < Element include RSS10 class << self def required_uri URI end end [ ["resource", [URI, ""], true] ].each do |name, uri, required| install_get_attribute(name, uri, required) end def initialize(*args) if Utils.element_initialize_arguments?(args) super else super() self.resource = args[0] end end def full_name tag_name_with_prefix(PREFIX) end end class Seq < Element include RSS10 Li = ::RSS::RDF::Li class << self def required_uri URI end end @tag_name = 'Seq' install_have_children_element("li", URI, "*") install_must_call_validator('rdf', ::RSS::RDF::URI) def initialize(*args) if Utils.element_initialize_arguments?(args) super else super() @li = args[0] if args[0] end end def full_name tag_name_with_prefix(PREFIX) end def setup_maker(target) lis.each do |li| target << li.resource end end end class Bag < Element include RSS10 Li = ::RSS::RDF::Li class << self def required_uri URI end end @tag_name = 'Bag' install_have_children_element("li", URI, "*") install_must_call_validator('rdf', URI) def initialize(*args) if Utils.element_initialize_arguments?(args) super else super() @li = args[0] if args[0] end end def full_name tag_name_with_prefix(PREFIX) end def setup_maker(target) lis.each do |li| target << li.resource end end end class Channel < Element include RSS10 class << self def required_uri ::RSS::URI end end [ ["about", URI, true] ].each do |name, uri, required| install_get_attribute(name, uri, required, nil, nil, "#{PREFIX}:#{name}") end [ ['title', nil, :text], ['link', nil, :text], ['description', nil, :text], ['image', '?', :have_child], ['items', nil, :have_child], ['textinput', '?', :have_child], ].each do |tag, occurs, type| __send__("install_#{type}_element", tag, ::RSS::URI, occurs) end def initialize(*args) if Utils.element_initialize_arguments?(args) super else super() self.about = args[0] end end private def maker_target(maker) maker.channel end def setup_maker_attributes(channel) channel.about = about end class Image < Element include RSS10 class << self def required_uri ::RSS::URI end end [ ["resource", URI, true] ].each do |name, uri, required| install_get_attribute(name, uri, required, nil, nil, "#{PREFIX}:#{name}") end def initialize(*args) if Utils.element_initialize_arguments?(args) super else super() self.resource = args[0] end end end class Textinput < Element include RSS10 class << self def required_uri ::RSS::URI end end [ ["resource", URI, true] ].each do |name, uri, required| install_get_attribute(name, uri, required, nil, nil, "#{PREFIX}:#{name}") end def initialize(*args) if Utils.element_initialize_arguments?(args) super else super() self.resource = args[0] end end end class Items < Element include RSS10 Seq = ::RSS::RDF::Seq class << self def required_uri ::RSS::URI end end install_have_child_element("Seq", URI, nil) install_must_call_validator('rdf', URI) def initialize(*args) if Utils.element_initialize_arguments?(args) super else super() self.Seq = args[0] end self.Seq ||= Seq.new end def resources if @Seq @Seq.lis.collect do |li| li.resource end else [] end end end end class Image < Element include RSS10 class << self def required_uri ::RSS::URI end end [ ["about", URI, true] ].each do |name, uri, required| install_get_attribute(name, uri, required, nil, nil, "#{PREFIX}:#{name}") end %w(title url link).each do |name| install_text_element(name, ::RSS::URI, nil) end def initialize(*args) if Utils.element_initialize_arguments?(args) super else super() self.about = args[0] end end private def maker_target(maker) maker.image end end class Item < Element include RSS10 class << self def required_uri ::RSS::URI end end [ ["about", URI, true] ].each do |name, uri, required| install_get_attribute(name, uri, required, nil, nil, "#{PREFIX}:#{name}") end [ ["title", nil], ["link", nil], ["description", "?"], ].each do |tag, occurs| install_text_element(tag, ::RSS::URI, occurs) end def initialize(*args) if Utils.element_initialize_arguments?(args) super else super() self.about = args[0] end end private def maker_target(items) if items.respond_to?("items") # For backward compatibility items = items.items end items.new_item end end class Textinput < Element include RSS10 class << self def required_uri ::RSS::URI end end [ ["about", URI, true] ].each do |name, uri, required| install_get_attribute(name, uri, required, nil, nil, "#{PREFIX}:#{name}") end %w(title description name link).each do |name| install_text_element(name, ::RSS::URI, nil) end def initialize(*args) if Utils.element_initialize_arguments?(args) super else super() self.about = args[0] end end private def maker_target(maker) maker.textinput end end end RSS10::ELEMENTS.each do |name| BaseListener.install_get_text_element(URI, name, name) end module ListenerMixin private def initial_start_RDF(tag_name, prefix, attrs, ns) check_ns(tag_name, prefix, ns, RDF::URI, false) @rss = RDF.new(@version, @encoding, @standalone) @rss.do_validate = @do_validate @rss.xml_stylesheets = @xml_stylesheets @last_element = @rss pr = Proc.new do |text, tags| @rss.validate_for_stream(tags, @ignore_unknown_element) if @do_validate end @proc_stack.push(pr) end end end PK! h 112.2.0/rss/slash.rbnu[require 'rss/1.0' module RSS # The prefix for the Slash XML namespace. SLASH_PREFIX = 'slash' # The URI of the Slash specification. SLASH_URI = "http://purl.org/rss/1.0/modules/slash/" RDF.install_ns(SLASH_PREFIX, SLASH_URI) module SlashModel extend BaseModel ELEMENT_INFOS = \ [ ["section"], ["department"], ["comments", :positive_integer], ["hit_parade", :csv_integer], ] class << self def append_features(klass) super return if klass.instance_of?(Module) klass.install_must_call_validator(SLASH_PREFIX, SLASH_URI) ELEMENT_INFOS.each do |name, type, *additional_infos| full_name = "#{SLASH_PREFIX}_#{name}" klass.install_text_element(full_name, SLASH_URI, "?", full_name, type, name) end klass.module_eval do alias_method(:slash_hit_parades, :slash_hit_parade) undef_method(:slash_hit_parade) alias_method(:slash_hit_parade, :slash_hit_parade_content) end end end end class RDF class Item; include SlashModel; end end SlashModel::ELEMENT_INFOS.each do |name, type| accessor_base = "#{SLASH_PREFIX}_#{name}" BaseListener.install_get_text_element(SLASH_URI, name, accessor_base) end end PK!o2.2.0/rss/trackback.rbnu[# This file contains the implementation of trackbacks. It is entirely internal # and not useful to outside developers. require 'rss/1.0' require 'rss/2.0' module RSS # :nodoc: all TRACKBACK_PREFIX = 'trackback' TRACKBACK_URI = 'http://madskills.com/public/xml/rss/module/trackback/' RDF.install_ns(TRACKBACK_PREFIX, TRACKBACK_URI) Rss.install_ns(TRACKBACK_PREFIX, TRACKBACK_URI) module TrackBackUtils private def trackback_validate(ignore_unknown_element, tags, uri) return if tags.nil? if tags.find {|tag| tag == "about"} and !tags.find {|tag| tag == "ping"} raise MissingTagError.new("#{TRACKBACK_PREFIX}:ping", tag_name) end end end module BaseTrackBackModel ELEMENTS = %w(ping about) def append_features(klass) super unless klass.class == Module klass.module_eval {include TrackBackUtils} klass.install_must_call_validator(TRACKBACK_PREFIX, TRACKBACK_URI) %w(ping).each do |name| var_name = "#{TRACKBACK_PREFIX}_#{name}" klass_name = "TrackBack#{Utils.to_class_name(name)}" klass.install_have_child_element(name, TRACKBACK_URI, "?", var_name) klass.module_eval(<<-EOC, __FILE__, __LINE__) remove_method :#{var_name} def #{var_name} @#{var_name} and @#{var_name}.value end remove_method :#{var_name}= def #{var_name}=(value) @#{var_name} = Utils.new_with_value_if_need(#{klass_name}, value) end EOC end [%w(about s)].each do |name, postfix| var_name = "#{TRACKBACK_PREFIX}_#{name}" klass_name = "TrackBack#{Utils.to_class_name(name)}" klass.install_have_children_element(name, TRACKBACK_URI, "*", var_name) klass.module_eval(<<-EOC, __FILE__, __LINE__) remove_method :#{var_name} def #{var_name}(*args) if args.empty? @#{var_name}.first and @#{var_name}.first.value else ret = @#{var_name}.__send__("[]", *args) if ret.is_a?(Array) ret.collect {|x| x.value} else ret.value end end end remove_method :#{var_name}= remove_method :set_#{var_name} def #{var_name}=(*args) if args.size == 1 item = Utils.new_with_value_if_need(#{klass_name}, args[0]) @#{var_name}.push(item) else new_val = args.last if new_val.is_a?(Array) new_val = new_value.collect do |val| Utils.new_with_value_if_need(#{klass_name}, val) end else new_val = Utils.new_with_value_if_need(#{klass_name}, new_val) end @#{var_name}.__send__("[]=", *(args[0..-2] + [new_val])) end end alias set_#{var_name} #{var_name}= EOC end end end end module TrackBackModel10 extend BaseModel extend BaseTrackBackModel class TrackBackPing < Element include RSS10 class << self def required_prefix TRACKBACK_PREFIX end def required_uri TRACKBACK_URI end end @tag_name = "ping" [ ["resource", ::RSS::RDF::URI, true] ].each do |name, uri, required| install_get_attribute(name, uri, required, nil, nil, "#{::RSS::RDF::PREFIX}:#{name}") end alias_method(:value, :resource) alias_method(:value=, :resource=) def initialize(*args) if Utils.element_initialize_arguments?(args) super else super() self.resource = args[0] end end def full_name tag_name_with_prefix(TRACKBACK_PREFIX) end end class TrackBackAbout < Element include RSS10 class << self def required_prefix TRACKBACK_PREFIX end def required_uri TRACKBACK_URI end end @tag_name = "about" [ ["resource", ::RSS::RDF::URI, true] ].each do |name, uri, required| install_get_attribute(name, uri, required, nil, nil, "#{::RSS::RDF::PREFIX}:#{name}") end alias_method(:value, :resource) alias_method(:value=, :resource=) def initialize(*args) if Utils.element_initialize_arguments?(args) super else super() self.resource = args[0] end end def full_name tag_name_with_prefix(TRACKBACK_PREFIX) end private def maker_target(abouts) abouts.new_about end def setup_maker_attributes(about) about.resource = self.resource end end end module TrackBackModel20 extend BaseModel extend BaseTrackBackModel class TrackBackPing < Element include RSS09 @tag_name = "ping" content_setup class << self def required_prefix TRACKBACK_PREFIX end def required_uri TRACKBACK_URI end end alias_method(:value, :content) alias_method(:value=, :content=) def initialize(*args) if Utils.element_initialize_arguments?(args) super else super() self.content = args[0] end end def full_name tag_name_with_prefix(TRACKBACK_PREFIX) end end class TrackBackAbout < Element include RSS09 @tag_name = "about" content_setup class << self def required_prefix TRACKBACK_PREFIX end def required_uri TRACKBACK_URI end end alias_method(:value, :content) alias_method(:value=, :content=) def initialize(*args) if Utils.element_initialize_arguments?(args) super else super() self.content = args[0] end end def full_name tag_name_with_prefix(TRACKBACK_PREFIX) end end end class RDF class Item; include TrackBackModel10; end end class Rss class Channel class Item; include TrackBackModel20; end end end BaseTrackBackModel::ELEMENTS.each do |name| class_name = Utils.to_class_name(name) BaseListener.install_class_name(TRACKBACK_URI, name, "TrackBack#{class_name}") end BaseTrackBackModel::ELEMENTS.collect! {|name| "#{TRACKBACK_PREFIX}_#{name}"} end PK!@2.2.0/rss/rss.rbnu[require "time" class Time class << self unless respond_to?(:w3cdtf) # This method converts a W3CDTF string date/time format to Time object. # # The W3CDTF format is defined here: http://www.w3.org/TR/NOTE-datetime # # Time.w3cdtf('2003-02-15T13:50:05-05:00') # # => 2003-02-15 10:50:05 -0800 # Time.w3cdtf('2003-02-15T13:50:05-05:00').class # # => Time def w3cdtf(date) if /\A\s* (-?\d+)-(\d\d)-(\d\d) (?:T (\d\d):(\d\d)(?::(\d\d))? (\.\d+)? (Z|[+-]\d\d:\d\d)?)? \s*\z/ix =~ date and (($5 and $8) or (!$5 and !$8)) datetime = [$1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, $6.to_i] usec = 0 usec = $7.to_f * 1000000 if $7 zone = $8 if zone off = zone_offset(zone, datetime[0]) datetime = apply_offset(*(datetime + [off])) datetime << usec time = Time.utc(*datetime) force_zone!(time, zone, off) time else datetime << usec Time.local(*datetime) end else raise ArgumentError.new("invalid date: #{date.inspect}") end end end end unless method_defined?(:w3cdtf) # This method converts a Time object to a String. The String contains the # time in W3CDTF date/time format. # # The W3CDTF format is defined here: http://www.w3.org/TR/NOTE-datetime # # Time.now.w3cdtf # # => "2013-08-26T14:12:10.817124-07:00" def w3cdtf if usec.zero? fraction_digits = 0 else fraction_digits = strftime('%6N').index(/0*\z/) end xmlschema(fraction_digits) end end end require "English" require "rss/utils" require "rss/converter" require "rss/xml-stylesheet" module RSS # The current version of RSS VERSION = "0.2.7" # The URI of the RSS 1.0 specification URI = "http://purl.org/rss/1.0/" DEBUG = false # :nodoc: # The basic error all other RSS errors stem from. Rescue this error if you # want to handle any given RSS error and you don't care about the details. class Error < StandardError; end # RSS, being an XML-based format, has namespace support. If two namespaces are # declared with the same name, an OverlappedPrefixError will be raised. class OverlappedPrefixError < Error attr_reader :prefix def initialize(prefix) @prefix = prefix end end # The InvalidRSSError error is the base class for a variety of errors # related to a poorly-formed RSS feed. Rescue this error if you only # care that a file could be invalid, but don't care how it is invalid. class InvalidRSSError < Error; end # Since RSS is based on XML, it must have opening and closing tags that # match. If they don't, a MissingTagError will be raised. class MissingTagError < InvalidRSSError attr_reader :tag, :parent def initialize(tag, parent) @tag, @parent = tag, parent super("tag <#{tag}> is missing in tag <#{parent}>") end end # Some tags must only exist a specific number of times in a given RSS feed. # If a feed has too many occurrences of one of these tags, a TooMuchTagError # will be raised. class TooMuchTagError < InvalidRSSError attr_reader :tag, :parent def initialize(tag, parent) @tag, @parent = tag, parent super("tag <#{tag}> is too much in tag <#{parent}>") end end # Certain attributes are required on specific tags in an RSS feed. If a feed # is missing one of these attributes, a MissingAttributeError is raised. class MissingAttributeError < InvalidRSSError attr_reader :tag, :attribute def initialize(tag, attribute) @tag, @attribute = tag, attribute super("attribute <#{attribute}> is missing in tag <#{tag}>") end end # RSS does not allow for free-form tag names, so if an RSS feed contains a # tag that we don't know about, an UnknownTagError is raised. class UnknownTagError < InvalidRSSError attr_reader :tag, :uri def initialize(tag, uri) @tag, @uri = tag, uri super("tag <#{tag}> is unknown in namespace specified by uri <#{uri}>") end end # Raised when an unexpected tag is encountered. class NotExpectedTagError < InvalidRSSError attr_reader :tag, :uri, :parent def initialize(tag, uri, parent) @tag, @uri, @parent = tag, uri, parent super("tag <{#{uri}}#{tag}> is not expected in tag <#{parent}>") end end # For backward compatibility :X NotExceptedTagError = NotExpectedTagError # :nodoc: # Attributes are in key-value form, and if there's no value provided for an # attribute, a NotAvailableValueError will be raised. class NotAvailableValueError < InvalidRSSError attr_reader :tag, :value, :attribute def initialize(tag, value, attribute=nil) @tag, @value, @attribute = tag, value, attribute message = "value <#{value}> of " message << "attribute <#{attribute}> of " if attribute message << "tag <#{tag}> is not available." super(message) end end # Raised when an unknown conversion error occurs. class UnknownConversionMethodError < Error attr_reader :to, :from def initialize(to, from) @to = to @from = from super("can't convert to #{to} from #{from}.") end end # for backward compatibility UnknownConvertMethod = UnknownConversionMethodError # :nodoc: # Raised when a conversion failure occurs. class ConversionError < Error attr_reader :string, :to, :from def initialize(string, to, from) @string = string @to = to @from = from super("can't convert #{@string} to #{to} from #{from}.") end end # Raised when a required variable is not set. class NotSetError < Error attr_reader :name, :variables def initialize(name, variables) @name = name @variables = variables super("required variables of #{@name} are not set: #{@variables.join(', ')}") end end # Raised when a RSS::Maker attempts to use an unknown maker. class UnsupportedMakerVersionError < Error attr_reader :version def initialize(version) @version = version super("Maker doesn't support version: #{@version}") end end module BaseModel include Utils def install_have_child_element(tag_name, uri, occurs, name=nil, type=nil) name ||= tag_name add_need_initialize_variable(name) install_model(tag_name, uri, occurs, name) writer_type, reader_type = type def_corresponded_attr_writer name, writer_type def_corresponded_attr_reader name, reader_type install_element(name) do |n, elem_name| <<-EOC if @#{n} "\#{@#{n}.to_s(need_convert, indent)}" else '' end EOC end end alias_method(:install_have_attribute_element, :install_have_child_element) def install_have_children_element(tag_name, uri, occurs, name=nil, plural_name=nil) name ||= tag_name plural_name ||= "#{name}s" add_have_children_element(name, plural_name) add_plural_form(name, plural_name) install_model(tag_name, uri, occurs, plural_name, true) def_children_accessor(name, plural_name) install_element(name, "s") do |n, elem_name| <<-EOC rv = [] @#{n}.each do |x| value = "\#{x.to_s(need_convert, indent)}" rv << value if /\\A\\s*\\z/ !~ value end rv.join("\n") EOC end end def install_text_element(tag_name, uri, occurs, name=nil, type=nil, disp_name=nil) name ||= tag_name disp_name ||= name self::ELEMENTS << name unless self::ELEMENTS.include?(name) add_need_initialize_variable(name) install_model(tag_name, uri, occurs, name) def_corresponded_attr_writer(name, type, disp_name) def_corresponded_attr_reader(name, type || :convert) install_element(name) do |n, elem_name| <<-EOC if respond_to?(:#{n}_content) content = #{n}_content else content = @#{n} end if content rv = "\#{indent}<#{elem_name}>" value = html_escape(content) if need_convert rv << convert(value) else rv << value end rv << "" rv else '' end EOC end end def install_date_element(tag_name, uri, occurs, name=nil, type=nil, disp_name=nil) name ||= tag_name type ||= :w3cdtf disp_name ||= name self::ELEMENTS << name add_need_initialize_variable(name) install_model(tag_name, uri, occurs, name) # accessor convert_attr_reader name date_writer(name, type, disp_name) install_element(name) do |n, elem_name| <<-EOC if @#{n} rv = "\#{indent}<#{elem_name}>" value = html_escape(@#{n}.#{type}) if need_convert rv << convert(value) else rv << value end rv << "" rv else '' end EOC end end private def install_element(name, postfix="") elem_name = name.sub('_', ':') method_name = "#{name}_element#{postfix}" add_to_element_method(method_name) module_eval(<<-EOC, *get_file_and_line_from_caller(2)) def #{method_name}(need_convert=true, indent='') #{yield(name, elem_name)} end private :#{method_name} EOC end def inherit_convert_attr_reader(*attrs) attrs.each do |attr| attr = attr.id2name if attr.kind_of?(Integer) module_eval(<<-EOC, *get_file_and_line_from_caller(2)) def #{attr}_without_inherit convert(@#{attr}) end def #{attr} if @#{attr} #{attr}_without_inherit elsif @parent @parent.#{attr} else nil end end EOC end end def uri_convert_attr_reader(*attrs) attrs.each do |attr| attr = attr.id2name if attr.kind_of?(Integer) module_eval(<<-EOC, *get_file_and_line_from_caller(2)) def #{attr}_without_base convert(@#{attr}) end def #{attr} value = #{attr}_without_base return nil if value.nil? if /\\A[a-z][a-z0-9+.\\-]*:/i =~ value value else "\#{base}\#{value}" end end EOC end end def convert_attr_reader(*attrs) attrs.each do |attr| attr = attr.id2name if attr.kind_of?(Integer) module_eval(<<-EOC, *get_file_and_line_from_caller(2)) def #{attr} convert(@#{attr}) end EOC end end def yes_clean_other_attr_reader(*attrs) attrs.each do |attr| attr = attr.id2name if attr.kind_of?(Integer) module_eval(<<-EOC, __FILE__, __LINE__ + 1) attr_reader(:#{attr}) def #{attr}? YesCleanOther.parse(@#{attr}) end EOC end end def yes_other_attr_reader(*attrs) attrs.each do |attr| attr = attr.id2name if attr.kind_of?(Integer) module_eval(<<-EOC, __FILE__, __LINE__ + 1) attr_reader(:#{attr}) def #{attr}? Utils::YesOther.parse(@#{attr}) end EOC end end def csv_attr_reader(*attrs) separator = nil if attrs.last.is_a?(Hash) options = attrs.pop separator = options[:separator] end separator ||= ", " attrs.each do |attr| attr = attr.id2name if attr.kind_of?(Integer) module_eval(<<-EOC, __FILE__, __LINE__ + 1) attr_reader(:#{attr}) def #{attr}_content if @#{attr}.nil? @#{attr} else @#{attr}.join(#{separator.dump}) end end EOC end end def date_writer(name, type, disp_name=name) module_eval(<<-EOC, *get_file_and_line_from_caller(2)) def #{name}=(new_value) if new_value.nil? @#{name} = new_value elsif new_value.kind_of?(Time) @#{name} = new_value.dup else if @do_validate begin @#{name} = Time.__send__('#{type}', new_value) rescue ArgumentError raise NotAvailableValueError.new('#{disp_name}', new_value) end else @#{name} = nil if /\\A\\s*\\z/ !~ new_value.to_s begin unless Date._parse(new_value, false).empty? @#{name} = Time.parse(new_value) end rescue ArgumentError end end end end # Is it need? if @#{name} class << @#{name} undef_method(:to_s) alias_method(:to_s, :#{type}) end end end EOC end def integer_writer(name, disp_name=name) module_eval(<<-EOC, *get_file_and_line_from_caller(2)) def #{name}=(new_value) if new_value.nil? @#{name} = new_value else if @do_validate begin @#{name} = Integer(new_value) rescue ArgumentError raise NotAvailableValueError.new('#{disp_name}', new_value) end else @#{name} = new_value.to_i end end end EOC end def positive_integer_writer(name, disp_name=name) module_eval(<<-EOC, *get_file_and_line_from_caller(2)) def #{name}=(new_value) if new_value.nil? @#{name} = new_value else if @do_validate begin tmp = Integer(new_value) raise ArgumentError if tmp <= 0 @#{name} = tmp rescue ArgumentError raise NotAvailableValueError.new('#{disp_name}', new_value) end else @#{name} = new_value.to_i end end end EOC end def boolean_writer(name, disp_name=name) module_eval(<<-EOC, *get_file_and_line_from_caller(2)) def #{name}=(new_value) if new_value.nil? @#{name} = new_value else if @do_validate and ![true, false, "true", "false"].include?(new_value) raise NotAvailableValueError.new('#{disp_name}', new_value) end if [true, false].include?(new_value) @#{name} = new_value else @#{name} = new_value == "true" end end end EOC end def text_type_writer(name, disp_name=name) module_eval(<<-EOC, *get_file_and_line_from_caller(2)) def #{name}=(new_value) if @do_validate and !["text", "html", "xhtml", nil].include?(new_value) raise NotAvailableValueError.new('#{disp_name}', new_value) end @#{name} = new_value end EOC end def content_writer(name, disp_name=name) klass_name = "self.class::#{Utils.to_class_name(name)}" module_eval(<<-EOC, *get_file_and_line_from_caller(2)) def #{name}=(new_value) if new_value.is_a?(#{klass_name}) @#{name} = new_value else @#{name} = #{klass_name}.new @#{name}.content = new_value end end EOC end def yes_clean_other_writer(name, disp_name=name) module_eval(<<-EOC, __FILE__, __LINE__ + 1) def #{name}=(value) value = (value ? "yes" : "no") if [true, false].include?(value) @#{name} = value end EOC end def yes_other_writer(name, disp_name=name) module_eval(<<-EOC, __FILE__, __LINE__ + 1) def #{name}=(new_value) if [true, false].include?(new_value) new_value = new_value ? "yes" : "no" end @#{name} = new_value end EOC end def csv_writer(name, disp_name=name) module_eval(<<-EOC, __FILE__, __LINE__ + 1) def #{name}=(new_value) @#{name} = Utils::CSV.parse(new_value) end EOC end def csv_integer_writer(name, disp_name=name) module_eval(<<-EOC, __FILE__, __LINE__ + 1) def #{name}=(new_value) @#{name} = Utils::CSV.parse(new_value) {|v| Integer(v)} end EOC end def def_children_accessor(accessor_name, plural_name) module_eval(<<-EOC, *get_file_and_line_from_caller(2)) def #{plural_name} @#{accessor_name} end def #{accessor_name}(*args) if args.empty? @#{accessor_name}.first else @#{accessor_name}[*args] end end def #{accessor_name}=(*args) receiver = self.class.name warn("Warning:\#{caller.first.sub(/:in `.*'\z/, '')}: " \ "Don't use `\#{receiver}\##{accessor_name} = XXX'/" \ "`\#{receiver}\#set_#{accessor_name}(XXX)'. " \ "Those APIs are not sense of Ruby. " \ "Use `\#{receiver}\##{plural_name} << XXX' instead of them.") if args.size == 1 @#{accessor_name}.push(args[0]) else @#{accessor_name}.__send__("[]=", *args) end end alias_method(:set_#{accessor_name}, :#{accessor_name}=) EOC end end module SetupMaker def setup_maker(maker) target = maker_target(maker) unless target.nil? setup_maker_attributes(target) setup_maker_element(target) setup_maker_elements(target) end end private def maker_target(maker) nil end def setup_maker_attributes(target) end def setup_maker_element(target) self.class.need_initialize_variables.each do |var| value = __send__(var) next if value.nil? if value.respond_to?("setup_maker") and !not_need_to_call_setup_maker_variables.include?(var) value.setup_maker(target) else setter = "#{var}=" if target.respond_to?(setter) target.__send__(setter, value) end end end end def not_need_to_call_setup_maker_variables [] end def setup_maker_elements(parent) self.class.have_children_elements.each do |name, plural_name| if parent.respond_to?(plural_name) target = parent.__send__(plural_name) __send__(plural_name).each do |elem| elem.setup_maker(target) end end end end end class Element extend BaseModel include Utils extend Utils::InheritedReader include SetupMaker INDENT = " " MUST_CALL_VALIDATORS = {} MODELS = [] GET_ATTRIBUTES = [] HAVE_CHILDREN_ELEMENTS = [] TO_ELEMENT_METHODS = [] NEED_INITIALIZE_VARIABLES = [] PLURAL_FORMS = {} class << self def must_call_validators inherited_hash_reader("MUST_CALL_VALIDATORS") end def models inherited_array_reader("MODELS") end def get_attributes inherited_array_reader("GET_ATTRIBUTES") end def have_children_elements inherited_array_reader("HAVE_CHILDREN_ELEMENTS") end def to_element_methods inherited_array_reader("TO_ELEMENT_METHODS") end def need_initialize_variables inherited_array_reader("NEED_INITIALIZE_VARIABLES") end def plural_forms inherited_hash_reader("PLURAL_FORMS") end def inherited_base ::RSS::Element end def inherited(klass) klass.const_set(:MUST_CALL_VALIDATORS, {}) klass.const_set(:MODELS, []) klass.const_set(:GET_ATTRIBUTES, []) klass.const_set(:HAVE_CHILDREN_ELEMENTS, []) klass.const_set(:TO_ELEMENT_METHODS, []) klass.const_set(:NEED_INITIALIZE_VARIABLES, []) klass.const_set(:PLURAL_FORMS, {}) tag_name = klass.name.split(/::/).last tag_name[0, 1] = tag_name[0, 1].downcase klass.instance_variable_set(:@tag_name, tag_name) klass.instance_variable_set(:@have_content, false) end def install_must_call_validator(prefix, uri) self::MUST_CALL_VALIDATORS[uri] = prefix end def install_model(tag, uri, occurs=nil, getter=nil, plural=false) getter ||= tag if m = self::MODELS.find {|t, u, o, g, p| t == tag and u == uri} m[2] = occurs else self::MODELS << [tag, uri, occurs, getter, plural] end end def install_get_attribute(name, uri, required=true, type=nil, disp_name=nil, element_name=nil) disp_name ||= name element_name ||= name writer_type, reader_type = type def_corresponded_attr_writer name, writer_type, disp_name def_corresponded_attr_reader name, reader_type if type == :boolean and /^is/ =~ name alias_method "#{$POSTMATCH}?", name end self::GET_ATTRIBUTES << [name, uri, required, element_name] add_need_initialize_variable(disp_name) end def def_corresponded_attr_writer(name, type=nil, disp_name=nil) disp_name ||= name case type when :integer integer_writer name, disp_name when :positive_integer positive_integer_writer name, disp_name when :boolean boolean_writer name, disp_name when :w3cdtf, :rfc822, :rfc2822 date_writer name, type, disp_name when :text_type text_type_writer name, disp_name when :content content_writer name, disp_name when :yes_clean_other yes_clean_other_writer name, disp_name when :yes_other yes_other_writer name, disp_name when :csv csv_writer name when :csv_integer csv_integer_writer name else attr_writer name end end def def_corresponded_attr_reader(name, type=nil) case type when :inherit inherit_convert_attr_reader name when :uri uri_convert_attr_reader name when :yes_clean_other yes_clean_other_attr_reader name when :yes_other yes_other_attr_reader name when :csv csv_attr_reader name when :csv_integer csv_attr_reader name, :separator => "," else convert_attr_reader name end end def content_setup(type=nil, disp_name=nil) writer_type, reader_type = type def_corresponded_attr_writer :content, writer_type, disp_name def_corresponded_attr_reader :content, reader_type @have_content = true end def have_content? @have_content end def add_have_children_element(variable_name, plural_name) self::HAVE_CHILDREN_ELEMENTS << [variable_name, plural_name] end def add_to_element_method(method_name) self::TO_ELEMENT_METHODS << method_name end def add_need_initialize_variable(variable_name) self::NEED_INITIALIZE_VARIABLES << variable_name end def add_plural_form(singular, plural) self::PLURAL_FORMS[singular] = plural end def required_prefix nil end def required_uri "" end def need_parent? false end def install_ns(prefix, uri) if self::NSPOOL.has_key?(prefix) raise OverlappedPrefixError.new(prefix) end self::NSPOOL[prefix] = uri end def tag_name @tag_name end end attr_accessor :parent, :do_validate def initialize(do_validate=true, attrs=nil) @parent = nil @converter = nil if attrs.nil? and (do_validate.is_a?(Hash) or do_validate.is_a?(Array)) do_validate, attrs = true, do_validate end @do_validate = do_validate initialize_variables(attrs || {}) end def tag_name self.class.tag_name end def full_name tag_name end def converter=(converter) @converter = converter targets = children.dup self.class.have_children_elements.each do |variable_name, plural_name| targets.concat(__send__(plural_name)) end targets.each do |target| target.converter = converter unless target.nil? end end def convert(value) if @converter @converter.convert(value) else value end end def valid?(ignore_unknown_element=true) validate(ignore_unknown_element) true rescue RSS::Error false end def validate(ignore_unknown_element=true) do_validate = @do_validate @do_validate = true validate_attribute __validate(ignore_unknown_element) ensure @do_validate = do_validate end def validate_for_stream(tags, ignore_unknown_element=true) validate_attribute __validate(ignore_unknown_element, tags, false) end def to_s(need_convert=true, indent='') if self.class.have_content? return "" if !empty_content? and !content_is_set? rv = tag(indent) do |next_indent| if empty_content? "" else xmled_content end end else rv = tag(indent) do |next_indent| self.class.to_element_methods.collect do |method_name| __send__(method_name, false, next_indent) end end end rv = convert(rv) if need_convert rv end def have_xml_content? false end def need_base64_encode? false end def set_next_element(tag_name, next_element) klass = next_element.class prefix = "" prefix << "#{klass.required_prefix}_" if klass.required_prefix key = "#{prefix}#{tag_name.gsub(/-/, '_')}" if self.class.plural_forms.has_key?(key) ary = __send__("#{self.class.plural_forms[key]}") ary << next_element else __send__("#{key}=", next_element) end end protected def have_required_elements? self.class::MODELS.all? do |tag, uri, occurs, getter| if occurs.nil? or occurs == "+" child = __send__(getter) if child.is_a?(Array) children = child children.any? {|c| c.have_required_elements?} else !child.to_s.empty? end else true end end end private def initialize_variables(attrs) normalized_attrs = {} attrs.each do |key, value| normalized_attrs[key.to_s] = value end self.class.need_initialize_variables.each do |variable_name| value = normalized_attrs[variable_name.to_s] if value __send__("#{variable_name}=", value) else instance_variable_set("@#{variable_name}", nil) end end initialize_have_children_elements @content = normalized_attrs["content"] if self.class.have_content? end def initialize_have_children_elements self.class.have_children_elements.each do |variable_name, plural_name| instance_variable_set("@#{variable_name}", []) end end def tag(indent, additional_attrs={}, &block) next_indent = indent + INDENT attrs = collect_attrs return "" if attrs.nil? return "" unless have_required_elements? attrs.update(additional_attrs) start_tag = make_start_tag(indent, next_indent, attrs.dup) if block content = block.call(next_indent) else content = [] end if content.is_a?(String) content = [content] start_tag << ">" end_tag = "" else content = content.reject{|x| x.empty?} if content.empty? return "" if attrs.empty? end_tag = "/>" else start_tag << ">\n" end_tag = "\n#{indent}" end end start_tag + content.join("\n") + end_tag end def make_start_tag(indent, next_indent, attrs) start_tag = ["#{indent}<#{full_name}"] unless attrs.empty? start_tag << attrs.collect do |key, value| %Q[#{h key}="#{h value}"] end.join("\n#{next_indent}") end start_tag.join(" ") end def collect_attrs attrs = {} _attrs.each do |name, required, alias_name| value = __send__(alias_name || name) return nil if required and value.nil? next if value.nil? return nil if attrs.has_key?(name) attrs[name] = value end attrs end def tag_name_with_prefix(prefix) "#{prefix}:#{tag_name}" end # For backward compatibility def calc_indent '' end def children rv = [] self.class.models.each do |name, uri, occurs, getter| value = __send__(getter) next if value.nil? value = [value] unless value.is_a?(Array) value.each do |v| rv << v if v.is_a?(Element) end end rv end def _tags rv = [] self.class.models.each do |name, uri, occurs, getter, plural| value = __send__(getter) next if value.nil? if plural and value.is_a?(Array) rv.concat([[uri, name]] * value.size) else rv << [uri, name] end end rv end def _attrs self.class.get_attributes.collect do |name, uri, required, element_name| [element_name, required, name] end end def __validate(ignore_unknown_element, tags=_tags, recursive=true) if recursive children.compact.each do |child| child.validate end end must_call_validators = self.class.must_call_validators tags = tag_filter(tags.dup) p tags if DEBUG must_call_validators.each do |uri, prefix| _validate(ignore_unknown_element, tags[uri], uri) meth = "#{prefix}_validate" if !prefix.empty? and respond_to?(meth, true) __send__(meth, ignore_unknown_element, tags[uri], uri) end end end def validate_attribute _attrs.each do |a_name, required, alias_name| value = instance_variable_get("@#{alias_name || a_name}") if required and value.nil? raise MissingAttributeError.new(tag_name, a_name) end __send__("#{alias_name || a_name}=", value) end end def _validate(ignore_unknown_element, tags, uri, models=self.class.models) count = 1 do_redo = false not_shift = false tag = nil models = models.find_all {|model| model[1] == uri} element_names = models.collect {|model| model[0]} if tags tags_size = tags.size tags = tags.sort_by {|x| element_names.index(x) || tags_size} end models.each_with_index do |model, i| name, _, occurs, = model if DEBUG p "before" p tags p model end if not_shift not_shift = false elsif tags tag = tags.shift end if DEBUG p "mid" p count end case occurs when '?' if count > 2 raise TooMuchTagError.new(name, tag_name) else if name == tag do_redo = true else not_shift = true end end when '*' if name == tag do_redo = true else not_shift = true end when '+' if name == tag do_redo = true else if count > 1 not_shift = true else raise MissingTagError.new(name, tag_name) end end else if name == tag if models[i+1] and models[i+1][0] != name and tags and tags.first == name raise TooMuchTagError.new(name, tag_name) end else raise MissingTagError.new(name, tag_name) end end if DEBUG p "after" p not_shift p do_redo p tag end if do_redo do_redo = false count += 1 redo else count = 1 end end if !ignore_unknown_element and !tags.nil? and !tags.empty? raise NotExpectedTagError.new(tags.first, uri, tag_name) end end def tag_filter(tags) rv = {} tags.each do |tag| rv[tag[0]] = [] unless rv.has_key?(tag[0]) rv[tag[0]].push(tag[1]) end rv end def empty_content? false end def content_is_set? if have_xml_content? __send__(self.class.xml_getter) else content end end def xmled_content if have_xml_content? __send__(self.class.xml_getter).to_s else _content = content _content = [_content].pack("m").delete("\n") if need_base64_encode? h(_content) end end end module RootElementMixin include XMLStyleSheetMixin attr_reader :output_encoding attr_reader :feed_type, :feed_subtype, :feed_version attr_accessor :version, :encoding, :standalone def initialize(feed_version, version=nil, encoding=nil, standalone=nil) super() @feed_type = nil @feed_subtype = nil @feed_version = feed_version @version = version || '1.0' @encoding = encoding @standalone = standalone @output_encoding = nil end def feed_info [@feed_type, @feed_version, @feed_subtype] end def output_encoding=(enc) @output_encoding = enc self.converter = Converter.new(@output_encoding, @encoding) end def setup_maker(maker) maker.version = version maker.encoding = encoding maker.standalone = standalone xml_stylesheets.each do |xss| xss.setup_maker(maker) end super end def to_feed(type, &block) Maker.make(type) do |maker| setup_maker(maker) block.call(maker) if block end end def to_rss(type, &block) to_feed("rss#{type}", &block) end def to_atom(type, &block) to_feed("atom:#{type}", &block) end def to_xml(type=nil, &block) if type.nil? or same_feed_type?(type) to_s else to_feed(type, &block).to_s end end private def same_feed_type?(type) if /^(atom|rss)?(\d+\.\d+)?(?::(.+))?$/i =~ type feed_type = ($1 || @feed_type).downcase feed_version = $2 || @feed_version feed_subtype = $3 || @feed_subtype [feed_type, feed_version, feed_subtype] == feed_info else false end end def tag(indent, attrs={}, &block) rv = super(indent, ns_declarations.merge(attrs), &block) return rv if rv.empty? "#{xmldecl}#{xml_stylesheet_pi}#{rv}" end def xmldecl rv = %Q[\n" rv end def ns_declarations decls = {} self.class::NSPOOL.collect do |prefix, uri| prefix = ":#{prefix}" unless prefix.empty? decls["xmlns#{prefix}"] = uri end decls end def maker_target(target) target end end end PK!gjj2.2.0/rss/xmlscanner.rbnu[require 'xmlscan/scanner' require 'stringio' module RSS class XMLScanParser < BaseParser class << self def listener XMLScanListener end end private def _parse begin if @rss.is_a?(String) input = StringIO.new(@rss) else input = @rss end scanner = XMLScan::XMLScanner.new(@listener) scanner.parse(input) rescue XMLScan::Error => e lineno = e.lineno || scanner.lineno || input.lineno raise NotWellFormedError.new(lineno){e.message} end end end class XMLScanListener < BaseListener include XMLScan::Visitor include ListenerMixin ENTITIES = { 'lt' => '<', 'gt' => '>', 'amp' => '&', 'quot' => '"', 'apos' => '\'' } def on_xmldecl_version(str) @version = str end def on_xmldecl_encoding(str) @encoding = str end def on_xmldecl_standalone(str) @standalone = str end def on_xmldecl_end xmldecl(@version, @encoding, @standalone == "yes") end alias_method(:on_pi, :instruction) alias_method(:on_chardata, :text) alias_method(:on_cdata, :text) def on_etag(name) tag_end(name) end def on_entityref(ref) text(entity(ref)) end def on_charref(code) text([code].pack('U')) end alias_method(:on_charref_hex, :on_charref) def on_stag(name) @attrs = {} end def on_attribute(name) @attrs[name] = @current_attr = '' end def on_attr_value(str) @current_attr << str end def on_attr_entityref(ref) @current_attr << entity(ref) end def on_attr_charref(code) @current_attr << [code].pack('U') end alias_method(:on_attr_charref_hex, :on_attr_charref) def on_stag_end(name) tag_start(name, @attrs) end def on_stag_end_empty(name) tag_start(name, @attrs) tag_end(name) end private def entity(ref) ent = ENTITIES[ref] if ent ent else wellformed_error("undefined entity: #{ref}") end end end end PK![[2.2.0/rss/content.rbnu[require "rss/rss" module RSS # The prefix for the Content XML namespace. CONTENT_PREFIX = 'content' # The URI of the Content specification. CONTENT_URI = "http://purl.org/rss/1.0/modules/content/" module ContentModel extend BaseModel ELEMENTS = ["#{CONTENT_PREFIX}_encoded"] def self.append_features(klass) super klass.install_must_call_validator(CONTENT_PREFIX, CONTENT_URI) ELEMENTS.each do |full_name| name = full_name[(CONTENT_PREFIX.size + 1)..-1] klass.install_text_element(name, CONTENT_URI, "?", full_name) end end end prefix_size = CONTENT_PREFIX.size + 1 ContentModel::ELEMENTS.each do |full_name| name = full_name[prefix_size..-1] BaseListener.install_get_text_element(CONTENT_URI, name, full_name) end end require 'rss/content/1.0' require 'rss/content/2.0' PK!RG2.2.0/rss/rexmlparser.rbnu[require "rexml/document" require "rexml/streamlistener" module RSS class REXMLParser < BaseParser class << self def listener REXMLListener end end private def _parse begin REXML::Document.parse_stream(@rss, @listener) rescue RuntimeError => e raise NotWellFormedError.new{e.message} rescue REXML::ParseException => e context = e.context line = context[0] if context raise NotWellFormedError.new(line){e.message} end end end class REXMLListener < BaseListener include REXML::StreamListener include ListenerMixin class << self def raise_for_undefined_entity? false end end def xmldecl(version, encoding, standalone) super(version, encoding, standalone == "yes") # Encoding is converted to UTF-8 when REXML parse XML. @encoding = 'UTF-8' end alias_method(:cdata, :text) end end PK!$)2.2.0/rss/content/1.0.rbnu[require 'rss/1.0' module RSS RDF.install_ns(CONTENT_PREFIX, CONTENT_URI) class RDF class Item; include ContentModel; end end end PK!2.2.0/rss/content/2.0.rbnu[require "rss/2.0" module RSS Rss.install_ns(CONTENT_PREFIX, CONTENT_URI) class Rss class Channel class Item; include ContentModel; end end end end PK!6OYY2.2.0/rss/atom.rbnu[require 'rss/parser' module RSS ## # Atom is an XML-based document format that is used to describe 'feeds' of related information. # A typical use is in a news feed where the information is periodically updated and which users # can subscribe to. The Atom format is described in http://tools.ietf.org/html/rfc4287 # # The Atom module provides support in reading and creating feeds. # # See the RSS module for examples consuming and creating feeds. module Atom ## # The Atom URI W3C Namespace URI = "http://www.w3.org/2005/Atom" ## # The XHTML URI W3C Namespace XHTML_URI = "http://www.w3.org/1999/xhtml" module CommonModel NSPOOL = {} ELEMENTS = [] def self.append_features(klass) super klass.install_must_call_validator("atom", URI) [ ["lang", :xml], ["base", :xml], ].each do |name, uri, required| klass.install_get_attribute(name, uri, required, [nil, :inherit]) end klass.class_eval do class << self def required_uri URI end def need_parent? true end end end end end module ContentModel module ClassMethods def content_type @content_type ||= nil end end class << self def append_features(klass) super klass.extend(ClassMethods) klass.content_setup(klass.content_type, klass.tag_name) end end def maker_target(target) target end private def setup_maker_element_writer "#{self.class.name.split(/::/).last.downcase}=" end def setup_maker_element(target) target.__send__(setup_maker_element_writer, content) super end end module URIContentModel class << self def append_features(klass) super klass.class_eval do @content_type = [nil, :uri] include(ContentModel) end end end end # The TextConstruct module is used to define a Text construct Atom element, # which is used to store small quantities of human-readable text # # The TextConstruct has a type attribute, e.g. text, html, xhtml module TextConstruct def self.append_features(klass) super klass.class_eval do [ ["type", ""], ].each do |name, uri, required| install_get_attribute(name, uri, required, :text_type) end content_setup add_need_initialize_variable("xhtml") class << self def xml_getter "xhtml" end def xml_setter "xhtml=" end end end end attr_writer :xhtml def xhtml return @xhtml if @xhtml.nil? if @xhtml.is_a?(XML::Element) and [@xhtml.name, @xhtml.uri] == ["div", XHTML_URI] return @xhtml end children = @xhtml children = [children] unless children.is_a?(Array) XML::Element.new("div", nil, XHTML_URI, {"xmlns" => XHTML_URI}, children) end # Returns true if type is "xhtml" def have_xml_content? @type == "xhtml" end def atom_validate(ignore_unknown_element, tags, uri) if have_xml_content? if @xhtml.nil? raise MissingTagError.new("div", tag_name) end unless [@xhtml.name, @xhtml.uri] == ["div", XHTML_URI] raise NotExpectedTagError.new(@xhtml.name, @xhtml.uri, tag_name) end end end private def maker_target(target) target.__send__(self.class.name.split(/::/).last.downcase) {|x| x} end def setup_maker_attributes(target) target.type = type target.content = content target.xml_content = @xhtml end end # The PersonConstruct module is used to define a Person Atom element that can be # used to describe a person, corporation, or similar entity # # The PersonConstruct has a Name, Uri, and Email child elements module PersonConstruct # Adds attributes for name, uri, and email to the +klass+ def self.append_features(klass) super klass.class_eval do [ ["name", nil], ["uri", "?"], ["email", "?"], ].each do |tag, occurs| install_have_attribute_element(tag, URI, occurs, nil, :content) end end end def maker_target(target) target.__send__("new_#{self.class.name.split(/::/).last.downcase}") end # The name of the person or entity class Name < RSS::Element include CommonModel include ContentModel end # The URI of the person or entity class Uri < RSS::Element include CommonModel include URIContentModel end # The email of the person or entity class Email < RSS::Element include CommonModel include ContentModel end end # Element used to describe an Atom date and time in the ISO 8601 format # # Examples: # * 2013-03-04T15:30:02Z # * 2013-03-04T10:30:02-05:00 module DateConstruct def self.append_features(klass) super klass.class_eval do @content_type = :w3cdtf include(ContentModel) end end # Raises NotAvailableValueError if element content is nil def atom_validate(ignore_unknown_element, tags, uri) raise NotAvailableValueError.new(tag_name, "") if content.nil? end end module DuplicateLinkChecker # Checks if there are duplicate links with the same type and hreflang attributes # that have an alternate (or empty) rel attribute # # Raises a TooMuchTagError if there are duplicates found def validate_duplicate_links(links) link_infos = {} links.each do |link| rel = link.rel || "alternate" next unless rel == "alternate" key = [link.hreflang, link.type] if link_infos.has_key?(key) raise TooMuchTagError.new("link", tag_name) end link_infos[key] = true end end end # Atom feed element # # A Feed has several metadata attributes in addition to a number of Entry child elements class Feed < RSS::Element include RootElementMixin include CommonModel include DuplicateLinkChecker install_ns('', URI) [ ["author", "*", :children], ["category", "*", :children, "categories"], ["contributor", "*", :children], ["generator", "?"], ["icon", "?", nil, :content], ["id", nil, nil, :content], ["link", "*", :children], ["logo", "?"], ["rights", "?"], ["subtitle", "?", nil, :content], ["title", nil, nil, :content], ["updated", nil, nil, :content], ["entry", "*", :children, "entries"], ].each do |tag, occurs, type, *args| type ||= :child __send__("install_have_#{type}_element", tag, URI, occurs, tag, *args) end # Creates a new Atom feed def initialize(version=nil, encoding=nil, standalone=nil) super("1.0", version, encoding, standalone) @feed_type = "atom" @feed_subtype = "feed" end alias_method :items, :entries # Returns true if there are any authors for the feed or any of the Entry # child elements have an author def have_author? authors.any? {|author| !author.to_s.empty?} or entries.any? {|entry| entry.have_author?(false)} end private def atom_validate(ignore_unknown_element, tags, uri) unless have_author? raise MissingTagError.new("author", tag_name) end validate_duplicate_links(links) end def have_required_elements? super and have_author? end def maker_target(maker) maker.channel end def setup_maker_element(channel) prev_dc_dates = channel.dc_dates.to_a.dup super channel.about = id.content if id channel.dc_dates.replace(prev_dc_dates) end def setup_maker_elements(channel) super items = channel.maker.items entries.each do |entry| entry.setup_maker(items) end end class Author < RSS::Element include CommonModel include PersonConstruct end class Category < RSS::Element include CommonModel [ ["term", "", true], ["scheme", "", false, [nil, :uri]], ["label", ""], ].each do |name, uri, required, type| install_get_attribute(name, uri, required, type) end private def maker_target(target) target.new_category end end class Contributor < RSS::Element include CommonModel include PersonConstruct end class Generator < RSS::Element include CommonModel include ContentModel [ ["uri", "", false, [nil, :uri]], ["version", ""], ].each do |name, uri, required, type| install_get_attribute(name, uri, required, type) end private def setup_maker_attributes(target) target.generator do |generator| generator.uri = uri if uri generator.version = version if version end end end # Atom Icon element # # Image that provides a visual identification for the Feed. Image should have an aspect # ratio of 1:1 class Icon < RSS::Element include CommonModel include URIContentModel end # Atom ID element # # Universally Unique Identifier (UUID) for the Feed class Id < RSS::Element include CommonModel include URIContentModel end # Defines an Atom Link element # # A Link has the following attributes: # * href # * rel # * type # * hreflang # * title # * length class Link < RSS::Element include CommonModel [ ["href", "", true, [nil, :uri]], ["rel", ""], ["type", ""], ["hreflang", ""], ["title", ""], ["length", ""], ].each do |name, uri, required, type| install_get_attribute(name, uri, required, type) end private def maker_target(target) target.new_link end end # Atom Logo element # # Image that provides a visual identification for the Feed. Image should have an aspect # ratio of 2:1 (horizontal:vertical) class Logo < RSS::Element include CommonModel include URIContentModel def maker_target(target) target.maker.image end private def setup_maker_element_writer "url=" end end # Atom Rights element # # TextConstruct that contains copyright information regarding the content in an Entry or Feed class Rights < RSS::Element include CommonModel include TextConstruct end # Atom Subtitle element # # TextConstruct that conveys a description or subtitle for a Feed class Subtitle < RSS::Element include CommonModel include TextConstruct end # Atom Title element # # TextConstruct that conveys a description or title for a feed or Entry class Title < RSS::Element include CommonModel include TextConstruct end # Atom Updated element # # DateConstruct indicating the most recent time when an Entry or Feed was modified # in a way the publisher considers significant class Updated < RSS::Element include CommonModel include DateConstruct end # Defines a child Atom Entry element for an Atom Feed class Entry < RSS::Element include CommonModel include DuplicateLinkChecker [ ["author", "*", :children], ["category", "*", :children, "categories"], ["content", "?", :child], ["contributor", "*", :children], ["id", nil, nil, :content], ["link", "*", :children], ["published", "?", :child, :content], ["rights", "?", :child], ["source", "?"], ["summary", "?", :child], ["title", nil], ["updated", nil, :child, :content], ].each do |tag, occurs, type, *args| type ||= :attribute __send__("install_have_#{type}_element", tag, URI, occurs, tag, *args) end # Returns whether any of the following are true # * There are any authors in the feed # * If the parent element has an author and the +check_parent+ parameter was given. # * There is a source element that has an author def have_author?(check_parent=true) authors.any? {|author| !author.to_s.empty?} or (check_parent and @parent and @parent.have_author?) or (source and source.have_author?) end private def atom_validate(ignore_unknown_element, tags, uri) unless have_author? raise MissingTagError.new("author", tag_name) end validate_duplicate_links(links) end def have_required_elements? super and have_author? end def maker_target(items) if items.respond_to?("items") # For backward compatibility items = items.items end items.new_item end Author = Feed::Author Category = Feed::Category class Content < RSS::Element include CommonModel class << self def xml_setter "xml=" end def xml_getter "xml" end end [ ["type", ""], ["src", "", false, [nil, :uri]], ].each do |name, uri, required, type| install_get_attribute(name, uri, required, type) end content_setup add_need_initialize_variable("xml") attr_writer :xml def have_xml_content? inline_xhtml? or inline_other_xml? end def xml return @xml unless inline_xhtml? return @xml if @xml.nil? if @xml.is_a?(XML::Element) and [@xml.name, @xml.uri] == ["div", XHTML_URI] return @xml end children = @xml children = [children] unless children.is_a?(Array) XML::Element.new("div", nil, XHTML_URI, {"xmlns" => XHTML_URI}, children) end def xhtml if inline_xhtml? xml else nil end end def atom_validate(ignore_unknown_element, tags, uri) if out_of_line? raise MissingAttributeError.new(tag_name, "type") if @type.nil? unless (content.nil? or content.empty?) raise NotAvailableValueError.new(tag_name, content) end elsif inline_xhtml? if @xml.nil? raise MissingTagError.new("div", tag_name) end unless @xml.name == "div" and @xml.uri == XHTML_URI raise NotExpectedTagError.new(@xml.name, @xml.uri, tag_name) end end end def inline_text? !out_of_line? and [nil, "text", "html"].include?(@type) end def inline_html? return false if out_of_line? @type == "html" or mime_split == ["text", "html"] end def inline_xhtml? !out_of_line? and @type == "xhtml" end def inline_other? return false if out_of_line? media_type, subtype = mime_split return false if media_type.nil? or subtype.nil? true end def inline_other_text? return false unless inline_other? return false if inline_other_xml? media_type, = mime_split return true if "text" == media_type.downcase false end def inline_other_xml? return false unless inline_other? media_type, subtype = mime_split normalized_mime_type = "#{media_type}/#{subtype}".downcase if /(?:\+xml|^xml)$/ =~ subtype or %w(text/xml-external-parsed-entity application/xml-external-parsed-entity application/xml-dtd).find {|x| x == normalized_mime_type} return true end false end def inline_other_base64? inline_other? and !inline_other_text? and !inline_other_xml? end def out_of_line? not @src.nil? end def mime_split media_type = subtype = nil if /\A\s*([a-z]+)\/([a-z\+]+)\s*(?:;.*)?\z/i =~ @type.to_s media_type = $1.downcase subtype = $2.downcase end [media_type, subtype] end def need_base64_encode? inline_other_base64? end private def empty_content? out_of_line? or super end end Contributor = Feed::Contributor Id = Feed::Id Link = Feed::Link class Published < RSS::Element include CommonModel include DateConstruct end Rights = Feed::Rights class Source < RSS::Element include CommonModel [ ["author", "*", :children], ["category", "*", :children, "categories"], ["contributor", "*", :children], ["generator", "?"], ["icon", "?"], ["id", "?", nil, :content], ["link", "*", :children], ["logo", "?"], ["rights", "?"], ["subtitle", "?"], ["title", "?"], ["updated", "?", nil, :content], ].each do |tag, occurs, type, *args| type ||= :attribute __send__("install_have_#{type}_element", tag, URI, occurs, tag, *args) end def have_author? !author.to_s.empty? end Author = Feed::Author Category = Feed::Category Contributor = Feed::Contributor Generator = Feed::Generator Icon = Feed::Icon Id = Feed::Id Link = Feed::Link Logo = Feed::Logo Rights = Feed::Rights Subtitle = Feed::Subtitle Title = Feed::Title Updated = Feed::Updated end class Summary < RSS::Element include CommonModel include TextConstruct end Title = Feed::Title Updated = Feed::Updated end end # Defines a top-level Atom Entry element # class Entry < RSS::Element include RootElementMixin include CommonModel include DuplicateLinkChecker [ ["author", "*", :children], ["category", "*", :children, "categories"], ["content", "?"], ["contributor", "*", :children], ["id", nil, nil, :content], ["link", "*", :children], ["published", "?", :child, :content], ["rights", "?"], ["source", "?"], ["summary", "?"], ["title", nil], ["updated", nil, nil, :content], ].each do |tag, occurs, type, *args| type ||= :attribute __send__("install_have_#{type}_element", tag, URI, occurs, tag, *args) end # Creates a new Atom Entry element def initialize(version=nil, encoding=nil, standalone=nil) super("1.0", version, encoding, standalone) @feed_type = "atom" @feed_subtype = "entry" end # Returns the Entry in an array def items [self] end # sets up the +maker+ for constructing Entry elements def setup_maker(maker) maker = maker.maker if maker.respond_to?("maker") super(maker) end # Returns where there are any authors present or there is a source with an author def have_author? authors.any? {|author| !author.to_s.empty?} or (source and source.have_author?) end private def atom_validate(ignore_unknown_element, tags, uri) unless have_author? raise MissingTagError.new("author", tag_name) end validate_duplicate_links(links) end def have_required_elements? super and have_author? end def maker_target(maker) maker.items.new_item end Author = Feed::Entry::Author Category = Feed::Entry::Category Content = Feed::Entry::Content Contributor = Feed::Entry::Contributor Id = Feed::Entry::Id Link = Feed::Entry::Link Published = Feed::Entry::Published Rights = Feed::Entry::Rights Source = Feed::Entry::Source Summary = Feed::Entry::Summary Title = Feed::Entry::Title Updated = Feed::Entry::Updated end end Atom::CommonModel::ELEMENTS.each do |name| BaseListener.install_get_text_element(Atom::URI, name, "#{name}=") end module ListenerMixin private def initial_start_feed(tag_name, prefix, attrs, ns) check_ns(tag_name, prefix, ns, Atom::URI, false) @rss = Atom::Feed.new(@version, @encoding, @standalone) @rss.do_validate = @do_validate @rss.xml_stylesheets = @xml_stylesheets @rss.lang = attrs["xml:lang"] @rss.base = attrs["xml:base"] @last_element = @rss pr = Proc.new do |text, tags| @rss.validate_for_stream(tags) if @do_validate end @proc_stack.push(pr) end def initial_start_entry(tag_name, prefix, attrs, ns) check_ns(tag_name, prefix, ns, Atom::URI, false) @rss = Atom::Entry.new(@version, @encoding, @standalone) @rss.do_validate = @do_validate @rss.xml_stylesheets = @xml_stylesheets @rss.lang = attrs["xml:lang"] @rss.base = attrs["xml:base"] @last_element = @rss pr = Proc.new do |text, tags| @rss.validate_for_stream(tags) if @do_validate end @proc_stack.push(pr) end end end PK!p  2.2.0/rss/2.0.rbnu[require "rss/0.9" module RSS ## # = RSS 2.0 support # # RSS has three different versions. This module contains support for version # 2.0[http://www.rssboard.org/rss-specification] # # == Producing RSS 2.0 # # Producing our own RSS feeds is easy as well. Let's make a very basic feed: # # require "rss" # # rss = RSS::Maker.make("2.0") do |maker| # maker.channel.language = "en" # maker.channel.author = "matz" # maker.channel.updated = Time.now.to_s # maker.channel.link = "http://www.ruby-lang.org/en/feeds/news.rss" # maker.channel.title = "Example Feed" # maker.channel.description = "A longer description of my feed." # maker.items.new_item do |item| # item.link = "http://www.ruby-lang.org/en/news/2010/12/25/ruby-1-9-2-p136-is-released/" # item.title = "Ruby 1.9.2-p136 is released" # item.updated = Time.now.to_s # end # end # # puts rss # # As you can see, this is a very Builder-like DSL. This code will spit out an # RSS 2.0 feed with one item. If we needed a second item, we'd make another # block with maker.items.new_item and build a second one. class Rss class Channel [ ["generator"], ["ttl", :integer], ].each do |name, type| install_text_element(name, "", "?", name, type) end [ %w(category categories), ].each do |name, plural_name| install_have_children_element(name, "", "*", name, plural_name) end [ ["image", "?"], ["language", "?"], ].each do |name, occurs| install_model(name, "", occurs) end Category = Item::Category class Item [ ["comments", "?"], ["author", "?"], ].each do |name, occurs| install_text_element(name, "", occurs) end [ ["pubDate", '?'], ].each do |name, occurs| install_date_element(name, "", occurs, name, 'rfc822') end alias date pubDate alias date= pubDate= [ ["guid", '?'], ].each do |name, occurs| install_have_child_element(name, "", occurs) end private alias _setup_maker_element setup_maker_element def setup_maker_element(item) _setup_maker_element(item) @guid.setup_maker(item) if @guid end class Guid < Element include RSS09 [ ["isPermaLink", "", false, :boolean] ].each do |name, uri, required, type| install_get_attribute(name, uri, required, type) end content_setup def initialize(*args) if Utils.element_initialize_arguments?(args) super else super() self.isPermaLink = args[0] self.content = args[1] end end alias_method :_PermaLink?, :PermaLink? private :_PermaLink? def PermaLink? perma = _PermaLink? perma or perma.nil? end private def maker_target(item) item.guid end def setup_maker_attributes(guid) guid.isPermaLink = isPermaLink guid.content = content end end end end end RSS09::ELEMENTS.each do |name| BaseListener.install_get_text_element("", name, name) end end PK! xx2.2.0/rss/converter.rbnu[require "rss/utils" module RSS class Converter include Utils def initialize(to_enc, from_enc=nil) if "".respond_to?(:encode) @to_encoding = to_enc return end normalized_to_enc = to_enc.downcase.gsub(/-/, '_') from_enc ||= 'utf-8' normalized_from_enc = from_enc.downcase.gsub(/-/, '_') if normalized_to_enc == normalized_from_enc def_same_enc() else def_diff_enc = "def_to_#{normalized_to_enc}_from_#{normalized_from_enc}" if respond_to?(def_diff_enc) __send__(def_diff_enc) else def_else_enc(to_enc, from_enc) end end end def convert(value) if value.is_a?(String) and value.respond_to?(:encode) value.encode(@to_encoding) else value end end def def_convert(depth=0) instance_eval(<<-EOC, *get_file_and_line_from_caller(depth)) def convert(value) if value.kind_of?(String) #{yield('value')} else value end end EOC end def def_iconv_convert(to_enc, from_enc, depth=0) begin require "iconv" @iconv = Iconv.new(to_enc, from_enc) def_convert(depth+1) do |value| <<-EOC begin @iconv.iconv(#{value}) rescue Iconv::Failure raise ConversionError.new(#{value}, "#{to_enc}", "#{from_enc}") end EOC end rescue LoadError, ArgumentError, SystemCallError raise UnknownConversionMethodError.new(to_enc, from_enc) end end def def_else_enc(to_enc, from_enc) def_iconv_convert(to_enc, from_enc, 0) end def def_same_enc() def_convert do |value| value end end def def_uconv_convert_if_can(meth, to_enc, from_enc, nkf_arg) begin require "uconv" def_convert(1) do |value| <<-EOC begin Uconv.#{meth}(#{value}) rescue Uconv::Error raise ConversionError.new(#{value}, "#{to_enc}", "#{from_enc}") end EOC end rescue LoadError require 'nkf' if NKF.const_defined?(:UTF8) def_convert(1) do |value| "NKF.nkf(#{nkf_arg.dump}, #{value})" end else def_iconv_convert(to_enc, from_enc, 1) end end end def def_to_euc_jp_from_utf_8 def_uconv_convert_if_can('u8toeuc', 'EUC-JP', 'UTF-8', '-We') end def def_to_utf_8_from_euc_jp def_uconv_convert_if_can('euctou8', 'UTF-8', 'EUC-JP', '-Ew') end def def_to_shift_jis_from_utf_8 def_uconv_convert_if_can('u8tosjis', 'Shift_JIS', 'UTF-8', '-Ws') end def def_to_utf_8_from_shift_jis def_uconv_convert_if_can('sjistou8', 'UTF-8', 'Shift_JIS', '-Sw') end def def_to_euc_jp_from_shift_jis require "nkf" def_convert do |value| "NKF.nkf('-Se', #{value})" end end def def_to_shift_jis_from_euc_jp require "nkf" def_convert do |value| "NKF.nkf('-Es', #{value})" end end def def_to_euc_jp_from_iso_2022_jp require "nkf" def_convert do |value| "NKF.nkf('-Je', #{value})" end end def def_to_iso_2022_jp_from_euc_jp require "nkf" def_convert do |value| "NKF.nkf('-Ej', #{value})" end end def def_to_utf_8_from_iso_8859_1 def_convert do |value| "#{value}.unpack('C*').pack('U*')" end end def def_to_iso_8859_1_from_utf_8 def_convert do |value| <<-EOC array_utf8 = #{value}.unpack('U*') array_enc = [] array_utf8.each do |num| if num <= 0xFF array_enc << num else array_enc.concat "&\#\#{num};".unpack('C*') end end array_enc.pack('C*') EOC end end end end PK!BX2.2.0/rss/xml-stylesheet.rbnu[require "rss/utils" module RSS module XMLStyleSheetMixin attr_accessor :xml_stylesheets def initialize(*args) super @xml_stylesheets = [] end private def xml_stylesheet_pi xsss = @xml_stylesheets.collect do |xss| pi = xss.to_s pi = nil if /\A\s*\z/ =~ pi pi end.compact xsss.push("") unless xsss.empty? xsss.join("\n") end end class XMLStyleSheet include Utils ATTRIBUTES = %w(href type title media charset alternate) GUESS_TABLE = { "xsl" => "text/xsl", "css" => "text/css", } attr_accessor(*ATTRIBUTES) attr_accessor(:do_validate) def initialize(*attrs) if attrs.size == 1 and (attrs.first.is_a?(Hash) or attrs.first.is_a?(Array)) attrs = attrs.first end @do_validate = true ATTRIBUTES.each do |attr| __send__("#{attr}=", nil) end vars = ATTRIBUTES.dup vars.unshift(:do_validate) attrs.each do |name, value| if vars.include?(name.to_s) __send__("#{name}=", value) end end end def to_s rv = "" if @href rv << %Q[] end rv end remove_method(:href=) def href=(value) @href = value if @href and @type.nil? @type = guess_type(@href) end @href end remove_method(:alternate=) def alternate=(value) if value.nil? or /\A(?:yes|no)\z/ =~ value @alternate = value else if @do_validate args = ["?xml-stylesheet?", %Q[alternate="#{value}"]] raise NotAvailableValueError.new(*args) end end @alternate end def setup_maker(maker) xss = maker.xml_stylesheets.new_xml_stylesheet ATTRIBUTES.each do |attr| xss.__send__("#{attr}=", __send__(attr)) end end private def guess_type(filename) /\.([^.]+)$/ =~ filename GUESS_TABLE[$1] end end end PK!.誄T>T>2.2.0/rss/parser.rbnu[require "forwardable" require "open-uri" require "rss/rss" require "rss/xml" module RSS class NotWellFormedError < Error attr_reader :line, :element # Create a new NotWellFormedError for an error at +line+ # in +element+. If a block is given the return value of # the block ends up in the error message. def initialize(line=nil, element=nil) message = "This is not well formed XML" if element or line message << "\nerror occurred" message << " in #{element}" if element message << " at about #{line} line" if line end message << "\n#{yield}" if block_given? super(message) end end class XMLParserNotFound < Error def initialize super("available XML parser was not found in " << "#{AVAILABLE_PARSER_LIBRARIES.inspect}.") end end class NotValidXMLParser < Error def initialize(parser) super("#{parser} is not an available XML parser. " << "Available XML parser" << (AVAILABLE_PARSERS.size > 1 ? "s are " : " is ") << "#{AVAILABLE_PARSERS.inspect}.") end end class NSError < InvalidRSSError attr_reader :tag, :prefix, :uri def initialize(tag, prefix, require_uri) @tag, @prefix, @uri = tag, prefix, require_uri super("prefix <#{prefix}> doesn't associate uri " << "<#{require_uri}> in tag <#{tag}>") end end class Parser extend Forwardable class << self @@default_parser = nil def default_parser @@default_parser || AVAILABLE_PARSERS.first end # Set @@default_parser to new_value if it is one of the # available parsers. Else raise NotValidXMLParser error. def default_parser=(new_value) if AVAILABLE_PARSERS.include?(new_value) @@default_parser = new_value else raise NotValidXMLParser.new(new_value) end end def parse(rss, do_validate=true, ignore_unknown_element=true, parser_class=default_parser) parser = new(rss, parser_class) parser.do_validate = do_validate parser.ignore_unknown_element = ignore_unknown_element parser.parse end end def_delegators(:@parser, :parse, :rss, :ignore_unknown_element, :ignore_unknown_element=, :do_validate, :do_validate=) def initialize(rss, parser_class=self.class.default_parser) @parser = parser_class.new(normalize_rss(rss)) end private # Try to get the XML associated with +rss+. # Return +rss+ if it already looks like XML, or treat it as a URI, # or a file to get the XML, def normalize_rss(rss) return rss if maybe_xml?(rss) uri = to_uri(rss) if uri.respond_to?(:read) uri.read elsif !rss.tainted? and File.readable?(rss) File.open(rss) {|f| f.read} else rss end end # maybe_xml? tests if source is a string that looks like XML. def maybe_xml?(source) source.is_a?(String) and / :xml}] @tag_stack = [[]] @text_stack = [''] @proc_stack = [] @last_element = nil @version = @encoding = @standalone = nil @xml_stylesheets = [] @xml_child_mode = false @xml_element = nil @last_xml_element = nil end # set instance vars for version, encoding, standalone def xmldecl(version, encoding, standalone) @version, @encoding, @standalone = version, encoding, standalone end def instruction(name, content) if name == "xml-stylesheet" params = parse_pi_content(content) if params.has_key?("href") @xml_stylesheets << XMLStyleSheet.new(params) end end end def tag_start(name, attributes) @text_stack.push('') ns = @ns_stack.last.dup attrs = {} attributes.each do |n, v| if /\Axmlns(?:\z|:)/ =~ n ns[$POSTMATCH] = v else attrs[n] = v end end @ns_stack.push(ns) prefix, local = split_name(name) @tag_stack.last.push([_ns(ns, prefix), local]) @tag_stack.push([]) if @xml_child_mode previous = @last_xml_element element_attrs = attributes.dup unless previous ns.each do |ns_prefix, value| next if ns_prefix == "xml" key = ns_prefix.empty? ? "xmlns" : "xmlns:#{ns_prefix}" element_attrs[key] ||= value end end next_element = XML::Element.new(local, prefix.empty? ? nil : prefix, _ns(ns, prefix), element_attrs) previous << next_element if previous @last_xml_element = next_element pr = Proc.new do |text, tags| if previous @last_xml_element = previous else @xml_element = @last_xml_element @last_xml_element = nil end end @proc_stack.push(pr) else if @rss.nil? and respond_to?("initial_start_#{local}", true) __send__("initial_start_#{local}", local, prefix, attrs, ns.dup) elsif respond_to?("start_#{local}", true) __send__("start_#{local}", local, prefix, attrs, ns.dup) else start_else_element(local, prefix, attrs, ns.dup) end end end def tag_end(name) if DEBUG p "end tag #{name}" p @tag_stack end text = @text_stack.pop tags = @tag_stack.pop pr = @proc_stack.pop pr.call(text, tags) unless pr.nil? @ns_stack.pop end def text(data) if @xml_child_mode @last_xml_element << data if @last_xml_element else @text_stack.last << data end end private def _ns(ns, prefix) ns.fetch(prefix, "") end CONTENT_PATTERN = /\s*([^=]+)=(["'])([^\2]+?)\2/ # Extract the first name="value" pair from content. # Works with single quotes according to the constant # CONTENT_PATTERN. Return a Hash. def parse_pi_content(content) params = {} content.scan(CONTENT_PATTERN) do |name, quote, value| params[name] = value end params end def start_else_element(local, prefix, attrs, ns) class_name = self.class.class_name(_ns(ns, prefix), local) current_class = @last_element.class if known_class?(current_class, class_name) next_class = current_class.const_get(class_name) start_have_something_element(local, prefix, attrs, ns, next_class) else if !@do_validate or @ignore_unknown_element @proc_stack.push(setup_next_element_in_unknown_element) else parent = "ROOT ELEMENT???" if current_class.tag_name parent = current_class.tag_name end raise NotExpectedTagError.new(local, _ns(ns, prefix), parent) end end end if Module.method(:const_defined?).arity == -1 def known_class?(target_class, class_name) class_name and (target_class.const_defined?(class_name, false) or target_class.constants.include?(class_name.to_sym)) end else def known_class?(target_class, class_name) class_name and (target_class.const_defined?(class_name) or target_class.constants.include?(class_name)) end end NAMESPLIT = /^(?:([\w:][-\w.]*):)?([\w:][-\w.]*)/ def split_name(name) name =~ NAMESPLIT [$1 || '', $2] end def check_ns(tag_name, prefix, ns, require_uri, ignore_unknown_element=nil) if _ns(ns, prefix) == require_uri true else if ignore_unknown_element.nil? ignore_unknown_element = @ignore_unknown_element end if ignore_unknown_element false elsif @do_validate raise NSError.new(tag_name, prefix, require_uri) else # Force bind required URI with prefix @ns_stack.last[prefix] = require_uri true end end end def start_get_text_element(tag_name, prefix, ns, required_uri) pr = Proc.new do |text, tags| setter = self.class.setter(required_uri, tag_name) if setter and @last_element.respond_to?(setter) if @do_validate getter = self.class.getter(required_uri, tag_name) if @last_element.__send__(getter) raise TooMuchTagError.new(tag_name, @last_element.tag_name) end end @last_element.__send__(setter, text.to_s) else if @do_validate and !@ignore_unknown_element raise NotExpectedTagError.new(tag_name, _ns(ns, prefix), @last_element.tag_name) end end end @proc_stack.push(pr) end def start_have_something_element(tag_name, prefix, attrs, ns, klass) if check_ns(tag_name, prefix, ns, klass.required_uri) attributes = collect_attributes(tag_name, prefix, attrs, ns, klass) @proc_stack.push(setup_next_element(tag_name, klass, attributes)) else @proc_stack.push(setup_next_element_in_unknown_element) end end def collect_attributes(tag_name, prefix, attrs, ns, klass) attributes = {} klass.get_attributes.each do |a_name, a_uri, required, element_name| if a_uri.is_a?(String) or !a_uri.respond_to?(:include?) a_uri = [a_uri] end unless a_uri == [""] for prefix, uri in ns if a_uri.include?(uri) val = attrs["#{prefix}:#{a_name}"] break if val end end end if val.nil? and a_uri.include?("") val = attrs[a_name] end if @do_validate and required and val.nil? unless a_uri.include?("") for prefix, uri in ns if a_uri.include?(uri) a_name = "#{prefix}:#{a_name}" end end end raise MissingAttributeError.new(tag_name, a_name) end attributes[a_name] = val end attributes end def setup_next_element(tag_name, klass, attributes) previous = @last_element next_element = klass.new(@do_validate, attributes) previous.set_next_element(tag_name, next_element) @last_element = next_element @last_element.parent = previous if klass.need_parent? @xml_child_mode = @last_element.have_xml_content? Proc.new do |text, tags| p(@last_element.class) if DEBUG if @xml_child_mode @last_element.content = @xml_element.to_s xml_setter = @last_element.class.xml_setter @last_element.__send__(xml_setter, @xml_element) @xml_element = nil @xml_child_mode = false else if klass.have_content? if @last_element.need_base64_encode? text = text.lstrip.unpack("m").first end @last_element.content = text end end if @do_validate @last_element.validate_for_stream(tags, @ignore_unknown_element) end @last_element = previous end end def setup_next_element_in_unknown_element current_element, @last_element = @last_element, nil Proc.new {@last_element = current_element} end end unless const_defined? :AVAILABLE_PARSER_LIBRARIES # The list of all available libraries for parsing. AVAILABLE_PARSER_LIBRARIES = [ ["rss/xmlparser", :XMLParserParser], ["rss/xmlscanner", :XMLScanParser], ["rss/rexmlparser", :REXMLParser], ] end # The list of all available parsers, in constant form. AVAILABLE_PARSERS = [] AVAILABLE_PARSER_LIBRARIES.each do |lib, parser| begin require lib AVAILABLE_PARSERS.push(const_get(parser)) rescue LoadError end end if AVAILABLE_PARSERS.empty? raise XMLParserNotFound end end PK!KNh?h?2.2.0/prettyprint.rbnu[# This class implements a pretty printing algorithm. It finds line breaks and # nice indentations for grouped structure. # # By default, the class assumes that primitive elements are strings and each # byte in the strings have single column in width. But it can be used for # other situations by giving suitable arguments for some methods: # * newline object and space generation block for PrettyPrint.new # * optional width argument for PrettyPrint#text # * PrettyPrint#breakable # # There are several candidate uses: # * text formatting using proportional fonts # * multibyte characters which has columns different to number of bytes # * non-string formatting # # == Bugs # * Box based formatting? # * Other (better) model/algorithm? # # Report any bugs at http://bugs.ruby-lang.org # # == References # Christian Lindig, Strictly Pretty, March 2000, # http://www.st.cs.uni-sb.de/~lindig/papers/#pretty # # Philip Wadler, A prettier printer, March 1998, # http://homepages.inf.ed.ac.uk/wadler/topics/language-design.html#prettier # # == Author # Tanaka Akira # class PrettyPrint # This is a convenience method which is same as follows: # # begin # q = PrettyPrint.new(output, maxwidth, newline, &genspace) # ... # q.flush # output # end # def PrettyPrint.format(output='', maxwidth=79, newline="\n", genspace=lambda {|n| ' ' * n}) q = PrettyPrint.new(output, maxwidth, newline, &genspace) yield q q.flush output end # This is similar to PrettyPrint::format but the result has no breaks. # # +maxwidth+, +newline+ and +genspace+ are ignored. # # The invocation of +breakable+ in the block doesn't break a line and is # treated as just an invocation of +text+. # def PrettyPrint.singleline_format(output='', maxwidth=nil, newline=nil, genspace=nil) q = SingleLine.new(output) yield q output end # Creates a buffer for pretty printing. # # +output+ is an output target. If it is not specified, '' is assumed. It # should have a << method which accepts the first argument +obj+ of # PrettyPrint#text, the first argument +sep+ of PrettyPrint#breakable, the # first argument +newline+ of PrettyPrint.new, and the result of a given # block for PrettyPrint.new. # # +maxwidth+ specifies maximum line length. If it is not specified, 79 is # assumed. However actual outputs may overflow +maxwidth+ if long # non-breakable texts are provided. # # +newline+ is used for line breaks. "\n" is used if it is not specified. # # The block is used to generate spaces. {|width| ' ' * width} is used if it # is not given. # def initialize(output='', maxwidth=79, newline="\n", &genspace) @output = output @maxwidth = maxwidth @newline = newline @genspace = genspace || lambda {|n| ' ' * n} @output_width = 0 @buffer_width = 0 @buffer = [] root_group = Group.new(0) @group_stack = [root_group] @group_queue = GroupQueue.new(root_group) @indent = 0 end # The output object. # # This defaults to '', and should accept the << method attr_reader :output # The maximum width of a line, before it is separated in to a newline # # This defaults to 79, and should be a Fixnum attr_reader :maxwidth # The value that is appended to +output+ to add a new line. # # This defaults to "\n", and should be String attr_reader :newline # A lambda or Proc, that takes one argument, of a Fixnum, and returns # the corresponding number of spaces. # # By default this is: # lambda {|n| ' ' * n} attr_reader :genspace # The number of spaces to be indented attr_reader :indent # The PrettyPrint::GroupQueue of groups in stack to be pretty printed attr_reader :group_queue # Returns the group most recently added to the stack. # # Contrived example: # out = "" # => "" # q = PrettyPrint.new(out) # => #, @output_width=0, @buffer_width=0, @buffer=[], @group_stack=[#], @group_queue=#]]>, @indent=0> # q.group { # q.text q.current_group.inspect # q.text q.newline # q.group(q.current_group.depth + 1) { # q.text q.current_group.inspect # q.text q.newline # q.group(q.current_group.depth + 1) { # q.text q.current_group.inspect # q.text q.newline # q.group(q.current_group.depth + 1) { # q.text q.current_group.inspect # q.text q.newline # } # } # } # } # => 284 # puts out # # # # # # # # def current_group @group_stack.last end # Breaks the buffer into lines that are shorter than #maxwidth def break_outmost_groups while @maxwidth < @output_width + @buffer_width return unless group = @group_queue.deq until group.breakables.empty? data = @buffer.shift @output_width = data.output(@output, @output_width) @buffer_width -= data.width end while !@buffer.empty? && Text === @buffer.first text = @buffer.shift @output_width = text.output(@output, @output_width) @buffer_width -= text.width end end end # This adds +obj+ as a text of +width+ columns in width. # # If +width+ is not specified, obj.length is used. # def text(obj, width=obj.length) if @buffer.empty? @output << obj @output_width += width else text = @buffer.last unless Text === text text = Text.new @buffer << text end text.add(obj, width) @buffer_width += width break_outmost_groups end end # This is similar to #breakable except # the decision to break or not is determined individually. # # Two #fill_breakable under a group may cause 4 results: # (break,break), (break,non-break), (non-break,break), (non-break,non-break). # This is different to #breakable because two #breakable under a group # may cause 2 results: # (break,break), (non-break,non-break). # # The text +sep+ is inserted if a line is not broken at this point. # # If +sep+ is not specified, " " is used. # # If +width+ is not specified, +sep.length+ is used. You will have to # specify this when +sep+ is a multibyte character, for example. # def fill_breakable(sep=' ', width=sep.length) group { breakable sep, width } end # This says "you can break a line here if necessary", and a +width+\-column # text +sep+ is inserted if a line is not broken at the point. # # If +sep+ is not specified, " " is used. # # If +width+ is not specified, +sep.length+ is used. You will have to # specify this when +sep+ is a multibyte character, for example. # def breakable(sep=' ', width=sep.length) group = @group_stack.last if group.break? flush @output << @newline @output << @genspace.call(@indent) @output_width = @indent @buffer_width = 0 else @buffer << Breakable.new(sep, width, self) @buffer_width += width break_outmost_groups end end # Groups line break hints added in the block. The line break hints are all # to be used or not. # # If +indent+ is specified, the method call is regarded as nested by # nest(indent) { ... }. # # If +open_obj+ is specified, text open_obj, open_width is called # before grouping. If +close_obj+ is specified, text close_obj, # close_width is called after grouping. # def group(indent=0, open_obj='', close_obj='', open_width=open_obj.length, close_width=close_obj.length) text open_obj, open_width group_sub { nest(indent) { yield } } text close_obj, close_width end # Takes a block and queues a new group that is indented 1 level further. def group_sub group = Group.new(@group_stack.last.depth + 1) @group_stack.push group @group_queue.enq group begin yield ensure @group_stack.pop if group.breakables.empty? @group_queue.delete group end end end # Increases left margin after newline with +indent+ for line breaks added in # the block. # def nest(indent) @indent += indent begin yield ensure @indent -= indent end end # outputs buffered data. # def flush @buffer.each {|data| @output_width = data.output(@output, @output_width) } @buffer.clear @buffer_width = 0 end # The Text class is the means by which to collect strings from objects. # # This class is intended for internal use of the PrettyPrint buffers. class Text # :nodoc: # Creates a new text object. # # This constructor takes no arguments. # # The workflow is to append a PrettyPrint::Text object to the buffer, and # being able to call the buffer.last() to reference it. # # As there are objects, use PrettyPrint::Text#add to include the objects # and the width to utilized by the String version of this object. def initialize @objs = [] @width = 0 end # The total width of the objects included in this Text object. attr_reader :width # Render the String text of the objects that have been added to this Text object. # # Output the text to +out+, and increment the width to +output_width+ def output(out, output_width) @objs.each {|obj| out << obj} output_width + @width end # Include +obj+ in the objects to be pretty printed, and increment # this Text object's total width by +width+ def add(obj, width) @objs << obj @width += width end end # The Breakable class is used for breaking up object information # # This class is intended for internal use of the PrettyPrint buffers. class Breakable # :nodoc: # Create a new Breakable object. # # Arguments: # * +sep+ String of the separator # * +width+ Fixnum width of the +sep+ # * +q+ parent PrettyPrint object, to base from def initialize(sep, width, q) @obj = sep @width = width @pp = q @indent = q.indent @group = q.current_group @group.breakables.push self end # Holds the separator String # # The +sep+ argument from ::new attr_reader :obj # The width of +obj+ / +sep+ attr_reader :width # The number of spaces to indent. # # This is inferred from +q+ within PrettyPrint, passed in ::new attr_reader :indent # Render the String text of the objects that have been added to this # Breakable object. # # Output the text to +out+, and increment the width to +output_width+ def output(out, output_width) @group.breakables.shift if @group.break? out << @pp.newline out << @pp.genspace.call(@indent) @indent else @pp.group_queue.delete @group if @group.breakables.empty? out << @obj output_width + @width end end end # The Group class is used for making indentation easier. # # While this class does neither the breaking into newlines nor indentation, # it is used in a stack (as well as a queue) within PrettyPrint, to group # objects. # # For information on using groups, see PrettyPrint#group # # This class is intended for internal use of the PrettyPrint buffers. class Group # :nodoc: # Create a Group object # # Arguments: # * +depth+ - this group's relation to previous groups def initialize(depth) @depth = depth @breakables = [] @break = false end # This group's relation to previous groups attr_reader :depth # Array to hold the Breakable objects for this Group attr_reader :breakables # Makes a break for this Group, and returns true def break @break = true end # Boolean of whether this Group has made a break def break? @break end # Boolean of whether this Group has been queried for being first # # This is used as a predicate, and ought to be called first. def first? if defined? @first false else @first = false true end end end # The GroupQueue class is used for managing the queue of Group to be pretty # printed. # # This queue groups the Group objects, based on their depth. # # This class is intended for internal use of the PrettyPrint buffers. class GroupQueue # :nodoc: # Create a GroupQueue object # # Arguments: # * +groups+ - one or more PrettyPrint::Group objects def initialize(*groups) @queue = [] groups.each {|g| enq g} end # Enqueue +group+ # # This does not strictly append the group to the end of the queue, # but instead adds it in line, base on the +group.depth+ def enq(group) depth = group.depth @queue << [] until depth < @queue.length @queue[depth] << group end # Returns the outer group of the queue def deq @queue.each {|gs| (gs.length-1).downto(0) {|i| unless gs[i].breakables.empty? group = gs.slice!(i, 1).first group.break return group end } gs.each {|group| group.break} gs.clear } return nil end # Remote +group+ from this queue def delete(group) @queue[group.depth].delete(group) end end # PrettyPrint::SingleLine is used by PrettyPrint.singleline_format # # It is passed to be similar to a PrettyPrint object itself, by responding to: # * #text # * #breakable # * #nest # * #group # * #flush # * #first? # # but instead, the output has no line breaks # class SingleLine # Create a PrettyPrint::SingleLine object # # Arguments: # * +output+ - String (or similar) to store rendered text. Needs to respond to '<<' # * +maxwidth+ - Argument position expected to be here for compatibility. # This argument is a noop. # * +newline+ - Argument position expected to be here for compatibility. # This argument is a noop. def initialize(output, maxwidth=nil, newline=nil) @output = output @first = [true] end # Add +obj+ to the text to be output. # # +width+ argument is here for compatibility. It is a noop argument. def text(obj, width=nil) @output << obj end # Appends +sep+ to the text to be output. By default +sep+ is ' ' # # +width+ argument is here for compatibility. It is a noop argument. def breakable(sep=' ', width=nil) @output << sep end # Takes +indent+ arg, but does nothing with it. # # Yields to a block. def nest(indent) # :nodoc: yield end # Opens a block for grouping objects to be pretty printed. # # Arguments: # * +indent+ - noop argument. Present for compatibility. # * +open_obj+ - text appended before the &blok. Default is '' # * +close_obj+ - text appended after the &blok. Default is '' # * +open_width+ - noop argument. Present for compatibility. # * +close_width+ - noop argument. Present for compatibility. def group(indent=nil, open_obj='', close_obj='', open_width=nil, close_width=nil) @first.push true @output << open_obj yield @output << close_obj @first.pop end # Method present for compatibility, but is a noop def flush # :nodoc: end # This is used as a predicate, and ought to be called first. def first? result = @first[-1] @first[-1] = false result end end end PK!l%hpSQSQ2.2.0/logger.rbnu[# logger.rb - simple logging utility # Copyright (C) 2000-2003, 2005, 2008, 2011 NAKAMURA, Hiroshi . # # Documentation:: NAKAMURA, Hiroshi and Gavin Sinclair # License:: # You can redistribute it and/or modify it under the same terms of Ruby's # license; either the dual license version in 2003, or any later version. # Revision:: $Id: logger.rb 56504 2016-10-27 07:47:14Z usa $ # # A simple system for logging messages. See Logger for more documentation. require 'monitor' # == Description # # The Logger class provides a simple but sophisticated logging utility that # you can use to output messages. # # The messages have associated levels, such as +INFO+ or +ERROR+ that indicate # their importance. You can then give the Logger a level, and only messages # at that level or higher will be printed. # # The levels are: # # +UNKNOWN+:: An unknown message that should always be logged. # +FATAL+:: An unhandleable error that results in a program crash. # +ERROR+:: A handleable error condition. # +WARN+:: A warning. # +INFO+:: Generic (useful) information about system operation. # +DEBUG+:: Low-level information for developers. # # For instance, in a production system, you may have your Logger set to # +INFO+ or even +WARN+. # When you are developing the system, however, you probably # want to know about the program's internal state, and would set the Logger to # +DEBUG+. # # *Note*: Logger does not escape or sanitize any messages passed to it. # Developers should be aware of when potentially malicious data (user-input) # is passed to Logger, and manually escape the untrusted data: # # logger.info("User-input: #{input.dump}") # logger.info("User-input: %p" % input) # # You can use #formatter= for escaping all data. # # original_formatter = Logger::Formatter.new # logger.formatter = proc { |severity, datetime, progname, msg| # original_formatter.call(severity, datetime, progname, msg.dump) # } # logger.info(input) # # === Example # # This creates a Logger that outputs to the standard output stream, with a # level of +WARN+: # # require 'logger' # # logger = Logger.new(STDOUT) # logger.level = Logger::WARN # # logger.debug("Created logger") # logger.info("Program started") # logger.warn("Nothing to do!") # # path = "a_non_existent_file" # # begin # File.foreach(path) do |line| # unless line =~ /^(\w+) = (.*)$/ # logger.error("Line in wrong format: #{line.chomp}") # end # end # rescue => err # logger.fatal("Caught exception; exiting") # logger.fatal(err) # end # # Because the Logger's level is set to +WARN+, only the warning, error, and # fatal messages are recorded. The debug and info messages are silently # discarded. # # === Features # # There are several interesting features that Logger provides, like # auto-rolling of log files, setting the format of log messages, and # specifying a program name in conjunction with the message. The next section # shows you how to achieve these things. # # # == HOWTOs # # === How to create a logger # # The options below give you various choices, in more or less increasing # complexity. # # 1. Create a logger which logs messages to STDERR/STDOUT. # # logger = Logger.new(STDERR) # logger = Logger.new(STDOUT) # # 2. Create a logger for the file which has the specified name. # # logger = Logger.new('logfile.log') # # 3. Create a logger for the specified file. # # file = File.open('foo.log', File::WRONLY | File::APPEND) # # To create new (and to remove old) logfile, add File::CREAT like: # # file = File.open('foo.log', File::WRONLY | File::APPEND | File::CREAT) # logger = Logger.new(file) # # 4. Create a logger which ages the logfile once it reaches a certain size. # Leave 10 "old" log files where each file is about 1,024,000 bytes. # # logger = Logger.new('foo.log', 10, 1024000) # # 5. Create a logger which ages the logfile daily/weekly/monthly. # # logger = Logger.new('foo.log', 'daily') # logger = Logger.new('foo.log', 'weekly') # logger = Logger.new('foo.log', 'monthly') # # === How to log a message # # Notice the different methods (+fatal+, +error+, +info+) being used to log # messages of various levels? Other methods in this family are +warn+ and # +debug+. +add+ is used below to log a message of an arbitrary (perhaps # dynamic) level. # # 1. Message in a block. # # logger.fatal { "Argument 'foo' not given." } # # 2. Message as a string. # # logger.error "Argument #{@foo} mismatch." # # 3. With progname. # # logger.info('initialize') { "Initializing..." } # # 4. With severity. # # logger.add(Logger::FATAL) { 'Fatal error!' } # # The block form allows you to create potentially complex log messages, # but to delay their evaluation until and unless the message is # logged. For example, if we have the following: # # logger.debug { "This is a " + potentially + " expensive operation" } # # If the logger's level is +INFO+ or higher, no debug messages will be logged, # and the entire block will not even be evaluated. Compare to this: # # logger.debug("This is a " + potentially + " expensive operation") # # Here, the string concatenation is done every time, even if the log # level is not set to show the debug message. # # === How to close a logger # # logger.close # # === Setting severity threshold # # 1. Original interface. # # logger.sev_threshold = Logger::WARN # # 2. Log4r (somewhat) compatible interface. # # logger.level = Logger::INFO # # # DEBUG < INFO < WARN < ERROR < FATAL < UNKNOWN # # == Format # # Log messages are rendered in the output stream in a certain format by # default. The default format and a sample are shown below: # # Log format: # SeverityID, [DateTime #pid] SeverityLabel -- ProgName: message # # Log sample: # I, [1999-03-03T02:34:24.895701 #19074] INFO -- Main: info. # # You may change the date and time format via #datetime_format=. # # logger.datetime_format = '%Y-%m-%d %H:%M:%S' # # e.g. "2004-01-03 00:54:26" # # Or, you may change the overall format via the #formatter= method. # # logger.formatter = proc do |severity, datetime, progname, msg| # "#{datetime}: #{msg}\n" # end # # e.g. "2005-09-22 08:51:08 +0900: hello world" # class Logger VERSION = "1.2.7" _, name, rev = %w$Id: logger.rb 56504 2016-10-27 07:47:14Z usa $ if name name = name.chomp(",v") else name = File.basename(__FILE__) end rev ||= "v#{VERSION}" ProgName = "#{name}/#{rev}" class Error < RuntimeError # :nodoc: end # not used after 1.2.7. just for compat. class ShiftingError < Error # :nodoc: end # Logging severity. module Severity # Low-level information, mostly for developers. DEBUG = 0 # Generic (useful) information about system operation. INFO = 1 # A warning. WARN = 2 # A handleable error condition. ERROR = 3 # An unhandleable error that results in a program crash. FATAL = 4 # An unknown message that should always be logged. UNKNOWN = 5 end include Severity # Logging severity threshold (e.g. Logger::INFO). attr_accessor :level # Program name to include in log messages. attr_accessor :progname # Set date-time format. # # +datetime_format+:: A string suitable for passing to +strftime+. def datetime_format=(datetime_format) @default_formatter.datetime_format = datetime_format end # Returns the date format being used. See #datetime_format= def datetime_format @default_formatter.datetime_format end # Logging formatter, as a +Proc+ that will take four arguments and # return the formatted message. The arguments are: # # +severity+:: The Severity of the log message. # +time+:: A Time instance representing when the message was logged. # +progname+:: The #progname configured, or passed to the logger method. # +msg+:: The _Object_ the user passed to the log message; not necessarily a # String. # # The block should return an Object that can be written to the logging # device via +write+. The default formatter is used when no formatter is # set. attr_accessor :formatter alias sev_threshold level alias sev_threshold= level= # Returns +true+ iff the current severity level allows for the printing of # +DEBUG+ messages. def debug?; @level <= DEBUG; end # Returns +true+ iff the current severity level allows for the printing of # +INFO+ messages. def info?; @level <= INFO; end # Returns +true+ iff the current severity level allows for the printing of # +WARN+ messages. def warn?; @level <= WARN; end # Returns +true+ iff the current severity level allows for the printing of # +ERROR+ messages. def error?; @level <= ERROR; end # Returns +true+ iff the current severity level allows for the printing of # +FATAL+ messages. def fatal?; @level <= FATAL; end # # :call-seq: # Logger.new(logdev, shift_age = 7, shift_size = 1048576) # Logger.new(logdev, shift_age = 'weekly') # # === Args # # +logdev+:: # The log device. This is a filename (String) or IO object (typically # +STDOUT+, +STDERR+, or an open file). # +shift_age+:: # Number of old log files to keep, *or* frequency of rotation (+daily+, # +weekly+ or +monthly+). # +shift_size+:: # Maximum logfile size (only applies when +shift_age+ is a number). # # === Description # # Create an instance. # def initialize(logdev, shift_age = 0, shift_size = 1048576) @progname = nil @level = DEBUG @default_formatter = Formatter.new @formatter = nil @logdev = nil if logdev @logdev = LogDevice.new(logdev, :shift_age => shift_age, :shift_size => shift_size) end end # # :call-seq: # Logger#add(severity, message = nil, progname = nil) { ... } # # === Args # # +severity+:: # Severity. Constants are defined in Logger namespace: +DEBUG+, +INFO+, # +WARN+, +ERROR+, +FATAL+, or +UNKNOWN+. # +message+:: # The log message. A String or Exception. # +progname+:: # Program name string. Can be omitted. Treated as a message if no # +message+ and +block+ are given. # +block+:: # Can be omitted. Called to get a message string if +message+ is nil. # # === Return # # When the given severity is not high enough (for this particular logger), # log no message, and return +true+. # # === Description # # Log a message if the given severity is high enough. This is the generic # logging method. Users will be more inclined to use #debug, #info, #warn, # #error, and #fatal. # # Message format: +message+ can be any object, but it has to be # converted to a String in order to log it. Generally, +inspect+ is used # if the given object is not a String. # A special case is an +Exception+ object, which will be printed in detail, # including message, class, and backtrace. See #msg2str for the # implementation if required. # # === Bugs # # * Logfile is not locked. # * Append open does not need to lock file. # * If the OS supports multi I/O, records possibly may be mixed. # def add(severity, message = nil, progname = nil) severity ||= UNKNOWN if @logdev.nil? or severity < @level return true end progname ||= @progname if message.nil? if block_given? message = yield else message = progname progname = @progname end end @logdev.write( format_message(format_severity(severity), Time.now, progname, message)) true end alias log add # # Dump given message to the log device without any formatting. If no log # device exists, return +nil+. # def <<(msg) unless @logdev.nil? @logdev.write(msg) end end # # Log a +DEBUG+ message. # # See #info for more information. # def debug(progname = nil, &block) add(DEBUG, nil, progname, &block) end # # :call-seq: # info(message) # info(progname, &block) # # Log an +INFO+ message. # # +message+:: The message to log; does not need to be a String. # +progname+:: In the block form, this is the #progname to use in the # log message. The default can be set with #progname=. # +block+:: Evaluates to the message to log. This is not evaluated unless # the logger's level is sufficient to log the message. This # allows you to create potentially expensive logging messages that # are only called when the logger is configured to show them. # # === Examples # # logger.info("MainApp") { "Received connection from #{ip}" } # # ... # logger.info "Waiting for input from user" # # ... # logger.info { "User typed #{input}" } # # You'll probably stick to the second form above, unless you want to provide a # program name (which you can do with #progname= as well). # # === Return # # See #add. # def info(progname = nil, &block) add(INFO, nil, progname, &block) end # # Log a +WARN+ message. # # See #info for more information. # def warn(progname = nil, &block) add(WARN, nil, progname, &block) end # # Log an +ERROR+ message. # # See #info for more information. # def error(progname = nil, &block) add(ERROR, nil, progname, &block) end # # Log a +FATAL+ message. # # See #info for more information. # def fatal(progname = nil, &block) add(FATAL, nil, progname, &block) end # # Log an +UNKNOWN+ message. This will be printed no matter what the logger's # level is. # # See #info for more information. # def unknown(progname = nil, &block) add(UNKNOWN, nil, progname, &block) end # # Close the logging device. # def close @logdev.close if @logdev end private # Severity label for logging (max 5 chars). SEV_LABEL = %w(DEBUG INFO WARN ERROR FATAL ANY) def format_severity(severity) SEV_LABEL[severity] || 'ANY' end def format_message(severity, datetime, progname, msg) (@formatter || @default_formatter).call(severity, datetime, progname, msg) end # Default formatter for log messages. class Formatter Format = "%s, [%s#%d] %5s -- %s: %s\n" attr_accessor :datetime_format def initialize @datetime_format = nil end def call(severity, time, progname, msg) Format % [severity[0..0], format_datetime(time), $$, severity, progname, msg2str(msg)] end private def format_datetime(time) time.strftime(@datetime_format || "%Y-%m-%dT%H:%M:%S.%6N ".freeze) end def msg2str(msg) case msg when ::String msg when ::Exception "#{ msg.message } (#{ msg.class })\n" << (msg.backtrace || []).join("\n") else msg.inspect end end end module Period module_function SiD = 24 * 60 * 60 def next_rotate_time(now, shift_age) case shift_age when /^daily$/ t = Time.mktime(now.year, now.month, now.mday) + SiD when /^weekly$/ t = Time.mktime(now.year, now.month, now.mday) + SiD * (7 - now.wday) when /^monthly$/ t = Time.mktime(now.year, now.month, 1) + SiD * 32 mday = 1 else return now end if mday or t.hour.nonzero? or t.min.nonzero? or t.sec.nonzero? t = Time.mktime(t.year, t.month, mday || (t.mday + (t.hour > 12 ? 1 : 0))) end t end def previous_period_end(now, shift_age) case shift_age when /^daily$/ t = Time.mktime(now.year, now.month, now.mday) - SiD / 2 when /^weekly$/ t = Time.mktime(now.year, now.month, now.mday) - (SiD * (now.wday + 1) + SiD / 2) when /^monthly$/ t = Time.mktime(now.year, now.month, 1) - SiD / 2 else return now end Time.mktime(t.year, t.month, t.mday, 23, 59, 59) end end # Device used for logging messages. class LogDevice include Period attr_reader :dev attr_reader :filename class LogDeviceMutex include MonitorMixin end def initialize(log = nil, opt = {}) @dev = @filename = @shift_age = @shift_size = nil @mutex = LogDeviceMutex.new if log.respond_to?(:write) and log.respond_to?(:close) @dev = log else @dev = open_logfile(log) @dev.sync = true @filename = log @shift_age = opt[:shift_age] || 7 @shift_size = opt[:shift_size] || 1048576 @next_rotate_time = next_rotate_time(Time.now, @shift_age) unless @shift_age.is_a?(Integer) end end def write(message) begin @mutex.synchronize do if @shift_age and @dev.respond_to?(:stat) begin check_shift_log rescue warn("log shifting failed. #{$!}") end end begin @dev.write(message) rescue warn("log writing failed. #{$!}") end end rescue Exception => ignored warn("log writing failed. #{ignored}") end end def close begin @mutex.synchronize do @dev.close rescue nil end rescue Exception @dev.close rescue nil end end private def open_logfile(filename) begin open(filename, (File::WRONLY | File::APPEND)) rescue Errno::ENOENT create_logfile(filename) end end def create_logfile(filename) begin logdev = open(filename, (File::WRONLY | File::APPEND | File::CREAT | File::EXCL)) logdev.flock(File::LOCK_EX) logdev.sync = true add_log_header(logdev) logdev.flock(File::LOCK_UN) rescue Errno::EEXIST # file is created by another process logdev = open_logfile(filename) logdev.sync = true end logdev end def add_log_header(file) file.write( "# Logfile created on %s by %s\n" % [Time.now.to_s, Logger::ProgName] ) if file.size == 0 end def check_shift_log if @shift_age.is_a?(Integer) # Note: always returns false if '0'. if @filename && (@shift_age > 0) && (@dev.stat.size > @shift_size) lock_shift_log { shift_log_age } end else now = Time.now if now >= @next_rotate_time @next_rotate_time = next_rotate_time(now, @shift_age) lock_shift_log { shift_log_period(previous_period_end(now, @shift_age)) } end end end if /mswin|mingw/ =~ RUBY_PLATFORM def lock_shift_log yield end else def lock_shift_log retry_limit = 8 retry_sleep = 0.1 begin File.open(@filename, File::WRONLY | File::APPEND) do |lock| lock.flock(File::LOCK_EX) # inter-process locking. will be unlocked at closing file if File.identical?(@filename, lock) and File.identical?(lock, @dev) yield # log shifting else # log shifted by another process (i-node before locking and i-node after locking are different) @dev.close rescue nil @dev = open_logfile(@filename) @dev.sync = true end end rescue Errno::ENOENT # @filename file would not exist right after #rename and before #create_logfile if retry_limit <= 0 warn("log rotation inter-process lock failed. #{$!}") else sleep retry_sleep retry_limit -= 1 retry_sleep *= 2 retry end end rescue warn("log rotation inter-process lock failed. #{$!}") end end def shift_log_age (@shift_age-3).downto(0) do |i| if FileTest.exist?("#{@filename}.#{i}") File.rename("#{@filename}.#{i}", "#{@filename}.#{i+1}") end end @dev.close rescue nil File.rename("#{@filename}", "#{@filename}.0") @dev = create_logfile(@filename) return true end def shift_log_period(period_end) postfix = period_end.strftime("%Y%m%d") # YYYYMMDD age_file = "#{@filename}.#{postfix}" if FileTest.exist?(age_file) # try to avoid filename crash caused by Timestamp change. idx = 0 # .99 can be overridden; avoid too much file search with 'loop do' while idx < 100 idx += 1 age_file = "#{@filename}.#{postfix}.#{idx}" break unless FileTest.exist?(age_file) end end @dev.close rescue nil File.rename("#{@filename}", age_file) @dev = create_logfile(@filename) return true end end end PK!_|2.2.0/tracer.rbnu[#-- # $Release Version: 0.3$ # $Revision: 1.12 $ require "thread" ## # Outputs a source level execution trace of a Ruby program. # # It does this by registering an event handler with Kernel#set_trace_func for # processing incoming events. It also provides methods for filtering unwanted # trace output (see Tracer.add_filter, Tracer.on, and Tracer.off). # # == Example # # Consider the following Ruby script # # class A # def square(a) # return a*a # end # end # # a = A.new # a.square(5) # # Running the above script using ruby -r tracer example.rb will # output the following trace to STDOUT (Note you can also explicitly # require 'tracer') # # #0::38:Kernel:<: - # #0:example.rb:3::-: class A # #0:example.rb:3::C: class A # #0:example.rb:4::-: def square(a) # #0:example.rb:7::E: end # #0:example.rb:9::-: a = A.new # #0:example.rb:10::-: a.square(5) # #0:example.rb:4:A:>: def square(a) # #0:example.rb:5:A:-: return a*a # #0:example.rb:6:A:<: end # | | | | | # | | | | ---------------------+ event # | | | ------------------------+ class # | | --------------------------+ line # | ------------------------------------+ filename # ---------------------------------------+ thread # # Symbol table used for displaying incoming events: # # +}+:: call a C-language routine # +{+:: return from a C-language routine # +>+:: call a Ruby method # +C+:: start a class or module definition # +E+:: finish a class or module definition # +-+:: execute code on a new line # +^+:: raise an exception # +<+:: return from a Ruby method # # == Copyright # # by Keiju ISHITSUKA(keiju@ishitsuka.com) # class Tracer class << self # display additional debug information (defaults to false) attr_accessor :verbose alias verbose? verbose # output stream used to output trace (defaults to STDOUT) attr_accessor :stdout # mutex lock used by tracer for displaying trace output attr_reader :stdout_mutex # display process id in trace output (defaults to false) attr_accessor :display_process_id alias display_process_id? display_process_id # display thread id in trace output (defaults to true) attr_accessor :display_thread_id alias display_thread_id? display_thread_id # display C-routine calls in trace output (defaults to false) attr_accessor :display_c_call alias display_c_call? display_c_call end Tracer::stdout = STDOUT Tracer::verbose = false Tracer::display_process_id = false Tracer::display_thread_id = true Tracer::display_c_call = false @stdout_mutex = Mutex.new # Symbol table used for displaying trace information EVENT_SYMBOL = { "line" => "-", "call" => ">", "return" => "<", "class" => "C", "end" => "E", "raise" => "^", "c-call" => "}", "c-return" => "{", "unknown" => "?" } def initialize # :nodoc: @threads = Hash.new if defined? Thread.main @threads[Thread.main.object_id] = 0 else @threads[Thread.current.object_id] = 0 end @get_line_procs = {} @filters = [] end def stdout # :nodoc: Tracer.stdout end def on # :nodoc: if block_given? on begin yield ensure off end else set_trace_func method(:trace_func).to_proc stdout.print "Trace on\n" if Tracer.verbose? end end def off # :nodoc: set_trace_func nil stdout.print "Trace off\n" if Tracer.verbose? end def add_filter(p = proc) # :nodoc: @filters.push p end def set_get_line_procs(file, p = proc) # :nodoc: @get_line_procs[file] = p end def get_line(file, line) # :nodoc: if p = @get_line_procs[file] return p.call(line) end unless list = SCRIPT_LINES__[file] list = File.readlines(file) rescue [] SCRIPT_LINES__[file] = list end if l = list[line - 1] l else "-\n" end end def get_thread_no # :nodoc: if no = @threads[Thread.current.object_id] no else @threads[Thread.current.object_id] = @threads.size end end def trace_func(event, file, line, id, binding, klass, *) # :nodoc: return if file == __FILE__ for p in @filters return unless p.call event, file, line, id, binding, klass end return unless Tracer::display_c_call? or event != "c-call" && event != "c-return" Tracer::stdout_mutex.synchronize do if EVENT_SYMBOL[event] stdout.printf("<%d>", $$) if Tracer::display_process_id? stdout.printf("#%d:", get_thread_no) if Tracer::display_thread_id? if line == 0 source = "?\n" else source = get_line(file, line) end stdout.printf("%s:%d:%s:%s: %s", file, line, klass || '', EVENT_SYMBOL[event], source) end end end # Reference to singleton instance of Tracer Single = new ## # Start tracing # # === Example # # Tracer.on # # code to trace here # Tracer.off # # You can also pass a block: # # Tracer.on { # # trace everything in this block # } def Tracer.on if block_given? Single.on{yield} else Single.on end end ## # Disable tracing def Tracer.off Single.off end ## # Register an event handler p which is called everytime a line # in +file_name+ is executed. # # Example: # # Tracer.set_get_line_procs("example.rb", lambda { |line| # puts "line number executed is #{line}" # }) def Tracer.set_get_line_procs(file_name, p = proc) Single.set_get_line_procs(file_name, p) end ## # Used to filter unwanted trace output # # Example which only outputs lines of code executed within the Kernel class: # # Tracer.add_filter do |event, file, line, id, binding, klass, *rest| # "Kernel" == klass.to_s # end def Tracer.add_filter(p = proc) Single.add_filter(p) end end # :stopdoc: SCRIPT_LINES__ = {} unless defined? SCRIPT_LINES__ if $0 == __FILE__ # direct call $0 = ARGV[0] ARGV.shift Tracer.on require $0 else # call Tracer.on only if required by -r command-line option count = caller.count {|bt| %r%/rubygems/core_ext/kernel_require\.rb:% !~ bt} if (defined?(Gem) and count == 0) or (!defined?(Gem) and count <= 1) Tracer.on end end # :startdoc: PK!.EE2.2.0/uri/https.rbnu[# = uri/https.rb # # Author:: Akira Yamada # License:: You can redistribute it and/or modify it under the same term as Ruby. # Revision:: $Id: https.rb 31555 2011-05-13 20:03:21Z drbrain $ # # See URI for general documentation # require 'uri/http' module URI # The default port for HTTPS URIs is 443, and the scheme is 'https:' rather # than 'http:'. Other than that, HTTPS URIs are identical to HTTP URIs; # see URI::HTTP. class HTTPS < HTTP # A Default port of 443 for URI::HTTPS DEFAULT_PORT = 443 end @@schemes['HTTPS'] = HTTPS end PK!"RYEYE2.2.0/uri/rfc2396_parser.rbnu[#-- # = uri/common.rb # # Author:: Akira Yamada # Revision:: $Id$ # License:: # You can redistribute it and/or modify it under the same term as Ruby. # # See URI for general documentation # module URI # # Includes URI::REGEXP::PATTERN # module RFC2396_REGEXP # # Patterns used to parse URI's # module PATTERN # :stopdoc: # RFC 2396 (URI Generic Syntax) # RFC 2732 (IPv6 Literal Addresses in URL's) # RFC 2373 (IPv6 Addressing Architecture) # alpha = lowalpha | upalpha ALPHA = "a-zA-Z" # alphanum = alpha | digit ALNUM = "#{ALPHA}\\d" # hex = digit | "A" | "B" | "C" | "D" | "E" | "F" | # "a" | "b" | "c" | "d" | "e" | "f" HEX = "a-fA-F\\d" # escaped = "%" hex hex ESCAPED = "%[#{HEX}]{2}" # mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | # "(" | ")" # unreserved = alphanum | mark UNRESERVED = "\\-_.!~*'()#{ALNUM}" # reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | # "$" | "," # reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | # "$" | "," | "[" | "]" (RFC 2732) RESERVED = ";/?:@&=+$,\\[\\]" # domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum DOMLABEL = "(?:[#{ALNUM}](?:[-#{ALNUM}]*[#{ALNUM}])?)" # toplabel = alpha | alpha *( alphanum | "-" ) alphanum TOPLABEL = "(?:[#{ALPHA}](?:[-#{ALNUM}]*[#{ALNUM}])?)" # hostname = *( domainlabel "." ) toplabel [ "." ] HOSTNAME = "(?:#{DOMLABEL}\\.)*#{TOPLABEL}\\.?" # :startdoc: end # PATTERN # :startdoc: end # REGEXP # class that Parses String's into URI's # # It contains a Hash set of patterns and Regexp's that match and validate. # class RFC2396_Parser include RFC2396_REGEXP # # == Synopsis # # URI::Parser.new([opts]) # # == Args # # The constructor accepts a hash as options for parser. # Keys of options are pattern names of URI components # and values of options are pattern strings. # The constructor generates set of regexps for parsing URIs. # # You can use the following keys: # # * :ESCAPED (URI::PATTERN::ESCAPED in default) # * :UNRESERVED (URI::PATTERN::UNRESERVED in default) # * :DOMLABEL (URI::PATTERN::DOMLABEL in default) # * :TOPLABEL (URI::PATTERN::TOPLABEL in default) # * :HOSTNAME (URI::PATTERN::HOSTNAME in default) # # == Examples # # p = URI::Parser.new(:ESCAPED => "(?:%[a-fA-F0-9]{2}|%u[a-fA-F0-9]{4})") # u = p.parse("http://example.jp/%uABCD") #=> # # URI.parse(u.to_s) #=> raises URI::InvalidURIError # # s = "http://example.com/ABCD" # u1 = p.parse(s) #=> # # u2 = URI.parse(s) #=> # # u1 == u2 #=> true # u1.eql?(u2) #=> false # def initialize(opts = {}) @pattern = initialize_pattern(opts) @pattern.each_value(&:freeze) @pattern.freeze @regexp = initialize_regexp(@pattern) @regexp.each_value(&:freeze) @regexp.freeze end # The Hash of patterns. # # see also URI::Parser.initialize_pattern attr_reader :pattern # The Hash of Regexp # # see also URI::Parser.initialize_regexp attr_reader :regexp # Returns a split URI against regexp[:ABS_URI] def split(uri) case uri when '' # null uri when @regexp[:ABS_URI] scheme, opaque, userinfo, host, port, registry, path, query, fragment = $~[1..-1] # URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ] # absoluteURI = scheme ":" ( hier_part | opaque_part ) # hier_part = ( net_path | abs_path ) [ "?" query ] # opaque_part = uric_no_slash *uric # abs_path = "/" path_segments # net_path = "//" authority [ abs_path ] # authority = server | reg_name # server = [ [ userinfo "@" ] hostport ] if !scheme raise InvalidURIError, "bad URI(absolute but no scheme): #{uri}" end if !opaque && (!path && (!host && !registry)) raise InvalidURIError, "bad URI(absolute but no path): #{uri}" end when @regexp[:REL_URI] scheme = nil opaque = nil userinfo, host, port, registry, rel_segment, abs_path, query, fragment = $~[1..-1] if rel_segment && abs_path path = rel_segment + abs_path elsif rel_segment path = rel_segment elsif abs_path path = abs_path end # URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ] # relativeURI = ( net_path | abs_path | rel_path ) [ "?" query ] # net_path = "//" authority [ abs_path ] # abs_path = "/" path_segments # rel_path = rel_segment [ abs_path ] # authority = server | reg_name # server = [ [ userinfo "@" ] hostport ] else raise InvalidURIError, "bad URI(is not URI?): #{uri}" end path = '' if !path && !opaque # (see RFC2396 Section 5.2) ret = [ scheme, userinfo, host, port, # X registry, # X path, # Y opaque, # Y query, fragment ] return ret end # # == Args # # +uri+:: # String # # == Description # # parses +uri+ and constructs either matching URI scheme object # (FTP, HTTP, HTTPS, LDAP, LDAPS, or MailTo) or URI::Generic # # == Usage # # p = URI::Parser.new # p.parse("ldap://ldap.example.com/dc=example?user=john") # #=> # # def parse(uri) scheme, userinfo, host, port, registry, path, opaque, query, fragment = self.split(uri) if scheme && URI.scheme_list.include?(scheme.upcase) URI.scheme_list[scheme.upcase].new(scheme, userinfo, host, port, registry, path, opaque, query, fragment, self) else Generic.new(scheme, userinfo, host, port, registry, path, opaque, query, fragment, self) end end # # == Args # # +uris+:: # an Array of Strings # # == Description # # Attempts to parse and merge a set of URIs # def join(*uris) uris[0] = convert_to_uri(uris[0]) uris.inject :merge end # # :call-seq: # extract( str ) # extract( str, schemes ) # extract( str, schemes ) {|item| block } # # == Args # # +str+:: # String to search # +schemes+:: # Patterns to apply to +str+ # # == Description # # Attempts to parse and merge a set of URIs # If no +block+ given , then returns the result, # else it calls +block+ for each element in result. # # see also URI::Parser.make_regexp # def extract(str, schemes = nil) if block_given? str.scan(make_regexp(schemes)) { yield $& } nil else result = [] str.scan(make_regexp(schemes)) { result.push $& } result end end # returns Regexp that is default self.regexp[:ABS_URI_REF], # unless +schemes+ is provided. Then it is a Regexp.union with self.pattern[:X_ABS_URI] def make_regexp(schemes = nil) unless schemes @regexp[:ABS_URI_REF] else /(?=#{Regexp.union(*schemes)}:)#{@pattern[:X_ABS_URI]}/x end end # # :call-seq: # escape( str ) # escape( str, unsafe ) # # == Args # # +str+:: # String to make safe # +unsafe+:: # Regexp to apply. Defaults to self.regexp[:UNSAFE] # # == Description # # constructs a safe String from +str+, removing unsafe characters, # replacing them with codes. # def escape(str, unsafe = @regexp[:UNSAFE]) unless unsafe.kind_of?(Regexp) # perhaps unsafe is String object unsafe = Regexp.new("[#{Regexp.quote(unsafe)}]", false) end str.gsub(unsafe) do us = $& tmp = '' us.each_byte do |uc| tmp << sprintf('%%%02X', uc) end tmp end.force_encoding(Encoding::US_ASCII) end # # :call-seq: # unescape( str ) # unescape( str, unsafe ) # # == Args # # +str+:: # String to remove escapes from # +unsafe+:: # Regexp to apply. Defaults to self.regexp[:ESCAPED] # # == Description # # Removes escapes from +str+ # def unescape(str, escaped = @regexp[:ESCAPED]) str.gsub(escaped) { [$&[1, 2].hex].pack('C') }.force_encoding(str.encoding) end @@to_s = Kernel.instance_method(:to_s) def inspect @@to_s.bind(self).call end private # Constructs the default Hash of patterns def initialize_pattern(opts = {}) ret = {} ret[:ESCAPED] = escaped = (opts.delete(:ESCAPED) || PATTERN::ESCAPED) ret[:UNRESERVED] = unreserved = opts.delete(:UNRESERVED) || PATTERN::UNRESERVED ret[:RESERVED] = reserved = opts.delete(:RESERVED) || PATTERN::RESERVED ret[:DOMLABEL] = opts.delete(:DOMLABEL) || PATTERN::DOMLABEL ret[:TOPLABEL] = opts.delete(:TOPLABEL) || PATTERN::TOPLABEL ret[:HOSTNAME] = hostname = opts.delete(:HOSTNAME) # RFC 2396 (URI Generic Syntax) # RFC 2732 (IPv6 Literal Addresses in URL's) # RFC 2373 (IPv6 Addressing Architecture) # uric = reserved | unreserved | escaped ret[:URIC] = uric = "(?:[#{unreserved}#{reserved}]|#{escaped})" # uric_no_slash = unreserved | escaped | ";" | "?" | ":" | "@" | # "&" | "=" | "+" | "$" | "," ret[:URIC_NO_SLASH] = uric_no_slash = "(?:[#{unreserved};?:@&=+$,]|#{escaped})" # query = *uric ret[:QUERY] = query = "#{uric}*" # fragment = *uric ret[:FRAGMENT] = fragment = "#{uric}*" # hostname = *( domainlabel "." ) toplabel [ "." ] # reg-name = *( unreserved / pct-encoded / sub-delims ) # RFC3986 unless hostname ret[:HOSTNAME] = hostname = "(?:[a-zA-Z0-9\\-.]|%\\h\\h)+" end # RFC 2373, APPENDIX B: # IPv6address = hexpart [ ":" IPv4address ] # IPv4address = 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT # hexpart = hexseq | hexseq "::" [ hexseq ] | "::" [ hexseq ] # hexseq = hex4 *( ":" hex4) # hex4 = 1*4HEXDIG # # XXX: This definition has a flaw. "::" + IPv4address must be # allowed too. Here is a replacement. # # IPv4address = 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT ret[:IPV4ADDR] = ipv4addr = "\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}" # hex4 = 1*4HEXDIG hex4 = "[#{PATTERN::HEX}]{1,4}" # lastpart = hex4 | IPv4address lastpart = "(?:#{hex4}|#{ipv4addr})" # hexseq1 = *( hex4 ":" ) hex4 hexseq1 = "(?:#{hex4}:)*#{hex4}" # hexseq2 = *( hex4 ":" ) lastpart hexseq2 = "(?:#{hex4}:)*#{lastpart}" # IPv6address = hexseq2 | [ hexseq1 ] "::" [ hexseq2 ] ret[:IPV6ADDR] = ipv6addr = "(?:#{hexseq2}|(?:#{hexseq1})?::(?:#{hexseq2})?)" # IPv6prefix = ( hexseq1 | [ hexseq1 ] "::" [ hexseq1 ] ) "/" 1*2DIGIT # unused # ipv6reference = "[" IPv6address "]" (RFC 2732) ret[:IPV6REF] = ipv6ref = "\\[#{ipv6addr}\\]" # host = hostname | IPv4address # host = hostname | IPv4address | IPv6reference (RFC 2732) ret[:HOST] = host = "(?:#{hostname}|#{ipv4addr}|#{ipv6ref})" # port = *digit port = '\d*' # hostport = host [ ":" port ] ret[:HOSTPORT] = hostport = "#{host}(?::#{port})?" # userinfo = *( unreserved | escaped | # ";" | ":" | "&" | "=" | "+" | "$" | "," ) ret[:USERINFO] = userinfo = "(?:[#{unreserved};:&=+$,]|#{escaped})*" # pchar = unreserved | escaped | # ":" | "@" | "&" | "=" | "+" | "$" | "," pchar = "(?:[#{unreserved}:@&=+$,]|#{escaped})" # param = *pchar param = "#{pchar}*" # segment = *pchar *( ";" param ) segment = "#{pchar}*(?:;#{param})*" # path_segments = segment *( "/" segment ) ret[:PATH_SEGMENTS] = path_segments = "#{segment}(?:/#{segment})*" # server = [ [ userinfo "@" ] hostport ] server = "(?:#{userinfo}@)?#{hostport}" # reg_name = 1*( unreserved | escaped | "$" | "," | # ";" | ":" | "@" | "&" | "=" | "+" ) ret[:REG_NAME] = reg_name = "(?:[#{unreserved}$,;:@&=+]|#{escaped})+" # authority = server | reg_name authority = "(?:#{server}|#{reg_name})" # rel_segment = 1*( unreserved | escaped | # ";" | "@" | "&" | "=" | "+" | "$" | "," ) ret[:REL_SEGMENT] = rel_segment = "(?:[#{unreserved};@&=+$,]|#{escaped})+" # scheme = alpha *( alpha | digit | "+" | "-" | "." ) ret[:SCHEME] = scheme = "[#{PATTERN::ALPHA}][\\-+.#{PATTERN::ALPHA}\\d]*" # abs_path = "/" path_segments ret[:ABS_PATH] = abs_path = "/#{path_segments}" # rel_path = rel_segment [ abs_path ] ret[:REL_PATH] = rel_path = "#{rel_segment}(?:#{abs_path})?" # net_path = "//" authority [ abs_path ] ret[:NET_PATH] = net_path = "//#{authority}(?:#{abs_path})?" # hier_part = ( net_path | abs_path ) [ "?" query ] ret[:HIER_PART] = hier_part = "(?:#{net_path}|#{abs_path})(?:\\?(?:#{query}))?" # opaque_part = uric_no_slash *uric ret[:OPAQUE_PART] = opaque_part = "#{uric_no_slash}#{uric}*" # absoluteURI = scheme ":" ( hier_part | opaque_part ) ret[:ABS_URI] = abs_uri = "#{scheme}:(?:#{hier_part}|#{opaque_part})" # relativeURI = ( net_path | abs_path | rel_path ) [ "?" query ] ret[:REL_URI] = rel_uri = "(?:#{net_path}|#{abs_path}|#{rel_path})(?:\\?#{query})?" # URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ] ret[:URI_REF] = "(?:#{abs_uri}|#{rel_uri})?(?:##{fragment})?" ret[:X_ABS_URI] = " (#{scheme}): (?# 1: scheme) (?: (#{opaque_part}) (?# 2: opaque) | (?:(?: //(?: (?:(?:(#{userinfo})@)? (?# 3: userinfo) (?:(#{host})(?::(\\d*))?))? (?# 4: host, 5: port) | (#{reg_name}) (?# 6: registry) ) | (?!//)) (?# XXX: '//' is the mark for hostport) (#{abs_path})? (?# 7: path) )(?:\\?(#{query}))? (?# 8: query) ) (?:\\#(#{fragment}))? (?# 9: fragment) " ret[:X_REL_URI] = " (?: (?: // (?: (?:(#{userinfo})@)? (?# 1: userinfo) (#{host})?(?::(\\d*))? (?# 2: host, 3: port) | (#{reg_name}) (?# 4: registry) ) ) | (#{rel_segment}) (?# 5: rel_segment) )? (#{abs_path})? (?# 6: abs_path) (?:\\?(#{query}))? (?# 7: query) (?:\\#(#{fragment}))? (?# 8: fragment) " ret end # Constructs the default Hash of Regexp's def initialize_regexp(pattern) ret = {} # for URI::split ret[:ABS_URI] = Regexp.new('\A\s*' + pattern[:X_ABS_URI] + '\s*\z', Regexp::EXTENDED) ret[:REL_URI] = Regexp.new('\A\s*' + pattern[:X_REL_URI] + '\s*\z', Regexp::EXTENDED) # for URI::extract ret[:URI_REF] = Regexp.new(pattern[:URI_REF]) ret[:ABS_URI_REF] = Regexp.new(pattern[:X_ABS_URI], Regexp::EXTENDED) ret[:REL_URI_REF] = Regexp.new(pattern[:X_REL_URI], Regexp::EXTENDED) # for URI::escape/unescape ret[:ESCAPED] = Regexp.new(pattern[:ESCAPED]) ret[:UNSAFE] = Regexp.new("[^#{pattern[:UNRESERVED]}#{pattern[:RESERVED]}]") # for Generic#initialize ret[:SCHEME] = Regexp.new("\\A#{pattern[:SCHEME]}\\z") ret[:USERINFO] = Regexp.new("\\A#{pattern[:USERINFO]}\\z") ret[:HOST] = Regexp.new("\\A#{pattern[:HOST]}\\z") ret[:PORT] = Regexp.new("\\A#{pattern[:PORT]}\\z") ret[:OPAQUE] = Regexp.new("\\A#{pattern[:OPAQUE_PART]}\\z") ret[:REGISTRY] = Regexp.new("\\A#{pattern[:REG_NAME]}\\z") ret[:ABS_PATH] = Regexp.new("\\A#{pattern[:ABS_PATH]}\\z") ret[:REL_PATH] = Regexp.new("\\A#{pattern[:REL_PATH]}\\z") ret[:QUERY] = Regexp.new("\\A#{pattern[:QUERY]}\\z") ret[:FRAGMENT] = Regexp.new("\\A#{pattern[:FRAGMENT]}\\z") ret end def convert_to_uri(uri) if uri.is_a?(URI::Generic) uri elsif uri = String.try_convert(uri) parse(uri) else raise ArgumentError, "bad argument (expected URI object or URI string)" end end end # class Parser end # module URI PK!o2.2.0/uri/ldaps.rbnu[# = uri/ldap.rb # # License:: You can redistribute it and/or modify it under the same term as Ruby. # # See URI for general documentation # require 'uri/ldap' module URI # The default port for LDAPS URIs is 636, and the scheme is 'ldaps:' rather # than 'ldap:'. Other than that, LDAPS URIs are identical to LDAP URIs; # see URI::LDAP. class LDAPS < LDAP # A Default port of 636 for URI::LDAPS DEFAULT_PORT = 636 end @@schemes['LDAPS'] = LDAPS end PK!rMJ2.2.0/uri/rfc3986_parser.rbnu[module URI class RFC3986_Parser # :nodoc: # URI defined in RFC3986 # this regexp is modified not to host is not empty string RFC3986_URI = /\A(?(?[A-Za-z][+\-.0-9A-Za-z]*):(?\/\/(?(?:(?(?:%\h\h|[!$&-.0-;=A-Z_a-z~])*)@)?(?(?\[(?:(?(?:\h{1,4}:){6}(?\h{1,4}:\h{1,4}|(?(?[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]|\d)\.\g\.\g\.\g))|::(?:\h{1,4}:){5}\g|\h{1,4}?::(?:\h{1,4}:){4}\g|(?:(?:\h{1,4}:)?\h{1,4})?::(?:\h{1,4}:){3}\g|(?:(?:\h{1,4}:){,2}\h{1,4})?::(?:\h{1,4}:){2}\g|(?:(?:\h{1,4}:){,3}\h{1,4})?::\h{1,4}:\g|(?:(?:\h{1,4}:){,4}\h{1,4})?::\g|(?:(?:\h{1,4}:){,5}\h{1,4})?::\h{1,4}|(?:(?:\h{1,4}:){,6}\h{1,4})?::)|(?v\h+\.[!$&-.0-;=A-Z_a-z~]+))\])|\g|(?(?:%\h\h|[!$&-.0-9;=A-Z_a-z~])+))?(?::(?\d*))?)(?(?:\/(?(?:%\h\h|[!$&-.0-;=@-Z_a-z~])*))*)|(?\/(?:(?(?:%\h\h|[!$&-.0-;=@-Z_a-z~])+)(?:\/\g)*)?)|(?\g(?:\/\g)*)|(?))(?:\?(?[^#]*))?(?:\#(?(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*))?)\z/ RFC3986_relative_ref = /\A(?(?\/\/(?(?:(?(?:%\h\h|[!$&-.0-;=A-Z_a-z~])*)@)?(?(?\[(?(?:\h{1,4}:){6}(?\h{1,4}:\h{1,4}|(?(?[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]|\d)\.\g\.\g\.\g))|::(?:\h{1,4}:){5}\g|\h{1,4}?::(?:\h{1,4}:){4}\g|(?:(?:\h{1,4}:){,1}\h{1,4})?::(?:\h{1,4}:){3}\g|(?:(?:\h{1,4}:){,2}\h{1,4})?::(?:\h{1,4}:){2}\g|(?:(?:\h{1,4}:){,3}\h{1,4})?::\h{1,4}:\g|(?:(?:\h{1,4}:){,4}\h{1,4})?::\g|(?:(?:\h{1,4}:){,5}\h{1,4})?::\h{1,4}|(?:(?:\h{1,4}:){,6}\h{1,4})?::)|(?v\h+\.[!$&-.0-;=A-Z_a-z~]+)\])|\g|(?(?:%\h\h|[!$&-.0-9;=A-Z_a-z~])+))?(?::(?\d*))?)(?(?:\/(?(?:%\h\h|[!$&-.0-;=@-Z_a-z~])*))*)|(?\/(?:(?(?:%\h\h|[!$&-.0-;=@-Z_a-z~])+)(?:\/\g)*)?)|(?(?(?:%\h\h|[!$&-.0-9;=@-Z_a-z~])+)(?:\/\g)*)|(?))(?:\?(?[^#]*))?(?:\#(?(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*))?)\z/ attr_reader :regexp def initialize @regexp = default_regexp.each_value(&:freeze).freeze end def split(uri) #:nodoc: begin uri = uri.to_str rescue NoMethodError raise InvalidURIError, "bad URI(is not URI?): #{uri}" end uri.ascii_only? or raise InvalidURIError, "URI must be ascii only #{uri.dump}" if m = RFC3986_URI.match(uri) query = m["query".freeze] scheme = m["scheme".freeze] opaque = m["path-rootless".freeze] if opaque opaque << "?#{query}" if query [ scheme, nil, # userinfo nil, # host nil, # port nil, # registry nil, # path opaque, nil, # query m["fragment".freeze] ] else # normal [ scheme, m["userinfo".freeze], m["host".freeze], m["port".freeze], nil, # registry (m["path-abempty".freeze] || m["path-absolute".freeze] || m["path-empty".freeze]), nil, # opaque query, m["fragment".freeze] ] end elsif m = RFC3986_relative_ref.match(uri) [ nil, # scheme m["userinfo".freeze], m["host".freeze], m["port".freeze], nil, # registry, (m["path-abempty".freeze] || m["path-absolute".freeze] || m["path-noscheme".freeze] || m["path-empty".freeze]), nil, # opaque m["query".freeze], m["fragment".freeze] ] else raise InvalidURIError, "bad URI(is not URI?): #{uri}" end end def parse(uri) # :nodoc: scheme, userinfo, host, port, registry, path, opaque, query, fragment = self.split(uri) scheme_list = URI.scheme_list if scheme && scheme_list.include?(uc = scheme.upcase) scheme_list[uc].new(scheme, userinfo, host, port, registry, path, opaque, query, fragment, self) else Generic.new(scheme, userinfo, host, port, registry, path, opaque, query, fragment, self) end end def join(*uris) # :nodoc: uris[0] = convert_to_uri(uris[0]) uris.inject :merge end @@to_s = Kernel.instance_method(:to_s) def inspect @@to_s.bind(self).call end private def default_regexp # :nodoc: { SCHEME: /\A[A-Za-z][A-Za-z0-9+\-.]*\z/, USERINFO: /\A(?:%\h\h|[!$&-.0-;=A-Z_a-z~])*\z/, HOST: /\A(?:(?\[(?:(?(?:\h{1,4}:){6}(?\h{1,4}:\h{1,4}|(?(?[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]|\d)\.\g\.\g\.\g))|::(?:\h{1,4}:){5}\g|\h{,4}::(?:\h{1,4}:){4}\g|(?:(?:\h{1,4}:)?\h{1,4})?::(?:\h{1,4}:){3}\g|(?:(?:\h{1,4}:){,2}\h{1,4})?::(?:\h{1,4}:){2}\g|(?:(?:\h{1,4}:){,3}\h{1,4})?::\h{1,4}:\g|(?:(?:\h{1,4}:){,4}\h{1,4})?::\g|(?:(?:\h{1,4}:){,5}\h{1,4})?::\h{1,4}|(?:(?:\h{1,4}:){,6}\h{1,4})?::)|(?v\h+\.[!$&-.0-;=A-Z_a-z~]+))\])|\g|(?(?:%\h\h|[!$&-.0-9;=A-Z_a-z~])*))\z/, ABS_PATH: /\A\/(?:%\h\h|[!$&-.0-;=@-Z_a-z~])*(?:\/(?:%\h\h|[!$&-.0-;=@-Z_a-z~])*)*\z/, REL_PATH: /\A(?:%\h\h|[!$&-.0-;=@-Z_a-z~])+(?:\/(?:%\h\h|[!$&-.0-;=@-Z_a-z~])*)*\z/, QUERY: /\A(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*\z/, FRAGMENT: /\A(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*\z/, OPAQUE: /\A(?:[^\/].*)?\z/, PORT: /\A[\x09\x0a\x0c\x0d ]*\d*[\x09\x0a\x0c\x0d ]*\z/, } end def convert_to_uri(uri) if uri.is_a?(URI::Generic) uri elsif uri = String.try_convert(uri) parse(uri) else raise ArgumentError, "bad argument (expected URI object or URI string)" end end end # class Parser end # module URI PK!J222.2.0/uri/mailto.rbnu[# = uri/mailto.rb # # Author:: Akira Yamada # License:: You can redistribute it and/or modify it under the same term as Ruby. # Revision:: $Id: mailto.rb 55941 2016-08-16 12:02:37Z usa $ # # See URI for general documentation # require 'uri/generic' module URI # # RFC6068, The mailto URL scheme # class MailTo < Generic include REGEXP # A Default port of nil for URI::MailTo DEFAULT_PORT = nil # An Array of the available components for URI::MailTo COMPONENT = [ :scheme, :to, :headers ].freeze # :stopdoc: # "hname" and "hvalue" are encodings of an RFC 822 header name and # value, respectively. As with "to", all URL reserved characters must # be encoded. # # "#mailbox" is as specified in RFC 822 [RFC822]. This means that it # consists of zero or more comma-separated mail addresses, possibly # including "phrase" and "comment" components. Note that all URL # reserved characters in "to" must be encoded: in particular, # parentheses, commas, and the percent sign ("%"), which commonly occur # in the "mailbox" syntax. # # Within mailto URLs, the characters "?", "=", "&" are reserved. # ; RFC 6068 # hfields = "?" hfield *( "&" hfield ) # hfield = hfname "=" hfvalue # hfname = *qchar # hfvalue = *qchar # qchar = unreserved / pct-encoded / some-delims # some-delims = "!" / "$" / "'" / "(" / ")" / "*" # / "+" / "," / ";" / ":" / "@" # # ; RFC3986 # unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" # pct-encoded = "%" HEXDIG HEXDIG HEADER_REGEXP = /\A(?(?:%\h\h|[!$'-.0-;@-Z_a-z~])*=(?:%\h\h|[!$'-.0-;@-Z_a-z~])*)(?:&\g)*\z/ # practical regexp for email address # http://www.whatwg.org/specs/web-apps/current-work/multipage/states-of-the-type-attribute.html#valid-e-mail-address EMAIL_REGEXP = /\A[a-zA-Z0-9.!\#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*\z/ # :startdoc: # # == Description # # Creates a new URI::MailTo object from components, with syntax checking. # # Components can be provided as an Array or Hash. If an Array is used, # the components must be supplied as [to, headers]. # # If a Hash is used, the keys are the component names preceded by colons. # # The headers can be supplied as a pre-encoded string, such as # "subject=subscribe&cc=address", or as an Array of Arrays like # [['subject', 'subscribe'], ['cc', 'address']] # # Examples: # # require 'uri' # # m1 = URI::MailTo.build(['joe@example.com', 'subject=Ruby']) # puts m1.to_s -> mailto:joe@example.com?subject=Ruby # # m2 = URI::MailTo.build(['john@example.com', [['Subject', 'Ruby'], ['Cc', 'jack@example.com']]]) # puts m2.to_s -> mailto:john@example.com?Subject=Ruby&Cc=jack@example.com # # m3 = URI::MailTo.build({:to => 'listman@example.com', :headers => [['subject', 'subscribe']]}) # puts m3.to_s -> mailto:listman@example.com?subject=subscribe # def self.build(args) tmp = Util::make_components_hash(self, args) case tmp[:to] when Array tmp[:opaque] = tmp[:to].join(',') when String tmp[:opaque] = tmp[:to].dup else tmp[:opaque] = '' end if tmp[:headers] query = case tmp[:headers] when Array tmp[:headers].collect { |x| if x.kind_of?(Array) x[0] + '=' + x[1..-1].join else x.to_s end }.join('&') when Hash tmp[:headers].collect { |h,v| h + '=' + v }.join('&') else tmp[:headers].to_s end unless query.empty? tmp[:opaque] << '?' << query end end return super(tmp) end # # == Description # # Creates a new URI::MailTo object from generic URL components with # no syntax checking. # # This method is usually called from URI::parse, which checks # the validity of each component. # def initialize(*arg) super(*arg) @to = nil @headers = [] # The RFC3986 parser does not normally populate opaque @opaque = "?#{@query}" if @query && !@opaque unless @opaque raise InvalidComponentError, "missing opaque part for mailto URL" end to, header = @opaque.split('?', 2) # allow semicolon as a addr-spec separator # http://support.microsoft.com/kb/820868 unless /\A(?:[^@,;]+@[^@,;]+(?:\z|[,;]))*\z/ =~ to raise InvalidComponentError, "unrecognised opaque part for mailtoURL: #{@opaque}" end if arg[10] # arg_check self.to = to self.headers = header else set_to(to) set_headers(header) end end # The primary e-mail address of the URL, as a String attr_reader :to # E-mail headers set by the URL, as an Array of Arrays attr_reader :headers # check the to +v+ component def check_to(v) return true unless v return true if v.size == 0 v.split(/[,;]/).each do |addr| # check url safety as path-rootless if /\A(?:%\h\h|[!$&-.0-;=@-Z_a-z~])*\z/ !~ addr raise InvalidComponentError, "an address in 'to' is invalid as URI #{addr.dump}" end # check addr-spec # don't s/\+/ /g addr.gsub!(/%\h\h/, URI::TBLDECWWWCOMP_) if EMAIL_REGEXP !~ addr raise InvalidComponentError, "an address in 'to' is invalid as uri-escaped addr-spec #{addr.dump}" end end return true end private :check_to # private setter for to +v+ def set_to(v) @to = v end protected :set_to # setter for to +v+ def to=(v) check_to(v) set_to(v) v end # check the headers +v+ component against either # * HEADER_REGEXP def check_headers(v) return true unless v return true if v.size == 0 if HEADER_REGEXP !~ v raise InvalidComponentError, "bad component(expected opaque component): #{v}" end return true end private :check_headers # private setter for headers +v+ def set_headers(v) @headers = [] if v v.split('&').each do |x| @headers << x.split(/=/, 2) end end end protected :set_headers # setter for headers +v+ def headers=(v) check_headers(v) set_headers(v) v end # Constructs String from URI def to_s @scheme + ':' + if @to @to else '' end + if @headers.size > 0 '?' + @headers.collect{|x| x.join('=')}.join('&') else '' end + if @fragment '#' + @fragment else '' end end # Returns the RFC822 e-mail text equivalent of the URL, as a String. # # Example: # # require 'uri' # # uri = URI.parse("mailto:ruby-list@ruby-lang.org?Subject=subscribe&cc=myaddr") # uri.to_mailtext # # => "To: ruby-list@ruby-lang.org\nSubject: subscribe\nCc: myaddr\n\n\n" # def to_mailtext to = parser.unescape(@to) head = '' body = '' @headers.each do |x| case x[0] when 'body' body = parser.unescape(x[1]) when 'to' to << ', ' + parser.unescape(x[1]) else head << parser.unescape(x[0]).capitalize + ': ' + parser.unescape(x[1]) + "\n" end end return "To: #{to} #{head} #{body} " end alias to_rfc822text to_mailtext end @@schemes['MAILTO'] = MailTo end PK! 2.2.0/uri/http.rbnu[# = uri/http.rb # # Author:: Akira Yamada # License:: You can redistribute it and/or modify it under the same term as Ruby. # Revision:: $Id: http.rb 54427 2016-03-29 20:13:52Z nagachika $ # # See URI for general documentation # require 'uri/generic' module URI # # The syntax of HTTP URIs is defined in RFC1738 section 3.3. # # Note that the Ruby URI library allows HTTP URLs containing usernames and # passwords. This is not legal as per the RFC, but used to be # supported in Internet Explorer 5 and 6, before the MS04-004 security # update. See . # class HTTP < Generic # A Default port of 80 for URI::HTTP DEFAULT_PORT = 80 # An Array of the available components for URI::HTTP COMPONENT = [ :scheme, :userinfo, :host, :port, :path, :query, :fragment ].freeze # # == Description # # Create a new URI::HTTP object from components, with syntax checking. # # The components accepted are userinfo, host, port, path, query and # fragment. # # The components should be provided either as an Array, or as a Hash # with keys formed by preceding the component names with a colon. # # If an Array is used, the components must be passed in the order # [userinfo, host, port, path, query, fragment]. # # Example: # # newuri = URI::HTTP.build({:host => 'www.example.com', # :path => '/foo/bar'}) # # newuri = URI::HTTP.build([nil, "www.example.com", nil, "/path", # "query", 'fragment']) # # Currently, if passed userinfo components this method generates # invalid HTTP URIs as per RFC 1738. # def self.build(args) tmp = Util::make_components_hash(self, args) return super(tmp) end =begin # # == Description # # Create a new URI::HTTP object from generic URI components as per # RFC 2396. No HTTP-specific syntax checking (as per RFC 1738) is # performed. # # Arguments are +scheme+, +userinfo+, +host+, +port+, +registry+, +path+, # +opaque+, +query+ and +fragment+, in that order. # # Example: # # uri = URI::HTTP.new("http", nil, "www.example.com", nil, nil, # "/path", nil, "query", "fragment") # # # See also URI::Generic.new # def initialize(*arg) super(*arg) end =end # # == Description # # Returns the full path for an HTTP request, as required by Net::HTTP::Get. # # If the URI contains a query, the full path is URI#path + '?' + URI#query. # Otherwise, the path is simply URI#path. # def request_uri return nil unless @path if @path.start_with?(?/.freeze) @query ? "#@path?#@query" : @path.dup else @query ? "/#@path?#@query" : "/#@path" end end end @@schemes['HTTP'] = HTTP end PK!'>BB2.2.0/uri/ftp.rbnu[# = uri/ftp.rb # # Author:: Akira Yamada # License:: You can redistribute it and/or modify it under the same term as Ruby. # Revision:: $Id: ftp.rb 46489 2014-06-22 00:21:57Z naruse $ # # See URI for general documentation # require 'uri/generic' module URI # # FTP URI syntax is defined by RFC1738 section 3.2. # # This class will be redesigned because of difference of implementations; # the structure of its path. draft-hoffman-ftp-uri-04 is a draft but it # is a good summary about the de facto spec. # http://tools.ietf.org/html/draft-hoffman-ftp-uri-04 # class FTP < Generic # A Default port of 21 for URI::FTP DEFAULT_PORT = 21 # # An Array of the available components for URI::FTP # COMPONENT = [ :scheme, :userinfo, :host, :port, :path, :typecode ].freeze # # Typecode is "a", "i" or "d". # # * "a" indicates a text file (the FTP command was ASCII) # * "i" indicates a binary file (FTP command IMAGE) # * "d" indicates the contents of a directory should be displayed # TYPECODE = ['a', 'i', 'd'].freeze # Typecode prefix # ';type=' TYPECODE_PREFIX = ';type='.freeze def self.new2(user, password, host, port, path, typecode = nil, arg_check = true) # :nodoc: # Do not use this method! Not tested. [Bug #7301] # This methods remains just for compatibility, # Keep it undocumented until the active maintainer is assigned. typecode = nil if typecode.size == 0 if typecode && !TYPECODE.include?(typecode) raise ArgumentError, "bad typecode is specified: #{typecode}" end # do escape self.new('ftp', [user, password], host, port, nil, typecode ? path + TYPECODE_PREFIX + typecode : path, nil, nil, nil, arg_check) end # # == Description # # Creates a new URI::FTP object from components, with syntax checking. # # The components accepted are +userinfo+, +host+, +port+, +path+ and # +typecode+. # # The components should be provided either as an Array, or as a Hash # with keys formed by preceding the component names with a colon. # # If an Array is used, the components must be passed in the order # [userinfo, host, port, path, typecode] # # If the path supplied is absolute, it will be escaped in order to # make it absolute in the URI. Examples: # # require 'uri' # # uri = URI::FTP.build(['user:password', 'ftp.example.com', nil, # '/path/file.> zip', 'i']) # puts uri.to_s -> ftp://user:password@ftp.example.com/%2Fpath/file.zip;type=a # # uri2 = URI::FTP.build({:host => 'ftp.example.com', # :path => 'ruby/src'}) # puts uri2.to_s -> ftp://ftp.example.com/ruby/src # def self.build(args) # Fix the incoming path to be generic URL syntax # FTP path -> URL path # foo/bar /foo/bar # /foo/bar /%2Ffoo/bar # if args.kind_of?(Array) args[3] = '/' + args[3].sub(/^\//, '%2F') else args[:path] = '/' + args[:path].sub(/^\//, '%2F') end tmp = Util::make_components_hash(self, args) if tmp[:typecode] if tmp[:typecode].size == 1 tmp[:typecode] = TYPECODE_PREFIX + tmp[:typecode] end tmp[:path] << tmp[:typecode] end return super(tmp) end # # == Description # # Creates a new URI::FTP object from generic URL components with no # syntax checking. # # Unlike build(), this method does not escape the path component as # required by RFC1738; instead it is treated as per RFC2396. # # Arguments are +scheme+, +userinfo+, +host+, +port+, +registry+, +path+, # +opaque+, +query+ and +fragment+, in that order. # def initialize(scheme, userinfo, host, port, registry, path, opaque, query, fragment, parser = nil, arg_check = false) raise InvalidURIError unless path path = path.sub(/^\//,'') path.sub!(/^%2F/,'/') super(scheme, userinfo, host, port, registry, path, opaque, query, fragment, parser, arg_check) @typecode = nil if tmp = @path.index(TYPECODE_PREFIX) typecode = @path[tmp + TYPECODE_PREFIX.size..-1] @path = @path[0..tmp - 1] if arg_check self.typecode = typecode else self.set_typecode(typecode) end end end # typecode accessor # # see URI::FTP::COMPONENT attr_reader :typecode # validates typecode +v+, # returns a +true+ or +false+ boolean # def check_typecode(v) if TYPECODE.include?(v) return true else raise InvalidComponentError, "bad typecode(expected #{TYPECODE.join(', ')}): #{v}" end end private :check_typecode # Private setter for the typecode +v+ # # see also URI::FTP.typecode= # def set_typecode(v) @typecode = v end protected :set_typecode # # == Args # # +v+:: # String # # == Description # # public setter for the typecode +v+. # (with validation) # # see also URI::FTP.check_typecode # # == Usage # # require 'uri' # # uri = URI.parse("ftp://john@ftp.example.com/my_file.img") # #=> # # uri.typecode = "i" # # => "i" # uri # #=> # # def typecode=(typecode) check_typecode(typecode) set_typecode(typecode) typecode end def merge(oth) # :nodoc: tmp = super(oth) if self != tmp tmp.set_typecode(oth.typecode) end return tmp end # Returns the path from an FTP URI. # # RFC 1738 specifically states that the path for an FTP URI does not # include the / which separates the URI path from the URI host. Example: # # ftp://ftp.example.com/pub/ruby # # The above URI indicates that the client should connect to # ftp.example.com then cd pub/ruby from the initial login directory. # # If you want to cd to an absolute directory, you must include an # escaped / (%2F) in the path. Example: # # ftp://ftp.example.com/%2Fpub/ruby # # This method will then return "/pub/ruby" # def path return @path.sub(/^\//,'').sub(/^%2F/,'/') end # Private setter for the path of the URI::FTP def set_path(v) super("/" + v.sub(/^\//, "%2F")) end protected :set_path # Returns a String representation of the URI::FTP def to_s save_path = nil if @typecode save_path = @path @path = @path + TYPECODE_PREFIX + @typecode end str = super if @typecode @path = save_path end return str end end @@schemes['FTP'] = FTP end PK!u2qMqM2.2.0/uri/common.rbnu[#-- # = uri/common.rb # # Author:: Akira Yamada # Revision:: $Id: common.rb 47299 2014-08-27 12:21:41Z hsbt $ # License:: # You can redistribute it and/or modify it under the same term as Ruby. # # See URI for general documentation # require "uri/rfc2396_parser" require "uri/rfc3986_parser" module URI REGEXP = RFC2396_REGEXP Parser = RFC2396_Parser RFC3986_PARSER = RFC3986_Parser.new # URI::Parser.new DEFAULT_PARSER = Parser.new DEFAULT_PARSER.pattern.each_pair do |sym, str| unless REGEXP::PATTERN.const_defined?(sym) REGEXP::PATTERN.const_set(sym, str) end end DEFAULT_PARSER.regexp.each_pair do |sym, str| const_set(sym, str) end module Util # :nodoc: def make_components_hash(klass, array_hash) tmp = {} if array_hash.kind_of?(Array) && array_hash.size == klass.component.size - 1 klass.component[1..-1].each_index do |i| begin tmp[klass.component[i + 1]] = array_hash[i].clone rescue TypeError tmp[klass.component[i + 1]] = array_hash[i] end end elsif array_hash.kind_of?(Hash) array_hash.each do |key, value| begin tmp[key] = value.clone rescue TypeError tmp[key] = value end end else raise ArgumentError, "expected Array of or Hash of components of #{klass} (#{klass.component[1..-1].join(', ')})" end tmp[:scheme] = klass.to_s.sub(/\A.*::/, '').downcase return tmp end module_function :make_components_hash end # module for escaping unsafe characters with codes. module Escape # # == Synopsis # # URI.escape(str [, unsafe]) # # == Args # # +str+:: # String to replaces in. # +unsafe+:: # Regexp that matches all symbols that must be replaced with codes. # By default uses REGEXP::UNSAFE. # When this argument is a String, it represents a character set. # # == Description # # Escapes the string, replacing all unsafe characters with codes. # # == Usage # # require 'uri' # # enc_uri = URI.escape("http://example.com/?a=\11\15") # p enc_uri # # => "http://example.com/?a=%09%0D" # # p URI.unescape(enc_uri) # # => "http://example.com/?a=\t\r" # # p URI.escape("@?@!", "!?") # # => "@%3F@%21" # def escape(*arg) warn "#{caller(1)[0]}: warning: URI.escape is obsolete" if $VERBOSE DEFAULT_PARSER.escape(*arg) end alias encode escape # # == Synopsis # # URI.unescape(str) # # == Args # # +str+:: # Unescapes the string. # # == Usage # # require 'uri' # # enc_uri = URI.escape("http://example.com/?a=\11\15") # p enc_uri # # => "http://example.com/?a=%09%0D" # # p URI.unescape(enc_uri) # # => "http://example.com/?a=\t\r" # def unescape(*arg) warn "#{caller(1)[0]}: warning: URI.unescape is obsolete" if $VERBOSE DEFAULT_PARSER.unescape(*arg) end alias decode unescape end # module Escape extend Escape include REGEXP @@schemes = {} # Returns a Hash of the defined schemes def self.scheme_list @@schemes end # # Base class for all URI exceptions. # class Error < StandardError; end # # Not a URI. # class InvalidURIError < Error; end # # Not a URI component. # class InvalidComponentError < Error; end # # URI is valid, bad usage is not. # class BadURIError < Error; end # # == Synopsis # # URI::split(uri) # # == Args # # +uri+:: # String with URI. # # == Description # # Splits the string on following parts and returns array with result: # # * Scheme # * Userinfo # * Host # * Port # * Registry # * Path # * Opaque # * Query # * Fragment # # == Usage # # require 'uri' # # p URI.split("http://www.ruby-lang.org/") # # => ["http", nil, "www.ruby-lang.org", nil, nil, "/", nil, nil, nil] # def self.split(uri) RFC3986_PARSER.split(uri) end # # == Synopsis # # URI::parse(uri_str) # # == Args # # +uri_str+:: # String with URI. # # == Description # # Creates one of the URI's subclasses instance from the string. # # == Raises # # URI::InvalidURIError # Raised if URI given is not a correct one. # # == Usage # # require 'uri' # # uri = URI.parse("http://www.ruby-lang.org/") # p uri # # => # # p uri.scheme # # => "http" # p uri.host # # => "www.ruby-lang.org" # # It's recommended to first ::escape the provided +uri_str+ if there are any # invalid URI characters. # def self.parse(uri) RFC3986_PARSER.parse(uri) end # # == Synopsis # # URI::join(str[, str, ...]) # # == Args # # +str+:: # String(s) to work with, will be converted to RFC3986 URIs before merging. # # == Description # # Joins URIs. # # == Usage # # require 'uri' # # p URI.join("http://example.com/","main.rbx") # # => # # # p URI.join('http://example.com', 'foo') # # => # # # p URI.join('http://example.com', '/foo', '/bar') # # => # # # p URI.join('http://example.com', '/foo', 'bar') # # => # # # p URI.join('http://example.com', '/foo/', 'bar') # # => # # # def self.join(*str) RFC3986_PARSER.join(*str) end # # == Synopsis # # URI::extract(str[, schemes][,&blk]) # # == Args # # +str+:: # String to extract URIs from. # +schemes+:: # Limit URI matching to a specific schemes. # # == Description # # Extracts URIs from a string. If block given, iterates through all matched URIs. # Returns nil if block given or array with matches. # # == Usage # # require "uri" # # URI.extract("text here http://foo.example.org/bla and here mailto:test@example.com and here also.") # # => ["http://foo.example.com/bla", "mailto:test@example.com"] # def self.extract(str, schemes = nil, &block) warn "#{caller(1)[0]}: warning: URI.extract is obsolete" if $VERBOSE DEFAULT_PARSER.extract(str, schemes, &block) end # # == Synopsis # # URI::regexp([match_schemes]) # # == Args # # +match_schemes+:: # Array of schemes. If given, resulting regexp matches to URIs # whose scheme is one of the match_schemes. # # == Description # Returns a Regexp object which matches to URI-like strings. # The Regexp object returned by this method includes arbitrary # number of capture group (parentheses). Never rely on it's number. # # == Usage # # require 'uri' # # # extract first URI from html_string # html_string.slice(URI.regexp) # # # remove ftp URIs # html_string.sub(URI.regexp(['ftp']) # # # You should not rely on the number of parentheses # html_string.scan(URI.regexp) do |*matches| # p $& # end # def self.regexp(schemes = nil) warn "#{caller(1)[0]}: warning: URI.regexp is obsolete" if $VERBOSE DEFAULT_PARSER.make_regexp(schemes) end TBLENCWWWCOMP_ = {} # :nodoc: 256.times do |i| TBLENCWWWCOMP_[i.chr] = '%%%02X' % i end TBLENCWWWCOMP_[' '] = '+' TBLENCWWWCOMP_.freeze TBLDECWWWCOMP_ = {} # :nodoc: 256.times do |i| h, l = i>>4, i&15 TBLDECWWWCOMP_['%%%X%X' % [h, l]] = i.chr TBLDECWWWCOMP_['%%%x%X' % [h, l]] = i.chr TBLDECWWWCOMP_['%%%X%x' % [h, l]] = i.chr TBLDECWWWCOMP_['%%%x%x' % [h, l]] = i.chr end TBLDECWWWCOMP_['+'] = ' ' TBLDECWWWCOMP_.freeze HTML5ASCIIINCOMPAT = [Encoding::UTF_7, Encoding::UTF_16BE, Encoding::UTF_16LE, Encoding::UTF_32BE, Encoding::UTF_32LE] # :nodoc: # Encode given +str+ to URL-encoded form data. # # This method doesn't convert *, -, ., 0-9, A-Z, _, a-z, but does convert SP # (ASCII space) to + and converts others to %XX. # # If +enc+ is given, convert +str+ to the encoding before percent encoding. # # This is an implementation of # http://www.w3.org/TR/2013/CR-html5-20130806/forms.html#url-encoded-form-data # # See URI.decode_www_form_component, URI.encode_www_form def self.encode_www_form_component(str, enc=nil) str = str.to_s.dup if str.encoding != Encoding::ASCII_8BIT if enc && enc != Encoding::ASCII_8BIT str.encode!(Encoding::UTF_8, invalid: :replace, undef: :replace) str.encode!(enc, fallback: ->(x){"&#{x.ord};"}) end str.force_encoding(Encoding::ASCII_8BIT) end str.gsub!(/[^*\-.0-9A-Z_a-z]/, TBLENCWWWCOMP_) str.force_encoding(Encoding::US_ASCII) end # Decode given +str+ of URL-encoded form data. # # This decodes + to SP. # # See URI.encode_www_form_component, URI.decode_www_form def self.decode_www_form_component(str, enc=Encoding::UTF_8) raise ArgumentError, "invalid %-encoding (#{str})" if /%(?!\h\h)/ =~ str str.b.gsub(/\+|%\h\h/, TBLDECWWWCOMP_).force_encoding(enc) end # Generate URL-encoded form data from given +enum+. # # This generates application/x-www-form-urlencoded data defined in HTML5 # from given an Enumerable object. # # This internally uses URI.encode_www_form_component(str). # # This method doesn't convert the encoding of given items, so convert them # before call this method if you want to send data as other than original # encoding or mixed encoding data. (Strings which are encoded in an HTML5 # ASCII incompatible encoding are converted to UTF-8.) # # This method doesn't handle files. When you send a file, use # multipart/form-data. # # This refers http://url.spec.whatwg.org/#concept-urlencoded-serializer # # URI.encode_www_form([["q", "ruby"], ["lang", "en"]]) # #=> "q=ruby&lang=en" # URI.encode_www_form("q" => "ruby", "lang" => "en") # #=> "q=ruby&lang=en" # URI.encode_www_form("q" => ["ruby", "perl"], "lang" => "en") # #=> "q=ruby&q=perl&lang=en" # URI.encode_www_form([["q", "ruby"], ["q", "perl"], ["lang", "en"]]) # #=> "q=ruby&q=perl&lang=en" # # See URI.encode_www_form_component, URI.decode_www_form def self.encode_www_form(enum, enc=nil) enum.map do |k,v| if v.nil? encode_www_form_component(k, enc) elsif v.respond_to?(:to_ary) v.to_ary.map do |w| str = encode_www_form_component(k, enc) unless w.nil? str << '=' str << encode_www_form_component(w, enc) end end.join('&') else str = encode_www_form_component(k, enc) str << '=' str << encode_www_form_component(v, enc) end end.join('&') end # Decode URL-encoded form data from given +str+. # # This decodes application/x-www-form-urlencoded data # and returns array of key-value array. # # This refers http://url.spec.whatwg.org/#concept-urlencoded-parser , # so this supports only &-separator, don't support ;-separator. # # ary = URI.decode_www_form("a=1&a=2&b=3") # p ary #=> [['a', '1'], ['a', '2'], ['b', '3']] # p ary.assoc('a').last #=> '1' # p ary.assoc('b').last #=> '3' # p ary.rassoc('a').last #=> '2' # p Hash[ary] # => {"a"=>"2", "b"=>"3"} # # See URI.decode_www_form_component, URI.encode_www_form def self.decode_www_form(str, enc=Encoding::UTF_8, separator: '&', use__charset_: false, isindex: false) raise ArgumentError, "the input of #{self.name}.#{__method__} must be ASCII only string" unless str.ascii_only? ary = [] return ary if str.empty? enc = Encoding.find(enc) str.b.each_line(separator) do |string| string.chomp!(separator) key, sep, val = string.partition('=') if isindex if sep.empty? val = key key = '' end isindex = false end if use__charset_ and key == '_charset_' and e = get_encoding(val) enc = e use__charset_ = false end key.gsub!(/\+|%\h\h/, TBLDECWWWCOMP_) if val val.gsub!(/\+|%\h\h/, TBLDECWWWCOMP_) else val = '' end ary << [key, val] end ary.each do |k, v| k.force_encoding(enc) k.scrub! v.force_encoding(enc) v.scrub! end ary end private # curl http://encoding.spec.whatwg.org/encodings.json|rb -rpp -rjson -e'H={};h={"shift_jis"=>"Windows-31J","euc-jp"=>"cp51932","iso-2022-jp"=>"cp50221","x-mac-cyrillic"=>"macCyrillic"};JSON($<.read).map{|x|x["encodings"]}.flatten.each{|x|Encoding.find(n=h.fetch(n=x["name"],n))rescue next;x["labels"].each{|y|H[y]=n}};pp H' WEB_ENCODINGS_ = { "unicode-1-1-utf-8"=>"utf-8", "utf-8"=>"utf-8", "utf8"=>"utf-8", "866"=>"ibm866", "cp866"=>"ibm866", "csibm866"=>"ibm866", "ibm866"=>"ibm866", "csisolatin2"=>"iso-8859-2", "iso-8859-2"=>"iso-8859-2", "iso-ir-101"=>"iso-8859-2", "iso8859-2"=>"iso-8859-2", "iso88592"=>"iso-8859-2", "iso_8859-2"=>"iso-8859-2", "iso_8859-2:1987"=>"iso-8859-2", "l2"=>"iso-8859-2", "latin2"=>"iso-8859-2", "csisolatin3"=>"iso-8859-3", "iso-8859-3"=>"iso-8859-3", "iso-ir-109"=>"iso-8859-3", "iso8859-3"=>"iso-8859-3", "iso88593"=>"iso-8859-3", "iso_8859-3"=>"iso-8859-3", "iso_8859-3:1988"=>"iso-8859-3", "l3"=>"iso-8859-3", "latin3"=>"iso-8859-3", "csisolatin4"=>"iso-8859-4", "iso-8859-4"=>"iso-8859-4", "iso-ir-110"=>"iso-8859-4", "iso8859-4"=>"iso-8859-4", "iso88594"=>"iso-8859-4", "iso_8859-4"=>"iso-8859-4", "iso_8859-4:1988"=>"iso-8859-4", "l4"=>"iso-8859-4", "latin4"=>"iso-8859-4", "csisolatincyrillic"=>"iso-8859-5", "cyrillic"=>"iso-8859-5", "iso-8859-5"=>"iso-8859-5", "iso-ir-144"=>"iso-8859-5", "iso8859-5"=>"iso-8859-5", "iso88595"=>"iso-8859-5", "iso_8859-5"=>"iso-8859-5", "iso_8859-5:1988"=>"iso-8859-5", "arabic"=>"iso-8859-6", "asmo-708"=>"iso-8859-6", "csiso88596e"=>"iso-8859-6", "csiso88596i"=>"iso-8859-6", "csisolatinarabic"=>"iso-8859-6", "ecma-114"=>"iso-8859-6", "iso-8859-6"=>"iso-8859-6", "iso-8859-6-e"=>"iso-8859-6", "iso-8859-6-i"=>"iso-8859-6", "iso-ir-127"=>"iso-8859-6", "iso8859-6"=>"iso-8859-6", "iso88596"=>"iso-8859-6", "iso_8859-6"=>"iso-8859-6", "iso_8859-6:1987"=>"iso-8859-6", "csisolatingreek"=>"iso-8859-7", "ecma-118"=>"iso-8859-7", "elot_928"=>"iso-8859-7", "greek"=>"iso-8859-7", "greek8"=>"iso-8859-7", "iso-8859-7"=>"iso-8859-7", "iso-ir-126"=>"iso-8859-7", "iso8859-7"=>"iso-8859-7", "iso88597"=>"iso-8859-7", "iso_8859-7"=>"iso-8859-7", "iso_8859-7:1987"=>"iso-8859-7", "sun_eu_greek"=>"iso-8859-7", "csiso88598e"=>"iso-8859-8", "csisolatinhebrew"=>"iso-8859-8", "hebrew"=>"iso-8859-8", "iso-8859-8"=>"iso-8859-8", "iso-8859-8-e"=>"iso-8859-8", "iso-ir-138"=>"iso-8859-8", "iso8859-8"=>"iso-8859-8", "iso88598"=>"iso-8859-8", "iso_8859-8"=>"iso-8859-8", "iso_8859-8:1988"=>"iso-8859-8", "visual"=>"iso-8859-8", "csisolatin6"=>"iso-8859-10", "iso-8859-10"=>"iso-8859-10", "iso-ir-157"=>"iso-8859-10", "iso8859-10"=>"iso-8859-10", "iso885910"=>"iso-8859-10", "l6"=>"iso-8859-10", "latin6"=>"iso-8859-10", "iso-8859-13"=>"iso-8859-13", "iso8859-13"=>"iso-8859-13", "iso885913"=>"iso-8859-13", "iso-8859-14"=>"iso-8859-14", "iso8859-14"=>"iso-8859-14", "iso885914"=>"iso-8859-14", "csisolatin9"=>"iso-8859-15", "iso-8859-15"=>"iso-8859-15", "iso8859-15"=>"iso-8859-15", "iso885915"=>"iso-8859-15", "iso_8859-15"=>"iso-8859-15", "l9"=>"iso-8859-15", "iso-8859-16"=>"iso-8859-16", "cskoi8r"=>"koi8-r", "koi"=>"koi8-r", "koi8"=>"koi8-r", "koi8-r"=>"koi8-r", "koi8_r"=>"koi8-r", "koi8-u"=>"koi8-u", "dos-874"=>"windows-874", "iso-8859-11"=>"windows-874", "iso8859-11"=>"windows-874", "iso885911"=>"windows-874", "tis-620"=>"windows-874", "windows-874"=>"windows-874", "cp1250"=>"windows-1250", "windows-1250"=>"windows-1250", "x-cp1250"=>"windows-1250", "cp1251"=>"windows-1251", "windows-1251"=>"windows-1251", "x-cp1251"=>"windows-1251", "ansi_x3.4-1968"=>"windows-1252", "ascii"=>"windows-1252", "cp1252"=>"windows-1252", "cp819"=>"windows-1252", "csisolatin1"=>"windows-1252", "ibm819"=>"windows-1252", "iso-8859-1"=>"windows-1252", "iso-ir-100"=>"windows-1252", "iso8859-1"=>"windows-1252", "iso88591"=>"windows-1252", "iso_8859-1"=>"windows-1252", "iso_8859-1:1987"=>"windows-1252", "l1"=>"windows-1252", "latin1"=>"windows-1252", "us-ascii"=>"windows-1252", "windows-1252"=>"windows-1252", "x-cp1252"=>"windows-1252", "cp1253"=>"windows-1253", "windows-1253"=>"windows-1253", "x-cp1253"=>"windows-1253", "cp1254"=>"windows-1254", "csisolatin5"=>"windows-1254", "iso-8859-9"=>"windows-1254", "iso-ir-148"=>"windows-1254", "iso8859-9"=>"windows-1254", "iso88599"=>"windows-1254", "iso_8859-9"=>"windows-1254", "iso_8859-9:1989"=>"windows-1254", "l5"=>"windows-1254", "latin5"=>"windows-1254", "windows-1254"=>"windows-1254", "x-cp1254"=>"windows-1254", "cp1255"=>"windows-1255", "windows-1255"=>"windows-1255", "x-cp1255"=>"windows-1255", "cp1256"=>"windows-1256", "windows-1256"=>"windows-1256", "x-cp1256"=>"windows-1256", "cp1257"=>"windows-1257", "windows-1257"=>"windows-1257", "x-cp1257"=>"windows-1257", "cp1258"=>"windows-1258", "windows-1258"=>"windows-1258", "x-cp1258"=>"windows-1258", "x-mac-cyrillic"=>"macCyrillic", "x-mac-ukrainian"=>"macCyrillic", "chinese"=>"gbk", "csgb2312"=>"gbk", "csiso58gb231280"=>"gbk", "gb2312"=>"gbk", "gb_2312"=>"gbk", "gb_2312-80"=>"gbk", "gbk"=>"gbk", "iso-ir-58"=>"gbk", "x-gbk"=>"gbk", "gb18030"=>"gb18030", "big5"=>"big5", "big5-hkscs"=>"big5", "cn-big5"=>"big5", "csbig5"=>"big5", "x-x-big5"=>"big5", "cseucpkdfmtjapanese"=>"cp51932", "euc-jp"=>"cp51932", "x-euc-jp"=>"cp51932", "csiso2022jp"=>"cp50221", "iso-2022-jp"=>"cp50221", "csshiftjis"=>"Windows-31J", "ms_kanji"=>"Windows-31J", "shift-jis"=>"Windows-31J", "shift_jis"=>"Windows-31J", "sjis"=>"Windows-31J", "windows-31j"=>"Windows-31J", "x-sjis"=>"Windows-31J", "cseuckr"=>"euc-kr", "csksc56011987"=>"euc-kr", "euc-kr"=>"euc-kr", "iso-ir-149"=>"euc-kr", "korean"=>"euc-kr", "ks_c_5601-1987"=>"euc-kr", "ks_c_5601-1989"=>"euc-kr", "ksc5601"=>"euc-kr", "ksc_5601"=>"euc-kr", "windows-949"=>"euc-kr", "utf-16be"=>"utf-16be", "utf-16"=>"utf-16le", "utf-16le"=>"utf-16le" } # :nodoc: # :nodoc: # return encoding or nil # http://encoding.spec.whatwg.org/#concept-encoding-get def self.get_encoding(label) Encoding.find(WEB_ENCODINGS_[label.to_str.strip.downcase]) rescue nil end end # module URI module Kernel # # Returns +uri+ converted to a URI object. # def URI(uri) if uri.is_a?(URI::Generic) uri elsif uri = String.try_convert(uri) URI.parse(uri) else raise ArgumentError, "bad argument (expected URI object or URI string)" end end module_function :URI end PK!1r2.2.0/uri/ldap.rbnu[# = uri/ldap.rb # # Author:: # Takaaki Tateishi # Akira Yamada # License:: # URI::LDAP is copyrighted free software by Takaaki Tateishi and Akira Yamada. # You can redistribute it and/or modify it under the same term as Ruby. # Revision:: $Id: ldap.rb 31555 2011-05-13 20:03:21Z drbrain $ # # See URI for general documentation # require 'uri/generic' module URI # # LDAP URI SCHEMA (described in RFC2255) # ldap:///[?[?[?[?]]]] # class LDAP < Generic # A Default port of 389 for URI::LDAP DEFAULT_PORT = 389 # An Array of the available components for URI::LDAP COMPONENT = [ :scheme, :host, :port, :dn, :attributes, :scope, :filter, :extensions, ].freeze # Scopes available for the starting point. # # * SCOPE_BASE - the Base DN # * SCOPE_ONE - one level under the Base DN, not including the base DN and # not including any entries under this. # * SCOPE_SUB - subtress, all entries at all levels # SCOPE = [ SCOPE_ONE = 'one', SCOPE_SUB = 'sub', SCOPE_BASE = 'base', ].freeze # # == Description # # Create a new URI::LDAP object from components, with syntax checking. # # The components accepted are host, port, dn, attributes, # scope, filter, and extensions. # # The components should be provided either as an Array, or as a Hash # with keys formed by preceding the component names with a colon. # # If an Array is used, the components must be passed in the order # [host, port, dn, attributes, scope, filter, extensions]. # # Example: # # newuri = URI::LDAP.build({:host => 'ldap.example.com', # :dn> => '/dc=example'}) # # newuri = URI::LDAP.build(["ldap.example.com", nil, # "/dc=example;dc=com", "query", nil, nil, nil]) # def self.build(args) tmp = Util::make_components_hash(self, args) if tmp[:dn] tmp[:path] = tmp[:dn] end query = [] [:extensions, :filter, :scope, :attributes].collect do |x| next if !tmp[x] && query.size == 0 query.unshift(tmp[x]) end tmp[:query] = query.join('?') return super(tmp) end # # == Description # # Create a new URI::LDAP object from generic URI components as per # RFC 2396. No LDAP-specific syntax checking is performed. # # Arguments are +scheme+, +userinfo+, +host+, +port+, +registry+, +path+, # +opaque+, +query+ and +fragment+, in that order. # # Example: # # uri = URI::LDAP.new("ldap", nil, "ldap.example.com", nil, # "/dc=example;dc=com", "query", nil, nil, nil, nil) # # # See also URI::Generic.new # def initialize(*arg) super(*arg) if @fragment raise InvalidURIError, 'bad LDAP URL' end parse_dn parse_query end # private method to cleanup +dn+ from using the +path+ component attribute def parse_dn @dn = @path[1..-1] end private :parse_dn # private method to cleanup +attributes+, +scope+, +filter+ and +extensions+, # from using the +query+ component attribute def parse_query @attributes = nil @scope = nil @filter = nil @extensions = nil if @query attrs, scope, filter, extensions = @query.split('?') @attributes = attrs if attrs && attrs.size > 0 @scope = scope if scope && scope.size > 0 @filter = filter if filter && filter.size > 0 @extensions = extensions if extensions && extensions.size > 0 end end private :parse_query # private method to assemble +query+ from +attributes+, +scope+, +filter+ and +extensions+. def build_path_query @path = '/' + @dn query = [] [@extensions, @filter, @scope, @attributes].each do |x| next if !x && query.size == 0 query.unshift(x) end @query = query.join('?') end private :build_path_query # returns dn. def dn @dn end # private setter for dn +val+ def set_dn(val) @dn = val build_path_query @dn end protected :set_dn # setter for dn +val+ def dn=(val) set_dn(val) val end # returns attributes. def attributes @attributes end # private setter for attributes +val+ def set_attributes(val) @attributes = val build_path_query @attributes end protected :set_attributes # setter for attributes +val+ def attributes=(val) set_attributes(val) val end # returns scope. def scope @scope end # private setter for scope +val+ def set_scope(val) @scope = val build_path_query @scope end protected :set_scope # setter for scope +val+ def scope=(val) set_scope(val) val end # returns filter. def filter @filter end # private setter for filter +val+ def set_filter(val) @filter = val build_path_query @filter end protected :set_filter # setter for filter +val+ def filter=(val) set_filter(val) val end # returns extensions. def extensions @extensions end # private setter for extensions +val+ def set_extensions(val) @extensions = val build_path_query @extensions end protected :set_extensions # setter for extensions +val+ def extensions=(val) set_extensions(val) val end # Checks if URI has a path # For URI::LDAP this will return +false+ def hierarchical? false end end @@schemes['LDAP'] = LDAP end PK!E#iv2.2.0/uri/generic.rbnu[# = uri/generic.rb # # Author:: Akira Yamada # License:: You can redistribute it and/or modify it under the same term as Ruby. # Revision:: $Id: generic.rb 56307 2016-09-30 15:57:06Z usa $ # # See URI for general documentation # require 'uri/common' module URI # # Base class for all URI classes. # Implements generic URI syntax as per RFC 2396. # class Generic include URI # # A Default port of nil for URI::Generic # DEFAULT_PORT = nil # # Returns default port # def self.default_port self::DEFAULT_PORT end # # Returns default port # def default_port self.class.default_port end # # An Array of the available components for URI::Generic # COMPONENT = [ :scheme, :userinfo, :host, :port, :registry, :path, :opaque, :query, :fragment ].freeze # # Components of the URI in the order. # def self.component self::COMPONENT end USE_REGISTRY = false # :nodoc: def self.use_registry # :nodoc: self::USE_REGISTRY end # # == Synopsis # # See #new # # == Description # # At first, tries to create a new URI::Generic instance using # URI::Generic::build. But, if exception URI::InvalidComponentError is raised, # then it URI::Escape.escape all URI components and tries again. # # def self.build2(args) begin return self.build(args) rescue InvalidComponentError if args.kind_of?(Array) return self.build(args.collect{|x| if x.is_a?(String) DEFAULT_PARSER.escape(x) else x end }) elsif args.kind_of?(Hash) tmp = {} args.each do |key, value| tmp[key] = if value DEFAULT_PARSER.escape(value) else value end end return self.build(tmp) end end end # # == Synopsis # # See #new # # == Description # # Creates a new URI::Generic instance from components of URI::Generic # with check. Components are: scheme, userinfo, host, port, registry, path, # opaque, query and fragment. You can provide arguments either by an Array or a Hash. # See #new for hash keys to use or for order of array items. # def self.build(args) if args.kind_of?(Array) && args.size == ::URI::Generic::COMPONENT.size tmp = args.dup elsif args.kind_of?(Hash) tmp = ::URI::Generic::COMPONENT.collect do |c| if args.include?(c) args[c] else nil end end else component = self.class.component rescue ::URI::Generic::COMPONENT raise ArgumentError, "expected Array of or Hash of components of #{self.class} (#{component.join(', ')})" end tmp << nil tmp << true return self.new(*tmp) end # # == Args # # +scheme+:: # Protocol scheme, i.e. 'http','ftp','mailto' and so on. # +userinfo+:: # User name and password, i.e. 'sdmitry:bla' # +host+:: # Server host name # +port+:: # Server port # +registry+:: # Registry of naming authorities. # +path+:: # Path on server # +opaque+:: # Opaque part # +query+:: # Query data # +fragment+:: # A part of URI after '#' sign # +parser+:: # Parser for internal use [URI::DEFAULT_PARSER by default] # +arg_check+:: # Check arguments [false by default] # # == Description # # Creates a new URI::Generic instance from ``generic'' components without check. # def initialize(scheme, userinfo, host, port, registry, path, opaque, query, fragment, parser = DEFAULT_PARSER, arg_check = false) @scheme = nil @user = nil @password = nil @host = nil @port = nil @path = nil @query = nil @opaque = nil @fragment = nil @parser = parser == DEFAULT_PARSER ? nil : parser if arg_check self.scheme = scheme self.userinfo = userinfo self.hostname = host self.port = port self.path = path self.query = query self.opaque = opaque self.fragment = fragment else self.set_scheme(scheme) self.set_userinfo(userinfo) self.set_host(host) self.set_port(port) self.set_path(path) self.query = query self.set_opaque(opaque) self.fragment=(fragment) end if registry raise InvalidURIError, "the scheme #{@scheme} does not accept registry part: #{registry} (or bad hostname?)" end @scheme.freeze if @scheme self.set_path('') if !@path && !@opaque # (see RFC2396 Section 5.2) self.set_port(self.default_port) if self.default_port && !@port end # # returns the scheme component of the URI. # # URI("http://foo/bar/baz").scheme #=> "http" # attr_reader :scheme # returns the host component of the URI. # # URI("http://foo/bar/baz").host #=> "foo" # # It returns nil if no host component. # # URI("mailto:foo@example.org").host #=> nil # # The component doesn't contains the port number. # # URI("http://foo:8080/bar/baz").host #=> "foo" # # Since IPv6 addresses are wrapped by brackets in URIs, # this method returns IPv6 addresses wrapped by brackets. # This form is not appropriate to pass socket methods such as TCPSocket.open. # If unwrapped host names are required, use "hostname" method. # # URI("http://[::1]/bar/baz").host #=> "[::1]" # URI("http://[::1]/bar/baz").hostname #=> "::1" # attr_reader :host # returns the port component of the URI. # # URI("http://foo/bar/baz").port #=> "80" # # URI("http://foo:8080/bar/baz").port #=> "8080" # attr_reader :port def registry # :nodoc: nil end # returns the path component of the URI. # # URI("http://foo/bar/baz").path #=> "/bar/baz" # attr_reader :path # returns the query component of the URI. # # URI("http://foo/bar/baz?search=FooBar").query #=> "search=FooBar" # attr_reader :query # returns the opaque part of the URI. # # URI("mailto:foo@example.org").opaque #=> "foo@example.org" # # Portion of the path that does make use of the slash '/'. # The path typically refers to the absolute path and the opaque part. # (see RFC2396 Section 3 and 5.2) # attr_reader :opaque # returns the fragment component of the URI. # # URI("http://foo/bar/baz?search=FooBar#ponies").fragment #=> "ponies" # attr_reader :fragment # returns the parser to be used. # # Unless a URI::Parser is defined, then DEFAULT_PARSER is used. # def parser if !defined?(@parser) || !@parser DEFAULT_PARSER else @parser || DEFAULT_PARSER end end # replace self by other URI object def replace!(oth) if self.class != oth.class raise ArgumentError, "expected #{self.class} object" end component.each do |c| self.__send__("#{c}=", oth.__send__(c)) end end private :replace! # # Components of the URI in the order. # def component self.class.component end # # check the scheme +v+ component against the URI::Parser Regexp for :SCHEME # def check_scheme(v) if v && parser.regexp[:SCHEME] !~ v raise InvalidComponentError, "bad component(expected scheme component): #{v}" end return true end private :check_scheme # protected setter for the scheme component +v+ # # see also URI::Generic.scheme= # def set_scheme(v) @scheme = v ? v.downcase : v end protected :set_scheme # # == Args # # +v+:: # String # # == Description # # public setter for the scheme component +v+. # (with validation) # # see also URI::Generic.check_scheme # # == Usage # # require 'uri' # # uri = URI.parse("http://my.example.com") # uri.scheme = "https" # # => "https" # uri # #=> # # def scheme=(v) check_scheme(v) set_scheme(v) v end # # check the +user+ and +password+. # # If +password+ is not provided, then +user+ is # split, using URI::Generic.split_userinfo, to # pull +user+ and +password. # # see also URI::Generic.check_user, URI::Generic.check_password # def check_userinfo(user, password = nil) if !password user, password = split_userinfo(user) end check_user(user) check_password(password, user) return true end private :check_userinfo # # check the user +v+ component for RFC2396 compliance # and against the URI::Parser Regexp for :USERINFO # # Can not have a registry or opaque component defined, # with a user component defined. # def check_user(v) if @opaque raise InvalidURIError, "can not set user with opaque" end return v unless v if parser.regexp[:USERINFO] !~ v raise InvalidComponentError, "bad component(expected userinfo component or user component): #{v}" end return true end private :check_user # # check the password +v+ component for RFC2396 compliance # and against the URI::Parser Regexp for :USERINFO # # Can not have a registry or opaque component defined, # with a user component defined. # def check_password(v, user = @user) if @opaque raise InvalidURIError, "can not set password with opaque" end return v unless v if !user raise InvalidURIError, "password component depends user component" end if parser.regexp[:USERINFO] !~ v raise InvalidComponentError, "bad password component" end return true end private :check_password # # Sets userinfo, argument is string like 'name:pass' # def userinfo=(userinfo) if userinfo.nil? return nil end check_userinfo(*userinfo) set_userinfo(*userinfo) # returns userinfo end # # == Args # # +v+:: # String # # == Description # # public setter for the +user+ component. # (with validation) # # see also URI::Generic.check_user # # == Usage # # require 'uri' # # uri = URI.parse("http://john:S3nsit1ve@my.example.com") # uri.user = "sam" # # => "sam" # uri # #=> # # def user=(user) check_user(user) set_user(user) # returns user end # # == Args # # +v+:: # String # # == Description # # public setter for the +password+ component. # (with validation) # # see also URI::Generic.check_password # # == Usage # # require 'uri' # # uri = URI.parse("http://john:S3nsit1ve@my.example.com") # uri.password = "V3ry_S3nsit1ve" # # => "V3ry_S3nsit1ve" # uri # #=> # # def password=(password) check_password(password) set_password(password) # returns password end # protect setter for the +user+ component, and +password+ if available. # (with validation) # # see also URI::Generic.userinfo= # def set_userinfo(user, password = nil) unless password user, password = split_userinfo(user) end @user = user @password = password if password [@user, @password] end protected :set_userinfo # protected setter for the user component +v+ # # see also URI::Generic.user= # def set_user(v) set_userinfo(v, @password) v end protected :set_user # protected setter for the password component +v+ # # see also URI::Generic.password= # def set_password(v) @password = v # returns v end protected :set_password # returns the userinfo +ui+ as user, password # if properly formatted as 'user:password' def split_userinfo(ui) return nil, nil unless ui user, password = ui.split(':'.freeze, 2) return user, password end private :split_userinfo # escapes 'user:password' +v+ based on RFC 1738 section 3.1 def escape_userpass(v) parser.escape(v, /[@:\/]/o) # RFC 1738 section 3.1 #/ end private :escape_userpass # returns the userinfo, either as 'user' or 'user:password' def userinfo if @user.nil? nil elsif @password.nil? @user else @user + ':' + @password end end # returns the user component def user @user end # returns the password component def password @password end # # check the host +v+ component for RFC2396 compliance # and against the URI::Parser Regexp for :HOST # # Can not have a registry or opaque component defined, # with a host component defined. # def check_host(v) return v unless v if @opaque raise InvalidURIError, "can not set host with registry or opaque" elsif parser.regexp[:HOST] !~ v raise InvalidComponentError, "bad component(expected host component): #{v}" end return true end private :check_host # protected setter for the host component +v+ # # see also URI::Generic.host= # def set_host(v) @host = v end protected :set_host # # == Args # # +v+:: # String # # == Description # # public setter for the host component +v+. # (with validation) # # see also URI::Generic.check_host # # == Usage # # require 'uri' # # uri = URI.parse("http://my.example.com") # uri.host = "foo.com" # # => "foo.com" # uri # #=> # # def host=(v) check_host(v) set_host(v) v end # extract the host part of the URI and unwrap brackets for IPv6 addresses. # # This method is same as URI::Generic#host except # brackets for IPv6 (and future IP) addresses are removed. # # u = URI("http://[::1]/bar") # p u.hostname #=> "::1" # p u.host #=> "[::1]" # def hostname v = self.host /\A\[(.*)\]\z/ =~ v ? $1 : v end # set the host part of the URI as the argument with brackets for IPv6 addresses. # # This method is same as URI::Generic#host= except # the argument can be bare IPv6 address. # # u = URI("http://foo/bar") # p u.to_s #=> "http://foo/bar" # u.hostname = "::1" # p u.to_s #=> "http://[::1]/bar" # # If the argument seems IPv6 address, # it is wrapped by brackets. # def hostname=(v) v = "[#{v}]" if /\A\[.*\]\z/ !~ v && /:/ =~ v self.host = v end # # check the port +v+ component for RFC2396 compliance # and against the URI::Parser Regexp for :PORT # # Can not have a registry or opaque component defined, # with a port component defined. # def check_port(v) return v unless v if @opaque raise InvalidURIError, "can not set port with registry or opaque" elsif !v.kind_of?(Fixnum) && parser.regexp[:PORT] !~ v raise InvalidComponentError, "bad component(expected port component): #{v.inspect}" end return true end private :check_port # protected setter for the port component +v+ # # see also URI::Generic.port= # def set_port(v) v = v.empty? ? nil : v.to_i unless !v || v.kind_of?(Fixnum) @port = v end protected :set_port # # == Args # # +v+:: # String # # == Description # # public setter for the port component +v+. # (with validation) # # see also URI::Generic.check_port # # == Usage # # require 'uri' # # uri = URI.parse("http://my.example.com") # uri.port = 8080 # # => 8080 # uri # #=> # # def port=(v) check_port(v) set_port(v) port end def check_registry(v) # :nodoc: raise InvalidURIError, "can not set registry" end private :check_registry def set_registry(v) #:nodoc: raise InvalidURIError, "can not set registry" end protected :set_registry def registry=(v) raise InvalidURIError, "can not set registry" end # # check the path +v+ component for RFC2396 compliance # and against the URI::Parser Regexp # for :ABS_PATH and :REL_PATH # # Can not have a opaque component defined, # with a path component defined. # def check_path(v) # raise if both hier and opaque are not nil, because: # absoluteURI = scheme ":" ( hier_part | opaque_part ) # hier_part = ( net_path | abs_path ) [ "?" query ] if v && @opaque raise InvalidURIError, "path conflicts with opaque" end # If scheme is ftp, path may be relative. # See RFC 1738 section 3.2.2, and RFC 2396. if @scheme && @scheme != "ftp".freeze if v && v != ''.freeze && parser.regexp[:ABS_PATH] !~ v raise InvalidComponentError, "bad component(expected absolute path component): #{v}" end else if v && v != ''.freeze && parser.regexp[:ABS_PATH] !~ v && parser.regexp[:REL_PATH] !~ v raise InvalidComponentError, "bad component(expected relative path component): #{v}" end end return true end private :check_path # protected setter for the path component +v+ # # see also URI::Generic.path= # def set_path(v) @path = v end protected :set_path # # == Args # # +v+:: # String # # == Description # # public setter for the path component +v+. # (with validation) # # see also URI::Generic.check_path # # == Usage # # require 'uri' # # uri = URI.parse("http://my.example.com/pub/files") # uri.path = "/faq/" # # => "/faq/" # uri # #=> # # def path=(v) check_path(v) set_path(v) v end # # == Args # # +v+:: # String # # == Description # # public setter for the query component +v+. # # == Usage # # require 'uri' # # uri = URI.parse("http://my.example.com/?id=25") # uri.query = "id=1" # # => "id=1" # uri # #=> # # def query=(v) return @query = nil unless v raise InvalidURIError, "query conflicts with opaque" if @opaque x = v.to_str v = x.dup if x.equal? v v.encode!(Encoding::UTF_8) rescue nil v.delete!("\t\r\n".freeze) v.force_encoding(Encoding::ASCII_8BIT) v.gsub!(/(?!%\h\h|[!$-&(-;=?-_a-~])./n.freeze){'%%%02X'.freeze % $&.ord} v.force_encoding(Encoding::US_ASCII) @query = v end # # check the opaque +v+ component for RFC2396 compliance and # against the URI::Parser Regexp for :OPAQUE # # Can not have a host, port, user or path component defined, # with an opaque component defined. # def check_opaque(v) return v unless v # raise if both hier and opaque are not nil, because: # absoluteURI = scheme ":" ( hier_part | opaque_part ) # hier_part = ( net_path | abs_path ) [ "?" query ] if @host || @port || @user || @path # userinfo = @user + ':' + @password raise InvalidURIError, "can not set opaque with host, port, userinfo or path" elsif v && parser.regexp[:OPAQUE] !~ v raise InvalidComponentError, "bad component(expected opaque component): #{v}" end return true end private :check_opaque # protected setter for the opaque component +v+ # # see also URI::Generic.opaque= # def set_opaque(v) @opaque = v end protected :set_opaque # # == Args # # +v+:: # String # # == Description # # public setter for the opaque component +v+. # (with validation) # # see also URI::Generic.check_opaque # def opaque=(v) check_opaque(v) set_opaque(v) v end # # check the fragment +v+ component against the URI::Parser Regexp for :FRAGMENT # # # == Args # # +v+:: # String # # == Description # # public setter for the fragment component +v+. # (with validation) # # == Usage # # require 'uri' # # uri = URI.parse("http://my.example.com/?id=25#time=1305212049") # uri.fragment = "time=1305212086" # # => "time=1305212086" # uri # #=> # # def fragment=(v) return @fragment = nil unless v x = v.to_str v = x.dup if x.equal? v v.encode!(Encoding::UTF_8) rescue nil v.delete!("\t\r\n".freeze) v.force_encoding(Encoding::ASCII_8BIT) v.gsub!(/(?!%\h\h|[!-~])./n){'%%%02X'.freeze % $&.ord} v.force_encoding(Encoding::US_ASCII) @fragment = v end # # Checks if URI has a path # def hierarchical? if @path true else false end end # # Checks if URI is an absolute one # def absolute? if @scheme true else false end end alias absolute absolute? # # Checks if URI is relative # def relative? !absolute? end # # returns an Array of the path split on '/' # def split_path(path) path.split(%r{/+}, -1) end private :split_path # # Merges a base path +base+, with relative path +rel+, # returns a modified base path. # def merge_path(base, rel) # RFC2396, Section 5.2, 5) # RFC2396, Section 5.2, 6) base_path = split_path(base) rel_path = split_path(rel) # RFC2396, Section 5.2, 6), a) base_path << '' if base_path.last == '..' while i = base_path.index('..') base_path.slice!(i - 1, 2) end if (first = rel_path.first) and first.empty? base_path.clear rel_path.shift end # RFC2396, Section 5.2, 6), c) # RFC2396, Section 5.2, 6), d) rel_path.push('') if rel_path.last == '.' || rel_path.last == '..' rel_path.delete('.') # RFC2396, Section 5.2, 6), e) tmp = [] rel_path.each do |x| if x == '..' && !(tmp.empty? || tmp.last == '..') tmp.pop else tmp << x end end add_trailer_slash = !tmp.empty? if base_path.empty? base_path = [''] # keep '/' for root directory elsif add_trailer_slash base_path.pop end while x = tmp.shift if x == '..' # RFC2396, Section 4 # a .. or . in an absolute path has no special meaning base_path.pop if base_path.size > 1 else # if x == '..' # valid absolute (but abnormal) path "/../..." # else # valid absolute path # end base_path << x tmp.each {|t| base_path << t} add_trailer_slash = false break end end base_path.push('') if add_trailer_slash return base_path.join('/') end private :merge_path # # == Args # # +oth+:: # URI or String # # == Description # # Destructive form of #merge # # == Usage # # require 'uri' # # uri = URI.parse("http://my.example.com") # uri.merge!("/main.rbx?page=1") # p uri # # => # # def merge!(oth) t = merge(oth) if self == t nil else replace!(t) self end end # # == Args # # +oth+:: # URI or String # # == Description # # Merges two URI's. # # == Usage # # require 'uri' # # uri = URI.parse("http://my.example.com") # p uri.merge("/main.rbx?page=1") # # => # # def merge(oth) begin base, rel = merge0(oth) rescue raise $!.class, $!.message end if base == rel return base end authority = rel.userinfo || rel.host || rel.port # RFC2396, Section 5.2, 2) if (rel.path.nil? || rel.path.empty?) && !authority && !rel.query base.fragment=(rel.fragment) if rel.fragment return base end base.query = nil base.fragment=(nil) # RFC2396, Section 5.2, 4) if !authority base.set_path(merge_path(base.path, rel.path)) if base.path && rel.path else # RFC2396, Section 5.2, 4) base.set_path(rel.path) if rel.path end # RFC2396, Section 5.2, 7) base.set_userinfo(rel.userinfo) if rel.userinfo base.set_host(rel.host) if rel.host base.set_port(rel.port) if rel.port base.query = rel.query if rel.query base.fragment=(rel.fragment) if rel.fragment return base end # merge alias + merge # return base and rel. # you can modify `base', but can not `rel'. def merge0(oth) oth = parser.send(:convert_to_uri, oth) if self.relative? && oth.relative? raise BadURIError, "both URI are relative" end if self.absolute? && oth.absolute? #raise BadURIError, # "both URI are absolute" # hmm... should return oth for usability? return oth, oth end if self.absolute? return self.dup, oth else return oth, oth end end private :merge0 # :stopdoc: def route_from_path(src, dst) case dst when src # RFC2396, Section 4.2 return '' when %r{(?:\A|/)\.\.?(?:/|\z)} # dst has abnormal absolute path, # like "/./", "/../", "/x/../", ... return dst.dup end src_path = src.scan(%r{(?:\A|[^/]+)/}) dst_path = dst.scan(%r{(?:\A|[^/]+)/?}) # discard same parts while !dst_path.empty? && dst_path.first == src_path.first src_path.shift dst_path.shift end tmp = dst_path.join # calculate if src_path.empty? if tmp.empty? return './' elsif dst_path.first.include?(':') # (see RFC2396 Section 5) return './' + tmp else return tmp end end return '../' * src_path.size + tmp end private :route_from_path # :startdoc: # :stopdoc: def route_from0(oth) oth = parser.send(:convert_to_uri, oth) if self.relative? raise BadURIError, "relative URI: #{self}" end if oth.relative? raise BadURIError, "relative URI: #{oth}" end if self.scheme != oth.scheme return self, self.dup end rel = URI::Generic.new(nil, # it is relative URI self.userinfo, self.host, self.port, nil, self.path, self.opaque, self.query, self.fragment, parser) if rel.userinfo != oth.userinfo || rel.host.to_s.downcase != oth.host.to_s.downcase || rel.port != oth.port if self.userinfo.nil? && self.host.nil? return self, self.dup end rel.set_port(nil) if rel.port == oth.default_port return rel, rel end rel.set_userinfo(nil) rel.set_host(nil) rel.set_port(nil) if rel.path && rel.path == oth.path rel.set_path('') rel.query = nil if rel.query == oth.query return rel, rel elsif rel.opaque && rel.opaque == oth.opaque rel.set_opaque('') rel.query = nil if rel.query == oth.query return rel, rel end # you can modify `rel', but can not `oth'. return oth, rel end private :route_from0 # :startdoc: # # == Args # # +oth+:: # URI or String # # == Description # # Calculates relative path from oth to self # # == Usage # # require 'uri' # # uri = URI.parse('http://my.example.com/main.rbx?page=1') # p uri.route_from('http://my.example.com') # #=> # # def route_from(oth) # you can modify `rel', but can not `oth'. begin oth, rel = route_from0(oth) rescue raise $!.class, $!.message end if oth == rel return rel end rel.set_path(route_from_path(oth.path, self.path)) if rel.path == './' && self.query # "./?foo" -> "?foo" rel.set_path('') end return rel end alias - route_from # # == Args # # +oth+:: # URI or String # # == Description # # Calculates relative path to oth from self # # == Usage # # require 'uri' # # uri = URI.parse('http://my.example.com') # p uri.route_to('http://my.example.com/main.rbx?page=1') # #=> # # def route_to(oth) parser.send(:convert_to_uri, oth).route_from(self) end # # Returns normalized URI # def normalize uri = dup uri.normalize! uri end # # Destructive version of #normalize # def normalize! if path && path.empty? set_path('/') end if scheme && scheme != scheme.downcase set_scheme(self.scheme.downcase) end if host && host != host.downcase set_host(self.host.downcase) end end # # Constructs String from URI # def to_s str = '' if @scheme str << @scheme str << ':'.freeze end if @opaque str << @opaque else if @host str << '//'.freeze end if self.userinfo str << self.userinfo str << '@'.freeze end if @host str << @host end if @port && @port != self.default_port str << ':'.freeze str << @port.to_s end str << @path if @query str << '?'.freeze str << @query end end if @fragment str << '#'.freeze str << @fragment end str end # # Compares to URI's # def ==(oth) if self.class == oth.class self.normalize.component_ary == oth.normalize.component_ary else false end end def hash self.component_ary.hash end def eql?(oth) self.class == oth.class && parser == oth.parser && self.component_ary.eql?(oth.component_ary) end =begin --- URI::Generic#===(oth) =end # def ===(oth) # raise NotImplementedError # end =begin =end # returns an Array of the components defined from the COMPONENT Array def component_ary component.collect do |x| self.send(x) end end protected :component_ary # == Args # # +components+:: # Multiple Symbol arguments defined in URI::HTTP # # == Description # # Selects specified components from URI # # == Usage # # require 'uri' # # uri = URI.parse('http://myuser:mypass@my.example.com/test.rbx') # p uri.select(:userinfo, :host, :path) # # => ["myuser:mypass", "my.example.com", "/test.rbx"] # def select(*components) components.collect do |c| if component.include?(c) self.send(c) else raise ArgumentError, "expected of components of #{self.class} (#{self.class.component.join(', ')})" end end end def inspect "#<#{self.class} #{self}>" end # # == Args # # +v+:: # URI or String # # == Description # # attempt to parse other URI +oth+ # return [parsed_oth, self] # # == Usage # # require 'uri' # # uri = URI.parse("http://my.example.com") # uri.coerce("http://foo.com") # #=> [#, #] # def coerce(oth) case oth when String oth = parser.parse(oth) else super end return oth, self end # returns a proxy URI. # The proxy URI is obtained from environment variables such as http_proxy, # ftp_proxy, no_proxy, etc. # If there is no proper proxy, nil is returned. # # Note that capitalized variables (HTTP_PROXY, FTP_PROXY, NO_PROXY, etc.) # are examined too. # # But http_proxy and HTTP_PROXY is treated specially under CGI environment. # It's because HTTP_PROXY may be set by Proxy: header. # So HTTP_PROXY is not used. # http_proxy is not used too if the variable is case insensitive. # CGI_HTTP_PROXY can be used instead. def find_proxy raise BadURIError, "relative URI: #{self}" if self.relative? name = self.scheme.downcase + '_proxy' proxy_uri = nil if name == 'http_proxy' && ENV.include?('REQUEST_METHOD') # CGI? # HTTP_PROXY conflicts with *_proxy for proxy settings and # HTTP_* for header information in CGI. # So it should be careful to use it. pairs = ENV.reject {|k, v| /\Ahttp_proxy\z/i !~ k } case pairs.length when 0 # no proxy setting anyway. proxy_uri = nil when 1 k, _ = pairs.shift if k == 'http_proxy' && ENV[k.upcase] == nil # http_proxy is safe to use because ENV is case sensitive. proxy_uri = ENV[name] else proxy_uri = nil end else # http_proxy is safe to use because ENV is case sensitive. proxy_uri = ENV.to_hash[name] end if !proxy_uri # Use CGI_HTTP_PROXY. cf. libwww-perl. proxy_uri = ENV["CGI_#{name.upcase}"] end elsif name == 'http_proxy' unless proxy_uri = ENV[name] if proxy_uri = ENV[name.upcase] warn 'The environment variable HTTP_PROXY is discouraged. Use http_proxy.' end end else proxy_uri = ENV[name] || ENV[name.upcase] end if proxy_uri.nil? || proxy_uri.empty? return nil end if self.hostname require 'socket' begin addr = IPSocket.getaddress(self.hostname) return nil if /\A127\.|\A::1\z/ =~ addr rescue SocketError end end name = 'no_proxy' if no_proxy = ENV[name] || ENV[name.upcase] no_proxy.scan(/([^:,]*)(?::(\d+))?/) {|host, port| if /(\A|\.)#{Regexp.quote host}\z/i =~ self.host && (!port || self.port == port.to_i) return nil end } end URI.parse(proxy_uri) end end end PK!B7-7-2.2.0/shell.rbnu[# # shell.rb - # $Release Version: 0.7 $ # $Revision: 1.9 $ # by Keiju ISHITSUKA(keiju@ruby-lang.org) # # -- # # # require "e2mmap" require "thread" unless defined?(Mutex) require "forwardable" require "shell/error" require "shell/command-processor" require "shell/process-controller" # Shell implements an idiomatic Ruby interface for common UNIX shell commands. # # It provides users the ability to execute commands with filters and pipes, # like +sh+/+csh+ by using native facilities of Ruby. # # == Examples # # === Temp file creation # # In this example we will create three +tmpFile+'s in three different folders # under the +/tmp+ directory. # # sh = Shell.cd("/tmp") # Change to the /tmp directory # sh.mkdir "shell-test-1" unless sh.exists?("shell-test-1") # # make the 'shell-test-1' directory if it doesn't already exist # sh.cd("shell-test-1") # Change to the /tmp/shell-test-1 directory # for dir in ["dir1", "dir3", "dir5"] # if !sh.exists?(dir) # sh.mkdir dir # make dir if it doesn't already exist # sh.cd(dir) do # # change to the `dir` directory # f = sh.open("tmpFile", "w") # open a new file in write mode # f.print "TEST\n" # write to the file # f.close # close the file handler # end # print sh.pwd # output the process working directory # end # end # # === Temp file creation with self # # This example is identical to the first, except we're using # CommandProcessor#transact. # # CommandProcessor#transact executes the given block against self, in this case # +sh+; our Shell object. Within the block we can substitute +sh.cd+ to +cd+, # because the scope within the block uses +sh+ already. # # sh = Shell.cd("/tmp") # sh.transact do # mkdir "shell-test-1" unless exists?("shell-test-1") # cd("shell-test-1") # for dir in ["dir1", "dir3", "dir5"] # if !exists?(dir) # mkdir dir # cd(dir) do # f = open("tmpFile", "w") # f.print "TEST\n" # f.close # end # print pwd # end # end # end # # === Pipe /etc/printcap into a file # # In this example we will read the operating system file +/etc/printcap+, # generated by +cupsd+, and then output it to a new file relative to the +pwd+ # of +sh+. # # sh = Shell.new # sh.cat("/etc/printcap") | sh.tee("tee1") > "tee2" # (sh.cat < "/etc/printcap") | sh.tee("tee11") > "tee12" # sh.cat("/etc/printcap") | sh.tee("tee1") >> "tee2" # (sh.cat < "/etc/printcap") | sh.tee("tee11") >> "tee12" # class Shell include Error extend Exception2MessageMapper # debug: true -> normal debug # debug: 1 -> eval definition debug # debug: 2 -> detail inspect debug @debug = false @verbose = true @debug_display_process_id = false @debug_display_thread_id = true @debug_output_mutex = Mutex.new class << Shell extend Forwardable attr_accessor :cascade, :debug, :verbose alias debug? debug alias verbose? verbose @verbose = true def debug=(val) @debug = val @verbose = val if val end # call-seq: # Shell.cd(path) # # Creates a new Shell instance with the current working directory # set to +path+. def cd(path) new(path) end # Returns the directories in the current shell's PATH environment variable # as an array of directory names. This sets the system_path for all # instances of Shell. # # Example: If in your current shell, you did: # # $ echo $PATH # /usr/bin:/bin:/usr/local/bin # # Running this method in the above shell would then return: # # ["/usr/bin", "/bin", "/usr/local/bin"] # def default_system_path if @default_system_path @default_system_path else ENV["PATH"].split(":") end end # Sets the system_path that new instances of Shell should have as their # initial system_path. # # +path+ should be an array of directory name strings. def default_system_path=(path) @default_system_path = path end def default_record_separator if @default_record_separator @default_record_separator else $/ end end def default_record_separator=(rs) @default_record_separator = rs end # os resource mutex mutex_methods = ["unlock", "lock", "locked?", "synchronize", "try_lock", "exclusive_unlock"] for m in mutex_methods def_delegator("@debug_output_mutex", m, "debug_output_"+m.to_s) end end # call-seq: # Shell.new(pwd, umask) -> obj # # Creates a Shell object which current directory is set to the process # current directory, unless otherwise specified by the +pwd+ argument. def initialize(pwd = Dir.pwd, umask = nil) @cwd = File.expand_path(pwd) @dir_stack = [] @umask = umask @system_path = Shell.default_system_path @record_separator = Shell.default_record_separator @command_processor = CommandProcessor.new(self) @process_controller = ProcessController.new(self) @verbose = Shell.verbose @debug = Shell.debug end # Returns the command search path in an array attr_reader :system_path # Sets the system path (the Shell instance's PATH environment variable). # # +path+ should be an array of directory name strings. def system_path=(path) @system_path = path rehash end # Returns the umask attr_accessor :umask attr_accessor :record_separator attr_accessor :verbose, :debug def debug=(val) @debug = val @verbose = val if val end alias verbose? verbose alias debug? debug attr_reader :command_processor attr_reader :process_controller def expand_path(path) File.expand_path(path, @cwd) end # Most Shell commands are defined via CommandProcessor # # Dir related methods # # Shell#cwd/dir/getwd/pwd # Shell#chdir/cd # Shell#pushdir/pushd # Shell#popdir/popd # Shell#mkdir # Shell#rmdir # Returns the current working directory. attr_reader :cwd alias dir cwd alias getwd cwd alias pwd cwd attr_reader :dir_stack alias dirs dir_stack # call-seq: # Shell.chdir(path) # # Creates a Shell object which current directory is set to +path+. # # If a block is given, it restores the current directory when the block ends. # # If called as iterator, it restores the current directory when the # block ends. def chdir(path = nil, verbose = @verbose) check_point if iterator? notify("chdir(with block) #{path}") if verbose cwd_old = @cwd begin chdir(path, nil) yield ensure chdir(cwd_old, nil) end else notify("chdir #{path}") if verbose path = "~" unless path @cwd = expand_path(path) notify "current dir: #{@cwd}" rehash Void.new(self) end end alias cd chdir # call-seq: # pushdir(path) # pushdir(path) { &block } # # Pushes the current directory to the directory stack, changing the current # directory to +path+. # # If +path+ is omitted, it exchanges its current directory and the top of its # directory stack. # # If a block is given, it restores the current directory when the block ends. def pushdir(path = nil, verbose = @verbose) check_point if iterator? notify("pushdir(with block) #{path}") if verbose pushdir(path, nil) begin yield ensure popdir end elsif path notify("pushdir #{path}") if verbose @dir_stack.push @cwd chdir(path, nil) notify "dir stack: [#{@dir_stack.join ', '}]" self else notify("pushdir") if verbose if pop = @dir_stack.pop @dir_stack.push @cwd chdir pop notify "dir stack: [#{@dir_stack.join ', '}]" self else Shell.Fail DirStackEmpty end end Void.new(self) end alias pushd pushdir # Pops a directory from the directory stack, and sets the current directory # to it. def popdir check_point notify("popdir") if pop = @dir_stack.pop chdir pop notify "dir stack: [#{@dir_stack.join ', '}]" self else Shell.Fail DirStackEmpty end Void.new(self) end alias popd popdir # Returns a list of scheduled jobs. def jobs @process_controller.jobs end # call-seq: # kill(signal, job) # # Sends the given +signal+ to the given +job+ def kill(sig, command) @process_controller.kill_job(sig, command) end # call-seq: # def_system_command(command, path = command) # # Convenience method for Shell::CommandProcessor.def_system_command. # Defines an instance method which will execute the given shell command. # If the executable is not in Shell.default_system_path, you must # supply the path to it. # # Shell.def_system_command('hostname') # Shell.new.hostname # => localhost # # # How to use an executable that's not in the default path # # Shell.def_system_command('run_my_program', "~/hello") # Shell.new.run_my_program # prints "Hello from a C program!" # def Shell.def_system_command(command, path = command) CommandProcessor.def_system_command(command, path) end # Convenience method for Shell::CommandProcessor.undef_system_command def Shell.undef_system_command(command) CommandProcessor.undef_system_command(command) end # call-seq: # alias_command(alias, command, *opts, &block) # # Convenience method for Shell::CommandProcessor.alias_command. # Defines an instance method which will execute a command under # an alternative name. # # Shell.def_system_command('date') # Shell.alias_command('date_in_utc', 'date', '-u') # Shell.new.date_in_utc # => Sat Jan 25 16:59:57 UTC 2014 # def Shell.alias_command(ali, command, *opts, &block) CommandProcessor.alias_command(ali, command, *opts, &block) end # Convenience method for Shell::CommandProcessor.unalias_command def Shell.unalias_command(ali) CommandProcessor.unalias_command(ali) end # call-seq: # install_system_commands(pre = "sys_") # # Convenience method for Shell::CommandProcessor.install_system_commands. # Defines instance methods representing all the executable files found in # Shell.default_system_path, with the given prefix prepended to their # names. # # Shell.install_system_commands # Shell.new.sys_echo("hello") # => hello # def Shell.install_system_commands(pre = "sys_") CommandProcessor.install_system_commands(pre) end # def inspect if debug.kind_of?(Integer) && debug > 2 super else to_s end end def self.notify(*opts) Shell::debug_output_synchronize do if opts[-1].kind_of?(String) yorn = verbose? else yorn = opts.pop end return unless yorn if @debug_display_thread_id if @debug_display_process_id prefix = "shell(##{Process.pid}:#{Thread.current.to_s.sub("Thread", "Th")}): " else prefix = "shell(#{Thread.current.to_s.sub("Thread", "Th")}): " end else prefix = "shell: " end _head = true STDERR.print opts.collect{|mes| mes = mes.dup yield mes if iterator? if _head _head = false prefix + mes else " "* prefix.size + mes end }.join("\n")+"\n" end end CommandProcessor.initialize CommandProcessor.run_config end PK!2.2.0/e2mmap.rbnu[# #-- # e2mmap.rb - for Ruby 1.1 # $Release Version: 2.0$ # $Revision: 1.10 $ # by Keiju ISHITSUKA # #++ # # Helper module for easily defining exceptions with predefined messages. # # == Usage # # 1. # class Foo # extend Exception2MessageMapper # def_e2message ExistingExceptionClass, "message..." # def_exception :NewExceptionClass, "message..."[, superclass] # ... # end # # 2. # module Error # extend Exception2MessageMapper # def_e2message ExistingExceptionClass, "message..." # def_exception :NewExceptionClass, "message..."[, superclass] # ... # end # class Foo # include Error # ... # end # # foo = Foo.new # foo.Fail .... # # 3. # module Error # extend Exception2MessageMapper # def_e2message ExistingExceptionClass, "message..." # def_exception :NewExceptionClass, "message..."[, superclass] # ... # end # class Foo # extend Exception2MessageMapper # include Error # ... # end # # Foo.Fail NewExceptionClass, arg... # Foo.Fail ExistingExceptionClass, arg... # # module Exception2MessageMapper E2MM = Exception2MessageMapper # :nodoc: def E2MM.extend_object(cl) super cl.bind(self) unless cl < E2MM end def bind(cl) self.module_eval %[ def Raise(err = nil, *rest) Exception2MessageMapper.Raise(self.class, err, *rest) end alias Fail Raise def self.included(mod) mod.extend Exception2MessageMapper end ] end # Fail(err, *rest) # err: exception # rest: message arguments # def Raise(err = nil, *rest) E2MM.Raise(self, err, *rest) end alias Fail Raise alias fail Raise # def_e2message(c, m) # c: exception # m: message_form # define exception c with message m. # def def_e2message(c, m) E2MM.def_e2message(self, c, m) end # def_exception(n, m, s) # n: exception_name # m: message_form # s: superclass(default: StandardError) # define exception named ``c'' with message m. # def def_exception(n, m, s = StandardError) E2MM.def_exception(self, n, m, s) end # # Private definitions. # # {[class, exp] => message, ...} @MessageMap = {} # E2MM.def_e2message(k, e, m) # k: class to define exception under. # e: exception # m: message_form # define exception c with message m. # def E2MM.def_e2message(k, c, m) E2MM.instance_eval{@MessageMap[[k, c]] = m} c end # E2MM.def_exception(k, n, m, s) # k: class to define exception under. # n: exception_name # m: message_form # s: superclass(default: StandardError) # define exception named ``c'' with message m. # def E2MM.def_exception(k, n, m, s = StandardError) n = n.id2name if n.kind_of?(Fixnum) e = Class.new(s) E2MM.instance_eval{@MessageMap[[k, e]] = m} k.const_set(n, e) end # Fail(klass, err, *rest) # klass: class to define exception under. # err: exception # rest: message arguments # def E2MM.Raise(klass = E2MM, err = nil, *rest) if form = e2mm_message(klass, err) b = $@.nil? ? caller(1) : $@ b.shift if b[0] =~ /^#{Regexp.quote(__FILE__)}:/ raise err, sprintf(form, *rest), b else E2MM.Fail E2MM, ErrNotRegisteredException, err.inspect end end class << E2MM alias Fail Raise end def E2MM.e2mm_message(klass, exp) for c in klass.ancestors if mes = @MessageMap[[c,exp]] m = klass.instance_eval('"' + mes + '"') return m end end nil end class << self alias message e2mm_message end E2MM.def_exception(E2MM, :ErrNotRegisteredException, "not registered exception(%s)") end PK!rU  2.2.0/yaml/dbm.rbnu[require 'yaml' require 'dbm' module YAML # YAML + DBM = YDBM # # YAML::DBM provides the same interface as ::DBM. # # However, while DBM only allows strings for both keys and values, # this library allows one to use most Ruby objects for values # by first converting them to YAML. Keys must be strings. # # Conversion to and from YAML is performed automatically. # # See the documentation for ::DBM and ::YAML for more information. class DBM < ::DBM VERSION = "0.1" # :nodoc: # :call-seq: # ydbm[key] -> value # # Return value associated with +key+ from database. # # Returns +nil+ if there is no such +key+. # # See #fetch for more information. def []( key ) fetch( key ) end # :call-seq: # ydbm[key] = value # # Set +key+ to +value+ in database. # # +value+ will be converted to YAML before storage. # # See #store for more information. def []=( key, val ) store( key, val ) end # :call-seq: # ydbm.fetch( key, ifnone = nil ) # ydbm.fetch( key ) { |key| ... } # # Return value associated with +key+. # # If there is no value for +key+ and no block is given, returns +ifnone+. # # Otherwise, calls block passing in the given +key+. # # See ::DBM#fetch for more information. def fetch( keystr, ifnone = nil ) begin val = super( keystr ) return YAML.load( val ) if String === val rescue IndexError end if block_given? yield keystr else ifnone end end # Deprecated, used YAML::DBM#key instead. # ---- # Note: # YAML::DBM#index makes warning from internal of ::DBM#index. # It says 'DBM#index is deprecated; use DBM#key', but DBM#key # behaves not same as DBM#index. # def index( keystr ) super( keystr.to_yaml ) end # :call-seq: # ydbm.key(value) -> string # # Returns the key for the specified value. def key( keystr ) invert[keystr] end # :call-seq: # ydbm.values_at(*keys) # # Returns an array containing the values associated with the given keys. def values_at( *keys ) keys.collect { |k| fetch( k ) } end # :call-seq: # ydbm.delete(key) # # Deletes value from database associated with +key+. # # Returns value or +nil+. def delete( key ) v = super( key ) if String === v v = YAML.load( v ) end v end # :call-seq: # ydbm.delete_if { |key, value| ... } # # Calls the given block once for each +key+, +value+ pair in the database. # Deletes all entries for which the block returns true. # # Returns +self+. def delete_if # :yields: [key, value] del_keys = keys.dup del_keys.delete_if { |k| yield( k, fetch( k ) ) == false } del_keys.each { |k| delete( k ) } self end # :call-seq: # ydbm.reject { |key, value| ... } # # Converts the contents of the database to an in-memory Hash, then calls # Hash#reject with the specified code block, returning a new Hash. def reject hsh = self.to_hash hsh.reject { |k,v| yield k, v } end # :call-seq: # ydbm.each_pair { |key, value| ... } # # Calls the given block once for each +key+, +value+ pair in the database. # # Returns +self+. def each_pair # :yields: [key, value] keys.each { |k| yield k, fetch( k ) } self end # :call-seq: # ydbm.each_value { |value| ... } # # Calls the given block for each value in database. # # Returns +self+. def each_value # :yields: value super { |v| yield YAML.load( v ) } self end # :call-seq: # ydbm.values # # Returns an array of values from the database. def values super.collect { |v| YAML.load( v ) } end # :call-seq: # ydbm.has_value?(value) # # Returns true if specified +value+ is found in the database. def has_value?( val ) each_value { |v| return true if v == val } return false end # :call-seq: # ydbm.invert -> hash # # Returns a Hash (not a DBM database) created by using each value in the # database as a key, with the corresponding key as its value. # # Note that all values in the hash will be Strings, but the keys will be # actual objects. def invert h = {} keys.each { |k| h[ self.fetch( k ) ] = k } h end # :call-seq: # ydbm.replace(hash) -> ydbm # # Replaces the contents of the database with the contents of the specified # object. Takes any object which implements the each_pair method, including # Hash and DBM objects. def replace( hsh ) clear update( hsh ) end # :call-seq: # ydbm.shift -> [key, value] # # Removes a [key, value] pair from the database, and returns it. # If the database is empty, returns +nil+. # # The order in which values are removed/returned is not guaranteed. def shift a = super a[1] = YAML.load( a[1] ) if a a end # :call-seq: # ydbm.select { |key, value| ... } # ydbm.select(*keys) # # If a block is provided, returns a new array containing [key, value] pairs # for which the block returns true. # # Otherwise, same as #values_at def select( *keys ) if block_given? self.keys.collect { |k| v = self[k]; [k, v] if yield k, v }.compact else values_at( *keys ) end end # :call-seq: # ydbm.store(key, value) -> value # # Stores +value+ in database with +key+ as the index. +value+ is converted # to YAML before being stored. # # Returns +value+ def store( key, val ) super( key, val.to_yaml ) val end # :call-seq: # ydbm.update(hash) -> ydbm # # Updates the database with multiple values from the specified object. # Takes any object which implements the each_pair method, including # Hash and DBM objects. # # Returns +self+. def update( hsh ) hsh.each_pair do |k,v| self.store( k, v ) end self end # :call-seq: # ydbm.to_a -> array # # Converts the contents of the database to an array of [key, value] arrays, # and returns it. def to_a a = [] keys.each { |k| a.push [ k, self.fetch( k ) ] } a end # :call-seq: # ydbm.to_hash -> hash # # Converts the contents of the database to an in-memory Hash object, and # returns it. def to_hash h = {} keys.each { |k| h[ k ] = self.fetch( k ) } h end alias :each :each_pair end end PK!e=||2.2.0/yaml/store.rbnu[# # YAML::Store # require 'yaml' require 'pstore' # YAML::Store provides the same functionality as PStore, except it uses YAML # to dump objects instead of Marshal. # # == Example # # require 'yaml/store' # # Person = Struct.new :first_name, :last_name # # people = [Person.new("Bob", "Smith"), Person.new("Mary", "Johnson")] # # store = YAML::Store.new "test.store" # # store.transaction do # store["people"] = people # store["greeting"] = { "hello" => "world" } # end # # After running the above code, the contents of "test.store" will be: # # --- # people: # - !ruby/struct:Person # first_name: Bob # last_name: Smith # - !ruby/struct:Person # first_name: Mary # last_name: Johnson # greeting: # hello: world class YAML::Store < PStore # :call-seq: # initialize( file_name, yaml_opts = {} ) # # Creates a new YAML::Store object, which will store data in +file_name+. # If the file does not already exist, it will be created. # # # Options passed in through +yaml_opts+ will be used when converting the # store to YAML via Hash#to_yaml(). def initialize file_name, yaml_opts = {} @opt = yaml_opts super end # :stopdoc: def dump(table) YAML.dump @table end def load(content) table = YAML.load(content) if table == false {} else table end end def marshal_dump_supports_canonical_option? false end EMPTY_MARSHAL_DATA = YAML.dump({}) EMPTY_MARSHAL_CHECKSUM = Digest::MD5.digest(EMPTY_MARSHAL_DATA) def empty_marshal_data EMPTY_MARSHAL_DATA end def empty_marshal_checksum EMPTY_MARSHAL_CHECKSUM end end PK!Ex 2.2.0/rdoc.rbnu[$DEBUG_RDOC = nil # :main: README.rdoc ## # RDoc produces documentation for Ruby source files by parsing the source and # extracting the definition for classes, modules, methods, includes and # requires. It associates these with optional documentation contained in an # immediately preceding comment block then renders the result using an output # formatter. # # For a simple introduction to writing or generating documentation using RDoc # see the README. # # == Roadmap # # If you think you found a bug in RDoc see CONTRIBUTING@Bugs # # If you want to use RDoc to create documentation for your Ruby source files, # see RDoc::Markup and refer to rdoc --help for command line usage. # # If you want to set the default markup format see # RDoc::Markup@Supported+Formats # # If you want to store rdoc configuration in your gem (such as the default # markup format) see RDoc::Options@Saved+Options # # If you want to write documentation for Ruby files see RDoc::Parser::Ruby # # If you want to write documentation for extensions written in C see # RDoc::Parser::C # # If you want to generate documentation using rake see RDoc::Task. # # If you want to drive RDoc programmatically, see RDoc::RDoc. # # If you want to use the library to format text blocks into HTML or other # formats, look at RDoc::Markup. # # If you want to make an RDoc plugin such as a generator or directive handler # see RDoc::RDoc. # # If you want to write your own output generator see RDoc::Generator. # # If you want an overview of how RDoc works see CONTRIBUTING # # == Credits # # RDoc is currently being maintained by Eric Hodel . # # Dave Thomas is the original author of RDoc. # # * The Ruby parser in rdoc/parse.rb is based heavily on the outstanding # work of Keiju ISHITSUKA of Nippon Rational Inc, who produced the Ruby # parser for irb and the rtags package. module RDoc ## # Exception thrown by any rdoc error. class Error < RuntimeError; end ## # RDoc version you are using VERSION = '4.2.0' ## # Method visibilities VISIBILITIES = [:public, :protected, :private] ## # Name of the dotfile that contains the description of files to be processed # in the current directory DOT_DOC_FILENAME = ".document" ## # General RDoc modifiers GENERAL_MODIFIERS = %w[nodoc].freeze ## # RDoc modifiers for classes CLASS_MODIFIERS = GENERAL_MODIFIERS ## # RDoc modifiers for attributes ATTR_MODIFIERS = GENERAL_MODIFIERS ## # RDoc modifiers for constants CONSTANT_MODIFIERS = GENERAL_MODIFIERS ## # RDoc modifiers for methods METHOD_MODIFIERS = GENERAL_MODIFIERS + %w[arg args yield yields notnew not-new not_new doc] ## # Loads the best available YAML library. def self.load_yaml begin gem 'psych' rescue Gem::LoadError end begin require 'psych' rescue ::LoadError ensure require 'yaml' end end autoload :RDoc, 'rdoc/rdoc' autoload :TestCase, 'rdoc/test_case' autoload :CrossReference, 'rdoc/cross_reference' autoload :ERBIO, 'rdoc/erbio' autoload :ERBPartial, 'rdoc/erb_partial' autoload :Encoding, 'rdoc/encoding' autoload :Generator, 'rdoc/generator' autoload :Options, 'rdoc/options' autoload :Parser, 'rdoc/parser' autoload :Servlet, 'rdoc/servlet' autoload :RI, 'rdoc/ri' autoload :Stats, 'rdoc/stats' autoload :Store, 'rdoc/store' autoload :Task, 'rdoc/task' autoload :Text, 'rdoc/text' autoload :Markdown, 'rdoc/markdown' autoload :Markup, 'rdoc/markup' autoload :RD, 'rdoc/rd' autoload :TomDoc, 'rdoc/tom_doc' autoload :KNOWN_CLASSES, 'rdoc/known_classes' autoload :RubyLex, 'rdoc/ruby_lex' autoload :RubyToken, 'rdoc/ruby_token' autoload :TokenStream, 'rdoc/token_stream' autoload :Comment, 'rdoc/comment' autoload :I18n, 'rdoc/i18n' # code objects # # We represent the various high-level code constructs that appear in Ruby # programs: classes, modules, methods, and so on. autoload :CodeObject, 'rdoc/code_object' autoload :Context, 'rdoc/context' autoload :TopLevel, 'rdoc/top_level' autoload :AnonClass, 'rdoc/anon_class' autoload :ClassModule, 'rdoc/class_module' autoload :NormalClass, 'rdoc/normal_class' autoload :NormalModule, 'rdoc/normal_module' autoload :SingleClass, 'rdoc/single_class' autoload :Alias, 'rdoc/alias' autoload :AnyMethod, 'rdoc/any_method' autoload :MethodAttr, 'rdoc/method_attr' autoload :GhostMethod, 'rdoc/ghost_method' autoload :MetaMethod, 'rdoc/meta_method' autoload :Attr, 'rdoc/attr' autoload :Constant, 'rdoc/constant' autoload :Mixin, 'rdoc/mixin' autoload :Include, 'rdoc/include' autoload :Extend, 'rdoc/extend' autoload :Require, 'rdoc/require' end PK!,k 2.2.0/forwardable.rbnu[# frozen_string_literal: false # # forwardable.rb - # $Release Version: 1.1$ # $Revision: 58085 $ # by Keiju ISHITSUKA(keiju@ishitsuka.com) # original definition by delegator.rb # Revised by Daniel J. Berger with suggestions from Florian Gross. # # Documentation by James Edward Gray II and Gavin Sinclair # The Forwardable module provides delegation of specified # methods to a designated object, using the methods #def_delegator # and #def_delegators. # # For example, say you have a class RecordCollection which # contains an array @records. You could provide the lookup method # #record_number(), which simply calls #[] on the @records # array, like this: # # require 'forwardable' # # class RecordCollection # attr_accessor :records # extend Forwardable # def_delegator :@records, :[], :record_number # end # # We can use the lookup method like so: # # r = RecordCollection.new # r.records = [4,5,6] # r.record_number(0) # => 4 # # Further, if you wish to provide the methods #size, #<<, and #map, # all of which delegate to @records, this is how you can do it: # # class RecordCollection # re-open RecordCollection class # def_delegators :@records, :size, :<<, :map # end # # r = RecordCollection.new # r.records = [1,2,3] # r.record_number(0) # => 1 # r.size # => 3 # r << 4 # => [1, 2, 3, 4] # r.map { |x| x * 2 } # => [2, 4, 6, 8] # # You can even extend regular objects with Forwardable. # # my_hash = Hash.new # my_hash.extend Forwardable # prepare object for delegation # my_hash.def_delegator "STDOUT", "puts" # add delegation for STDOUT.puts() # my_hash.puts "Howdy!" # # == Another example # # We want to rely on what has come before obviously, but with delegation we can # take just the methods we need and even rename them as appropriate. In many # cases this is preferable to inheritance, which gives us the entire old # interface, even if much of it isn't needed. # # class Queue # extend Forwardable # # def initialize # @q = [ ] # prepare delegate object # end # # # setup preferred interface, enq() and deq()... # def_delegator :@q, :push, :enq # def_delegator :@q, :shift, :deq # # # support some general Array methods that fit Queues well # def_delegators :@q, :clear, :first, :push, :shift, :size # end # # q = Queue.new # q.enq 1, 2, 3, 4, 5 # q.push 6 # # q.shift # => 1 # while q.size > 0 # puts q.deq # end # # q.enq "Ruby", "Perl", "Python" # puts q.first # q.clear # puts q.first # # This should output: # # 2 # 3 # 4 # 5 # 6 # Ruby # nil # # == Notes # # Be advised, RDoc will not detect delegated methods. # # +forwardable.rb+ provides single-method delegation via the def_delegator and # def_delegators methods. For full-class delegation via DelegateClass, see # +delegate.rb+. # module Forwardable # Version of +forwardable.rb+ FORWARDABLE_VERSION = "1.1.0" FILE_REGEXP = %r"#{Regexp.quote(__FILE__)}" @debug = nil class << self # If true, __FILE__ will remain in the backtrace in the event an # Exception is raised. attr_accessor :debug end # Takes a hash as its argument. The key is a symbol or an array of # symbols. These symbols correspond to method names. The value is # the accessor to which the methods will be delegated. # # :call-seq: # delegate method => accessor # delegate [method, method, ...] => accessor # def instance_delegate(hash) hash.each{ |methods, accessor| methods = [methods] unless methods.respond_to?(:each) methods.each{ |method| def_instance_delegator(accessor, method) } } end # # Shortcut for defining multiple delegator methods, but with no # provision for using a different name. The following two code # samples have the same effect: # # def_delegators :@records, :size, :<<, :map # # def_delegator :@records, :size # def_delegator :@records, :<< # def_delegator :@records, :map # def def_instance_delegators(accessor, *methods) methods.delete("__send__") methods.delete("__id__") for method in methods def_instance_delegator(accessor, method) end end # Define +method+ as delegator instance method with an optional # alias name +ali+. Method calls to +ali+ will be delegated to # +accessor.method+. # # class MyQueue # extend Forwardable # attr_reader :queue # def initialize # @queue = [] # end # # def_delegator :@queue, :push, :mypush # end # # q = MyQueue.new # q.mypush 42 # q.queue #=> [42] # q.push 23 #=> NoMethodError # def def_instance_delegator(accessor, method, ali = method) gen = Forwardable._delegator_method(self, accessor, method, ali) # If it's not a class or module, it's an instance (Module === self ? self : singleton_class).module_eval(&gen) end alias delegate instance_delegate alias def_delegators def_instance_delegators alias def_delegator def_instance_delegator def self._delegator_method(obj, accessor, method, ali) accessor = accessor.to_s unless Symbol === accessor if Module === obj ? obj.method_defined?(accessor) || obj.private_method_defined?(accessor) : obj.respond_to?(accessor, true) accessor = "#{accessor}()" end line_no = __LINE__+1; str = "#{<<-"begin;"}\n#{<<-"end;"}" begin; proc do def #{ali}(*args, &block) begin #{accessor} ensure $@.delete_if {|s| ::Forwardable::FILE_REGEXP =~ s} if $@ and !::Forwardable::debug end.__send__ :#{method}, *args, &block end end end; RubyVM::InstructionSequence .compile(str, __FILE__, __FILE__, line_no, trace_instruction: false, tailcall_optimization: true) .eval end end # SingleForwardable can be used to setup delegation at the object level as well. # # printer = String.new # printer.extend SingleForwardable # prepare object for delegation # printer.def_delegator "STDOUT", "puts" # add delegation for STDOUT.puts() # printer.puts "Howdy!" # # Also, SingleForwardable can be used to set up delegation for a Class or Module. # # class Implementation # def self.service # puts "serviced!" # end # end # # module Facade # extend SingleForwardable # def_delegator :Implementation, :service # end # # Facade.service #=> serviced! # # If you want to use both Forwardable and SingleForwardable, you can # use methods def_instance_delegator and def_single_delegator, etc. module SingleForwardable # Takes a hash as its argument. The key is a symbol or an array of # symbols. These symbols correspond to method names. The value is # the accessor to which the methods will be delegated. # # :call-seq: # delegate method => accessor # delegate [method, method, ...] => accessor # def single_delegate(hash) hash.each{ |methods, accessor| methods = [methods] unless methods.respond_to?(:each) methods.each{ |method| def_single_delegator(accessor, method) } } end # # Shortcut for defining multiple delegator methods, but with no # provision for using a different name. The following two code # samples have the same effect: # # def_delegators :@records, :size, :<<, :map # # def_delegator :@records, :size # def_delegator :@records, :<< # def_delegator :@records, :map # def def_single_delegators(accessor, *methods) methods.delete("__send__") methods.delete("__id__") for method in methods def_single_delegator(accessor, method) end end # :call-seq: # def_single_delegator(accessor, method, new_name=method) # # Defines a method _method_ which delegates to _accessor_ (i.e. it calls # the method of the same name in _accessor_). If _new_name_ is # provided, it is used as the name for the delegate method. def def_single_delegator(accessor, method, ali = method) gen = Forwardable._delegator_method(self, accessor, method, ali) instance_eval(&gen) end alias delegate single_delegate alias def_delegators def_single_delegators alias def_delegator def_single_delegator end PK!l 2.2.0/rake/alt_system.rbnu[# # Copyright (c) 2008 James M. Lawrence # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation files # (the "Software"), to deal in the Software without restriction, # including without limitation the rights to use, copy, modify, merge, # publish, distribute, sublicense, and/or sell copies of the Software, # and to permit persons to whom the Software is furnished to do so, # subject to the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. # require 'rbconfig' ## # Alternate implementations of system() and backticks `` on Windows # for ruby-1.8 and earlier. #-- # TODO: Remove in Rake 11 module Rake::AltSystem # :nodoc: all WINDOWS = RbConfig::CONFIG["host_os"] =~ %r!(msdos|mswin|djgpp|mingw|[Ww]indows)! class << self def define_module_function(name, &block) define_method(name, &block) module_function(name) end end if WINDOWS && RUBY_VERSION < "1.9.0" RUNNABLE_EXTS = %w[com exe bat cmd] RUNNABLE_PATTERN = %r!\.(#{RUNNABLE_EXTS.join('|')})\Z!i define_module_function :kernel_system, &Kernel.method(:system) define_module_function :kernel_backticks, &Kernel.method(:'`') module_function def repair_command(cmd) "call " + ( if cmd =~ %r!\A\s*\".*?\"! # already quoted cmd elsif match = cmd.match(%r!\A\s*(\S+)!) if match[1] =~ %r!/! # avoid x/y.bat interpretation as x with option /y %Q!"#{match[1]}"! + match.post_match else # a shell command will fail if quoted cmd end else # empty or whitespace cmd end ) end def find_runnable(file) if file =~ RUNNABLE_PATTERN file else RUNNABLE_EXTS.each { |ext| test = "#{file}.#{ext}" return test if File.exist?(test) } nil end end def system(cmd, *args) repaired = ( if args.empty? [repair_command(cmd)] elsif runnable = find_runnable(cmd) [File.expand_path(runnable), *args] else # non-existent file [cmd, *args] end ) kernel_system(*repaired) end def backticks(cmd) kernel_backticks(repair_command(cmd)) end define_module_function :'`', &method(:backticks) else # Non-Windows or ruby-1.9+: same as Kernel versions define_module_function :system, &Kernel.method(:system) define_module_function :backticks, &Kernel.method(:'`') define_module_function :'`', &Kernel.method(:'`') end end PK!f8! ! 2.2.0/rake/promise.rbnu[module Rake # A Promise object represents a promise to do work (a chore) in the # future. The promise is created with a block and a list of # arguments for the block. Calling value will return the value of # the promised chore. # # Used by ThreadPool. # class Promise # :nodoc: all NOT_SET = Object.new.freeze # :nodoc: attr_accessor :recorder # Create a promise to do the chore specified by the block. def initialize(args, &block) @mutex = Mutex.new @result = NOT_SET @error = NOT_SET @args = args @block = block end # Return the value of this promise. # # If the promised chore is not yet complete, then do the work # synchronously. We will wait. def value unless complete? stat :sleeping_on, :item_id => object_id @mutex.synchronize do stat :has_lock_on, :item_id => object_id chore stat :releasing_lock_on, :item_id => object_id end end error? ? raise(@error) : @result end # If no one else is working this promise, go ahead and do the chore. def work stat :attempting_lock_on, :item_id => object_id if @mutex.try_lock stat :has_lock_on, :item_id => object_id chore stat :releasing_lock_on, :item_id => object_id @mutex.unlock else stat :bailed_on, :item_id => object_id end end private # Perform the chore promised def chore if complete? stat :found_completed, :item_id => object_id return end stat :will_execute, :item_id => object_id begin @result = @block.call(*@args) rescue Exception => e @error = e end stat :did_execute, :item_id => object_id discard end # Do we have a result for the promise def result? ! @result.equal?(NOT_SET) end # Did the promise throw an error def error? ! @error.equal?(NOT_SET) end # Are we done with the promise def complete? result? || error? end # free up these items for the GC def discard @args = nil @block = nil end # Record execution statistics if there is a recorder def stat(*args) @recorder.call(*args) if @recorder end end end PK!DLq2.2.0/rake/version.rbnu[module Rake module Version # :nodoc: all MAJOR, MINOR, BUILD, *OTHER = Rake::VERSION.split '.' NUMBERS = [MAJOR, MINOR, BUILD, *OTHER] end end PK!8ll2.2.0/rake/private_reader.rbnu[module Rake # Include PrivateReader to use +private_reader+. module PrivateReader # :nodoc: all def self.included(base) base.extend(ClassMethods) end module ClassMethods # Declare a list of private accessors def private_reader(*names) attr_reader(*names) private(*names) end end end end PK!_(2.2.0/rake/invocation_exception_mixin.rbnu[module Rake module InvocationExceptionMixin # Return the invocation chain (list of Rake tasks) that were in # effect when this exception was detected by rake. May be null if # no tasks were active. def chain @rake_invocation_chain ||= nil end # Set the invocation chain in effect when this exception was # detected. def chain=(value) @rake_invocation_chain = value end end end PK!@;Β2.2.0/rake/dsl_definition.rbnu[# Rake DSL functions. require 'rake/file_utils_ext' module Rake ## # DSL is a module that provides #task, #desc, #namespace, etc. Use this # when you'd like to use rake outside the top level scope. # # For a Rakefile you run from the comamnd line this module is automatically # included. module DSL #-- # Include the FileUtils file manipulation functions in the top # level module, but mark them private so that they don't # unintentionally define methods on other objects. #++ include FileUtilsExt private(*FileUtils.instance_methods(false)) private(*FileUtilsExt.instance_methods(false)) private # :call-seq: # task task_name # task task_name: dependencies # task task_name, arguments => dependencies # task task_name, argument[, argument ...], :needs: dependencies # # Declare a basic task. The +task_name+ is always the first argument. If # the task name contains a ":" it is defined in that namespace. # # The +dependencies+ may be a single task name or an Array of task names. # The +argument+ (a single name) or +arguments+ (an Array of names) define # the arguments provided to the task. # # The task, argument and dependency names may be either symbols or # strings. # # A task with a single dependency: # # task clobber: %w[clean] do # rm_rf "html" # end # # A task with an argument and a dependency: # # task :package, [:version] => :test do |t, args| # # ... # end # # To invoke this task from the command line: # # $ rake package[1.2.3] # # Alternate definition: # # task :package, :version, needs: :test do |t, args| # # ... # end # def task(*args, &block) # :doc: Rake::Task.define_task(*args, &block) end # Declare a file task. # # Example: # file "config.cfg" => ["config.template"] do # open("config.cfg", "w") do |outfile| # open("config.template") do |infile| # while line = infile.gets # outfile.puts line # end # end # end # end # def file(*args, &block) # :doc: Rake::FileTask.define_task(*args, &block) end # Declare a file creation task. # (Mainly used for the directory command). def file_create(*args, &block) Rake::FileCreationTask.define_task(*args, &block) end # Declare a set of files tasks to create the given directories on # demand. # # Example: # directory "testdata/doc" # def directory(*args, &block) # :doc: result = file_create(*args, &block) dir, _ = *Rake.application.resolve_args(args) dir = Rake.from_pathname(dir) Rake.each_dir_parent(dir) do |d| file_create d do |t| mkdir_p t.name unless File.exist?(t.name) end end result end # Declare a task that performs its prerequisites in # parallel. Multitasks does *not* guarantee that its prerequisites # will execute in any given order (which is obvious when you think # about it) # # Example: # multitask deploy: %w[deploy_gem deploy_rdoc] # def multitask(*args, &block) # :doc: Rake::MultiTask.define_task(*args, &block) end # Create a new rake namespace and use it for evaluating the given # block. Returns a NameSpace object that can be used to lookup # tasks defined in the namespace. # # Example: # # ns = namespace "nested" do # # the "nested:run" task # task :run # end # task_run = ns[:run] # find :run in the given namespace. # # Tasks can also be defined in a namespace by using a ":" in the task # name: # # task "nested:test" do # # ... # end # def namespace(name=nil, &block) # :doc: name = name.to_s if name.kind_of?(Symbol) name = name.to_str if name.respond_to?(:to_str) unless name.kind_of?(String) || name.nil? raise ArgumentError, "Expected a String or Symbol for a namespace name" end Rake.application.in_namespace(name, &block) end # Declare a rule for auto-tasks. # # Example: # rule '.o' => '.c' do |t| # sh 'cc', '-o', t.name, t.source # end # def rule(*args, &block) # :doc: Rake::Task.create_rule(*args, &block) end # Describes the next rake task. Duplicate descriptions are discarded. # Descriptions are shown with rake -T (up to the first # sentence) and rake -D (the entire description). # # Example: # desc "Run the Unit Tests" # task test: [:build] # # ... run tests # end # def desc(description) # :doc: Rake.application.last_description = description end # Import the partial Rakefiles +fn+. Imported files are loaded # _after_ the current file is completely loaded. This allows the # import statement to appear anywhere in the importing file, and yet # allowing the imported files to depend on objects defined in the # importing file. # # A common use of the import statement is to include files # containing dependency declarations. # # See also the --rakelibdir command line option. # # Example: # import ".depend", "my_rules" # def import(*fns) # :doc: fns.each do |fn| Rake.application.add_import(fn) end end end extend FileUtilsExt end # Extend the main object with the DSL commands. This allows top-level # calls to task, etc. to work from a Rakefile without polluting the # object inheritance tree. self.extend Rake::DSL PK!tʇ:RR2.2.0/rake/runtest.rbnu[require 'test/unit' require 'test/unit/assertions' require 'rake/file_list' module Rake include Test::Unit::Assertions ## # Deprecated way of running tests in process, but only for Test::Unit. #-- # TODO: Remove in rake 11 def run_tests(pattern='test/test*.rb', log_enabled=false) # :nodoc: FileList.glob(pattern).each do |fn| $stderr.puts fn if log_enabled begin require fn rescue Exception => ex $stderr.puts "Error in #{fn}: #{ex.message}" $stderr.puts ex.backtrace assert false end end end extend self end PK!׭2.2.0/rake/rake_module.rbnu[require 'rake/application' module Rake class << self # Current Rake Application def application @application ||= Rake::Application.new end # Set the current Rake application object. def application=(app) @application = app end def suggested_thread_count # :nodoc: @cpu_count ||= Rake::CpuCounter.count @cpu_count + 4 end # Return the original directory where the Rake application was started. def original_dir application.original_dir end # Load a rakefile. def load_rakefile(path) load(path) end # Add files to the rakelib list def add_rakelib(*files) application.options.rakelib ||= [] application.options.rakelib.concat(files) end end end PK!Kjj2.2.0/rake/tasklib.rbnu[require 'rake' module Rake # Base class for Task Libraries. class TaskLib include Cloneable include Rake::DSL # Make a symbol by pasting two strings together. # # NOTE: DEPRECATED! This method is kinda stupid. I don't know why # I didn't just use string interpolation. But now other task # libraries depend on this so I can't remove it without breaking # other people's code. So for now it stays for backwards # compatibility. BUT DON'T USE IT. #-- # TODO: Remove in Rake 11 def paste(a, b) # :nodoc: (a.to_s + b.to_s).intern end end end PK!NW#2.2.0/rake/ruby182_test_unit_fix.rbnu[# TODO: Remove in rake 11 # Local Rake override to fix bug in Ruby 0.8.2 module Test # :nodoc: # Local Rake override to fix bug in Ruby 0.8.2 module Unit # :nodoc: # Local Rake override to fix bug in Ruby 0.8.2 module Collector # :nodoc: # Local Rake override to fix bug in Ruby 0.8.2 class Dir # :nodoc: undef collect_file def collect_file(name, suites, already_gathered) # :nodoc: dir = File.dirname(File.expand_path(name)) $:.unshift(dir) unless $:.first == dir if @req @req.require(name) else require(name) end find_test_cases(already_gathered).each do |t| add_suite(suites, t.suite) end ensure $:.delete_at $:.rindex(dir) end end end end end PK!~jg~2.2.0/rake/packagetask.rbnu[# Define a package task library to aid in the definition of # redistributable package files. require 'rake' require 'rake/tasklib' module Rake # Create a packaging task that will package the project into # distributable files (e.g zip archive or tar files). # # The PackageTask will create the following targets: # # +:package+ :: # Create all the requested package files. # # +:clobber_package+ :: # Delete all the package files. This target is automatically # added to the main clobber target. # # +:repackage+ :: # Rebuild the package files from scratch, even if they are not out # of date. # # "package_dir/name-version.tgz" :: # Create a gzipped tar package (if need_tar is true). # # "package_dir/name-version.tar.gz" :: # Create a gzipped tar package (if need_tar_gz is true). # # "package_dir/name-version.tar.bz2" :: # Create a bzip2'd tar package (if need_tar_bz2 is true). # # "package_dir/name-version.zip" :: # Create a zip package archive (if need_zip is true). # # Example: # # Rake::PackageTask.new("rake", "1.2.3") do |p| # p.need_tar = true # p.package_files.include("lib/**/*.rb") # end # class PackageTask < TaskLib # Name of the package (from the GEM Spec). attr_accessor :name # Version of the package (e.g. '1.3.2'). attr_accessor :version # Directory used to store the package files (default is 'pkg'). attr_accessor :package_dir # True if a gzipped tar file (tgz) should be produced (default is # false). attr_accessor :need_tar # True if a gzipped tar file (tar.gz) should be produced (default # is false). attr_accessor :need_tar_gz # True if a bzip2'd tar file (tar.bz2) should be produced (default # is false). attr_accessor :need_tar_bz2 # True if a zip file should be produced (default is false) attr_accessor :need_zip # List of files to be included in the package. attr_accessor :package_files # Tar command for gzipped or bzip2ed archives. The default is 'tar'. attr_accessor :tar_command # Zip command for zipped archives. The default is 'zip'. attr_accessor :zip_command # Create a Package Task with the given name and version. Use +:noversion+ # as the version to build a package without a version or to provide a # fully-versioned package name. def initialize(name=nil, version=nil) init(name, version) yield self if block_given? define unless name.nil? end # Initialization that bypasses the "yield self" and "define" step. def init(name, version) @name = name @version = version @package_files = Rake::FileList.new @package_dir = 'pkg' @need_tar = false @need_tar_gz = false @need_tar_bz2 = false @need_zip = false @tar_command = 'tar' @zip_command = 'zip' end # Create the tasks defined by this task library. def define fail "Version required (or :noversion)" if @version.nil? @version = nil if :noversion == @version desc "Build all the packages" task :package desc "Force a rebuild of the package files" task :repackage => [:clobber_package, :package] desc "Remove package products" task :clobber_package do rm_r package_dir rescue nil end task :clobber => [:clobber_package] [ [need_tar, tgz_file, "z"], [need_tar_gz, tar_gz_file, "z"], [need_tar_bz2, tar_bz2_file, "j"] ].each do |(need, file, flag)| if need task :package => ["#{package_dir}/#{file}"] file "#{package_dir}/#{file}" => [package_dir_path] + package_files do chdir(package_dir) do sh @tar_command, "#{flag}cvf", file, package_name end end end end if need_zip task :package => ["#{package_dir}/#{zip_file}"] file "#{package_dir}/#{zip_file}" => [package_dir_path] + package_files do chdir(package_dir) do sh @zip_command, "-r", zip_file, package_name end end end directory package_dir_path => @package_files do @package_files.each do |fn| f = File.join(package_dir_path, fn) fdir = File.dirname(f) mkdir_p(fdir) unless File.exist?(fdir) if File.directory?(fn) mkdir_p(f) else rm_f f safe_ln(fn, f) end end end self end # The name of this package def package_name @version ? "#{@name}-#{@version}" : @name end # The directory this package will be built in def package_dir_path "#{package_dir}/#{package_name}" end # The package name with .tgz added def tgz_file "#{package_name}.tgz" end # The package name with .tar.gz added def tar_gz_file "#{package_name}.tar.gz" end # The package name with .tar.bz2 added def tar_bz2_file "#{package_name}.tar.bz2" end # The package name with .zip added def zip_file "#{package_name}.zip" end end end PK!C! 2.2.0/rake/file_creation_task.rbnu[require 'rake/file_task' require 'rake/early_time' module Rake # A FileCreationTask is a file task that when used as a dependency will be # needed if and only if the file has not been created. Once created, it is # not re-triggered if any of its dependencies are newer, nor does trigger # any rebuilds of tasks that depend on it whenever it is updated. # class FileCreationTask < FileTask # Is this file task needed? Yes if it doesn't exist. def needed? ! File.exist?(name) end # Time stamp for file creation task. This time stamp is earlier # than any other time stamp. def timestamp Rake::EARLY end end end PK!2.2.0/rake/invocation_chain.rbnu[module Rake # InvocationChain tracks the chain of task invocations to detect # circular dependencies. class InvocationChain < LinkedList # Is the invocation already in the chain? def member?(invocation) head == invocation || tail.member?(invocation) end # Append an invocation to the chain of invocations. It is an error # if the invocation already listed. def append(invocation) if member?(invocation) fail RuntimeError, "Circular dependency detected: #{to_s} => #{invocation}" end conj(invocation) end # Convert to string, ie: TOP => invocation => invocation def to_s "#{prefix}#{head}" end # Class level append. def self.append(invocation, chain) chain.append(invocation) end private def prefix "#{tail} => " end # Null object for an empty chain. class EmptyInvocationChain < LinkedList::EmptyLinkedList @parent = InvocationChain def member?(obj) false end def append(invocation) conj(invocation) end def to_s "TOP" end end EMPTY = EmptyInvocationChain.new end end PK!g\\\2.2.0/rake/application.rbnu[require 'shellwords' require 'optparse' require 'rake/task_manager' require 'rake/file_list' require 'rake/thread_pool' require 'rake/thread_history_display' require 'rake/trace_output' require 'rake/win32' module Rake CommandLineOptionError = Class.new(StandardError) ## # Rake main application object. When invoking +rake+ from the # command line, a Rake::Application object is created and run. class Application include TaskManager include TraceOutput # The name of the application (typically 'rake') attr_reader :name # The original directory where rake was invoked. attr_reader :original_dir # Name of the actual rakefile used. attr_reader :rakefile # Number of columns on the terminal attr_accessor :terminal_columns # List of the top level task names (task names from the command line). attr_reader :top_level_tasks DEFAULT_RAKEFILES = [ 'rakefile', 'Rakefile', 'rakefile.rb', 'Rakefile.rb' ].freeze # Initialize a Rake::Application object. def initialize super @name = 'rake' @rakefiles = DEFAULT_RAKEFILES.dup @rakefile = nil @pending_imports = [] @imported = [] @loaders = {} @default_loader = Rake::DefaultLoader.new @original_dir = Dir.pwd @top_level_tasks = [] add_loader('rb', DefaultLoader.new) add_loader('rf', DefaultLoader.new) add_loader('rake', DefaultLoader.new) @tty_output = STDOUT.tty? @terminal_columns = ENV['RAKE_COLUMNS'].to_i end # Run the Rake application. The run method performs the following # three steps: # # * Initialize the command line options (+init+). # * Define the tasks (+load_rakefile+). # * Run the top level tasks (+top_level+). # # If you wish to build a custom rake command, you should call # +init+ on your application. Then define any tasks. Finally, # call +top_level+ to run your top level tasks. def run standard_exception_handling do init load_rakefile top_level end end # Initialize the command line parameters and app name. def init(app_name='rake') standard_exception_handling do @name = app_name args = handle_options collect_command_line_tasks(args) end end # Find the rakefile and then load it and any pending imports. def load_rakefile standard_exception_handling do raw_load_rakefile end end # Run the top level tasks of a Rake application. def top_level run_with_threads do if options.show_tasks display_tasks_and_comments elsif options.show_prereqs display_prerequisites else top_level_tasks.each { |task_name| invoke_task(task_name) } end end end # Run the given block with the thread startup and shutdown. def run_with_threads thread_pool.gather_history if options.job_stats == :history yield thread_pool.join if options.job_stats stats = thread_pool.statistics puts "Maximum active threads: #{stats[:max_active_threads]} + main" puts "Total threads in play: #{stats[:total_threads_in_play]} + main" end ThreadHistoryDisplay.new(thread_pool.history).show if options.job_stats == :history end # Add a loader to handle imported files ending in the extension # +ext+. def add_loader(ext, loader) ext = ".#{ext}" unless ext =~ /^\./ @loaders[ext] = loader end # Application options from the command line def options @options ||= OpenStruct.new end # Return the thread pool used for multithreaded processing. def thread_pool # :nodoc: @thread_pool ||= ThreadPool.new(options.thread_pool_size || Rake.suggested_thread_count-1) end # internal ---------------------------------------------------------------- # Invokes a task with arguments that are extracted from +task_string+ def invoke_task(task_string) # :nodoc: name, args = parse_task_string(task_string) t = self[name] t.invoke(*args) end def parse_task_string(string) # :nodoc: /^([^\[]+)(?:\[(.*)\])$/ =~ string.to_s name = $1 remaining_args = $2 return string, [] unless name return name, [] if remaining_args.empty? args = [] begin /((?:[^\\,]|\\.)*?)\s*(?:,\s*(.*))?$/ =~ remaining_args remaining_args = $2 args << $1.gsub(/\\(.)/, '\1') end while remaining_args return name, args end # Provide standard exception handling for the given block. def standard_exception_handling # :nodoc: yield rescue SystemExit # Exit silently with current status raise rescue OptionParser::InvalidOption => ex $stderr.puts ex.message exit(false) rescue Exception => ex # Exit with error message display_error_message(ex) exit_because_of_exception(ex) end # Exit the program because of an unhandle exception. # (may be overridden by subclasses) def exit_because_of_exception(ex) # :nodoc: exit(false) end # Display the error message that caused the exception. def display_error_message(ex) # :nodoc: trace "#{name} aborted!" display_exception_details(ex) trace "Tasks: #{ex.chain}" if has_chain?(ex) trace "(See full trace by running task with --trace)" unless options.backtrace end def display_exception_details(ex) # :nodoc: seen = Thread.current[:rake_display_exception_details_seen] ||= [] return if seen.include? ex seen << ex display_exception_message_details(ex) display_exception_backtrace(ex) display_exception_details(ex.cause) if has_cause?(ex) end def has_cause?(ex) # :nodoc: ex.respond_to?(:cause) && ex.cause end def display_exception_message_details(ex) # :nodoc: if ex.instance_of?(RuntimeError) trace ex.message else trace "#{ex.class.name}: #{ex.message}" end end def display_exception_backtrace(ex) # :nodoc: if options.backtrace trace ex.backtrace.join("\n") else trace Backtrace.collapse(ex.backtrace).join("\n") end end # Warn about deprecated usage. # # Example: # Rake.application.deprecate("import", "Rake.import", caller.first) # def deprecate(old_usage, new_usage, call_site) # :nodoc: unless options.ignore_deprecate $stderr.puts "WARNING: '#{old_usage}' is deprecated. " + "Please use '#{new_usage}' instead.\n" + " at #{call_site}" end end # Does the exception have a task invocation chain? def has_chain?(exception) # :nodoc: exception.respond_to?(:chain) && exception.chain end private :has_chain? # True if one of the files in RAKEFILES is in the current directory. # If a match is found, it is copied into @rakefile. def have_rakefile # :nodoc: @rakefiles.each do |fn| if File.exist?(fn) others = FileList.glob(fn, File::FNM_CASEFOLD) return others.size == 1 ? others.first : fn elsif fn == '' return fn end end return nil end # True if we are outputting to TTY, false otherwise def tty_output? # :nodoc: @tty_output end # Override the detected TTY output state (mostly for testing) def tty_output=(tty_output_state) # :nodoc: @tty_output = tty_output_state end # We will truncate output if we are outputting to a TTY or if we've been # given an explicit column width to honor def truncate_output? # :nodoc: tty_output? || @terminal_columns.nonzero? end # Display the tasks and comments. def display_tasks_and_comments # :nodoc: displayable_tasks = tasks.select { |t| (options.show_all_tasks || t.comment) && t.name =~ options.show_task_pattern } case options.show_tasks when :tasks width = displayable_tasks.map { |t| t.name_with_args.length }.max || 10 if truncate_output? max_column = terminal_width - name.size - width - 7 else max_column = nil end displayable_tasks.each do |t| printf("#{name} %-#{width}s # %s\n", t.name_with_args, max_column ? truncate(t.comment, max_column) : t.comment) end when :describe displayable_tasks.each do |t| puts "#{name} #{t.name_with_args}" comment = t.full_comment || "" comment.split("\n").each do |line| puts " #{line}" end puts end when :lines displayable_tasks.each do |t| t.locations.each do |loc| printf "#{name} %-30s %s\n", t.name_with_args, loc end end else fail "Unknown show task mode: '#{options.show_tasks}'" end end def terminal_width # :nodoc: if @terminal_columns.nonzero? result = @terminal_columns else result = unix? ? dynamic_width : 80 end (result < 10) ? 80 : result rescue 80 end # Calculate the dynamic width of the def dynamic_width # :nodoc: @dynamic_width ||= (dynamic_width_stty.nonzero? || dynamic_width_tput) end def dynamic_width_stty # :nodoc: %x{stty size 2>/dev/null}.split[1].to_i end def dynamic_width_tput # :nodoc: %x{tput cols 2>/dev/null}.to_i end def unix? # :nodoc: RbConfig::CONFIG['host_os'] =~ /(aix|darwin|linux|(net|free|open)bsd|cygwin|solaris|irix|hpux)/i end def windows? # :nodoc: Win32.windows? end def truncate(string, width) # :nodoc: if string.nil? "" elsif string.length <= width string else (string[0, width - 3] || "") + "..." end end # Display the tasks and prerequisites def display_prerequisites # :nodoc: tasks.each do |t| puts "#{name} #{t.name}" t.prerequisites.each { |pre| puts " #{pre}" } end end def trace(*strings) # :nodoc: options.trace_output ||= $stderr trace_on(options.trace_output, *strings) end def sort_options(options) # :nodoc: options.sort_by { |opt| opt.select { |o| o =~ /^-/ }.map { |o| o.downcase }.sort.reverse } end private :sort_options # A list of all the standard options used in rake, suitable for # passing to OptionParser. def standard_rake_options # :nodoc: sort_options( [ ['--all', '-A', "Show all tasks, even uncommented ones (in combination with -T or -D)", lambda { |value| options.show_all_tasks = value } ], ['--backtrace=[OUT]', "Enable full backtrace. OUT can be stderr (default) or stdout.", lambda { |value| options.backtrace = true select_trace_output(options, 'backtrace', value) } ], ['--build-all', '-B', "Build all prerequisites, including those which are up-to-date.", lambda { |value| options.build_all = true } ], ['--comments', "Show commented tasks only", lambda { |value| options.show_all_tasks = !value } ], ['--describe', '-D [PATTERN]', "Describe the tasks (matching optional PATTERN), then exit.", lambda { |value| select_tasks_to_show(options, :describe, value) } ], ['--dry-run', '-n', "Do a dry run without executing actions.", lambda { |value| Rake.verbose(true) Rake.nowrite(true) options.dryrun = true options.trace = true } ], ['--execute', '-e CODE', "Execute some Ruby code and exit.", lambda { |value| eval(value) exit } ], ['--execute-print', '-p CODE', "Execute some Ruby code, print the result, then exit.", lambda { |value| puts eval(value) exit } ], ['--execute-continue', '-E CODE', "Execute some Ruby code, " + "then continue with normal task processing.", lambda { |value| eval(value) } ], ['--jobs', '-j [NUMBER]', "Specifies the maximum number of tasks to execute in parallel. " + "(default is number of CPU cores + 4)", lambda { |value| if value.nil? || value == '' value = FIXNUM_MAX elsif value =~ /^\d+$/ value = value.to_i else value = Rake.suggested_thread_count end value = 1 if value < 1 options.thread_pool_size = value - 1 } ], ['--job-stats [LEVEL]', "Display job statistics. " + "LEVEL=history displays a complete job list", lambda { |value| if value =~ /^history/i options.job_stats = :history else options.job_stats = true end } ], ['--libdir', '-I LIBDIR', "Include LIBDIR in the search path for required modules.", lambda { |value| $:.push(value) } ], ['--multitask', '-m', "Treat all tasks as multitasks.", lambda { |value| options.always_multitask = true } ], ['--no-search', '--nosearch', '-N', "Do not search parent directories for the Rakefile.", lambda { |value| options.nosearch = true } ], ['--prereqs', '-P', "Display the tasks and dependencies, then exit.", lambda { |value| options.show_prereqs = true } ], ['--quiet', '-q', "Do not log messages to standard output.", lambda { |value| Rake.verbose(false) } ], ['--rakefile', '-f [FILENAME]', "Use FILENAME as the rakefile to search for.", lambda { |value| value ||= '' @rakefiles.clear @rakefiles << value } ], ['--rakelibdir', '--rakelib', '-R RAKELIBDIR', "Auto-import any .rake files in RAKELIBDIR. " + "(default is 'rakelib')", lambda { |value| options.rakelib = value.split(File::PATH_SEPARATOR) } ], ['--require', '-r MODULE', "Require MODULE before executing rakefile.", lambda { |value| begin require value rescue LoadError => ex begin rake_require value rescue LoadError raise ex end end } ], ['--rules', "Trace the rules resolution.", lambda { |value| options.trace_rules = true } ], ['--silent', '-s', "Like --quiet, but also suppresses the " + "'in directory' announcement.", lambda { |value| Rake.verbose(false) options.silent = true } ], ['--suppress-backtrace PATTERN', "Suppress backtrace lines matching regexp PATTERN. " + "Ignored if --trace is on.", lambda { |value| options.suppress_backtrace_pattern = Regexp.new(value) } ], ['--system', '-g', "Using system wide (global) rakefiles " + "(usually '~/.rake/*.rake').", lambda { |value| options.load_system = true } ], ['--no-system', '--nosystem', '-G', "Use standard project Rakefile search paths, " + "ignore system wide rakefiles.", lambda { |value| options.ignore_system = true } ], ['--tasks', '-T [PATTERN]', "Display the tasks (matching optional PATTERN) " + "with descriptions, then exit.", lambda { |value| select_tasks_to_show(options, :tasks, value) } ], ['--trace=[OUT]', '-t', "Turn on invoke/execute tracing, enable full backtrace. " + "OUT can be stderr (default) or stdout.", lambda { |value| options.trace = true options.backtrace = true select_trace_output(options, 'trace', value) Rake.verbose(true) } ], ['--verbose', '-v', "Log message to standard output.", lambda { |value| Rake.verbose(true) } ], ['--version', '-V', "Display the program version.", lambda { |value| puts "rake, version #{RAKEVERSION}" exit } ], ['--where', '-W [PATTERN]', "Describe the tasks (matching optional PATTERN), then exit.", lambda { |value| select_tasks_to_show(options, :lines, value) options.show_all_tasks = true } ], ['--no-deprecation-warnings', '-X', "Disable the deprecation warnings.", lambda { |value| options.ignore_deprecate = true } ], ]) end def select_tasks_to_show(options, show_tasks, value) # :nodoc: options.show_tasks = show_tasks options.show_task_pattern = Regexp.new(value || '') Rake::TaskManager.record_task_metadata = true end private :select_tasks_to_show def select_trace_output(options, trace_option, value) # :nodoc: value = value.strip unless value.nil? case value when 'stdout' options.trace_output = $stdout when 'stderr', nil options.trace_output = $stderr else fail CommandLineOptionError, "Unrecognized --#{trace_option} option '#{value}'" end end private :select_trace_output # Read and handle the command line options. Returns the command line # arguments that we didn't understand, which should (in theory) be just # task names and env vars. def handle_options # :nodoc: options.rakelib = ['rakelib'] options.trace_output = $stderr OptionParser.new do |opts| opts.banner = "#{Rake.application.name} [-f rakefile] {options} targets..." opts.separator "" opts.separator "Options are ..." opts.on_tail("-h", "--help", "-H", "Display this help message.") do puts opts exit end standard_rake_options.each { |args| opts.on(*args) } opts.environment('RAKEOPT') end.parse(ARGV) end # Similar to the regular Ruby +require+ command, but will check # for *.rake files in addition to *.rb files. def rake_require(file_name, paths=$LOAD_PATH, loaded=$") # :nodoc: fn = file_name + ".rake" return false if loaded.include?(fn) paths.each do |path| full_path = File.join(path, fn) if File.exist?(full_path) Rake.load_rakefile(full_path) loaded << fn return true end end fail LoadError, "Can't find #{file_name}" end def find_rakefile_location # :nodoc: here = Dir.pwd until (fn = have_rakefile) Dir.chdir("..") return nil if Dir.pwd == here || options.nosearch here = Dir.pwd end [fn, here] ensure Dir.chdir(Rake.original_dir) end def print_rakefile_directory(location) # :nodoc: $stderr.puts "(in #{Dir.pwd})" unless options.silent or original_dir == location end def raw_load_rakefile # :nodoc: rakefile, location = find_rakefile_location if (! options.ignore_system) && (options.load_system || rakefile.nil?) && system_dir && File.directory?(system_dir) print_rakefile_directory(location) glob("#{system_dir}/*.rake") do |name| add_import name end else fail "No Rakefile found (looking for: #{@rakefiles.join(', ')})" if rakefile.nil? @rakefile = rakefile Dir.chdir(location) print_rakefile_directory(location) Rake.load_rakefile(File.expand_path(@rakefile)) if @rakefile && @rakefile != '' options.rakelib.each do |rlib| glob("#{rlib}/*.rake") do |name| add_import name end end end load_imports end def glob(path, &block) # :nodoc: FileList.glob(path.gsub("\\", '/')).each(&block) end private :glob # The directory path containing the system wide rakefiles. def system_dir # :nodoc: @system_dir ||= begin if ENV['RAKE_SYSTEM'] ENV['RAKE_SYSTEM'] else standard_system_dir end end end # The standard directory containing system wide rake files. if Win32.windows? def standard_system_dir #:nodoc: Win32.win32_system_dir end else def standard_system_dir #:nodoc: File.join(File.expand_path('~'), '.rake') end end private :standard_system_dir # Collect the list of tasks on the command line. If no tasks are # given, return a list containing only the default task. # Environmental assignments are processed at this time as well. # # `args` is the list of arguments to peruse to get the list of tasks. # It should be the command line that was given to rake, less any # recognised command-line options, which OptionParser.parse will # have taken care of already. def collect_command_line_tasks(args) # :nodoc: @top_level_tasks = [] args.each do |arg| if arg =~ /^(\w+)=(.*)$/m ENV[$1] = $2 else @top_level_tasks << arg unless arg =~ /^-/ end end @top_level_tasks.push(default_task_name) if @top_level_tasks.empty? end # Default task name ("default"). # (May be overridden by subclasses) def default_task_name # :nodoc: "default" end # Add a file to the list of files to be imported. def add_import(fn) # :nodoc: @pending_imports << fn end # Load the pending list of imported files. def load_imports # :nodoc: while fn = @pending_imports.shift next if @imported.member?(fn) fn_task = lookup(fn) and fn_task.invoke ext = File.extname(fn) loader = @loaders[ext] || @default_loader loader.load(fn) if fn_task = lookup(fn) and fn_task.needed? fn_task.reenable fn_task.invoke loader.load(fn) end @imported << fn end end def rakefile_location(backtrace=caller) # :nodoc: backtrace.map { |t| t[/([^:]+):/, 1] } re = /^#{@rakefile}$/ re = /#{re.source}/i if windows? backtrace.find { |str| str =~ re } || '' end private FIXNUM_MAX = (2**(0.size * 8 - 2) - 1) # :nodoc: end end PK!;;2.2.0/rake/multi_task.rbnu[module Rake # Same as a regular task, but the immediate prerequisites are done in # parallel using Ruby threads. # class MultiTask < Task private def invoke_prerequisites(task_args, invocation_chain) # :nodoc: invoke_prerequisites_concurrently(task_args, invocation_chain) end end end PK!`2.2.0/rake/ext/pathname.rbnu[require 'rake/ext/core' require 'pathname' class Pathname rake_extension("ext") do # Return a new Pathname with String#ext applied to it. # # This Pathname extension comes from Rake def ext(newext='') Pathname.new(Rake.from_pathname(self).ext(newext)) end end rake_extension("pathmap") do # Apply the pathmap spec to the Pathname, returning a # new Pathname with the modified paths. (See String#pathmap for # details.) # # This Pathname extension comes from Rake def pathmap(spec=nil, &block) Pathname.new(Rake.from_pathname(self).pathmap(spec, &block)) end end end PK!S\9FF2.2.0/rake/ext/string.rbnu[require 'rake/ext/core' class String rake_extension("ext") do # Replace the file extension with +newext+. If there is no extension on # the string, append the new extension to the end. If the new extension # is not given, or is the empty string, remove any existing extension. # # +ext+ is a user added method for the String class. # # This String extension comes from Rake def ext(newext='') return self.dup if ['.', '..'].include? self newext = (newext =~ /^\./) ? newext : ("." + newext) if newext != '' self.chomp(File.extname(self)) << newext end end rake_extension("pathmap") do # Explode a path into individual components. Used by +pathmap+. # # This String extension comes from Rake def pathmap_explode head, tail = File.split(self) return [self] if head == self return [tail] if head == '.' || tail == '/' return [head, tail] if head == '/' return head.pathmap_explode + [tail] end protected :pathmap_explode # Extract a partial path from the path. Include +n+ directories from the # front end (left hand side) if +n+ is positive. Include |+n+| # directories from the back end (right hand side) if +n+ is negative. # # This String extension comes from Rake def pathmap_partial(n) dirs = File.dirname(self).pathmap_explode partial_dirs = if n > 0 dirs[0...n] elsif n < 0 dirs.reverse[0...-n].reverse else "." end File.join(partial_dirs) end protected :pathmap_partial # Perform the pathmap replacement operations on the given path. The # patterns take the form 'pat1,rep1;pat2,rep2...'. # # This String extension comes from Rake def pathmap_replace(patterns, &block) result = self patterns.split(';').each do |pair| pattern, replacement = pair.split(',') pattern = Regexp.new(pattern) if replacement == '*' && block_given? result = result.sub(pattern, &block) elsif replacement result = result.sub(pattern, replacement) else result = result.sub(pattern, '') end end result end protected :pathmap_replace # Map the path according to the given specification. The specification # controls the details of the mapping. The following special patterns are # recognized: # # %p :: The complete path. # %f :: The base file name of the path, with its file extension, # but without any directories. # %n :: The file name of the path without its file extension. # %d :: The directory list of the path. # %x :: The file extension of the path. An empty string if there # is no extension. # %X :: Everything *but* the file extension. # %s :: The alternate file separator if defined, otherwise use # # the standard file separator. # %% :: A percent sign. # # The %d specifier can also have a numeric prefix (e.g. '%2d'). # If the number is positive, only return (up to) +n+ directories in the # path, starting from the left hand side. If +n+ is negative, return (up # to) +n+ directories from the right hand side of the path. # # Examples: # # 'a/b/c/d/file.txt'.pathmap("%2d") => 'a/b' # 'a/b/c/d/file.txt'.pathmap("%-2d") => 'c/d' # # Also the %d, %p, %f, %n, # %x, and %X operators can take a pattern/replacement # argument to perform simple string substitutions on a particular part of # the path. The pattern and replacement are separated by a comma and are # enclosed by curly braces. The replacement spec comes after the % # character but before the operator letter. (e.g. "%{old,new}d"). # Multiple replacement specs should be separated by semi-colons (e.g. # "%{old,new;src,bin}d"). # # Regular expressions may be used for the pattern, and back refs may be # used in the replacement text. Curly braces, commas and semi-colons are # excluded from both the pattern and replacement text (let's keep parsing # reasonable). # # For example: # # "src/org/onestepback/proj/A.java".pathmap("%{^src,class}X.class") # # returns: # # "class/org/onestepback/proj/A.class" # # If the replacement text is '*', then a block may be provided to perform # some arbitrary calculation for the replacement. # # For example: # # "/path/to/file.TXT".pathmap("%X%{.*,*}x") { |ext| # ext.downcase # } # # Returns: # # "/path/to/file.txt" # # This String extension comes from Rake def pathmap(spec=nil, &block) return self if spec.nil? result = '' spec.scan(/%\{[^}]*\}-?\d*[sdpfnxX%]|%-?\d+d|%.|[^%]+/) do |frag| case frag when '%f' result << File.basename(self) when '%n' result << File.basename(self).ext when '%d' result << File.dirname(self) when '%x' result << File.extname(self) when '%X' result << self.ext when '%p' result << self when '%s' result << (File::ALT_SEPARATOR || File::SEPARATOR) when '%-' # do nothing when '%%' result << "%" when /%(-?\d+)d/ result << pathmap_partial($1.to_i) when /^%\{([^}]*)\}(\d*[dpfnxX])/ patterns, operator = $1, $2 result << pathmap('%' + operator).pathmap_replace(patterns, &block) when /^%/ fail ArgumentError, "Unknown pathmap specifier #{frag} in '#{spec}'" else result << frag end end result end end end PK!T2.2.0/rake/ext/module.rbnu[ # TODO: remove in Rake 11 PK!{Voo2.2.0/rake/ext/time.rbnu[#-- # Extensions to time to allow comparisons with early and late time classes. require 'rake/early_time' require 'rake/late_time' class Time # :nodoc: all alias rake_original_time_compare :<=> def <=>(other) if Rake::EarlyTime === other || Rake::LateTime === other - other.<=>(self) else rake_original_time_compare(other) end end end PK!:hy~~2.2.0/rake/ext/core.rbnu[class Module # Check for an existing method in the current class before extending. If # the method already exists, then a warning is printed and the extension is # not added. Otherwise the block is yielded and any definitions in the # block will take effect. # # Usage: # # class String # rake_extension("xyz") do # def xyz # ... # end # end # end # def rake_extension(method) # :nodoc: if method_defined?(method) $stderr.puts "WARNING: Possible conflict with Rake extension: " + "#{self}##{method} already exists" else yield end end end PK!|U2.2.0/rake/gempackagetask.rbnu[# TODO: Remove in Rake 11 fail "ERROR: 'rake/gempackagetask' is obsolete and no longer supported. " + "Use 'rubygems/package_task' instead." PK!K\2.2.0/rake/thread_pool.rbnu[require 'thread' require 'set' require 'rake/promise' module Rake class ThreadPool # :nodoc: all # Creates a ThreadPool object. The +thread_count+ parameter is the size # of the pool. def initialize(thread_count) @max_active_threads = [thread_count, 0].max @threads = Set.new @threads_mon = Monitor.new @queue = Queue.new @join_cond = @threads_mon.new_cond @history_start_time = nil @history = [] @history_mon = Monitor.new @total_threads_in_play = 0 end # Creates a future executed by the +ThreadPool+. # # The args are passed to the block when executing (similarly to # Thread#new) The return value is an object representing # a future which has been created and added to the queue in the # pool. Sending #value to the object will sleep the # current thread until the future is finished and will return the # result (or raise an exception thrown from the future) def future(*args, &block) promise = Promise.new(args, &block) promise.recorder = lambda { |*stats| stat(*stats) } @queue.enq promise stat :queued, :item_id => promise.object_id start_thread promise end # Waits until the queue of futures is empty and all threads have exited. def join @threads_mon.synchronize do begin stat :joining @join_cond.wait unless @threads.empty? stat :joined rescue Exception => e stat :joined $stderr.puts e $stderr.print "Queue contains #{@queue.size} items. " + "Thread pool contains #{@threads.count} threads\n" $stderr.print "Current Thread #{Thread.current} status = " + "#{Thread.current.status}\n" $stderr.puts e.backtrace.join("\n") @threads.each do |t| $stderr.print "Thread #{t} status = #{t.status}\n" # 1.8 doesn't support Thread#backtrace $stderr.puts t.backtrace.join("\n") if t.respond_to? :backtrace end raise e end end end # Enable the gathering of history events. def gather_history #:nodoc: @history_start_time = Time.now if @history_start_time.nil? end # Return a array of history events for the thread pool. # # History gathering must be enabled to be able to see the events # (see #gather_history). Best to call this when the job is # complete (i.e. after ThreadPool#join is called). def history # :nodoc: @history_mon.synchronize { @history.dup }. sort_by { |i| i[:time] }. each { |i| i[:time] -= @history_start_time } end # Return a hash of always collected statistics for the thread pool. def statistics # :nodoc: { :total_threads_in_play => @total_threads_in_play, :max_active_threads => @max_active_threads, } end private # processes one item on the queue. Returns true if there was an # item to process, false if there was no item def process_queue_item #:nodoc: return false if @queue.empty? # Even though we just asked if the queue was empty, it # still could have had an item which by this statement # is now gone. For this reason we pass true to Queue#deq # because we will sleep indefinitely if it is empty. promise = @queue.deq(true) stat :dequeued, :item_id => promise.object_id promise.work return true rescue ThreadError # this means the queue is empty false end def safe_thread_count @threads_mon.synchronize do @threads.count end end def start_thread # :nodoc: @threads_mon.synchronize do next unless @threads.count < @max_active_threads t = Thread.new do begin while safe_thread_count <= @max_active_threads break unless process_queue_item end ensure @threads_mon.synchronize do @threads.delete Thread.current stat :ended, :thread_count => @threads.count @join_cond.broadcast if @threads.empty? end end end @threads << t stat( :spawned, :new_thread => t.object_id, :thread_count => @threads.count) @total_threads_in_play = @threads.count if @threads.count > @total_threads_in_play end end def stat(event, data=nil) # :nodoc: return if @history_start_time.nil? info = { :event => event, :data => data, :time => Time.now, :thread => Thread.current.object_id, } @history_mon.synchronize { @history << info } end # for testing only def __queue__ # :nodoc: @queue end end end PK!C222.2.0/rake/testtask.rbnu[require 'rake' require 'rake/tasklib' module Rake # Create a task that runs a set of tests. # # Example: # # Rake::TestTask.new do |t| # t.libs << "test" # t.test_files = FileList['test/test*.rb'] # t.verbose = true # end # # If rake is invoked with a "TEST=filename" command line option, # then the list of test files will be overridden to include only the # filename specified on the command line. This provides an easy way # to run just one test. # # If rake is invoked with a "TESTOPTS=options" command line option, # then the given options are passed to the test process after a # '--'. This allows Test::Unit options to be passed to the test # suite. # # Examples: # # rake test # run tests normally # rake test TEST=just_one_file.rb # run just one test file. # rake test TESTOPTS="-v" # run in verbose mode # rake test TESTOPTS="--runner=fox" # use the fox test runner # class TestTask < TaskLib # Name of test task. (default is :test) attr_accessor :name # List of directories to added to $LOAD_PATH before running the # tests. (default is 'lib') attr_accessor :libs # True if verbose test output desired. (default is false) attr_accessor :verbose # Test options passed to the test suite. An explicit # TESTOPTS=opts on the command line will override this. (default # is NONE) attr_accessor :options # Request that the tests be run with the warning flag set. # E.g. warning=true implies "ruby -w" used to run the tests. attr_accessor :warning # Glob pattern to match test files. (default is 'test/test*.rb') attr_accessor :pattern # Style of test loader to use. Options are: # # * :rake -- Rake provided test loading script (default). # * :testrb -- Ruby provided test loading script. # * :direct -- Load tests using command line loader. # attr_accessor :loader # Array of commandline options to pass to ruby when running test loader. attr_accessor :ruby_opts # Description of the test task. (default is 'Run tests') attr_accessor :description # Explicitly define the list of test files to be included in a # test. +list+ is expected to be an array of file names (a # FileList is acceptable). If both +pattern+ and +test_files+ are # used, then the list of test files is the union of the two. def test_files=(list) @test_files = list end # Create a testing task. def initialize(name=:test) @name = name @libs = ["lib"] @pattern = nil @options = nil @test_files = nil @verbose = false @warning = false @loader = :rake @ruby_opts = [] @description = "Run tests" + (@name == :test ? "" : " for #{@name}") yield self if block_given? @pattern = 'test/test*.rb' if @pattern.nil? && @test_files.nil? define end # Create the tasks defined by this task lib. def define desc @description task @name do FileUtilsExt.verbose(@verbose) do args = "#{ruby_opts_string} #{run_code} " + "#{file_list_string} #{option_list}" ruby args do |ok, status| if !ok && status.respond_to?(:signaled?) && status.signaled? raise SignalException.new(status.termsig) elsif !ok fail "Command failed with status (#{status.exitstatus}): " + "[ruby #{args}]" end end end end self end def option_list # :nodoc: (ENV['TESTOPTS'] || ENV['TESTOPT'] || ENV['TEST_OPTS'] || ENV['TEST_OPT'] || @options || "") end def ruby_opts_string # :nodoc: opts = @ruby_opts.dup opts.unshift("-I\"#{lib_path}\"") unless @libs.empty? opts.unshift("-w") if @warning opts.join(" ") end def lib_path # :nodoc: @libs.join(File::PATH_SEPARATOR) end def file_list_string # :nodoc: file_list.map { |fn| "\"#{fn}\"" }.join(' ') end def file_list # :nodoc: if ENV['TEST'] FileList[ENV['TEST']] else result = [] result += @test_files.to_a if @test_files result << @pattern if @pattern result end end def fix # :nodoc: case ruby_version when '1.8.2' "\"#{find_file 'rake/ruby182_test_unit_fix'}\"" else nil end || '' end def ruby_version # :nodoc: RUBY_VERSION end def run_code # :nodoc: case @loader when :direct "-e \"ARGV.each{|f| require f}\"" when :testrb "-S testrb #{fix}" when :rake "#{rake_include_arg} \"#{rake_loader}\"" end end def rake_loader # :nodoc: find_file('rake/rake_test_loader') or fail "unable to find rake test loader" end def find_file(fn) # :nodoc: $LOAD_PATH.each do |path| file_path = File.join(path, "#{fn}.rb") return file_path if File.exist? file_path end nil end def rake_include_arg # :nodoc: spec = Gem.loaded_specs['rake'] if spec.respond_to?(:default_gem?) && spec.default_gem? "" else "-I\"#{rake_lib_dir}\"" end end def rake_lib_dir # :nodoc: find_dir('rake') or fail "unable to find rake lib" end def find_dir(fn) # :nodoc: $LOAD_PATH.each do |path| file_path = File.join(path, "#{fn}.rb") return path if File.exist? file_path end nil end end end PK!3-F2.2.0/rake/trace_output.rbnu[module Rake module TraceOutput # :nodoc: all # Write trace output to output stream +out+. # # The write is done as a single IO call (to print) to lessen the # chance that the trace output is interrupted by other tasks also # producing output. def trace_on(out, *strings) sep = $\ || "\n" if strings.empty? output = sep else output = strings.map { |s| next if s.nil? s =~ /#{sep}$/ ? s : s + sep }.join end out.print(output) end end end PK!?(,,2.2.0/rake/task.rbnu[require 'rake/invocation_exception_mixin' module Rake ## # A Task is the basic unit of work in a Rakefile. Tasks have associated # actions (possibly more than one) and a list of prerequisites. When # invoked, a task will first ensure that all of its prerequisites have an # opportunity to run and then it will execute its own actions. # # Tasks are not usually created directly using the new method, but rather # use the +file+ and +task+ convenience methods. # class Task # List of prerequisites for a task. attr_reader :prerequisites # List of actions attached to a task. attr_reader :actions # Application owning this task. attr_accessor :application # Array of nested namespaces names used for task lookup by this task. attr_reader :scope # File/Line locations of each of the task definitions for this # task (only valid if the task was defined with the detect # location option set). attr_reader :locations # Return task name def to_s name end def inspect # :nodoc: "<#{self.class} #{name} => [#{prerequisites.join(', ')}]>" end # List of sources for task. attr_writer :sources def sources if defined?(@sources) @sources else prerequisites end end # List of prerequisite tasks def prerequisite_tasks prerequisites.map { |pre| lookup_prerequisite(pre) } end def lookup_prerequisite(prerequisite_name) # :nodoc: application[prerequisite_name, @scope] end private :lookup_prerequisite # List of all unique prerequisite tasks including prerequisite tasks' # prerequisites. # Includes self when cyclic dependencies are found. def all_prerequisite_tasks seen = {} collect_prerequisites(seen) seen.values end def collect_prerequisites(seen) # :nodoc: prerequisite_tasks.each do |pre| next if seen[pre.name] seen[pre.name] = pre pre.collect_prerequisites(seen) end end protected :collect_prerequisites # First source from a rule (nil if no sources) def source sources.first end # Create a task named +task_name+ with no actions or prerequisites. Use # +enhance+ to add actions and prerequisites. def initialize(task_name, app) @name = task_name.to_s @prerequisites = [] @actions = [] @already_invoked = false @comments = [] @lock = Monitor.new @application = app @scope = app.current_scope @arg_names = nil @locations = [] end # Enhance a task with prerequisites or actions. Returns self. def enhance(deps=nil, &block) @prerequisites |= deps if deps @actions << block if block_given? self end # Name of the task, including any namespace qualifiers. def name @name.to_s end # Name of task with argument list description. def name_with_args # :nodoc: if arg_description "#{name}#{arg_description}" else name end end # Argument description (nil if none). def arg_description # :nodoc: @arg_names ? "[#{arg_names.join(',')}]" : nil end # Name of arguments for this task. def arg_names @arg_names || [] end # Reenable the task, allowing its tasks to be executed if the task # is invoked again. def reenable @already_invoked = false end # Clear the existing prerequisites and actions of a rake task. def clear clear_prerequisites clear_actions clear_comments self end # Clear the existing prerequisites of a rake task. def clear_prerequisites prerequisites.clear self end # Clear the existing actions on a rake task. def clear_actions actions.clear self end # Clear the existing comments on a rake task. def clear_comments @comments = [] self end # Invoke the task if it is needed. Prerequisites are invoked first. def invoke(*args) task_args = TaskArguments.new(arg_names, args) invoke_with_call_chain(task_args, InvocationChain::EMPTY) end # Same as invoke, but explicitly pass a call chain to detect # circular dependencies. def invoke_with_call_chain(task_args, invocation_chain) # :nodoc: new_chain = InvocationChain.append(self, invocation_chain) @lock.synchronize do if application.options.trace application.trace "** Invoke #{name} #{format_trace_flags}" end return if @already_invoked @already_invoked = true invoke_prerequisites(task_args, new_chain) execute(task_args) if needed? end rescue Exception => ex add_chain_to(ex, new_chain) raise ex end protected :invoke_with_call_chain def add_chain_to(exception, new_chain) # :nodoc: exception.extend(InvocationExceptionMixin) unless exception.respond_to?(:chain) exception.chain = new_chain if exception.chain.nil? end private :add_chain_to # Invoke all the prerequisites of a task. def invoke_prerequisites(task_args, invocation_chain) # :nodoc: if application.options.always_multitask invoke_prerequisites_concurrently(task_args, invocation_chain) else prerequisite_tasks.each { |p| prereq_args = task_args.new_scope(p.arg_names) p.invoke_with_call_chain(prereq_args, invocation_chain) } end end # Invoke all the prerequisites of a task in parallel. def invoke_prerequisites_concurrently(task_args, invocation_chain)# :nodoc: futures = prerequisite_tasks.map do |p| prereq_args = task_args.new_scope(p.arg_names) application.thread_pool.future(p) do |r| r.invoke_with_call_chain(prereq_args, invocation_chain) end end futures.each { |f| f.value } end # Format the trace flags for display. def format_trace_flags flags = [] flags << "first_time" unless @already_invoked flags << "not_needed" unless needed? flags.empty? ? "" : "(" + flags.join(", ") + ")" end private :format_trace_flags # Execute the actions associated with this task. def execute(args=nil) args ||= EMPTY_TASK_ARGS if application.options.dryrun application.trace "** Execute (dry run) #{name}" return end application.trace "** Execute #{name}" if application.options.trace application.enhance_with_matching_rule(name) if @actions.empty? @actions.each do |act| case act.arity when 1 act.call(self) else act.call(self, args) end end end # Is this task needed? def needed? true end # Timestamp for this task. Basic tasks return the current time for their # time stamp. Other tasks can be more sophisticated. def timestamp Time.now end # Add a description to the task. The description can consist of an option # argument list (enclosed brackets) and an optional comment. def add_description(description) return unless description comment = description.strip add_comment(comment) if comment && ! comment.empty? end def comment=(comment) # :nodoc: add_comment(comment) end def add_comment(comment) # :nodoc: return if comment.nil? @comments << comment unless @comments.include?(comment) end private :add_comment # Full collection of comments. Multiple comments are separated by # newlines. def full_comment transform_comments("\n") end # First line (or sentence) of all comments. Multiple comments are # separated by a "/". def comment transform_comments(" / ") { |c| first_sentence(c) } end # Transform the list of comments as specified by the block and # join with the separator. def transform_comments(separator, &block) if @comments.empty? nil else block ||= lambda { |c| c } @comments.map(&block).join(separator) end end private :transform_comments # Get the first sentence in a string. The sentence is terminated # by the first period or the end of the line. Decimal points do # not count as periods. def first_sentence(string) string.split(/\.[ \t]|\.$|\n/).first end private :first_sentence # Set the names of the arguments for this task. +args+ should be # an array of symbols, one for each argument name. def set_arg_names(args) @arg_names = args.map { |a| a.to_sym } end # Return a string describing the internal state of a task. Useful for # debugging. def investigation result = "------------------------------\n" result << "Investigating #{name}\n" result << "class: #{self.class}\n" result << "task needed: #{needed?}\n" result << "timestamp: #{timestamp}\n" result << "pre-requisites: \n" prereqs = prerequisite_tasks prereqs.sort! { |a, b| a.timestamp <=> b.timestamp } prereqs.each do |p| result << "--#{p.name} (#{p.timestamp})\n" end latest_prereq = prerequisite_tasks.map { |pre| pre.timestamp }.max result << "latest-prerequisite time: #{latest_prereq}\n" result << "................................\n\n" return result end # ---------------------------------------------------------------- # Rake Module Methods # class << self # Clear the task list. This cause rake to immediately forget all the # tasks that have been assigned. (Normally used in the unit tests.) def clear Rake.application.clear end # List of all defined tasks. def tasks Rake.application.tasks end # Return a task with the given name. If the task is not currently # known, try to synthesize one from the defined rules. If no rules are # found, but an existing file matches the task name, assume it is a file # task with no dependencies or actions. def [](task_name) Rake.application[task_name] end # TRUE if the task name is already defined. def task_defined?(task_name) Rake.application.lookup(task_name) != nil end # Define a task given +args+ and an option block. If a rule with the # given name already exists, the prerequisites and actions are added to # the existing task. Returns the defined task. def define_task(*args, &block) Rake.application.define_task(self, *args, &block) end # Define a rule for synthesizing tasks. def create_rule(*args, &block) Rake.application.create_rule(*args, &block) end # Apply the scope to the task name according to the rules for # this kind of task. Generic tasks will accept the scope as # part of the name. def scope_name(scope, task_name) # (scope + [task_name]).join(':') scope.path_with_task_name(task_name) end end # class << Rake::Task end # class Rake::Task end PK!V2.2.0/rake/task_arguments.rbnu[module Rake ## # TaskArguments manage the arguments passed to a task. # class TaskArguments include Enumerable # Argument names attr_reader :names # Create a TaskArgument object with a list of argument +names+ and a set # of associated +values+. +parent+ is the parent argument object. def initialize(names, values, parent=nil) @names = names @parent = parent @hash = {} @values = values names.each_with_index { |name, i| @hash[name.to_sym] = values[i] unless values[i].nil? } end # Retrieve the complete array of sequential values def to_a @values.dup end # Retrieve the list of values not associated with named arguments def extras @values[@names.length..-1] || [] end # Create a new argument scope using the prerequisite argument # names. def new_scope(names) values = names.map { |n| self[n] } self.class.new(names, values + extras, self) end # Find an argument value by name or index. def [](index) lookup(index.to_sym) end # Specify a hash of default values for task arguments. Use the # defaults only if there is no specific value for the given # argument. def with_defaults(defaults) @hash = defaults.merge(@hash) end # Enumerates the arguments and their values def each(&block) @hash.each(&block) end # Extracts the argument values at +keys+ def values_at(*keys) keys.map { |k| lookup(k) } end # Returns the value of the given argument via method_missing def method_missing(sym, *args) lookup(sym.to_sym) end # Returns a Hash of arguments and their values def to_hash @hash end def to_s # :nodoc: @hash.inspect end def inspect # :nodoc: to_s end # Returns true if +key+ is one of the arguments def has_key?(key) @hash.has_key?(key) end protected def lookup(name) # :nodoc: if @hash.has_key?(name) @hash[name] elsif @parent @parent.lookup(name) end end end EMPTY_TASK_ARGS = TaskArguments.new([], []) # :nodoc: end PK!K2.2.0/rake/default_loader.rbnu[module Rake # Default Rakefile loader used by +import+. class DefaultLoader ## # Loads a rakefile into the current application from +fn+ def load(fn) Rake.load_rakefile(File.expand_path(fn)) end end end PK!22.2.0/rake/clean.rbnu[# The 'rake/clean' file defines two file lists (CLEAN and CLOBBER) and # two rake tasks (:clean and :clobber). # # [:clean] Clean up the project by deleting scratch files and backup # files. Add files to the CLEAN file list to have the :clean # target handle them. # # [:clobber] Clobber all generated and non-source files in a project. # The task depends on :clean, so all the clean files will # be deleted as well as files in the CLOBBER file list. # The intent of this task is to return a project to its # pristine, just unpacked state. require 'rake' # :stopdoc: module Rake module Cleaner extend FileUtils module_function def cleanup_files(file_names) file_names.each do |file_name| cleanup(file_name) end end def cleanup(file_name, opts={}) begin rm_r file_name, opts rescue StandardError => ex puts "Failed to remove #{file_name}: #{ex}" unless file_already_gone?(file_name) end end def file_already_gone?(file_name) return false if File.exist?(file_name) path = file_name prev = nil while path = File.dirname(path) return false if cant_be_deleted?(path) break if [prev, "."].include?(path) prev = path end true end private_class_method :file_already_gone? def cant_be_deleted?(path_name) File.exist?(path_name) && (!File.readable?(path_name) || !File.executable?(path_name)) end private_class_method :cant_be_deleted? end end CLEAN = ::Rake::FileList["**/*~", "**/*.bak", "**/core"] CLEAN.clear_exclude.exclude { |fn| fn.pathmap("%f").downcase == 'core' && File.directory?(fn) } desc "Remove any temporary products." task :clean do Rake::Cleaner.cleanup_files(CLEAN) end CLOBBER = ::Rake::FileList.new desc "Remove any generated file." task :clobber => [:clean] do Rake::Cleaner.cleanup_files(CLOBBER) end PK!1K002.2.0/rake/file_list.rbnu[require 'rake/cloneable' require 'rake/file_utils_ext' require 'rake/pathmap' module Rake ## # A FileList is essentially an array with a few helper methods defined to # make file manipulation a bit easier. # # FileLists are lazy. When given a list of glob patterns for possible files # to be included in the file list, instead of searching the file structures # to find the files, a FileList holds the pattern for latter use. # # This allows us to define a number of FileList to match any number of # files, but only search out the actual files when then FileList itself is # actually used. The key is that the first time an element of the # FileList/Array is requested, the pending patterns are resolved into a real # list of file names. # class FileList include Cloneable # == Method Delegation # # The lazy evaluation magic of FileLists happens by implementing all the # array specific methods to call +resolve+ before delegating the heavy # lifting to an embedded array object (@items). # # In addition, there are two kinds of delegation calls. The regular kind # delegates to the @items array and returns the result directly. Well, # almost directly. It checks if the returned value is the @items object # itself, and if so will return the FileList object instead. # # The second kind of delegation call is used in methods that normally # return a new Array object. We want to capture the return value of these # methods and wrap them in a new FileList object. We enumerate these # methods in the +SPECIAL_RETURN+ list below. # List of array methods (that are not in +Object+) that need to be # delegated. ARRAY_METHODS = (Array.instance_methods - Object.instance_methods). map { |n| n.to_s } # List of additional methods that must be delegated. MUST_DEFINE = %w[inspect <=>] # List of methods that should not be delegated here (we define special # versions of them explicitly below). MUST_NOT_DEFINE = %w[to_a to_ary partition * <<] # List of delegated methods that return new array values which need # wrapping. SPECIAL_RETURN = %w[ map collect sort sort_by select find_all reject grep compact flatten uniq values_at + - & | ] DELEGATING_METHODS = (ARRAY_METHODS + MUST_DEFINE - MUST_NOT_DEFINE). map { |s| s.to_s }.sort.uniq # Now do the delegation. DELEGATING_METHODS.each do |sym| if SPECIAL_RETURN.include?(sym) ln = __LINE__ + 1 class_eval %{ def #{sym}(*args, &block) resolve result = @items.send(:#{sym}, *args, &block) FileList.new.import(result) end }, __FILE__, ln else ln = __LINE__ + 1 class_eval %{ def #{sym}(*args, &block) resolve result = @items.send(:#{sym}, *args, &block) result.object_id == @items.object_id ? self : result end }, __FILE__, ln end end # Create a file list from the globbable patterns given. If you wish to # perform multiple includes or excludes at object build time, use the # "yield self" pattern. # # Example: # file_list = FileList.new('lib/**/*.rb', 'test/test*.rb') # # pkg_files = FileList.new('lib/**/*') do |fl| # fl.exclude(/\bCVS\b/) # end # def initialize(*patterns) @pending_add = [] @pending = false @exclude_patterns = DEFAULT_IGNORE_PATTERNS.dup @exclude_procs = DEFAULT_IGNORE_PROCS.dup @items = [] patterns.each { |pattern| include(pattern) } yield self if block_given? end # Add file names defined by glob patterns to the file list. If an array # is given, add each element of the array. # # Example: # file_list.include("*.java", "*.cfg") # file_list.include %w( math.c lib.h *.o ) # def include(*filenames) # TODO: check for pending filenames.each do |fn| if fn.respond_to? :to_ary include(*fn.to_ary) else @pending_add << Rake.from_pathname(fn) end end @pending = true self end alias :add :include # Register a list of file name patterns that should be excluded from the # list. Patterns may be regular expressions, glob patterns or regular # strings. In addition, a block given to exclude will remove entries that # return true when given to the block. # # Note that glob patterns are expanded against the file system. If a file # is explicitly added to a file list, but does not exist in the file # system, then an glob pattern in the exclude list will not exclude the # file. # # Examples: # FileList['a.c', 'b.c'].exclude("a.c") => ['b.c'] # FileList['a.c', 'b.c'].exclude(/^a/) => ['b.c'] # # If "a.c" is a file, then ... # FileList['a.c', 'b.c'].exclude("a.*") => ['b.c'] # # If "a.c" is not a file, then ... # FileList['a.c', 'b.c'].exclude("a.*") => ['a.c', 'b.c'] # def exclude(*patterns, &block) patterns.each do |pat| @exclude_patterns << Rake.from_pathname(pat) end @exclude_procs << block if block_given? resolve_exclude unless @pending self end # Clear all the exclude patterns so that we exclude nothing. def clear_exclude @exclude_patterns = [] @exclude_procs = [] self end # A FileList is equal through array equality. def ==(array) to_ary == array end # Return the internal array object. def to_a resolve @items end # Return the internal array object. def to_ary to_a end # Lie about our class. def is_a?(klass) klass == Array || super(klass) end alias kind_of? is_a? # Redefine * to return either a string or a new file list. def *(other) result = @items * other case result when Array FileList.new.import(result) else result end end def <<(obj) resolve @items << Rake.from_pathname(obj) self end # Resolve all the pending adds now. def resolve if @pending @pending = false @pending_add.each do |fn| resolve_add(fn) end @pending_add = [] resolve_exclude end self end def resolve_add(fn) # :nodoc: case fn when %r{[*?\[\{]} add_matching(fn) else self << fn end end private :resolve_add def resolve_exclude # :nodoc: reject! { |fn| excluded_from_list?(fn) } self end private :resolve_exclude # Return a new FileList with the results of running +sub+ against each # element of the original list. # # Example: # FileList['a.c', 'b.c'].sub(/\.c$/, '.o') => ['a.o', 'b.o'] # def sub(pat, rep) inject(FileList.new) { |res, fn| res << fn.sub(pat, rep) } end # Return a new FileList with the results of running +gsub+ against each # element of the original list. # # Example: # FileList['lib/test/file', 'x/y'].gsub(/\//, "\\") # => ['lib\\test\\file', 'x\\y'] # def gsub(pat, rep) inject(FileList.new) { |res, fn| res << fn.gsub(pat, rep) } end # Same as +sub+ except that the original file list is modified. def sub!(pat, rep) each_with_index { |fn, i| self[i] = fn.sub(pat, rep) } self end # Same as +gsub+ except that the original file list is modified. def gsub!(pat, rep) each_with_index { |fn, i| self[i] = fn.gsub(pat, rep) } self end # Apply the pathmap spec to each of the included file names, returning a # new file list with the modified paths. (See String#pathmap for # details.) def pathmap(spec=nil) collect { |fn| fn.pathmap(spec) } end # Return a new FileList with String#ext method applied to # each member of the array. # # This method is a shortcut for: # # array.collect { |item| item.ext(newext) } # # +ext+ is a user added method for the Array class. def ext(newext='') collect { |fn| fn.ext(newext) } end # Grep each of the files in the filelist using the given pattern. If a # block is given, call the block on each matching line, passing the file # name, line number, and the matching line of text. If no block is given, # a standard emacs style file:linenumber:line message will be printed to # standard out. Returns the number of matched items. def egrep(pattern, *options) matched = 0 each do |fn| begin open(fn, "r", *options) do |inf| count = 0 inf.each do |line| count += 1 if pattern.match(line) matched += 1 if block_given? yield fn, count, line else puts "#{fn}:#{count}:#{line}" end end end end rescue StandardError => ex $stderr.puts "Error while processing '#{fn}': #{ex}" end end matched end # Return a new file list that only contains file names from the current # file list that exist on the file system. def existing select { |fn| File.exist?(fn) } end # Modify the current file list so that it contains only file name that # exist on the file system. def existing! resolve @items = @items.select { |fn| File.exist?(fn) } self end # FileList version of partition. Needed because the nested arrays should # be FileLists in this version. def partition(&block) # :nodoc: resolve result = @items.partition(&block) [ FileList.new.import(result[0]), FileList.new.import(result[1]), ] end # Convert a FileList to a string by joining all elements with a space. def to_s resolve self.join(' ') end # Add matching glob patterns. def add_matching(pattern) FileList.glob(pattern).each do |fn| self << fn unless excluded_from_list?(fn) end end private :add_matching # Should the given file name be excluded from the list? # # NOTE: This method was formerly named "exclude?", but Rails # introduced an exclude? method as an array method and setup a # conflict with file list. We renamed the method to avoid # confusion. If you were using "FileList#exclude?" in your user # code, you will need to update. def excluded_from_list?(fn) return true if @exclude_patterns.any? do |pat| case pat when Regexp fn =~ pat when /[*?]/ File.fnmatch?(pat, fn, File::FNM_PATHNAME) else fn == pat end end @exclude_procs.any? { |p| p.call(fn) } end DEFAULT_IGNORE_PATTERNS = [ /(^|[\/\\])CVS([\/\\]|$)/, /(^|[\/\\])\.svn([\/\\]|$)/, /\.bak$/, /~$/ ] DEFAULT_IGNORE_PROCS = [ proc { |fn| fn =~ /(^|[\/\\])core$/ && ! File.directory?(fn) } ] def import(array) # :nodoc: @items = array self end class << self # Create a new file list including the files listed. Similar to: # # FileList.new(*args) def [](*args) new(*args) end # Get a sorted list of files matching the pattern. This method # should be preferred to Dir[pattern] and Dir.glob(pattern) because # the files returned are guaranteed to be sorted. def glob(pattern, *args) Dir.glob(pattern, *args).sort end end end end module Rake class << self # Yield each file or directory component. def each_dir_parent(dir) # :nodoc: old_length = nil while dir != '.' && dir.length != old_length yield(dir) old_length = dir.length dir = File.dirname(dir) end end # Convert Pathname and Pathname-like objects to strings; # leave everything else alone def from_pathname(path) # :nodoc: path = path.to_path if path.respond_to?(:to_path) path = path.to_str if path.respond_to?(:to_str) path end end end # module Rake PK!C552.2.0/rake/pathmap.rbnu[# TODO: Remove in Rake 11 require 'rake/ext/string' PK!P P 2.2.0/rake/cpu_counter.rbnu[module Rake # Based on a script at: # http://stackoverflow.com/questions/891537/ruby-detect-number-of-cpus-installed class CpuCounter # :nodoc: all def self.count new.count_with_default end def count_with_default(default=4) count || default rescue StandardError default end begin require 'etc' rescue LoadError else if Etc.respond_to?(:nprocessors) def count return Etc.nprocessors end end end end end unless Rake::CpuCounter.method_defined?(:count) Rake::CpuCounter.class_eval <<-'end;', __FILE__, __LINE__+1 require 'rbconfig' # TODO: replace with IO.popen using array-style arguments in Rake 11 require 'open3' def count if defined?(Java::Java) count_via_java_runtime else case RbConfig::CONFIG['host_os'] when /darwin9/ count_via_hwprefs_cpu_count when /darwin/ count_via_hwprefs_thread_count || count_via_sysctl when /linux/ count_via_cpuinfo when /bsd/ count_via_sysctl when /mswin|mingw/ count_via_win32 else # Try everything count_via_win32 || count_via_sysctl || count_via_hwprefs_thread_count || count_via_hwprefs_cpu_count || count_via_cpuinfo end end end def count_via_java_runtime Java::Java.lang.Runtime.getRuntime.availableProcessors rescue StandardError nil end def count_via_win32 require 'win32ole' wmi = WIN32OLE.connect("winmgmts://") cpu = wmi.ExecQuery("select NumberOfCores from Win32_Processor") # TODO count hyper-threaded in this cpu.to_enum.first.NumberOfCores rescue StandardError, LoadError nil end def count_via_cpuinfo open('/proc/cpuinfo') { |f| f.readlines }.grep(/processor/).size rescue StandardError nil end def count_via_hwprefs_thread_count run 'hwprefs', 'thread_count' end def count_via_hwprefs_cpu_count run 'hwprefs', 'cpu_count' end def count_via_sysctl run 'sysctl', '-n', 'hw.ncpu' end def run(command, *args) cmd = resolve_command(command) if cmd Open3.popen3 cmd, *args do |inn, out, err,| inn.close err.read out.read.to_i end else nil end end def resolve_command(command) look_for_command("/usr/sbin", command) || look_for_command("/sbin", command) || in_path_command(command) end def look_for_command(dir, command) path = File.join(dir, command) File.exist?(path) ? path : nil end def in_path_command(command) Open3.popen3 'which', command do |_, out,| out.eof? ? nil : command end end end; end PK!׬$UU2.2.0/rake/rake_test_loader.rbnu[require 'rake' # Load the test files from the command line. argv = ARGV.select do |argument| case argument when /^-/ then argument when /\*/ then FileList[argument].to_a.each do |file| require File.expand_path file end false else require File.expand_path argument false end end ARGV.replace argv PK!$552.2.0/rake/file_utils_ext.rbnu[require 'rake/file_utils' module Rake # # FileUtilsExt provides a custom version of the FileUtils methods # that respond to the verbose and nowrite # commands. # module FileUtilsExt include FileUtils class << self attr_accessor :verbose_flag, :nowrite_flag end DEFAULT = Object.new FileUtilsExt.verbose_flag = DEFAULT FileUtilsExt.nowrite_flag = false FileUtils.commands.each do |name| opts = FileUtils.options_of name default_options = [] if opts.include?("verbose") default_options << ':verbose => FileUtilsExt.verbose_flag' end if opts.include?("noop") default_options << ':noop => FileUtilsExt.nowrite_flag' end next if default_options.empty? module_eval(<<-EOS, __FILE__, __LINE__ + 1) def #{name}( *args, &block ) super( *rake_merge_option(args, #{default_options.join(', ')} ), &block) end EOS end # Get/set the verbose flag controlling output from the FileUtils # utilities. If verbose is true, then the utility method is # echoed to standard output. # # Examples: # verbose # return the current value of the # # verbose flag # verbose(v) # set the verbose flag to _v_. # verbose(v) { code } # Execute code with the verbose flag set # # temporarily to _v_. Return to the # # original value when code is done. def verbose(value=nil) oldvalue = FileUtilsExt.verbose_flag FileUtilsExt.verbose_flag = value unless value.nil? if block_given? begin yield ensure FileUtilsExt.verbose_flag = oldvalue end end FileUtilsExt.verbose_flag end # Get/set the nowrite flag controlling output from the FileUtils # utilities. If verbose is true, then the utility method is # echoed to standard output. # # Examples: # nowrite # return the current value of the # # nowrite flag # nowrite(v) # set the nowrite flag to _v_. # nowrite(v) { code } # Execute code with the nowrite flag set # # temporarily to _v_. Return to the # # original value when code is done. def nowrite(value=nil) oldvalue = FileUtilsExt.nowrite_flag FileUtilsExt.nowrite_flag = value unless value.nil? if block_given? begin yield ensure FileUtilsExt.nowrite_flag = oldvalue end end oldvalue end # Use this function to prevent potentially destructive ruby code # from running when the :nowrite flag is set. # # Example: # # when_writing("Building Project") do # project.build # end # # The following code will build the project under normal # conditions. If the nowrite(true) flag is set, then the example # will print: # # DRYRUN: Building Project # # instead of actually building the project. # def when_writing(msg=nil) if FileUtilsExt.nowrite_flag $stderr.puts "DRYRUN: #{msg}" if msg else yield end end # Merge the given options with the default values. def rake_merge_option(args, defaults) if Hash === args.last defaults.update(args.last) args.pop end args.push defaults args end # Send the message to the default rake output (which is $stderr). def rake_output_message(message) $stderr.puts(message) end # Check that the options do not contain options not listed in # +optdecl+. An ArgumentError exception is thrown if non-declared # options are found. def rake_check_options(options, *optdecl) h = options.dup optdecl.each do |name| h.delete name end raise ArgumentError, "no such option: #{h.keys.join(' ')}" unless h.empty? end extend self end end PK!@i2.2.0/rake/rdoctask.rbnu[# TODO: Remove in Rake 11 fail "ERROR: 'rake/rdoctask' is obsolete and no longer supported. " + "Use 'rdoc/task' (available in RDoc 2.4.2+) instead." PK!ٹT{ww!2.2.0/rake/task_argument_error.rbnu[module Rake # Error indicating an ill-formed task declaration. class TaskArgumentError < ArgumentError end end PK!  2.2.0/rake/file_task.rbnu[require 'rake/task.rb' require 'rake/early_time' module Rake # A FileTask is a task that includes time based dependencies. If any of a # FileTask's prerequisites have a timestamp that is later than the file # represented by this task, then the file must be rebuilt (using the # supplied actions). # class FileTask < Task # Is this file task needed? Yes if it doesn't exist, or if its time stamp # is out of date. def needed? ! File.exist?(name) || out_of_date?(timestamp) || @application.options.build_all end # Time stamp for file task. def timestamp if File.exist?(name) File.mtime(name.to_s) else Rake::LATE end end private # Are there any prerequisites with a later time than the given time stamp? def out_of_date?(stamp) @prerequisites.any? { |n| application[n, @scope].timestamp > stamp } end # ---------------------------------------------------------------- # Task class methods. # class << self # Apply the scope to the task name according to the rules for this kind # of task. File based tasks ignore the scope when creating the name. def scope_name(scope, task_name) Rake.from_pathname(task_name) end end end end PK! Iddd2.2.0/rake/backtrace.rbnu[module Rake module Backtrace # :nodoc: all SYS_KEYS = RbConfig::CONFIG.keys.grep(/(?:[a-z]prefix|libdir)\z/) SYS_PATHS = RbConfig::CONFIG.values_at(*SYS_KEYS).uniq + [ File.join(File.dirname(__FILE__), "..") ] SUPPRESSED_PATHS = SYS_PATHS. map { |s| s.gsub("\\", "/") }. map { |f| File.expand_path(f) }. reject { |s| s.nil? || s =~ /^ *$/ } SUPPRESSED_PATHS_RE = SUPPRESSED_PATHS.map { |f| Regexp.quote(f) }.join("|") SUPPRESSED_PATHS_RE << "|^org\\/jruby\\/\\w+\\.java" if Object.const_defined?(:RUBY_ENGINE) and RUBY_ENGINE == 'jruby' SUPPRESS_PATTERN = %r!(\A(#{SUPPRESSED_PATHS_RE})|bin/rake:\d+)!i def self.collapse(backtrace) pattern = Rake.application.options.suppress_backtrace_pattern || SUPPRESS_PATTERN backtrace.reject { |elem| elem =~ pattern } end end end PK!(.  2.2.0/rake/late_time.rbnu[module Rake # LateTime is a fake timestamp that occurs _after_ any other time value. class LateTime include Comparable include Singleton def <=>(other) 1 end def to_s '' end end LATE = LateTime.instance end PK!a[2.2.0/rake/loaders/makefile.rbnu[module Rake # Makefile loader to be used with the import file loader. class MakefileLoader include Rake::DSL SPACE_MARK = "\0" # Load the makefile dependencies in +fn+. def load(fn) lines = File.read fn lines.gsub!(/\\ /, SPACE_MARK) lines.gsub!(/#[^\n]*\n/m, "") lines.gsub!(/\\\n/, ' ') lines.each_line do |line| process_line(line) end end private # Process one logical line of makefile data. def process_line(line) file_tasks, args = line.split(':', 2) return if args.nil? dependents = args.split.map { |d| respace(d) } file_tasks.scan(/\S+/) do |file_task| file_task = respace(file_task) file file_task => dependents end end def respace(str) str.tr SPACE_MARK, ' ' end end # Install the handler Rake.application.add_loader('mf', MakefileLoader.new) end PK!FHw2.2.0/rake/cloneable.rbnu[module Rake ## # Mixin for creating easily cloned objects. module Cloneable # :nodoc: # The hook that is invoked by 'clone' and 'dup' methods. def initialize_copy(source) super source.instance_variables.each do |var| src_value = source.instance_variable_get(var) value = src_value.clone rescue src_value instance_variable_set(var, value) end end end end PK!=uTT2.2.0/rake/early_time.rbnu[module Rake # EarlyTime is a fake timestamp that occurs _before_ any other time value. class EarlyTime include Comparable include Singleton ## # The EarlyTime always comes before +other+! def <=>(other) -1 end def to_s # :nodoc: "" end end EARLY = EarlyTime.instance end PK!P2__2.2.0/rake/phony.rbnu[# Defines a :phony task that you can use as a dependency. This allows # file-based tasks to use non-file-based tasks as prerequisites # without forcing them to rebuild. # # See FileTask#out_of_date? and Task#timestamp for more info. require 'rake' task :phony Rake::Task[:phony].tap do |task| def task.timestamp # :nodoc: Time.at 0 end end PK!@\442.2.0/rake/win32.rbnu[ module Rake require 'rake/alt_system' # Win 32 interface methods for Rake. Windows specific functionality # will be placed here to collect that knowledge in one spot. module Win32 # :nodoc: all # Error indicating a problem in locating the home directory on a # Win32 system. class Win32HomeError < RuntimeError end class << self # True if running on a windows system. def windows? AltSystem::WINDOWS end # Run a command line on windows. def rake_system(*cmd) AltSystem.system(*cmd) end # The standard directory containing system wide rake files on # Win 32 systems. Try the following environment variables (in # order): # # * HOME # * HOMEDRIVE + HOMEPATH # * APPDATA # * USERPROFILE # # If the above are not defined, the return nil. def win32_system_dir #:nodoc: win32_shared_path = ENV['HOME'] if win32_shared_path.nil? && ENV['HOMEDRIVE'] && ENV['HOMEPATH'] win32_shared_path = ENV['HOMEDRIVE'] + ENV['HOMEPATH'] end win32_shared_path ||= ENV['APPDATA'] win32_shared_path ||= ENV['USERPROFILE'] raise Win32HomeError, "Unable to determine home path environment variable." if win32_shared_path.nil? or win32_shared_path.empty? normalize(File.join(win32_shared_path, 'Rake')) end # Normalize a win32 path so that the slashes are all forward slashes. def normalize(path) path.gsub(/\\/, '/') end end end end PK!  2.2.0/rake/linked_list.rbnu[module Rake # Polylithic linked list structure used to implement several data # structures in Rake. class LinkedList include Enumerable attr_reader :head, :tail def initialize(head, tail=EMPTY) @head = head @tail = tail end # Polymorphically add a new element to the head of a list. The # type of head node will be the same list type as the tail. def conj(item) self.class.cons(item, self) end # Is the list empty? def empty? false end # Lists are structurally equivalent. def ==(other) current = self while ! current.empty? && ! other.empty? return false if current.head != other.head current = current.tail other = other.tail end current.empty? && other.empty? end # Convert to string: LL(item, item...) def to_s items = map { |item| item.to_s }.join(", ") "LL(#{items})" end # Same as +to_s+, but with inspected items. def inspect items = map { |item| item.inspect }.join(", ") "LL(#{items})" end # For each item in the list. def each current = self while ! current.empty? yield(current.head) current = current.tail end self end # Make a list out of the given arguments. This method is # polymorphic def self.make(*args) result = empty args.reverse_each do |item| result = cons(item, result) end result end # Cons a new head onto the tail list. def self.cons(head, tail) new(head, tail) end # The standard empty list class for the given LinkedList class. def self.empty self::EMPTY end # Represent an empty list, using the Null Object Pattern. # # When inheriting from the LinkedList class, you should implement # a type specific Empty class as well. Make sure you set the class # instance variable @parent to the associated list class (this # allows conj, cons and make to work polymorphically). class EmptyLinkedList < LinkedList @parent = LinkedList def initialize end def empty? true end def self.cons(head, tail) @parent.cons(head, tail) end end EMPTY = EmptyLinkedList.new end end PK!l!WW(2.2.0/rake/contrib/rubyforgepublisher.rbnu[# TODO: Remove in Rake 11 require 'rake/contrib/sshpublisher' module Rake class RubyForgePublisher < SshDirPublisher # :nodoc: all attr_reader :project, :proj_id, :user def initialize(projname, user) super( "#{user}@rubyforge.org", "/var/www/gforge-projects/#{projname}", "html") end end end PK!"2.2.0/rake/contrib/publisher.rbnu[# Copyright 2003-2010 by Jim Weirich (jim.weirich@gmail.com) # All rights reserved. # :stopdoc: # Configuration information about an upload host system. # name :: Name of host system. # webdir :: Base directory for the web information for the # application. The application name (APP) is appended to # this directory before using. # pkgdir :: Directory on the host system where packages can be # placed. HostInfo = Struct.new(:name, :webdir, :pkgdir) # :startdoc: # TODO: Move to contrib/sshpublisher #-- # Manage several publishers as a single entity. class CompositePublisher # :nodoc: def initialize @publishers = [] end # Add a publisher to the composite. def add(pub) @publishers << pub end # Upload all the individual publishers. def upload @publishers.each { |p| p.upload } end end # TODO: Remove in Rake 11, duplicated #-- # Publish an entire directory to an existing remote directory using # SSH. class SshDirPublisher # :nodoc: all def initialize(host, remote_dir, local_dir) @host = host @remote_dir = remote_dir @local_dir = local_dir end def upload run %{scp -rq #{@local_dir}/* #{@host}:#{@remote_dir}} end end # TODO: Remove in Rake 11, duplicated #-- # Publish an entire directory to a fresh remote directory using SSH. class SshFreshDirPublisher < SshDirPublisher # :nodoc: all def upload run %{ssh #{@host} rm -rf #{@remote_dir}} rescue nil run %{ssh #{@host} mkdir #{@remote_dir}} super end end # TODO: Remove in Rake 11, duplicated #-- # Publish a list of files to an existing remote directory. class SshFilePublisher # :nodoc: all # Create a publisher using the give host information. def initialize(host, remote_dir, local_dir, *files) @host = host @remote_dir = remote_dir @local_dir = local_dir @files = files end # Upload the local directory to the remote directory. def upload @files.each do |fn| run %{scp -q #{@local_dir}/#{fn} #{@host}:#{@remote_dir}} end end end PK!_.<2.2.0/rake/contrib/sys.rbnu[# TODO: Remove in Rake 11 fail "ERROR: 'rake/contrib/sys' is obsolete and no longer supported. " + "Use 'FileUtils' instead." PK!ȉ`t__(2.2.0/rake/contrib/compositepublisher.rbnu[module Rake # Manage several publishers as a single entity. class CompositePublisher def initialize @publishers = [] end # Add a publisher to the composite. def add(pub) @publishers << pub end # Upload all the individual publishers. def upload @publishers.each { |p| p.upload } end end end PK!""2.2.0/rake/contrib/sshpublisher.rbnu[require 'rake/dsl_definition' require 'rake/contrib/compositepublisher' module Rake # Publish an entire directory to an existing remote directory using # SSH. class SshDirPublisher include Rake::DSL # Creates an SSH publisher which will scp all files in +local_dir+ to # +remote_dir+ on +host+ def initialize(host, remote_dir, local_dir) @host = host @remote_dir = remote_dir @local_dir = local_dir end # Uploads the files def upload sh "scp", "-rq", "#{@local_dir}/*", "#{@host}:#{@remote_dir}" end end # Publish an entire directory to a fresh remote directory using SSH. class SshFreshDirPublisher < SshDirPublisher # Uploads the files after removing the existing remote directory. def upload sh "ssh", @host, "rm", "-rf", @remote_dir rescue nil sh "ssh", @host, "mkdir", @remote_dir super end end # Publish a list of files to an existing remote directory. class SshFilePublisher include Rake::DSL # Creates an SSH publisher which will scp all +files+ in +local_dir+ to # +remote_dir+ on +host+. def initialize(host, remote_dir, local_dir, *files) @host = host @remote_dir = remote_dir @local_dir = local_dir @files = files end # Uploads the files def upload @files.each do |fn| sh "scp", "-q", "#{@local_dir}/#{fn}", "#{@host}:#{@remote_dir}" end end end end PK! 2.2.0/rake/contrib/ftptools.rbnu[# = Tools for FTP uploading. # # This file is still under development and is not released for general # use. require 'date' require 'net/ftp' require 'rake/file_list' module Rake # :nodoc: class FtpFile # :nodoc: all attr_reader :name, :size, :owner, :group, :time def self.date @date_class ||= Date end def self.time @time_class ||= Time end def initialize(path, entry) @path = path @mode, _, @owner, @group, size, d1, d2, d3, @name = entry.split(' ') @size = size.to_i @time = determine_time(d1, d2, d3) end def path File.join(@path, @name) end def directory? @mode[0] == ?d end def mode parse_mode(@mode) end def symlink? @mode[0] == ?l end private # -------------------------------------------------------- def parse_mode(m) result = 0 (1..9).each do |i| result = 2 * result + ((m[i] == ?-) ? 0 : 1) end result end def determine_time(d1, d2, d3) now = self.class.time.now if /:/ !~ d3 result = Time.parse("#{d1} #{d2} #{d3}") else result = Time.parse("#{d1} #{d2} #{now.year} #{d3}") result = Time.parse("#{d1} #{d2} #{now.year - 1} #{d3}") if result > now end result end end ## # Manage the uploading of files to an FTP account. class FtpUploader # :nodoc: # Log uploads to standard output when true. attr_accessor :verbose class << FtpUploader # Create an uploader and pass it to the given block as +up+. # When the block is complete, close the uploader. def connect(path, host, account, password) up = self.new(path, host, account, password) begin yield(up) ensure up.close end end end # Create an FTP uploader targeting the directory +path+ on +host+ # using the given account and password. +path+ will be the root # path of the uploader. def initialize(path, host, account, password) @created = Hash.new @path = path @ftp = Net::FTP.new(host, account, password) makedirs(@path) @ftp.chdir(@path) end # Create the directory +path+ in the uploader root path. def makedirs(path) route = [] File.split(path).each do |dir| route << dir current_dir = File.join(route) if @created[current_dir].nil? @created[current_dir] = true $stderr.puts "Creating Directory #{current_dir}" if @verbose @ftp.mkdir(current_dir) rescue nil end end end # Upload all files matching +wildcard+ to the uploader's root # path. def upload_files(wildcard) FileList.glob(wildcard).each do |fn| upload(fn) end end # Close the uploader. def close @ftp.close end private # -------------------------------------------------------- # Upload a single file to the uploader's root path. def upload(file) $stderr.puts "Uploading #{file}" if @verbose dir = File.dirname(file) makedirs(dir) @ftp.putbinaryfile(file, file) unless File.directory?(file) end end end PK!fhmm$2.2.0/rake/thread_history_display.rbnu[require 'rake/private_reader' module Rake class ThreadHistoryDisplay # :nodoc: all include Rake::PrivateReader private_reader :stats, :items, :threads def initialize(stats) @stats = stats @items = { :_seq_ => 1 } @threads = { :_seq_ => "A" } end def show puts "Job History:" stats.each do |stat| stat[:data] ||= {} rename(stat, :thread, threads) rename(stat[:data], :item_id, items) rename(stat[:data], :new_thread, threads) rename(stat[:data], :deleted_thread, threads) printf("%8d %2s %-20s %s\n", (stat[:time] * 1_000_000).round, stat[:thread], stat[:event], stat[:data].map do |k, v| "#{k}:#{v}" end.join(" ")) end end private def rename(hash, key, renames) if hash && hash[key] original = hash[key] value = renames[original] unless value value = renames[:_seq_] renames[:_seq_] = renames[:_seq_].succ renames[original] = value end hash[key] = value end end end end PK!bّaa+2.2.0/rake/rule_recursion_overflow_error.rbnu[ module Rake # Error indicating a recursion overflow error in task selection. class RuleRecursionOverflowError < StandardError def initialize(*args) super @targets = [] end def add_target(target) @targets << target end def message super + ": [" + @targets.reverse.join(' => ') + "]" end end end PK!+rr2.2.0/rake/scope.rbnu[module Rake class Scope < LinkedList # :nodoc: all # Path for the scope. def path map { |item| item.to_s }.reverse.join(":") end # Path for the scope + the named path. def path_with_task_name(task_name) "#{path}:#{task_name}" end # Trim +n+ innermost scope levels from the scope. In no case will # this trim beyond the toplevel scope. def trim(n) result = self while n > 0 && ! result.empty? result = result.tail n -= 1 end result end # Scope lists always end with an EmptyScope object. See Null # Object Pattern) class EmptyScope < EmptyLinkedList @parent = Scope def path "" end def path_with_task_name(task_name) task_name end end # Singleton null object for an empty scope. EMPTY = EmptyScope.new end end PK!!Y#Y#2.2.0/rake/task_manager.rbnu[module Rake # The TaskManager module is a mixin for managing tasks. module TaskManager # Track the last comment made in the Rakefile. attr_accessor :last_description # TODO: Remove in Rake 11 alias :last_comment :last_description # :nodoc: Backwards compatibility def initialize # :nodoc: super @tasks = Hash.new @rules = Array.new @scope = Scope.make @last_description = nil end def create_rule(*args, &block) # :nodoc: pattern, args, deps = resolve_args(args) pattern = Regexp.new(Regexp.quote(pattern) + '$') if String === pattern @rules << [pattern, args, deps, block] end def define_task(task_class, *args, &block) # :nodoc: task_name, arg_names, deps = resolve_args(args) original_scope = @scope if String === task_name and not task_class.ancestors.include? Rake::FileTask then task_name, *definition_scope = *(task_name.split(":").reverse) @scope = Scope.make(*(definition_scope + @scope.to_a)) end task_name = task_class.scope_name(@scope, task_name) deps = [deps] unless deps.respond_to?(:to_ary) deps = deps.map { |d| Rake.from_pathname(d).to_s } task = intern(task_class, task_name) task.set_arg_names(arg_names) unless arg_names.empty? if Rake::TaskManager.record_task_metadata add_location(task) task.add_description(get_description(task)) end task.enhance(deps, &block) ensure @scope = original_scope end # Lookup a task. Return an existing task if found, otherwise # create a task of the current type. def intern(task_class, task_name) @tasks[task_name.to_s] ||= task_class.new(task_name, self) end # Find a matching task for +task_name+. def [](task_name, scopes=nil) task_name = task_name.to_s self.lookup(task_name, scopes) or enhance_with_matching_rule(task_name) or synthesize_file_task(task_name) or fail "Don't know how to build task '#{task_name}'" end def synthesize_file_task(task_name) # :nodoc: return nil unless File.exist?(task_name) define_task(Rake::FileTask, task_name) end # Resolve the arguments for a task/rule. Returns a triplet of # [task_name, arg_name_list, prerequisites]. def resolve_args(args) if args.last.is_a?(Hash) deps = args.pop resolve_args_with_dependencies(args, deps) else resolve_args_without_dependencies(args) end end # Resolve task arguments for a task or rule when there are no # dependencies declared. # # The patterns recognized by this argument resolving function are: # # task :t # task :t, [:a] # def resolve_args_without_dependencies(args) task_name = args.shift if args.size == 1 && args.first.respond_to?(:to_ary) arg_names = args.first.to_ary else arg_names = args end [task_name, arg_names, []] end private :resolve_args_without_dependencies # Resolve task arguments for a task or rule when there are # dependencies declared. # # The patterns recognized by this argument resolving function are: # # task :t => [:d] # task :t, [a] => [:d] # def resolve_args_with_dependencies(args, hash) # :nodoc: fail "Task Argument Error" if hash.size != 1 key, value = hash.map { |k, v| [k, v] }.first if args.empty? task_name = key arg_names = [] deps = value || [] else task_name = args.shift arg_names = key deps = value end deps = [deps] unless deps.respond_to?(:to_ary) [task_name, arg_names, deps] end private :resolve_args_with_dependencies # If a rule can be found that matches the task name, enhance the # task with the prerequisites and actions from the rule. Set the # source attribute of the task appropriately for the rule. Return # the enhanced task or nil of no rule was found. def enhance_with_matching_rule(task_name, level=0) fail Rake::RuleRecursionOverflowError, "Rule Recursion Too Deep" if level >= 16 @rules.each do |pattern, args, extensions, block| if pattern.match(task_name) task = attempt_rule(task_name, args, extensions, block, level) return task if task end end nil rescue Rake::RuleRecursionOverflowError => ex ex.add_target(task_name) fail ex end # List of all defined tasks in this application. def tasks @tasks.values.sort_by { |t| t.name } end # List of all the tasks defined in the given scope (and its # sub-scopes). def tasks_in_scope(scope) prefix = scope.path tasks.select { |t| /^#{prefix}:/ =~ t.name } end # Clear all tasks in this application. def clear @tasks.clear @rules.clear end # Lookup a task, using scope and the scope hints in the task name. # This method performs straight lookups without trying to # synthesize file tasks or rules. Special scope names (e.g. '^') # are recognized. If no scope argument is supplied, use the # current scope. Return nil if the task cannot be found. def lookup(task_name, initial_scope=nil) initial_scope ||= @scope task_name = task_name.to_s if task_name =~ /^rake:/ scopes = Scope.make task_name = task_name.sub(/^rake:/, '') elsif task_name =~ /^(\^+)/ scopes = initial_scope.trim($1.size) task_name = task_name.sub(/^(\^+)/, '') else scopes = initial_scope end lookup_in_scope(task_name, scopes) end # Lookup the task name def lookup_in_scope(name, scope) loop do tn = scope.path_with_task_name(name) task = @tasks[tn] return task if task break if scope.empty? scope = scope.tail end nil end private :lookup_in_scope # Return the list of scope names currently active in the task # manager. def current_scope @scope end # Evaluate the block in a nested namespace named +name+. Create # an anonymous namespace if +name+ is nil. def in_namespace(name) name ||= generate_name @scope = Scope.new(name, @scope) ns = NameSpace.new(self, @scope) yield(ns) ns ensure @scope = @scope.tail end private # Add a location to the locations field of the given task. def add_location(task) loc = find_location task.locations << loc if loc task end # Find the location that called into the dsl layer. def find_location locations = caller i = 0 while locations[i] return locations[i + 1] if locations[i] =~ /rake\/dsl_definition.rb/ i += 1 end nil end # Generate an anonymous namespace name. def generate_name @seed ||= 0 @seed += 1 "_anon_#{@seed}" end def trace_rule(level, message) # :nodoc: options.trace_output.puts "#{" " * level}#{message}" if Rake.application.options.trace_rules end # Attempt to create a rule given the list of prerequisites. def attempt_rule(task_name, args, extensions, block, level) sources = make_sources(task_name, extensions) prereqs = sources.map { |source| trace_rule level, "Attempting Rule #{task_name} => #{source}" if File.exist?(source) || Rake::Task.task_defined?(source) trace_rule level, "(#{task_name} => #{source} ... EXIST)" source elsif parent = enhance_with_matching_rule(source, level + 1) trace_rule level, "(#{task_name} => #{source} ... ENHANCE)" parent.name else trace_rule level, "(#{task_name} => #{source} ... FAIL)" return nil end } task = FileTask.define_task(task_name, {args => prereqs}, &block) task.sources = prereqs task end # Make a list of sources from the list of file name extensions / # translation procs. def make_sources(task_name, extensions) result = extensions.map { |ext| case ext when /%/ task_name.pathmap(ext) when %r{/} ext when /^\./ task_name.ext(ext) when String ext when Proc, Method if ext.arity == 1 ext.call(task_name) else ext.call end else fail "Don't know how to handle rule dependent: #{ext.inspect}" end } result.flatten end private # Return the current description, clearing it in the process. def get_description(task) desc = @last_description @last_description = nil desc end class << self attr_accessor :record_task_metadata # :nodoc: TaskManager.record_task_metadata = false end end end PK!932.2.0/rake/name_space.rbnu[## # The NameSpace class will lookup task names in the scope defined by a # +namespace+ command. class Rake::NameSpace ## # Create a namespace lookup object using the given task manager # and the list of scopes. def initialize(task_manager, scope_list) @task_manager = task_manager @scope = scope_list.dup end ## # Lookup a task named +name+ in the namespace. def [](name) @task_manager.lookup(name, @scope) end ## # The scope of the namespace (a LinkedList) def scope @scope.dup end ## # Return the list of tasks defined in this and nested namespaces. def tasks @task_manager.tasks_in_scope(@scope) end end PK!aww2.2.0/rake/pseudo_status.rbnu[module Rake ## # Exit status class for times the system just gives us a nil. class PseudoStatus # :nodoc: all attr_reader :exitstatus def initialize(code=0) @exitstatus = code end def to_i @exitstatus << 8 end def >>(n) to_i >> n end def stopped? false end def exited? true end end end PK!]2.2.0/rake/file_utils.rbnu[require 'rbconfig' require 'fileutils' #-- # This a FileUtils extension that defines several additional commands to be # added to the FileUtils utility functions. module FileUtils # Path to the currently running Ruby program RUBY = ENV['RUBY'] || File.join( RbConfig::CONFIG['bindir'], RbConfig::CONFIG['ruby_install_name'] + RbConfig::CONFIG['EXEEXT']). sub(/.*\s.*/m, '"\&"') OPT_TABLE['sh'] = %w(noop verbose) OPT_TABLE['ruby'] = %w(noop verbose) # Run the system command +cmd+. If multiple arguments are given the command # is run directly (without the shell, same semantics as Kernel::exec and # Kernel::system). # # It is recommended you use the multiple argument form over interpolating # user input for both usability and security reasons. With the multiple # argument form you can easily process files with spaces or other shell # reserved characters in them. With the multiple argument form your rake # tasks are not vulnerable to users providing an argument like # ; rm # -rf /. # # If a block is given, upon command completion the block is called with an # OK flag (true on a zero exit status) and a Process::Status object. # Without a block a RuntimeError is raised when the command exits non-zero. # # Examples: # # sh 'ls -ltr' # # sh 'ls', 'file with spaces' # # # check exit status after command runs # sh %{grep pattern file} do |ok, res| # if ! ok # puts "pattern not found (status = #{res.exitstatus})" # end # end # def sh(*cmd, &block) options = (Hash === cmd.last) ? cmd.pop : {} shell_runner = block_given? ? block : create_shell_runner(cmd) set_verbose_option(options) options[:noop] ||= Rake::FileUtilsExt.nowrite_flag Rake.rake_check_options options, :noop, :verbose Rake.rake_output_message cmd.join(" ") if options[:verbose] unless options[:noop] res = rake_system(*cmd) status = $? status = Rake::PseudoStatus.new(1) if !res && status.nil? shell_runner.call(res, status) end end def create_shell_runner(cmd) # :nodoc: show_command = cmd.join(" ") show_command = show_command[0, 42] + "..." unless $trace lambda do |ok, status| ok or fail "Command failed with status (#{status.exitstatus}): " + "[#{show_command}]" end end private :create_shell_runner def set_verbose_option(options) # :nodoc: unless options.key? :verbose options[:verbose] = (Rake::FileUtilsExt.verbose_flag == Rake::FileUtilsExt::DEFAULT) || Rake::FileUtilsExt.verbose_flag end end private :set_verbose_option def rake_system(*cmd) # :nodoc: Rake::AltSystem.system(*cmd) end private :rake_system # Run a Ruby interpreter with the given arguments. # # Example: # ruby %{-pe '$_.upcase!' 1 sh(*([RUBY] + args + [options]), &block) else sh("#{RUBY} #{args.first}", options, &block) end end LN_SUPPORTED = [true] # Attempt to do a normal file link, but fall back to a copy if the link # fails. def safe_ln(*args) if ! LN_SUPPORTED[0] cp(*args) else begin ln(*args) rescue StandardError, NotImplementedError LN_SUPPORTED[0] = false cp(*args) end end end # Split a file path into individual directory names. # # Example: # split_all("a/b/c") => ['a', 'b', 'c'] # def split_all(path) head, tail = File.split(path) return [tail] if head == '.' || tail == '/' return [head, tail] if head == '/' return split_all(head) + [tail] end end PK!Ο2.2.0/shell/version.rbnu[# # version.rb - shell version definition file # $Release Version: 0.7$ # $Revision: 38201 $ # by Keiju ISHITSUKA(keiju@ruby-lang.org) # # -- # # # class Shell # :nodoc: @RELEASE_VERSION = "0.7" @LAST_UPDATE_DATE = "07/03/20" end PK!ȟ::2.2.0/shell/system-command.rbnu[# # shell/system-command.rb - # $Release Version: 0.7 $ # $Revision: 46969 $ # by Keiju ISHITSUKA(keiju@ruby-lang.org) # # -- # # # require "shell/filter" class Shell class SystemCommand < Filter def initialize(sh, command, *opts) if t = opts.find{|opt| !opt.kind_of?(String) && opt.class} Shell.Fail Error::TypeError, t.class, "String" end super(sh) @command = command @opts = opts @input_queue = Queue.new @pid = nil sh.process_controller.add_schedule(self) end attr_reader :command alias name command def wait? @shell.process_controller.waiting_job?(self) end def active? @shell.process_controller.active_job?(self) end def input=(inp) super if active? start_export end end def start notify([@command, *@opts].join(" ")) @pid, @pipe_in, @pipe_out = @shell.process_controller.sfork(self) { Dir.chdir @shell.pwd $0 = @command exec(@command, *@opts) } if @input start_export end start_import end def flush @pipe_out.flush if @pipe_out and !@pipe_out.closed? end def terminate begin @pipe_in.close rescue IOError end begin @pipe_out.close rescue IOError end end def kill(sig) if @pid Process.kill(sig, @pid) end end def start_import notify "Job(%id) start imp-pipe.", @shell.debug? _eop = true Thread.start { begin while l = @pipe_in.gets @input_queue.push l end _eop = false rescue Errno::EPIPE _eop = false ensure if !ProcessController::USING_AT_EXIT_WHEN_PROCESS_EXIT and _eop notify("warn: Process finishing...", "wait for Job[%id] to finish pipe importing.", "You can use Shell#transact or Shell#check_point for more safe execution.") redo end notify "job(%id}) close imp-pipe.", @shell.debug? @input_queue.push :EOF @pipe_in.close end } end def start_export notify "job(%id) start exp-pipe.", @shell.debug? _eop = true Thread.start{ begin @input.each do |l| ProcessController::block_output_synchronize do @pipe_out.print l end end _eop = false rescue Errno::EPIPE, Errno::EIO _eop = false ensure if !ProcessController::USING_AT_EXIT_WHEN_PROCESS_EXIT and _eop notify("shell: warn: Process finishing...", "wait for Job(%id) to finish pipe exporting.", "You can use Shell#transact or Shell#check_point for more safe execution.") redo end notify "job(%id) close exp-pipe.", @shell.debug? @pipe_out.close end } end alias super_each each def each(rs = nil) while (l = @input_queue.pop) != :EOF yield l end end # ex) # if you wish to output: # "shell: job(#{@command}:#{@pid}) close pipe-out." # then # mes: "job(%id) close pipe-out." # yorn: Boolean(@shell.debug? or @shell.verbose?) def notify(*opts) @shell.notify(*opts) do |mes| yield mes if iterator? mes.gsub!("%id", "#{@command}:##{@pid}") mes.gsub!("%name", "#{@command}") mes.gsub!("%pid", "#{@pid}") mes end end end end PK! F!2.2.0/shell/process-controller.rbnu[# # shell/process-controller.rb - # $Release Version: 0.7 $ # $Revision: 47284 $ # by Keiju ISHITSUKA(keiju@ruby-lang.org) # # -- # # # require "forwardable" require "thread" require "sync" class Shell class ProcessController @ProcessControllers = {} @ProcessControllersMonitor = Mutex.new @ProcessControllersCV = ConditionVariable.new @BlockOutputMonitor = Mutex.new @BlockOutputCV = ConditionVariable.new class << self extend Forwardable def_delegator("@ProcessControllersMonitor", "synchronize", "process_controllers_exclusive") def active_process_controllers process_controllers_exclusive do @ProcessControllers.dup end end def activate(pc) process_controllers_exclusive do @ProcessControllers[pc] ||= 0 @ProcessControllers[pc] += 1 end end def inactivate(pc) process_controllers_exclusive do if @ProcessControllers[pc] if (@ProcessControllers[pc] -= 1) == 0 @ProcessControllers.delete(pc) @ProcessControllersCV.signal end end end end def each_active_object process_controllers_exclusive do for ref in @ProcessControllers.keys yield ref end end end def block_output_synchronize(&b) @BlockOutputMonitor.synchronize(&b) end def wait_to_finish_all_process_controllers process_controllers_exclusive do while !@ProcessControllers.empty? Shell::notify("Process finishing, but active shell exists", "You can use Shell#transact or Shell#check_point for more safe execution.") if Shell.debug? for pc in @ProcessControllers.keys Shell::notify(" Not finished jobs in "+pc.shell.to_s) for com in pc.jobs com.notify(" Jobs: %id") end end end @ProcessControllersCV.wait(@ProcessControllersMonitor) end end end end # for shell-command complete finish at this process exit. USING_AT_EXIT_WHEN_PROCESS_EXIT = true at_exit do wait_to_finish_all_process_controllers unless $@ end def initialize(shell) @shell = shell @waiting_jobs = [] @active_jobs = [] @jobs_sync = Sync.new @job_monitor = Mutex.new @job_condition = ConditionVariable.new end attr_reader :shell def jobs jobs = [] @jobs_sync.synchronize(:SH) do jobs.concat @waiting_jobs jobs.concat @active_jobs end jobs end def active_jobs @active_jobs end def waiting_jobs @waiting_jobs end def jobs_exist? @jobs_sync.synchronize(:SH) do @active_jobs.empty? or @waiting_jobs.empty? end end def active_jobs_exist? @jobs_sync.synchronize(:SH) do @active_jobs.empty? end end def waiting_jobs_exist? @jobs_sync.synchronize(:SH) do @waiting_jobs.empty? end end # schedule a command def add_schedule(command) @jobs_sync.synchronize(:EX) do ProcessController.activate(self) if @active_jobs.empty? start_job command else @waiting_jobs.push(command) end end end # start a job def start_job(command = nil) @jobs_sync.synchronize(:EX) do if command return if command.active? @waiting_jobs.delete command else command = @waiting_jobs.shift return unless command end @active_jobs.push command command.start # start all jobs that input from the job for job in @waiting_jobs.dup start_job(job) if job.input == command end end end def waiting_job?(job) @jobs_sync.synchronize(:SH) do @waiting_jobs.include?(job) end end def active_job?(job) @jobs_sync.synchronize(:SH) do @active_jobs.include?(job) end end # terminate a job def terminate_job(command) @jobs_sync.synchronize(:EX) do @active_jobs.delete command ProcessController.inactivate(self) if @active_jobs.empty? command.notify("start_job in terminate_job(%id)", Shell::debug?) start_job end end end # kill a job def kill_job(sig, command) @jobs_sync.synchronize(:EX) do if @waiting_jobs.delete command ProcessController.inactivate(self) return elsif @active_jobs.include?(command) begin r = command.kill(sig) ProcessController.inactivate(self) rescue print "Shell: Warn: $!\n" if @shell.verbose? return nil end @active_jobs.delete command r end end end # wait for all jobs to terminate def wait_all_jobs_execution @job_monitor.synchronize do begin while !jobs.empty? @job_condition.wait(@job_monitor) for job in jobs job.notify("waiting job(%id)", Shell::debug?) end end ensure redo unless jobs.empty? end end end # simple fork def sfork(command) pipe_me_in, pipe_peer_out = IO.pipe pipe_peer_in, pipe_me_out = IO.pipe pid = nil pid_mutex = Mutex.new pid_cv = ConditionVariable.new Thread.start do ProcessController.block_output_synchronize do STDOUT.flush ProcessController.each_active_object do |pc| for jobs in pc.active_jobs jobs.flush end end pid = fork { Thread.list.each do |th| th.kill unless Thread.current == th end STDIN.reopen(pipe_peer_in) STDOUT.reopen(pipe_peer_out) ObjectSpace.each_object(IO) do |io| if ![STDIN, STDOUT, STDERR].include?(io) io.close unless io.closed? end end yield } end pid_cv.signal pipe_peer_in.close pipe_peer_out.close command.notify "job(%name:##{pid}) start", @shell.debug? begin _pid = nil command.notify("job(%id) start to waiting finish.", @shell.debug?) _pid = Process.waitpid(pid, nil) rescue Errno::ECHILD command.notify "warn: job(%id) was done already waitpid." _pid = true ensure command.notify("Job(%id): Wait to finish when Process finished.", @shell.debug?) # when the process ends, wait until the command terminates if USING_AT_EXIT_WHEN_PROCESS_EXIT or _pid else command.notify("notice: Process finishing...", "wait for Job[%id] to finish.", "You can use Shell#transact or Shell#check_point for more safe execution.") redo end @job_monitor.synchronize do terminate_job(command) @job_condition.signal command.notify "job(%id) finish.", @shell.debug? end end end pid_mutex.synchronize do while !pid pid_cv.wait(pid_mutex) end end return pid, pipe_me_in, pipe_me_out end end end PK!k 2.2.0/shell/builtin-command.rbnu[# # shell/builtin-command.rb - # $Release Version: 0.7 $ # $Revision: 47246 $ # by Keiju ISHITSUKA(keiju@ruby-lang.org) # # -- # # # require "shell/filter" class Shell class BuiltInCommand # def expand_path(path) @shell.expand_path(path) end # call-seq: # foreach(path, record_separator) -> Enumerator # foreach(path, record_separator) { block } # # See IO.foreach when +path+ is a file. # # See Dir.foreach when +path+ is a directory. # def foreach(path = nil, *rs) path = "." unless path path = expand_path(path) if File.directory?(path) Dir.foreach(path){|fn| yield fn} else IO.foreach(path, *rs){|l| yield l} end end # call-seq: # open(path, mode, permissions) -> Enumerator # open(path, mode, permissions) { block } # # See IO.open when +path+ is a file. # # See Dir.open when +path+ is a directory. # def open(path, mode = nil, perm = 0666, &b) path = expand_path(path) if File.directory?(path) Dir.open(path, &b) else if @shell.umask f = File.open(path, mode, perm) File.chmod(perm & ~@shell.umask, path) if block_given? f.each(&b) end f else File.open(path, mode, perm, &b) end end end # call-seq: # unlink(path) # # See IO.unlink when +path+ is a file. # # See Dir.unlink when +path+ is a directory. # def unlink(path) @shell.check_point path = expand_path(path) if File.directory?(path) Dir.unlink(path) else IO.unlink(path) end Void.new(@shell) end # See Shell::CommandProcessor#test alias top_level_test test # call-seq: # test(command, file1, file2) -> true or false # [command, file1, file2] -> true or false # # Tests if the given +command+ exists in +file1+, or optionally +file2+. # # Example: # sh[?e, "foo"] # sh[:e, "foo"] # sh["e", "foo"] # sh[:exists?, "foo"] # sh["exists?", "foo"] # def test(command, file1, file2=nil) file1 = expand_path(file1) file2 = expand_path(file2) if file2 command = command.id2name if command.kind_of?(Symbol) case command when Integer if file2 top_level_test(command, file1, file2) else top_level_test(command, file1) end when String if command.size == 1 if file2 top_level_test(command, file1, file2) else top_level_test(command, file1) end else if file2 FileTest.send(command, file1, file2) else FileTest.send(command, file1) end end end end # See Shell::CommandProcessor#test alias [] test # call-seq: # mkdir(path) # # Same as Dir.mkdir, except multiple directories are allowed. def mkdir(*path) @shell.check_point notify("mkdir #{path.join(' ')}") perm = nil if path.last.kind_of?(Integer) perm = path.pop end for dir in path d = expand_path(dir) if perm Dir.mkdir(d, perm) else Dir.mkdir(d) end File.chmod(d, 0666 & ~@shell.umask) if @shell.umask end Void.new(@shell) end # call-seq: # rmdir(path) # # Same as Dir.rmdir, except multiple directories are allowed. def rmdir(*path) @shell.check_point notify("rmdir #{path.join(' ')}") for dir in path Dir.rmdir(expand_path(dir)) end Void.new(@shell) end # call-seq: # system(command, *options) -> SystemCommand # # Executes the given +command+ with the +options+ parameter. # # Example: # print sh.system("ls", "-l") # sh.system("ls", "-l") | sh.head > STDOUT # def system(command, *opts) if opts.empty? if command =~ /\*|\?|\{|\}|\[|\]|<|>|\(|\)|~|&|\||\\|\$|;|'|`|"|\n/ return SystemCommand.new(@shell, find_system_command("sh"), "-c", command) else command, *opts = command.split(/\s+/) end end SystemCommand.new(@shell, find_system_command(command), *opts) end # call-seq: # rehash # # Clears the command hash table. def rehash @system_commands = {} end def check_point # :nodoc: @shell.process_controller.wait_all_jobs_execution end alias finish_all_jobs check_point # :nodoc: # call-seq: # transact { block } # # Executes a block as self # # Example: # sh.transact { system("ls", "-l") | head > STDOUT } def transact(&block) begin @shell.instance_eval(&block) ensure check_point end end # call-seq: # out(device) { block } # # Calls device.print on the result passing the _block_ to # #transact def out(dev = STDOUT, &block) dev.print transact(&block) end # call-seq: # echo(*strings) -> Echo # # Returns a Echo object, for the given +strings+ def echo(*strings) Echo.new(@shell, *strings) end # call-seq: # cat(*filename) -> Cat # # Returns a Cat object, for the given +filenames+ def cat(*filenames) Cat.new(@shell, *filenames) end # def sort(*filenames) # Sort.new(self, *filenames) # end # call-seq: # glob(pattern) -> Glob # # Returns a Glob filter object, with the given +pattern+ object def glob(pattern) Glob.new(@shell, pattern) end def append(to, filter) case to when String AppendFile.new(@shell, to, filter) when IO AppendIO.new(@shell, to, filter) else Shell.Fail Error::CantApplyMethod, "append", to.class end end # call-seq: # tee(file) -> Tee # # Returns a Tee filter object, with the given +file+ command def tee(file) Tee.new(@shell, file) end # call-seq: # concat(*jobs) -> Concat # # Returns a Concat object, for the given +jobs+ def concat(*jobs) Concat.new(@shell, *jobs) end # %pwd, %cwd -> @pwd def notify(*opts) Shell.notify(*opts) {|mes| yield mes if iterator? mes.gsub!("%pwd", "#{@cwd}") mes.gsub!("%cwd", "#{@cwd}") } end # # private functions # def find_system_command(command) return command if /^\// =~ command case path = @system_commands[command] when String if exists?(path) return path else Shell.Fail Error::CommandNotFound, command end when false Shell.Fail Error::CommandNotFound, command end for p in @shell.system_path path = join(p, command) begin st = File.stat(path) rescue SystemCallError next else next unless st.executable? and !st.directory? @system_commands[command] = path return path end end @system_commands[command] = false Shell.Fail Error::CommandNotFound, command end # call-seq: # def_system_command(command, path) -> Shell::SystemCommand # # Defines a command, registering +path+ as a Shell method for the given # +command+. # # Shell::CommandProcessor.def_system_command "ls" # #=> Defines ls. # # Shell::CommandProcessor.def_system_command "sys_sort", "sort" # #=> Defines sys_sort as sort # def self.def_system_command(command, path = command) begin eval((d = %Q[def #{command}(*opts) SystemCommand.new(@shell, '#{path}', *opts) end]), nil, __FILE__, __LINE__ - 1) rescue SyntaxError Shell.notify "warn: Can't define #{command} path: #{path}." end Shell.notify "Define #{command} path: #{path}.", Shell.debug? Shell.notify("Definition of #{command}: ", d, Shell.debug.kind_of?(Integer) && Shell.debug > 1) end # call-seq: # undef_system_command(command) -> self # # Undefines a command def self.undef_system_command(command) command = command.id2name if command.kind_of?(Symbol) remove_method(command) Shell.module_eval{remove_method(command)} Filter.module_eval{remove_method(command)} self end @alias_map = {} # Returns a list of aliased commands def self.alias_map @alias_map end # call-seq: # alias_command(alias, command, *options) -> self # # Creates a command alias at the given +alias+ for the given +command+, # passing any +options+ along with it. # # Shell::CommandProcessor.alias_command "lsC", "ls", "-CBF", "--show-control-chars" # Shell::CommandProcessor.alias_command("lsC", "ls"){|*opts| ["-CBF", "--show-control-chars", *opts]} # def self.alias_command(ali, command, *opts) ali = ali.id2name if ali.kind_of?(Symbol) command = command.id2name if command.kind_of?(Symbol) begin if iterator? @alias_map[ali.intern] = proc eval((d = %Q[def #{ali}(*opts) @shell.__send__(:#{command}, *(CommandProcessor.alias_map[:#{ali}].call *opts)) end]), nil, __FILE__, __LINE__ - 1) else args = opts.collect{|opt| '"' + opt + '"'}.join(",") eval((d = %Q[def #{ali}(*opts) @shell.__send__(:#{command}, #{args}, *opts) end]), nil, __FILE__, __LINE__ - 1) end rescue SyntaxError Shell.notify "warn: Can't alias #{ali} command: #{command}." Shell.notify("Definition of #{ali}: ", d) raise end Shell.notify "Define #{ali} command: #{command}.", Shell.debug? Shell.notify("Definition of #{ali}: ", d, Shell.debug.kind_of?(Integer) && Shell.debug > 1) self end # call-seq: # unalias_command(alias) -> self # # Unaliases the given +alias+ command. def self.unalias_command(ali) ali = ali.id2name if ali.kind_of?(Symbol) @alias_map.delete ali.intern undef_system_command(ali) end # :nodoc: # # Delegates File and FileTest methods into Shell, including the following # commands: # # * Shell#blockdev?(file) # * Shell#chardev?(file) # * Shell#directory?(file) # * Shell#executable?(file) # * Shell#executable_real?(file) # * Shell#exist?(file)/Shell#exists?(file) # * Shell#file?(file) # * Shell#grpowned?(file) # * Shell#owned?(file) # * Shell#pipe?(file) # * Shell#readable?(file) # * Shell#readable_real?(file) # * Shell#setgid?(file) # * Shell#setuid?(file) # * Shell#size(file)/Shell#size?(file) # * Shell#socket?(file) # * Shell#sticky?(file) # * Shell#symlink?(file) # * Shell#writable?(file) # * Shell#writable_real?(file) # * Shell#zero?(file) # * Shell#syscopy(filename_from, filename_to) # * Shell#copy(filename_from, filename_to) # * Shell#move(filename_from, filename_to) # * Shell#compare(filename_from, filename_to) # * Shell#safe_unlink(*filenames) # * Shell#makedirs(*filenames) # * Shell#install(filename_from, filename_to, mode) # # And also, there are some aliases for convenience: # # * Shell#cmp <- Shell#compare # * Shell#mv <- Shell#move # * Shell#cp <- Shell#copy # * Shell#rm_f <- Shell#safe_unlink # * Shell#mkpath <- Shell#makedirs # def self.def_builtin_commands(delegation_class, command_specs) for meth, args in command_specs arg_str = args.collect{|arg| arg.downcase}.join(", ") call_arg_str = args.collect{ |arg| case arg when /^(FILENAME.*)$/ format("expand_path(%s)", $1.downcase) when /^(\*FILENAME.*)$/ # \*FILENAME* -> filenames.collect{|fn| expand_path(fn)}.join(", ") $1.downcase + '.collect{|fn| expand_path(fn)}' else arg end }.join(", ") d = %Q[def #{meth}(#{arg_str}) #{delegation_class}.#{meth}(#{call_arg_str}) end] Shell.notify "Define #{meth}(#{arg_str})", Shell.debug? Shell.notify("Definition of #{meth}: ", d, Shell.debug.kind_of?(Integer) && Shell.debug > 1) eval d end end # call-seq: # install_system_commands(prefix = "sys_") # # Defines all commands in the Shell.default_system_path as Shell method, # all with given +prefix+ appended to their names. # # Any invalid character names are converted to +_+, and errors are passed # to Shell.notify. # # Methods already defined are skipped. def self.install_system_commands(pre = "sys_") defined_meth = {} for m in Shell.methods defined_meth[m] = true end sh = Shell.new for path in Shell.default_system_path next unless sh.directory? path sh.cd path sh.foreach do |cn| if !defined_meth[pre + cn] && sh.file?(cn) && sh.executable?(cn) command = (pre + cn).gsub(/\W/, "_").sub(/^([0-9])/, '_\1') begin def_system_command(command, sh.expand_path(cn)) rescue Shell.notify "warn: Can't define #{command} path: #{cn}" end defined_meth[command] = command end end end end def self.add_delegate_command_to_shell(id) # :nodoc: id = id.intern if id.kind_of?(String) name = id.id2name if Shell.method_defined?(id) Shell.notify "warn: override definition of Shell##{name}." Shell.notify "warn: alias Shell##{name} to Shell##{name}_org.\n" Shell.module_eval "alias #{name}_org #{name}" end Shell.notify "method added: Shell##{name}.", Shell.debug? Shell.module_eval(%Q[def #{name}(*args, &block) begin @command_processor.__send__(:#{name}, *args, &block) rescue Exception $@.delete_if{|s| /:in `__getobj__'$/ =~ s} #` $@.delete_if{|s| /^\\(eval\\):/ =~ s} raise end end], __FILE__, __LINE__) if Shell::Filter.method_defined?(id) Shell.notify "warn: override definition of Shell::Filter##{name}." Shell.notify "warn: alias Shell##{name} to Shell::Filter##{name}_org." Filter.module_eval "alias #{name}_org #{name}" end Shell.notify "method added: Shell::Filter##{name}.", Shell.debug? Filter.module_eval(%Q[def #{name}(*args, &block) begin self | @shell.__send__(:#{name}, *args, &block) rescue Exception $@.delete_if{|s| /:in `__getobj__'$/ =~ s} #` $@.delete_if{|s| /^\\(eval\\):/ =~ s} raise end end], __FILE__, __LINE__) end # Delegates File methods into Shell, including the following commands: # # * Shell#atime(file) # * Shell#basename(file, *opt) # * Shell#chmod(mode, *files) # * Shell#chown(owner, group, *file) # * Shell#ctime(file) # * Shell#delete(*file) # * Shell#dirname(file) # * Shell#ftype(file) # * Shell#join(*file) # * Shell#link(file_from, file_to) # * Shell#lstat(file) # * Shell#mtime(file) # * Shell#readlink(file) # * Shell#rename(file_from, file_to) # * Shell#split(file) # * Shell#stat(file) # * Shell#symlink(file_from, file_to) # * Shell#truncate(file, length) # * Shell#utime(atime, mtime, *file) # def self.install_builtin_commands # method related File. # (exclude open/foreach/unlink) normal_delegation_file_methods = [ ["atime", ["FILENAME"]], ["basename", ["fn", "*opts"]], ["chmod", ["mode", "*FILENAMES"]], ["chown", ["owner", "group", "*FILENAME"]], ["ctime", ["FILENAMES"]], ["delete", ["*FILENAMES"]], ["dirname", ["FILENAME"]], ["ftype", ["FILENAME"]], ["join", ["*items"]], ["link", ["FILENAME_O", "FILENAME_N"]], ["lstat", ["FILENAME"]], ["mtime", ["FILENAME"]], ["readlink", ["FILENAME"]], ["rename", ["FILENAME_FROM", "FILENAME_TO"]], ["split", ["pathname"]], ["stat", ["FILENAME"]], ["symlink", ["FILENAME_O", "FILENAME_N"]], ["truncate", ["FILENAME", "length"]], ["utime", ["atime", "mtime", "*FILENAMES"]]] def_builtin_commands(File, normal_delegation_file_methods) alias_method :rm, :delete # method related FileTest def_builtin_commands(FileTest, FileTest.singleton_methods(false).collect{|m| [m, ["FILENAME"]]}) end end end PK!FΏ> > 2.2.0/shell/filter.rbnu[# # shell/filter.rb - # $Release Version: 0.7 $ # $Revision: 44221 $ # by Keiju ISHITSUKA(keiju@ruby-lang.org) # # -- # # # class Shell #:nodoc: # Any result of command execution is a Filter. # # This class includes Enumerable, therefore a Filter object can use all # Enumerable # facilities. # class Filter include Enumerable def initialize(sh) @shell = sh # parent shell @input = nil # input filter end attr_reader :input def input=(filter) @input = filter end # call-seq: # each(record_separator=nil) { block } # # Iterates a block for each line. def each(rs = nil) rs = @shell.record_separator unless rs if @input @input.each(rs){|l| yield l} end end # call-seq: # < source # # Inputs from +source+, which is either a string of a file name or an IO # object. def < (src) case src when String cat = Cat.new(@shell, src) cat | self when IO self.input = src self else Shell.Fail Error::CantApplyMethod, "<", to.class end end # call-seq: # > source # # Outputs from +source+, which is either a string of a file name or an IO # object. def > (to) case to when String dst = @shell.open(to, "w") begin each(){|l| dst << l} ensure dst.close end when IO each(){|l| to << l} else Shell.Fail Error::CantApplyMethod, ">", to.class end self end # call-seq: # >> source # # Appends the output to +source+, which is either a string of a file name # or an IO object. def >> (to) begin Shell.cd(@shell.pwd).append(to, self) rescue CantApplyMethod Shell.Fail Error::CantApplyMethod, ">>", to.class end end # call-seq: # | filter # # Processes a pipeline. def | (filter) filter.input = self if active? @shell.process_controller.start_job filter end filter end # call-seq: # filter1 + filter2 # # Outputs +filter1+, and then +filter2+ using Join.new def + (filter) Join.new(@shell, self, filter) end def to_a ary = [] each(){|l| ary.push l} ary end def to_s str = "" each(){|l| str.concat l} str end def inspect if @shell.debug.kind_of?(Integer) && @shell.debug > 2 super else to_s end end end end PK!=x//2.2.0/optparse.rbnu[# # optparse.rb - command-line option analysis with the OptionParser class. # # Author:: Nobu Nakada # Documentation:: Nobu Nakada and Gavin Sinclair. # # See OptionParser for documentation. # #-- # == Developer Documentation (not for RDoc output) # # === Class tree # # - OptionParser:: front end # - OptionParser::Switch:: each switches # - OptionParser::List:: options list # - OptionParser::ParseError:: errors on parsing # - OptionParser::AmbiguousOption # - OptionParser::NeedlessArgument # - OptionParser::MissingArgument # - OptionParser::InvalidOption # - OptionParser::InvalidArgument # - OptionParser::AmbiguousArgument # # === Object relationship diagram # # +--------------+ # | OptionParser |<>-----+ # +--------------+ | +--------+ # | ,-| Switch | # on_head -------->+---------------+ / +--------+ # accept/reject -->| List |<|>- # | |<|>- +----------+ # on ------------->+---------------+ `-| argument | # : : | class | # +---------------+ |==========| # on_tail -------->| | |pattern | # +---------------+ |----------| # OptionParser.accept ->| DefaultList | |converter | # reject |(shared between| +----------+ # | all instances)| # +---------------+ # #++ # # == OptionParser # # === Introduction # # OptionParser is a class for command-line option analysis. It is much more # advanced, yet also easier to use, than GetoptLong, and is a more Ruby-oriented # solution. # # === Features # # 1. The argument specification and the code to handle it are written in the # same place. # 2. It can output an option summary; you don't need to maintain this string # separately. # 3. Optional and mandatory arguments are specified very gracefully. # 4. Arguments can be automatically converted to a specified class. # 5. Arguments can be restricted to a certain set. # # All of these features are demonstrated in the examples below. See # #make_switch for full documentation. # # === Minimal example # # require 'optparse' # # options = {} # OptionParser.new do |opts| # opts.banner = "Usage: example.rb [options]" # # opts.on("-v", "--[no-]verbose", "Run verbosely") do |v| # options[:verbose] = v # end # end.parse! # # p options # p ARGV # # === Generating Help # # OptionParser can be used to automatically generate help for the commands you # write: # # require 'optparse' # # Options = Struct.new(:name) # # class Parser # def self.parse(options) # args = Options.new("world") # # opt_parser = OptionParser.new do |opts| # opts.banner = "Usage: example.rb [options]" # # opts.on("-nNAME", "--name=NAME", "Name to say hello to") do |n| # args.name = n # end # # opts.on("-h", "--help", "Prints this help") do # puts opts # exit # end # end # # opt_parser.parse!(options) # return args # end # end # options = Parser.parse %w[--help] # # #=> # # Usage: example.rb [options] # # -n, --name=NAME Name to say hello to # # -h, --help Prints this help# # # === Complete example # # The following example is a complete Ruby program. You can run it and see the # effect of specifying various options. This is probably the best way to learn # the features of +optparse+. # # require 'optparse' # require 'optparse/time' # require 'ostruct' # require 'pp' # # class OptparseExample # # CODES = %w[iso-2022-jp shift_jis euc-jp utf8 binary] # CODE_ALIASES = { "jis" => "iso-2022-jp", "sjis" => "shift_jis" } # # # # # Return a structure describing the options. # # # def self.parse(args) # # The options specified on the command line will be collected in *options*. # # We set default values here. # options = OpenStruct.new # options.library = [] # options.inplace = false # options.encoding = "utf8" # options.transfer_type = :auto # options.verbose = false # # opt_parser = OptionParser.new do |opts| # opts.banner = "Usage: example.rb [options]" # # opts.separator "" # opts.separator "Specific options:" # # # Mandatory argument. # opts.on("-r", "--require LIBRARY", # "Require the LIBRARY before executing your script") do |lib| # options.library << lib # end # # # Optional argument; multi-line description. # opts.on("-i", "--inplace [EXTENSION]", # "Edit ARGV files in place", # " (make backup if EXTENSION supplied)") do |ext| # options.inplace = true # options.extension = ext || '' # options.extension.sub!(/\A\.?(?=.)/, ".") # Ensure extension begins with dot. # end # # # Cast 'delay' argument to a Float. # opts.on("--delay N", Float, "Delay N seconds before executing") do |n| # options.delay = n # end # # # Cast 'time' argument to a Time object. # opts.on("-t", "--time [TIME]", Time, "Begin execution at given time") do |time| # options.time = time # end # # # Cast to octal integer. # opts.on("-F", "--irs [OCTAL]", OptionParser::OctalInteger, # "Specify record separator (default \\0)") do |rs| # options.record_separator = rs # end # # # List of arguments. # opts.on("--list x,y,z", Array, "Example 'list' of arguments") do |list| # options.list = list # end # # # Keyword completion. We are specifying a specific set of arguments (CODES # # and CODE_ALIASES - notice the latter is a Hash), and the user may provide # # the shortest unambiguous text. # code_list = (CODE_ALIASES.keys + CODES).join(',') # opts.on("--code CODE", CODES, CODE_ALIASES, "Select encoding", # " (#{code_list})") do |encoding| # options.encoding = encoding # end # # # Optional argument with keyword completion. # opts.on("--type [TYPE]", [:text, :binary, :auto], # "Select transfer type (text, binary, auto)") do |t| # options.transfer_type = t # end # # # Boolean switch. # opts.on("-v", "--[no-]verbose", "Run verbosely") do |v| # options.verbose = v # end # # opts.separator "" # opts.separator "Common options:" # # # No argument, shows at tail. This will print an options summary. # # Try it and see! # opts.on_tail("-h", "--help", "Show this message") do # puts opts # exit # end # # # Another typical switch to print the version. # opts.on_tail("--version", "Show version") do # puts ::Version.join('.') # exit # end # end # # opt_parser.parse!(args) # options # end # parse() # # end # class OptparseExample # # options = OptparseExample.parse(ARGV) # pp options # pp ARGV # # === Shell Completion # # For modern shells (e.g. bash, zsh, etc.), you can use shell # completion for command line options. # # === Further documentation # # The above examples should be enough to learn how to use this class. If you # have any questions, file a ticket at http://bugs.ruby-lang.org. # class OptionParser # :stopdoc: NoArgument = [NO_ARGUMENT = :NONE, nil].freeze RequiredArgument = [REQUIRED_ARGUMENT = :REQUIRED, true].freeze OptionalArgument = [OPTIONAL_ARGUMENT = :OPTIONAL, false].freeze # :startdoc: # # Keyword completion module. This allows partial arguments to be specified # and resolved against a list of acceptable values. # module Completion def self.regexp(key, icase) Regexp.new('\A' + Regexp.quote(key).gsub(/\w+\b/, '\&\w*'), icase) end def self.candidate(key, icase = false, pat = nil, &block) pat ||= Completion.regexp(key, icase) candidates = [] block.call do |k, *v| (if Regexp === k kn = "".freeze k === key else kn = defined?(k.id2name) ? k.id2name : k pat === kn end) or next v << k if v.empty? candidates << [k, v, kn] end candidates end def candidate(key, icase = false, pat = nil) Completion.candidate(key, icase, pat, &method(:each)) end public def complete(key, icase = false, pat = nil) candidates = candidate(key, icase, pat, &method(:each)).sort_by {|k, v, kn| kn.size} if candidates.size == 1 canon, sw, * = candidates[0] elsif candidates.size > 1 canon, sw, cn = candidates.shift candidates.each do |k, v, kn| next if sw == v if String === cn and String === kn if cn.rindex(kn, 0) canon, sw, cn = k, v, kn next elsif kn.rindex(cn, 0) next end end throw :ambiguous, key end end if canon block_given? or return key, *sw yield(key, *sw) end end def convert(opt = nil, val = nil, *) val end end # # Map from option/keyword string to object with completion. # class OptionMap < Hash include Completion end # # Individual switch class. Not important to the user. # # Defined within Switch are several Switch-derived classes: NoArgument, # RequiredArgument, etc. # class Switch attr_reader :pattern, :conv, :short, :long, :arg, :desc, :block # # Guesses argument style from +arg+. Returns corresponding # OptionParser::Switch class (OptionalArgument, etc.). # def self.guess(arg) case arg when "" t = self when /\A=?\[/ t = Switch::OptionalArgument when /\A\s+\[/ t = Switch::PlacedArgument else t = Switch::RequiredArgument end self >= t or incompatible_argument_styles(arg, t) t end def self.incompatible_argument_styles(arg, t) raise(ArgumentError, "#{arg}: incompatible argument styles\n #{self}, #{t}", ParseError.filter_backtrace(caller(2))) end def self.pattern NilClass end def initialize(pattern = nil, conv = nil, short = nil, long = nil, arg = nil, desc = ([] if short or long), block = Proc.new) raise if Array === pattern @pattern, @conv, @short, @long, @arg, @desc, @block = pattern, conv, short, long, arg, desc, block end # # Parses +arg+ and returns rest of +arg+ and matched portion to the # argument pattern. Yields when the pattern doesn't match substring. # def parse_arg(arg) pattern or return nil, [arg] unless m = pattern.match(arg) yield(InvalidArgument, arg) return arg, [] end if String === m m = [s = m] else m = m.to_a s = m[0] return nil, m unless String === s end raise InvalidArgument, arg unless arg.rindex(s, 0) return nil, m if s.length == arg.length yield(InvalidArgument, arg) # didn't match whole arg return arg[s.length..-1], m end private :parse_arg # # Parses argument, converts and returns +arg+, +block+ and result of # conversion. Yields at semi-error condition instead of raising an # exception. # def conv_arg(arg, val = []) if conv val = conv.call(*val) else val = proc {|v| v}.call(*val) end return arg, block, val end private :conv_arg # # Produces the summary text. Each line of the summary is yielded to the # block (without newline). # # +sdone+:: Already summarized short style options keyed hash. # +ldone+:: Already summarized long style options keyed hash. # +width+:: Width of left side (option part). In other words, the right # side (description part) starts after +width+ columns. # +max+:: Maximum width of left side -> the options are filled within # +max+ columns. # +indent+:: Prefix string indents all summarized lines. # def summarize(sdone = [], ldone = [], width = 1, max = width - 1, indent = "") sopts, lopts = [], [], nil @short.each {|s| sdone.fetch(s) {sopts << s}; sdone[s] = true} if @short @long.each {|s| ldone.fetch(s) {lopts << s}; ldone[s] = true} if @long return if sopts.empty? and lopts.empty? # completely hidden left = [sopts.join(', ')] right = desc.dup while s = lopts.shift l = left[-1].length + s.length l += arg.length if left.size == 1 && arg l < max or sopts.empty? or left << '' left[-1] << if left[-1].empty? then ' ' * 4 else ', ' end << s end if arg left[0] << (left[1] ? arg.sub(/\A(\[?)=/, '\1') + ',' : arg) end mlen = left.collect {|ss| ss.length}.max.to_i while mlen > width and l = left.shift mlen = left.collect {|ss| ss.length}.max.to_i if l.length == mlen if l.length < width and (r = right[0]) and !r.empty? l = l.to_s.ljust(width) + ' ' + r right.shift end yield(indent + l) end while begin l = left.shift; r = right.shift; l or r end l = l.to_s.ljust(width) + ' ' + r if r and !r.empty? yield(indent + l) end self end def add_banner(to) # :nodoc: unless @short or @long s = desc.join to << " [" + s + "]..." unless s.empty? end to end def match_nonswitch?(str) # :nodoc: @pattern =~ str unless @short or @long end # # Main name of the switch. # def switch_name (long.first || short.first).sub(/\A-+(?:\[no-\])?/, '') end def compsys(sdone, ldone) # :nodoc: sopts, lopts = [], [] @short.each {|s| sdone.fetch(s) {sopts << s}; sdone[s] = true} if @short @long.each {|s| ldone.fetch(s) {lopts << s}; ldone[s] = true} if @long return if sopts.empty? and lopts.empty? # completely hidden (sopts+lopts).each do |opt| # "(-x -c -r)-l[left justify]" \ if /^--\[no-\](.+)$/ =~ opt o = $1 yield("--#{o}", desc.join("")) yield("--no-#{o}", desc.join("")) else yield("#{opt}", desc.join("")) end end end # # Switch that takes no arguments. # class NoArgument < self # # Raises an exception if any arguments given. # def parse(arg, argv) yield(NeedlessArgument, arg) if arg conv_arg(arg) end def self.incompatible_argument_styles(*) end def self.pattern Object end end # # Switch that takes an argument. # class RequiredArgument < self # # Raises an exception if argument is not present. # def parse(arg, argv) unless arg raise MissingArgument if argv.empty? arg = argv.shift end conv_arg(*parse_arg(arg, &method(:raise))) end end # # Switch that can omit argument. # class OptionalArgument < self # # Parses argument if given, or uses default value. # def parse(arg, argv, &error) if arg conv_arg(*parse_arg(arg, &error)) else conv_arg(arg) end end end # # Switch that takes an argument, which does not begin with '-'. # class PlacedArgument < self # # Returns nil if argument is not present or begins with '-'. # def parse(arg, argv, &error) if !(val = arg) and (argv.empty? or /\A-/ =~ (val = argv[0])) return nil, block, nil end opt = (val = parse_arg(val, &error))[1] val = conv_arg(*val) if opt and !arg argv.shift else val[0] = nil end val end end end # # Simple option list providing mapping from short and/or long option # string to OptionParser::Switch and mapping from acceptable argument to # matching pattern and converter pair. Also provides summary feature. # class List # Map from acceptable argument types to pattern and converter pairs. attr_reader :atype # Map from short style option switches to actual switch objects. attr_reader :short # Map from long style option switches to actual switch objects. attr_reader :long # List of all switches and summary string. attr_reader :list # # Just initializes all instance variables. # def initialize @atype = {} @short = OptionMap.new @long = OptionMap.new @list = [] end # # See OptionParser.accept. # def accept(t, pat = /.*/m, &block) if pat pat.respond_to?(:match) or raise TypeError, "has no `match'", ParseError.filter_backtrace(caller(2)) else pat = t if t.respond_to?(:match) end unless block block = pat.method(:convert).to_proc if pat.respond_to?(:convert) end @atype[t] = [pat, block] end # # See OptionParser.reject. # def reject(t) @atype.delete(t) end # # Adds +sw+ according to +sopts+, +lopts+ and +nlopts+. # # +sw+:: OptionParser::Switch instance to be added. # +sopts+:: Short style option list. # +lopts+:: Long style option list. # +nlopts+:: Negated long style options list. # def update(sw, sopts, lopts, nsw = nil, nlopts = nil) sopts.each {|o| @short[o] = sw} if sopts lopts.each {|o| @long[o] = sw} if lopts nlopts.each {|o| @long[o] = nsw} if nsw and nlopts used = @short.invert.update(@long.invert) @list.delete_if {|o| Switch === o and !used[o]} end private :update # # Inserts +switch+ at the head of the list, and associates short, long # and negated long options. Arguments are: # # +switch+:: OptionParser::Switch instance to be inserted. # +short_opts+:: List of short style options. # +long_opts+:: List of long style options. # +nolong_opts+:: List of long style options with "no-" prefix. # # prepend(switch, short_opts, long_opts, nolong_opts) # def prepend(*args) update(*args) @list.unshift(args[0]) end # # Appends +switch+ at the tail of the list, and associates short, long # and negated long options. Arguments are: # # +switch+:: OptionParser::Switch instance to be inserted. # +short_opts+:: List of short style options. # +long_opts+:: List of long style options. # +nolong_opts+:: List of long style options with "no-" prefix. # # append(switch, short_opts, long_opts, nolong_opts) # def append(*args) update(*args) @list.push(args[0]) end # # Searches +key+ in +id+ list. The result is returned or yielded if a # block is given. If it isn't found, nil is returned. # def search(id, key) if list = __send__(id) val = list.fetch(key) {return nil} block_given? ? yield(val) : val end end # # Searches list +id+ for +opt+ and the optional patterns for completion # +pat+. If +icase+ is true, the search is case insensitive. The result # is returned or yielded if a block is given. If it isn't found, nil is # returned. # def complete(id, opt, icase = false, *pat, &block) __send__(id).complete(opt, icase, *pat, &block) end # # Iterates over each option, passing the option to the +block+. # def each_option(&block) list.each(&block) end # # Creates the summary table, passing each line to the +block+ (without # newline). The arguments +args+ are passed along to the summarize # method which is called on every option. # def summarize(*args, &block) sum = [] list.reverse_each do |opt| if opt.respond_to?(:summarize) # perhaps OptionParser::Switch s = [] opt.summarize(*args) {|l| s << l} sum.concat(s.reverse) elsif !opt or opt.empty? sum << "" elsif opt.respond_to?(:each_line) sum.concat([*opt.each_line].reverse) else sum.concat([*opt.each].reverse) end end sum.reverse_each(&block) end def add_banner(to) # :nodoc: list.each do |opt| if opt.respond_to?(:add_banner) opt.add_banner(to) end end to end def compsys(*args, &block) # :nodoc: list.each do |opt| if opt.respond_to?(:compsys) opt.compsys(*args, &block) end end end end # # Hash with completion search feature. See OptionParser::Completion. # class CompletingHash < Hash include Completion # # Completion for hash key. # def match(key) *values = fetch(key) { raise AmbiguousArgument, catch(:ambiguous) {return complete(key)} } return key, *values end end # :stopdoc: # # Enumeration of acceptable argument styles. Possible values are: # # NO_ARGUMENT:: The switch takes no arguments. (:NONE) # REQUIRED_ARGUMENT:: The switch requires an argument. (:REQUIRED) # OPTIONAL_ARGUMENT:: The switch requires an optional argument. (:OPTIONAL) # # Use like --switch=argument (long style) or -Xargument (short style). For # short style, only portion matched to argument pattern is treated as # argument. # ArgumentStyle = {} NoArgument.each {|el| ArgumentStyle[el] = Switch::NoArgument} RequiredArgument.each {|el| ArgumentStyle[el] = Switch::RequiredArgument} OptionalArgument.each {|el| ArgumentStyle[el] = Switch::OptionalArgument} ArgumentStyle.freeze # # Switches common used such as '--', and also provides default # argument classes # DefaultList = List.new DefaultList.short['-'] = Switch::NoArgument.new {} DefaultList.long[''] = Switch::NoArgument.new {throw :terminate} COMPSYS_HEADER = <<'XXX' # :nodoc: typeset -A opt_args local context state line _arguments -s -S \ XXX def compsys(to, name = File.basename($0)) # :nodoc: to << "#compdef #{name}\n" to << COMPSYS_HEADER visit(:compsys, {}, {}) {|o, d| to << %Q[ "#{o}[#{d.gsub(/[\"\[\]]/, '\\\\\&')}]" \\\n] } to << " '*:file:_files' && return 0\n" end # # Default options for ARGV, which never appear in option summary. # Officious = {} # # --help # Shows option summary. # Officious['help'] = proc do |parser| Switch::NoArgument.new do |arg| puts parser.help exit end end # # --*-completion-bash=WORD # Shows candidates for command line completion. # Officious['*-completion-bash'] = proc do |parser| Switch::RequiredArgument.new do |arg| puts parser.candidate(arg) exit end end # # --*-completion-zsh[=NAME:FILE] # Creates zsh completion file. # Officious['*-completion-zsh'] = proc do |parser| Switch::OptionalArgument.new do |arg| parser.compsys(STDOUT, arg) exit end end # # --version # Shows version string if Version is defined. # Officious['version'] = proc do |parser| Switch::OptionalArgument.new do |pkg| if pkg begin require 'optparse/version' rescue LoadError else show_version(*pkg.split(/,/)) or abort("#{parser.program_name}: no version found in package #{pkg}") exit end end v = parser.ver or abort("#{parser.program_name}: version unknown") puts v exit end end # :startdoc: # # Class methods # # # Initializes a new instance and evaluates the optional block in context # of the instance. Arguments +args+ are passed to #new, see there for # description of parameters. # # This method is *deprecated*, its behavior corresponds to the older #new # method. # def self.with(*args, &block) opts = new(*args) opts.instance_eval(&block) opts end # # Returns an incremented value of +default+ according to +arg+. # def self.inc(arg, default = nil) case arg when Integer arg.nonzero? when nil default.to_i + 1 end end def inc(*args) self.class.inc(*args) end # # Initializes the instance and yields itself if called with a block. # # +banner+:: Banner message. # +width+:: Summary width. # +indent+:: Summary indent. # def initialize(banner = nil, width = 32, indent = ' ' * 4) @stack = [DefaultList, List.new, List.new] @program_name = nil @banner = banner @summary_width = width @summary_indent = indent @default_argv = ARGV add_officious yield self if block_given? end def add_officious # :nodoc: list = base() Officious.each do |opt, block| list.long[opt] ||= block.call(self) end end # # Terminates option parsing. Optional parameter +arg+ is a string pushed # back to be the first non-option argument. # def terminate(arg = nil) self.class.terminate(arg) end def self.terminate(arg = nil) throw :terminate, arg end @stack = [DefaultList] def self.top() DefaultList end # # Directs to accept specified class +t+. The argument string is passed to # the block in which it should be converted to the desired class. # # +t+:: Argument class specifier, any object including Class. # +pat+:: Pattern for argument, defaults to +t+ if it responds to match. # # accept(t, pat, &block) # def accept(*args, &blk) top.accept(*args, &blk) end # # See #accept. # def self.accept(*args, &blk) top.accept(*args, &blk) end # # Directs to reject specified class argument. # # +t+:: Argument class specifier, any object including Class. # # reject(t) # def reject(*args, &blk) top.reject(*args, &blk) end # # See #reject. # def self.reject(*args, &blk) top.reject(*args, &blk) end # # Instance methods # # Heading banner preceding summary. attr_writer :banner # Program name to be emitted in error message and default banner, # defaults to $0. attr_writer :program_name # Width for option list portion of summary. Must be Numeric. attr_accessor :summary_width # Indentation for summary. Must be String (or have + String method). attr_accessor :summary_indent # Strings to be parsed in default. attr_accessor :default_argv # # Heading banner preceding summary. # def banner unless @banner @banner = "Usage: #{program_name} [options]" visit(:add_banner, @banner) end @banner end # # Program name to be emitted in error message and default banner, defaults # to $0. # def program_name @program_name || File.basename($0, '.*') end # for experimental cascading :-) alias set_banner banner= alias set_program_name program_name= alias set_summary_width summary_width= alias set_summary_indent summary_indent= # Version attr_writer :version # Release code attr_writer :release # # Version # def version @version || (defined?(::Version) && ::Version) end # # Release code # def release @release || (defined?(::Release) && ::Release) || (defined?(::RELEASE) && ::RELEASE) end # # Returns version string from program_name, version and release. # def ver if v = version str = "#{program_name} #{[v].join('.')}" str << " (#{v})" if v = release str end end def warn(mesg = $!) super("#{program_name}: #{mesg}") end def abort(mesg = $!) super("#{program_name}: #{mesg}") end # # Subject of #on / #on_head, #accept / #reject # def top @stack[-1] end # # Subject of #on_tail. # def base @stack[1] end # # Pushes a new List. # def new @stack.push(List.new) if block_given? yield self else self end end # # Removes the last List. # def remove @stack.pop end # # Puts option summary into +to+ and returns +to+. Yields each line if # a block is given. # # +to+:: Output destination, which must have method <<. Defaults to []. # +width+:: Width of left side, defaults to @summary_width. # +max+:: Maximum length allowed for left side, defaults to +width+ - 1. # +indent+:: Indentation, defaults to @summary_indent. # def summarize(to = [], width = @summary_width, max = width - 1, indent = @summary_indent, &blk) blk ||= proc {|l| to << (l.index($/, -1) ? l : l + $/)} visit(:summarize, {}, {}, width, max, indent, &blk) to end # # Returns option summary string. # def help; summarize("#{banner}".sub(/\n?\z/, "\n")) end alias to_s help # # Returns option summary list. # def to_a; summarize("#{banner}".split(/^/)) end # # Checks if an argument is given twice, in which case an ArgumentError is # raised. Called from OptionParser#switch only. # # +obj+:: New argument. # +prv+:: Previously specified argument. # +msg+:: Exception message. # def notwice(obj, prv, msg) unless !prv or prv == obj raise(ArgumentError, "argument #{msg} given twice: #{obj}", ParseError.filter_backtrace(caller(2))) end obj end private :notwice SPLAT_PROC = proc {|*a| a.length <= 1 ? a.first : a} # :nodoc: # # Creates an OptionParser::Switch from the parameters. The parsed argument # value is passed to the given block, where it can be processed. # # See at the beginning of OptionParser for some full examples. # # +opts+ can include the following elements: # # [Argument style:] # One of the following: # :NONE, :REQUIRED, :OPTIONAL # # [Argument pattern:] # Acceptable option argument format, must be pre-defined with # OptionParser.accept or OptionParser#accept, or Regexp. This can appear # once or assigned as String if not present, otherwise causes an # ArgumentError. Examples: # Float, Time, Array # # [Possible argument values:] # Hash or Array. # [:text, :binary, :auto] # %w[iso-2022-jp shift_jis euc-jp utf8 binary] # { "jis" => "iso-2022-jp", "sjis" => "shift_jis" } # # [Long style switch:] # Specifies a long style switch which takes a mandatory, optional or no # argument. It's a string of the following form: # "--switch=MANDATORY" or "--switch MANDATORY" # "--switch[=OPTIONAL]" # "--switch" # # [Short style switch:] # Specifies short style switch which takes a mandatory, optional or no # argument. It's a string of the following form: # "-xMANDATORY" # "-x[OPTIONAL]" # "-x" # There is also a special form which matches character range (not full # set of regular expression): # "-[a-z]MANDATORY" # "-[a-z][OPTIONAL]" # "-[a-z]" # # [Argument style and description:] # Instead of specifying mandatory or optional arguments directly in the # switch parameter, this separate parameter can be used. # "=MANDATORY" # "=[OPTIONAL]" # # [Description:] # Description string for the option. # "Run verbosely" # # [Handler:] # Handler for the parsed argument value. Either give a block or pass a # Proc or Method as an argument. # def make_switch(opts, block = nil) short, long, nolong, style, pattern, conv, not_pattern, not_conv, not_style = [], [], [] ldesc, sdesc, desc, arg = [], [], [] default_style = Switch::NoArgument default_pattern = nil klass = nil q, a = nil has_arg = false opts.each do |o| # argument class next if search(:atype, o) do |pat, c| klass = notwice(o, klass, 'type') if not_style and not_style != Switch::NoArgument not_pattern, not_conv = pat, c else default_pattern, conv = pat, c end end # directly specified pattern(any object possible to match) if (!(String === o || Symbol === o)) and o.respond_to?(:match) pattern = notwice(o, pattern, 'pattern') if pattern.respond_to?(:convert) conv = pattern.method(:convert).to_proc else conv = SPLAT_PROC end next end # anything others case o when Proc, Method block = notwice(o, block, 'block') when Array, Hash case pattern when CompletingHash when nil pattern = CompletingHash.new conv = pattern.method(:convert).to_proc if pattern.respond_to?(:convert) else raise ArgumentError, "argument pattern given twice" end o.each {|pat, *v| pattern[pat] = v.fetch(0) {pat}} when Module raise ArgumentError, "unsupported argument type: #{o}", ParseError.filter_backtrace(caller(4)) when *ArgumentStyle.keys style = notwice(ArgumentStyle[o], style, 'style') when /^--no-([^\[\]=\s]*)(.+)?/ q, a = $1, $2 o = notwice(a ? Object : TrueClass, klass, 'type') not_pattern, not_conv = search(:atype, o) unless not_style not_style = (not_style || default_style).guess(arg = a) if a default_style = Switch::NoArgument default_pattern, conv = search(:atype, FalseClass) unless default_pattern ldesc << "--no-#{q}" long << 'no-' + (q = q.downcase) nolong << q when /^--\[no-\]([^\[\]=\s]*)(.+)?/ q, a = $1, $2 o = notwice(a ? Object : TrueClass, klass, 'type') if a default_style = default_style.guess(arg = a) default_pattern, conv = search(:atype, o) unless default_pattern end ldesc << "--[no-]#{q}" long << (o = q.downcase) not_pattern, not_conv = search(:atype, FalseClass) unless not_style not_style = Switch::NoArgument nolong << 'no-' + o when /^--([^\[\]=\s]*)(.+)?/ q, a = $1, $2 if a o = notwice(NilClass, klass, 'type') default_style = default_style.guess(arg = a) default_pattern, conv = search(:atype, o) unless default_pattern end ldesc << "--#{q}" long << (o = q.downcase) when /^-(\[\^?\]?(?:[^\\\]]|\\.)*\])(.+)?/ q, a = $1, $2 o = notwice(Object, klass, 'type') if a default_style = default_style.guess(arg = a) default_pattern, conv = search(:atype, o) unless default_pattern else has_arg = true end sdesc << "-#{q}" short << Regexp.new(q) when /^-(.)(.+)?/ q, a = $1, $2 if a o = notwice(NilClass, klass, 'type') default_style = default_style.guess(arg = a) default_pattern, conv = search(:atype, o) unless default_pattern end sdesc << "-#{q}" short << q when /^=/ style = notwice(default_style.guess(arg = o), style, 'style') default_pattern, conv = search(:atype, Object) unless default_pattern else desc.push(o) end end default_pattern, conv = search(:atype, default_style.pattern) unless default_pattern if !(short.empty? and long.empty?) if has_arg and default_style == Switch::NoArgument default_style = Switch::RequiredArgument end s = (style || default_style).new(pattern || default_pattern, conv, sdesc, ldesc, arg, desc, block) elsif !block if style or pattern raise ArgumentError, "no switch given", ParseError.filter_backtrace(caller) end s = desc else short << pattern s = (style || default_style).new(pattern, conv, nil, nil, arg, desc, block) end return s, short, long, (not_style.new(not_pattern, not_conv, sdesc, ldesc, nil, desc, block) if not_style), nolong end def define(*opts, &block) top.append(*(sw = make_switch(opts, block))) sw[0] end # # Add option switch and handler. See #make_switch for an explanation of # parameters. # def on(*opts, &block) define(*opts, &block) self end alias def_option define def define_head(*opts, &block) top.prepend(*(sw = make_switch(opts, block))) sw[0] end # # Add option switch like with #on, but at head of summary. # def on_head(*opts, &block) define_head(*opts, &block) self end alias def_head_option define_head def define_tail(*opts, &block) base.append(*(sw = make_switch(opts, block))) sw[0] end # # Add option switch like with #on, but at tail of summary. # def on_tail(*opts, &block) define_tail(*opts, &block) self end alias def_tail_option define_tail # # Add separator in summary. # def separator(string) top.append(string, nil, nil) end # # Parses command line arguments +argv+ in order. When a block is given, # each non-option argument is yielded. # # Returns the rest of +argv+ left unparsed. # def order(*argv, &block) argv = argv[0].dup if argv.size == 1 and Array === argv[0] order!(argv, &block) end # # Same as #order, but removes switches destructively. # Non-option arguments remain in +argv+. # def order!(argv = default_argv, &nonopt) parse_in_order(argv, &nonopt) end def parse_in_order(argv = default_argv, setter = nil, &nonopt) # :nodoc: opt, arg, val, rest = nil nonopt ||= proc {|a| throw :terminate, a} argv.unshift(arg) if arg = catch(:terminate) { while arg = argv.shift case arg # long option when /\A--([^=]*)(?:=(.*))?/m opt, rest = $1, $2 begin sw, = complete(:long, opt, true) rescue ParseError raise $!.set_option(arg, true) end begin opt, cb, val = sw.parse(rest, argv) {|*exc| raise(*exc)} val = cb.call(val) if cb setter.call(sw.switch_name, val) if setter rescue ParseError raise $!.set_option(arg, rest) end # short option when /\A-(.)((=).*|.+)?/m opt, has_arg, eq, val, rest = $1, $3, $3, $2, $2 begin sw, = search(:short, opt) unless sw begin sw, = complete(:short, opt) # short option matched. val = arg.sub(/\A-/, '') has_arg = true rescue InvalidOption # if no short options match, try completion with long # options. sw, = complete(:long, opt) eq ||= !rest end end rescue ParseError raise $!.set_option(arg, true) end begin opt, cb, val = sw.parse(val, argv) {|*exc| raise(*exc) if eq} raise InvalidOption, arg if has_arg and !eq and arg == "-#{opt}" argv.unshift(opt) if opt and (!rest or (opt = opt.sub(/\A-*/, '-')) != '-') val = cb.call(val) if cb setter.call(sw.switch_name, val) if setter rescue ParseError raise $!.set_option(arg, arg.length > 2) end # non-option argument else catch(:prune) do visit(:each_option) do |sw0| sw = sw0 sw.block.call(arg) if Switch === sw and sw.match_nonswitch?(arg) end nonopt.call(arg) end end end nil } visit(:search, :short, nil) {|sw| sw.block.call(*argv) if !sw.pattern} argv end private :parse_in_order # # Parses command line arguments +argv+ in permutation mode and returns # list of non-option arguments. # def permute(*argv) argv = argv[0].dup if argv.size == 1 and Array === argv[0] permute!(argv) end # # Same as #permute, but removes switches destructively. # Non-option arguments remain in +argv+. # def permute!(argv = default_argv) nonopts = [] order!(argv, &nonopts.method(:<<)) argv[0, 0] = nonopts argv end # # Parses command line arguments +argv+ in order when environment variable # POSIXLY_CORRECT is set, and in permutation mode otherwise. # def parse(*argv) argv = argv[0].dup if argv.size == 1 and Array === argv[0] parse!(argv) end # # Same as #parse, but removes switches destructively. # Non-option arguments remain in +argv+. # def parse!(argv = default_argv) if ENV.include?('POSIXLY_CORRECT') order!(argv) else permute!(argv) end end # # Wrapper method for getopts.rb. # # params = ARGV.getopts("ab:", "foo", "bar:", "zot:Z;zot option) # # params[:a] = true # -a # # params[:b] = "1" # -b1 # # params[:foo] = "1" # --foo # # params[:bar] = "x" # --bar x # # params[:zot] = "z" # --zot Z # def getopts(*args) argv = Array === args.first ? args.shift : default_argv single_options, *long_options = *args result = {} single_options.scan(/(.)(:)?/) do |opt, val| if val result[opt] = nil define("-#{opt} VAL") else result[opt] = false define("-#{opt}") end end if single_options long_options.each do |arg| arg, desc = arg.split(';', 2) opt, val = arg.split(':', 2) if val result[opt] = val.empty? ? nil : val define("--#{opt}=#{result[opt] || "VAL"}", *[desc].compact) else result[opt] = false define("--#{opt}", *[desc].compact) end end parse_in_order(argv, result.method(:[]=)) result end # # See #getopts. # def self.getopts(*args) new.getopts(*args) end # # Traverses @stack, sending each element method +id+ with +args+ and # +block+. # def visit(id, *args, &block) @stack.reverse_each do |el| el.send(id, *args, &block) end nil end private :visit # # Searches +key+ in @stack for +id+ hash and returns or yields the result. # def search(id, key) block_given = block_given? visit(:search, id, key) do |k| return block_given ? yield(k) : k end end private :search # # Completes shortened long style option switch and returns pair of # canonical switch and switch descriptor OptionParser::Switch. # # +id+:: Searching table. # +opt+:: Searching key. # +icase+:: Search case insensitive if true. # +pat+:: Optional pattern for completion. # def complete(typ, opt, icase = false, *pat) if pat.empty? search(typ, opt) {|sw| return [sw, opt]} # exact match or... end raise AmbiguousOption, catch(:ambiguous) { visit(:complete, typ, opt, icase, *pat) {|o, *sw| return sw} raise InvalidOption, opt } end private :complete def candidate(word) list = [] case word when /\A--/ word, arg = word.split(/=/, 2) argpat = Completion.regexp(arg, false) if arg and !arg.empty? long = true when /\A-(!-)/ short = true when /\A-/ long = short = true end pat = Completion.regexp(word, true) visit(:each_option) do |opt| next unless Switch === opt opts = (long ? opt.long : []) + (short ? opt.short : []) opts = Completion.candidate(word, true, pat, &opts.method(:each)).map(&:first) if pat if /\A=/ =~ opt.arg opts.map! {|sw| sw + "="} if arg and CompletingHash === opt.pattern if opts = opt.pattern.candidate(arg, false, argpat) opts.map!(&:last) end end end list.concat(opts) end list end # # Loads options from file names as +filename+. Does nothing when the file # is not present. Returns whether successfully loaded. # # +filename+ defaults to basename of the program without suffix in a # directory ~/.options. # def load(filename = nil) begin filename ||= File.expand_path(File.basename($0, '.*'), '~/.options') rescue return false end begin parse(*IO.readlines(filename).each {|s| s.chomp!}) true rescue Errno::ENOENT, Errno::ENOTDIR false end end # # Parses environment variable +env+ or its uppercase with splitting like a # shell. # # +env+ defaults to the basename of the program. # def environment(env = File.basename($0, '.*')) env = ENV[env] || ENV[env.upcase] or return require 'shellwords' parse(*Shellwords.shellwords(env)) end # # Acceptable argument classes # # # Any string and no conversion. This is fall-back. # accept(Object) {|s,|s or s.nil?} accept(NilClass) {|s,|s} # # Any non-empty string, and no conversion. # accept(String, /.+/m) {|s,*|s} # # Ruby/C-like integer, octal for 0-7 sequence, binary for 0b, hexadecimal # for 0x, and decimal for others; with optional sign prefix. Converts to # Integer. # decimal = '\d+(?:_\d+)*' binary = 'b[01]+(?:_[01]+)*' hex = 'x[\da-f]+(?:_[\da-f]+)*' octal = "0(?:[0-7]+(?:_[0-7]+)*|#{binary}|#{hex})?" integer = "#{octal}|#{decimal}" accept(Integer, %r"\A[-+]?(?:#{integer})\z"io) {|s,| begin Integer(s) rescue ArgumentError raise OptionParser::InvalidArgument, s end if s } # # Float number format, and converts to Float. # float = "(?:#{decimal}(?:\\.(?:#{decimal})?)?|\\.#{decimal})(?:E[-+]?#{decimal})?" floatpat = %r"\A[-+]?#{float}\z"io accept(Float, floatpat) {|s,| s.to_f if s} # # Generic numeric format, converts to Integer for integer format, Float # for float format, and Rational for rational format. # real = "[-+]?(?:#{octal}|#{float})" accept(Numeric, /\A(#{real})(?:\/(#{real}))?\z/io) {|s, d, n| if n Rational(d, n) elsif s eval(s) end } # # Decimal integer format, to be converted to Integer. # DecimalInteger = /\A[-+]?#{decimal}\z/io accept(DecimalInteger, DecimalInteger) {|s,| begin Integer(s) rescue ArgumentError raise OptionParser::InvalidArgument, s end if s } # # Ruby/C like octal/hexadecimal/binary integer format, to be converted to # Integer. # OctalInteger = /\A[-+]?(?:[0-7]+(?:_[0-7]+)*|0(?:#{binary}|#{hex}))\z/io accept(OctalInteger, OctalInteger) {|s,| begin Integer(s, 8) rescue ArgumentError raise OptionParser::InvalidArgument, s end if s } # # Decimal integer/float number format, to be converted to Integer for # integer format, Float for float format. # DecimalNumeric = floatpat # decimal integer is allowed as float also. accept(DecimalNumeric, floatpat) {|s,| begin eval(s) rescue SyntaxError raise OptionParser::InvalidArgument, s end if s } # # Boolean switch, which means whether it is present or not, whether it is # absent or not with prefix no-, or it takes an argument # yes/no/true/false/+/-. # yesno = CompletingHash.new %w[- no false].each {|el| yesno[el] = false} %w[+ yes true].each {|el| yesno[el] = true} yesno['nil'] = false # should be nil? accept(TrueClass, yesno) {|arg, val| val == nil or val} # # Similar to TrueClass, but defaults to false. # accept(FalseClass, yesno) {|arg, val| val != nil and val} # # List of strings separated by ",". # accept(Array) do |s,| if s s = s.split(',').collect {|ss| ss unless ss.empty?} end s end # # Regular expression with options. # accept(Regexp, %r"\A/((?:\\.|[^\\])*)/([[:alpha:]]+)?\z|.*") do |all, s, o| f = 0 if o f |= Regexp::IGNORECASE if /i/ =~ o f |= Regexp::MULTILINE if /m/ =~ o f |= Regexp::EXTENDED if /x/ =~ o k = o.delete("imx") k = nil if k.empty? end Regexp.new(s || all, f, k) end # # Exceptions # # # Base class of exceptions from OptionParser. # class ParseError < RuntimeError # Reason which caused the error. Reason = 'parse error'.freeze def initialize(*args) @args = args @reason = nil end attr_reader :args attr_writer :reason # # Pushes back erred argument(s) to +argv+. # def recover(argv) argv[0, 0] = @args argv end def self.filter_backtrace(array) unless $DEBUG array.delete_if(&%r"\A#{Regexp.quote(__FILE__)}:"o.method(:=~)) end array end def set_backtrace(array) super(self.class.filter_backtrace(array)) end def set_option(opt, eq) if eq @args[0] = opt else @args.unshift(opt) end self end # # Returns error reason. Override this for I18N. # def reason @reason || self.class::Reason end def inspect "#<#{self.class}: #{args.join(' ')}>" end # # Default stringizing method to emit standard error message. # def message reason + ': ' + args.join(' ') end alias to_s message end # # Raises when ambiguously completable string is encountered. # class AmbiguousOption < ParseError const_set(:Reason, 'ambiguous option'.freeze) end # # Raises when there is an argument for a switch which takes no argument. # class NeedlessArgument < ParseError const_set(:Reason, 'needless argument'.freeze) end # # Raises when a switch with mandatory argument has no argument. # class MissingArgument < ParseError const_set(:Reason, 'missing argument'.freeze) end # # Raises when switch is undefined. # class InvalidOption < ParseError const_set(:Reason, 'invalid option'.freeze) end # # Raises when the given argument does not match required format. # class InvalidArgument < ParseError const_set(:Reason, 'invalid argument'.freeze) end # # Raises when the given argument word can't be completed uniquely. # class AmbiguousArgument < InvalidArgument const_set(:Reason, 'ambiguous argument'.freeze) end # # Miscellaneous # # # Extends command line arguments array (ARGV) to parse itself. # module Arguable # # Sets OptionParser object, when +opt+ is +false+ or +nil+, methods # OptionParser::Arguable#options and OptionParser::Arguable#options= are # undefined. Thus, there is no ways to access the OptionParser object # via the receiver object. # def options=(opt) unless @optparse = opt class << self undef_method(:options) undef_method(:options=) end end end # # Actual OptionParser object, automatically created if nonexistent. # # If called with a block, yields the OptionParser object and returns the # result of the block. If an OptionParser::ParseError exception occurs # in the block, it is rescued, a error message printed to STDERR and # +nil+ returned. # def options @optparse ||= OptionParser.new @optparse.default_argv = self block_given? or return @optparse begin yield @optparse rescue ParseError @optparse.warn $! nil end end # # Parses +self+ destructively in order and returns +self+ containing the # rest arguments left unparsed. # def order!(&blk) options.order!(self, &blk) end # # Parses +self+ destructively in permutation mode and returns +self+ # containing the rest arguments left unparsed. # def permute!() options.permute!(self) end # # Parses +self+ destructively and returns +self+ containing the # rest arguments left unparsed. # def parse!() options.parse!(self) end # # Substitution of getopts is possible as follows. Also see # OptionParser#getopts. # # def getopts(*args) # ($OPT = ARGV.getopts(*args)).each do |opt, val| # eval "$OPT_#{opt.gsub(/[^A-Za-z0-9_]/, '_')} = val" # end # rescue OptionParser::ParseError # end # def getopts(*args) options.getopts(self, *args) end # # Initializes instance variable. # def self.extend_object(obj) super obj.instance_eval {@optparse = nil} end def initialize(*args) super @optparse = nil end end # # Acceptable argument classes. Now contains DecimalInteger, OctalInteger # and DecimalNumeric. See Acceptable argument classes (in source code). # module Acceptables const_set(:DecimalInteger, OptionParser::DecimalInteger) const_set(:OctalInteger, OptionParser::OctalInteger) const_set(:DecimalNumeric, OptionParser::DecimalNumeric) end end # ARGV is arguable by OptionParser ARGV.extend(OptionParser::Arguable) # An alias for OptionParser. OptParse = OptionParser # :nodoc: PK!I 2.2.0/yaml.rbnu[## # The YAML module is an alias of Psych, the YAML engine for Ruby. begin require 'psych' rescue LoadError warn "#{caller[0]}:" warn "It seems your ruby installation is missing psych (for YAML output)." warn "To eliminate this warning, please install libyaml and reinstall your ruby." raise end YAML = Psych # :nodoc: # YAML Ain't Markup Language # # This module provides a Ruby interface for data serialization in YAML format. # # The underlying implementation is the libyaml wrapper Psych. # # == Usage # # Working with YAML can be very simple, for example: # # require 'yaml' # # Parse a YAML string # YAML.load("--- foo") #=> "foo" # # # Emit some YAML # YAML.dump("foo") # => "--- foo\n...\n" # { :a => 'b'}.to_yaml # => "---\n:a: b\n" # # == Security # # Do not use YAML to load untrusted data. Doing so is unsafe and could allow # malicious input to execute arbitrary code inside your application. Please see # doc/security.rdoc for more information. # # == History # # Syck was the original for YAML implementation in Ruby's standard library # developed by why the lucky stiff. # # You can still use Syck, if you prefer, for parsing and emitting YAML, but you # must install the 'syck' gem now in order to use it. # # In older Ruby versions, ie. <= 1.9, Syck is still provided, however it was # completely removed with the release of Ruby 2.0.0. # # == More info # # For more advanced details on the implementation see Psych, and also check out # http://yaml.org for spec details and other helpful information. # # Pysch is maintained by Aaron Patterson on github: https://github.com/tenderlove/psych # # Syck can also be found on github: https://github.com/tenderlove/syck module YAML end PK!IL2.2.0/matrix.rbnu[# encoding: utf-8 # # = matrix.rb # # An implementation of Matrix and Vector classes. # # See classes Matrix and Vector for documentation. # # Current Maintainer:: Marc-André Lafortune # Original Author:: Keiju ISHITSUKA # Original Documentation:: Gavin Sinclair (sourced from Ruby in a Nutshell (Matsumoto, O'Reilly)) ## require "e2mmap.rb" module ExceptionForMatrix # :nodoc: extend Exception2MessageMapper def_e2message(TypeError, "wrong argument type %s (expected %s)") def_e2message(ArgumentError, "Wrong # of arguments(%d for %d)") def_exception("ErrDimensionMismatch", "\#{self.name} dimension mismatch") def_exception("ErrNotRegular", "Not Regular Matrix") def_exception("ErrOperationNotDefined", "Operation(%s) can\\'t be defined: %s op %s") def_exception("ErrOperationNotImplemented", "Sorry, Operation(%s) not implemented: %s op %s") end # # The +Matrix+ class represents a mathematical matrix. It provides methods for creating # matrices, operating on them arithmetically and algebraically, # and determining their mathematical properties (trace, rank, inverse, determinant). # # == Method Catalogue # # To create a matrix: # * Matrix[*rows] # * Matrix.[](*rows) # * Matrix.rows(rows, copy = true) # * Matrix.columns(columns) # * Matrix.build(row_count, column_count, &block) # * Matrix.diagonal(*values) # * Matrix.scalar(n, value) # * Matrix.identity(n) # * Matrix.unit(n) # * Matrix.I(n) # * Matrix.zero(n) # * Matrix.row_vector(row) # * Matrix.column_vector(column) # * Matrix.hstack(*matrices) # * Matrix.vstack(*matrices) # # To access Matrix elements/columns/rows/submatrices/properties: # * #[](i, j) # * #row_count (row_size) # * #column_count (column_size) # * #row(i) # * #column(j) # * #collect # * #map # * #each # * #each_with_index # * #find_index # * #minor(*param) # * #first_minor(row, column) # * #cofactor(row, column) # * #adjugate # * #laplace_expansion(row_or_column: num) # * #cofactor_expansion(row_or_column: num) # # Properties of a matrix: # * #diagonal? # * #empty? # * #hermitian? # * #lower_triangular? # * #normal? # * #orthogonal? # * #permutation? # * #real? # * #regular? # * #singular? # * #square? # * #symmetric? # * #unitary? # * #upper_triangular? # * #zero? # # Matrix arithmetic: # * #*(m) # * #+(m) # * #-(m) # * #/(m) # * #inverse # * #inv # * #** # * #+@ # * #-@ # # Matrix functions: # * #determinant # * #det # * #hstack(*matrices) # * #rank # * #round # * #trace # * #tr # * #transpose # * #t # * #vstack(*matrices) # # Matrix decompositions: # * #eigen # * #eigensystem # * #lup # * #lup_decomposition # # Complex arithmetic: # * conj # * conjugate # * imag # * imaginary # * real # * rect # * rectangular # # Conversion to other data types: # * #coerce(other) # * #row_vectors # * #column_vectors # * #to_a # # String representations: # * #to_s # * #inspect # class Matrix include Enumerable include ExceptionForMatrix autoload :EigenvalueDecomposition, "matrix/eigenvalue_decomposition" autoload :LUPDecomposition, "matrix/lup_decomposition" # instance creations private_class_method :new attr_reader :rows protected :rows # # Creates a matrix where each argument is a row. # Matrix[ [25, 93], [-1, 66] ] # => 25 93 # -1 66 # def Matrix.[](*rows) rows(rows, false) end # # Creates a matrix where +rows+ is an array of arrays, each of which is a row # of the matrix. If the optional argument +copy+ is false, use the given # arrays as the internal structure of the matrix without copying. # Matrix.rows([[25, 93], [-1, 66]]) # => 25 93 # -1 66 # def Matrix.rows(rows, copy = true) rows = convert_to_array(rows, copy) rows.map! do |row| convert_to_array(row, copy) end size = (rows[0] || []).size rows.each do |row| raise ErrDimensionMismatch, "row size differs (#{row.size} should be #{size})" unless row.size == size end new rows, size end # # Creates a matrix using +columns+ as an array of column vectors. # Matrix.columns([[25, 93], [-1, 66]]) # => 25 -1 # 93 66 # def Matrix.columns(columns) rows(columns, false).transpose end # # Creates a matrix of size +row_count+ x +column_count+. # It fills the values by calling the given block, # passing the current row and column. # Returns an enumerator if no block is given. # # m = Matrix.build(2, 4) {|row, col| col - row } # => Matrix[[0, 1, 2, 3], [-1, 0, 1, 2]] # m = Matrix.build(3) { rand } # => a 3x3 matrix with random elements # def Matrix.build(row_count, column_count = row_count) row_count = CoercionHelper.coerce_to_int(row_count) column_count = CoercionHelper.coerce_to_int(column_count) raise ArgumentError if row_count < 0 || column_count < 0 return to_enum :build, row_count, column_count unless block_given? rows = Array.new(row_count) do |i| Array.new(column_count) do |j| yield i, j end end new rows, column_count end # # Creates a matrix where the diagonal elements are composed of +values+. # Matrix.diagonal(9, 5, -3) # => 9 0 0 # 0 5 0 # 0 0 -3 # def Matrix.diagonal(*values) size = values.size return Matrix.empty if size == 0 rows = Array.new(size) {|j| row = Array.new(size, 0) row[j] = values[j] row } new rows end # # Creates an +n+ by +n+ diagonal matrix where each diagonal element is # +value+. # Matrix.scalar(2, 5) # => 5 0 # 0 5 # def Matrix.scalar(n, value) diagonal(*Array.new(n, value)) end # # Creates an +n+ by +n+ identity matrix. # Matrix.identity(2) # => 1 0 # 0 1 # def Matrix.identity(n) scalar(n, 1) end class << Matrix alias unit identity alias I identity end # # Creates a zero matrix. # Matrix.zero(2) # => 0 0 # 0 0 # def Matrix.zero(row_count, column_count = row_count) rows = Array.new(row_count){Array.new(column_count, 0)} new rows, column_count end # # Creates a single-row matrix where the values of that row are as given in # +row+. # Matrix.row_vector([4,5,6]) # => 4 5 6 # def Matrix.row_vector(row) row = convert_to_array(row) new [row] end # # Creates a single-column matrix where the values of that column are as given # in +column+. # Matrix.column_vector([4,5,6]) # => 4 # 5 # 6 # def Matrix.column_vector(column) column = convert_to_array(column) new [column].transpose, 1 end # # Creates a empty matrix of +row_count+ x +column_count+. # At least one of +row_count+ or +column_count+ must be 0. # # m = Matrix.empty(2, 0) # m == Matrix[ [], [] ] # => true # n = Matrix.empty(0, 3) # n == Matrix.columns([ [], [], [] ]) # => true # m * n # => Matrix[[0, 0, 0], [0, 0, 0]] # def Matrix.empty(row_count = 0, column_count = 0) raise ArgumentError, "One size must be 0" if column_count != 0 && row_count != 0 raise ArgumentError, "Negative size" if column_count < 0 || row_count < 0 new([[]]*row_count, column_count) end # # Create a matrix by stacking matrices vertically # # x = Matrix[[1, 2], [3, 4]] # y = Matrix[[5, 6], [7, 8]] # Matrix.vstack(x, y) # => Matrix[[1, 2], [3, 4], [5, 6], [7, 8]] # def Matrix.vstack(x, *matrices) raise TypeError, "Expected a Matrix, got a #{x.class}" unless x.is_a?(Matrix) result = x.send(:rows).map(&:dup) matrices.each do |m| raise TypeError, "Expected a Matrix, got a #{m.class}" unless m.is_a?(Matrix) if m.column_count != x.column_count raise ErrDimensionMismatch, "The given matrices must have #{x.column_count} columns, but one has #{m.column_count}" end result.concat(m.send(:rows)) end new result, x.column_count end # # Create a matrix by stacking matrices horizontally # # x = Matrix[[1, 2], [3, 4]] # y = Matrix[[5, 6], [7, 8]] # Matrix.hstack(x, y) # => Matrix[[1, 2, 5, 6], [3, 4, 7, 8]] # def Matrix.hstack(x, *matrices) raise TypeError, "Expected a Matrix, got a #{x.class}" unless x.is_a?(Matrix) result = x.send(:rows).map(&:dup) total_column_count = x.column_count matrices.each do |m| raise TypeError, "Expected a Matrix, got a #{m.class}" unless m.is_a?(Matrix) if m.row_count != x.row_count raise ErrDimensionMismatch, "The given matrices must have #{x.row_count} rows, but one has #{m.row_count}" end result.each_with_index do |row, i| row.concat m.send(:rows)[i] end total_column_count += m.column_count end new result, total_column_count end # # Matrix.new is private; use Matrix.rows, columns, [], etc... to create. # def initialize(rows, column_count = rows[0].size) # No checking is done at this point. rows must be an Array of Arrays. # column_count must be the size of the first row, if there is one, # otherwise it *must* be specified and can be any integer >= 0 @rows = rows @column_count = column_count end def new_matrix(rows, column_count = rows[0].size) # :nodoc: self.class.send(:new, rows, column_count) # bypass privacy of Matrix.new end private :new_matrix # # Returns element (+i+,+j+) of the matrix. That is: row +i+, column +j+. # def [](i, j) @rows.fetch(i){return nil}[j] end alias element [] alias component [] def []=(i, j, v) @rows[i][j] = v end alias set_element []= alias set_component []= private :[]=, :set_element, :set_component # # Returns the number of rows. # def row_count @rows.size end alias_method :row_size, :row_count # # Returns the number of columns. # attr_reader :column_count alias_method :column_size, :column_count # # Returns row vector number +i+ of the matrix as a Vector (starting at 0 like # an array). When a block is given, the elements of that vector are iterated. # def row(i, &block) # :yield: e if block_given? @rows.fetch(i){return self}.each(&block) self else Vector.elements(@rows.fetch(i){return nil}) end end # # Returns column vector number +j+ of the matrix as a Vector (starting at 0 # like an array). When a block is given, the elements of that vector are # iterated. # def column(j) # :yield: e if block_given? return self if j >= column_count || j < -column_count row_count.times do |i| yield @rows[i][j] end self else return nil if j >= column_count || j < -column_count col = Array.new(row_count) {|i| @rows[i][j] } Vector.elements(col, false) end end # # Returns a matrix that is the result of iteration of the given block over all # elements of the matrix. # Matrix[ [1,2], [3,4] ].collect { |e| e**2 } # => 1 4 # 9 16 # def collect(&block) # :yield: e return to_enum(:collect) unless block_given? rows = @rows.collect{|row| row.collect(&block)} new_matrix rows, column_count end alias map collect # # Yields all elements of the matrix, starting with those of the first row, # or returns an Enumerator if no block given. # Elements can be restricted by passing an argument: # * :all (default): yields all elements # * :diagonal: yields only elements on the diagonal # * :off_diagonal: yields all elements except on the diagonal # * :lower: yields only elements on or below the diagonal # * :strict_lower: yields only elements below the diagonal # * :strict_upper: yields only elements above the diagonal # * :upper: yields only elements on or above the diagonal # # Matrix[ [1,2], [3,4] ].each { |e| puts e } # # => prints the numbers 1 to 4 # Matrix[ [1,2], [3,4] ].each(:strict_lower).to_a # => [3] # def each(which = :all) # :yield: e return to_enum :each, which unless block_given? last = column_count - 1 case which when :all block = Proc.new @rows.each do |row| row.each(&block) end when :diagonal @rows.each_with_index do |row, row_index| yield row.fetch(row_index){return self} end when :off_diagonal @rows.each_with_index do |row, row_index| column_count.times do |col_index| yield row[col_index] unless row_index == col_index end end when :lower @rows.each_with_index do |row, row_index| 0.upto([row_index, last].min) do |col_index| yield row[col_index] end end when :strict_lower @rows.each_with_index do |row, row_index| [row_index, column_count].min.times do |col_index| yield row[col_index] end end when :strict_upper @rows.each_with_index do |row, row_index| (row_index+1).upto(last) do |col_index| yield row[col_index] end end when :upper @rows.each_with_index do |row, row_index| row_index.upto(last) do |col_index| yield row[col_index] end end else raise ArgumentError, "expected #{which.inspect} to be one of :all, :diagonal, :off_diagonal, :lower, :strict_lower, :strict_upper or :upper" end self end # # Same as #each, but the row index and column index in addition to the element # # Matrix[ [1,2], [3,4] ].each_with_index do |e, row, col| # puts "#{e} at #{row}, #{col}" # end # # => Prints: # # 1 at 0, 0 # # 2 at 0, 1 # # 3 at 1, 0 # # 4 at 1, 1 # def each_with_index(which = :all) # :yield: e, row, column return to_enum :each_with_index, which unless block_given? last = column_count - 1 case which when :all @rows.each_with_index do |row, row_index| row.each_with_index do |e, col_index| yield e, row_index, col_index end end when :diagonal @rows.each_with_index do |row, row_index| yield row.fetch(row_index){return self}, row_index, row_index end when :off_diagonal @rows.each_with_index do |row, row_index| column_count.times do |col_index| yield row[col_index], row_index, col_index unless row_index == col_index end end when :lower @rows.each_with_index do |row, row_index| 0.upto([row_index, last].min) do |col_index| yield row[col_index], row_index, col_index end end when :strict_lower @rows.each_with_index do |row, row_index| [row_index, column_count].min.times do |col_index| yield row[col_index], row_index, col_index end end when :strict_upper @rows.each_with_index do |row, row_index| (row_index+1).upto(last) do |col_index| yield row[col_index], row_index, col_index end end when :upper @rows.each_with_index do |row, row_index| row_index.upto(last) do |col_index| yield row[col_index], row_index, col_index end end else raise ArgumentError, "expected #{which.inspect} to be one of :all, :diagonal, :off_diagonal, :lower, :strict_lower, :strict_upper or :upper" end self end SELECTORS = {all: true, diagonal: true, off_diagonal: true, lower: true, strict_lower: true, strict_upper: true, upper: true}.freeze # # :call-seq: # index(value, selector = :all) -> [row, column] # index(selector = :all){ block } -> [row, column] # index(selector = :all) -> an_enumerator # # The index method is specialized to return the index as [row, column] # It also accepts an optional +selector+ argument, see #each for details. # # Matrix[ [1,2], [3,4] ].index(&:even?) # => [0, 1] # Matrix[ [1,1], [1,1] ].index(1, :strict_lower) # => [1, 0] # def index(*args) raise ArgumentError, "wrong number of arguments(#{args.size} for 0-2)" if args.size > 2 which = (args.size == 2 || SELECTORS.include?(args.last)) ? args.pop : :all return to_enum :find_index, which, *args unless block_given? || args.size == 1 if args.size == 1 value = args.first each_with_index(which) do |e, row_index, col_index| return row_index, col_index if e == value end else each_with_index(which) do |e, row_index, col_index| return row_index, col_index if yield e end end nil end alias_method :find_index, :index # # Returns a section of the matrix. The parameters are either: # * start_row, nrows, start_col, ncols; OR # * row_range, col_range # # Matrix.diagonal(9, 5, -3).minor(0..1, 0..2) # => 9 0 0 # 0 5 0 # # Like Array#[], negative indices count backward from the end of the # row or column (-1 is the last element). Returns nil if the starting # row or column is greater than row_count or column_count respectively. # def minor(*param) case param.size when 2 row_range, col_range = param from_row = row_range.first from_row += row_count if from_row < 0 to_row = row_range.end to_row += row_count if to_row < 0 to_row += 1 unless row_range.exclude_end? size_row = to_row - from_row from_col = col_range.first from_col += column_count if from_col < 0 to_col = col_range.end to_col += column_count if to_col < 0 to_col += 1 unless col_range.exclude_end? size_col = to_col - from_col when 4 from_row, size_row, from_col, size_col = param return nil if size_row < 0 || size_col < 0 from_row += row_count if from_row < 0 from_col += column_count if from_col < 0 else raise ArgumentError, param.inspect end return nil if from_row > row_count || from_col > column_count || from_row < 0 || from_col < 0 rows = @rows[from_row, size_row].collect{|row| row[from_col, size_col] } new_matrix rows, [column_count - from_col, size_col].min end # # Returns the submatrix obtained by deleting the specified row and column. # # Matrix.diagonal(9, 5, -3, 4).first_minor(1, 2) # => 9 0 0 # 0 0 0 # 0 0 4 # def first_minor(row, column) raise RuntimeError, "first_minor of empty matrix is not defined" if empty? unless 0 <= row && row < row_count raise ArgumentError, "invalid row (#{row.inspect} for 0..#{row_count - 1})" end unless 0 <= column && column < column_count raise ArgumentError, "invalid column (#{column.inspect} for 0..#{column_count - 1})" end arrays = to_a arrays.delete_at(row) arrays.each do |array| array.delete_at(column) end new_matrix arrays, column_count - 1 end # # Returns the (row, column) cofactor which is obtained by multiplying # the first minor by (-1)**(row + column). # # Matrix.diagonal(9, 5, -3, 4).cofactor(1, 1) # => -108 # def cofactor(row, column) raise RuntimeError, "cofactor of empty matrix is not defined" if empty? Matrix.Raise ErrDimensionMismatch unless square? det_of_minor = first_minor(row, column).determinant det_of_minor * (-1) ** (row + column) end # # Returns the adjugate of the matrix. # # Matrix[ [7,6],[3,9] ].adjugate # => 9 -6 # -3 7 # def adjugate Matrix.Raise ErrDimensionMismatch unless square? Matrix.build(row_count, column_count) do |row, column| cofactor(column, row) end end # # Returns the Laplace expansion along given row or column. # # Matrix[[7,6], [3,9]].laplace_expansion(column: 1) # => 45 # # Matrix[[Vector[1, 0], Vector[0, 1]], [2, 3]].laplace_expansion(row: 0) # => Vector[3, -2] # # def laplace_expansion(row: nil, column: nil) num = row || column if !num || (row && column) raise ArgumentError, "exactly one the row or column arguments must be specified" end Matrix.Raise ErrDimensionMismatch unless square? raise RuntimeError, "laplace_expansion of empty matrix is not defined" if empty? unless 0 <= num && num < row_count raise ArgumentError, "invalid num (#{num.inspect} for 0..#{row_count - 1})" end send(row ? :row : :column, num).map.with_index { |e, k| e * cofactor(*(row ? [num, k] : [k,num])) }.inject(:+) end alias_method :cofactor_expansion, :laplace_expansion #-- # TESTING -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- #++ # # Returns +true+ if this is a diagonal matrix. # Raises an error if matrix is not square. # def diagonal? Matrix.Raise ErrDimensionMismatch unless square? each(:off_diagonal).all?(&:zero?) end # # Returns +true+ if this is an empty matrix, i.e. if the number of rows # or the number of columns is 0. # def empty? column_count == 0 || row_count == 0 end # # Returns +true+ if this is an hermitian matrix. # Raises an error if matrix is not square. # def hermitian? Matrix.Raise ErrDimensionMismatch unless square? each_with_index(:upper).all? do |e, row, col| e == rows[col][row].conj end end # # Returns +true+ if this is a lower triangular matrix. # def lower_triangular? each(:strict_upper).all?(&:zero?) end # # Returns +true+ if this is a normal matrix. # Raises an error if matrix is not square. # def normal? Matrix.Raise ErrDimensionMismatch unless square? rows.each_with_index do |row_i, i| rows.each_with_index do |row_j, j| s = 0 rows.each_with_index do |row_k, k| s += row_i[k] * row_j[k].conj - row_k[i].conj * row_k[j] end return false unless s == 0 end end true end # # Returns +true+ if this is an orthogonal matrix # Raises an error if matrix is not square. # def orthogonal? Matrix.Raise ErrDimensionMismatch unless square? rows.each_with_index do |row, i| column_count.times do |j| s = 0 row_count.times do |k| s += row[k] * rows[k][j] end return false unless s == (i == j ? 1 : 0) end end true end # # Returns +true+ if this is a permutation matrix # Raises an error if matrix is not square. # def permutation? Matrix.Raise ErrDimensionMismatch unless square? cols = Array.new(column_count) rows.each_with_index do |row, i| found = false row.each_with_index do |e, j| if e == 1 return false if found || cols[j] found = cols[j] = true elsif e != 0 return false end end return false unless found end true end # # Returns +true+ if all entries of the matrix are real. # def real? all?(&:real?) end # # Returns +true+ if this is a regular (i.e. non-singular) matrix. # def regular? not singular? end # # Returns +true+ if this is a singular matrix. # def singular? determinant == 0 end # # Returns +true+ if this is a square matrix. # def square? column_count == row_count end # # Returns +true+ if this is a symmetric matrix. # Raises an error if matrix is not square. # def symmetric? Matrix.Raise ErrDimensionMismatch unless square? each_with_index(:strict_upper) do |e, row, col| return false if e != rows[col][row] end true end # # Returns +true+ if this is a unitary matrix # Raises an error if matrix is not square. # def unitary? Matrix.Raise ErrDimensionMismatch unless square? rows.each_with_index do |row, i| column_count.times do |j| s = 0 row_count.times do |k| s += row[k].conj * rows[k][j] end return false unless s == (i == j ? 1 : 0) end end true end # # Returns +true+ if this is an upper triangular matrix. # def upper_triangular? each(:strict_lower).all?(&:zero?) end # # Returns +true+ if this is a matrix with only zero elements # def zero? all?(&:zero?) end #-- # OBJECT METHODS -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- #++ # # Returns +true+ if and only if the two matrices contain equal elements. # def ==(other) return false unless Matrix === other && column_count == other.column_count # necessary for empty matrices rows == other.rows end def eql?(other) return false unless Matrix === other && column_count == other.column_count # necessary for empty matrices rows.eql? other.rows end # # Returns a clone of the matrix, so that the contents of each do not reference # identical objects. # There should be no good reason to do this since Matrices are immutable. # def clone new_matrix @rows.map(&:dup), column_count end # # Returns a hash-code for the matrix. # def hash @rows.hash end #-- # ARITHMETIC -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- #++ # # Matrix multiplication. # Matrix[[2,4], [6,8]] * Matrix.identity(2) # => 2 4 # 6 8 # def *(m) # m is matrix or vector or number case(m) when Numeric rows = @rows.collect {|row| row.collect {|e| e * m } } return new_matrix rows, column_count when Vector m = self.class.column_vector(m) r = self * m return r.column(0) when Matrix Matrix.Raise ErrDimensionMismatch if column_count != m.row_count rows = Array.new(row_count) {|i| Array.new(m.column_count) {|j| (0 ... column_count).inject(0) do |vij, k| vij + self[i, k] * m[k, j] end } } return new_matrix rows, m.column_count else return apply_through_coercion(m, __method__) end end # # Matrix addition. # Matrix.scalar(2,5) + Matrix[[1,0], [-4,7]] # => 6 0 # -4 12 # def +(m) case m when Numeric Matrix.Raise ErrOperationNotDefined, "+", self.class, m.class when Vector m = self.class.column_vector(m) when Matrix else return apply_through_coercion(m, __method__) end Matrix.Raise ErrDimensionMismatch unless row_count == m.row_count && column_count == m.column_count rows = Array.new(row_count) {|i| Array.new(column_count) {|j| self[i, j] + m[i, j] } } new_matrix rows, column_count end # # Matrix subtraction. # Matrix[[1,5], [4,2]] - Matrix[[9,3], [-4,1]] # => -8 2 # 8 1 # def -(m) case m when Numeric Matrix.Raise ErrOperationNotDefined, "-", self.class, m.class when Vector m = self.class.column_vector(m) when Matrix else return apply_through_coercion(m, __method__) end Matrix.Raise ErrDimensionMismatch unless row_count == m.row_count && column_count == m.column_count rows = Array.new(row_count) {|i| Array.new(column_count) {|j| self[i, j] - m[i, j] } } new_matrix rows, column_count end # # Matrix division (multiplication by the inverse). # Matrix[[7,6], [3,9]] / Matrix[[2,9], [3,1]] # => -7 1 # -3 -6 # def /(other) case other when Numeric rows = @rows.collect {|row| row.collect {|e| e / other } } return new_matrix rows, column_count when Matrix return self * other.inverse else return apply_through_coercion(other, __method__) end end # # Returns the inverse of the matrix. # Matrix[[-1, -1], [0, -1]].inverse # => -1 1 # 0 -1 # def inverse Matrix.Raise ErrDimensionMismatch unless square? self.class.I(row_count).send(:inverse_from, self) end alias inv inverse def inverse_from(src) # :nodoc: last = row_count - 1 a = src.to_a 0.upto(last) do |k| i = k akk = a[k][k].abs (k+1).upto(last) do |j| v = a[j][k].abs if v > akk i = j akk = v end end Matrix.Raise ErrNotRegular if akk == 0 if i != k a[i], a[k] = a[k], a[i] @rows[i], @rows[k] = @rows[k], @rows[i] end akk = a[k][k] 0.upto(last) do |ii| next if ii == k q = a[ii][k].quo(akk) a[ii][k] = 0 (k + 1).upto(last) do |j| a[ii][j] -= a[k][j] * q end 0.upto(last) do |j| @rows[ii][j] -= @rows[k][j] * q end end (k+1).upto(last) do |j| a[k][j] = a[k][j].quo(akk) end 0.upto(last) do |j| @rows[k][j] = @rows[k][j].quo(akk) end end self end private :inverse_from # # Matrix exponentiation. # Equivalent to multiplying the matrix by itself N times. # Non integer exponents will be handled by diagonalizing the matrix. # # Matrix[[7,6], [3,9]] ** 2 # => 67 96 # 48 99 # def ** (other) case other when Integer x = self if other <= 0 x = self.inverse return self.class.identity(self.column_count) if other == 0 other = -other end z = nil loop do z = z ? z * x : x if other[0] == 1 return z if (other >>= 1).zero? x *= x end when Numeric v, d, v_inv = eigensystem v * self.class.diagonal(*d.each(:diagonal).map{|e| e ** other}) * v_inv else Matrix.Raise ErrOperationNotDefined, "**", self.class, other.class end end def +@ self end def -@ collect {|e| -e } end #-- # MATRIX FUNCTIONS -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- #++ # # Returns the determinant of the matrix. # # Beware that using Float values can yield erroneous results # because of their lack of precision. # Consider using exact types like Rational or BigDecimal instead. # # Matrix[[7,6], [3,9]].determinant # => 45 # def determinant Matrix.Raise ErrDimensionMismatch unless square? m = @rows case row_count # Up to 4x4, give result using Laplacian expansion by minors. # This will typically be faster, as well as giving good results # in case of Floats when 0 +1 when 1 + m[0][0] when 2 + m[0][0] * m[1][1] - m[0][1] * m[1][0] when 3 m0, m1, m2 = m + m0[0] * m1[1] * m2[2] - m0[0] * m1[2] * m2[1] \ - m0[1] * m1[0] * m2[2] + m0[1] * m1[2] * m2[0] \ + m0[2] * m1[0] * m2[1] - m0[2] * m1[1] * m2[0] when 4 m0, m1, m2, m3 = m + m0[0] * m1[1] * m2[2] * m3[3] - m0[0] * m1[1] * m2[3] * m3[2] \ - m0[0] * m1[2] * m2[1] * m3[3] + m0[0] * m1[2] * m2[3] * m3[1] \ + m0[0] * m1[3] * m2[1] * m3[2] - m0[0] * m1[3] * m2[2] * m3[1] \ - m0[1] * m1[0] * m2[2] * m3[3] + m0[1] * m1[0] * m2[3] * m3[2] \ + m0[1] * m1[2] * m2[0] * m3[3] - m0[1] * m1[2] * m2[3] * m3[0] \ - m0[1] * m1[3] * m2[0] * m3[2] + m0[1] * m1[3] * m2[2] * m3[0] \ + m0[2] * m1[0] * m2[1] * m3[3] - m0[2] * m1[0] * m2[3] * m3[1] \ - m0[2] * m1[1] * m2[0] * m3[3] + m0[2] * m1[1] * m2[3] * m3[0] \ + m0[2] * m1[3] * m2[0] * m3[1] - m0[2] * m1[3] * m2[1] * m3[0] \ - m0[3] * m1[0] * m2[1] * m3[2] + m0[3] * m1[0] * m2[2] * m3[1] \ + m0[3] * m1[1] * m2[0] * m3[2] - m0[3] * m1[1] * m2[2] * m3[0] \ - m0[3] * m1[2] * m2[0] * m3[1] + m0[3] * m1[2] * m2[1] * m3[0] else # For bigger matrices, use an efficient and general algorithm. # Currently, we use the Gauss-Bareiss algorithm determinant_bareiss end end alias_method :det, :determinant # # Private. Use Matrix#determinant # # Returns the determinant of the matrix, using # Bareiss' multistep integer-preserving gaussian elimination. # It has the same computational cost order O(n^3) as standard Gaussian elimination. # Intermediate results are fraction free and of lower complexity. # A matrix of Integers will have thus intermediate results that are also Integers, # with smaller bignums (if any), while a matrix of Float will usually have # intermediate results with better precision. # def determinant_bareiss size = row_count last = size - 1 a = to_a no_pivot = Proc.new{ return 0 } sign = +1 pivot = 1 size.times do |k| previous_pivot = pivot if (pivot = a[k][k]) == 0 switch = (k+1 ... size).find(no_pivot) {|row| a[row][k] != 0 } a[switch], a[k] = a[k], a[switch] pivot = a[k][k] sign = -sign end (k+1).upto(last) do |i| ai = a[i] (k+1).upto(last) do |j| ai[j] = (pivot * ai[j] - ai[k] * a[k][j]) / previous_pivot end end end sign * pivot end private :determinant_bareiss # # deprecated; use Matrix#determinant # def determinant_e warn "#{caller(1)[0]}: warning: Matrix#determinant_e is deprecated; use #determinant" determinant end alias det_e determinant_e # # Returns a new matrix resulting by stacking horizontally # the receiver with the given matrices # # x = Matrix[[1, 2], [3, 4]] # y = Matrix[[5, 6], [7, 8]] # x.hstack(y) # => Matrix[[1, 2, 5, 6], [3, 4, 7, 8]] # def hstack(*matrices) self.class.hstack(self, *matrices) end # # Returns the rank of the matrix. # Beware that using Float values can yield erroneous results # because of their lack of precision. # Consider using exact types like Rational or BigDecimal instead. # # Matrix[[7,6], [3,9]].rank # => 2 # def rank # We currently use Bareiss' multistep integer-preserving gaussian elimination # (see comments on determinant) a = to_a last_column = column_count - 1 last_row = row_count - 1 pivot_row = 0 previous_pivot = 1 0.upto(last_column) do |k| switch_row = (pivot_row .. last_row).find {|row| a[row][k] != 0 } if switch_row a[switch_row], a[pivot_row] = a[pivot_row], a[switch_row] unless pivot_row == switch_row pivot = a[pivot_row][k] (pivot_row+1).upto(last_row) do |i| ai = a[i] (k+1).upto(last_column) do |j| ai[j] = (pivot * ai[j] - ai[k] * a[pivot_row][j]) / previous_pivot end end pivot_row += 1 previous_pivot = pivot end end pivot_row end # # deprecated; use Matrix#rank # def rank_e warn "#{caller(1)[0]}: warning: Matrix#rank_e is deprecated; use #rank" rank end # Returns a matrix with entries rounded to the given precision # (see Float#round) # def round(ndigits=0) map{|e| e.round(ndigits)} end # # Returns the trace (sum of diagonal elements) of the matrix. # Matrix[[7,6], [3,9]].trace # => 16 # def trace Matrix.Raise ErrDimensionMismatch unless square? (0...column_count).inject(0) do |tr, i| tr + @rows[i][i] end end alias tr trace # # Returns the transpose of the matrix. # Matrix[[1,2], [3,4], [5,6]] # => 1 2 # 3 4 # 5 6 # Matrix[[1,2], [3,4], [5,6]].transpose # => 1 3 5 # 2 4 6 # def transpose return self.class.empty(column_count, 0) if row_count.zero? new_matrix @rows.transpose, row_count end alias t transpose # # Returns a new matrix resulting by stacking vertically # the receiver with the given matrices # # x = Matrix[[1, 2], [3, 4]] # y = Matrix[[5, 6], [7, 8]] # x.vstack(y) # => Matrix[[1, 2], [3, 4], [5, 6], [7, 8]] # def vstack(*matrices) self.class.vstack(self, *matrices) end #-- # DECOMPOSITIONS -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= #++ # # Returns the Eigensystem of the matrix; see +EigenvalueDecomposition+. # m = Matrix[[1, 2], [3, 4]] # v, d, v_inv = m.eigensystem # d.diagonal? # => true # v.inv == v_inv # => true # (v * d * v_inv).round(5) == m # => true # def eigensystem EigenvalueDecomposition.new(self) end alias eigen eigensystem # # Returns the LUP decomposition of the matrix; see +LUPDecomposition+. # a = Matrix[[1, 2], [3, 4]] # l, u, p = a.lup # l.lower_triangular? # => true # u.upper_triangular? # => true # p.permutation? # => true # l * u == p * a # => true # a.lup.solve([2, 5]) # => Vector[(1/1), (1/2)] # def lup LUPDecomposition.new(self) end alias lup_decomposition lup #-- # COMPLEX ARITHMETIC -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= #++ # # Returns the conjugate of the matrix. # Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]] # => 1+2i i 0 # 1 2 3 # Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]].conjugate # => 1-2i -i 0 # 1 2 3 # def conjugate collect(&:conjugate) end alias conj conjugate # # Returns the imaginary part of the matrix. # Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]] # => 1+2i i 0 # 1 2 3 # Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]].imaginary # => 2i i 0 # 0 0 0 # def imaginary collect(&:imaginary) end alias imag imaginary # # Returns the real part of the matrix. # Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]] # => 1+2i i 0 # 1 2 3 # Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]].real # => 1 0 0 # 1 2 3 # def real collect(&:real) end # # Returns an array containing matrices corresponding to the real and imaginary # parts of the matrix # # m.rect == [m.real, m.imag] # ==> true for all matrices m # def rect [real, imag] end alias rectangular rect #-- # CONVERTING -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- #++ # # The coerce method provides support for Ruby type coercion. # This coercion mechanism is used by Ruby to handle mixed-type # numeric operations: it is intended to find a compatible common # type between the two operands of the operator. # See also Numeric#coerce. # def coerce(other) case other when Numeric return Scalar.new(other), self else raise TypeError, "#{self.class} can't be coerced into #{other.class}" end end # # Returns an array of the row vectors of the matrix. See Vector. # def row_vectors Array.new(row_count) {|i| row(i) } end # # Returns an array of the column vectors of the matrix. See Vector. # def column_vectors Array.new(column_count) {|i| column(i) } end # # Returns an array of arrays that describe the rows of the matrix. # def to_a @rows.collect(&:dup) end def elements_to_f warn "#{caller(1)[0]}: warning: Matrix#elements_to_f is deprecated, use map(&:to_f)" map(&:to_f) end def elements_to_i warn "#{caller(1)[0]}: warning: Matrix#elements_to_i is deprecated, use map(&:to_i)" map(&:to_i) end def elements_to_r warn "#{caller(1)[0]}: warning: Matrix#elements_to_r is deprecated, use map(&:to_r)" map(&:to_r) end #-- # PRINTING -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- #++ # # Overrides Object#to_s # def to_s if empty? "#{self.class}.empty(#{row_count}, #{column_count})" else "#{self.class}[" + @rows.collect{|row| "[" + row.collect{|e| e.to_s}.join(", ") + "]" }.join(", ")+"]" end end # # Overrides Object#inspect # def inspect if empty? "#{self.class}.empty(#{row_count}, #{column_count})" else "#{self.class}#{@rows.inspect}" end end # Private helper modules module ConversionHelper # :nodoc: # # Converts the obj to an Array. If copy is set to true # a copy of obj will be made if necessary. # def convert_to_array(obj, copy = false) # :nodoc: case obj when Array copy ? obj.dup : obj when Vector obj.to_a else begin converted = obj.to_ary rescue Exception => e raise TypeError, "can't convert #{obj.class} into an Array (#{e.message})" end raise TypeError, "#{obj.class}#to_ary should return an Array" unless converted.is_a? Array converted end end private :convert_to_array end extend ConversionHelper module CoercionHelper # :nodoc: # # Applies the operator +oper+ with argument +obj+ # through coercion of +obj+ # def apply_through_coercion(obj, oper) coercion = obj.coerce(self) raise TypeError unless coercion.is_a?(Array) && coercion.length == 2 coercion[0].public_send(oper, coercion[1]) rescue raise TypeError, "#{obj.inspect} can't be coerced into #{self.class}" end private :apply_through_coercion # # Helper method to coerce a value into a specific class. # Raises a TypeError if the coercion fails or the returned value # is not of the right class. # (from Rubinius) # def self.coerce_to(obj, cls, meth) # :nodoc: return obj if obj.kind_of?(cls) begin ret = obj.__send__(meth) rescue Exception => e raise TypeError, "Coercion error: #{obj.inspect}.#{meth} => #{cls} failed:\n" \ "(#{e.message})" end raise TypeError, "Coercion error: obj.#{meth} did NOT return a #{cls} (was #{ret.class})" unless ret.kind_of? cls ret end def self.coerce_to_int(obj) coerce_to(obj, Integer, :to_int) end end include CoercionHelper # Private CLASS class Scalar < Numeric # :nodoc: include ExceptionForMatrix include CoercionHelper def initialize(value) @value = value end # ARITHMETIC def +(other) case other when Numeric Scalar.new(@value + other) when Vector, Matrix Scalar.Raise ErrOperationNotDefined, "+", @value.class, other.class else apply_through_coercion(other, __method__) end end def -(other) case other when Numeric Scalar.new(@value - other) when Vector, Matrix Scalar.Raise ErrOperationNotDefined, "-", @value.class, other.class else apply_through_coercion(other, __method__) end end def *(other) case other when Numeric Scalar.new(@value * other) when Vector, Matrix other.collect{|e| @value * e} else apply_through_coercion(other, __method__) end end def / (other) case other when Numeric Scalar.new(@value / other) when Vector Scalar.Raise ErrOperationNotDefined, "/", @value.class, other.class when Matrix self * other.inverse else apply_through_coercion(other, __method__) end end def ** (other) case other when Numeric Scalar.new(@value ** other) when Vector Scalar.Raise ErrOperationNotDefined, "**", @value.class, other.class when Matrix #other.powered_by(self) Scalar.Raise ErrOperationNotImplemented, "**", @value.class, other.class else apply_through_coercion(other, __method__) end end end end # # The +Vector+ class represents a mathematical vector, which is useful in its own right, and # also constitutes a row or column of a Matrix. # # == Method Catalogue # # To create a Vector: # * Vector.[](*array) # * Vector.elements(array, copy = true) # * Vector.basis(size: n, index: k) # # To access elements: # * #[](i) # # To enumerate the elements: # * #each2(v) # * #collect2(v) # # Properties of vectors: # * #angle_with(v) # * Vector.independent?(*vs) # * #independent?(*vs) # # Vector arithmetic: # * #*(x) "is matrix or number" # * #+(v) # * #-(v) # * #+@ # * #-@ # # Vector functions: # * #inner_product(v), dot(v) # * #cross_product(v), cross(v) # * #collect # * #magnitude # * #map # * #map2(v) # * #norm # * #normalize # * #r # * #size # # Conversion to other data types: # * #covector # * #to_a # * #coerce(other) # # String representations: # * #to_s # * #inspect # class Vector include ExceptionForMatrix include Enumerable include Matrix::CoercionHelper extend Matrix::ConversionHelper #INSTANCE CREATION private_class_method :new attr_reader :elements protected :elements # # Creates a Vector from a list of elements. # Vector[7, 4, ...] # def Vector.[](*array) new convert_to_array(array, false) end # # Creates a vector from an Array. The optional second argument specifies # whether the array itself or a copy is used internally. # def Vector.elements(array, copy = true) new convert_to_array(array, copy) end # # Returns a standard basis +n+-vector, where k is the index. # # Vector.basis(size:, index:) # => Vector[0, 1, 0] # def Vector.basis(size:, index:) raise ArgumentError, "invalid size (#{size} for 1..)" if size < 1 raise ArgumentError, "invalid index (#{index} for 0...#{size})" unless 0 <= index && index < size array = Array.new(size, 0) array[index] = 1 new convert_to_array(array, false) end # # Vector.new is private; use Vector[] or Vector.elements to create. # def initialize(array) # No checking is done at this point. @elements = array end # ACCESSING # # Returns element number +i+ (starting at zero) of the vector. # def [](i) @elements[i] end alias element [] alias component [] def []=(i, v) @elements[i]= v end alias set_element []= alias set_component []= private :[]=, :set_element, :set_component # # Returns the number of elements in the vector. # def size @elements.size end #-- # ENUMERATIONS -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- #++ # # Iterate over the elements of this vector # def each(&block) return to_enum(:each) unless block_given? @elements.each(&block) self end # # Iterate over the elements of this vector and +v+ in conjunction. # def each2(v) # :yield: e1, e2 raise TypeError, "Integer is not like Vector" if v.kind_of?(Integer) Vector.Raise ErrDimensionMismatch if size != v.size return to_enum(:each2, v) unless block_given? size.times do |i| yield @elements[i], v[i] end self end # # Collects (as in Enumerable#collect) over the elements of this vector and +v+ # in conjunction. # def collect2(v) # :yield: e1, e2 raise TypeError, "Integer is not like Vector" if v.kind_of?(Integer) Vector.Raise ErrDimensionMismatch if size != v.size return to_enum(:collect2, v) unless block_given? Array.new(size) do |i| yield @elements[i], v[i] end end #-- # PROPERTIES -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- #++ # # Returns +true+ iff all of vectors are linearly independent. # # Vector.independent?(Vector[1,0], Vector[0,1]) # => true # # Vector.independent?(Vector[1,2], Vector[2,4]) # => false # def Vector.independent?(*vs) vs.each do |v| raise TypeError, "expected Vector, got #{v.class}" unless v.is_a?(Vector) Vector.Raise ErrDimensionMismatch unless v.size == vs.first.size end return false if vs.count > vs.first.size Matrix[*vs].rank.eql?(vs.count) end # # Returns +true+ iff all of vectors are linearly independent. # # Vector[1,0].independent?(Vector[0,1]) # => true # # Vector[1,2].independent?(Vector[2,4]) # => false # def independent?(*vs) self.class.independent?(self, *vs) end #-- # COMPARING -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- #++ # # Returns +true+ iff the two vectors have the same elements in the same order. # def ==(other) return false unless Vector === other @elements == other.elements end def eql?(other) return false unless Vector === other @elements.eql? other.elements end # # Returns a copy of the vector. # def clone self.class.elements(@elements) end # # Returns a hash-code for the vector. # def hash @elements.hash end #-- # ARITHMETIC -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- #++ # # Multiplies the vector by +x+, where +x+ is a number or another vector. # def *(x) case x when Numeric els = @elements.collect{|e| e * x} self.class.elements(els, false) when Matrix Matrix.column_vector(self) * x when Vector Vector.Raise ErrOperationNotDefined, "*", self.class, x.class else apply_through_coercion(x, __method__) end end # # Vector addition. # def +(v) case v when Vector Vector.Raise ErrDimensionMismatch if size != v.size els = collect2(v) {|v1, v2| v1 + v2 } self.class.elements(els, false) when Matrix Matrix.column_vector(self) + v else apply_through_coercion(v, __method__) end end # # Vector subtraction. # def -(v) case v when Vector Vector.Raise ErrDimensionMismatch if size != v.size els = collect2(v) {|v1, v2| v1 - v2 } self.class.elements(els, false) when Matrix Matrix.column_vector(self) - v else apply_through_coercion(v, __method__) end end # # Vector division. # def /(x) case x when Numeric els = @elements.collect{|e| e / x} self.class.elements(els, false) when Matrix, Vector Vector.Raise ErrOperationNotDefined, "/", self.class, x.class else apply_through_coercion(x, __method__) end end def +@ self end def -@ collect {|e| -e } end #-- # VECTOR FUNCTIONS -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- #++ # # Returns the inner product of this vector with the other. # Vector[4,7].inner_product Vector[10,1] => 47 # def inner_product(v) Vector.Raise ErrDimensionMismatch if size != v.size p = 0 each2(v) {|v1, v2| p += v1 * v2.conj } p end alias_method :dot, :inner_product # # Returns the cross product of this vector with the others. # Vector[1, 0, 0].cross_product Vector[0, 1, 0] => Vector[0, 0, 1] # # It is generalized to other dimensions to return a vector perpendicular # to the arguments. # Vector[1, 2].cross_product # => Vector[-2, 1] # Vector[1, 0, 0, 0].cross_product( # Vector[0, 1, 0, 0], # Vector[0, 0, 1, 0] # ) #=> Vector[0, 0, 0, 1] # def cross_product(*vs) raise ErrOperationNotDefined, "cross product is not defined on vectors of dimension #{size}" unless size >= 2 raise ArgumentError, "wrong number of arguments (#{vs.size} for #{size - 2})" unless vs.size == size - 2 vs.each do |v| raise TypeError, "expected Vector, got #{v.class}" unless v.is_a? Vector Vector.Raise ErrDimensionMismatch unless v.size == size end case size when 2 Vector[-@elements[1], @elements[0]] when 3 v = vs[0] Vector[ v[2]*@elements[1] - v[1]*@elements[2], v[0]*@elements[2] - v[2]*@elements[0], v[1]*@elements[0] - v[0]*@elements[1] ] else rows = self, *vs, Array.new(size) {|i| Vector.basis(size: size, index: i) } Matrix.rows(rows).laplace_expansion(row: size - 1) end end alias_method :cross, :cross_product # # Like Array#collect. # def collect(&block) # :yield: e return to_enum(:collect) unless block_given? els = @elements.collect(&block) self.class.elements(els, false) end alias map collect # # Returns the modulus (Pythagorean distance) of the vector. # Vector[5,8,2].r => 9.643650761 # def magnitude Math.sqrt(@elements.inject(0) {|v, e| v + e.abs2}) end alias r magnitude alias norm magnitude # # Like Vector#collect2, but returns a Vector instead of an Array. # def map2(v, &block) # :yield: e1, e2 return to_enum(:map2, v) unless block_given? els = collect2(v, &block) self.class.elements(els, false) end class ZeroVectorError < StandardError end # # Returns a new vector with the same direction but with norm 1. # v = Vector[5,8,2].normalize # # => Vector[0.5184758473652127, 0.8295613557843402, 0.20739033894608505] # v.norm => 1.0 # def normalize n = magnitude raise ZeroVectorError, "Zero vectors can not be normalized" if n == 0 self / n end # # Returns an angle with another vector. Result is within the [0...Math::PI]. # Vector[1,0].angle_with(Vector[0,1]) # # => Math::PI / 2 # def angle_with(v) raise TypeError, "Expected a Vector, got a #{v.class}" unless v.is_a?(Vector) Vector.Raise ErrDimensionMismatch if size != v.size prod = magnitude * v.magnitude raise ZeroVectorError, "Can't get angle of zero vector" if prod == 0 Math.acos( inner_product(v) / prod ) end #-- # CONVERTING #++ # # Creates a single-row matrix from this vector. # def covector Matrix.row_vector(self) end # # Returns the elements of the vector in an array. # def to_a @elements.dup end def elements_to_f warn "#{caller(1)[0]}: warning: Vector#elements_to_f is deprecated" map(&:to_f) end def elements_to_i warn "#{caller(1)[0]}: warning: Vector#elements_to_i is deprecated" map(&:to_i) end def elements_to_r warn "#{caller(1)[0]}: warning: Vector#elements_to_r is deprecated" map(&:to_r) end # # The coerce method provides support for Ruby type coercion. # This coercion mechanism is used by Ruby to handle mixed-type # numeric operations: it is intended to find a compatible common # type between the two operands of the operator. # See also Numeric#coerce. # def coerce(other) case other when Numeric return Matrix::Scalar.new(other), self else raise TypeError, "#{self.class} can't be coerced into #{other.class}" end end #-- # PRINTING -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- #++ # # Overrides Object#to_s # def to_s "Vector[" + @elements.join(", ") + "]" end # # Overrides Object#inspect # def inspect "Vector" + @elements.inspect end end PK!]\%\%2.2.0/cmath.rbnu[## # = Trigonometric and transcendental functions for complex numbers. # # CMath is a library that provides trigonometric and transcendental # functions for complex numbers. The functions in this module accept # integers, floating-point numbers or complex numbers as arguments. # # Note that the selection of functions is similar, but not identical, # to that in module math. The reason for having two modules is that # some users aren't interested in complex numbers, and perhaps don't # even know what they are. They would rather have Math.sqrt(-1) raise # an exception than return a complex number. # # == Usage # # To start using this library, simply require cmath library: # # require "cmath" # # And after call any CMath function. For example: # # CMath.sqrt(-9) #=> 0+3.0i # CMath.exp(0 + 0i) #=> 1.0+0.0i # CMath.log10(-5.to_c) #=> (0.6989700043360187+1.3643763538418412i) # # # For more information you can see Complec class. module CMath include Math alias exp! exp alias log! log alias log2! log2 alias log10! log10 alias sqrt! sqrt alias cbrt! cbrt alias sin! sin alias cos! cos alias tan! tan alias sinh! sinh alias cosh! cosh alias tanh! tanh alias asin! asin alias acos! acos alias atan! atan alias atan2! atan2 alias asinh! asinh alias acosh! acosh alias atanh! atanh ## # Math::E raised to the +z+ power # # CMath.exp(2i) #=> (-0.4161468365471424+0.9092974268256817i) def exp(z) begin if z.real? exp!(z) else ere = exp!(z.real) Complex(ere * cos!(z.imag), ere * sin!(z.imag)) end rescue NoMethodError handle_no_method_error end end ## # Returns the natural logarithm of Complex. If a second argument is given, # it will be the base of logarithm. # # CMath.log(1 + 4i) #=> (1.416606672028108+1.3258176636680326i) # CMath.log(1 + 4i, 10) #=> (0.6152244606891369+0.5757952953408879i) def log(*args) begin z, b = args unless b.nil? || b.kind_of?(Numeric) raise TypeError, "Numeric Number required" end if z.real? and z >= 0 and (b.nil? or b >= 0) log!(*args) else a = Complex(log!(z.abs), z.arg) if b a /= log(b) end a end rescue NoMethodError handle_no_method_error end end ## # returns the base 2 logarithm of +z+ # # CMath.log2(-1) => (0.0+4.532360141827194i) def log2(z) begin if z.real? and z >= 0 log2!(z) else log(z) / log!(2) end rescue NoMethodError handle_no_method_error end end ## # returns the base 10 logarithm of +z+ # # CMath.log10(-1) #=> (0.0+1.3643763538418412i) def log10(z) begin if z.real? and z >= 0 log10!(z) else log(z) / log!(10) end rescue NoMethodError handle_no_method_error end end ## # Returns the non-negative square root of Complex. # # CMath.sqrt(-1 + 0i) #=> 0.0+1.0i def sqrt(z) begin if z.real? if z < 0 Complex(0, sqrt!(-z)) else sqrt!(z) end else if z.imag < 0 || (z.imag == 0 && z.imag.to_s[0] == '-') sqrt(z.conjugate).conjugate else r = z.abs x = z.real Complex(sqrt!((r + x) / 2.0), sqrt!((r - x) / 2.0)) end end rescue NoMethodError handle_no_method_error end end ## # returns the principal value of the cube root of +z+ # # CMath.cbrt(1 + 4i) #=> (1.449461632813119+0.6858152562177092i) def cbrt(z) z ** (1.0/3) end ## # returns the sine of +z+, where +z+ is given in radians # # CMath.sin(1 + 1i) #=> (1.2984575814159773+0.6349639147847361i) def sin(z) begin if z.real? sin!(z) else Complex(sin!(z.real) * cosh!(z.imag), cos!(z.real) * sinh!(z.imag)) end rescue NoMethodError handle_no_method_error end end ## # returns the cosine of +z+, where +z+ is given in radians # # CMath.cos(1 + 1i) #=> (0.8337300251311491-0.9888977057628651i) def cos(z) begin if z.real? cos!(z) else Complex(cos!(z.real) * cosh!(z.imag), -sin!(z.real) * sinh!(z.imag)) end rescue NoMethodError handle_no_method_error end end ## # returns the tangent of +z+, where +z+ is given in radians # # CMath.tan(1 + 1i) #=> (0.27175258531951174+1.0839233273386943i) def tan(z) begin if z.real? tan!(z) else sin(z) / cos(z) end rescue NoMethodError handle_no_method_error end end ## # returns the hyperbolic sine of +z+, where +z+ is given in radians # # CMath.sinh(1 + 1i) #=> (0.6349639147847361+1.2984575814159773i) def sinh(z) begin if z.real? sinh!(z) else Complex(sinh!(z.real) * cos!(z.imag), cosh!(z.real) * sin!(z.imag)) end rescue NoMethodError handle_no_method_error end end ## # returns the hyperbolic cosine of +z+, where +z+ is given in radians # # CMath.cosh(1 + 1i) #=> (0.8337300251311491+0.9888977057628651i) def cosh(z) begin if z.real? cosh!(z) else Complex(cosh!(z.real) * cos!(z.imag), sinh!(z.real) * sin!(z.imag)) end rescue NoMethodError handle_no_method_error end end ## # returns the hyperbolic tangent of +z+, where +z+ is given in radians # # CMath.tanh(1 + 1i) #=> (1.0839233273386943+0.27175258531951174i) def tanh(z) begin if z.real? tanh!(z) else sinh(z) / cosh(z) end rescue NoMethodError handle_no_method_error end end ## # returns the arc sine of +z+ # # CMath.asin(1 + 1i) #=> (0.6662394324925153+1.0612750619050355i) def asin(z) begin if z.real? and z >= -1 and z <= 1 asin!(z) else (-1.0).i * log(1.0.i * z + sqrt(1.0 - z * z)) end rescue NoMethodError handle_no_method_error end end ## # returns the arc cosine of +z+ # # CMath.acos(1 + 1i) #=> (0.9045568943023813-1.0612750619050357i) def acos(z) begin if z.real? and z >= -1 and z <= 1 acos!(z) else (-1.0).i * log(z + 1.0.i * sqrt(1.0 - z * z)) end rescue NoMethodError handle_no_method_error end end ## # returns the arc tangent of +z+ # # CMath.atan(1 + 1i) #=> (1.0172219678978514+0.4023594781085251i) def atan(z) begin if z.real? atan!(z) else 1.0.i * log((1.0.i + z) / (1.0.i - z)) / 2.0 end rescue NoMethodError handle_no_method_error end end ## # returns the arc tangent of +y+ divided by +x+ using the signs of +y+ and # +x+ to determine the quadrant # # CMath.atan2(1 + 1i, 0) #=> (1.5707963267948966+0.0i) def atan2(y,x) begin if y.real? and x.real? atan2!(y,x) else (-1.0).i * log((x + 1.0.i * y) / sqrt(x * x + y * y)) end rescue NoMethodError handle_no_method_error end end ## # returns the inverse hyperbolic sine of +z+ # # CMath.asinh(1 + 1i) #=> (1.0612750619050357+0.6662394324925153i) def asinh(z) begin if z.real? asinh!(z) else log(z + sqrt(1.0 + z * z)) end rescue NoMethodError handle_no_method_error end end ## # returns the inverse hyperbolic cosine of +z+ # # CMath.acosh(1 + 1i) #=> (1.0612750619050357+0.9045568943023813i) def acosh(z) begin if z.real? and z >= 1 acosh!(z) else log(z + sqrt(z * z - 1.0)) end rescue NoMethodError handle_no_method_error end end ## # returns the inverse hyperbolic tangent of +z+ # # CMath.atanh(1 + 1i) #=> (0.4023594781085251+1.0172219678978514i) def atanh(z) begin if z.real? and z >= -1 and z <= 1 atanh!(z) else log((1.0 + z) / (1.0 - z)) / 2.0 end rescue NoMethodError handle_no_method_error end end module_function :exp! module_function :exp module_function :log! module_function :log module_function :log2! module_function :log2 module_function :log10! module_function :log10 module_function :sqrt! module_function :sqrt module_function :cbrt! module_function :cbrt module_function :sin! module_function :sin module_function :cos! module_function :cos module_function :tan! module_function :tan module_function :sinh! module_function :sinh module_function :cosh! module_function :cosh module_function :tanh! module_function :tanh module_function :asin! module_function :asin module_function :acos! module_function :acos module_function :atan! module_function :atan module_function :atan2! module_function :atan2 module_function :asinh! module_function :asinh module_function :acosh! module_function :acosh module_function :atanh! module_function :atanh module_function :frexp module_function :ldexp module_function :hypot module_function :erf module_function :erfc module_function :gamma module_function :lgamma private def handle_no_method_error # :nodoc: if $!.name == :real? raise TypeError, "Numeric Number required" else raise end end module_function :handle_no_method_error end PK!,ܽܽ2.2.0/fileutils.rbnu[# # = fileutils.rb # # Copyright (c) 2000-2007 Minero Aoki # # This program is free software. # You can distribute/modify this program under the same terms of ruby. # # == module FileUtils # # Namespace for several file utility methods for copying, moving, removing, etc. # # === Module Functions # # require 'fileutils' # # FileUtils.cd(dir, options) # FileUtils.cd(dir, options) {|dir| .... } # FileUtils.pwd() # FileUtils.mkdir(dir, options) # FileUtils.mkdir(list, options) # FileUtils.mkdir_p(dir, options) # FileUtils.mkdir_p(list, options) # FileUtils.rmdir(dir, options) # FileUtils.rmdir(list, options) # FileUtils.ln(old, new, options) # FileUtils.ln(list, destdir, options) # FileUtils.ln_s(old, new, options) # FileUtils.ln_s(list, destdir, options) # FileUtils.ln_sf(src, dest, options) # FileUtils.cp(src, dest, options) # FileUtils.cp(list, dir, options) # FileUtils.cp_r(src, dest, options) # FileUtils.cp_r(list, dir, options) # FileUtils.mv(src, dest, options) # FileUtils.mv(list, dir, options) # FileUtils.rm(list, options) # FileUtils.rm_r(list, options) # FileUtils.rm_rf(list, options) # FileUtils.install(src, dest, mode = , options) # FileUtils.chmod(mode, list, options) # FileUtils.chmod_R(mode, list, options) # FileUtils.chown(user, group, list, options) # FileUtils.chown_R(user, group, list, options) # FileUtils.touch(list, options) # # The options parameter is a hash of options, taken from the list # :force, :noop, :preserve, and :verbose. # :noop means that no changes are made. The other two are obvious. # Each method documents the options that it honours. # # All methods that have the concept of a "source" file or directory can take # either one file or a list of files in that argument. See the method # documentation for examples. # # There are some `low level' methods, which do not accept any option: # # FileUtils.copy_entry(src, dest, preserve = false, dereference = false) # FileUtils.copy_file(src, dest, preserve = false, dereference = true) # FileUtils.copy_stream(srcstream, deststream) # FileUtils.remove_entry(path, force = false) # FileUtils.remove_entry_secure(path, force = false) # FileUtils.remove_file(path, force = false) # FileUtils.compare_file(path_a, path_b) # FileUtils.compare_stream(stream_a, stream_b) # FileUtils.uptodate?(file, cmp_list) # # == module FileUtils::Verbose # # This module has all methods of FileUtils module, but it outputs messages # before acting. This equates to passing the :verbose flag to methods # in FileUtils. # # == module FileUtils::NoWrite # # This module has all methods of FileUtils module, but never changes # files/directories. This equates to passing the :noop flag to methods # in FileUtils. # # == module FileUtils::DryRun # # This module has all methods of FileUtils module, but never changes # files/directories. This equates to passing the :noop and # :verbose flags to methods in FileUtils. # module FileUtils def self.private_module_function(name) #:nodoc: module_function name private_class_method name end # This hash table holds command options. OPT_TABLE = {} #:nodoc: internal use only # # Options: (none) # # Returns the name of the current directory. # def pwd Dir.pwd end module_function :pwd alias getwd pwd module_function :getwd # # Options: verbose # # Changes the current directory to the directory +dir+. # # If this method is called with block, resumes to the old # working directory after the block execution finished. # # FileUtils.cd('/', :verbose => true) # chdir and report it # # FileUtils.cd('/') do # chdir # [...] # do something # end # return to original directory # def cd(dir, options = {}, &block) # :yield: dir fu_check_options options, OPT_TABLE['cd'] fu_output_message "cd #{dir}" if options[:verbose] Dir.chdir(dir, &block) fu_output_message 'cd -' if options[:verbose] and block end module_function :cd alias chdir cd module_function :chdir OPT_TABLE['cd'] = OPT_TABLE['chdir'] = [:verbose] # # Options: (none) # # Returns true if +new+ is newer than all +old_list+. # Non-existent files are older than any file. # # FileUtils.uptodate?('hello.o', %w(hello.c hello.h)) or \ # system 'make hello.o' # def uptodate?(new, old_list) return false unless File.exist?(new) new_time = File.mtime(new) old_list.each do |old| if File.exist?(old) return false unless new_time > File.mtime(old) end end true end module_function :uptodate? def remove_tailing_slash(dir) dir == '/' ? dir : dir.chomp(?/) end private_module_function :remove_tailing_slash # # Options: mode noop verbose # # Creates one or more directories. # # FileUtils.mkdir 'test' # FileUtils.mkdir %w( tmp data ) # FileUtils.mkdir 'notexist', :noop => true # Does not really create. # FileUtils.mkdir 'tmp', :mode => 0700 # def mkdir(list, options = {}) fu_check_options options, OPT_TABLE['mkdir'] list = fu_list(list) fu_output_message "mkdir #{options[:mode] ? ('-m %03o ' % options[:mode]) : ''}#{list.join ' '}" if options[:verbose] return if options[:noop] list.each do |dir| fu_mkdir dir, options[:mode] end end module_function :mkdir OPT_TABLE['mkdir'] = [:mode, :noop, :verbose] # # Options: mode noop verbose # # Creates a directory and all its parent directories. # For example, # # FileUtils.mkdir_p '/usr/local/lib/ruby' # # causes to make following directories, if it does not exist. # * /usr # * /usr/local # * /usr/local/lib # * /usr/local/lib/ruby # # You can pass several directories at a time in a list. # def mkdir_p(list, options = {}) fu_check_options options, OPT_TABLE['mkdir_p'] list = fu_list(list) fu_output_message "mkdir -p #{options[:mode] ? ('-m %03o ' % options[:mode]) : ''}#{list.join ' '}" if options[:verbose] return *list if options[:noop] list.map {|path| remove_tailing_slash(path)}.each do |path| # optimize for the most common case begin fu_mkdir path, options[:mode] next rescue SystemCallError next if File.directory?(path) end stack = [] until path == stack.last # dirname("/")=="/", dirname("C:/")=="C:/" stack.push path path = File.dirname(path) end stack.pop # root directory should exist stack.reverse_each do |dir| begin fu_mkdir dir, options[:mode] rescue SystemCallError raise unless File.directory?(dir) end end end return *list end module_function :mkdir_p alias mkpath mkdir_p alias makedirs mkdir_p module_function :mkpath module_function :makedirs OPT_TABLE['mkdir_p'] = OPT_TABLE['mkpath'] = OPT_TABLE['makedirs'] = [:mode, :noop, :verbose] def fu_mkdir(path, mode) #:nodoc: path = remove_tailing_slash(path) if mode Dir.mkdir path, mode File.chmod mode, path else Dir.mkdir path end end private_module_function :fu_mkdir # # Options: parents, noop, verbose # # Removes one or more directories. # # FileUtils.rmdir 'somedir' # FileUtils.rmdir %w(somedir anydir otherdir) # # Does not really remove directory; outputs message. # FileUtils.rmdir 'somedir', :verbose => true, :noop => true # def rmdir(list, options = {}) fu_check_options options, OPT_TABLE['rmdir'] list = fu_list(list) parents = options[:parents] fu_output_message "rmdir #{parents ? '-p ' : ''}#{list.join ' '}" if options[:verbose] return if options[:noop] list.each do |dir| begin Dir.rmdir(dir = remove_tailing_slash(dir)) if parents until (parent = File.dirname(dir)) == '.' or parent == dir dir = parent Dir.rmdir(dir) end end rescue Errno::ENOTEMPTY, Errno::EEXIST, Errno::ENOENT end end end module_function :rmdir OPT_TABLE['rmdir'] = [:parents, :noop, :verbose] # # Options: force noop verbose # # ln(old, new, options = {}) # # Creates a hard link +new+ which points to +old+. # If +new+ already exists and it is a directory, creates a link +new/old+. # If +new+ already exists and it is not a directory, raises Errno::EEXIST. # But if :force option is set, overwrite +new+. # # FileUtils.ln 'gcc', 'cc', :verbose => true # FileUtils.ln '/usr/bin/emacs21', '/usr/bin/emacs' # # ln(list, destdir, options = {}) # # Creates several hard links in a directory, with each one pointing to the # item in +list+. If +destdir+ is not a directory, raises Errno::ENOTDIR. # # include FileUtils # cd '/sbin' # FileUtils.ln %w(cp mv mkdir), '/bin' # Now /sbin/cp and /bin/cp are linked. # def ln(src, dest, options = {}) fu_check_options options, OPT_TABLE['ln'] fu_output_message "ln#{options[:force] ? ' -f' : ''} #{[src,dest].flatten.join ' '}" if options[:verbose] return if options[:noop] fu_each_src_dest0(src, dest) do |s,d| remove_file d, true if options[:force] File.link s, d end end module_function :ln alias link ln module_function :link OPT_TABLE['ln'] = OPT_TABLE['link'] = [:force, :noop, :verbose] # # Options: force noop verbose # # ln_s(old, new, options = {}) # # Creates a symbolic link +new+ which points to +old+. If +new+ already # exists and it is a directory, creates a symbolic link +new/old+. If +new+ # already exists and it is not a directory, raises Errno::EEXIST. But if # :force option is set, overwrite +new+. # # FileUtils.ln_s '/usr/bin/ruby', '/usr/local/bin/ruby' # FileUtils.ln_s 'verylongsourcefilename.c', 'c', :force => true # # ln_s(list, destdir, options = {}) # # Creates several symbolic links in a directory, with each one pointing to the # item in +list+. If +destdir+ is not a directory, raises Errno::ENOTDIR. # # If +destdir+ is not a directory, raises Errno::ENOTDIR. # # FileUtils.ln_s Dir.glob('bin/*.rb'), '/home/aamine/bin' # def ln_s(src, dest, options = {}) fu_check_options options, OPT_TABLE['ln_s'] fu_output_message "ln -s#{options[:force] ? 'f' : ''} #{[src,dest].flatten.join ' '}" if options[:verbose] return if options[:noop] fu_each_src_dest0(src, dest) do |s,d| remove_file d, true if options[:force] File.symlink s, d end end module_function :ln_s alias symlink ln_s module_function :symlink OPT_TABLE['ln_s'] = OPT_TABLE['symlink'] = [:force, :noop, :verbose] # # Options: noop verbose # # Same as # #ln_s(src, dest, :force => true) # def ln_sf(src, dest, options = {}) fu_check_options options, OPT_TABLE['ln_sf'] options = options.dup options[:force] = true ln_s src, dest, options end module_function :ln_sf OPT_TABLE['ln_sf'] = [:noop, :verbose] # # Options: preserve noop verbose # # Copies a file content +src+ to +dest+. If +dest+ is a directory, # copies +src+ to +dest/src+. # # If +src+ is a list of files, then +dest+ must be a directory. # # FileUtils.cp 'eval.c', 'eval.c.org' # FileUtils.cp %w(cgi.rb complex.rb date.rb), '/usr/lib/ruby/1.6' # FileUtils.cp %w(cgi.rb complex.rb date.rb), '/usr/lib/ruby/1.6', :verbose => true # FileUtils.cp 'symlink', 'dest' # copy content, "dest" is not a symlink # def cp(src, dest, options = {}) fu_check_options options, OPT_TABLE['cp'] fu_output_message "cp#{options[:preserve] ? ' -p' : ''} #{[src,dest].flatten.join ' '}" if options[:verbose] return if options[:noop] fu_each_src_dest(src, dest) do |s, d| copy_file s, d, options[:preserve] end end module_function :cp alias copy cp module_function :copy OPT_TABLE['cp'] = OPT_TABLE['copy'] = [:preserve, :noop, :verbose] # # Options: preserve noop verbose dereference_root remove_destination # # Copies +src+ to +dest+. If +src+ is a directory, this method copies # all its contents recursively. If +dest+ is a directory, copies # +src+ to +dest/src+. # # +src+ can be a list of files. # # # Installing Ruby library "mylib" under the site_ruby # FileUtils.rm_r site_ruby + '/mylib', :force # FileUtils.cp_r 'lib/', site_ruby + '/mylib' # # # Examples of copying several files to target directory. # FileUtils.cp_r %w(mail.rb field.rb debug/), site_ruby + '/tmail' # FileUtils.cp_r Dir.glob('*.rb'), '/home/aamine/lib/ruby', :noop => true, :verbose => true # # # If you want to copy all contents of a directory instead of the # # directory itself, c.f. src/x -> dest/x, src/y -> dest/y, # # use following code. # FileUtils.cp_r 'src/.', 'dest' # cp_r('src', 'dest') makes dest/src, # # but this doesn't. # def cp_r(src, dest, options = {}) fu_check_options options, OPT_TABLE['cp_r'] fu_output_message "cp -r#{options[:preserve] ? 'p' : ''}#{options[:remove_destination] ? ' --remove-destination' : ''} #{[src,dest].flatten.join ' '}" if options[:verbose] return if options[:noop] options = options.dup options[:dereference_root] = true unless options.key?(:dereference_root) fu_each_src_dest(src, dest) do |s, d| copy_entry s, d, options[:preserve], options[:dereference_root], options[:remove_destination] end end module_function :cp_r OPT_TABLE['cp_r'] = [:preserve, :noop, :verbose, :dereference_root, :remove_destination] # # Copies a file system entry +src+ to +dest+. # If +src+ is a directory, this method copies its contents recursively. # This method preserves file types, c.f. symlink, directory... # (FIFO, device files and etc. are not supported yet) # # Both of +src+ and +dest+ must be a path name. # +src+ must exist, +dest+ must not exist. # # If +preserve+ is true, this method preserves owner, group, and # modified time. Permissions are copied regardless +preserve+. # # If +dereference_root+ is true, this method dereference tree root. # # If +remove_destination+ is true, this method removes each destination file before copy. # def copy_entry(src, dest, preserve = false, dereference_root = false, remove_destination = false) Entry_.new(src, nil, dereference_root).wrap_traverse(proc do |ent| destent = Entry_.new(dest, ent.rel, false) File.unlink destent.path if remove_destination && File.file?(destent.path) ent.copy destent.path end, proc do |ent| destent = Entry_.new(dest, ent.rel, false) ent.copy_metadata destent.path if preserve end) end module_function :copy_entry # # Copies file contents of +src+ to +dest+. # Both of +src+ and +dest+ must be a path name. # def copy_file(src, dest, preserve = false, dereference = true) ent = Entry_.new(src, nil, dereference) ent.copy_file dest ent.copy_metadata dest if preserve end module_function :copy_file # # Copies stream +src+ to +dest+. # +src+ must respond to #read(n) and # +dest+ must respond to #write(str). # def copy_stream(src, dest) IO.copy_stream(src, dest) end module_function :copy_stream # # Options: force noop verbose # # Moves file(s) +src+ to +dest+. If +file+ and +dest+ exist on the different # disk partition, the file is copied then the original file is removed. # # FileUtils.mv 'badname.rb', 'goodname.rb' # FileUtils.mv 'stuff.rb', '/notexist/lib/ruby', :force => true # no error # # FileUtils.mv %w(junk.txt dust.txt), '/home/aamine/.trash/' # FileUtils.mv Dir.glob('test*.rb'), 'test', :noop => true, :verbose => true # def mv(src, dest, options = {}) fu_check_options options, OPT_TABLE['mv'] fu_output_message "mv#{options[:force] ? ' -f' : ''} #{[src,dest].flatten.join ' '}" if options[:verbose] return if options[:noop] fu_each_src_dest(src, dest) do |s, d| destent = Entry_.new(d, nil, true) begin if destent.exist? if destent.directory? raise Errno::EEXIST, d else destent.remove_file if rename_cannot_overwrite_file? end end begin File.rename s, d rescue Errno::EXDEV copy_entry s, d, true if options[:secure] remove_entry_secure s, options[:force] else remove_entry s, options[:force] end end rescue SystemCallError raise unless options[:force] end end end module_function :mv alias move mv module_function :move OPT_TABLE['mv'] = OPT_TABLE['move'] = [:force, :noop, :verbose, :secure] def rename_cannot_overwrite_file? #:nodoc: /cygwin|mswin|mingw|bccwin|emx/ =~ RUBY_PLATFORM end private_module_function :rename_cannot_overwrite_file? # # Options: force noop verbose # # Remove file(s) specified in +list+. This method cannot remove directories. # All StandardErrors are ignored when the :force option is set. # # FileUtils.rm %w( junk.txt dust.txt ) # FileUtils.rm Dir.glob('*.so') # FileUtils.rm 'NotExistFile', :force => true # never raises exception # def rm(list, options = {}) fu_check_options options, OPT_TABLE['rm'] list = fu_list(list) fu_output_message "rm#{options[:force] ? ' -f' : ''} #{list.join ' '}" if options[:verbose] return if options[:noop] list.each do |path| remove_file path, options[:force] end end module_function :rm alias remove rm module_function :remove OPT_TABLE['rm'] = OPT_TABLE['remove'] = [:force, :noop, :verbose] # # Options: noop verbose # # Equivalent to # # #rm(list, :force => true) # def rm_f(list, options = {}) fu_check_options options, OPT_TABLE['rm_f'] options = options.dup options[:force] = true rm list, options end module_function :rm_f alias safe_unlink rm_f module_function :safe_unlink OPT_TABLE['rm_f'] = OPT_TABLE['safe_unlink'] = [:noop, :verbose] # # Options: force noop verbose secure # # remove files +list+[0] +list+[1]... If +list+[n] is a directory, # removes its all contents recursively. This method ignores # StandardError when :force option is set. # # FileUtils.rm_r Dir.glob('/tmp/*') # FileUtils.rm_r '/', :force => true # :-) # # WARNING: This method causes local vulnerability # if one of parent directories or removing directory tree are world # writable (including /tmp, whose permission is 1777), and the current # process has strong privilege such as Unix super user (root), and the # system has symbolic link. For secure removing, read the documentation # of #remove_entry_secure carefully, and set :secure option to true. # Default is :secure=>false. # # NOTE: This method calls #remove_entry_secure if :secure option is set. # See also #remove_entry_secure. # def rm_r(list, options = {}) fu_check_options options, OPT_TABLE['rm_r'] # options[:secure] = true unless options.key?(:secure) list = fu_list(list) fu_output_message "rm -r#{options[:force] ? 'f' : ''} #{list.join ' '}" if options[:verbose] return if options[:noop] list.each do |path| if options[:secure] remove_entry_secure path, options[:force] else remove_entry path, options[:force] end end end module_function :rm_r OPT_TABLE['rm_r'] = [:force, :noop, :verbose, :secure] # # Options: noop verbose secure # # Equivalent to # # #rm_r(list, :force => true) # # WARNING: This method causes local vulnerability. # Read the documentation of #rm_r first. # def rm_rf(list, options = {}) fu_check_options options, OPT_TABLE['rm_rf'] options = options.dup options[:force] = true rm_r list, options end module_function :rm_rf alias rmtree rm_rf module_function :rmtree OPT_TABLE['rm_rf'] = OPT_TABLE['rmtree'] = [:noop, :verbose, :secure] # # This method removes a file system entry +path+. +path+ shall be a # regular file, a directory, or something. If +path+ is a directory, # remove it recursively. This method is required to avoid TOCTTOU # (time-of-check-to-time-of-use) local security vulnerability of #rm_r. # #rm_r causes security hole when: # # * Parent directory is world writable (including /tmp). # * Removing directory tree includes world writable directory. # * The system has symbolic link. # # To avoid this security hole, this method applies special preprocess. # If +path+ is a directory, this method chown(2) and chmod(2) all # removing directories. This requires the current process is the # owner of the removing whole directory tree, or is the super user (root). # # WARNING: You must ensure that *ALL* parent directories cannot be # moved by other untrusted users. For example, parent directories # should not be owned by untrusted users, and should not be world # writable except when the sticky bit set. # # WARNING: Only the owner of the removing directory tree, or Unix super # user (root) should invoke this method. Otherwise this method does not # work. # # For details of this security vulnerability, see Perl's case: # # http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2005-0448 # http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2004-0452 # # For fileutils.rb, this vulnerability is reported in [ruby-dev:26100]. # def remove_entry_secure(path, force = false) unless fu_have_symlink? remove_entry path, force return end fullpath = File.expand_path(path) st = File.lstat(fullpath) unless st.directory? File.unlink fullpath return end # is a directory. parent_st = File.stat(File.dirname(fullpath)) unless parent_st.world_writable? remove_entry path, force return end unless parent_st.sticky? raise ArgumentError, "parent directory is world writable, FileUtils#remove_entry_secure does not work; abort: #{path.inspect} (parent directory mode #{'%o' % parent_st.mode})" end # freeze tree root euid = Process.euid File.open(fullpath + '/.') {|f| unless fu_stat_identical_entry?(st, f.stat) # symlink (TOC-to-TOU attack?) File.unlink fullpath return end f.chown euid, -1 f.chmod 0700 unless fu_stat_identical_entry?(st, File.lstat(fullpath)) # TOC-to-TOU attack? File.unlink fullpath return end } # ---- tree root is frozen ---- root = Entry_.new(path) root.preorder_traverse do |ent| if ent.directory? ent.chown euid, -1 ent.chmod 0700 end end root.postorder_traverse do |ent| begin ent.remove rescue raise unless force end end rescue raise unless force end module_function :remove_entry_secure def fu_have_symlink? #:nodoc: File.symlink nil, nil rescue NotImplementedError return false rescue TypeError return true end private_module_function :fu_have_symlink? def fu_stat_identical_entry?(a, b) #:nodoc: a.dev == b.dev and a.ino == b.ino end private_module_function :fu_stat_identical_entry? # # This method removes a file system entry +path+. # +path+ might be a regular file, a directory, or something. # If +path+ is a directory, remove it recursively. # # See also #remove_entry_secure. # def remove_entry(path, force = false) Entry_.new(path).postorder_traverse do |ent| begin ent.remove rescue raise unless force end end rescue raise unless force end module_function :remove_entry # # Removes a file +path+. # This method ignores StandardError if +force+ is true. # def remove_file(path, force = false) Entry_.new(path).remove_file rescue raise unless force end module_function :remove_file # # Removes a directory +dir+ and its contents recursively. # This method ignores StandardError if +force+ is true. # def remove_dir(path, force = false) remove_entry path, force # FIXME?? check if it is a directory end module_function :remove_dir # # Returns true if the contents of a file A and a file B are identical. # # FileUtils.compare_file('somefile', 'somefile') #=> true # FileUtils.compare_file('/bin/cp', '/bin/mv') #=> maybe false # def compare_file(a, b) return false unless File.size(a) == File.size(b) File.open(a, 'rb') {|fa| File.open(b, 'rb') {|fb| return compare_stream(fa, fb) } } end module_function :compare_file alias identical? compare_file alias cmp compare_file module_function :identical? module_function :cmp # # Returns true if the contents of a stream +a+ and +b+ are identical. # def compare_stream(a, b) bsize = fu_stream_blksize(a, b) sa = "" sb = "" begin a.read(bsize, sa) b.read(bsize, sb) return true if sa.empty? && sb.empty? end while sa == sb false end module_function :compare_stream # # Options: mode preserve noop verbose # # If +src+ is not same as +dest+, copies it and changes the permission # mode to +mode+. If +dest+ is a directory, destination is +dest+/+src+. # This method removes destination before copy. # # FileUtils.install 'ruby', '/usr/local/bin/ruby', :mode => 0755, :verbose => true # FileUtils.install 'lib.rb', '/usr/local/lib/ruby/site_ruby', :verbose => true # def install(src, dest, options = {}) fu_check_options options, OPT_TABLE['install'] fu_output_message "install -c#{options[:preserve] && ' -p'}#{options[:mode] ? (' -m 0%o' % options[:mode]) : ''} #{[src,dest].flatten.join ' '}" if options[:verbose] return if options[:noop] fu_each_src_dest(src, dest) do |s, d| st = File.stat(s) unless File.exist?(d) and compare_file(s, d) remove_file d, true copy_file s, d File.utime st.atime, st.mtime, d if options[:preserve] File.chmod options[:mode], d if options[:mode] end end end module_function :install OPT_TABLE['install'] = [:mode, :preserve, :noop, :verbose] def user_mask(target) #:nodoc: target.each_char.inject(0) do |mask, chr| case chr when "u" mask | 04700 when "g" mask | 02070 when "o" mask | 01007 when "a" mask | 07777 else raise ArgumentError, "invalid `who' symbol in file mode: #{chr}" end end end private_module_function :user_mask def apply_mask(mode, user_mask, op, mode_mask) case op when '=' (mode & ~user_mask) | (user_mask & mode_mask) when '+' mode | (user_mask & mode_mask) when '-' mode & ~(user_mask & mode_mask) end end private_module_function :apply_mask def symbolic_modes_to_i(mode_sym, path) #:nodoc: mode_sym.split(/,/).inject(File.stat(path).mode & 07777) do |current_mode, clause| target, *actions = clause.split(/([=+-])/) raise ArgumentError, "invalid file mode: #{mode_sym}" if actions.empty? target = 'a' if target.empty? user_mask = user_mask(target) actions.each_slice(2) do |op, perm| need_apply = op == '=' mode_mask = (perm || '').each_char.inject(0) do |mask, chr| case chr when "r" mask | 0444 when "w" mask | 0222 when "x" mask | 0111 when "X" if FileTest.directory? path mask | 0111 else mask end when "s" mask | 06000 when "t" mask | 01000 when "u", "g", "o" if mask.nonzero? current_mode = apply_mask(current_mode, user_mask, op, mask) end need_apply = false copy_mask = user_mask(chr) (current_mode & copy_mask) / (copy_mask & 0111) * (user_mask & 0111) else raise ArgumentError, "invalid `perm' symbol in file mode: #{chr}" end end if mode_mask.nonzero? || need_apply current_mode = apply_mask(current_mode, user_mask, op, mode_mask) end end current_mode end end private_module_function :symbolic_modes_to_i def fu_mode(mode, path) #:nodoc: mode.is_a?(String) ? symbolic_modes_to_i(mode, path) : mode end private_module_function :fu_mode def mode_to_s(mode) #:nodoc: mode.is_a?(String) ? mode : "%o" % mode end private_module_function :mode_to_s # # Options: noop verbose # # Changes permission bits on the named files (in +list+) to the bit pattern # represented by +mode+. # # +mode+ is the symbolic and absolute mode can be used. # # Absolute mode is # FileUtils.chmod 0755, 'somecommand' # FileUtils.chmod 0644, %w(my.rb your.rb his.rb her.rb) # FileUtils.chmod 0755, '/usr/bin/ruby', :verbose => true # # Symbolic mode is # FileUtils.chmod "u=wrx,go=rx", 'somecommand' # FileUtils.chmod "u=wr,go=rr", %w(my.rb your.rb his.rb her.rb) # FileUtils.chmod "u=wrx,go=rx", '/usr/bin/ruby', :verbose => true # # "a" :: is user, group, other mask. # "u" :: is user's mask. # "g" :: is group's mask. # "o" :: is other's mask. # "w" :: is write permission. # "r" :: is read permission. # "x" :: is execute permission. # "X" :: # is execute permission for directories only, must be used in conjunction with "+" # "s" :: is uid, gid. # "t" :: is sticky bit. # "+" :: is added to a class given the specified mode. # "-" :: Is removed from a given class given mode. # "=" :: Is the exact nature of the class will be given a specified mode. def chmod(mode, list, options = {}) fu_check_options options, OPT_TABLE['chmod'] list = fu_list(list) fu_output_message sprintf('chmod %s %s', mode_to_s(mode), list.join(' ')) if options[:verbose] return if options[:noop] list.each do |path| Entry_.new(path).chmod(fu_mode(mode, path)) end end module_function :chmod OPT_TABLE['chmod'] = [:noop, :verbose] # # Options: noop verbose force # # Changes permission bits on the named files (in +list+) # to the bit pattern represented by +mode+. # # FileUtils.chmod_R 0700, "/tmp/app.#{$$}" # FileUtils.chmod_R "u=wrx", "/tmp/app.#{$$}" # def chmod_R(mode, list, options = {}) fu_check_options options, OPT_TABLE['chmod_R'] list = fu_list(list) fu_output_message sprintf('chmod -R%s %s %s', (options[:force] ? 'f' : ''), mode_to_s(mode), list.join(' ')) if options[:verbose] return if options[:noop] list.each do |root| Entry_.new(root).traverse do |ent| begin ent.chmod(fu_mode(mode, ent.path)) rescue raise unless options[:force] end end end end module_function :chmod_R OPT_TABLE['chmod_R'] = [:noop, :verbose, :force] # # Options: noop verbose # # Changes owner and group on the named files (in +list+) # to the user +user+ and the group +group+. +user+ and +group+ # may be an ID (Integer/String) or a name (String). # If +user+ or +group+ is nil, this method does not change # the attribute. # # FileUtils.chown 'root', 'staff', '/usr/local/bin/ruby' # FileUtils.chown nil, 'bin', Dir.glob('/usr/bin/*'), :verbose => true # def chown(user, group, list, options = {}) fu_check_options options, OPT_TABLE['chown'] list = fu_list(list) fu_output_message sprintf('chown %s %s', (group ? "#{user}:#{group}" : user || ':'), list.join(' ')) if options[:verbose] return if options[:noop] uid = fu_get_uid(user) gid = fu_get_gid(group) list.each do |path| Entry_.new(path).chown uid, gid end end module_function :chown OPT_TABLE['chown'] = [:noop, :verbose] # # Options: noop verbose force # # Changes owner and group on the named files (in +list+) # to the user +user+ and the group +group+ recursively. # +user+ and +group+ may be an ID (Integer/String) or # a name (String). If +user+ or +group+ is nil, this # method does not change the attribute. # # FileUtils.chown_R 'www', 'www', '/var/www/htdocs' # FileUtils.chown_R 'cvs', 'cvs', '/var/cvs', :verbose => true # def chown_R(user, group, list, options = {}) fu_check_options options, OPT_TABLE['chown_R'] list = fu_list(list) fu_output_message sprintf('chown -R%s %s %s', (options[:force] ? 'f' : ''), (group ? "#{user}:#{group}" : user || ':'), list.join(' ')) if options[:verbose] return if options[:noop] uid = fu_get_uid(user) gid = fu_get_gid(group) list.each do |root| Entry_.new(root).traverse do |ent| begin ent.chown uid, gid rescue raise unless options[:force] end end end end module_function :chown_R OPT_TABLE['chown_R'] = [:noop, :verbose, :force] begin require 'etc' rescue LoadError # rescue LoadError for miniruby end def fu_get_uid(user) #:nodoc: return nil unless user case user when Integer user when /\A\d+\z/ user.to_i else Etc.getpwnam(user) ? Etc.getpwnam(user).uid : nil end end private_module_function :fu_get_uid def fu_get_gid(group) #:nodoc: return nil unless group case group when Integer group when /\A\d+\z/ group.to_i else Etc.getgrnam(group) ? Etc.getgrnam(group).gid : nil end end private_module_function :fu_get_gid # # Options: noop verbose mtime nocreate # # Updates modification time (mtime) and access time (atime) of file(s) in # +list+. Files are created if they don't exist. # # FileUtils.touch 'timestamp' # FileUtils.touch Dir.glob('*.c'); system 'make' # def touch(list, options = {}) fu_check_options options, OPT_TABLE['touch'] list = fu_list(list) nocreate = options[:nocreate] t = options[:mtime] if options[:verbose] fu_output_message "touch #{nocreate ? '-c ' : ''}#{t ? t.strftime('-t %Y%m%d%H%M.%S ') : ''}#{list.join ' '}" end return if options[:noop] list.each do |path| created = nocreate begin File.utime(t, t, path) rescue Errno::ENOENT raise if created File.open(path, 'a') { ; } created = true retry if t end end end module_function :touch OPT_TABLE['touch'] = [:noop, :verbose, :mtime, :nocreate] private module StreamUtils_ private def fu_windows? /mswin|mingw|bccwin|emx/ =~ RUBY_PLATFORM end def fu_copy_stream0(src, dest, blksize = nil) #:nodoc: IO.copy_stream(src, dest) end def fu_stream_blksize(*streams) streams.each do |s| next unless s.respond_to?(:stat) size = fu_blksize(s.stat) return size if size end fu_default_blksize() end def fu_blksize(st) s = st.blksize return nil unless s return nil if s == 0 s end def fu_default_blksize 1024 end end include StreamUtils_ extend StreamUtils_ class Entry_ #:nodoc: internal use only include StreamUtils_ def initialize(a, b = nil, deref = false) @prefix = @rel = @path = nil if b @prefix = a @rel = b else @path = a end @deref = deref @stat = nil @lstat = nil end def inspect "\#<#{self.class} #{path()}>" end def path if @path File.path(@path) else join(@prefix, @rel) end end def prefix @prefix || @path end def rel @rel end def dereference? @deref end def exist? begin lstat true rescue Errno::ENOENT false end end def file? s = lstat! s and s.file? end def directory? s = lstat! s and s.directory? end def symlink? s = lstat! s and s.symlink? end def chardev? s = lstat! s and s.chardev? end def blockdev? s = lstat! s and s.blockdev? end def socket? s = lstat! s and s.socket? end def pipe? s = lstat! s and s.pipe? end S_IF_DOOR = 0xD000 def door? s = lstat! s and (s.mode & 0xF000 == S_IF_DOOR) end def entries opts = {} opts[:encoding] = ::Encoding::UTF_8 if fu_windows? Dir.entries(path(), opts)\ .reject {|n| n == '.' or n == '..' }\ .map {|n| Entry_.new(prefix(), join(rel(), n.untaint)) } end def stat return @stat if @stat if lstat() and lstat().symlink? @stat = File.stat(path()) else @stat = lstat() end @stat end def stat! return @stat if @stat if lstat! and lstat!.symlink? @stat = File.stat(path()) else @stat = lstat! end @stat rescue SystemCallError nil end def lstat if dereference? @lstat ||= File.stat(path()) else @lstat ||= File.lstat(path()) end end def lstat! lstat() rescue SystemCallError nil end def chmod(mode) if symlink? File.lchmod mode, path() if have_lchmod? else File.chmod mode, path() end end def chown(uid, gid) if symlink? File.lchown uid, gid, path() if have_lchown? else File.chown uid, gid, path() end end def copy(dest) case when file? copy_file dest when directory? if !File.exist?(dest) and descendant_directory?(dest, path) raise ArgumentError, "cannot copy directory %s to itself %s" % [path, dest] end begin Dir.mkdir dest rescue raise unless File.directory?(dest) end when symlink? File.symlink File.readlink(path()), dest when chardev? raise "cannot handle device file" unless File.respond_to?(:mknod) mknod dest, ?c, 0666, lstat().rdev when blockdev? raise "cannot handle device file" unless File.respond_to?(:mknod) mknod dest, ?b, 0666, lstat().rdev when socket? raise "cannot handle socket" unless File.respond_to?(:mknod) mknod dest, nil, lstat().mode, 0 when pipe? raise "cannot handle FIFO" unless File.respond_to?(:mkfifo) mkfifo dest, 0666 when door? raise "cannot handle door: #{path()}" else raise "unknown file type: #{path()}" end end def copy_file(dest) File.open(path()) do |s| File.open(dest, 'wb', s.stat.mode) do |f| IO.copy_stream(s, f) end end end def copy_metadata(path) st = lstat() if !st.symlink? File.utime st.atime, st.mtime, path end begin if st.symlink? begin File.lchown st.uid, st.gid, path rescue NotImplementedError end else File.chown st.uid, st.gid, path end rescue Errno::EPERM # clear setuid/setgid if st.symlink? begin File.lchmod st.mode & 01777, path rescue NotImplementedError end else File.chmod st.mode & 01777, path end else if st.symlink? begin File.lchmod st.mode, path rescue NotImplementedError end else File.chmod st.mode, path end end end def remove if directory? remove_dir1 else remove_file end end def remove_dir1 platform_support { Dir.rmdir path().chomp(?/) } end def remove_file platform_support { File.unlink path } end def platform_support return yield unless fu_windows? first_time_p = true begin yield rescue Errno::ENOENT raise rescue => err if first_time_p first_time_p = false begin File.chmod 0700, path() # Windows does not have symlink retry rescue SystemCallError end end raise err end end def preorder_traverse stack = [self] while ent = stack.pop yield ent stack.concat ent.entries.reverse if ent.directory? end end alias traverse preorder_traverse def postorder_traverse if directory? entries().each do |ent| ent.postorder_traverse do |e| yield e end end end ensure yield self end def wrap_traverse(pre, post) pre.call self if directory? entries.each do |ent| ent.wrap_traverse pre, post end end post.call self end private $fileutils_rb_have_lchmod = nil def have_lchmod? # This is not MT-safe, but it does not matter. if $fileutils_rb_have_lchmod == nil $fileutils_rb_have_lchmod = check_have_lchmod? end $fileutils_rb_have_lchmod end def check_have_lchmod? return false unless File.respond_to?(:lchmod) File.lchmod 0 return true rescue NotImplementedError return false end $fileutils_rb_have_lchown = nil def have_lchown? # This is not MT-safe, but it does not matter. if $fileutils_rb_have_lchown == nil $fileutils_rb_have_lchown = check_have_lchown? end $fileutils_rb_have_lchown end def check_have_lchown? return false unless File.respond_to?(:lchown) File.lchown nil, nil return true rescue NotImplementedError return false end def join(dir, base) return File.path(dir) if not base or base == '.' return File.path(base) if not dir or dir == '.' File.join(dir, base) end if File::ALT_SEPARATOR DIRECTORY_TERM = "(?=[/#{Regexp.quote(File::ALT_SEPARATOR)}]|\\z)".freeze else DIRECTORY_TERM = "(?=/|\\z)".freeze end SYSCASE = File::FNM_SYSCASE.nonzero? ? "-i" : "" def descendant_directory?(descendant, ascendant) /\A(?#{SYSCASE}:#{Regexp.quote(ascendant)})#{DIRECTORY_TERM}/ =~ File.dirname(descendant) end end # class Entry_ def fu_list(arg) #:nodoc: [arg].flatten.map {|path| File.path(path) } end private_module_function :fu_list def fu_each_src_dest(src, dest) #:nodoc: fu_each_src_dest0(src, dest) do |s, d| raise ArgumentError, "same file: #{s} and #{d}" if fu_same?(s, d) yield s, d end end private_module_function :fu_each_src_dest def fu_each_src_dest0(src, dest) #:nodoc: if tmp = Array.try_convert(src) tmp.each do |s| s = File.path(s) yield s, File.join(dest, File.basename(s)) end else src = File.path(src) if File.directory?(dest) yield src, File.join(dest, File.basename(src)) else yield src, File.path(dest) end end end private_module_function :fu_each_src_dest0 def fu_same?(a, b) #:nodoc: File.identical?(a, b) end private_module_function :fu_same? def fu_check_options(options, optdecl) #:nodoc: h = options.dup optdecl.each do |opt| h.delete opt end raise ArgumentError, "no such option: #{h.keys.join(' ')}" unless h.empty? end private_module_function :fu_check_options def fu_update_option(args, new) #:nodoc: if tmp = Hash.try_convert(args.last) args[-1] = tmp.dup.update(new) else args.push new end args end private_module_function :fu_update_option @fileutils_output = $stderr @fileutils_label = '' def fu_output_message(msg) #:nodoc: @fileutils_output ||= $stderr @fileutils_label ||= '' @fileutils_output.puts @fileutils_label + msg end private_module_function :fu_output_message # # Returns an Array of method names which have any options. # # p FileUtils.commands #=> ["chmod", "cp", "cp_r", "install", ...] # def FileUtils.commands OPT_TABLE.keys end # # Returns an Array of option names. # # p FileUtils.options #=> ["noop", "force", "verbose", "preserve", "mode"] # def FileUtils.options OPT_TABLE.values.flatten.uniq.map {|sym| sym.to_s } end # # Returns true if the method +mid+ have an option +opt+. # # p FileUtils.have_option?(:cp, :noop) #=> true # p FileUtils.have_option?(:rm, :force) #=> true # p FileUtils.have_option?(:rm, :preserve) #=> false # def FileUtils.have_option?(mid, opt) li = OPT_TABLE[mid.to_s] or raise ArgumentError, "no such method: #{mid}" li.include?(opt) end # # Returns an Array of option names of the method +mid+. # # p FileUtils.options_of(:rm) #=> ["noop", "verbose", "force"] # def FileUtils.options_of(mid) OPT_TABLE[mid.to_s].map {|sym| sym.to_s } end # # Returns an Array of method names which have the option +opt+. # # p FileUtils.collect_method(:preserve) #=> ["cp", "cp_r", "copy", "install"] # def FileUtils.collect_method(opt) OPT_TABLE.keys.select {|m| OPT_TABLE[m].include?(opt) } end LOW_METHODS = singleton_methods(false) - collect_method(:noop).map(&:intern) module LowMethods module_eval("private\n" + ::FileUtils::LOW_METHODS.map {|name| "def #{name}(*)end"}.join("\n"), __FILE__, __LINE__) end METHODS = singleton_methods() - [:private_module_function, :commands, :options, :have_option?, :options_of, :collect_method] # # This module has all methods of FileUtils module, but it outputs messages # before acting. This equates to passing the :verbose flag to # methods in FileUtils. # module Verbose include FileUtils @fileutils_output = $stderr @fileutils_label = '' ::FileUtils.collect_method(:verbose).each do |name| module_eval(<<-EOS, __FILE__, __LINE__ + 1) def #{name}(*args) super(*fu_update_option(args, :verbose => true)) end private :#{name} EOS end extend self class << self ::FileUtils::METHODS.each do |m| public m end end end # # This module has all methods of FileUtils module, but never changes # files/directories. This equates to passing the :noop flag # to methods in FileUtils. # module NoWrite include FileUtils include LowMethods @fileutils_output = $stderr @fileutils_label = '' ::FileUtils.collect_method(:noop).each do |name| module_eval(<<-EOS, __FILE__, __LINE__ + 1) def #{name}(*args) super(*fu_update_option(args, :noop => true)) end private :#{name} EOS end extend self class << self ::FileUtils::METHODS.each do |m| public m end end end # # This module has all methods of FileUtils module, but never changes # files/directories, with printing message before acting. # This equates to passing the :noop and :verbose flag # to methods in FileUtils. # module DryRun include FileUtils include LowMethods @fileutils_output = $stderr @fileutils_label = '' ::FileUtils.collect_method(:noop).each do |name| module_eval(<<-EOS, __FILE__, __LINE__ + 1) def #{name}(*args) super(*fu_update_option(args, :noop => true, :verbose => true)) end private :#{name} EOS end extend self class << self ::FileUtils::METHODS.each do |m| public m end end end end PK!{qq!2.2.0/unicode_normalize/tables.rbnu[# coding: us-ascii # automatically generated by template/unicode_norm_gen.tmpl module UnicodeNormalize UNICODE_VERSION = "7.0.0".freeze accents = "" \ "[\u0300-\u034E\u0350-\u036F\u0483-\u0487\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7" \ "\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7\u06E8\u06EA-\u06ED\u0711" \ "\u0730-\u074A\u07EB-\u07F3\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u08E4-\u08FF" \ "\u093C\u094D\u0951-\u0954\u09BC\u09BE\u09CD\u09D7\u0A3C" \ "\u0A4D\u0ABC\u0ACD\u0B3C\u0B3E\u0B4D\u0B56\u0B57\u0BBE" \ "\u0BCD\u0BD7\u0C4D\u0C55\u0C56\u0CBC\u0CC2\u0CCD\u0CD5\u0CD6" \ "\u0D3E\u0D4D\u0D57\u0DCA\u0DCF\u0DDF\u0E38-\u0E3A\u0E48-\u0E4B" \ "\u0EB8\u0EB9\u0EC8-\u0ECB\u0F18\u0F19\u0F35\u0F37\u0F39\u0F71\u0F72\u0F74" \ "\u0F7A-\u0F7D\u0F80\u0F82-\u0F84\u0F86\u0F87\u0FC6\u102E\u1037\u1039\u103A" \ "\u108D\u135D-\u135F\u1714\u1734\u17D2\u17DD\u18A9\u1939-\u193B" \ "\u1A17\u1A18\u1A60\u1A75-\u1A7C\u1A7F\u1AB0-\u1ABD\u1B34\u1B35\u1B44\u1B6B-\u1B73" \ "\u1BAA\u1BAB\u1BE6\u1BF2\u1BF3\u1C37\u1CD0-\u1CD2\u1CD4-\u1CE0\u1CE2-\u1CE8\u1CED" \ "\u1CF4\u1CF8\u1CF9\u1DC0-\u1DF5\u1DFC-\u1DFF\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2CEF-\u2CF1" \ "\u2D7F\u2DE0-\u2DFF\u302A-\u302F\u3099\u309A\uA66F\uA674-\uA67D\uA69F\uA6F0\uA6F1" \ "\uA806\uA8C4\uA8E0-\uA8F1\uA92B-\uA92D\uA953\uA9B3\uA9C0\uAAB0" \ "\uAAB2-\uAAB4\uAAB7\uAAB8\uAABE\uAABF\uAAC1\uAAF6\uABED\uFB1E\uFE20-\uFE2D" \ "\u{101FD}\u{102E0}\u{10376}-\u{1037A}\u{10A0D}\u{10A0F}\u{10A38}-\u{10A3A}\u{10A3F}\u{10AE5}\u{10AE6}" \ "\u{11046}\u{1107F}\u{110B9}\u{110BA}\u{11100}-\u{11102}\u{11127}\u{11133}\u{11134}\u{11173}\u{111C0}" \ "\u{11235}\u{11236}\u{112E9}\u{112EA}\u{1133C}\u{1133E}\u{1134D}\u{11357}\u{11366}-\u{1136C}\u{11370}-\u{11374}" \ "\u{114B0}\u{114BA}\u{114BD}\u{114C2}\u{114C3}\u{115AF}\u{115BF}\u{115C0}\u{1163F}\u{116B6}\u{116B7}" \ "\u{16AF0}-\u{16AF4}\u{16B30}-\u{16B36}\u{1BC9E}\u{1D165}-\u{1D169}\u{1D16D}-\u{1D172}\u{1D17B}-\u{1D182}\u{1D185}-\u{1D18B}\u{1D1AA}-\u{1D1AD}" \ "\u{1D242}-\u{1D244}\u{1E8D0}-\u{1E8D6}" \ "]" \ "".freeze ACCENTS = accents REGEXP_D_STRING = "#{'' # composition starters and composition exclusions }" \ "[\u00C0-\u00C5\u00C7-\u00CF\u00D1-\u00D6\u00D9-\u00DD\u00E0-\u00E5\u00E7-\u00EF\u00F1-\u00F6\u00F9-\u00FD" \ "\u00FF-\u010F\u0112-\u0125\u0128-\u0130\u0134-\u0137\u0139-\u013E\u0143-\u0148\u014C-\u0151\u0154-\u0165" \ "\u0168-\u017E\u01A0\u01A1\u01AF\u01B0\u01CD-\u01DC\u01DE-\u01E3\u01E6-\u01F0\u01F4\u01F5\u01F8-\u021B" \ "\u021E\u021F\u0226-\u0233\u0340\u0341\u0343\u0344\u0374\u037E\u0385-\u038A\u038C" \ "\u038E-\u0390\u03AA-\u03B0\u03CA-\u03CE\u03D3\u03D4\u0400\u0401\u0403\u0407\u040C-\u040E" \ "\u0419\u0439\u0450\u0451\u0453\u0457\u045C-\u045E\u0476\u0477\u04C1\u04C2" \ "\u04D0-\u04D3\u04D6\u04D7\u04DA-\u04DF\u04E2-\u04E7\u04EA-\u04F5\u04F8\u04F9\u0622-\u0626\u06C0" \ "\u06C2\u06D3\u0929\u0931\u0934\u0958-\u095F\u09CB\u09CC\u09DC\u09DD" \ "\u09DF\u0A33\u0A36\u0A59-\u0A5B\u0A5E\u0B48\u0B4B\u0B4C\u0B5C\u0B5D" \ "\u0B94\u0BCA-\u0BCC\u0C48\u0CC0\u0CC7\u0CC8\u0CCA\u0CCB\u0D4A-\u0D4C\u0DDA" \ "\u0DDC-\u0DDE\u0F43\u0F4D\u0F52\u0F57\u0F5C\u0F69\u0F73" \ "\u0F75\u0F76\u0F78\u0F81\u0F93\u0F9D\u0FA2\u0FA7\u0FAC" \ "\u0FB9\u1026\u1B06\u1B08\u1B0A\u1B0C\u1B0E\u1B12" \ "\u1B3B\u1B3D\u1B40\u1B41\u1B43\u1E00-\u1E99\u1E9B\u1EA0-\u1EF9\u1F00-\u1F15" \ "\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D" \ "\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC1-\u1FC4\u1FC6-\u1FD3\u1FD6-\u1FDB\u1FDD-\u1FEF\u1FF2-\u1FF4" \ "\u1FF6-\u1FFD\u2000\u2001\u2126\u212A\u212B\u219A\u219B\u21AE\u21CD-\u21CF\u2204" \ "\u2209\u220C\u2224\u2226\u2241\u2244\u2247\u2249" \ "\u2260\u2262\u226D-\u2271\u2274\u2275\u2278\u2279\u2280\u2281\u2284\u2285\u2288\u2289" \ "\u22AC-\u22AF\u22E0-\u22E3\u22EA-\u22ED\u2329\u232A\u2ADC\u304C\u304E\u3050" \ "\u3052\u3054\u3056\u3058\u305A\u305C\u305E\u3060" \ "\u3062\u3065\u3067\u3069\u3070\u3071\u3073\u3074\u3076\u3077\u3079\u307A" \ "\u307C\u307D\u3094\u309E\u30AC\u30AE\u30B0\u30B2\u30B4" \ "\u30B6\u30B8\u30BA\u30BC\u30BE\u30C0\u30C2\u30C5" \ "\u30C7\u30C9\u30D0\u30D1\u30D3\u30D4\u30D6\u30D7\u30D9\u30DA\u30DC\u30DD\u30F4" \ "\u30F7-\u30FA\u30FE\uF900-\uFA0D\uFA10\uFA12\uFA15-\uFA1E\uFA20\uFA22" \ "\uFA25\uFA26\uFA2A-\uFA6D\uFA70-\uFAD9\uFB1D\uFB1F\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E" \ "\uFB40\uFB41\uFB43\uFB44\uFB46-\uFB4E\u{1109A}\u{1109C}\u{110AB}\u{1112E}\u{1112F}\u{1134B}\u{1134C}" \ "\u{114BB}\u{114BC}\u{114BE}\u{115BA}\u{115BB}\u{1D15E}-\u{1D164}\u{1D1BB}-\u{1D1C0}\u{2F800}-\u{2FA1D}" \ "]#{accents}*" \ "|#{'' # characters that can be the result of a composition, except composition starters }" \ "[<->A-PR-Za-pr-z\u00A8\u00C6\u00D8" \ "\u00E6\u00F8\u017F\u01B7\u0292\u0391\u0395\u0397" \ "\u0399\u039F\u03A1\u03A5\u03A9\u03B1\u03B5\u03B7" \ "\u03B9\u03BF\u03C1\u03C5\u03C9\u03D2\u0406\u0410" \ "\u0413\u0415-\u0418\u041A\u041E\u0423\u0427\u042B\u042D" \ "\u0430\u0433\u0435-\u0438\u043A\u043E\u0443\u0447\u044B" \ "\u044D\u0456\u0474\u0475\u04D8\u04D9\u04E8\u04E9\u0627\u0648\u064A" \ "\u06C1\u06D2\u06D5\u0928\u0930\u0933\u09C7\u0B47" \ "\u0B92\u0BC6\u0BC7\u0C46\u0CBF\u0CC6\u0D46\u0D47\u0DD9\u1025" \ "\u1B05\u1B07\u1B09\u1B0B\u1B0D\u1B11\u1B3A\u1B3C" \ "\u1B3E\u1B3F\u1B42\u1FBF\u1FFE\u2190\u2192\u2194\u21D0" \ "\u21D2\u21D4\u2203\u2208\u220B\u2223\u2225\u223C" \ "\u2243\u2245\u2248\u224D\u2261\u2264\u2265\u2272\u2273\u2276\u2277" \ "\u227A-\u227D\u2282\u2283\u2286\u2287\u2291\u2292\u22A2\u22A8\u22A9\u22AB\u22B2-\u22B5" \ "\u3046\u304B\u304D\u304F\u3051\u3053\u3055\u3057" \ "\u3059\u305B\u305D\u305F\u3061\u3064\u3066\u3068" \ "\u306F\u3072\u3075\u3078\u307B\u309D\u30A6\u30AB" \ "\u30AD\u30AF\u30B1\u30B3\u30B5\u30B7\u30B9\u30BB" \ "\u30BD\u30BF\u30C1\u30C4\u30C6\u30C8\u30CF\u30D2" \ "\u30D5\u30D8\u30DB\u30EF-\u30F2\u30FD\u{11099}\u{1109B}\u{110A5}" \ "\u{11131}\u{11132}\u{11347}\u{114B9}\u{115B8}\u{115B9}" \ "]?#{accents}+" \ "|#{'' # precomposed Hangul syllables }" \ "[\u{AC00}-\u{D7A4}]" \ "".freeze REGEXP_C_STRING = "#{'' # composition exclusions }" \ "[\u0340\u0341\u0343\u0344\u0374\u037E\u0387\u0958-\u095F\u09DC\u09DD\u09DF" \ "\u0A33\u0A36\u0A59-\u0A5B\u0A5E\u0B5C\u0B5D\u0F43\u0F4D\u0F52" \ "\u0F57\u0F5C\u0F69\u0F73\u0F75\u0F76\u0F78\u0F81\u0F93" \ "\u0F9D\u0FA2\u0FA7\u0FAC\u0FB9\u1F71\u1F73\u1F75" \ "\u1F77\u1F79\u1F7B\u1F7D\u1FBB\u1FBE\u1FC9\u1FCB" \ "\u1FD3\u1FDB\u1FE3\u1FEB\u1FEE\u1FEF\u1FF9\u1FFB\u1FFD" \ "\u2000\u2001\u2126\u212A\u212B\u2329\u232A\u2ADC\uF900-\uFA0D\uFA10\uFA12" \ "\uFA15-\uFA1E\uFA20\uFA22\uFA25\uFA26\uFA2A-\uFA6D\uFA70-\uFAD9\uFB1D\uFB1F" \ "\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFB4E\u{1D15E}-\u{1D164}\u{1D1BB}-\u{1D1C0}" \ "\u{2F800}-\u{2FA1D}" \ "]#{accents}*" \ "|#{'' # composition starters and characters that can be the result of a composition }" \ "[<->A-PR-Za-pr-z\u00A8\u00C0-\u00CF\u00D1-\u00D6" \ "\u00D8-\u00DD\u00E0-\u00EF\u00F1-\u00F6\u00F8-\u00FD\u00FF-\u010F\u0112-\u0125\u0128-\u0130\u0134-\u0137" \ "\u0139-\u013E\u0143-\u0148\u014C-\u0151\u0154-\u0165\u0168-\u017F\u01A0\u01A1\u01AF\u01B0\u01B7" \ "\u01CD-\u01DC\u01DE-\u01E3\u01E6-\u01F0\u01F4\u01F5\u01F8-\u021B\u021E\u021F\u0226-\u0233\u0292" \ "\u0385\u0386\u0388-\u038A\u038C\u038E-\u0391\u0395\u0397\u0399\u039F" \ "\u03A1\u03A5\u03A9-\u03B1\u03B5\u03B7\u03B9\u03BF\u03C1" \ "\u03C5\u03C9-\u03CE\u03D2-\u03D4\u0400\u0401\u0403\u0406\u0407\u040C-\u040E\u0410" \ "\u0413\u0415-\u041A\u041E\u0423\u0427\u042B\u042D\u0430" \ "\u0433\u0435-\u043A\u043E\u0443\u0447\u044B\u044D\u0450\u0451" \ "\u0453\u0456\u0457\u045C-\u045E\u0474-\u0477\u04C1\u04C2\u04D0-\u04D3\u04D6-\u04DF\u04E2-\u04F5" \ "\u04F8\u04F9\u0622-\u0627\u0648\u064A\u06C0-\u06C2\u06D2\u06D3\u06D5\u0928\u0929" \ "\u0930\u0931\u0933\u0934\u09C7\u09CB\u09CC\u0B47\u0B48\u0B4B\u0B4C\u0B92\u0B94" \ "\u0BC6\u0BC7\u0BCA-\u0BCC\u0C46\u0C48\u0CBF\u0CC0\u0CC6-\u0CC8\u0CCA\u0CCB\u0D46\u0D47" \ "\u0D4A-\u0D4C\u0DD9\u0DDA\u0DDC-\u0DDE\u1025\u1026\u1B05-\u1B0E\u1B11\u1B12\u1B3A-\u1B43\u1E00-\u1E99" \ "\u1E9B\u1EA0-\u1EF9\u1F00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59" \ "\u1F5B\u1F5D\u1F5F-\u1F70\u1F72\u1F74\u1F76\u1F78\u1F7A" \ "\u1F7C\u1F80-\u1FB4\u1FB6-\u1FBA\u1FBC\u1FBF\u1FC1-\u1FC4\u1FC6-\u1FC8\u1FCA" \ "\u1FCC-\u1FD2\u1FD6-\u1FDA\u1FDD-\u1FE2\u1FE4-\u1FEA\u1FEC\u1FED\u1FF2-\u1FF4\u1FF6-\u1FF8\u1FFA" \ "\u1FFC\u1FFE\u2190\u2192\u2194\u219A\u219B\u21AE\u21CD-\u21D0" \ "\u21D2\u21D4\u2203\u2204\u2208\u2209\u220B\u220C\u2223-\u2226\u223C\u2241" \ "\u2243-\u2245\u2247-\u2249\u224D\u2260-\u2262\u2264\u2265\u226D-\u227D\u2280-\u2289\u2291\u2292" \ "\u22A2\u22A8\u22A9\u22AB-\u22AF\u22B2-\u22B5\u22E0-\u22E3\u22EA-\u22ED\u3046\u304B-\u3062" \ "\u3064-\u3069\u306F-\u307D\u3094\u309D\u309E\u30A6\u30AB-\u30C2\u30C4-\u30C9\u30CF-\u30DD" \ "\u30EF-\u30F2\u30F4\u30F7-\u30FA\u30FD\u30FE\u{11099}-\u{1109C}\u{110A5}\u{110AB}\u{1112E}\u{1112F}" \ "\u{11131}\u{11132}\u{11347}\u{1134B}\u{1134C}\u{114B9}\u{114BB}\u{114BC}\u{114BE}\u{115B8}-\u{115BB}" \ "]?#{accents}+" \ "|#{'' # Hangul syllables with separate trailer }" \ "[\uAC00\uAC1C\uAC38\uAC54\uAC70\uAC8C\uACA8\uACC4" \ "\uACE0\uACFC\uAD18\uAD34\uAD50\uAD6C\uAD88\uADA4" \ "\uADC0\uADDC\uADF8\uAE14\uAE30\uAE4C\uAE68\uAE84" \ "\uAEA0\uAEBC\uAED8\uAEF4\uAF10\uAF2C\uAF48\uAF64" \ "\uAF80\uAF9C\uAFB8\uAFD4\uAFF0\uB00C\uB028\uB044" \ "\uB060\uB07C\uB098\uB0B4\uB0D0\uB0EC\uB108\uB124" \ "\uB140\uB15C\uB178\uB194\uB1B0\uB1CC\uB1E8\uB204" \ "\uB220\uB23C\uB258\uB274\uB290\uB2AC\uB2C8\uB2E4" \ "\uB300\uB31C\uB338\uB354\uB370\uB38C\uB3A8\uB3C4" \ "\uB3E0\uB3FC\uB418\uB434\uB450\uB46C\uB488\uB4A4" \ "\uB4C0\uB4DC\uB4F8\uB514\uB530\uB54C\uB568\uB584" \ "\uB5A0\uB5BC\uB5D8\uB5F4\uB610\uB62C\uB648\uB664" \ "\uB680\uB69C\uB6B8\uB6D4\uB6F0\uB70C\uB728\uB744" \ "\uB760\uB77C\uB798\uB7B4\uB7D0\uB7EC\uB808\uB824" \ "\uB840\uB85C\uB878\uB894\uB8B0\uB8CC\uB8E8\uB904" \ "\uB920\uB93C\uB958\uB974\uB990\uB9AC\uB9C8\uB9E4" \ "\uBA00\uBA1C\uBA38\uBA54\uBA70\uBA8C\uBAA8\uBAC4" \ "\uBAE0\uBAFC\uBB18\uBB34\uBB50\uBB6C\uBB88\uBBA4" \ "\uBBC0\uBBDC\uBBF8\uBC14\uBC30\uBC4C\uBC68\uBC84" \ "\uBCA0\uBCBC\uBCD8\uBCF4\uBD10\uBD2C\uBD48\uBD64" \ "\uBD80\uBD9C\uBDB8\uBDD4\uBDF0\uBE0C\uBE28\uBE44" \ "\uBE60\uBE7C\uBE98\uBEB4\uBED0\uBEEC\uBF08\uBF24" \ "\uBF40\uBF5C\uBF78\uBF94\uBFB0\uBFCC\uBFE8\uC004" \ "\uC020\uC03C\uC058\uC074\uC090\uC0AC\uC0C8\uC0E4" \ "\uC100\uC11C\uC138\uC154\uC170\uC18C\uC1A8\uC1C4" \ "\uC1E0\uC1FC\uC218\uC234\uC250\uC26C\uC288\uC2A4" \ "\uC2C0\uC2DC\uC2F8\uC314\uC330\uC34C\uC368\uC384" \ "\uC3A0\uC3BC\uC3D8\uC3F4\uC410\uC42C\uC448\uC464" \ "\uC480\uC49C\uC4B8\uC4D4\uC4F0\uC50C\uC528\uC544" \ "\uC560\uC57C\uC598\uC5B4\uC5D0\uC5EC\uC608\uC624" \ "\uC640\uC65C\uC678\uC694\uC6B0\uC6CC\uC6E8\uC704" \ "\uC720\uC73C\uC758\uC774\uC790\uC7AC\uC7C8\uC7E4" \ "\uC800\uC81C\uC838\uC854\uC870\uC88C\uC8A8\uC8C4" \ "\uC8E0\uC8FC\uC918\uC934\uC950\uC96C\uC988\uC9A4" \ "\uC9C0\uC9DC\uC9F8\uCA14\uCA30\uCA4C\uCA68\uCA84" \ "\uCAA0\uCABC\uCAD8\uCAF4\uCB10\uCB2C\uCB48\uCB64" \ "\uCB80\uCB9C\uCBB8\uCBD4\uCBF0\uCC0C\uCC28\uCC44" \ "\uCC60\uCC7C\uCC98\uCCB4\uCCD0\uCCEC\uCD08\uCD24" \ "\uCD40\uCD5C\uCD78\uCD94\uCDB0\uCDCC\uCDE8\uCE04" \ "\uCE20\uCE3C\uCE58\uCE74\uCE90\uCEAC\uCEC8\uCEE4" \ "\uCF00\uCF1C\uCF38\uCF54\uCF70\uCF8C\uCFA8\uCFC4" \ "\uCFE0\uCFFC\uD018\uD034\uD050\uD06C\uD088\uD0A4" \ "\uD0C0\uD0DC\uD0F8\uD114\uD130\uD14C\uD168\uD184" \ "\uD1A0\uD1BC\uD1D8\uD1F4\uD210\uD22C\uD248\uD264" \ "\uD280\uD29C\uD2B8\uD2D4\uD2F0\uD30C\uD328\uD344" \ "\uD360\uD37C\uD398\uD3B4\uD3D0\uD3EC\uD408\uD424" \ "\uD440\uD45C\uD478\uD494\uD4B0\uD4CC\uD4E8\uD504" \ "\uD520\uD53C\uD558\uD574\uD590\uD5AC\uD5C8\uD5E4" \ "\uD600\uD61C\uD638\uD654\uD670\uD68C\uD6A8\uD6C4" \ "\uD6E0\uD6FC\uD718\uD734\uD750\uD76C\uD788" \ "][\u11A8-\u11C2]" \ "|#{'' # decomposed Hangul syllables }" \ "[\u1100-\u1112][\u1161-\u1175][\u11A8-\u11C2]?" \ "".freeze REGEXP_K_STRING = "" \ "[\u00A0\u00A8\u00AA\u00AF\u00B2-\u00B5\u00B8-\u00BA\u00BC-\u00BE\u0132\u0133" \ "\u013F\u0140\u0149\u017F\u01C4-\u01CC\u01F1-\u01F3\u02B0-\u02B8\u02D8-\u02DD\u02E0-\u02E4" \ "\u037A\u0384\u0385\u03D0-\u03D6\u03F0-\u03F2\u03F4\u03F5\u03F9\u0587\u0675-\u0678" \ "\u0E33\u0EB3\u0EDC\u0EDD\u0F0C\u0F77\u0F79\u10FC\u1D2C-\u1D2E" \ "\u1D30-\u1D3A\u1D3C-\u1D4D\u1D4F-\u1D6A\u1D78\u1D9B-\u1DBF\u1E9A\u1E9B\u1FBD\u1FBF-\u1FC1" \ "\u1FCD-\u1FCF\u1FDD-\u1FDF\u1FED\u1FEE\u1FFD\u1FFE\u2000-\u200A\u2011\u2017\u2024-\u2026" \ "\u202F\u2033\u2034\u2036\u2037\u203C\u203E\u2047-\u2049\u2057\u205F" \ "\u2070\u2071\u2074-\u208E\u2090-\u209C\u20A8\u2100-\u2103\u2105-\u2107\u2109-\u2113\u2115\u2116" \ "\u2119-\u211D\u2120-\u2122\u2124\u2128\u212C\u212D\u212F-\u2131\u2133-\u2139\u213B-\u2140" \ "\u2145-\u2149\u2150-\u217F\u2189\u222C\u222D\u222F\u2230\u2460-\u24EA\u2A0C\u2A74-\u2A76" \ "\u2C7C\u2C7D\u2D6F\u2E9F\u2EF3\u2F00-\u2FD5\u3000\u3036\u3038-\u303A" \ "\u309B\u309C\u309F\u30FF\u3131-\u318E\u3192-\u319F\u3200-\u321E\u3220-\u3247\u3250-\u327E" \ "\u3280-\u32FE\u3300-\u33FF\uA69C\uA69D\uA770\uA7F8\uA7F9\uAB5C-\uAB5F\uFB00-\uFB06\uFB13-\uFB17" \ "\uFB20-\uFB29\uFB4F-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFC\uFE10-\uFE19\uFE30-\uFE44" \ "\uFE47-\uFE52\uFE54-\uFE66\uFE68-\uFE6B\uFE70-\uFE72\uFE74\uFE76-\uFEFC\uFF01-\uFFBE\uFFC2-\uFFC7" \ "\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC\uFFE0-\uFFE6\uFFE8-\uFFEE\u{1D400}-\u{1D454}\u{1D456}-\u{1D49C}\u{1D49E}\u{1D49F}" \ "\u{1D4A2}\u{1D4A5}\u{1D4A6}\u{1D4A9}-\u{1D4AC}\u{1D4AE}-\u{1D4B9}\u{1D4BB}\u{1D4BD}-\u{1D4C3}\u{1D4C5}-\u{1D505}\u{1D507}-\u{1D50A}" \ "\u{1D50D}-\u{1D514}\u{1D516}-\u{1D51C}\u{1D51E}-\u{1D539}\u{1D53B}-\u{1D53E}\u{1D540}-\u{1D544}\u{1D546}\u{1D54A}-\u{1D550}\u{1D552}-\u{1D6A5}" \ "\u{1D6A8}-\u{1D7CB}\u{1D7CE}-\u{1D7FF}\u{1EE00}-\u{1EE03}\u{1EE05}-\u{1EE1F}\u{1EE21}\u{1EE22}\u{1EE24}\u{1EE27}\u{1EE29}-\u{1EE32}" \ "\u{1EE34}-\u{1EE37}\u{1EE39}\u{1EE3B}\u{1EE42}\u{1EE47}\u{1EE49}\u{1EE4B}\u{1EE4D}-\u{1EE4F}" \ "\u{1EE51}\u{1EE52}\u{1EE54}\u{1EE57}\u{1EE59}\u{1EE5B}\u{1EE5D}\u{1EE5F}\u{1EE61}\u{1EE62}" \ "\u{1EE64}\u{1EE67}-\u{1EE6A}\u{1EE6C}-\u{1EE72}\u{1EE74}-\u{1EE77}\u{1EE79}-\u{1EE7C}\u{1EE7E}\u{1EE80}-\u{1EE89}\u{1EE8B}-\u{1EE9B}" \ "\u{1EEA1}-\u{1EEA3}\u{1EEA5}-\u{1EEA9}\u{1EEAB}-\u{1EEBB}\u{1F100}-\u{1F10A}\u{1F110}-\u{1F12E}\u{1F130}-\u{1F14F}\u{1F16A}\u{1F16B}\u{1F190}" \ "\u{1F200}-\u{1F202}\u{1F210}-\u{1F23A}\u{1F240}-\u{1F248}\u{1F250}\u{1F251}" \ "]" \ "".freeze class_table = { "\u0300"=>230, "\u0301"=>230, "\u0302"=>230, "\u0303"=>230, "\u0304"=>230, "\u0305"=>230, "\u0306"=>230, "\u0307"=>230, "\u0308"=>230, "\u0309"=>230, "\u030A"=>230, "\u030B"=>230, "\u030C"=>230, "\u030D"=>230, "\u030E"=>230, "\u030F"=>230, "\u0310"=>230, "\u0311"=>230, "\u0312"=>230, "\u0313"=>230, "\u0314"=>230, "\u0315"=>232, "\u0316"=>220, "\u0317"=>220, "\u0318"=>220, "\u0319"=>220, "\u031A"=>232, "\u031B"=>216, "\u031C"=>220, "\u031D"=>220, "\u031E"=>220, "\u031F"=>220, "\u0320"=>220, "\u0321"=>202, "\u0322"=>202, "\u0323"=>220, "\u0324"=>220, "\u0325"=>220, "\u0326"=>220, "\u0327"=>202, "\u0328"=>202, "\u0329"=>220, "\u032A"=>220, "\u032B"=>220, "\u032C"=>220, "\u032D"=>220, "\u032E"=>220, "\u032F"=>220, "\u0330"=>220, "\u0331"=>220, "\u0332"=>220, "\u0333"=>220, "\u0334"=>1, "\u0335"=>1, "\u0336"=>1, "\u0337"=>1, "\u0338"=>1, "\u0339"=>220, "\u033A"=>220, "\u033B"=>220, "\u033C"=>220, "\u033D"=>230, "\u033E"=>230, "\u033F"=>230, "\u0340"=>230, "\u0341"=>230, "\u0342"=>230, "\u0343"=>230, "\u0344"=>230, "\u0345"=>240, "\u0346"=>230, "\u0347"=>220, "\u0348"=>220, "\u0349"=>220, "\u034A"=>230, "\u034B"=>230, "\u034C"=>230, "\u034D"=>220, "\u034E"=>220, "\u0350"=>230, "\u0351"=>230, "\u0352"=>230, "\u0353"=>220, "\u0354"=>220, "\u0355"=>220, "\u0356"=>220, "\u0357"=>230, "\u0358"=>232, "\u0359"=>220, "\u035A"=>220, "\u035B"=>230, "\u035C"=>233, "\u035D"=>234, "\u035E"=>234, "\u035F"=>233, "\u0360"=>234, "\u0361"=>234, "\u0362"=>233, "\u0363"=>230, "\u0364"=>230, "\u0365"=>230, "\u0366"=>230, "\u0367"=>230, "\u0368"=>230, "\u0369"=>230, "\u036A"=>230, "\u036B"=>230, "\u036C"=>230, "\u036D"=>230, "\u036E"=>230, "\u036F"=>230, "\u0483"=>230, "\u0484"=>230, "\u0485"=>230, "\u0486"=>230, "\u0487"=>230, "\u0591"=>220, "\u0592"=>230, "\u0593"=>230, "\u0594"=>230, "\u0595"=>230, "\u0596"=>220, "\u0597"=>230, "\u0598"=>230, "\u0599"=>230, "\u059A"=>222, "\u059B"=>220, "\u059C"=>230, "\u059D"=>230, "\u059E"=>230, "\u059F"=>230, "\u05A0"=>230, "\u05A1"=>230, "\u05A2"=>220, "\u05A3"=>220, "\u05A4"=>220, "\u05A5"=>220, "\u05A6"=>220, "\u05A7"=>220, "\u05A8"=>230, "\u05A9"=>230, "\u05AA"=>220, "\u05AB"=>230, "\u05AC"=>230, "\u05AD"=>222, "\u05AE"=>228, "\u05AF"=>230, "\u05B0"=>10, "\u05B1"=>11, "\u05B2"=>12, "\u05B3"=>13, "\u05B4"=>14, "\u05B5"=>15, "\u05B6"=>16, "\u05B7"=>17, "\u05B8"=>18, "\u05B9"=>19, "\u05BA"=>19, "\u05BB"=>20, "\u05BC"=>21, "\u05BD"=>22, "\u05BF"=>23, "\u05C1"=>24, "\u05C2"=>25, "\u05C4"=>230, "\u05C5"=>220, "\u05C7"=>18, "\u0610"=>230, "\u0611"=>230, "\u0612"=>230, "\u0613"=>230, "\u0614"=>230, "\u0615"=>230, "\u0616"=>230, "\u0617"=>230, "\u0618"=>30, "\u0619"=>31, "\u061A"=>32, "\u064B"=>27, "\u064C"=>28, "\u064D"=>29, "\u064E"=>30, "\u064F"=>31, "\u0650"=>32, "\u0651"=>33, "\u0652"=>34, "\u0653"=>230, "\u0654"=>230, "\u0655"=>220, "\u0656"=>220, "\u0657"=>230, "\u0658"=>230, "\u0659"=>230, "\u065A"=>230, "\u065B"=>230, "\u065C"=>220, "\u065D"=>230, "\u065E"=>230, "\u065F"=>220, "\u0670"=>35, "\u06D6"=>230, "\u06D7"=>230, "\u06D8"=>230, "\u06D9"=>230, "\u06DA"=>230, "\u06DB"=>230, "\u06DC"=>230, "\u06DF"=>230, "\u06E0"=>230, "\u06E1"=>230, "\u06E2"=>230, "\u06E3"=>220, "\u06E4"=>230, "\u06E7"=>230, "\u06E8"=>230, "\u06EA"=>220, "\u06EB"=>230, "\u06EC"=>230, "\u06ED"=>220, "\u0711"=>36, "\u0730"=>230, "\u0731"=>220, "\u0732"=>230, "\u0733"=>230, "\u0734"=>220, "\u0735"=>230, "\u0736"=>230, "\u0737"=>220, "\u0738"=>220, "\u0739"=>220, "\u073A"=>230, "\u073B"=>220, "\u073C"=>220, "\u073D"=>230, "\u073E"=>220, "\u073F"=>230, "\u0740"=>230, "\u0741"=>230, "\u0742"=>220, "\u0743"=>230, "\u0744"=>220, "\u0745"=>230, "\u0746"=>220, "\u0747"=>230, "\u0748"=>220, "\u0749"=>230, "\u074A"=>230, "\u07EB"=>230, "\u07EC"=>230, "\u07ED"=>230, "\u07EE"=>230, "\u07EF"=>230, "\u07F0"=>230, "\u07F1"=>230, "\u07F2"=>220, "\u07F3"=>230, "\u0816"=>230, "\u0817"=>230, "\u0818"=>230, "\u0819"=>230, "\u081B"=>230, "\u081C"=>230, "\u081D"=>230, "\u081E"=>230, "\u081F"=>230, "\u0820"=>230, "\u0821"=>230, "\u0822"=>230, "\u0823"=>230, "\u0825"=>230, "\u0826"=>230, "\u0827"=>230, "\u0829"=>230, "\u082A"=>230, "\u082B"=>230, "\u082C"=>230, "\u082D"=>230, "\u0859"=>220, "\u085A"=>220, "\u085B"=>220, "\u08E4"=>230, "\u08E5"=>230, "\u08E6"=>220, "\u08E7"=>230, "\u08E8"=>230, "\u08E9"=>220, "\u08EA"=>230, "\u08EB"=>230, "\u08EC"=>230, "\u08ED"=>220, "\u08EE"=>220, "\u08EF"=>220, "\u08F0"=>27, "\u08F1"=>28, "\u08F2"=>29, "\u08F3"=>230, "\u08F4"=>230, "\u08F5"=>230, "\u08F6"=>220, "\u08F7"=>230, "\u08F8"=>230, "\u08F9"=>220, "\u08FA"=>220, "\u08FB"=>230, "\u08FC"=>230, "\u08FD"=>230, "\u08FE"=>230, "\u08FF"=>230, "\u093C"=>7, "\u094D"=>9, "\u0951"=>230, "\u0952"=>220, "\u0953"=>230, "\u0954"=>230, "\u09BC"=>7, "\u09CD"=>9, "\u0A3C"=>7, "\u0A4D"=>9, "\u0ABC"=>7, "\u0ACD"=>9, "\u0B3C"=>7, "\u0B4D"=>9, "\u0BCD"=>9, "\u0C4D"=>9, "\u0C55"=>84, "\u0C56"=>91, "\u0CBC"=>7, "\u0CCD"=>9, "\u0D4D"=>9, "\u0DCA"=>9, "\u0E38"=>103, "\u0E39"=>103, "\u0E3A"=>9, "\u0E48"=>107, "\u0E49"=>107, "\u0E4A"=>107, "\u0E4B"=>107, "\u0EB8"=>118, "\u0EB9"=>118, "\u0EC8"=>122, "\u0EC9"=>122, "\u0ECA"=>122, "\u0ECB"=>122, "\u0F18"=>220, "\u0F19"=>220, "\u0F35"=>220, "\u0F37"=>220, "\u0F39"=>216, "\u0F71"=>129, "\u0F72"=>130, "\u0F74"=>132, "\u0F7A"=>130, "\u0F7B"=>130, "\u0F7C"=>130, "\u0F7D"=>130, "\u0F80"=>130, "\u0F82"=>230, "\u0F83"=>230, "\u0F84"=>9, "\u0F86"=>230, "\u0F87"=>230, "\u0FC6"=>220, "\u1037"=>7, "\u1039"=>9, "\u103A"=>9, "\u108D"=>220, "\u135D"=>230, "\u135E"=>230, "\u135F"=>230, "\u1714"=>9, "\u1734"=>9, "\u17D2"=>9, "\u17DD"=>230, "\u18A9"=>228, "\u1939"=>222, "\u193A"=>230, "\u193B"=>220, "\u1A17"=>230, "\u1A18"=>220, "\u1A60"=>9, "\u1A75"=>230, "\u1A76"=>230, "\u1A77"=>230, "\u1A78"=>230, "\u1A79"=>230, "\u1A7A"=>230, "\u1A7B"=>230, "\u1A7C"=>230, "\u1A7F"=>220, "\u1AB0"=>230, "\u1AB1"=>230, "\u1AB2"=>230, "\u1AB3"=>230, "\u1AB4"=>230, "\u1AB5"=>220, "\u1AB6"=>220, "\u1AB7"=>220, "\u1AB8"=>220, "\u1AB9"=>220, "\u1ABA"=>220, "\u1ABB"=>230, "\u1ABC"=>230, "\u1ABD"=>220, "\u1B34"=>7, "\u1B44"=>9, "\u1B6B"=>230, "\u1B6C"=>220, "\u1B6D"=>230, "\u1B6E"=>230, "\u1B6F"=>230, "\u1B70"=>230, "\u1B71"=>230, "\u1B72"=>230, "\u1B73"=>230, "\u1BAA"=>9, "\u1BAB"=>9, "\u1BE6"=>7, "\u1BF2"=>9, "\u1BF3"=>9, "\u1C37"=>7, "\u1CD0"=>230, "\u1CD1"=>230, "\u1CD2"=>230, "\u1CD4"=>1, "\u1CD5"=>220, "\u1CD6"=>220, "\u1CD7"=>220, "\u1CD8"=>220, "\u1CD9"=>220, "\u1CDA"=>230, "\u1CDB"=>230, "\u1CDC"=>220, "\u1CDD"=>220, "\u1CDE"=>220, "\u1CDF"=>220, "\u1CE0"=>230, "\u1CE2"=>1, "\u1CE3"=>1, "\u1CE4"=>1, "\u1CE5"=>1, "\u1CE6"=>1, "\u1CE7"=>1, "\u1CE8"=>1, "\u1CED"=>220, "\u1CF4"=>230, "\u1CF8"=>230, "\u1CF9"=>230, "\u1DC0"=>230, "\u1DC1"=>230, "\u1DC2"=>220, "\u1DC3"=>230, "\u1DC4"=>230, "\u1DC5"=>230, "\u1DC6"=>230, "\u1DC7"=>230, "\u1DC8"=>230, "\u1DC9"=>230, "\u1DCA"=>220, "\u1DCB"=>230, "\u1DCC"=>230, "\u1DCD"=>234, "\u1DCE"=>214, "\u1DCF"=>220, "\u1DD0"=>202, "\u1DD1"=>230, "\u1DD2"=>230, "\u1DD3"=>230, "\u1DD4"=>230, "\u1DD5"=>230, "\u1DD6"=>230, "\u1DD7"=>230, "\u1DD8"=>230, "\u1DD9"=>230, "\u1DDA"=>230, "\u1DDB"=>230, "\u1DDC"=>230, "\u1DDD"=>230, "\u1DDE"=>230, "\u1DDF"=>230, "\u1DE0"=>230, "\u1DE1"=>230, "\u1DE2"=>230, "\u1DE3"=>230, "\u1DE4"=>230, "\u1DE5"=>230, "\u1DE6"=>230, "\u1DE7"=>230, "\u1DE8"=>230, "\u1DE9"=>230, "\u1DEA"=>230, "\u1DEB"=>230, "\u1DEC"=>230, "\u1DED"=>230, "\u1DEE"=>230, "\u1DEF"=>230, "\u1DF0"=>230, "\u1DF1"=>230, "\u1DF2"=>230, "\u1DF3"=>230, "\u1DF4"=>230, "\u1DF5"=>230, "\u1DFC"=>233, "\u1DFD"=>220, "\u1DFE"=>230, "\u1DFF"=>220, "\u20D0"=>230, "\u20D1"=>230, "\u20D2"=>1, "\u20D3"=>1, "\u20D4"=>230, "\u20D5"=>230, "\u20D6"=>230, "\u20D7"=>230, "\u20D8"=>1, "\u20D9"=>1, "\u20DA"=>1, "\u20DB"=>230, "\u20DC"=>230, "\u20E1"=>230, "\u20E5"=>1, "\u20E6"=>1, "\u20E7"=>230, "\u20E8"=>220, "\u20E9"=>230, "\u20EA"=>1, "\u20EB"=>1, "\u20EC"=>220, "\u20ED"=>220, "\u20EE"=>220, "\u20EF"=>220, "\u20F0"=>230, "\u2CEF"=>230, "\u2CF0"=>230, "\u2CF1"=>230, "\u2D7F"=>9, "\u2DE0"=>230, "\u2DE1"=>230, "\u2DE2"=>230, "\u2DE3"=>230, "\u2DE4"=>230, "\u2DE5"=>230, "\u2DE6"=>230, "\u2DE7"=>230, "\u2DE8"=>230, "\u2DE9"=>230, "\u2DEA"=>230, "\u2DEB"=>230, "\u2DEC"=>230, "\u2DED"=>230, "\u2DEE"=>230, "\u2DEF"=>230, "\u2DF0"=>230, "\u2DF1"=>230, "\u2DF2"=>230, "\u2DF3"=>230, "\u2DF4"=>230, "\u2DF5"=>230, "\u2DF6"=>230, "\u2DF7"=>230, "\u2DF8"=>230, "\u2DF9"=>230, "\u2DFA"=>230, "\u2DFB"=>230, "\u2DFC"=>230, "\u2DFD"=>230, "\u2DFE"=>230, "\u2DFF"=>230, "\u302A"=>218, "\u302B"=>228, "\u302C"=>232, "\u302D"=>222, "\u302E"=>224, "\u302F"=>224, "\u3099"=>8, "\u309A"=>8, "\uA66F"=>230, "\uA674"=>230, "\uA675"=>230, "\uA676"=>230, "\uA677"=>230, "\uA678"=>230, "\uA679"=>230, "\uA67A"=>230, "\uA67B"=>230, "\uA67C"=>230, "\uA67D"=>230, "\uA69F"=>230, "\uA6F0"=>230, "\uA6F1"=>230, "\uA806"=>9, "\uA8C4"=>9, "\uA8E0"=>230, "\uA8E1"=>230, "\uA8E2"=>230, "\uA8E3"=>230, "\uA8E4"=>230, "\uA8E5"=>230, "\uA8E6"=>230, "\uA8E7"=>230, "\uA8E8"=>230, "\uA8E9"=>230, "\uA8EA"=>230, "\uA8EB"=>230, "\uA8EC"=>230, "\uA8ED"=>230, "\uA8EE"=>230, "\uA8EF"=>230, "\uA8F0"=>230, "\uA8F1"=>230, "\uA92B"=>220, "\uA92C"=>220, "\uA92D"=>220, "\uA953"=>9, "\uA9B3"=>7, "\uA9C0"=>9, "\uAAB0"=>230, "\uAAB2"=>230, "\uAAB3"=>230, "\uAAB4"=>220, "\uAAB7"=>230, "\uAAB8"=>230, "\uAABE"=>230, "\uAABF"=>230, "\uAAC1"=>230, "\uAAF6"=>9, "\uABED"=>9, "\uFB1E"=>26, "\uFE20"=>230, "\uFE21"=>230, "\uFE22"=>230, "\uFE23"=>230, "\uFE24"=>230, "\uFE25"=>230, "\uFE26"=>230, "\uFE27"=>220, "\uFE28"=>220, "\uFE29"=>220, "\uFE2A"=>220, "\uFE2B"=>220, "\uFE2C"=>220, "\uFE2D"=>220, "\u{101FD}"=>220, "\u{102E0}"=>220, "\u{10376}"=>230, "\u{10377}"=>230, "\u{10378}"=>230, "\u{10379}"=>230, "\u{1037A}"=>230, "\u{10A0D}"=>220, "\u{10A0F}"=>230, "\u{10A38}"=>230, "\u{10A39}"=>1, "\u{10A3A}"=>220, "\u{10A3F}"=>9, "\u{10AE5}"=>230, "\u{10AE6}"=>220, "\u{11046}"=>9, "\u{1107F}"=>9, "\u{110B9}"=>9, "\u{110BA}"=>7, "\u{11100}"=>230, "\u{11101}"=>230, "\u{11102}"=>230, "\u{11133}"=>9, "\u{11134}"=>9, "\u{11173}"=>7, "\u{111C0}"=>9, "\u{11235}"=>9, "\u{11236}"=>7, "\u{112E9}"=>7, "\u{112EA}"=>9, "\u{1133C}"=>7, "\u{1134D}"=>9, "\u{11366}"=>230, "\u{11367}"=>230, "\u{11368}"=>230, "\u{11369}"=>230, "\u{1136A}"=>230, "\u{1136B}"=>230, "\u{1136C}"=>230, "\u{11370}"=>230, "\u{11371}"=>230, "\u{11372}"=>230, "\u{11373}"=>230, "\u{11374}"=>230, "\u{114C2}"=>9, "\u{114C3}"=>7, "\u{115BF}"=>9, "\u{115C0}"=>7, "\u{1163F}"=>9, "\u{116B6}"=>9, "\u{116B7}"=>7, "\u{16AF0}"=>1, "\u{16AF1}"=>1, "\u{16AF2}"=>1, "\u{16AF3}"=>1, "\u{16AF4}"=>1, "\u{16B30}"=>230, "\u{16B31}"=>230, "\u{16B32}"=>230, "\u{16B33}"=>230, "\u{16B34}"=>230, "\u{16B35}"=>230, "\u{16B36}"=>230, "\u{1BC9E}"=>1, "\u{1D165}"=>216, "\u{1D166}"=>216, "\u{1D167}"=>1, "\u{1D168}"=>1, "\u{1D169}"=>1, "\u{1D16D}"=>226, "\u{1D16E}"=>216, "\u{1D16F}"=>216, "\u{1D170}"=>216, "\u{1D171}"=>216, "\u{1D172}"=>216, "\u{1D17B}"=>220, "\u{1D17C}"=>220, "\u{1D17D}"=>220, "\u{1D17E}"=>220, "\u{1D17F}"=>220, "\u{1D180}"=>220, "\u{1D181}"=>220, "\u{1D182}"=>220, "\u{1D185}"=>230, "\u{1D186}"=>230, "\u{1D187}"=>230, "\u{1D188}"=>230, "\u{1D189}"=>230, "\u{1D18A}"=>220, "\u{1D18B}"=>220, "\u{1D1AA}"=>230, "\u{1D1AB}"=>230, "\u{1D1AC}"=>230, "\u{1D1AD}"=>230, "\u{1D242}"=>230, "\u{1D243}"=>230, "\u{1D244}"=>230, "\u{1E8D0}"=>220, "\u{1E8D1}"=>220, "\u{1E8D2}"=>220, "\u{1E8D3}"=>220, "\u{1E8D4}"=>220, "\u{1E8D5}"=>220, "\u{1E8D6}"=>220, } class_table.default = 0 CLASS_TABLE = class_table.freeze DECOMPOSITION_TABLE = { "\u00C0"=>"A\u0300".freeze, "\u00C1"=>"A\u0301".freeze, "\u00C2"=>"A\u0302".freeze, "\u00C3"=>"A\u0303".freeze, "\u00C4"=>"A\u0308".freeze, "\u00C5"=>"A\u030A".freeze, "\u00C7"=>"C\u0327".freeze, "\u00C8"=>"E\u0300".freeze, "\u00C9"=>"E\u0301".freeze, "\u00CA"=>"E\u0302".freeze, "\u00CB"=>"E\u0308".freeze, "\u00CC"=>"I\u0300".freeze, "\u00CD"=>"I\u0301".freeze, "\u00CE"=>"I\u0302".freeze, "\u00CF"=>"I\u0308".freeze, "\u00D1"=>"N\u0303".freeze, "\u00D2"=>"O\u0300".freeze, "\u00D3"=>"O\u0301".freeze, "\u00D4"=>"O\u0302".freeze, "\u00D5"=>"O\u0303".freeze, "\u00D6"=>"O\u0308".freeze, "\u00D9"=>"U\u0300".freeze, "\u00DA"=>"U\u0301".freeze, "\u00DB"=>"U\u0302".freeze, "\u00DC"=>"U\u0308".freeze, "\u00DD"=>"Y\u0301".freeze, "\u00E0"=>"a\u0300".freeze, "\u00E1"=>"a\u0301".freeze, "\u00E2"=>"a\u0302".freeze, "\u00E3"=>"a\u0303".freeze, "\u00E4"=>"a\u0308".freeze, "\u00E5"=>"a\u030A".freeze, "\u00E7"=>"c\u0327".freeze, "\u00E8"=>"e\u0300".freeze, "\u00E9"=>"e\u0301".freeze, "\u00EA"=>"e\u0302".freeze, "\u00EB"=>"e\u0308".freeze, "\u00EC"=>"i\u0300".freeze, "\u00ED"=>"i\u0301".freeze, "\u00EE"=>"i\u0302".freeze, "\u00EF"=>"i\u0308".freeze, "\u00F1"=>"n\u0303".freeze, "\u00F2"=>"o\u0300".freeze, "\u00F3"=>"o\u0301".freeze, "\u00F4"=>"o\u0302".freeze, "\u00F5"=>"o\u0303".freeze, "\u00F6"=>"o\u0308".freeze, "\u00F9"=>"u\u0300".freeze, "\u00FA"=>"u\u0301".freeze, "\u00FB"=>"u\u0302".freeze, "\u00FC"=>"u\u0308".freeze, "\u00FD"=>"y\u0301".freeze, "\u00FF"=>"y\u0308".freeze, "\u0100"=>"A\u0304".freeze, "\u0101"=>"a\u0304".freeze, "\u0102"=>"A\u0306".freeze, "\u0103"=>"a\u0306".freeze, "\u0104"=>"A\u0328".freeze, "\u0105"=>"a\u0328".freeze, "\u0106"=>"C\u0301".freeze, "\u0107"=>"c\u0301".freeze, "\u0108"=>"C\u0302".freeze, "\u0109"=>"c\u0302".freeze, "\u010A"=>"C\u0307".freeze, "\u010B"=>"c\u0307".freeze, "\u010C"=>"C\u030C".freeze, "\u010D"=>"c\u030C".freeze, "\u010E"=>"D\u030C".freeze, "\u010F"=>"d\u030C".freeze, "\u0112"=>"E\u0304".freeze, "\u0113"=>"e\u0304".freeze, "\u0114"=>"E\u0306".freeze, "\u0115"=>"e\u0306".freeze, "\u0116"=>"E\u0307".freeze, "\u0117"=>"e\u0307".freeze, "\u0118"=>"E\u0328".freeze, "\u0119"=>"e\u0328".freeze, "\u011A"=>"E\u030C".freeze, "\u011B"=>"e\u030C".freeze, "\u011C"=>"G\u0302".freeze, "\u011D"=>"g\u0302".freeze, "\u011E"=>"G\u0306".freeze, "\u011F"=>"g\u0306".freeze, "\u0120"=>"G\u0307".freeze, "\u0121"=>"g\u0307".freeze, "\u0122"=>"G\u0327".freeze, "\u0123"=>"g\u0327".freeze, "\u0124"=>"H\u0302".freeze, "\u0125"=>"h\u0302".freeze, "\u0128"=>"I\u0303".freeze, "\u0129"=>"i\u0303".freeze, "\u012A"=>"I\u0304".freeze, "\u012B"=>"i\u0304".freeze, "\u012C"=>"I\u0306".freeze, "\u012D"=>"i\u0306".freeze, "\u012E"=>"I\u0328".freeze, "\u012F"=>"i\u0328".freeze, "\u0130"=>"I\u0307".freeze, "\u0134"=>"J\u0302".freeze, "\u0135"=>"j\u0302".freeze, "\u0136"=>"K\u0327".freeze, "\u0137"=>"k\u0327".freeze, "\u0139"=>"L\u0301".freeze, "\u013A"=>"l\u0301".freeze, "\u013B"=>"L\u0327".freeze, "\u013C"=>"l\u0327".freeze, "\u013D"=>"L\u030C".freeze, "\u013E"=>"l\u030C".freeze, "\u0143"=>"N\u0301".freeze, "\u0144"=>"n\u0301".freeze, "\u0145"=>"N\u0327".freeze, "\u0146"=>"n\u0327".freeze, "\u0147"=>"N\u030C".freeze, "\u0148"=>"n\u030C".freeze, "\u014C"=>"O\u0304".freeze, "\u014D"=>"o\u0304".freeze, "\u014E"=>"O\u0306".freeze, "\u014F"=>"o\u0306".freeze, "\u0150"=>"O\u030B".freeze, "\u0151"=>"o\u030B".freeze, "\u0154"=>"R\u0301".freeze, "\u0155"=>"r\u0301".freeze, "\u0156"=>"R\u0327".freeze, "\u0157"=>"r\u0327".freeze, "\u0158"=>"R\u030C".freeze, "\u0159"=>"r\u030C".freeze, "\u015A"=>"S\u0301".freeze, "\u015B"=>"s\u0301".freeze, "\u015C"=>"S\u0302".freeze, "\u015D"=>"s\u0302".freeze, "\u015E"=>"S\u0327".freeze, "\u015F"=>"s\u0327".freeze, "\u0160"=>"S\u030C".freeze, "\u0161"=>"s\u030C".freeze, "\u0162"=>"T\u0327".freeze, "\u0163"=>"t\u0327".freeze, "\u0164"=>"T\u030C".freeze, "\u0165"=>"t\u030C".freeze, "\u0168"=>"U\u0303".freeze, "\u0169"=>"u\u0303".freeze, "\u016A"=>"U\u0304".freeze, "\u016B"=>"u\u0304".freeze, "\u016C"=>"U\u0306".freeze, "\u016D"=>"u\u0306".freeze, "\u016E"=>"U\u030A".freeze, "\u016F"=>"u\u030A".freeze, "\u0170"=>"U\u030B".freeze, "\u0171"=>"u\u030B".freeze, "\u0172"=>"U\u0328".freeze, "\u0173"=>"u\u0328".freeze, "\u0174"=>"W\u0302".freeze, "\u0175"=>"w\u0302".freeze, "\u0176"=>"Y\u0302".freeze, "\u0177"=>"y\u0302".freeze, "\u0178"=>"Y\u0308".freeze, "\u0179"=>"Z\u0301".freeze, "\u017A"=>"z\u0301".freeze, "\u017B"=>"Z\u0307".freeze, "\u017C"=>"z\u0307".freeze, "\u017D"=>"Z\u030C".freeze, "\u017E"=>"z\u030C".freeze, "\u01A0"=>"O\u031B".freeze, "\u01A1"=>"o\u031B".freeze, "\u01AF"=>"U\u031B".freeze, "\u01B0"=>"u\u031B".freeze, "\u01CD"=>"A\u030C".freeze, "\u01CE"=>"a\u030C".freeze, "\u01CF"=>"I\u030C".freeze, "\u01D0"=>"i\u030C".freeze, "\u01D1"=>"O\u030C".freeze, "\u01D2"=>"o\u030C".freeze, "\u01D3"=>"U\u030C".freeze, "\u01D4"=>"u\u030C".freeze, "\u01D5"=>"U\u0308\u0304".freeze, "\u01D6"=>"u\u0308\u0304".freeze, "\u01D7"=>"U\u0308\u0301".freeze, "\u01D8"=>"u\u0308\u0301".freeze, "\u01D9"=>"U\u0308\u030C".freeze, "\u01DA"=>"u\u0308\u030C".freeze, "\u01DB"=>"U\u0308\u0300".freeze, "\u01DC"=>"u\u0308\u0300".freeze, "\u01DE"=>"A\u0308\u0304".freeze, "\u01DF"=>"a\u0308\u0304".freeze, "\u01E0"=>"A\u0307\u0304".freeze, "\u01E1"=>"a\u0307\u0304".freeze, "\u01E2"=>"\u00C6\u0304".freeze, "\u01E3"=>"\u00E6\u0304".freeze, "\u01E6"=>"G\u030C".freeze, "\u01E7"=>"g\u030C".freeze, "\u01E8"=>"K\u030C".freeze, "\u01E9"=>"k\u030C".freeze, "\u01EA"=>"O\u0328".freeze, "\u01EB"=>"o\u0328".freeze, "\u01EC"=>"O\u0328\u0304".freeze, "\u01ED"=>"o\u0328\u0304".freeze, "\u01EE"=>"\u01B7\u030C".freeze, "\u01EF"=>"\u0292\u030C".freeze, "\u01F0"=>"j\u030C".freeze, "\u01F4"=>"G\u0301".freeze, "\u01F5"=>"g\u0301".freeze, "\u01F8"=>"N\u0300".freeze, "\u01F9"=>"n\u0300".freeze, "\u01FA"=>"A\u030A\u0301".freeze, "\u01FB"=>"a\u030A\u0301".freeze, "\u01FC"=>"\u00C6\u0301".freeze, "\u01FD"=>"\u00E6\u0301".freeze, "\u01FE"=>"\u00D8\u0301".freeze, "\u01FF"=>"\u00F8\u0301".freeze, "\u0200"=>"A\u030F".freeze, "\u0201"=>"a\u030F".freeze, "\u0202"=>"A\u0311".freeze, "\u0203"=>"a\u0311".freeze, "\u0204"=>"E\u030F".freeze, "\u0205"=>"e\u030F".freeze, "\u0206"=>"E\u0311".freeze, "\u0207"=>"e\u0311".freeze, "\u0208"=>"I\u030F".freeze, "\u0209"=>"i\u030F".freeze, "\u020A"=>"I\u0311".freeze, "\u020B"=>"i\u0311".freeze, "\u020C"=>"O\u030F".freeze, "\u020D"=>"o\u030F".freeze, "\u020E"=>"O\u0311".freeze, "\u020F"=>"o\u0311".freeze, "\u0210"=>"R\u030F".freeze, "\u0211"=>"r\u030F".freeze, "\u0212"=>"R\u0311".freeze, "\u0213"=>"r\u0311".freeze, "\u0214"=>"U\u030F".freeze, "\u0215"=>"u\u030F".freeze, "\u0216"=>"U\u0311".freeze, "\u0217"=>"u\u0311".freeze, "\u0218"=>"S\u0326".freeze, "\u0219"=>"s\u0326".freeze, "\u021A"=>"T\u0326".freeze, "\u021B"=>"t\u0326".freeze, "\u021E"=>"H\u030C".freeze, "\u021F"=>"h\u030C".freeze, "\u0226"=>"A\u0307".freeze, "\u0227"=>"a\u0307".freeze, "\u0228"=>"E\u0327".freeze, "\u0229"=>"e\u0327".freeze, "\u022A"=>"O\u0308\u0304".freeze, "\u022B"=>"o\u0308\u0304".freeze, "\u022C"=>"O\u0303\u0304".freeze, "\u022D"=>"o\u0303\u0304".freeze, "\u022E"=>"O\u0307".freeze, "\u022F"=>"o\u0307".freeze, "\u0230"=>"O\u0307\u0304".freeze, "\u0231"=>"o\u0307\u0304".freeze, "\u0232"=>"Y\u0304".freeze, "\u0233"=>"y\u0304".freeze, "\u0340"=>"\u0300".freeze, "\u0341"=>"\u0301".freeze, "\u0343"=>"\u0313".freeze, "\u0344"=>"\u0308\u0301".freeze, "\u0374"=>"\u02B9".freeze, "\u037E"=>";".freeze, "\u0385"=>"\u00A8\u0301".freeze, "\u0386"=>"\u0391\u0301".freeze, "\u0387"=>"\u00B7".freeze, "\u0388"=>"\u0395\u0301".freeze, "\u0389"=>"\u0397\u0301".freeze, "\u038A"=>"\u0399\u0301".freeze, "\u038C"=>"\u039F\u0301".freeze, "\u038E"=>"\u03A5\u0301".freeze, "\u038F"=>"\u03A9\u0301".freeze, "\u0390"=>"\u03B9\u0308\u0301".freeze, "\u03AA"=>"\u0399\u0308".freeze, "\u03AB"=>"\u03A5\u0308".freeze, "\u03AC"=>"\u03B1\u0301".freeze, "\u03AD"=>"\u03B5\u0301".freeze, "\u03AE"=>"\u03B7\u0301".freeze, "\u03AF"=>"\u03B9\u0301".freeze, "\u03B0"=>"\u03C5\u0308\u0301".freeze, "\u03CA"=>"\u03B9\u0308".freeze, "\u03CB"=>"\u03C5\u0308".freeze, "\u03CC"=>"\u03BF\u0301".freeze, "\u03CD"=>"\u03C5\u0301".freeze, "\u03CE"=>"\u03C9\u0301".freeze, "\u03D3"=>"\u03D2\u0301".freeze, "\u03D4"=>"\u03D2\u0308".freeze, "\u0400"=>"\u0415\u0300".freeze, "\u0401"=>"\u0415\u0308".freeze, "\u0403"=>"\u0413\u0301".freeze, "\u0407"=>"\u0406\u0308".freeze, "\u040C"=>"\u041A\u0301".freeze, "\u040D"=>"\u0418\u0300".freeze, "\u040E"=>"\u0423\u0306".freeze, "\u0419"=>"\u0418\u0306".freeze, "\u0439"=>"\u0438\u0306".freeze, "\u0450"=>"\u0435\u0300".freeze, "\u0451"=>"\u0435\u0308".freeze, "\u0453"=>"\u0433\u0301".freeze, "\u0457"=>"\u0456\u0308".freeze, "\u045C"=>"\u043A\u0301".freeze, "\u045D"=>"\u0438\u0300".freeze, "\u045E"=>"\u0443\u0306".freeze, "\u0476"=>"\u0474\u030F".freeze, "\u0477"=>"\u0475\u030F".freeze, "\u04C1"=>"\u0416\u0306".freeze, "\u04C2"=>"\u0436\u0306".freeze, "\u04D0"=>"\u0410\u0306".freeze, "\u04D1"=>"\u0430\u0306".freeze, "\u04D2"=>"\u0410\u0308".freeze, "\u04D3"=>"\u0430\u0308".freeze, "\u04D6"=>"\u0415\u0306".freeze, "\u04D7"=>"\u0435\u0306".freeze, "\u04DA"=>"\u04D8\u0308".freeze, "\u04DB"=>"\u04D9\u0308".freeze, "\u04DC"=>"\u0416\u0308".freeze, "\u04DD"=>"\u0436\u0308".freeze, "\u04DE"=>"\u0417\u0308".freeze, "\u04DF"=>"\u0437\u0308".freeze, "\u04E2"=>"\u0418\u0304".freeze, "\u04E3"=>"\u0438\u0304".freeze, "\u04E4"=>"\u0418\u0308".freeze, "\u04E5"=>"\u0438\u0308".freeze, "\u04E6"=>"\u041E\u0308".freeze, "\u04E7"=>"\u043E\u0308".freeze, "\u04EA"=>"\u04E8\u0308".freeze, "\u04EB"=>"\u04E9\u0308".freeze, "\u04EC"=>"\u042D\u0308".freeze, "\u04ED"=>"\u044D\u0308".freeze, "\u04EE"=>"\u0423\u0304".freeze, "\u04EF"=>"\u0443\u0304".freeze, "\u04F0"=>"\u0423\u0308".freeze, "\u04F1"=>"\u0443\u0308".freeze, "\u04F2"=>"\u0423\u030B".freeze, "\u04F3"=>"\u0443\u030B".freeze, "\u04F4"=>"\u0427\u0308".freeze, "\u04F5"=>"\u0447\u0308".freeze, "\u04F8"=>"\u042B\u0308".freeze, "\u04F9"=>"\u044B\u0308".freeze, "\u0622"=>"\u0627\u0653".freeze, "\u0623"=>"\u0627\u0654".freeze, "\u0624"=>"\u0648\u0654".freeze, "\u0625"=>"\u0627\u0655".freeze, "\u0626"=>"\u064A\u0654".freeze, "\u06C0"=>"\u06D5\u0654".freeze, "\u06C2"=>"\u06C1\u0654".freeze, "\u06D3"=>"\u06D2\u0654".freeze, "\u0929"=>"\u0928\u093C".freeze, "\u0931"=>"\u0930\u093C".freeze, "\u0934"=>"\u0933\u093C".freeze, "\u0958"=>"\u0915\u093C".freeze, "\u0959"=>"\u0916\u093C".freeze, "\u095A"=>"\u0917\u093C".freeze, "\u095B"=>"\u091C\u093C".freeze, "\u095C"=>"\u0921\u093C".freeze, "\u095D"=>"\u0922\u093C".freeze, "\u095E"=>"\u092B\u093C".freeze, "\u095F"=>"\u092F\u093C".freeze, "\u09CB"=>"\u09C7\u09BE".freeze, "\u09CC"=>"\u09C7\u09D7".freeze, "\u09DC"=>"\u09A1\u09BC".freeze, "\u09DD"=>"\u09A2\u09BC".freeze, "\u09DF"=>"\u09AF\u09BC".freeze, "\u0A33"=>"\u0A32\u0A3C".freeze, "\u0A36"=>"\u0A38\u0A3C".freeze, "\u0A59"=>"\u0A16\u0A3C".freeze, "\u0A5A"=>"\u0A17\u0A3C".freeze, "\u0A5B"=>"\u0A1C\u0A3C".freeze, "\u0A5E"=>"\u0A2B\u0A3C".freeze, "\u0B48"=>"\u0B47\u0B56".freeze, "\u0B4B"=>"\u0B47\u0B3E".freeze, "\u0B4C"=>"\u0B47\u0B57".freeze, "\u0B5C"=>"\u0B21\u0B3C".freeze, "\u0B5D"=>"\u0B22\u0B3C".freeze, "\u0B94"=>"\u0B92\u0BD7".freeze, "\u0BCA"=>"\u0BC6\u0BBE".freeze, "\u0BCB"=>"\u0BC7\u0BBE".freeze, "\u0BCC"=>"\u0BC6\u0BD7".freeze, "\u0C48"=>"\u0C46\u0C56".freeze, "\u0CC0"=>"\u0CBF\u0CD5".freeze, "\u0CC7"=>"\u0CC6\u0CD5".freeze, "\u0CC8"=>"\u0CC6\u0CD6".freeze, "\u0CCA"=>"\u0CC6\u0CC2".freeze, "\u0CCB"=>"\u0CC6\u0CC2\u0CD5".freeze, "\u0D4A"=>"\u0D46\u0D3E".freeze, "\u0D4B"=>"\u0D47\u0D3E".freeze, "\u0D4C"=>"\u0D46\u0D57".freeze, "\u0DDA"=>"\u0DD9\u0DCA".freeze, "\u0DDC"=>"\u0DD9\u0DCF".freeze, "\u0DDD"=>"\u0DD9\u0DCF\u0DCA".freeze, "\u0DDE"=>"\u0DD9\u0DDF".freeze, "\u0F43"=>"\u0F42\u0FB7".freeze, "\u0F4D"=>"\u0F4C\u0FB7".freeze, "\u0F52"=>"\u0F51\u0FB7".freeze, "\u0F57"=>"\u0F56\u0FB7".freeze, "\u0F5C"=>"\u0F5B\u0FB7".freeze, "\u0F69"=>"\u0F40\u0FB5".freeze, "\u0F73"=>"\u0F71\u0F72".freeze, "\u0F75"=>"\u0F71\u0F74".freeze, "\u0F76"=>"\u0FB2\u0F80".freeze, "\u0F78"=>"\u0FB3\u0F80".freeze, "\u0F81"=>"\u0F71\u0F80".freeze, "\u0F93"=>"\u0F92\u0FB7".freeze, "\u0F9D"=>"\u0F9C\u0FB7".freeze, "\u0FA2"=>"\u0FA1\u0FB7".freeze, "\u0FA7"=>"\u0FA6\u0FB7".freeze, "\u0FAC"=>"\u0FAB\u0FB7".freeze, "\u0FB9"=>"\u0F90\u0FB5".freeze, "\u1026"=>"\u1025\u102E".freeze, "\u1B06"=>"\u1B05\u1B35".freeze, "\u1B08"=>"\u1B07\u1B35".freeze, "\u1B0A"=>"\u1B09\u1B35".freeze, "\u1B0C"=>"\u1B0B\u1B35".freeze, "\u1B0E"=>"\u1B0D\u1B35".freeze, "\u1B12"=>"\u1B11\u1B35".freeze, "\u1B3B"=>"\u1B3A\u1B35".freeze, "\u1B3D"=>"\u1B3C\u1B35".freeze, "\u1B40"=>"\u1B3E\u1B35".freeze, "\u1B41"=>"\u1B3F\u1B35".freeze, "\u1B43"=>"\u1B42\u1B35".freeze, "\u1E00"=>"A\u0325".freeze, "\u1E01"=>"a\u0325".freeze, "\u1E02"=>"B\u0307".freeze, "\u1E03"=>"b\u0307".freeze, "\u1E04"=>"B\u0323".freeze, "\u1E05"=>"b\u0323".freeze, "\u1E06"=>"B\u0331".freeze, "\u1E07"=>"b\u0331".freeze, "\u1E08"=>"C\u0327\u0301".freeze, "\u1E09"=>"c\u0327\u0301".freeze, "\u1E0A"=>"D\u0307".freeze, "\u1E0B"=>"d\u0307".freeze, "\u1E0C"=>"D\u0323".freeze, "\u1E0D"=>"d\u0323".freeze, "\u1E0E"=>"D\u0331".freeze, "\u1E0F"=>"d\u0331".freeze, "\u1E10"=>"D\u0327".freeze, "\u1E11"=>"d\u0327".freeze, "\u1E12"=>"D\u032D".freeze, "\u1E13"=>"d\u032D".freeze, "\u1E14"=>"E\u0304\u0300".freeze, "\u1E15"=>"e\u0304\u0300".freeze, "\u1E16"=>"E\u0304\u0301".freeze, "\u1E17"=>"e\u0304\u0301".freeze, "\u1E18"=>"E\u032D".freeze, "\u1E19"=>"e\u032D".freeze, "\u1E1A"=>"E\u0330".freeze, "\u1E1B"=>"e\u0330".freeze, "\u1E1C"=>"E\u0327\u0306".freeze, "\u1E1D"=>"e\u0327\u0306".freeze, "\u1E1E"=>"F\u0307".freeze, "\u1E1F"=>"f\u0307".freeze, "\u1E20"=>"G\u0304".freeze, "\u1E21"=>"g\u0304".freeze, "\u1E22"=>"H\u0307".freeze, "\u1E23"=>"h\u0307".freeze, "\u1E24"=>"H\u0323".freeze, "\u1E25"=>"h\u0323".freeze, "\u1E26"=>"H\u0308".freeze, "\u1E27"=>"h\u0308".freeze, "\u1E28"=>"H\u0327".freeze, "\u1E29"=>"h\u0327".freeze, "\u1E2A"=>"H\u032E".freeze, "\u1E2B"=>"h\u032E".freeze, "\u1E2C"=>"I\u0330".freeze, "\u1E2D"=>"i\u0330".freeze, "\u1E2E"=>"I\u0308\u0301".freeze, "\u1E2F"=>"i\u0308\u0301".freeze, "\u1E30"=>"K\u0301".freeze, "\u1E31"=>"k\u0301".freeze, "\u1E32"=>"K\u0323".freeze, "\u1E33"=>"k\u0323".freeze, "\u1E34"=>"K\u0331".freeze, "\u1E35"=>"k\u0331".freeze, "\u1E36"=>"L\u0323".freeze, "\u1E37"=>"l\u0323".freeze, "\u1E38"=>"L\u0323\u0304".freeze, "\u1E39"=>"l\u0323\u0304".freeze, "\u1E3A"=>"L\u0331".freeze, "\u1E3B"=>"l\u0331".freeze, "\u1E3C"=>"L\u032D".freeze, "\u1E3D"=>"l\u032D".freeze, "\u1E3E"=>"M\u0301".freeze, "\u1E3F"=>"m\u0301".freeze, "\u1E40"=>"M\u0307".freeze, "\u1E41"=>"m\u0307".freeze, "\u1E42"=>"M\u0323".freeze, "\u1E43"=>"m\u0323".freeze, "\u1E44"=>"N\u0307".freeze, "\u1E45"=>"n\u0307".freeze, "\u1E46"=>"N\u0323".freeze, "\u1E47"=>"n\u0323".freeze, "\u1E48"=>"N\u0331".freeze, "\u1E49"=>"n\u0331".freeze, "\u1E4A"=>"N\u032D".freeze, "\u1E4B"=>"n\u032D".freeze, "\u1E4C"=>"O\u0303\u0301".freeze, "\u1E4D"=>"o\u0303\u0301".freeze, "\u1E4E"=>"O\u0303\u0308".freeze, "\u1E4F"=>"o\u0303\u0308".freeze, "\u1E50"=>"O\u0304\u0300".freeze, "\u1E51"=>"o\u0304\u0300".freeze, "\u1E52"=>"O\u0304\u0301".freeze, "\u1E53"=>"o\u0304\u0301".freeze, "\u1E54"=>"P\u0301".freeze, "\u1E55"=>"p\u0301".freeze, "\u1E56"=>"P\u0307".freeze, "\u1E57"=>"p\u0307".freeze, "\u1E58"=>"R\u0307".freeze, "\u1E59"=>"r\u0307".freeze, "\u1E5A"=>"R\u0323".freeze, "\u1E5B"=>"r\u0323".freeze, "\u1E5C"=>"R\u0323\u0304".freeze, "\u1E5D"=>"r\u0323\u0304".freeze, "\u1E5E"=>"R\u0331".freeze, "\u1E5F"=>"r\u0331".freeze, "\u1E60"=>"S\u0307".freeze, "\u1E61"=>"s\u0307".freeze, "\u1E62"=>"S\u0323".freeze, "\u1E63"=>"s\u0323".freeze, "\u1E64"=>"S\u0301\u0307".freeze, "\u1E65"=>"s\u0301\u0307".freeze, "\u1E66"=>"S\u030C\u0307".freeze, "\u1E67"=>"s\u030C\u0307".freeze, "\u1E68"=>"S\u0323\u0307".freeze, "\u1E69"=>"s\u0323\u0307".freeze, "\u1E6A"=>"T\u0307".freeze, "\u1E6B"=>"t\u0307".freeze, "\u1E6C"=>"T\u0323".freeze, "\u1E6D"=>"t\u0323".freeze, "\u1E6E"=>"T\u0331".freeze, "\u1E6F"=>"t\u0331".freeze, "\u1E70"=>"T\u032D".freeze, "\u1E71"=>"t\u032D".freeze, "\u1E72"=>"U\u0324".freeze, "\u1E73"=>"u\u0324".freeze, "\u1E74"=>"U\u0330".freeze, "\u1E75"=>"u\u0330".freeze, "\u1E76"=>"U\u032D".freeze, "\u1E77"=>"u\u032D".freeze, "\u1E78"=>"U\u0303\u0301".freeze, "\u1E79"=>"u\u0303\u0301".freeze, "\u1E7A"=>"U\u0304\u0308".freeze, "\u1E7B"=>"u\u0304\u0308".freeze, "\u1E7C"=>"V\u0303".freeze, "\u1E7D"=>"v\u0303".freeze, "\u1E7E"=>"V\u0323".freeze, "\u1E7F"=>"v\u0323".freeze, "\u1E80"=>"W\u0300".freeze, "\u1E81"=>"w\u0300".freeze, "\u1E82"=>"W\u0301".freeze, "\u1E83"=>"w\u0301".freeze, "\u1E84"=>"W\u0308".freeze, "\u1E85"=>"w\u0308".freeze, "\u1E86"=>"W\u0307".freeze, "\u1E87"=>"w\u0307".freeze, "\u1E88"=>"W\u0323".freeze, "\u1E89"=>"w\u0323".freeze, "\u1E8A"=>"X\u0307".freeze, "\u1E8B"=>"x\u0307".freeze, "\u1E8C"=>"X\u0308".freeze, "\u1E8D"=>"x\u0308".freeze, "\u1E8E"=>"Y\u0307".freeze, "\u1E8F"=>"y\u0307".freeze, "\u1E90"=>"Z\u0302".freeze, "\u1E91"=>"z\u0302".freeze, "\u1E92"=>"Z\u0323".freeze, "\u1E93"=>"z\u0323".freeze, "\u1E94"=>"Z\u0331".freeze, "\u1E95"=>"z\u0331".freeze, "\u1E96"=>"h\u0331".freeze, "\u1E97"=>"t\u0308".freeze, "\u1E98"=>"w\u030A".freeze, "\u1E99"=>"y\u030A".freeze, "\u1E9B"=>"\u017F\u0307".freeze, "\u1EA0"=>"A\u0323".freeze, "\u1EA1"=>"a\u0323".freeze, "\u1EA2"=>"A\u0309".freeze, "\u1EA3"=>"a\u0309".freeze, "\u1EA4"=>"A\u0302\u0301".freeze, "\u1EA5"=>"a\u0302\u0301".freeze, "\u1EA6"=>"A\u0302\u0300".freeze, "\u1EA7"=>"a\u0302\u0300".freeze, "\u1EA8"=>"A\u0302\u0309".freeze, "\u1EA9"=>"a\u0302\u0309".freeze, "\u1EAA"=>"A\u0302\u0303".freeze, "\u1EAB"=>"a\u0302\u0303".freeze, "\u1EAC"=>"A\u0323\u0302".freeze, "\u1EAD"=>"a\u0323\u0302".freeze, "\u1EAE"=>"A\u0306\u0301".freeze, "\u1EAF"=>"a\u0306\u0301".freeze, "\u1EB0"=>"A\u0306\u0300".freeze, "\u1EB1"=>"a\u0306\u0300".freeze, "\u1EB2"=>"A\u0306\u0309".freeze, "\u1EB3"=>"a\u0306\u0309".freeze, "\u1EB4"=>"A\u0306\u0303".freeze, "\u1EB5"=>"a\u0306\u0303".freeze, "\u1EB6"=>"A\u0323\u0306".freeze, "\u1EB7"=>"a\u0323\u0306".freeze, "\u1EB8"=>"E\u0323".freeze, "\u1EB9"=>"e\u0323".freeze, "\u1EBA"=>"E\u0309".freeze, "\u1EBB"=>"e\u0309".freeze, "\u1EBC"=>"E\u0303".freeze, "\u1EBD"=>"e\u0303".freeze, "\u1EBE"=>"E\u0302\u0301".freeze, "\u1EBF"=>"e\u0302\u0301".freeze, "\u1EC0"=>"E\u0302\u0300".freeze, "\u1EC1"=>"e\u0302\u0300".freeze, "\u1EC2"=>"E\u0302\u0309".freeze, "\u1EC3"=>"e\u0302\u0309".freeze, "\u1EC4"=>"E\u0302\u0303".freeze, "\u1EC5"=>"e\u0302\u0303".freeze, "\u1EC6"=>"E\u0323\u0302".freeze, "\u1EC7"=>"e\u0323\u0302".freeze, "\u1EC8"=>"I\u0309".freeze, "\u1EC9"=>"i\u0309".freeze, "\u1ECA"=>"I\u0323".freeze, "\u1ECB"=>"i\u0323".freeze, "\u1ECC"=>"O\u0323".freeze, "\u1ECD"=>"o\u0323".freeze, "\u1ECE"=>"O\u0309".freeze, "\u1ECF"=>"o\u0309".freeze, "\u1ED0"=>"O\u0302\u0301".freeze, "\u1ED1"=>"o\u0302\u0301".freeze, "\u1ED2"=>"O\u0302\u0300".freeze, "\u1ED3"=>"o\u0302\u0300".freeze, "\u1ED4"=>"O\u0302\u0309".freeze, "\u1ED5"=>"o\u0302\u0309".freeze, "\u1ED6"=>"O\u0302\u0303".freeze, "\u1ED7"=>"o\u0302\u0303".freeze, "\u1ED8"=>"O\u0323\u0302".freeze, "\u1ED9"=>"o\u0323\u0302".freeze, "\u1EDA"=>"O\u031B\u0301".freeze, "\u1EDB"=>"o\u031B\u0301".freeze, "\u1EDC"=>"O\u031B\u0300".freeze, "\u1EDD"=>"o\u031B\u0300".freeze, "\u1EDE"=>"O\u031B\u0309".freeze, "\u1EDF"=>"o\u031B\u0309".freeze, "\u1EE0"=>"O\u031B\u0303".freeze, "\u1EE1"=>"o\u031B\u0303".freeze, "\u1EE2"=>"O\u031B\u0323".freeze, "\u1EE3"=>"o\u031B\u0323".freeze, "\u1EE4"=>"U\u0323".freeze, "\u1EE5"=>"u\u0323".freeze, "\u1EE6"=>"U\u0309".freeze, "\u1EE7"=>"u\u0309".freeze, "\u1EE8"=>"U\u031B\u0301".freeze, "\u1EE9"=>"u\u031B\u0301".freeze, "\u1EEA"=>"U\u031B\u0300".freeze, "\u1EEB"=>"u\u031B\u0300".freeze, "\u1EEC"=>"U\u031B\u0309".freeze, "\u1EED"=>"u\u031B\u0309".freeze, "\u1EEE"=>"U\u031B\u0303".freeze, "\u1EEF"=>"u\u031B\u0303".freeze, "\u1EF0"=>"U\u031B\u0323".freeze, "\u1EF1"=>"u\u031B\u0323".freeze, "\u1EF2"=>"Y\u0300".freeze, "\u1EF3"=>"y\u0300".freeze, "\u1EF4"=>"Y\u0323".freeze, "\u1EF5"=>"y\u0323".freeze, "\u1EF6"=>"Y\u0309".freeze, "\u1EF7"=>"y\u0309".freeze, "\u1EF8"=>"Y\u0303".freeze, "\u1EF9"=>"y\u0303".freeze, "\u1F00"=>"\u03B1\u0313".freeze, "\u1F01"=>"\u03B1\u0314".freeze, "\u1F02"=>"\u03B1\u0313\u0300".freeze, "\u1F03"=>"\u03B1\u0314\u0300".freeze, "\u1F04"=>"\u03B1\u0313\u0301".freeze, "\u1F05"=>"\u03B1\u0314\u0301".freeze, "\u1F06"=>"\u03B1\u0313\u0342".freeze, "\u1F07"=>"\u03B1\u0314\u0342".freeze, "\u1F08"=>"\u0391\u0313".freeze, "\u1F09"=>"\u0391\u0314".freeze, "\u1F0A"=>"\u0391\u0313\u0300".freeze, "\u1F0B"=>"\u0391\u0314\u0300".freeze, "\u1F0C"=>"\u0391\u0313\u0301".freeze, "\u1F0D"=>"\u0391\u0314\u0301".freeze, "\u1F0E"=>"\u0391\u0313\u0342".freeze, "\u1F0F"=>"\u0391\u0314\u0342".freeze, "\u1F10"=>"\u03B5\u0313".freeze, "\u1F11"=>"\u03B5\u0314".freeze, "\u1F12"=>"\u03B5\u0313\u0300".freeze, "\u1F13"=>"\u03B5\u0314\u0300".freeze, "\u1F14"=>"\u03B5\u0313\u0301".freeze, "\u1F15"=>"\u03B5\u0314\u0301".freeze, "\u1F18"=>"\u0395\u0313".freeze, "\u1F19"=>"\u0395\u0314".freeze, "\u1F1A"=>"\u0395\u0313\u0300".freeze, "\u1F1B"=>"\u0395\u0314\u0300".freeze, "\u1F1C"=>"\u0395\u0313\u0301".freeze, "\u1F1D"=>"\u0395\u0314\u0301".freeze, "\u1F20"=>"\u03B7\u0313".freeze, "\u1F21"=>"\u03B7\u0314".freeze, "\u1F22"=>"\u03B7\u0313\u0300".freeze, "\u1F23"=>"\u03B7\u0314\u0300".freeze, "\u1F24"=>"\u03B7\u0313\u0301".freeze, "\u1F25"=>"\u03B7\u0314\u0301".freeze, "\u1F26"=>"\u03B7\u0313\u0342".freeze, "\u1F27"=>"\u03B7\u0314\u0342".freeze, "\u1F28"=>"\u0397\u0313".freeze, "\u1F29"=>"\u0397\u0314".freeze, "\u1F2A"=>"\u0397\u0313\u0300".freeze, "\u1F2B"=>"\u0397\u0314\u0300".freeze, "\u1F2C"=>"\u0397\u0313\u0301".freeze, "\u1F2D"=>"\u0397\u0314\u0301".freeze, "\u1F2E"=>"\u0397\u0313\u0342".freeze, "\u1F2F"=>"\u0397\u0314\u0342".freeze, "\u1F30"=>"\u03B9\u0313".freeze, "\u1F31"=>"\u03B9\u0314".freeze, "\u1F32"=>"\u03B9\u0313\u0300".freeze, "\u1F33"=>"\u03B9\u0314\u0300".freeze, "\u1F34"=>"\u03B9\u0313\u0301".freeze, "\u1F35"=>"\u03B9\u0314\u0301".freeze, "\u1F36"=>"\u03B9\u0313\u0342".freeze, "\u1F37"=>"\u03B9\u0314\u0342".freeze, "\u1F38"=>"\u0399\u0313".freeze, "\u1F39"=>"\u0399\u0314".freeze, "\u1F3A"=>"\u0399\u0313\u0300".freeze, "\u1F3B"=>"\u0399\u0314\u0300".freeze, "\u1F3C"=>"\u0399\u0313\u0301".freeze, "\u1F3D"=>"\u0399\u0314\u0301".freeze, "\u1F3E"=>"\u0399\u0313\u0342".freeze, "\u1F3F"=>"\u0399\u0314\u0342".freeze, "\u1F40"=>"\u03BF\u0313".freeze, "\u1F41"=>"\u03BF\u0314".freeze, "\u1F42"=>"\u03BF\u0313\u0300".freeze, "\u1F43"=>"\u03BF\u0314\u0300".freeze, "\u1F44"=>"\u03BF\u0313\u0301".freeze, "\u1F45"=>"\u03BF\u0314\u0301".freeze, "\u1F48"=>"\u039F\u0313".freeze, "\u1F49"=>"\u039F\u0314".freeze, "\u1F4A"=>"\u039F\u0313\u0300".freeze, "\u1F4B"=>"\u039F\u0314\u0300".freeze, "\u1F4C"=>"\u039F\u0313\u0301".freeze, "\u1F4D"=>"\u039F\u0314\u0301".freeze, "\u1F50"=>"\u03C5\u0313".freeze, "\u1F51"=>"\u03C5\u0314".freeze, "\u1F52"=>"\u03C5\u0313\u0300".freeze, "\u1F53"=>"\u03C5\u0314\u0300".freeze, "\u1F54"=>"\u03C5\u0313\u0301".freeze, "\u1F55"=>"\u03C5\u0314\u0301".freeze, "\u1F56"=>"\u03C5\u0313\u0342".freeze, "\u1F57"=>"\u03C5\u0314\u0342".freeze, "\u1F59"=>"\u03A5\u0314".freeze, "\u1F5B"=>"\u03A5\u0314\u0300".freeze, "\u1F5D"=>"\u03A5\u0314\u0301".freeze, "\u1F5F"=>"\u03A5\u0314\u0342".freeze, "\u1F60"=>"\u03C9\u0313".freeze, "\u1F61"=>"\u03C9\u0314".freeze, "\u1F62"=>"\u03C9\u0313\u0300".freeze, "\u1F63"=>"\u03C9\u0314\u0300".freeze, "\u1F64"=>"\u03C9\u0313\u0301".freeze, "\u1F65"=>"\u03C9\u0314\u0301".freeze, "\u1F66"=>"\u03C9\u0313\u0342".freeze, "\u1F67"=>"\u03C9\u0314\u0342".freeze, "\u1F68"=>"\u03A9\u0313".freeze, "\u1F69"=>"\u03A9\u0314".freeze, "\u1F6A"=>"\u03A9\u0313\u0300".freeze, "\u1F6B"=>"\u03A9\u0314\u0300".freeze, "\u1F6C"=>"\u03A9\u0313\u0301".freeze, "\u1F6D"=>"\u03A9\u0314\u0301".freeze, "\u1F6E"=>"\u03A9\u0313\u0342".freeze, "\u1F6F"=>"\u03A9\u0314\u0342".freeze, "\u1F70"=>"\u03B1\u0300".freeze, "\u1F71"=>"\u03B1\u0301".freeze, "\u1F72"=>"\u03B5\u0300".freeze, "\u1F73"=>"\u03B5\u0301".freeze, "\u1F74"=>"\u03B7\u0300".freeze, "\u1F75"=>"\u03B7\u0301".freeze, "\u1F76"=>"\u03B9\u0300".freeze, "\u1F77"=>"\u03B9\u0301".freeze, "\u1F78"=>"\u03BF\u0300".freeze, "\u1F79"=>"\u03BF\u0301".freeze, "\u1F7A"=>"\u03C5\u0300".freeze, "\u1F7B"=>"\u03C5\u0301".freeze, "\u1F7C"=>"\u03C9\u0300".freeze, "\u1F7D"=>"\u03C9\u0301".freeze, "\u1F80"=>"\u03B1\u0313\u0345".freeze, "\u1F81"=>"\u03B1\u0314\u0345".freeze, "\u1F82"=>"\u03B1\u0313\u0300\u0345".freeze, "\u1F83"=>"\u03B1\u0314\u0300\u0345".freeze, "\u1F84"=>"\u03B1\u0313\u0301\u0345".freeze, "\u1F85"=>"\u03B1\u0314\u0301\u0345".freeze, "\u1F86"=>"\u03B1\u0313\u0342\u0345".freeze, "\u1F87"=>"\u03B1\u0314\u0342\u0345".freeze, "\u1F88"=>"\u0391\u0313\u0345".freeze, "\u1F89"=>"\u0391\u0314\u0345".freeze, "\u1F8A"=>"\u0391\u0313\u0300\u0345".freeze, "\u1F8B"=>"\u0391\u0314\u0300\u0345".freeze, "\u1F8C"=>"\u0391\u0313\u0301\u0345".freeze, "\u1F8D"=>"\u0391\u0314\u0301\u0345".freeze, "\u1F8E"=>"\u0391\u0313\u0342\u0345".freeze, "\u1F8F"=>"\u0391\u0314\u0342\u0345".freeze, "\u1F90"=>"\u03B7\u0313\u0345".freeze, "\u1F91"=>"\u03B7\u0314\u0345".freeze, "\u1F92"=>"\u03B7\u0313\u0300\u0345".freeze, "\u1F93"=>"\u03B7\u0314\u0300\u0345".freeze, "\u1F94"=>"\u03B7\u0313\u0301\u0345".freeze, "\u1F95"=>"\u03B7\u0314\u0301\u0345".freeze, "\u1F96"=>"\u03B7\u0313\u0342\u0345".freeze, "\u1F97"=>"\u03B7\u0314\u0342\u0345".freeze, "\u1F98"=>"\u0397\u0313\u0345".freeze, "\u1F99"=>"\u0397\u0314\u0345".freeze, "\u1F9A"=>"\u0397\u0313\u0300\u0345".freeze, "\u1F9B"=>"\u0397\u0314\u0300\u0345".freeze, "\u1F9C"=>"\u0397\u0313\u0301\u0345".freeze, "\u1F9D"=>"\u0397\u0314\u0301\u0345".freeze, "\u1F9E"=>"\u0397\u0313\u0342\u0345".freeze, "\u1F9F"=>"\u0397\u0314\u0342\u0345".freeze, "\u1FA0"=>"\u03C9\u0313\u0345".freeze, "\u1FA1"=>"\u03C9\u0314\u0345".freeze, "\u1FA2"=>"\u03C9\u0313\u0300\u0345".freeze, "\u1FA3"=>"\u03C9\u0314\u0300\u0345".freeze, "\u1FA4"=>"\u03C9\u0313\u0301\u0345".freeze, "\u1FA5"=>"\u03C9\u0314\u0301\u0345".freeze, "\u1FA6"=>"\u03C9\u0313\u0342\u0345".freeze, "\u1FA7"=>"\u03C9\u0314\u0342\u0345".freeze, "\u1FA8"=>"\u03A9\u0313\u0345".freeze, "\u1FA9"=>"\u03A9\u0314\u0345".freeze, "\u1FAA"=>"\u03A9\u0313\u0300\u0345".freeze, "\u1FAB"=>"\u03A9\u0314\u0300\u0345".freeze, "\u1FAC"=>"\u03A9\u0313\u0301\u0345".freeze, "\u1FAD"=>"\u03A9\u0314\u0301\u0345".freeze, "\u1FAE"=>"\u03A9\u0313\u0342\u0345".freeze, "\u1FAF"=>"\u03A9\u0314\u0342\u0345".freeze, "\u1FB0"=>"\u03B1\u0306".freeze, "\u1FB1"=>"\u03B1\u0304".freeze, "\u1FB2"=>"\u03B1\u0300\u0345".freeze, "\u1FB3"=>"\u03B1\u0345".freeze, "\u1FB4"=>"\u03B1\u0301\u0345".freeze, "\u1FB6"=>"\u03B1\u0342".freeze, "\u1FB7"=>"\u03B1\u0342\u0345".freeze, "\u1FB8"=>"\u0391\u0306".freeze, "\u1FB9"=>"\u0391\u0304".freeze, "\u1FBA"=>"\u0391\u0300".freeze, "\u1FBB"=>"\u0391\u0301".freeze, "\u1FBC"=>"\u0391\u0345".freeze, "\u1FBE"=>"\u03B9".freeze, "\u1FC1"=>"\u00A8\u0342".freeze, "\u1FC2"=>"\u03B7\u0300\u0345".freeze, "\u1FC3"=>"\u03B7\u0345".freeze, "\u1FC4"=>"\u03B7\u0301\u0345".freeze, "\u1FC6"=>"\u03B7\u0342".freeze, "\u1FC7"=>"\u03B7\u0342\u0345".freeze, "\u1FC8"=>"\u0395\u0300".freeze, "\u1FC9"=>"\u0395\u0301".freeze, "\u1FCA"=>"\u0397\u0300".freeze, "\u1FCB"=>"\u0397\u0301".freeze, "\u1FCC"=>"\u0397\u0345".freeze, "\u1FCD"=>"\u1FBF\u0300".freeze, "\u1FCE"=>"\u1FBF\u0301".freeze, "\u1FCF"=>"\u1FBF\u0342".freeze, "\u1FD0"=>"\u03B9\u0306".freeze, "\u1FD1"=>"\u03B9\u0304".freeze, "\u1FD2"=>"\u03B9\u0308\u0300".freeze, "\u1FD3"=>"\u03B9\u0308\u0301".freeze, "\u1FD6"=>"\u03B9\u0342".freeze, "\u1FD7"=>"\u03B9\u0308\u0342".freeze, "\u1FD8"=>"\u0399\u0306".freeze, "\u1FD9"=>"\u0399\u0304".freeze, "\u1FDA"=>"\u0399\u0300".freeze, "\u1FDB"=>"\u0399\u0301".freeze, "\u1FDD"=>"\u1FFE\u0300".freeze, "\u1FDE"=>"\u1FFE\u0301".freeze, "\u1FDF"=>"\u1FFE\u0342".freeze, "\u1FE0"=>"\u03C5\u0306".freeze, "\u1FE1"=>"\u03C5\u0304".freeze, "\u1FE2"=>"\u03C5\u0308\u0300".freeze, "\u1FE3"=>"\u03C5\u0308\u0301".freeze, "\u1FE4"=>"\u03C1\u0313".freeze, "\u1FE5"=>"\u03C1\u0314".freeze, "\u1FE6"=>"\u03C5\u0342".freeze, "\u1FE7"=>"\u03C5\u0308\u0342".freeze, "\u1FE8"=>"\u03A5\u0306".freeze, "\u1FE9"=>"\u03A5\u0304".freeze, "\u1FEA"=>"\u03A5\u0300".freeze, "\u1FEB"=>"\u03A5\u0301".freeze, "\u1FEC"=>"\u03A1\u0314".freeze, "\u1FED"=>"\u00A8\u0300".freeze, "\u1FEE"=>"\u00A8\u0301".freeze, "\u1FEF"=>"`".freeze, "\u1FF2"=>"\u03C9\u0300\u0345".freeze, "\u1FF3"=>"\u03C9\u0345".freeze, "\u1FF4"=>"\u03C9\u0301\u0345".freeze, "\u1FF6"=>"\u03C9\u0342".freeze, "\u1FF7"=>"\u03C9\u0342\u0345".freeze, "\u1FF8"=>"\u039F\u0300".freeze, "\u1FF9"=>"\u039F\u0301".freeze, "\u1FFA"=>"\u03A9\u0300".freeze, "\u1FFB"=>"\u03A9\u0301".freeze, "\u1FFC"=>"\u03A9\u0345".freeze, "\u1FFD"=>"\u00B4".freeze, "\u2000"=>"\u2002".freeze, "\u2001"=>"\u2003".freeze, "\u2126"=>"\u03A9".freeze, "\u212A"=>"K".freeze, "\u212B"=>"A\u030A".freeze, "\u219A"=>"\u2190\u0338".freeze, "\u219B"=>"\u2192\u0338".freeze, "\u21AE"=>"\u2194\u0338".freeze, "\u21CD"=>"\u21D0\u0338".freeze, "\u21CE"=>"\u21D4\u0338".freeze, "\u21CF"=>"\u21D2\u0338".freeze, "\u2204"=>"\u2203\u0338".freeze, "\u2209"=>"\u2208\u0338".freeze, "\u220C"=>"\u220B\u0338".freeze, "\u2224"=>"\u2223\u0338".freeze, "\u2226"=>"\u2225\u0338".freeze, "\u2241"=>"\u223C\u0338".freeze, "\u2244"=>"\u2243\u0338".freeze, "\u2247"=>"\u2245\u0338".freeze, "\u2249"=>"\u2248\u0338".freeze, "\u2260"=>"=\u0338".freeze, "\u2262"=>"\u2261\u0338".freeze, "\u226D"=>"\u224D\u0338".freeze, "\u226E"=>"<\u0338".freeze, "\u226F"=>">\u0338".freeze, "\u2270"=>"\u2264\u0338".freeze, "\u2271"=>"\u2265\u0338".freeze, "\u2274"=>"\u2272\u0338".freeze, "\u2275"=>"\u2273\u0338".freeze, "\u2278"=>"\u2276\u0338".freeze, "\u2279"=>"\u2277\u0338".freeze, "\u2280"=>"\u227A\u0338".freeze, "\u2281"=>"\u227B\u0338".freeze, "\u2284"=>"\u2282\u0338".freeze, "\u2285"=>"\u2283\u0338".freeze, "\u2288"=>"\u2286\u0338".freeze, "\u2289"=>"\u2287\u0338".freeze, "\u22AC"=>"\u22A2\u0338".freeze, "\u22AD"=>"\u22A8\u0338".freeze, "\u22AE"=>"\u22A9\u0338".freeze, "\u22AF"=>"\u22AB\u0338".freeze, "\u22E0"=>"\u227C\u0338".freeze, "\u22E1"=>"\u227D\u0338".freeze, "\u22E2"=>"\u2291\u0338".freeze, "\u22E3"=>"\u2292\u0338".freeze, "\u22EA"=>"\u22B2\u0338".freeze, "\u22EB"=>"\u22B3\u0338".freeze, "\u22EC"=>"\u22B4\u0338".freeze, "\u22ED"=>"\u22B5\u0338".freeze, "\u2329"=>"\u3008".freeze, "\u232A"=>"\u3009".freeze, "\u2ADC"=>"\u2ADD\u0338".freeze, "\u304C"=>"\u304B\u3099".freeze, "\u304E"=>"\u304D\u3099".freeze, "\u3050"=>"\u304F\u3099".freeze, "\u3052"=>"\u3051\u3099".freeze, "\u3054"=>"\u3053\u3099".freeze, "\u3056"=>"\u3055\u3099".freeze, "\u3058"=>"\u3057\u3099".freeze, "\u305A"=>"\u3059\u3099".freeze, "\u305C"=>"\u305B\u3099".freeze, "\u305E"=>"\u305D\u3099".freeze, "\u3060"=>"\u305F\u3099".freeze, "\u3062"=>"\u3061\u3099".freeze, "\u3065"=>"\u3064\u3099".freeze, "\u3067"=>"\u3066\u3099".freeze, "\u3069"=>"\u3068\u3099".freeze, "\u3070"=>"\u306F\u3099".freeze, "\u3071"=>"\u306F\u309A".freeze, "\u3073"=>"\u3072\u3099".freeze, "\u3074"=>"\u3072\u309A".freeze, "\u3076"=>"\u3075\u3099".freeze, "\u3077"=>"\u3075\u309A".freeze, "\u3079"=>"\u3078\u3099".freeze, "\u307A"=>"\u3078\u309A".freeze, "\u307C"=>"\u307B\u3099".freeze, "\u307D"=>"\u307B\u309A".freeze, "\u3094"=>"\u3046\u3099".freeze, "\u309E"=>"\u309D\u3099".freeze, "\u30AC"=>"\u30AB\u3099".freeze, "\u30AE"=>"\u30AD\u3099".freeze, "\u30B0"=>"\u30AF\u3099".freeze, "\u30B2"=>"\u30B1\u3099".freeze, "\u30B4"=>"\u30B3\u3099".freeze, "\u30B6"=>"\u30B5\u3099".freeze, "\u30B8"=>"\u30B7\u3099".freeze, "\u30BA"=>"\u30B9\u3099".freeze, "\u30BC"=>"\u30BB\u3099".freeze, "\u30BE"=>"\u30BD\u3099".freeze, "\u30C0"=>"\u30BF\u3099".freeze, "\u30C2"=>"\u30C1\u3099".freeze, "\u30C5"=>"\u30C4\u3099".freeze, "\u30C7"=>"\u30C6\u3099".freeze, "\u30C9"=>"\u30C8\u3099".freeze, "\u30D0"=>"\u30CF\u3099".freeze, "\u30D1"=>"\u30CF\u309A".freeze, "\u30D3"=>"\u30D2\u3099".freeze, "\u30D4"=>"\u30D2\u309A".freeze, "\u30D6"=>"\u30D5\u3099".freeze, "\u30D7"=>"\u30D5\u309A".freeze, "\u30D9"=>"\u30D8\u3099".freeze, "\u30DA"=>"\u30D8\u309A".freeze, "\u30DC"=>"\u30DB\u3099".freeze, "\u30DD"=>"\u30DB\u309A".freeze, "\u30F4"=>"\u30A6\u3099".freeze, "\u30F7"=>"\u30EF\u3099".freeze, "\u30F8"=>"\u30F0\u3099".freeze, "\u30F9"=>"\u30F1\u3099".freeze, "\u30FA"=>"\u30F2\u3099".freeze, "\u30FE"=>"\u30FD\u3099".freeze, "\uF900"=>"\u8C48".freeze, "\uF901"=>"\u66F4".freeze, "\uF902"=>"\u8ECA".freeze, "\uF903"=>"\u8CC8".freeze, "\uF904"=>"\u6ED1".freeze, "\uF905"=>"\u4E32".freeze, "\uF906"=>"\u53E5".freeze, "\uF907"=>"\u9F9C".freeze, "\uF908"=>"\u9F9C".freeze, "\uF909"=>"\u5951".freeze, "\uF90A"=>"\u91D1".freeze, "\uF90B"=>"\u5587".freeze, "\uF90C"=>"\u5948".freeze, "\uF90D"=>"\u61F6".freeze, "\uF90E"=>"\u7669".freeze, "\uF90F"=>"\u7F85".freeze, "\uF910"=>"\u863F".freeze, "\uF911"=>"\u87BA".freeze, "\uF912"=>"\u88F8".freeze, "\uF913"=>"\u908F".freeze, "\uF914"=>"\u6A02".freeze, "\uF915"=>"\u6D1B".freeze, "\uF916"=>"\u70D9".freeze, "\uF917"=>"\u73DE".freeze, "\uF918"=>"\u843D".freeze, "\uF919"=>"\u916A".freeze, "\uF91A"=>"\u99F1".freeze, "\uF91B"=>"\u4E82".freeze, "\uF91C"=>"\u5375".freeze, "\uF91D"=>"\u6B04".freeze, "\uF91E"=>"\u721B".freeze, "\uF91F"=>"\u862D".freeze, "\uF920"=>"\u9E1E".freeze, "\uF921"=>"\u5D50".freeze, "\uF922"=>"\u6FEB".freeze, "\uF923"=>"\u85CD".freeze, "\uF924"=>"\u8964".freeze, "\uF925"=>"\u62C9".freeze, "\uF926"=>"\u81D8".freeze, "\uF927"=>"\u881F".freeze, "\uF928"=>"\u5ECA".freeze, "\uF929"=>"\u6717".freeze, "\uF92A"=>"\u6D6A".freeze, "\uF92B"=>"\u72FC".freeze, "\uF92C"=>"\u90CE".freeze, "\uF92D"=>"\u4F86".freeze, "\uF92E"=>"\u51B7".freeze, "\uF92F"=>"\u52DE".freeze, "\uF930"=>"\u64C4".freeze, "\uF931"=>"\u6AD3".freeze, "\uF932"=>"\u7210".freeze, "\uF933"=>"\u76E7".freeze, "\uF934"=>"\u8001".freeze, "\uF935"=>"\u8606".freeze, "\uF936"=>"\u865C".freeze, "\uF937"=>"\u8DEF".freeze, "\uF938"=>"\u9732".freeze, "\uF939"=>"\u9B6F".freeze, "\uF93A"=>"\u9DFA".freeze, "\uF93B"=>"\u788C".freeze, "\uF93C"=>"\u797F".freeze, "\uF93D"=>"\u7DA0".freeze, "\uF93E"=>"\u83C9".freeze, "\uF93F"=>"\u9304".freeze, "\uF940"=>"\u9E7F".freeze, "\uF941"=>"\u8AD6".freeze, "\uF942"=>"\u58DF".freeze, "\uF943"=>"\u5F04".freeze, "\uF944"=>"\u7C60".freeze, "\uF945"=>"\u807E".freeze, "\uF946"=>"\u7262".freeze, "\uF947"=>"\u78CA".freeze, "\uF948"=>"\u8CC2".freeze, "\uF949"=>"\u96F7".freeze, "\uF94A"=>"\u58D8".freeze, "\uF94B"=>"\u5C62".freeze, "\uF94C"=>"\u6A13".freeze, "\uF94D"=>"\u6DDA".freeze, "\uF94E"=>"\u6F0F".freeze, "\uF94F"=>"\u7D2F".freeze, "\uF950"=>"\u7E37".freeze, "\uF951"=>"\u964B".freeze, "\uF952"=>"\u52D2".freeze, "\uF953"=>"\u808B".freeze, "\uF954"=>"\u51DC".freeze, "\uF955"=>"\u51CC".freeze, "\uF956"=>"\u7A1C".freeze, "\uF957"=>"\u7DBE".freeze, "\uF958"=>"\u83F1".freeze, "\uF959"=>"\u9675".freeze, "\uF95A"=>"\u8B80".freeze, "\uF95B"=>"\u62CF".freeze, "\uF95C"=>"\u6A02".freeze, "\uF95D"=>"\u8AFE".freeze, "\uF95E"=>"\u4E39".freeze, "\uF95F"=>"\u5BE7".freeze, "\uF960"=>"\u6012".freeze, "\uF961"=>"\u7387".freeze, "\uF962"=>"\u7570".freeze, "\uF963"=>"\u5317".freeze, "\uF964"=>"\u78FB".freeze, "\uF965"=>"\u4FBF".freeze, "\uF966"=>"\u5FA9".freeze, "\uF967"=>"\u4E0D".freeze, "\uF968"=>"\u6CCC".freeze, "\uF969"=>"\u6578".freeze, "\uF96A"=>"\u7D22".freeze, "\uF96B"=>"\u53C3".freeze, "\uF96C"=>"\u585E".freeze, "\uF96D"=>"\u7701".freeze, "\uF96E"=>"\u8449".freeze, "\uF96F"=>"\u8AAA".freeze, "\uF970"=>"\u6BBA".freeze, "\uF971"=>"\u8FB0".freeze, "\uF972"=>"\u6C88".freeze, "\uF973"=>"\u62FE".freeze, "\uF974"=>"\u82E5".freeze, "\uF975"=>"\u63A0".freeze, "\uF976"=>"\u7565".freeze, "\uF977"=>"\u4EAE".freeze, "\uF978"=>"\u5169".freeze, "\uF979"=>"\u51C9".freeze, "\uF97A"=>"\u6881".freeze, "\uF97B"=>"\u7CE7".freeze, "\uF97C"=>"\u826F".freeze, "\uF97D"=>"\u8AD2".freeze, "\uF97E"=>"\u91CF".freeze, "\uF97F"=>"\u52F5".freeze, "\uF980"=>"\u5442".freeze, "\uF981"=>"\u5973".freeze, "\uF982"=>"\u5EEC".freeze, "\uF983"=>"\u65C5".freeze, "\uF984"=>"\u6FFE".freeze, "\uF985"=>"\u792A".freeze, "\uF986"=>"\u95AD".freeze, "\uF987"=>"\u9A6A".freeze, "\uF988"=>"\u9E97".freeze, "\uF989"=>"\u9ECE".freeze, "\uF98A"=>"\u529B".freeze, "\uF98B"=>"\u66C6".freeze, "\uF98C"=>"\u6B77".freeze, "\uF98D"=>"\u8F62".freeze, "\uF98E"=>"\u5E74".freeze, "\uF98F"=>"\u6190".freeze, "\uF990"=>"\u6200".freeze, "\uF991"=>"\u649A".freeze, "\uF992"=>"\u6F23".freeze, "\uF993"=>"\u7149".freeze, "\uF994"=>"\u7489".freeze, "\uF995"=>"\u79CA".freeze, "\uF996"=>"\u7DF4".freeze, "\uF997"=>"\u806F".freeze, "\uF998"=>"\u8F26".freeze, "\uF999"=>"\u84EE".freeze, "\uF99A"=>"\u9023".freeze, "\uF99B"=>"\u934A".freeze, "\uF99C"=>"\u5217".freeze, "\uF99D"=>"\u52A3".freeze, "\uF99E"=>"\u54BD".freeze, "\uF99F"=>"\u70C8".freeze, "\uF9A0"=>"\u88C2".freeze, "\uF9A1"=>"\u8AAA".freeze, "\uF9A2"=>"\u5EC9".freeze, "\uF9A3"=>"\u5FF5".freeze, "\uF9A4"=>"\u637B".freeze, "\uF9A5"=>"\u6BAE".freeze, "\uF9A6"=>"\u7C3E".freeze, "\uF9A7"=>"\u7375".freeze, "\uF9A8"=>"\u4EE4".freeze, "\uF9A9"=>"\u56F9".freeze, "\uF9AA"=>"\u5BE7".freeze, "\uF9AB"=>"\u5DBA".freeze, "\uF9AC"=>"\u601C".freeze, "\uF9AD"=>"\u73B2".freeze, "\uF9AE"=>"\u7469".freeze, "\uF9AF"=>"\u7F9A".freeze, "\uF9B0"=>"\u8046".freeze, "\uF9B1"=>"\u9234".freeze, "\uF9B2"=>"\u96F6".freeze, "\uF9B3"=>"\u9748".freeze, "\uF9B4"=>"\u9818".freeze, "\uF9B5"=>"\u4F8B".freeze, "\uF9B6"=>"\u79AE".freeze, "\uF9B7"=>"\u91B4".freeze, "\uF9B8"=>"\u96B8".freeze, "\uF9B9"=>"\u60E1".freeze, "\uF9BA"=>"\u4E86".freeze, "\uF9BB"=>"\u50DA".freeze, "\uF9BC"=>"\u5BEE".freeze, "\uF9BD"=>"\u5C3F".freeze, "\uF9BE"=>"\u6599".freeze, "\uF9BF"=>"\u6A02".freeze, "\uF9C0"=>"\u71CE".freeze, "\uF9C1"=>"\u7642".freeze, "\uF9C2"=>"\u84FC".freeze, "\uF9C3"=>"\u907C".freeze, "\uF9C4"=>"\u9F8D".freeze, "\uF9C5"=>"\u6688".freeze, "\uF9C6"=>"\u962E".freeze, "\uF9C7"=>"\u5289".freeze, "\uF9C8"=>"\u677B".freeze, "\uF9C9"=>"\u67F3".freeze, "\uF9CA"=>"\u6D41".freeze, "\uF9CB"=>"\u6E9C".freeze, "\uF9CC"=>"\u7409".freeze, "\uF9CD"=>"\u7559".freeze, "\uF9CE"=>"\u786B".freeze, "\uF9CF"=>"\u7D10".freeze, "\uF9D0"=>"\u985E".freeze, "\uF9D1"=>"\u516D".freeze, "\uF9D2"=>"\u622E".freeze, "\uF9D3"=>"\u9678".freeze, "\uF9D4"=>"\u502B".freeze, "\uF9D5"=>"\u5D19".freeze, "\uF9D6"=>"\u6DEA".freeze, "\uF9D7"=>"\u8F2A".freeze, "\uF9D8"=>"\u5F8B".freeze, "\uF9D9"=>"\u6144".freeze, "\uF9DA"=>"\u6817".freeze, "\uF9DB"=>"\u7387".freeze, "\uF9DC"=>"\u9686".freeze, "\uF9DD"=>"\u5229".freeze, "\uF9DE"=>"\u540F".freeze, "\uF9DF"=>"\u5C65".freeze, "\uF9E0"=>"\u6613".freeze, "\uF9E1"=>"\u674E".freeze, "\uF9E2"=>"\u68A8".freeze, "\uF9E3"=>"\u6CE5".freeze, "\uF9E4"=>"\u7406".freeze, "\uF9E5"=>"\u75E2".freeze, "\uF9E6"=>"\u7F79".freeze, "\uF9E7"=>"\u88CF".freeze, "\uF9E8"=>"\u88E1".freeze, "\uF9E9"=>"\u91CC".freeze, "\uF9EA"=>"\u96E2".freeze, "\uF9EB"=>"\u533F".freeze, "\uF9EC"=>"\u6EBA".freeze, "\uF9ED"=>"\u541D".freeze, "\uF9EE"=>"\u71D0".freeze, "\uF9EF"=>"\u7498".freeze, "\uF9F0"=>"\u85FA".freeze, "\uF9F1"=>"\u96A3".freeze, "\uF9F2"=>"\u9C57".freeze, "\uF9F3"=>"\u9E9F".freeze, "\uF9F4"=>"\u6797".freeze, "\uF9F5"=>"\u6DCB".freeze, "\uF9F6"=>"\u81E8".freeze, "\uF9F7"=>"\u7ACB".freeze, "\uF9F8"=>"\u7B20".freeze, "\uF9F9"=>"\u7C92".freeze, "\uF9FA"=>"\u72C0".freeze, "\uF9FB"=>"\u7099".freeze, "\uF9FC"=>"\u8B58".freeze, "\uF9FD"=>"\u4EC0".freeze, "\uF9FE"=>"\u8336".freeze, "\uF9FF"=>"\u523A".freeze, "\uFA00"=>"\u5207".freeze, "\uFA01"=>"\u5EA6".freeze, "\uFA02"=>"\u62D3".freeze, "\uFA03"=>"\u7CD6".freeze, "\uFA04"=>"\u5B85".freeze, "\uFA05"=>"\u6D1E".freeze, "\uFA06"=>"\u66B4".freeze, "\uFA07"=>"\u8F3B".freeze, "\uFA08"=>"\u884C".freeze, "\uFA09"=>"\u964D".freeze, "\uFA0A"=>"\u898B".freeze, "\uFA0B"=>"\u5ED3".freeze, "\uFA0C"=>"\u5140".freeze, "\uFA0D"=>"\u55C0".freeze, "\uFA10"=>"\u585A".freeze, "\uFA12"=>"\u6674".freeze, "\uFA15"=>"\u51DE".freeze, "\uFA16"=>"\u732A".freeze, "\uFA17"=>"\u76CA".freeze, "\uFA18"=>"\u793C".freeze, "\uFA19"=>"\u795E".freeze, "\uFA1A"=>"\u7965".freeze, "\uFA1B"=>"\u798F".freeze, "\uFA1C"=>"\u9756".freeze, "\uFA1D"=>"\u7CBE".freeze, "\uFA1E"=>"\u7FBD".freeze, "\uFA20"=>"\u8612".freeze, "\uFA22"=>"\u8AF8".freeze, "\uFA25"=>"\u9038".freeze, "\uFA26"=>"\u90FD".freeze, "\uFA2A"=>"\u98EF".freeze, "\uFA2B"=>"\u98FC".freeze, "\uFA2C"=>"\u9928".freeze, "\uFA2D"=>"\u9DB4".freeze, "\uFA2E"=>"\u90DE".freeze, "\uFA2F"=>"\u96B7".freeze, "\uFA30"=>"\u4FAE".freeze, "\uFA31"=>"\u50E7".freeze, "\uFA32"=>"\u514D".freeze, "\uFA33"=>"\u52C9".freeze, "\uFA34"=>"\u52E4".freeze, "\uFA35"=>"\u5351".freeze, "\uFA36"=>"\u559D".freeze, "\uFA37"=>"\u5606".freeze, "\uFA38"=>"\u5668".freeze, "\uFA39"=>"\u5840".freeze, "\uFA3A"=>"\u58A8".freeze, "\uFA3B"=>"\u5C64".freeze, "\uFA3C"=>"\u5C6E".freeze, "\uFA3D"=>"\u6094".freeze, "\uFA3E"=>"\u6168".freeze, "\uFA3F"=>"\u618E".freeze, "\uFA40"=>"\u61F2".freeze, "\uFA41"=>"\u654F".freeze, "\uFA42"=>"\u65E2".freeze, "\uFA43"=>"\u6691".freeze, "\uFA44"=>"\u6885".freeze, "\uFA45"=>"\u6D77".freeze, "\uFA46"=>"\u6E1A".freeze, "\uFA47"=>"\u6F22".freeze, "\uFA48"=>"\u716E".freeze, "\uFA49"=>"\u722B".freeze, "\uFA4A"=>"\u7422".freeze, "\uFA4B"=>"\u7891".freeze, "\uFA4C"=>"\u793E".freeze, "\uFA4D"=>"\u7949".freeze, "\uFA4E"=>"\u7948".freeze, "\uFA4F"=>"\u7950".freeze, "\uFA50"=>"\u7956".freeze, "\uFA51"=>"\u795D".freeze, "\uFA52"=>"\u798D".freeze, "\uFA53"=>"\u798E".freeze, "\uFA54"=>"\u7A40".freeze, "\uFA55"=>"\u7A81".freeze, "\uFA56"=>"\u7BC0".freeze, "\uFA57"=>"\u7DF4".freeze, "\uFA58"=>"\u7E09".freeze, "\uFA59"=>"\u7E41".freeze, "\uFA5A"=>"\u7F72".freeze, "\uFA5B"=>"\u8005".freeze, "\uFA5C"=>"\u81ED".freeze, "\uFA5D"=>"\u8279".freeze, "\uFA5E"=>"\u8279".freeze, "\uFA5F"=>"\u8457".freeze, "\uFA60"=>"\u8910".freeze, "\uFA61"=>"\u8996".freeze, "\uFA62"=>"\u8B01".freeze, "\uFA63"=>"\u8B39".freeze, "\uFA64"=>"\u8CD3".freeze, "\uFA65"=>"\u8D08".freeze, "\uFA66"=>"\u8FB6".freeze, "\uFA67"=>"\u9038".freeze, "\uFA68"=>"\u96E3".freeze, "\uFA69"=>"\u97FF".freeze, "\uFA6A"=>"\u983B".freeze, "\uFA6B"=>"\u6075".freeze, "\uFA6C"=>"\u{242EE}".freeze, "\uFA6D"=>"\u8218".freeze, "\uFA70"=>"\u4E26".freeze, "\uFA71"=>"\u51B5".freeze, "\uFA72"=>"\u5168".freeze, "\uFA73"=>"\u4F80".freeze, "\uFA74"=>"\u5145".freeze, "\uFA75"=>"\u5180".freeze, "\uFA76"=>"\u52C7".freeze, "\uFA77"=>"\u52FA".freeze, "\uFA78"=>"\u559D".freeze, "\uFA79"=>"\u5555".freeze, "\uFA7A"=>"\u5599".freeze, "\uFA7B"=>"\u55E2".freeze, "\uFA7C"=>"\u585A".freeze, "\uFA7D"=>"\u58B3".freeze, "\uFA7E"=>"\u5944".freeze, "\uFA7F"=>"\u5954".freeze, "\uFA80"=>"\u5A62".freeze, "\uFA81"=>"\u5B28".freeze, "\uFA82"=>"\u5ED2".freeze, "\uFA83"=>"\u5ED9".freeze, "\uFA84"=>"\u5F69".freeze, "\uFA85"=>"\u5FAD".freeze, "\uFA86"=>"\u60D8".freeze, "\uFA87"=>"\u614E".freeze, "\uFA88"=>"\u6108".freeze, "\uFA89"=>"\u618E".freeze, "\uFA8A"=>"\u6160".freeze, "\uFA8B"=>"\u61F2".freeze, "\uFA8C"=>"\u6234".freeze, "\uFA8D"=>"\u63C4".freeze, "\uFA8E"=>"\u641C".freeze, "\uFA8F"=>"\u6452".freeze, "\uFA90"=>"\u6556".freeze, "\uFA91"=>"\u6674".freeze, "\uFA92"=>"\u6717".freeze, "\uFA93"=>"\u671B".freeze, "\uFA94"=>"\u6756".freeze, "\uFA95"=>"\u6B79".freeze, "\uFA96"=>"\u6BBA".freeze, "\uFA97"=>"\u6D41".freeze, "\uFA98"=>"\u6EDB".freeze, "\uFA99"=>"\u6ECB".freeze, "\uFA9A"=>"\u6F22".freeze, "\uFA9B"=>"\u701E".freeze, "\uFA9C"=>"\u716E".freeze, "\uFA9D"=>"\u77A7".freeze, "\uFA9E"=>"\u7235".freeze, "\uFA9F"=>"\u72AF".freeze, "\uFAA0"=>"\u732A".freeze, "\uFAA1"=>"\u7471".freeze, "\uFAA2"=>"\u7506".freeze, "\uFAA3"=>"\u753B".freeze, "\uFAA4"=>"\u761D".freeze, "\uFAA5"=>"\u761F".freeze, "\uFAA6"=>"\u76CA".freeze, "\uFAA7"=>"\u76DB".freeze, "\uFAA8"=>"\u76F4".freeze, "\uFAA9"=>"\u774A".freeze, "\uFAAA"=>"\u7740".freeze, "\uFAAB"=>"\u78CC".freeze, "\uFAAC"=>"\u7AB1".freeze, "\uFAAD"=>"\u7BC0".freeze, "\uFAAE"=>"\u7C7B".freeze, "\uFAAF"=>"\u7D5B".freeze, "\uFAB0"=>"\u7DF4".freeze, "\uFAB1"=>"\u7F3E".freeze, "\uFAB2"=>"\u8005".freeze, "\uFAB3"=>"\u8352".freeze, "\uFAB4"=>"\u83EF".freeze, "\uFAB5"=>"\u8779".freeze, "\uFAB6"=>"\u8941".freeze, "\uFAB7"=>"\u8986".freeze, "\uFAB8"=>"\u8996".freeze, "\uFAB9"=>"\u8ABF".freeze, "\uFABA"=>"\u8AF8".freeze, "\uFABB"=>"\u8ACB".freeze, "\uFABC"=>"\u8B01".freeze, "\uFABD"=>"\u8AFE".freeze, "\uFABE"=>"\u8AED".freeze, "\uFABF"=>"\u8B39".freeze, "\uFAC0"=>"\u8B8A".freeze, "\uFAC1"=>"\u8D08".freeze, "\uFAC2"=>"\u8F38".freeze, "\uFAC3"=>"\u9072".freeze, "\uFAC4"=>"\u9199".freeze, "\uFAC5"=>"\u9276".freeze, "\uFAC6"=>"\u967C".freeze, "\uFAC7"=>"\u96E3".freeze, "\uFAC8"=>"\u9756".freeze, "\uFAC9"=>"\u97DB".freeze, "\uFACA"=>"\u97FF".freeze, "\uFACB"=>"\u980B".freeze, "\uFACC"=>"\u983B".freeze, "\uFACD"=>"\u9B12".freeze, "\uFACE"=>"\u9F9C".freeze, "\uFACF"=>"\u{2284A}".freeze, "\uFAD0"=>"\u{22844}".freeze, "\uFAD1"=>"\u{233D5}".freeze, "\uFAD2"=>"\u3B9D".freeze, "\uFAD3"=>"\u4018".freeze, "\uFAD4"=>"\u4039".freeze, "\uFAD5"=>"\u{25249}".freeze, "\uFAD6"=>"\u{25CD0}".freeze, "\uFAD7"=>"\u{27ED3}".freeze, "\uFAD8"=>"\u9F43".freeze, "\uFAD9"=>"\u9F8E".freeze, "\uFB1D"=>"\u05D9\u05B4".freeze, "\uFB1F"=>"\u05F2\u05B7".freeze, "\uFB2A"=>"\u05E9\u05C1".freeze, "\uFB2B"=>"\u05E9\u05C2".freeze, "\uFB2C"=>"\u05E9\u05BC\u05C1".freeze, "\uFB2D"=>"\u05E9\u05BC\u05C2".freeze, "\uFB2E"=>"\u05D0\u05B7".freeze, "\uFB2F"=>"\u05D0\u05B8".freeze, "\uFB30"=>"\u05D0\u05BC".freeze, "\uFB31"=>"\u05D1\u05BC".freeze, "\uFB32"=>"\u05D2\u05BC".freeze, "\uFB33"=>"\u05D3\u05BC".freeze, "\uFB34"=>"\u05D4\u05BC".freeze, "\uFB35"=>"\u05D5\u05BC".freeze, "\uFB36"=>"\u05D6\u05BC".freeze, "\uFB38"=>"\u05D8\u05BC".freeze, "\uFB39"=>"\u05D9\u05BC".freeze, "\uFB3A"=>"\u05DA\u05BC".freeze, "\uFB3B"=>"\u05DB\u05BC".freeze, "\uFB3C"=>"\u05DC\u05BC".freeze, "\uFB3E"=>"\u05DE\u05BC".freeze, "\uFB40"=>"\u05E0\u05BC".freeze, "\uFB41"=>"\u05E1\u05BC".freeze, "\uFB43"=>"\u05E3\u05BC".freeze, "\uFB44"=>"\u05E4\u05BC".freeze, "\uFB46"=>"\u05E6\u05BC".freeze, "\uFB47"=>"\u05E7\u05BC".freeze, "\uFB48"=>"\u05E8\u05BC".freeze, "\uFB49"=>"\u05E9\u05BC".freeze, "\uFB4A"=>"\u05EA\u05BC".freeze, "\uFB4B"=>"\u05D5\u05B9".freeze, "\uFB4C"=>"\u05D1\u05BF".freeze, "\uFB4D"=>"\u05DB\u05BF".freeze, "\uFB4E"=>"\u05E4\u05BF".freeze, "\u{1109A}"=>"\u{11099}\u{110BA}".freeze, "\u{1109C}"=>"\u{1109B}\u{110BA}".freeze, "\u{110AB}"=>"\u{110A5}\u{110BA}".freeze, "\u{1112E}"=>"\u{11131}\u{11127}".freeze, "\u{1112F}"=>"\u{11132}\u{11127}".freeze, "\u{1134B}"=>"\u{11347}\u{1133E}".freeze, "\u{1134C}"=>"\u{11347}\u{11357}".freeze, "\u{114BB}"=>"\u{114B9}\u{114BA}".freeze, "\u{114BC}"=>"\u{114B9}\u{114B0}".freeze, "\u{114BE}"=>"\u{114B9}\u{114BD}".freeze, "\u{115BA}"=>"\u{115B8}\u{115AF}".freeze, "\u{115BB}"=>"\u{115B9}\u{115AF}".freeze, "\u{1D15E}"=>"\u{1D157}\u{1D165}".freeze, "\u{1D15F}"=>"\u{1D158}\u{1D165}".freeze, "\u{1D160}"=>"\u{1D158}\u{1D165}\u{1D16E}".freeze, "\u{1D161}"=>"\u{1D158}\u{1D165}\u{1D16F}".freeze, "\u{1D162}"=>"\u{1D158}\u{1D165}\u{1D170}".freeze, "\u{1D163}"=>"\u{1D158}\u{1D165}\u{1D171}".freeze, "\u{1D164}"=>"\u{1D158}\u{1D165}\u{1D172}".freeze, "\u{1D1BB}"=>"\u{1D1B9}\u{1D165}".freeze, "\u{1D1BC}"=>"\u{1D1BA}\u{1D165}".freeze, "\u{1D1BD}"=>"\u{1D1B9}\u{1D165}\u{1D16E}".freeze, "\u{1D1BE}"=>"\u{1D1BA}\u{1D165}\u{1D16E}".freeze, "\u{1D1BF}"=>"\u{1D1B9}\u{1D165}\u{1D16F}".freeze, "\u{1D1C0}"=>"\u{1D1BA}\u{1D165}\u{1D16F}".freeze, "\u{2F800}"=>"\u4E3D".freeze, "\u{2F801}"=>"\u4E38".freeze, "\u{2F802}"=>"\u4E41".freeze, "\u{2F803}"=>"\u{20122}".freeze, "\u{2F804}"=>"\u4F60".freeze, "\u{2F805}"=>"\u4FAE".freeze, "\u{2F806}"=>"\u4FBB".freeze, "\u{2F807}"=>"\u5002".freeze, "\u{2F808}"=>"\u507A".freeze, "\u{2F809}"=>"\u5099".freeze, "\u{2F80A}"=>"\u50E7".freeze, "\u{2F80B}"=>"\u50CF".freeze, "\u{2F80C}"=>"\u349E".freeze, "\u{2F80D}"=>"\u{2063A}".freeze, "\u{2F80E}"=>"\u514D".freeze, "\u{2F80F}"=>"\u5154".freeze, "\u{2F810}"=>"\u5164".freeze, "\u{2F811}"=>"\u5177".freeze, "\u{2F812}"=>"\u{2051C}".freeze, "\u{2F813}"=>"\u34B9".freeze, "\u{2F814}"=>"\u5167".freeze, "\u{2F815}"=>"\u518D".freeze, "\u{2F816}"=>"\u{2054B}".freeze, "\u{2F817}"=>"\u5197".freeze, "\u{2F818}"=>"\u51A4".freeze, "\u{2F819}"=>"\u4ECC".freeze, "\u{2F81A}"=>"\u51AC".freeze, "\u{2F81B}"=>"\u51B5".freeze, "\u{2F81C}"=>"\u{291DF}".freeze, "\u{2F81D}"=>"\u51F5".freeze, "\u{2F81E}"=>"\u5203".freeze, "\u{2F81F}"=>"\u34DF".freeze, "\u{2F820}"=>"\u523B".freeze, "\u{2F821}"=>"\u5246".freeze, "\u{2F822}"=>"\u5272".freeze, "\u{2F823}"=>"\u5277".freeze, "\u{2F824}"=>"\u3515".freeze, "\u{2F825}"=>"\u52C7".freeze, "\u{2F826}"=>"\u52C9".freeze, "\u{2F827}"=>"\u52E4".freeze, "\u{2F828}"=>"\u52FA".freeze, "\u{2F829}"=>"\u5305".freeze, "\u{2F82A}"=>"\u5306".freeze, "\u{2F82B}"=>"\u5317".freeze, "\u{2F82C}"=>"\u5349".freeze, "\u{2F82D}"=>"\u5351".freeze, "\u{2F82E}"=>"\u535A".freeze, "\u{2F82F}"=>"\u5373".freeze, "\u{2F830}"=>"\u537D".freeze, "\u{2F831}"=>"\u537F".freeze, "\u{2F832}"=>"\u537F".freeze, "\u{2F833}"=>"\u537F".freeze, "\u{2F834}"=>"\u{20A2C}".freeze, "\u{2F835}"=>"\u7070".freeze, "\u{2F836}"=>"\u53CA".freeze, "\u{2F837}"=>"\u53DF".freeze, "\u{2F838}"=>"\u{20B63}".freeze, "\u{2F839}"=>"\u53EB".freeze, "\u{2F83A}"=>"\u53F1".freeze, "\u{2F83B}"=>"\u5406".freeze, "\u{2F83C}"=>"\u549E".freeze, "\u{2F83D}"=>"\u5438".freeze, "\u{2F83E}"=>"\u5448".freeze, "\u{2F83F}"=>"\u5468".freeze, "\u{2F840}"=>"\u54A2".freeze, "\u{2F841}"=>"\u54F6".freeze, "\u{2F842}"=>"\u5510".freeze, "\u{2F843}"=>"\u5553".freeze, "\u{2F844}"=>"\u5563".freeze, "\u{2F845}"=>"\u5584".freeze, "\u{2F846}"=>"\u5584".freeze, "\u{2F847}"=>"\u5599".freeze, "\u{2F848}"=>"\u55AB".freeze, "\u{2F849}"=>"\u55B3".freeze, "\u{2F84A}"=>"\u55C2".freeze, "\u{2F84B}"=>"\u5716".freeze, "\u{2F84C}"=>"\u5606".freeze, "\u{2F84D}"=>"\u5717".freeze, "\u{2F84E}"=>"\u5651".freeze, "\u{2F84F}"=>"\u5674".freeze, "\u{2F850}"=>"\u5207".freeze, "\u{2F851}"=>"\u58EE".freeze, "\u{2F852}"=>"\u57CE".freeze, "\u{2F853}"=>"\u57F4".freeze, "\u{2F854}"=>"\u580D".freeze, "\u{2F855}"=>"\u578B".freeze, "\u{2F856}"=>"\u5832".freeze, "\u{2F857}"=>"\u5831".freeze, "\u{2F858}"=>"\u58AC".freeze, "\u{2F859}"=>"\u{214E4}".freeze, "\u{2F85A}"=>"\u58F2".freeze, "\u{2F85B}"=>"\u58F7".freeze, "\u{2F85C}"=>"\u5906".freeze, "\u{2F85D}"=>"\u591A".freeze, "\u{2F85E}"=>"\u5922".freeze, "\u{2F85F}"=>"\u5962".freeze, "\u{2F860}"=>"\u{216A8}".freeze, "\u{2F861}"=>"\u{216EA}".freeze, "\u{2F862}"=>"\u59EC".freeze, "\u{2F863}"=>"\u5A1B".freeze, "\u{2F864}"=>"\u5A27".freeze, "\u{2F865}"=>"\u59D8".freeze, "\u{2F866}"=>"\u5A66".freeze, "\u{2F867}"=>"\u36EE".freeze, "\u{2F868}"=>"\u36FC".freeze, "\u{2F869}"=>"\u5B08".freeze, "\u{2F86A}"=>"\u5B3E".freeze, "\u{2F86B}"=>"\u5B3E".freeze, "\u{2F86C}"=>"\u{219C8}".freeze, "\u{2F86D}"=>"\u5BC3".freeze, "\u{2F86E}"=>"\u5BD8".freeze, "\u{2F86F}"=>"\u5BE7".freeze, "\u{2F870}"=>"\u5BF3".freeze, "\u{2F871}"=>"\u{21B18}".freeze, "\u{2F872}"=>"\u5BFF".freeze, "\u{2F873}"=>"\u5C06".freeze, "\u{2F874}"=>"\u5F53".freeze, "\u{2F875}"=>"\u5C22".freeze, "\u{2F876}"=>"\u3781".freeze, "\u{2F877}"=>"\u5C60".freeze, "\u{2F878}"=>"\u5C6E".freeze, "\u{2F879}"=>"\u5CC0".freeze, "\u{2F87A}"=>"\u5C8D".freeze, "\u{2F87B}"=>"\u{21DE4}".freeze, "\u{2F87C}"=>"\u5D43".freeze, "\u{2F87D}"=>"\u{21DE6}".freeze, "\u{2F87E}"=>"\u5D6E".freeze, "\u{2F87F}"=>"\u5D6B".freeze, "\u{2F880}"=>"\u5D7C".freeze, "\u{2F881}"=>"\u5DE1".freeze, "\u{2F882}"=>"\u5DE2".freeze, "\u{2F883}"=>"\u382F".freeze, "\u{2F884}"=>"\u5DFD".freeze, "\u{2F885}"=>"\u5E28".freeze, "\u{2F886}"=>"\u5E3D".freeze, "\u{2F887}"=>"\u5E69".freeze, "\u{2F888}"=>"\u3862".freeze, "\u{2F889}"=>"\u{22183}".freeze, "\u{2F88A}"=>"\u387C".freeze, "\u{2F88B}"=>"\u5EB0".freeze, "\u{2F88C}"=>"\u5EB3".freeze, "\u{2F88D}"=>"\u5EB6".freeze, "\u{2F88E}"=>"\u5ECA".freeze, "\u{2F88F}"=>"\u{2A392}".freeze, "\u{2F890}"=>"\u5EFE".freeze, "\u{2F891}"=>"\u{22331}".freeze, "\u{2F892}"=>"\u{22331}".freeze, "\u{2F893}"=>"\u8201".freeze, "\u{2F894}"=>"\u5F22".freeze, "\u{2F895}"=>"\u5F22".freeze, "\u{2F896}"=>"\u38C7".freeze, "\u{2F897}"=>"\u{232B8}".freeze, "\u{2F898}"=>"\u{261DA}".freeze, "\u{2F899}"=>"\u5F62".freeze, "\u{2F89A}"=>"\u5F6B".freeze, "\u{2F89B}"=>"\u38E3".freeze, "\u{2F89C}"=>"\u5F9A".freeze, "\u{2F89D}"=>"\u5FCD".freeze, "\u{2F89E}"=>"\u5FD7".freeze, "\u{2F89F}"=>"\u5FF9".freeze, "\u{2F8A0}"=>"\u6081".freeze, "\u{2F8A1}"=>"\u393A".freeze, "\u{2F8A2}"=>"\u391C".freeze, "\u{2F8A3}"=>"\u6094".freeze, "\u{2F8A4}"=>"\u{226D4}".freeze, "\u{2F8A5}"=>"\u60C7".freeze, "\u{2F8A6}"=>"\u6148".freeze, "\u{2F8A7}"=>"\u614C".freeze, "\u{2F8A8}"=>"\u614E".freeze, "\u{2F8A9}"=>"\u614C".freeze, "\u{2F8AA}"=>"\u617A".freeze, "\u{2F8AB}"=>"\u618E".freeze, "\u{2F8AC}"=>"\u61B2".freeze, "\u{2F8AD}"=>"\u61A4".freeze, "\u{2F8AE}"=>"\u61AF".freeze, "\u{2F8AF}"=>"\u61DE".freeze, "\u{2F8B0}"=>"\u61F2".freeze, "\u{2F8B1}"=>"\u61F6".freeze, "\u{2F8B2}"=>"\u6210".freeze, "\u{2F8B3}"=>"\u621B".freeze, "\u{2F8B4}"=>"\u625D".freeze, "\u{2F8B5}"=>"\u62B1".freeze, "\u{2F8B6}"=>"\u62D4".freeze, "\u{2F8B7}"=>"\u6350".freeze, "\u{2F8B8}"=>"\u{22B0C}".freeze, "\u{2F8B9}"=>"\u633D".freeze, "\u{2F8BA}"=>"\u62FC".freeze, "\u{2F8BB}"=>"\u6368".freeze, "\u{2F8BC}"=>"\u6383".freeze, "\u{2F8BD}"=>"\u63E4".freeze, "\u{2F8BE}"=>"\u{22BF1}".freeze, "\u{2F8BF}"=>"\u6422".freeze, "\u{2F8C0}"=>"\u63C5".freeze, "\u{2F8C1}"=>"\u63A9".freeze, "\u{2F8C2}"=>"\u3A2E".freeze, "\u{2F8C3}"=>"\u6469".freeze, "\u{2F8C4}"=>"\u647E".freeze, "\u{2F8C5}"=>"\u649D".freeze, "\u{2F8C6}"=>"\u6477".freeze, "\u{2F8C7}"=>"\u3A6C".freeze, "\u{2F8C8}"=>"\u654F".freeze, "\u{2F8C9}"=>"\u656C".freeze, "\u{2F8CA}"=>"\u{2300A}".freeze, "\u{2F8CB}"=>"\u65E3".freeze, "\u{2F8CC}"=>"\u66F8".freeze, "\u{2F8CD}"=>"\u6649".freeze, "\u{2F8CE}"=>"\u3B19".freeze, "\u{2F8CF}"=>"\u6691".freeze, "\u{2F8D0}"=>"\u3B08".freeze, "\u{2F8D1}"=>"\u3AE4".freeze, "\u{2F8D2}"=>"\u5192".freeze, "\u{2F8D3}"=>"\u5195".freeze, "\u{2F8D4}"=>"\u6700".freeze, "\u{2F8D5}"=>"\u669C".freeze, "\u{2F8D6}"=>"\u80AD".freeze, "\u{2F8D7}"=>"\u43D9".freeze, "\u{2F8D8}"=>"\u6717".freeze, "\u{2F8D9}"=>"\u671B".freeze, "\u{2F8DA}"=>"\u6721".freeze, "\u{2F8DB}"=>"\u675E".freeze, "\u{2F8DC}"=>"\u6753".freeze, "\u{2F8DD}"=>"\u{233C3}".freeze, "\u{2F8DE}"=>"\u3B49".freeze, "\u{2F8DF}"=>"\u67FA".freeze, "\u{2F8E0}"=>"\u6785".freeze, "\u{2F8E1}"=>"\u6852".freeze, "\u{2F8E2}"=>"\u6885".freeze, "\u{2F8E3}"=>"\u{2346D}".freeze, "\u{2F8E4}"=>"\u688E".freeze, "\u{2F8E5}"=>"\u681F".freeze, "\u{2F8E6}"=>"\u6914".freeze, "\u{2F8E7}"=>"\u3B9D".freeze, "\u{2F8E8}"=>"\u6942".freeze, "\u{2F8E9}"=>"\u69A3".freeze, "\u{2F8EA}"=>"\u69EA".freeze, "\u{2F8EB}"=>"\u6AA8".freeze, "\u{2F8EC}"=>"\u{236A3}".freeze, "\u{2F8ED}"=>"\u6ADB".freeze, "\u{2F8EE}"=>"\u3C18".freeze, "\u{2F8EF}"=>"\u6B21".freeze, "\u{2F8F0}"=>"\u{238A7}".freeze, "\u{2F8F1}"=>"\u6B54".freeze, "\u{2F8F2}"=>"\u3C4E".freeze, "\u{2F8F3}"=>"\u6B72".freeze, "\u{2F8F4}"=>"\u6B9F".freeze, "\u{2F8F5}"=>"\u6BBA".freeze, "\u{2F8F6}"=>"\u6BBB".freeze, "\u{2F8F7}"=>"\u{23A8D}".freeze, "\u{2F8F8}"=>"\u{21D0B}".freeze, "\u{2F8F9}"=>"\u{23AFA}".freeze, "\u{2F8FA}"=>"\u6C4E".freeze, "\u{2F8FB}"=>"\u{23CBC}".freeze, "\u{2F8FC}"=>"\u6CBF".freeze, "\u{2F8FD}"=>"\u6CCD".freeze, "\u{2F8FE}"=>"\u6C67".freeze, "\u{2F8FF}"=>"\u6D16".freeze, "\u{2F900}"=>"\u6D3E".freeze, "\u{2F901}"=>"\u6D77".freeze, "\u{2F902}"=>"\u6D41".freeze, "\u{2F903}"=>"\u6D69".freeze, "\u{2F904}"=>"\u6D78".freeze, "\u{2F905}"=>"\u6D85".freeze, "\u{2F906}"=>"\u{23D1E}".freeze, "\u{2F907}"=>"\u6D34".freeze, "\u{2F908}"=>"\u6E2F".freeze, "\u{2F909}"=>"\u6E6E".freeze, "\u{2F90A}"=>"\u3D33".freeze, "\u{2F90B}"=>"\u6ECB".freeze, "\u{2F90C}"=>"\u6EC7".freeze, "\u{2F90D}"=>"\u{23ED1}".freeze, "\u{2F90E}"=>"\u6DF9".freeze, "\u{2F90F}"=>"\u6F6E".freeze, "\u{2F910}"=>"\u{23F5E}".freeze, "\u{2F911}"=>"\u{23F8E}".freeze, "\u{2F912}"=>"\u6FC6".freeze, "\u{2F913}"=>"\u7039".freeze, "\u{2F914}"=>"\u701E".freeze, "\u{2F915}"=>"\u701B".freeze, "\u{2F916}"=>"\u3D96".freeze, "\u{2F917}"=>"\u704A".freeze, "\u{2F918}"=>"\u707D".freeze, "\u{2F919}"=>"\u7077".freeze, "\u{2F91A}"=>"\u70AD".freeze, "\u{2F91B}"=>"\u{20525}".freeze, "\u{2F91C}"=>"\u7145".freeze, "\u{2F91D}"=>"\u{24263}".freeze, "\u{2F91E}"=>"\u719C".freeze, "\u{2F91F}"=>"\u{243AB}".freeze, "\u{2F920}"=>"\u7228".freeze, "\u{2F921}"=>"\u7235".freeze, "\u{2F922}"=>"\u7250".freeze, "\u{2F923}"=>"\u{24608}".freeze, "\u{2F924}"=>"\u7280".freeze, "\u{2F925}"=>"\u7295".freeze, "\u{2F926}"=>"\u{24735}".freeze, "\u{2F927}"=>"\u{24814}".freeze, "\u{2F928}"=>"\u737A".freeze, "\u{2F929}"=>"\u738B".freeze, "\u{2F92A}"=>"\u3EAC".freeze, "\u{2F92B}"=>"\u73A5".freeze, "\u{2F92C}"=>"\u3EB8".freeze, "\u{2F92D}"=>"\u3EB8".freeze, "\u{2F92E}"=>"\u7447".freeze, "\u{2F92F}"=>"\u745C".freeze, "\u{2F930}"=>"\u7471".freeze, "\u{2F931}"=>"\u7485".freeze, "\u{2F932}"=>"\u74CA".freeze, "\u{2F933}"=>"\u3F1B".freeze, "\u{2F934}"=>"\u7524".freeze, "\u{2F935}"=>"\u{24C36}".freeze, "\u{2F936}"=>"\u753E".freeze, "\u{2F937}"=>"\u{24C92}".freeze, "\u{2F938}"=>"\u7570".freeze, "\u{2F939}"=>"\u{2219F}".freeze, "\u{2F93A}"=>"\u7610".freeze, "\u{2F93B}"=>"\u{24FA1}".freeze, "\u{2F93C}"=>"\u{24FB8}".freeze, "\u{2F93D}"=>"\u{25044}".freeze, "\u{2F93E}"=>"\u3FFC".freeze, "\u{2F93F}"=>"\u4008".freeze, "\u{2F940}"=>"\u76F4".freeze, "\u{2F941}"=>"\u{250F3}".freeze, "\u{2F942}"=>"\u{250F2}".freeze, "\u{2F943}"=>"\u{25119}".freeze, "\u{2F944}"=>"\u{25133}".freeze, "\u{2F945}"=>"\u771E".freeze, "\u{2F946}"=>"\u771F".freeze, "\u{2F947}"=>"\u771F".freeze, "\u{2F948}"=>"\u774A".freeze, "\u{2F949}"=>"\u4039".freeze, "\u{2F94A}"=>"\u778B".freeze, "\u{2F94B}"=>"\u4046".freeze, "\u{2F94C}"=>"\u4096".freeze, "\u{2F94D}"=>"\u{2541D}".freeze, "\u{2F94E}"=>"\u784E".freeze, "\u{2F94F}"=>"\u788C".freeze, "\u{2F950}"=>"\u78CC".freeze, "\u{2F951}"=>"\u40E3".freeze, "\u{2F952}"=>"\u{25626}".freeze, "\u{2F953}"=>"\u7956".freeze, "\u{2F954}"=>"\u{2569A}".freeze, "\u{2F955}"=>"\u{256C5}".freeze, "\u{2F956}"=>"\u798F".freeze, "\u{2F957}"=>"\u79EB".freeze, "\u{2F958}"=>"\u412F".freeze, "\u{2F959}"=>"\u7A40".freeze, "\u{2F95A}"=>"\u7A4A".freeze, "\u{2F95B}"=>"\u7A4F".freeze, "\u{2F95C}"=>"\u{2597C}".freeze, "\u{2F95D}"=>"\u{25AA7}".freeze, "\u{2F95E}"=>"\u{25AA7}".freeze, "\u{2F95F}"=>"\u7AEE".freeze, "\u{2F960}"=>"\u4202".freeze, "\u{2F961}"=>"\u{25BAB}".freeze, "\u{2F962}"=>"\u7BC6".freeze, "\u{2F963}"=>"\u7BC9".freeze, "\u{2F964}"=>"\u4227".freeze, "\u{2F965}"=>"\u{25C80}".freeze, "\u{2F966}"=>"\u7CD2".freeze, "\u{2F967}"=>"\u42A0".freeze, "\u{2F968}"=>"\u7CE8".freeze, "\u{2F969}"=>"\u7CE3".freeze, "\u{2F96A}"=>"\u7D00".freeze, "\u{2F96B}"=>"\u{25F86}".freeze, "\u{2F96C}"=>"\u7D63".freeze, "\u{2F96D}"=>"\u4301".freeze, "\u{2F96E}"=>"\u7DC7".freeze, "\u{2F96F}"=>"\u7E02".freeze, "\u{2F970}"=>"\u7E45".freeze, "\u{2F971}"=>"\u4334".freeze, "\u{2F972}"=>"\u{26228}".freeze, "\u{2F973}"=>"\u{26247}".freeze, "\u{2F974}"=>"\u4359".freeze, "\u{2F975}"=>"\u{262D9}".freeze, "\u{2F976}"=>"\u7F7A".freeze, "\u{2F977}"=>"\u{2633E}".freeze, "\u{2F978}"=>"\u7F95".freeze, "\u{2F979}"=>"\u7FFA".freeze, "\u{2F97A}"=>"\u8005".freeze, "\u{2F97B}"=>"\u{264DA}".freeze, "\u{2F97C}"=>"\u{26523}".freeze, "\u{2F97D}"=>"\u8060".freeze, "\u{2F97E}"=>"\u{265A8}".freeze, "\u{2F97F}"=>"\u8070".freeze, "\u{2F980}"=>"\u{2335F}".freeze, "\u{2F981}"=>"\u43D5".freeze, "\u{2F982}"=>"\u80B2".freeze, "\u{2F983}"=>"\u8103".freeze, "\u{2F984}"=>"\u440B".freeze, "\u{2F985}"=>"\u813E".freeze, "\u{2F986}"=>"\u5AB5".freeze, "\u{2F987}"=>"\u{267A7}".freeze, "\u{2F988}"=>"\u{267B5}".freeze, "\u{2F989}"=>"\u{23393}".freeze, "\u{2F98A}"=>"\u{2339C}".freeze, "\u{2F98B}"=>"\u8201".freeze, "\u{2F98C}"=>"\u8204".freeze, "\u{2F98D}"=>"\u8F9E".freeze, "\u{2F98E}"=>"\u446B".freeze, "\u{2F98F}"=>"\u8291".freeze, "\u{2F990}"=>"\u828B".freeze, "\u{2F991}"=>"\u829D".freeze, "\u{2F992}"=>"\u52B3".freeze, "\u{2F993}"=>"\u82B1".freeze, "\u{2F994}"=>"\u82B3".freeze, "\u{2F995}"=>"\u82BD".freeze, "\u{2F996}"=>"\u82E6".freeze, "\u{2F997}"=>"\u{26B3C}".freeze, "\u{2F998}"=>"\u82E5".freeze, "\u{2F999}"=>"\u831D".freeze, "\u{2F99A}"=>"\u8363".freeze, "\u{2F99B}"=>"\u83AD".freeze, "\u{2F99C}"=>"\u8323".freeze, "\u{2F99D}"=>"\u83BD".freeze, "\u{2F99E}"=>"\u83E7".freeze, "\u{2F99F}"=>"\u8457".freeze, "\u{2F9A0}"=>"\u8353".freeze, "\u{2F9A1}"=>"\u83CA".freeze, "\u{2F9A2}"=>"\u83CC".freeze, "\u{2F9A3}"=>"\u83DC".freeze, "\u{2F9A4}"=>"\u{26C36}".freeze, "\u{2F9A5}"=>"\u{26D6B}".freeze, "\u{2F9A6}"=>"\u{26CD5}".freeze, "\u{2F9A7}"=>"\u452B".freeze, "\u{2F9A8}"=>"\u84F1".freeze, "\u{2F9A9}"=>"\u84F3".freeze, "\u{2F9AA}"=>"\u8516".freeze, "\u{2F9AB}"=>"\u{273CA}".freeze, "\u{2F9AC}"=>"\u8564".freeze, "\u{2F9AD}"=>"\u{26F2C}".freeze, "\u{2F9AE}"=>"\u455D".freeze, "\u{2F9AF}"=>"\u4561".freeze, "\u{2F9B0}"=>"\u{26FB1}".freeze, "\u{2F9B1}"=>"\u{270D2}".freeze, "\u{2F9B2}"=>"\u456B".freeze, "\u{2F9B3}"=>"\u8650".freeze, "\u{2F9B4}"=>"\u865C".freeze, "\u{2F9B5}"=>"\u8667".freeze, "\u{2F9B6}"=>"\u8669".freeze, "\u{2F9B7}"=>"\u86A9".freeze, "\u{2F9B8}"=>"\u8688".freeze, "\u{2F9B9}"=>"\u870E".freeze, "\u{2F9BA}"=>"\u86E2".freeze, "\u{2F9BB}"=>"\u8779".freeze, "\u{2F9BC}"=>"\u8728".freeze, "\u{2F9BD}"=>"\u876B".freeze, "\u{2F9BE}"=>"\u8786".freeze, "\u{2F9BF}"=>"\u45D7".freeze, "\u{2F9C0}"=>"\u87E1".freeze, "\u{2F9C1}"=>"\u8801".freeze, "\u{2F9C2}"=>"\u45F9".freeze, "\u{2F9C3}"=>"\u8860".freeze, "\u{2F9C4}"=>"\u8863".freeze, "\u{2F9C5}"=>"\u{27667}".freeze, "\u{2F9C6}"=>"\u88D7".freeze, "\u{2F9C7}"=>"\u88DE".freeze, "\u{2F9C8}"=>"\u4635".freeze, "\u{2F9C9}"=>"\u88FA".freeze, "\u{2F9CA}"=>"\u34BB".freeze, "\u{2F9CB}"=>"\u{278AE}".freeze, "\u{2F9CC}"=>"\u{27966}".freeze, "\u{2F9CD}"=>"\u46BE".freeze, "\u{2F9CE}"=>"\u46C7".freeze, "\u{2F9CF}"=>"\u8AA0".freeze, "\u{2F9D0}"=>"\u8AED".freeze, "\u{2F9D1}"=>"\u8B8A".freeze, "\u{2F9D2}"=>"\u8C55".freeze, "\u{2F9D3}"=>"\u{27CA8}".freeze, "\u{2F9D4}"=>"\u8CAB".freeze, "\u{2F9D5}"=>"\u8CC1".freeze, "\u{2F9D6}"=>"\u8D1B".freeze, "\u{2F9D7}"=>"\u8D77".freeze, "\u{2F9D8}"=>"\u{27F2F}".freeze, "\u{2F9D9}"=>"\u{20804}".freeze, "\u{2F9DA}"=>"\u8DCB".freeze, "\u{2F9DB}"=>"\u8DBC".freeze, "\u{2F9DC}"=>"\u8DF0".freeze, "\u{2F9DD}"=>"\u{208DE}".freeze, "\u{2F9DE}"=>"\u8ED4".freeze, "\u{2F9DF}"=>"\u8F38".freeze, "\u{2F9E0}"=>"\u{285D2}".freeze, "\u{2F9E1}"=>"\u{285ED}".freeze, "\u{2F9E2}"=>"\u9094".freeze, "\u{2F9E3}"=>"\u90F1".freeze, "\u{2F9E4}"=>"\u9111".freeze, "\u{2F9E5}"=>"\u{2872E}".freeze, "\u{2F9E6}"=>"\u911B".freeze, "\u{2F9E7}"=>"\u9238".freeze, "\u{2F9E8}"=>"\u92D7".freeze, "\u{2F9E9}"=>"\u92D8".freeze, "\u{2F9EA}"=>"\u927C".freeze, "\u{2F9EB}"=>"\u93F9".freeze, "\u{2F9EC}"=>"\u9415".freeze, "\u{2F9ED}"=>"\u{28BFA}".freeze, "\u{2F9EE}"=>"\u958B".freeze, "\u{2F9EF}"=>"\u4995".freeze, "\u{2F9F0}"=>"\u95B7".freeze, "\u{2F9F1}"=>"\u{28D77}".freeze, "\u{2F9F2}"=>"\u49E6".freeze, "\u{2F9F3}"=>"\u96C3".freeze, "\u{2F9F4}"=>"\u5DB2".freeze, "\u{2F9F5}"=>"\u9723".freeze, "\u{2F9F6}"=>"\u{29145}".freeze, "\u{2F9F7}"=>"\u{2921A}".freeze, "\u{2F9F8}"=>"\u4A6E".freeze, "\u{2F9F9}"=>"\u4A76".freeze, "\u{2F9FA}"=>"\u97E0".freeze, "\u{2F9FB}"=>"\u{2940A}".freeze, "\u{2F9FC}"=>"\u4AB2".freeze, "\u{2F9FD}"=>"\u{29496}".freeze, "\u{2F9FE}"=>"\u980B".freeze, "\u{2F9FF}"=>"\u980B".freeze, "\u{2FA00}"=>"\u9829".freeze, "\u{2FA01}"=>"\u{295B6}".freeze, "\u{2FA02}"=>"\u98E2".freeze, "\u{2FA03}"=>"\u4B33".freeze, "\u{2FA04}"=>"\u9929".freeze, "\u{2FA05}"=>"\u99A7".freeze, "\u{2FA06}"=>"\u99C2".freeze, "\u{2FA07}"=>"\u99FE".freeze, "\u{2FA08}"=>"\u4BCE".freeze, "\u{2FA09}"=>"\u{29B30}".freeze, "\u{2FA0A}"=>"\u9B12".freeze, "\u{2FA0B}"=>"\u9C40".freeze, "\u{2FA0C}"=>"\u9CFD".freeze, "\u{2FA0D}"=>"\u4CCE".freeze, "\u{2FA0E}"=>"\u4CED".freeze, "\u{2FA0F}"=>"\u9D67".freeze, "\u{2FA10}"=>"\u{2A0CE}".freeze, "\u{2FA11}"=>"\u4CF8".freeze, "\u{2FA12}"=>"\u{2A105}".freeze, "\u{2FA13}"=>"\u{2A20E}".freeze, "\u{2FA14}"=>"\u{2A291}".freeze, "\u{2FA15}"=>"\u9EBB".freeze, "\u{2FA16}"=>"\u4D56".freeze, "\u{2FA17}"=>"\u9EF9".freeze, "\u{2FA18}"=>"\u9EFE".freeze, "\u{2FA19}"=>"\u9F05".freeze, "\u{2FA1A}"=>"\u9F0F".freeze, "\u{2FA1B}"=>"\u9F16".freeze, "\u{2FA1C}"=>"\u9F3B".freeze, "\u{2FA1D}"=>"\u{2A600}".freeze, }.freeze KOMPATIBLE_TABLE = { "\u00A0"=>" ".freeze, "\u00A8"=>" \u0308".freeze, "\u00AA"=>"a".freeze, "\u00AF"=>" \u0304".freeze, "\u00B2"=>"2".freeze, "\u00B3"=>"3".freeze, "\u00B4"=>" \u0301".freeze, "\u00B5"=>"\u03BC".freeze, "\u00B8"=>" \u0327".freeze, "\u00B9"=>"1".freeze, "\u00BA"=>"o".freeze, "\u00BC"=>"1\u20444".freeze, "\u00BD"=>"1\u20442".freeze, "\u00BE"=>"3\u20444".freeze, "\u0132"=>"IJ".freeze, "\u0133"=>"ij".freeze, "\u013F"=>"L\u00B7".freeze, "\u0140"=>"l\u00B7".freeze, "\u0149"=>"\u02BCn".freeze, "\u017F"=>"s".freeze, "\u01C4"=>"D\u017D".freeze, "\u01C5"=>"D\u017E".freeze, "\u01C6"=>"d\u017E".freeze, "\u01C7"=>"LJ".freeze, "\u01C8"=>"Lj".freeze, "\u01C9"=>"lj".freeze, "\u01CA"=>"NJ".freeze, "\u01CB"=>"Nj".freeze, "\u01CC"=>"nj".freeze, "\u01F1"=>"DZ".freeze, "\u01F2"=>"Dz".freeze, "\u01F3"=>"dz".freeze, "\u02B0"=>"h".freeze, "\u02B1"=>"\u0266".freeze, "\u02B2"=>"j".freeze, "\u02B3"=>"r".freeze, "\u02B4"=>"\u0279".freeze, "\u02B5"=>"\u027B".freeze, "\u02B6"=>"\u0281".freeze, "\u02B7"=>"w".freeze, "\u02B8"=>"y".freeze, "\u02D8"=>" \u0306".freeze, "\u02D9"=>" \u0307".freeze, "\u02DA"=>" \u030A".freeze, "\u02DB"=>" \u0328".freeze, "\u02DC"=>" \u0303".freeze, "\u02DD"=>" \u030B".freeze, "\u02E0"=>"\u0263".freeze, "\u02E1"=>"l".freeze, "\u02E2"=>"s".freeze, "\u02E3"=>"x".freeze, "\u02E4"=>"\u0295".freeze, "\u037A"=>" \u0345".freeze, "\u0384"=>" \u0301".freeze, "\u03D0"=>"\u03B2".freeze, "\u03D1"=>"\u03B8".freeze, "\u03D2"=>"\u03A5".freeze, "\u03D5"=>"\u03C6".freeze, "\u03D6"=>"\u03C0".freeze, "\u03F0"=>"\u03BA".freeze, "\u03F1"=>"\u03C1".freeze, "\u03F2"=>"\u03C2".freeze, "\u03F4"=>"\u0398".freeze, "\u03F5"=>"\u03B5".freeze, "\u03F9"=>"\u03A3".freeze, "\u0587"=>"\u0565\u0582".freeze, "\u0675"=>"\u0627\u0674".freeze, "\u0676"=>"\u0648\u0674".freeze, "\u0677"=>"\u06C7\u0674".freeze, "\u0678"=>"\u064A\u0674".freeze, "\u0E33"=>"\u0E4D\u0E32".freeze, "\u0EB3"=>"\u0ECD\u0EB2".freeze, "\u0EDC"=>"\u0EAB\u0E99".freeze, "\u0EDD"=>"\u0EAB\u0EA1".freeze, "\u0F0C"=>"\u0F0B".freeze, "\u0F77"=>"\u0FB2\u0F81".freeze, "\u0F79"=>"\u0FB3\u0F81".freeze, "\u10FC"=>"\u10DC".freeze, "\u1D2C"=>"A".freeze, "\u1D2D"=>"\u00C6".freeze, "\u1D2E"=>"B".freeze, "\u1D30"=>"D".freeze, "\u1D31"=>"E".freeze, "\u1D32"=>"\u018E".freeze, "\u1D33"=>"G".freeze, "\u1D34"=>"H".freeze, "\u1D35"=>"I".freeze, "\u1D36"=>"J".freeze, "\u1D37"=>"K".freeze, "\u1D38"=>"L".freeze, "\u1D39"=>"M".freeze, "\u1D3A"=>"N".freeze, "\u1D3C"=>"O".freeze, "\u1D3D"=>"\u0222".freeze, "\u1D3E"=>"P".freeze, "\u1D3F"=>"R".freeze, "\u1D40"=>"T".freeze, "\u1D41"=>"U".freeze, "\u1D42"=>"W".freeze, "\u1D43"=>"a".freeze, "\u1D44"=>"\u0250".freeze, "\u1D45"=>"\u0251".freeze, "\u1D46"=>"\u1D02".freeze, "\u1D47"=>"b".freeze, "\u1D48"=>"d".freeze, "\u1D49"=>"e".freeze, "\u1D4A"=>"\u0259".freeze, "\u1D4B"=>"\u025B".freeze, "\u1D4C"=>"\u025C".freeze, "\u1D4D"=>"g".freeze, "\u1D4F"=>"k".freeze, "\u1D50"=>"m".freeze, "\u1D51"=>"\u014B".freeze, "\u1D52"=>"o".freeze, "\u1D53"=>"\u0254".freeze, "\u1D54"=>"\u1D16".freeze, "\u1D55"=>"\u1D17".freeze, "\u1D56"=>"p".freeze, "\u1D57"=>"t".freeze, "\u1D58"=>"u".freeze, "\u1D59"=>"\u1D1D".freeze, "\u1D5A"=>"\u026F".freeze, "\u1D5B"=>"v".freeze, "\u1D5C"=>"\u1D25".freeze, "\u1D5D"=>"\u03B2".freeze, "\u1D5E"=>"\u03B3".freeze, "\u1D5F"=>"\u03B4".freeze, "\u1D60"=>"\u03C6".freeze, "\u1D61"=>"\u03C7".freeze, "\u1D62"=>"i".freeze, "\u1D63"=>"r".freeze, "\u1D64"=>"u".freeze, "\u1D65"=>"v".freeze, "\u1D66"=>"\u03B2".freeze, "\u1D67"=>"\u03B3".freeze, "\u1D68"=>"\u03C1".freeze, "\u1D69"=>"\u03C6".freeze, "\u1D6A"=>"\u03C7".freeze, "\u1D78"=>"\u043D".freeze, "\u1D9B"=>"\u0252".freeze, "\u1D9C"=>"c".freeze, "\u1D9D"=>"\u0255".freeze, "\u1D9E"=>"\u00F0".freeze, "\u1D9F"=>"\u025C".freeze, "\u1DA0"=>"f".freeze, "\u1DA1"=>"\u025F".freeze, "\u1DA2"=>"\u0261".freeze, "\u1DA3"=>"\u0265".freeze, "\u1DA4"=>"\u0268".freeze, "\u1DA5"=>"\u0269".freeze, "\u1DA6"=>"\u026A".freeze, "\u1DA7"=>"\u1D7B".freeze, "\u1DA8"=>"\u029D".freeze, "\u1DA9"=>"\u026D".freeze, "\u1DAA"=>"\u1D85".freeze, "\u1DAB"=>"\u029F".freeze, "\u1DAC"=>"\u0271".freeze, "\u1DAD"=>"\u0270".freeze, "\u1DAE"=>"\u0272".freeze, "\u1DAF"=>"\u0273".freeze, "\u1DB0"=>"\u0274".freeze, "\u1DB1"=>"\u0275".freeze, "\u1DB2"=>"\u0278".freeze, "\u1DB3"=>"\u0282".freeze, "\u1DB4"=>"\u0283".freeze, "\u1DB5"=>"\u01AB".freeze, "\u1DB6"=>"\u0289".freeze, "\u1DB7"=>"\u028A".freeze, "\u1DB8"=>"\u1D1C".freeze, "\u1DB9"=>"\u028B".freeze, "\u1DBA"=>"\u028C".freeze, "\u1DBB"=>"z".freeze, "\u1DBC"=>"\u0290".freeze, "\u1DBD"=>"\u0291".freeze, "\u1DBE"=>"\u0292".freeze, "\u1DBF"=>"\u03B8".freeze, "\u1E9A"=>"a\u02BE".freeze, "\u1FBD"=>" \u0313".freeze, "\u1FBF"=>" \u0313".freeze, "\u1FC0"=>" \u0342".freeze, "\u1FFE"=>" \u0314".freeze, "\u2002"=>" ".freeze, "\u2003"=>" ".freeze, "\u2004"=>" ".freeze, "\u2005"=>" ".freeze, "\u2006"=>" ".freeze, "\u2007"=>" ".freeze, "\u2008"=>" ".freeze, "\u2009"=>" ".freeze, "\u200A"=>" ".freeze, "\u2011"=>"\u2010".freeze, "\u2017"=>" \u0333".freeze, "\u2024"=>".".freeze, "\u2025"=>"..".freeze, "\u2026"=>"...".freeze, "\u202F"=>" ".freeze, "\u2033"=>"\u2032\u2032".freeze, "\u2034"=>"\u2032\u2032\u2032".freeze, "\u2036"=>"\u2035\u2035".freeze, "\u2037"=>"\u2035\u2035\u2035".freeze, "\u203C"=>"!!".freeze, "\u203E"=>" \u0305".freeze, "\u2047"=>"??".freeze, "\u2048"=>"?!".freeze, "\u2049"=>"!?".freeze, "\u2057"=>"\u2032\u2032\u2032\u2032".freeze, "\u205F"=>" ".freeze, "\u2070"=>"0".freeze, "\u2071"=>"i".freeze, "\u2074"=>"4".freeze, "\u2075"=>"5".freeze, "\u2076"=>"6".freeze, "\u2077"=>"7".freeze, "\u2078"=>"8".freeze, "\u2079"=>"9".freeze, "\u207A"=>"+".freeze, "\u207B"=>"\u2212".freeze, "\u207C"=>"=".freeze, "\u207D"=>"(".freeze, "\u207E"=>")".freeze, "\u207F"=>"n".freeze, "\u2080"=>"0".freeze, "\u2081"=>"1".freeze, "\u2082"=>"2".freeze, "\u2083"=>"3".freeze, "\u2084"=>"4".freeze, "\u2085"=>"5".freeze, "\u2086"=>"6".freeze, "\u2087"=>"7".freeze, "\u2088"=>"8".freeze, "\u2089"=>"9".freeze, "\u208A"=>"+".freeze, "\u208B"=>"\u2212".freeze, "\u208C"=>"=".freeze, "\u208D"=>"(".freeze, "\u208E"=>")".freeze, "\u2090"=>"a".freeze, "\u2091"=>"e".freeze, "\u2092"=>"o".freeze, "\u2093"=>"x".freeze, "\u2094"=>"\u0259".freeze, "\u2095"=>"h".freeze, "\u2096"=>"k".freeze, "\u2097"=>"l".freeze, "\u2098"=>"m".freeze, "\u2099"=>"n".freeze, "\u209A"=>"p".freeze, "\u209B"=>"s".freeze, "\u209C"=>"t".freeze, "\u20A8"=>"Rs".freeze, "\u2100"=>"a/c".freeze, "\u2101"=>"a/s".freeze, "\u2102"=>"C".freeze, "\u2103"=>"\u00B0C".freeze, "\u2105"=>"c/o".freeze, "\u2106"=>"c/u".freeze, "\u2107"=>"\u0190".freeze, "\u2109"=>"\u00B0F".freeze, "\u210A"=>"g".freeze, "\u210B"=>"H".freeze, "\u210C"=>"H".freeze, "\u210D"=>"H".freeze, "\u210E"=>"h".freeze, "\u210F"=>"\u0127".freeze, "\u2110"=>"I".freeze, "\u2111"=>"I".freeze, "\u2112"=>"L".freeze, "\u2113"=>"l".freeze, "\u2115"=>"N".freeze, "\u2116"=>"No".freeze, "\u2119"=>"P".freeze, "\u211A"=>"Q".freeze, "\u211B"=>"R".freeze, "\u211C"=>"R".freeze, "\u211D"=>"R".freeze, "\u2120"=>"SM".freeze, "\u2121"=>"TEL".freeze, "\u2122"=>"TM".freeze, "\u2124"=>"Z".freeze, "\u2128"=>"Z".freeze, "\u212C"=>"B".freeze, "\u212D"=>"C".freeze, "\u212F"=>"e".freeze, "\u2130"=>"E".freeze, "\u2131"=>"F".freeze, "\u2133"=>"M".freeze, "\u2134"=>"o".freeze, "\u2135"=>"\u05D0".freeze, "\u2136"=>"\u05D1".freeze, "\u2137"=>"\u05D2".freeze, "\u2138"=>"\u05D3".freeze, "\u2139"=>"i".freeze, "\u213B"=>"FAX".freeze, "\u213C"=>"\u03C0".freeze, "\u213D"=>"\u03B3".freeze, "\u213E"=>"\u0393".freeze, "\u213F"=>"\u03A0".freeze, "\u2140"=>"\u2211".freeze, "\u2145"=>"D".freeze, "\u2146"=>"d".freeze, "\u2147"=>"e".freeze, "\u2148"=>"i".freeze, "\u2149"=>"j".freeze, "\u2150"=>"1\u20447".freeze, "\u2151"=>"1\u20449".freeze, "\u2152"=>"1\u204410".freeze, "\u2153"=>"1\u20443".freeze, "\u2154"=>"2\u20443".freeze, "\u2155"=>"1\u20445".freeze, "\u2156"=>"2\u20445".freeze, "\u2157"=>"3\u20445".freeze, "\u2158"=>"4\u20445".freeze, "\u2159"=>"1\u20446".freeze, "\u215A"=>"5\u20446".freeze, "\u215B"=>"1\u20448".freeze, "\u215C"=>"3\u20448".freeze, "\u215D"=>"5\u20448".freeze, "\u215E"=>"7\u20448".freeze, "\u215F"=>"1\u2044".freeze, "\u2160"=>"I".freeze, "\u2161"=>"II".freeze, "\u2162"=>"III".freeze, "\u2163"=>"IV".freeze, "\u2164"=>"V".freeze, "\u2165"=>"VI".freeze, "\u2166"=>"VII".freeze, "\u2167"=>"VIII".freeze, "\u2168"=>"IX".freeze, "\u2169"=>"X".freeze, "\u216A"=>"XI".freeze, "\u216B"=>"XII".freeze, "\u216C"=>"L".freeze, "\u216D"=>"C".freeze, "\u216E"=>"D".freeze, "\u216F"=>"M".freeze, "\u2170"=>"i".freeze, "\u2171"=>"ii".freeze, "\u2172"=>"iii".freeze, "\u2173"=>"iv".freeze, "\u2174"=>"v".freeze, "\u2175"=>"vi".freeze, "\u2176"=>"vii".freeze, "\u2177"=>"viii".freeze, "\u2178"=>"ix".freeze, "\u2179"=>"x".freeze, "\u217A"=>"xi".freeze, "\u217B"=>"xii".freeze, "\u217C"=>"l".freeze, "\u217D"=>"c".freeze, "\u217E"=>"d".freeze, "\u217F"=>"m".freeze, "\u2189"=>"0\u20443".freeze, "\u222C"=>"\u222B\u222B".freeze, "\u222D"=>"\u222B\u222B\u222B".freeze, "\u222F"=>"\u222E\u222E".freeze, "\u2230"=>"\u222E\u222E\u222E".freeze, "\u2460"=>"1".freeze, "\u2461"=>"2".freeze, "\u2462"=>"3".freeze, "\u2463"=>"4".freeze, "\u2464"=>"5".freeze, "\u2465"=>"6".freeze, "\u2466"=>"7".freeze, "\u2467"=>"8".freeze, "\u2468"=>"9".freeze, "\u2469"=>"10".freeze, "\u246A"=>"11".freeze, "\u246B"=>"12".freeze, "\u246C"=>"13".freeze, "\u246D"=>"14".freeze, "\u246E"=>"15".freeze, "\u246F"=>"16".freeze, "\u2470"=>"17".freeze, "\u2471"=>"18".freeze, "\u2472"=>"19".freeze, "\u2473"=>"20".freeze, "\u2474"=>"(1)".freeze, "\u2475"=>"(2)".freeze, "\u2476"=>"(3)".freeze, "\u2477"=>"(4)".freeze, "\u2478"=>"(5)".freeze, "\u2479"=>"(6)".freeze, "\u247A"=>"(7)".freeze, "\u247B"=>"(8)".freeze, "\u247C"=>"(9)".freeze, "\u247D"=>"(10)".freeze, "\u247E"=>"(11)".freeze, "\u247F"=>"(12)".freeze, "\u2480"=>"(13)".freeze, "\u2481"=>"(14)".freeze, "\u2482"=>"(15)".freeze, "\u2483"=>"(16)".freeze, "\u2484"=>"(17)".freeze, "\u2485"=>"(18)".freeze, "\u2486"=>"(19)".freeze, "\u2487"=>"(20)".freeze, "\u2488"=>"1.".freeze, "\u2489"=>"2.".freeze, "\u248A"=>"3.".freeze, "\u248B"=>"4.".freeze, "\u248C"=>"5.".freeze, "\u248D"=>"6.".freeze, "\u248E"=>"7.".freeze, "\u248F"=>"8.".freeze, "\u2490"=>"9.".freeze, "\u2491"=>"10.".freeze, "\u2492"=>"11.".freeze, "\u2493"=>"12.".freeze, "\u2494"=>"13.".freeze, "\u2495"=>"14.".freeze, "\u2496"=>"15.".freeze, "\u2497"=>"16.".freeze, "\u2498"=>"17.".freeze, "\u2499"=>"18.".freeze, "\u249A"=>"19.".freeze, "\u249B"=>"20.".freeze, "\u249C"=>"(a)".freeze, "\u249D"=>"(b)".freeze, "\u249E"=>"(c)".freeze, "\u249F"=>"(d)".freeze, "\u24A0"=>"(e)".freeze, "\u24A1"=>"(f)".freeze, "\u24A2"=>"(g)".freeze, "\u24A3"=>"(h)".freeze, "\u24A4"=>"(i)".freeze, "\u24A5"=>"(j)".freeze, "\u24A6"=>"(k)".freeze, "\u24A7"=>"(l)".freeze, "\u24A8"=>"(m)".freeze, "\u24A9"=>"(n)".freeze, "\u24AA"=>"(o)".freeze, "\u24AB"=>"(p)".freeze, "\u24AC"=>"(q)".freeze, "\u24AD"=>"(r)".freeze, "\u24AE"=>"(s)".freeze, "\u24AF"=>"(t)".freeze, "\u24B0"=>"(u)".freeze, "\u24B1"=>"(v)".freeze, "\u24B2"=>"(w)".freeze, "\u24B3"=>"(x)".freeze, "\u24B4"=>"(y)".freeze, "\u24B5"=>"(z)".freeze, "\u24B6"=>"A".freeze, "\u24B7"=>"B".freeze, "\u24B8"=>"C".freeze, "\u24B9"=>"D".freeze, "\u24BA"=>"E".freeze, "\u24BB"=>"F".freeze, "\u24BC"=>"G".freeze, "\u24BD"=>"H".freeze, "\u24BE"=>"I".freeze, "\u24BF"=>"J".freeze, "\u24C0"=>"K".freeze, "\u24C1"=>"L".freeze, "\u24C2"=>"M".freeze, "\u24C3"=>"N".freeze, "\u24C4"=>"O".freeze, "\u24C5"=>"P".freeze, "\u24C6"=>"Q".freeze, "\u24C7"=>"R".freeze, "\u24C8"=>"S".freeze, "\u24C9"=>"T".freeze, "\u24CA"=>"U".freeze, "\u24CB"=>"V".freeze, "\u24CC"=>"W".freeze, "\u24CD"=>"X".freeze, "\u24CE"=>"Y".freeze, "\u24CF"=>"Z".freeze, "\u24D0"=>"a".freeze, "\u24D1"=>"b".freeze, "\u24D2"=>"c".freeze, "\u24D3"=>"d".freeze, "\u24D4"=>"e".freeze, "\u24D5"=>"f".freeze, "\u24D6"=>"g".freeze, "\u24D7"=>"h".freeze, "\u24D8"=>"i".freeze, "\u24D9"=>"j".freeze, "\u24DA"=>"k".freeze, "\u24DB"=>"l".freeze, "\u24DC"=>"m".freeze, "\u24DD"=>"n".freeze, "\u24DE"=>"o".freeze, "\u24DF"=>"p".freeze, "\u24E0"=>"q".freeze, "\u24E1"=>"r".freeze, "\u24E2"=>"s".freeze, "\u24E3"=>"t".freeze, "\u24E4"=>"u".freeze, "\u24E5"=>"v".freeze, "\u24E6"=>"w".freeze, "\u24E7"=>"x".freeze, "\u24E8"=>"y".freeze, "\u24E9"=>"z".freeze, "\u24EA"=>"0".freeze, "\u2A0C"=>"\u222B\u222B\u222B\u222B".freeze, "\u2A74"=>"::=".freeze, "\u2A75"=>"==".freeze, "\u2A76"=>"===".freeze, "\u2C7C"=>"j".freeze, "\u2C7D"=>"V".freeze, "\u2D6F"=>"\u2D61".freeze, "\u2E9F"=>"\u6BCD".freeze, "\u2EF3"=>"\u9F9F".freeze, "\u2F00"=>"\u4E00".freeze, "\u2F01"=>"\u4E28".freeze, "\u2F02"=>"\u4E36".freeze, "\u2F03"=>"\u4E3F".freeze, "\u2F04"=>"\u4E59".freeze, "\u2F05"=>"\u4E85".freeze, "\u2F06"=>"\u4E8C".freeze, "\u2F07"=>"\u4EA0".freeze, "\u2F08"=>"\u4EBA".freeze, "\u2F09"=>"\u513F".freeze, "\u2F0A"=>"\u5165".freeze, "\u2F0B"=>"\u516B".freeze, "\u2F0C"=>"\u5182".freeze, "\u2F0D"=>"\u5196".freeze, "\u2F0E"=>"\u51AB".freeze, "\u2F0F"=>"\u51E0".freeze, "\u2F10"=>"\u51F5".freeze, "\u2F11"=>"\u5200".freeze, "\u2F12"=>"\u529B".freeze, "\u2F13"=>"\u52F9".freeze, "\u2F14"=>"\u5315".freeze, "\u2F15"=>"\u531A".freeze, "\u2F16"=>"\u5338".freeze, "\u2F17"=>"\u5341".freeze, "\u2F18"=>"\u535C".freeze, "\u2F19"=>"\u5369".freeze, "\u2F1A"=>"\u5382".freeze, "\u2F1B"=>"\u53B6".freeze, "\u2F1C"=>"\u53C8".freeze, "\u2F1D"=>"\u53E3".freeze, "\u2F1E"=>"\u56D7".freeze, "\u2F1F"=>"\u571F".freeze, "\u2F20"=>"\u58EB".freeze, "\u2F21"=>"\u5902".freeze, "\u2F22"=>"\u590A".freeze, "\u2F23"=>"\u5915".freeze, "\u2F24"=>"\u5927".freeze, "\u2F25"=>"\u5973".freeze, "\u2F26"=>"\u5B50".freeze, "\u2F27"=>"\u5B80".freeze, "\u2F28"=>"\u5BF8".freeze, "\u2F29"=>"\u5C0F".freeze, "\u2F2A"=>"\u5C22".freeze, "\u2F2B"=>"\u5C38".freeze, "\u2F2C"=>"\u5C6E".freeze, "\u2F2D"=>"\u5C71".freeze, "\u2F2E"=>"\u5DDB".freeze, "\u2F2F"=>"\u5DE5".freeze, "\u2F30"=>"\u5DF1".freeze, "\u2F31"=>"\u5DFE".freeze, "\u2F32"=>"\u5E72".freeze, "\u2F33"=>"\u5E7A".freeze, "\u2F34"=>"\u5E7F".freeze, "\u2F35"=>"\u5EF4".freeze, "\u2F36"=>"\u5EFE".freeze, "\u2F37"=>"\u5F0B".freeze, "\u2F38"=>"\u5F13".freeze, "\u2F39"=>"\u5F50".freeze, "\u2F3A"=>"\u5F61".freeze, "\u2F3B"=>"\u5F73".freeze, "\u2F3C"=>"\u5FC3".freeze, "\u2F3D"=>"\u6208".freeze, "\u2F3E"=>"\u6236".freeze, "\u2F3F"=>"\u624B".freeze, "\u2F40"=>"\u652F".freeze, "\u2F41"=>"\u6534".freeze, "\u2F42"=>"\u6587".freeze, "\u2F43"=>"\u6597".freeze, "\u2F44"=>"\u65A4".freeze, "\u2F45"=>"\u65B9".freeze, "\u2F46"=>"\u65E0".freeze, "\u2F47"=>"\u65E5".freeze, "\u2F48"=>"\u66F0".freeze, "\u2F49"=>"\u6708".freeze, "\u2F4A"=>"\u6728".freeze, "\u2F4B"=>"\u6B20".freeze, "\u2F4C"=>"\u6B62".freeze, "\u2F4D"=>"\u6B79".freeze, "\u2F4E"=>"\u6BB3".freeze, "\u2F4F"=>"\u6BCB".freeze, "\u2F50"=>"\u6BD4".freeze, "\u2F51"=>"\u6BDB".freeze, "\u2F52"=>"\u6C0F".freeze, "\u2F53"=>"\u6C14".freeze, "\u2F54"=>"\u6C34".freeze, "\u2F55"=>"\u706B".freeze, "\u2F56"=>"\u722A".freeze, "\u2F57"=>"\u7236".freeze, "\u2F58"=>"\u723B".freeze, "\u2F59"=>"\u723F".freeze, "\u2F5A"=>"\u7247".freeze, "\u2F5B"=>"\u7259".freeze, "\u2F5C"=>"\u725B".freeze, "\u2F5D"=>"\u72AC".freeze, "\u2F5E"=>"\u7384".freeze, "\u2F5F"=>"\u7389".freeze, "\u2F60"=>"\u74DC".freeze, "\u2F61"=>"\u74E6".freeze, "\u2F62"=>"\u7518".freeze, "\u2F63"=>"\u751F".freeze, "\u2F64"=>"\u7528".freeze, "\u2F65"=>"\u7530".freeze, "\u2F66"=>"\u758B".freeze, "\u2F67"=>"\u7592".freeze, "\u2F68"=>"\u7676".freeze, "\u2F69"=>"\u767D".freeze, "\u2F6A"=>"\u76AE".freeze, "\u2F6B"=>"\u76BF".freeze, "\u2F6C"=>"\u76EE".freeze, "\u2F6D"=>"\u77DB".freeze, "\u2F6E"=>"\u77E2".freeze, "\u2F6F"=>"\u77F3".freeze, "\u2F70"=>"\u793A".freeze, "\u2F71"=>"\u79B8".freeze, "\u2F72"=>"\u79BE".freeze, "\u2F73"=>"\u7A74".freeze, "\u2F74"=>"\u7ACB".freeze, "\u2F75"=>"\u7AF9".freeze, "\u2F76"=>"\u7C73".freeze, "\u2F77"=>"\u7CF8".freeze, "\u2F78"=>"\u7F36".freeze, "\u2F79"=>"\u7F51".freeze, "\u2F7A"=>"\u7F8A".freeze, "\u2F7B"=>"\u7FBD".freeze, "\u2F7C"=>"\u8001".freeze, "\u2F7D"=>"\u800C".freeze, "\u2F7E"=>"\u8012".freeze, "\u2F7F"=>"\u8033".freeze, "\u2F80"=>"\u807F".freeze, "\u2F81"=>"\u8089".freeze, "\u2F82"=>"\u81E3".freeze, "\u2F83"=>"\u81EA".freeze, "\u2F84"=>"\u81F3".freeze, "\u2F85"=>"\u81FC".freeze, "\u2F86"=>"\u820C".freeze, "\u2F87"=>"\u821B".freeze, "\u2F88"=>"\u821F".freeze, "\u2F89"=>"\u826E".freeze, "\u2F8A"=>"\u8272".freeze, "\u2F8B"=>"\u8278".freeze, "\u2F8C"=>"\u864D".freeze, "\u2F8D"=>"\u866B".freeze, "\u2F8E"=>"\u8840".freeze, "\u2F8F"=>"\u884C".freeze, "\u2F90"=>"\u8863".freeze, "\u2F91"=>"\u897E".freeze, "\u2F92"=>"\u898B".freeze, "\u2F93"=>"\u89D2".freeze, "\u2F94"=>"\u8A00".freeze, "\u2F95"=>"\u8C37".freeze, "\u2F96"=>"\u8C46".freeze, "\u2F97"=>"\u8C55".freeze, "\u2F98"=>"\u8C78".freeze, "\u2F99"=>"\u8C9D".freeze, "\u2F9A"=>"\u8D64".freeze, "\u2F9B"=>"\u8D70".freeze, "\u2F9C"=>"\u8DB3".freeze, "\u2F9D"=>"\u8EAB".freeze, "\u2F9E"=>"\u8ECA".freeze, "\u2F9F"=>"\u8F9B".freeze, "\u2FA0"=>"\u8FB0".freeze, "\u2FA1"=>"\u8FB5".freeze, "\u2FA2"=>"\u9091".freeze, "\u2FA3"=>"\u9149".freeze, "\u2FA4"=>"\u91C6".freeze, "\u2FA5"=>"\u91CC".freeze, "\u2FA6"=>"\u91D1".freeze, "\u2FA7"=>"\u9577".freeze, "\u2FA8"=>"\u9580".freeze, "\u2FA9"=>"\u961C".freeze, "\u2FAA"=>"\u96B6".freeze, "\u2FAB"=>"\u96B9".freeze, "\u2FAC"=>"\u96E8".freeze, "\u2FAD"=>"\u9751".freeze, "\u2FAE"=>"\u975E".freeze, "\u2FAF"=>"\u9762".freeze, "\u2FB0"=>"\u9769".freeze, "\u2FB1"=>"\u97CB".freeze, "\u2FB2"=>"\u97ED".freeze, "\u2FB3"=>"\u97F3".freeze, "\u2FB4"=>"\u9801".freeze, "\u2FB5"=>"\u98A8".freeze, "\u2FB6"=>"\u98DB".freeze, "\u2FB7"=>"\u98DF".freeze, "\u2FB8"=>"\u9996".freeze, "\u2FB9"=>"\u9999".freeze, "\u2FBA"=>"\u99AC".freeze, "\u2FBB"=>"\u9AA8".freeze, "\u2FBC"=>"\u9AD8".freeze, "\u2FBD"=>"\u9ADF".freeze, "\u2FBE"=>"\u9B25".freeze, "\u2FBF"=>"\u9B2F".freeze, "\u2FC0"=>"\u9B32".freeze, "\u2FC1"=>"\u9B3C".freeze, "\u2FC2"=>"\u9B5A".freeze, "\u2FC3"=>"\u9CE5".freeze, "\u2FC4"=>"\u9E75".freeze, "\u2FC5"=>"\u9E7F".freeze, "\u2FC6"=>"\u9EA5".freeze, "\u2FC7"=>"\u9EBB".freeze, "\u2FC8"=>"\u9EC3".freeze, "\u2FC9"=>"\u9ECD".freeze, "\u2FCA"=>"\u9ED1".freeze, "\u2FCB"=>"\u9EF9".freeze, "\u2FCC"=>"\u9EFD".freeze, "\u2FCD"=>"\u9F0E".freeze, "\u2FCE"=>"\u9F13".freeze, "\u2FCF"=>"\u9F20".freeze, "\u2FD0"=>"\u9F3B".freeze, "\u2FD1"=>"\u9F4A".freeze, "\u2FD2"=>"\u9F52".freeze, "\u2FD3"=>"\u9F8D".freeze, "\u2FD4"=>"\u9F9C".freeze, "\u2FD5"=>"\u9FA0".freeze, "\u3000"=>" ".freeze, "\u3036"=>"\u3012".freeze, "\u3038"=>"\u5341".freeze, "\u3039"=>"\u5344".freeze, "\u303A"=>"\u5345".freeze, "\u309B"=>" \u3099".freeze, "\u309C"=>" \u309A".freeze, "\u309F"=>"\u3088\u308A".freeze, "\u30FF"=>"\u30B3\u30C8".freeze, "\u3131"=>"\u1100".freeze, "\u3132"=>"\u1101".freeze, "\u3133"=>"\u11AA".freeze, "\u3134"=>"\u1102".freeze, "\u3135"=>"\u11AC".freeze, "\u3136"=>"\u11AD".freeze, "\u3137"=>"\u1103".freeze, "\u3138"=>"\u1104".freeze, "\u3139"=>"\u1105".freeze, "\u313A"=>"\u11B0".freeze, "\u313B"=>"\u11B1".freeze, "\u313C"=>"\u11B2".freeze, "\u313D"=>"\u11B3".freeze, "\u313E"=>"\u11B4".freeze, "\u313F"=>"\u11B5".freeze, "\u3140"=>"\u111A".freeze, "\u3141"=>"\u1106".freeze, "\u3142"=>"\u1107".freeze, "\u3143"=>"\u1108".freeze, "\u3144"=>"\u1121".freeze, "\u3145"=>"\u1109".freeze, "\u3146"=>"\u110A".freeze, "\u3147"=>"\u110B".freeze, "\u3148"=>"\u110C".freeze, "\u3149"=>"\u110D".freeze, "\u314A"=>"\u110E".freeze, "\u314B"=>"\u110F".freeze, "\u314C"=>"\u1110".freeze, "\u314D"=>"\u1111".freeze, "\u314E"=>"\u1112".freeze, "\u314F"=>"\u1161".freeze, "\u3150"=>"\u1162".freeze, "\u3151"=>"\u1163".freeze, "\u3152"=>"\u1164".freeze, "\u3153"=>"\u1165".freeze, "\u3154"=>"\u1166".freeze, "\u3155"=>"\u1167".freeze, "\u3156"=>"\u1168".freeze, "\u3157"=>"\u1169".freeze, "\u3158"=>"\u116A".freeze, "\u3159"=>"\u116B".freeze, "\u315A"=>"\u116C".freeze, "\u315B"=>"\u116D".freeze, "\u315C"=>"\u116E".freeze, "\u315D"=>"\u116F".freeze, "\u315E"=>"\u1170".freeze, "\u315F"=>"\u1171".freeze, "\u3160"=>"\u1172".freeze, "\u3161"=>"\u1173".freeze, "\u3162"=>"\u1174".freeze, "\u3163"=>"\u1175".freeze, "\u3164"=>"\u1160".freeze, "\u3165"=>"\u1114".freeze, "\u3166"=>"\u1115".freeze, "\u3167"=>"\u11C7".freeze, "\u3168"=>"\u11C8".freeze, "\u3169"=>"\u11CC".freeze, "\u316A"=>"\u11CE".freeze, "\u316B"=>"\u11D3".freeze, "\u316C"=>"\u11D7".freeze, "\u316D"=>"\u11D9".freeze, "\u316E"=>"\u111C".freeze, "\u316F"=>"\u11DD".freeze, "\u3170"=>"\u11DF".freeze, "\u3171"=>"\u111D".freeze, "\u3172"=>"\u111E".freeze, "\u3173"=>"\u1120".freeze, "\u3174"=>"\u1122".freeze, "\u3175"=>"\u1123".freeze, "\u3176"=>"\u1127".freeze, "\u3177"=>"\u1129".freeze, "\u3178"=>"\u112B".freeze, "\u3179"=>"\u112C".freeze, "\u317A"=>"\u112D".freeze, "\u317B"=>"\u112E".freeze, "\u317C"=>"\u112F".freeze, "\u317D"=>"\u1132".freeze, "\u317E"=>"\u1136".freeze, "\u317F"=>"\u1140".freeze, "\u3180"=>"\u1147".freeze, "\u3181"=>"\u114C".freeze, "\u3182"=>"\u11F1".freeze, "\u3183"=>"\u11F2".freeze, "\u3184"=>"\u1157".freeze, "\u3185"=>"\u1158".freeze, "\u3186"=>"\u1159".freeze, "\u3187"=>"\u1184".freeze, "\u3188"=>"\u1185".freeze, "\u3189"=>"\u1188".freeze, "\u318A"=>"\u1191".freeze, "\u318B"=>"\u1192".freeze, "\u318C"=>"\u1194".freeze, "\u318D"=>"\u119E".freeze, "\u318E"=>"\u11A1".freeze, "\u3192"=>"\u4E00".freeze, "\u3193"=>"\u4E8C".freeze, "\u3194"=>"\u4E09".freeze, "\u3195"=>"\u56DB".freeze, "\u3196"=>"\u4E0A".freeze, "\u3197"=>"\u4E2D".freeze, "\u3198"=>"\u4E0B".freeze, "\u3199"=>"\u7532".freeze, "\u319A"=>"\u4E59".freeze, "\u319B"=>"\u4E19".freeze, "\u319C"=>"\u4E01".freeze, "\u319D"=>"\u5929".freeze, "\u319E"=>"\u5730".freeze, "\u319F"=>"\u4EBA".freeze, "\u3200"=>"(\u1100)".freeze, "\u3201"=>"(\u1102)".freeze, "\u3202"=>"(\u1103)".freeze, "\u3203"=>"(\u1105)".freeze, "\u3204"=>"(\u1106)".freeze, "\u3205"=>"(\u1107)".freeze, "\u3206"=>"(\u1109)".freeze, "\u3207"=>"(\u110B)".freeze, "\u3208"=>"(\u110C)".freeze, "\u3209"=>"(\u110E)".freeze, "\u320A"=>"(\u110F)".freeze, "\u320B"=>"(\u1110)".freeze, "\u320C"=>"(\u1111)".freeze, "\u320D"=>"(\u1112)".freeze, "\u320E"=>"(\u1100\u1161)".freeze, "\u320F"=>"(\u1102\u1161)".freeze, "\u3210"=>"(\u1103\u1161)".freeze, "\u3211"=>"(\u1105\u1161)".freeze, "\u3212"=>"(\u1106\u1161)".freeze, "\u3213"=>"(\u1107\u1161)".freeze, "\u3214"=>"(\u1109\u1161)".freeze, "\u3215"=>"(\u110B\u1161)".freeze, "\u3216"=>"(\u110C\u1161)".freeze, "\u3217"=>"(\u110E\u1161)".freeze, "\u3218"=>"(\u110F\u1161)".freeze, "\u3219"=>"(\u1110\u1161)".freeze, "\u321A"=>"(\u1111\u1161)".freeze, "\u321B"=>"(\u1112\u1161)".freeze, "\u321C"=>"(\u110C\u116E)".freeze, "\u321D"=>"(\u110B\u1169\u110C\u1165\u11AB)".freeze, "\u321E"=>"(\u110B\u1169\u1112\u116E)".freeze, "\u3220"=>"(\u4E00)".freeze, "\u3221"=>"(\u4E8C)".freeze, "\u3222"=>"(\u4E09)".freeze, "\u3223"=>"(\u56DB)".freeze, "\u3224"=>"(\u4E94)".freeze, "\u3225"=>"(\u516D)".freeze, "\u3226"=>"(\u4E03)".freeze, "\u3227"=>"(\u516B)".freeze, "\u3228"=>"(\u4E5D)".freeze, "\u3229"=>"(\u5341)".freeze, "\u322A"=>"(\u6708)".freeze, "\u322B"=>"(\u706B)".freeze, "\u322C"=>"(\u6C34)".freeze, "\u322D"=>"(\u6728)".freeze, "\u322E"=>"(\u91D1)".freeze, "\u322F"=>"(\u571F)".freeze, "\u3230"=>"(\u65E5)".freeze, "\u3231"=>"(\u682A)".freeze, "\u3232"=>"(\u6709)".freeze, "\u3233"=>"(\u793E)".freeze, "\u3234"=>"(\u540D)".freeze, "\u3235"=>"(\u7279)".freeze, "\u3236"=>"(\u8CA1)".freeze, "\u3237"=>"(\u795D)".freeze, "\u3238"=>"(\u52B4)".freeze, "\u3239"=>"(\u4EE3)".freeze, "\u323A"=>"(\u547C)".freeze, "\u323B"=>"(\u5B66)".freeze, "\u323C"=>"(\u76E3)".freeze, "\u323D"=>"(\u4F01)".freeze, "\u323E"=>"(\u8CC7)".freeze, "\u323F"=>"(\u5354)".freeze, "\u3240"=>"(\u796D)".freeze, "\u3241"=>"(\u4F11)".freeze, "\u3242"=>"(\u81EA)".freeze, "\u3243"=>"(\u81F3)".freeze, "\u3244"=>"\u554F".freeze, "\u3245"=>"\u5E7C".freeze, "\u3246"=>"\u6587".freeze, "\u3247"=>"\u7B8F".freeze, "\u3250"=>"PTE".freeze, "\u3251"=>"21".freeze, "\u3252"=>"22".freeze, "\u3253"=>"23".freeze, "\u3254"=>"24".freeze, "\u3255"=>"25".freeze, "\u3256"=>"26".freeze, "\u3257"=>"27".freeze, "\u3258"=>"28".freeze, "\u3259"=>"29".freeze, "\u325A"=>"30".freeze, "\u325B"=>"31".freeze, "\u325C"=>"32".freeze, "\u325D"=>"33".freeze, "\u325E"=>"34".freeze, "\u325F"=>"35".freeze, "\u3260"=>"\u1100".freeze, "\u3261"=>"\u1102".freeze, "\u3262"=>"\u1103".freeze, "\u3263"=>"\u1105".freeze, "\u3264"=>"\u1106".freeze, "\u3265"=>"\u1107".freeze, "\u3266"=>"\u1109".freeze, "\u3267"=>"\u110B".freeze, "\u3268"=>"\u110C".freeze, "\u3269"=>"\u110E".freeze, "\u326A"=>"\u110F".freeze, "\u326B"=>"\u1110".freeze, "\u326C"=>"\u1111".freeze, "\u326D"=>"\u1112".freeze, "\u326E"=>"\u1100\u1161".freeze, "\u326F"=>"\u1102\u1161".freeze, "\u3270"=>"\u1103\u1161".freeze, "\u3271"=>"\u1105\u1161".freeze, "\u3272"=>"\u1106\u1161".freeze, "\u3273"=>"\u1107\u1161".freeze, "\u3274"=>"\u1109\u1161".freeze, "\u3275"=>"\u110B\u1161".freeze, "\u3276"=>"\u110C\u1161".freeze, "\u3277"=>"\u110E\u1161".freeze, "\u3278"=>"\u110F\u1161".freeze, "\u3279"=>"\u1110\u1161".freeze, "\u327A"=>"\u1111\u1161".freeze, "\u327B"=>"\u1112\u1161".freeze, "\u327C"=>"\u110E\u1161\u11B7\u1100\u1169".freeze, "\u327D"=>"\u110C\u116E\u110B\u1174".freeze, "\u327E"=>"\u110B\u116E".freeze, "\u3280"=>"\u4E00".freeze, "\u3281"=>"\u4E8C".freeze, "\u3282"=>"\u4E09".freeze, "\u3283"=>"\u56DB".freeze, "\u3284"=>"\u4E94".freeze, "\u3285"=>"\u516D".freeze, "\u3286"=>"\u4E03".freeze, "\u3287"=>"\u516B".freeze, "\u3288"=>"\u4E5D".freeze, "\u3289"=>"\u5341".freeze, "\u328A"=>"\u6708".freeze, "\u328B"=>"\u706B".freeze, "\u328C"=>"\u6C34".freeze, "\u328D"=>"\u6728".freeze, "\u328E"=>"\u91D1".freeze, "\u328F"=>"\u571F".freeze, "\u3290"=>"\u65E5".freeze, "\u3291"=>"\u682A".freeze, "\u3292"=>"\u6709".freeze, "\u3293"=>"\u793E".freeze, "\u3294"=>"\u540D".freeze, "\u3295"=>"\u7279".freeze, "\u3296"=>"\u8CA1".freeze, "\u3297"=>"\u795D".freeze, "\u3298"=>"\u52B4".freeze, "\u3299"=>"\u79D8".freeze, "\u329A"=>"\u7537".freeze, "\u329B"=>"\u5973".freeze, "\u329C"=>"\u9069".freeze, "\u329D"=>"\u512A".freeze, "\u329E"=>"\u5370".freeze, "\u329F"=>"\u6CE8".freeze, "\u32A0"=>"\u9805".freeze, "\u32A1"=>"\u4F11".freeze, "\u32A2"=>"\u5199".freeze, "\u32A3"=>"\u6B63".freeze, "\u32A4"=>"\u4E0A".freeze, "\u32A5"=>"\u4E2D".freeze, "\u32A6"=>"\u4E0B".freeze, "\u32A7"=>"\u5DE6".freeze, "\u32A8"=>"\u53F3".freeze, "\u32A9"=>"\u533B".freeze, "\u32AA"=>"\u5B97".freeze, "\u32AB"=>"\u5B66".freeze, "\u32AC"=>"\u76E3".freeze, "\u32AD"=>"\u4F01".freeze, "\u32AE"=>"\u8CC7".freeze, "\u32AF"=>"\u5354".freeze, "\u32B0"=>"\u591C".freeze, "\u32B1"=>"36".freeze, "\u32B2"=>"37".freeze, "\u32B3"=>"38".freeze, "\u32B4"=>"39".freeze, "\u32B5"=>"40".freeze, "\u32B6"=>"41".freeze, "\u32B7"=>"42".freeze, "\u32B8"=>"43".freeze, "\u32B9"=>"44".freeze, "\u32BA"=>"45".freeze, "\u32BB"=>"46".freeze, "\u32BC"=>"47".freeze, "\u32BD"=>"48".freeze, "\u32BE"=>"49".freeze, "\u32BF"=>"50".freeze, "\u32C0"=>"1\u6708".freeze, "\u32C1"=>"2\u6708".freeze, "\u32C2"=>"3\u6708".freeze, "\u32C3"=>"4\u6708".freeze, "\u32C4"=>"5\u6708".freeze, "\u32C5"=>"6\u6708".freeze, "\u32C6"=>"7\u6708".freeze, "\u32C7"=>"8\u6708".freeze, "\u32C8"=>"9\u6708".freeze, "\u32C9"=>"10\u6708".freeze, "\u32CA"=>"11\u6708".freeze, "\u32CB"=>"12\u6708".freeze, "\u32CC"=>"Hg".freeze, "\u32CD"=>"erg".freeze, "\u32CE"=>"eV".freeze, "\u32CF"=>"LTD".freeze, "\u32D0"=>"\u30A2".freeze, "\u32D1"=>"\u30A4".freeze, "\u32D2"=>"\u30A6".freeze, "\u32D3"=>"\u30A8".freeze, "\u32D4"=>"\u30AA".freeze, "\u32D5"=>"\u30AB".freeze, "\u32D6"=>"\u30AD".freeze, "\u32D7"=>"\u30AF".freeze, "\u32D8"=>"\u30B1".freeze, "\u32D9"=>"\u30B3".freeze, "\u32DA"=>"\u30B5".freeze, "\u32DB"=>"\u30B7".freeze, "\u32DC"=>"\u30B9".freeze, "\u32DD"=>"\u30BB".freeze, "\u32DE"=>"\u30BD".freeze, "\u32DF"=>"\u30BF".freeze, "\u32E0"=>"\u30C1".freeze, "\u32E1"=>"\u30C4".freeze, "\u32E2"=>"\u30C6".freeze, "\u32E3"=>"\u30C8".freeze, "\u32E4"=>"\u30CA".freeze, "\u32E5"=>"\u30CB".freeze, "\u32E6"=>"\u30CC".freeze, "\u32E7"=>"\u30CD".freeze, "\u32E8"=>"\u30CE".freeze, "\u32E9"=>"\u30CF".freeze, "\u32EA"=>"\u30D2".freeze, "\u32EB"=>"\u30D5".freeze, "\u32EC"=>"\u30D8".freeze, "\u32ED"=>"\u30DB".freeze, "\u32EE"=>"\u30DE".freeze, "\u32EF"=>"\u30DF".freeze, "\u32F0"=>"\u30E0".freeze, "\u32F1"=>"\u30E1".freeze, "\u32F2"=>"\u30E2".freeze, "\u32F3"=>"\u30E4".freeze, "\u32F4"=>"\u30E6".freeze, "\u32F5"=>"\u30E8".freeze, "\u32F6"=>"\u30E9".freeze, "\u32F7"=>"\u30EA".freeze, "\u32F8"=>"\u30EB".freeze, "\u32F9"=>"\u30EC".freeze, "\u32FA"=>"\u30ED".freeze, "\u32FB"=>"\u30EF".freeze, "\u32FC"=>"\u30F0".freeze, "\u32FD"=>"\u30F1".freeze, "\u32FE"=>"\u30F2".freeze, "\u3300"=>"\u30A2\u30D1\u30FC\u30C8".freeze, "\u3301"=>"\u30A2\u30EB\u30D5\u30A1".freeze, "\u3302"=>"\u30A2\u30F3\u30DA\u30A2".freeze, "\u3303"=>"\u30A2\u30FC\u30EB".freeze, "\u3304"=>"\u30A4\u30CB\u30F3\u30B0".freeze, "\u3305"=>"\u30A4\u30F3\u30C1".freeze, "\u3306"=>"\u30A6\u30A9\u30F3".freeze, "\u3307"=>"\u30A8\u30B9\u30AF\u30FC\u30C9".freeze, "\u3308"=>"\u30A8\u30FC\u30AB\u30FC".freeze, "\u3309"=>"\u30AA\u30F3\u30B9".freeze, "\u330A"=>"\u30AA\u30FC\u30E0".freeze, "\u330B"=>"\u30AB\u30A4\u30EA".freeze, "\u330C"=>"\u30AB\u30E9\u30C3\u30C8".freeze, "\u330D"=>"\u30AB\u30ED\u30EA\u30FC".freeze, "\u330E"=>"\u30AC\u30ED\u30F3".freeze, "\u330F"=>"\u30AC\u30F3\u30DE".freeze, "\u3310"=>"\u30AE\u30AC".freeze, "\u3311"=>"\u30AE\u30CB\u30FC".freeze, "\u3312"=>"\u30AD\u30E5\u30EA\u30FC".freeze, "\u3313"=>"\u30AE\u30EB\u30C0\u30FC".freeze, "\u3314"=>"\u30AD\u30ED".freeze, "\u3315"=>"\u30AD\u30ED\u30B0\u30E9\u30E0".freeze, "\u3316"=>"\u30AD\u30ED\u30E1\u30FC\u30C8\u30EB".freeze, "\u3317"=>"\u30AD\u30ED\u30EF\u30C3\u30C8".freeze, "\u3318"=>"\u30B0\u30E9\u30E0".freeze, "\u3319"=>"\u30B0\u30E9\u30E0\u30C8\u30F3".freeze, "\u331A"=>"\u30AF\u30EB\u30BC\u30A4\u30ED".freeze, "\u331B"=>"\u30AF\u30ED\u30FC\u30CD".freeze, "\u331C"=>"\u30B1\u30FC\u30B9".freeze, "\u331D"=>"\u30B3\u30EB\u30CA".freeze, "\u331E"=>"\u30B3\u30FC\u30DD".freeze, "\u331F"=>"\u30B5\u30A4\u30AF\u30EB".freeze, "\u3320"=>"\u30B5\u30F3\u30C1\u30FC\u30E0".freeze, "\u3321"=>"\u30B7\u30EA\u30F3\u30B0".freeze, "\u3322"=>"\u30BB\u30F3\u30C1".freeze, "\u3323"=>"\u30BB\u30F3\u30C8".freeze, "\u3324"=>"\u30C0\u30FC\u30B9".freeze, "\u3325"=>"\u30C7\u30B7".freeze, "\u3326"=>"\u30C9\u30EB".freeze, "\u3327"=>"\u30C8\u30F3".freeze, "\u3328"=>"\u30CA\u30CE".freeze, "\u3329"=>"\u30CE\u30C3\u30C8".freeze, "\u332A"=>"\u30CF\u30A4\u30C4".freeze, "\u332B"=>"\u30D1\u30FC\u30BB\u30F3\u30C8".freeze, "\u332C"=>"\u30D1\u30FC\u30C4".freeze, "\u332D"=>"\u30D0\u30FC\u30EC\u30EB".freeze, "\u332E"=>"\u30D4\u30A2\u30B9\u30C8\u30EB".freeze, "\u332F"=>"\u30D4\u30AF\u30EB".freeze, "\u3330"=>"\u30D4\u30B3".freeze, "\u3331"=>"\u30D3\u30EB".freeze, "\u3332"=>"\u30D5\u30A1\u30E9\u30C3\u30C9".freeze, "\u3333"=>"\u30D5\u30A3\u30FC\u30C8".freeze, "\u3334"=>"\u30D6\u30C3\u30B7\u30A7\u30EB".freeze, "\u3335"=>"\u30D5\u30E9\u30F3".freeze, "\u3336"=>"\u30D8\u30AF\u30BF\u30FC\u30EB".freeze, "\u3337"=>"\u30DA\u30BD".freeze, "\u3338"=>"\u30DA\u30CB\u30D2".freeze, "\u3339"=>"\u30D8\u30EB\u30C4".freeze, "\u333A"=>"\u30DA\u30F3\u30B9".freeze, "\u333B"=>"\u30DA\u30FC\u30B8".freeze, "\u333C"=>"\u30D9\u30FC\u30BF".freeze, "\u333D"=>"\u30DD\u30A4\u30F3\u30C8".freeze, "\u333E"=>"\u30DC\u30EB\u30C8".freeze, "\u333F"=>"\u30DB\u30F3".freeze, "\u3340"=>"\u30DD\u30F3\u30C9".freeze, "\u3341"=>"\u30DB\u30FC\u30EB".freeze, "\u3342"=>"\u30DB\u30FC\u30F3".freeze, "\u3343"=>"\u30DE\u30A4\u30AF\u30ED".freeze, "\u3344"=>"\u30DE\u30A4\u30EB".freeze, "\u3345"=>"\u30DE\u30C3\u30CF".freeze, "\u3346"=>"\u30DE\u30EB\u30AF".freeze, "\u3347"=>"\u30DE\u30F3\u30B7\u30E7\u30F3".freeze, "\u3348"=>"\u30DF\u30AF\u30ED\u30F3".freeze, "\u3349"=>"\u30DF\u30EA".freeze, "\u334A"=>"\u30DF\u30EA\u30D0\u30FC\u30EB".freeze, "\u334B"=>"\u30E1\u30AC".freeze, "\u334C"=>"\u30E1\u30AC\u30C8\u30F3".freeze, "\u334D"=>"\u30E1\u30FC\u30C8\u30EB".freeze, "\u334E"=>"\u30E4\u30FC\u30C9".freeze, "\u334F"=>"\u30E4\u30FC\u30EB".freeze, "\u3350"=>"\u30E6\u30A2\u30F3".freeze, "\u3351"=>"\u30EA\u30C3\u30C8\u30EB".freeze, "\u3352"=>"\u30EA\u30E9".freeze, "\u3353"=>"\u30EB\u30D4\u30FC".freeze, "\u3354"=>"\u30EB\u30FC\u30D6\u30EB".freeze, "\u3355"=>"\u30EC\u30E0".freeze, "\u3356"=>"\u30EC\u30F3\u30C8\u30B2\u30F3".freeze, "\u3357"=>"\u30EF\u30C3\u30C8".freeze, "\u3358"=>"0\u70B9".freeze, "\u3359"=>"1\u70B9".freeze, "\u335A"=>"2\u70B9".freeze, "\u335B"=>"3\u70B9".freeze, "\u335C"=>"4\u70B9".freeze, "\u335D"=>"5\u70B9".freeze, "\u335E"=>"6\u70B9".freeze, "\u335F"=>"7\u70B9".freeze, "\u3360"=>"8\u70B9".freeze, "\u3361"=>"9\u70B9".freeze, "\u3362"=>"10\u70B9".freeze, "\u3363"=>"11\u70B9".freeze, "\u3364"=>"12\u70B9".freeze, "\u3365"=>"13\u70B9".freeze, "\u3366"=>"14\u70B9".freeze, "\u3367"=>"15\u70B9".freeze, "\u3368"=>"16\u70B9".freeze, "\u3369"=>"17\u70B9".freeze, "\u336A"=>"18\u70B9".freeze, "\u336B"=>"19\u70B9".freeze, "\u336C"=>"20\u70B9".freeze, "\u336D"=>"21\u70B9".freeze, "\u336E"=>"22\u70B9".freeze, "\u336F"=>"23\u70B9".freeze, "\u3370"=>"24\u70B9".freeze, "\u3371"=>"hPa".freeze, "\u3372"=>"da".freeze, "\u3373"=>"AU".freeze, "\u3374"=>"bar".freeze, "\u3375"=>"oV".freeze, "\u3376"=>"pc".freeze, "\u3377"=>"dm".freeze, "\u3378"=>"dm2".freeze, "\u3379"=>"dm3".freeze, "\u337A"=>"IU".freeze, "\u337B"=>"\u5E73\u6210".freeze, "\u337C"=>"\u662D\u548C".freeze, "\u337D"=>"\u5927\u6B63".freeze, "\u337E"=>"\u660E\u6CBB".freeze, "\u337F"=>"\u682A\u5F0F\u4F1A\u793E".freeze, "\u3380"=>"pA".freeze, "\u3381"=>"nA".freeze, "\u3382"=>"\u03BCA".freeze, "\u3383"=>"mA".freeze, "\u3384"=>"kA".freeze, "\u3385"=>"KB".freeze, "\u3386"=>"MB".freeze, "\u3387"=>"GB".freeze, "\u3388"=>"cal".freeze, "\u3389"=>"kcal".freeze, "\u338A"=>"pF".freeze, "\u338B"=>"nF".freeze, "\u338C"=>"\u03BCF".freeze, "\u338D"=>"\u03BCg".freeze, "\u338E"=>"mg".freeze, "\u338F"=>"kg".freeze, "\u3390"=>"Hz".freeze, "\u3391"=>"kHz".freeze, "\u3392"=>"MHz".freeze, "\u3393"=>"GHz".freeze, "\u3394"=>"THz".freeze, "\u3395"=>"\u03BCl".freeze, "\u3396"=>"ml".freeze, "\u3397"=>"dl".freeze, "\u3398"=>"kl".freeze, "\u3399"=>"fm".freeze, "\u339A"=>"nm".freeze, "\u339B"=>"\u03BCm".freeze, "\u339C"=>"mm".freeze, "\u339D"=>"cm".freeze, "\u339E"=>"km".freeze, "\u339F"=>"mm2".freeze, "\u33A0"=>"cm2".freeze, "\u33A1"=>"m2".freeze, "\u33A2"=>"km2".freeze, "\u33A3"=>"mm3".freeze, "\u33A4"=>"cm3".freeze, "\u33A5"=>"m3".freeze, "\u33A6"=>"km3".freeze, "\u33A7"=>"m\u2215s".freeze, "\u33A8"=>"m\u2215s2".freeze, "\u33A9"=>"Pa".freeze, "\u33AA"=>"kPa".freeze, "\u33AB"=>"MPa".freeze, "\u33AC"=>"GPa".freeze, "\u33AD"=>"rad".freeze, "\u33AE"=>"rad\u2215s".freeze, "\u33AF"=>"rad\u2215s2".freeze, "\u33B0"=>"ps".freeze, "\u33B1"=>"ns".freeze, "\u33B2"=>"\u03BCs".freeze, "\u33B3"=>"ms".freeze, "\u33B4"=>"pV".freeze, "\u33B5"=>"nV".freeze, "\u33B6"=>"\u03BCV".freeze, "\u33B7"=>"mV".freeze, "\u33B8"=>"kV".freeze, "\u33B9"=>"MV".freeze, "\u33BA"=>"pW".freeze, "\u33BB"=>"nW".freeze, "\u33BC"=>"\u03BCW".freeze, "\u33BD"=>"mW".freeze, "\u33BE"=>"kW".freeze, "\u33BF"=>"MW".freeze, "\u33C0"=>"k\u03A9".freeze, "\u33C1"=>"M\u03A9".freeze, "\u33C2"=>"a.m.".freeze, "\u33C3"=>"Bq".freeze, "\u33C4"=>"cc".freeze, "\u33C5"=>"cd".freeze, "\u33C6"=>"C\u2215kg".freeze, "\u33C7"=>"Co.".freeze, "\u33C8"=>"dB".freeze, "\u33C9"=>"Gy".freeze, "\u33CA"=>"ha".freeze, "\u33CB"=>"HP".freeze, "\u33CC"=>"in".freeze, "\u33CD"=>"KK".freeze, "\u33CE"=>"KM".freeze, "\u33CF"=>"kt".freeze, "\u33D0"=>"lm".freeze, "\u33D1"=>"ln".freeze, "\u33D2"=>"log".freeze, "\u33D3"=>"lx".freeze, "\u33D4"=>"mb".freeze, "\u33D5"=>"mil".freeze, "\u33D6"=>"mol".freeze, "\u33D7"=>"PH".freeze, "\u33D8"=>"p.m.".freeze, "\u33D9"=>"PPM".freeze, "\u33DA"=>"PR".freeze, "\u33DB"=>"sr".freeze, "\u33DC"=>"Sv".freeze, "\u33DD"=>"Wb".freeze, "\u33DE"=>"V\u2215m".freeze, "\u33DF"=>"A\u2215m".freeze, "\u33E0"=>"1\u65E5".freeze, "\u33E1"=>"2\u65E5".freeze, "\u33E2"=>"3\u65E5".freeze, "\u33E3"=>"4\u65E5".freeze, "\u33E4"=>"5\u65E5".freeze, "\u33E5"=>"6\u65E5".freeze, "\u33E6"=>"7\u65E5".freeze, "\u33E7"=>"8\u65E5".freeze, "\u33E8"=>"9\u65E5".freeze, "\u33E9"=>"10\u65E5".freeze, "\u33EA"=>"11\u65E5".freeze, "\u33EB"=>"12\u65E5".freeze, "\u33EC"=>"13\u65E5".freeze, "\u33ED"=>"14\u65E5".freeze, "\u33EE"=>"15\u65E5".freeze, "\u33EF"=>"16\u65E5".freeze, "\u33F0"=>"17\u65E5".freeze, "\u33F1"=>"18\u65E5".freeze, "\u33F2"=>"19\u65E5".freeze, "\u33F3"=>"20\u65E5".freeze, "\u33F4"=>"21\u65E5".freeze, "\u33F5"=>"22\u65E5".freeze, "\u33F6"=>"23\u65E5".freeze, "\u33F7"=>"24\u65E5".freeze, "\u33F8"=>"25\u65E5".freeze, "\u33F9"=>"26\u65E5".freeze, "\u33FA"=>"27\u65E5".freeze, "\u33FB"=>"28\u65E5".freeze, "\u33FC"=>"29\u65E5".freeze, "\u33FD"=>"30\u65E5".freeze, "\u33FE"=>"31\u65E5".freeze, "\u33FF"=>"gal".freeze, "\uA69C"=>"\u044A".freeze, "\uA69D"=>"\u044C".freeze, "\uA770"=>"\uA76F".freeze, "\uA7F8"=>"\u0126".freeze, "\uA7F9"=>"\u0153".freeze, "\uAB5C"=>"\uA727".freeze, "\uAB5D"=>"\uAB37".freeze, "\uAB5E"=>"\u026B".freeze, "\uAB5F"=>"\uAB52".freeze, "\uFB00"=>"ff".freeze, "\uFB01"=>"fi".freeze, "\uFB02"=>"fl".freeze, "\uFB03"=>"ffi".freeze, "\uFB04"=>"ffl".freeze, "\uFB05"=>"st".freeze, "\uFB06"=>"st".freeze, "\uFB13"=>"\u0574\u0576".freeze, "\uFB14"=>"\u0574\u0565".freeze, "\uFB15"=>"\u0574\u056B".freeze, "\uFB16"=>"\u057E\u0576".freeze, "\uFB17"=>"\u0574\u056D".freeze, "\uFB20"=>"\u05E2".freeze, "\uFB21"=>"\u05D0".freeze, "\uFB22"=>"\u05D3".freeze, "\uFB23"=>"\u05D4".freeze, "\uFB24"=>"\u05DB".freeze, "\uFB25"=>"\u05DC".freeze, "\uFB26"=>"\u05DD".freeze, "\uFB27"=>"\u05E8".freeze, "\uFB28"=>"\u05EA".freeze, "\uFB29"=>"+".freeze, "\uFB4F"=>"\u05D0\u05DC".freeze, "\uFB50"=>"\u0671".freeze, "\uFB51"=>"\u0671".freeze, "\uFB52"=>"\u067B".freeze, "\uFB53"=>"\u067B".freeze, "\uFB54"=>"\u067B".freeze, "\uFB55"=>"\u067B".freeze, "\uFB56"=>"\u067E".freeze, "\uFB57"=>"\u067E".freeze, "\uFB58"=>"\u067E".freeze, "\uFB59"=>"\u067E".freeze, "\uFB5A"=>"\u0680".freeze, "\uFB5B"=>"\u0680".freeze, "\uFB5C"=>"\u0680".freeze, "\uFB5D"=>"\u0680".freeze, "\uFB5E"=>"\u067A".freeze, "\uFB5F"=>"\u067A".freeze, "\uFB60"=>"\u067A".freeze, "\uFB61"=>"\u067A".freeze, "\uFB62"=>"\u067F".freeze, "\uFB63"=>"\u067F".freeze, "\uFB64"=>"\u067F".freeze, "\uFB65"=>"\u067F".freeze, "\uFB66"=>"\u0679".freeze, "\uFB67"=>"\u0679".freeze, "\uFB68"=>"\u0679".freeze, "\uFB69"=>"\u0679".freeze, "\uFB6A"=>"\u06A4".freeze, "\uFB6B"=>"\u06A4".freeze, "\uFB6C"=>"\u06A4".freeze, "\uFB6D"=>"\u06A4".freeze, "\uFB6E"=>"\u06A6".freeze, "\uFB6F"=>"\u06A6".freeze, "\uFB70"=>"\u06A6".freeze, "\uFB71"=>"\u06A6".freeze, "\uFB72"=>"\u0684".freeze, "\uFB73"=>"\u0684".freeze, "\uFB74"=>"\u0684".freeze, "\uFB75"=>"\u0684".freeze, "\uFB76"=>"\u0683".freeze, "\uFB77"=>"\u0683".freeze, "\uFB78"=>"\u0683".freeze, "\uFB79"=>"\u0683".freeze, "\uFB7A"=>"\u0686".freeze, "\uFB7B"=>"\u0686".freeze, "\uFB7C"=>"\u0686".freeze, "\uFB7D"=>"\u0686".freeze, "\uFB7E"=>"\u0687".freeze, "\uFB7F"=>"\u0687".freeze, "\uFB80"=>"\u0687".freeze, "\uFB81"=>"\u0687".freeze, "\uFB82"=>"\u068D".freeze, "\uFB83"=>"\u068D".freeze, "\uFB84"=>"\u068C".freeze, "\uFB85"=>"\u068C".freeze, "\uFB86"=>"\u068E".freeze, "\uFB87"=>"\u068E".freeze, "\uFB88"=>"\u0688".freeze, "\uFB89"=>"\u0688".freeze, "\uFB8A"=>"\u0698".freeze, "\uFB8B"=>"\u0698".freeze, "\uFB8C"=>"\u0691".freeze, "\uFB8D"=>"\u0691".freeze, "\uFB8E"=>"\u06A9".freeze, "\uFB8F"=>"\u06A9".freeze, "\uFB90"=>"\u06A9".freeze, "\uFB91"=>"\u06A9".freeze, "\uFB92"=>"\u06AF".freeze, "\uFB93"=>"\u06AF".freeze, "\uFB94"=>"\u06AF".freeze, "\uFB95"=>"\u06AF".freeze, "\uFB96"=>"\u06B3".freeze, "\uFB97"=>"\u06B3".freeze, "\uFB98"=>"\u06B3".freeze, "\uFB99"=>"\u06B3".freeze, "\uFB9A"=>"\u06B1".freeze, "\uFB9B"=>"\u06B1".freeze, "\uFB9C"=>"\u06B1".freeze, "\uFB9D"=>"\u06B1".freeze, "\uFB9E"=>"\u06BA".freeze, "\uFB9F"=>"\u06BA".freeze, "\uFBA0"=>"\u06BB".freeze, "\uFBA1"=>"\u06BB".freeze, "\uFBA2"=>"\u06BB".freeze, "\uFBA3"=>"\u06BB".freeze, "\uFBA4"=>"\u06C0".freeze, "\uFBA5"=>"\u06C0".freeze, "\uFBA6"=>"\u06C1".freeze, "\uFBA7"=>"\u06C1".freeze, "\uFBA8"=>"\u06C1".freeze, "\uFBA9"=>"\u06C1".freeze, "\uFBAA"=>"\u06BE".freeze, "\uFBAB"=>"\u06BE".freeze, "\uFBAC"=>"\u06BE".freeze, "\uFBAD"=>"\u06BE".freeze, "\uFBAE"=>"\u06D2".freeze, "\uFBAF"=>"\u06D2".freeze, "\uFBB0"=>"\u06D3".freeze, "\uFBB1"=>"\u06D3".freeze, "\uFBD3"=>"\u06AD".freeze, "\uFBD4"=>"\u06AD".freeze, "\uFBD5"=>"\u06AD".freeze, "\uFBD6"=>"\u06AD".freeze, "\uFBD7"=>"\u06C7".freeze, "\uFBD8"=>"\u06C7".freeze, "\uFBD9"=>"\u06C6".freeze, "\uFBDA"=>"\u06C6".freeze, "\uFBDB"=>"\u06C8".freeze, "\uFBDC"=>"\u06C8".freeze, "\uFBDD"=>"\u06C7\u0674".freeze, "\uFBDE"=>"\u06CB".freeze, "\uFBDF"=>"\u06CB".freeze, "\uFBE0"=>"\u06C5".freeze, "\uFBE1"=>"\u06C5".freeze, "\uFBE2"=>"\u06C9".freeze, "\uFBE3"=>"\u06C9".freeze, "\uFBE4"=>"\u06D0".freeze, "\uFBE5"=>"\u06D0".freeze, "\uFBE6"=>"\u06D0".freeze, "\uFBE7"=>"\u06D0".freeze, "\uFBE8"=>"\u0649".freeze, "\uFBE9"=>"\u0649".freeze, "\uFBEA"=>"\u0626\u0627".freeze, "\uFBEB"=>"\u0626\u0627".freeze, "\uFBEC"=>"\u0626\u06D5".freeze, "\uFBED"=>"\u0626\u06D5".freeze, "\uFBEE"=>"\u0626\u0648".freeze, "\uFBEF"=>"\u0626\u0648".freeze, "\uFBF0"=>"\u0626\u06C7".freeze, "\uFBF1"=>"\u0626\u06C7".freeze, "\uFBF2"=>"\u0626\u06C6".freeze, "\uFBF3"=>"\u0626\u06C6".freeze, "\uFBF4"=>"\u0626\u06C8".freeze, "\uFBF5"=>"\u0626\u06C8".freeze, "\uFBF6"=>"\u0626\u06D0".freeze, "\uFBF7"=>"\u0626\u06D0".freeze, "\uFBF8"=>"\u0626\u06D0".freeze, "\uFBF9"=>"\u0626\u0649".freeze, "\uFBFA"=>"\u0626\u0649".freeze, "\uFBFB"=>"\u0626\u0649".freeze, "\uFBFC"=>"\u06CC".freeze, "\uFBFD"=>"\u06CC".freeze, "\uFBFE"=>"\u06CC".freeze, "\uFBFF"=>"\u06CC".freeze, "\uFC00"=>"\u0626\u062C".freeze, "\uFC01"=>"\u0626\u062D".freeze, "\uFC02"=>"\u0626\u0645".freeze, "\uFC03"=>"\u0626\u0649".freeze, "\uFC04"=>"\u0626\u064A".freeze, "\uFC05"=>"\u0628\u062C".freeze, "\uFC06"=>"\u0628\u062D".freeze, "\uFC07"=>"\u0628\u062E".freeze, "\uFC08"=>"\u0628\u0645".freeze, "\uFC09"=>"\u0628\u0649".freeze, "\uFC0A"=>"\u0628\u064A".freeze, "\uFC0B"=>"\u062A\u062C".freeze, "\uFC0C"=>"\u062A\u062D".freeze, "\uFC0D"=>"\u062A\u062E".freeze, "\uFC0E"=>"\u062A\u0645".freeze, "\uFC0F"=>"\u062A\u0649".freeze, "\uFC10"=>"\u062A\u064A".freeze, "\uFC11"=>"\u062B\u062C".freeze, "\uFC12"=>"\u062B\u0645".freeze, "\uFC13"=>"\u062B\u0649".freeze, "\uFC14"=>"\u062B\u064A".freeze, "\uFC15"=>"\u062C\u062D".freeze, "\uFC16"=>"\u062C\u0645".freeze, "\uFC17"=>"\u062D\u062C".freeze, "\uFC18"=>"\u062D\u0645".freeze, "\uFC19"=>"\u062E\u062C".freeze, "\uFC1A"=>"\u062E\u062D".freeze, "\uFC1B"=>"\u062E\u0645".freeze, "\uFC1C"=>"\u0633\u062C".freeze, "\uFC1D"=>"\u0633\u062D".freeze, "\uFC1E"=>"\u0633\u062E".freeze, "\uFC1F"=>"\u0633\u0645".freeze, "\uFC20"=>"\u0635\u062D".freeze, "\uFC21"=>"\u0635\u0645".freeze, "\uFC22"=>"\u0636\u062C".freeze, "\uFC23"=>"\u0636\u062D".freeze, "\uFC24"=>"\u0636\u062E".freeze, "\uFC25"=>"\u0636\u0645".freeze, "\uFC26"=>"\u0637\u062D".freeze, "\uFC27"=>"\u0637\u0645".freeze, "\uFC28"=>"\u0638\u0645".freeze, "\uFC29"=>"\u0639\u062C".freeze, "\uFC2A"=>"\u0639\u0645".freeze, "\uFC2B"=>"\u063A\u062C".freeze, "\uFC2C"=>"\u063A\u0645".freeze, "\uFC2D"=>"\u0641\u062C".freeze, "\uFC2E"=>"\u0641\u062D".freeze, "\uFC2F"=>"\u0641\u062E".freeze, "\uFC30"=>"\u0641\u0645".freeze, "\uFC31"=>"\u0641\u0649".freeze, "\uFC32"=>"\u0641\u064A".freeze, "\uFC33"=>"\u0642\u062D".freeze, "\uFC34"=>"\u0642\u0645".freeze, "\uFC35"=>"\u0642\u0649".freeze, "\uFC36"=>"\u0642\u064A".freeze, "\uFC37"=>"\u0643\u0627".freeze, "\uFC38"=>"\u0643\u062C".freeze, "\uFC39"=>"\u0643\u062D".freeze, "\uFC3A"=>"\u0643\u062E".freeze, "\uFC3B"=>"\u0643\u0644".freeze, "\uFC3C"=>"\u0643\u0645".freeze, "\uFC3D"=>"\u0643\u0649".freeze, "\uFC3E"=>"\u0643\u064A".freeze, "\uFC3F"=>"\u0644\u062C".freeze, "\uFC40"=>"\u0644\u062D".freeze, "\uFC41"=>"\u0644\u062E".freeze, "\uFC42"=>"\u0644\u0645".freeze, "\uFC43"=>"\u0644\u0649".freeze, "\uFC44"=>"\u0644\u064A".freeze, "\uFC45"=>"\u0645\u062C".freeze, "\uFC46"=>"\u0645\u062D".freeze, "\uFC47"=>"\u0645\u062E".freeze, "\uFC48"=>"\u0645\u0645".freeze, "\uFC49"=>"\u0645\u0649".freeze, "\uFC4A"=>"\u0645\u064A".freeze, "\uFC4B"=>"\u0646\u062C".freeze, "\uFC4C"=>"\u0646\u062D".freeze, "\uFC4D"=>"\u0646\u062E".freeze, "\uFC4E"=>"\u0646\u0645".freeze, "\uFC4F"=>"\u0646\u0649".freeze, "\uFC50"=>"\u0646\u064A".freeze, "\uFC51"=>"\u0647\u062C".freeze, "\uFC52"=>"\u0647\u0645".freeze, "\uFC53"=>"\u0647\u0649".freeze, "\uFC54"=>"\u0647\u064A".freeze, "\uFC55"=>"\u064A\u062C".freeze, "\uFC56"=>"\u064A\u062D".freeze, "\uFC57"=>"\u064A\u062E".freeze, "\uFC58"=>"\u064A\u0645".freeze, "\uFC59"=>"\u064A\u0649".freeze, "\uFC5A"=>"\u064A\u064A".freeze, "\uFC5B"=>"\u0630\u0670".freeze, "\uFC5C"=>"\u0631\u0670".freeze, "\uFC5D"=>"\u0649\u0670".freeze, "\uFC5E"=>" \u064C\u0651".freeze, "\uFC5F"=>" \u064D\u0651".freeze, "\uFC60"=>" \u064E\u0651".freeze, "\uFC61"=>" \u064F\u0651".freeze, "\uFC62"=>" \u0650\u0651".freeze, "\uFC63"=>" \u0651\u0670".freeze, "\uFC64"=>"\u0626\u0631".freeze, "\uFC65"=>"\u0626\u0632".freeze, "\uFC66"=>"\u0626\u0645".freeze, "\uFC67"=>"\u0626\u0646".freeze, "\uFC68"=>"\u0626\u0649".freeze, "\uFC69"=>"\u0626\u064A".freeze, "\uFC6A"=>"\u0628\u0631".freeze, "\uFC6B"=>"\u0628\u0632".freeze, "\uFC6C"=>"\u0628\u0645".freeze, "\uFC6D"=>"\u0628\u0646".freeze, "\uFC6E"=>"\u0628\u0649".freeze, "\uFC6F"=>"\u0628\u064A".freeze, "\uFC70"=>"\u062A\u0631".freeze, "\uFC71"=>"\u062A\u0632".freeze, "\uFC72"=>"\u062A\u0645".freeze, "\uFC73"=>"\u062A\u0646".freeze, "\uFC74"=>"\u062A\u0649".freeze, "\uFC75"=>"\u062A\u064A".freeze, "\uFC76"=>"\u062B\u0631".freeze, "\uFC77"=>"\u062B\u0632".freeze, "\uFC78"=>"\u062B\u0645".freeze, "\uFC79"=>"\u062B\u0646".freeze, "\uFC7A"=>"\u062B\u0649".freeze, "\uFC7B"=>"\u062B\u064A".freeze, "\uFC7C"=>"\u0641\u0649".freeze, "\uFC7D"=>"\u0641\u064A".freeze, "\uFC7E"=>"\u0642\u0649".freeze, "\uFC7F"=>"\u0642\u064A".freeze, "\uFC80"=>"\u0643\u0627".freeze, "\uFC81"=>"\u0643\u0644".freeze, "\uFC82"=>"\u0643\u0645".freeze, "\uFC83"=>"\u0643\u0649".freeze, "\uFC84"=>"\u0643\u064A".freeze, "\uFC85"=>"\u0644\u0645".freeze, "\uFC86"=>"\u0644\u0649".freeze, "\uFC87"=>"\u0644\u064A".freeze, "\uFC88"=>"\u0645\u0627".freeze, "\uFC89"=>"\u0645\u0645".freeze, "\uFC8A"=>"\u0646\u0631".freeze, "\uFC8B"=>"\u0646\u0632".freeze, "\uFC8C"=>"\u0646\u0645".freeze, "\uFC8D"=>"\u0646\u0646".freeze, "\uFC8E"=>"\u0646\u0649".freeze, "\uFC8F"=>"\u0646\u064A".freeze, "\uFC90"=>"\u0649\u0670".freeze, "\uFC91"=>"\u064A\u0631".freeze, "\uFC92"=>"\u064A\u0632".freeze, "\uFC93"=>"\u064A\u0645".freeze, "\uFC94"=>"\u064A\u0646".freeze, "\uFC95"=>"\u064A\u0649".freeze, "\uFC96"=>"\u064A\u064A".freeze, "\uFC97"=>"\u0626\u062C".freeze, "\uFC98"=>"\u0626\u062D".freeze, "\uFC99"=>"\u0626\u062E".freeze, "\uFC9A"=>"\u0626\u0645".freeze, "\uFC9B"=>"\u0626\u0647".freeze, "\uFC9C"=>"\u0628\u062C".freeze, "\uFC9D"=>"\u0628\u062D".freeze, "\uFC9E"=>"\u0628\u062E".freeze, "\uFC9F"=>"\u0628\u0645".freeze, "\uFCA0"=>"\u0628\u0647".freeze, "\uFCA1"=>"\u062A\u062C".freeze, "\uFCA2"=>"\u062A\u062D".freeze, "\uFCA3"=>"\u062A\u062E".freeze, "\uFCA4"=>"\u062A\u0645".freeze, "\uFCA5"=>"\u062A\u0647".freeze, "\uFCA6"=>"\u062B\u0645".freeze, "\uFCA7"=>"\u062C\u062D".freeze, "\uFCA8"=>"\u062C\u0645".freeze, "\uFCA9"=>"\u062D\u062C".freeze, "\uFCAA"=>"\u062D\u0645".freeze, "\uFCAB"=>"\u062E\u062C".freeze, "\uFCAC"=>"\u062E\u0645".freeze, "\uFCAD"=>"\u0633\u062C".freeze, "\uFCAE"=>"\u0633\u062D".freeze, "\uFCAF"=>"\u0633\u062E".freeze, "\uFCB0"=>"\u0633\u0645".freeze, "\uFCB1"=>"\u0635\u062D".freeze, "\uFCB2"=>"\u0635\u062E".freeze, "\uFCB3"=>"\u0635\u0645".freeze, "\uFCB4"=>"\u0636\u062C".freeze, "\uFCB5"=>"\u0636\u062D".freeze, "\uFCB6"=>"\u0636\u062E".freeze, "\uFCB7"=>"\u0636\u0645".freeze, "\uFCB8"=>"\u0637\u062D".freeze, "\uFCB9"=>"\u0638\u0645".freeze, "\uFCBA"=>"\u0639\u062C".freeze, "\uFCBB"=>"\u0639\u0645".freeze, "\uFCBC"=>"\u063A\u062C".freeze, "\uFCBD"=>"\u063A\u0645".freeze, "\uFCBE"=>"\u0641\u062C".freeze, "\uFCBF"=>"\u0641\u062D".freeze, "\uFCC0"=>"\u0641\u062E".freeze, "\uFCC1"=>"\u0641\u0645".freeze, "\uFCC2"=>"\u0642\u062D".freeze, "\uFCC3"=>"\u0642\u0645".freeze, "\uFCC4"=>"\u0643\u062C".freeze, "\uFCC5"=>"\u0643\u062D".freeze, "\uFCC6"=>"\u0643\u062E".freeze, "\uFCC7"=>"\u0643\u0644".freeze, "\uFCC8"=>"\u0643\u0645".freeze, "\uFCC9"=>"\u0644\u062C".freeze, "\uFCCA"=>"\u0644\u062D".freeze, "\uFCCB"=>"\u0644\u062E".freeze, "\uFCCC"=>"\u0644\u0645".freeze, "\uFCCD"=>"\u0644\u0647".freeze, "\uFCCE"=>"\u0645\u062C".freeze, "\uFCCF"=>"\u0645\u062D".freeze, "\uFCD0"=>"\u0645\u062E".freeze, "\uFCD1"=>"\u0645\u0645".freeze, "\uFCD2"=>"\u0646\u062C".freeze, "\uFCD3"=>"\u0646\u062D".freeze, "\uFCD4"=>"\u0646\u062E".freeze, "\uFCD5"=>"\u0646\u0645".freeze, "\uFCD6"=>"\u0646\u0647".freeze, "\uFCD7"=>"\u0647\u062C".freeze, "\uFCD8"=>"\u0647\u0645".freeze, "\uFCD9"=>"\u0647\u0670".freeze, "\uFCDA"=>"\u064A\u062C".freeze, "\uFCDB"=>"\u064A\u062D".freeze, "\uFCDC"=>"\u064A\u062E".freeze, "\uFCDD"=>"\u064A\u0645".freeze, "\uFCDE"=>"\u064A\u0647".freeze, "\uFCDF"=>"\u0626\u0645".freeze, "\uFCE0"=>"\u0626\u0647".freeze, "\uFCE1"=>"\u0628\u0645".freeze, "\uFCE2"=>"\u0628\u0647".freeze, "\uFCE3"=>"\u062A\u0645".freeze, "\uFCE4"=>"\u062A\u0647".freeze, "\uFCE5"=>"\u062B\u0645".freeze, "\uFCE6"=>"\u062B\u0647".freeze, "\uFCE7"=>"\u0633\u0645".freeze, "\uFCE8"=>"\u0633\u0647".freeze, "\uFCE9"=>"\u0634\u0645".freeze, "\uFCEA"=>"\u0634\u0647".freeze, "\uFCEB"=>"\u0643\u0644".freeze, "\uFCEC"=>"\u0643\u0645".freeze, "\uFCED"=>"\u0644\u0645".freeze, "\uFCEE"=>"\u0646\u0645".freeze, "\uFCEF"=>"\u0646\u0647".freeze, "\uFCF0"=>"\u064A\u0645".freeze, "\uFCF1"=>"\u064A\u0647".freeze, "\uFCF2"=>"\u0640\u064E\u0651".freeze, "\uFCF3"=>"\u0640\u064F\u0651".freeze, "\uFCF4"=>"\u0640\u0650\u0651".freeze, "\uFCF5"=>"\u0637\u0649".freeze, "\uFCF6"=>"\u0637\u064A".freeze, "\uFCF7"=>"\u0639\u0649".freeze, "\uFCF8"=>"\u0639\u064A".freeze, "\uFCF9"=>"\u063A\u0649".freeze, "\uFCFA"=>"\u063A\u064A".freeze, "\uFCFB"=>"\u0633\u0649".freeze, "\uFCFC"=>"\u0633\u064A".freeze, "\uFCFD"=>"\u0634\u0649".freeze, "\uFCFE"=>"\u0634\u064A".freeze, "\uFCFF"=>"\u062D\u0649".freeze, "\uFD00"=>"\u062D\u064A".freeze, "\uFD01"=>"\u062C\u0649".freeze, "\uFD02"=>"\u062C\u064A".freeze, "\uFD03"=>"\u062E\u0649".freeze, "\uFD04"=>"\u062E\u064A".freeze, "\uFD05"=>"\u0635\u0649".freeze, "\uFD06"=>"\u0635\u064A".freeze, "\uFD07"=>"\u0636\u0649".freeze, "\uFD08"=>"\u0636\u064A".freeze, "\uFD09"=>"\u0634\u062C".freeze, "\uFD0A"=>"\u0634\u062D".freeze, "\uFD0B"=>"\u0634\u062E".freeze, "\uFD0C"=>"\u0634\u0645".freeze, "\uFD0D"=>"\u0634\u0631".freeze, "\uFD0E"=>"\u0633\u0631".freeze, "\uFD0F"=>"\u0635\u0631".freeze, "\uFD10"=>"\u0636\u0631".freeze, "\uFD11"=>"\u0637\u0649".freeze, "\uFD12"=>"\u0637\u064A".freeze, "\uFD13"=>"\u0639\u0649".freeze, "\uFD14"=>"\u0639\u064A".freeze, "\uFD15"=>"\u063A\u0649".freeze, "\uFD16"=>"\u063A\u064A".freeze, "\uFD17"=>"\u0633\u0649".freeze, "\uFD18"=>"\u0633\u064A".freeze, "\uFD19"=>"\u0634\u0649".freeze, "\uFD1A"=>"\u0634\u064A".freeze, "\uFD1B"=>"\u062D\u0649".freeze, "\uFD1C"=>"\u062D\u064A".freeze, "\uFD1D"=>"\u062C\u0649".freeze, "\uFD1E"=>"\u062C\u064A".freeze, "\uFD1F"=>"\u062E\u0649".freeze, "\uFD20"=>"\u062E\u064A".freeze, "\uFD21"=>"\u0635\u0649".freeze, "\uFD22"=>"\u0635\u064A".freeze, "\uFD23"=>"\u0636\u0649".freeze, "\uFD24"=>"\u0636\u064A".freeze, "\uFD25"=>"\u0634\u062C".freeze, "\uFD26"=>"\u0634\u062D".freeze, "\uFD27"=>"\u0634\u062E".freeze, "\uFD28"=>"\u0634\u0645".freeze, "\uFD29"=>"\u0634\u0631".freeze, "\uFD2A"=>"\u0633\u0631".freeze, "\uFD2B"=>"\u0635\u0631".freeze, "\uFD2C"=>"\u0636\u0631".freeze, "\uFD2D"=>"\u0634\u062C".freeze, "\uFD2E"=>"\u0634\u062D".freeze, "\uFD2F"=>"\u0634\u062E".freeze, "\uFD30"=>"\u0634\u0645".freeze, "\uFD31"=>"\u0633\u0647".freeze, "\uFD32"=>"\u0634\u0647".freeze, "\uFD33"=>"\u0637\u0645".freeze, "\uFD34"=>"\u0633\u062C".freeze, "\uFD35"=>"\u0633\u062D".freeze, "\uFD36"=>"\u0633\u062E".freeze, "\uFD37"=>"\u0634\u062C".freeze, "\uFD38"=>"\u0634\u062D".freeze, "\uFD39"=>"\u0634\u062E".freeze, "\uFD3A"=>"\u0637\u0645".freeze, "\uFD3B"=>"\u0638\u0645".freeze, "\uFD3C"=>"\u0627\u064B".freeze, "\uFD3D"=>"\u0627\u064B".freeze, "\uFD50"=>"\u062A\u062C\u0645".freeze, "\uFD51"=>"\u062A\u062D\u062C".freeze, "\uFD52"=>"\u062A\u062D\u062C".freeze, "\uFD53"=>"\u062A\u062D\u0645".freeze, "\uFD54"=>"\u062A\u062E\u0645".freeze, "\uFD55"=>"\u062A\u0645\u062C".freeze, "\uFD56"=>"\u062A\u0645\u062D".freeze, "\uFD57"=>"\u062A\u0645\u062E".freeze, "\uFD58"=>"\u062C\u0645\u062D".freeze, "\uFD59"=>"\u062C\u0645\u062D".freeze, "\uFD5A"=>"\u062D\u0645\u064A".freeze, "\uFD5B"=>"\u062D\u0645\u0649".freeze, "\uFD5C"=>"\u0633\u062D\u062C".freeze, "\uFD5D"=>"\u0633\u062C\u062D".freeze, "\uFD5E"=>"\u0633\u062C\u0649".freeze, "\uFD5F"=>"\u0633\u0645\u062D".freeze, "\uFD60"=>"\u0633\u0645\u062D".freeze, "\uFD61"=>"\u0633\u0645\u062C".freeze, "\uFD62"=>"\u0633\u0645\u0645".freeze, "\uFD63"=>"\u0633\u0645\u0645".freeze, "\uFD64"=>"\u0635\u062D\u062D".freeze, "\uFD65"=>"\u0635\u062D\u062D".freeze, "\uFD66"=>"\u0635\u0645\u0645".freeze, "\uFD67"=>"\u0634\u062D\u0645".freeze, "\uFD68"=>"\u0634\u062D\u0645".freeze, "\uFD69"=>"\u0634\u062C\u064A".freeze, "\uFD6A"=>"\u0634\u0645\u062E".freeze, "\uFD6B"=>"\u0634\u0645\u062E".freeze, "\uFD6C"=>"\u0634\u0645\u0645".freeze, "\uFD6D"=>"\u0634\u0645\u0645".freeze, "\uFD6E"=>"\u0636\u062D\u0649".freeze, "\uFD6F"=>"\u0636\u062E\u0645".freeze, "\uFD70"=>"\u0636\u062E\u0645".freeze, "\uFD71"=>"\u0637\u0645\u062D".freeze, "\uFD72"=>"\u0637\u0645\u062D".freeze, "\uFD73"=>"\u0637\u0645\u0645".freeze, "\uFD74"=>"\u0637\u0645\u064A".freeze, "\uFD75"=>"\u0639\u062C\u0645".freeze, "\uFD76"=>"\u0639\u0645\u0645".freeze, "\uFD77"=>"\u0639\u0645\u0645".freeze, "\uFD78"=>"\u0639\u0645\u0649".freeze, "\uFD79"=>"\u063A\u0645\u0645".freeze, "\uFD7A"=>"\u063A\u0645\u064A".freeze, "\uFD7B"=>"\u063A\u0645\u0649".freeze, "\uFD7C"=>"\u0641\u062E\u0645".freeze, "\uFD7D"=>"\u0641\u062E\u0645".freeze, "\uFD7E"=>"\u0642\u0645\u062D".freeze, "\uFD7F"=>"\u0642\u0645\u0645".freeze, "\uFD80"=>"\u0644\u062D\u0645".freeze, "\uFD81"=>"\u0644\u062D\u064A".freeze, "\uFD82"=>"\u0644\u062D\u0649".freeze, "\uFD83"=>"\u0644\u062C\u062C".freeze, "\uFD84"=>"\u0644\u062C\u062C".freeze, "\uFD85"=>"\u0644\u062E\u0645".freeze, "\uFD86"=>"\u0644\u062E\u0645".freeze, "\uFD87"=>"\u0644\u0645\u062D".freeze, "\uFD88"=>"\u0644\u0645\u062D".freeze, "\uFD89"=>"\u0645\u062D\u062C".freeze, "\uFD8A"=>"\u0645\u062D\u0645".freeze, "\uFD8B"=>"\u0645\u062D\u064A".freeze, "\uFD8C"=>"\u0645\u062C\u062D".freeze, "\uFD8D"=>"\u0645\u062C\u0645".freeze, "\uFD8E"=>"\u0645\u062E\u062C".freeze, "\uFD8F"=>"\u0645\u062E\u0645".freeze, "\uFD92"=>"\u0645\u062C\u062E".freeze, "\uFD93"=>"\u0647\u0645\u062C".freeze, "\uFD94"=>"\u0647\u0645\u0645".freeze, "\uFD95"=>"\u0646\u062D\u0645".freeze, "\uFD96"=>"\u0646\u062D\u0649".freeze, "\uFD97"=>"\u0646\u062C\u0645".freeze, "\uFD98"=>"\u0646\u062C\u0645".freeze, "\uFD99"=>"\u0646\u062C\u0649".freeze, "\uFD9A"=>"\u0646\u0645\u064A".freeze, "\uFD9B"=>"\u0646\u0645\u0649".freeze, "\uFD9C"=>"\u064A\u0645\u0645".freeze, "\uFD9D"=>"\u064A\u0645\u0645".freeze, "\uFD9E"=>"\u0628\u062E\u064A".freeze, "\uFD9F"=>"\u062A\u062C\u064A".freeze, "\uFDA0"=>"\u062A\u062C\u0649".freeze, "\uFDA1"=>"\u062A\u062E\u064A".freeze, "\uFDA2"=>"\u062A\u062E\u0649".freeze, "\uFDA3"=>"\u062A\u0645\u064A".freeze, "\uFDA4"=>"\u062A\u0645\u0649".freeze, "\uFDA5"=>"\u062C\u0645\u064A".freeze, "\uFDA6"=>"\u062C\u062D\u0649".freeze, "\uFDA7"=>"\u062C\u0645\u0649".freeze, "\uFDA8"=>"\u0633\u062E\u0649".freeze, "\uFDA9"=>"\u0635\u062D\u064A".freeze, "\uFDAA"=>"\u0634\u062D\u064A".freeze, "\uFDAB"=>"\u0636\u062D\u064A".freeze, "\uFDAC"=>"\u0644\u062C\u064A".freeze, "\uFDAD"=>"\u0644\u0645\u064A".freeze, "\uFDAE"=>"\u064A\u062D\u064A".freeze, "\uFDAF"=>"\u064A\u062C\u064A".freeze, "\uFDB0"=>"\u064A\u0645\u064A".freeze, "\uFDB1"=>"\u0645\u0645\u064A".freeze, "\uFDB2"=>"\u0642\u0645\u064A".freeze, "\uFDB3"=>"\u0646\u062D\u064A".freeze, "\uFDB4"=>"\u0642\u0645\u062D".freeze, "\uFDB5"=>"\u0644\u062D\u0645".freeze, "\uFDB6"=>"\u0639\u0645\u064A".freeze, "\uFDB7"=>"\u0643\u0645\u064A".freeze, "\uFDB8"=>"\u0646\u062C\u062D".freeze, "\uFDB9"=>"\u0645\u062E\u064A".freeze, "\uFDBA"=>"\u0644\u062C\u0645".freeze, "\uFDBB"=>"\u0643\u0645\u0645".freeze, "\uFDBC"=>"\u0644\u062C\u0645".freeze, "\uFDBD"=>"\u0646\u062C\u062D".freeze, "\uFDBE"=>"\u062C\u062D\u064A".freeze, "\uFDBF"=>"\u062D\u062C\u064A".freeze, "\uFDC0"=>"\u0645\u062C\u064A".freeze, "\uFDC1"=>"\u0641\u0645\u064A".freeze, "\uFDC2"=>"\u0628\u062D\u064A".freeze, "\uFDC3"=>"\u0643\u0645\u0645".freeze, "\uFDC4"=>"\u0639\u062C\u0645".freeze, "\uFDC5"=>"\u0635\u0645\u0645".freeze, "\uFDC6"=>"\u0633\u062E\u064A".freeze, "\uFDC7"=>"\u0646\u062C\u064A".freeze, "\uFDF0"=>"\u0635\u0644\u06D2".freeze, "\uFDF1"=>"\u0642\u0644\u06D2".freeze, "\uFDF2"=>"\u0627\u0644\u0644\u0647".freeze, "\uFDF3"=>"\u0627\u0643\u0628\u0631".freeze, "\uFDF4"=>"\u0645\u062D\u0645\u062F".freeze, "\uFDF5"=>"\u0635\u0644\u0639\u0645".freeze, "\uFDF6"=>"\u0631\u0633\u0648\u0644".freeze, "\uFDF7"=>"\u0639\u0644\u064A\u0647".freeze, "\uFDF8"=>"\u0648\u0633\u0644\u0645".freeze, "\uFDF9"=>"\u0635\u0644\u0649".freeze, "\uFDFA"=>"\u0635\u0644\u0649 \u0627\u0644\u0644\u0647 \u0639\u0644\u064A\u0647 \u0648\u0633\u0644\u0645".freeze, "\uFDFB"=>"\u062C\u0644 \u062C\u0644\u0627\u0644\u0647".freeze, "\uFDFC"=>"\u0631\u06CC\u0627\u0644".freeze, "\uFE10"=>",".freeze, "\uFE11"=>"\u3001".freeze, "\uFE12"=>"\u3002".freeze, "\uFE13"=>":".freeze, "\uFE14"=>";".freeze, "\uFE15"=>"!".freeze, "\uFE16"=>"?".freeze, "\uFE17"=>"\u3016".freeze, "\uFE18"=>"\u3017".freeze, "\uFE19"=>"...".freeze, "\uFE30"=>"..".freeze, "\uFE31"=>"\u2014".freeze, "\uFE32"=>"\u2013".freeze, "\uFE33"=>"_".freeze, "\uFE34"=>"_".freeze, "\uFE35"=>"(".freeze, "\uFE36"=>")".freeze, "\uFE37"=>"{".freeze, "\uFE38"=>"}".freeze, "\uFE39"=>"\u3014".freeze, "\uFE3A"=>"\u3015".freeze, "\uFE3B"=>"\u3010".freeze, "\uFE3C"=>"\u3011".freeze, "\uFE3D"=>"\u300A".freeze, "\uFE3E"=>"\u300B".freeze, "\uFE3F"=>"\u3008".freeze, "\uFE40"=>"\u3009".freeze, "\uFE41"=>"\u300C".freeze, "\uFE42"=>"\u300D".freeze, "\uFE43"=>"\u300E".freeze, "\uFE44"=>"\u300F".freeze, "\uFE47"=>"[".freeze, "\uFE48"=>"]".freeze, "\uFE49"=>" \u0305".freeze, "\uFE4A"=>" \u0305".freeze, "\uFE4B"=>" \u0305".freeze, "\uFE4C"=>" \u0305".freeze, "\uFE4D"=>"_".freeze, "\uFE4E"=>"_".freeze, "\uFE4F"=>"_".freeze, "\uFE50"=>",".freeze, "\uFE51"=>"\u3001".freeze, "\uFE52"=>".".freeze, "\uFE54"=>";".freeze, "\uFE55"=>":".freeze, "\uFE56"=>"?".freeze, "\uFE57"=>"!".freeze, "\uFE58"=>"\u2014".freeze, "\uFE59"=>"(".freeze, "\uFE5A"=>")".freeze, "\uFE5B"=>"{".freeze, "\uFE5C"=>"}".freeze, "\uFE5D"=>"\u3014".freeze, "\uFE5E"=>"\u3015".freeze, "\uFE5F"=>"#".freeze, "\uFE60"=>"&".freeze, "\uFE61"=>"*".freeze, "\uFE62"=>"+".freeze, "\uFE63"=>"-".freeze, "\uFE64"=>"<".freeze, "\uFE65"=>">".freeze, "\uFE66"=>"=".freeze, "\uFE68"=>"\\".freeze, "\uFE69"=>"$".freeze, "\uFE6A"=>"%".freeze, "\uFE6B"=>"@".freeze, "\uFE70"=>" \u064B".freeze, "\uFE71"=>"\u0640\u064B".freeze, "\uFE72"=>" \u064C".freeze, "\uFE74"=>" \u064D".freeze, "\uFE76"=>" \u064E".freeze, "\uFE77"=>"\u0640\u064E".freeze, "\uFE78"=>" \u064F".freeze, "\uFE79"=>"\u0640\u064F".freeze, "\uFE7A"=>" \u0650".freeze, "\uFE7B"=>"\u0640\u0650".freeze, "\uFE7C"=>" \u0651".freeze, "\uFE7D"=>"\u0640\u0651".freeze, "\uFE7E"=>" \u0652".freeze, "\uFE7F"=>"\u0640\u0652".freeze, "\uFE80"=>"\u0621".freeze, "\uFE81"=>"\u0622".freeze, "\uFE82"=>"\u0622".freeze, "\uFE83"=>"\u0623".freeze, "\uFE84"=>"\u0623".freeze, "\uFE85"=>"\u0624".freeze, "\uFE86"=>"\u0624".freeze, "\uFE87"=>"\u0625".freeze, "\uFE88"=>"\u0625".freeze, "\uFE89"=>"\u0626".freeze, "\uFE8A"=>"\u0626".freeze, "\uFE8B"=>"\u0626".freeze, "\uFE8C"=>"\u0626".freeze, "\uFE8D"=>"\u0627".freeze, "\uFE8E"=>"\u0627".freeze, "\uFE8F"=>"\u0628".freeze, "\uFE90"=>"\u0628".freeze, "\uFE91"=>"\u0628".freeze, "\uFE92"=>"\u0628".freeze, "\uFE93"=>"\u0629".freeze, "\uFE94"=>"\u0629".freeze, "\uFE95"=>"\u062A".freeze, "\uFE96"=>"\u062A".freeze, "\uFE97"=>"\u062A".freeze, "\uFE98"=>"\u062A".freeze, "\uFE99"=>"\u062B".freeze, "\uFE9A"=>"\u062B".freeze, "\uFE9B"=>"\u062B".freeze, "\uFE9C"=>"\u062B".freeze, "\uFE9D"=>"\u062C".freeze, "\uFE9E"=>"\u062C".freeze, "\uFE9F"=>"\u062C".freeze, "\uFEA0"=>"\u062C".freeze, "\uFEA1"=>"\u062D".freeze, "\uFEA2"=>"\u062D".freeze, "\uFEA3"=>"\u062D".freeze, "\uFEA4"=>"\u062D".freeze, "\uFEA5"=>"\u062E".freeze, "\uFEA6"=>"\u062E".freeze, "\uFEA7"=>"\u062E".freeze, "\uFEA8"=>"\u062E".freeze, "\uFEA9"=>"\u062F".freeze, "\uFEAA"=>"\u062F".freeze, "\uFEAB"=>"\u0630".freeze, "\uFEAC"=>"\u0630".freeze, "\uFEAD"=>"\u0631".freeze, "\uFEAE"=>"\u0631".freeze, "\uFEAF"=>"\u0632".freeze, "\uFEB0"=>"\u0632".freeze, "\uFEB1"=>"\u0633".freeze, "\uFEB2"=>"\u0633".freeze, "\uFEB3"=>"\u0633".freeze, "\uFEB4"=>"\u0633".freeze, "\uFEB5"=>"\u0634".freeze, "\uFEB6"=>"\u0634".freeze, "\uFEB7"=>"\u0634".freeze, "\uFEB8"=>"\u0634".freeze, "\uFEB9"=>"\u0635".freeze, "\uFEBA"=>"\u0635".freeze, "\uFEBB"=>"\u0635".freeze, "\uFEBC"=>"\u0635".freeze, "\uFEBD"=>"\u0636".freeze, "\uFEBE"=>"\u0636".freeze, "\uFEBF"=>"\u0636".freeze, "\uFEC0"=>"\u0636".freeze, "\uFEC1"=>"\u0637".freeze, "\uFEC2"=>"\u0637".freeze, "\uFEC3"=>"\u0637".freeze, "\uFEC4"=>"\u0637".freeze, "\uFEC5"=>"\u0638".freeze, "\uFEC6"=>"\u0638".freeze, "\uFEC7"=>"\u0638".freeze, "\uFEC8"=>"\u0638".freeze, "\uFEC9"=>"\u0639".freeze, "\uFECA"=>"\u0639".freeze, "\uFECB"=>"\u0639".freeze, "\uFECC"=>"\u0639".freeze, "\uFECD"=>"\u063A".freeze, "\uFECE"=>"\u063A".freeze, "\uFECF"=>"\u063A".freeze, "\uFED0"=>"\u063A".freeze, "\uFED1"=>"\u0641".freeze, "\uFED2"=>"\u0641".freeze, "\uFED3"=>"\u0641".freeze, "\uFED4"=>"\u0641".freeze, "\uFED5"=>"\u0642".freeze, "\uFED6"=>"\u0642".freeze, "\uFED7"=>"\u0642".freeze, "\uFED8"=>"\u0642".freeze, "\uFED9"=>"\u0643".freeze, "\uFEDA"=>"\u0643".freeze, "\uFEDB"=>"\u0643".freeze, "\uFEDC"=>"\u0643".freeze, "\uFEDD"=>"\u0644".freeze, "\uFEDE"=>"\u0644".freeze, "\uFEDF"=>"\u0644".freeze, "\uFEE0"=>"\u0644".freeze, "\uFEE1"=>"\u0645".freeze, "\uFEE2"=>"\u0645".freeze, "\uFEE3"=>"\u0645".freeze, "\uFEE4"=>"\u0645".freeze, "\uFEE5"=>"\u0646".freeze, "\uFEE6"=>"\u0646".freeze, "\uFEE7"=>"\u0646".freeze, "\uFEE8"=>"\u0646".freeze, "\uFEE9"=>"\u0647".freeze, "\uFEEA"=>"\u0647".freeze, "\uFEEB"=>"\u0647".freeze, "\uFEEC"=>"\u0647".freeze, "\uFEED"=>"\u0648".freeze, "\uFEEE"=>"\u0648".freeze, "\uFEEF"=>"\u0649".freeze, "\uFEF0"=>"\u0649".freeze, "\uFEF1"=>"\u064A".freeze, "\uFEF2"=>"\u064A".freeze, "\uFEF3"=>"\u064A".freeze, "\uFEF4"=>"\u064A".freeze, "\uFEF5"=>"\u0644\u0622".freeze, "\uFEF6"=>"\u0644\u0622".freeze, "\uFEF7"=>"\u0644\u0623".freeze, "\uFEF8"=>"\u0644\u0623".freeze, "\uFEF9"=>"\u0644\u0625".freeze, "\uFEFA"=>"\u0644\u0625".freeze, "\uFEFB"=>"\u0644\u0627".freeze, "\uFEFC"=>"\u0644\u0627".freeze, "\uFF01"=>"!".freeze, "\uFF02"=>"\"".freeze, "\uFF03"=>"#".freeze, "\uFF04"=>"$".freeze, "\uFF05"=>"%".freeze, "\uFF06"=>"&".freeze, "\uFF07"=>"'".freeze, "\uFF08"=>"(".freeze, "\uFF09"=>")".freeze, "\uFF0A"=>"*".freeze, "\uFF0B"=>"+".freeze, "\uFF0C"=>",".freeze, "\uFF0D"=>"-".freeze, "\uFF0E"=>".".freeze, "\uFF0F"=>"/".freeze, "\uFF10"=>"0".freeze, "\uFF11"=>"1".freeze, "\uFF12"=>"2".freeze, "\uFF13"=>"3".freeze, "\uFF14"=>"4".freeze, "\uFF15"=>"5".freeze, "\uFF16"=>"6".freeze, "\uFF17"=>"7".freeze, "\uFF18"=>"8".freeze, "\uFF19"=>"9".freeze, "\uFF1A"=>":".freeze, "\uFF1B"=>";".freeze, "\uFF1C"=>"<".freeze, "\uFF1D"=>"=".freeze, "\uFF1E"=>">".freeze, "\uFF1F"=>"?".freeze, "\uFF20"=>"@".freeze, "\uFF21"=>"A".freeze, "\uFF22"=>"B".freeze, "\uFF23"=>"C".freeze, "\uFF24"=>"D".freeze, "\uFF25"=>"E".freeze, "\uFF26"=>"F".freeze, "\uFF27"=>"G".freeze, "\uFF28"=>"H".freeze, "\uFF29"=>"I".freeze, "\uFF2A"=>"J".freeze, "\uFF2B"=>"K".freeze, "\uFF2C"=>"L".freeze, "\uFF2D"=>"M".freeze, "\uFF2E"=>"N".freeze, "\uFF2F"=>"O".freeze, "\uFF30"=>"P".freeze, "\uFF31"=>"Q".freeze, "\uFF32"=>"R".freeze, "\uFF33"=>"S".freeze, "\uFF34"=>"T".freeze, "\uFF35"=>"U".freeze, "\uFF36"=>"V".freeze, "\uFF37"=>"W".freeze, "\uFF38"=>"X".freeze, "\uFF39"=>"Y".freeze, "\uFF3A"=>"Z".freeze, "\uFF3B"=>"[".freeze, "\uFF3C"=>"\\".freeze, "\uFF3D"=>"]".freeze, "\uFF3E"=>"^".freeze, "\uFF3F"=>"_".freeze, "\uFF40"=>"`".freeze, "\uFF41"=>"a".freeze, "\uFF42"=>"b".freeze, "\uFF43"=>"c".freeze, "\uFF44"=>"d".freeze, "\uFF45"=>"e".freeze, "\uFF46"=>"f".freeze, "\uFF47"=>"g".freeze, "\uFF48"=>"h".freeze, "\uFF49"=>"i".freeze, "\uFF4A"=>"j".freeze, "\uFF4B"=>"k".freeze, "\uFF4C"=>"l".freeze, "\uFF4D"=>"m".freeze, "\uFF4E"=>"n".freeze, "\uFF4F"=>"o".freeze, "\uFF50"=>"p".freeze, "\uFF51"=>"q".freeze, "\uFF52"=>"r".freeze, "\uFF53"=>"s".freeze, "\uFF54"=>"t".freeze, "\uFF55"=>"u".freeze, "\uFF56"=>"v".freeze, "\uFF57"=>"w".freeze, "\uFF58"=>"x".freeze, "\uFF59"=>"y".freeze, "\uFF5A"=>"z".freeze, "\uFF5B"=>"{".freeze, "\uFF5C"=>"|".freeze, "\uFF5D"=>"}".freeze, "\uFF5E"=>"~".freeze, "\uFF5F"=>"\u2985".freeze, "\uFF60"=>"\u2986".freeze, "\uFF61"=>"\u3002".freeze, "\uFF62"=>"\u300C".freeze, "\uFF63"=>"\u300D".freeze, "\uFF64"=>"\u3001".freeze, "\uFF65"=>"\u30FB".freeze, "\uFF66"=>"\u30F2".freeze, "\uFF67"=>"\u30A1".freeze, "\uFF68"=>"\u30A3".freeze, "\uFF69"=>"\u30A5".freeze, "\uFF6A"=>"\u30A7".freeze, "\uFF6B"=>"\u30A9".freeze, "\uFF6C"=>"\u30E3".freeze, "\uFF6D"=>"\u30E5".freeze, "\uFF6E"=>"\u30E7".freeze, "\uFF6F"=>"\u30C3".freeze, "\uFF70"=>"\u30FC".freeze, "\uFF71"=>"\u30A2".freeze, "\uFF72"=>"\u30A4".freeze, "\uFF73"=>"\u30A6".freeze, "\uFF74"=>"\u30A8".freeze, "\uFF75"=>"\u30AA".freeze, "\uFF76"=>"\u30AB".freeze, "\uFF77"=>"\u30AD".freeze, "\uFF78"=>"\u30AF".freeze, "\uFF79"=>"\u30B1".freeze, "\uFF7A"=>"\u30B3".freeze, "\uFF7B"=>"\u30B5".freeze, "\uFF7C"=>"\u30B7".freeze, "\uFF7D"=>"\u30B9".freeze, "\uFF7E"=>"\u30BB".freeze, "\uFF7F"=>"\u30BD".freeze, "\uFF80"=>"\u30BF".freeze, "\uFF81"=>"\u30C1".freeze, "\uFF82"=>"\u30C4".freeze, "\uFF83"=>"\u30C6".freeze, "\uFF84"=>"\u30C8".freeze, "\uFF85"=>"\u30CA".freeze, "\uFF86"=>"\u30CB".freeze, "\uFF87"=>"\u30CC".freeze, "\uFF88"=>"\u30CD".freeze, "\uFF89"=>"\u30CE".freeze, "\uFF8A"=>"\u30CF".freeze, "\uFF8B"=>"\u30D2".freeze, "\uFF8C"=>"\u30D5".freeze, "\uFF8D"=>"\u30D8".freeze, "\uFF8E"=>"\u30DB".freeze, "\uFF8F"=>"\u30DE".freeze, "\uFF90"=>"\u30DF".freeze, "\uFF91"=>"\u30E0".freeze, "\uFF92"=>"\u30E1".freeze, "\uFF93"=>"\u30E2".freeze, "\uFF94"=>"\u30E4".freeze, "\uFF95"=>"\u30E6".freeze, "\uFF96"=>"\u30E8".freeze, "\uFF97"=>"\u30E9".freeze, "\uFF98"=>"\u30EA".freeze, "\uFF99"=>"\u30EB".freeze, "\uFF9A"=>"\u30EC".freeze, "\uFF9B"=>"\u30ED".freeze, "\uFF9C"=>"\u30EF".freeze, "\uFF9D"=>"\u30F3".freeze, "\uFF9E"=>"\u3099".freeze, "\uFF9F"=>"\u309A".freeze, "\uFFA0"=>"\u1160".freeze, "\uFFA1"=>"\u1100".freeze, "\uFFA2"=>"\u1101".freeze, "\uFFA3"=>"\u11AA".freeze, "\uFFA4"=>"\u1102".freeze, "\uFFA5"=>"\u11AC".freeze, "\uFFA6"=>"\u11AD".freeze, "\uFFA7"=>"\u1103".freeze, "\uFFA8"=>"\u1104".freeze, "\uFFA9"=>"\u1105".freeze, "\uFFAA"=>"\u11B0".freeze, "\uFFAB"=>"\u11B1".freeze, "\uFFAC"=>"\u11B2".freeze, "\uFFAD"=>"\u11B3".freeze, "\uFFAE"=>"\u11B4".freeze, "\uFFAF"=>"\u11B5".freeze, "\uFFB0"=>"\u111A".freeze, "\uFFB1"=>"\u1106".freeze, "\uFFB2"=>"\u1107".freeze, "\uFFB3"=>"\u1108".freeze, "\uFFB4"=>"\u1121".freeze, "\uFFB5"=>"\u1109".freeze, "\uFFB6"=>"\u110A".freeze, "\uFFB7"=>"\u110B".freeze, "\uFFB8"=>"\u110C".freeze, "\uFFB9"=>"\u110D".freeze, "\uFFBA"=>"\u110E".freeze, "\uFFBB"=>"\u110F".freeze, "\uFFBC"=>"\u1110".freeze, "\uFFBD"=>"\u1111".freeze, "\uFFBE"=>"\u1112".freeze, "\uFFC2"=>"\u1161".freeze, "\uFFC3"=>"\u1162".freeze, "\uFFC4"=>"\u1163".freeze, "\uFFC5"=>"\u1164".freeze, "\uFFC6"=>"\u1165".freeze, "\uFFC7"=>"\u1166".freeze, "\uFFCA"=>"\u1167".freeze, "\uFFCB"=>"\u1168".freeze, "\uFFCC"=>"\u1169".freeze, "\uFFCD"=>"\u116A".freeze, "\uFFCE"=>"\u116B".freeze, "\uFFCF"=>"\u116C".freeze, "\uFFD2"=>"\u116D".freeze, "\uFFD3"=>"\u116E".freeze, "\uFFD4"=>"\u116F".freeze, "\uFFD5"=>"\u1170".freeze, "\uFFD6"=>"\u1171".freeze, "\uFFD7"=>"\u1172".freeze, "\uFFDA"=>"\u1173".freeze, "\uFFDB"=>"\u1174".freeze, "\uFFDC"=>"\u1175".freeze, "\uFFE0"=>"\u00A2".freeze, "\uFFE1"=>"\u00A3".freeze, "\uFFE2"=>"\u00AC".freeze, "\uFFE3"=>" \u0304".freeze, "\uFFE4"=>"\u00A6".freeze, "\uFFE5"=>"\u00A5".freeze, "\uFFE6"=>"\u20A9".freeze, "\uFFE8"=>"\u2502".freeze, "\uFFE9"=>"\u2190".freeze, "\uFFEA"=>"\u2191".freeze, "\uFFEB"=>"\u2192".freeze, "\uFFEC"=>"\u2193".freeze, "\uFFED"=>"\u25A0".freeze, "\uFFEE"=>"\u25CB".freeze, "\u{1D400}"=>"A".freeze, "\u{1D401}"=>"B".freeze, "\u{1D402}"=>"C".freeze, "\u{1D403}"=>"D".freeze, "\u{1D404}"=>"E".freeze, "\u{1D405}"=>"F".freeze, "\u{1D406}"=>"G".freeze, "\u{1D407}"=>"H".freeze, "\u{1D408}"=>"I".freeze, "\u{1D409}"=>"J".freeze, "\u{1D40A}"=>"K".freeze, "\u{1D40B}"=>"L".freeze, "\u{1D40C}"=>"M".freeze, "\u{1D40D}"=>"N".freeze, "\u{1D40E}"=>"O".freeze, "\u{1D40F}"=>"P".freeze, "\u{1D410}"=>"Q".freeze, "\u{1D411}"=>"R".freeze, "\u{1D412}"=>"S".freeze, "\u{1D413}"=>"T".freeze, "\u{1D414}"=>"U".freeze, "\u{1D415}"=>"V".freeze, "\u{1D416}"=>"W".freeze, "\u{1D417}"=>"X".freeze, "\u{1D418}"=>"Y".freeze, "\u{1D419}"=>"Z".freeze, "\u{1D41A}"=>"a".freeze, "\u{1D41B}"=>"b".freeze, "\u{1D41C}"=>"c".freeze, "\u{1D41D}"=>"d".freeze, "\u{1D41E}"=>"e".freeze, "\u{1D41F}"=>"f".freeze, "\u{1D420}"=>"g".freeze, "\u{1D421}"=>"h".freeze, "\u{1D422}"=>"i".freeze, "\u{1D423}"=>"j".freeze, "\u{1D424}"=>"k".freeze, "\u{1D425}"=>"l".freeze, "\u{1D426}"=>"m".freeze, "\u{1D427}"=>"n".freeze, "\u{1D428}"=>"o".freeze, "\u{1D429}"=>"p".freeze, "\u{1D42A}"=>"q".freeze, "\u{1D42B}"=>"r".freeze, "\u{1D42C}"=>"s".freeze, "\u{1D42D}"=>"t".freeze, "\u{1D42E}"=>"u".freeze, "\u{1D42F}"=>"v".freeze, "\u{1D430}"=>"w".freeze, "\u{1D431}"=>"x".freeze, "\u{1D432}"=>"y".freeze, "\u{1D433}"=>"z".freeze, "\u{1D434}"=>"A".freeze, "\u{1D435}"=>"B".freeze, "\u{1D436}"=>"C".freeze, "\u{1D437}"=>"D".freeze, "\u{1D438}"=>"E".freeze, "\u{1D439}"=>"F".freeze, "\u{1D43A}"=>"G".freeze, "\u{1D43B}"=>"H".freeze, "\u{1D43C}"=>"I".freeze, "\u{1D43D}"=>"J".freeze, "\u{1D43E}"=>"K".freeze, "\u{1D43F}"=>"L".freeze, "\u{1D440}"=>"M".freeze, "\u{1D441}"=>"N".freeze, "\u{1D442}"=>"O".freeze, "\u{1D443}"=>"P".freeze, "\u{1D444}"=>"Q".freeze, "\u{1D445}"=>"R".freeze, "\u{1D446}"=>"S".freeze, "\u{1D447}"=>"T".freeze, "\u{1D448}"=>"U".freeze, "\u{1D449}"=>"V".freeze, "\u{1D44A}"=>"W".freeze, "\u{1D44B}"=>"X".freeze, "\u{1D44C}"=>"Y".freeze, "\u{1D44D}"=>"Z".freeze, "\u{1D44E}"=>"a".freeze, "\u{1D44F}"=>"b".freeze, "\u{1D450}"=>"c".freeze, "\u{1D451}"=>"d".freeze, "\u{1D452}"=>"e".freeze, "\u{1D453}"=>"f".freeze, "\u{1D454}"=>"g".freeze, "\u{1D456}"=>"i".freeze, "\u{1D457}"=>"j".freeze, "\u{1D458}"=>"k".freeze, "\u{1D459}"=>"l".freeze, "\u{1D45A}"=>"m".freeze, "\u{1D45B}"=>"n".freeze, "\u{1D45C}"=>"o".freeze, "\u{1D45D}"=>"p".freeze, "\u{1D45E}"=>"q".freeze, "\u{1D45F}"=>"r".freeze, "\u{1D460}"=>"s".freeze, "\u{1D461}"=>"t".freeze, "\u{1D462}"=>"u".freeze, "\u{1D463}"=>"v".freeze, "\u{1D464}"=>"w".freeze, "\u{1D465}"=>"x".freeze, "\u{1D466}"=>"y".freeze, "\u{1D467}"=>"z".freeze, "\u{1D468}"=>"A".freeze, "\u{1D469}"=>"B".freeze, "\u{1D46A}"=>"C".freeze, "\u{1D46B}"=>"D".freeze, "\u{1D46C}"=>"E".freeze, "\u{1D46D}"=>"F".freeze, "\u{1D46E}"=>"G".freeze, "\u{1D46F}"=>"H".freeze, "\u{1D470}"=>"I".freeze, "\u{1D471}"=>"J".freeze, "\u{1D472}"=>"K".freeze, "\u{1D473}"=>"L".freeze, "\u{1D474}"=>"M".freeze, "\u{1D475}"=>"N".freeze, "\u{1D476}"=>"O".freeze, "\u{1D477}"=>"P".freeze, "\u{1D478}"=>"Q".freeze, "\u{1D479}"=>"R".freeze, "\u{1D47A}"=>"S".freeze, "\u{1D47B}"=>"T".freeze, "\u{1D47C}"=>"U".freeze, "\u{1D47D}"=>"V".freeze, "\u{1D47E}"=>"W".freeze, "\u{1D47F}"=>"X".freeze, "\u{1D480}"=>"Y".freeze, "\u{1D481}"=>"Z".freeze, "\u{1D482}"=>"a".freeze, "\u{1D483}"=>"b".freeze, "\u{1D484}"=>"c".freeze, "\u{1D485}"=>"d".freeze, "\u{1D486}"=>"e".freeze, "\u{1D487}"=>"f".freeze, "\u{1D488}"=>"g".freeze, "\u{1D489}"=>"h".freeze, "\u{1D48A}"=>"i".freeze, "\u{1D48B}"=>"j".freeze, "\u{1D48C}"=>"k".freeze, "\u{1D48D}"=>"l".freeze, "\u{1D48E}"=>"m".freeze, "\u{1D48F}"=>"n".freeze, "\u{1D490}"=>"o".freeze, "\u{1D491}"=>"p".freeze, "\u{1D492}"=>"q".freeze, "\u{1D493}"=>"r".freeze, "\u{1D494}"=>"s".freeze, "\u{1D495}"=>"t".freeze, "\u{1D496}"=>"u".freeze, "\u{1D497}"=>"v".freeze, "\u{1D498}"=>"w".freeze, "\u{1D499}"=>"x".freeze, "\u{1D49A}"=>"y".freeze, "\u{1D49B}"=>"z".freeze, "\u{1D49C}"=>"A".freeze, "\u{1D49E}"=>"C".freeze, "\u{1D49F}"=>"D".freeze, "\u{1D4A2}"=>"G".freeze, "\u{1D4A5}"=>"J".freeze, "\u{1D4A6}"=>"K".freeze, "\u{1D4A9}"=>"N".freeze, "\u{1D4AA}"=>"O".freeze, "\u{1D4AB}"=>"P".freeze, "\u{1D4AC}"=>"Q".freeze, "\u{1D4AE}"=>"S".freeze, "\u{1D4AF}"=>"T".freeze, "\u{1D4B0}"=>"U".freeze, "\u{1D4B1}"=>"V".freeze, "\u{1D4B2}"=>"W".freeze, "\u{1D4B3}"=>"X".freeze, "\u{1D4B4}"=>"Y".freeze, "\u{1D4B5}"=>"Z".freeze, "\u{1D4B6}"=>"a".freeze, "\u{1D4B7}"=>"b".freeze, "\u{1D4B8}"=>"c".freeze, "\u{1D4B9}"=>"d".freeze, "\u{1D4BB}"=>"f".freeze, "\u{1D4BD}"=>"h".freeze, "\u{1D4BE}"=>"i".freeze, "\u{1D4BF}"=>"j".freeze, "\u{1D4C0}"=>"k".freeze, "\u{1D4C1}"=>"l".freeze, "\u{1D4C2}"=>"m".freeze, "\u{1D4C3}"=>"n".freeze, "\u{1D4C5}"=>"p".freeze, "\u{1D4C6}"=>"q".freeze, "\u{1D4C7}"=>"r".freeze, "\u{1D4C8}"=>"s".freeze, "\u{1D4C9}"=>"t".freeze, "\u{1D4CA}"=>"u".freeze, "\u{1D4CB}"=>"v".freeze, "\u{1D4CC}"=>"w".freeze, "\u{1D4CD}"=>"x".freeze, "\u{1D4CE}"=>"y".freeze, "\u{1D4CF}"=>"z".freeze, "\u{1D4D0}"=>"A".freeze, "\u{1D4D1}"=>"B".freeze, "\u{1D4D2}"=>"C".freeze, "\u{1D4D3}"=>"D".freeze, "\u{1D4D4}"=>"E".freeze, "\u{1D4D5}"=>"F".freeze, "\u{1D4D6}"=>"G".freeze, "\u{1D4D7}"=>"H".freeze, "\u{1D4D8}"=>"I".freeze, "\u{1D4D9}"=>"J".freeze, "\u{1D4DA}"=>"K".freeze, "\u{1D4DB}"=>"L".freeze, "\u{1D4DC}"=>"M".freeze, "\u{1D4DD}"=>"N".freeze, "\u{1D4DE}"=>"O".freeze, "\u{1D4DF}"=>"P".freeze, "\u{1D4E0}"=>"Q".freeze, "\u{1D4E1}"=>"R".freeze, "\u{1D4E2}"=>"S".freeze, "\u{1D4E3}"=>"T".freeze, "\u{1D4E4}"=>"U".freeze, "\u{1D4E5}"=>"V".freeze, "\u{1D4E6}"=>"W".freeze, "\u{1D4E7}"=>"X".freeze, "\u{1D4E8}"=>"Y".freeze, "\u{1D4E9}"=>"Z".freeze, "\u{1D4EA}"=>"a".freeze, "\u{1D4EB}"=>"b".freeze, "\u{1D4EC}"=>"c".freeze, "\u{1D4ED}"=>"d".freeze, "\u{1D4EE}"=>"e".freeze, "\u{1D4EF}"=>"f".freeze, "\u{1D4F0}"=>"g".freeze, "\u{1D4F1}"=>"h".freeze, "\u{1D4F2}"=>"i".freeze, "\u{1D4F3}"=>"j".freeze, "\u{1D4F4}"=>"k".freeze, "\u{1D4F5}"=>"l".freeze, "\u{1D4F6}"=>"m".freeze, "\u{1D4F7}"=>"n".freeze, "\u{1D4F8}"=>"o".freeze, "\u{1D4F9}"=>"p".freeze, "\u{1D4FA}"=>"q".freeze, "\u{1D4FB}"=>"r".freeze, "\u{1D4FC}"=>"s".freeze, "\u{1D4FD}"=>"t".freeze, "\u{1D4FE}"=>"u".freeze, "\u{1D4FF}"=>"v".freeze, "\u{1D500}"=>"w".freeze, "\u{1D501}"=>"x".freeze, "\u{1D502}"=>"y".freeze, "\u{1D503}"=>"z".freeze, "\u{1D504}"=>"A".freeze, "\u{1D505}"=>"B".freeze, "\u{1D507}"=>"D".freeze, "\u{1D508}"=>"E".freeze, "\u{1D509}"=>"F".freeze, "\u{1D50A}"=>"G".freeze, "\u{1D50D}"=>"J".freeze, "\u{1D50E}"=>"K".freeze, "\u{1D50F}"=>"L".freeze, "\u{1D510}"=>"M".freeze, "\u{1D511}"=>"N".freeze, "\u{1D512}"=>"O".freeze, "\u{1D513}"=>"P".freeze, "\u{1D514}"=>"Q".freeze, "\u{1D516}"=>"S".freeze, "\u{1D517}"=>"T".freeze, "\u{1D518}"=>"U".freeze, "\u{1D519}"=>"V".freeze, "\u{1D51A}"=>"W".freeze, "\u{1D51B}"=>"X".freeze, "\u{1D51C}"=>"Y".freeze, "\u{1D51E}"=>"a".freeze, "\u{1D51F}"=>"b".freeze, "\u{1D520}"=>"c".freeze, "\u{1D521}"=>"d".freeze, "\u{1D522}"=>"e".freeze, "\u{1D523}"=>"f".freeze, "\u{1D524}"=>"g".freeze, "\u{1D525}"=>"h".freeze, "\u{1D526}"=>"i".freeze, "\u{1D527}"=>"j".freeze, "\u{1D528}"=>"k".freeze, "\u{1D529}"=>"l".freeze, "\u{1D52A}"=>"m".freeze, "\u{1D52B}"=>"n".freeze, "\u{1D52C}"=>"o".freeze, "\u{1D52D}"=>"p".freeze, "\u{1D52E}"=>"q".freeze, "\u{1D52F}"=>"r".freeze, "\u{1D530}"=>"s".freeze, "\u{1D531}"=>"t".freeze, "\u{1D532}"=>"u".freeze, "\u{1D533}"=>"v".freeze, "\u{1D534}"=>"w".freeze, "\u{1D535}"=>"x".freeze, "\u{1D536}"=>"y".freeze, "\u{1D537}"=>"z".freeze, "\u{1D538}"=>"A".freeze, "\u{1D539}"=>"B".freeze, "\u{1D53B}"=>"D".freeze, "\u{1D53C}"=>"E".freeze, "\u{1D53D}"=>"F".freeze, "\u{1D53E}"=>"G".freeze, "\u{1D540}"=>"I".freeze, "\u{1D541}"=>"J".freeze, "\u{1D542}"=>"K".freeze, "\u{1D543}"=>"L".freeze, "\u{1D544}"=>"M".freeze, "\u{1D546}"=>"O".freeze, "\u{1D54A}"=>"S".freeze, "\u{1D54B}"=>"T".freeze, "\u{1D54C}"=>"U".freeze, "\u{1D54D}"=>"V".freeze, "\u{1D54E}"=>"W".freeze, "\u{1D54F}"=>"X".freeze, "\u{1D550}"=>"Y".freeze, "\u{1D552}"=>"a".freeze, "\u{1D553}"=>"b".freeze, "\u{1D554}"=>"c".freeze, "\u{1D555}"=>"d".freeze, "\u{1D556}"=>"e".freeze, "\u{1D557}"=>"f".freeze, "\u{1D558}"=>"g".freeze, "\u{1D559}"=>"h".freeze, "\u{1D55A}"=>"i".freeze, "\u{1D55B}"=>"j".freeze, "\u{1D55C}"=>"k".freeze, "\u{1D55D}"=>"l".freeze, "\u{1D55E}"=>"m".freeze, "\u{1D55F}"=>"n".freeze, "\u{1D560}"=>"o".freeze, "\u{1D561}"=>"p".freeze, "\u{1D562}"=>"q".freeze, "\u{1D563}"=>"r".freeze, "\u{1D564}"=>"s".freeze, "\u{1D565}"=>"t".freeze, "\u{1D566}"=>"u".freeze, "\u{1D567}"=>"v".freeze, "\u{1D568}"=>"w".freeze, "\u{1D569}"=>"x".freeze, "\u{1D56A}"=>"y".freeze, "\u{1D56B}"=>"z".freeze, "\u{1D56C}"=>"A".freeze, "\u{1D56D}"=>"B".freeze, "\u{1D56E}"=>"C".freeze, "\u{1D56F}"=>"D".freeze, "\u{1D570}"=>"E".freeze, "\u{1D571}"=>"F".freeze, "\u{1D572}"=>"G".freeze, "\u{1D573}"=>"H".freeze, "\u{1D574}"=>"I".freeze, "\u{1D575}"=>"J".freeze, "\u{1D576}"=>"K".freeze, "\u{1D577}"=>"L".freeze, "\u{1D578}"=>"M".freeze, "\u{1D579}"=>"N".freeze, "\u{1D57A}"=>"O".freeze, "\u{1D57B}"=>"P".freeze, "\u{1D57C}"=>"Q".freeze, "\u{1D57D}"=>"R".freeze, "\u{1D57E}"=>"S".freeze, "\u{1D57F}"=>"T".freeze, "\u{1D580}"=>"U".freeze, "\u{1D581}"=>"V".freeze, "\u{1D582}"=>"W".freeze, "\u{1D583}"=>"X".freeze, "\u{1D584}"=>"Y".freeze, "\u{1D585}"=>"Z".freeze, "\u{1D586}"=>"a".freeze, "\u{1D587}"=>"b".freeze, "\u{1D588}"=>"c".freeze, "\u{1D589}"=>"d".freeze, "\u{1D58A}"=>"e".freeze, "\u{1D58B}"=>"f".freeze, "\u{1D58C}"=>"g".freeze, "\u{1D58D}"=>"h".freeze, "\u{1D58E}"=>"i".freeze, "\u{1D58F}"=>"j".freeze, "\u{1D590}"=>"k".freeze, "\u{1D591}"=>"l".freeze, "\u{1D592}"=>"m".freeze, "\u{1D593}"=>"n".freeze, "\u{1D594}"=>"o".freeze, "\u{1D595}"=>"p".freeze, "\u{1D596}"=>"q".freeze, "\u{1D597}"=>"r".freeze, "\u{1D598}"=>"s".freeze, "\u{1D599}"=>"t".freeze, "\u{1D59A}"=>"u".freeze, "\u{1D59B}"=>"v".freeze, "\u{1D59C}"=>"w".freeze, "\u{1D59D}"=>"x".freeze, "\u{1D59E}"=>"y".freeze, "\u{1D59F}"=>"z".freeze, "\u{1D5A0}"=>"A".freeze, "\u{1D5A1}"=>"B".freeze, "\u{1D5A2}"=>"C".freeze, "\u{1D5A3}"=>"D".freeze, "\u{1D5A4}"=>"E".freeze, "\u{1D5A5}"=>"F".freeze, "\u{1D5A6}"=>"G".freeze, "\u{1D5A7}"=>"H".freeze, "\u{1D5A8}"=>"I".freeze, "\u{1D5A9}"=>"J".freeze, "\u{1D5AA}"=>"K".freeze, "\u{1D5AB}"=>"L".freeze, "\u{1D5AC}"=>"M".freeze, "\u{1D5AD}"=>"N".freeze, "\u{1D5AE}"=>"O".freeze, "\u{1D5AF}"=>"P".freeze, "\u{1D5B0}"=>"Q".freeze, "\u{1D5B1}"=>"R".freeze, "\u{1D5B2}"=>"S".freeze, "\u{1D5B3}"=>"T".freeze, "\u{1D5B4}"=>"U".freeze, "\u{1D5B5}"=>"V".freeze, "\u{1D5B6}"=>"W".freeze, "\u{1D5B7}"=>"X".freeze, "\u{1D5B8}"=>"Y".freeze, "\u{1D5B9}"=>"Z".freeze, "\u{1D5BA}"=>"a".freeze, "\u{1D5BB}"=>"b".freeze, "\u{1D5BC}"=>"c".freeze, "\u{1D5BD}"=>"d".freeze, "\u{1D5BE}"=>"e".freeze, "\u{1D5BF}"=>"f".freeze, "\u{1D5C0}"=>"g".freeze, "\u{1D5C1}"=>"h".freeze, "\u{1D5C2}"=>"i".freeze, "\u{1D5C3}"=>"j".freeze, "\u{1D5C4}"=>"k".freeze, "\u{1D5C5}"=>"l".freeze, "\u{1D5C6}"=>"m".freeze, "\u{1D5C7}"=>"n".freeze, "\u{1D5C8}"=>"o".freeze, "\u{1D5C9}"=>"p".freeze, "\u{1D5CA}"=>"q".freeze, "\u{1D5CB}"=>"r".freeze, "\u{1D5CC}"=>"s".freeze, "\u{1D5CD}"=>"t".freeze, "\u{1D5CE}"=>"u".freeze, "\u{1D5CF}"=>"v".freeze, "\u{1D5D0}"=>"w".freeze, "\u{1D5D1}"=>"x".freeze, "\u{1D5D2}"=>"y".freeze, "\u{1D5D3}"=>"z".freeze, "\u{1D5D4}"=>"A".freeze, "\u{1D5D5}"=>"B".freeze, "\u{1D5D6}"=>"C".freeze, "\u{1D5D7}"=>"D".freeze, "\u{1D5D8}"=>"E".freeze, "\u{1D5D9}"=>"F".freeze, "\u{1D5DA}"=>"G".freeze, "\u{1D5DB}"=>"H".freeze, "\u{1D5DC}"=>"I".freeze, "\u{1D5DD}"=>"J".freeze, "\u{1D5DE}"=>"K".freeze, "\u{1D5DF}"=>"L".freeze, "\u{1D5E0}"=>"M".freeze, "\u{1D5E1}"=>"N".freeze, "\u{1D5E2}"=>"O".freeze, "\u{1D5E3}"=>"P".freeze, "\u{1D5E4}"=>"Q".freeze, "\u{1D5E5}"=>"R".freeze, "\u{1D5E6}"=>"S".freeze, "\u{1D5E7}"=>"T".freeze, "\u{1D5E8}"=>"U".freeze, "\u{1D5E9}"=>"V".freeze, "\u{1D5EA}"=>"W".freeze, "\u{1D5EB}"=>"X".freeze, "\u{1D5EC}"=>"Y".freeze, "\u{1D5ED}"=>"Z".freeze, "\u{1D5EE}"=>"a".freeze, "\u{1D5EF}"=>"b".freeze, "\u{1D5F0}"=>"c".freeze, "\u{1D5F1}"=>"d".freeze, "\u{1D5F2}"=>"e".freeze, "\u{1D5F3}"=>"f".freeze, "\u{1D5F4}"=>"g".freeze, "\u{1D5F5}"=>"h".freeze, "\u{1D5F6}"=>"i".freeze, "\u{1D5F7}"=>"j".freeze, "\u{1D5F8}"=>"k".freeze, "\u{1D5F9}"=>"l".freeze, "\u{1D5FA}"=>"m".freeze, "\u{1D5FB}"=>"n".freeze, "\u{1D5FC}"=>"o".freeze, "\u{1D5FD}"=>"p".freeze, "\u{1D5FE}"=>"q".freeze, "\u{1D5FF}"=>"r".freeze, "\u{1D600}"=>"s".freeze, "\u{1D601}"=>"t".freeze, "\u{1D602}"=>"u".freeze, "\u{1D603}"=>"v".freeze, "\u{1D604}"=>"w".freeze, "\u{1D605}"=>"x".freeze, "\u{1D606}"=>"y".freeze, "\u{1D607}"=>"z".freeze, "\u{1D608}"=>"A".freeze, "\u{1D609}"=>"B".freeze, "\u{1D60A}"=>"C".freeze, "\u{1D60B}"=>"D".freeze, "\u{1D60C}"=>"E".freeze, "\u{1D60D}"=>"F".freeze, "\u{1D60E}"=>"G".freeze, "\u{1D60F}"=>"H".freeze, "\u{1D610}"=>"I".freeze, "\u{1D611}"=>"J".freeze, "\u{1D612}"=>"K".freeze, "\u{1D613}"=>"L".freeze, "\u{1D614}"=>"M".freeze, "\u{1D615}"=>"N".freeze, "\u{1D616}"=>"O".freeze, "\u{1D617}"=>"P".freeze, "\u{1D618}"=>"Q".freeze, "\u{1D619}"=>"R".freeze, "\u{1D61A}"=>"S".freeze, "\u{1D61B}"=>"T".freeze, "\u{1D61C}"=>"U".freeze, "\u{1D61D}"=>"V".freeze, "\u{1D61E}"=>"W".freeze, "\u{1D61F}"=>"X".freeze, "\u{1D620}"=>"Y".freeze, "\u{1D621}"=>"Z".freeze, "\u{1D622}"=>"a".freeze, "\u{1D623}"=>"b".freeze, "\u{1D624}"=>"c".freeze, "\u{1D625}"=>"d".freeze, "\u{1D626}"=>"e".freeze, "\u{1D627}"=>"f".freeze, "\u{1D628}"=>"g".freeze, "\u{1D629}"=>"h".freeze, "\u{1D62A}"=>"i".freeze, "\u{1D62B}"=>"j".freeze, "\u{1D62C}"=>"k".freeze, "\u{1D62D}"=>"l".freeze, "\u{1D62E}"=>"m".freeze, "\u{1D62F}"=>"n".freeze, "\u{1D630}"=>"o".freeze, "\u{1D631}"=>"p".freeze, "\u{1D632}"=>"q".freeze, "\u{1D633}"=>"r".freeze, "\u{1D634}"=>"s".freeze, "\u{1D635}"=>"t".freeze, "\u{1D636}"=>"u".freeze, "\u{1D637}"=>"v".freeze, "\u{1D638}"=>"w".freeze, "\u{1D639}"=>"x".freeze, "\u{1D63A}"=>"y".freeze, "\u{1D63B}"=>"z".freeze, "\u{1D63C}"=>"A".freeze, "\u{1D63D}"=>"B".freeze, "\u{1D63E}"=>"C".freeze, "\u{1D63F}"=>"D".freeze, "\u{1D640}"=>"E".freeze, "\u{1D641}"=>"F".freeze, "\u{1D642}"=>"G".freeze, "\u{1D643}"=>"H".freeze, "\u{1D644}"=>"I".freeze, "\u{1D645}"=>"J".freeze, "\u{1D646}"=>"K".freeze, "\u{1D647}"=>"L".freeze, "\u{1D648}"=>"M".freeze, "\u{1D649}"=>"N".freeze, "\u{1D64A}"=>"O".freeze, "\u{1D64B}"=>"P".freeze, "\u{1D64C}"=>"Q".freeze, "\u{1D64D}"=>"R".freeze, "\u{1D64E}"=>"S".freeze, "\u{1D64F}"=>"T".freeze, "\u{1D650}"=>"U".freeze, "\u{1D651}"=>"V".freeze, "\u{1D652}"=>"W".freeze, "\u{1D653}"=>"X".freeze, "\u{1D654}"=>"Y".freeze, "\u{1D655}"=>"Z".freeze, "\u{1D656}"=>"a".freeze, "\u{1D657}"=>"b".freeze, "\u{1D658}"=>"c".freeze, "\u{1D659}"=>"d".freeze, "\u{1D65A}"=>"e".freeze, "\u{1D65B}"=>"f".freeze, "\u{1D65C}"=>"g".freeze, "\u{1D65D}"=>"h".freeze, "\u{1D65E}"=>"i".freeze, "\u{1D65F}"=>"j".freeze, "\u{1D660}"=>"k".freeze, "\u{1D661}"=>"l".freeze, "\u{1D662}"=>"m".freeze, "\u{1D663}"=>"n".freeze, "\u{1D664}"=>"o".freeze, "\u{1D665}"=>"p".freeze, "\u{1D666}"=>"q".freeze, "\u{1D667}"=>"r".freeze, "\u{1D668}"=>"s".freeze, "\u{1D669}"=>"t".freeze, "\u{1D66A}"=>"u".freeze, "\u{1D66B}"=>"v".freeze, "\u{1D66C}"=>"w".freeze, "\u{1D66D}"=>"x".freeze, "\u{1D66E}"=>"y".freeze, "\u{1D66F}"=>"z".freeze, "\u{1D670}"=>"A".freeze, "\u{1D671}"=>"B".freeze, "\u{1D672}"=>"C".freeze, "\u{1D673}"=>"D".freeze, "\u{1D674}"=>"E".freeze, "\u{1D675}"=>"F".freeze, "\u{1D676}"=>"G".freeze, "\u{1D677}"=>"H".freeze, "\u{1D678}"=>"I".freeze, "\u{1D679}"=>"J".freeze, "\u{1D67A}"=>"K".freeze, "\u{1D67B}"=>"L".freeze, "\u{1D67C}"=>"M".freeze, "\u{1D67D}"=>"N".freeze, "\u{1D67E}"=>"O".freeze, "\u{1D67F}"=>"P".freeze, "\u{1D680}"=>"Q".freeze, "\u{1D681}"=>"R".freeze, "\u{1D682}"=>"S".freeze, "\u{1D683}"=>"T".freeze, "\u{1D684}"=>"U".freeze, "\u{1D685}"=>"V".freeze, "\u{1D686}"=>"W".freeze, "\u{1D687}"=>"X".freeze, "\u{1D688}"=>"Y".freeze, "\u{1D689}"=>"Z".freeze, "\u{1D68A}"=>"a".freeze, "\u{1D68B}"=>"b".freeze, "\u{1D68C}"=>"c".freeze, "\u{1D68D}"=>"d".freeze, "\u{1D68E}"=>"e".freeze, "\u{1D68F}"=>"f".freeze, "\u{1D690}"=>"g".freeze, "\u{1D691}"=>"h".freeze, "\u{1D692}"=>"i".freeze, "\u{1D693}"=>"j".freeze, "\u{1D694}"=>"k".freeze, "\u{1D695}"=>"l".freeze, "\u{1D696}"=>"m".freeze, "\u{1D697}"=>"n".freeze, "\u{1D698}"=>"o".freeze, "\u{1D699}"=>"p".freeze, "\u{1D69A}"=>"q".freeze, "\u{1D69B}"=>"r".freeze, "\u{1D69C}"=>"s".freeze, "\u{1D69D}"=>"t".freeze, "\u{1D69E}"=>"u".freeze, "\u{1D69F}"=>"v".freeze, "\u{1D6A0}"=>"w".freeze, "\u{1D6A1}"=>"x".freeze, "\u{1D6A2}"=>"y".freeze, "\u{1D6A3}"=>"z".freeze, "\u{1D6A4}"=>"\u0131".freeze, "\u{1D6A5}"=>"\u0237".freeze, "\u{1D6A8}"=>"\u0391".freeze, "\u{1D6A9}"=>"\u0392".freeze, "\u{1D6AA}"=>"\u0393".freeze, "\u{1D6AB}"=>"\u0394".freeze, "\u{1D6AC}"=>"\u0395".freeze, "\u{1D6AD}"=>"\u0396".freeze, "\u{1D6AE}"=>"\u0397".freeze, "\u{1D6AF}"=>"\u0398".freeze, "\u{1D6B0}"=>"\u0399".freeze, "\u{1D6B1}"=>"\u039A".freeze, "\u{1D6B2}"=>"\u039B".freeze, "\u{1D6B3}"=>"\u039C".freeze, "\u{1D6B4}"=>"\u039D".freeze, "\u{1D6B5}"=>"\u039E".freeze, "\u{1D6B6}"=>"\u039F".freeze, "\u{1D6B7}"=>"\u03A0".freeze, "\u{1D6B8}"=>"\u03A1".freeze, "\u{1D6B9}"=>"\u0398".freeze, "\u{1D6BA}"=>"\u03A3".freeze, "\u{1D6BB}"=>"\u03A4".freeze, "\u{1D6BC}"=>"\u03A5".freeze, "\u{1D6BD}"=>"\u03A6".freeze, "\u{1D6BE}"=>"\u03A7".freeze, "\u{1D6BF}"=>"\u03A8".freeze, "\u{1D6C0}"=>"\u03A9".freeze, "\u{1D6C1}"=>"\u2207".freeze, "\u{1D6C2}"=>"\u03B1".freeze, "\u{1D6C3}"=>"\u03B2".freeze, "\u{1D6C4}"=>"\u03B3".freeze, "\u{1D6C5}"=>"\u03B4".freeze, "\u{1D6C6}"=>"\u03B5".freeze, "\u{1D6C7}"=>"\u03B6".freeze, "\u{1D6C8}"=>"\u03B7".freeze, "\u{1D6C9}"=>"\u03B8".freeze, "\u{1D6CA}"=>"\u03B9".freeze, "\u{1D6CB}"=>"\u03BA".freeze, "\u{1D6CC}"=>"\u03BB".freeze, "\u{1D6CD}"=>"\u03BC".freeze, "\u{1D6CE}"=>"\u03BD".freeze, "\u{1D6CF}"=>"\u03BE".freeze, "\u{1D6D0}"=>"\u03BF".freeze, "\u{1D6D1}"=>"\u03C0".freeze, "\u{1D6D2}"=>"\u03C1".freeze, "\u{1D6D3}"=>"\u03C2".freeze, "\u{1D6D4}"=>"\u03C3".freeze, "\u{1D6D5}"=>"\u03C4".freeze, "\u{1D6D6}"=>"\u03C5".freeze, "\u{1D6D7}"=>"\u03C6".freeze, "\u{1D6D8}"=>"\u03C7".freeze, "\u{1D6D9}"=>"\u03C8".freeze, "\u{1D6DA}"=>"\u03C9".freeze, "\u{1D6DB}"=>"\u2202".freeze, "\u{1D6DC}"=>"\u03B5".freeze, "\u{1D6DD}"=>"\u03B8".freeze, "\u{1D6DE}"=>"\u03BA".freeze, "\u{1D6DF}"=>"\u03C6".freeze, "\u{1D6E0}"=>"\u03C1".freeze, "\u{1D6E1}"=>"\u03C0".freeze, "\u{1D6E2}"=>"\u0391".freeze, "\u{1D6E3}"=>"\u0392".freeze, "\u{1D6E4}"=>"\u0393".freeze, "\u{1D6E5}"=>"\u0394".freeze, "\u{1D6E6}"=>"\u0395".freeze, "\u{1D6E7}"=>"\u0396".freeze, "\u{1D6E8}"=>"\u0397".freeze, "\u{1D6E9}"=>"\u0398".freeze, "\u{1D6EA}"=>"\u0399".freeze, "\u{1D6EB}"=>"\u039A".freeze, "\u{1D6EC}"=>"\u039B".freeze, "\u{1D6ED}"=>"\u039C".freeze, "\u{1D6EE}"=>"\u039D".freeze, "\u{1D6EF}"=>"\u039E".freeze, "\u{1D6F0}"=>"\u039F".freeze, "\u{1D6F1}"=>"\u03A0".freeze, "\u{1D6F2}"=>"\u03A1".freeze, "\u{1D6F3}"=>"\u0398".freeze, "\u{1D6F4}"=>"\u03A3".freeze, "\u{1D6F5}"=>"\u03A4".freeze, "\u{1D6F6}"=>"\u03A5".freeze, "\u{1D6F7}"=>"\u03A6".freeze, "\u{1D6F8}"=>"\u03A7".freeze, "\u{1D6F9}"=>"\u03A8".freeze, "\u{1D6FA}"=>"\u03A9".freeze, "\u{1D6FB}"=>"\u2207".freeze, "\u{1D6FC}"=>"\u03B1".freeze, "\u{1D6FD}"=>"\u03B2".freeze, "\u{1D6FE}"=>"\u03B3".freeze, "\u{1D6FF}"=>"\u03B4".freeze, "\u{1D700}"=>"\u03B5".freeze, "\u{1D701}"=>"\u03B6".freeze, "\u{1D702}"=>"\u03B7".freeze, "\u{1D703}"=>"\u03B8".freeze, "\u{1D704}"=>"\u03B9".freeze, "\u{1D705}"=>"\u03BA".freeze, "\u{1D706}"=>"\u03BB".freeze, "\u{1D707}"=>"\u03BC".freeze, "\u{1D708}"=>"\u03BD".freeze, "\u{1D709}"=>"\u03BE".freeze, "\u{1D70A}"=>"\u03BF".freeze, "\u{1D70B}"=>"\u03C0".freeze, "\u{1D70C}"=>"\u03C1".freeze, "\u{1D70D}"=>"\u03C2".freeze, "\u{1D70E}"=>"\u03C3".freeze, "\u{1D70F}"=>"\u03C4".freeze, "\u{1D710}"=>"\u03C5".freeze, "\u{1D711}"=>"\u03C6".freeze, "\u{1D712}"=>"\u03C7".freeze, "\u{1D713}"=>"\u03C8".freeze, "\u{1D714}"=>"\u03C9".freeze, "\u{1D715}"=>"\u2202".freeze, "\u{1D716}"=>"\u03B5".freeze, "\u{1D717}"=>"\u03B8".freeze, "\u{1D718}"=>"\u03BA".freeze, "\u{1D719}"=>"\u03C6".freeze, "\u{1D71A}"=>"\u03C1".freeze, "\u{1D71B}"=>"\u03C0".freeze, "\u{1D71C}"=>"\u0391".freeze, "\u{1D71D}"=>"\u0392".freeze, "\u{1D71E}"=>"\u0393".freeze, "\u{1D71F}"=>"\u0394".freeze, "\u{1D720}"=>"\u0395".freeze, "\u{1D721}"=>"\u0396".freeze, "\u{1D722}"=>"\u0397".freeze, "\u{1D723}"=>"\u0398".freeze, "\u{1D724}"=>"\u0399".freeze, "\u{1D725}"=>"\u039A".freeze, "\u{1D726}"=>"\u039B".freeze, "\u{1D727}"=>"\u039C".freeze, "\u{1D728}"=>"\u039D".freeze, "\u{1D729}"=>"\u039E".freeze, "\u{1D72A}"=>"\u039F".freeze, "\u{1D72B}"=>"\u03A0".freeze, "\u{1D72C}"=>"\u03A1".freeze, "\u{1D72D}"=>"\u0398".freeze, "\u{1D72E}"=>"\u03A3".freeze, "\u{1D72F}"=>"\u03A4".freeze, "\u{1D730}"=>"\u03A5".freeze, "\u{1D731}"=>"\u03A6".freeze, "\u{1D732}"=>"\u03A7".freeze, "\u{1D733}"=>"\u03A8".freeze, "\u{1D734}"=>"\u03A9".freeze, "\u{1D735}"=>"\u2207".freeze, "\u{1D736}"=>"\u03B1".freeze, "\u{1D737}"=>"\u03B2".freeze, "\u{1D738}"=>"\u03B3".freeze, "\u{1D739}"=>"\u03B4".freeze, "\u{1D73A}"=>"\u03B5".freeze, "\u{1D73B}"=>"\u03B6".freeze, "\u{1D73C}"=>"\u03B7".freeze, "\u{1D73D}"=>"\u03B8".freeze, "\u{1D73E}"=>"\u03B9".freeze, "\u{1D73F}"=>"\u03BA".freeze, "\u{1D740}"=>"\u03BB".freeze, "\u{1D741}"=>"\u03BC".freeze, "\u{1D742}"=>"\u03BD".freeze, "\u{1D743}"=>"\u03BE".freeze, "\u{1D744}"=>"\u03BF".freeze, "\u{1D745}"=>"\u03C0".freeze, "\u{1D746}"=>"\u03C1".freeze, "\u{1D747}"=>"\u03C2".freeze, "\u{1D748}"=>"\u03C3".freeze, "\u{1D749}"=>"\u03C4".freeze, "\u{1D74A}"=>"\u03C5".freeze, "\u{1D74B}"=>"\u03C6".freeze, "\u{1D74C}"=>"\u03C7".freeze, "\u{1D74D}"=>"\u03C8".freeze, "\u{1D74E}"=>"\u03C9".freeze, "\u{1D74F}"=>"\u2202".freeze, "\u{1D750}"=>"\u03B5".freeze, "\u{1D751}"=>"\u03B8".freeze, "\u{1D752}"=>"\u03BA".freeze, "\u{1D753}"=>"\u03C6".freeze, "\u{1D754}"=>"\u03C1".freeze, "\u{1D755}"=>"\u03C0".freeze, "\u{1D756}"=>"\u0391".freeze, "\u{1D757}"=>"\u0392".freeze, "\u{1D758}"=>"\u0393".freeze, "\u{1D759}"=>"\u0394".freeze, "\u{1D75A}"=>"\u0395".freeze, "\u{1D75B}"=>"\u0396".freeze, "\u{1D75C}"=>"\u0397".freeze, "\u{1D75D}"=>"\u0398".freeze, "\u{1D75E}"=>"\u0399".freeze, "\u{1D75F}"=>"\u039A".freeze, "\u{1D760}"=>"\u039B".freeze, "\u{1D761}"=>"\u039C".freeze, "\u{1D762}"=>"\u039D".freeze, "\u{1D763}"=>"\u039E".freeze, "\u{1D764}"=>"\u039F".freeze, "\u{1D765}"=>"\u03A0".freeze, "\u{1D766}"=>"\u03A1".freeze, "\u{1D767}"=>"\u0398".freeze, "\u{1D768}"=>"\u03A3".freeze, "\u{1D769}"=>"\u03A4".freeze, "\u{1D76A}"=>"\u03A5".freeze, "\u{1D76B}"=>"\u03A6".freeze, "\u{1D76C}"=>"\u03A7".freeze, "\u{1D76D}"=>"\u03A8".freeze, "\u{1D76E}"=>"\u03A9".freeze, "\u{1D76F}"=>"\u2207".freeze, "\u{1D770}"=>"\u03B1".freeze, "\u{1D771}"=>"\u03B2".freeze, "\u{1D772}"=>"\u03B3".freeze, "\u{1D773}"=>"\u03B4".freeze, "\u{1D774}"=>"\u03B5".freeze, "\u{1D775}"=>"\u03B6".freeze, "\u{1D776}"=>"\u03B7".freeze, "\u{1D777}"=>"\u03B8".freeze, "\u{1D778}"=>"\u03B9".freeze, "\u{1D779}"=>"\u03BA".freeze, "\u{1D77A}"=>"\u03BB".freeze, "\u{1D77B}"=>"\u03BC".freeze, "\u{1D77C}"=>"\u03BD".freeze, "\u{1D77D}"=>"\u03BE".freeze, "\u{1D77E}"=>"\u03BF".freeze, "\u{1D77F}"=>"\u03C0".freeze, "\u{1D780}"=>"\u03C1".freeze, "\u{1D781}"=>"\u03C2".freeze, "\u{1D782}"=>"\u03C3".freeze, "\u{1D783}"=>"\u03C4".freeze, "\u{1D784}"=>"\u03C5".freeze, "\u{1D785}"=>"\u03C6".freeze, "\u{1D786}"=>"\u03C7".freeze, "\u{1D787}"=>"\u03C8".freeze, "\u{1D788}"=>"\u03C9".freeze, "\u{1D789}"=>"\u2202".freeze, "\u{1D78A}"=>"\u03B5".freeze, "\u{1D78B}"=>"\u03B8".freeze, "\u{1D78C}"=>"\u03BA".freeze, "\u{1D78D}"=>"\u03C6".freeze, "\u{1D78E}"=>"\u03C1".freeze, "\u{1D78F}"=>"\u03C0".freeze, "\u{1D790}"=>"\u0391".freeze, "\u{1D791}"=>"\u0392".freeze, "\u{1D792}"=>"\u0393".freeze, "\u{1D793}"=>"\u0394".freeze, "\u{1D794}"=>"\u0395".freeze, "\u{1D795}"=>"\u0396".freeze, "\u{1D796}"=>"\u0397".freeze, "\u{1D797}"=>"\u0398".freeze, "\u{1D798}"=>"\u0399".freeze, "\u{1D799}"=>"\u039A".freeze, "\u{1D79A}"=>"\u039B".freeze, "\u{1D79B}"=>"\u039C".freeze, "\u{1D79C}"=>"\u039D".freeze, "\u{1D79D}"=>"\u039E".freeze, "\u{1D79E}"=>"\u039F".freeze, "\u{1D79F}"=>"\u03A0".freeze, "\u{1D7A0}"=>"\u03A1".freeze, "\u{1D7A1}"=>"\u0398".freeze, "\u{1D7A2}"=>"\u03A3".freeze, "\u{1D7A3}"=>"\u03A4".freeze, "\u{1D7A4}"=>"\u03A5".freeze, "\u{1D7A5}"=>"\u03A6".freeze, "\u{1D7A6}"=>"\u03A7".freeze, "\u{1D7A7}"=>"\u03A8".freeze, "\u{1D7A8}"=>"\u03A9".freeze, "\u{1D7A9}"=>"\u2207".freeze, "\u{1D7AA}"=>"\u03B1".freeze, "\u{1D7AB}"=>"\u03B2".freeze, "\u{1D7AC}"=>"\u03B3".freeze, "\u{1D7AD}"=>"\u03B4".freeze, "\u{1D7AE}"=>"\u03B5".freeze, "\u{1D7AF}"=>"\u03B6".freeze, "\u{1D7B0}"=>"\u03B7".freeze, "\u{1D7B1}"=>"\u03B8".freeze, "\u{1D7B2}"=>"\u03B9".freeze, "\u{1D7B3}"=>"\u03BA".freeze, "\u{1D7B4}"=>"\u03BB".freeze, "\u{1D7B5}"=>"\u03BC".freeze, "\u{1D7B6}"=>"\u03BD".freeze, "\u{1D7B7}"=>"\u03BE".freeze, "\u{1D7B8}"=>"\u03BF".freeze, "\u{1D7B9}"=>"\u03C0".freeze, "\u{1D7BA}"=>"\u03C1".freeze, "\u{1D7BB}"=>"\u03C2".freeze, "\u{1D7BC}"=>"\u03C3".freeze, "\u{1D7BD}"=>"\u03C4".freeze, "\u{1D7BE}"=>"\u03C5".freeze, "\u{1D7BF}"=>"\u03C6".freeze, "\u{1D7C0}"=>"\u03C7".freeze, "\u{1D7C1}"=>"\u03C8".freeze, "\u{1D7C2}"=>"\u03C9".freeze, "\u{1D7C3}"=>"\u2202".freeze, "\u{1D7C4}"=>"\u03B5".freeze, "\u{1D7C5}"=>"\u03B8".freeze, "\u{1D7C6}"=>"\u03BA".freeze, "\u{1D7C7}"=>"\u03C6".freeze, "\u{1D7C8}"=>"\u03C1".freeze, "\u{1D7C9}"=>"\u03C0".freeze, "\u{1D7CA}"=>"\u03DC".freeze, "\u{1D7CB}"=>"\u03DD".freeze, "\u{1D7CE}"=>"0".freeze, "\u{1D7CF}"=>"1".freeze, "\u{1D7D0}"=>"2".freeze, "\u{1D7D1}"=>"3".freeze, "\u{1D7D2}"=>"4".freeze, "\u{1D7D3}"=>"5".freeze, "\u{1D7D4}"=>"6".freeze, "\u{1D7D5}"=>"7".freeze, "\u{1D7D6}"=>"8".freeze, "\u{1D7D7}"=>"9".freeze, "\u{1D7D8}"=>"0".freeze, "\u{1D7D9}"=>"1".freeze, "\u{1D7DA}"=>"2".freeze, "\u{1D7DB}"=>"3".freeze, "\u{1D7DC}"=>"4".freeze, "\u{1D7DD}"=>"5".freeze, "\u{1D7DE}"=>"6".freeze, "\u{1D7DF}"=>"7".freeze, "\u{1D7E0}"=>"8".freeze, "\u{1D7E1}"=>"9".freeze, "\u{1D7E2}"=>"0".freeze, "\u{1D7E3}"=>"1".freeze, "\u{1D7E4}"=>"2".freeze, "\u{1D7E5}"=>"3".freeze, "\u{1D7E6}"=>"4".freeze, "\u{1D7E7}"=>"5".freeze, "\u{1D7E8}"=>"6".freeze, "\u{1D7E9}"=>"7".freeze, "\u{1D7EA}"=>"8".freeze, "\u{1D7EB}"=>"9".freeze, "\u{1D7EC}"=>"0".freeze, "\u{1D7ED}"=>"1".freeze, "\u{1D7EE}"=>"2".freeze, "\u{1D7EF}"=>"3".freeze, "\u{1D7F0}"=>"4".freeze, "\u{1D7F1}"=>"5".freeze, "\u{1D7F2}"=>"6".freeze, "\u{1D7F3}"=>"7".freeze, "\u{1D7F4}"=>"8".freeze, "\u{1D7F5}"=>"9".freeze, "\u{1D7F6}"=>"0".freeze, "\u{1D7F7}"=>"1".freeze, "\u{1D7F8}"=>"2".freeze, "\u{1D7F9}"=>"3".freeze, "\u{1D7FA}"=>"4".freeze, "\u{1D7FB}"=>"5".freeze, "\u{1D7FC}"=>"6".freeze, "\u{1D7FD}"=>"7".freeze, "\u{1D7FE}"=>"8".freeze, "\u{1D7FF}"=>"9".freeze, "\u{1EE00}"=>"\u0627".freeze, "\u{1EE01}"=>"\u0628".freeze, "\u{1EE02}"=>"\u062C".freeze, "\u{1EE03}"=>"\u062F".freeze, "\u{1EE05}"=>"\u0648".freeze, "\u{1EE06}"=>"\u0632".freeze, "\u{1EE07}"=>"\u062D".freeze, "\u{1EE08}"=>"\u0637".freeze, "\u{1EE09}"=>"\u064A".freeze, "\u{1EE0A}"=>"\u0643".freeze, "\u{1EE0B}"=>"\u0644".freeze, "\u{1EE0C}"=>"\u0645".freeze, "\u{1EE0D}"=>"\u0646".freeze, "\u{1EE0E}"=>"\u0633".freeze, "\u{1EE0F}"=>"\u0639".freeze, "\u{1EE10}"=>"\u0641".freeze, "\u{1EE11}"=>"\u0635".freeze, "\u{1EE12}"=>"\u0642".freeze, "\u{1EE13}"=>"\u0631".freeze, "\u{1EE14}"=>"\u0634".freeze, "\u{1EE15}"=>"\u062A".freeze, "\u{1EE16}"=>"\u062B".freeze, "\u{1EE17}"=>"\u062E".freeze, "\u{1EE18}"=>"\u0630".freeze, "\u{1EE19}"=>"\u0636".freeze, "\u{1EE1A}"=>"\u0638".freeze, "\u{1EE1B}"=>"\u063A".freeze, "\u{1EE1C}"=>"\u066E".freeze, "\u{1EE1D}"=>"\u06BA".freeze, "\u{1EE1E}"=>"\u06A1".freeze, "\u{1EE1F}"=>"\u066F".freeze, "\u{1EE21}"=>"\u0628".freeze, "\u{1EE22}"=>"\u062C".freeze, "\u{1EE24}"=>"\u0647".freeze, "\u{1EE27}"=>"\u062D".freeze, "\u{1EE29}"=>"\u064A".freeze, "\u{1EE2A}"=>"\u0643".freeze, "\u{1EE2B}"=>"\u0644".freeze, "\u{1EE2C}"=>"\u0645".freeze, "\u{1EE2D}"=>"\u0646".freeze, "\u{1EE2E}"=>"\u0633".freeze, "\u{1EE2F}"=>"\u0639".freeze, "\u{1EE30}"=>"\u0641".freeze, "\u{1EE31}"=>"\u0635".freeze, "\u{1EE32}"=>"\u0642".freeze, "\u{1EE34}"=>"\u0634".freeze, "\u{1EE35}"=>"\u062A".freeze, "\u{1EE36}"=>"\u062B".freeze, "\u{1EE37}"=>"\u062E".freeze, "\u{1EE39}"=>"\u0636".freeze, "\u{1EE3B}"=>"\u063A".freeze, "\u{1EE42}"=>"\u062C".freeze, "\u{1EE47}"=>"\u062D".freeze, "\u{1EE49}"=>"\u064A".freeze, "\u{1EE4B}"=>"\u0644".freeze, "\u{1EE4D}"=>"\u0646".freeze, "\u{1EE4E}"=>"\u0633".freeze, "\u{1EE4F}"=>"\u0639".freeze, "\u{1EE51}"=>"\u0635".freeze, "\u{1EE52}"=>"\u0642".freeze, "\u{1EE54}"=>"\u0634".freeze, "\u{1EE57}"=>"\u062E".freeze, "\u{1EE59}"=>"\u0636".freeze, "\u{1EE5B}"=>"\u063A".freeze, "\u{1EE5D}"=>"\u06BA".freeze, "\u{1EE5F}"=>"\u066F".freeze, "\u{1EE61}"=>"\u0628".freeze, "\u{1EE62}"=>"\u062C".freeze, "\u{1EE64}"=>"\u0647".freeze, "\u{1EE67}"=>"\u062D".freeze, "\u{1EE68}"=>"\u0637".freeze, "\u{1EE69}"=>"\u064A".freeze, "\u{1EE6A}"=>"\u0643".freeze, "\u{1EE6C}"=>"\u0645".freeze, "\u{1EE6D}"=>"\u0646".freeze, "\u{1EE6E}"=>"\u0633".freeze, "\u{1EE6F}"=>"\u0639".freeze, "\u{1EE70}"=>"\u0641".freeze, "\u{1EE71}"=>"\u0635".freeze, "\u{1EE72}"=>"\u0642".freeze, "\u{1EE74}"=>"\u0634".freeze, "\u{1EE75}"=>"\u062A".freeze, "\u{1EE76}"=>"\u062B".freeze, "\u{1EE77}"=>"\u062E".freeze, "\u{1EE79}"=>"\u0636".freeze, "\u{1EE7A}"=>"\u0638".freeze, "\u{1EE7B}"=>"\u063A".freeze, "\u{1EE7C}"=>"\u066E".freeze, "\u{1EE7E}"=>"\u06A1".freeze, "\u{1EE80}"=>"\u0627".freeze, "\u{1EE81}"=>"\u0628".freeze, "\u{1EE82}"=>"\u062C".freeze, "\u{1EE83}"=>"\u062F".freeze, "\u{1EE84}"=>"\u0647".freeze, "\u{1EE85}"=>"\u0648".freeze, "\u{1EE86}"=>"\u0632".freeze, "\u{1EE87}"=>"\u062D".freeze, "\u{1EE88}"=>"\u0637".freeze, "\u{1EE89}"=>"\u064A".freeze, "\u{1EE8B}"=>"\u0644".freeze, "\u{1EE8C}"=>"\u0645".freeze, "\u{1EE8D}"=>"\u0646".freeze, "\u{1EE8E}"=>"\u0633".freeze, "\u{1EE8F}"=>"\u0639".freeze, "\u{1EE90}"=>"\u0641".freeze, "\u{1EE91}"=>"\u0635".freeze, "\u{1EE92}"=>"\u0642".freeze, "\u{1EE93}"=>"\u0631".freeze, "\u{1EE94}"=>"\u0634".freeze, "\u{1EE95}"=>"\u062A".freeze, "\u{1EE96}"=>"\u062B".freeze, "\u{1EE97}"=>"\u062E".freeze, "\u{1EE98}"=>"\u0630".freeze, "\u{1EE99}"=>"\u0636".freeze, "\u{1EE9A}"=>"\u0638".freeze, "\u{1EE9B}"=>"\u063A".freeze, "\u{1EEA1}"=>"\u0628".freeze, "\u{1EEA2}"=>"\u062C".freeze, "\u{1EEA3}"=>"\u062F".freeze, "\u{1EEA5}"=>"\u0648".freeze, "\u{1EEA6}"=>"\u0632".freeze, "\u{1EEA7}"=>"\u062D".freeze, "\u{1EEA8}"=>"\u0637".freeze, "\u{1EEA9}"=>"\u064A".freeze, "\u{1EEAB}"=>"\u0644".freeze, "\u{1EEAC}"=>"\u0645".freeze, "\u{1EEAD}"=>"\u0646".freeze, "\u{1EEAE}"=>"\u0633".freeze, "\u{1EEAF}"=>"\u0639".freeze, "\u{1EEB0}"=>"\u0641".freeze, "\u{1EEB1}"=>"\u0635".freeze, "\u{1EEB2}"=>"\u0642".freeze, "\u{1EEB3}"=>"\u0631".freeze, "\u{1EEB4}"=>"\u0634".freeze, "\u{1EEB5}"=>"\u062A".freeze, "\u{1EEB6}"=>"\u062B".freeze, "\u{1EEB7}"=>"\u062E".freeze, "\u{1EEB8}"=>"\u0630".freeze, "\u{1EEB9}"=>"\u0636".freeze, "\u{1EEBA}"=>"\u0638".freeze, "\u{1EEBB}"=>"\u063A".freeze, "\u{1F100}"=>"0.".freeze, "\u{1F101}"=>"0,".freeze, "\u{1F102}"=>"1,".freeze, "\u{1F103}"=>"2,".freeze, "\u{1F104}"=>"3,".freeze, "\u{1F105}"=>"4,".freeze, "\u{1F106}"=>"5,".freeze, "\u{1F107}"=>"6,".freeze, "\u{1F108}"=>"7,".freeze, "\u{1F109}"=>"8,".freeze, "\u{1F10A}"=>"9,".freeze, "\u{1F110}"=>"(A)".freeze, "\u{1F111}"=>"(B)".freeze, "\u{1F112}"=>"(C)".freeze, "\u{1F113}"=>"(D)".freeze, "\u{1F114}"=>"(E)".freeze, "\u{1F115}"=>"(F)".freeze, "\u{1F116}"=>"(G)".freeze, "\u{1F117}"=>"(H)".freeze, "\u{1F118}"=>"(I)".freeze, "\u{1F119}"=>"(J)".freeze, "\u{1F11A}"=>"(K)".freeze, "\u{1F11B}"=>"(L)".freeze, "\u{1F11C}"=>"(M)".freeze, "\u{1F11D}"=>"(N)".freeze, "\u{1F11E}"=>"(O)".freeze, "\u{1F11F}"=>"(P)".freeze, "\u{1F120}"=>"(Q)".freeze, "\u{1F121}"=>"(R)".freeze, "\u{1F122}"=>"(S)".freeze, "\u{1F123}"=>"(T)".freeze, "\u{1F124}"=>"(U)".freeze, "\u{1F125}"=>"(V)".freeze, "\u{1F126}"=>"(W)".freeze, "\u{1F127}"=>"(X)".freeze, "\u{1F128}"=>"(Y)".freeze, "\u{1F129}"=>"(Z)".freeze, "\u{1F12A}"=>"\u3014S\u3015".freeze, "\u{1F12B}"=>"C".freeze, "\u{1F12C}"=>"R".freeze, "\u{1F12D}"=>"CD".freeze, "\u{1F12E}"=>"WZ".freeze, "\u{1F130}"=>"A".freeze, "\u{1F131}"=>"B".freeze, "\u{1F132}"=>"C".freeze, "\u{1F133}"=>"D".freeze, "\u{1F134}"=>"E".freeze, "\u{1F135}"=>"F".freeze, "\u{1F136}"=>"G".freeze, "\u{1F137}"=>"H".freeze, "\u{1F138}"=>"I".freeze, "\u{1F139}"=>"J".freeze, "\u{1F13A}"=>"K".freeze, "\u{1F13B}"=>"L".freeze, "\u{1F13C}"=>"M".freeze, "\u{1F13D}"=>"N".freeze, "\u{1F13E}"=>"O".freeze, "\u{1F13F}"=>"P".freeze, "\u{1F140}"=>"Q".freeze, "\u{1F141}"=>"R".freeze, "\u{1F142}"=>"S".freeze, "\u{1F143}"=>"T".freeze, "\u{1F144}"=>"U".freeze, "\u{1F145}"=>"V".freeze, "\u{1F146}"=>"W".freeze, "\u{1F147}"=>"X".freeze, "\u{1F148}"=>"Y".freeze, "\u{1F149}"=>"Z".freeze, "\u{1F14A}"=>"HV".freeze, "\u{1F14B}"=>"MV".freeze, "\u{1F14C}"=>"SD".freeze, "\u{1F14D}"=>"SS".freeze, "\u{1F14E}"=>"PPV".freeze, "\u{1F14F}"=>"WC".freeze, "\u{1F16A}"=>"MC".freeze, "\u{1F16B}"=>"MD".freeze, "\u{1F190}"=>"DJ".freeze, "\u{1F200}"=>"\u307B\u304B".freeze, "\u{1F201}"=>"\u30B3\u30B3".freeze, "\u{1F202}"=>"\u30B5".freeze, "\u{1F210}"=>"\u624B".freeze, "\u{1F211}"=>"\u5B57".freeze, "\u{1F212}"=>"\u53CC".freeze, "\u{1F213}"=>"\u30C7".freeze, "\u{1F214}"=>"\u4E8C".freeze, "\u{1F215}"=>"\u591A".freeze, "\u{1F216}"=>"\u89E3".freeze, "\u{1F217}"=>"\u5929".freeze, "\u{1F218}"=>"\u4EA4".freeze, "\u{1F219}"=>"\u6620".freeze, "\u{1F21A}"=>"\u7121".freeze, "\u{1F21B}"=>"\u6599".freeze, "\u{1F21C}"=>"\u524D".freeze, "\u{1F21D}"=>"\u5F8C".freeze, "\u{1F21E}"=>"\u518D".freeze, "\u{1F21F}"=>"\u65B0".freeze, "\u{1F220}"=>"\u521D".freeze, "\u{1F221}"=>"\u7D42".freeze, "\u{1F222}"=>"\u751F".freeze, "\u{1F223}"=>"\u8CA9".freeze, "\u{1F224}"=>"\u58F0".freeze, "\u{1F225}"=>"\u5439".freeze, "\u{1F226}"=>"\u6F14".freeze, "\u{1F227}"=>"\u6295".freeze, "\u{1F228}"=>"\u6355".freeze, "\u{1F229}"=>"\u4E00".freeze, "\u{1F22A}"=>"\u4E09".freeze, "\u{1F22B}"=>"\u904A".freeze, "\u{1F22C}"=>"\u5DE6".freeze, "\u{1F22D}"=>"\u4E2D".freeze, "\u{1F22E}"=>"\u53F3".freeze, "\u{1F22F}"=>"\u6307".freeze, "\u{1F230}"=>"\u8D70".freeze, "\u{1F231}"=>"\u6253".freeze, "\u{1F232}"=>"\u7981".freeze, "\u{1F233}"=>"\u7A7A".freeze, "\u{1F234}"=>"\u5408".freeze, "\u{1F235}"=>"\u6E80".freeze, "\u{1F236}"=>"\u6709".freeze, "\u{1F237}"=>"\u6708".freeze, "\u{1F238}"=>"\u7533".freeze, "\u{1F239}"=>"\u5272".freeze, "\u{1F23A}"=>"\u55B6".freeze, "\u{1F240}"=>"\u3014\u672C\u3015".freeze, "\u{1F241}"=>"\u3014\u4E09\u3015".freeze, "\u{1F242}"=>"\u3014\u4E8C\u3015".freeze, "\u{1F243}"=>"\u3014\u5B89\u3015".freeze, "\u{1F244}"=>"\u3014\u70B9\u3015".freeze, "\u{1F245}"=>"\u3014\u6253\u3015".freeze, "\u{1F246}"=>"\u3014\u76D7\u3015".freeze, "\u{1F247}"=>"\u3014\u52DD\u3015".freeze, "\u{1F248}"=>"\u3014\u6557\u3015".freeze, "\u{1F250}"=>"\u5F97".freeze, "\u{1F251}"=>"\u53EF".freeze, "\u0385"=>" \u0308\u0301".freeze, "\u03D3"=>"\u03A5\u0301".freeze, "\u03D4"=>"\u03A5\u0308".freeze, "\u1E9B"=>"s\u0307".freeze, "\u1FC1"=>" \u0308\u0342".freeze, "\u1FCD"=>" \u0313\u0300".freeze, "\u1FCE"=>" \u0313\u0301".freeze, "\u1FCF"=>" \u0313\u0342".freeze, "\u1FDD"=>" \u0314\u0300".freeze, "\u1FDE"=>" \u0314\u0301".freeze, "\u1FDF"=>" \u0314\u0342".freeze, "\u1FED"=>" \u0308\u0300".freeze, "\u1FEE"=>" \u0308\u0301".freeze, "\u1FFD"=>" \u0301".freeze, "\u2000"=>" ".freeze, "\u2001"=>" ".freeze, }.freeze COMPOSITION_TABLE = { "A\u0300"=>"\u00C0".freeze, "A\u0301"=>"\u00C1".freeze, "A\u0302"=>"\u00C2".freeze, "A\u0303"=>"\u00C3".freeze, "A\u0308"=>"\u00C4".freeze, "A\u030A"=>"\u00C5".freeze, "C\u0327"=>"\u00C7".freeze, "E\u0300"=>"\u00C8".freeze, "E\u0301"=>"\u00C9".freeze, "E\u0302"=>"\u00CA".freeze, "E\u0308"=>"\u00CB".freeze, "I\u0300"=>"\u00CC".freeze, "I\u0301"=>"\u00CD".freeze, "I\u0302"=>"\u00CE".freeze, "I\u0308"=>"\u00CF".freeze, "N\u0303"=>"\u00D1".freeze, "O\u0300"=>"\u00D2".freeze, "O\u0301"=>"\u00D3".freeze, "O\u0302"=>"\u00D4".freeze, "O\u0303"=>"\u00D5".freeze, "O\u0308"=>"\u00D6".freeze, "U\u0300"=>"\u00D9".freeze, "U\u0301"=>"\u00DA".freeze, "U\u0302"=>"\u00DB".freeze, "U\u0308"=>"\u00DC".freeze, "Y\u0301"=>"\u00DD".freeze, "a\u0300"=>"\u00E0".freeze, "a\u0301"=>"\u00E1".freeze, "a\u0302"=>"\u00E2".freeze, "a\u0303"=>"\u00E3".freeze, "a\u0308"=>"\u00E4".freeze, "a\u030A"=>"\u00E5".freeze, "c\u0327"=>"\u00E7".freeze, "e\u0300"=>"\u00E8".freeze, "e\u0301"=>"\u00E9".freeze, "e\u0302"=>"\u00EA".freeze, "e\u0308"=>"\u00EB".freeze, "i\u0300"=>"\u00EC".freeze, "i\u0301"=>"\u00ED".freeze, "i\u0302"=>"\u00EE".freeze, "i\u0308"=>"\u00EF".freeze, "n\u0303"=>"\u00F1".freeze, "o\u0300"=>"\u00F2".freeze, "o\u0301"=>"\u00F3".freeze, "o\u0302"=>"\u00F4".freeze, "o\u0303"=>"\u00F5".freeze, "o\u0308"=>"\u00F6".freeze, "u\u0300"=>"\u00F9".freeze, "u\u0301"=>"\u00FA".freeze, "u\u0302"=>"\u00FB".freeze, "u\u0308"=>"\u00FC".freeze, "y\u0301"=>"\u00FD".freeze, "y\u0308"=>"\u00FF".freeze, "A\u0304"=>"\u0100".freeze, "a\u0304"=>"\u0101".freeze, "A\u0306"=>"\u0102".freeze, "a\u0306"=>"\u0103".freeze, "A\u0328"=>"\u0104".freeze, "a\u0328"=>"\u0105".freeze, "C\u0301"=>"\u0106".freeze, "c\u0301"=>"\u0107".freeze, "C\u0302"=>"\u0108".freeze, "c\u0302"=>"\u0109".freeze, "C\u0307"=>"\u010A".freeze, "c\u0307"=>"\u010B".freeze, "C\u030C"=>"\u010C".freeze, "c\u030C"=>"\u010D".freeze, "D\u030C"=>"\u010E".freeze, "d\u030C"=>"\u010F".freeze, "E\u0304"=>"\u0112".freeze, "e\u0304"=>"\u0113".freeze, "E\u0306"=>"\u0114".freeze, "e\u0306"=>"\u0115".freeze, "E\u0307"=>"\u0116".freeze, "e\u0307"=>"\u0117".freeze, "E\u0328"=>"\u0118".freeze, "e\u0328"=>"\u0119".freeze, "E\u030C"=>"\u011A".freeze, "e\u030C"=>"\u011B".freeze, "G\u0302"=>"\u011C".freeze, "g\u0302"=>"\u011D".freeze, "G\u0306"=>"\u011E".freeze, "g\u0306"=>"\u011F".freeze, "G\u0307"=>"\u0120".freeze, "g\u0307"=>"\u0121".freeze, "G\u0327"=>"\u0122".freeze, "g\u0327"=>"\u0123".freeze, "H\u0302"=>"\u0124".freeze, "h\u0302"=>"\u0125".freeze, "I\u0303"=>"\u0128".freeze, "i\u0303"=>"\u0129".freeze, "I\u0304"=>"\u012A".freeze, "i\u0304"=>"\u012B".freeze, "I\u0306"=>"\u012C".freeze, "i\u0306"=>"\u012D".freeze, "I\u0328"=>"\u012E".freeze, "i\u0328"=>"\u012F".freeze, "I\u0307"=>"\u0130".freeze, "J\u0302"=>"\u0134".freeze, "j\u0302"=>"\u0135".freeze, "K\u0327"=>"\u0136".freeze, "k\u0327"=>"\u0137".freeze, "L\u0301"=>"\u0139".freeze, "l\u0301"=>"\u013A".freeze, "L\u0327"=>"\u013B".freeze, "l\u0327"=>"\u013C".freeze, "L\u030C"=>"\u013D".freeze, "l\u030C"=>"\u013E".freeze, "N\u0301"=>"\u0143".freeze, "n\u0301"=>"\u0144".freeze, "N\u0327"=>"\u0145".freeze, "n\u0327"=>"\u0146".freeze, "N\u030C"=>"\u0147".freeze, "n\u030C"=>"\u0148".freeze, "O\u0304"=>"\u014C".freeze, "o\u0304"=>"\u014D".freeze, "O\u0306"=>"\u014E".freeze, "o\u0306"=>"\u014F".freeze, "O\u030B"=>"\u0150".freeze, "o\u030B"=>"\u0151".freeze, "R\u0301"=>"\u0154".freeze, "r\u0301"=>"\u0155".freeze, "R\u0327"=>"\u0156".freeze, "r\u0327"=>"\u0157".freeze, "R\u030C"=>"\u0158".freeze, "r\u030C"=>"\u0159".freeze, "S\u0301"=>"\u015A".freeze, "s\u0301"=>"\u015B".freeze, "S\u0302"=>"\u015C".freeze, "s\u0302"=>"\u015D".freeze, "S\u0327"=>"\u015E".freeze, "s\u0327"=>"\u015F".freeze, "S\u030C"=>"\u0160".freeze, "s\u030C"=>"\u0161".freeze, "T\u0327"=>"\u0162".freeze, "t\u0327"=>"\u0163".freeze, "T\u030C"=>"\u0164".freeze, "t\u030C"=>"\u0165".freeze, "U\u0303"=>"\u0168".freeze, "u\u0303"=>"\u0169".freeze, "U\u0304"=>"\u016A".freeze, "u\u0304"=>"\u016B".freeze, "U\u0306"=>"\u016C".freeze, "u\u0306"=>"\u016D".freeze, "U\u030A"=>"\u016E".freeze, "u\u030A"=>"\u016F".freeze, "U\u030B"=>"\u0170".freeze, "u\u030B"=>"\u0171".freeze, "U\u0328"=>"\u0172".freeze, "u\u0328"=>"\u0173".freeze, "W\u0302"=>"\u0174".freeze, "w\u0302"=>"\u0175".freeze, "Y\u0302"=>"\u0176".freeze, "y\u0302"=>"\u0177".freeze, "Y\u0308"=>"\u0178".freeze, "Z\u0301"=>"\u0179".freeze, "z\u0301"=>"\u017A".freeze, "Z\u0307"=>"\u017B".freeze, "z\u0307"=>"\u017C".freeze, "Z\u030C"=>"\u017D".freeze, "z\u030C"=>"\u017E".freeze, "O\u031B"=>"\u01A0".freeze, "o\u031B"=>"\u01A1".freeze, "U\u031B"=>"\u01AF".freeze, "u\u031B"=>"\u01B0".freeze, "A\u030C"=>"\u01CD".freeze, "a\u030C"=>"\u01CE".freeze, "I\u030C"=>"\u01CF".freeze, "i\u030C"=>"\u01D0".freeze, "O\u030C"=>"\u01D1".freeze, "o\u030C"=>"\u01D2".freeze, "U\u030C"=>"\u01D3".freeze, "u\u030C"=>"\u01D4".freeze, "\u00DC\u0304"=>"\u01D5".freeze, "\u00FC\u0304"=>"\u01D6".freeze, "\u00DC\u0301"=>"\u01D7".freeze, "\u00FC\u0301"=>"\u01D8".freeze, "\u00DC\u030C"=>"\u01D9".freeze, "\u00FC\u030C"=>"\u01DA".freeze, "\u00DC\u0300"=>"\u01DB".freeze, "\u00FC\u0300"=>"\u01DC".freeze, "\u00C4\u0304"=>"\u01DE".freeze, "\u00E4\u0304"=>"\u01DF".freeze, "\u0226\u0304"=>"\u01E0".freeze, "\u0227\u0304"=>"\u01E1".freeze, "\u00C6\u0304"=>"\u01E2".freeze, "\u00E6\u0304"=>"\u01E3".freeze, "G\u030C"=>"\u01E6".freeze, "g\u030C"=>"\u01E7".freeze, "K\u030C"=>"\u01E8".freeze, "k\u030C"=>"\u01E9".freeze, "O\u0328"=>"\u01EA".freeze, "o\u0328"=>"\u01EB".freeze, "\u01EA\u0304"=>"\u01EC".freeze, "\u01EB\u0304"=>"\u01ED".freeze, "\u01B7\u030C"=>"\u01EE".freeze, "\u0292\u030C"=>"\u01EF".freeze, "j\u030C"=>"\u01F0".freeze, "G\u0301"=>"\u01F4".freeze, "g\u0301"=>"\u01F5".freeze, "N\u0300"=>"\u01F8".freeze, "n\u0300"=>"\u01F9".freeze, "\u00C5\u0301"=>"\u01FA".freeze, "\u00E5\u0301"=>"\u01FB".freeze, "\u00C6\u0301"=>"\u01FC".freeze, "\u00E6\u0301"=>"\u01FD".freeze, "\u00D8\u0301"=>"\u01FE".freeze, "\u00F8\u0301"=>"\u01FF".freeze, "A\u030F"=>"\u0200".freeze, "a\u030F"=>"\u0201".freeze, "A\u0311"=>"\u0202".freeze, "a\u0311"=>"\u0203".freeze, "E\u030F"=>"\u0204".freeze, "e\u030F"=>"\u0205".freeze, "E\u0311"=>"\u0206".freeze, "e\u0311"=>"\u0207".freeze, "I\u030F"=>"\u0208".freeze, "i\u030F"=>"\u0209".freeze, "I\u0311"=>"\u020A".freeze, "i\u0311"=>"\u020B".freeze, "O\u030F"=>"\u020C".freeze, "o\u030F"=>"\u020D".freeze, "O\u0311"=>"\u020E".freeze, "o\u0311"=>"\u020F".freeze, "R\u030F"=>"\u0210".freeze, "r\u030F"=>"\u0211".freeze, "R\u0311"=>"\u0212".freeze, "r\u0311"=>"\u0213".freeze, "U\u030F"=>"\u0214".freeze, "u\u030F"=>"\u0215".freeze, "U\u0311"=>"\u0216".freeze, "u\u0311"=>"\u0217".freeze, "S\u0326"=>"\u0218".freeze, "s\u0326"=>"\u0219".freeze, "T\u0326"=>"\u021A".freeze, "t\u0326"=>"\u021B".freeze, "H\u030C"=>"\u021E".freeze, "h\u030C"=>"\u021F".freeze, "A\u0307"=>"\u0226".freeze, "a\u0307"=>"\u0227".freeze, "E\u0327"=>"\u0228".freeze, "e\u0327"=>"\u0229".freeze, "\u00D6\u0304"=>"\u022A".freeze, "\u00F6\u0304"=>"\u022B".freeze, "\u00D5\u0304"=>"\u022C".freeze, "\u00F5\u0304"=>"\u022D".freeze, "O\u0307"=>"\u022E".freeze, "o\u0307"=>"\u022F".freeze, "\u022E\u0304"=>"\u0230".freeze, "\u022F\u0304"=>"\u0231".freeze, "Y\u0304"=>"\u0232".freeze, "y\u0304"=>"\u0233".freeze, "\u00A8\u0301"=>"\u0385".freeze, "\u0391\u0301"=>"\u0386".freeze, "\u0395\u0301"=>"\u0388".freeze, "\u0397\u0301"=>"\u0389".freeze, "\u0399\u0301"=>"\u038A".freeze, "\u039F\u0301"=>"\u038C".freeze, "\u03A5\u0301"=>"\u038E".freeze, "\u03A9\u0301"=>"\u038F".freeze, "\u03CA\u0301"=>"\u0390".freeze, "\u0399\u0308"=>"\u03AA".freeze, "\u03A5\u0308"=>"\u03AB".freeze, "\u03B1\u0301"=>"\u03AC".freeze, "\u03B5\u0301"=>"\u03AD".freeze, "\u03B7\u0301"=>"\u03AE".freeze, "\u03B9\u0301"=>"\u03AF".freeze, "\u03CB\u0301"=>"\u03B0".freeze, "\u03B9\u0308"=>"\u03CA".freeze, "\u03C5\u0308"=>"\u03CB".freeze, "\u03BF\u0301"=>"\u03CC".freeze, "\u03C5\u0301"=>"\u03CD".freeze, "\u03C9\u0301"=>"\u03CE".freeze, "\u03D2\u0301"=>"\u03D3".freeze, "\u03D2\u0308"=>"\u03D4".freeze, "\u0415\u0300"=>"\u0400".freeze, "\u0415\u0308"=>"\u0401".freeze, "\u0413\u0301"=>"\u0403".freeze, "\u0406\u0308"=>"\u0407".freeze, "\u041A\u0301"=>"\u040C".freeze, "\u0418\u0300"=>"\u040D".freeze, "\u0423\u0306"=>"\u040E".freeze, "\u0418\u0306"=>"\u0419".freeze, "\u0438\u0306"=>"\u0439".freeze, "\u0435\u0300"=>"\u0450".freeze, "\u0435\u0308"=>"\u0451".freeze, "\u0433\u0301"=>"\u0453".freeze, "\u0456\u0308"=>"\u0457".freeze, "\u043A\u0301"=>"\u045C".freeze, "\u0438\u0300"=>"\u045D".freeze, "\u0443\u0306"=>"\u045E".freeze, "\u0474\u030F"=>"\u0476".freeze, "\u0475\u030F"=>"\u0477".freeze, "\u0416\u0306"=>"\u04C1".freeze, "\u0436\u0306"=>"\u04C2".freeze, "\u0410\u0306"=>"\u04D0".freeze, "\u0430\u0306"=>"\u04D1".freeze, "\u0410\u0308"=>"\u04D2".freeze, "\u0430\u0308"=>"\u04D3".freeze, "\u0415\u0306"=>"\u04D6".freeze, "\u0435\u0306"=>"\u04D7".freeze, "\u04D8\u0308"=>"\u04DA".freeze, "\u04D9\u0308"=>"\u04DB".freeze, "\u0416\u0308"=>"\u04DC".freeze, "\u0436\u0308"=>"\u04DD".freeze, "\u0417\u0308"=>"\u04DE".freeze, "\u0437\u0308"=>"\u04DF".freeze, "\u0418\u0304"=>"\u04E2".freeze, "\u0438\u0304"=>"\u04E3".freeze, "\u0418\u0308"=>"\u04E4".freeze, "\u0438\u0308"=>"\u04E5".freeze, "\u041E\u0308"=>"\u04E6".freeze, "\u043E\u0308"=>"\u04E7".freeze, "\u04E8\u0308"=>"\u04EA".freeze, "\u04E9\u0308"=>"\u04EB".freeze, "\u042D\u0308"=>"\u04EC".freeze, "\u044D\u0308"=>"\u04ED".freeze, "\u0423\u0304"=>"\u04EE".freeze, "\u0443\u0304"=>"\u04EF".freeze, "\u0423\u0308"=>"\u04F0".freeze, "\u0443\u0308"=>"\u04F1".freeze, "\u0423\u030B"=>"\u04F2".freeze, "\u0443\u030B"=>"\u04F3".freeze, "\u0427\u0308"=>"\u04F4".freeze, "\u0447\u0308"=>"\u04F5".freeze, "\u042B\u0308"=>"\u04F8".freeze, "\u044B\u0308"=>"\u04F9".freeze, "\u0627\u0653"=>"\u0622".freeze, "\u0627\u0654"=>"\u0623".freeze, "\u0648\u0654"=>"\u0624".freeze, "\u0627\u0655"=>"\u0625".freeze, "\u064A\u0654"=>"\u0626".freeze, "\u06D5\u0654"=>"\u06C0".freeze, "\u06C1\u0654"=>"\u06C2".freeze, "\u06D2\u0654"=>"\u06D3".freeze, "\u0928\u093C"=>"\u0929".freeze, "\u0930\u093C"=>"\u0931".freeze, "\u0933\u093C"=>"\u0934".freeze, "\u09C7\u09BE"=>"\u09CB".freeze, "\u09C7\u09D7"=>"\u09CC".freeze, "\u0B47\u0B56"=>"\u0B48".freeze, "\u0B47\u0B3E"=>"\u0B4B".freeze, "\u0B47\u0B57"=>"\u0B4C".freeze, "\u0B92\u0BD7"=>"\u0B94".freeze, "\u0BC6\u0BBE"=>"\u0BCA".freeze, "\u0BC7\u0BBE"=>"\u0BCB".freeze, "\u0BC6\u0BD7"=>"\u0BCC".freeze, "\u0C46\u0C56"=>"\u0C48".freeze, "\u0CBF\u0CD5"=>"\u0CC0".freeze, "\u0CC6\u0CD5"=>"\u0CC7".freeze, "\u0CC6\u0CD6"=>"\u0CC8".freeze, "\u0CC6\u0CC2"=>"\u0CCA".freeze, "\u0CCA\u0CD5"=>"\u0CCB".freeze, "\u0D46\u0D3E"=>"\u0D4A".freeze, "\u0D47\u0D3E"=>"\u0D4B".freeze, "\u0D46\u0D57"=>"\u0D4C".freeze, "\u0DD9\u0DCA"=>"\u0DDA".freeze, "\u0DD9\u0DCF"=>"\u0DDC".freeze, "\u0DDC\u0DCA"=>"\u0DDD".freeze, "\u0DD9\u0DDF"=>"\u0DDE".freeze, "\u1025\u102E"=>"\u1026".freeze, "\u1B05\u1B35"=>"\u1B06".freeze, "\u1B07\u1B35"=>"\u1B08".freeze, "\u1B09\u1B35"=>"\u1B0A".freeze, "\u1B0B\u1B35"=>"\u1B0C".freeze, "\u1B0D\u1B35"=>"\u1B0E".freeze, "\u1B11\u1B35"=>"\u1B12".freeze, "\u1B3A\u1B35"=>"\u1B3B".freeze, "\u1B3C\u1B35"=>"\u1B3D".freeze, "\u1B3E\u1B35"=>"\u1B40".freeze, "\u1B3F\u1B35"=>"\u1B41".freeze, "\u1B42\u1B35"=>"\u1B43".freeze, "A\u0325"=>"\u1E00".freeze, "a\u0325"=>"\u1E01".freeze, "B\u0307"=>"\u1E02".freeze, "b\u0307"=>"\u1E03".freeze, "B\u0323"=>"\u1E04".freeze, "b\u0323"=>"\u1E05".freeze, "B\u0331"=>"\u1E06".freeze, "b\u0331"=>"\u1E07".freeze, "\u00C7\u0301"=>"\u1E08".freeze, "\u00E7\u0301"=>"\u1E09".freeze, "D\u0307"=>"\u1E0A".freeze, "d\u0307"=>"\u1E0B".freeze, "D\u0323"=>"\u1E0C".freeze, "d\u0323"=>"\u1E0D".freeze, "D\u0331"=>"\u1E0E".freeze, "d\u0331"=>"\u1E0F".freeze, "D\u0327"=>"\u1E10".freeze, "d\u0327"=>"\u1E11".freeze, "D\u032D"=>"\u1E12".freeze, "d\u032D"=>"\u1E13".freeze, "\u0112\u0300"=>"\u1E14".freeze, "\u0113\u0300"=>"\u1E15".freeze, "\u0112\u0301"=>"\u1E16".freeze, "\u0113\u0301"=>"\u1E17".freeze, "E\u032D"=>"\u1E18".freeze, "e\u032D"=>"\u1E19".freeze, "E\u0330"=>"\u1E1A".freeze, "e\u0330"=>"\u1E1B".freeze, "\u0228\u0306"=>"\u1E1C".freeze, "\u0229\u0306"=>"\u1E1D".freeze, "F\u0307"=>"\u1E1E".freeze, "f\u0307"=>"\u1E1F".freeze, "G\u0304"=>"\u1E20".freeze, "g\u0304"=>"\u1E21".freeze, "H\u0307"=>"\u1E22".freeze, "h\u0307"=>"\u1E23".freeze, "H\u0323"=>"\u1E24".freeze, "h\u0323"=>"\u1E25".freeze, "H\u0308"=>"\u1E26".freeze, "h\u0308"=>"\u1E27".freeze, "H\u0327"=>"\u1E28".freeze, "h\u0327"=>"\u1E29".freeze, "H\u032E"=>"\u1E2A".freeze, "h\u032E"=>"\u1E2B".freeze, "I\u0330"=>"\u1E2C".freeze, "i\u0330"=>"\u1E2D".freeze, "\u00CF\u0301"=>"\u1E2E".freeze, "\u00EF\u0301"=>"\u1E2F".freeze, "K\u0301"=>"\u1E30".freeze, "k\u0301"=>"\u1E31".freeze, "K\u0323"=>"\u1E32".freeze, "k\u0323"=>"\u1E33".freeze, "K\u0331"=>"\u1E34".freeze, "k\u0331"=>"\u1E35".freeze, "L\u0323"=>"\u1E36".freeze, "l\u0323"=>"\u1E37".freeze, "\u1E36\u0304"=>"\u1E38".freeze, "\u1E37\u0304"=>"\u1E39".freeze, "L\u0331"=>"\u1E3A".freeze, "l\u0331"=>"\u1E3B".freeze, "L\u032D"=>"\u1E3C".freeze, "l\u032D"=>"\u1E3D".freeze, "M\u0301"=>"\u1E3E".freeze, "m\u0301"=>"\u1E3F".freeze, "M\u0307"=>"\u1E40".freeze, "m\u0307"=>"\u1E41".freeze, "M\u0323"=>"\u1E42".freeze, "m\u0323"=>"\u1E43".freeze, "N\u0307"=>"\u1E44".freeze, "n\u0307"=>"\u1E45".freeze, "N\u0323"=>"\u1E46".freeze, "n\u0323"=>"\u1E47".freeze, "N\u0331"=>"\u1E48".freeze, "n\u0331"=>"\u1E49".freeze, "N\u032D"=>"\u1E4A".freeze, "n\u032D"=>"\u1E4B".freeze, "\u00D5\u0301"=>"\u1E4C".freeze, "\u00F5\u0301"=>"\u1E4D".freeze, "\u00D5\u0308"=>"\u1E4E".freeze, "\u00F5\u0308"=>"\u1E4F".freeze, "\u014C\u0300"=>"\u1E50".freeze, "\u014D\u0300"=>"\u1E51".freeze, "\u014C\u0301"=>"\u1E52".freeze, "\u014D\u0301"=>"\u1E53".freeze, "P\u0301"=>"\u1E54".freeze, "p\u0301"=>"\u1E55".freeze, "P\u0307"=>"\u1E56".freeze, "p\u0307"=>"\u1E57".freeze, "R\u0307"=>"\u1E58".freeze, "r\u0307"=>"\u1E59".freeze, "R\u0323"=>"\u1E5A".freeze, "r\u0323"=>"\u1E5B".freeze, "\u1E5A\u0304"=>"\u1E5C".freeze, "\u1E5B\u0304"=>"\u1E5D".freeze, "R\u0331"=>"\u1E5E".freeze, "r\u0331"=>"\u1E5F".freeze, "S\u0307"=>"\u1E60".freeze, "s\u0307"=>"\u1E61".freeze, "S\u0323"=>"\u1E62".freeze, "s\u0323"=>"\u1E63".freeze, "\u015A\u0307"=>"\u1E64".freeze, "\u015B\u0307"=>"\u1E65".freeze, "\u0160\u0307"=>"\u1E66".freeze, "\u0161\u0307"=>"\u1E67".freeze, "\u1E62\u0307"=>"\u1E68".freeze, "\u1E63\u0307"=>"\u1E69".freeze, "T\u0307"=>"\u1E6A".freeze, "t\u0307"=>"\u1E6B".freeze, "T\u0323"=>"\u1E6C".freeze, "t\u0323"=>"\u1E6D".freeze, "T\u0331"=>"\u1E6E".freeze, "t\u0331"=>"\u1E6F".freeze, "T\u032D"=>"\u1E70".freeze, "t\u032D"=>"\u1E71".freeze, "U\u0324"=>"\u1E72".freeze, "u\u0324"=>"\u1E73".freeze, "U\u0330"=>"\u1E74".freeze, "u\u0330"=>"\u1E75".freeze, "U\u032D"=>"\u1E76".freeze, "u\u032D"=>"\u1E77".freeze, "\u0168\u0301"=>"\u1E78".freeze, "\u0169\u0301"=>"\u1E79".freeze, "\u016A\u0308"=>"\u1E7A".freeze, "\u016B\u0308"=>"\u1E7B".freeze, "V\u0303"=>"\u1E7C".freeze, "v\u0303"=>"\u1E7D".freeze, "V\u0323"=>"\u1E7E".freeze, "v\u0323"=>"\u1E7F".freeze, "W\u0300"=>"\u1E80".freeze, "w\u0300"=>"\u1E81".freeze, "W\u0301"=>"\u1E82".freeze, "w\u0301"=>"\u1E83".freeze, "W\u0308"=>"\u1E84".freeze, "w\u0308"=>"\u1E85".freeze, "W\u0307"=>"\u1E86".freeze, "w\u0307"=>"\u1E87".freeze, "W\u0323"=>"\u1E88".freeze, "w\u0323"=>"\u1E89".freeze, "X\u0307"=>"\u1E8A".freeze, "x\u0307"=>"\u1E8B".freeze, "X\u0308"=>"\u1E8C".freeze, "x\u0308"=>"\u1E8D".freeze, "Y\u0307"=>"\u1E8E".freeze, "y\u0307"=>"\u1E8F".freeze, "Z\u0302"=>"\u1E90".freeze, "z\u0302"=>"\u1E91".freeze, "Z\u0323"=>"\u1E92".freeze, "z\u0323"=>"\u1E93".freeze, "Z\u0331"=>"\u1E94".freeze, "z\u0331"=>"\u1E95".freeze, "h\u0331"=>"\u1E96".freeze, "t\u0308"=>"\u1E97".freeze, "w\u030A"=>"\u1E98".freeze, "y\u030A"=>"\u1E99".freeze, "\u017F\u0307"=>"\u1E9B".freeze, "A\u0323"=>"\u1EA0".freeze, "a\u0323"=>"\u1EA1".freeze, "A\u0309"=>"\u1EA2".freeze, "a\u0309"=>"\u1EA3".freeze, "\u00C2\u0301"=>"\u1EA4".freeze, "\u00E2\u0301"=>"\u1EA5".freeze, "\u00C2\u0300"=>"\u1EA6".freeze, "\u00E2\u0300"=>"\u1EA7".freeze, "\u00C2\u0309"=>"\u1EA8".freeze, "\u00E2\u0309"=>"\u1EA9".freeze, "\u00C2\u0303"=>"\u1EAA".freeze, "\u00E2\u0303"=>"\u1EAB".freeze, "\u1EA0\u0302"=>"\u1EAC".freeze, "\u1EA1\u0302"=>"\u1EAD".freeze, "\u0102\u0301"=>"\u1EAE".freeze, "\u0103\u0301"=>"\u1EAF".freeze, "\u0102\u0300"=>"\u1EB0".freeze, "\u0103\u0300"=>"\u1EB1".freeze, "\u0102\u0309"=>"\u1EB2".freeze, "\u0103\u0309"=>"\u1EB3".freeze, "\u0102\u0303"=>"\u1EB4".freeze, "\u0103\u0303"=>"\u1EB5".freeze, "\u1EA0\u0306"=>"\u1EB6".freeze, "\u1EA1\u0306"=>"\u1EB7".freeze, "E\u0323"=>"\u1EB8".freeze, "e\u0323"=>"\u1EB9".freeze, "E\u0309"=>"\u1EBA".freeze, "e\u0309"=>"\u1EBB".freeze, "E\u0303"=>"\u1EBC".freeze, "e\u0303"=>"\u1EBD".freeze, "\u00CA\u0301"=>"\u1EBE".freeze, "\u00EA\u0301"=>"\u1EBF".freeze, "\u00CA\u0300"=>"\u1EC0".freeze, "\u00EA\u0300"=>"\u1EC1".freeze, "\u00CA\u0309"=>"\u1EC2".freeze, "\u00EA\u0309"=>"\u1EC3".freeze, "\u00CA\u0303"=>"\u1EC4".freeze, "\u00EA\u0303"=>"\u1EC5".freeze, "\u1EB8\u0302"=>"\u1EC6".freeze, "\u1EB9\u0302"=>"\u1EC7".freeze, "I\u0309"=>"\u1EC8".freeze, "i\u0309"=>"\u1EC9".freeze, "I\u0323"=>"\u1ECA".freeze, "i\u0323"=>"\u1ECB".freeze, "O\u0323"=>"\u1ECC".freeze, "o\u0323"=>"\u1ECD".freeze, "O\u0309"=>"\u1ECE".freeze, "o\u0309"=>"\u1ECF".freeze, "\u00D4\u0301"=>"\u1ED0".freeze, "\u00F4\u0301"=>"\u1ED1".freeze, "\u00D4\u0300"=>"\u1ED2".freeze, "\u00F4\u0300"=>"\u1ED3".freeze, "\u00D4\u0309"=>"\u1ED4".freeze, "\u00F4\u0309"=>"\u1ED5".freeze, "\u00D4\u0303"=>"\u1ED6".freeze, "\u00F4\u0303"=>"\u1ED7".freeze, "\u1ECC\u0302"=>"\u1ED8".freeze, "\u1ECD\u0302"=>"\u1ED9".freeze, "\u01A0\u0301"=>"\u1EDA".freeze, "\u01A1\u0301"=>"\u1EDB".freeze, "\u01A0\u0300"=>"\u1EDC".freeze, "\u01A1\u0300"=>"\u1EDD".freeze, "\u01A0\u0309"=>"\u1EDE".freeze, "\u01A1\u0309"=>"\u1EDF".freeze, "\u01A0\u0303"=>"\u1EE0".freeze, "\u01A1\u0303"=>"\u1EE1".freeze, "\u01A0\u0323"=>"\u1EE2".freeze, "\u01A1\u0323"=>"\u1EE3".freeze, "U\u0323"=>"\u1EE4".freeze, "u\u0323"=>"\u1EE5".freeze, "U\u0309"=>"\u1EE6".freeze, "u\u0309"=>"\u1EE7".freeze, "\u01AF\u0301"=>"\u1EE8".freeze, "\u01B0\u0301"=>"\u1EE9".freeze, "\u01AF\u0300"=>"\u1EEA".freeze, "\u01B0\u0300"=>"\u1EEB".freeze, "\u01AF\u0309"=>"\u1EEC".freeze, "\u01B0\u0309"=>"\u1EED".freeze, "\u01AF\u0303"=>"\u1EEE".freeze, "\u01B0\u0303"=>"\u1EEF".freeze, "\u01AF\u0323"=>"\u1EF0".freeze, "\u01B0\u0323"=>"\u1EF1".freeze, "Y\u0300"=>"\u1EF2".freeze, "y\u0300"=>"\u1EF3".freeze, "Y\u0323"=>"\u1EF4".freeze, "y\u0323"=>"\u1EF5".freeze, "Y\u0309"=>"\u1EF6".freeze, "y\u0309"=>"\u1EF7".freeze, "Y\u0303"=>"\u1EF8".freeze, "y\u0303"=>"\u1EF9".freeze, "\u03B1\u0313"=>"\u1F00".freeze, "\u03B1\u0314"=>"\u1F01".freeze, "\u1F00\u0300"=>"\u1F02".freeze, "\u1F01\u0300"=>"\u1F03".freeze, "\u1F00\u0301"=>"\u1F04".freeze, "\u1F01\u0301"=>"\u1F05".freeze, "\u1F00\u0342"=>"\u1F06".freeze, "\u1F01\u0342"=>"\u1F07".freeze, "\u0391\u0313"=>"\u1F08".freeze, "\u0391\u0314"=>"\u1F09".freeze, "\u1F08\u0300"=>"\u1F0A".freeze, "\u1F09\u0300"=>"\u1F0B".freeze, "\u1F08\u0301"=>"\u1F0C".freeze, "\u1F09\u0301"=>"\u1F0D".freeze, "\u1F08\u0342"=>"\u1F0E".freeze, "\u1F09\u0342"=>"\u1F0F".freeze, "\u03B5\u0313"=>"\u1F10".freeze, "\u03B5\u0314"=>"\u1F11".freeze, "\u1F10\u0300"=>"\u1F12".freeze, "\u1F11\u0300"=>"\u1F13".freeze, "\u1F10\u0301"=>"\u1F14".freeze, "\u1F11\u0301"=>"\u1F15".freeze, "\u0395\u0313"=>"\u1F18".freeze, "\u0395\u0314"=>"\u1F19".freeze, "\u1F18\u0300"=>"\u1F1A".freeze, "\u1F19\u0300"=>"\u1F1B".freeze, "\u1F18\u0301"=>"\u1F1C".freeze, "\u1F19\u0301"=>"\u1F1D".freeze, "\u03B7\u0313"=>"\u1F20".freeze, "\u03B7\u0314"=>"\u1F21".freeze, "\u1F20\u0300"=>"\u1F22".freeze, "\u1F21\u0300"=>"\u1F23".freeze, "\u1F20\u0301"=>"\u1F24".freeze, "\u1F21\u0301"=>"\u1F25".freeze, "\u1F20\u0342"=>"\u1F26".freeze, "\u1F21\u0342"=>"\u1F27".freeze, "\u0397\u0313"=>"\u1F28".freeze, "\u0397\u0314"=>"\u1F29".freeze, "\u1F28\u0300"=>"\u1F2A".freeze, "\u1F29\u0300"=>"\u1F2B".freeze, "\u1F28\u0301"=>"\u1F2C".freeze, "\u1F29\u0301"=>"\u1F2D".freeze, "\u1F28\u0342"=>"\u1F2E".freeze, "\u1F29\u0342"=>"\u1F2F".freeze, "\u03B9\u0313"=>"\u1F30".freeze, "\u03B9\u0314"=>"\u1F31".freeze, "\u1F30\u0300"=>"\u1F32".freeze, "\u1F31\u0300"=>"\u1F33".freeze, "\u1F30\u0301"=>"\u1F34".freeze, "\u1F31\u0301"=>"\u1F35".freeze, "\u1F30\u0342"=>"\u1F36".freeze, "\u1F31\u0342"=>"\u1F37".freeze, "\u0399\u0313"=>"\u1F38".freeze, "\u0399\u0314"=>"\u1F39".freeze, "\u1F38\u0300"=>"\u1F3A".freeze, "\u1F39\u0300"=>"\u1F3B".freeze, "\u1F38\u0301"=>"\u1F3C".freeze, "\u1F39\u0301"=>"\u1F3D".freeze, "\u1F38\u0342"=>"\u1F3E".freeze, "\u1F39\u0342"=>"\u1F3F".freeze, "\u03BF\u0313"=>"\u1F40".freeze, "\u03BF\u0314"=>"\u1F41".freeze, "\u1F40\u0300"=>"\u1F42".freeze, "\u1F41\u0300"=>"\u1F43".freeze, "\u1F40\u0301"=>"\u1F44".freeze, "\u1F41\u0301"=>"\u1F45".freeze, "\u039F\u0313"=>"\u1F48".freeze, "\u039F\u0314"=>"\u1F49".freeze, "\u1F48\u0300"=>"\u1F4A".freeze, "\u1F49\u0300"=>"\u1F4B".freeze, "\u1F48\u0301"=>"\u1F4C".freeze, "\u1F49\u0301"=>"\u1F4D".freeze, "\u03C5\u0313"=>"\u1F50".freeze, "\u03C5\u0314"=>"\u1F51".freeze, "\u1F50\u0300"=>"\u1F52".freeze, "\u1F51\u0300"=>"\u1F53".freeze, "\u1F50\u0301"=>"\u1F54".freeze, "\u1F51\u0301"=>"\u1F55".freeze, "\u1F50\u0342"=>"\u1F56".freeze, "\u1F51\u0342"=>"\u1F57".freeze, "\u03A5\u0314"=>"\u1F59".freeze, "\u1F59\u0300"=>"\u1F5B".freeze, "\u1F59\u0301"=>"\u1F5D".freeze, "\u1F59\u0342"=>"\u1F5F".freeze, "\u03C9\u0313"=>"\u1F60".freeze, "\u03C9\u0314"=>"\u1F61".freeze, "\u1F60\u0300"=>"\u1F62".freeze, "\u1F61\u0300"=>"\u1F63".freeze, "\u1F60\u0301"=>"\u1F64".freeze, "\u1F61\u0301"=>"\u1F65".freeze, "\u1F60\u0342"=>"\u1F66".freeze, "\u1F61\u0342"=>"\u1F67".freeze, "\u03A9\u0313"=>"\u1F68".freeze, "\u03A9\u0314"=>"\u1F69".freeze, "\u1F68\u0300"=>"\u1F6A".freeze, "\u1F69\u0300"=>"\u1F6B".freeze, "\u1F68\u0301"=>"\u1F6C".freeze, "\u1F69\u0301"=>"\u1F6D".freeze, "\u1F68\u0342"=>"\u1F6E".freeze, "\u1F69\u0342"=>"\u1F6F".freeze, "\u03B1\u0300"=>"\u1F70".freeze, "\u03B5\u0300"=>"\u1F72".freeze, "\u03B7\u0300"=>"\u1F74".freeze, "\u03B9\u0300"=>"\u1F76".freeze, "\u03BF\u0300"=>"\u1F78".freeze, "\u03C5\u0300"=>"\u1F7A".freeze, "\u03C9\u0300"=>"\u1F7C".freeze, "\u1F00\u0345"=>"\u1F80".freeze, "\u1F01\u0345"=>"\u1F81".freeze, "\u1F02\u0345"=>"\u1F82".freeze, "\u1F03\u0345"=>"\u1F83".freeze, "\u1F04\u0345"=>"\u1F84".freeze, "\u1F05\u0345"=>"\u1F85".freeze, "\u1F06\u0345"=>"\u1F86".freeze, "\u1F07\u0345"=>"\u1F87".freeze, "\u1F08\u0345"=>"\u1F88".freeze, "\u1F09\u0345"=>"\u1F89".freeze, "\u1F0A\u0345"=>"\u1F8A".freeze, "\u1F0B\u0345"=>"\u1F8B".freeze, "\u1F0C\u0345"=>"\u1F8C".freeze, "\u1F0D\u0345"=>"\u1F8D".freeze, "\u1F0E\u0345"=>"\u1F8E".freeze, "\u1F0F\u0345"=>"\u1F8F".freeze, "\u1F20\u0345"=>"\u1F90".freeze, "\u1F21\u0345"=>"\u1F91".freeze, "\u1F22\u0345"=>"\u1F92".freeze, "\u1F23\u0345"=>"\u1F93".freeze, "\u1F24\u0345"=>"\u1F94".freeze, "\u1F25\u0345"=>"\u1F95".freeze, "\u1F26\u0345"=>"\u1F96".freeze, "\u1F27\u0345"=>"\u1F97".freeze, "\u1F28\u0345"=>"\u1F98".freeze, "\u1F29\u0345"=>"\u1F99".freeze, "\u1F2A\u0345"=>"\u1F9A".freeze, "\u1F2B\u0345"=>"\u1F9B".freeze, "\u1F2C\u0345"=>"\u1F9C".freeze, "\u1F2D\u0345"=>"\u1F9D".freeze, "\u1F2E\u0345"=>"\u1F9E".freeze, "\u1F2F\u0345"=>"\u1F9F".freeze, "\u1F60\u0345"=>"\u1FA0".freeze, "\u1F61\u0345"=>"\u1FA1".freeze, "\u1F62\u0345"=>"\u1FA2".freeze, "\u1F63\u0345"=>"\u1FA3".freeze, "\u1F64\u0345"=>"\u1FA4".freeze, "\u1F65\u0345"=>"\u1FA5".freeze, "\u1F66\u0345"=>"\u1FA6".freeze, "\u1F67\u0345"=>"\u1FA7".freeze, "\u1F68\u0345"=>"\u1FA8".freeze, "\u1F69\u0345"=>"\u1FA9".freeze, "\u1F6A\u0345"=>"\u1FAA".freeze, "\u1F6B\u0345"=>"\u1FAB".freeze, "\u1F6C\u0345"=>"\u1FAC".freeze, "\u1F6D\u0345"=>"\u1FAD".freeze, "\u1F6E\u0345"=>"\u1FAE".freeze, "\u1F6F\u0345"=>"\u1FAF".freeze, "\u03B1\u0306"=>"\u1FB0".freeze, "\u03B1\u0304"=>"\u1FB1".freeze, "\u1F70\u0345"=>"\u1FB2".freeze, "\u03B1\u0345"=>"\u1FB3".freeze, "\u03AC\u0345"=>"\u1FB4".freeze, "\u03B1\u0342"=>"\u1FB6".freeze, "\u1FB6\u0345"=>"\u1FB7".freeze, "\u0391\u0306"=>"\u1FB8".freeze, "\u0391\u0304"=>"\u1FB9".freeze, "\u0391\u0300"=>"\u1FBA".freeze, "\u0391\u0345"=>"\u1FBC".freeze, "\u00A8\u0342"=>"\u1FC1".freeze, "\u1F74\u0345"=>"\u1FC2".freeze, "\u03B7\u0345"=>"\u1FC3".freeze, "\u03AE\u0345"=>"\u1FC4".freeze, "\u03B7\u0342"=>"\u1FC6".freeze, "\u1FC6\u0345"=>"\u1FC7".freeze, "\u0395\u0300"=>"\u1FC8".freeze, "\u0397\u0300"=>"\u1FCA".freeze, "\u0397\u0345"=>"\u1FCC".freeze, "\u1FBF\u0300"=>"\u1FCD".freeze, "\u1FBF\u0301"=>"\u1FCE".freeze, "\u1FBF\u0342"=>"\u1FCF".freeze, "\u03B9\u0306"=>"\u1FD0".freeze, "\u03B9\u0304"=>"\u1FD1".freeze, "\u03CA\u0300"=>"\u1FD2".freeze, "\u03B9\u0342"=>"\u1FD6".freeze, "\u03CA\u0342"=>"\u1FD7".freeze, "\u0399\u0306"=>"\u1FD8".freeze, "\u0399\u0304"=>"\u1FD9".freeze, "\u0399\u0300"=>"\u1FDA".freeze, "\u1FFE\u0300"=>"\u1FDD".freeze, "\u1FFE\u0301"=>"\u1FDE".freeze, "\u1FFE\u0342"=>"\u1FDF".freeze, "\u03C5\u0306"=>"\u1FE0".freeze, "\u03C5\u0304"=>"\u1FE1".freeze, "\u03CB\u0300"=>"\u1FE2".freeze, "\u03C1\u0313"=>"\u1FE4".freeze, "\u03C1\u0314"=>"\u1FE5".freeze, "\u03C5\u0342"=>"\u1FE6".freeze, "\u03CB\u0342"=>"\u1FE7".freeze, "\u03A5\u0306"=>"\u1FE8".freeze, "\u03A5\u0304"=>"\u1FE9".freeze, "\u03A5\u0300"=>"\u1FEA".freeze, "\u03A1\u0314"=>"\u1FEC".freeze, "\u00A8\u0300"=>"\u1FED".freeze, "\u1F7C\u0345"=>"\u1FF2".freeze, "\u03C9\u0345"=>"\u1FF3".freeze, "\u03CE\u0345"=>"\u1FF4".freeze, "\u03C9\u0342"=>"\u1FF6".freeze, "\u1FF6\u0345"=>"\u1FF7".freeze, "\u039F\u0300"=>"\u1FF8".freeze, "\u03A9\u0300"=>"\u1FFA".freeze, "\u03A9\u0345"=>"\u1FFC".freeze, "\u2190\u0338"=>"\u219A".freeze, "\u2192\u0338"=>"\u219B".freeze, "\u2194\u0338"=>"\u21AE".freeze, "\u21D0\u0338"=>"\u21CD".freeze, "\u21D4\u0338"=>"\u21CE".freeze, "\u21D2\u0338"=>"\u21CF".freeze, "\u2203\u0338"=>"\u2204".freeze, "\u2208\u0338"=>"\u2209".freeze, "\u220B\u0338"=>"\u220C".freeze, "\u2223\u0338"=>"\u2224".freeze, "\u2225\u0338"=>"\u2226".freeze, "\u223C\u0338"=>"\u2241".freeze, "\u2243\u0338"=>"\u2244".freeze, "\u2245\u0338"=>"\u2247".freeze, "\u2248\u0338"=>"\u2249".freeze, "=\u0338"=>"\u2260".freeze, "\u2261\u0338"=>"\u2262".freeze, "\u224D\u0338"=>"\u226D".freeze, "<\u0338"=>"\u226E".freeze, ">\u0338"=>"\u226F".freeze, "\u2264\u0338"=>"\u2270".freeze, "\u2265\u0338"=>"\u2271".freeze, "\u2272\u0338"=>"\u2274".freeze, "\u2273\u0338"=>"\u2275".freeze, "\u2276\u0338"=>"\u2278".freeze, "\u2277\u0338"=>"\u2279".freeze, "\u227A\u0338"=>"\u2280".freeze, "\u227B\u0338"=>"\u2281".freeze, "\u2282\u0338"=>"\u2284".freeze, "\u2283\u0338"=>"\u2285".freeze, "\u2286\u0338"=>"\u2288".freeze, "\u2287\u0338"=>"\u2289".freeze, "\u22A2\u0338"=>"\u22AC".freeze, "\u22A8\u0338"=>"\u22AD".freeze, "\u22A9\u0338"=>"\u22AE".freeze, "\u22AB\u0338"=>"\u22AF".freeze, "\u227C\u0338"=>"\u22E0".freeze, "\u227D\u0338"=>"\u22E1".freeze, "\u2291\u0338"=>"\u22E2".freeze, "\u2292\u0338"=>"\u22E3".freeze, "\u22B2\u0338"=>"\u22EA".freeze, "\u22B3\u0338"=>"\u22EB".freeze, "\u22B4\u0338"=>"\u22EC".freeze, "\u22B5\u0338"=>"\u22ED".freeze, "\u304B\u3099"=>"\u304C".freeze, "\u304D\u3099"=>"\u304E".freeze, "\u304F\u3099"=>"\u3050".freeze, "\u3051\u3099"=>"\u3052".freeze, "\u3053\u3099"=>"\u3054".freeze, "\u3055\u3099"=>"\u3056".freeze, "\u3057\u3099"=>"\u3058".freeze, "\u3059\u3099"=>"\u305A".freeze, "\u305B\u3099"=>"\u305C".freeze, "\u305D\u3099"=>"\u305E".freeze, "\u305F\u3099"=>"\u3060".freeze, "\u3061\u3099"=>"\u3062".freeze, "\u3064\u3099"=>"\u3065".freeze, "\u3066\u3099"=>"\u3067".freeze, "\u3068\u3099"=>"\u3069".freeze, "\u306F\u3099"=>"\u3070".freeze, "\u306F\u309A"=>"\u3071".freeze, "\u3072\u3099"=>"\u3073".freeze, "\u3072\u309A"=>"\u3074".freeze, "\u3075\u3099"=>"\u3076".freeze, "\u3075\u309A"=>"\u3077".freeze, "\u3078\u3099"=>"\u3079".freeze, "\u3078\u309A"=>"\u307A".freeze, "\u307B\u3099"=>"\u307C".freeze, "\u307B\u309A"=>"\u307D".freeze, "\u3046\u3099"=>"\u3094".freeze, "\u309D\u3099"=>"\u309E".freeze, "\u30AB\u3099"=>"\u30AC".freeze, "\u30AD\u3099"=>"\u30AE".freeze, "\u30AF\u3099"=>"\u30B0".freeze, "\u30B1\u3099"=>"\u30B2".freeze, "\u30B3\u3099"=>"\u30B4".freeze, "\u30B5\u3099"=>"\u30B6".freeze, "\u30B7\u3099"=>"\u30B8".freeze, "\u30B9\u3099"=>"\u30BA".freeze, "\u30BB\u3099"=>"\u30BC".freeze, "\u30BD\u3099"=>"\u30BE".freeze, "\u30BF\u3099"=>"\u30C0".freeze, "\u30C1\u3099"=>"\u30C2".freeze, "\u30C4\u3099"=>"\u30C5".freeze, "\u30C6\u3099"=>"\u30C7".freeze, "\u30C8\u3099"=>"\u30C9".freeze, "\u30CF\u3099"=>"\u30D0".freeze, "\u30CF\u309A"=>"\u30D1".freeze, "\u30D2\u3099"=>"\u30D3".freeze, "\u30D2\u309A"=>"\u30D4".freeze, "\u30D5\u3099"=>"\u30D6".freeze, "\u30D5\u309A"=>"\u30D7".freeze, "\u30D8\u3099"=>"\u30D9".freeze, "\u30D8\u309A"=>"\u30DA".freeze, "\u30DB\u3099"=>"\u30DC".freeze, "\u30DB\u309A"=>"\u30DD".freeze, "\u30A6\u3099"=>"\u30F4".freeze, "\u30EF\u3099"=>"\u30F7".freeze, "\u30F0\u3099"=>"\u30F8".freeze, "\u30F1\u3099"=>"\u30F9".freeze, "\u30F2\u3099"=>"\u30FA".freeze, "\u30FD\u3099"=>"\u30FE".freeze, "\u{11099}\u{110BA}"=>"\u{1109A}".freeze, "\u{1109B}\u{110BA}"=>"\u{1109C}".freeze, "\u{110A5}\u{110BA}"=>"\u{110AB}".freeze, "\u{11131}\u{11127}"=>"\u{1112E}".freeze, "\u{11132}\u{11127}"=>"\u{1112F}".freeze, "\u{11347}\u{1133E}"=>"\u{1134B}".freeze, "\u{11347}\u{11357}"=>"\u{1134C}".freeze, "\u{114B9}\u{114BA}"=>"\u{114BB}".freeze, "\u{114B9}\u{114B0}"=>"\u{114BC}".freeze, "\u{114B9}\u{114BD}"=>"\u{114BE}".freeze, "\u{115B8}\u{115AF}"=>"\u{115BA}".freeze, "\u{115B9}\u{115AF}"=>"\u{115BB}".freeze, }.freeze end PK!$2.2.0/unicode_normalize/normalize.rbnu[# coding: utf-8 # Copyright Ayumu Nojima (野島 歩) and Martin J. Dürst (duerst@it.aoyama.ac.jp) require 'unicode_normalize/tables.rb' module UnicodeNormalize ## Constant for max hash capacity to avoid DoS attack MAX_HASH_LENGTH = 18000 # enough for all test cases, otherwise tests get slow ## Regular Expressions and Hash Constants REGEXP_D = Regexp.compile(REGEXP_D_STRING, Regexp::EXTENDED) REGEXP_C = Regexp.compile(REGEXP_C_STRING, Regexp::EXTENDED) REGEXP_K = Regexp.compile(REGEXP_K_STRING, Regexp::EXTENDED) NF_HASH_D = Hash.new do |hash, key| hash.shift if hash.length>MAX_HASH_LENGTH # prevent DoS attack hash[key] = nfd_one(key) end NF_HASH_C = Hash.new do |hash, key| hash.shift if hash.length>MAX_HASH_LENGTH # prevent DoS attack hash[key] = nfc_one(key) end NF_HASH_K = Hash.new do |hash, key| hash.shift if hash.length>MAX_HASH_LENGTH # prevent DoS attack hash[key] = nfkd_one(key) end ## Constants For Hangul # for details such as the meaning of the identifiers below, please see # http://www.unicode.org/versions/Unicode7.0.0/ch03.pdf, pp. 144/145 SBASE = 0xAC00 LBASE = 0x1100 VBASE = 0x1161 TBASE = 0x11A7 LCOUNT = 19 VCOUNT = 21 TCOUNT = 28 NCOUNT = VCOUNT * TCOUNT SCOUNT = LCOUNT * NCOUNT # Unicode-based encodings (except UTF-8) UNICODE_ENCODINGS = [Encoding::UTF_16BE, Encoding::UTF_16LE, Encoding::UTF_32BE, Encoding::UTF_32LE, Encoding::GB18030, Encoding::UCS_2BE, Encoding::UCS_4BE] ## Hangul Algorithm def self.hangul_decomp_one(target) syllable_index = target.ord - SBASE return target if syllable_index < 0 || syllable_index >= SCOUNT l = LBASE + syllable_index / NCOUNT v = VBASE + (syllable_index % NCOUNT) / TCOUNT t = TBASE + syllable_index % TCOUNT (t==TBASE ? [l, v] : [l, v, t]).pack('U*') + target[1..-1] end def self.hangul_comp_one(string) length = string.length if length>1 and 0 <= (lead =string[0].ord-LBASE) and lead < LCOUNT and 0 <= (vowel=string[1].ord-VBASE) and vowel < VCOUNT lead_vowel = SBASE + (lead * VCOUNT + vowel) * TCOUNT if length>2 and 0 <= (trail=string[2].ord-TBASE) and trail < TCOUNT (lead_vowel + trail).chr(Encoding::UTF_8) + string[3..-1] else lead_vowel.chr(Encoding::UTF_8) + string[2..-1] end else string end end ## Canonical Ordering def self.canonical_ordering_one(string) sorting = string.each_char.collect { |c| [c, CLASS_TABLE[c]] } (sorting.length-2).downto(0) do |i| # almost, but not exactly bubble sort (0..i).each do |j| later_class = sorting[j+1].last if 0--file as well # as single letter options like -f # # The empty option -- (two minus symbols) is used to end option # processing. This can be particularly important if options have optional # arguments. # # Here is a simple example of usage: # # require 'getoptlong' # # opts = GetoptLong.new( # [ '--help', '-h', GetoptLong::NO_ARGUMENT ], # [ '--repeat', '-n', GetoptLong::REQUIRED_ARGUMENT ], # [ '--name', GetoptLong::OPTIONAL_ARGUMENT ] # ) # # dir = nil # name = nil # repetitions = 1 # opts.each do |opt, arg| # case opt # when '--help' # puts <<-EOF # hello [OPTION] ... DIR # # -h, --help: # show help # # --repeat x, -n x: # repeat x times # # --name [name]: # greet user by name, if name not supplied default is John # # DIR: The directory in which to issue the greeting. # EOF # when '--repeat' # repetitions = arg.to_i # when '--name' # if arg == '' # name = 'John' # else # name = arg # end # end # end # # if ARGV.length != 1 # puts "Missing dir argument (try --help)" # exit 0 # end # # dir = ARGV.shift # # Dir.chdir(dir) # for i in (1..repetitions) # print "Hello" # if name # print ", #{name}" # end # puts # end # # Example command line: # # hello -n 6 --name -- /tmp # class GetoptLong # # Orderings. # ORDERINGS = [REQUIRE_ORDER = 0, PERMUTE = 1, RETURN_IN_ORDER = 2] # # Argument flags. # ARGUMENT_FLAGS = [NO_ARGUMENT = 0, REQUIRED_ARGUMENT = 1, OPTIONAL_ARGUMENT = 2] # # Status codes. # STATUS_YET, STATUS_STARTED, STATUS_TERMINATED = 0, 1, 2 # # Error types. # class Error < StandardError; end class AmbiguousOption < Error; end class NeedlessArgument < Error; end class MissingArgument < Error; end class InvalidOption < Error; end # # Set up option processing. # # The options to support are passed to new() as an array of arrays. # Each sub-array contains any number of String option names which carry # the same meaning, and one of the following flags: # # GetoptLong::NO_ARGUMENT :: Option does not take an argument. # # GetoptLong::REQUIRED_ARGUMENT :: Option always takes an argument. # # GetoptLong::OPTIONAL_ARGUMENT :: Option may or may not take an argument. # # The first option name is considered to be the preferred (canonical) name. # Other than that, the elements of each sub-array can be in any order. # def initialize(*arguments) # # Current ordering. # if ENV.include?('POSIXLY_CORRECT') @ordering = REQUIRE_ORDER else @ordering = PERMUTE end # # Hash table of option names. # Keys of the table are option names, and their values are canonical # names of the options. # @canonical_names = Hash.new # # Hash table of argument flags. # Keys of the table are option names, and their values are argument # flags of the options. # @argument_flags = Hash.new # # Whether error messages are output to $stderr. # @quiet = FALSE # # Status code. # @status = STATUS_YET # # Error code. # @error = nil # # Error message. # @error_message = nil # # Rest of catenated short options. # @rest_singles = '' # # List of non-option-arguments. # Append them to ARGV when option processing is terminated. # @non_option_arguments = Array.new if 0 < arguments.length set_options(*arguments) end end # # Set the handling of the ordering of options and arguments. # A RuntimeError is raised if option processing has already started. # # The supplied value must be a member of GetoptLong::ORDERINGS. It alters # the processing of options as follows: # # REQUIRE_ORDER : # # Options are required to occur before non-options. # # Processing of options ends as soon as a word is encountered that has not # been preceded by an appropriate option flag. # # For example, if -a and -b are options which do not take arguments, # parsing command line arguments of '-a one -b two' would result in # 'one', '-b', 'two' being left in ARGV, and only ('-a', '') being # processed as an option/arg pair. # # This is the default ordering, if the environment variable # POSIXLY_CORRECT is set. (This is for compatibility with GNU getopt_long.) # # PERMUTE : # # Options can occur anywhere in the command line parsed. This is the # default behavior. # # Every sequence of words which can be interpreted as an option (with or # without argument) is treated as an option; non-option words are skipped. # # For example, if -a does not require an argument and -b optionally takes # an argument, parsing '-a one -b two three' would result in ('-a','') and # ('-b', 'two') being processed as option/arg pairs, and 'one','three' # being left in ARGV. # # If the ordering is set to PERMUTE but the environment variable # POSIXLY_CORRECT is set, REQUIRE_ORDER is used instead. This is for # compatibility with GNU getopt_long. # # RETURN_IN_ORDER : # # All words on the command line are processed as options. Words not # preceded by a short or long option flag are passed as arguments # with an option of '' (empty string). # # For example, if -a requires an argument but -b does not, a command line # of '-a one -b two three' would result in option/arg pairs of ('-a', 'one') # ('-b', ''), ('', 'two'), ('', 'three') being processed. # def ordering=(ordering) # # The method is failed if option processing has already started. # if @status != STATUS_YET set_error(ArgumentError, "argument error") raise RuntimeError, "invoke ordering=, but option processing has already started" end # # Check ordering. # if !ORDERINGS.include?(ordering) raise ArgumentError, "invalid ordering `#{ordering}'" end if ordering == PERMUTE && ENV.include?('POSIXLY_CORRECT') @ordering = REQUIRE_ORDER else @ordering = ordering end end # # Return ordering. # attr_reader :ordering # # Set options. Takes the same argument as GetoptLong.new. # # Raises a RuntimeError if option processing has already started. # def set_options(*arguments) # # The method is failed if option processing has already started. # if @status != STATUS_YET raise RuntimeError, "invoke set_options, but option processing has already started" end # # Clear tables of option names and argument flags. # @canonical_names.clear @argument_flags.clear arguments.each do |arg| if !arg.is_a?(Array) raise ArgumentError, "the option list contains non-Array argument" end # # Find an argument flag and it set to `argument_flag'. # argument_flag = nil arg.each do |i| if ARGUMENT_FLAGS.include?(i) if argument_flag != nil raise ArgumentError, "too many argument-flags" end argument_flag = i end end raise ArgumentError, "no argument-flag" if argument_flag == nil canonical_name = nil arg.each do |i| # # Check an option name. # next if i == argument_flag begin if !i.is_a?(String) || i !~ /^-([^-]|-.+)$/ raise ArgumentError, "an invalid option `#{i}'" end if (@canonical_names.include?(i)) raise ArgumentError, "option redefined `#{i}'" end rescue @canonical_names.clear @argument_flags.clear raise end # # Register the option (`i') to the `@canonical_names' and # `@canonical_names' Hashes. # if canonical_name == nil canonical_name = i end @canonical_names[i] = canonical_name @argument_flags[i] = argument_flag end raise ArgumentError, "no option name" if canonical_name == nil end return self end # # Set/Unset `quiet' mode. # attr_writer :quiet # # Return the flag of `quiet' mode. # attr_reader :quiet # # `quiet?' is an alias of `quiet'. # alias quiet? quiet # # Explicitly terminate option processing. # def terminate return nil if @status == STATUS_TERMINATED raise RuntimeError, "an error has occurred" if @error != nil @status = STATUS_TERMINATED @non_option_arguments.reverse_each do |argument| ARGV.unshift(argument) end @canonical_names = nil @argument_flags = nil @rest_singles = nil @non_option_arguments = nil return self end # # Returns true if option processing has terminated, false otherwise. # def terminated? return @status == STATUS_TERMINATED end # # Set an error (a protected method). # def set_error(type, message) $stderr.print("#{$0}: #{message}\n") if !@quiet @error = type @error_message = message @canonical_names = nil @argument_flags = nil @rest_singles = nil @non_option_arguments = nil raise type, message end protected :set_error # # Examine whether an option processing is failed. # attr_reader :error # # `error?' is an alias of `error'. # alias error? error # Return the appropriate error message in POSIX-defined format. # If no error has occurred, returns nil. # def error_message return @error_message end # # Get next option name and its argument, as an Array of two elements. # # The option name is always converted to the first (preferred) # name given in the original options to GetoptLong.new. # # Example: ['--option', 'value'] # # Returns nil if the processing is complete (as determined by # STATUS_TERMINATED). # def get option_name, option_argument = nil, '' # # Check status. # return nil if @error != nil case @status when STATUS_YET @status = STATUS_STARTED when STATUS_TERMINATED return nil end # # Get next option argument. # if 0 < @rest_singles.length argument = '-' + @rest_singles elsif (ARGV.length == 0) terminate return nil elsif @ordering == PERMUTE while 0 < ARGV.length && ARGV[0] !~ /^-./ @non_option_arguments.push(ARGV.shift) end if ARGV.length == 0 terminate return nil end argument = ARGV.shift elsif @ordering == REQUIRE_ORDER if (ARGV[0] !~ /^-./) terminate return nil end argument = ARGV.shift else argument = ARGV.shift end # # Check the special argument `--'. # `--' indicates the end of the option list. # if argument == '--' && @rest_singles.length == 0 terminate return nil end # # Check for long and short options. # if argument =~ /^(--[^=]+)/ && @rest_singles.length == 0 # # This is a long style option, which start with `--'. # pattern = $1 if @canonical_names.include?(pattern) option_name = pattern else # # The option `option_name' is not registered in `@canonical_names'. # It may be an abbreviated. # matches = [] @canonical_names.each_key do |key| if key.index(pattern) == 0 option_name = key matches << key end end if 2 <= matches.length set_error(AmbiguousOption, "option `#{argument}' is ambiguous between #{matches.join(', ')}") elsif matches.length == 0 set_error(InvalidOption, "unrecognized option `#{argument}'") end end # # Check an argument to the option. # if @argument_flags[option_name] == REQUIRED_ARGUMENT if argument =~ /=(.*)$/ option_argument = $1 elsif 0 < ARGV.length option_argument = ARGV.shift else set_error(MissingArgument, "option `#{argument}' requires an argument") end elsif @argument_flags[option_name] == OPTIONAL_ARGUMENT if argument =~ /=(.*)$/ option_argument = $1 elsif 0 < ARGV.length && ARGV[0] !~ /^-./ option_argument = ARGV.shift else option_argument = '' end elsif argument =~ /=(.*)$/ set_error(NeedlessArgument, "option `#{option_name}' doesn't allow an argument") end elsif argument =~ /^(-(.))(.*)/ # # This is a short style option, which start with `-' (not `--'). # Short options may be catenated (e.g. `-l -g' is equivalent to # `-lg'). # option_name, ch, @rest_singles = $1, $2, $3 if @canonical_names.include?(option_name) # # The option `option_name' is found in `@canonical_names'. # Check its argument. # if @argument_flags[option_name] == REQUIRED_ARGUMENT if 0 < @rest_singles.length option_argument = @rest_singles @rest_singles = '' elsif 0 < ARGV.length option_argument = ARGV.shift else # 1003.2 specifies the format of this message. set_error(MissingArgument, "option requires an argument -- #{ch}") end elsif @argument_flags[option_name] == OPTIONAL_ARGUMENT if 0 < @rest_singles.length option_argument = @rest_singles @rest_singles = '' elsif 0 < ARGV.length && ARGV[0] !~ /^-./ option_argument = ARGV.shift else option_argument = '' end end else # # This is an invalid option. # 1003.2 specifies the format of this message. # if ENV.include?('POSIXLY_CORRECT') set_error(InvalidOption, "invalid option -- #{ch}") else set_error(InvalidOption, "invalid option -- #{ch}") end end else # # This is a non-option argument. # Only RETURN_IN_ORDER falled into here. # return '', argument end return @canonical_names[option_name], option_argument end # # `get_option' is an alias of `get'. # alias get_option get # Iterator version of `get'. # # The block is called repeatedly with two arguments: # The first is the option name. # The second is the argument which followed it (if any). # Example: ('--opt', 'value') # # The option name is always converted to the first (preferred) # name given in the original options to GetoptLong.new. # def each loop do option_name, option_argument = get_option break if option_name == nil yield option_name, option_argument end end # # `each_option' is an alias of `each'. # alias each_option each end PK!4c_2.2.0/singleton.rbnu[require 'thread' # The Singleton module implements the Singleton pattern. # # == Usage # # To use Singleton, include the module in your class. # # class Klass # include Singleton # # ... # end # # This ensures that only one instance of Klass can be created. # # a,b = Klass.instance, Klass.instance # # a == b # # => true # # Klass.new # # => NoMethodError - new is private ... # # The instance is created at upon the first call of Klass.instance(). # # class OtherKlass # include Singleton # # ... # end # # ObjectSpace.each_object(OtherKlass){} # # => 0 # # OtherKlass.instance # ObjectSpace.each_object(OtherKlass){} # # => 1 # # # This behavior is preserved under inheritance and cloning. # # == Implementation # # This above is achieved by: # # * Making Klass.new and Klass.allocate private. # # * Overriding Klass.inherited(sub_klass) and Klass.clone() to ensure that the # Singleton properties are kept when inherited and cloned. # # * Providing the Klass.instance() method that returns the same object each # time it is called. # # * Overriding Klass._load(str) to call Klass.instance(). # # * Overriding Klass#clone and Klass#dup to raise TypeErrors to prevent # cloning or duping. # # == Singleton and Marshal # # By default Singleton's #_dump(depth) returns the empty string. Marshalling by # default will strip state information, e.g. instance variables and taint # state, from the instance. Classes using Singleton can provide custom # _load(str) and _dump(depth) methods to retain some of the previous state of # the instance. # # require 'singleton' # # class Example # include Singleton # attr_accessor :keep, :strip # def _dump(depth) # # this strips the @strip information from the instance # Marshal.dump(@keep, depth) # end # # def self._load(str) # instance.keep = Marshal.load(str) # instance # end # end # # a = Example.instance # a.keep = "keep this" # a.strip = "get rid of this" # a.taint # # stored_state = Marshal.dump(a) # # a.keep = nil # a.strip = nil # b = Marshal.load(stored_state) # p a == b # => true # p a.keep # => "keep this" # p a.strip # => nil # module Singleton # Raises a TypeError to prevent cloning. def clone raise TypeError, "can't clone instance of singleton #{self.class}" end # Raises a TypeError to prevent duping. def dup raise TypeError, "can't dup instance of singleton #{self.class}" end # By default, do not retain any state when marshalling. def _dump(depth = -1) '' end module SingletonClassMethods # :nodoc: def clone # :nodoc: Singleton.__init__(super) end # By default calls instance(). Override to retain singleton state. def _load(str) instance end private def inherited(sub_klass) super Singleton.__init__(sub_klass) end end class << Singleton # :nodoc: def __init__(klass) # :nodoc: klass.instance_eval { @singleton__instance__ = nil @singleton__mutex__ = Mutex.new } def klass.instance # :nodoc: return @singleton__instance__ if @singleton__instance__ @singleton__mutex__.synchronize { return @singleton__instance__ if @singleton__instance__ @singleton__instance__ = new() } @singleton__instance__ end klass end private # extending an object with Singleton is a bad idea undef_method :extend_object def append_features(mod) # help out people counting on transitive mixins unless mod.instance_of?(Class) raise TypeError, "Inclusion of the OO-Singleton module in module #{mod}" end super end def included(klass) super klass.private_class_method :new, :allocate klass.extend SingletonClassMethods Singleton.__init__(klass) end end ## # :singleton-method: _load # By default calls instance(). Override to retain singleton state. end PK!8g**2.2.0/delegate.rbnu[# = delegate -- Support for the Delegation Pattern # # Documentation by James Edward Gray II and Gavin Sinclair ## # This library provides three different ways to delegate method calls to an # object. The easiest to use is SimpleDelegator. Pass an object to the # constructor and all methods supported by the object will be delegated. This # object can be changed later. # # Going a step further, the top level DelegateClass method allows you to easily # setup delegation through class inheritance. This is considerably more # flexible and thus probably the most common use for this library. # # Finally, if you need full control over the delegation scheme, you can inherit # from the abstract class Delegator and customize as needed. (If you find # yourself needing this control, have a look at Forwardable which is also in # the standard library. It may suit your needs better.) # # SimpleDelegator's implementation serves as a nice example if the use of # Delegator: # # class SimpleDelegator < Delegator # def initialize(obj) # super # pass obj to Delegator constructor, required # @delegate_sd_obj = obj # store obj for future use # end # # def __getobj__ # @delegate_sd_obj # return object we are delegating to, required # end # # def __setobj__(obj) # @delegate_sd_obj = obj # change delegation object, # # a feature we're providing # end # end # # == Notes # # Be advised, RDoc will not detect delegated methods. # class Delegator < BasicObject kernel = ::Kernel.dup kernel.class_eval do alias __raise__ raise [:to_s,:inspect,:=~,:!~,:===,:<=>,:eql?,:hash].each do |m| undef_method m end private_instance_methods.each do |m| if /\Ablock_given\?\z|iterator\?\z|\A__.*__\z/ =~ m next end undef_method m end end include kernel # :stopdoc: def self.const_missing(n) ::Object.const_get(n) end # :startdoc: ## # :method: raise # Use __raise__ if your Delegator does not have a object to delegate the # raise method call. # # # Pass in the _obj_ to delegate method calls to. All methods supported by # _obj_ will be delegated to. # def initialize(obj) __setobj__(obj) end # # Handles the magic of delegation through \_\_getobj\_\_. # def method_missing(m, *args, &block) r = true target = self.__getobj__ {r = false} begin if r && target.respond_to?(m) target.__send__(m, *args, &block) elsif ::Kernel.respond_to?(m, true) ::Kernel.instance_method(m).bind(self).(*args, &block) else super(m, *args, &block) end ensure $@.delete_if {|t| %r"\A#{Regexp.quote(__FILE__)}:(?:#{[__LINE__-7, __LINE__-5, __LINE__-3].join('|')}):"o =~ t} if $@ end end # # Checks for a method provided by this the delegate object by forwarding the # call through \_\_getobj\_\_. # def respond_to_missing?(m, include_private) r = true target = self.__getobj__ {r = false} r &&= target.respond_to?(m, include_private) if r && include_private && !target.respond_to?(m, false) warn "#{caller(3)[0]}: delegator does not forward private method \##{m}" return false end r end # # Returns the methods available to this delegate object as the union # of this object's and \_\_getobj\_\_ methods. # def methods(all=true) __getobj__.methods(all) | super end # # Returns the methods available to this delegate object as the union # of this object's and \_\_getobj\_\_ public methods. # def public_methods(all=true) __getobj__.public_methods(all) | super end # # Returns the methods available to this delegate object as the union # of this object's and \_\_getobj\_\_ protected methods. # def protected_methods(all=true) __getobj__.protected_methods(all) | super end # Note: no need to specialize private_methods, since they are not forwarded # # Returns true if two objects are considered of equal value. # def ==(obj) return true if obj.equal?(self) self.__getobj__ == obj end # # Returns true if two objects are not considered of equal value. # def !=(obj) return false if obj.equal?(self) __getobj__ != obj end # # Delegates ! to the \_\_getobj\_\_ # def ! !__getobj__ end # # This method must be overridden by subclasses and should return the object # method calls are being delegated to. # def __getobj__ __raise__ ::NotImplementedError, "need to define `__getobj__'" end # # This method must be overridden by subclasses and change the object delegate # to _obj_. # def __setobj__(obj) __raise__ ::NotImplementedError, "need to define `__setobj__'" end # # Serialization support for the object returned by \_\_getobj\_\_. # def marshal_dump ivars = instance_variables.reject {|var| /\A@delegate_/ =~ var} [ :__v2__, ivars, ivars.map{|var| instance_variable_get(var)}, __getobj__ ] end # # Reinitializes delegation from a serialized object. # def marshal_load(data) version, vars, values, obj = data if version == :__v2__ vars.each_with_index{|var, i| instance_variable_set(var, values[i])} __setobj__(obj) else __setobj__(data) end end def initialize_clone(obj) # :nodoc: self.__setobj__(obj.__getobj__.clone) end def initialize_dup(obj) # :nodoc: self.__setobj__(obj.__getobj__.dup) end private :initialize_clone, :initialize_dup ## # :method: trust # Trust both the object returned by \_\_getobj\_\_ and self. # ## # :method: untrust # Untrust both the object returned by \_\_getobj\_\_ and self. # ## # :method: taint # Taint both the object returned by \_\_getobj\_\_ and self. # ## # :method: untaint # Untaint both the object returned by \_\_getobj\_\_ and self. # ## # :method: freeze # Freeze both the object returned by \_\_getobj\_\_ and self. # [:trust, :untrust, :taint, :untaint, :freeze].each do |method| define_method method do __getobj__.send(method) super() end end @delegator_api = self.public_instance_methods def self.public_api # :nodoc: @delegator_api end end ## # A concrete implementation of Delegator, this class provides the means to # delegate all supported method calls to the object passed into the constructor # and even to change the object being delegated to at a later time with # #__setobj__. # # class User # def born_on # Date.new(1989, 9, 10) # end # end # # class UserDecorator < SimpleDelegator # def birth_year # born_on.year # end # end # # decorated_user = UserDecorator.new(User.new) # decorated_user.birth_year #=> 1989 # decorated_user.__getobj__ #=> # # # A SimpleDelegator instance can take advantage of the fact that SimpleDelegator # is a subclass of +Delegator+ to call super to have methods called on # the object being delegated to. # # class SuperArray < SimpleDelegator # def [](*args) # super + 1 # end # end # # SuperArray.new([1])[0] #=> 2 # # Here's a simple example that takes advantage of the fact that # SimpleDelegator's delegation object can be changed at any time. # # class Stats # def initialize # @source = SimpleDelegator.new([]) # end # # def stats(records) # @source.__setobj__(records) # # "Elements: #{@source.size}\n" + # " Non-Nil: #{@source.compact.size}\n" + # " Unique: #{@source.uniq.size}\n" # end # end # # s = Stats.new # puts s.stats(%w{James Edward Gray II}) # puts # puts s.stats([1, 2, 3, nil, 4, 5, 1, 2]) # # Prints: # # Elements: 4 # Non-Nil: 4 # Unique: 4 # # Elements: 8 # Non-Nil: 7 # Unique: 6 # class SimpleDelegator Edward # names.__setobj__(%w{Gavin Sinclair}) # puts names[1] # => Sinclair # def __setobj__(obj) __raise__ ::ArgumentError, "cannot delegate to self" if self.equal?(obj) @delegate_sd_obj = obj end end def Delegator.delegating_block(mid) # :nodoc: lambda do |*args, &block| target = self.__getobj__ begin target.__send__(mid, *args, &block) ensure $@.delete_if {|t| /\A#{Regexp.quote(__FILE__)}:#{__LINE__-2}:/o =~ t} if $@ end end end # # The primary interface to this library. Use to setup delegation when defining # your class. # # class MyClass < DelegateClass(ClassToDelegateTo) # Step 1 # def initialize # super(obj_of_ClassToDelegateTo) # Step 2 # end # end # # Here's a sample of use from Tempfile which is really a File object with a # few special rules about storage location and when the File should be # deleted. That makes for an almost textbook perfect example of how to use # delegation. # # class Tempfile < DelegateClass(File) # # constant and class member data initialization... # # def initialize(basename, tmpdir=Dir::tmpdir) # # build up file path/name in var tmpname... # # @tmpfile = File.open(tmpname, File::RDWR|File::CREAT|File::EXCL, 0600) # # # ... # # super(@tmpfile) # # # below this point, all methods of File are supported... # end # # # ... # end # def DelegateClass(superclass) klass = Class.new(Delegator) methods = superclass.instance_methods methods -= ::Delegator.public_api methods -= [:to_s,:inspect,:=~,:!~,:===] klass.module_eval do def __getobj__ # :nodoc: unless defined?(@delegate_dc_obj) return yield if block_given? __raise__ ::ArgumentError, "not delegated" end @delegate_dc_obj end def __setobj__(obj) # :nodoc: __raise__ ::ArgumentError, "cannot delegate to self" if self.equal?(obj) @delegate_dc_obj = obj end methods.each do |method| define_method(method, Delegator.delegating_block(method)) end end klass.define_singleton_method :public_instance_methods do |all=true| super(all) - superclass.protected_instance_methods end klass.define_singleton_method :protected_instance_methods do |all=true| super(all) | superclass.protected_instance_methods end return klass end PK!9Q_2.2.0/json/version.rbnu[module JSON # JSON version VERSION = '1.8.1.1' VERSION_ARRAY = VERSION.split(/\./).map { |x| x.to_i } # :nodoc: VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc: VERSION_MINOR = VERSION_ARRAY[1] # :nodoc: VERSION_BUILD = VERSION_ARRAY[2] # :nodoc: end PK! 2.2.0/json/ext.rbnu[if ENV['SIMPLECOV_COVERAGE'].to_i == 1 require 'simplecov' SimpleCov.start do add_filter "/tests/" end end require 'json/common' module JSON # This module holds all the modules/classes that implement JSON's # functionality as C extensions. module Ext require 'json/ext/parser' require 'json/ext/generator' $DEBUG and warn "Using Ext extension for JSON." JSON.parser = Parser JSON.generator = Generator end JSON_LOADED = true unless defined?(::JSON::JSON_LOADED) end PK! G@@2.2.0/json/generic_object.rbnu[require 'ostruct' module JSON class GenericObject < OpenStruct class << self alias [] new def json_creatable? @json_creatable end attr_writer :json_creatable def json_create(data) data = data.dup data.delete JSON.create_id self[data] end def from_hash(object) case when object.respond_to?(:to_hash) result = new object.to_hash.each do |key, value| result[key] = from_hash(value) end result when object.respond_to?(:to_ary) object.to_ary.map { |a| from_hash(a) } else object end end def load(source, proc = nil, opts = {}) result = ::JSON.load(source, proc, opts.merge(:object_class => self)) result.nil? ? new : result end def dump(obj, *args) ::JSON.dump(obj, *args) end end self.json_creatable = false def to_hash table end def [](name) table[name.to_sym] end def []=(name, value) __send__ "#{name}=", value end def |(other) self.class[other.to_hash.merge(to_hash)] end def as_json(*) { JSON.create_id => self.class.name }.merge to_hash end def to_json(*a) as_json.to_json(*a) end end end PK!w>>2.2.0/json/common.rbnu[require 'json/version' require 'json/generic_object' module JSON class << self # If _object_ is string-like, parse the string and return the parsed result # as a Ruby data structure. Otherwise generate a JSON text from the Ruby # data structure object and return it. # # The _opts_ argument is passed through to generate/parse respectively. See # generate and parse for their documentation. def [](object, opts = {}) if object.respond_to? :to_str JSON.parse(object.to_str, opts) else JSON.generate(object, opts) end end # Returns the JSON parser class that is used by JSON. This is either # JSON::Ext::Parser or JSON::Pure::Parser. attr_reader :parser # Set the JSON parser class _parser_ to be used by JSON. def parser=(parser) # :nodoc: @parser = parser remove_const :Parser if JSON.const_defined_in?(self, :Parser) const_set :Parser, parser end # Return the constant located at _path_. The format of _path_ has to be # either ::A::B::C or A::B::C. In any case, A has to be located at the top # level (absolute namespace path?). If there doesn't exist a constant at # the given path, an ArgumentError is raised. def deep_const_get(path) # :nodoc: path.to_s.split(/::/).inject(Object) do |p, c| case when c.empty? then p when JSON.const_defined_in?(p, c) then p.const_get(c) else begin p.const_missing(c) rescue NameError => e raise ArgumentError, "can't get const #{path}: #{e}" end end end end # Set the module _generator_ to be used by JSON. def generator=(generator) # :nodoc: old, $VERBOSE = $VERBOSE, nil @generator = generator generator_methods = generator::GeneratorMethods for const in generator_methods.constants klass = deep_const_get(const) modul = generator_methods.const_get(const) klass.class_eval do instance_methods(false).each do |m| m.to_s == 'to_json' and remove_method m end include modul end end self.state = generator::State const_set :State, self.state const_set :SAFE_STATE_PROTOTYPE, State.new const_set :FAST_STATE_PROTOTYPE, State.new( :indent => '', :space => '', :object_nl => "", :array_nl => "", :max_nesting => false ) const_set :PRETTY_STATE_PROTOTYPE, State.new( :indent => ' ', :space => ' ', :object_nl => "\n", :array_nl => "\n" ) ensure $VERBOSE = old end # Returns the JSON generator module that is used by JSON. This is # either JSON::Ext::Generator or JSON::Pure::Generator. attr_reader :generator # Returns the JSON generator state class that is used by JSON. This is # either JSON::Ext::Generator::State or JSON::Pure::Generator::State. attr_accessor :state # This is create identifier, which is used to decide if the _json_create_ # hook of a class should be called. It defaults to 'json_class'. attr_accessor :create_id end self.create_id = 'json_class' NaN = 0.0/0 Infinity = 1.0/0 MinusInfinity = -Infinity # The base exception for JSON errors. class JSONError < StandardError def self.wrap(exception) obj = new("Wrapped(#{exception.class}): #{exception.message.inspect}") obj.set_backtrace exception.backtrace obj end end # This exception is raised if a parser error occurs. class ParserError < JSONError; end # This exception is raised if the nesting of parsed data structures is too # deep. class NestingError < ParserError; end # :stopdoc: class CircularDatastructure < NestingError; end # :startdoc: # This exception is raised if a generator or unparser error occurs. class GeneratorError < JSONError; end # For backwards compatibility UnparserError = GeneratorError # This exception is raised if the required unicode support is missing on the # system. Usually this means that the iconv library is not installed. class MissingUnicodeSupport < JSONError; end module_function # Parse the JSON document _source_ into a Ruby data structure and return it. # # _opts_ can have the following # keys: # * *max_nesting*: The maximum depth of nesting allowed in the parsed data # structures. Disable depth checking with :max_nesting => false. It defaults # to 100. # * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in # defiance of RFC 4627 to be parsed by the Parser. This option defaults # to false. # * *symbolize_names*: If set to true, returns symbols for the names # (keys) in a JSON object. Otherwise strings are returned. Strings are # the default. # * *create_additions*: If set to false, the Parser doesn't create # additions even if a matching class and create_id was found. This option # defaults to true. # * *object_class*: Defaults to Hash # * *array_class*: Defaults to Array def parse(source, opts = {}) Parser.new(source, opts).parse end # Parse the JSON document _source_ into a Ruby data structure and return it. # The bang version of the parse method defaults to the more dangerous values # for the _opts_ hash, so be sure only to parse trusted _source_ documents. # # _opts_ can have the following keys: # * *max_nesting*: The maximum depth of nesting allowed in the parsed data # structures. Enable depth checking with :max_nesting => anInteger. The parse! # methods defaults to not doing max depth checking: This can be dangerous # if someone wants to fill up your stack. # * *allow_nan*: If set to true, allow NaN, Infinity, and -Infinity in # defiance of RFC 4627 to be parsed by the Parser. This option defaults # to true. # * *create_additions*: If set to false, the Parser doesn't create # additions even if a matching class and create_id was found. This option # defaults to true. def parse!(source, opts = {}) opts = { :max_nesting => false, :allow_nan => true }.update(opts) Parser.new(source, opts).parse end # Generate a JSON document from the Ruby data structure _obj_ and return # it. _state_ is * a JSON::State object, # * or a Hash like object (responding to to_hash), # * an object convertible into a hash by a to_h method, # that is used as or to configure a State object. # # It defaults to a state object, that creates the shortest possible JSON text # in one line, checks for circular data structures and doesn't allow NaN, # Infinity, and -Infinity. # # A _state_ hash can have the following keys: # * *indent*: a string used to indent levels (default: ''), # * *space*: a string that is put after, a : or , delimiter (default: ''), # * *space_before*: a string that is put before a : pair delimiter (default: ''), # * *object_nl*: a string that is put at the end of a JSON object (default: ''), # * *array_nl*: a string that is put at the end of a JSON array (default: ''), # * *allow_nan*: true if NaN, Infinity, and -Infinity should be # generated, otherwise an exception is thrown if these values are # encountered. This options defaults to false. # * *max_nesting*: The maximum depth of nesting allowed in the data # structures from which JSON is to be generated. Disable depth checking # with :max_nesting => false, it defaults to 100. # # See also the fast_generate for the fastest creation method with the least # amount of sanity checks, and the pretty_generate method for some # defaults for pretty output. def generate(obj, opts = nil) if State === opts state, opts = opts, nil else state = SAFE_STATE_PROTOTYPE.dup end if opts if opts.respond_to? :to_hash opts = opts.to_hash elsif opts.respond_to? :to_h opts = opts.to_h else raise TypeError, "can't convert #{opts.class} into Hash" end state = state.configure(opts) end state.generate(obj) end # :stopdoc: # I want to deprecate these later, so I'll first be silent about them, and # later delete them. alias unparse generate module_function :unparse # :startdoc: # Generate a JSON document from the Ruby data structure _obj_ and return it. # This method disables the checks for circles in Ruby objects. # # *WARNING*: Be careful not to pass any Ruby data structures with circles as # _obj_ argument because this will cause JSON to go into an infinite loop. def fast_generate(obj, opts = nil) if State === opts state, opts = opts, nil else state = FAST_STATE_PROTOTYPE.dup end if opts if opts.respond_to? :to_hash opts = opts.to_hash elsif opts.respond_to? :to_h opts = opts.to_h else raise TypeError, "can't convert #{opts.class} into Hash" end state.configure(opts) end state.generate(obj) end # :stopdoc: # I want to deprecate these later, so I'll first be silent about them, and later delete them. alias fast_unparse fast_generate module_function :fast_unparse # :startdoc: # Generate a JSON document from the Ruby data structure _obj_ and return it. # The returned document is a prettier form of the document returned by # #unparse. # # The _opts_ argument can be used to configure the generator. See the # generate method for a more detailed explanation. def pretty_generate(obj, opts = nil) if State === opts state, opts = opts, nil else state = PRETTY_STATE_PROTOTYPE.dup end if opts if opts.respond_to? :to_hash opts = opts.to_hash elsif opts.respond_to? :to_h opts = opts.to_h else raise TypeError, "can't convert #{opts.class} into Hash" end state.configure(opts) end state.generate(obj) end # :stopdoc: # I want to deprecate these later, so I'll first be silent about them, and later delete them. alias pretty_unparse pretty_generate module_function :pretty_unparse # :startdoc: class << self # The global default options for the JSON.load method: # :max_nesting: false # :allow_nan: true # :quirks_mode: true attr_accessor :load_default_options end self.load_default_options = { :max_nesting => false, :allow_nan => true, :quirks_mode => true, :create_additions => true, } # Load a ruby data structure from a JSON _source_ and return it. A source can # either be a string-like object, an IO-like object, or an object responding # to the read method. If _proc_ was given, it will be called with any nested # Ruby object as an argument recursively in depth first order. To modify the # default options pass in the optional _options_ argument as well. # # BEWARE: This method is meant to serialise data from trusted user input, # like from your own database server or clients under your control, it could # be dangerous to allow untrusted users to pass JSON sources into it. The # default options for the parser can be changed via the load_default_options # method. # # This method is part of the implementation of the load/dump interface of # Marshal and YAML. def load(source, proc = nil, options = {}) opts = load_default_options.merge options if source.respond_to? :to_str source = source.to_str elsif source.respond_to? :to_io source = source.to_io.read elsif source.respond_to?(:read) source = source.read end if opts[:quirks_mode] && (source.nil? || source.empty?) source = 'null' end result = parse(source, opts) recurse_proc(result, &proc) if proc result end # Recursively calls passed _Proc_ if the parsed data structure is an _Array_ or _Hash_ def recurse_proc(result, &proc) case result when Array result.each { |x| recurse_proc x, &proc } proc.call result when Hash result.each { |x, y| recurse_proc x, &proc; recurse_proc y, &proc } proc.call result else proc.call result end end alias restore load module_function :restore class << self # The global default options for the JSON.dump method: # :max_nesting: false # :allow_nan: true # :quirks_mode: true attr_accessor :dump_default_options end self.dump_default_options = { :max_nesting => false, :allow_nan => true, :quirks_mode => true, } # Dumps _obj_ as a JSON string, i.e. calls generate on the object and returns # the result. # # If anIO (an IO-like object or an object that responds to the write method) # was given, the resulting JSON is written to it. # # If the number of nested arrays or objects exceeds _limit_, an ArgumentError # exception is raised. This argument is similar (but not exactly the # same!) to the _limit_ argument in Marshal.dump. # # The default options for the generator can be changed via the # dump_default_options method. # # This method is part of the implementation of the load/dump interface of # Marshal and YAML. def dump(obj, anIO = nil, limit = nil) if anIO and limit.nil? anIO = anIO.to_io if anIO.respond_to?(:to_io) unless anIO.respond_to?(:write) limit = anIO anIO = nil end end opts = JSON.dump_default_options limit and opts.update(:max_nesting => limit) result = generate(obj, opts) if anIO anIO.write result anIO else result end rescue JSON::NestingError raise ArgumentError, "exceed depth limit" end # Swap consecutive bytes of _string_ in place. def self.swap!(string) # :nodoc: 0.upto(string.size / 2) do |i| break unless string[2 * i + 1] string[2 * i], string[2 * i + 1] = string[2 * i + 1], string[2 * i] end string end # Shortuct for iconv. if ::String.method_defined?(:encode) # Encodes string using Ruby's _String.encode_ def self.iconv(to, from, string) string.encode(to, from) end else require 'iconv' # Encodes string using _iconv_ library def self.iconv(to, from, string) Iconv.conv(to, from, string) end end if ::Object.method(:const_defined?).arity == 1 def self.const_defined_in?(modul, constant) modul.const_defined?(constant) end else def self.const_defined_in?(modul, constant) modul.const_defined?(constant, false) end end end module ::Kernel private # Outputs _objs_ to STDOUT as JSON strings in the shortest form, that is in # one line. def j(*objs) objs.each do |obj| puts JSON::generate(obj, :allow_nan => true, :max_nesting => false) end nil end # Outputs _objs_ to STDOUT as JSON strings in a pretty format, with # indentation and over many lines. def jj(*objs) objs.each do |obj| puts JSON::pretty_generate(obj, :allow_nan => true, :max_nesting => false) end nil end # If _object_ is string-like, parse the string and return the parsed result as # a Ruby data structure. Otherwise, generate a JSON text from the Ruby data # structure object and return it. # # The _opts_ argument is passed through to generate/parse respectively. See # generate and parse for their documentation. def JSON(object, *args) if object.respond_to? :to_str JSON.parse(object.to_str, args.first) else JSON.generate(object, args.first) end end end # Extends any Class to include _json_creatable?_ method. class ::Class # Returns true if this class can be used to create an instance # from a serialised JSON string. The class has to implement a class # method _json_create_ that expects a hash as first parameter. The hash # should include the required data. def json_creatable? respond_to?(:json_create) end end PK!x`2.2.0/json/add/rational.rbnu[unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED require 'json' end defined?(::Rational) or require 'rational' class Rational def self.json_create(object) Rational(object['n'], object['d']) end def as_json(*) { JSON.create_id => self.class.name, 'n' => numerator, 'd' => denominator, } end def to_json(*) as_json.to_json end end PK!)K 2.2.0/json/add/exception.rbnu[unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED require 'json' end class Exception # Deserializes JSON string by constructing new Exception object with message # m and backtrace b serialized with to_json def self.json_create(object) result = new(object['m']) result.set_backtrace object['b'] result end # Returns a hash, that will be turned into a JSON object and represent this # object. def as_json(*) { JSON.create_id => self.class.name, 'm' => message, 'b' => backtrace, } end # Stores class name (Exception) with message m and backtrace array # b as JSON string def to_json(*args) as_json.to_json(*args) end end PK!frHH2.2.0/json/add/symbol.rbnu[unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED require 'json' end class Symbol # Returns a hash, that will be turned into a JSON object and represent this # object. def as_json(*) { JSON.create_id => self.class.name, 's' => to_s, } end # Stores class name (Symbol) with String representation of Symbol as a JSON string. def to_json(*a) as_json.to_json(*a) end # Deserializes JSON string by converting the string value stored in the object to a Symbol def self.json_create(o) o['s'].to_sym end end PK!c\2.2.0/json/add/complex.rbnu[unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED require 'json' end defined?(::Complex) or require 'complex' class Complex def self.json_create(object) Complex(object['r'], object['i']) end def as_json(*) { JSON.create_id => self.class.name, 'r' => real, 'i' => imag, } end def to_json(*) as_json.to_json end end PK!{>SS2.2.0/json/add/date.rbnu[unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED require 'json' end require 'date' class Date # Deserializes JSON string by converting Julian year y, month # m, day d and Day of Calendar Reform sg to Date. def self.json_create(object) civil(*object.values_at('y', 'm', 'd', 'sg')) end alias start sg unless method_defined?(:start) # Returns a hash, that will be turned into a JSON object and represent this # object. def as_json(*) { JSON.create_id => self.class.name, 'y' => year, 'm' => month, 'd' => day, 'sg' => start, } end # Stores class name (Date) with Julian year y, month m, day # d and Day of Calendar Reform sg as JSON string def to_json(*args) as_json.to_json(*args) end end PK!n\y2.2.0/json/add/time.rbnu[unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED require 'json' end class Time # Deserializes JSON string by converting time since epoch to Time def self.json_create(object) if usec = object.delete('u') # used to be tv_usec -> tv_nsec object['n'] = usec * 1000 end if instance_methods.include?(:tv_nsec) at(object['s'], Rational(object['n'], 1000)) else at(object['s'], object['n'] / 1000) end end # Returns a hash, that will be turned into a JSON object and represent this # object. def as_json(*) nanoseconds = [ tv_usec * 1000 ] respond_to?(:tv_nsec) and nanoseconds << tv_nsec nanoseconds = nanoseconds.max { JSON.create_id => self.class.name, 's' => tv_sec, 'n' => nanoseconds, } end # Stores class name (Time) with number of seconds since epoch and number of # microseconds for Time as JSON string def to_json(*args) as_json.to_json(*args) end end PK!9h2.2.0/json/add/regexp.rbnu[unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED require 'json' end class Regexp # Deserializes JSON string by constructing new Regexp object with source # s (Regexp or String) and options o serialized by # to_json def self.json_create(object) new(object['s'], object['o']) end # Returns a hash, that will be turned into a JSON object and represent this # object. def as_json(*) { JSON.create_id => self.class.name, 'o' => options, 's' => source, } end # Stores class name (Regexp) with options o and source s # (Regexp or String) as JSON string def to_json(*) as_json.to_json end end PK!882.2.0/json/add/bigdecimal.rbnu[unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED require 'json' end defined?(::BigDecimal) or require 'bigdecimal' class BigDecimal # Import a JSON Marshalled object. # # method used for JSON marshalling support. def self.json_create(object) BigDecimal._load object['b'] end # Marshal the object to JSON. # # method used for JSON marshalling support. def as_json(*) { JSON.create_id => self.class.name, 'b' => _dump, } end # return the JSON value def to_json(*) as_json.to_json end end PK!m2.2.0/json/add/date_time.rbnu[unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED require 'json' end require 'date' class DateTime # Deserializes JSON string by converting year y, month m, # day d, hour H, minute M, second S, # offset of and Day of Calendar Reform sg to DateTime. def self.json_create(object) args = object.values_at('y', 'm', 'd', 'H', 'M', 'S') of_a, of_b = object['of'].split('/') if of_b and of_b != '0' args << Rational(of_a.to_i, of_b.to_i) else args << of_a end args << object['sg'] civil(*args) end alias start sg unless method_defined?(:start) # Returns a hash, that will be turned into a JSON object and represent this # object. def as_json(*) { JSON.create_id => self.class.name, 'y' => year, 'm' => month, 'd' => day, 'H' => hour, 'M' => min, 'S' => sec, 'of' => offset.to_s, 'sg' => start, } end # Stores class name (DateTime) with Julian year y, month m, # day d, hour H, minute M, second S, # offset of and Day of Calendar Reform sg as JSON string def to_json(*args) as_json.to_json(*args) end end PK!Gxq2.2.0/json/add/struct.rbnu[unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED require 'json' end class Struct # Deserializes JSON string by constructing new Struct object with values # v serialized by to_json. def self.json_create(object) new(*object['v']) end # Returns a hash, that will be turned into a JSON object and represent this # object. def as_json(*) klass = self.class.name klass.to_s.empty? and raise JSON::JSONError, "Only named structs are supported!" { JSON.create_id => klass, 'v' => values, } end # Stores class name (Struct) with Struct values v as a JSON string. # Only named structs are supported. def to_json(*args) as_json.to_json(*args) end end PK!42.2.0/json/add/range.rbnu[unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED require 'json' end class Range # Deserializes JSON string by constructing new Range object with arguments # a serialized by to_json. def self.json_create(object) new(*object['a']) end # Returns a hash, that will be turned into a JSON object and represent this # object. def as_json(*) { JSON.create_id => self.class.name, 'a' => [ first, last, exclude_end? ] } end # Stores class name (Range) with JSON array of arguments a which # include first (integer), last (integer), and # exclude_end? (boolean) as JSON string. def to_json(*args) as_json.to_json(*args) end end PK!2>>2.2.0/json/add/core.rbnu[# This file requires the implementations of ruby core's custom objects for # serialisation/deserialisation. require 'json/add/date' require 'json/add/date_time' require 'json/add/exception' require 'json/add/range' require 'json/add/regexp' require 'json/add/struct' require 'json/add/symbol' require 'json/add/time' PK!*2.2.0/json/add/ostruct.rbnu[unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED require 'json' end require 'ostruct' class OpenStruct # Deserializes JSON string by constructing new Struct object with values # v serialized by to_json. def self.json_create(object) new(object['t'] || object[:t]) end # Returns a hash, that will be turned into a JSON object and represent this # object. def as_json(*) klass = self.class.name klass.to_s.empty? and raise JSON::JSONError, "Only named structs are supported!" { JSON.create_id => klass, 't' => table, } end # Stores class name (OpenStruct) with this struct's values v as a # JSON string. def to_json(*args) as_json.to_json(*args) end end PK!Րk 2.2.0/drb.rbnu[require 'drb/drb' PK!O2.2.0/webrick.rbnu[## # = WEB server toolkit. # # WEBrick is an HTTP server toolkit that can be configured as an HTTPS server, # a proxy server, and a virtual-host server. WEBrick features complete # logging of both server operations and HTTP access. WEBrick supports both # basic and digest authentication in addition to algorithms not in RFC 2617. # # A WEBrick server can be composed of multiple WEBrick servers or servlets to # provide differing behavior on a per-host or per-path basis. WEBrick # includes servlets for handling CGI scripts, ERb pages, Ruby blocks and # directory listings. # # WEBrick also includes tools for daemonizing a process and starting a process # at a higher privilege level and dropping permissions. # # == Starting an HTTP server # # To create a new WEBrick::HTTPServer that will listen to connections on port # 8000 and serve documents from the current user's public_html folder: # # require 'webrick' # # root = File.expand_path '~/public_html' # server = WEBrick::HTTPServer.new :Port => 8000, :DocumentRoot => root # # To run the server you will need to provide a suitable shutdown hook as # starting the server blocks the current thread: # # trap 'INT' do server.shutdown end # # server.start # # == Custom Behavior # # The easiest way to have a server perform custom operations is through # WEBrick::HTTPServer#mount_proc. The block given will be called with a # WEBrick::HTTPRequest with request info and a WEBrick::HTTPResponse which # must be filled in appropriately: # # server.mount_proc '/' do |req, res| # res.body = 'Hello, world!' # end # # Remember that +server.mount_proc+ must precede +server.start+. # # == Servlets # # Advanced custom behavior can be obtained through mounting a subclass of # WEBrick::HTTPServlet::AbstractServlet. Servlets provide more modularity # when writing an HTTP server than mount_proc allows. Here is a simple # servlet: # # class Simple < WEBrick::HTTPServlet::AbstractServlet # def do_GET request, response # status, content_type, body = do_stuff_with request # # response.status = 200 # response['Content-Type'] = 'text/plain' # response.body = 'Hello, World!' # end # end # # To initialize the servlet you mount it on the server: # # server.mount '/simple', Simple # # See WEBrick::HTTPServlet::AbstractServlet for more details. # # == Virtual Hosts # # A server can act as a virtual host for multiple host names. After creating # the listening host, additional hosts that do not listen can be created and # attached as virtual hosts: # # server = WEBrick::HTTPServer.new # ... # # vhost = WEBrick::HTTPServer.new :ServerName => 'vhost.example', # :DoNotListen => true, # ... # vhost.mount '/', ... # # server.virtual_host vhost # # If no +:DocumentRoot+ is provided and no servlets or procs are mounted on the # main server it will return 404 for all URLs. # # == HTTPS # # To create an HTTPS server you only need to enable SSL and provide an SSL # certificate name: # # require 'webrick' # require 'webrick/https' # # cert_name = [ # %w[CN localhost], # ] # # server = WEBrick::HTTPServer.new(:Port => 8000, # :SSLEnable => true, # :SSLCertName => cert_name) # # This will start the server with a self-generated self-signed certificate. # The certificate will be changed every time the server is restarted. # # To create a server with a pre-determined key and certificate you can provide # them: # # require 'webrick' # require 'webrick/https' # require 'openssl' # # cert = OpenSSL::X509::Certificate.new File.read '/path/to/cert.pem' # pkey = OpenSSL::PKey::RSA.new File.read '/path/to/pkey.pem' # # server = WEBrick::HTTPServer.new(:Port => 8000, # :SSLEnable => true, # :SSLCertificate => cert, # :SSLPrivateKey => pkey) # # == Proxy Server # # WEBrick can act as a proxy server: # # require 'webrick' # require 'webrick/httpproxy' # # proxy = WEBrick::HTTPProxyServer.new :Port => 8000 # # trap 'INT' do proxy.shutdown end # # See WEBrick::HTTPProxy for further details including modifying proxied # responses. # # == Basic and Digest authentication # # WEBrick provides both Basic and Digest authentication for regular and proxy # servers. See WEBrick::HTTPAuth, WEBrick::HTTPAuth::BasicAuth and # WEBrick::HTTPAuth::DigestAuth. # # == WEBrick as a Production Web Server # # WEBrick can be run as a production server for small loads. # # === Daemonizing # # To start a WEBrick server as a daemon simple run WEBrick::Daemon.start # before starting the server. # # === Dropping Permissions # # WEBrick can be started as one user to gain permission to bind to port 80 or # 443 for serving HTTP or HTTPS traffic then can drop these permissions for # regular operation. To listen on all interfaces for HTTP traffic: # # sockets = WEBrick::Utils.create_listeners nil, 80 # # Then drop privileges: # # WEBrick::Utils.su 'www' # # Then create a server that does not listen by default: # # server = WEBrick::HTTPServer.new :DoNotListen => true, # ... # # Then overwrite the listening sockets with the port 80 sockets: # # server.listeners.replace sockets # # === Logging # # WEBrick can separately log server operations and end-user access. For # server operations: # # log_file = File.open '/var/log/webrick.log', 'a+' # log = WEBrick::Log.new log_file # # For user access logging: # # access_log = [ # [log_file, WEBrick::AccessLog::COMBINED_LOG_FORMAT], # ] # # server = WEBrick::HTTPServer.new :Logger => log, :AccessLog => access_log # # See WEBrick::AccessLog for further log formats. # # === Log Rotation # # To rotate logs in WEBrick on a HUP signal (like syslogd can send), open the # log file in 'a+' mode (as above) and trap 'HUP' to reopen the log file: # # trap 'HUP' do log_file.reopen '/path/to/webrick.log', 'a+' # # == Copyright # # Author: IPR -- Internet Programming with Ruby -- writers # # Copyright (c) 2000 TAKAHASHI Masayoshi, GOTOU YUUZOU # Copyright (c) 2002 Internet Programming with Ruby writers. All rights # reserved. #-- # $IPR: webrick.rb,v 1.12 2002/10/01 17:16:31 gotoyuzo Exp $ module WEBrick end require 'webrick/compat.rb' require 'webrick/version.rb' require 'webrick/config.rb' require 'webrick/log.rb' require 'webrick/server.rb' require 'webrick/utils.rb' require 'webrick/accesslog' require 'webrick/htmlutils.rb' require 'webrick/httputils.rb' require 'webrick/cookie.rb' require 'webrick/httpversion.rb' require 'webrick/httpstatus.rb' require 'webrick/httprequest.rb' require 'webrick/httpresponse.rb' require 'webrick/httpserver.rb' require 'webrick/httpservlet.rb' require 'webrick/httpauth.rb' PK!Mh##2.2.0/xmlrpc/create.rbnu[# # Copyright (C) 2001, 2002, 2003 by Michael Neumann (mneumann@ntecs.de) # # $Id: create.rb 36958 2012-09-13 02:22:10Z zzak $ # require "date" require "xmlrpc/base64" module XMLRPC # :nodoc: module XMLWriter class Abstract def ele(name, *children) element(name, nil, *children) end def tag(name, txt) element(name, nil, text(txt)) end end class Simple < Abstract def document_to_str(doc) doc end def document(*params) params.join("") end def pi(name, *params) "" end def element(name, attrs, *children) raise "attributes not yet implemented" unless attrs.nil? if children.empty? "<#{name}/>" else "<#{name}>" + children.join("") + "" end end def text(txt) cleaned = txt.dup cleaned.gsub!(/&/, '&') cleaned.gsub!(//, '>') cleaned end end # class Simple class XMLParser < Abstract def initialize require "xmltreebuilder" end def document_to_str(doc) doc.to_s end def document(*params) XML::SimpleTree::Document.new(*params) end def pi(name, *params) XML::SimpleTree::ProcessingInstruction.new(name, *params) end def element(name, attrs, *children) XML::SimpleTree::Element.new(name, attrs, *children) end def text(txt) XML::SimpleTree::Text.new(txt) end end # class XMLParser Classes = [Simple, XMLParser] # yields an instance of each installed XML writer def self.each_installed_writer XMLRPC::XMLWriter::Classes.each do |klass| begin yield klass.new rescue LoadError end end end end # module XMLWriter # Creates XML-RPC call/response documents # class Create def initialize(xml_writer = nil) @writer = xml_writer || Config::DEFAULT_WRITER.new end def methodCall(name, *params) name = name.to_s if name !~ /[a-zA-Z0-9_.:\/]+/ raise ArgumentError, "Wrong XML-RPC method-name" end parameter = params.collect do |param| @writer.ele("param", conv2value(param)) end tree = @writer.document( @writer.pi("xml", 'version="1.0"'), @writer.ele("methodCall", @writer.tag("methodName", name), @writer.ele("params", *parameter) ) ) @writer.document_to_str(tree) + "\n" end # # Generates a XML-RPC methodResponse document # # When +is_ret+ is +false+ then the +params+ array must # contain only one element, which is a structure # of a fault return-value. # # When +is_ret+ is +true+ then a normal # return-value of all the given +params+ is created. # def methodResponse(is_ret, *params) if is_ret resp = params.collect do |param| @writer.ele("param", conv2value(param)) end resp = [@writer.ele("params", *resp)] else if params.size != 1 or params[0] === XMLRPC::FaultException raise ArgumentError, "no valid fault-structure given" end resp = @writer.ele("fault", conv2value(params[0].to_h)) end tree = @writer.document( @writer.pi("xml", 'version="1.0"'), @writer.ele("methodResponse", resp) ) @writer.document_to_str(tree) + "\n" end private # # Converts a Ruby object into a XML-RPC tag # def conv2value(param) # :doc: val = case param when Fixnum, Bignum # XML-RPC's int is 32bit int, and Fixnum also may be beyond 32bit if Config::ENABLE_BIGINT @writer.tag("i4", param.to_s) else if param >= -(2**31) and param <= (2**31-1) @writer.tag("i4", param.to_s) else raise "Bignum is too big! Must be signed 32-bit integer!" end end when TrueClass, FalseClass @writer.tag("boolean", param ? "1" : "0") when Symbol @writer.tag("string", param.to_s) when String @writer.tag("string", param) when NilClass if Config::ENABLE_NIL_CREATE @writer.ele("nil") else raise "Wrong type NilClass. Not allowed!" end when Float raise "Wrong value #{param}. Not allowed!" unless param.finite? @writer.tag("double", param.to_s) when Struct h = param.members.collect do |key| value = param[key] @writer.ele("member", @writer.tag("name", key.to_s), conv2value(value) ) end @writer.ele("struct", *h) when Hash # TODO: can a Hash be empty? h = param.collect do |key, value| @writer.ele("member", @writer.tag("name", key.to_s), conv2value(value) ) end @writer.ele("struct", *h) when Array # TODO: can an Array be empty? a = param.collect {|v| conv2value(v) } @writer.ele("array", @writer.ele("data", *a) ) when Time, Date, ::DateTime @writer.tag("dateTime.iso8601", param.strftime("%Y%m%dT%H:%M:%S")) when XMLRPC::DateTime @writer.tag("dateTime.iso8601", format("%.4d%02d%02dT%02d:%02d:%02d", *param.to_a)) when XMLRPC::Base64 @writer.tag("base64", param.encoded) else if Config::ENABLE_MARSHALLING and param.class.included_modules.include? XMLRPC::Marshallable # convert Ruby object into Hash ret = {"___class___" => param.class.name} param.instance_variables.each {|v| name = v[1..-1] val = param.instance_variable_get(v) if val.nil? ret[name] = val if Config::ENABLE_NIL_CREATE else ret[name] = val end } return conv2value(ret) else ok, pa = wrong_type(param) if ok return conv2value(pa) else raise "Wrong type!" end end end @writer.ele("value", val) end def wrong_type(value) false end end # class Create end # module XMLRPC PK!de!!2.2.0/xmlrpc/datetime.rbnu[# # xmlrpc/datetime.rb # Copyright (C) 2001, 2002, 2003 by Michael Neumann (mneumann@ntecs.de) # # Released under the same term of license as Ruby. # require "date" module XMLRPC # :nodoc: # This class is important to handle XMLRPC +dateTime.iso8601+ values, # correctly, because normal UNIX-dates, ie: Date, only handle dates # from year 1970 on, and ruby's native Time class handles dates without the # time component. # # XMLRPC::DateTime is able to store a XMLRPC +dateTime.iso8601+ value correctly. class DateTime # Return the value of the specified date/time component. attr_reader :year, :month, :day, :hour, :min, :sec # Set +value+ as the new date/time component. # # Raises ArgumentError if the given +value+ is out of range, or in the case # of XMLRPC::DateTime#year= if +value+ is not of type Integer. def year= (value) raise ArgumentError, "date/time out of range" unless value.is_a? Integer @year = value end # Set +value+ as the new date/time component. # # Raises an ArgumentError if the given +value+ isn't between 1 and 12. def month= (value) raise ArgumentError, "date/time out of range" unless (1..12).include? value @month = value end # Set +value+ as the new date/time component. # # Raises an ArgumentError if the given +value+ isn't between 1 and 31. def day= (value) raise ArgumentError, "date/time out of range" unless (1..31).include? value @day = value end # Set +value+ as the new date/time component. # # Raises an ArgumentError if the given +value+ isn't between 0 and 24. def hour= (value) raise ArgumentError, "date/time out of range" unless (0..24).include? value @hour = value end # Set +value+ as the new date/time component. # # Raises an ArgumentError if the given +value+ isn't between 0 and 59. def min= (value) raise ArgumentError, "date/time out of range" unless (0..59).include? value @min = value end # Set +value+ as the new date/time component. # # Raises an ArgumentError if the given +value+ isn't between 0 and 59. def sec= (value) raise ArgumentError, "date/time out of range" unless (0..59).include? value @sec = value end # Alias for XMLRPC::DateTime#month. alias mon month # Alias for XMLRPC::DateTime#month=. alias mon= month= # Creates a new XMLRPC::DateTime instance with the # parameters +year+, +month+, +day+ as date and # +hour+, +min+, +sec+ as time. # # Raises an ArgumentError if a parameter is out of range, # or if +year+ is not of the Integer type. def initialize(year, month, day, hour, min, sec) self.year, self.month, self.day = year, month, day self.hour, self.min, self.sec = hour, min, sec end # Return a Time object of the date/time which represents +self+. # If the @year is below 1970, this method returns +nil+, # because Time cannot handle years below 1970. # # The timezone used is GMT. def to_time if @year >= 1970 Time.gm(*to_a) else nil end end # Return a Date object of the date which represents +self+. # # The Date object do _not_ contain the time component (only date). def to_date Date.new(*to_a[0,3]) end # Returns all date/time components in an array. # # Returns +[year, month, day, hour, min, sec]+. def to_a [@year, @month, @day, @hour, @min, @sec] end # Returns whether or not all date/time components are an array. def ==(o) self.to_a == Array(o) rescue false end end end # module XMLRPC =begin = History $Id: datetime.rb 44024 2013-12-06 02:10:11Z hsbt $ =end PK!42.2.0/xmlrpc/utils.rbnu[# # Copyright (C) 2001, 2002, 2003 by Michael Neumann (mneumann@ntecs.de) # # $Id: utils.rb 36958 2012-09-13 02:22:10Z zzak $ # module XMLRPC # :nodoc: # This module enables a user-class to be marshalled # by XML-RPC for Ruby into a Hash, with one additional # key/value pair ___class___ => ClassName # module Marshallable end # Defines ParserWriterChooseMixin, which makes it possible to choose a # different XMLWriter and/or XMLParser then the default one. # # The Mixin is used in client.rb (class XMLRPC::Client) # and server.rb (class XMLRPC::BasicServer) module ParserWriterChooseMixin # Sets the XMLWriter to use for generating XML output. # # Should be an instance of a class from module XMLRPC::XMLWriter. # # If this method is not called, then XMLRPC::Config::DEFAULT_WRITER is used. def set_writer(writer) @create = Create.new(writer) self end # Sets the XMLParser to use for parsing XML documents. # # Should be an instance of a class from module XMLRPC::XMLParser. # # If this method is not called, then XMLRPC::Config::DEFAULT_PARSER is used. def set_parser(parser) @parser = parser self end private def create # if set_writer was not already called then call it now if @create.nil? then set_writer(Config::DEFAULT_WRITER.new) end @create end def parser # if set_parser was not already called then call it now if @parser.nil? then set_parser(Config::DEFAULT_PARSER.new) end @parser end end # module ParserWriterChooseMixin module Service # Base class for XMLRPC::Service::Interface definitions, used # by XMLRPC::BasicServer#add_handler class BasicInterface attr_reader :prefix, :methods def initialize(prefix) @prefix = prefix @methods = [] end def add_method(sig, help=nil, meth_name=nil) mname = nil sig = [sig] if sig.kind_of? String sig = sig.collect do |s| name, si = parse_sig(s) raise "Wrong signatures!" if mname != nil and name != mname mname = name si end @methods << [mname, meth_name || mname, sig, help] end private def parse_sig(sig) # sig is a String if sig =~ /^\s*(\w+)\s+([^(]+)(\(([^)]*)\))?\s*$/ params = [$1] name = $2.strip $4.split(",").each {|i| params << i.strip} if $4 != nil return name, params else raise "Syntax error in signature" end end end # class BasicInterface # # Class which wraps a XMLRPC::Service::Interface definition, used # by XMLRPC::BasicServer#add_handler # class Interface < BasicInterface def initialize(prefix, &p) raise "No interface specified" if p.nil? super(prefix) instance_eval(&p) end def get_methods(obj, delim=".") prefix = @prefix + delim @methods.collect { |name, meth, sig, help| [prefix + name.to_s, obj.method(meth).to_proc, sig, help] } end private def meth(*a) add_method(*a) end end # class Interface class PublicInstanceMethodsInterface < BasicInterface def initialize(prefix) super(prefix) end def get_methods(obj, delim=".") prefix = @prefix + delim obj.class.public_instance_methods(false).collect { |name| [prefix + name.to_s, obj.method(name).to_proc, nil, nil] } end end end # module Service # # Short-form to create a XMLRPC::Service::Interface # def self.interface(prefix, &p) Service::Interface.new(prefix, &p) end # Short-cut for creating a XMLRPC::Service::PublicInstanceMethodsInterface def self.iPIMethods(prefix) Service::PublicInstanceMethodsInterface.new(prefix) end module ParseContentType def parse_content_type(str) a, *b = str.split(";") return a.strip.downcase, *b end end end # module XMLRPC PK!8:O:O2.2.0/xmlrpc/server.rbnu[# xmlrpc/server.rb # Copyright (C) 2001, 2002, 2003, 2005 by Michael Neumann (mneumann@ntecs.de) # # Released under the same term of license as Ruby. require "xmlrpc/parser" require "xmlrpc/create" require "xmlrpc/config" require "xmlrpc/utils" # ParserWriterChooseMixin module XMLRPC # :nodoc: # This is the base class for all XML-RPC server-types (CGI, standalone). # You can add handler and set a default handler. # Do not use this server, as this is/should be an abstract class. # # === How the method to call is found # The arity (number of accepted arguments) of a handler (method or Proc # object) is compared to the given arguments submitted by the client for a # RPC, or Remote Procedure Call. # # A handler is only called if it accepts the number of arguments, otherwise # the search for another handler will go on. When at the end no handler was # found, the default_handler, XMLRPC::BasicServer#set_default_handler will be # called. # # With this technique it is possible to do overloading by number of parameters, but # only for Proc handler, because you cannot define two methods of the same name in # the same class. class BasicServer include ParserWriterChooseMixin include ParseContentType ERR_METHOD_MISSING = 1 ERR_UNCAUGHT_EXCEPTION = 2 ERR_MC_WRONG_PARAM = 3 ERR_MC_MISSING_PARAMS = 4 ERR_MC_MISSING_METHNAME = 5 ERR_MC_RECURSIVE_CALL = 6 ERR_MC_WRONG_PARAM_PARAMS = 7 ERR_MC_EXPECTED_STRUCT = 8 # Creates a new XMLRPC::BasicServer instance, which should not be # done, because XMLRPC::BasicServer is an abstract class. This # method should be called from a subclass indirectly by a +super+ call # in the initialize method. # # The parameter +class_delim+ is used by add_handler, see # XMLRPC::BasicServer#add_handler, when an object is added as a handler, to # delimit the object-prefix and the method-name. def initialize(class_delim=".") @handler = [] @default_handler = nil @service_hook = nil @class_delim = class_delim @create = nil @parser = nil add_multicall if Config::ENABLE_MULTICALL add_introspection if Config::ENABLE_INTROSPECTION end # Adds +aBlock+ to the list of handlers, with +name+ as the name of # the method. # # Parameters +signature+ and +help+ are used by the Introspection method if # specified, where +signature+ is either an Array containing strings each # representing a type of it's signature (the first is the return value) or # an Array of Arrays if the method has multiple signatures. # # Value type-names are "int, boolean, double, string, dateTime.iso8601, # base64, array, struct". # # Parameter +help+ is a String with information about how to call this method etc. # # When a method fails, it can tell the client by throwing an # XMLRPC::FaultException like in this example: # # s.add_handler("michael.div") do |a,b| # if b == 0 # raise XMLRPC::FaultException.new(1, "division by zero") # else # a / b # end # end # # In the case of b==0 the client gets an object back of type # XMLRPC::FaultException that has a +faultCode+ and +faultString+ field. # # This is the second form of (()). # To add an object write: # # server.add_handler("michael", MyHandlerClass.new) # # All public methods of MyHandlerClass are accessible to # the XML-RPC clients by michael."name of method". This is # where the +class_delim+ in XMLRPC::BasicServer.new plays it's role, a # XML-RPC method-name is defined by +prefix+ + +class_delim+ + "name # of method". # # The third form of +add_handler is to use XMLRPC::Service::Interface to # generate an object, which represents an interface (with signature and # help text) for a handler class. # # The +interface+ parameter must be an instance of XMLRPC::Service::Interface. # Adds all methods of +obj+ which are defined in the +interface+ to the server. # # This is the recommended way of adding services to a server! def add_handler(prefix, obj_or_signature=nil, help=nil, &block) if block_given? # proc-handler @handler << [prefix, block, obj_or_signature, help] else if prefix.kind_of? String # class-handler raise ArgumentError, "Expected non-nil value" if obj_or_signature.nil? @handler << [prefix + @class_delim, obj_or_signature] elsif prefix.kind_of? XMLRPC::Service::BasicInterface # class-handler with interface # add all methods @handler += prefix.get_methods(obj_or_signature, @class_delim) else raise ArgumentError, "Wrong type for parameter 'prefix'" end end self end # Returns the service-hook, which is called on each service request (RPC) # unless it's +nil+. def get_service_hook @service_hook end # A service-hook is called for each service request (RPC). # # You can use a service-hook for example to wrap existing methods and catch # exceptions of them or convert values to values recognized by XMLRPC. # # You can disable it by passing +nil+ as the +handler+ parameter. # # The service-hook is called with a Proc object along with any parameters. # # An example: # # server.set_service_hook {|obj, *args| # begin # ret = obj.call(*args) # call the original service-method # # could convert the return value # rescue # # rescue exceptions # end # } # def set_service_hook(&handler) @service_hook = handler self end # Returns the default-handler, which is called when no handler for # a method-name is found. # # It is either a Proc object or +nil+. def get_default_handler @default_handler end # Sets +handler+ as the default-handler, which is called when # no handler for a method-name is found. # # +handler+ is a code-block. # # The default-handler is called with the (XML-RPC) method-name as first # argument, and the other arguments are the parameters given by the # client-call. # # If no block is specified the default of XMLRPC::BasicServer is # used, which raises a XMLRPC::FaultException saying "method missing". def set_default_handler(&handler) @default_handler = handler self end # Adds the multi-call handler "system.multicall". def add_multicall add_handler("system.multicall", %w(array array), "Multicall Extension") do |arrStructs| unless arrStructs.is_a? Array raise XMLRPC::FaultException.new(ERR_MC_WRONG_PARAM, "system.multicall expects an array") end arrStructs.collect {|call| if call.is_a? Hash methodName = call["methodName"] params = call["params"] if params.nil? multicall_fault(ERR_MC_MISSING_PARAMS, "Missing params") elsif methodName.nil? multicall_fault(ERR_MC_MISSING_METHNAME, "Missing methodName") else if methodName == "system.multicall" multicall_fault(ERR_MC_RECURSIVE_CALL, "Recursive system.multicall forbidden") else unless params.is_a? Array multicall_fault(ERR_MC_WRONG_PARAM_PARAMS, "Parameter params have to be an Array") else ok, val = call_method(methodName, *params) if ok # correct return value [val] else # exception multicall_fault(val.faultCode, val.faultString) end end end end else multicall_fault(ERR_MC_EXPECTED_STRUCT, "system.multicall expected struct") end } end # end add_handler self end # Adds the introspection handlers "system.listMethods", # "system.methodSignature" and # "system.methodHelp", where only the first one works. def add_introspection add_handler("system.listMethods",%w(array), "List methods available on this XML-RPC server") do methods = [] @handler.each do |name, obj| if obj.kind_of? Proc methods << name else obj.class.public_instance_methods(false).each do |meth| methods << "#{name}#{meth}" end end end methods end add_handler("system.methodSignature", %w(array string), "Returns method signature") do |meth| sigs = [] @handler.each do |name, obj, sig| if obj.kind_of? Proc and sig != nil and name == meth if sig[0].kind_of? Array # sig contains multiple signatures, e.g. [["array"], ["array", "string"]] sig.each {|s| sigs << s} else # sig is a single signature, e.g. ["array"] sigs << sig end end end sigs.uniq! || sigs # remove eventually duplicated signatures end add_handler("system.methodHelp", %w(string string), "Returns help on using this method") do |meth| help = nil @handler.each do |name, obj, sig, hlp| if obj.kind_of? Proc and name == meth help = hlp break end end help || "" end self end def process(data) method, params = parser().parseMethodCall(data) handle(method, *params) end private def multicall_fault(nr, str) {"faultCode" => nr, "faultString" => str} end def dispatch(methodname, *args) for name, obj in @handler if obj.kind_of? Proc next unless methodname == name else next unless methodname =~ /^#{name}(.+)$/ next unless obj.respond_to? $1 obj = obj.method($1) end if check_arity(obj, args.size) if @service_hook.nil? return obj.call(*args) else return @service_hook.call(obj, *args) end end end if @default_handler.nil? raise XMLRPC::FaultException.new(ERR_METHOD_MISSING, "Method #{methodname} missing or wrong number of parameters!") else @default_handler.call(methodname, *args) end end # Returns +true+, if the arity of +obj+ matches +n_args+ def check_arity(obj, n_args) ary = obj.arity if ary >= 0 n_args == ary else n_args >= (ary+1).abs end end def call_method(methodname, *args) begin [true, dispatch(methodname, *args)] rescue XMLRPC::FaultException => e [false, e] rescue Exception => e [false, XMLRPC::FaultException.new(ERR_UNCAUGHT_EXCEPTION, "Uncaught exception #{e.message} in method #{methodname}")] end end def handle(methodname, *args) create().methodResponse(*call_method(methodname, *args)) end end # Implements a CGI-based XML-RPC server. # # require "xmlrpc/server" # # s = XMLRPC::CGIServer.new # # s.add_handler("michael.add") do |a,b| # a + b # end # # s.add_handler("michael.div") do |a,b| # if b == 0 # raise XMLRPC::FaultException.new(1, "division by zero") # else # a / b # end # end # # s.set_default_handler do |name, *args| # raise XMLRPC::FaultException.new(-99, "Method #{name} missing" + # " or wrong number of parameters!") # end # # s.serve # # # Note: Make sure that you don't write to standard-output in a # handler, or in any other part of your program, this would cause a CGI-based # server to fail! class CGIServer < BasicServer @@obj = nil # Creates a new XMLRPC::CGIServer instance. # # All parameters given are by-passed to XMLRPC::BasicServer.new. # # You can only create one XMLRPC::CGIServer instance, because more # than one makes no sense. def CGIServer.new(*a) @@obj = super(*a) if @@obj.nil? @@obj end def initialize(*a) super(*a) end # Call this after you have added all you handlers to the server. # # This method processes a XML-RPC method call and sends the answer # back to the client. def serve catch(:exit_serve) { length = ENV['CONTENT_LENGTH'].to_i http_error(405, "Method Not Allowed") unless ENV['REQUEST_METHOD'] == "POST" http_error(400, "Bad Request") unless parse_content_type(ENV['CONTENT_TYPE']).first == "text/xml" http_error(411, "Length Required") unless length > 0 # TODO: do we need a call to binmode? $stdin.binmode if $stdin.respond_to? :binmode data = $stdin.read(length) http_error(400, "Bad Request") if data.nil? or data.bytesize != length http_write(process(data), "Content-type" => "text/xml; charset=utf-8") } end private def http_error(status, message) err = "#{status} #{message}" msg = <<-"MSGEND" #{err}

    #{err}

    Unexpected error occurred while processing XML-RPC request!

    MSGEND http_write(msg, "Status" => err, "Content-type" => "text/html") throw :exit_serve # exit from the #serve method end def http_write(body, header) h = {} header.each {|key, value| h[key.to_s.capitalize] = value} h['Status'] ||= "200 OK" h['Content-length'] ||= body.bytesize.to_s str = "" h.each {|key, value| str << "#{key}: #{value}\r\n"} str << "\r\n#{body}" print str end end # Implements a XML-RPC server, which works with Apache mod_ruby. # # Use it in the same way as XMLRPC::CGIServer! class ModRubyServer < BasicServer # Creates a new XMLRPC::ModRubyServer instance. # # All parameters given are by-passed to XMLRPC::BasicServer.new. def initialize(*a) @ap = Apache::request super(*a) end # Call this after you have added all you handlers to the server. # # This method processes a XML-RPC method call and sends the answer # back to the client. def serve catch(:exit_serve) { header = {} @ap.headers_in.each {|key, value| header[key.capitalize] = value} length = header['Content-length'].to_i http_error(405, "Method Not Allowed") unless @ap.request_method == "POST" http_error(400, "Bad Request") unless parse_content_type(header['Content-type']).first == "text/xml" http_error(411, "Length Required") unless length > 0 # TODO: do we need a call to binmode? @ap.binmode data = @ap.read(length) http_error(400, "Bad Request") if data.nil? or data.bytesize != length http_write(process(data), 200, "Content-type" => "text/xml; charset=utf-8") } end private def http_error(status, message) err = "#{status} #{message}" msg = <<-"MSGEND" #{err}

    #{err}

    Unexpected error occurred while processing XML-RPC request!

    MSGEND http_write(msg, status, "Status" => err, "Content-type" => "text/html") throw :exit_serve # exit from the #serve method end def http_write(body, status, header) h = {} header.each {|key, value| h[key.to_s.capitalize] = value} h['Status'] ||= "200 OK" h['Content-length'] ||= body.bytesize.to_s h.each {|key, value| @ap.headers_out[key] = value } @ap.content_type = h["Content-type"] @ap.status = status.to_i @ap.send_http_header @ap.print body end end class WEBrickServlet < BasicServer; end # forward declaration # Implements a standalone XML-RPC server. The method XMLRPC::Server#serve is # left if a SIGHUP is sent to the program. # # require "xmlrpc/server" # # s = XMLRPC::Server.new(8080) # # s.add_handler("michael.add") do |a,b| # a + b # end # # s.add_handler("michael.div") do |a,b| # if b == 0 # raise XMLRPC::FaultException.new(1, "division by zero") # else # a / b # end # end # # s.set_default_handler do |name, *args| # raise XMLRPC::FaultException.new(-99, "Method #{name} missing" + # " or wrong number of parameters!") # end # # s.serve class Server < WEBrickServlet # Creates a new XMLRPC::Server instance, which is a XML-RPC server # listening on the given +port+ and accepts requests for the given +host+, # which is +localhost+ by default. # # The server is not started, to start it you have to call # XMLRPC::Server#serve. # # The optional +audit+ and +debug+ parameters are obsolete! # # All additionally provided parameters in *a are by-passed to # XMLRPC::BasicServer.new. def initialize(port=8080, host="127.0.0.1", maxConnections=4, stdlog=$stdout, audit=true, debug=true, *a) super(*a) require 'webrick' @server = WEBrick::HTTPServer.new(:Port => port, :BindAddress => host, :MaxClients => maxConnections, :Logger => WEBrick::Log.new(stdlog)) @server.mount("/", self) end # Call this after you have added all you handlers to the server. # This method starts the server to listen for XML-RPC requests and answer them. def serve signals = %w[INT TERM HUP] & Signal.list.keys signals.each { |signal| trap(signal) { @server.shutdown } } @server.start end # Stops and shuts the server down. def shutdown @server.shutdown end end # Implements a servlet for use with WEBrick, a pure Ruby (HTTP) server # framework. # # require "webrick" # require "xmlrpc/server" # # s = XMLRPC::WEBrickServlet.new # s.add_handler("michael.add") do |a,b| # a + b # end # # s.add_handler("michael.div") do |a,b| # if b == 0 # raise XMLRPC::FaultException.new(1, "division by zero") # else # a / b # end # end # # s.set_default_handler do |name, *args| # raise XMLRPC::FaultException.new(-99, "Method #{name} missing" + # " or wrong number of parameters!") # end # # httpserver = WEBrick::HTTPServer.new(:Port => 8080) # httpserver.mount("/RPC2", s) # trap("HUP") { httpserver.shutdown } # use 1 instead of "HUP" on Windows # httpserver.start class WEBrickServlet < BasicServer def initialize(*a) super require "webrick/httpstatus" @valid_ip = nil end # Deprecated from WEBrick/1.2.2, but does not break anything. def require_path_info? false end def get_instance(config, *options) # TODO: set config & options self end # Specifies the valid IP addresses that are allowed to connect to the server. # # Each IP is either a String or a Regexp. def set_valid_ip(*ip_addr) if ip_addr.size == 1 and ip_addr[0].nil? @valid_ip = nil else @valid_ip = ip_addr end end # Return the valid IP addresses that are allowed to connect to the server. # # See also, XMLRPC::Server#set_valid_ip def get_valid_ip @valid_ip end def service(request, response) if @valid_ip raise WEBrick::HTTPStatus::Forbidden unless @valid_ip.any? { |ip| request.peeraddr[3] =~ ip } end if request.request_method != "POST" raise WEBrick::HTTPStatus::MethodNotAllowed, "unsupported method `#{request.request_method}'." end if parse_content_type(request['Content-type']).first != "text/xml" raise WEBrick::HTTPStatus::BadRequest end length = (request['Content-length'] || 0).to_i raise WEBrick::HTTPStatus::LengthRequired unless length > 0 data = request.body if data.nil? or data.bytesize != length raise WEBrick::HTTPStatus::BadRequest end resp = process(data) if resp.nil? or resp.bytesize <= 0 raise WEBrick::HTTPStatus::InternalServerError end response.status = 200 response['Content-Length'] = resp.bytesize response['Content-Type'] = "text/xml; charset=utf-8" response.body = resp end end end # module XMLRPC =begin = History $Id: server.rb 44049 2013-12-07 10:27:27Z a_matsuda $ =end PK!~2.2.0/xmlrpc/marshal.rbnu[# # Copyright (C) 2001, 2002, 2003 by Michael Neumann (mneumann@ntecs.de) # # $Id: marshal.rb 36958 2012-09-13 02:22:10Z zzak $ # require "xmlrpc/parser" require "xmlrpc/create" require "xmlrpc/config" require "xmlrpc/utils" module XMLRPC # :nodoc: # Marshalling of XMLRPC::Create#methodCall and XMLRPC::Create#methodResponse class Marshal include ParserWriterChooseMixin class << self def dump_call( methodName, *params ) new.dump_call( methodName, *params ) end def dump_response( param ) new.dump_response( param ) end def load_call( stringOrReadable ) new.load_call( stringOrReadable ) end def load_response( stringOrReadable ) new.load_response( stringOrReadable ) end alias dump dump_response alias load load_response end # class self def initialize( parser = nil, writer = nil ) set_parser( parser ) set_writer( writer ) end def dump_call( methodName, *params ) create.methodCall( methodName, *params ) end def dump_response( param ) create.methodResponse( ! param.kind_of?( XMLRPC::FaultException ) , param ) end # Returns [ methodname, params ] def load_call( stringOrReadable ) parser.parseMethodCall( stringOrReadable ) end # Returns +paramOrFault+ def load_response( stringOrReadable ) parser.parseMethodResponse( stringOrReadable )[1] end end # class Marshal end PK!;Ww2.2.0/xmlrpc/config.rbnu[# # $Id: config.rb 47902 2014-10-13 08:53:16Z hsbt $ # Configuration file for XML-RPC for Ruby # module XMLRPC # :nodoc: module Config # or XMLWriter::XMLParser DEFAULT_WRITER = XMLWriter::Simple # === Available parsers # # * XMLParser::NQXMLTreeParser # * XMLParser::NQXMLStreamParser # * XMLParser::XMLTreeParser # * XMLParser::XMLStreamParser (fastest) # * XMLParser::REXMLStreamParser # * XMLParser::XMLScanStreamParser # * XMLParser::LibXMLStreamParser DEFAULT_PARSER = XMLParser::REXMLStreamParser # enable tag ENABLE_NIL_CREATE = false ENABLE_NIL_PARSER = false # allows integers greater than 32-bit if +true+ ENABLE_BIGINT = false # enable marshalling Ruby objects which include XMLRPC::Marshallable ENABLE_MARSHALLING = true # enable multiCall extension by default ENABLE_MULTICALL = false # enable Introspection extension by default ENABLE_INTROSPECTION = false end end PK!]bKbK2.2.0/xmlrpc/client.rbnu[# xmlrpc/client.rb # Copyright (C) 2001, 2002, 2003 by Michael Neumann (mneumann@ntecs.de) # # Released under the same term of license as Ruby. # # History # $Id: client.rb 54069 2016-03-09 14:01:02Z nagachika $ # require "xmlrpc/parser" require "xmlrpc/create" require "xmlrpc/config" require "xmlrpc/utils" # ParserWriterChooseMixin require "net/http" require "uri" module XMLRPC # :nodoc: # Provides remote procedure calls to a XML-RPC server. # # After setting the connection-parameters with XMLRPC::Client.new which # creates a new XMLRPC::Client instance, you can execute a remote procedure # by sending the XMLRPC::Client#call or XMLRPC::Client#call2 # message to this new instance. # # The given parameters indicate which method to call on the remote-side and # of course the parameters for the remote procedure. # # require "xmlrpc/client" # # server = XMLRPC::Client.new("www.ruby-lang.org", "/RPC2", 80) # begin # param = server.call("michael.add", 4, 5) # puts "4 + 5 = #{param}" # rescue XMLRPC::FaultException => e # puts "Error:" # puts e.faultCode # puts e.faultString # end # # or # # require "xmlrpc/client" # # server = XMLRPC::Client.new("www.ruby-lang.org", "/RPC2", 80) # ok, param = server.call2("michael.add", 4, 5) # if ok then # puts "4 + 5 = #{param}" # else # puts "Error:" # puts param.faultCode # puts param.faultString # end class Client USER_AGENT = "XMLRPC::Client (Ruby #{RUBY_VERSION})" include ParserWriterChooseMixin include ParseContentType # Creates an object which represents the remote XML-RPC server on the # given +host+. If the server is CGI-based, +path+ is the # path to the CGI-script, which will be called, otherwise (in the # case of a standalone server) +path+ should be "/RPC2". # +port+ is the port on which the XML-RPC server listens. # # If +proxy_host+ is given, then a proxy server listening at # +proxy_host+ is used. +proxy_port+ is the port of the # proxy server. # # Default values for +host+, +path+ and +port+ are 'localhost', '/RPC2' and # '80' respectively using SSL '443'. # # If +user+ and +password+ are given, each time a request is sent, # an Authorization header is sent. Currently only Basic Authentication is # implemented, no Digest. # # If +use_ssl+ is set to +true+, communication over SSL is enabled. # # Parameter +timeout+ is the time to wait for a XML-RPC response, defaults to 30. def initialize(host=nil, path=nil, port=nil, proxy_host=nil, proxy_port=nil, user=nil, password=nil, use_ssl=nil, timeout=nil) @http_header_extra = nil @http_last_response = nil @cookie = nil @host = host || "localhost" @path = path || "/RPC2" @proxy_host = proxy_host @proxy_port = proxy_port @proxy_host ||= 'localhost' if @proxy_port != nil @proxy_port ||= 8080 if @proxy_host != nil @use_ssl = use_ssl || false @timeout = timeout || 30 if use_ssl require "net/https" @port = port || 443 else @port = port || 80 end @user, @password = user, password set_auth # convert ports to integers @port = @port.to_i if @port != nil @proxy_port = @proxy_port.to_i if @proxy_port != nil # HTTP object for synchronous calls @http = net_http(@host, @port, @proxy_host, @proxy_port) @http.use_ssl = @use_ssl if @use_ssl @http.read_timeout = @timeout @http.open_timeout = @timeout @parser = nil @create = nil end class << self # Creates an object which represents the remote XML-RPC server at the # given +uri+. The URI should have a host, port, path, user and password. # Example: https://user:password@host:port/path # # Raises an ArgumentError if the +uri+ is invalid, # or if the protocol isn't http or https. # # If a +proxy+ is given it should be in the form of "host:port". # # The optional +timeout+ defaults to 30 seconds. def new2(uri, proxy=nil, timeout=nil) begin url = URI(uri) rescue URI::InvalidURIError => e raise ArgumentError, e.message, e.backtrace end unless URI::HTTP === url raise ArgumentError, "Wrong protocol specified. Only http or https allowed!" end proto = url.scheme user = url.user passwd = url.password host = url.host port = url.port path = url.path.empty? ? nil : url.request_uri proxy_host, proxy_port = (proxy || "").split(":") proxy_port = proxy_port.to_i if proxy_port self.new(host, path, port, proxy_host, proxy_port, user, passwd, (proto == "https"), timeout) end alias new_from_uri new2 # Receives a Hash and calls XMLRPC::Client.new # with the corresponding values. # # The +hash+ parameter has following case-insensitive keys: # * host # * path # * port # * proxy_host # * proxy_port # * user # * password # * use_ssl # * timeout def new3(hash={}) # convert all keys into lowercase strings h = {} hash.each { |k,v| h[k.to_s.downcase] = v } self.new(h['host'], h['path'], h['port'], h['proxy_host'], h['proxy_port'], h['user'], h['password'], h['use_ssl'], h['timeout']) end alias new_from_hash new3 end # Returns the Net::HTTP object for the client. If you want to # change HTTP client options except header, cookie, timeout, # user and password, use Net::HTTP directly. # # Since 2.1.0. attr_reader :http # Add additional HTTP headers to the request attr_accessor :http_header_extra # Returns the Net::HTTPResponse object of the last RPC. attr_reader :http_last_response # Get and set the HTTP Cookie header. attr_accessor :cookie # Return the corresponding attributes. attr_reader :timeout, :user, :password # Sets the Net::HTTP#read_timeout and Net::HTTP#open_timeout to # +new_timeout+ def timeout=(new_timeout) @timeout = new_timeout @http.read_timeout = @timeout @http.open_timeout = @timeout end # Changes the user for the Basic Authentication header to +new_user+ def user=(new_user) @user = new_user set_auth end # Changes the password for the Basic Authentication header to # +new_password+ def password=(new_password) @password = new_password set_auth end # Invokes the method named +method+ with the parameters given by # +args+ on the XML-RPC server. # # The +method+ parameter is converted into a String and should # be a valid XML-RPC method-name. # # Each parameter of +args+ must be of one of the following types, # where Hash, Struct and Array can contain any of these listed _types_: # # * Fixnum, Bignum # * TrueClass, FalseClass, +true+, +false+ # * String, Symbol # * Float # * Hash, Struct # * Array # * Date, Time, XMLRPC::DateTime # * XMLRPC::Base64 # * A Ruby object which class includes XMLRPC::Marshallable # (only if Config::ENABLE_MARSHALLING is +true+). # That object is converted into a hash, with one additional key/value # pair ___class___ which contains the class name # for restoring that object later. # # The method returns the return-value from the Remote Procedure Call. # # The type of the return-value is one of the types shown above. # # A Bignum is only allowed when it fits in 32-bit. A XML-RPC # +dateTime.iso8601+ type is always returned as a XMLRPC::DateTime object. # Struct is never returned, only a Hash, the same for a Symbol, where as a # String is always returned. XMLRPC::Base64 is returned as a String from # xmlrpc4r version 1.6.1 on. # # If the remote procedure returned a fault-structure, then a # XMLRPC::FaultException exception is raised, which has two accessor-methods # +faultCode+ an Integer, and +faultString+ a String. def call(method, *args) ok, param = call2(method, *args) if ok param else raise param end end # The difference between this method and XMLRPC::Client#call is, that # this method will NOT raise a XMLRPC::FaultException exception. # # The method returns an array of two values. The first value indicates if # the second value is +true+ or an XMLRPC::FaultException. # # Both are explained in XMLRPC::Client#call. # # Simple to remember: The "2" in "call2" denotes the number of values it returns. def call2(method, *args) request = create().methodCall(method, *args) data = do_rpc(request, false) parser().parseMethodResponse(data) end # Similar to XMLRPC::Client#call, however can be called concurrently and # use a new connection for each request. In contrast to the corresponding # method without the +_async+ suffix, which use connect-alive (one # connection for all requests). # # Note, that you have to use Thread to call these methods concurrently. # The following example calls two methods concurrently: # # Thread.new { # p client.call_async("michael.add", 4, 5) # } # # Thread.new { # p client.call_async("michael.div", 7, 9) # } # def call_async(method, *args) ok, param = call2_async(method, *args) if ok param else raise param end end # Same as XMLRPC::Client#call2, but can be called concurrently. # # See also XMLRPC::Client#call_async def call2_async(method, *args) request = create().methodCall(method, *args) data = do_rpc(request, true) parser().parseMethodResponse(data) end # You can use this method to execute several methods on a XMLRPC server # which support the multi-call extension. # # s.multicall( # ['michael.add', 3, 4], # ['michael.sub', 4, 5] # ) # # => [7, -1] def multicall(*methods) ok, params = multicall2(*methods) if ok params else raise params end end # Same as XMLRPC::Client#multicall, but returns two parameters instead of # raising an XMLRPC::FaultException. # # See XMLRPC::Client#call2 def multicall2(*methods) gen_multicall(methods, false) end # Similar to XMLRPC::Client#multicall, however can be called concurrently and # use a new connection for each request. In contrast to the corresponding # method without the +_async+ suffix, which use connect-alive (one # connection for all requests). # # Note, that you have to use Thread to call these methods concurrently. # The following example calls two methods concurrently: # # Thread.new { # p client.multicall_async("michael.add", 4, 5) # } # # Thread.new { # p client.multicall_async("michael.div", 7, 9) # } # def multicall_async(*methods) ok, params = multicall2_async(*methods) if ok params else raise params end end # Same as XMLRPC::Client#multicall2, but can be called concurrently. # # See also XMLRPC::Client#multicall_async def multicall2_async(*methods) gen_multicall(methods, true) end # Returns an object of class XMLRPC::Client::Proxy, initialized with # +prefix+ and +args+. # # A proxy object returned by this method behaves like XMLRPC::Client#call, # i.e. a call on that object will raise a XMLRPC::FaultException when a # fault-structure is returned by that call. def proxy(prefix=nil, *args) Proxy.new(self, prefix, args, :call) end # Almost the same like XMLRPC::Client#proxy only that a call on the returned # XMLRPC::Client::Proxy object will return two parameters. # # See XMLRPC::Client#call2 def proxy2(prefix=nil, *args) Proxy.new(self, prefix, args, :call2) end # Similar to XMLRPC::Client#proxy, however can be called concurrently and # use a new connection for each request. In contrast to the corresponding # method without the +_async+ suffix, which use connect-alive (one # connection for all requests). # # Note, that you have to use Thread to call these methods concurrently. # The following example calls two methods concurrently: # # Thread.new { # p client.proxy_async("michael.add", 4, 5) # } # # Thread.new { # p client.proxy_async("michael.div", 7, 9) # } # def proxy_async(prefix=nil, *args) Proxy.new(self, prefix, args, :call_async) end # Same as XMLRPC::Client#proxy2, but can be called concurrently. # # See also XMLRPC::Client#proxy_async def proxy2_async(prefix=nil, *args) Proxy.new(self, prefix, args, :call2_async) end private def net_http(host, port, proxy_host, proxy_port) Net::HTTP.new host, port, proxy_host, proxy_port end def dup_net_http http = net_http(@http.address, @http.port, @http.proxy_address, @http.proxy_port) http.proxy_user = @http.proxy_user http.proxy_pass = @http.proxy_pass if @http.use_ssl? http.use_ssl = true Net::HTTP::SSL_ATTRIBUTES.each do |attribute| http.__send__("#{attribute}=", @http.__send__(attribute)) end end http.read_timeout = @http.read_timeout http.open_timeout = @http.open_timeout http end def set_auth if @user.nil? @auth = nil else a = "#@user" a << ":#@password" if @password != nil @auth = "Basic " + [a].pack("m0") end end def do_rpc(request, async=false) header = { "User-Agent" => USER_AGENT, "Content-Type" => "text/xml; charset=utf-8", "Content-Length" => request.bytesize.to_s, "Connection" => (async ? "close" : "keep-alive") } header["Cookie"] = @cookie if @cookie header.update(@http_header_extra) if @http_header_extra if @auth != nil # add authorization header header["Authorization"] = @auth end resp = nil @http_last_response = nil if async # use a new HTTP object for each call http = dup_net_http # post request http.start { resp = http.request_post(@path, request, header) } else # reuse the HTTP object for each call => connection alive is possible # we must start connection explicitly first time so that http.request # does not assume that we don't want keepalive @http.start if not @http.started? # post request resp = @http.request_post(@path, request, header) end @http_last_response = resp data = resp.body if resp.code == "401" # Authorization Required raise "Authorization failed.\nHTTP-Error: #{resp.code} #{resp.message}" elsif resp.code[0,1] != "2" raise "HTTP-Error: #{resp.code} #{resp.message}" end # assume text/xml on instances where Content-Type header is not set ct_expected = resp["Content-Type"] || 'text/xml' ct = parse_content_type(ct_expected).first if ct != "text/xml" if ct == "text/html" raise "Wrong content-type (received '#{ct}' but expected 'text/xml'): \n#{data}" else raise "Wrong content-type (received '#{ct}' but expected 'text/xml')" end end expected = resp["Content-Length"] || "" if data.nil? or data.bytesize == 0 raise "Wrong size. Was #{data.bytesize}, should be #{expected}" end parse_set_cookies(resp.get_fields("Set-Cookie")) return data end def parse_set_cookies(set_cookies) return if set_cookies.nil? return if set_cookies.empty? require 'webrick/cookie' pairs = {} set_cookies.each do |set_cookie| cookie = WEBrick::Cookie.parse_set_cookie(set_cookie) pairs.delete(cookie.name) pairs[cookie.name] = cookie.value end cookies = pairs.collect do |name, value| WEBrick::Cookie.new(name, value).to_s end @cookie = cookies.join("; ") end def gen_multicall(methods=[], async=false) meth = :call2 meth = :call2_async if async ok, params = self.send(meth, "system.multicall", methods.collect {|m| {'methodName' => m[0], 'params' => m[1..-1]} } ) if ok params = params.collect do |param| if param.is_a? Array param[0] elsif param.is_a? Hash XMLRPC::FaultException.new(param["faultCode"], param["faultString"]) else raise "Wrong multicall return value" end end end return ok, params end # XML-RPC calls look nicer! # # You can call any method onto objects of that class - the object handles # XMLRPC::Client::Proxy#method_missing and will forward the method call to # a XML-RPC server. # # Don't use this class directly, instead use the public instance method # XMLRPC::Client#proxy or XMLRPC::Client#proxy2. # # require "xmlrpc/client" # # server = XMLRPC::Client.new("www.ruby-lang.org", "/RPC2", 80) # # michael = server.proxy("michael") # michael2 = server.proxy("michael", 4) # # # both calls should return the same value '9'. # p michael.add(4,5) # p michael2.add(5) class Proxy # Creates an object which provides XMLRPC::Client::Proxy#method_missing. # # The given +server+ must be an instance of XMLRPC::Client, which is the # XML-RPC server to be used for a XML-RPC call. # # +prefix+ and +delim+ will be prepended to the method name called onto this object. # # An optional parameter +meth+ is the method to use for a RPC. # It can be either, call, call2, call_async, call2_async # # +args+ are arguments which are automatically given to every XML-RPC # call before being provided through +method_missing+. def initialize(server, prefix, args=[], meth=:call, delim=".") @server = server @prefix = prefix ? prefix + delim : "" @args = args @meth = meth end # Every method call is forwarded to the XML-RPC server defined in # XMLRPC::Client::Proxy#new. # # Note: Inherited methods from class Object cannot be used as XML-RPC # names, because they get around +method_missing+. def method_missing(mid, *args) pre = @prefix + mid.to_s arg = @args + args @server.send(@meth, pre, *arg) end end # class Proxy end # class Client end # module XMLRPC PK!AS۠2.2.0/xmlrpc/base64.rbnu[# # xmlrpc/base64.rb # Copyright (C) 2001, 2002, 2003 by Michael Neumann (mneumann@ntecs.de) # # Released under the same term of license as Ruby. module XMLRPC # :nodoc: # This class is necessary for 'xmlrpc4r' to determine that a string should # be transmitted base64-encoded and not as a raw-string. # # You can use XMLRPC::Base64 on the client and server-side as a # parameter and/or return-value. class Base64 # Creates a new XMLRPC::Base64 instance with string +str+ as the # internal string. When +state+ is +:dec+ it assumes that the # string +str+ is not in base64 format (perhaps already decoded), # otherwise if +state+ is +:enc+ it decodes +str+ # and stores it as the internal string. def initialize(str, state = :dec) case state when :enc @str = Base64.decode(str) when :dec @str = str else raise ArgumentError, "wrong argument; either :enc or :dec" end end # Returns the decoded internal string. def decoded @str end # Returns the base64 encoded internal string. def encoded Base64.encode(@str) end # Decodes string +str+ with base64 and returns that value. def Base64.decode(str) str.gsub(/\s+/, "").unpack("m")[0] end # Encodes string +str+ with base64 and returns that value. def Base64.encode(str) [str].pack("m") end end end # module XMLRPC =begin = History $Id: base64.rb 36958 2012-09-13 02:22:10Z zzak $ =end PK!|$RR2.2.0/xmlrpc/parser.rbnu[# Copyright (C) 2001, 2002, 2003 by Michael Neumann (mneumann@ntecs.de) # # $Id: parser.rb 47902 2014-10-13 08:53:16Z hsbt $ # require "date" require "xmlrpc/base64" require "xmlrpc/datetime" module NQXML class Node def removeChild(node) @children.delete(node) end def childNodes @children end def hasChildNodes not @children.empty? end def [] (index) @children[index] end def nodeType if @entity.instance_of? NQXML::Text then :TEXT elsif @entity.instance_of? NQXML::Comment then :COMMENT #elsif @entity.instance_of? NQXML::Element then :ELEMENT elsif @entity.instance_of? NQXML::Tag then :ELEMENT else :ELSE end end def nodeValue #TODO: error when wrong Entity-type @entity.text end def nodeName #TODO: error when wrong Entity-type @entity.name end end # class Node end # module NQXML module XMLRPC # :nodoc: # Raised when the remote procedure returns a fault-structure, which has two # accessor-methods +faultCode+ an Integer, and +faultString+ a String. class FaultException < StandardError attr_reader :faultCode, :faultString # Creates a new XMLRPC::FaultException instance. # # +faultString+ is passed to StandardError as the +msg+ of the Exception. def initialize(faultCode, faultString) @faultCode = faultCode @faultString = faultString super(@faultString) end # The +faultCode+ and +faultString+ of the exception in a Hash. def to_h {"faultCode" => @faultCode, "faultString" => @faultString} end end # Helper class used to convert types. module Convert # Converts a String to an Integer # # See also String.to_i def self.int(str) str.to_i end # Converts a String to +true+ or +false+ # # Raises an exception if +str+ is not +0+ or +1+ def self.boolean(str) case str when "0" then false when "1" then true else raise "RPC-value of type boolean is wrong" end end # Converts a String to a Float # # See also String.to_f def self.double(str) str.to_f end # Converts a the given +str+ to a +dateTime.iso8601+ formatted date. # # Raises an exception if the String isn't in +dateTime.iso8601+ format. # # See also, XMLRPC::DateTime def self.dateTime(str) case str when /^(-?\d\d\d\d)-?(\d\d)-?(\d\d)T(\d\d):(\d\d):(\d\d)(?:Z|([+-])(\d\d):?(\d\d))?$/ a = [$1, $2, $3, $4, $5, $6].collect{|i| i.to_i} if $7 ofs = $8.to_i*3600 + $9.to_i*60 ofs = -ofs if $7=='+' utc = Time.utc(*a) + ofs a = [ utc.year, utc.month, utc.day, utc.hour, utc.min, utc.sec ] end XMLRPC::DateTime.new(*a) when /^(-?\d\d)-?(\d\d)-?(\d\d)T(\d\d):(\d\d):(\d\d)(Z|([+-]\d\d):(\d\d))?$/ a = [$1, $2, $3, $4, $5, $6].collect{|i| i.to_i} if a[0] < 70 a[0] += 2000 else a[0] += 1900 end if $7 ofs = $8.to_i*3600 + $9.to_i*60 ofs = -ofs if $7=='+' utc = Time.utc(*a) + ofs a = [ utc.year, utc.month, utc.day, utc.hour, utc.min, utc.sec ] end XMLRPC::DateTime.new(*a) else raise "wrong dateTime.iso8601 format " + str end end # Decodes the given +str+ using XMLRPC::Base64.decode def self.base64(str) XMLRPC::Base64.decode(str) end # Converts the given +hash+ to a marshalled object. # # Returns the given +hash+ if an exception occurs. def self.struct(hash) # convert to marshalled object klass = hash["___class___"] if klass.nil? or Config::ENABLE_MARSHALLING == false hash else begin mod = Module klass.split("::").each {|const| mod = mod.const_get(const.strip)} obj = mod.allocate hash.delete "___class___" hash.each {|key, value| obj.instance_variable_set("@#{ key }", value) if key =~ /^([a-zA-Z_]\w*)$/ } obj rescue hash end end end # Converts the given +hash+ to an XMLRPC::FaultException object by passing # the +faultCode+ and +faultString+ attributes of the Hash to # XMLRPC::FaultException.new # # Raises an Exception if the given +hash+ doesn't meet the requirements. # Those requirements being: # * 2 keys # * 'faultCode' key is an Integer # * 'faultString' key is a String def self.fault(hash) if hash.kind_of? Hash and hash.size == 2 and hash.has_key? "faultCode" and hash.has_key? "faultString" and hash["faultCode"].kind_of? Integer and hash["faultString"].kind_of? String XMLRPC::FaultException.new(hash["faultCode"], hash["faultString"]) else raise "wrong fault-structure: #{hash.inspect}" end end end # module Convert # Parser for XML-RPC call and response module XMLParser class AbstractTreeParser def parseMethodResponse(str) methodResponse_document(createCleanedTree(str)) end def parseMethodCall(str) methodCall_document(createCleanedTree(str)) end private # Removes all whitespaces but in the tags i4, i8, int, boolean.... # and all comments def removeWhitespacesAndComments(node) remove = [] childs = node.childNodes.to_a childs.each do |nd| case _nodeType(nd) when :TEXT # TODO: add nil? unless %w(i4 i8 int boolean string double dateTime.iso8601 base64).include? node.nodeName if node.nodeName == "value" if not node.childNodes.to_a.detect {|n| _nodeType(n) == :ELEMENT}.nil? remove << nd if nd.nodeValue.strip == "" end else remove << nd if nd.nodeValue.strip == "" end end when :COMMENT remove << nd else removeWhitespacesAndComments(nd) end end remove.each { |i| node.removeChild(i) } end def nodeMustBe(node, name) cmp = case name when Array name.include?(node.nodeName) when String name == node.nodeName else raise "error" end if not cmp then raise "wrong xml-rpc (name)" end node end # Returns, when successfully the only child-node def hasOnlyOneChild(node, name=nil) if node.childNodes.to_a.size != 1 raise "wrong xml-rpc (size)" end if name != nil then nodeMustBe(node.firstChild, name) end end def assert(b) if not b then raise "assert-fail" end end # The node `node` has empty string or string def text_zero_one(node) nodes = node.childNodes.to_a.size if nodes == 1 text(node.firstChild) elsif nodes == 0 "" else raise "wrong xml-rpc (size)" end end def integer(node) #TODO: check string for float because to_i returnsa # 0 when wrong string nodeMustBe(node, %w(i4 i8 int)) hasOnlyOneChild(node) Convert.int(text(node.firstChild)) end def boolean(node) nodeMustBe(node, "boolean") hasOnlyOneChild(node) Convert.boolean(text(node.firstChild)) end def v_nil(node) nodeMustBe(node, "nil") assert( node.childNodes.to_a.size == 0 ) nil end def string(node) nodeMustBe(node, "string") text_zero_one(node) end def double(node) #TODO: check string for float because to_f returnsa # 0.0 when wrong string nodeMustBe(node, "double") hasOnlyOneChild(node) Convert.double(text(node.firstChild)) end def dateTime(node) nodeMustBe(node, "dateTime.iso8601") hasOnlyOneChild(node) Convert.dateTime( text(node.firstChild) ) end def base64(node) nodeMustBe(node, "base64") #hasOnlyOneChild(node) Convert.base64(text_zero_one(node)) end def member(node) nodeMustBe(node, "member") assert( node.childNodes.to_a.size == 2 ) [ name(node[0]), value(node[1]) ] end def name(node) nodeMustBe(node, "name") #hasOnlyOneChild(node) text_zero_one(node) end def array(node) nodeMustBe(node, "array") hasOnlyOneChild(node, "data") data(node.firstChild) end def data(node) nodeMustBe(node, "data") node.childNodes.to_a.collect do |val| value(val) end end def param(node) nodeMustBe(node, "param") hasOnlyOneChild(node, "value") value(node.firstChild) end def methodResponse(node) nodeMustBe(node, "methodResponse") hasOnlyOneChild(node, %w(params fault)) child = node.firstChild case child.nodeName when "params" [ true, params(child,false) ] when "fault" [ false, fault(child) ] else raise "unexpected error" end end def methodName(node) nodeMustBe(node, "methodName") hasOnlyOneChild(node) text(node.firstChild) end def params(node, call=true) nodeMustBe(node, "params") if call node.childNodes.to_a.collect do |n| param(n) end else # response (only one param) hasOnlyOneChild(node) param(node.firstChild) end end def fault(node) nodeMustBe(node, "fault") hasOnlyOneChild(node, "value") f = value(node.firstChild) Convert.fault(f) end # _nodeType is defined in the subclass def text(node) assert( _nodeType(node) == :TEXT ) assert( node.hasChildNodes == false ) assert( node.nodeValue != nil ) node.nodeValue.to_s end def struct(node) nodeMustBe(node, "struct") hash = {} node.childNodes.to_a.each do |me| n, v = member(me) hash[n] = v end Convert.struct(hash) end def value(node) nodeMustBe(node, "value") nodes = node.childNodes.to_a.size if nodes == 0 return "" elsif nodes > 1 raise "wrong xml-rpc (size)" end child = node.firstChild case _nodeType(child) when :TEXT text_zero_one(node) when :ELEMENT case child.nodeName when "i4", "i8", "int" then integer(child) when "boolean" then boolean(child) when "string" then string(child) when "double" then double(child) when "dateTime.iso8601" then dateTime(child) when "base64" then base64(child) when "struct" then struct(child) when "array" then array(child) when "nil" if Config::ENABLE_NIL_PARSER v_nil(child) else raise "wrong/unknown XML-RPC type 'nil'" end else raise "wrong/unknown XML-RPC type" end else raise "wrong type of node" end end def methodCall(node) nodeMustBe(node, "methodCall") assert( (1..2).include?( node.childNodes.to_a.size ) ) name = methodName(node[0]) if node.childNodes.to_a.size == 2 then pa = params(node[1]) else # no parameters given pa = [] end [name, pa] end end # module TreeParserMixin class AbstractStreamParser def parseMethodResponse(str) parser = @parser_class.new parser.parse(str) raise "No valid method response!" if parser.method_name != nil if parser.fault != nil # is a fault structure [false, parser.fault] else # is a normal return value raise "Missing return value!" if parser.params.size == 0 raise "Too many return values. Only one allowed!" if parser.params.size > 1 [true, parser.params[0]] end end def parseMethodCall(str) parser = @parser_class.new parser.parse(str) raise "No valid method call - missing method name!" if parser.method_name.nil? [parser.method_name, parser.params] end end module StreamParserMixin attr_reader :params attr_reader :method_name attr_reader :fault def initialize(*a) super(*a) @params = [] @values = [] @val_stack = [] @names = [] @name = [] @structs = [] @struct = {} @method_name = nil @fault = nil @data = nil end def startElement(name, attrs=[]) @data = nil case name when "value" @value = nil when "nil" raise "wrong/unknown XML-RPC type 'nil'" unless Config::ENABLE_NIL_PARSER @value = :nil when "array" @val_stack << @values @values = [] when "struct" @names << @name @name = [] @structs << @struct @struct = {} end end def endElement(name) @data ||= "" case name when "string" @value = @data when "i4", "i8", "int" @value = Convert.int(@data) when "boolean" @value = Convert.boolean(@data) when "double" @value = Convert.double(@data) when "dateTime.iso8601" @value = Convert.dateTime(@data) when "base64" @value = Convert.base64(@data) when "value" @value = @data if @value.nil? @values << (@value == :nil ? nil : @value) when "array" @value = @values @values = @val_stack.pop when "struct" @value = Convert.struct(@struct) @name = @names.pop @struct = @structs.pop when "name" @name[0] = @data when "member" @struct[@name[0]] = @values.pop when "param" @params << @values[0] @values = [] when "fault" @fault = Convert.fault(@values[0]) when "methodName" @method_name = @data end @data = nil end def character(data) if @data @data << data else @data = data end end end # module StreamParserMixin class XMLStreamParser < AbstractStreamParser def initialize require "xmlparser" @parser_class = Class.new(::XMLParser) { include StreamParserMixin } end end # class XMLStreamParser class NQXMLStreamParser < AbstractStreamParser def initialize require "nqxml/streamingparser" @parser_class = XMLRPCParser end class XMLRPCParser include StreamParserMixin def parse(str) parser = NQXML::StreamingParser.new(str) parser.each do |ele| case ele when NQXML::Text @data = ele.text #character(ele.text) when NQXML::Tag if ele.isTagEnd endElement(ele.name) else startElement(ele.name, ele.attrs) end end end # do end # method parse end # class XMLRPCParser end # class NQXMLStreamParser class XMLTreeParser < AbstractTreeParser def initialize require "xmltreebuilder" # The new XMLParser library (0.6.2+) uses a slightly different DOM implementation. # The following code removes the differences between both versions. if defined? XML::DOM::Builder return if defined? XML::DOM::Node::DOCUMENT # code below has been already executed klass = XML::DOM::Node klass.const_set(:DOCUMENT, klass::DOCUMENT_NODE) klass.const_set(:TEXT, klass::TEXT_NODE) klass.const_set(:COMMENT, klass::COMMENT_NODE) klass.const_set(:ELEMENT, klass::ELEMENT_NODE) end end private def _nodeType(node) tp = node.nodeType if tp == XML::SimpleTree::Node::TEXT then :TEXT elsif tp == XML::SimpleTree::Node::COMMENT then :COMMENT elsif tp == XML::SimpleTree::Node::ELEMENT then :ELEMENT else :ELSE end end def methodResponse_document(node) assert( node.nodeType == XML::SimpleTree::Node::DOCUMENT ) hasOnlyOneChild(node, "methodResponse") methodResponse(node.firstChild) end def methodCall_document(node) assert( node.nodeType == XML::SimpleTree::Node::DOCUMENT ) hasOnlyOneChild(node, "methodCall") methodCall(node.firstChild) end def createCleanedTree(str) doc = XML::SimpleTreeBuilder.new.parse(str) doc.documentElement.normalize removeWhitespacesAndComments(doc) doc end end # class XMLParser class NQXMLTreeParser < AbstractTreeParser def initialize require "nqxml/treeparser" end private def _nodeType(node) node.nodeType end def methodResponse_document(node) methodResponse(node) end def methodCall_document(node) methodCall(node) end def createCleanedTree(str) doc = ::NQXML::TreeParser.new(str).document.rootNode removeWhitespacesAndComments(doc) doc end end # class NQXMLTreeParser class REXMLStreamParser < AbstractStreamParser def initialize require "rexml/document" @parser_class = StreamListener end class StreamListener include StreamParserMixin alias :tag_start :startElement alias :tag_end :endElement alias :text :character alias :cdata :character def method_missing(*a) # ignore end def parse(str) REXML::Document.parse_stream(str, self) end end end class XMLScanStreamParser < AbstractStreamParser def initialize require "xmlscan/parser" @parser_class = XMLScanParser end class XMLScanParser include StreamParserMixin Entities = { "lt" => "<", "gt" => ">", "amp" => "&", "quot" => '"', "apos" => "'" } def parse(str) parser = XMLScan::XMLParser.new(self) parser.parse(str) end alias :on_stag :startElement alias :on_etag :endElement def on_stag_end(name); end def on_stag_end_empty(name) startElement(name) endElement(name) end def on_chardata(str) character(str) end def on_cdata(str) character(str) end def on_entityref(ent) str = Entities[ent] if str character(str) else raise "unknown entity" end end def on_charref(code) character(code.chr) end def on_charref_hex(code) character(code.chr) end def method_missing(*a) end # TODO: call/implement? # valid_name? # valid_chardata? # valid_char? # parse_error end end class LibXMLStreamParser < AbstractStreamParser def initialize require 'libxml' @parser_class = LibXMLStreamListener end class LibXMLStreamListener include StreamParserMixin def on_start_element_ns(name, attributes, prefix, uri, namespaces) startElement(name) end def on_end_element_ns(name, prefix, uri) endElement(name) end alias :on_characters :character alias :on_cdata_block :character def method_missing(*a) end def parse(str) parser = LibXML::XML::SaxParser.string(str) parser.callbacks = self parser.parse() end end end XMLParser = XMLTreeParser NQXMLParser = NQXMLTreeParser Classes = [XMLStreamParser, XMLTreeParser, NQXMLStreamParser, NQXMLTreeParser, REXMLStreamParser, XMLScanStreamParser, LibXMLStreamParser] # yields an instance of each installed parser def self.each_installed_parser XMLRPC::XMLParser::Classes.each do |klass| begin yield klass.new rescue LoadError end end end end # module XMLParser end # module XMLRPC PK!* 2.2.0/unicode_normalize.rbnu[# coding: utf-8 # Copyright Ayumu Nojima (野島 歩) and Martin J. Dürst (duerst@it.aoyama.ac.jp) # additions to class String for Unicode normalization class String # === Unicode Normalization # # :call-seq: # str.unicode_normalize(form=:nfc) # # Returns a normalized form of +str+, using Unicode normalizations # NFC, NFD, NFKC, or NFKD. The normalization form used is determined # by +form+, which is any of the four values :nfc, :nfd, :nfkc, or :nfkd. # The default is :nfc. # # If the string is not in a Unicode Encoding, then an Exception is raised. # In this context, 'Unicode Encoding' means any of UTF-8, UTF-16BE/LE, # and UTF-32BE/LE, as well as GB18030, UCS_2BE, and UCS_4BE. Anything # else than UTF-8 is implemented by converting to UTF-8, # which makes it slower than UTF-8. # # _Examples_ # # "a\u0300".unicode_normalize #=> 'à' (same as "\u00E0") # "a\u0300".unicode_normalize(:nfc) #=> 'à' (same as "\u00E0") # "\u00E0".unicode_normalize(:nfd) #=> 'à' (same as "a\u0300") # "\xE0".force_encoding('ISO-8859-1').unicode_normalize(:nfd) # #=> Encoding::CompatibilityError raised # def unicode_normalize(form = :nfc) require 'unicode_normalize/normalize.rb' unless defined? UnicodeNormalize ## The following line can be uncommented to avoid repeated checking for ## UnicodeNormalize. However, tests didn't show any noticeable speedup ## when doing this. This comment also applies to the commented out lines ## in String#unicode_normalize! and String#unicode_normalized?. # String.send(:define_method, :unicode_normalize, ->(form = :nfc) { UnicodeNormalize.normalize(self, form) } ) UnicodeNormalize.normalize(self, form) end # :call-seq: # str.unicode_normalize!(form=:nfc) # # Destructive version of String#unicode_normalize, doing Unicode # normalization in place. # def unicode_normalize!(form = :nfc) require 'unicode_normalize/normalize.rb' unless defined? UnicodeNormalize # String.send(:define_method, :unicode_normalize!, ->(form = :nfc) { replace(unicode_normalize(form)) } ) replace(unicode_normalize(form)) end # :call-seq: # str.unicode_normalized?(form=:nfc) # # Checks whether +str+ is in Unicode normalization form +form+, # which is any of the four values :nfc, :nfd, :nfkc, or :nfkd. # The default is :nfc. # # If the string is not in a Unicode Encoding, then an Exception is raised. # For details, see String#unicode_normalize. # # _Examples_ # # "a\u0300".unicode_normalized? #=> false # "a\u0300".unicode_normalized?(:nfd) #=> true # "\u00E0".unicode_normalized? #=> true # "\u00E0".unicode_normalized?(:nfd) #=> false # "\xE0".force_encoding('ISO-8859-1').unicode_normalized? # #=> Encoding::CompatibilityError raised # def unicode_normalized?(form = :nfc) require 'unicode_normalize/normalize.rb' unless defined? UnicodeNormalize # String.send(:define_method, :unicode_normalized?, ->(form = :nfc) { UnicodeNormalize.normalized?(self, form) } ) UnicodeNormalize.normalized?(self, form) end end PK!֌jiji 2.2.0/erb.rbnu[# -*- coding: us-ascii -*- # = ERB -- Ruby Templating # # Author:: Masatoshi SEKI # Documentation:: James Edward Gray II, Gavin Sinclair, and Simon Chiang # # See ERB for primary documentation and ERB::Util for a couple of utility # routines. # # Copyright (c) 1999-2000,2002,2003 Masatoshi SEKI # # You can redistribute it and/or modify it under the same terms as Ruby. require "cgi/util" # # = ERB -- Ruby Templating # # == Introduction # # ERB provides an easy to use but powerful templating system for Ruby. Using # ERB, actual Ruby code can be added to any plain text document for the # purposes of generating document information details and/or flow control. # # A very simple example is this: # # require 'erb' # # x = 42 # template = ERB.new <<-EOF # The value of x is: <%= x %> # EOF # puts template.result(binding) # # Prints: The value of x is: 42 # # More complex examples are given below. # # # == Recognized Tags # # ERB recognizes certain tags in the provided template and converts them based # on the rules below: # # <% Ruby code -- inline with output %> # <%= Ruby expression -- replace with result %> # <%# comment -- ignored -- useful in testing %> # % a line of Ruby code -- treated as <% line %> (optional -- see ERB.new) # %% replaced with % if first thing on a line and % processing is used # <%% or %%> -- replace with <% or %> respectively # # All other text is passed through ERB filtering unchanged. # # # == Options # # There are several settings you can change when you use ERB: # * the nature of the tags that are recognized; # * the value of $SAFE under which the template is run; # * the binding used to resolve local variables in the template. # # See the ERB.new and ERB#result methods for more detail. # # == Character encodings # # ERB (or Ruby code generated by ERB) returns a string in the same # character encoding as the input string. When the input string has # a magic comment, however, it returns a string in the encoding specified # by the magic comment. # # # -*- coding: utf-8 -*- # require 'erb' # # template = ERB.new < # \_\_ENCODING\_\_ is <%= \_\_ENCODING\_\_ %>. # EOF # puts template.result # # Prints: \_\_ENCODING\_\_ is Big5. # # # == Examples # # === Plain Text # # ERB is useful for any generic templating situation. Note that in this example, we use the # convenient "% at start of line" tag, and we quote the template literally with # %q{...} to avoid trouble with the backslash. # # require "erb" # # # Create template. # template = %q{ # From: James Edward Gray II # To: <%= to %> # Subject: Addressing Needs # # <%= to[/\w+/] %>: # # Just wanted to send a quick note assuring that your needs are being # addressed. # # I want you to know that my team will keep working on the issues, # especially: # # <%# ignore numerous minor requests -- focus on priorities %> # % priorities.each do |priority| # * <%= priority %> # % end # # Thanks for your patience. # # James Edward Gray II # }.gsub(/^ /, '') # # message = ERB.new(template, 0, "%<>") # # # Set up template data. # to = "Community Spokesman " # priorities = [ "Run Ruby Quiz", # "Document Modules", # "Answer Questions on Ruby Talk" ] # # # Produce result. # email = message.result # puts email # # Generates: # # From: James Edward Gray II # To: Community Spokesman # Subject: Addressing Needs # # Community: # # Just wanted to send a quick note assuring that your needs are being addressed. # # I want you to know that my team will keep working on the issues, especially: # # * Run Ruby Quiz # * Document Modules # * Answer Questions on Ruby Talk # # Thanks for your patience. # # James Edward Gray II # # === Ruby in HTML # # ERB is often used in .rhtml files (HTML with embedded Ruby). Notice the need in # this example to provide a special binding when the template is run, so that the instance # variables in the Product object can be resolved. # # require "erb" # # # Build template data class. # class Product # def initialize( code, name, desc, cost ) # @code = code # @name = name # @desc = desc # @cost = cost # # @features = [ ] # end # # def add_feature( feature ) # @features << feature # end # # # Support templating of member data. # def get_binding # binding # end # # # ... # end # # # Create template. # template = %{ # # Ruby Toys -- <%= @name %> # # #

    <%= @name %> (<%= @code %>)

    #

    <%= @desc %>

    # #
      # <% @features.each do |f| %> #
    • <%= f %>
    • # <% end %> #
    # #

    # <% if @cost < 10 %> # Only <%= @cost %>!!! # <% else %> # Call for a price, today! # <% end %> #

    # # # # }.gsub(/^ /, '') # # rhtml = ERB.new(template) # # # Set up template data. # toy = Product.new( "TZ-1002", # "Rubysapien", # "Geek's Best Friend! Responds to Ruby commands...", # 999.95 ) # toy.add_feature("Listens for verbal commands in the Ruby language!") # toy.add_feature("Ignores Perl, Java, and all C variants.") # toy.add_feature("Karate-Chop Action!!!") # toy.add_feature("Matz signature on left leg.") # toy.add_feature("Gem studded eyes... Rubies, of course!") # # # Produce result. # rhtml.run(toy.get_binding) # # Generates (some blank lines removed): # # # Ruby Toys -- Rubysapien # # #

    Rubysapien (TZ-1002)

    #

    Geek's Best Friend! Responds to Ruby commands...

    # #
      #
    • Listens for verbal commands in the Ruby language!
    • #
    • Ignores Perl, Java, and all C variants.
    • #
    • Karate-Chop Action!!!
    • #
    • Matz signature on left leg.
    • #
    • Gem studded eyes... Rubies, of course!
    • #
    # #

    # Call for a price, today! #

    # # # # # # == Notes # # There are a variety of templating solutions available in various Ruby projects: # * ERB's big brother, eRuby, works the same but is written in C for speed; # * Amrita (smart at producing HTML/XML); # * cs/Template (written in C for speed); # * RDoc, distributed with Ruby, uses its own template engine, which can be reused elsewhere; # * and others; search {RubyGems.org}[https://rubygems.org/] or # {The Ruby Toolbox}[https://www.ruby-toolbox.com/]. # # Rails, the web application framework, uses ERB to create views. # class ERB Revision = '$Date:: 2014-12-12 19:48:57 +0900#$' # :nodoc: #' # Returns revision information for the erb.rb module. def self.version "erb.rb [2.1.0 #{ERB::Revision.split[1]}]" end end #-- # ERB::Compiler class ERB # = ERB::Compiler # # Compiles ERB templates into Ruby code; the compiled code produces the # template result when evaluated. ERB::Compiler provides hooks to define how # generated output is handled. # # Internally ERB does something like this to generate the code returned by # ERB#src: # # compiler = ERB::Compiler.new('<>') # compiler.pre_cmd = ["_erbout=''"] # compiler.put_cmd = "_erbout.concat" # compiler.insert_cmd = "_erbout.concat" # compiler.post_cmd = ["_erbout"] # # code, enc = compiler.compile("Got <%= obj %>!\n") # puts code # # Generates: # # #coding:UTF-8 # _erbout=''; _erbout.concat "Got "; _erbout.concat(( obj ).to_s); _erbout.concat "!\n"; _erbout # # By default the output is sent to the print method. For example: # # compiler = ERB::Compiler.new('<>') # code, enc = compiler.compile("Got <%= obj %>!\n") # puts code # # Generates: # # #coding:UTF-8 # print "Got "; print(( obj ).to_s); print "!\n" # # == Evaluation # # The compiled code can be used in any context where the names in the code # correctly resolve. Using the last example, each of these print 'Got It!' # # Evaluate using a variable: # # obj = 'It' # eval code # # Evaluate using an input: # # mod = Module.new # mod.module_eval %{ # def get(obj) # #{code} # end # } # extend mod # get('It') # # Evaluate using an accessor: # # klass = Class.new Object # klass.class_eval %{ # attr_accessor :obj # def initialize(obj) # @obj = obj # end # def get_it # #{code} # end # } # klass.new('It').get_it # # Good! See also ERB#def_method, ERB#def_module, and ERB#def_class. class Compiler # :nodoc: class PercentLine # :nodoc: def initialize(str) @value = str end attr_reader :value alias :to_s :value def empty? @value.empty? end end class Scanner # :nodoc: @scanner_map = {} def self.regist_scanner(klass, trim_mode, percent) @scanner_map[[trim_mode, percent]] = klass end def self.default_scanner=(klass) @default_scanner = klass end def self.make_scanner(src, trim_mode, percent) klass = @scanner_map.fetch([trim_mode, percent], @default_scanner) klass.new(src, trim_mode, percent) end def initialize(src, trim_mode, percent) @src = src @stag = nil end attr_accessor :stag def scan; end end class TrimScanner < Scanner # :nodoc: def initialize(src, trim_mode, percent) super @trim_mode = trim_mode @percent = percent if @trim_mode == '>' @scan_line = self.method(:trim_line1) elsif @trim_mode == '<>' @scan_line = self.method(:trim_line2) elsif @trim_mode == '-' @scan_line = self.method(:explicit_trim_line) else @scan_line = self.method(:scan_line) end end attr_accessor :stag def scan(&block) @stag = nil if @percent @src.each_line do |line| percent_line(line, &block) end else @scan_line.call(@src, &block) end nil end def percent_line(line, &block) if @stag || line[0] != ?% return @scan_line.call(line, &block) end line[0] = '' if line[0] == ?% @scan_line.call(line, &block) else yield(PercentLine.new(line.chomp)) end end def scan_line(line) line.scan(/(.*?)(<%%|%%>|<%=|<%#|<%|%>|\n|\z)/m) do |tokens| tokens.each do |token| next if token.empty? yield(token) end end end def trim_line1(line) line.scan(/(.*?)(<%%|%%>|<%=|<%#|<%|%>\n|%>|\n|\z)/m) do |tokens| tokens.each do |token| next if token.empty? if token == "%>\n" yield('%>') yield(:cr) else yield(token) end end end end def trim_line2(line) head = nil line.scan(/(.*?)(<%%|%%>|<%=|<%#|<%|%>\n|%>|\n|\z)/m) do |tokens| tokens.each do |token| next if token.empty? head = token unless head if token == "%>\n" yield('%>') if is_erb_stag?(head) yield(:cr) else yield("\n") end head = nil else yield(token) head = nil if token == "\n" end end end end def explicit_trim_line(line) line.scan(/(.*?)(^[ \t]*<%\-|<%\-|<%%|%%>|<%=|<%#|<%|-%>\n|-%>|%>|\z)/m) do |tokens| tokens.each do |token| next if token.empty? if @stag.nil? && /[ \t]*<%-/ =~ token yield('<%') elsif @stag && token == "-%>\n" yield('%>') yield(:cr) elsif @stag && token == '-%>' yield('%>') else yield(token) end end end end ERB_STAG = %w(<%= <%# <%) def is_erb_stag?(s) ERB_STAG.member?(s) end end Scanner.default_scanner = TrimScanner class SimpleScanner < Scanner # :nodoc: def scan @src.scan(/(.*?)(<%%|%%>|<%=|<%#|<%|%>|\n|\z)/m) do |tokens| tokens.each do |token| next if token.empty? yield(token) end end end end Scanner.regist_scanner(SimpleScanner, nil, false) begin require 'strscan' class SimpleScanner2 < Scanner # :nodoc: def scan stag_reg = /(.*?)(<%%|<%=|<%#|<%|\z)/m etag_reg = /(.*?)(%%>|%>|\z)/m scanner = StringScanner.new(@src) while ! scanner.eos? scanner.scan(@stag ? etag_reg : stag_reg) yield(scanner[1]) yield(scanner[2]) end end end Scanner.regist_scanner(SimpleScanner2, nil, false) class ExplicitScanner < Scanner # :nodoc: def scan stag_reg = /(.*?)(^[ \t]*<%-|<%%|<%=|<%#|<%-|<%|\z)/m etag_reg = /(.*?)(%%>|-%>|%>|\z)/m scanner = StringScanner.new(@src) while ! scanner.eos? scanner.scan(@stag ? etag_reg : stag_reg) yield(scanner[1]) elem = scanner[2] if /[ \t]*<%-/ =~ elem yield('<%') elsif elem == '-%>' yield('%>') yield(:cr) if scanner.scan(/(\n|\z)/) else yield(elem) end end end end Scanner.regist_scanner(ExplicitScanner, '-', false) rescue LoadError end class Buffer # :nodoc: def initialize(compiler, enc=nil) @compiler = compiler @line = [] @script = enc ? "#coding:#{enc}\n" : "" @compiler.pre_cmd.each do |x| push(x) end end attr_reader :script def push(cmd) @line << cmd end def cr @script << (@line.join('; ')) @line = [] @script << "\n" end def close return unless @line @compiler.post_cmd.each do |x| push(x) end @script << (@line.join('; ')) @line = nil end end def content_dump(s) # :nodoc: n = s.count("\n") if n > 0 s.dump + "\n" * n else s.dump end end def add_put_cmd(out, content) out.push("#{@put_cmd} #{content_dump(content)}") end def add_insert_cmd(out, content) out.push("#{@insert_cmd}((#{content}).to_s)") end # Compiles an ERB template into Ruby code. Returns an array of the code # and encoding like ["code", Encoding]. def compile(s) enc = s.encoding raise ArgumentError, "#{enc} is not ASCII compatible" if enc.dummy? s = s.b # see String#b enc = detect_magic_comment(s) || enc out = Buffer.new(self, enc) content = '' scanner = make_scanner(s) scanner.scan do |token| next if token.nil? next if token == '' if scanner.stag.nil? case token when PercentLine add_put_cmd(out, content) if content.size > 0 content = '' out.push(token.to_s) out.cr when :cr out.cr when '<%', '<%=', '<%#' scanner.stag = token add_put_cmd(out, content) if content.size > 0 content = '' when "\n" content << "\n" add_put_cmd(out, content) content = '' when '<%%' content << '<%' else content << token end else case token when '%>' case scanner.stag when '<%' if content[-1] == ?\n content.chop! out.push(content) out.cr else out.push(content) end when '<%=' add_insert_cmd(out, content) when '<%#' # out.push("# #{content_dump(content)}") end scanner.stag = nil content = '' when '%%>' content << '%>' else content << token end end end add_put_cmd(out, content) if content.size > 0 out.close return out.script, enc end def prepare_trim_mode(mode) # :nodoc: case mode when 1 return [false, '>'] when 2 return [false, '<>'] when 0 return [false, nil] when String perc = mode.include?('%') if mode.include?('-') return [perc, '-'] elsif mode.include?('<>') return [perc, '<>'] elsif mode.include?('>') return [perc, '>'] else [perc, nil] end else return [false, nil] end end def make_scanner(src) # :nodoc: Scanner.make_scanner(src, @trim_mode, @percent) end # Construct a new compiler using the trim_mode. See ERB::new for available # trim modes. def initialize(trim_mode) @percent, @trim_mode = prepare_trim_mode(trim_mode) @put_cmd = 'print' @insert_cmd = @put_cmd @pre_cmd = [] @post_cmd = [] end attr_reader :percent, :trim_mode # The command to handle text that ends with a newline attr_accessor :put_cmd # The command to handle text that is inserted prior to a newline attr_accessor :insert_cmd # An array of commands prepended to compiled code attr_accessor :pre_cmd # An array of commands appended to compiled code attr_accessor :post_cmd private def detect_magic_comment(s) if /\A<%#(.*)%>/ =~ s or (@percent and /\A%#(.*)/ =~ s) comment = $1 comment = $1 if comment[/-\*-\s*(.*?)\s*-*-$/] if %r"coding\s*[=:]\s*([[:alnum:]\-_]+)" =~ comment enc = $1.sub(/-(?:mac|dos|unix)/i, '') Encoding.find(enc) end end end end end #-- # ERB class ERB # # Constructs a new ERB object with the template specified in _str_. # # An ERB object works by building a chunk of Ruby code that will output # the completed template when run. If _safe_level_ is set to a non-nil value, # ERB code will be run in a separate thread with $SAFE set to the # provided level. # # If _trim_mode_ is passed a String containing one or more of the following # modifiers, ERB will adjust its code generation as listed: # # % enables Ruby code processing for lines beginning with % # <> omit newline for lines starting with <% and ending in %> # > omit newline for lines ending in %> # - omit blank lines ending in -%> # # _eoutvar_ can be used to set the name of the variable ERB will build up # its output in. This is useful when you need to run multiple ERB # templates through the same binding and/or when you want to control where # output ends up. Pass the name of the variable to be used inside a String. # # === Example # # require "erb" # # # build data class # class Listings # PRODUCT = { :name => "Chicken Fried Steak", # :desc => "A well messages pattie, breaded and fried.", # :cost => 9.95 } # # attr_reader :product, :price # # def initialize( product = "", price = "" ) # @product = product # @price = price # end # # def build # b = binding # # create and run templates, filling member data variables # ERB.new(<<-'END_PRODUCT'.gsub(/^\s+/, ""), 0, "", "@product").result b # <%= PRODUCT[:name] %> # <%= PRODUCT[:desc] %> # END_PRODUCT # ERB.new(<<-'END_PRICE'.gsub(/^\s+/, ""), 0, "", "@price").result b # <%= PRODUCT[:name] %> -- <%= PRODUCT[:cost] %> # <%= PRODUCT[:desc] %> # END_PRICE # end # end # # # setup template data # listings = Listings.new # listings.build # # puts listings.product + "\n" + listings.price # # _Generates_ # # Chicken Fried Steak # A well messages pattie, breaded and fried. # # Chicken Fried Steak -- 9.95 # A well messages pattie, breaded and fried. # def initialize(str, safe_level=nil, trim_mode=nil, eoutvar='_erbout') @safe_level = safe_level compiler = make_compiler(trim_mode) set_eoutvar(compiler, eoutvar) @src, @encoding = *compiler.compile(str) @filename = nil @lineno = 0 end ## # Creates a new compiler for ERB. See ERB::Compiler.new for details def make_compiler(trim_mode) ERB::Compiler.new(trim_mode) end # The Ruby code generated by ERB attr_reader :src # The encoding to eval attr_reader :encoding # The optional _filename_ argument passed to Kernel#eval when the ERB code # is run attr_accessor :filename # The optional _lineno_ argument passed to Kernel#eval when the ERB code # is run attr_accessor :lineno def location=((filename, lineno)) @filename = filename @lineno = lineno if lineno end # # Can be used to set _eoutvar_ as described in ERB::new. It's probably # easier to just use the constructor though, since calling this method # requires the setup of an ERB _compiler_ object. # def set_eoutvar(compiler, eoutvar = '_erbout') compiler.put_cmd = "#{eoutvar}.concat" compiler.insert_cmd = "#{eoutvar}.concat" compiler.pre_cmd = ["#{eoutvar} = ''"] compiler.post_cmd = ["#{eoutvar}.force_encoding(__ENCODING__)"] end # Generate results and print them. (see ERB#result) def run(b=new_toplevel) print self.result(b) end # # Executes the generated ERB code to produce a completed template, returning # the results of that code. (See ERB::new for details on how this process # can be affected by _safe_level_.) # # _b_ accepts a Binding object which is used to set the context of # code evaluation. # def result(b=new_toplevel) if @safe_level proc { $SAFE = @safe_level eval(@src, b, (@filename || '(erb)'), @lineno) }.call else eval(@src, b, (@filename || '(erb)'), @lineno) end end ## # Returns a new binding each time *near* TOPLEVEL_BINDING for runs that do # not specify a binding. def new_toplevel TOPLEVEL_BINDING.dup end private :new_toplevel # Define _methodname_ as instance method of _mod_ from compiled Ruby source. # # example: # filename = 'example.rhtml' # 'arg1' and 'arg2' are used in example.rhtml # erb = ERB.new(File.read(filename)) # erb.def_method(MyClass, 'render(arg1, arg2)', filename) # print MyClass.new.render('foo', 123) def def_method(mod, methodname, fname='(ERB)') src = self.src magic_comment = "#coding:#{@encoding}\n" mod.module_eval do eval(magic_comment + "def #{methodname}\n" + src + "\nend\n", binding, fname, -2) end end # Create unnamed module, define _methodname_ as instance method of it, and return it. # # example: # filename = 'example.rhtml' # 'arg1' and 'arg2' are used in example.rhtml # erb = ERB.new(File.read(filename)) # erb.filename = filename # MyModule = erb.def_module('render(arg1, arg2)') # class MyClass # include MyModule # end def def_module(methodname='erb') mod = Module.new def_method(mod, methodname, @filename || '(ERB)') mod end # Define unnamed class which has _methodname_ as instance method, and return it. # # example: # class MyClass_ # def initialize(arg1, arg2) # @arg1 = arg1; @arg2 = arg2 # end # end # filename = 'example.rhtml' # @arg1 and @arg2 are used in example.rhtml # erb = ERB.new(File.read(filename)) # erb.filename = filename # MyClass = erb.def_class(MyClass_, 'render()') # print MyClass.new('foo', 123).render() def def_class(superklass=Object, methodname='result') cls = Class.new(superklass) def_method(cls, methodname, @filename || '(ERB)') cls end end #-- # ERB::Util class ERB # A utility module for conversion routines, often handy in HTML generation. module Util public # # A utility method for escaping HTML tag characters in _s_. # # require "erb" # include ERB::Util # # puts html_escape("is a > 0 & a < 10?") # # _Generates_ # # is a > 0 & a < 10? # def html_escape(s) CGI.escapeHTML(s.to_s) end alias h html_escape module_function :h module_function :html_escape # # A utility method for encoding the String _s_ as a URL. # # require "erb" # include ERB::Util # # puts url_encode("Programming Ruby: The Pragmatic Programmer's Guide") # # _Generates_ # # Programming%20Ruby%3A%20%20The%20Pragmatic%20Programmer%27s%20Guide # def url_encode(s) s.to_s.b.gsub(/[^a-zA-Z0-9_\-.]/n) { |m| sprintf("%%%02X", m.unpack("C")[0]) } end alias u url_encode module_function :u module_function :url_encode end end #-- # ERB::DefMethod class ERB # Utility module to define eRuby script as instance method. # # === Example # # example.rhtml: # <% for item in @items %> # <%= item %> # <% end %> # # example.rb: # require 'erb' # class MyClass # extend ERB::DefMethod # def_erb_method('render()', 'example.rhtml') # def initialize(items) # @items = items # end # end # print MyClass.new([10,20,30]).render() # # result: # # 10 # # 20 # # 30 # module DefMethod public # define _methodname_ as instance method of current module, using ERB # object or eRuby file def def_erb_method(methodname, erb_or_fname) if erb_or_fname.kind_of? String fname = erb_or_fname erb = ERB.new(File.read(fname)) erb.def_method(self, methodname, fname) else erb = erb_or_fname erb.def_method(self, methodname, erb.filename || '(ERB)') end end module_function :def_erb_method end end PK!Cr2.2.0/rbconfig/datadir.rbnu[#-- # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. # All rights reserved. # See LICENSE.txt for permissions. #++ # N.B. This file is used by Config.datadir in rubygems.rb, and must not be # removed before that require is removed. I require to avoid warning more than # once. warn 'rbconfig/datadir.rb and {Rb}Config.datadir is being deprecated from '\ 'RubyGems. It will be removed completely on or after June 2011. If you '\ 'wish to rely on a datadir, please use Gem.datadir.' PK!շDZ~#~# 2.2.0/un.rbnu[# # = un.rb # # Copyright (c) 2003 WATANABE Hirofumi # # This program is free software. # You can distribute/modify this program under the same terms of Ruby. # # == Utilities to replace common UNIX commands in Makefiles etc # # == SYNOPSIS # # ruby -run -e cp -- [OPTION] SOURCE DEST # ruby -run -e ln -- [OPTION] TARGET LINK_NAME # ruby -run -e mv -- [OPTION] SOURCE DEST # ruby -run -e rm -- [OPTION] FILE # ruby -run -e mkdir -- [OPTION] DIRS # ruby -run -e rmdir -- [OPTION] DIRS # ruby -run -e install -- [OPTION] SOURCE DEST # ruby -run -e chmod -- [OPTION] OCTAL-MODE FILE # ruby -run -e touch -- [OPTION] FILE # ruby -run -e wait_writable -- [OPTION] FILE # ruby -run -e mkmf -- [OPTION] EXTNAME [OPTION] # ruby -run -e httpd -- [OPTION] DocumentRoot # ruby -run -e help [COMMAND] require "fileutils" require "optparse" module FileUtils # @fileutils_label = "" @fileutils_output = $stdout end # :nodoc: def setup(options = "", *long_options) caller = caller_locations(1, 1)[0].label opt_hash = {} argv = [] OptionParser.new do |o| options.scan(/.:?/) do |s| opt_name = s.delete(":").intern o.on("-" + s.tr(":", " ")) do |val| opt_hash[opt_name] = val end end long_options.each do |s| opt_name, arg_name = s.split(/(?=[\s=])/, 2) opt_name.sub!(/\A--/, '') s = "--#{opt_name.gsub(/([A-Z]+|[a-z])([A-Z])/, '\1-\2').downcase}#{arg_name}" puts "#{opt_name}=>#{s}" if $DEBUG opt_name = opt_name.intern o.on(s) do |val| opt_hash[opt_name] = val end end o.on("-v") do opt_hash[:verbose] = true end o.on("--help") do UN.help([caller]) exit end o.order!(ARGV) do |x| if /[*?\[{]/ =~ x argv.concat(Dir[x]) else argv << x end end end yield argv, opt_hash end ## # Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY # # ruby -run -e cp -- [OPTION] SOURCE DEST # # -p preserve file attributes if possible # -r copy recursively # -v verbose # def cp setup("pr") do |argv, options| cmd = "cp" cmd += "_r" if options.delete :r options[:preserve] = true if options.delete :p dest = argv.pop argv = argv[0] if argv.size == 1 FileUtils.send cmd, argv, dest, options end end ## # Create a link to the specified TARGET with LINK_NAME. # # ruby -run -e ln -- [OPTION] TARGET LINK_NAME # # -s make symbolic links instead of hard links # -f remove existing destination files # -v verbose # def ln setup("sf") do |argv, options| cmd = "ln" cmd += "_s" if options.delete :s options[:force] = true if options.delete :f dest = argv.pop argv = argv[0] if argv.size == 1 FileUtils.send cmd, argv, dest, options end end ## # Rename SOURCE to DEST, or move SOURCE(s) to DIRECTORY. # # ruby -run -e mv -- [OPTION] SOURCE DEST # # -v verbose # def mv setup do |argv, options| dest = argv.pop argv = argv[0] if argv.size == 1 FileUtils.mv argv, dest, options end end ## # Remove the FILE # # ruby -run -e rm -- [OPTION] FILE # # -f ignore nonexistent files # -r remove the contents of directories recursively # -v verbose # def rm setup("fr") do |argv, options| cmd = "rm" cmd += "_r" if options.delete :r options[:force] = true if options.delete :f FileUtils.send cmd, argv, options end end ## # Create the DIR, if they do not already exist. # # ruby -run -e mkdir -- [OPTION] DIR # # -p no error if existing, make parent directories as needed # -v verbose # def mkdir setup("p") do |argv, options| cmd = "mkdir" cmd += "_p" if options.delete :p FileUtils.send cmd, argv, options end end ## # Remove the DIR. # # ruby -run -e rmdir -- [OPTION] DIR # # -p remove DIRECTORY and its ancestors. # -v verbose # def rmdir setup("p") do |argv, options| options[:parents] = true if options.delete :p FileUtils.rmdir argv, options end end ## # Copy SOURCE to DEST. # # ruby -run -e install -- [OPTION] SOURCE DEST # # -p apply access/modification times of SOURCE files to # corresponding destination files # -m set permission mode (as in chmod), instead of 0755 # -v verbose # def install setup("pm:") do |argv, options| options[:mode] = (mode = options.delete :m) ? mode.oct : 0755 options[:preserve] = true if options.delete :p dest = argv.pop argv = argv[0] if argv.size == 1 FileUtils.install argv, dest, options end end ## # Change the mode of each FILE to OCTAL-MODE. # # ruby -run -e chmod -- [OPTION] OCTAL-MODE FILE # # -v verbose # def chmod setup do |argv, options| mode = argv.shift.oct FileUtils.chmod mode, argv, options end end ## # Update the access and modification times of each FILE to the current time. # # ruby -run -e touch -- [OPTION] FILE # # -v verbose # def touch setup do |argv, options| FileUtils.touch argv, options end end ## # Wait until the file becomes writable. # # ruby -run -e wait_writable -- [OPTION] FILE # # -n RETRY count to retry # -w SEC each wait time in seconds # -v verbose # def wait_writable setup("n:w:v") do |argv, options| verbose = options[:verbose] n = options[:n] and n = Integer(n) wait = (wait = options[:w]) ? Float(wait) : 0.2 argv.each do |file| begin open(file, "r+b") rescue Errno::ENOENT break rescue Errno::EACCES => e raise if n and (n -= 1) <= 0 if verbose puts e STDOUT.flush end sleep wait retry end end end end ## # Create makefile using mkmf. # # ruby -run -e mkmf -- [OPTION] EXTNAME [OPTION] # # -d ARGS run dir_config # -h ARGS run have_header # -l ARGS run have_library # -f ARGS run have_func # -v ARGS run have_var # -t ARGS run have_type # -m ARGS run have_macro # -c ARGS run have_const # --vendor install to vendor_ruby # def mkmf setup("d:h:l:f:v:t:m:c:", "vendor") do |argv, options| require 'mkmf' opt = options[:d] and opt.split(/:/).each {|n| dir_config(*n.split(/,/))} opt = options[:h] and opt.split(/:/).each {|n| have_header(*n.split(/,/))} opt = options[:l] and opt.split(/:/).each {|n| have_library(*n.split(/,/))} opt = options[:f] and opt.split(/:/).each {|n| have_func(*n.split(/,/))} opt = options[:v] and opt.split(/:/).each {|n| have_var(*n.split(/,/))} opt = options[:t] and opt.split(/:/).each {|n| have_type(*n.split(/,/))} opt = options[:m] and opt.split(/:/).each {|n| have_macro(*n.split(/,/))} opt = options[:c] and opt.split(/:/).each {|n| have_const(*n.split(/,/))} $configure_args["--vendor"] = true if options[:vendor] create_makefile(*argv) end end ## # Run WEBrick HTTP server. # # ruby -run -e httpd -- [OPTION] DocumentRoot # # --bind-address=ADDR address to bind # --port=NUM listening port number # --max-clients=MAX max number of simultaneous clients # --temp-dir=DIR temporary directory # --do-not-reverse-lookup disable reverse lookup # --request-timeout=SECOND request timeout in seconds # --http-version=VERSION HTTP version # -v verbose # def httpd setup("", "BindAddress=ADDR", "Port=PORT", "MaxClients=NUM", "TempDir=DIR", "DoNotReverseLookup", "RequestTimeout=SECOND", "HTTPVersion=VERSION") do |argv, options| require 'webrick' opt = options[:RequestTimeout] and options[:RequestTimeout] = opt.to_i [:Port, :MaxClients].each do |name| opt = options[name] and (options[name] = Integer(opt)) rescue nil end unless argv.size == 1 raise ArgumentError, "DocumentRoot is mandatory" end options[:DocumentRoot] = argv.shift s = WEBrick::HTTPServer.new(options) shut = proc {s.shutdown} siglist = %w"TERM QUIT" siglist.concat(%w"HUP INT") if STDIN.tty? siglist &= Signal.list.keys siglist.each do |sig| Signal.trap(sig, shut) end s.start end end ## # Display help message. # # ruby -run -e help [COMMAND] # def help setup do |argv,| UN.help(argv) end end module UN # :nodoc: module_function def help(argv, output: $stdout) all = argv.empty? cmd = nil if all store = proc {|msg| output << msg} else messages = {} store = proc {|msg| messages[cmd] = msg} end open(__FILE__) do |me| while me.gets("##\n") if help = me.gets("\n\n") if all or argv.include?(cmd = help[/^#\s*ruby\s.*-e\s+(\w+)/, 1]) store[help.gsub(/^# ?/, "")] break unless all or argv.size > messages.size end end end end if messages argv.each {|cmd| output << messages[cmd]} end end end PK!FF2.2.0/benchmark.rbnu[#-- # benchmark.rb - a performance benchmarking library # # $Id: benchmark.rb 47526 2014-09-11 08:09:07Z normal $ # # Created by Gotoken (gotoken@notwork.org). # # Documentation by Gotoken (original RD), Lyle Johnson (RDoc conversion), and # Gavin Sinclair (editing). #++ # # == Overview # # The Benchmark module provides methods for benchmarking Ruby code, giving # detailed reports on the time taken for each task. # # The Benchmark module provides methods to measure and report the time # used to execute Ruby code. # # * Measure the time to construct the string given by the expression # "a"*1_000_000_000: # # require 'benchmark' # # puts Benchmark.measure { "a"*1_000_000_000 } # # On my machine (OSX 10.8.3 on i5 1.7 Ghz) this generates: # # 0.350000 0.400000 0.750000 ( 0.835234) # # This report shows the user CPU time, system CPU time, the sum of # the user and system CPU times, and the elapsed real time. The unit # of time is seconds. # # * Do some experiments sequentially using the #bm method: # # require 'benchmark' # # n = 5000000 # Benchmark.bm do |x| # x.report { for i in 1..n; a = "1"; end } # x.report { n.times do ; a = "1"; end } # x.report { 1.upto(n) do ; a = "1"; end } # end # # The result: # # user system total real # 1.010000 0.000000 1.010000 ( 1.014479) # 1.000000 0.000000 1.000000 ( 0.998261) # 0.980000 0.000000 0.980000 ( 0.981335) # # * Continuing the previous example, put a label in each report: # # require 'benchmark' # # n = 5000000 # Benchmark.bm(7) do |x| # x.report("for:") { for i in 1..n; a = "1"; end } # x.report("times:") { n.times do ; a = "1"; end } # x.report("upto:") { 1.upto(n) do ; a = "1"; end } # end # # The result: # # user system total real # for: 1.010000 0.000000 1.010000 ( 1.015688) # times: 1.000000 0.000000 1.000000 ( 1.003611) # upto: 1.030000 0.000000 1.030000 ( 1.028098) # # * The times for some benchmarks depend on the order in which items # are run. These differences are due to the cost of memory # allocation and garbage collection. To avoid these discrepancies, # the #bmbm method is provided. For example, to compare ways to # sort an array of floats: # # require 'benchmark' # # array = (1..1000000).map { rand } # # Benchmark.bmbm do |x| # x.report("sort!") { array.dup.sort! } # x.report("sort") { array.dup.sort } # end # # The result: # # Rehearsal ----------------------------------------- # sort! 1.490000 0.010000 1.500000 ( 1.490520) # sort 1.460000 0.000000 1.460000 ( 1.463025) # -------------------------------- total: 2.960000sec # # user system total real # sort! 1.460000 0.000000 1.460000 ( 1.460465) # sort 1.450000 0.010000 1.460000 ( 1.448327) # # * Report statistics of sequential experiments with unique labels, # using the #benchmark method: # # require 'benchmark' # include Benchmark # we need the CAPTION and FORMAT constants # # n = 5000000 # Benchmark.benchmark(CAPTION, 7, FORMAT, ">total:", ">avg:") do |x| # tf = x.report("for:") { for i in 1..n; a = "1"; end } # tt = x.report("times:") { n.times do ; a = "1"; end } # tu = x.report("upto:") { 1.upto(n) do ; a = "1"; end } # [tf+tt+tu, (tf+tt+tu)/3] # end # # The result: # # user system total real # for: 0.950000 0.000000 0.950000 ( 0.952039) # times: 0.980000 0.000000 0.980000 ( 0.984938) # upto: 0.950000 0.000000 0.950000 ( 0.946787) # >total: 2.880000 0.000000 2.880000 ( 2.883764) # >avg: 0.960000 0.000000 0.960000 ( 0.961255) module Benchmark BENCHMARK_VERSION = "2002-04-25" # :nodoc: # Invokes the block with a Benchmark::Report object, which # may be used to collect and report on the results of individual # benchmark tests. Reserves +label_width+ leading spaces for # labels on each line. Prints +caption+ at the top of the # report, and uses +format+ to format each line. # Returns an array of Benchmark::Tms objects. # # If the block returns an array of # Benchmark::Tms objects, these will be used to format # additional lines of output. If +label+ parameters are # given, these are used to label these extra lines. # # _Note_: Other methods provide a simpler interface to this one, and are # suitable for nearly all benchmarking requirements. See the examples in # Benchmark, and the #bm and #bmbm methods. # # Example: # # require 'benchmark' # include Benchmark # we need the CAPTION and FORMAT constants # # n = 5000000 # Benchmark.benchmark(CAPTION, 7, FORMAT, ">total:", ">avg:") do |x| # tf = x.report("for:") { for i in 1..n; a = "1"; end } # tt = x.report("times:") { n.times do ; a = "1"; end } # tu = x.report("upto:") { 1.upto(n) do ; a = "1"; end } # [tf+tt+tu, (tf+tt+tu)/3] # end # # Generates: # # user system total real # for: 0.970000 0.000000 0.970000 ( 0.970493) # times: 0.990000 0.000000 0.990000 ( 0.989542) # upto: 0.970000 0.000000 0.970000 ( 0.972854) # >total: 2.930000 0.000000 2.930000 ( 2.932889) # >avg: 0.976667 0.000000 0.976667 ( 0.977630) # def benchmark(caption = "", label_width = nil, format = nil, *labels) # :yield: report sync = STDOUT.sync STDOUT.sync = true label_width ||= 0 label_width += 1 format ||= FORMAT print ' '*label_width + caption unless caption.empty? report = Report.new(label_width, format) results = yield(report) Array === results and results.grep(Tms).each {|t| print((labels.shift || t.label || "").ljust(label_width), t.format(format)) } report.list ensure STDOUT.sync = sync unless sync.nil? end # A simple interface to the #benchmark method, #bm generates sequential # reports with labels. The parameters have the same meaning as for # #benchmark. # # require 'benchmark' # # n = 5000000 # Benchmark.bm(7) do |x| # x.report("for:") { for i in 1..n; a = "1"; end } # x.report("times:") { n.times do ; a = "1"; end } # x.report("upto:") { 1.upto(n) do ; a = "1"; end } # end # # Generates: # # user system total real # for: 0.960000 0.000000 0.960000 ( 0.957966) # times: 0.960000 0.000000 0.960000 ( 0.960423) # upto: 0.950000 0.000000 0.950000 ( 0.954864) # def bm(label_width = 0, *labels, &blk) # :yield: report benchmark(CAPTION, label_width, FORMAT, *labels, &blk) end # Sometimes benchmark results are skewed because code executed # earlier encounters different garbage collection overheads than # that run later. #bmbm attempts to minimize this effect by running # the tests twice, the first time as a rehearsal in order to get the # runtime environment stable, the second time for # real. GC.start is executed before the start of each of # the real timings; the cost of this is not included in the # timings. In reality, though, there's only so much that #bmbm can # do, and the results are not guaranteed to be isolated from garbage # collection and other effects. # # Because #bmbm takes two passes through the tests, it can # calculate the required label width. # # require 'benchmark' # # array = (1..1000000).map { rand } # # Benchmark.bmbm do |x| # x.report("sort!") { array.dup.sort! } # x.report("sort") { array.dup.sort } # end # # Generates: # # Rehearsal ----------------------------------------- # sort! 1.440000 0.010000 1.450000 ( 1.446833) # sort 1.440000 0.000000 1.440000 ( 1.448257) # -------------------------------- total: 2.890000sec # # user system total real # sort! 1.460000 0.000000 1.460000 ( 1.458065) # sort 1.450000 0.000000 1.450000 ( 1.455963) # # #bmbm yields a Benchmark::Job object and returns an array of # Benchmark::Tms objects. # def bmbm(width = 0) # :yield: job job = Job.new(width) yield(job) width = job.width + 1 sync = STDOUT.sync STDOUT.sync = true # rehearsal puts 'Rehearsal '.ljust(width+CAPTION.length,'-') ets = job.list.inject(Tms.new) { |sum,(label,item)| print label.ljust(width) res = Benchmark.measure(&item) print res.format sum + res }.format("total: %tsec") print " #{ets}\n\n".rjust(width+CAPTION.length+2,'-') # take print ' '*width + CAPTION job.list.map { |label,item| GC.start print label.ljust(width) Benchmark.measure(label, &item).tap { |res| print res } } ensure STDOUT.sync = sync unless sync.nil? end # :stopdoc: case when defined?(Process::CLOCK_MONOTONIC) BENCHMARK_CLOCK = Process::CLOCK_MONOTONIC else BENCHMARK_CLOCK = Process::CLOCK_REALTIME end # :startdoc: # # Returns the time used to execute the given block as a # Benchmark::Tms object. # def measure(label = "") # :yield: t0, r0 = Process.times, Process.clock_gettime(BENCHMARK_CLOCK) yield t1, r1 = Process.times, Process.clock_gettime(BENCHMARK_CLOCK) Benchmark::Tms.new(t1.utime - t0.utime, t1.stime - t0.stime, t1.cutime - t0.cutime, t1.cstime - t0.cstime, r1 - r0, label) end # # Returns the elapsed real time used to execute the given block. # def realtime # :yield: r0 = Process.clock_gettime(BENCHMARK_CLOCK) yield Process.clock_gettime(BENCHMARK_CLOCK) - r0 end module_function :benchmark, :measure, :realtime, :bm, :bmbm # # A Job is a sequence of labelled blocks to be processed by the # Benchmark.bmbm method. It is of little direct interest to the user. # class Job # :nodoc: # # Returns an initialized Job instance. # Usually, one doesn't call this method directly, as new # Job objects are created by the #bmbm method. # +width+ is a initial value for the label offset used in formatting; # the #bmbm method passes its +width+ argument to this constructor. # def initialize(width) @width = width @list = [] end # # Registers the given label and block pair in the job list. # def item(label = "", &blk) # :yield: raise ArgumentError, "no block" unless block_given? label = label.to_s w = label.length @width = w if @width < w @list << [label, blk] self end alias report item # An array of 2-element arrays, consisting of label and block pairs. attr_reader :list # Length of the widest label in the #list. attr_reader :width end # # This class is used by the Benchmark.benchmark and Benchmark.bm methods. # It is of little direct interest to the user. # class Report # :nodoc: # # Returns an initialized Report instance. # Usually, one doesn't call this method directly, as new # Report objects are created by the #benchmark and #bm methods. # +width+ and +format+ are the label offset and # format string used by Tms#format. # def initialize(width = 0, format = nil) @width, @format, @list = width, format, [] end # # Prints the +label+ and measured time for the block, # formatted by +format+. See Tms#format for the # formatting rules. # def item(label = "", *format, &blk) # :yield: print label.to_s.ljust(@width) @list << res = Benchmark.measure(label, &blk) print res.format(@format, *format) res end alias report item # An array of Benchmark::Tms objects representing each item. attr_reader :list end # # A data object, representing the times associated with a benchmark # measurement. # class Tms # Default caption, see also Benchmark::CAPTION CAPTION = " user system total real\n" # Default format string, see also Benchmark::FORMAT FORMAT = "%10.6u %10.6y %10.6t %10.6r\n" # User CPU time attr_reader :utime # System CPU time attr_reader :stime # User CPU time of children attr_reader :cutime # System CPU time of children attr_reader :cstime # Elapsed real time attr_reader :real # Total time, that is +utime+ + +stime+ + +cutime+ + +cstime+ attr_reader :total # Label attr_reader :label # # Returns an initialized Tms object which has # +utime+ as the user CPU time, +stime+ as the system CPU time, # +cutime+ as the children's user CPU time, +cstime+ as the children's # system CPU time, +real+ as the elapsed real time and +label+ as the label. # def initialize(utime = 0.0, stime = 0.0, cutime = 0.0, cstime = 0.0, real = 0.0, label = nil) @utime, @stime, @cutime, @cstime, @real, @label = utime, stime, cutime, cstime, real, label.to_s @total = @utime + @stime + @cutime + @cstime end # # Returns a new Tms object whose times are the sum of the times for this # Tms object, plus the time required to execute the code block (+blk+). # def add(&blk) # :yield: self + Benchmark.measure(&blk) end # # An in-place version of #add. # def add!(&blk) t = Benchmark.measure(&blk) @utime = utime + t.utime @stime = stime + t.stime @cutime = cutime + t.cutime @cstime = cstime + t.cstime @real = real + t.real self end # # Returns a new Tms object obtained by memberwise summation # of the individual times for this Tms object with those of the other # Tms object. # This method and #/() are useful for taking statistics. # def +(other); memberwise(:+, other) end # # Returns a new Tms object obtained by memberwise subtraction # of the individual times for the other Tms object from those of this # Tms object. # def -(other); memberwise(:-, other) end # # Returns a new Tms object obtained by memberwise multiplication # of the individual times for this Tms object by _x_. # def *(x); memberwise(:*, x) end # # Returns a new Tms object obtained by memberwise division # of the individual times for this Tms object by _x_. # This method and #+() are useful for taking statistics. # def /(x); memberwise(:/, x) end # # Returns the contents of this Tms object as # a formatted string, according to a format string # like that passed to Kernel.format. In addition, #format # accepts the following extensions: # # %u:: Replaced by the user CPU time, as reported by Tms#utime. # %y:: Replaced by the system CPU time, as reported by #stime (Mnemonic: y of "s*y*stem") # %U:: Replaced by the children's user CPU time, as reported by Tms#cutime # %Y:: Replaced by the children's system CPU time, as reported by Tms#cstime # %t:: Replaced by the total CPU time, as reported by Tms#total # %r:: Replaced by the elapsed real time, as reported by Tms#real # %n:: Replaced by the label string, as reported by Tms#label (Mnemonic: n of "*n*ame") # # If _format_ is not given, FORMAT is used as default value, detailing the # user, system and real elapsed time. # def format(format = nil, *args) str = (format || FORMAT).dup str.gsub!(/(%[-+.\d]*)n/) { "#{$1}s" % label } str.gsub!(/(%[-+.\d]*)u/) { "#{$1}f" % utime } str.gsub!(/(%[-+.\d]*)y/) { "#{$1}f" % stime } str.gsub!(/(%[-+.\d]*)U/) { "#{$1}f" % cutime } str.gsub!(/(%[-+.\d]*)Y/) { "#{$1}f" % cstime } str.gsub!(/(%[-+.\d]*)t/) { "#{$1}f" % total } str.gsub!(/(%[-+.\d]*)r/) { "(#{$1}f)" % real } format ? str % args : str end # # Same as #format. # def to_s format end # # Returns a new 6-element array, consisting of the # label, user CPU time, system CPU time, children's # user CPU time, children's system CPU time and elapsed # real time. # def to_a [@label, @utime, @stime, @cutime, @cstime, @real] end protected # # Returns a new Tms object obtained by memberwise operation +op+ # of the individual times for this Tms object with those of the other # Tms object. # # +op+ can be a mathematical operation such as +, -, # *, / # def memberwise(op, x) case x when Benchmark::Tms Benchmark::Tms.new(utime.__send__(op, x.utime), stime.__send__(op, x.stime), cutime.__send__(op, x.cutime), cstime.__send__(op, x.cstime), real.__send__(op, x.real) ) else Benchmark::Tms.new(utime.__send__(op, x), stime.__send__(op, x), cutime.__send__(op, x), cstime.__send__(op, x), real.__send__(op, x) ) end end end # The default caption string (heading above the output times). CAPTION = Benchmark::Tms::CAPTION # The default format string used to display times. See also Benchmark::Tms#format. FORMAT = Benchmark::Tms::FORMAT end PK!X#I2.2.0/kconv.rbnu[# # kconv.rb - Kanji Converter. # # $Id: kconv.rb 30112 2010-12-07 11:47:39Z naruse $ # # ---- # # kconv.rb implements the Kconv class for Kanji Converter. Additionally, # some methods in String classes are added to allow easy conversion. # require 'nkf' # # Kanji Converter for Ruby. # module Kconv # # Public Constants # #Constant of Encoding # Auto-Detect AUTO = NKF::AUTO # ISO-2022-JP JIS = NKF::JIS # EUC-JP EUC = NKF::EUC # Shift_JIS SJIS = NKF::SJIS # BINARY BINARY = NKF::BINARY # NOCONV NOCONV = NKF::NOCONV # ASCII ASCII = NKF::ASCII # UTF-8 UTF8 = NKF::UTF8 # UTF-16 UTF16 = NKF::UTF16 # UTF-32 UTF32 = NKF::UTF32 # UNKNOWN UNKNOWN = NKF::UNKNOWN # # Public Methods # # call-seq: # Kconv.kconv(str, to_enc, from_enc=nil) # # Convert str to to_enc. # to_enc and from_enc are given as constants of Kconv or Encoding objects. def kconv(str, to_enc, from_enc=nil) opt = '' opt += ' --ic=' + from_enc.to_s if from_enc opt += ' --oc=' + to_enc.to_s if to_enc ::NKF::nkf(opt, str) end module_function :kconv # # Encode to # # call-seq: # Kconv.tojis(str) => string # # Convert str to ISO-2022-JP def tojis(str) kconv(str, JIS) end module_function :tojis # call-seq: # Kconv.toeuc(str) => string # # Convert str to EUC-JP def toeuc(str) kconv(str, EUC) end module_function :toeuc # call-seq: # Kconv.tosjis(str) => string # # Convert str to Shift_JIS def tosjis(str) kconv(str, SJIS) end module_function :tosjis # call-seq: # Kconv.toutf8(str) => string # # Convert str to UTF-8 def toutf8(str) kconv(str, UTF8) end module_function :toutf8 # call-seq: # Kconv.toutf16(str) => string # # Convert str to UTF-16 def toutf16(str) kconv(str, UTF16) end module_function :toutf16 # call-seq: # Kconv.toutf32(str) => string # # Convert str to UTF-32 def toutf32(str) kconv(str, UTF32) end module_function :toutf32 # call-seq: # Kconv.tolocale => string # # Convert self to locale encoding def tolocale(str) kconv(str, Encoding.locale_charmap) end module_function :tolocale # # guess # # call-seq: # Kconv.guess(str) => encoding # # Guess input encoding by NKF.guess def guess(str) ::NKF::guess(str) end module_function :guess # # isEncoding # # call-seq: # Kconv.iseuc(str) => true or false # # Returns whether input encoding is EUC-JP or not. # # *Note* don't expect this return value is MatchData. def iseuc(str) str.dup.force_encoding(EUC).valid_encoding? end module_function :iseuc # call-seq: # Kconv.issjis(str) => true or false # # Returns whether input encoding is Shift_JIS or not. def issjis(str) str.dup.force_encoding(SJIS).valid_encoding? end module_function :issjis # call-seq: # Kconv.isjis(str) => true or false # # Returns whether input encoding is ISO-2022-JP or not. def isjis(str) /\A [\t\n\r\x20-\x7E]* (?: (?:\x1b \x28 I [\x21-\x7E]* |\x1b \x28 J [\x21-\x7E]* |\x1b \x24 @ (?:[\x21-\x7E]{2})* |\x1b \x24 B (?:[\x21-\x7E]{2})* |\x1b \x24 \x28 D (?:[\x21-\x7E]{2})* )* \x1b \x28 B [\t\n\r\x20-\x7E]* )* \z/nox =~ str.dup.force_encoding('BINARY') ? true : false end module_function :isjis # call-seq: # Kconv.isutf8(str) => true or false # # Returns whether input encoding is UTF-8 or not. def isutf8(str) str.dup.force_encoding(UTF8).valid_encoding? end module_function :isutf8 end class String # call-seq: # String#kconv(to_enc, from_enc) # # Convert self to to_enc. # to_enc and from_enc are given as constants of Kconv or Encoding objects. def kconv(to_enc, from_enc=nil) from_enc = self.encoding if !from_enc && self.encoding != Encoding.list[0] Kconv::kconv(self, to_enc, from_enc) end # # to Encoding # # call-seq: # String#tojis => string # # Convert self to ISO-2022-JP def tojis; Kconv.tojis(self) end # call-seq: # String#toeuc => string # # Convert self to EUC-JP def toeuc; Kconv.toeuc(self) end # call-seq: # String#tosjis => string # # Convert self to Shift_JIS def tosjis; Kconv.tosjis(self) end # call-seq: # String#toutf8 => string # # Convert self to UTF-8 def toutf8; Kconv.toutf8(self) end # call-seq: # String#toutf16 => string # # Convert self to UTF-16 def toutf16; Kconv.toutf16(self) end # call-seq: # String#toutf32 => string # # Convert self to UTF-32 def toutf32; Kconv.toutf32(self) end # call-seq: # String#tolocale => string # # Convert self to locale encoding def tolocale; Kconv.tolocale(self) end # # is Encoding # # call-seq: # String#iseuc => true or false # # Returns whether self's encoding is EUC-JP or not. def iseuc; Kconv.iseuc(self) end # call-seq: # String#issjis => true or false # # Returns whether self's encoding is Shift_JIS or not. def issjis; Kconv.issjis(self) end # call-seq: # String#isjis => true or false # # Returns whether self's encoding is ISO-2022-JP or not. def isjis; Kconv.isjis(self) end # call-seq: # String#isutf8 => true or false # # Returns whether self's encoding is UTF-8 or not. def isutf8; Kconv.isutf8(self) end end PK! x 2.2.0/find.rbnu[# # find.rb: the Find module for processing all files under a given directory. # # # The +Find+ module supports the top-down traversal of a set of file paths. # # For example, to total the size of all files under your home directory, # ignoring anything in a "dot" directory (e.g. $HOME/.ssh): # # require 'find' # # total_size = 0 # # Find.find(ENV["HOME"]) do |path| # if FileTest.directory?(path) # if File.basename(path)[0] == ?. # Find.prune # Don't look any further into this directory. # else # next # end # else # total_size += FileTest.size(path) # end # end # module Find # # Calls the associated block with the name of every file and directory listed # as arguments, then recursively on their subdirectories, and so on. # # Returns an enumerator if no block is given. # # See the +Find+ module documentation for an example. # def find(*paths, ignore_error: true) # :yield: path block_given? or return enum_for(__method__, *paths, ignore_error: ignore_error) fs_encoding = Encoding.find("filesystem") paths.collect!{|d| raise Errno::ENOENT unless File.exist?(d); d.dup}.each do |path| path = path.to_path if path.respond_to? :to_path enc = path.encoding == Encoding::US_ASCII ? fs_encoding : path.encoding ps = [path] while file = ps.shift catch(:prune) do yield file.dup.taint begin s = File.lstat(file) rescue Errno::ENOENT, Errno::EACCES, Errno::ENOTDIR, Errno::ELOOP, Errno::ENAMETOOLONG raise unless ignore_error next end if s.directory? then begin fs = Dir.entries(file, encoding: enc) rescue Errno::ENOENT, Errno::EACCES, Errno::ENOTDIR, Errno::ELOOP, Errno::ENAMETOOLONG raise unless ignore_error next end fs.sort! fs.reverse_each {|f| next if f == "." or f == ".." f = File.join(file, f) ps.unshift f.untaint } end end end end nil end # # Skips the current file or directory, restarting the loop with the next # entry. If the current file is a directory, that directory will not be # recursively entered. Meaningful only within the block associated with # Find::find. # # See the +Find+ module documentation for an example. # def prune throw :prune end module_function :find, :prune end PK!yi5!!2.2.0/xmlrpc.rbnu[# == Author and Copyright # # Copyright (C) 2001-2004 by Michael Neumann (mailto:mneumann@ntecs.de) # # Released under the same term of license as Ruby. # # == Overview # # XMLRPC is a lightweight protocol that enables remote procedure calls over # HTTP. It is defined at http://www.xmlrpc.com. # # XMLRPC allows you to create simple distributed computing solutions that span # computer languages. Its distinctive feature is its simplicity compared to # other approaches like SOAP and CORBA. # # The Ruby standard library package 'xmlrpc' enables you to create a server that # implements remote procedures and a client that calls them. Very little code # is required to achieve either of these. # # == Example # # Try the following code. It calls a standard demonstration remote procedure. # # require 'xmlrpc/client' # require 'pp' # # server = XMLRPC::Client.new2("http://xmlrpc-c.sourceforge.net/api/sample.php") # result = server.call("sample.sumAndDifference", 5, 3) # pp result # # == Documentation # # See http://www.ntecs.de/ruby/xmlrpc4r/. There is plenty of detail there to # use the client and implement a server. # # == Features of XMLRPC for Ruby # # * Extensions # * Introspection # * multiCall # * optionally nil values and integers larger than 32 Bit # # * Server # * Standalone XML-RPC server # * CGI-based (works with FastCGI) # * Apache mod_ruby server # * WEBrick servlet # # * Client # * synchronous/asynchronous calls # * Basic HTTP-401 Authentication # * HTTPS protocol (SSL) # # * Parsers # * NQXML (XMLParser::NQXMLStreamParser, XMLParser::NQXMLTreeParser) # * Expat (XMLParser::XMLStreamParser, XMLParser::XMLTreeParser) # * REXML (XMLParser::REXMLStreamParser) # * xml-scan (XMLParser::XMLScanStreamParser) # * Fastest parser is Expat's XMLParser::XMLStreamParser! # # * General # * possible to choose between XMLParser module (Expat wrapper) and REXML/NQXML (pure Ruby) parsers # * Marshalling Ruby objects to Hashs and reconstruct them later from a Hash # * SandStorm component architecture XMLRPC::Client interface # # == Howto # # === Client # # require "xmlrpc/client" # # # Make an object to represent the XML-RPC server. # server = XMLRPC::Client.new( "xmlrpc-c.sourceforge.net", "/api/sample.php") # # # Call the remote server and get our result # result = server.call("sample.sumAndDifference", 5, 3) # # sum = result["sum"] # difference = result["difference"] # # puts "Sum: #{sum}, Difference: #{difference}" # # === XMLRPC::Client with XML-RPC fault-structure handling # # There are two possible ways, of handling a fault-structure: # # ==== by catching a XMLRPC::FaultException exception # # require "xmlrpc/client" # # # Make an object to represent the XML-RPC server. # server = XMLRPC::Client.new( "xmlrpc-c.sourceforge.net", "/api/sample.php") # # begin # # Call the remote server and get our result # result = server.call("sample.sumAndDifference", 5, 3) # # sum = result["sum"] # difference = result["difference"] # # puts "Sum: #{sum}, Difference: #{difference}" # # rescue XMLRPC::FaultException => e # puts "Error: " # puts e.faultCode # puts e.faultString # end # # ==== by calling "call2" which returns a boolean # # require "xmlrpc/client" # # # Make an object to represent the XML-RPC server. # server = XMLRPC::Client.new( "xmlrpc-c.sourceforge.net", "/api/sample.php") # # # Call the remote server and get our result # ok, result = server.call2("sample.sumAndDifference", 5, 3) # # if ok # sum = result["sum"] # difference = result["difference"] # # puts "Sum: #{sum}, Difference: #{difference}" # else # puts "Error: " # puts result.faultCode # puts result.faultString # end # # === Using XMLRPC::Client::Proxy # # You can create a Proxy object onto which you can call methods. This way it # looks nicer. Both forms, _call_ and _call2_ are supported through _proxy_ and # _proxy2_. You can additionally give arguments to the Proxy, which will be # given to each XML-RPC call using that Proxy. # # require "xmlrpc/client" # # # Make an object to represent the XML-RPC server. # server = XMLRPC::Client.new( "xmlrpc-c.sourceforge.net", "/api/sample.php") # # # Create a Proxy object # sample = server.proxy("sample") # # # Call the remote server and get our result # result = sample.sumAndDifference(5,3) # # sum = result["sum"] # difference = result["difference"] # # puts "Sum: #{sum}, Difference: #{difference}" # # === CGI-based server using XMLRPC::CGIServer # # There are also two ways to define handler, the first is # like C/PHP, the second like Java, of course both ways # can be mixed: # # ==== C/PHP-like (handler functions) # # require "xmlrpc/server" # # s = XMLRPC::CGIServer.new # # s.add_handler("sample.sumAndDifference") do |a,b| # { "sum" => a + b, "difference" => a - b } # end # # s.serve # # ==== Java-like (handler classes) # # require "xmlrpc/server" # # s = XMLRPC::CGIServer.new # # class MyHandler # def sumAndDifference(a, b) # { "sum" => a + b, "difference" => a - b } # end # end # # # NOTE: Security Hole (read below)!!! # s.add_handler("sample", MyHandler.new) # s.serve # # # To return a fault-structure you have to raise an XMLRPC::FaultException e.g.: # # raise XMLRPC::FaultException.new(3, "division by Zero") # # ===== Security Note # # From Brian Candler: # # Above code sample has an extremely nasty security hole, in that you can now call # any method of 'MyHandler' remotely, including methods inherited from Object # and Kernel! For example, in the client code, you can use # # puts server.call("sample.send","`","ls") # # (backtick being the method name for running system processes). Needless to # say, 'ls' can be replaced with something else. # # The version which binds proc objects (or the version presented below in the next section) # doesn't have this problem, but people may be tempted to use the second version because it's # so nice and 'Rubyesque'. I think it needs a big red disclaimer. # # # From Michael: # # A solution is to undef insecure methods or to use # XMLRPC::Service::PublicInstanceMethodsInterface as shown below: # # class MyHandler # def sumAndDifference(a, b) # { "sum" => a + b, "difference" => a - b } # end # end # # # ... server initialization ... # # s.add_handler(XMLRPC::iPIMethods("sample"), MyHandler.new) # # # ... # # This adds only public instance methods explicitly declared in class MyHandler # (and not those inherited from any other class). # # ==== With interface declarations # # Code sample from the book Ruby Developer's Guide: # # require "xmlrpc/server" # # class Num # INTERFACE = XMLRPC::interface("num") { # meth 'int add(int, int)', 'Add two numbers', 'add' # meth 'int div(int, int)', 'Divide two numbers' # } # # def add(a, b) a + b end # def div(a, b) a / b end # end # # # s = XMLRPC::CGIServer.new # s.add_handler(Num::INTERFACE, Num.new) # s.serve # # === Standalone XMLRPC::Server # # Same as CGI-based server, the only difference being # # server = XMLRPC::CGIServer.new # # must be changed to # # server = XMLRPC::Server.new(8080) # # if you want a server listening on port 8080. # The rest is the same. # # === Choosing a different XMLParser or XMLWriter # # The examples above all use the default parser (which is now since 1.8 # XMLParser::REXMLStreamParser) and a default XMLRPC::XMLWriter. # If you want to use a different XMLParser, then you have to call the # ParserWriterChooseMixin#set_parser method of XMLRPC::Client instances # or instances of subclasses of XMLRPC::BasicServer or by editing # xmlrpc/config.rb. # # XMLRPC::Client Example: # # # ... # server = XMLRPC::Client.new( "xmlrpc-c.sourceforge.net", "/api/sample.php") # server.set_parser(XMLRPC::XMLParser::XMLParser.new) # # ... # # XMLRPC::Server Example: # # # ... # s = XMLRPC::CGIServer.new # s.set_parser(XMLRPC::XMLParser::XMLStreamParser.new) # # ... # # or: # # # ... # server = XMLRPC::Server.new(8080) # server.set_parser(XMLRPC::XMLParser::NQXMLParser.new) # # ... # # # Note that XMLParser::XMLStreamParser is incredible faster (and uses less memory) than any # other parser and scales well for large documents. For example for a 0.5 MB XML # document with many tags, XMLParser::XMLStreamParser is ~350 (!) times faster than # XMLParser::NQXMLTreeParser and still ~18 times as fast as XMLParser::XMLTreeParser. # # You can change the XML-writer by calling method ParserWriterChooseMixin#set_writer. module XMLRPC; end PK!U  2.2.0/ripper.rbnu[require 'ripper/core' require 'ripper/lexer' require 'ripper/filter' require 'ripper/sexp' # Ripper is a Ruby script parser. # # You can get information from the parser with event-based style. # Information such as abstract syntax trees or simple lexical analysis of the # Ruby program. # # == Usage # # Ripper provides an easy interface for parsing your program into a symbolic # expression tree (or S-expression). # # Understanding the output of the parser may come as a challenge, it's # recommended you use PP to format the output for legibility. # # require 'ripper' # require 'pp' # # pp Ripper.sexp('def hello(world) "Hello, #{world}!"; end') # #=> [:program, # [[:def, # [:@ident, "hello", [1, 4]], # [:paren, # [:params, [[:@ident, "world", [1, 10]]], nil, nil, nil, nil, nil, nil]], # [:bodystmt, # [[:string_literal, # [:string_content, # [:@tstring_content, "Hello, ", [1, 18]], # [:string_embexpr, [[:var_ref, [:@ident, "world", [1, 27]]]]], # [:@tstring_content, "!", [1, 33]]]]], # nil, # nil, # nil]]]] # # You can see in the example above, the expression starts with +:program+. # # From here, a method definition at +:def+, followed by the method's identifier # :@ident. After the method's identifier comes the parentheses # +:paren+ and the method parameters under +:params+. # # Next is the method body, starting at +:bodystmt+ (+stmt+ meaning statement), # which contains the full definition of the method. # # In our case, we're simply returning a String, so next we have the # +:string_literal+ expression. # # Within our +:string_literal+ you'll notice two @tstring_content, # this is the literal part for Hello, and !. Between # the two @tstring_content statements is a +:string_embexpr+, # where _embexpr_ is an embedded expression. Our expression consists of a local # variable, or +var_ref+, with the identifier (@ident) of +world+. # # == Resources # # * {Ruby Inside}[http://www.rubyinside.com/using-ripper-to-see-how-ruby-is-parsing-your-code-5270.html] # # == Requirements # # * ruby 1.9 (support CVS HEAD only) # * bison 1.28 or later (Other yaccs do not work) # # == License # # Ruby License. # # Minero Aoki # aamine@loveruby.net # http://i.loveruby.net class Ripper; end PK!/)G 2.2.0/io/console/size.rbnu[# fallback to console window size def IO.default_console_size [ ENV["LINES"].to_i.nonzero? || 25, ENV["COLUMNS"].to_i.nonzero? || 80, ] end begin require 'io/console' rescue LoadError class IO alias console_size default_console_size end else # returns console window size def IO.console_size console.winsize rescue NoMethodError default_console_size end end PK!"IGIG2.2.0/racc/parser.rbnu[#-- # $originalId: parser.rb,v 1.8 2006/07/06 11:42:07 aamine Exp $ # # Copyright (c) 1999-2006 Minero Aoki # # This program is free software. # You can distribute/modify this program under the same terms of ruby. # # As a special exception, when this code is copied by Racc # into a Racc output file, you may use that output file # without restriction. #++ module Racc class ParseError < StandardError; end end unless defined?(::ParseError) ParseError = Racc::ParseError end # Racc is a LALR(1) parser generator. # It is written in Ruby itself, and generates Ruby programs. # # == Command-line Reference # # racc [-ofilename] [--output-file=filename] # [-erubypath] [--embedded=rubypath] # [-v] [--verbose] # [-Ofilename] [--log-file=filename] # [-g] [--debug] # [-E] [--embedded] # [-l] [--no-line-convert] # [-c] [--line-convert-all] # [-a] [--no-omit-actions] # [-C] [--check-only] # [-S] [--output-status] # [--version] [--copyright] [--help] grammarfile # # [+filename+] # Racc grammar file. Any extension is permitted. # [-o+outfile+, --output-file=+outfile+] # A filename for output. default is <+filename+>.tab.rb # [-O+filename+, --log-file=+filename+] # Place logging output in file +filename+. # Default log file name is <+filename+>.output. # [-e+rubypath+, --executable=+rubypath+] # output executable file(mode 755). where +path+ is the Ruby interpreter. # [-v, --verbose] # verbose mode. create +filename+.output file, like yacc's y.output file. # [-g, --debug] # add debug code to parser class. To display debugging information, # use this '-g' option and set @yydebug true in parser class. # [-E, --embedded] # Output parser which doesn't need runtime files (racc/parser.rb). # [-C, --check-only] # Check syntax of racc grammar file and quit. # [-S, --output-status] # Print messages time to time while compiling. # [-l, --no-line-convert] # turns off line number converting. # [-c, --line-convert-all] # Convert line number of actions, inner, header and footer. # [-a, --no-omit-actions] # Call all actions, even if an action is empty. # [--version] # print Racc version and quit. # [--copyright] # Print copyright and quit. # [--help] # Print usage and quit. # # == Generating Parser Using Racc # # To compile Racc grammar file, simply type: # # $ racc parse.y # # This creates Ruby script file "parse.tab.y". The -o option can change the output filename. # # == Writing A Racc Grammar File # # If you want your own parser, you have to write a grammar file. # A grammar file contains the name of your parser class, grammar for the parser, # user code, and anything else. # When writing a grammar file, yacc's knowledge is helpful. # If you have not used yacc before, Racc is not too difficult. # # Here's an example Racc grammar file. # # class Calcparser # rule # target: exp { print val[0] } # # exp: exp '+' exp # | exp '*' exp # | '(' exp ')' # | NUMBER # end # # Racc grammar files resemble yacc files. # But (of course), this is Ruby code. # yacc's $$ is the 'result', $0, $1... is # an array called 'val', and $-1, $-2... is an array called '_values'. # # See the {Grammar File Reference}[rdoc-ref:lib/racc/rdoc/grammar.en.rdoc] for # more information on grammar files. # # == Parser # # Then you must prepare the parse entry method. There are two types of # parse methods in Racc, Racc::Parser#do_parse and Racc::Parser#yyparse # # Racc::Parser#do_parse is simple. # # It's yyparse() of yacc, and Racc::Parser#next_token is yylex(). # This method must returns an array like [TOKENSYMBOL, ITS_VALUE]. # EOF is [false, false]. # (TOKENSYMBOL is a Ruby symbol (taken from String#intern) by default. # If you want to change this, see the grammar reference. # # Racc::Parser#yyparse is little complicated, but useful. # It does not use Racc::Parser#next_token, instead it gets tokens from any iterator. # # For example, yyparse(obj, :scan) causes # calling +obj#scan+, and you can return tokens by yielding them from +obj#scan+. # # == Debugging # # When debugging, "-v" or/and the "-g" option is helpful. # # "-v" creates verbose log file (.output). # "-g" creates a "Verbose Parser". # Verbose Parser prints the internal status when parsing. # But it's _not_ automatic. # You must use -g option and set +@yydebug+ to +true+ in order to get output. # -g option only creates the verbose parser. # # === Racc reported syntax error. # # Isn't there too many "end"? # grammar of racc file is changed in v0.10. # # Racc does not use '%' mark, while yacc uses huge number of '%' marks.. # # === Racc reported "XXXX conflicts". # # Try "racc -v xxxx.y". # It causes producing racc's internal log file, xxxx.output. # # === Generated parsers does not work correctly # # Try "racc -g xxxx.y". # This command let racc generate "debugging parser". # Then set @yydebug=true in your parser. # It produces a working log of your parser. # # == Re-distributing Racc runtime # # A parser, which is created by Racc, requires the Racc runtime module; # racc/parser.rb. # # Ruby 1.8.x comes with Racc runtime module, # you need NOT distribute Racc runtime files. # # If you want to include the Racc runtime module with your parser. # This can be done by using '-E' option: # # $ racc -E -omyparser.rb myparser.y # # This command creates myparser.rb which `includes' Racc runtime. # Only you must do is to distribute your parser file (myparser.rb). # # Note: parser.rb is LGPL, but your parser is not. # Your own parser is completely yours. module Racc unless defined?(Racc_No_Extensions) Racc_No_Extensions = false # :nodoc: end class Parser Racc_Runtime_Version = '1.4.6' Racc_Runtime_Revision = %w$originalRevision: 1.8 $[1] Racc_Runtime_Core_Version_R = '1.4.6' Racc_Runtime_Core_Revision_R = %w$originalRevision: 1.8 $[1] begin require 'racc/cparse' # Racc_Runtime_Core_Version_C = (defined in extension) Racc_Runtime_Core_Revision_C = Racc_Runtime_Core_Id_C.split[2] unless new.respond_to?(:_racc_do_parse_c, true) raise LoadError, 'old cparse.so' end if Racc_No_Extensions raise LoadError, 'selecting ruby version of racc runtime core' end Racc_Main_Parsing_Routine = :_racc_do_parse_c # :nodoc: Racc_YY_Parse_Method = :_racc_yyparse_c # :nodoc: Racc_Runtime_Core_Version = Racc_Runtime_Core_Version_C # :nodoc: Racc_Runtime_Core_Revision = Racc_Runtime_Core_Revision_C # :nodoc: Racc_Runtime_Type = 'c' # :nodoc: rescue LoadError Racc_Main_Parsing_Routine = :_racc_do_parse_rb Racc_YY_Parse_Method = :_racc_yyparse_rb Racc_Runtime_Core_Version = Racc_Runtime_Core_Version_R Racc_Runtime_Core_Revision = Racc_Runtime_Core_Revision_R Racc_Runtime_Type = 'ruby' end def Parser.racc_runtime_type # :nodoc: Racc_Runtime_Type end def _racc_setup @yydebug = false unless self.class::Racc_debug_parser @yydebug = false unless defined?(@yydebug) if @yydebug @racc_debug_out = $stderr unless defined?(@racc_debug_out) @racc_debug_out ||= $stderr end arg = self.class::Racc_arg arg[13] = true if arg.size < 14 arg end def _racc_init_sysvars @racc_state = [0] @racc_tstack = [] @racc_vstack = [] @racc_t = nil @racc_val = nil @racc_read_next = true @racc_user_yyerror = false @racc_error_status = 0 end # The entry point of the parser. This method is used with #next_token. # If Racc wants to get token (and its value), calls next_token. # # Example: # def parse # @q = [[1,1], # [2,2], # [3,3], # [false, '$']] # do_parse # end # # def next_token # @q.shift # end def do_parse __send__(Racc_Main_Parsing_Routine, _racc_setup(), false) end # The method to fetch next token. # If you use #do_parse method, you must implement #next_token. # # The format of return value is [TOKEN_SYMBOL, VALUE]. # +token-symbol+ is represented by Ruby's symbol by default, e.g. :IDENT # for 'IDENT'. ";" (String) for ';'. # # The final symbol (End of file) must be false. def next_token raise NotImplementedError, "#{self.class}\#next_token is not defined" end def _racc_do_parse_rb(arg, in_debug) action_table, action_check, action_default, action_pointer, _, _, _, _, _, _, token_table, _, _, _, * = arg _racc_init_sysvars tok = act = i = nil catch(:racc_end_parse) { while true if i = action_pointer[@racc_state[-1]] if @racc_read_next if @racc_t != 0 # not EOF tok, @racc_val = next_token() unless tok # EOF @racc_t = 0 else @racc_t = (token_table[tok] or 1) # error token end racc_read_token(@racc_t, tok, @racc_val) if @yydebug @racc_read_next = false end end i += @racc_t unless i >= 0 and act = action_table[i] and action_check[i] == @racc_state[-1] act = action_default[@racc_state[-1]] end else act = action_default[@racc_state[-1]] end while act = _racc_evalact(act, arg) ; end end } end # Another entry point for the parser. # If you use this method, you must implement RECEIVER#METHOD_ID method. # # RECEIVER#METHOD_ID is a method to get next token. # It must 'yield' the token, which format is [TOKEN-SYMBOL, VALUE]. def yyparse(recv, mid) __send__(Racc_YY_Parse_Method, recv, mid, _racc_setup(), true) end def _racc_yyparse_rb(recv, mid, arg, c_debug) action_table, action_check, action_default, action_pointer, _, _, _, _, _, _, token_table, _, _, _, * = arg _racc_init_sysvars act = nil i = nil catch(:racc_end_parse) { until i = action_pointer[@racc_state[-1]] while act = _racc_evalact(action_default[@racc_state[-1]], arg) ; end end recv.__send__(mid) do |tok, val| unless tok @racc_t = 0 else @racc_t = (token_table[tok] or 1) # error token end @racc_val = val @racc_read_next = false i += @racc_t unless i >= 0 and act = action_table[i] and action_check[i] == @racc_state[-1] act = action_default[@racc_state[-1]] end while act = _racc_evalact(act, arg) ; end while not(i = action_pointer[@racc_state[-1]]) or not @racc_read_next or @racc_t == 0 # $ unless i and i += @racc_t and i >= 0 and act = action_table[i] and action_check[i] == @racc_state[-1] act = action_default[@racc_state[-1]] end while act = _racc_evalact(act, arg) ; end end end } end ### ### common ### def _racc_evalact(act, arg) action_table, action_check, _, action_pointer, _, _, _, _, _, _, _, shift_n, reduce_n, _, _, * = arg if act > 0 and act < shift_n # # shift # if @racc_error_status > 0 @racc_error_status -= 1 unless @racc_t == 1 # error token end @racc_vstack.push @racc_val @racc_state.push act @racc_read_next = true if @yydebug @racc_tstack.push @racc_t racc_shift @racc_t, @racc_tstack, @racc_vstack end elsif act < 0 and act > -reduce_n # # reduce # code = catch(:racc_jump) { @racc_state.push _racc_do_reduce(arg, act) false } if code case code when 1 # yyerror @racc_user_yyerror = true # user_yyerror return -reduce_n when 2 # yyaccept return shift_n else raise '[Racc Bug] unknown jump code' end end elsif act == shift_n # # accept # racc_accept if @yydebug throw :racc_end_parse, @racc_vstack[0] elsif act == -reduce_n # # error # case @racc_error_status when 0 unless arg[21] # user_yyerror on_error @racc_t, @racc_val, @racc_vstack end when 3 if @racc_t == 0 # is $ throw :racc_end_parse, nil end @racc_read_next = true end @racc_user_yyerror = false @racc_error_status = 3 while true if i = action_pointer[@racc_state[-1]] i += 1 # error token if i >= 0 and (act = action_table[i]) and action_check[i] == @racc_state[-1] break end end throw :racc_end_parse, nil if @racc_state.size <= 1 @racc_state.pop @racc_vstack.pop if @yydebug @racc_tstack.pop racc_e_pop @racc_state, @racc_tstack, @racc_vstack end end return act else raise "[Racc Bug] unknown action #{act.inspect}" end racc_next_state(@racc_state[-1], @racc_state) if @yydebug nil end def _racc_do_reduce(arg, act) _, _, _, _, goto_table, goto_check, goto_default, goto_pointer, nt_base, reduce_table, _, _, _, use_result, * = arg state = @racc_state vstack = @racc_vstack tstack = @racc_tstack i = act * -3 len = reduce_table[i] reduce_to = reduce_table[i+1] method_id = reduce_table[i+2] void_array = [] tmp_t = tstack[-len, len] if @yydebug tmp_v = vstack[-len, len] tstack[-len, len] = void_array if @yydebug vstack[-len, len] = void_array state[-len, len] = void_array # tstack must be updated AFTER method call if use_result vstack.push __send__(method_id, tmp_v, vstack, tmp_v[0]) else vstack.push __send__(method_id, tmp_v, vstack) end tstack.push reduce_to racc_reduce(tmp_t, reduce_to, tstack, vstack) if @yydebug k1 = reduce_to - nt_base if i = goto_pointer[k1] i += state[-1] if i >= 0 and (curstate = goto_table[i]) and goto_check[i] == k1 return curstate end end goto_default[k1] end # This method is called when a parse error is found. # # ERROR_TOKEN_ID is an internal ID of token which caused error. # You can get string representation of this ID by calling # #token_to_str. # # ERROR_VALUE is a value of error token. # # value_stack is a stack of symbol values. # DO NOT MODIFY this object. # # This method raises ParseError by default. # # If this method returns, parsers enter "error recovering mode". def on_error(t, val, vstack) raise ParseError, sprintf("\nparse error on value %s (%s)", val.inspect, token_to_str(t) || '?') end # Enter error recovering mode. # This method does not call #on_error. def yyerror throw :racc_jump, 1 end # Exit parser. # Return value is Symbol_Value_Stack[0]. def yyaccept throw :racc_jump, 2 end # Leave error recovering mode. def yyerrok @racc_error_status = 0 end # For debugging output def racc_read_token(t, tok, val) @racc_debug_out.print 'read ' @racc_debug_out.print tok.inspect, '(', racc_token2str(t), ') ' @racc_debug_out.puts val.inspect @racc_debug_out.puts end def racc_shift(tok, tstack, vstack) @racc_debug_out.puts "shift #{racc_token2str tok}" racc_print_stacks tstack, vstack @racc_debug_out.puts end def racc_reduce(toks, sim, tstack, vstack) out = @racc_debug_out out.print 'reduce ' if toks.empty? out.print ' ' else toks.each {|t| out.print ' ', racc_token2str(t) } end out.puts " --> #{racc_token2str(sim)}" racc_print_stacks tstack, vstack @racc_debug_out.puts end def racc_accept @racc_debug_out.puts 'accept' @racc_debug_out.puts end def racc_e_pop(state, tstack, vstack) @racc_debug_out.puts 'error recovering mode: pop token' racc_print_states state racc_print_stacks tstack, vstack @racc_debug_out.puts end def racc_next_state(curstate, state) @racc_debug_out.puts "goto #{curstate}" racc_print_states state @racc_debug_out.puts end def racc_print_stacks(t, v) out = @racc_debug_out out.print ' [' t.each_index do |i| out.print ' (', racc_token2str(t[i]), ' ', v[i].inspect, ')' end out.puts ' ]' end def racc_print_states(s) out = @racc_debug_out out.print ' [' s.each {|st| out.print ' ', st } out.puts ' ]' end def racc_token2str(tok) self.class::Racc_token_to_s_table[tok] or raise "[Racc Bug] can't convert token #{tok} to string" end # Convert internal ID of token symbol to the string. def token_to_str(t) self.class::Racc_token_to_s_table[t] end end end PK!?552.2.0/observer.rbnu[# # Implementation of the _Observer_ object-oriented design pattern. The # following documentation is copied, with modifications, from "Programming # Ruby", by Hunt and Thomas; http://www.ruby-doc.org/docs/ProgrammingRuby/html/lib_patterns.html. # # See Observable for more info. # The Observer pattern (also known as publish/subscribe) provides a simple # mechanism for one object to inform a set of interested third-party objects # when its state changes. # # == Mechanism # # The notifying class mixes in the +Observable+ # module, which provides the methods for managing the associated observer # objects. # # The observable object must: # * assert that it has +#changed+ # * call +#notify_observers+ # # An observer subscribes to updates using Observable#add_observer, which also # specifies the method called via #notify_observers. The default method for # #notify_observers is #update. # # === Example # # The following example demonstrates this nicely. A +Ticker+, when run, # continually receives the stock +Price+ for its @symbol. A +Warner+ # is a general observer of the price, and two warners are demonstrated, a # +WarnLow+ and a +WarnHigh+, which print a warning if the price is below or # above their set limits, respectively. # # The +update+ callback allows the warners to run without being explicitly # called. The system is set up with the +Ticker+ and several observers, and the # observers do their duty without the top-level code having to interfere. # # Note that the contract between publisher and subscriber (observable and # observer) is not declared or enforced. The +Ticker+ publishes a time and a # price, and the warners receive that. But if you don't ensure that your # contracts are correct, nothing else can warn you. # # require "observer" # # class Ticker ### Periodically fetch a stock price. # include Observable # # def initialize(symbol) # @symbol = symbol # end # # def run # last_price = nil # loop do # price = Price.fetch(@symbol) # print "Current price: #{price}\n" # if price != last_price # changed # notify observers # last_price = price # notify_observers(Time.now, price) # end # sleep 1 # end # end # end # # class Price ### A mock class to fetch a stock price (60 - 140). # def self.fetch(symbol) # 60 + rand(80) # end # end # # class Warner ### An abstract observer of Ticker objects. # def initialize(ticker, limit) # @limit = limit # ticker.add_observer(self) # end # end # # class WarnLow < Warner # def update(time, price) # callback for observer # if price < @limit # print "--- #{time.to_s}: Price below #@limit: #{price}\n" # end # end # end # # class WarnHigh < Warner # def update(time, price) # callback for observer # if price > @limit # print "+++ #{time.to_s}: Price above #@limit: #{price}\n" # end # end # end # # ticker = Ticker.new("MSFT") # WarnLow.new(ticker, 80) # WarnHigh.new(ticker, 120) # ticker.run # # Produces: # # Current price: 83 # Current price: 75 # --- Sun Jun 09 00:10:25 CDT 2002: Price below 80: 75 # Current price: 90 # Current price: 134 # +++ Sun Jun 09 00:10:25 CDT 2002: Price above 120: 134 # Current price: 134 # Current price: 112 # Current price: 79 # --- Sun Jun 09 00:10:25 CDT 2002: Price below 80: 79 module Observable # # Add +observer+ as an observer on this object. so that it will receive # notifications. # # +observer+:: the object that will be notified of changes. # +func+:: Symbol naming the method that will be called when this Observable # has changes. # # This method must return true for +observer.respond_to?+ and will # receive *arg when #notify_observers is called, where # *arg is the value passed to #notify_observers by this # Observable def add_observer(observer, func=:update) @observer_peers = {} unless defined? @observer_peers unless observer.respond_to? func raise NoMethodError, "observer does not respond to `#{func}'" end @observer_peers[observer] = func end # # Remove +observer+ as an observer on this object so that it will no longer # receive notifications. # # +observer+:: An observer of this Observable def delete_observer(observer) @observer_peers.delete observer if defined? @observer_peers end # # Remove all observers associated with this object. # def delete_observers @observer_peers.clear if defined? @observer_peers end # # Return the number of observers associated with this object. # def count_observers if defined? @observer_peers @observer_peers.size else 0 end end # # Set the changed state of this object. Notifications will be sent only if # the changed +state+ is +true+. # # +state+:: Boolean indicating the changed state of this Observable. # def changed(state=true) @observer_state = state end # # Returns true if this object's state has been changed since the last # #notify_observers call. # def changed? if defined? @observer_state and @observer_state true else false end end # # Notify observers of a change in state *if* this object's changed state is # +true+. # # This will invoke the method named in #add_observer, passing *arg. # The changed state is then set to +false+. # # *arg:: Any arguments to pass to the observers. def notify_observers(*arg) if defined? @observer_state and @observer_state if defined? @observer_peers @observer_peers.each do |k, v| k.send v, *arg end end @observer_state = false end end end PK!2.2.0/webrick/version.rbnu[#-- # version.rb -- version and release date # # Author: IPR -- Internet Programming with Ruby -- writers # Copyright (c) 2000 TAKAHASHI Masayoshi, GOTOU YUUZOU # Copyright (c) 2003 Internet Programming with Ruby writers. All rights # reserved. # # $IPR: version.rb,v 1.74 2003/07/22 19:20:43 gotoyuzo Exp $ module WEBrick ## # The WEBrick version VERSION = "1.3.1" end PK!q"Kvv2.2.0/webrick/https.rbnu[# # https.rb -- SSL/TLS enhancement for HTTPServer # # Author: IPR -- Internet Programming with Ruby -- writers # Copyright (c) 2001 GOTOU Yuuzou # Copyright (c) 2002 Internet Programming with Ruby writers. All rights # reserved. # # $IPR: https.rb,v 1.15 2003/07/22 19:20:42 gotoyuzo Exp $ require 'webrick/ssl' module WEBrick module Config HTTP.update(SSL) end ## #-- # Adds SSL functionality to WEBrick::HTTPRequest class HTTPRequest ## # HTTP request SSL cipher attr_reader :cipher ## # HTTP request server certificate attr_reader :server_cert ## # HTTP request client certificate attr_reader :client_cert # :stopdoc: alias orig_parse parse def parse(socket=nil) if socket.respond_to?(:cert) @server_cert = socket.cert || @config[:SSLCertificate] @client_cert = socket.peer_cert @client_cert_chain = socket.peer_cert_chain @cipher = socket.cipher end orig_parse(socket) end alias orig_parse_uri parse_uri def parse_uri(str, scheme="https") if server_cert return orig_parse_uri(str, scheme) end return orig_parse_uri(str) end private :parse_uri alias orig_meta_vars meta_vars def meta_vars meta = orig_meta_vars if server_cert meta["HTTPS"] = "on" meta["SSL_SERVER_CERT"] = @server_cert.to_pem meta["SSL_CLIENT_CERT"] = @client_cert ? @client_cert.to_pem : "" if @client_cert_chain @client_cert_chain.each_with_index{|cert, i| meta["SSL_CLIENT_CERT_CHAIN_#{i}"] = cert.to_pem } end meta["SSL_CIPHER"] = @cipher[0] meta["SSL_PROTOCOL"] = @cipher[1] meta["SSL_CIPHER_USEKEYSIZE"] = @cipher[2].to_s meta["SSL_CIPHER_ALGKEYSIZE"] = @cipher[3].to_s end meta end # :startdoc: end end PK!`[2.2.0/webrick/cookie.rbnu[# # cookie.rb -- Cookie class # # Author: IPR -- Internet Programming with Ruby -- writers # Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou # Copyright (c) 2002 Internet Programming with Ruby writers. All rights # reserved. # # $IPR: cookie.rb,v 1.16 2002/09/21 12:23:35 gotoyuzo Exp $ require 'time' require 'webrick/httputils' module WEBrick ## # Processes HTTP cookies class Cookie ## # The cookie name attr_reader :name ## # The cookie value attr_accessor :value ## # The cookie version attr_accessor :version ## # The cookie domain attr_accessor :domain ## # The cookie path attr_accessor :path ## # Is this a secure cookie? attr_accessor :secure ## # The cookie comment attr_accessor :comment ## # The maximum age of the cookie attr_accessor :max_age #attr_accessor :comment_url, :discard, :port ## # Creates a new cookie with the given +name+ and +value+ def initialize(name, value) @name = name @value = value @version = 0 # Netscape Cookie @domain = @path = @secure = @comment = @max_age = @expires = @comment_url = @discard = @port = nil end ## # Sets the cookie expiration to the time +t+. The expiration time may be # a false value to disable expiration or a Time or HTTP format time string # to set the expiration date. def expires=(t) @expires = t && (t.is_a?(Time) ? t.httpdate : t.to_s) end ## # Retrieves the expiration time as a Time def expires @expires && Time.parse(@expires) end ## # The cookie string suitable for use in an HTTP header def to_s ret = "" ret << @name << "=" << @value ret << "; " << "Version=" << @version.to_s if @version > 0 ret << "; " << "Domain=" << @domain if @domain ret << "; " << "Expires=" << @expires if @expires ret << "; " << "Max-Age=" << @max_age.to_s if @max_age ret << "; " << "Comment=" << @comment if @comment ret << "; " << "Path=" << @path if @path ret << "; " << "Secure" if @secure ret end ## # Parses a Cookie field sent from the user-agent. Returns an array of # cookies. def self.parse(str) if str ret = [] cookie = nil ver = 0 str.split(/[;,]\s+/).each{|x| key, val = x.split(/=/,2) val = val ? HTTPUtils::dequote(val) : "" case key when "$Version"; ver = val.to_i when "$Path"; cookie.path = val when "$Domain"; cookie.domain = val when "$Port"; cookie.port = val else ret << cookie if cookie cookie = self.new(key, val) cookie.version = ver end } ret << cookie if cookie ret end end ## # Parses the cookie in +str+ def self.parse_set_cookie(str) cookie_elem = str.split(/;/) first_elem = cookie_elem.shift first_elem.strip! key, value = first_elem.split(/=/, 2) cookie = new(key, HTTPUtils.dequote(value)) cookie_elem.each{|pair| pair.strip! key, value = pair.split(/=/, 2) if value value = HTTPUtils.dequote(value.strip) end case key.downcase when "domain" then cookie.domain = value when "path" then cookie.path = value when "expires" then cookie.expires = value when "max-age" then cookie.max_age = Integer(value) when "comment" then cookie.comment = value when "version" then cookie.version = Integer(value) when "secure" then cookie.secure = true end } return cookie end ## # Parses the cookies in +str+ def self.parse_set_cookies(str) return str.split(/,(?=[^;,]*=)|,$/).collect{|c| parse_set_cookie(c) } end end end PK! n>2.2.0/webrick/httpservlet.rbnu[# # httpservlet.rb -- HTTPServlet Utility File # # Author: IPR -- Internet Programming with Ruby -- writers # Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou # Copyright (c) 2002 Internet Programming with Ruby writers. All rights # reserved. # # $IPR: httpservlet.rb,v 1.21 2003/02/23 12:24:46 gotoyuzo Exp $ require 'webrick/httpservlet/abstract' require 'webrick/httpservlet/filehandler' require 'webrick/httpservlet/cgihandler' require 'webrick/httpservlet/erbhandler' require 'webrick/httpservlet/prochandler' module WEBrick module HTTPServlet FileHandler.add_handler("cgi", CGIHandler) FileHandler.add_handler("rhtml", ERBHandler) end end PK!SW2.2.0/webrick/htmlutils.rbnu[#-- # htmlutils.rb -- HTMLUtils Module # # Author: IPR -- Internet Programming with Ruby -- writers # Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou # Copyright (c) 2002 Internet Programming with Ruby writers. All rights # reserved. # # $IPR: htmlutils.rb,v 1.7 2002/09/21 12:23:35 gotoyuzo Exp $ module WEBrick module HTMLUtils ## # Escapes &, ", > and < in +string+ def escape(string) return "" unless string str = string.b str.gsub!(/&/n, '&') str.gsub!(/\"/n, '"') str.gsub!(/>/n, '>') str.gsub!(/:SSLCertName is set. For more information on the various # SSL options see OpenSSL::SSL::SSLContext. # # :ServerSoftware :: # The server software name used in the Server: header. # :SSLEnable :: false, # Enable SSL for this server. Defaults to false. # :SSLCertificate :: # The SSL certificate for the server. # :SSLPrivateKey :: # The SSL private key for the server certificate. # :SSLClientCA :: nil, # Array of certificates that will be sent to the client. # :SSLExtraChainCert :: nil, # Array of certificates that will be added to the certificate chain # :SSLCACertificateFile :: nil, # Path to a CA certificate file # :SSLCACertificatePath :: nil, # Path to a directory containing CA certificates # :SSLCertificateStore :: nil, # OpenSSL::X509::Store used for certificate validation of the client # :SSLTmpDhCallback :: nil, # Callback invoked when DH parameters are required. # :SSLVerifyClient :: # Sets whether the client is verified. This defaults to VERIFY_NONE # which is typical for an HTTPS server. # :SSLVerifyDepth :: # Number of CA certificates to walk when verifying a certificate chain # :SSLVerifyCallback :: # Custom certificate verification callback # :SSLTimeout :: # Maximum session lifetime # :SSLOptions :: # Various SSL options # :SSLStartImmediately :: # Immediately start SSL upon connection? Defaults to true # :SSLCertName :: # SSL certificate name. Must be set to enable automatic certificate # creation. # :SSLCertComment :: # Comment used during automatic certificate creation. SSL = { :ServerSoftware => "#{svrsoft} OpenSSL/#{osslv}", :SSLEnable => false, :SSLCertificate => nil, :SSLPrivateKey => nil, :SSLClientCA => nil, :SSLExtraChainCert => nil, :SSLCACertificateFile => nil, :SSLCACertificatePath => nil, :SSLCertificateStore => nil, :SSLTmpDhCallback => nil, :SSLVerifyClient => ::OpenSSL::SSL::VERIFY_NONE, :SSLVerifyDepth => nil, :SSLVerifyCallback => nil, # custom verification :SSLTimeout => nil, :SSLOptions => nil, :SSLStartImmediately => true, # Must specify if you use auto generated certificate. :SSLCertName => nil, :SSLCertComment => "Generated by Ruby/OpenSSL" } General.update(SSL) end module Utils ## # Creates a self-signed certificate with the given number of +bits+, # the issuer +cn+ and a +comment+ to be stored in the certificate. def create_self_signed_cert(bits, cn, comment) rsa = OpenSSL::PKey::RSA.new(bits){|p, n| case p when 0; $stderr.putc "." # BN_generate_prime when 1; $stderr.putc "+" # BN_generate_prime when 2; $stderr.putc "*" # searching good prime, # n = #of try, # but also data from BN_generate_prime when 3; $stderr.putc "\n" # found good prime, n==0 - p, n==1 - q, # but also data from BN_generate_prime else; $stderr.putc "*" # BN_generate_prime end } cert = OpenSSL::X509::Certificate.new cert.version = 2 cert.serial = 1 name = OpenSSL::X509::Name.new(cn) cert.subject = name cert.issuer = name cert.not_before = Time.now cert.not_after = Time.now + (365*24*60*60) cert.public_key = rsa.public_key ef = OpenSSL::X509::ExtensionFactory.new(nil,cert) ef.issuer_certificate = cert cert.extensions = [ ef.create_extension("basicConstraints","CA:FALSE"), ef.create_extension("keyUsage", "keyEncipherment"), ef.create_extension("subjectKeyIdentifier", "hash"), ef.create_extension("extendedKeyUsage", "serverAuth"), ef.create_extension("nsComment", comment), ] aki = ef.create_extension("authorityKeyIdentifier", "keyid:always,issuer:always") cert.add_extension(aki) cert.sign(rsa, OpenSSL::Digest::SHA1.new) return [ cert, rsa ] end module_function :create_self_signed_cert end ## #-- # Updates WEBrick::GenericServer with SSL functionality class GenericServer ## # SSL context for the server when run in SSL mode def ssl_context # :nodoc: @ssl_context ||= nil end undef listen ## # Updates +listen+ to enable SSL when the SSL configuration is active. def listen(address, port) # :nodoc: listeners = Utils::create_listeners(address, port, @logger) if @config[:SSLEnable] unless ssl_context @ssl_context = setup_ssl_context(@config) @logger.info("\n" + @config[:SSLCertificate].to_text) end listeners.collect!{|svr| ssvr = ::OpenSSL::SSL::SSLServer.new(svr, ssl_context) ssvr.start_immediately = @config[:SSLStartImmediately] ssvr } end @listeners += listeners setup_shutdown_pipe end ## # Sets up an SSL context for +config+ def setup_ssl_context(config) # :nodoc: unless config[:SSLCertificate] cn = config[:SSLCertName] comment = config[:SSLCertComment] cert, key = Utils::create_self_signed_cert(1024, cn, comment) config[:SSLCertificate] = cert config[:SSLPrivateKey] = key end ctx = OpenSSL::SSL::SSLContext.new ctx.key = config[:SSLPrivateKey] ctx.cert = config[:SSLCertificate] ctx.client_ca = config[:SSLClientCA] ctx.extra_chain_cert = config[:SSLExtraChainCert] ctx.ca_file = config[:SSLCACertificateFile] ctx.ca_path = config[:SSLCACertificatePath] ctx.cert_store = config[:SSLCertificateStore] ctx.tmp_dh_callback = config[:SSLTmpDhCallback] ctx.verify_mode = config[:SSLVerifyClient] ctx.verify_depth = config[:SSLVerifyDepth] ctx.verify_callback = config[:SSLVerifyCallback] ctx.timeout = config[:SSLTimeout] ctx.options = config[:SSLOptions] ctx end end end PK!&O '2.2.0/webrick/httpservlet/erbhandler.rbnu[# # erbhandler.rb -- ERBHandler Class # # Author: IPR -- Internet Programming with Ruby -- writers # Copyright (c) 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou # Copyright (c) 2002 Internet Programming with Ruby writers. All rights # reserved. # # $IPR: erbhandler.rb,v 1.25 2003/02/24 19:25:31 gotoyuzo Exp $ require 'webrick/httpservlet/abstract.rb' require 'erb' module WEBrick module HTTPServlet ## # ERBHandler evaluates an ERB file and returns the result. This handler # is automatically used if there are .rhtml files in a directory served by # the FileHandler. # # ERBHandler supports GET and POST methods. # # The ERB file is evaluated with the local variables +servlet_request+ and # +servlet_response+ which are a WEBrick::HTTPRequest and # WEBrick::HTTPResponse respectively. # # Example .rhtml file: # # Request to <%= servlet_request.request_uri %> # # Query params <%= servlet_request.query.inspect %> class ERBHandler < AbstractServlet ## # Creates a new ERBHandler on +server+ that will evaluate and serve the # ERB file +name+ def initialize(server, name) super(server, name) @script_filename = name end ## # Handles GET requests def do_GET(req, res) unless defined?(ERB) @logger.warn "#{self.class}: ERB not defined." raise HTTPStatus::Forbidden, "ERBHandler cannot work." end begin data = open(@script_filename){|io| io.read } res.body = evaluate(ERB.new(data), req, res) res['content-type'] ||= HTTPUtils::mime_type(@script_filename, @config[:MimeTypes]) rescue StandardError raise rescue Exception => ex @logger.error(ex) raise HTTPStatus::InternalServerError, ex.message end end ## # Handles POST requests alias do_POST do_GET private ## # Evaluates +erb+ providing +servlet_request+ and +servlet_response+ as # local variables. def evaluate(erb, servlet_request, servlet_response) Module.new.module_eval{ servlet_request.meta_vars servlet_request.query erb.result(binding) } end end end end PK!x66'2.2.0/webrick/httpservlet/cgihandler.rbnu[# # cgihandler.rb -- CGIHandler Class # # Author: IPR -- Internet Programming with Ruby -- writers # Copyright (c) 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou # Copyright (c) 2002 Internet Programming with Ruby writers. All rights # reserved. # # $IPR: cgihandler.rb,v 1.27 2003/03/21 19:56:01 gotoyuzo Exp $ require 'rbconfig' require 'tempfile' require 'webrick/config' require 'webrick/httpservlet/abstract' module WEBrick module HTTPServlet ## # Servlet for handling CGI scripts # # Example: # # server.mount('/cgi/my_script', WEBrick::HTTPServlet::CGIHandler, # '/path/to/my_script') class CGIHandler < AbstractServlet Ruby = RbConfig.ruby # :nodoc: CGIRunner = "\"#{Ruby}\" \"#{WEBrick::Config::LIBDIR}/httpservlet/cgi_runner.rb\"" # :nodoc: ## # Creates a new CGI script servlet for the script at +name+ def initialize(server, name) super(server, name) @script_filename = name @tempdir = server[:TempDir] @cgicmd = "#{CGIRunner} #{server[:CGIInterpreter]}" end # :stopdoc: def do_GET(req, res) cgi_in = IO::popen(@cgicmd, "wb") cgi_out = Tempfile.new("webrick.cgiout.", @tempdir, mode: IO::BINARY) cgi_out.set_encoding("ASCII-8BIT") cgi_err = Tempfile.new("webrick.cgierr.", @tempdir, mode: IO::BINARY) cgi_err.set_encoding("ASCII-8BIT") begin cgi_in.sync = true meta = req.meta_vars meta["SCRIPT_FILENAME"] = @script_filename meta["PATH"] = @config[:CGIPathEnv] meta.delete("HTTP_PROXY") if /mswin|bccwin|mingw/ =~ RUBY_PLATFORM meta["SystemRoot"] = ENV["SystemRoot"] end dump = Marshal.dump(meta) cgi_in.write("%8d" % cgi_out.path.bytesize) cgi_in.write(cgi_out.path) cgi_in.write("%8d" % cgi_err.path.bytesize) cgi_in.write(cgi_err.path) cgi_in.write("%8d" % dump.bytesize) cgi_in.write(dump) req.body { |chunk| cgi_in.write(chunk) } ensure cgi_in.close status = $?.exitstatus sleep 0.1 if /mswin|bccwin|mingw/ =~ RUBY_PLATFORM data = cgi_out.read cgi_out.close(true) if errmsg = cgi_err.read if errmsg.bytesize > 0 @logger.error("CGIHandler: #{@script_filename}:\n" + errmsg) end end cgi_err.close(true) end if status != 0 @logger.error("CGIHandler: #{@script_filename} exit with #{status}") end data = "" unless data raw_header, body = data.split(/^[\xd\xa]+/, 2) raise HTTPStatus::InternalServerError, "Premature end of script headers: #{@script_filename}" if body.nil? begin header = HTTPUtils::parse_header(raw_header) if /^(\d+)/ =~ header['status'][0] res.status = $1.to_i header.delete('status') end if header.has_key?('location') # RFC 3875 6.2.3, 6.2.4 res.status = 302 unless (300...400) === res.status end if header.has_key?('set-cookie') header['set-cookie'].each{|k| res.cookies << Cookie.parse_set_cookie(k) } header.delete('set-cookie') end header.each{|key, val| res[key] = val.join(", ") } rescue => ex raise HTTPStatus::InternalServerError, ex.message end res.body = body end alias do_POST do_GET # :startdoc: end end end PK!ժ`uCC(2.2.0/webrick/httpservlet/filehandler.rbnu[# # filehandler.rb -- FileHandler Module # # Author: IPR -- Internet Programming with Ruby -- writers # Copyright (c) 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou # Copyright (c) 2003 Internet Programming with Ruby writers. All rights # reserved. # # $IPR: filehandler.rb,v 1.44 2003/06/07 01:34:51 gotoyuzo Exp $ require 'thread' require 'time' require 'webrick/htmlutils' require 'webrick/httputils' require 'webrick/httpstatus' module WEBrick module HTTPServlet ## # Servlet for serving a single file. You probably want to use the # FileHandler servlet instead as it handles directories and fancy indexes. # # Example: # # server.mount('/my_page.txt', WEBrick::HTTPServlet::DefaultFileHandler, # '/path/to/my_page.txt') # # This servlet handles If-Modified-Since and Range requests. class DefaultFileHandler < AbstractServlet ## # Creates a DefaultFileHandler instance for the file at +local_path+. def initialize(server, local_path) super(server, local_path) @local_path = local_path end # :stopdoc: def do_GET(req, res) st = File::stat(@local_path) mtime = st.mtime res['etag'] = sprintf("%x-%x-%x", st.ino, st.size, st.mtime.to_i) if not_modified?(req, res, mtime, res['etag']) res.body = '' raise HTTPStatus::NotModified elsif req['range'] make_partial_content(req, res, @local_path, st.size) raise HTTPStatus::PartialContent else mtype = HTTPUtils::mime_type(@local_path, @config[:MimeTypes]) res['content-type'] = mtype res['content-length'] = st.size res['last-modified'] = mtime.httpdate res.body = open(@local_path, "rb") end end def not_modified?(req, res, mtime, etag) if ir = req['if-range'] begin if Time.httpdate(ir) >= mtime return true end rescue if HTTPUtils::split_header_value(ir).member?(res['etag']) return true end end end if (ims = req['if-modified-since']) && Time.parse(ims) >= mtime return true end if (inm = req['if-none-match']) && HTTPUtils::split_header_value(inm).member?(res['etag']) return true end return false end # returns a lambda for webrick/httpresponse.rb send_body_proc def multipart_body(body, parts, boundary, mtype, filesize) lambda do |socket| begin begin first = parts.shift last = parts.shift socket.write( "--#{boundary}#{CRLF}" \ "Content-Type: #{mtype}#{CRLF}" \ "Content-Range: bytes #{first}-#{last}/#{filesize}#{CRLF}" \ "#{CRLF}" ) begin IO.copy_stream(body, socket, last - first + 1, first) rescue NotImplementedError body.seek(first, IO::SEEK_SET) IO.copy_stream(body, socket, last - first + 1) end socket.write(CRLF) end while parts[0] socket.write("--#{boundary}--#{CRLF}") ensure body.close end end end def make_partial_content(req, res, filename, filesize) mtype = HTTPUtils::mime_type(filename, @config[:MimeTypes]) unless ranges = HTTPUtils::parse_range_header(req['range']) raise HTTPStatus::BadRequest, "Unrecognized range-spec: \"#{req['range']}\"" end open(filename, "rb"){|io| if ranges.size > 1 time = Time.now boundary = "#{time.sec}_#{time.usec}_#{Process::pid}" parts = [] ranges.each {|range| prange = prepare_range(range, filesize) next if prange[0] < 0 parts.concat(prange) } raise HTTPStatus::RequestRangeNotSatisfiable if parts.empty? res["content-type"] = "multipart/byteranges; boundary=#{boundary}" if req.http_version < '1.1' res['connection'] = 'close' else res.chunked = true end res.body = multipart_body(io.dup, parts, boundary, mtype, filesize) elsif range = ranges[0] first, last = prepare_range(range, filesize) raise HTTPStatus::RequestRangeNotSatisfiable if first < 0 res['content-type'] = mtype res['content-range'] = "bytes #{first}-#{last}/#{filesize}" res['content-length'] = last - first + 1 res.body = io.dup else raise HTTPStatus::BadRequest end } end def prepare_range(range, filesize) first = range.first < 0 ? filesize + range.first : range.first return -1, -1 if first < 0 || first >= filesize last = range.last < 0 ? filesize + range.last : range.last last = filesize - 1 if last >= filesize return first, last end # :startdoc: end ## # Serves a directory including fancy indexing and a variety of other # options. # # Example: # # server.mount '/assets', WEBrick::FileHandler, '/path/to/assets' class FileHandler < AbstractServlet HandlerTable = Hash.new # :nodoc: ## # Allow custom handling of requests for files with +suffix+ by class # +handler+ def self.add_handler(suffix, handler) HandlerTable[suffix] = handler end ## # Remove custom handling of requests for files with +suffix+ def self.remove_handler(suffix) HandlerTable.delete(suffix) end ## # Creates a FileHandler servlet on +server+ that serves files starting # at directory +root+ # # +options+ may be a Hash containing keys from # WEBrick::Config::FileHandler or +true+ or +false+. # # If +options+ is true or false then +:FancyIndexing+ is enabled or # disabled respectively. def initialize(server, root, options={}, default=Config::FileHandler) @config = server.config @logger = @config[:Logger] @root = File.expand_path(root) if options == true || options == false options = { :FancyIndexing => options } end @options = default.dup.update(options) end # :stopdoc: def service(req, res) # if this class is mounted on "/" and /~username is requested. # we're going to override path informations before invoking service. if defined?(Etc) && @options[:UserDir] && req.script_name.empty? if %r|^(/~([^/]+))| =~ req.path_info script_name, user = $1, $2 path_info = $' begin passwd = Etc::getpwnam(user) @root = File::join(passwd.dir, @options[:UserDir]) req.script_name = script_name req.path_info = path_info rescue @logger.debug "#{self.class}#do_GET: getpwnam(#{user}) failed" end end end prevent_directory_traversal(req, res) super(req, res) end def do_GET(req, res) unless exec_handler(req, res) set_dir_list(req, res) end end def do_POST(req, res) unless exec_handler(req, res) raise HTTPStatus::NotFound, "`#{req.path}' not found." end end def do_OPTIONS(req, res) unless exec_handler(req, res) super(req, res) end end # ToDo # RFC2518: HTTP Extensions for Distributed Authoring -- WEBDAV # # PROPFIND PROPPATCH MKCOL DELETE PUT COPY MOVE # LOCK UNLOCK # RFC3253: Versioning Extensions to WebDAV # (Web Distributed Authoring and Versioning) # # VERSION-CONTROL REPORT CHECKOUT CHECK_IN UNCHECKOUT # MKWORKSPACE UPDATE LABEL MERGE ACTIVITY private def trailing_pathsep?(path) # check for trailing path separator: # File.dirname("/aaaa/bbbb/") #=> "/aaaa") # File.dirname("/aaaa/bbbb/x") #=> "/aaaa/bbbb") # File.dirname("/aaaa/bbbb") #=> "/aaaa") # File.dirname("/aaaa/bbbbx") #=> "/aaaa") return File.dirname(path) != File.dirname(path+"x") end def prevent_directory_traversal(req, res) # Preventing directory traversal on Windows platforms; # Backslashes (0x5c) in path_info are not interpreted as special # character in URI notation. So the value of path_info should be # normalize before accessing to the filesystem. # dirty hack for filesystem encoding; in nature, File.expand_path # should not be used for path normalization. [Bug #3345] path = req.path_info.dup.force_encoding(Encoding.find("filesystem")) if trailing_pathsep?(req.path_info) # File.expand_path removes the trailing path separator. # Adding a character is a workaround to save it. # File.expand_path("/aaa/") #=> "/aaa" # File.expand_path("/aaa/" + "x") #=> "/aaa/x" expanded = File.expand_path(path + "x") expanded.chop! # remove trailing "x" else expanded = File.expand_path(path) end expanded.force_encoding(req.path_info.encoding) req.path_info = expanded end def exec_handler(req, res) raise HTTPStatus::NotFound, "`#{req.path}' not found" unless @root if set_filename(req, res) handler = get_handler(req, res) call_callback(:HandlerCallback, req, res) h = handler.get_instance(@config, res.filename) h.service(req, res) return true end call_callback(:HandlerCallback, req, res) return false end def get_handler(req, res) suffix1 = (/\.(\w+)\z/ =~ res.filename) && $1.downcase if /\.(\w+)\.([\w\-]+)\z/ =~ res.filename if @options[:AcceptableLanguages].include?($2.downcase) suffix2 = $1.downcase end end handler_table = @options[:HandlerTable] return handler_table[suffix1] || handler_table[suffix2] || HandlerTable[suffix1] || HandlerTable[suffix2] || DefaultFileHandler end def set_filename(req, res) res.filename = @root.dup path_info = req.path_info.scan(%r|/[^/]*|) path_info.unshift("") # dummy for checking @root dir while base = path_info.first break if base == "/" break unless File.directory?(File.expand_path(res.filename + base)) shift_path_info(req, res, path_info) call_callback(:DirectoryCallback, req, res) end if base = path_info.first if base == "/" if file = search_index_file(req, res) shift_path_info(req, res, path_info, file) call_callback(:FileCallback, req, res) return true end shift_path_info(req, res, path_info) elsif file = search_file(req, res, base) shift_path_info(req, res, path_info, file) call_callback(:FileCallback, req, res) return true else raise HTTPStatus::NotFound, "`#{req.path}' not found." end end return false end def check_filename(req, res, name) if nondisclosure_name?(name) || windows_ambiguous_name?(name) @logger.warn("the request refers nondisclosure name `#{name}'.") raise HTTPStatus::NotFound, "`#{req.path}' not found." end end def shift_path_info(req, res, path_info, base=nil) tmp = path_info.shift base = base || tmp req.path_info = path_info.join req.script_name << base res.filename = File.expand_path(res.filename + base) check_filename(req, res, File.basename(res.filename)) end def search_index_file(req, res) @config[:DirectoryIndex].each{|index| if file = search_file(req, res, "/"+index) return file end } return nil end def search_file(req, res, basename) langs = @options[:AcceptableLanguages] path = res.filename + basename if File.file?(path) return basename elsif langs.size > 0 req.accept_language.each{|lang| path_with_lang = path + ".#{lang}" if langs.member?(lang) && File.file?(path_with_lang) return basename + ".#{lang}" end } (langs - req.accept_language).each{|lang| path_with_lang = path + ".#{lang}" if File.file?(path_with_lang) return basename + ".#{lang}" end } end return nil end def call_callback(callback_name, req, res) if cb = @options[callback_name] cb.call(req, res) end end def windows_ambiguous_name?(name) return true if /[. ]+\z/ =~ name return true if /::\$DATA\z/ =~ name return false end def nondisclosure_name?(name) @options[:NondisclosureName].each{|pattern| if File.fnmatch(pattern, name, File::FNM_CASEFOLD) return true end } return false end def set_dir_list(req, res) redirect_to_directory_uri(req, res) unless @options[:FancyIndexing] raise HTTPStatus::Forbidden, "no access permission to `#{req.path}'" end local_path = res.filename list = Dir::entries(local_path).collect{|name| next if name == "." || name == ".." next if nondisclosure_name?(name) next if windows_ambiguous_name?(name) st = (File::stat(File.join(local_path, name)) rescue nil) if st.nil? [ name, nil, -1 ] elsif st.directory? [ name + "/", st.mtime, -1 ] else [ name, st.mtime, st.size ] end } list.compact! query = req.query d0 = nil idx = nil %w[N M S].each_with_index do |q, i| if d = query.delete(q) idx ||= i d0 ||= d end end d0 ||= "A" idx ||= 0 d1 = (d0 == "A") ? "D" : "A" if d0 == "A" list.sort!{|a,b| a[idx] <=> b[idx] } else list.sort!{|a,b| b[idx] <=> a[idx] } end namewidth = query["NameWidth"] if namewidth == "*" namewidth = nil elsif !namewidth or (namewidth = namewidth.to_i) < 2 namewidth = 25 end query = query.inject('') {|s, (k, v)| s << '&' << HTMLUtils::escape("#{k}=#{v}")} type = "text/html" case enc = Encoding.find('filesystem') when Encoding::US_ASCII, Encoding::ASCII_8BIT else type << "; charset=\"#{enc.name}\"" end res['content-type'] = type title = "Index of #{HTMLUtils::escape(req.path)}" res.body = <<-_end_of_html_ #{title}

    #{title}

    _end_of_html_ res.body << "\n" res.body << "" res.body << "" res.body << "\n" res.body << "\n" res.body << "\n" query.sub!(/\A&/, '?') list.unshift [ "..", File::mtime(local_path+"/.."), -1 ] list.each{ |name, time, size| if name == ".." dname = "Parent Directory" elsif namewidth and name.size > namewidth dname = name[0...(namewidth - 2)] << '..' else dname = name end s = "" s << "" s << "\n" res.body << s } res.body << "
    NameLast modifiedSize
    #{HTMLUtils::escape(dname)}" << (time ? time.strftime("%Y/%m/%d %H:%M") : "") << "" << (size >= 0 ? size.to_s : "-") << "
    " res.body << "
    " res.body << <<-_end_of_html_
    #{HTMLUtils::escape(@config[:ServerSoftware])}
    at #{req.host}:#{req.port}
    _end_of_html_ end # :startdoc: end end end PK!<7J%2.2.0/webrick/httpservlet/abstract.rbnu[# # httpservlet.rb -- HTTPServlet Module # # Author: IPR -- Internet Programming with Ruby -- writers # Copyright (c) 2000 TAKAHASHI Masayoshi, GOTOU Yuuzou # Copyright (c) 2002 Internet Programming with Ruby writers. All rights # reserved. # # $IPR: abstract.rb,v 1.24 2003/07/11 11:16:46 gotoyuzo Exp $ require 'thread' require 'webrick/htmlutils' require 'webrick/httputils' require 'webrick/httpstatus' module WEBrick module HTTPServlet class HTTPServletError < StandardError; end ## # AbstractServlet allows HTTP server modules to be reused across multiple # servers and allows encapsulation of functionality. # # By default a servlet will respond to GET, HEAD (through an alias to GET) # and OPTIONS requests. # # By default a new servlet is initialized for every request. A servlet # instance can be reused by overriding ::get_instance in the # AbstractServlet subclass. # # == A Simple Servlet # # class Simple < WEBrick::HTTPServlet::AbstractServlet # def do_GET request, response # status, content_type, body = do_stuff_with request # # response.status = status # response['Content-Type'] = content_type # response.body = body # end # # def do_stuff_with request # return 200, 'text/plain', 'you got a page' # end # end # # This servlet can be mounted on a server at a given path: # # server.mount '/simple', Simple # # == Servlet Configuration # # Servlets can be configured via initialize. The first argument is the # HTTP server the servlet is being initialized for. # # class Configurable < Simple # def initialize server, color, size # super server # @color = color # @size = size # end # # def do_stuff_with request # content = "

    Hello, World!" # # return 200, "text/html", content # end # end # # This servlet must be provided two arguments at mount time: # # server.mount '/configurable', Configurable, 'red', '2em' class AbstractServlet ## # Factory for servlet instances that will handle a request from +server+ # using +options+ from the mount point. By default a new servlet # instance is created for every call. def self.get_instance(server, *options) self.new(server, *options) end ## # Initializes a new servlet for +server+ using +options+ which are # stored as-is in +@options+. +@logger+ is also provided. def initialize(server, *options) @server = @config = server @logger = @server[:Logger] @options = options end ## # Dispatches to a +do_+ method based on +req+ if such a method is # available. (+do_GET+ for a GET request). Raises a MethodNotAllowed # exception if the method is not implemented. def service(req, res) method_name = "do_" + req.request_method.gsub(/-/, "_") if respond_to?(method_name) __send__(method_name, req, res) else raise HTTPStatus::MethodNotAllowed, "unsupported method `#{req.request_method}'." end end ## # Raises a NotFound exception def do_GET(req, res) raise HTTPStatus::NotFound, "not found." end ## # Dispatches to do_GET def do_HEAD(req, res) do_GET(req, res) end ## # Returns the allowed HTTP request methods def do_OPTIONS(req, res) m = self.methods.grep(/\Ado_([A-Z]+)\z/) {$1} m.sort! res["allow"] = m.join(",") end private ## # Redirects to a path ending in / def redirect_to_directory_uri(req, res) if req.path[-1] != ?/ location = WEBrick::HTTPUtils.escape_path(req.path + "/") if req.query_string && req.query_string.bytesize > 0 location << "?" << req.query_string end res.set_redirect(HTTPStatus::MovedPermanently, location) end end end end end PK!';P'2.2.0/webrick/httpservlet/cgi_runner.rbnu[# # cgi_runner.rb -- CGI launcher. # # Author: IPR -- Internet Programming with Ruby -- writers # Copyright (c) 2000 TAKAHASHI Masayoshi, GOTOU YUUZOU # Copyright (c) 2002 Internet Programming with Ruby writers. All rights # reserved. # # $IPR: cgi_runner.rb,v 1.9 2002/09/25 11:33:15 gotoyuzo Exp $ def sysread(io, size) buf = "" while size > 0 tmp = io.sysread(size) buf << tmp size -= tmp.bytesize end return buf end STDIN.binmode len = sysread(STDIN, 8).to_i out = sysread(STDIN, len) STDOUT.reopen(open(out, "w")) len = sysread(STDIN, 8).to_i err = sysread(STDIN, len) STDERR.reopen(open(err, "w")) len = sysread(STDIN, 8).to_i dump = sysread(STDIN, len) hash = Marshal.restore(dump) ENV.keys.each{|name| ENV.delete(name) } hash.each{|k, v| ENV[k] = v if v } dir = File::dirname(ENV["SCRIPT_FILENAME"]) Dir::chdir dir if ARGV[0] argv = ARGV.dup argv << ENV["SCRIPT_FILENAME"] exec(*argv) # NOTREACHED end exec ENV["SCRIPT_FILENAME"] PK!8'  (2.2.0/webrick/httpservlet/prochandler.rbnu[# # prochandler.rb -- ProcHandler Class # # Author: IPR -- Internet Programming with Ruby -- writers # Copyright (c) 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou # Copyright (c) 2002 Internet Programming with Ruby writers. All rights # reserved. # # $IPR: prochandler.rb,v 1.7 2002/09/21 12:23:42 gotoyuzo Exp $ require 'webrick/httpservlet/abstract.rb' module WEBrick module HTTPServlet ## # Mounts a proc at a path that accepts a request and response. # # Instead of mounting this servlet with WEBrick::HTTPServer#mount use # WEBrick::HTTPServer#mount_proc: # # server.mount_proc '/' do |req, res| # res.body = 'it worked!' # res.status = 200 # end class ProcHandler < AbstractServlet # :stopdoc: def get_instance(server, *options) self end def initialize(proc) @proc = proc end def do_GET(request, response) @proc.call(request, response) end alias do_POST do_GET # :startdoc: end end end PK!!v%%2.2.0/webrick/server.rbnu[# # server.rb -- GenericServer Class # # Author: IPR -- Internet Programming with Ruby -- writers # Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou # Copyright (c) 2002 Internet Programming with Ruby writers. All rights # reserved. # # $IPR: server.rb,v 1.62 2003/07/22 19:20:43 gotoyuzo Exp $ require 'thread' require 'socket' require 'webrick/config' require 'webrick/log' module WEBrick ## # Server error exception class ServerError < StandardError; end ## # Base server class class SimpleServer ## # A SimpleServer only yields when you start it def SimpleServer.start yield end end ## # A generic module for daemonizing a process class Daemon ## # Performs the standard operations for daemonizing a process. Runs a # block, if given. def Daemon.start exit!(0) if fork Process::setsid exit!(0) if fork Dir::chdir("/") File::umask(0) STDIN.reopen("/dev/null") STDOUT.reopen("/dev/null", "w") STDERR.reopen("/dev/null", "w") yield if block_given? end end ## # Base TCP server class. You must subclass GenericServer and provide a #run # method. class GenericServer ## # The server status. One of :Stop, :Running or :Shutdown attr_reader :status ## # The server configuration attr_reader :config ## # The server logger. This is independent from the HTTP access log. attr_reader :logger ## # Tokens control the number of outstanding clients. The # :MaxClients configuration sets this. attr_reader :tokens ## # Sockets listening for connections. attr_reader :listeners ## # Creates a new generic server from +config+. The default configuration # comes from +default+. def initialize(config={}, default=Config::General) @config = default.dup.update(config) @status = :Stop @config[:Logger] ||= Log::new @logger = @config[:Logger] @tokens = SizedQueue.new(@config[:MaxClients]) @config[:MaxClients].times{ @tokens.push(nil) } webrickv = WEBrick::VERSION rubyv = "#{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]" @logger.info("WEBrick #{webrickv}") @logger.info("ruby #{rubyv}") @listeners = [] @shutdown_pipe = nil unless @config[:DoNotListen] if @config[:Listen] warn(":Listen option is deprecated; use GenericServer#listen") end listen(@config[:BindAddress], @config[:Port]) if @config[:Port] == 0 @config[:Port] = @listeners[0].addr[1] end end end ## # Retrieves +key+ from the configuration def [](key) @config[key] end ## # Adds listeners from +address+ and +port+ to the server. See # WEBrick::Utils::create_listeners for details. def listen(address, port) @listeners += Utils::create_listeners(address, port, @logger) setup_shutdown_pipe end ## # Starts the server and runs the +block+ for each connection. This method # does not return until the server is stopped from a signal handler or # another thread using #stop or #shutdown. # # If the block raises a subclass of StandardError the exception is logged # and ignored. If an IOError or Errno::EBADF exception is raised the # exception is ignored. If an Exception subclass is raised the exception # is logged and re-raised which stops the server. # # To completely shut down a server call #shutdown from ensure: # # server = WEBrick::GenericServer.new # # or WEBrick::HTTPServer.new # # begin # server.start # ensure # server.shutdown # end def start(&block) raise ServerError, "already started." if @status != :Stop server_type = @config[:ServerType] || SimpleServer server_type.start{ @logger.info \ "#{self.class}#start: pid=#{$$} port=#{@config[:Port]}" call_callback(:StartCallback) shutdown_pipe = @shutdown_pipe thgroup = ThreadGroup.new @status = :Running begin while @status == :Running begin if svrs = IO.select([shutdown_pipe[0], *@listeners], nil, nil, 2.0) if svrs[0].include? shutdown_pipe[0] break end svrs[0].each{|svr| @tokens.pop # blocks while no token is there. if sock = accept_client(svr) sock.do_not_reverse_lookup = config[:DoNotReverseLookup] th = start_thread(sock, &block) th[:WEBrickThread] = true thgroup.add(th) else @tokens.push(nil) end } end rescue Errno::EBADF, Errno::ENOTSOCK, IOError => ex # if the listening socket was closed in GenericServer#shutdown, # IO::select raise it. rescue StandardError => ex msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}" @logger.error msg rescue Exception => ex @logger.fatal ex raise end end ensure cleanup_shutdown_pipe(shutdown_pipe) cleanup_listener @status = :Shutdown @logger.info "going to shutdown ..." thgroup.list.each{|th| th.join if th[:WEBrickThread] } call_callback(:StopCallback) @logger.info "#{self.class}#start done." @status = :Stop end } end ## # Stops the server from accepting new connections. def stop if @status == :Running @status = :Shutdown end end ## # Shuts down the server and all listening sockets. New listeners must be # provided to restart the server. def shutdown stop shutdown_pipe = @shutdown_pipe # another thread may modify @shutdown_pipe. if shutdown_pipe if !shutdown_pipe[1].closed? begin shutdown_pipe[1].close rescue IOError # closed by another thread. end end end end ## # You must subclass GenericServer and implement \#run which accepts a TCP # client socket def run(sock) @logger.fatal "run() must be provided by user." end private # :stopdoc: ## # Accepts a TCP client socket from the TCP server socket +svr+ and returns # the client socket. def accept_client(svr) sock = nil begin sock = svr.accept sock.sync = true Utils::set_non_blocking(sock) Utils::set_close_on_exec(sock) rescue Errno::ECONNRESET, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINVAL rescue StandardError => ex msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}" @logger.error msg end return sock end ## # Starts a server thread for the client socket +sock+ that runs the given # +block+. # # Sets the socket to the :WEBrickSocket thread local variable # in the thread. # # If any errors occur in the block they are logged and handled. def start_thread(sock, &block) Thread.start{ begin Thread.current[:WEBrickSocket] = sock begin addr = sock.peeraddr @logger.debug "accept: #{addr[3]}:#{addr[1]}" rescue SocketError @logger.debug "accept:

    " raise end call_callback(:AcceptCallback, sock) block ? block.call(sock) : run(sock) rescue Errno::ENOTCONN @logger.debug "Errno::ENOTCONN raised" rescue ServerError => ex msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}" @logger.error msg rescue Exception => ex @logger.error ex ensure @tokens.push(nil) Thread.current[:WEBrickSocket] = nil if addr @logger.debug "close: #{addr[3]}:#{addr[1]}" else @logger.debug "close:
    " end sock.close unless sock.closed? end } end ## # Calls the callback +callback_name+ from the configuration with +args+ def call_callback(callback_name, *args) if cb = @config[callback_name] cb.call(*args) end end def setup_shutdown_pipe if !@shutdown_pipe @shutdown_pipe = IO.pipe end @shutdown_pipe end def cleanup_shutdown_pipe(shutdown_pipe) @shutdown_pipe = nil shutdown_pipe.each {|io| if !io.closed? begin io.close rescue IOError # another thread closed io. end end } end def cleanup_listener @listeners.each{|s| if @logger.debug? addr = s.addr @logger.debug("close TCPSocket(#{addr[2]}, #{addr[1]})") end begin s.shutdown rescue Errno::ENOTCONN # when `Errno::ENOTCONN: Socket is not connected' on some platforms, # call #close instead of #shutdown. # (ignore @config[:ShutdownSocketWithoutClose]) s.close else unless @config[:ShutdownSocketWithoutClose] s.close end end } @listeners.clear end end # end of GenericServer end PK!̏2.2.0/webrick/httpserver.rbnu[# # httpserver.rb -- HTTPServer Class # # Author: IPR -- Internet Programming with Ruby -- writers # Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou # Copyright (c) 2002 Internet Programming with Ruby writers. All rights # reserved. # # $IPR: httpserver.rb,v 1.63 2002/10/01 17:16:32 gotoyuzo Exp $ require 'webrick/server' require 'webrick/httputils' require 'webrick/httpstatus' require 'webrick/httprequest' require 'webrick/httpresponse' require 'webrick/httpservlet' require 'webrick/accesslog' module WEBrick class HTTPServerError < ServerError; end ## # An HTTP Server class HTTPServer < ::WEBrick::GenericServer ## # Creates a new HTTP server according to +config+ # # An HTTP server uses the following attributes: # # :AccessLog:: An array of access logs. See WEBrick::AccessLog # :BindAddress:: Local address for the server to bind to # :DocumentRoot:: Root path to serve files from # :DocumentRootOptions:: Options for the default HTTPServlet::FileHandler # :HTTPVersion:: The HTTP version of this server # :Port:: Port to listen on # :RequestCallback:: Called with a request and response before each # request is serviced. # :RequestTimeout:: Maximum time to wait between requests # :ServerAlias:: Array of alternate names for this server for virtual # hosting # :ServerName:: Name for this server for virtual hosting def initialize(config={}, default=Config::HTTP) super(config, default) @http_version = HTTPVersion::convert(@config[:HTTPVersion]) @mount_tab = MountTable.new if @config[:DocumentRoot] mount("/", HTTPServlet::FileHandler, @config[:DocumentRoot], @config[:DocumentRootOptions]) end unless @config[:AccessLog] @config[:AccessLog] = [ [ $stderr, AccessLog::COMMON_LOG_FORMAT ], [ $stderr, AccessLog::REFERER_LOG_FORMAT ] ] end @virtual_hosts = Array.new end ## # Processes requests on +sock+ def run(sock) while true res = HTTPResponse.new(@config) req = HTTPRequest.new(@config) server = self begin timeout = @config[:RequestTimeout] while timeout > 0 break if IO.select([sock], nil, nil, 0.5) break if @status != :Running timeout -= 0.5 end raise HTTPStatus::EOFError if timeout <= 0 || @status != :Running raise HTTPStatus::EOFError if sock.eof? req.parse(sock) res.request_method = req.request_method res.request_uri = req.request_uri res.request_http_version = req.http_version res.keep_alive = req.keep_alive? server = lookup_server(req) || self if callback = server[:RequestCallback] callback.call(req, res) elsif callback = server[:RequestHandler] msg = ":RequestHandler is deprecated, please use :RequestCallback" @logger.warn(msg) callback.call(req, res) end server.service(req, res) rescue HTTPStatus::EOFError, HTTPStatus::RequestTimeout => ex res.set_error(ex) rescue HTTPStatus::Error => ex @logger.error(ex.message) res.set_error(ex) rescue HTTPStatus::Status => ex res.status = ex.code rescue StandardError => ex @logger.error(ex) res.set_error(ex, true) ensure if req.request_line if req.keep_alive? && res.keep_alive? req.fixup() end res.send_response(sock) server.access_log(@config, req, res) end end break if @http_version < "1.1" break unless req.keep_alive? break unless res.keep_alive? end end ## # Services +req+ and fills in +res+ def service(req, res) if req.unparsed_uri == "*" if req.request_method == "OPTIONS" do_OPTIONS(req, res) raise HTTPStatus::OK end raise HTTPStatus::NotFound, "`#{req.unparsed_uri}' not found." end servlet, options, script_name, path_info = search_servlet(req.path) raise HTTPStatus::NotFound, "`#{req.path}' not found." unless servlet req.script_name = script_name req.path_info = path_info si = servlet.get_instance(self, *options) @logger.debug(format("%s is invoked.", si.class.name)) si.service(req, res) end ## # The default OPTIONS request handler says GET, HEAD, POST and OPTIONS # requests are allowed. def do_OPTIONS(req, res) res["allow"] = "GET,HEAD,POST,OPTIONS" end ## # Mounts +servlet+ on +dir+ passing +options+ to the servlet at creation # time def mount(dir, servlet, *options) @logger.debug(sprintf("%s is mounted on %s.", servlet.inspect, dir)) @mount_tab[dir] = [ servlet, options ] end ## # Mounts +proc+ or +block+ on +dir+ and calls it with a # WEBrick::HTTPRequest and WEBrick::HTTPResponse def mount_proc(dir, proc=nil, &block) proc ||= block raise HTTPServerError, "must pass a proc or block" unless proc mount(dir, HTTPServlet::ProcHandler.new(proc)) end ## # Unmounts +dir+ def unmount(dir) @logger.debug(sprintf("unmount %s.", dir)) @mount_tab.delete(dir) end alias umount unmount ## # Finds a servlet for +path+ def search_servlet(path) script_name, path_info = @mount_tab.scan(path) servlet, options = @mount_tab[script_name] if servlet [ servlet, options, script_name, path_info ] end end ## # Adds +server+ as a virtual host. def virtual_host(server) @virtual_hosts << server @virtual_hosts = @virtual_hosts.sort_by{|s| num = 0 num -= 4 if s[:BindAddress] num -= 2 if s[:Port] num -= 1 if s[:ServerName] num } end ## # Finds the appropriate virtual host to handle +req+ def lookup_server(req) @virtual_hosts.find{|s| (s[:BindAddress].nil? || req.addr[3] == s[:BindAddress]) && (s[:Port].nil? || req.port == s[:Port]) && ((s[:ServerName].nil? || req.host == s[:ServerName]) || (!s[:ServerAlias].nil? && s[:ServerAlias].find{|h| h === req.host})) } end ## # Logs +req+ and +res+ in the access logs. +config+ is used for the # server name. def access_log(config, req, res) param = AccessLog::setup_params(config, req, res) @config[:AccessLog].each{|logger, fmt| logger << AccessLog::format(fmt+"\n", param) } end ## # Mount table for the path a servlet is mounted on in the directory space # of the server. Users of WEBrick can only access this indirectly via # WEBrick::HTTPServer#mount, WEBrick::HTTPServer#unmount and # WEBrick::HTTPServer#search_servlet class MountTable # :nodoc: def initialize @tab = Hash.new compile end def [](dir) dir = normalize(dir) @tab[dir] end def []=(dir, val) dir = normalize(dir) @tab[dir] = val compile val end def delete(dir) dir = normalize(dir) res = @tab.delete(dir) compile res end def scan(path) @scanner =~ path [ $&, $' ] end private def compile k = @tab.keys k.sort! k.reverse! k.collect!{|path| Regexp.escape(path) } @scanner = Regexp.new("^(" + k.join("|") +")(?=/|$)") end def normalize(dir) ret = dir ? dir.dup : "" ret.sub!(%r|/+$|, "") ret end end end end PK! _2.2.0/webrick/cgi.rbnu[# # cgi.rb -- Yet another CGI library # # Author: IPR -- Internet Programming with Ruby -- writers # Copyright (c) 2003 Internet Programming with Ruby writers. All rights # reserved. # # $Id: cgi.rb 38945 2013-01-26 01:12:54Z drbrain $ require "webrick/httprequest" require "webrick/httpresponse" require "webrick/config" require "stringio" module WEBrick # A CGI library using WEBrick requests and responses. # # Example: # # class MyCGI < WEBrick::CGI # def do_GET req, res # res.body = 'it worked!' # res.status = 200 # end # end # # MyCGI.new.start class CGI # The CGI error exception class CGIError = Class.new(StandardError) ## # The CGI configuration. This is based on WEBrick::Config::HTTP attr_reader :config ## # The CGI logger attr_reader :logger ## # Creates a new CGI interface. # # The first argument in +args+ is a configuration hash which would update # WEBrick::Config::HTTP. # # Any remaining arguments are stored in the @options instance # variable for use by a subclass. def initialize(*args) if defined?(MOD_RUBY) unless ENV.has_key?("GATEWAY_INTERFACE") Apache.request.setup_cgi_env end end if %r{HTTP/(\d+\.\d+)} =~ ENV["SERVER_PROTOCOL"] httpv = $1 end @config = WEBrick::Config::HTTP.dup.update( :ServerSoftware => ENV["SERVER_SOFTWARE"] || "null", :HTTPVersion => HTTPVersion.new(httpv || "1.0"), :RunOnCGI => true, # to detect if it runs on CGI. :NPH => false # set true to run as NPH script. ) if config = args.shift @config.update(config) end @config[:Logger] ||= WEBrick::BasicLog.new($stderr) @logger = @config[:Logger] @options = args end ## # Reads +key+ from the configuration def [](key) @config[key] end ## # Starts the CGI process with the given environment +env+ and standard # input and output +stdin+ and +stdout+. def start(env=ENV, stdin=$stdin, stdout=$stdout) sock = WEBrick::CGI::Socket.new(@config, env, stdin, stdout) req = HTTPRequest.new(@config) res = HTTPResponse.new(@config) unless @config[:NPH] or defined?(MOD_RUBY) def res.setup_header unless @header["status"] phrase = HTTPStatus::reason_phrase(@status) @header["status"] = "#{@status} #{phrase}" end super end def res.status_line "" end end begin req.parse(sock) req.script_name = (env["SCRIPT_NAME"] || File.expand_path($0)).dup req.path_info = (env["PATH_INFO"] || "").dup req.query_string = env["QUERY_STRING"] req.user = env["REMOTE_USER"] res.request_method = req.request_method res.request_uri = req.request_uri res.request_http_version = req.http_version res.keep_alive = req.keep_alive? self.service(req, res) rescue HTTPStatus::Error => ex res.set_error(ex) rescue HTTPStatus::Status => ex res.status = ex.code rescue Exception => ex @logger.error(ex) res.set_error(ex, true) ensure req.fixup if defined?(MOD_RUBY) res.setup_header Apache.request.status_line = "#{res.status} #{res.reason_phrase}" Apache.request.status = res.status table = Apache.request.headers_out res.header.each{|key, val| case key when /^content-encoding$/i Apache::request.content_encoding = val when /^content-type$/i Apache::request.content_type = val else table[key] = val.to_s end } res.cookies.each{|cookie| table.add("Set-Cookie", cookie.to_s) } Apache.request.send_http_header res.send_body(sock) else res.send_response(sock) end end end ## # Services the request +req+ which will fill in the response +res+. See # WEBrick::HTTPServlet::AbstractServlet#service for details. def service(req, res) method_name = "do_" + req.request_method.gsub(/-/, "_") if respond_to?(method_name) __send__(method_name, req, res) else raise HTTPStatus::MethodNotAllowed, "unsupported method `#{req.request_method}'." end end ## # Provides HTTP socket emulation from the CGI environment class Socket # :nodoc: include Enumerable private def initialize(config, env, stdin, stdout) @config = config @env = env @header_part = StringIO.new @body_part = stdin @out_port = stdout @out_port.binmode @server_addr = @env["SERVER_ADDR"] || "0.0.0.0" @server_name = @env["SERVER_NAME"] @server_port = @env["SERVER_PORT"] @remote_addr = @env["REMOTE_ADDR"] @remote_host = @env["REMOTE_HOST"] || @remote_addr @remote_port = @env["REMOTE_PORT"] || 0 begin @header_part << request_line << CRLF setup_header @header_part << CRLF @header_part.rewind rescue Exception raise CGIError, "invalid CGI environment" end end def request_line meth = @env["REQUEST_METHOD"] || "GET" unless url = @env["REQUEST_URI"] url = (@env["SCRIPT_NAME"] || File.expand_path($0)).dup url << @env["PATH_INFO"].to_s url = WEBrick::HTTPUtils.escape_path(url) if query_string = @env["QUERY_STRING"] unless query_string.empty? url << "?" << query_string end end end # we cannot get real HTTP version of client ;) httpv = @config[:HTTPVersion] return "#{meth} #{url} HTTP/#{httpv}" end def setup_header @env.each{|key, value| case key when "CONTENT_TYPE", "CONTENT_LENGTH" add_header(key.gsub(/_/, "-"), value) when /^HTTP_(.*)/ add_header($1.gsub(/_/, "-"), value) end } end def add_header(hdrname, value) unless value.empty? @header_part << hdrname << ": " << value << CRLF end end def input @header_part.eof? ? @body_part : @header_part end public def peeraddr [nil, @remote_port, @remote_host, @remote_addr] end def addr [nil, @server_port, @server_name, @server_addr] end def gets(eol=LF, size=nil) input.gets(eol, size) end def read(size=nil) input.read(size) end def each input.each{|line| yield(line) } end def eof? input.eof? end def <<(data) @out_port << data end def cert return nil unless defined?(OpenSSL) if pem = @env["SSL_SERVER_CERT"] OpenSSL::X509::Certificate.new(pem) unless pem.empty? end end def peer_cert return nil unless defined?(OpenSSL) if pem = @env["SSL_CLIENT_CERT"] OpenSSL::X509::Certificate.new(pem) unless pem.empty? end end def peer_cert_chain return nil unless defined?(OpenSSL) if @env["SSL_CLIENT_CERT_CHAIN_0"] keys = @env.keys certs = keys.sort.collect{|k| if /^SSL_CLIENT_CERT_CHAIN_\d+$/ =~ k if pem = @env[k] OpenSSL::X509::Certificate.new(pem) unless pem.empty? end end } certs.compact end end def cipher return nil unless defined?(OpenSSL) if cipher = @env["SSL_CIPHER"] ret = [ cipher ] ret << @env["SSL_PROTOCOL"] ret << @env["SSL_CIPHER_USEKEYSIZE"] ret << @env["SSL_CIPHER_ALGKEYSIZE"] ret end end end end end PK!oصN;;2.2.0/webrick/accesslog.rbnu[#-- # accesslog.rb -- Access log handling utilities # # Author: IPR -- Internet Programming with Ruby -- writers # Copyright (c) 2002 keita yamaguchi # Copyright (c) 2002 Internet Programming with Ruby writers # # $IPR: accesslog.rb,v 1.1 2002/10/01 17:16:32 gotoyuzo Exp $ module WEBrick ## # AccessLog provides logging to various files in various formats. # # Multiple logs may be written to at the same time: # # access_log = [ # [$stderr, WEBrick::AccessLog::COMMON_LOG_FORMAT], # [$stderr, WEBrick::AccessLog::REFERER_LOG_FORMAT], # ] # # server = WEBrick::HTTPServer.new :AccessLog => access_log # # Custom log formats may be defined. WEBrick::AccessLog provides a subset # of the formatting from Apache's mod_log_config # http://httpd.apache.org/docs/mod/mod_log_config.html#formats. See # AccessLog::setup_params for a list of supported options module AccessLog ## # Raised if a parameter such as %e, %i, %o or %n is used without fetching # a specific field. class AccessLogError < StandardError; end ## # The Common Log Format's time format CLF_TIME_FORMAT = "[%d/%b/%Y:%H:%M:%S %Z]" ## # Common Log Format COMMON_LOG_FORMAT = "%h %l %u %t \"%r\" %s %b" ## # Short alias for Common Log Format CLF = COMMON_LOG_FORMAT ## # Referer Log Format REFERER_LOG_FORMAT = "%{Referer}i -> %U" ## # User-Agent Log Format AGENT_LOG_FORMAT = "%{User-Agent}i" ## # Combined Log Format COMBINED_LOG_FORMAT = "#{CLF} \"%{Referer}i\" \"%{User-agent}i\"" module_function # This format specification is a subset of mod_log_config of Apache: # # %a:: Remote IP address # %b:: Total response size # %e{variable}:: Given variable in ENV # %f:: Response filename # %h:: Remote host name # %{header}i:: Given request header # %l:: Remote logname, always "-" # %m:: Request method # %{attr}n:: Given request attribute from req.attributes # %{header}o:: Given response header # %p:: Server's request port # %{format}p:: The canonical port of the server serving the request or the # actual port or the client's actual port. Valid formats are # canonical, local or remote. # %q:: Request query string # %r:: First line of the request # %s:: Request status # %t:: Time the request was received # %T:: Time taken to process the request # %u:: Remote user from auth # %U:: Unparsed URI # %%:: Literal % def setup_params(config, req, res) params = Hash.new("") params["a"] = req.peeraddr[3] params["b"] = res.sent_size params["e"] = ENV params["f"] = res.filename || "" params["h"] = req.peeraddr[2] params["i"] = req params["l"] = "-" params["m"] = req.request_method params["n"] = req.attributes params["o"] = res params["p"] = req.port params["q"] = req.query_string params["r"] = req.request_line.sub(/\x0d?\x0a\z/o, '') params["s"] = res.status # won't support "%>s" params["t"] = req.request_time params["T"] = Time.now - req.request_time params["u"] = req.user || "-" params["U"] = req.unparsed_uri params["v"] = config[:ServerName] params end ## # Formats +params+ according to +format_string+ which is described in # setup_params. def format(format_string, params) format_string.gsub(/\%(?:\{(.*?)\})?>?([a-zA-Z%])/){ param, spec = $1, $2 case spec[0] when ?e, ?i, ?n, ?o raise AccessLogError, "parameter is required for \"#{spec}\"" unless param (param = params[spec][param]) ? escape(param) : "-" when ?t params[spec].strftime(param || CLF_TIME_FORMAT) when ?p case param when 'remote' escape(params["i"].peeraddr[1].to_s) else escape(params["p"].to_s) end when ?% "%" else escape(params[spec].to_s) end } end ## # Escapes control characters in +data+ def escape(data) if data.tainted? data.gsub(/[[:cntrl:]\\]+/) {$&.dump[1...-1]}.untaint else data end end end end PK!NR/R/2.2.0/webrick/httpresponse.rbnu[# # httpresponse.rb -- HTTPResponse Class # # Author: IPR -- Internet Programming with Ruby -- writers # Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou # Copyright (c) 2002 Internet Programming with Ruby writers. All rights # reserved. # # $IPR: httpresponse.rb,v 1.45 2003/07/11 11:02:25 gotoyuzo Exp $ require 'time' require 'webrick/httpversion' require 'webrick/htmlutils' require 'webrick/httputils' require 'webrick/httpstatus' module WEBrick ## # An HTTP response. This is filled in by the service or do_* methods of a # WEBrick HTTP Servlet. class HTTPResponse class InvalidHeader < StandardError end ## # HTTP Response version attr_reader :http_version ## # Response status code (200) attr_reader :status ## # Response header attr_reader :header ## # Response cookies attr_reader :cookies ## # Response reason phrase ("OK") attr_accessor :reason_phrase ## # Body may be a String or IO-like object that responds to #read and # #readpartial. attr_accessor :body ## # Request method for this response attr_accessor :request_method ## # Request URI for this response attr_accessor :request_uri ## # Request HTTP version for this response attr_accessor :request_http_version ## # Filename of the static file in this response. Only used by the # FileHandler servlet. attr_accessor :filename ## # Is this a keep-alive response? attr_accessor :keep_alive ## # Configuration for this response attr_reader :config ## # Bytes sent in this response attr_reader :sent_size ## # Creates a new HTTP response object. WEBrick::Config::HTTP is the # default configuration. def initialize(config) @config = config @buffer_size = config[:OutputBufferSize] @logger = config[:Logger] @header = Hash.new @status = HTTPStatus::RC_OK @reason_phrase = nil @http_version = HTTPVersion::convert(@config[:HTTPVersion]) @body = '' @keep_alive = true @cookies = [] @request_method = nil @request_uri = nil @request_http_version = @http_version # temporary @chunked = false @filename = nil @sent_size = 0 end ## # The response's HTTP status line def status_line "HTTP/#@http_version #@status #@reason_phrase #{CRLF}" end ## # Sets the response's status to the +status+ code def status=(status) @status = status @reason_phrase = HTTPStatus::reason_phrase(status) end ## # Retrieves the response header +field+ def [](field) @header[field.downcase] end ## # Sets the response header +field+ to +value+ def []=(field, value) @header[field.downcase] = value.to_s end ## # The content-length header def content_length if len = self['content-length'] return Integer(len) end end ## # Sets the content-length header to +len+ def content_length=(len) self['content-length'] = len.to_s end ## # The content-type header def content_type self['content-type'] end ## # Sets the content-type header to +type+ def content_type=(type) self['content-type'] = type end ## # Iterates over each header in the response def each @header.each{|field, value| yield(field, value) } end ## # Will this response body be returned using chunked transfer-encoding? def chunked? @chunked end ## # Enables chunked transfer encoding. def chunked=(val) @chunked = val ? true : false end ## # Will this response's connection be kept alive? def keep_alive? @keep_alive end ## # Sends the response on +socket+ def send_response(socket) # :nodoc: begin setup_header() send_header(socket) send_body(socket) rescue Errno::EPIPE, Errno::ECONNRESET, Errno::ENOTCONN => ex @logger.debug(ex) @keep_alive = false rescue Exception => ex @logger.error(ex) @keep_alive = false end end ## # Sets up the headers for sending def setup_header() # :nodoc: @reason_phrase ||= HTTPStatus::reason_phrase(@status) @header['server'] ||= @config[:ServerSoftware] @header['date'] ||= Time.now.httpdate # HTTP/0.9 features if @request_http_version < "1.0" @http_version = HTTPVersion.new("0.9") @keep_alive = false end # HTTP/1.0 features if @request_http_version < "1.1" if chunked? @chunked = false ver = @request_http_version.to_s msg = "chunked is set for an HTTP/#{ver} request. (ignored)" @logger.warn(msg) end end # Determine the message length (RFC2616 -- 4.4 Message Length) if @status == 304 || @status == 204 || HTTPStatus::info?(@status) @header.delete('content-length') @body = "" elsif chunked? @header["transfer-encoding"] = "chunked" @header.delete('content-length') elsif %r{^multipart/byteranges} =~ @header['content-type'] @header.delete('content-length') elsif @header['content-length'].nil? unless @body.is_a?(IO) @header['content-length'] = @body ? @body.bytesize : 0 end end # Keep-Alive connection. if @header['connection'] == "close" @keep_alive = false elsif keep_alive? if chunked? || @header['content-length'] || @status == 304 || @status == 204 || HTTPStatus.info?(@status) @header['connection'] = "Keep-Alive" else msg = "Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true" @logger.warn(msg) @header['connection'] = "close" @keep_alive = false end else @header['connection'] = "close" end # Location is a single absoluteURI. if location = @header['location'] if @request_uri @header['location'] = @request_uri.merge(location) end end end ## # Sends the headers on +socket+ def send_header(socket) # :nodoc: if @http_version.major > 0 data = status_line() @header.each{|key, value| tmp = key.gsub(/\bwww|^te$|\b\w/){ $&.upcase } data << "#{tmp}: #{check_header(value)}" << CRLF } @cookies.each{|cookie| data << "Set-Cookie: " << check_header(cookie.to_s) << CRLF } data << CRLF _write_data(socket, data) end rescue InvalidHeader => e @header.clear @cookies.clear set_error e retry end ## # Sends the body on +socket+ def send_body(socket) # :nodoc: if @body.respond_to? :readpartial then send_body_io(socket) elsif @body.respond_to?(:call) then send_body_proc(socket) else send_body_string(socket) end end def to_s # :nodoc: ret = "" send_response(ret) ret end ## # Redirects to +url+ with a WEBrick::HTTPStatus::Redirect +status+. # # Example: # # res.set_redirect WEBrick::HTTPStatus::TemporaryRedirect def set_redirect(status, url) @body = "#{url}.\n" @header['location'] = url.to_s raise status end ## # Creates an error page for exception +ex+ with an optional +backtrace+ def set_error(ex, backtrace=false) case ex when HTTPStatus::Status @keep_alive = false if HTTPStatus::error?(ex.code) self.status = ex.code else @keep_alive = false self.status = HTTPStatus::RC_INTERNAL_SERVER_ERROR end @header['content-type'] = "text/html; charset=ISO-8859-1" if respond_to?(:create_error_page) create_error_page() return end if @request_uri host, port = @request_uri.host, @request_uri.port else host, port = @config[:ServerName], @config[:Port] end error_body(backtrace, ex, host, port) end private def check_header(header_value) if header_value =~ /\r\n/ raise InvalidHeader else header_value end end # :stopdoc: def error_body(backtrace, ex, host, port) @body = '' @body << <<-_end_of_html_ #{HTMLUtils::escape(@reason_phrase)}

    #{HTMLUtils::escape(@reason_phrase)}

    #{HTMLUtils::escape(ex.message)}
    _end_of_html_ if backtrace && $DEBUG @body << "backtrace of `#{HTMLUtils::escape(ex.class.to_s)}' " @body << "#{HTMLUtils::escape(ex.message)}" @body << "
    "
            ex.backtrace.each{|line| @body << "\t#{line}\n"}
            @body << "

    " end @body << <<-_end_of_html_
    #{HTMLUtils::escape(@config[:ServerSoftware])} at #{host}:#{port}
    _end_of_html_ end private # :stopdoc: def send_body_io(socket) begin if @request_method == "HEAD" # do nothing elsif chunked? begin buf = '' data = '' while true @body.readpartial( @buffer_size, buf ) # there is no need to clear buf? data << format("%x", buf.bytesize) << CRLF data << buf << CRLF _write_data(socket, data) data.clear @sent_size += buf.bytesize end rescue EOFError # do nothing end _write_data(socket, "0#{CRLF}#{CRLF}") else if %r{\Abytes (\d+)-(\d+)/\d+\z} =~ @header['content-range'] offset = $1.to_i size = $2.to_i - offset + 1 else offset = nil size = @header['content-length'] size = size.to_i if size end begin @sent_size = IO.copy_stream(@body, socket, size, offset) rescue NotImplementedError @body.seek(offset, IO::SEEK_SET) @sent_size = IO.copy_stream(@body, socket, size) end end ensure @body.close end end def send_body_string(socket) if @request_method == "HEAD" # do nothing elsif chunked? body ? @body.bytesize : 0 while buf = @body[@sent_size, @buffer_size] break if buf.empty? data = "" data << format("%x", buf.bytesize) << CRLF data << buf << CRLF _write_data(socket, data) @sent_size += buf.bytesize end _write_data(socket, "0#{CRLF}#{CRLF}") else if @body && @body.bytesize > 0 _write_data(socket, @body) @sent_size = @body.bytesize end end end def send_body_proc(socket) if @request_method == "HEAD" # do nothing elsif chunked? @body.call(ChunkedWrapper.new(socket, self)) _write_data(socket, "0#{CRLF}#{CRLF}") else size = @header['content-length'].to_i @body.call(socket) @sent_size = size end end class ChunkedWrapper def initialize(socket, resp) @socket = socket @resp = resp end def write(buf) return 0 if buf.empty? socket = @socket @resp.instance_eval { size = buf.bytesize data = "#{size.to_s(16)}#{CRLF}#{buf}#{CRLF}" _write_data(socket, data) data.clear @sent_size += size size } end def <<(*buf) write(buf) self end end def _write_data(socket, data) socket << data end # :startdoc: end end PK!TVTKK2.2.0/webrick/httpversion.rbnu[#-- # HTTPVersion.rb -- presentation of HTTP version # # Author: IPR -- Internet Programming with Ruby -- writers # Copyright (c) 2002 Internet Programming with Ruby writers. All rights # reserved. # # $IPR: httpversion.rb,v 1.5 2002/09/21 12:23:37 gotoyuzo Exp $ module WEBrick ## # Represents an HTTP protocol version class HTTPVersion include Comparable ## # The major protocol version number attr_accessor :major ## # The minor protocol version number attr_accessor :minor ## # Converts +version+ into an HTTPVersion def self.convert(version) version.is_a?(self) ? version : new(version) end ## # Creates a new HTTPVersion from +version+. def initialize(version) case version when HTTPVersion @major, @minor = version.major, version.minor when String if /^(\d+)\.(\d+)$/ =~ version @major, @minor = $1.to_i, $2.to_i end end if @major.nil? || @minor.nil? raise ArgumentError, format("cannot convert %s into %s", version.class, self.class) end end ## # Compares this version with +other+ according to the HTTP specification # rules. def <=>(other) unless other.is_a?(self.class) other = self.class.new(other) end if (ret = @major <=> other.major) == 0 return @minor <=> other.minor end return ret end ## # The HTTP version as show in the HTTP request and response. For example, # "1.1" def to_s format("%d.%d", @major, @minor) end end end PK!d 222.2.0/webrick/httputils.rbnu[# # httputils.rb -- HTTPUtils Module # # Author: IPR -- Internet Programming with Ruby -- writers # Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou # Copyright (c) 2002 Internet Programming with Ruby writers. All rights # reserved. # # $IPR: httputils.rb,v 1.34 2003/06/05 21:34:08 gotoyuzo Exp $ require 'socket' require 'tempfile' module WEBrick CR = "\x0d" # :nodoc: LF = "\x0a" # :nodoc: CRLF = "\x0d\x0a" # :nodoc: ## # HTTPUtils provides utility methods for working with the HTTP protocol. # # This module is generally used internally by WEBrick module HTTPUtils ## # Normalizes a request path. Raises an exception if the path cannot be # normalized. def normalize_path(path) raise "abnormal path `#{path}'" if path[0] != ?/ ret = path.dup ret.gsub!(%r{/+}o, '/') # // => / while ret.sub!(%r'/\.(?:/|\Z)', '/'); end # /. => / while ret.sub!(%r'/(?!\.\./)[^/]+/\.\.(?:/|\Z)', '/'); end # /foo/.. => /foo raise "abnormal path `#{path}'" if %r{/\.\.(/|\Z)} =~ ret ret end module_function :normalize_path ## # Default mime types DefaultMimeTypes = { "ai" => "application/postscript", "asc" => "text/plain", "avi" => "video/x-msvideo", "bin" => "application/octet-stream", "bmp" => "image/bmp", "class" => "application/octet-stream", "cer" => "application/pkix-cert", "crl" => "application/pkix-crl", "crt" => "application/x-x509-ca-cert", #"crl" => "application/x-pkcs7-crl", "css" => "text/css", "dms" => "application/octet-stream", "doc" => "application/msword", "dvi" => "application/x-dvi", "eps" => "application/postscript", "etx" => "text/x-setext", "exe" => "application/octet-stream", "gif" => "image/gif", "htm" => "text/html", "html" => "text/html", "jpe" => "image/jpeg", "jpeg" => "image/jpeg", "jpg" => "image/jpeg", "js" => "application/javascript", "lha" => "application/octet-stream", "lzh" => "application/octet-stream", "mov" => "video/quicktime", "mpe" => "video/mpeg", "mpeg" => "video/mpeg", "mpg" => "video/mpeg", "pbm" => "image/x-portable-bitmap", "pdf" => "application/pdf", "pgm" => "image/x-portable-graymap", "png" => "image/png", "pnm" => "image/x-portable-anymap", "ppm" => "image/x-portable-pixmap", "ppt" => "application/vnd.ms-powerpoint", "ps" => "application/postscript", "qt" => "video/quicktime", "ras" => "image/x-cmu-raster", "rb" => "text/plain", "rd" => "text/plain", "rtf" => "application/rtf", "sgm" => "text/sgml", "sgml" => "text/sgml", "svg" => "image/svg+xml", "tif" => "image/tiff", "tiff" => "image/tiff", "txt" => "text/plain", "xbm" => "image/x-xbitmap", "xhtml" => "text/html", "xls" => "application/vnd.ms-excel", "xml" => "text/xml", "xpm" => "image/x-xpixmap", "xwd" => "image/x-xwindowdump", "zip" => "application/zip", } ## # Loads Apache-compatible mime.types in +file+. def load_mime_types(file) open(file){ |io| hash = Hash.new io.each{ |line| next if /^#/ =~ line line.chomp! mimetype, ext0 = line.split(/\s+/, 2) next unless ext0 next if ext0.empty? ext0.split(/\s+/).each{ |ext| hash[ext] = mimetype } } hash } end module_function :load_mime_types ## # Returns the mime type of +filename+ from the list in +mime_tab+. If no # mime type was found application/octet-stream is returned. def mime_type(filename, mime_tab) suffix1 = (/\.(\w+)$/ =~ filename && $1.downcase) suffix2 = (/\.(\w+)\.[\w\-]+$/ =~ filename && $1.downcase) mime_tab[suffix1] || mime_tab[suffix2] || "application/octet-stream" end module_function :mime_type ## # Parses an HTTP header +raw+ into a hash of header fields with an Array # of values. def parse_header(raw) header = Hash.new([].freeze) field = nil raw.each_line{|line| case line when /^([A-Za-z0-9!\#$%&'*+\-.^_`|~]+):\s*(.*?)\s*\z/om field, value = $1, $2 field.downcase! header[field] = [] unless header.has_key?(field) header[field] << value when /^\s+(.*?)\s*\z/om value = $1 unless field raise HTTPStatus::BadRequest, "bad header '#{line}'." end header[field][-1] << " " << value else raise HTTPStatus::BadRequest, "bad header '#{line}'." end } header.each{|key, values| values.each{|value| value.strip! value.gsub!(/\s+/, " ") } } header end module_function :parse_header ## # Splits a header value +str+ according to HTTP specification. def split_header_value(str) str.scan(%r'\G((?:"(?:\\.|[^"])+?"|[^",]+)+) (?:,\s*|\Z)'xn).flatten end module_function :split_header_value ## # Parses a Range header value +ranges_specifier+ def parse_range_header(ranges_specifier) if /^bytes=(.*)/ =~ ranges_specifier byte_range_set = split_header_value($1) byte_range_set.collect{|range_spec| case range_spec when /^(\d+)-(\d+)/ then $1.to_i .. $2.to_i when /^(\d+)-/ then $1.to_i .. -1 when /^-(\d+)/ then -($1.to_i) .. -1 else return nil end } end end module_function :parse_range_header ## # Parses q values in +value+ as used in Accept headers. def parse_qvalues(value) tmp = [] if value parts = value.split(/,\s*/) parts.each {|part| if m = %r{^([^\s,]+?)(?:;\s*q=(\d+(?:\.\d+)?))?$}.match(part) val = m[1] q = (m[2] or 1).to_f tmp.push([val, q]) end } tmp = tmp.sort_by{|val, q| -q} tmp.collect!{|val, q| val} end return tmp end module_function :parse_qvalues ## # Removes quotes and escapes from +str+ def dequote(str) ret = (/\A"(.*)"\Z/ =~ str) ? $1 : str.dup ret.gsub!(/\\(.)/, "\\1") ret end module_function :dequote ## # Quotes and escapes quotes in +str+ def quote(str) '"' << str.gsub(/[\\\"]/o, "\\\1") << '"' end module_function :quote ## # Stores multipart form data. FormData objects are created when # WEBrick::HTTPUtils.parse_form_data is called. class FormData < String EmptyRawHeader = [].freeze # :nodoc: EmptyHeader = {}.freeze # :nodoc: ## # The name of the form data part attr_accessor :name ## # The filename of the form data part attr_accessor :filename attr_accessor :next_data # :nodoc: protected :next_data ## # Creates a new FormData object. # # +args+ is an Array of form data entries. One FormData will be created # for each entry. # # This is called by WEBrick::HTTPUtils.parse_form_data for you def initialize(*args) @name = @filename = @next_data = nil if args.empty? @raw_header = [] @header = nil super("") else @raw_header = EmptyRawHeader @header = EmptyHeader super(args.shift) unless args.empty? @next_data = self.class.new(*args) end end end ## # Retrieves the header at the first entry in +key+ def [](*key) begin @header[key[0].downcase].join(", ") rescue StandardError, NameError super end end ## # Adds +str+ to this FormData which may be the body, a header or a # header entry. # # This is called by WEBrick::HTTPUtils.parse_form_data for you def <<(str) if @header super elsif str == CRLF @header = HTTPUtils::parse_header(@raw_header.join) if cd = self['content-disposition'] if /\s+name="(.*?)"/ =~ cd then @name = $1 end if /\s+filename="(.*?)"/ =~ cd then @filename = $1 end end else @raw_header << str end self end ## # Adds +data+ at the end of the chain of entries # # This is called by WEBrick::HTTPUtils.parse_form_data for you. def append_data(data) tmp = self while tmp unless tmp.next_data tmp.next_data = data break end tmp = tmp.next_data end self end ## # Yields each entry in this FormData def each_data tmp = self while tmp next_data = tmp.next_data yield(tmp) tmp = next_data end end ## # Returns all the FormData as an Array def list ret = [] each_data{|data| ret << data.to_s } ret end ## # A FormData will behave like an Array alias :to_ary :list ## # This FormData's body def to_s String.new(self) end end ## # Parses the query component of a URI in +str+ def parse_query(str) query = Hash.new if str str.split(/[&;]/).each{|x| next if x.empty? key, val = x.split(/=/,2) key = unescape_form(key) val = unescape_form(val.to_s) val = FormData.new(val) val.name = key if query.has_key?(key) query[key].append_data(val) next end query[key] = val } end query end module_function :parse_query ## # Parses form data in +io+ with the given +boundary+ def parse_form_data(io, boundary) boundary_regexp = /\A--#{Regexp.quote(boundary)}(--)?#{CRLF}\z/ form_data = Hash.new return form_data unless io data = nil io.each_line{|line| if boundary_regexp =~ line if data data.chop! key = data.name if form_data.has_key?(key) form_data[key].append_data(data) else form_data[key] = data end end data = FormData.new next else if data data << line end end } return form_data end module_function :parse_form_data ##### reserved = ';/?:@&=+$,' num = '0123456789' lowalpha = 'abcdefghijklmnopqrstuvwxyz' upalpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' mark = '-_.!~*\'()' unreserved = num + lowalpha + upalpha + mark control = (0x0..0x1f).collect{|c| c.chr }.join + "\x7f" space = " " delims = '<>#%"' unwise = '{}|\\^[]`' nonascii = (0x80..0xff).collect{|c| c.chr }.join module_function # :stopdoc: def _make_regex(str) /([#{Regexp.escape(str)}])/n end def _make_regex!(str) /([^#{Regexp.escape(str)}])/n end def _escape(str, regex) str = str.b str.gsub!(regex) {"%%%02X" % $1.ord} # %-escaped string should contain US-ASCII only str.force_encoding(Encoding::US_ASCII) end def _unescape(str, regex) str = str.b str.gsub!(regex) {$1.hex.chr} # encoding of %-unescaped string is unknown str end UNESCAPED = _make_regex(control+space+delims+unwise+nonascii) UNESCAPED_FORM = _make_regex(reserved+control+delims+unwise+nonascii) NONASCII = _make_regex(nonascii) ESCAPED = /%([0-9a-fA-F]{2})/ UNESCAPED_PCHAR = _make_regex!(unreserved+":@&=+$,") # :startdoc: ## # Escapes HTTP reserved and unwise characters in +str+ def escape(str) _escape(str, UNESCAPED) end ## # Unescapes HTTP reserved and unwise characters in +str+ def unescape(str) _unescape(str, ESCAPED) end ## # Escapes form reserved characters in +str+ def escape_form(str) ret = _escape(str, UNESCAPED_FORM) ret.gsub!(/ /, "+") ret end ## # Unescapes form reserved characters in +str+ def unescape_form(str) _unescape(str.gsub(/\+/, " "), ESCAPED) end ## # Escapes path +str+ def escape_path(str) result = "" str.scan(%r{/([^/]*)}).each{|i| result << "/" << _escape(i[0], UNESCAPED_PCHAR) } return result end ## # Escapes 8 bit characters in +str+ def escape8bit(str) _escape(str, NONASCII) end end end PK!sep2.2.0/webrick/compat.rbnu[# # compat.rb -- cross platform compatibility # # Author: IPR -- Internet Programming with Ruby -- writers # Copyright (c) 2002 GOTOU Yuuzou # Copyright (c) 2002 Internet Programming with Ruby writers. All rights # reserved. # # $IPR: compat.rb,v 1.6 2002/10/01 17:16:32 gotoyuzo Exp $ ## # System call error module used by webrick for cross platform compatibility. # # EPROTO:: protocol error # ECONNRESET:: remote host reset the connection request # ECONNABORTED:: Client sent TCP reset (RST) before server has accepted the # connection requested by client. # module Errno ## # Protocol error. class EPROTO < SystemCallError; end ## # Remote host reset the connection request. class ECONNRESET < SystemCallError; end ## # Client sent TCP reset (RST) before server has accepted the connection # requested by client. class ECONNABORTED < SystemCallError; end end PK!8s;;2.2.0/webrick/httprequest.rbnu[# # httprequest.rb -- HTTPRequest Class # # Author: IPR -- Internet Programming with Ruby -- writers # Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou # Copyright (c) 2002 Internet Programming with Ruby writers. All rights # reserved. # # $IPR: httprequest.rb,v 1.64 2003/07/13 17:18:22 gotoyuzo Exp $ require 'uri' require 'webrick/httpversion' require 'webrick/httpstatus' require 'webrick/httputils' require 'webrick/cookie' module WEBrick ## # An HTTP request. This is consumed by service and do_* methods in # WEBrick servlets class HTTPRequest BODY_CONTAINABLE_METHODS = [ "POST", "PUT" ] # :nodoc: # :section: Request line ## # The complete request line such as: # # GET / HTTP/1.1 attr_reader :request_line ## # The request method, GET, POST, PUT, etc. attr_reader :request_method ## # The unparsed URI of the request attr_reader :unparsed_uri ## # The HTTP version of the request attr_reader :http_version # :section: Request-URI ## # The parsed URI of the request attr_reader :request_uri ## # The request path attr_reader :path ## # The script name (CGI variable) attr_accessor :script_name ## # The path info (CGI variable) attr_accessor :path_info ## # The query from the URI of the request attr_accessor :query_string # :section: Header and entity body ## # The raw header of the request attr_reader :raw_header ## # The parsed header of the request attr_reader :header ## # The parsed request cookies attr_reader :cookies ## # The Accept header value attr_reader :accept ## # The Accept-Charset header value attr_reader :accept_charset ## # The Accept-Encoding header value attr_reader :accept_encoding ## # The Accept-Language header value attr_reader :accept_language # :section: ## # The remote user (CGI variable) attr_accessor :user ## # The socket address of the server attr_reader :addr ## # The socket address of the client attr_reader :peeraddr ## # Hash of request attributes attr_reader :attributes ## # Is this a keep-alive connection? attr_reader :keep_alive ## # The local time this request was received attr_reader :request_time ## # Creates a new HTTP request. WEBrick::Config::HTTP is the default # configuration. def initialize(config) @config = config @buffer_size = @config[:InputBufferSize] @logger = config[:Logger] @request_line = @request_method = @unparsed_uri = @http_version = nil @request_uri = @host = @port = @path = nil @script_name = @path_info = nil @query_string = nil @query = nil @form_data = nil @raw_header = Array.new @header = nil @cookies = [] @accept = [] @accept_charset = [] @accept_encoding = [] @accept_language = [] @body = "" @addr = @peeraddr = nil @attributes = {} @user = nil @keep_alive = false @request_time = nil @remaining_size = nil @socket = nil @forwarded_proto = @forwarded_host = @forwarded_port = @forwarded_server = @forwarded_for = nil end ## # Parses a request from +socket+. This is called internally by # WEBrick::HTTPServer. def parse(socket=nil) @socket = socket begin @peeraddr = socket.respond_to?(:peeraddr) ? socket.peeraddr : [] @addr = socket.respond_to?(:addr) ? socket.addr : [] rescue Errno::ENOTCONN raise HTTPStatus::EOFError end read_request_line(socket) if @http_version.major > 0 read_header(socket) @header['cookie'].each{|cookie| @cookies += Cookie::parse(cookie) } @accept = HTTPUtils.parse_qvalues(self['accept']) @accept_charset = HTTPUtils.parse_qvalues(self['accept-charset']) @accept_encoding = HTTPUtils.parse_qvalues(self['accept-encoding']) @accept_language = HTTPUtils.parse_qvalues(self['accept-language']) end return if @request_method == "CONNECT" return if @unparsed_uri == "*" begin setup_forwarded_info @request_uri = parse_uri(@unparsed_uri) @path = HTTPUtils::unescape(@request_uri.path) @path = HTTPUtils::normalize_path(@path) @host = @request_uri.host @port = @request_uri.port @query_string = @request_uri.query @script_name = "" @path_info = @path.dup rescue raise HTTPStatus::BadRequest, "bad URI `#{@unparsed_uri}'." end if /close/io =~ self["connection"] @keep_alive = false elsif /keep-alive/io =~ self["connection"] @keep_alive = true elsif @http_version < "1.1" @keep_alive = false else @keep_alive = true end end ## # Generate HTTP/1.1 100 continue response if the client expects it, # otherwise does nothing. def continue # :nodoc: if self['expect'] == '100-continue' && @config[:HTTPVersion] >= "1.1" @socket << "HTTP/#{@config[:HTTPVersion]} 100 continue#{CRLF}#{CRLF}" @header.delete('expect') end end ## # Returns the request body. def body(&block) # :yields: body_chunk block ||= Proc.new{|chunk| @body << chunk } read_body(@socket, block) @body.empty? ? nil : @body end ## # Request query as a Hash def query unless @query parse_query() end @query end ## # The content-length header def content_length return Integer(self['content-length']) end ## # The content-type header def content_type return self['content-type'] end ## # Retrieves +header_name+ def [](header_name) if @header value = @header[header_name.downcase] value.empty? ? nil : value.join(", ") end end ## # Iterates over the request headers def each if @header @header.each{|k, v| value = @header[k] yield(k, value.empty? ? nil : value.join(", ")) } end end ## # The host this request is for def host return @forwarded_host || @host end ## # The port this request is for def port return @forwarded_port || @port end ## # The server name this request is for def server_name return @forwarded_server || @config[:ServerName] end ## # The client's IP address def remote_ip return self["client-ip"] || @forwarded_for || @peeraddr[3] end ## # Is this an SSL request? def ssl? return @request_uri.scheme == "https" end ## # Should the connection this request was made on be kept alive? def keep_alive? @keep_alive end def to_s # :nodoc: ret = @request_line.dup @raw_header.each{|line| ret << line } ret << CRLF ret << body if body ret end ## # Consumes any remaining body and updates keep-alive status def fixup() # :nodoc: begin body{|chunk| } # read remaining body rescue HTTPStatus::Error => ex @logger.error("HTTPRequest#fixup: #{ex.class} occurred.") @keep_alive = false rescue => ex @logger.error(ex) @keep_alive = false end end # This method provides the metavariables defined by the revision 3 # of "The WWW Common Gateway Interface Version 1.1" # To browse the current document of CGI Version 1.1, see below: # http://tools.ietf.org/html/rfc3875 def meta_vars meta = Hash.new cl = self["Content-Length"] ct = self["Content-Type"] meta["CONTENT_LENGTH"] = cl if cl.to_i > 0 meta["CONTENT_TYPE"] = ct.dup if ct meta["GATEWAY_INTERFACE"] = "CGI/1.1" meta["PATH_INFO"] = @path_info ? @path_info.dup : "" #meta["PATH_TRANSLATED"] = nil # no plan to be provided meta["QUERY_STRING"] = @query_string ? @query_string.dup : "" meta["REMOTE_ADDR"] = @peeraddr[3] meta["REMOTE_HOST"] = @peeraddr[2] #meta["REMOTE_IDENT"] = nil # no plan to be provided meta["REMOTE_USER"] = @user meta["REQUEST_METHOD"] = @request_method.dup meta["REQUEST_URI"] = @request_uri.to_s meta["SCRIPT_NAME"] = @script_name.dup meta["SERVER_NAME"] = @host meta["SERVER_PORT"] = @port.to_s meta["SERVER_PROTOCOL"] = "HTTP/" + @config[:HTTPVersion].to_s meta["SERVER_SOFTWARE"] = @config[:ServerSoftware].dup self.each{|key, val| next if /^content-type$/i =~ key next if /^content-length$/i =~ key name = "HTTP_" + key name.gsub!(/-/o, "_") name.upcase! meta[name] = val } meta end private # :stopdoc: MAX_URI_LENGTH = 2083 # :nodoc: # same as Mongrel, Thin and Puma MAX_HEADER_LENGTH = (112 * 1024) # :nodoc: def read_request_line(socket) @request_line = read_line(socket, MAX_URI_LENGTH) if socket @request_bytes = @request_line.bytesize if @request_bytes >= MAX_URI_LENGTH and @request_line[-1, 1] != LF raise HTTPStatus::RequestURITooLarge end @request_time = Time.now raise HTTPStatus::EOFError unless @request_line if /^(\S+)\s+(\S++)(?:\s+HTTP\/(\d+\.\d+))?\r?\n/mo =~ @request_line @request_method = $1 @unparsed_uri = $2 @http_version = HTTPVersion.new($3 ? $3 : "0.9") else rl = @request_line.sub(/\x0d?\x0a\z/o, '') raise HTTPStatus::BadRequest, "bad Request-Line `#{rl}'." end end def read_header(socket) if socket while line = read_line(socket) break if /\A(#{CRLF}|#{LF})\z/om =~ line if (@request_bytes += line.bytesize) > MAX_HEADER_LENGTH raise HTTPStatus::RequestEntityTooLarge, 'headers too large' end @raw_header << line end end @header = HTTPUtils::parse_header(@raw_header.join) end def parse_uri(str, scheme="http") if @config[:Escape8bitURI] str = HTTPUtils::escape8bit(str) end str.sub!(%r{\A/+}o, '/') uri = URI::parse(str) return uri if uri.absolute? if @forwarded_host host, port = @forwarded_host, @forwarded_port elsif self["host"] pattern = /\A(#{URI::REGEXP::PATTERN::HOST})(?::(\d+))?\z/n host, port = *self['host'].scan(pattern)[0] elsif @addr.size > 0 host, port = @addr[2], @addr[1] else host, port = @config[:ServerName], @config[:Port] end uri.scheme = @forwarded_proto || scheme uri.host = host uri.port = port ? port.to_i : nil return URI::parse(uri.to_s) end def read_body(socket, block) return unless socket if tc = self['transfer-encoding'] case tc when /chunked/io then read_chunked(socket, block) else raise HTTPStatus::NotImplemented, "Transfer-Encoding: #{tc}." end elsif self['content-length'] || @remaining_size @remaining_size ||= self['content-length'].to_i while @remaining_size > 0 sz = [@buffer_size, @remaining_size].min break unless buf = read_data(socket, sz) @remaining_size -= buf.bytesize block.call(buf) end if @remaining_size > 0 && @socket.eof? raise HTTPStatus::BadRequest, "invalid body size." end elsif BODY_CONTAINABLE_METHODS.member?(@request_method) raise HTTPStatus::LengthRequired end return @body end def read_chunk_size(socket) line = read_line(socket) if /^([0-9a-fA-F]+)(?:;(\S+))?/ =~ line chunk_size = $1.hex chunk_ext = $2 [ chunk_size, chunk_ext ] else raise HTTPStatus::BadRequest, "bad chunk `#{line}'." end end def read_chunked(socket, block) chunk_size, = read_chunk_size(socket) while chunk_size > 0 begin sz = [ chunk_size, @buffer_size ].min data = read_data(socket, sz) # read chunk-data if data.nil? || data.bytesize != sz raise HTTPStatus::BadRequest, "bad chunk data size." end block.call(data) end while (chunk_size -= sz) > 0 read_line(socket) # skip CRLF chunk_size, = read_chunk_size(socket) end read_header(socket) # trailer + CRLF @header.delete("transfer-encoding") @remaining_size = 0 end def _read_data(io, method, *arg) begin WEBrick::Utils.timeout(@config[:RequestTimeout]){ return io.__send__(method, *arg) } rescue Errno::ECONNRESET return nil rescue Timeout::Error raise HTTPStatus::RequestTimeout end end def read_line(io, size=4096) _read_data(io, :gets, LF, size) end def read_data(io, size) _read_data(io, :read, size) end def parse_query() begin if @request_method == "GET" || @request_method == "HEAD" @query = HTTPUtils::parse_query(@query_string) elsif self['content-type'] =~ /^application\/x-www-form-urlencoded/ @query = HTTPUtils::parse_query(body) elsif self['content-type'] =~ /^multipart\/form-data; boundary=(.+)/ boundary = HTTPUtils::dequote($1) @query = HTTPUtils::parse_form_data(body, boundary) else @query = Hash.new end rescue => ex raise HTTPStatus::BadRequest, ex.message end end PrivateNetworkRegexp = / ^unknown$| ^((::ffff:)?127.0.0.1|::1)$| ^(::ffff:)?(10|172\.(1[6-9]|2[0-9]|3[01])|192\.168)\. /ixo # It's said that all X-Forwarded-* headers will contain more than one # (comma-separated) value if the original request already contained one of # these headers. Since we could use these values as Host header, we choose # the initial(first) value. (apr_table_mergen() adds new value after the # existing value with ", " prefix) def setup_forwarded_info if @forwarded_server = self["x-forwarded-server"] @forwarded_server = @forwarded_server.split(",", 2).first end @forwarded_proto = self["x-forwarded-proto"] if host_port = self["x-forwarded-host"] host_port = host_port.split(",", 2).first @forwarded_host, tmp = host_port.split(":", 2) @forwarded_port = (tmp || (@forwarded_proto == "https" ? 443 : 80)).to_i end if addrs = self["x-forwarded-for"] addrs = addrs.split(",").collect(&:strip) addrs.reject!{|ip| PrivateNetworkRegexp =~ ip } @forwarded_for = addrs.first end end # :startdoc: end end PK!ד[`&`&2.2.0/webrick/httpproxy.rbnu[# # httpproxy.rb -- HTTPProxy Class # # Author: IPR -- Internet Programming with Ruby -- writers # Copyright (c) 2002 GOTO Kentaro # Copyright (c) 2002 Internet Programming with Ruby writers. All rights # reserved. # # $IPR: httpproxy.rb,v 1.18 2003/03/08 18:58:10 gotoyuzo Exp $ # $kNotwork: straw.rb,v 1.3 2002/02/12 15:13:07 gotoken Exp $ require "webrick/httpserver" require "net/http" module WEBrick NullReader = Object.new # :nodoc: class << NullReader # :nodoc: def read(*args) nil end alias gets read end FakeProxyURI = Object.new # :nodoc: class << FakeProxyURI # :nodoc: def method_missing(meth, *args) if %w(scheme host port path query userinfo).member?(meth.to_s) return nil end super end end # :startdoc: ## # An HTTP Proxy server which proxies GET, HEAD and POST requests. # # To create a simple proxy server: # # require 'webrick' # require 'webrick/httpproxy' # # proxy = WEBrick::HTTPProxyServer.new Port: 8000 # # trap 'INT' do proxy.shutdown end # trap 'TERM' do proxy.shutdown end # # proxy.start # # See ::new for proxy-specific configuration items. # # == Modifying proxied responses # # To modify content the proxy server returns use the +:ProxyContentHandler+ # option: # # handler = proc do |req, res| # if res['content-type'] == 'text/plain' then # res.body << "\nThis content was proxied!\n" # end # end # # proxy = # WEBrick::HTTPProxyServer.new Port: 8000, ProxyContentHandler: handler class HTTPProxyServer < HTTPServer ## # Proxy server configurations. The proxy server handles the following # configuration items in addition to those supported by HTTPServer: # # :ProxyAuthProc:: Called with a request and response to authorize a # request # :ProxyVia:: Appended to the via header # :ProxyURI:: The proxy server's URI # :ProxyContentHandler:: Called with a request and response and allows # modification of the response # :ProxyTimeout:: Sets the proxy timeouts to 30 seconds for open and 60 # seconds for read operations def initialize(config={}, default=Config::HTTP) super(config, default) c = @config @via = "#{c[:HTTPVersion]} #{c[:ServerName]}:#{c[:Port]}" end # :stopdoc: def service(req, res) if req.request_method == "CONNECT" do_CONNECT(req, res) elsif req.unparsed_uri =~ %r!^http://! proxy_service(req, res) else super(req, res) end end def proxy_auth(req, res) if proc = @config[:ProxyAuthProc] proc.call(req, res) end req.header.delete("proxy-authorization") end def proxy_uri(req, res) # should return upstream proxy server's URI return @config[:ProxyURI] end def proxy_service(req, res) # Proxy Authentication proxy_auth(req, res) begin self.send("do_#{req.request_method}", req, res) rescue NoMethodError raise HTTPStatus::MethodNotAllowed, "unsupported method `#{req.request_method}'." rescue => err logger.debug("#{err.class}: #{err.message}") raise HTTPStatus::ServiceUnavailable, err.message end # Process contents if handler = @config[:ProxyContentHandler] handler.call(req, res) end end def do_CONNECT(req, res) # Proxy Authentication proxy_auth(req, res) ua = Thread.current[:WEBrickSocket] # User-Agent raise HTTPStatus::InternalServerError, "[BUG] cannot get socket" unless ua host, port = req.unparsed_uri.split(":", 2) # Proxy authentication for upstream proxy server if proxy = proxy_uri(req, res) proxy_request_line = "CONNECT #{host}:#{port} HTTP/1.0" if proxy.userinfo credentials = "Basic " + [proxy.userinfo].pack("m").delete("\n") end host, port = proxy.host, proxy.port end begin @logger.debug("CONNECT: upstream proxy is `#{host}:#{port}'.") os = TCPSocket.new(host, port) # origin server if proxy @logger.debug("CONNECT: sending a Request-Line") os << proxy_request_line << CRLF @logger.debug("CONNECT: > #{proxy_request_line}") if credentials @logger.debug("CONNECT: sending a credentials") os << "Proxy-Authorization: " << credentials << CRLF end os << CRLF proxy_status_line = os.gets(LF) @logger.debug("CONNECT: read a Status-Line form the upstream server") @logger.debug("CONNECT: < #{proxy_status_line}") if %r{^HTTP/\d+\.\d+\s+200\s*} =~ proxy_status_line while line = os.gets(LF) break if /\A(#{CRLF}|#{LF})\z/om =~ line end else raise HTTPStatus::BadGateway end end @logger.debug("CONNECT #{host}:#{port}: succeeded") res.status = HTTPStatus::RC_OK rescue => ex @logger.debug("CONNECT #{host}:#{port}: failed `#{ex.message}'") res.set_error(ex) raise HTTPStatus::EOFError ensure if handler = @config[:ProxyContentHandler] handler.call(req, res) end res.send_response(ua) access_log(@config, req, res) # Should clear request-line not to send the response twice. # see: HTTPServer#run req.parse(NullReader) rescue nil end begin while fds = IO::select([ua, os]) if fds[0].member?(ua) buf = ua.sysread(1024); @logger.debug("CONNECT: #{buf.bytesize} byte from User-Agent") os.syswrite(buf) elsif fds[0].member?(os) buf = os.sysread(1024); @logger.debug("CONNECT: #{buf.bytesize} byte from #{host}:#{port}") ua.syswrite(buf) end end rescue os.close @logger.debug("CONNECT #{host}:#{port}: closed") end raise HTTPStatus::EOFError end def do_GET(req, res) perform_proxy_request(req, res) do |http, path, header| http.get(path, header) end end def do_HEAD(req, res) perform_proxy_request(req, res) do |http, path, header| http.head(path, header) end end def do_POST(req, res) perform_proxy_request(req, res) do |http, path, header| http.post(path, req.body || "", header) end end def do_OPTIONS(req, res) res['allow'] = "GET,HEAD,POST,OPTIONS,CONNECT" end private # Some header fields should not be transferred. HopByHop = %w( connection keep-alive proxy-authenticate upgrade proxy-authorization te trailers transfer-encoding ) ShouldNotTransfer = %w( set-cookie proxy-connection ) def split_field(f) f ? f.split(/,\s+/).collect{|i| i.downcase } : [] end def choose_header(src, dst) connections = split_field(src['connection']) src.each{|key, value| key = key.downcase if HopByHop.member?(key) || # RFC2616: 13.5.1 connections.member?(key) || # RFC2616: 14.10 ShouldNotTransfer.member?(key) # pragmatics @logger.debug("choose_header: `#{key}: #{value}'") next end dst[key] = value } end # Net::HTTP is stupid about the multiple header fields. # Here is workaround: def set_cookie(src, dst) if str = src['set-cookie'] cookies = [] str.split(/,\s*/).each{|token| if /^[^=]+;/o =~ token cookies[-1] << ", " << token elsif /=/o =~ token cookies << token else cookies[-1] << ", " << token end } dst.cookies.replace(cookies) end end def set_via(h) if @config[:ProxyVia] if h['via'] h['via'] << ", " << @via else h['via'] = @via end end end def setup_proxy_header(req, res) # Choose header fields to transfer header = Hash.new choose_header(req, header) set_via(header) return header end def setup_upstream_proxy_authentication(req, res, header) if upstream = proxy_uri(req, res) if upstream.userinfo header['proxy-authorization'] = "Basic " + [upstream.userinfo].pack("m").delete("\n") end return upstream end return FakeProxyURI end def perform_proxy_request(req, res) uri = req.request_uri path = uri.path.dup path << "?" << uri.query if uri.query header = setup_proxy_header(req, res) upstream = setup_upstream_proxy_authentication(req, res, header) response = nil http = Net::HTTP.new(uri.host, uri.port, upstream.host, upstream.port) http.start do if @config[:ProxyTimeout] ################################## these issues are http.open_timeout = 30 # secs # necessary (maybe because http.read_timeout = 60 # secs # Ruby's bug, but why?) ################################## end response = yield(http, path, header) end # Persistent connection requirements are mysterious for me. # So I will close the connection in every response. res['proxy-connection'] = "close" res['connection'] = "close" # Convert Net::HTTP::HTTPResponse to WEBrick::HTTPResponse res.status = response.code.to_i choose_header(response, res) set_cookie(response, res) set_via(res) res.body = response.body end # :stopdoc: end end PK!0BB2.2.0/webrick/config.rbnu[# # config.rb -- Default configurations. # # Author: IPR -- Internet Programming with Ruby -- writers # Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou # Copyright (c) 2003 Internet Programming with Ruby writers. All rights # reserved. # # $IPR: config.rb,v 1.52 2003/07/22 19:20:42 gotoyuzo Exp $ require 'webrick/version' require 'webrick/httpversion' require 'webrick/httputils' require 'webrick/utils' require 'webrick/log' module WEBrick module Config LIBDIR = File::dirname(__FILE__) # :nodoc: # for GenericServer General = { :ServerName => Utils::getservername, :BindAddress => nil, # "0.0.0.0" or "::" or nil :Port => nil, # users MUST specify this!! :MaxClients => 100, # maximum number of the concurrent connections :ServerType => nil, # default: WEBrick::SimpleServer :Logger => nil, # default: WEBrick::Log.new :ServerSoftware => "WEBrick/#{WEBrick::VERSION} " + "(Ruby/#{RUBY_VERSION}/#{RUBY_RELEASE_DATE})", :TempDir => ENV['TMPDIR']||ENV['TMP']||ENV['TEMP']||'/tmp', :DoNotListen => false, :StartCallback => nil, :StopCallback => nil, :AcceptCallback => nil, :DoNotReverseLookup => nil, :ShutdownSocketWithoutClose => false, } # for HTTPServer, HTTPRequest, HTTPResponse ... HTTP = General.dup.update( :Port => 80, :RequestTimeout => 30, :HTTPVersion => HTTPVersion.new("1.1"), :AccessLog => nil, :MimeTypes => HTTPUtils::DefaultMimeTypes, :DirectoryIndex => ["index.html","index.htm","index.cgi","index.rhtml"], :DocumentRoot => nil, :DocumentRootOptions => { :FancyIndexing => true }, :RequestCallback => nil, :ServerAlias => nil, :InputBufferSize => 65536, # input buffer size in reading request body :OutputBufferSize => 65536, # output buffer size in sending File or IO # for HTTPProxyServer :ProxyAuthProc => nil, :ProxyContentHandler => nil, :ProxyVia => true, :ProxyTimeout => true, :ProxyURI => nil, :CGIInterpreter => nil, :CGIPathEnv => nil, # workaround: if Request-URIs contain 8bit chars, # they should be escaped before calling of URI::parse(). :Escape8bitURI => false ) ## # Default configuration for WEBrick::HTTPServlet::FileHandler # # :AcceptableLanguages:: # Array of languages allowed for accept-language. There is no default # :DirectoryCallback:: # Allows preprocessing of directory requests. There is no default # callback. # :FancyIndexing:: # If true, show an index for directories. The default is true. # :FileCallback:: # Allows preprocessing of file requests. There is no default callback. # :HandlerCallback:: # Allows preprocessing of requests. There is no default callback. # :HandlerTable:: # Maps file suffixes to file handlers. DefaultFileHandler is used by # default but any servlet can be used. # :NondisclosureName:: # Do not show files matching this array of globs. .ht* and *~ are # excluded by default. # :UserDir:: # Directory inside ~user to serve content from for /~user requests. # Only works if mounted on /. Disabled by default. FileHandler = { :NondisclosureName => [".ht*", "*~"], :FancyIndexing => false, :HandlerTable => {}, :HandlerCallback => nil, :DirectoryCallback => nil, :FileCallback => nil, :UserDir => nil, # e.g. "public_html" :AcceptableLanguages => [] # ["en", "ja", ... ] } ## # Default configuration for WEBrick::HTTPAuth::BasicAuth # # :AutoReloadUserDB:: Reload the user database provided by :UserDB # automatically? BasicAuth = { :AutoReloadUserDB => true, } ## # Default configuration for WEBrick::HTTPAuth::DigestAuth. # # :Algorithm:: MD5, MD5-sess (default), SHA1, SHA1-sess # :Domain:: An Array of URIs that define the protected space # :Qop:: 'auth' for authentication, 'auth-int' for integrity protection or # both # :UseOpaque:: Should the server send opaque values to the client? This # helps prevent replay attacks. # :CheckNc:: Should the server check the nonce count? This helps the # server detect replay attacks. # :UseAuthenticationInfoHeader:: Should the server send an # AuthenticationInfo header? # :AutoReloadUserDB:: Reload the user database provided by :UserDB # automatically? # :NonceExpirePeriod:: How long should we store used nonces? Default is # 30 minutes. # :NonceExpireDelta:: How long is a nonce valid? Default is 1 minute # :InternetExplorerHack:: Hack which allows Internet Explorer to work. # :OperaHack:: Hack which allows Opera to work. DigestAuth = { :Algorithm => 'MD5-sess', # or 'MD5' :Domain => nil, # an array includes domain names. :Qop => [ 'auth' ], # 'auth' or 'auth-int' or both. :UseOpaque => true, :UseNextNonce => false, :CheckNc => false, :UseAuthenticationInfoHeader => true, :AutoReloadUserDB => true, :NonceExpirePeriod => 30*60, :NonceExpireDelta => 60, :InternetExplorerHack => true, :OperaHack => true, } end end PK!&2.2.0/webrick/log.rbnu[#-- # log.rb -- Log Class # # Author: IPR -- Internet Programming with Ruby -- writers # Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou # Copyright (c) 2002 Internet Programming with Ruby writers. All rights # reserved. # # $IPR: log.rb,v 1.26 2002/10/06 17:06:10 gotoyuzo Exp $ module WEBrick ## # A generic logging class class BasicLog # Fatal log level which indicates a server crash FATAL = 1 # Error log level which indicates a recoverable error ERROR = 2 # Warning log level which indicates a possible problem WARN = 3 # Information log level which indicates possibly useful information INFO = 4 # Debugging error level for messages used in server development or # debugging DEBUG = 5 # log-level, messages above this level will be logged attr_accessor :level ## # Initializes a new logger for +log_file+ that outputs messages at +level+ # or higher. +log_file+ can be a filename, an IO-like object that # responds to #<< or nil which outputs to $stderr. # # If no level is given INFO is chosen by default def initialize(log_file=nil, level=nil) @level = level || INFO case log_file when String @log = open(log_file, "a+") @log.sync = true @opened = true when NilClass @log = $stderr else @log = log_file # requires "<<". (see BasicLog#log) end end ## # Closes the logger (also closes the log device associated to the logger) def close @log.close if @opened @log = nil end ## # Logs +data+ at +level+ if the given level is above the current log # level. def log(level, data) if @log && level <= @level data += "\n" if /\n\Z/ !~ data @log << data end end ## # Synonym for log(INFO, obj.to_s) def <<(obj) log(INFO, obj.to_s) end # Shortcut for logging a FATAL message def fatal(msg) log(FATAL, "FATAL " << format(msg)); end # Shortcut for logging an ERROR message def error(msg) log(ERROR, "ERROR " << format(msg)); end # Shortcut for logging a WARN message def warn(msg) log(WARN, "WARN " << format(msg)); end # Shortcut for logging an INFO message def info(msg) log(INFO, "INFO " << format(msg)); end # Shortcut for logging a DEBUG message def debug(msg) log(DEBUG, "DEBUG " << format(msg)); end # Will the logger output FATAL messages? def fatal?; @level >= FATAL; end # Will the logger output ERROR messages? def error?; @level >= ERROR; end # Will the logger output WARN messages? def warn?; @level >= WARN; end # Will the logger output INFO messages? def info?; @level >= INFO; end # Will the logger output DEBUG messages? def debug?; @level >= DEBUG; end private ## # Formats +arg+ for the logger # # * If +arg+ is an Exception, it will format the error message and # the back trace. # * If +arg+ responds to #to_str, it will return it. # * Otherwise it will return +arg+.inspect. def format(arg) if arg.is_a?(Exception) "#{arg.class}: #{AccessLog.escape(arg.message)}\n\t" << arg.backtrace.join("\n\t") << "\n" elsif arg.respond_to?(:to_str) AccessLog.escape(arg.to_str) else arg.inspect end end end ## # A logging class that prepends a timestamp to each message. class Log < BasicLog # Format of the timestamp which is applied to each logged line. The # default is "[%Y-%m-%d %H:%M:%S]" attr_accessor :time_format ## # Same as BasicLog#initialize # # You can set the timestamp format through #time_format def initialize(log_file=nil, level=nil) super(log_file, level) @time_format = "[%Y-%m-%d %H:%M:%S]" end ## # Same as BasicLog#log def log(level, data) tmp = Time.now.strftime(@time_format) tmp << " " << data super(level, tmp) end end end PK!s #2.2.0/webrick/httpauth/basicauth.rbnu[# # httpauth/basicauth.rb -- HTTP basic access authentication # # Author: IPR -- Internet Programming with Ruby -- writers # Copyright (c) 2003 Internet Programming with Ruby writers. All rights # reserved. # # $IPR: basicauth.rb,v 1.5 2003/02/20 07:15:47 gotoyuzo Exp $ require 'webrick/config' require 'webrick/httpstatus' require 'webrick/httpauth/authenticator' module WEBrick module HTTPAuth ## # Basic Authentication for WEBrick # # Use this class to add basic authentication to a WEBrick servlet. # # Here is an example of how to set up a BasicAuth: # # config = { :Realm => 'BasicAuth example realm' } # # htpasswd = WEBrick::HTTPAuth::Htpasswd.new 'my_password_file' # htpasswd.set_passwd config[:Realm], 'username', 'password' # htpasswd.flush # # config[:UserDB] = htpasswd # # basic_auth = WEBrick::HTTPAuth::BasicAuth.new config class BasicAuth include Authenticator AuthScheme = "Basic" # :nodoc: ## # Used by UserDB to create a basic password entry def self.make_passwd(realm, user, pass) pass ||= "" pass.crypt(Utils::random_string(2)) end attr_reader :realm, :userdb, :logger ## # Creates a new BasicAuth instance. # # See WEBrick::Config::BasicAuth for default configuration entries # # You must supply the following configuration entries: # # :Realm:: The name of the realm being protected. # :UserDB:: A database of usernames and passwords. # A WEBrick::HTTPAuth::Htpasswd instance should be used. def initialize(config, default=Config::BasicAuth) check_init(config) @config = default.dup.update(config) end ## # Authenticates a +req+ and returns a 401 Unauthorized using +res+ if # the authentication was not correct. def authenticate(req, res) unless basic_credentials = check_scheme(req) challenge(req, res) end userid, password = basic_credentials.unpack("m*")[0].split(":", 2) password ||= "" if userid.empty? error("user id was not given.") challenge(req, res) end unless encpass = @userdb.get_passwd(@realm, userid, @reload_db) error("%s: the user is not allowed.", userid) challenge(req, res) end if password.crypt(encpass) != encpass error("%s: password unmatch.", userid) challenge(req, res) end info("%s: authentication succeeded.", userid) req.user = userid end ## # Returns a challenge response which asks for for authentication # information def challenge(req, res) res[@response_field] = "#{@auth_scheme} realm=\"#{@realm}\"" raise @auth_exception end end ## # Basic authentication for proxy servers. See BasicAuth for details. class ProxyBasicAuth < BasicAuth include ProxyAuthenticator end end end PK!z_Q Q !2.2.0/webrick/httpauth/htgroup.rbnu[# # httpauth/htgroup.rb -- Apache compatible htgroup file # # Author: IPR -- Internet Programming with Ruby -- writers # Copyright (c) 2003 Internet Programming with Ruby writers. All rights # reserved. # # $IPR: htgroup.rb,v 1.1 2003/02/16 22:22:56 gotoyuzo Exp $ require 'tempfile' module WEBrick module HTTPAuth ## # Htgroup accesses apache-compatible group files. Htgroup can be used to # provide group-based authentication for users. Currently Htgroup is not # directly integrated with any authenticators in WEBrick. For security, # the path for a digest password database should be stored outside of the # paths available to the HTTP server. # # Example: # # htgroup = WEBrick::HTTPAuth::Htgroup.new 'my_group_file' # htgroup.add 'superheroes', %w[spiderman batman] # # htgroup.members('superheroes').include? 'magneto' # => false class Htgroup ## # Open a group database at +path+ def initialize(path) @path = path @mtime = Time.at(0) @group = Hash.new open(@path,"a").close unless File::exist?(@path) reload end ## # Reload groups from the database def reload if (mtime = File::mtime(@path)) > @mtime @group.clear open(@path){|io| while line = io.gets line.chomp! group, members = line.split(/:\s*/) @group[group] = members.split(/\s+/) end } @mtime = mtime end end ## # Flush the group database. If +output+ is given the database will be # written there instead of to the original path. def flush(output=nil) output ||= @path tmp = Tempfile.new("htgroup", File::dirname(output)) begin @group.keys.sort.each{|group| tmp.puts(format("%s: %s", group, self.members(group).join(" "))) } tmp.close File::rename(tmp.path, output) rescue tmp.close(true) end end ## # Retrieve the list of members from +group+ def members(group) reload @group[group] || [] end ## # Add an Array of +members+ to +group+ def add(group, members) @group[group] = members(group) | members end end end end PK!Z  "2.2.0/webrick/httpauth/htpasswd.rbnu[# # httpauth/htpasswd -- Apache compatible htpasswd file # # Author: IPR -- Internet Programming with Ruby -- writers # Copyright (c) 2003 Internet Programming with Ruby writers. All rights # reserved. # # $IPR: htpasswd.rb,v 1.4 2003/07/22 19:20:45 gotoyuzo Exp $ require 'webrick/httpauth/userdb' require 'webrick/httpauth/basicauth' require 'tempfile' module WEBrick module HTTPAuth ## # Htpasswd accesses apache-compatible password files. Passwords are # matched to a realm where they are valid. For security, the path for a # password database should be stored outside of the paths available to the # HTTP server. # # Htpasswd is intended for use with WEBrick::HTTPAuth::BasicAuth. # # To create an Htpasswd database with a single user: # # htpasswd = WEBrick::HTTPAuth::Htpasswd.new 'my_password_file' # htpasswd.set_passwd 'my realm', 'username', 'password' # htpasswd.flush class Htpasswd include UserDB ## # Open a password database at +path+ def initialize(path) @path = path @mtime = Time.at(0) @passwd = Hash.new @auth_type = BasicAuth open(@path,"a").close unless File::exist?(@path) reload end ## # Reload passwords from the database def reload mtime = File::mtime(@path) if mtime > @mtime @passwd.clear open(@path){|io| while line = io.gets line.chomp! case line when %r!\A[^:]+:[a-zA-Z0-9./]{13}\z! user, pass = line.split(":") when /:\$/, /:{SHA}/ raise NotImplementedError, 'MD5, SHA1 .htpasswd file not supported' else raise StandardError, 'bad .htpasswd file' end @passwd[user] = pass end } @mtime = mtime end end ## # Flush the password database. If +output+ is given the database will # be written there instead of to the original path. def flush(output=nil) output ||= @path tmp = Tempfile.create("htpasswd", File::dirname(output)) renamed = false begin each{|item| tmp.puts(item.join(":")) } tmp.close File::rename(tmp.path, output) renamed = true ensure tmp.close if !tmp.closed? File.unlink(tmp.path) if !renamed end end ## # Retrieves a password from the database for +user+ in +realm+. If # +reload_db+ is true the database will be reloaded first. def get_passwd(realm, user, reload_db) reload() if reload_db @passwd[user] end ## # Sets a password in the database for +user+ in +realm+ to +pass+. def set_passwd(realm, user, pass) @passwd[user] = make_passwd(realm, user, pass) end ## # Removes a password from the database for +user+ in +realm+. def delete_passwd(realm, user) @passwd.delete(user) end ## # Iterate passwords in the database. def each # :yields: [user, password] @passwd.keys.sort.each{|user| yield([user, @passwd[user]]) } end end end end PK!0b "2.2.0/webrick/httpauth/htdigest.rbnu[# # httpauth/htdigest.rb -- Apache compatible htdigest file # # Author: IPR -- Internet Programming with Ruby -- writers # Copyright (c) 2003 Internet Programming with Ruby writers. All rights # reserved. # # $IPR: htdigest.rb,v 1.4 2003/07/22 19:20:45 gotoyuzo Exp $ require 'webrick/httpauth/userdb' require 'webrick/httpauth/digestauth' require 'tempfile' module WEBrick module HTTPAuth ## # Htdigest accesses apache-compatible digest password files. Passwords are # matched to a realm where they are valid. For security, the path for a # digest password database should be stored outside of the paths available # to the HTTP server. # # Htdigest is intended for use with WEBrick::HTTPAuth::DigestAuth and # stores passwords using cryptographic hashes. # # htpasswd = WEBrick::HTTPAuth::Htdigest.new 'my_password_file' # htpasswd.set_passwd 'my realm', 'username', 'password' # htpasswd.flush class Htdigest include UserDB ## # Open a digest password database at +path+ def initialize(path) @path = path @mtime = Time.at(0) @digest = Hash.new @mutex = Mutex::new @auth_type = DigestAuth open(@path,"a").close unless File::exist?(@path) reload end ## # Reloads passwords from the database def reload mtime = File::mtime(@path) if mtime > @mtime @digest.clear open(@path){|io| while line = io.gets line.chomp! user, realm, pass = line.split(/:/, 3) unless @digest[realm] @digest[realm] = Hash.new end @digest[realm][user] = pass end } @mtime = mtime end end ## # Flush the password database. If +output+ is given the database will # be written there instead of to the original path. def flush(output=nil) output ||= @path tmp = Tempfile.create("htpasswd", File::dirname(output)) renamed = false begin each{|item| tmp.puts(item.join(":")) } tmp.close File::rename(tmp.path, output) renamed = true ensure tmp.close if !tmp.closed? File.unlink(tmp.path) if !renamed end end ## # Retrieves a password from the database for +user+ in +realm+. If # +reload_db+ is true the database will be reloaded first. def get_passwd(realm, user, reload_db) reload() if reload_db if hash = @digest[realm] hash[user] end end ## # Sets a password in the database for +user+ in +realm+ to +pass+. def set_passwd(realm, user, pass) @mutex.synchronize{ unless @digest[realm] @digest[realm] = Hash.new end @digest[realm][user] = make_passwd(realm, user, pass) } end ## # Removes a password from the database for +user+ in +realm+. def delete_passwd(realm, user) if hash = @digest[realm] hash.delete(user) end end ## # Iterate passwords in the database. def each # :yields: [user, realm, password_hash] @digest.keys.sort.each{|realm| hash = @digest[realm] hash.keys.sort.each{|user| yield([user, realm, hash[user]]) } } end end end end PK!x '2.2.0/webrick/httpauth/authenticator.rbnu[#-- # httpauth/authenticator.rb -- Authenticator mix-in module. # # Author: IPR -- Internet Programming with Ruby -- writers # Copyright (c) 2003 Internet Programming with Ruby writers. All rights # reserved. # # $IPR: authenticator.rb,v 1.3 2003/02/20 07:15:47 gotoyuzo Exp $ module WEBrick module HTTPAuth ## # Module providing generic support for both Digest and Basic # authentication schemes. module Authenticator RequestField = "Authorization" # :nodoc: ResponseField = "WWW-Authenticate" # :nodoc: ResponseInfoField = "Authentication-Info" # :nodoc: AuthException = HTTPStatus::Unauthorized # :nodoc: ## # Method of authentication, must be overridden by the including class AuthScheme = nil ## # The realm this authenticator covers attr_reader :realm ## # The user database for this authenticator attr_reader :userdb ## # The logger for this authenticator attr_reader :logger private # :stopdoc: ## # Initializes the authenticator from +config+ def check_init(config) [:UserDB, :Realm].each{|sym| unless config[sym] raise ArgumentError, "Argument #{sym.inspect} missing." end } @realm = config[:Realm] @userdb = config[:UserDB] @logger = config[:Logger] || Log::new($stderr) @reload_db = config[:AutoReloadUserDB] @request_field = self::class::RequestField @response_field = self::class::ResponseField @resp_info_field = self::class::ResponseInfoField @auth_exception = self::class::AuthException @auth_scheme = self::class::AuthScheme end ## # Ensures +req+ has credentials that can be authenticated. def check_scheme(req) unless credentials = req[@request_field] error("no credentials in the request.") return nil end unless match = /^#{@auth_scheme}\s+/i.match(credentials) error("invalid scheme in %s.", credentials) info("%s: %s", @request_field, credentials) if $DEBUG return nil end return match.post_match end def log(meth, fmt, *args) msg = format("%s %s: ", @auth_scheme, @realm) msg << fmt % args @logger.send(meth, msg) end def error(fmt, *args) if @logger.error? log(:error, fmt, *args) end end def info(fmt, *args) if @logger.info? log(:info, fmt, *args) end end # :startdoc: end ## # Module providing generic support for both Digest and Basic # authentication schemes for proxies. module ProxyAuthenticator RequestField = "Proxy-Authorization" # :nodoc: ResponseField = "Proxy-Authenticate" # :nodoc: InfoField = "Proxy-Authentication-Info" # :nodoc: AuthException = HTTPStatus::ProxyAuthenticationRequired # :nodoc: end end end PK!`,44$2.2.0/webrick/httpauth/digestauth.rbnu[# # httpauth/digestauth.rb -- HTTP digest access authentication # # Author: IPR -- Internet Programming with Ruby -- writers # Copyright (c) 2003 Internet Programming with Ruby writers. # Copyright (c) 2003 H.M. # # The original implementation is provided by H.M. # URL: http://rwiki.jin.gr.jp/cgi-bin/rw-cgi.rb?cmd=view;name= # %C7%A7%BE%DA%B5%A1%C7%BD%A4%F2%B2%FE%C2%A4%A4%B7%A4%C6%A4%DF%A4%EB # # $IPR: digestauth.rb,v 1.5 2003/02/20 07:15:47 gotoyuzo Exp $ require 'webrick/config' require 'webrick/httpstatus' require 'webrick/httpauth/authenticator' require 'digest/md5' require 'digest/sha1' module WEBrick module HTTPAuth ## # RFC 2617 Digest Access Authentication for WEBrick # # Use this class to add digest authentication to a WEBrick servlet. # # Here is an example of how to set up DigestAuth: # # config = { :Realm => 'DigestAuth example realm' } # # htdigest = WEBrick::HTTPAuth::Htdigest.new 'my_password_file' # htdigest.set_passwd config[:Realm], 'username', 'password' # htdigest.flush # # config[:UserDB] = htdigest # # digest_auth = WEBrick::HTTPAuth::DigestAuth.new config # # When using this as with a servlet be sure not to create a new DigestAuth # object in the servlet's #initialize. By default WEBrick creates a new # servlet instance for every request and the DigestAuth object must be # used across requests. class DigestAuth include Authenticator AuthScheme = "Digest" # :nodoc: ## # Struct containing the opaque portion of the digest authentication OpaqueInfo = Struct.new(:time, :nonce, :nc) # :nodoc: ## # Digest authentication algorithm attr_reader :algorithm ## # Quality of protection. RFC 2617 defines "auth" and "auth-int" attr_reader :qop ## # Used by UserDB to create a digest password entry def self.make_passwd(realm, user, pass) pass ||= "" Digest::MD5::hexdigest([user, realm, pass].join(":")) end ## # Creates a new DigestAuth instance. Be sure to use the same DigestAuth # instance for multiple requests as it saves state between requests in # order to perform authentication. # # See WEBrick::Config::DigestAuth for default configuration entries # # You must supply the following configuration entries: # # :Realm:: The name of the realm being protected. # :UserDB:: A database of usernames and passwords. # A WEBrick::HTTPAuth::Htdigest instance should be used. def initialize(config, default=Config::DigestAuth) check_init(config) @config = default.dup.update(config) @algorithm = @config[:Algorithm] @domain = @config[:Domain] @qop = @config[:Qop] @use_opaque = @config[:UseOpaque] @use_next_nonce = @config[:UseNextNonce] @check_nc = @config[:CheckNc] @use_auth_info_header = @config[:UseAuthenticationInfoHeader] @nonce_expire_period = @config[:NonceExpirePeriod] @nonce_expire_delta = @config[:NonceExpireDelta] @internet_explorer_hack = @config[:InternetExplorerHack] case @algorithm when 'MD5','MD5-sess' @h = Digest::MD5 when 'SHA1','SHA1-sess' # it is a bonus feature :-) @h = Digest::SHA1 else msg = format('Algorithm "%s" is not supported.', @algorithm) raise ArgumentError.new(msg) end @instance_key = hexdigest(self.__id__, Time.now.to_i, Process.pid) @opaques = {} @last_nonce_expire = Time.now @mutex = Mutex.new end ## # Authenticates a +req+ and returns a 401 Unauthorized using +res+ if # the authentication was not correct. def authenticate(req, res) unless result = @mutex.synchronize{ _authenticate(req, res) } challenge(req, res) end if result == :nonce_is_stale challenge(req, res, true) end return true end ## # Returns a challenge response which asks for for authentication # information def challenge(req, res, stale=false) nonce = generate_next_nonce(req) if @use_opaque opaque = generate_opaque(req) @opaques[opaque].nonce = nonce end param = Hash.new param["realm"] = HTTPUtils::quote(@realm) param["domain"] = HTTPUtils::quote(@domain.to_a.join(" ")) if @domain param["nonce"] = HTTPUtils::quote(nonce) param["opaque"] = HTTPUtils::quote(opaque) if opaque param["stale"] = stale.to_s param["algorithm"] = @algorithm param["qop"] = HTTPUtils::quote(@qop.to_a.join(",")) if @qop res[@response_field] = "#{@auth_scheme} " + param.map{|k,v| "#{k}=#{v}" }.join(", ") info("%s: %s", @response_field, res[@response_field]) if $DEBUG raise @auth_exception end private # :stopdoc: MustParams = ['username','realm','nonce','uri','response'] MustParamsAuth = ['cnonce','nc'] def _authenticate(req, res) unless digest_credentials = check_scheme(req) return false end auth_req = split_param_value(digest_credentials) if auth_req['qop'] == "auth" || auth_req['qop'] == "auth-int" req_params = MustParams + MustParamsAuth else req_params = MustParams end req_params.each{|key| unless auth_req.has_key?(key) error('%s: parameter missing. "%s"', auth_req['username'], key) raise HTTPStatus::BadRequest end } if !check_uri(req, auth_req) raise HTTPStatus::BadRequest end if auth_req['realm'] != @realm error('%s: realm unmatch. "%s" for "%s"', auth_req['username'], auth_req['realm'], @realm) return false end auth_req['algorithm'] ||= 'MD5' if auth_req['algorithm'].upcase != @algorithm.upcase error('%s: algorithm unmatch. "%s" for "%s"', auth_req['username'], auth_req['algorithm'], @algorithm) return false end if (@qop.nil? && auth_req.has_key?('qop')) || (@qop && (! @qop.member?(auth_req['qop']))) error('%s: the qop is not allowed. "%s"', auth_req['username'], auth_req['qop']) return false end password = @userdb.get_passwd(@realm, auth_req['username'], @reload_db) unless password error('%s: the user is not allowed.', auth_req['username']) return false end nonce_is_invalid = false if @use_opaque info("@opaque = %s", @opaque.inspect) if $DEBUG if !(opaque = auth_req['opaque']) error('%s: opaque is not given.', auth_req['username']) nonce_is_invalid = true elsif !(opaque_struct = @opaques[opaque]) error('%s: invalid opaque is given.', auth_req['username']) nonce_is_invalid = true elsif !check_opaque(opaque_struct, req, auth_req) @opaques.delete(auth_req['opaque']) nonce_is_invalid = true end elsif !check_nonce(req, auth_req) nonce_is_invalid = true end if /-sess$/i =~ auth_req['algorithm'] ha1 = hexdigest(password, auth_req['nonce'], auth_req['cnonce']) else ha1 = password end if auth_req['qop'] == "auth" || auth_req['qop'] == nil ha2 = hexdigest(req.request_method, auth_req['uri']) ha2_res = hexdigest("", auth_req['uri']) elsif auth_req['qop'] == "auth-int" body_digest = @h.new req.body { |chunk| body_digest.update(chunk) } body_digest = body_digest.hexdigest ha2 = hexdigest(req.request_method, auth_req['uri'], body_digest) ha2_res = hexdigest("", auth_req['uri'], body_digest) end if auth_req['qop'] == "auth" || auth_req['qop'] == "auth-int" param2 = ['nonce', 'nc', 'cnonce', 'qop'].map{|key| auth_req[key] }.join(':') digest = hexdigest(ha1, param2, ha2) digest_res = hexdigest(ha1, param2, ha2_res) else digest = hexdigest(ha1, auth_req['nonce'], ha2) digest_res = hexdigest(ha1, auth_req['nonce'], ha2_res) end if digest != auth_req['response'] error("%s: digest unmatch.", auth_req['username']) return false elsif nonce_is_invalid error('%s: digest is valid, but nonce is not valid.', auth_req['username']) return :nonce_is_stale elsif @use_auth_info_header auth_info = { 'nextnonce' => generate_next_nonce(req), 'rspauth' => digest_res } if @use_opaque opaque_struct.time = req.request_time opaque_struct.nonce = auth_info['nextnonce'] opaque_struct.nc = "%08x" % (auth_req['nc'].hex + 1) end if auth_req['qop'] == "auth" || auth_req['qop'] == "auth-int" ['qop','cnonce','nc'].each{|key| auth_info[key] = auth_req[key] } end res[@resp_info_field] = auth_info.keys.map{|key| if key == 'nc' key + '=' + auth_info[key] else key + "=" + HTTPUtils::quote(auth_info[key]) end }.join(', ') end info('%s: authentication succeeded.', auth_req['username']) req.user = auth_req['username'] return true end def split_param_value(string) ret = {} while string.bytesize != 0 case string when /^\s*([\w\-\.\*\%\!]+)=\s*\"((\\.|[^\"])*)\"\s*,?/ key = $1 matched = $2 string = $' ret[key] = matched.gsub(/\\(.)/, "\\1") when /^\s*([\w\-\.\*\%\!]+)=\s*([^,\"]*),?/ key = $1 matched = $2 string = $' ret[key] = matched.clone when /^s*^,/ string = $' else break end end ret end def generate_next_nonce(req) now = "%012d" % req.request_time.to_i pk = hexdigest(now, @instance_key)[0,32] nonce = [now + ":" + pk].pack("m*").chop # it has 60 length of chars. nonce end def check_nonce(req, auth_req) username = auth_req['username'] nonce = auth_req['nonce'] pub_time, pk = nonce.unpack("m*")[0].split(":", 2) if (!pub_time || !pk) error("%s: empty nonce is given", username) return false elsif (hexdigest(pub_time, @instance_key)[0,32] != pk) error("%s: invalid private-key: %s for %s", username, hexdigest(pub_time, @instance_key)[0,32], pk) return false end diff_time = req.request_time.to_i - pub_time.to_i if (diff_time < 0) error("%s: difference of time-stamp is negative.", username) return false elsif diff_time > @nonce_expire_period error("%s: nonce is expired.", username) return false end return true end def generate_opaque(req) @mutex.synchronize{ now = req.request_time if now - @last_nonce_expire > @nonce_expire_delta @opaques.delete_if{|key,val| (now - val.time) > @nonce_expire_period } @last_nonce_expire = now end begin opaque = Utils::random_string(16) end while @opaques[opaque] @opaques[opaque] = OpaqueInfo.new(now, nil, '00000001') opaque } end def check_opaque(opaque_struct, req, auth_req) if (@use_next_nonce && auth_req['nonce'] != opaque_struct.nonce) error('%s: nonce unmatched. "%s" for "%s"', auth_req['username'], auth_req['nonce'], opaque_struct.nonce) return false elsif !check_nonce(req, auth_req) return false end if (@check_nc && auth_req['nc'] != opaque_struct.nc) error('%s: nc unmatched."%s" for "%s"', auth_req['username'], auth_req['nc'], opaque_struct.nc) return false end true end def check_uri(req, auth_req) uri = auth_req['uri'] if uri != req.request_uri.to_s && uri != req.unparsed_uri && (@internet_explorer_hack && uri != req.path) error('%s: uri unmatch. "%s" for "%s"', auth_req['username'], auth_req['uri'], req.request_uri.to_s) return false end true end def hexdigest(*args) @h.hexdigest(args.join(":")) end # :startdoc: end ## # Digest authentication for proxy servers. See DigestAuth for details. class ProxyDigestAuth < DigestAuth include ProxyAuthenticator private def check_uri(req, auth_req) # :nodoc: return true end end end end PK!i## 2.2.0/webrick/httpauth/userdb.rbnu[#-- # httpauth/userdb.rb -- UserDB mix-in module. # # Author: IPR -- Internet Programming with Ruby -- writers # Copyright (c) 2003 Internet Programming with Ruby writers. All rights # reserved. # # $IPR: userdb.rb,v 1.2 2003/02/20 07:15:48 gotoyuzo Exp $ module WEBrick module HTTPAuth ## # User database mixin for HTTPAuth. This mixin dispatches user record # access to the underlying auth_type for this database. module UserDB ## # The authentication type. # # WEBrick::HTTPAuth::BasicAuth or WEBrick::HTTPAuth::DigestAuth are # built-in. attr_accessor :auth_type ## # Creates an obscured password in +realm+ with +user+ and +password+ # using the auth_type of this database. def make_passwd(realm, user, pass) @auth_type::make_passwd(realm, user, pass) end ## # Sets a password in +realm+ with +user+ and +password+ for the # auth_type of this database. def set_passwd(realm, user, pass) self[user] = pass end ## # Retrieves a password in +realm+ for +user+ for the auth_type of this # database. +reload_db+ is a dummy value. def get_passwd(realm, user, reload_db=false) make_passwd(realm, user, self[user]) end end end end PK!A2.2.0/webrick/httpstatus.rbnu[#-- # httpstatus.rb -- HTTPStatus Class # # Author: IPR -- Internet Programming with Ruby -- writers # Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou # Copyright (c) 2002 Internet Programming with Ruby writers. All rights # reserved. # # $IPR: httpstatus.rb,v 1.11 2003/03/24 20:18:55 gotoyuzo Exp $ require 'webrick/accesslog' module WEBrick ## # This module is used to manager HTTP status codes. # # See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html for more # information. module HTTPStatus ## # Root of the HTTP status class hierarchy class Status < StandardError class << self attr_reader :code, :reason_phrase # :nodoc: end # Returns the HTTP status code def code() self::class::code end # Returns the HTTP status description def reason_phrase() self::class::reason_phrase end alias to_i code # :nodoc: end # Root of the HTTP info statuses class Info < Status; end # Root of the HTTP success statuses class Success < Status; end # Root of the HTTP redirect statuses class Redirect < Status; end # Root of the HTTP error statuses class Error < Status; end # Root of the HTTP client error statuses class ClientError < Error; end # Root of the HTTP server error statuses class ServerError < Error; end class EOFError < StandardError; end # HTTP status codes and descriptions StatusMessage = { # :nodoc: 100 => 'Continue', 101 => 'Switching Protocols', 200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information', 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content', 207 => 'Multi-Status', 300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Found', 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 307 => 'Temporary Redirect', 400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', 403 => 'Forbidden', 404 => 'Not Found', 405 => 'Method Not Allowed', 406 => 'Not Acceptable', 407 => 'Proxy Authentication Required', 408 => 'Request Timeout', 409 => 'Conflict', 410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed', 413 => 'Request Entity Too Large', 414 => 'Request-URI Too Large', 415 => 'Unsupported Media Type', 416 => 'Request Range Not Satisfiable', 417 => 'Expectation Failed', 422 => 'Unprocessable Entity', 423 => 'Locked', 424 => 'Failed Dependency', 426 => 'Upgrade Required', 428 => 'Precondition Required', 429 => 'Too Many Requests', 431 => 'Request Header Fields Too Large', 500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable', 504 => 'Gateway Timeout', 505 => 'HTTP Version Not Supported', 507 => 'Insufficient Storage', 511 => 'Network Authentication Required', } # Maps a status code to the corresponding Status class CodeToError = {} # :nodoc: # Creates a status or error class for each status code and # populates the CodeToError map. StatusMessage.each{|code, message| message.freeze var_name = message.gsub(/[ \-]/,'_').upcase err_name = message.gsub(/[ \-]/,'') case code when 100...200; parent = Info when 200...300; parent = Success when 300...400; parent = Redirect when 400...500; parent = ClientError when 500...600; parent = ServerError end const_set("RC_#{var_name}", code) err_class = Class.new(parent) err_class.instance_variable_set(:@code, code) err_class.instance_variable_set(:@reason_phrase, message) const_set(err_name, err_class) CodeToError[code] = err_class } ## # Returns the description corresponding to the HTTP status +code+ # # WEBrick::HTTPStatus.reason_phrase 404 # => "Not Found" def reason_phrase(code) StatusMessage[code.to_i] end ## # Is +code+ an informational status? def info?(code) code.to_i >= 100 and code.to_i < 200 end ## # Is +code+ a successful status? def success?(code) code.to_i >= 200 and code.to_i < 300 end ## # Is +code+ a redirection status? def redirect?(code) code.to_i >= 300 and code.to_i < 400 end ## # Is +code+ an error status? def error?(code) code.to_i >= 400 and code.to_i < 600 end ## # Is +code+ a client error status? def client_error?(code) code.to_i >= 400 and code.to_i < 500 end ## # Is +code+ a server error status? def server_error?(code) code.to_i >= 500 and code.to_i < 600 end ## # Returns the status class corresponding to +code+ # # WEBrick::HTTPStatus[302] # => WEBrick::HTTPStatus::NotFound # def self.[](code) CodeToError[code] end module_function :reason_phrase module_function :info?, :success?, :redirect?, :error? module_function :client_error?, :server_error? end end PK!E O O 2.2.0/webrick/httpauth.rbnu[# # httpauth.rb -- HTTP access authentication # # Author: IPR -- Internet Programming with Ruby -- writers # Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou # Copyright (c) 2002 Internet Programming with Ruby writers. All rights # reserved. # # $IPR: httpauth.rb,v 1.14 2003/07/22 19:20:42 gotoyuzo Exp $ require 'webrick/httpauth/basicauth' require 'webrick/httpauth/digestauth' require 'webrick/httpauth/htpasswd' require 'webrick/httpauth/htdigest' require 'webrick/httpauth/htgroup' module WEBrick ## # HTTPAuth provides both basic and digest authentication. # # To enable authentication for requests in WEBrick you will need a user # database and an authenticator. To start, here's an Htpasswd database for # use with a DigestAuth authenticator: # # config = { :Realm => 'DigestAuth example realm' } # # htpasswd = WEBrick::HTTPAuth::Htpasswd.new 'my_password_file' # htpasswd.auth_type = WEBrick::HTTPAuth::DigestAuth # htpasswd.set_passwd config[:Realm], 'username', 'password' # htpasswd.flush # # The +:Realm+ is used to provide different access to different groups # across several resources on a server. Typically you'll need only one # realm for a server. # # This database can be used to create an authenticator: # # config[:UserDB] = htpasswd # # digest_auth = WEBrick::HTTPAuth::DigestAuth.new config # # To authenticate a request call #authenticate with a request and response # object in a servlet: # # def do_GET req, res # @authenticator.authenticate req, res # end # # For digest authentication the authenticator must not be created every # request, it must be passed in as an option via WEBrick::HTTPServer#mount. module HTTPAuth module_function def _basic_auth(req, res, realm, req_field, res_field, err_type, block) # :nodoc: user = pass = nil if /^Basic\s+(.*)/o =~ req[req_field] userpass = $1 user, pass = userpass.unpack("m*")[0].split(":", 2) end if block.call(user, pass) req.user = user return end res[res_field] = "Basic realm=\"#{realm}\"" raise err_type end ## # Simple wrapper for providing basic authentication for a request. When # called with a request +req+, response +res+, authentication +realm+ and # +block+ the block will be called with a +username+ and +password+. If # the block returns true the request is allowed to continue, otherwise an # HTTPStatus::Unauthorized error is raised. def basic_auth(req, res, realm, &block) # :yield: username, password _basic_auth(req, res, realm, "Authorization", "WWW-Authenticate", HTTPStatus::Unauthorized, block) end ## # Simple wrapper for providing basic authentication for a proxied request. # When called with a request +req+, response +res+, authentication +realm+ # and +block+ the block will be called with a +username+ and +password+. # If the block returns true the request is allowed to continue, otherwise # an HTTPStatus::ProxyAuthenticationRequired error is raised. def proxy_basic_auth(req, res, realm, &block) # :yield: username, password _basic_auth(req, res, realm, "Proxy-Authorization", "Proxy-Authenticate", HTTPStatus::ProxyAuthenticationRequired, block) end end end PK!6++2.2.0/rexml/cdata.rbnu[require "rexml/text" module REXML class CData < Text START = '' ILLEGAL = /(\]\]>)/ # Constructor. CData is data between # # _Examples_ # CData.new( source ) # CData.new( "Here is some CDATA" ) # CData.new( "Some unprocessed data", respect_whitespace_TF, parent_element ) def initialize( first, whitespace=true, parent=nil ) super( first, whitespace, parent, false, true, ILLEGAL ) end # Make a copy of this object # # _Examples_ # c = CData.new( "Some text" ) # d = c.clone # d.to_s # -> "Some text" def clone CData.new self end # Returns the content of this CData object # # _Examples_ # c = CData.new( "Some text" ) # c.to_s # -> "Some text" def to_s @string end def value @string end # == DEPRECATED # See the rexml/formatters package # # Generates XML output of this object # # output:: # Where to write the string. Defaults to $stdout # indent:: # The amount to indent this node by # transitive:: # Ignored # ie_hack:: # Ignored # # _Examples_ # c = CData.new( " Some text " ) # c.write( $stdout ) #-> def write( output=$stdout, indent=-1, transitive=false, ie_hack=false ) Kernel.warn( "#{self.class.name}.write is deprecated" ) indent( output, indent ) output << START output << @string output << STOP end end end PK!7g88 2.2.0/rexml/formatters/pretty.rbnu[require 'rexml/formatters/default' module REXML module Formatters # Pretty-prints an XML document. This destroys whitespace in text nodes # and will insert carriage returns and indentations. # # TODO: Add an option to print attributes on new lines class Pretty < Default # If compact is set to true, then the formatter will attempt to use as # little space as possible attr_accessor :compact # The width of a page. Used for formatting text attr_accessor :width # Create a new pretty printer. # # output:: # An object implementing '<<(String)', to which the output will be written. # indentation:: # An integer greater than 0. The indentation of each level will be # this number of spaces. If this is < 1, the behavior of this object # is undefined. Defaults to 2. # ie_hack:: # If true, the printer will insert whitespace before closing empty # tags, thereby allowing Internet Explorer's XML parser to # function. Defaults to false. def initialize( indentation=2, ie_hack=false ) @indentation = indentation @level = 0 @ie_hack = ie_hack @width = 80 @compact = false end protected def write_element(node, output) output << ' '*@level output << "<#{node.expanded_name}" node.attributes.each_attribute do |attr| output << " " attr.write( output ) end unless node.attributes.empty? if node.children.empty? if @ie_hack output << " " end output << "/" else output << ">" # If compact and all children are text, and if the formatted output # is less than the specified width, then try to print everything on # one line skip = false if compact if node.children.inject(true) {|s,c| s & c.kind_of?(Text)} string = "" old_level = @level @level = 0 node.children.each { |child| write( child, string ) } @level = old_level if string.length < @width output << string skip = true end end end unless skip output << "\n" @level += @indentation node.children.each { |child| next if child.kind_of?(Text) and child.to_s.strip.length == 0 write( child, output ) output << "\n" } @level -= @indentation output << ' '*@level end output << "" end def write_text( node, output ) s = node.to_s() s.gsub!(/\s/,' ') s.squeeze!(" ") s = wrap(s, @width - @level) s = indent_text(s, @level, " ", true) output << (' '*@level + s) end def write_comment( node, output) output << ' ' * @level super end def write_cdata( node, output) output << ' ' * @level super end def write_document( node, output ) # Ok, this is a bit odd. All XML documents have an XML declaration, # but it may not write itself if the user didn't specifically add it, # either through the API or in the input document. If it doesn't write # itself, then we don't need a carriage return... which makes this # logic more complex. node.children.each { |child| next if child == node.children[-1] and child.instance_of?(Text) unless child == node.children[0] or child.instance_of?(Text) or (child == node.children[1] and !node.children[0].writethis) output << "\n" end write( child, output ) } end private def indent_text(string, level=1, style="\t", indentfirstline=true) return string if level < 0 string.gsub(/\n/, "\n#{style*level}") end def wrap(string, width) parts = [] while string.length > width and place = string.rindex(' ', width) parts << string[0...place] string = string[place+1..-1] end parts << string parts.join("\n") end end end end PK!Ri%%$2.2.0/rexml/formatters/transitive.rbnu[require 'rexml/formatters/pretty' module REXML module Formatters # The Transitive formatter writes an XML document that parses to an # identical document as the source document. This means that no extra # whitespace nodes are inserted, and whitespace within text nodes is # preserved. Within these constraints, the document is pretty-printed, # with whitespace inserted into the metadata to introduce formatting. # # Note that this is only useful if the original XML is not already # formatted. Since this formatter does not alter whitespace nodes, the # results of formatting already formatted XML will be odd. class Transitive < Default def initialize( indentation=2, ie_hack=false ) @indentation = indentation @level = 0 @ie_hack = ie_hack end protected def write_element( node, output ) output << "<#{node.expanded_name}" node.attributes.each_attribute do |attr| output << " " attr.write( output ) end unless node.attributes.empty? output << "\n" output << ' '*@level if node.children.empty? output << " " if @ie_hack output << "/" else output << ">" # If compact and all children are text, and if the formatted output # is less than the specified width, then try to print everything on # one line @level += @indentation node.children.each { |child| write( child, output ) } @level -= @indentation output << "" end def write_text( node, output ) output << node.to_s() end end end end PK! ) ) !2.2.0/rexml/formatters/default.rbnu[module REXML module Formatters class Default # Prints out the XML document with no formatting -- except if id_hack is # set. # # ie_hack:: # If set to true, then inserts whitespace before the close of an empty # tag, so that IE's bad XML parser doesn't choke. def initialize( ie_hack=false ) @ie_hack = ie_hack end # Writes the node to some output. # # node:: # The node to write # output:: # A class implementing <<. Pass in an Output object to # change the output encoding. def write( node, output ) case node when Document if node.xml_decl.encoding != 'UTF-8' && !output.kind_of?(Output) output = Output.new( output, node.xml_decl.encoding ) end write_document( node, output ) when Element write_element( node, output ) when Declaration, ElementDecl, NotationDecl, ExternalEntity, Entity, Attribute, AttlistDecl node.write( output,-1 ) when Instruction write_instruction( node, output ) when DocType, XMLDecl node.write( output ) when Comment write_comment( node, output ) when CData write_cdata( node, output ) when Text write_text( node, output ) else raise Exception.new("XML FORMATTING ERROR") end end protected def write_document( node, output ) node.children.each { |child| write( child, output ) } end def write_element( node, output ) output << "<#{node.expanded_name}" node.attributes.to_a.map { |a| Hash === a ? a.values : a }.flatten.sort_by {|attr| attr.name}.each do |attr| output << " " attr.write( output ) end unless node.attributes.empty? if node.children.empty? output << " " if @ie_hack output << "/" else output << ">" node.children.each { |child| write( child, output ) } output << "" end def write_text( node, output ) output << node.to_s() end def write_comment( node, output ) output << Comment::START output << node.to_s output << Comment::STOP end def write_cdata( node, output ) output << CData::START output << node.to_s output << CData::STOP end def write_instruction( node, output ) output << Instruction::START.sub(/\\/u, '') output << node.target output << ' ' output << node.content output << Instruction::STOP.sub(/\\/u, '') end end end end PK!~V$V$2.2.0/rexml/quickpath.rbnu[require 'rexml/functions' require 'rexml/xmltokens' module REXML class QuickPath include Functions include XMLTokens # A base Hash object to be used when initializing a # default empty namespaces set. EMPTY_HASH = {} def QuickPath::first element, path, namespaces=EMPTY_HASH match(element, path, namespaces)[0] end def QuickPath::each element, path, namespaces=EMPTY_HASH, &block path = "*" unless path match(element, path, namespaces).each( &block ) end def QuickPath::match element, path, namespaces=EMPTY_HASH raise "nil is not a valid xpath" unless path results = nil Functions::namespace_context = namespaces case path when /^\/([^\/]|$)/u # match on root path = path[1..-1] return [element.root.parent] if path == '' results = filter([element.root], path) when /^[-\w]*::/u results = filter([element], path) when /^\*/u results = filter(element.to_a, path) when /^[\[!\w:]/u # match on child children = element.to_a results = filter(children, path) else results = filter([element], path) end return results end # Given an array of nodes it filters the array based on the path. The # result is that when this method returns, the array will contain elements # which match the path def QuickPath::filter elements, path return elements if path.nil? or path == '' or elements.size == 0 case path when /^\/\//u # Descendant return axe( elements, "descendant-or-self", $' ) when /^\/?\b(\w[-\w]*)\b::/u # Axe return axe( elements, $1, $' ) when /^\/(?=\b([:!\w][-\.\w]*:)?[-!\*\.\w]*\b([^:(]|$)|\*)/u # Child rest = $' results = [] elements.each do |element| results |= filter( element.to_a, rest ) end return results when /^\/?(\w[-\w]*)\(/u # / Function return function( elements, $1, $' ) when Namespace::NAMESPLIT # Element name name = $2 ns = $1 rest = $' elements.delete_if do |element| !(element.kind_of? Element and (element.expanded_name == name or (element.name == name and element.namespace == Functions.namespace_context[ns]))) end return filter( elements, rest ) when /^\/\[/u matches = [] elements.each do |element| matches |= predicate( element.to_a, path[1..-1] ) if element.kind_of? Element end return matches when /^\[/u # Predicate return predicate( elements, path ) when /^\/?\.\.\./u # Ancestor return axe( elements, "ancestor", $' ) when /^\/?\.\./u # Parent return filter( elements.collect{|e|e.parent}, $' ) when /^\/?\./u # Self return filter( elements, $' ) when /^\*/u # Any results = [] elements.each do |element| results |= filter( [element], $' ) if element.kind_of? Element #if element.kind_of? Element # children = element.to_a # children.delete_if { |child| !child.kind_of?(Element) } # results |= filter( children, $' ) #end end return results end return [] end def QuickPath::axe( elements, axe_name, rest ) matches = [] matches = filter( elements.dup, rest ) if axe_name =~ /-or-self$/u case axe_name when /^descendant/u elements.each do |element| matches |= filter( element.to_a, "descendant-or-self::#{rest}" ) if element.kind_of? Element end when /^ancestor/u elements.each do |element| while element.parent matches << element.parent element = element.parent end end matches = filter( matches, rest ) when "self" matches = filter( elements, rest ) when "child" elements.each do |element| matches |= filter( element.to_a, rest ) if element.kind_of? Element end when "attribute" elements.each do |element| matches << element.attributes[ rest ] if element.kind_of? Element end when "parent" matches = filter(elements.collect{|element| element.parent}.uniq, rest) when "following-sibling" matches = filter(elements.collect{|element| element.next_sibling}.uniq, rest) when "previous-sibling" matches = filter(elements.collect{|element| element.previous_sibling}.uniq, rest ) end return matches.uniq end OPERAND_ = '((?=(?:(?!and|or).)*[^\s<>=])[^\s<>=]+)' # A predicate filters a node-set with respect to an axis to produce a # new node-set. For each node in the node-set to be filtered, the # PredicateExpr is evaluated with that node as the context node, with # the number of nodes in the node-set as the context size, and with the # proximity position of the node in the node-set with respect to the # axis as the context position; if PredicateExpr evaluates to true for # that node, the node is included in the new node-set; otherwise, it is # not included. # # A PredicateExpr is evaluated by evaluating the Expr and converting # the result to a boolean. If the result is a number, the result will # be converted to true if the number is equal to the context position # and will be converted to false otherwise; if the result is not a # number, then the result will be converted as if by a call to the # boolean function. Thus a location path para[3] is equivalent to # para[position()=3]. def QuickPath::predicate( elements, path ) ind = 1 bcount = 1 while bcount > 0 bcount += 1 if path[ind] == ?[ bcount -= 1 if path[ind] == ?] ind += 1 end ind -= 1 predicate = path[1..ind-1] rest = path[ind+1..-1] # have to change 'a [=<>] b [=<>] c' into 'a [=<>] b and b [=<>] c' # predicate.gsub!( /#{OPERAND_}\s*([<>=])\s*#{OPERAND_}\s*([<>=])\s*#{OPERAND_}/u, '\1 \2 \3 and \3 \4 \5' ) # Let's do some Ruby trickery to avoid some work: predicate.gsub!( /&/u, "&&" ) predicate.gsub!( /=/u, "==" ) predicate.gsub!( /@(\w[-\w.]*)/u, 'attribute("\1")' ) predicate.gsub!( /\bmod\b/u, "%" ) predicate.gsub!( /\b(\w[-\w.]*\()/u ) { fname = $1 fname.gsub( /-/u, "_" ) } Functions.pair = [ 0, elements.size ] results = [] elements.each do |element| Functions.pair[0] += 1 Functions.node = element res = eval( predicate ) case res when true results << element when Fixnum results << element if Functions.pair[0] == res when String results << element end end return filter( results, rest ) end def QuickPath::attribute( name ) return Functions.node.attributes[name] if Functions.node.kind_of? Element end def QuickPath::name() return Functions.node.name if Functions.node.kind_of? Element end def QuickPath::method_missing( id, *args ) begin Functions.send( id.id2name, *args ) rescue Exception raise "METHOD: #{id.id2name}(#{args.join ', '})\n#{$!.message}" end end def QuickPath::function( elements, fname, rest ) args = parse_args( elements, rest ) Functions.pair = [0, elements.size] results = [] elements.each do |element| Functions.pair[0] += 1 Functions.node = element res = Functions.send( fname, *args ) case res when true results << element when Fixnum results << element if Functions.pair[0] == res end end return results end def QuickPath::parse_args( element, string ) # /.*?(?:\)|,)/ arguments = [] buffer = "" while string and string != "" c = string[0] string.sub!(/^./u, "") case c when ?, # if depth = 1, then we start a new argument arguments << evaluate( buffer ) #arguments << evaluate( string[0..count] ) when ?( # start a new method call function( element, buffer, string ) buffer = "" when ?) # close the method call and return arguments return arguments else buffer << c end end "" end end end PK!:662.2.0/rexml/text.rbnu[require 'rexml/security' require 'rexml/entity' require 'rexml/doctype' require 'rexml/child' require 'rexml/doctype' require 'rexml/parseexception' module REXML # Represents text nodes in an XML document class Text < Child include Comparable # The order in which the substitutions occur SPECIALS = [ /&(?!#?[\w-]+;)/u, //u, /"/u, /'/u, /\r/u ] SUBSTITUTES = ['&', '<', '>', '"', ''', ' '] # Characters which are substituted in written strings SLAICEPS = [ '<', '>', '"', "'", '&' ] SETUTITSBUS = [ /</u, />/u, /"/u, /'/u, /&/u ] # If +raw+ is true, then REXML leaves the value alone attr_accessor :raw NEEDS_A_SECOND_CHECK = /(<|&((#{Entity::NAME});|(#0*((?:\d+)|(?:x[a-fA-F0-9]+)));)?)/um NUMERICENTITY = /�*((?:\d+)|(?:x[a-fA-F0-9]+));/ VALID_CHAR = [ 0x9, 0xA, 0xD, (0x20..0xD7FF), (0xE000..0xFFFD), (0x10000..0x10FFFF) ] if String.method_defined? :encode VALID_XML_CHARS = Regexp.new('^['+ VALID_CHAR.map { |item| case item when Fixnum [item].pack('U').force_encoding('utf-8') when Range [item.first, '-'.ord, item.last].pack('UUU').force_encoding('utf-8') end }.join + ']*$') else VALID_XML_CHARS = /^( [\x09\x0A\x0D\x20-\x7E] # ASCII | [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs | [\xE1-\xEC\xEE][\x80-\xBF]{2} # straight 3-byte | \xEF[\x80-\xBE]{2} # | \xEF\xBF[\x80-\xBD] # excluding U+fffe and U+ffff | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3 | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15 | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16 )*$/nx; end # Constructor # +arg+ if a String, the content is set to the String. If a Text, # the object is shallowly cloned. # # +respect_whitespace+ (boolean, false) if true, whitespace is # respected # # +parent+ (nil) if this is a Parent object, the parent # will be set to this. # # +raw+ (nil) This argument can be given three values. # If true, then the value of used to construct this object is expected to # contain no unescaped XML markup, and REXML will not change the text. If # this value is false, the string may contain any characters, and REXML will # escape any and all defined entities whose values are contained in the # text. If this value is nil (the default), then the raw value of the # parent will be used as the raw value for this node. If there is no raw # value for the parent, and no value is supplied, the default is false. # Use this field if you have entities defined for some text, and you don't # want REXML to escape that text in output. # Text.new( "<&", false, nil, false ) #-> "<&" # Text.new( "<&", false, nil, false ) #-> "&lt;&amp;" # Text.new( "<&", false, nil, true ) #-> Parse exception # Text.new( "<&", false, nil, true ) #-> "<&" # # Assume that the entity "s" is defined to be "sean" # # and that the entity "r" is defined to be "russell" # Text.new( "sean russell" ) #-> "&s; &r;" # Text.new( "sean russell", false, nil, true ) #-> "sean russell" # # +entity_filter+ (nil) This can be an array of entities to match in the # supplied text. This argument is only useful if +raw+ is set to false. # Text.new( "sean russell", false, nil, false, ["s"] ) #-> "&s; russell" # Text.new( "sean russell", false, nil, true, ["s"] ) #-> "sean russell" # In the last example, the +entity_filter+ argument is ignored. # # +illegal+ INTERNAL USE ONLY def initialize(arg, respect_whitespace=false, parent=nil, raw=nil, entity_filter=nil, illegal=NEEDS_A_SECOND_CHECK ) @raw = false @parent = nil if parent super( parent ) @raw = parent.raw end @raw = raw unless raw.nil? @entity_filter = entity_filter clear_cache if arg.kind_of? String @string = arg.dup @string.squeeze!(" \n\t") unless respect_whitespace elsif arg.kind_of? Text @string = arg.to_s @raw = arg.raw elsif raise "Illegal argument of type #{arg.type} for Text constructor (#{arg})" end @string.gsub!( /\r\n?/, "\n" ) Text.check(@string, illegal, doctype) if @raw end def parent= parent super(parent) Text.check(@string, NEEDS_A_SECOND_CHECK, doctype) if @raw and @parent end # check for illegal characters def Text.check string, pattern, doctype # illegal anywhere if string !~ VALID_XML_CHARS if String.method_defined? :encode string.chars.each do |c| case c.ord when *VALID_CHAR else raise "Illegal character #{c.inspect} in raw string \"#{string}\"" end end else string.scan(/[\x00-\x7F]|[\x80-\xBF][\xC0-\xF0]*|[\xC0-\xF0]/n) do |c| case c.unpack('U') when *VALID_CHAR else raise "Illegal character #{c.inspect} in raw string \"#{string}\"" end end end end # context sensitive string.scan(pattern) do if $1[-1] != ?; raise "Illegal character '#{$1}' in raw string \"#{string}\"" elsif $1[0] == ?& if $5 and $5[0] == ?# case ($5[1] == ?x ? $5[2..-1].to_i(16) : $5[1..-1].to_i) when *VALID_CHAR else raise "Illegal character '#{$1}' in raw string \"#{string}\"" end # FIXME: below can't work but this needs API change. # elsif @parent and $3 and !SUBSTITUTES.include?($1) # if !doctype or !doctype.entities.has_key?($3) # raise "Undeclared entity '#{$1}' in raw string \"#{string}\"" # end end end end end def node_type :text end def empty? @string.size==0 end def clone return Text.new(self) end # Appends text to this text node. The text is appended in the +raw+ mode # of this text node. # # +returns+ the text itself to enable method chain like # 'text << "XXX" << "YYY"'. def <<( to_append ) @string << to_append.gsub( /\r\n?/, "\n" ) clear_cache self end # +other+ a String or a Text # +returns+ the result of (to_s <=> arg.to_s) def <=>( other ) to_s() <=> other.to_s end def doctype if @parent doc = @parent.document doc.doctype if doc end end REFERENCE = /#{Entity::REFERENCE}/ # Returns the string value of this text node. This string is always # escaped, meaning that it is a valid XML text node string, and all # entities that can be escaped, have been inserted. This method respects # the entity filter set in the constructor. # # # Assume that the entity "s" is defined to be "sean", and that the # # entity "r" is defined to be "russell" # t = Text.new( "< & sean russell", false, nil, false, ['s'] ) # t.to_s #-> "< & &s; russell" # t = Text.new( "< & &s; russell", false, nil, false ) # t.to_s #-> "< & &s; russell" # u = Text.new( "sean russell", false, nil, true ) # u.to_s #-> "sean russell" def to_s return @string if @raw return @normalized if @normalized @normalized = Text::normalize( @string, doctype, @entity_filter ) end def inspect @string.inspect end # Returns the string value of this text. This is the text without # entities, as it might be used programmatically, or printed to the # console. This ignores the 'raw' attribute setting, and any # entity_filter. # # # Assume that the entity "s" is defined to be "sean", and that the # # entity "r" is defined to be "russell" # t = Text.new( "< & sean russell", false, nil, false, ['s'] ) # t.value #-> "< & sean russell" # t = Text.new( "< & &s; russell", false, nil, false ) # t.value #-> "< & sean russell" # u = Text.new( "sean russell", false, nil, true ) # u.value #-> "sean russell" def value return @unnormalized if @unnormalized @unnormalized = Text::unnormalize( @string, doctype ) end # Sets the contents of this text node. This expects the text to be # unnormalized. It returns self. # # e = Element.new( "a" ) # e.add_text( "foo" ) # foo # e[0].value = "bar" # bar # e[0].value = "" # <a> def value=( val ) @string = val.gsub( /\r\n?/, "\n" ) clear_cache @raw = false end def wrap(string, width, addnewline=false) # Recursively wrap string at width. return string if string.length <= width place = string.rindex(' ', width) # Position in string with last ' ' before cutoff if addnewline then return "\n" + string[0,place] + "\n" + wrap(string[place+1..-1], width) else return string[0,place] + "\n" + wrap(string[place+1..-1], width) end end def indent_text(string, level=1, style="\t", indentfirstline=true) return string if level < 0 new_string = '' string.each_line { |line| indent_string = style * level new_line = (indent_string + line).sub(/[\s]+$/,'') new_string << new_line } new_string.strip! unless indentfirstline return new_string end # == DEPRECATED # See REXML::Formatters # def write( writer, indent=-1, transitive=false, ie_hack=false ) Kernel.warn("#{self.class.name}.write is deprecated. See REXML::Formatters") formatter = if indent > -1 REXML::Formatters::Pretty.new( indent ) else REXML::Formatters::Default.new end formatter.write( self, writer ) end # FIXME # This probably won't work properly def xpath path = @parent.xpath path += "/text()" return path end # Writes out text, substituting special characters beforehand. # +out+ A String, IO, or any other object supporting <<( String ) # +input+ the text to substitute and the write out # # z=utf8.unpack("U*") # ascOut="" # z.each{|r| # if r < 0x100 # ascOut.concat(r.chr) # else # ascOut.concat(sprintf("&#x%x;", r)) # end # } # puts ascOut def write_with_substitution out, input copy = input.clone # Doing it like this rather than in a loop improves the speed copy.gsub!( SPECIALS[0], SUBSTITUTES[0] ) copy.gsub!( SPECIALS[1], SUBSTITUTES[1] ) copy.gsub!( SPECIALS[2], SUBSTITUTES[2] ) copy.gsub!( SPECIALS[3], SUBSTITUTES[3] ) copy.gsub!( SPECIALS[4], SUBSTITUTES[4] ) copy.gsub!( SPECIALS[5], SUBSTITUTES[5] ) out << copy end private def clear_cache @normalized = nil @unnormalized = nil end # Reads text, substituting entities def Text::read_with_substitution( input, illegal=nil ) copy = input.clone if copy =~ illegal raise ParseException.new( "malformed text: Illegal character #$& in \"#{copy}\"" ) end if illegal copy.gsub!( /\r\n?/, "\n" ) if copy.include? ?& copy.gsub!( SETUTITSBUS[0], SLAICEPS[0] ) copy.gsub!( SETUTITSBUS[1], SLAICEPS[1] ) copy.gsub!( SETUTITSBUS[2], SLAICEPS[2] ) copy.gsub!( SETUTITSBUS[3], SLAICEPS[3] ) copy.gsub!( SETUTITSBUS[4], SLAICEPS[4] ) copy.gsub!( /�*((?:\d+)|(?:x[a-f0-9]+));/ ) { m=$1 #m='0' if m=='' m = "0#{m}" if m[0] == ?x [Integer(m)].pack('U*') } end copy end EREFERENCE = /&(?!#{Entity::NAME};)/ # Escapes all possible entities def Text::normalize( input, doctype=nil, entity_filter=nil ) copy = input.to_s # Doing it like this rather than in a loop improves the speed #copy = copy.gsub( EREFERENCE, '&' ) copy = copy.gsub( "&", "&" ) if doctype # Replace all ampersands that aren't part of an entity doctype.entities.each_value do |entity| copy = copy.gsub( entity.value, "&#{entity.name};" ) if entity.value and not( entity_filter and entity_filter.include?(entity.name) ) end else # Replace all ampersands that aren't part of an entity DocType::DEFAULT_ENTITIES.each_value do |entity| copy = copy.gsub(entity.value, "&#{entity.name};" ) end end copy end # Unescapes all possible entities def Text::unnormalize( string, doctype=nil, filter=nil, illegal=nil ) sum = 0 string.gsub( /\r\n?/, "\n" ).gsub( REFERENCE ) { s = Text.expand($&, doctype, filter) if sum + s.bytesize > Security.entity_expansion_text_limit raise "entity expansion has grown too large" else sum += s.bytesize end s } end def Text.expand(ref, doctype, filter) if ref[1] == ?# if ref[2] == ?x [ref[3...-1].to_i(16)].pack('U*') else [ref[2...-1].to_i].pack('U*') end elsif ref == '&' '&' elsif filter and filter.include?( ref[1...-1] ) ref elsif doctype doctype.entity( ref[1...-1] ) or ref else entity_value = DocType::DEFAULT_ENTITIES[ ref[1...-1] ] entity_value ? entity_value.value : ref end end end end PK! !2.2.0/rexml/parsers/treeparser.rbnu[require 'rexml/validation/validationexception' require 'rexml/undefinednamespaceexception' module REXML module Parsers class TreeParser def initialize( source, build_context = Document.new ) @build_context = build_context @parser = Parsers::BaseParser.new( source ) end def add_listener( listener ) @parser.add_listener( listener ) end def parse tag_stack = [] in_doctype = false entities = nil begin while true event = @parser.pull #STDERR.puts "TREEPARSER GOT #{event.inspect}" case event[0] when :end_document unless tag_stack.empty? raise ParseException.new("No close tag for #{@build_context.xpath}", @parser.source, @parser) end return when :start_element tag_stack.push(event[1]) el = @build_context = @build_context.add_element( event[1] ) event[2].each do |key, value| el.attributes[key]=Attribute.new(key,value,self) end when :end_element tag_stack.pop @build_context = @build_context.parent when :text if not in_doctype if @build_context[-1].instance_of? Text @build_context[-1] << event[1] else @build_context.add( Text.new(event[1], @build_context.whitespace, nil, true) ) unless ( @build_context.ignore_whitespace_nodes and event[1].strip.size==0 ) end end when :comment c = Comment.new( event[1] ) @build_context.add( c ) when :cdata c = CData.new( event[1] ) @build_context.add( c ) when :processing_instruction @build_context.add( Instruction.new( event[1], event[2] ) ) when :end_doctype in_doctype = false entities.each { |k,v| entities[k] = @build_context.entities[k].value } @build_context = @build_context.parent when :start_doctype doctype = DocType.new( event[1..-1], @build_context ) @build_context = doctype entities = {} in_doctype = true when :attlistdecl n = AttlistDecl.new( event[1..-1] ) @build_context.add( n ) when :externalentity n = ExternalEntity.new( event[1] ) @build_context.add( n ) when :elementdecl n = ElementDecl.new( event[1] ) @build_context.add(n) when :entitydecl entities[ event[1] ] = event[2] unless event[2] =~ /PUBLIC|SYSTEM/ @build_context.add(Entity.new(event)) when :notationdecl n = NotationDecl.new( *event[1..-1] ) @build_context.add( n ) when :xmldecl x = XMLDecl.new( event[1], event[2], event[3] ) @build_context.add( x ) end end rescue REXML::Validation::ValidationException raise rescue REXML::ParseException raise rescue raise ParseException.new( $!.message, @parser.source, @parser, $! ) end end end end end PK!P "2.2.0/rexml/parsers/lightparser.rbnu[require 'rexml/parsers/streamparser' require 'rexml/parsers/baseparser' require 'rexml/light/node' module REXML module Parsers class LightParser def initialize stream @stream = stream @parser = REXML::Parsers::BaseParser.new( stream ) end def add_listener( listener ) @parser.add_listener( listener ) end def rewind @stream.rewind @parser.stream = @stream end def parse root = context = [ :document ] while true event = @parser.pull case event[0] when :end_document break when :start_element, :start_doctype new_node = event context << new_node new_node[1,0] = [context] context = new_node when :end_element, :end_doctype context = context[1] else new_node = event context << new_node new_node[1,0] = [context] end end root end end # An element is an array. The array contains: # 0 The parent element # 1 The tag name # 2 A hash of attributes # 3..-1 The child elements # An element is an array of size > 3 # Text is a String # PIs are [ :processing_instruction, target, data ] # Comments are [ :comment, data ] # DocTypes are DocType structs # The root is an array with XMLDecls, Text, DocType, Array, Text end end PK!)|&$&$!2.2.0/rexml/parsers/sax2parser.rbnu[require 'rexml/parsers/baseparser' require 'rexml/parseexception' require 'rexml/namespace' require 'rexml/text' module REXML module Parsers # SAX2Parser class SAX2Parser def initialize source @parser = BaseParser.new(source) @listeners = [] @procs = [] @namespace_stack = [] @has_listeners = false @tag_stack = [] @entities = {} end def source @parser.source end def add_listener( listener ) @parser.add_listener( listener ) end # Listen arguments: # # Symbol, Array, Block # Listen to Symbol events on Array elements # Symbol, Block # Listen to Symbol events # Array, Listener # Listen to all events on Array elements # Array, Block # Listen to :start_element events on Array elements # Listener # Listen to All events # # Symbol can be one of: :start_element, :end_element, # :start_prefix_mapping, :end_prefix_mapping, :characters, # :processing_instruction, :doctype, :attlistdecl, :elementdecl, # :entitydecl, :notationdecl, :cdata, :xmldecl, :comment # # There is an additional symbol that can be listened for: :progress. # This will be called for every event generated, passing in the current # stream position. # # Array contains regular expressions or strings which will be matched # against fully qualified element names. # # Listener must implement the methods in SAX2Listener # # Block will be passed the same arguments as a SAX2Listener method would # be, where the method name is the same as the matched Symbol. # See the SAX2Listener for more information. def listen( *args, &blok ) if args[0].kind_of? Symbol if args.size == 2 args[1].each { |match| @procs << [args[0], match, blok] } else add( [args[0], nil, blok] ) end elsif args[0].kind_of? Array if args.size == 2 args[0].each { |match| add( [nil, match, args[1]] ) } else args[0].each { |match| add( [ :start_element, match, blok ] ) } end else add([nil, nil, args[0]]) end end def deafen( listener=nil, &blok ) if listener @listeners.delete_if {|item| item[-1] == listener } @has_listeners = false if @listeners.size == 0 else @procs.delete_if {|item| item[-1] == blok } end end def parse @procs.each { |sym,match,block| block.call if sym == :start_document } @listeners.each { |sym,match,block| block.start_document if sym == :start_document or sym.nil? } context = [] while true event = @parser.pull case event[0] when :end_document handle( :end_document ) break when :start_doctype handle( :doctype, *event[1..-1]) when :end_doctype context = context[1] when :start_element @tag_stack.push(event[1]) # find the observers for namespaces procs = get_procs( :start_prefix_mapping, event[1] ) listeners = get_listeners( :start_prefix_mapping, event[1] ) if procs or listeners # break out the namespace declarations # The attributes live in event[2] event[2].each {|n, v| event[2][n] = @parser.normalize(v)} nsdecl = event[2].find_all { |n, value| n =~ /^xmlns(:|$)/ } nsdecl.collect! { |n, value| [ n[6..-1], value ] } @namespace_stack.push({}) nsdecl.each do |n,v| @namespace_stack[-1][n] = v # notify observers of namespaces procs.each { |ob| ob.call( n, v ) } if procs listeners.each { |ob| ob.start_prefix_mapping(n, v) } if listeners end end event[1] =~ Namespace::NAMESPLIT prefix = $1 local = $2 uri = get_namespace(prefix) # find the observers for start_element procs = get_procs( :start_element, event[1] ) listeners = get_listeners( :start_element, event[1] ) # notify observers procs.each { |ob| ob.call( uri, local, event[1], event[2] ) } if procs listeners.each { |ob| ob.start_element( uri, local, event[1], event[2] ) } if listeners when :end_element @tag_stack.pop event[1] =~ Namespace::NAMESPLIT prefix = $1 local = $2 uri = get_namespace(prefix) # find the observers for start_element procs = get_procs( :end_element, event[1] ) listeners = get_listeners( :end_element, event[1] ) # notify observers procs.each { |ob| ob.call( uri, local, event[1] ) } if procs listeners.each { |ob| ob.end_element( uri, local, event[1] ) } if listeners namespace_mapping = @namespace_stack.pop # find the observers for namespaces procs = get_procs( :end_prefix_mapping, event[1] ) listeners = get_listeners( :end_prefix_mapping, event[1] ) if procs or listeners namespace_mapping.each do |ns_prefix, ns_uri| # notify observers of namespaces procs.each { |ob| ob.call( ns_prefix ) } if procs listeners.each { |ob| ob.end_prefix_mapping(ns_prefix) } if listeners end end when :text #normalized = @parser.normalize( event[1] ) #handle( :characters, normalized ) copy = event[1].clone esub = proc { |match| if @entities.has_key?($1) @entities[$1].gsub(Text::REFERENCE, &esub) else match end } copy.gsub!( Text::REFERENCE, &esub ) copy.gsub!( Text::NUMERICENTITY ) {|m| m=$1 m = "0#{m}" if m[0] == ?x [Integer(m)].pack('U*') } handle( :characters, copy ) when :entitydecl handle_entitydecl( event ) when :processing_instruction, :comment, :attlistdecl, :elementdecl, :cdata, :notationdecl, :xmldecl handle( *event ) end handle( :progress, @parser.position ) end end private def handle( symbol, *arguments ) tag = @tag_stack[-1] procs = get_procs( symbol, tag ) listeners = get_listeners( symbol, tag ) # notify observers procs.each { |ob| ob.call( *arguments ) } if procs listeners.each { |l| l.send( symbol.to_s, *arguments ) } if listeners end def handle_entitydecl( event ) @entities[ event[1] ] = event[2] if event.size == 3 parameter_reference_p = false case event[2] when "SYSTEM" if event.size == 5 if event.last == "%" parameter_reference_p = true else event[4, 0] = "NDATA" end end when "PUBLIC" if event.size == 6 if event.last == "%" parameter_reference_p = true else event[5, 0] = "NDATA" end end else parameter_reference_p = (event.size == 4) end event[1, 0] = event.pop if parameter_reference_p handle( event[0], event[1..-1] ) end # The following methods are duplicates, but it is faster than using # a helper def get_procs( symbol, name ) return nil if @procs.size == 0 @procs.find_all do |sym, match, block| ( (sym.nil? or symbol == sym) and ((name.nil? and match.nil?) or match.nil? or ( (name == match) or (match.kind_of? Regexp and name =~ match) ) ) ) end.collect{|x| x[-1]} end def get_listeners( symbol, name ) return nil if @listeners.size == 0 @listeners.find_all do |sym, match, block| ( (sym.nil? or symbol == sym) and ((name.nil? and match.nil?) or match.nil? or ( (name == match) or (match.kind_of? Regexp and name =~ match) ) ) ) end.collect{|x| x[-1]} end def add( pair ) if pair[-1].respond_to? :call @procs << pair unless @procs.include? pair else @listeners << pair unless @listeners.include? pair @has_listeners = true end end def get_namespace( prefix ) uris = (@namespace_stack.find_all { |ns| not ns[prefix].nil? }) || (@namespace_stack.find { |ns| not ns[nil].nil? }) uris[-1][prefix] unless uris.nil? or 0 == uris.size end end end end PK!:VVV!2.2.0/rexml/parsers/pullparser.rbnu[require 'forwardable' require 'rexml/parseexception' require 'rexml/parsers/baseparser' require 'rexml/xmltokens' module REXML module Parsers # = Using the Pull Parser # This API is experimental, and subject to change. # parser = PullParser.new( "texttxet" ) # while parser.has_next? # res = parser.next # puts res[1]['att'] if res.start_tag? and res[0] == 'b' # end # See the PullEvent class for information on the content of the results. # The data is identical to the arguments passed for the various events to # the StreamListener API. # # Notice that: # parser = PullParser.new( "BAD DOCUMENT" ) # while parser.has_next? # res = parser.next # raise res[1] if res.error? # end # # Nat Price gave me some good ideas for the API. class PullParser include XMLTokens extend Forwardable def_delegators( :@parser, :has_next? ) def_delegators( :@parser, :entity ) def_delegators( :@parser, :empty? ) def_delegators( :@parser, :source ) def initialize stream @entities = {} @listeners = nil @parser = BaseParser.new( stream ) @my_stack = [] end def add_listener( listener ) @listeners = [] unless @listeners @listeners << listener end def each while has_next? yield self.pull end end def peek depth=0 if @my_stack.length <= depth (depth - @my_stack.length + 1).times { e = PullEvent.new(@parser.pull) @my_stack.push(e) } end @my_stack[depth] end def pull return @my_stack.shift if @my_stack.length > 0 event = @parser.pull case event[0] when :entitydecl @entities[ event[1] ] = event[2] unless event[2] =~ /PUBLIC|SYSTEM/ when :text unnormalized = @parser.unnormalize( event[1], @entities ) event << unnormalized end PullEvent.new( event ) end def unshift token @my_stack.unshift token end end # A parsing event. The contents of the event are accessed as an +Array?, # and the type is given either by the ...? methods, or by accessing the # +type+ accessor. The contents of this object vary from event to event, # but are identical to the arguments passed to +StreamListener+s for each # event. class PullEvent # The type of this event. Will be one of :tag_start, :tag_end, :text, # :processing_instruction, :comment, :doctype, :attlistdecl, :entitydecl, # :notationdecl, :entity, :cdata, :xmldecl, or :error. def initialize(arg) @contents = arg end def []( start, endd=nil) if start.kind_of? Range @contents.slice( start.begin+1 .. start.end ) elsif start.kind_of? Numeric if endd.nil? @contents.slice( start+1 ) else @contents.slice( start+1, endd ) end else raise "Illegal argument #{start.inspect} (#{start.class})" end end def event_type @contents[0] end # Content: [ String tag_name, Hash attributes ] def start_element? @contents[0] == :start_element end # Content: [ String tag_name ] def end_element? @contents[0] == :end_element end # Content: [ String raw_text, String unnormalized_text ] def text? @contents[0] == :text end # Content: [ String text ] def instruction? @contents[0] == :processing_instruction end # Content: [ String text ] def comment? @contents[0] == :comment end # Content: [ String name, String pub_sys, String long_name, String uri ] def doctype? @contents[0] == :start_doctype end # Content: [ String text ] def attlistdecl? @contents[0] == :attlistdecl end # Content: [ String text ] def elementdecl? @contents[0] == :elementdecl end # Due to the wonders of DTDs, an entity declaration can be just about # anything. There's no way to normalize it; you'll have to interpret the # content yourself. However, the following is true: # # * If the entity declaration is an internal entity: # [ String name, String value ] # Content: [ String text ] def entitydecl? @contents[0] == :entitydecl end # Content: [ String text ] def notationdecl? @contents[0] == :notationdecl end # Content: [ String text ] def entity? @contents[0] == :entity end # Content: [ String text ] def cdata? @contents[0] == :cdata end # Content: [ String version, String encoding, String standalone ] def xmldecl? @contents[0] == :xmldecl end def error? @contents[0] == :error end def inspect @contents[0].to_s + ": " + @contents[1..-1].inspect end end end end PK!C9SS#2.2.0/rexml/parsers/streamparser.rbnu[require "rexml/parsers/baseparser" module REXML module Parsers class StreamParser def initialize source, listener @listener = listener @parser = BaseParser.new( source ) end def add_listener( listener ) @parser.add_listener( listener ) end def parse # entity string while true event = @parser.pull case event[0] when :end_document return when :start_element attrs = event[2].each do |n, v| event[2][n] = @parser.unnormalize( v ) end @listener.tag_start( event[1], attrs ) when :end_element @listener.tag_end( event[1] ) when :text normalized = @parser.unnormalize( event[1] ) @listener.text( normalized ) when :processing_instruction @listener.instruction( *event[1,2] ) when :start_doctype @listener.doctype( *event[1..-1] ) when :end_doctype # FIXME: remove this condition for milestone:3.2 @listener.doctype_end if @listener.respond_to? :doctype_end when :comment, :attlistdecl, :cdata, :xmldecl, :elementdecl @listener.send( event[0].to_s, *event[1..-1] ) when :entitydecl, :notationdecl @listener.send( event[0].to_s, event[1..-1] ) when :externalentity entity_reference = event[1] content = entity_reference.gsub(/\A%|;\z/, "") @listener.entity(content) end end end end end end PK!@bGG"2.2.0/rexml/parsers/xpathparser.rbnu[require 'rexml/namespace' require 'rexml/xmltokens' module REXML module Parsers # You don't want to use this class. Really. Use XPath, which is a wrapper # for this class. Believe me. You don't want to poke around in here. # There is strange, dark magic at work in this code. Beware. Go back! Go # back while you still can! class XPathParser include XMLTokens LITERAL = /^'([^']*)'|^"([^"]*)"/u def namespaces=( namespaces ) Functions::namespace_context = namespaces @namespaces = namespaces end def parse path path = path.dup path.gsub!(/([\(\[])\s+/, '\1') # Strip ignorable spaces path.gsub!( /\s+([\]\)])/, '\1') parsed = [] OrExpr(path, parsed) parsed end def predicate path parsed = [] Predicate( "[#{path}]", parsed ) parsed end def abbreviate( path ) path = path.kind_of?(String) ? parse( path ) : path string = "" document = false while path.size > 0 op = path.shift case op when :node when :attribute string << "/" if string.size > 0 string << "@" when :child string << "/" if string.size > 0 when :descendant_or_self string << "/" when :self string << "." when :parent string << ".." when :any string << "*" when :text string << "text()" when :following, :following_sibling, :ancestor, :ancestor_or_self, :descendant, :namespace, :preceding, :preceding_sibling string << "/" unless string.size == 0 string << op.to_s.tr("_", "-") string << "::" when :qname prefix = path.shift name = path.shift string << prefix+":" if prefix.size > 0 string << name when :predicate string << '[' string << predicate_to_string( path.shift ) {|x| abbreviate( x ) } string << ']' when :document document = true when :function string << path.shift string << "( " string << predicate_to_string( path.shift[0] ) {|x| abbreviate( x )} string << " )" when :literal string << %Q{ "#{path.shift}" } else string << "/" unless string.size == 0 string << "UNKNOWN(" string << op.inspect string << ")" end end string = "/"+string if document return string end def expand( path ) path = path.kind_of?(String) ? parse( path ) : path string = "" document = false while path.size > 0 op = path.shift case op when :node string << "node()" when :attribute, :child, :following, :following_sibling, :ancestor, :ancestor_or_self, :descendant, :descendant_or_self, :namespace, :preceding, :preceding_sibling, :self, :parent string << "/" unless string.size == 0 string << op.to_s.tr("_", "-") string << "::" when :any string << "*" when :qname prefix = path.shift name = path.shift string << prefix+":" if prefix.size > 0 string << name when :predicate string << '[' string << predicate_to_string( path.shift ) { |x| expand(x) } string << ']' when :document document = true else string << "/" unless string.size == 0 string << "UNKNOWN(" string << op.inspect string << ")" end end string = "/"+string if document return string end def predicate_to_string( path, &block ) string = "" case path[0] when :and, :or, :mult, :plus, :minus, :neq, :eq, :lt, :gt, :lteq, :gteq, :div, :mod, :union op = path.shift case op when :eq op = "=" when :lt op = "<" when :gt op = ">" when :lteq op = "<=" when :gteq op = ">=" when :neq op = "!=" when :union op = "|" end left = predicate_to_string( path.shift, &block ) right = predicate_to_string( path.shift, &block ) string << " " string << left string << " " string << op.to_s string << " " string << right string << " " when :function path.shift name = path.shift string << name string << "( " string << predicate_to_string( path.shift, &block ) string << " )" when :literal path.shift string << " " string << path.shift.inspect string << " " else string << " " string << yield( path ) string << " " end return string.squeeze(" ") end private #LocationPath # | RelativeLocationPath # | '/' RelativeLocationPath? # | '//' RelativeLocationPath def LocationPath path, parsed path = path.strip if path[0] == ?/ parsed << :document if path[1] == ?/ parsed << :descendant_or_self parsed << :node path = path[2..-1] else path = path[1..-1] end end return RelativeLocationPath( path, parsed ) if path.size > 0 end #RelativeLocationPath # | Step # | (AXIS_NAME '::' | '@' | '') AxisSpecifier # NodeTest # Predicate # | '.' | '..' AbbreviatedStep # | RelativeLocationPath '/' Step # | RelativeLocationPath '//' Step AXIS = /^(ancestor|ancestor-or-self|attribute|child|descendant|descendant-or-self|following|following-sibling|namespace|parent|preceding|preceding-sibling|self)::/ def RelativeLocationPath path, parsed while path.size > 0 # (axis or @ or ) nodetest predicate > # OR > / Step # (. or ..) > if path[0] == ?. if path[1] == ?. parsed << :parent parsed << :node path = path[2..-1] else parsed << :self parsed << :node path = path[1..-1] end else if path[0] == ?@ parsed << :attribute path = path[1..-1] # Goto Nodetest elsif path =~ AXIS parsed << $1.tr('-','_').intern path = $' # Goto Nodetest else parsed << :child end n = [] path = NodeTest( path, n) if path[0] == ?[ path = Predicate( path, n ) end parsed.concat(n) end if path.size > 0 if path[0] == ?/ if path[1] == ?/ parsed << :descendant_or_self parsed << :node path = path[2..-1] else path = path[1..-1] end else return path end end end return path end # Returns a 1-1 map of the nodeset # The contents of the resulting array are either: # true/false, if a positive match # String, if a name match #NodeTest # | ('*' | NCNAME ':' '*' | QNAME) NameTest # | NODE_TYPE '(' ')' NodeType # | PI '(' LITERAL ')' PI # | '[' expr ']' Predicate NCNAMETEST= /^(#{NCNAME_STR}):\*/u QNAME = Namespace::NAMESPLIT NODE_TYPE = /^(comment|text|node)\(\s*\)/m PI = /^processing-instruction\(/ def NodeTest path, parsed case path when /^\*/ path = $' parsed << :any when NODE_TYPE type = $1 path = $' parsed << type.tr('-', '_').intern when PI path = $' literal = nil if path !~ /^\s*\)/ path =~ LITERAL literal = $1 path = $' raise ParseException.new("Missing ')' after processing instruction") if path[0] != ?) path = path[1..-1] end parsed << :processing_instruction parsed << (literal || '') when NCNAMETEST prefix = $1 path = $' parsed << :namespace parsed << prefix when QNAME prefix = $1 name = $2 path = $' prefix = "" unless prefix parsed << :qname parsed << prefix parsed << name end return path end # Filters the supplied nodeset on the predicate(s) def Predicate path, parsed return nil unless path[0] == ?[ predicates = [] while path[0] == ?[ path, expr = get_group(path) predicates << expr[1..-2] if expr end predicates.each{ |pred| preds = [] parsed << :predicate parsed << preds OrExpr(pred, preds) } path end # The following return arrays of true/false, a 1-1 mapping of the # supplied nodeset, except for axe(), which returns a filtered # nodeset #| OrExpr S 'or' S AndExpr #| AndExpr def OrExpr path, parsed n = [] rest = AndExpr( path, n ) if rest != path while rest =~ /^\s*( or )/ n = [ :or, n, [] ] rest = AndExpr( $', n[-1] ) end end if parsed.size == 0 and n.size != 0 parsed.replace(n) elsif n.size > 0 parsed << n end rest end #| AndExpr S 'and' S EqualityExpr #| EqualityExpr def AndExpr path, parsed n = [] rest = EqualityExpr( path, n ) if rest != path while rest =~ /^\s*( and )/ n = [ :and, n, [] ] rest = EqualityExpr( $', n[-1] ) end end if parsed.size == 0 and n.size != 0 parsed.replace(n) elsif n.size > 0 parsed << n end rest end #| EqualityExpr ('=' | '!=') RelationalExpr #| RelationalExpr def EqualityExpr path, parsed n = [] rest = RelationalExpr( path, n ) if rest != path while rest =~ /^\s*(!?=)\s*/ if $1[0] == ?! n = [ :neq, n, [] ] else n = [ :eq, n, [] ] end rest = RelationalExpr( $', n[-1] ) end end if parsed.size == 0 and n.size != 0 parsed.replace(n) elsif n.size > 0 parsed << n end rest end #| RelationalExpr ('<' | '>' | '<=' | '>=') AdditiveExpr #| AdditiveExpr def RelationalExpr path, parsed n = [] rest = AdditiveExpr( path, n ) if rest != path while rest =~ /^\s*([<>]=?)\s*/ if $1[0] == ?< sym = "lt" else sym = "gt" end sym << "eq" if $1[-1] == ?= n = [ sym.intern, n, [] ] rest = AdditiveExpr( $', n[-1] ) end end if parsed.size == 0 and n.size != 0 parsed.replace(n) elsif n.size > 0 parsed << n end rest end #| AdditiveExpr ('+' | S '-') MultiplicativeExpr #| MultiplicativeExpr def AdditiveExpr path, parsed n = [] rest = MultiplicativeExpr( path, n ) if rest != path while rest =~ /^\s*(\+| -)\s*/ if $1[0] == ?+ n = [ :plus, n, [] ] else n = [ :minus, n, [] ] end rest = MultiplicativeExpr( $', n[-1] ) end end if parsed.size == 0 and n.size != 0 parsed.replace(n) elsif n.size > 0 parsed << n end rest end #| MultiplicativeExpr ('*' | S ('div' | 'mod') S) UnaryExpr #| UnaryExpr def MultiplicativeExpr path, parsed n = [] rest = UnaryExpr( path, n ) if rest != path while rest =~ /^\s*(\*| div | mod )\s*/ if $1[0] == ?* n = [ :mult, n, [] ] elsif $1.include?( "div" ) n = [ :div, n, [] ] else n = [ :mod, n, [] ] end rest = UnaryExpr( $', n[-1] ) end end if parsed.size == 0 and n.size != 0 parsed.replace(n) elsif n.size > 0 parsed << n end rest end #| '-' UnaryExpr #| UnionExpr def UnaryExpr path, parsed path =~ /^(\-*)/ path = $' if $1 and (($1.size % 2) != 0) mult = -1 else mult = 1 end parsed << :neg if mult < 0 n = [] path = UnionExpr( path, n ) parsed.concat( n ) path end #| UnionExpr '|' PathExpr #| PathExpr def UnionExpr path, parsed n = [] rest = PathExpr( path, n ) if rest != path while rest =~ /^\s*(\|)\s*/ n = [ :union, n, [] ] rest = PathExpr( $', n[-1] ) end end if parsed.size == 0 and n.size != 0 parsed.replace( n ) elsif n.size > 0 parsed << n end rest end #| LocationPath #| FilterExpr ('/' | '//') RelativeLocationPath def PathExpr path, parsed path =~ /^\s*/ path = $' n = [] rest = FilterExpr( path, n ) if rest != path if rest and rest[0] == ?/ return RelativeLocationPath(rest, n) end end rest = LocationPath(rest, n) if rest =~ /\A[\/\.\@\[\w*]/ parsed.concat(n) return rest end #| FilterExpr Predicate #| PrimaryExpr def FilterExpr path, parsed n = [] path = PrimaryExpr( path, n ) path = Predicate(path, n) if path and path[0] == ?[ parsed.concat(n) path end #| VARIABLE_REFERENCE #| '(' expr ')' #| LITERAL #| NUMBER #| FunctionCall VARIABLE_REFERENCE = /^\$(#{NAME_STR})/u NUMBER = /^(\d*\.?\d+)/ NT = /^comment|text|processing-instruction|node$/ def PrimaryExpr path, parsed case path when VARIABLE_REFERENCE varname = $1 path = $' parsed << :variable parsed << varname #arry << @variables[ varname ] when /^(\w[-\w]*)(?:\()/ fname = $1 tmp = $' return path if fname =~ NT path = tmp parsed << :function parsed << fname path = FunctionCall(path, parsed) when NUMBER varname = $1.nil? ? $2 : $1 path = $' parsed << :literal parsed << (varname.include?('.') ? varname.to_f : varname.to_i) when LITERAL varname = $1.nil? ? $2 : $1 path = $' parsed << :literal parsed << varname when /^\(/ #/ path, contents = get_group(path) contents = contents[1..-2] n = [] OrExpr( contents, n ) parsed.concat(n) end path end #| FUNCTION_NAME '(' ( expr ( ',' expr )* )? ')' def FunctionCall rest, parsed path, arguments = parse_args(rest) argset = [] for argument in arguments args = [] OrExpr( argument, args ) argset << args end parsed << argset path end # get_group( '[foo]bar' ) -> ['bar', '[foo]'] def get_group string ind = 0 depth = 0 st = string[0,1] en = (st == "(" ? ")" : "]") begin case string[ind,1] when st depth += 1 when en depth -= 1 end ind += 1 end while depth > 0 and ind < string.length return nil unless depth==0 [string[ind..-1], string[0..ind-1]] end def parse_args( string ) arguments = [] ind = 0 inquot = false inapos = false depth = 1 begin case string[ind] when ?" inquot = !inquot unless inapos when ?' inapos = !inapos unless inquot else unless inquot or inapos case string[ind] when ?( depth += 1 if depth == 1 string = string[1..-1] ind -= 1 end when ?) depth -= 1 if depth == 0 s = string[0,ind].strip arguments << s unless s == "" string = string[ind+1..-1] end when ?, if depth == 1 s = string[0,ind].strip arguments << s unless s == "" string = string[ind+1..-1] ind = -1 end end end end ind += 1 end while depth > 0 and ind < string.length return nil unless depth==0 [string,arguments] end end end end PK!0=U'2.2.0/rexml/parsers/ultralightparser.rbnu[require 'rexml/parsers/streamparser' require 'rexml/parsers/baseparser' module REXML module Parsers class UltraLightParser def initialize stream @stream = stream @parser = REXML::Parsers::BaseParser.new( stream ) end def add_listener( listener ) @parser.add_listener( listener ) end def rewind @stream.rewind @parser.stream = @stream end def parse root = context = [] while true event = @parser.pull case event[0] when :end_document break when :end_doctype context = context[1] when :start_element, :start_doctype context << event event[1,0] = [context] context = event when :end_element context = context[1] else context << event end end root end end # An element is an array. The array contains: # 0 The parent element # 1 The tag name # 2 A hash of attributes # 3..-1 The child elements # An element is an array of size > 3 # Text is a String # PIs are [ :processing_instruction, target, data ] # Comments are [ :comment, data ] # DocTypes are DocType structs # The root is an array with XMLDecls, Text, DocType, Array, Text end end PK!)NN!2.2.0/rexml/parsers/baseparser.rbnu[require 'rexml/parseexception' require 'rexml/undefinednamespaceexception' require 'rexml/source' require 'set' module REXML module Parsers # = Using the Pull Parser # This API is experimental, and subject to change. # parser = PullParser.new( "texttxet" ) # while parser.has_next? # res = parser.next # puts res[1]['att'] if res.start_tag? and res[0] == 'b' # end # See the PullEvent class for information on the content of the results. # The data is identical to the arguments passed for the various events to # the StreamListener API. # # Notice that: # parser = PullParser.new( "BAD DOCUMENT" ) # while parser.has_next? # res = parser.next # raise res[1] if res.error? # end # # Nat Price gave me some good ideas for the API. class BaseParser LETTER = '[:alpha:]' DIGIT = '[:digit:]' COMBININGCHAR = '' # TODO EXTENDER = '' # TODO NCNAME_STR= "[#{LETTER}_:][-[:alnum:]._:#{COMBININGCHAR}#{EXTENDER}]*" NAME_STR= "(?:(#{NCNAME_STR}):)?(#{NCNAME_STR})" UNAME_STR= "(?:#{NCNAME_STR}:)?#{NCNAME_STR}" NAMECHAR = '[\-\w\.:]' NAME = "([\\w:]#{NAMECHAR}*)" NMTOKEN = "(?:#{NAMECHAR})+" NMTOKENS = "#{NMTOKEN}(\\s+#{NMTOKEN})*" REFERENCE = "&(?:#{NAME};|#\\d+;|#x[0-9a-fA-F]+;)" REFERENCE_RE = /#{REFERENCE}/ DOCTYPE_START = /\A\s*/um DOCTYPE_PATTERN = /\s*)/um ATTRIBUTE_PATTERN = /\s*(#{NAME_STR})\s*=\s*(["'])(.*?)\4/um COMMENT_START = /\A/um CDATA_START = /\A/um CDATA_PATTERN = //um XMLDECL_START = /\A<\?xml\s/u; XMLDECL_PATTERN = /<\?xml\s+(.*?)\?>/um INSTRUCTION_START = /\A<\?/u INSTRUCTION_PATTERN = /<\?(.*?)(\s+.*?)?\?>/um TAG_MATCH = /^<((?>#{NAME_STR}))\s*((?>\s+#{UNAME_STR}\s*=\s*(["']).*?\5)*)\s*(\/)?>/um CLOSE_MATCH = /^\s*<\/(#{NAME_STR})\s*>/um VERSION = /\bversion\s*=\s*["'](.*?)['"]/um ENCODING = /\bencoding\s*=\s*["'](.*?)['"]/um STANDALONE = /\bstandalone\s*=\s*["'](.*?)['"]/um ENTITY_START = /\A\s*/um SYSTEMENTITY = /\A\s*(%.*?;)\s*$/um ENUMERATION = "\\(\\s*#{NMTOKEN}(?:\\s*\\|\\s*#{NMTOKEN})*\\s*\\)" NOTATIONTYPE = "NOTATION\\s+\\(\\s*#{NAME}(?:\\s*\\|\\s*#{NAME})*\\s*\\)" ENUMERATEDTYPE = "(?:(?:#{NOTATIONTYPE})|(?:#{ENUMERATION}))" ATTTYPE = "(CDATA|ID|IDREF|IDREFS|ENTITY|ENTITIES|NMTOKEN|NMTOKENS|#{ENUMERATEDTYPE})" ATTVALUE = "(?:\"((?:[^<&\"]|#{REFERENCE})*)\")|(?:'((?:[^<&']|#{REFERENCE})*)')" DEFAULTDECL = "(#REQUIRED|#IMPLIED|(?:(#FIXED\\s+)?#{ATTVALUE}))" ATTDEF = "\\s+#{NAME}\\s+#{ATTTYPE}\\s+#{DEFAULTDECL}" ATTDEF_RE = /#{ATTDEF}/ ATTLISTDECL_START = /\A\s*/um NOTATIONDECL_START = /\A\s*/um SYSTEM = /\A\s*/um TEXT_PATTERN = /\A([^<]*)/um # Entity constants PUBIDCHAR = "\x20\x0D\x0Aa-zA-Z0-9\\-()+,./:=?;!*@$_%#" SYSTEMLITERAL = %Q{((?:"[^"]*")|(?:'[^']*'))} PUBIDLITERAL = %Q{("[#{PUBIDCHAR}']*"|'[#{PUBIDCHAR}]*')} EXTERNALID = "(?:(?:(SYSTEM)\\s+#{SYSTEMLITERAL})|(?:(PUBLIC)\\s+#{PUBIDLITERAL}\\s+#{SYSTEMLITERAL}))" NDATADECL = "\\s+NDATA\\s+#{NAME}" PEREFERENCE = "%#{NAME};" ENTITYVALUE = %Q{((?:"(?:[^%&"]|#{PEREFERENCE}|#{REFERENCE})*")|(?:'([^%&']|#{PEREFERENCE}|#{REFERENCE})*'))} PEDEF = "(?:#{ENTITYVALUE}|#{EXTERNALID})" ENTITYDEF = "(?:#{ENTITYVALUE}|(?:#{EXTERNALID}(#{NDATADECL})?))" PEDECL = "" GEDECL = "" ENTITYDECL = /\s*(?:#{GEDECL})|(?:#{PEDECL})/um EREFERENCE = /&(?!#{NAME};)/ DEFAULT_ENTITIES = { 'gt' => [/>/, '>', '>', />/], 'lt' => [/</, '<', '<', / [/"/, '"', '"', /"/], "apos" => [/'/, "'", "'", /'/] } ###################################################################### # These are patterns to identify common markup errors, to make the # error messages more informative. ###################################################################### MISSING_ATTRIBUTE_QUOTES = /^<#{NAME_STR}\s+#{NAME_STR}\s*=\s*[^"']/um def initialize( source ) self.stream = source @listeners = [] end def add_listener( listener ) @listeners << listener end attr_reader :source def stream=( source ) @source = SourceFactory.create_from( source ) @closed = nil @document_status = nil @tags = [] @stack = [] @entities = [] @nsstack = [] end def position if @source.respond_to? :position @source.position else # FIXME 0 end end # Returns true if there are no more events def empty? return (@source.empty? and @stack.empty?) end # Returns true if there are more events. Synonymous with !empty? def has_next? return !(@source.empty? and @stack.empty?) end # Push an event back on the head of the stream. This method # has (theoretically) infinite depth. def unshift token @stack.unshift(token) end # Peek at the +depth+ event in the stack. The first element on the stack # is at depth 0. If +depth+ is -1, will parse to the end of the input # stream and return the last event, which is always :end_document. # Be aware that this causes the stream to be parsed up to the +depth+ # event, so you can effectively pre-parse the entire document (pull the # entire thing into memory) using this method. def peek depth=0 raise %Q[Illegal argument "#{depth}"] if depth < -1 temp = [] if depth == -1 temp.push(pull()) until empty? else while @stack.size+temp.size < depth+1 temp.push(pull()) end end @stack += temp if temp.size > 0 @stack[depth] end # Returns the next event. This is a +PullEvent+ object. def pull pull_event.tap do |event| @listeners.each do |listener| listener.receive event end end end def pull_event if @closed x, @closed = @closed, nil return [ :end_element, x ] end return [ :end_document ] if empty? return @stack.shift if @stack.size > 0 #STDERR.puts @source.encoding @source.read if @source.buffer.size<2 #STDERR.puts "BUFFER = #{@source.buffer.inspect}" if @document_status == nil #@source.consume( /^\s*/um ) word = @source.match( /^((?:\s+)|(?:<[^>]*>))/um ) word = word[1] unless word.nil? #STDERR.puts "WORD = #{word.inspect}" case word when COMMENT_START return [ :comment, @source.match( COMMENT_PATTERN, true )[1] ] when XMLDECL_START #STDERR.puts "XMLDECL" results = @source.match( XMLDECL_PATTERN, true )[1] version = VERSION.match( results ) version = version[1] unless version.nil? encoding = ENCODING.match(results) encoding = encoding[1] unless encoding.nil? if need_source_encoding_update?(encoding) @source.encoding = encoding end if encoding.nil? and /\AUTF-16(?:BE|LE)\z/i =~ @source.encoding encoding = "UTF-16" end standalone = STANDALONE.match(results) standalone = standalone[1] unless standalone.nil? return [ :xmldecl, version, encoding, standalone ] when INSTRUCTION_START return [ :processing_instruction, *@source.match(INSTRUCTION_PATTERN, true)[1,2] ] when DOCTYPE_START md = @source.match( DOCTYPE_PATTERN, true ) @nsstack.unshift(curr_ns=Set.new) identity = md[1] close = md[2] identity =~ IDENTITY name = $1 raise REXML::ParseException.new("DOCTYPE is missing a name") if name.nil? pub_sys = $2.nil? ? nil : $2.strip long_name = $4.nil? ? nil : $4.strip uri = $6.nil? ? nil : $6.strip args = [ :start_doctype, name, pub_sys, long_name, uri ] if close == ">" @document_status = :after_doctype @source.read if @source.buffer.size<2 md = @source.match(/^\s*/um, true) @stack << [ :end_doctype ] else @document_status = :in_doctype end return args when /^\s+/ else @document_status = :after_doctype @source.read if @source.buffer.size<2 md = @source.match(/\s*/um, true) if @source.encoding == "UTF-8" @source.buffer.force_encoding(::Encoding::UTF_8) end end end if @document_status == :in_doctype md = @source.match(/\s*(.*?>)/um) case md[1] when SYSTEMENTITY match = @source.match( SYSTEMENTITY, true )[1] return [ :externalentity, match ] when ELEMENTDECL_START return [ :elementdecl, @source.match( ELEMENTDECL_PATTERN, true )[1] ] when ENTITY_START match = @source.match( ENTITYDECL, true ).to_a.compact match[0] = :entitydecl ref = false if match[1] == '%' ref = true match.delete_at 1 end # Now we have to sort out what kind of entity reference this is if match[2] == 'SYSTEM' # External reference match[3] = match[3][1..-2] # PUBID match.delete_at(4) if match.size > 4 # Chop out NDATA decl # match is [ :entity, name, SYSTEM, pubid(, ndata)? ] elsif match[2] == 'PUBLIC' # External reference match[3] = match[3][1..-2] # PUBID match[4] = match[4][1..-2] # HREF match.delete_at(5) if match.size > 5 # Chop out NDATA decl # match is [ :entity, name, PUBLIC, pubid, href(, ndata)? ] else match[2] = match[2][1..-2] match.pop if match.size == 4 # match is [ :entity, name, value ] end match << '%' if ref return match when ATTLISTDECL_START md = @source.match( ATTLISTDECL_PATTERN, true ) raise REXML::ParseException.new( "Bad ATTLIST declaration!", @source ) if md.nil? element = md[1] contents = md[0] pairs = {} values = md[0].scan( ATTDEF_RE ) values.each do |attdef| unless attdef[3] == "#IMPLIED" attdef.compact! val = attdef[3] val = attdef[4] if val == "#FIXED " pairs[attdef[0]] = val if attdef[0] =~ /^xmlns:(.*)/ @nsstack[0] << $1 end end end return [ :attlistdecl, element, pairs, contents ] when NOTATIONDECL_START md = nil if @source.match( PUBLIC ) md = @source.match( PUBLIC, true ) vals = [md[1],md[2],md[4],md[6]] elsif @source.match( SYSTEM ) md = @source.match( SYSTEM, true ) vals = [md[1],md[2],nil,md[4]] else raise REXML::ParseException.new( "error parsing notation: no matching pattern", @source ) end return [ :notationdecl, *vals ] when DOCTYPE_END @document_status = :after_doctype @source.match( DOCTYPE_END, true ) return [ :end_doctype ] end end begin if @source.buffer[0] == ?< if @source.buffer[1] == ?/ @nsstack.shift last_tag = @tags.pop #md = @source.match_to_consume( '>', CLOSE_MATCH) md = @source.match( CLOSE_MATCH, true ) raise REXML::ParseException.new( "Missing end tag for "+ "'#{last_tag}' (got \"#{md[1]}\")", @source) unless last_tag == md[1] return [ :end_element, last_tag ] elsif @source.buffer[1] == ?! md = @source.match(/\A(\s*[^>]*>)/um) #STDERR.puts "SOURCE BUFFER = #{source.buffer}, #{source.buffer.size}" raise REXML::ParseException.new("Malformed node", @source) unless md if md[0][2] == ?- md = @source.match( COMMENT_PATTERN, true ) case md[1] when /--/, /-\z/ raise REXML::ParseException.new("Malformed comment", @source) end return [ :comment, md[1] ] if md else md = @source.match( CDATA_PATTERN, true ) return [ :cdata, md[1] ] if md end raise REXML::ParseException.new( "Declarations can only occur "+ "in the doctype declaration.", @source) elsif @source.buffer[1] == ?? md = @source.match( INSTRUCTION_PATTERN, true ) return [ :processing_instruction, md[1], md[2] ] if md raise REXML::ParseException.new( "Bad instruction declaration", @source) else # Get the next tag md = @source.match(TAG_MATCH, true) unless md # Check for missing attribute quotes raise REXML::ParseException.new("missing attribute quote", @source) if @source.match(MISSING_ATTRIBUTE_QUOTES ) raise REXML::ParseException.new("malformed XML: missing tag start", @source) end attributes = {} prefixes = Set.new prefixes << md[2] if md[2] @nsstack.unshift(curr_ns=Set.new) if md[4].size > 0 attrs = md[4].scan( ATTRIBUTE_PATTERN ) raise REXML::ParseException.new( "error parsing attributes: [#{attrs.join ', '}], excess = \"#$'\"", @source) if $' and $'.strip.size > 0 attrs.each do |attr_name, prefix, local_part, quote, value| if prefix == "xmlns" if local_part == "xml" if value != "http://www.w3.org/XML/1998/namespace" msg = "The 'xml' prefix must not be bound to any other namespace "+ "(http://www.w3.org/TR/REC-xml-names/#ns-decl)" raise REXML::ParseException.new( msg, @source, self ) end elsif local_part == "xmlns" msg = "The 'xmlns' prefix must not be declared "+ "(http://www.w3.org/TR/REC-xml-names/#ns-decl)" raise REXML::ParseException.new( msg, @source, self) end curr_ns << local_part elsif prefix prefixes << prefix unless prefix == "xml" end if attributes.has_key?(attr_name) msg = "Duplicate attribute #{attr_name.inspect}" raise REXML::ParseException.new(msg, @source, self) end attributes[attr_name] = value end end # Verify that all of the prefixes have been defined for prefix in prefixes unless @nsstack.find{|k| k.member?(prefix)} raise UndefinedNamespaceException.new(prefix,@source,self) end end if md[6] @closed = md[1] @nsstack.shift else @tags.push( md[1] ) end return [ :start_element, md[1], attributes ] end else md = @source.match( TEXT_PATTERN, true ) if md[0].length == 0 @source.match( /(\s+)/, true ) end #STDERR.puts "GOT #{md[1].inspect}" unless md[0].length == 0 #return [ :text, "" ] if md[0].length == 0 # unnormalized = Text::unnormalize( md[1], self ) # return PullEvent.new( :text, md[1], unnormalized ) return [ :text, md[1] ] end rescue REXML::UndefinedNamespaceException raise rescue REXML::ParseException raise rescue Exception, NameError => error raise REXML::ParseException.new( "Exception parsing", @source, self, (error ? error : $!) ) end return [ :dummy ] end private :pull_event def entity( reference, entities ) value = nil value = entities[ reference ] if entities if not value value = DEFAULT_ENTITIES[ reference ] value = value[2] if value end unnormalize( value, entities ) if value end # Escapes all possible entities def normalize( input, entities=nil, entity_filter=nil ) copy = input.clone # Doing it like this rather than in a loop improves the speed copy.gsub!( EREFERENCE, '&' ) entities.each do |key, value| copy.gsub!( value, "&#{key};" ) unless entity_filter and entity_filter.include?(entity) end if entities copy.gsub!( EREFERENCE, '&' ) DEFAULT_ENTITIES.each do |key, value| copy.gsub!( value[3], value[1] ) end copy end # Unescapes all possible entities def unnormalize( string, entities=nil, filter=nil ) rv = string.clone rv.gsub!( /\r\n?/, "\n" ) matches = rv.scan( REFERENCE_RE ) return rv if matches.size == 0 rv.gsub!( /�*((?:\d+)|(?:x[a-fA-F0-9]+));/ ) { m=$1 m = "0#{m}" if m[0] == ?x [Integer(m)].pack('U*') } matches.collect!{|x|x[0]}.compact! if matches.size > 0 matches.each do |entity_reference| unless filter and filter.include?(entity_reference) entity_value = entity( entity_reference, entities ) if entity_value re = /&#{entity_reference};/ rv.gsub!( re, entity_value ) else er = DEFAULT_ENTITIES[entity_reference] rv.gsub!( er[0], er[2] ) if er end end end rv.gsub!( /&/, '&' ) end rv end private def need_source_encoding_update?(xml_declaration_encoding) return false if xml_declaration_encoding.nil? return false if /\AUTF-16\z/i =~ xml_declaration_encoding true end end end end =begin case event[0] when :start_element when :text when :end_element when :processing_instruction when :cdata when :comment when :xmldecl when :start_doctype when :end_doctype when :externalentity when :elementdecl when :entity when :attlistdecl when :notationdecl when :end_doctype end =end PK!ZUy2.2.0/rexml/parent.rbnu[require "rexml/child" module REXML # A parent has children, and has methods for accessing them. The Parent # class is never encountered except as the superclass for some other # object. class Parent < Child include Enumerable # Constructor # @param parent if supplied, will be set as the parent of this object def initialize parent=nil super(parent) @children = [] end def add( object ) object.parent = self @children << object object end alias :push :add alias :<< :push def unshift( object ) object.parent = self @children.unshift object end def delete( object ) found = false @children.delete_if {|c| c.equal?(object) and found = true } object.parent = nil if found found ? object : nil end def each(&block) @children.each(&block) end def delete_if( &block ) @children.delete_if(&block) end def delete_at( index ) @children.delete_at index end def each_index( &block ) @children.each_index(&block) end # Fetches a child at a given index # @param index the Integer index of the child to fetch def []( index ) @children[index] end alias :each_child :each # Set an index entry. See Array.[]= # @param index the index of the element to set # @param opt either the object to set, or an Integer length # @param child if opt is an Integer, this is the child to set # @return the parent (self) def []=( *args ) args[-1].parent = self @children[*args[0..-2]] = args[-1] end # Inserts an child before another child # @param child1 this is either an xpath or an Element. If an Element, # child2 will be inserted before child1 in the child list of the parent. # If an xpath, child2 will be inserted before the first child to match # the xpath. # @param child2 the child to insert # @return the parent (self) def insert_before( child1, child2 ) if child1.kind_of? String child1 = XPath.first( self, child1 ) child1.parent.insert_before child1, child2 else ind = index(child1) child2.parent.delete(child2) if child2.parent @children[ind,0] = child2 child2.parent = self end self end # Inserts an child after another child # @param child1 this is either an xpath or an Element. If an Element, # child2 will be inserted after child1 in the child list of the parent. # If an xpath, child2 will be inserted after the first child to match # the xpath. # @param child2 the child to insert # @return the parent (self) def insert_after( child1, child2 ) if child1.kind_of? String child1 = XPath.first( self, child1 ) child1.parent.insert_after child1, child2 else ind = index(child1)+1 child2.parent.delete(child2) if child2.parent @children[ind,0] = child2 child2.parent = self end self end def to_a @children.dup end # Fetches the index of a given child # @param child the child to get the index of # @return the index of the child, or nil if the object is not a child # of this parent. def index( child ) count = -1 @children.find { |i| count += 1 ; i.hash == child.hash } count end # @return the number of children of this parent def size @children.size end alias :length :size # Replaces one child with another, making sure the nodelist is correct # @param to_replace the child to replace (must be a Child) # @param replacement the child to insert into the nodelist (must be a # Child) def replace_child( to_replace, replacement ) @children.map! {|c| c.equal?( to_replace ) ? replacement : c } to_replace.parent = nil replacement.parent = self end # Deeply clones this object. This creates a complete duplicate of this # Parent, including all descendants. def deep_clone cl = clone() each do |child| if child.kind_of? Parent cl << child.deep_clone else cl << child.clone end end cl end alias :children :to_a def parent? true end end end PK!`*2.2.0/rexml/undefinednamespaceexception.rbnu[require 'rexml/parseexception' module REXML class UndefinedNamespaceException < ParseException def initialize( prefix, source, parser ) super( "Undefined prefix #{prefix} found" ) end end end PK!AO5O5!2.2.0/rexml/validation/relaxng.rbnu[require "rexml/validation/validation" require "rexml/parsers/baseparser" module REXML module Validation # Implemented: # * empty # * element # * attribute # * text # * optional # * choice # * oneOrMore # * zeroOrMore # * group # * value # * interleave # * mixed # * ref # * grammar # * start # * define # # Not implemented: # * data # * param # * include # * externalRef # * notAllowed # * anyName # * nsName # * except # * name class RelaxNG include Validator INFINITY = 1.0 / 0.0 EMPTY = Event.new( nil ) TEXT = [:start_element, "text"] attr_accessor :current attr_accessor :count attr_reader :references # FIXME: Namespaces def initialize source parser = REXML::Parsers::BaseParser.new( source ) @count = 0 @references = {} @root = @current = Sequence.new(self) @root.previous = true states = [ @current ] begin event = parser.pull case event[0] when :start_element case event[1] when "empty" when "element", "attribute", "text", "value" states[-1] << event when "optional" states << Optional.new( self ) states[-2] << states[-1] when "choice" states << Choice.new( self ) states[-2] << states[-1] when "oneOrMore" states << OneOrMore.new( self ) states[-2] << states[-1] when "zeroOrMore" states << ZeroOrMore.new( self ) states[-2] << states[-1] when "group" states << Sequence.new( self ) states[-2] << states[-1] when "interleave" states << Interleave.new( self ) states[-2] << states[-1] when "mixed" states << Interleave.new( self ) states[-2] << states[-1] states[-1] << TEXT when "define" states << [ event[2]["name"] ] when "ref" states[-1] << Ref.new( event[2]["name"] ) when "anyName" states << AnyName.new( self ) states[-2] << states[-1] when "nsName" when "except" when "name" when "data" when "param" when "include" when "grammar" when "start" when "externalRef" when "notAllowed" end when :end_element case event[1] when "element", "attribute" states[-1] << event when "zeroOrMore", "oneOrMore", "choice", "optional", "interleave", "group", "mixed" states.pop when "define" ref = states.pop @references[ ref.shift ] = ref #when "empty" end when :end_document states[-1] << event when :text states[-1] << event end end while event[0] != :end_document end def receive event validate( event ) end end class State def initialize( context ) @previous = [] @events = [] @current = 0 @count = context.count += 1 @references = context.references @value = false end def reset return if @current == 0 @current = 0 @events.each {|s| s.reset if s.kind_of? State } end def previous=( previous ) @previous << previous end def next( event ) #print "In next with #{event.inspect}. " #p @previous return @previous.pop.next( event ) if @events[@current].nil? expand_ref_in( @events, @current ) if @events[@current].class == Ref if ( @events[@current].kind_of? State ) @current += 1 @events[@current-1].previous = self return @events[@current-1].next( event ) end if ( @events[@current].matches?(event) ) @current += 1 if @events[@current].nil? return @previous.pop elsif @events[@current].kind_of? State @current += 1 @events[@current-1].previous = self return @events[@current-1] else return self end else return nil end end def to_s # Abbreviated: self.class.name =~ /(?:::)(\w)\w+$/ # Full: #self.class.name =~ /(?:::)(\w+)$/ "#$1.#@count" end def inspect "< #{to_s} #{@events.collect{|e| pre = e == @events[@current] ? '#' : '' pre + e.inspect unless self == e }.join(', ')} >" end def expected return [@events[@current]] end def <<( event ) add_event_to_arry( @events, event ) end protected def expand_ref_in( arry, ind ) new_events = [] @references[ arry[ind].to_s ].each{ |evt| add_event_to_arry(new_events,evt) } arry[ind,1] = new_events end def add_event_to_arry( arry, evt ) evt = generate_event( evt ) if evt.kind_of? String arry[-1].event_arg = evt if arry[-1].kind_of? Event and @value @value = false else arry << evt end end def generate_event( event ) return event if event.kind_of? State or event.class == Ref evt = nil arg = nil case event[0] when :start_element case event[1] when "element" evt = :start_element arg = event[2]["name"] when "attribute" evt = :start_attribute arg = event[2]["name"] when "text" evt = :text when "value" evt = :text @value = true end when :text return event[1] when :end_document return Event.new( event[0] ) else # then :end_element case event[1] when "element" evt = :end_element when "attribute" evt = :end_attribute end end return Event.new( evt, arg ) end end class Sequence < State def matches?(event) @events[@current].matches?( event ) end end class Optional < State def next( event ) if @current == 0 rv = super return rv if rv @prior = @previous.pop return @prior.next( event ) end super end def matches?(event) @events[@current].matches?(event) || (@current == 0 and @previous[-1].matches?(event)) end def expected return [ @prior.expected, @events[0] ].flatten if @current == 0 return [@events[@current]] end end class ZeroOrMore < Optional def next( event ) expand_ref_in( @events, @current ) if @events[@current].class == Ref if ( @events[@current].matches?(event) ) @current += 1 if @events[@current].nil? @current = 0 return self elsif @events[@current].kind_of? State @current += 1 @events[@current-1].previous = self return @events[@current-1] else return self end else @prior = @previous.pop return @prior.next( event ) if @current == 0 return nil end end def expected return [ @prior.expected, @events[0] ].flatten if @current == 0 return [@events[@current]] end end class OneOrMore < State def initialize context super @ord = 0 end def reset super @ord = 0 end def next( event ) expand_ref_in( @events, @current ) if @events[@current].class == Ref if ( @events[@current].matches?(event) ) @current += 1 @ord += 1 if @events[@current].nil? @current = 0 return self elsif @events[@current].kind_of? State @current += 1 @events[@current-1].previous = self return @events[@current-1] else return self end else return @previous.pop.next( event ) if @current == 0 and @ord > 0 return nil end end def matches?( event ) @events[@current].matches?(event) || (@current == 0 and @ord > 0 and @previous[-1].matches?(event)) end def expected if @current == 0 and @ord > 0 return [@previous[-1].expected, @events[0]].flatten else return [@events[@current]] end end end class Choice < State def initialize context super @choices = [] end def reset super @events = [] @choices.each { |c| c.each { |s| s.reset if s.kind_of? State } } end def <<( event ) add_event_to_arry( @choices, event ) end def next( event ) # Make the choice if we haven't if @events.size == 0 c = 0 ; max = @choices.size while c < max if @choices[c][0].class == Ref expand_ref_in( @choices[c], 0 ) @choices += @choices[c] @choices.delete( @choices[c] ) max -= 1 else c += 1 end end @events = @choices.find { |evt| evt[0].matches? event } # Remove the references # Find the events end unless @events @events = [] return nil end super end def matches?( event ) return @events[@current].matches?( event ) if @events.size > 0 !@choices.find{|evt| evt[0].matches?(event)}.nil? end def expected return [@events[@current]] if @events.size > 0 return @choices.collect do |x| if x[0].kind_of? State x[0].expected else x[0] end end.flatten end def inspect "< #{to_s} #{@choices.collect{|e| e.collect{|f|f.to_s}.join(', ')}.join(' or ')} >" end protected def add_event_to_arry( arry, evt ) if evt.kind_of? State or evt.class == Ref arry << [evt] elsif evt[0] == :text if arry[-1] and arry[-1][-1].kind_of?( Event ) and arry[-1][-1].event_type == :text and @value arry[-1][-1].event_arg = evt[1] @value = false end else arry << [] if evt[0] == :start_element arry[-1] << generate_event( evt ) end end end class Interleave < Choice def initialize context super @choice = 0 end def reset @choice = 0 end def next_current( event ) # Expand references c = 0 ; max = @choices.size while c < max if @choices[c][0].class == Ref expand_ref_in( @choices[c], 0 ) @choices += @choices[c] @choices.delete( @choices[c] ) max -= 1 else c += 1 end end @events = @choices[@choice..-1].find { |evt| evt[0].matches? event } @current = 0 if @events # reorder the choices old = @choices[@choice] idx = @choices.index( @events ) @choices[@choice] = @events @choices[idx] = old @choice += 1 end @events = [] unless @events end def next( event ) # Find the next series next_current(event) unless @events[@current] return nil unless @events[@current] expand_ref_in( @events, @current ) if @events[@current].class == Ref if ( @events[@current].kind_of? State ) @current += 1 @events[@current-1].previous = self return @events[@current-1].next( event ) end return @previous.pop.next( event ) if @events[@current].nil? if ( @events[@current].matches?(event) ) @current += 1 if @events[@current].nil? return self unless @choices[@choice].nil? return @previous.pop elsif @events[@current].kind_of? State @current += 1 @events[@current-1].previous = self return @events[@current-1] else return self end else return nil end end def matches?( event ) return @events[@current].matches?( event ) if @events[@current] !@choices[@choice..-1].find{|evt| evt[0].matches?(event)}.nil? end def expected return [@events[@current]] if @events[@current] return @choices[@choice..-1].collect do |x| if x[0].kind_of? State x[0].expected else x[0] end end.flatten end def inspect "< #{to_s} #{@choices.collect{|e| e.collect{|f|f.to_s}.join(', ')}.join(' and ')} >" end end class Ref def initialize value @value = value end def to_s @value end def inspect "{#{to_s}}" end end end end PK!Yڑ-2.2.0/rexml/validation/validationexception.rbnu[module REXML module Validation class ValidationException < RuntimeError def initialize msg super end end end end PK! $v$2.2.0/rexml/validation/validation.rbnu[require 'rexml/validation/validationexception' module REXML module Validation module Validator NILEVENT = [ nil ] def reset @current = @root @root.reset @root.previous = true @attr_stack = [] self end def dump puts @root.inspect end def validate( event ) @attr_stack = [] unless defined? @attr_stack match = @current.next(event) raise ValidationException.new( "Validation error. Expected: "+ @current.expected.join( " or " )+" from #{@current.inspect} "+ " but got #{Event.new( event[0], event[1] ).inspect}" ) unless match @current = match # Check for attributes case event[0] when :start_element @attr_stack << event[2] begin sattr = [:start_attribute, nil] eattr = [:end_attribute] text = [:text, nil] k, = event[2].find { |key,value| sattr[1] = key m = @current.next( sattr ) if m # If the state has text children... if m.matches?( eattr ) @current = m else text[1] = value m = m.next( text ) text[1] = nil return false unless m @current = m if m end m = @current.next( eattr ) if m @current = m true else false end else false end } event[2].delete(k) if k end while k when :end_element attrs = @attr_stack.pop raise ValidationException.new( "Validation error. Illegal "+ " attributes: #{attrs.inspect}") if attrs.length > 0 end end end class Event def initialize(event_type, event_arg=nil ) @event_type = event_type @event_arg = event_arg end attr_reader :event_type attr_accessor :event_arg def done? @done end def single? return (@event_type != :start_element and @event_type != :start_attribute) end def matches?( event ) return false unless event[0] == @event_type case event[0] when nil return true when :start_element return true if event[1] == @event_arg when :end_element return true when :start_attribute return true if event[1] == @event_arg when :end_attribute return true when :end_document return true when :text return (@event_arg.nil? or @event_arg == event[1]) =begin when :processing_instruction false when :xmldecl false when :start_doctype false when :end_doctype false when :externalentity false when :elementdecl false when :entity false when :attlistdecl false when :notationdecl false when :end_doctype false =end else false end end def ==( other ) return false unless other.kind_of? Event @event_type == other.event_type and @event_arg == other.event_arg end def to_s inspect end def inspect "#{@event_type.inspect}( #@event_arg )" end end end end PK!L>!!2.2.0/rexml/entity.rbnu[require 'rexml/child' require 'rexml/source' require 'rexml/xmltokens' module REXML # God, I hate DTDs. I really do. Why this idiot standard still # plagues us is beyond me. class Entity < Child include XMLTokens PUBIDCHAR = "\x20\x0D\x0Aa-zA-Z0-9\\-()+,./:=?;!*@$_%#" SYSTEMLITERAL = %Q{((?:"[^"]*")|(?:'[^']*'))} PUBIDLITERAL = %Q{("[#{PUBIDCHAR}']*"|'[#{PUBIDCHAR}]*')} EXTERNALID = "(?:(?:(SYSTEM)\\s+#{SYSTEMLITERAL})|(?:(PUBLIC)\\s+#{PUBIDLITERAL}\\s+#{SYSTEMLITERAL}))" NDATADECL = "\\s+NDATA\\s+#{NAME}" PEREFERENCE = "%#{NAME};" ENTITYVALUE = %Q{((?:"(?:[^%&"]|#{PEREFERENCE}|#{REFERENCE})*")|(?:'([^%&']|#{PEREFERENCE}|#{REFERENCE})*'))} PEDEF = "(?:#{ENTITYVALUE}|#{EXTERNALID})" ENTITYDEF = "(?:#{ENTITYVALUE}|(?:#{EXTERNALID}(#{NDATADECL})?))" PEDECL = "" GEDECL = "" ENTITYDECL = /\s*(?:#{GEDECL})|(?:#{PEDECL})/um attr_reader :name, :external, :ref, :ndata, :pubid # Create a new entity. Simple entities can be constructed by passing a # name, value to the constructor; this creates a generic, plain entity # reference. For anything more complicated, you have to pass a Source to # the constructor with the entity definition, or use the accessor methods. # +WARNING+: There is no validation of entity state except when the entity # is read from a stream. If you start poking around with the accessors, # you can easily create a non-conformant Entity. The best thing to do is # dump the stupid DTDs and use XMLSchema instead. # # e = Entity.new( 'amp', '&' ) def initialize stream, value=nil, parent=nil, reference=false super(parent) @ndata = @pubid = @value = @external = nil if stream.kind_of? Array @name = stream[1] if stream[-1] == '%' @reference = true stream.pop else @reference = false end if stream[2] =~ /SYSTEM|PUBLIC/ @external = stream[2] if @external == 'SYSTEM' @ref = stream[3] @ndata = stream[4] if stream.size == 5 else @pubid = stream[3] @ref = stream[4] end else @value = stream[2] end else @reference = reference @external = nil @name = stream @value = value end end # Evaluates whether the given string matches an entity definition, # returning true if so, and false otherwise. def Entity::matches? string (ENTITYDECL =~ string) == 0 end # Evaluates to the unnormalized value of this entity; that is, replacing # all entities -- both %ent; and &ent; entities. This differs from # +value()+ in that +value+ only replaces %ent; entities. def unnormalized document.record_entity_expansion unless document.nil? v = value() return nil if v.nil? @unnormalized = Text::unnormalize(v, parent) @unnormalized end #once :unnormalized # Returns the value of this entity unprocessed -- raw. This is the # normalized value; that is, with all %ent; and &ent; entities intact def normalized @value end # Write out a fully formed, correct entity definition (assuming the Entity # object itself is valid.) # # out:: # An object implementing << to which the entity will be # output # indent:: # *DEPRECATED* and ignored def write out, indent=-1 out << '' end # Returns this entity as a string. See write(). def to_s rv = '' write rv rv end PEREFERENCE_RE = /#{PEREFERENCE}/um # Returns the value of this entity. At the moment, only internal entities # are processed. If the value contains internal references (IE, # %blah;), those are replaced with their values. IE, if the doctype # contains: # # # then: # doctype.entity('yada').value #-> "nanoo bar nanoo" def value if @value matches = @value.scan(PEREFERENCE_RE) rv = @value.clone if @parent sum = 0 matches.each do |entity_reference| entity_value = @parent.entity( entity_reference[0] ) if sum + entity_value.bytesize > Security.entity_expansion_text_limit raise "entity expansion has grown too large" else sum += entity_value.bytesize end rv.gsub!( /%#{entity_reference.join};/um, entity_value ) end end return rv end nil end end # This is a set of entity constants -- the ones defined in the XML # specification. These are +gt+, +lt+, +amp+, +quot+ and +apos+. # CAUTION: these entities does not have parent and document module EntityConst # +>+ GT = Entity.new( 'gt', '>' ) # +<+ LT = Entity.new( 'lt', '<' ) # +&+ AMP = Entity.new( 'amp', '&' ) # +"+ QUOT = Entity.new( 'quot', '"' ) # +'+ APOS = Entity.new( 'apos', "'" ) end end PK!0  2.2.0/rexml/instruction.rbnu[require "rexml/child" require "rexml/source" module REXML # Represents an XML Instruction; IE, # TODO: Add parent arg (3rd arg) to constructor class Instruction < Child START = '<\?' STOP = '\?>' # target is the "name" of the Instruction; IE, the "tag" in # content is everything else. attr_accessor :target, :content # Constructs a new Instruction # @param target can be one of a number of things. If String, then # the target of this instruction is set to this. If an Instruction, # then the Instruction is shallowly cloned (target and content are # copied). If a Source, then the source is scanned and parsed for # an Instruction declaration. # @param content Must be either a String, or a Parent. Can only # be a Parent if the target argument is a Source. Otherwise, this # String is set as the content of this instruction. def initialize(target, content=nil) if target.kind_of? String super() @target = target @content = content elsif target.kind_of? Instruction super(content) @target = target.target @content = target.content end @content.strip! if @content end def clone Instruction.new self end # == DEPRECATED # See the rexml/formatters package # def write writer, indent=-1, transitive=false, ie_hack=false Kernel.warn( "#{self.class.name}.write is deprecated" ) indent(writer, indent) writer << START.sub(/\\/u, '') writer << @target writer << ' ' writer << @content writer << STOP.sub(/\\/u, '') end # @return true if other is an Instruction, and the content and target # of the other matches the target and content of this object. def ==( other ) other.kind_of? Instruction and other.target == @target and other.content == @content end def node_type :processing_instruction end def inspect "" end end end PK!S% 2.2.0/rexml/attribute.rbnu[require "rexml/namespace" require 'rexml/text' module REXML # Defines an Element Attribute; IE, a attribute=value pair, as in: # . Attributes can be in their own # namespaces. General users of REXML will not interact with the # Attribute class much. class Attribute include Node include Namespace # The element to which this attribute belongs attr_reader :element # The normalized value of this attribute. That is, the attribute with # entities intact. attr_writer :normalized PATTERN = /\s*(#{NAME_STR})\s*=\s*(["'])(.*?)\2/um NEEDS_A_SECOND_CHECK = /(<|&((#{Entity::NAME});|(#0*((?:\d+)|(?:x[a-fA-F0-9]+)));)?)/um # Constructor. # FIXME: The parser doesn't catch illegal characters in attributes # # first:: # Either: an Attribute, which this new attribute will become a # clone of; or a String, which is the name of this attribute # second:: # If +first+ is an Attribute, then this may be an Element, or nil. # If nil, then the Element parent of this attribute is the parent # of the +first+ Attribute. If the first argument is a String, # then this must also be a String, and is the content of the attribute. # If this is the content, it must be fully normalized (contain no # illegal characters). # parent:: # Ignored unless +first+ is a String; otherwise, may be the Element # parent of this attribute, or nil. # # # Attribute.new( attribute_to_clone ) # Attribute.new( attribute_to_clone, parent_element ) # Attribute.new( "attr", "attr_value" ) # Attribute.new( "attr", "attr_value", parent_element ) def initialize( first, second=nil, parent=nil ) @normalized = @unnormalized = @element = nil if first.kind_of? Attribute self.name = first.expanded_name @unnormalized = first.value if second.kind_of? Element @element = second else @element = first.element end elsif first.kind_of? String @element = parent self.name = first @normalized = second.to_s else raise "illegal argument #{first.class.name} to Attribute constructor" end end # Returns the namespace of the attribute. # # e = Element.new( "elns:myelement" ) # e.add_attribute( "nsa:a", "aval" ) # e.add_attribute( "b", "bval" ) # e.attributes.get_attribute( "a" ).prefix # -> "nsa" # e.attributes.get_attribute( "b" ).prefix # -> "elns" # a = Attribute.new( "x", "y" ) # a.prefix # -> "" def prefix pf = super if pf == "" pf = @element.prefix if @element end pf end # Returns the namespace URL, if defined, or nil otherwise # # e = Element.new("el") # e.add_namespace("ns", "http://url") # e.add_attribute("ns:a", "b") # e.add_attribute("nsx:a", "c") # e.attribute("ns:a").namespace # => "http://url" # e.attribute("nsx:a").namespace # => nil def namespace arg=nil arg = prefix if arg.nil? @element.namespace arg end # Returns true if other is an Attribute and has the same name and value, # false otherwise. def ==( other ) other.kind_of?(Attribute) and other.name==name and other.value==value end # Creates (and returns) a hash from both the name and value def hash name.hash + value.hash end # Returns this attribute out as XML source, expanding the name # # a = Attribute.new( "x", "y" ) # a.to_string # -> "x='y'" # b = Attribute.new( "ns:x", "y" ) # b.to_string # -> "ns:x='y'" def to_string if @element and @element.context and @element.context[:attribute_quote] == :quote %Q^#@expanded_name="#{to_s().gsub(/"/, '"')}"^ else "#@expanded_name='#{to_s().gsub(/'/, ''')}'" end end def doctype if @element doc = @element.document doc.doctype if doc end end # Returns the attribute value, with entities replaced def to_s return @normalized if @normalized @normalized = Text::normalize( @unnormalized, doctype ) @unnormalized = nil @normalized end # Returns the UNNORMALIZED value of this attribute. That is, entities # have been expanded to their values def value return @unnormalized if @unnormalized @unnormalized = Text::unnormalize( @normalized, doctype ) @normalized = nil @unnormalized end # Returns a copy of this attribute def clone Attribute.new self end # Sets the element of which this object is an attribute. Normally, this # is not directly called. # # Returns this attribute def element=( element ) @element = element if @normalized Text.check( @normalized, NEEDS_A_SECOND_CHECK, doctype ) end self end # Removes this Attribute from the tree, and returns true if successful # # This method is usually not called directly. def remove @element.attributes.delete self.name unless @element.nil? end # Writes this attribute (EG, puts 'key="value"' to the output) def write( output, indent=-1 ) output << to_string end def node_type :attribute end def inspect rv = "" write( rv ) rv end def xpath path = @element.xpath path += "/@#{self.expanded_name}" return path end end end #vim:ts=2 sw=2 noexpandtab: PK!Oz--2.2.0/rexml/functions.rbnu[module REXML # If you add a method, keep in mind two things: # (1) the first argument will always be a list of nodes from which to # filter. In the case of context methods (such as position), the function # should return an array with a value for each child in the array. # (2) all method calls from XML will have "-" replaced with "_". # Therefore, in XML, "local-name()" is identical (and actually becomes) # "local_name()" module Functions @@context = nil @@namespace_context = {} @@variables = {} def Functions::namespace_context=(x) ; @@namespace_context=x ; end def Functions::variables=(x) ; @@variables=x ; end def Functions::namespace_context ; @@namespace_context ; end def Functions::variables ; @@variables ; end def Functions::context=(value); @@context = value; end def Functions::text( ) if @@context[:node].node_type == :element return @@context[:node].find_all{|n| n.node_type == :text}.collect{|n| n.value} elsif @@context[:node].node_type == :text return @@context[:node].value else return false end end # Returns the last node of the given list of nodes. def Functions::last( ) @@context[:size] end def Functions::position( ) @@context[:index] end # Returns the size of the given list of nodes. def Functions::count( node_set ) node_set.size end # Since REXML is non-validating, this method is not implemented as it # requires a DTD def Functions::id( object ) end # UNTESTED def Functions::local_name( node_set=nil ) get_namespace( node_set ) do |node| return node.local_name end end def Functions::namespace_uri( node_set=nil ) get_namespace( node_set ) {|node| node.namespace} end def Functions::name( node_set=nil ) get_namespace( node_set ) do |node| node.expanded_name end end # Helper method. def Functions::get_namespace( node_set = nil ) if node_set == nil yield @@context[:node] if defined? @@context[:node].namespace else if node_set.respond_to? :each node_set.each { |node| yield node if defined? node.namespace } elsif node_set.respond_to? :namespace yield node_set end end end # A node-set is converted to a string by returning the string-value of the # node in the node-set that is first in document order. If the node-set is # empty, an empty string is returned. # # A number is converted to a string as follows # # NaN is converted to the string NaN # # positive zero is converted to the string 0 # # negative zero is converted to the string 0 # # positive infinity is converted to the string Infinity # # negative infinity is converted to the string -Infinity # # if the number is an integer, the number is represented in decimal form # as a Number with no decimal point and no leading zeros, preceded by a # minus sign (-) if the number is negative # # otherwise, the number is represented in decimal form as a Number # including a decimal point with at least one digit before the decimal # point and at least one digit after the decimal point, preceded by a # minus sign (-) if the number is negative; there must be no leading zeros # before the decimal point apart possibly from the one required digit # immediately before the decimal point; beyond the one required digit # after the decimal point there must be as many, but only as many, more # digits as are needed to uniquely distinguish the number from all other # IEEE 754 numeric values. # # The boolean false value is converted to the string false. The boolean # true value is converted to the string true. # # An object of a type other than the four basic types is converted to a # string in a way that is dependent on that type. def Functions::string( object=nil ) #object = @context unless object if object.instance_of? Array string( object[0] ) elsif defined? object.node_type if object.node_type == :attribute object.value elsif object.node_type == :element || object.node_type == :document string_value(object) else object.to_s end elsif object.nil? return "" else object.to_s end end # A node-set is converted to a string by # returning the concatenation of the string-value # of each of the children of the node in the # node-set that is first in document order. # If the node-set is empty, an empty string is returned. def Functions::string_value( o ) rv = "" o.children.each { |e| if e.node_type == :text rv << e.to_s elsif e.node_type == :element rv << string_value( e ) end } rv end # UNTESTED def Functions::concat( *objects ) objects.join end # Fixed by Mike Stok def Functions::starts_with( string, test ) string(string).index(string(test)) == 0 end # Fixed by Mike Stok def Functions::contains( string, test ) string(string).include?(string(test)) end # Kouhei fixed this def Functions::substring_before( string, test ) ruby_string = string(string) ruby_index = ruby_string.index(string(test)) if ruby_index.nil? "" else ruby_string[ 0...ruby_index ] end end # Kouhei fixed this too def Functions::substring_after( string, test ) ruby_string = string(string) return $1 if ruby_string =~ /#{test}(.*)/ "" end # Take equal portions of Mike Stok and Sean Russell; mix # vigorously, and pour into a tall, chilled glass. Serves 10,000. def Functions::substring( string, start, length=nil ) ruby_string = string(string) ruby_length = if length.nil? ruby_string.length.to_f else number(length) end ruby_start = number(start) # Handle the special cases return '' if ( ruby_length.nan? or ruby_start.nan? or ruby_start.infinite? ) infinite_length = ruby_length.infinite? == 1 ruby_length = ruby_string.length if infinite_length # Now, get the bounds. The XPath bounds are 1..length; the ruby bounds # are 0..length. Therefore, we have to offset the bounds by one. ruby_start = ruby_start.round - 1 ruby_length = ruby_length.round if ruby_start < 0 ruby_length += ruby_start unless infinite_length ruby_start = 0 end return '' if ruby_length <= 0 ruby_string[ruby_start,ruby_length] end # UNTESTED def Functions::string_length( string ) string(string).length end # UNTESTED def Functions::normalize_space( string=nil ) string = string(@@context[:node]) if string.nil? if string.kind_of? Array string.collect{|x| string.to_s.strip.gsub(/\s+/um, ' ') if string} else string.to_s.strip.gsub(/\s+/um, ' ') end end # This is entirely Mike Stok's beast def Functions::translate( string, tr1, tr2 ) from = string(tr1) to = string(tr2) # the map is our translation table. # # if a character occurs more than once in the # from string then we ignore the second & # subsequent mappings # # if a character maps to nil then we delete it # in the output. This happens if the from # string is longer than the to string # # there's nothing about - or ^ being special in # http://www.w3.org/TR/xpath#function-translate # so we don't build ranges or negated classes map = Hash.new 0.upto(from.length - 1) { |pos| from_char = from[pos] unless map.has_key? from_char map[from_char] = if pos < to.length to[pos] else nil end end } if ''.respond_to? :chars string(string).chars.collect { |c| if map.has_key? c then map[c] else c end }.compact.join else string(string).unpack('U*').collect { |c| if map.has_key? c then map[c] else c end }.compact.pack('U*') end end # UNTESTED def Functions::boolean( object=nil ) if object.kind_of? String if object =~ /\d+/u return object.to_f != 0 else return object.size > 0 end elsif object.kind_of? Array object = object.find{|x| x and true} end return object ? true : false end # UNTESTED def Functions::not( object ) not boolean( object ) end # UNTESTED def Functions::true( ) true end # UNTESTED def Functions::false( ) false end # UNTESTED def Functions::lang( language ) lang = false node = @@context[:node] attr = nil until node.nil? if node.node_type == :element attr = node.attributes["xml:lang"] unless attr.nil? lang = compare_language(string(language), attr) break else end end node = node.parent end lang end def Functions::compare_language lang1, lang2 lang2.downcase.index(lang1.downcase) == 0 end # a string that consists of optional whitespace followed by an optional # minus sign followed by a Number followed by whitespace is converted to # the IEEE 754 number that is nearest (according to the IEEE 754 # round-to-nearest rule) to the mathematical value represented by the # string; any other string is converted to NaN # # boolean true is converted to 1; boolean false is converted to 0 # # a node-set is first converted to a string as if by a call to the string # function and then converted in the same way as a string argument # # an object of a type other than the four basic types is converted to a # number in a way that is dependent on that type def Functions::number( object=nil ) object = @@context[:node] unless object case object when true Float(1) when false Float(0) when Array number(string( object )) when Numeric object.to_f else str = string( object ) # If XPath ever gets scientific notation... #if str =~ /^\s*-?(\d*\.?\d+|\d+\.)([Ee]\d*)?\s*$/ if str =~ /^\s*-?(\d*\.?\d+|\d+\.)\s*$/ str.to_f else (0.0 / 0.0) end end end def Functions::sum( nodes ) nodes = [nodes] unless nodes.kind_of? Array nodes.inject(0) { |r,n| r + number(string(n)) } end def Functions::floor( number ) number(number).floor end def Functions::ceiling( number ) number(number).ceil end def Functions::round( number ) begin number(number).round rescue FloatDomainError number(number) end end def Functions::processing_instruction( node ) node.node_type == :processing_instruction end def Functions::method_missing( id ) puts "METHOD MISSING #{id.id2name}" XPath.match( @@context[:node], id.id2name ) end end end PK!2(2.2.0/rexml/output.rbnu[require 'rexml/encoding' module REXML class Output include Encoding attr_reader :encoding def initialize real_IO, encd="iso-8859-1" @output = real_IO self.encoding = encd @to_utf = encoding != 'UTF-8' if encoding == "UTF-16" @output << "\ufeff".encode("UTF-16BE") self.encoding = "UTF-16BE" end end def <<( content ) @output << (@to_utf ? self.encode(content) : content) end def to_s "Output[#{encoding}]" end end end PK!9QQ2.2.0/rexml/xpath_parser.rbnu[require 'rexml/namespace' require 'rexml/xmltokens' require 'rexml/attribute' require 'rexml/syncenumerator' require 'rexml/parsers/xpathparser' class Object # provides a unified +clone+ operation, for REXML::XPathParser # to use across multiple Object types def dclone clone end end class Symbol # provides a unified +clone+ operation, for REXML::XPathParser # to use across multiple Object types def dclone ; self ; end end class Fixnum # provides a unified +clone+ operation, for REXML::XPathParser # to use across multiple Object types def dclone ; self ; end end class Float # provides a unified +clone+ operation, for REXML::XPathParser # to use across multiple Object types def dclone ; self ; end end class Array # provides a unified +clone+ operation, for REXML::XPathParser # to use across multiple Object+ types def dclone klone = self.clone klone.clear self.each{|v| klone << v.dclone} klone end end module REXML # You don't want to use this class. Really. Use XPath, which is a wrapper # for this class. Believe me. You don't want to poke around in here. # There is strange, dark magic at work in this code. Beware. Go back! Go # back while you still can! class XPathParser include XMLTokens LITERAL = /^'([^']*)'|^"([^"]*)"/u def initialize( ) @parser = REXML::Parsers::XPathParser.new @namespaces = nil @variables = {} end def namespaces=( namespaces={} ) Functions::namespace_context = namespaces @namespaces = namespaces end def variables=( vars={} ) Functions::variables = vars @variables = vars end def parse path, nodeset path_stack = @parser.parse( path ) match( path_stack, nodeset ) end def get_first path, nodeset path_stack = @parser.parse( path ) first( path_stack, nodeset ) end def predicate path, nodeset path_stack = @parser.parse( path ) expr( path_stack, nodeset ) end def []=( variable_name, value ) @variables[ variable_name ] = value end # Performs a depth-first (document order) XPath search, and returns the # first match. This is the fastest, lightest way to return a single result. # # FIXME: This method is incomplete! def first( path_stack, node ) return nil if path.size == 0 case path[0] when :document # do nothing return first( path[1..-1], node ) when :child for c in node.children r = first( path[1..-1], c ) return r if r end when :qname name = path[2] if node.name == name return node if path.size == 3 return first( path[3..-1], node ) else return nil end when :descendant_or_self r = first( path[1..-1], node ) return r if r for c in node.children r = first( path, c ) return r if r end when :node return first( path[1..-1], node ) when :any return first( path[1..-1], node ) end return nil end def match( path_stack, nodeset ) r = expr( path_stack, nodeset ) r end private # Returns a String namespace for a node, given a prefix # The rules are: # # 1. Use the supplied namespace mapping first. # 2. If no mapping was supplied, use the context node to look up the namespace def get_namespace( node, prefix ) if @namespaces return @namespaces[prefix] || '' else return node.namespace( prefix ) if node.node_type == :element return '' end end # Expr takes a stack of path elements and a set of nodes (either a Parent # or an Array and returns an Array of matching nodes ALL = [ :attribute, :element, :text, :processing_instruction, :comment ] ELEMENTS = [ :element ] def expr( path_stack, nodeset, context=nil ) node_types = ELEMENTS return nodeset if path_stack.length == 0 || nodeset.length == 0 while path_stack.length > 0 if nodeset.length == 0 path_stack.clear return [] end case (op = path_stack.shift) when :document nodeset = [ nodeset[0].root_node ] when :qname prefix = path_stack.shift name = path_stack.shift nodeset.delete_if do |node| # FIXME: This DOUBLES the time XPath searches take ns = get_namespace( node, prefix ) if node.node_type == :element if node.name == name end end !(node.node_type == :element and node.name == name and node.namespace == ns ) end node_types = ELEMENTS when :any nodeset.delete_if { |node| !node_types.include?(node.node_type) } when :self # This space left intentionally blank when :processing_instruction target = path_stack.shift nodeset.delete_if do |node| (node.node_type != :processing_instruction) or ( target!='' and ( node.target != target ) ) end when :text nodeset.delete_if { |node| node.node_type != :text } when :comment nodeset.delete_if { |node| node.node_type != :comment } when :node # This space left intentionally blank node_types = ALL when :child new_nodeset = [] nt = nil nodeset.each do |node| nt = node.node_type new_nodeset += node.children if nt == :element or nt == :document end nodeset = new_nodeset node_types = ELEMENTS when :literal return path_stack.shift when :attribute new_nodeset = [] case path_stack.shift when :qname prefix = path_stack.shift name = path_stack.shift for element in nodeset if element.node_type == :element attrib = element.attribute( name, get_namespace(element, prefix) ) new_nodeset << attrib if attrib end end when :any for element in nodeset if element.node_type == :element new_nodeset += element.attributes.to_a end end end nodeset = new_nodeset when :parent nodeset = nodeset.collect{|n| n.parent}.compact #nodeset = expr(path_stack.dclone, nodeset.collect{|n| n.parent}.compact) node_types = ELEMENTS when :ancestor new_nodeset = [] nodeset.each do |node| while node.parent node = node.parent new_nodeset << node unless new_nodeset.include? node end end nodeset = new_nodeset node_types = ELEMENTS when :ancestor_or_self new_nodeset = [] nodeset.each do |node| if node.node_type == :element new_nodeset << node while ( node.parent ) node = node.parent new_nodeset << node unless new_nodeset.include? node end end end nodeset = new_nodeset node_types = ELEMENTS when :predicate new_nodeset = [] subcontext = { :size => nodeset.size } pred = path_stack.shift nodeset.each_with_index { |node, index| subcontext[ :node ] = node subcontext[ :index ] = index+1 pc = pred.dclone result = expr( pc, [node], subcontext ) result = result[0] if result.kind_of? Array and result.length == 1 if result.kind_of? Numeric new_nodeset << node if result == (index+1) elsif result.instance_of? Array if result.size > 0 and result.inject(false) {|k,s| s or k} new_nodeset << node if result.size > 0 end else new_nodeset << node if result end } nodeset = new_nodeset =begin predicate = path_stack.shift ns = nodeset.clone result = expr( predicate, ns ) if result.kind_of? Array nodeset = result.zip(ns).collect{|m,n| n if m}.compact else nodeset = result ? nodeset : [] end =end when :descendant_or_self rv = descendant_or_self( path_stack, nodeset ) path_stack.clear nodeset = rv node_types = ELEMENTS when :descendant results = [] nt = nil nodeset.each do |node| nt = node.node_type results += expr( path_stack.dclone.unshift( :descendant_or_self ), node.children ) if nt == :element or nt == :document end nodeset = results node_types = ELEMENTS when :following_sibling results = [] nodeset.each do |node| next if node.parent.nil? all_siblings = node.parent.children current_index = all_siblings.index( node ) following_siblings = all_siblings[ current_index+1 .. -1 ] results += expr( path_stack.dclone, following_siblings ) end nodeset = results when :preceding_sibling results = [] nodeset.each do |node| next if node.parent.nil? all_siblings = node.parent.children current_index = all_siblings.index( node ) preceding_siblings = all_siblings[ 0, current_index ].reverse results += preceding_siblings end nodeset = results node_types = ELEMENTS when :preceding new_nodeset = [] nodeset.each do |node| new_nodeset += preceding( node ) end nodeset = new_nodeset node_types = ELEMENTS when :following new_nodeset = [] nodeset.each do |node| new_nodeset += following( node ) end nodeset = new_nodeset node_types = ELEMENTS when :namespace new_nodeset = [] prefix = path_stack.shift nodeset.each do |node| if (node.node_type == :element or node.node_type == :attribute) if @namespaces namespaces = @namespaces elsif (node.node_type == :element) namespaces = node.namespaces else namespaces = node.element.namesapces end if (node.namespace == namespaces[prefix]) new_nodeset << node end end end nodeset = new_nodeset when :variable var_name = path_stack.shift return @variables[ var_name ] # :and, :or, :eq, :neq, :lt, :lteq, :gt, :gteq # TODO: Special case for :or and :and -- not evaluate the right # operand if the left alone determines result (i.e. is true for # :or and false for :and). when :eq, :neq, :lt, :lteq, :gt, :gteq, :or left = expr( path_stack.shift, nodeset.dup, context ) right = expr( path_stack.shift, nodeset.dup, context ) res = equality_relational_compare( left, op, right ) return res when :and left = expr( path_stack.shift, nodeset.dup, context ) return [] unless left if left.respond_to?(:inject) and !left.inject(false) {|a,b| a | b} return [] end right = expr( path_stack.shift, nodeset.dup, context ) res = equality_relational_compare( left, op, right ) return res when :div left = Functions::number(expr(path_stack.shift, nodeset, context)).to_f right = Functions::number(expr(path_stack.shift, nodeset, context)).to_f return (left / right) when :mod left = Functions::number(expr(path_stack.shift, nodeset, context )).to_f right = Functions::number(expr(path_stack.shift, nodeset, context )).to_f return (left % right) when :mult left = Functions::number(expr(path_stack.shift, nodeset, context )).to_f right = Functions::number(expr(path_stack.shift, nodeset, context )).to_f return (left * right) when :plus left = Functions::number(expr(path_stack.shift, nodeset, context )).to_f right = Functions::number(expr(path_stack.shift, nodeset, context )).to_f return (left + right) when :minus left = Functions::number(expr(path_stack.shift, nodeset, context )).to_f right = Functions::number(expr(path_stack.shift, nodeset, context )).to_f return (left - right) when :union left = expr( path_stack.shift, nodeset, context ) right = expr( path_stack.shift, nodeset, context ) return (left | right) when :neg res = expr( path_stack, nodeset, context ) return -(res.to_f) when :not when :function func_name = path_stack.shift.tr('-','_') arguments = path_stack.shift subcontext = context ? nil : { :size => nodeset.size } res = [] cont = context nodeset.each_with_index { |n, i| if subcontext subcontext[:node] = n subcontext[:index] = i cont = subcontext end arg_clone = arguments.dclone args = arg_clone.collect { |arg| expr( arg, [n], cont ) } Functions.context = cont res << Functions.send( func_name, *args ) } return res end end # while return nodeset end ########################################################## # FIXME # The next two methods are BAD MOJO! # This is my achilles heel. If anybody thinks of a better # way of doing this, be my guest. This really sucks, but # it is a wonder it works at all. # ######################################################## def descendant_or_self( path_stack, nodeset ) rs = [] d_o_s( path_stack, nodeset, rs ) document_order(rs.flatten.compact) #rs.flatten.compact end def d_o_s( p, ns, r ) nt = nil ns.each_index do |i| n = ns[i] x = expr( p.dclone, [ n ] ) nt = n.node_type d_o_s( p, n.children, x ) if nt == :element or nt == :document and n.children.size > 0 r.concat(x) if x.size > 0 end end # Reorders an array of nodes so that they are in document order # It tries to do this efficiently. # # FIXME: I need to get rid of this, but the issue is that most of the XPath # interpreter functions as a filter, which means that we lose context going # in and out of function calls. If I knew what the index of the nodes was, # I wouldn't have to do this. Maybe add a document IDX for each node? # Problems with mutable documents. Or, rewrite everything. def document_order( array_of_nodes ) new_arry = [] array_of_nodes.each { |node| node_idx = [] np = node.node_type == :attribute ? node.element : node while np.parent and np.parent.node_type == :element node_idx << np.parent.index( np ) np = np.parent end new_arry << [ node_idx.reverse, node ] } new_arry.sort{ |s1, s2| s1[0] <=> s2[0] }.collect{ |s| s[1] } end def recurse( nodeset, &block ) for node in nodeset yield node recurse( node, &block ) if node.node_type == :element end end # Builds a nodeset of all of the preceding nodes of the supplied node, # in reverse document order # preceding:: includes every element in the document that precedes this node, # except for ancestors def preceding( node ) ancestors = [] p = node.parent while p ancestors << p p = p.parent end acc = [] p = preceding_node_of( node ) while p if ancestors.include? p ancestors.delete(p) else acc << p end p = preceding_node_of( p ) end acc end def preceding_node_of( node ) psn = node.previous_sibling_node if psn.nil? if node.parent.nil? or node.parent.class == Document return nil end return node.parent #psn = preceding_node_of( node.parent ) end while psn and psn.kind_of? Element and psn.children.size > 0 psn = psn.children[-1] end psn end def following( node ) acc = [] p = next_sibling_node( node ) while p acc << p p = following_node_of( p ) end acc end def following_node_of( node ) if node.kind_of? Element and node.children.size > 0 return node.children[0] end return next_sibling_node(node) end def next_sibling_node(node) psn = node.next_sibling_node while psn.nil? if node.parent.nil? or node.parent.class == Document return nil end node = node.parent psn = node.next_sibling_node end return psn end def norm b case b when true, false return b when 'true', 'false' return Functions::boolean( b ) when /^\d+(\.\d+)?$/ return Functions::number( b ) else return Functions::string( b ) end end def equality_relational_compare( set1, op, set2 ) if set1.kind_of? Array and set2.kind_of? Array if set1.size == 1 and set2.size == 1 set1 = set1[0] set2 = set2[0] elsif set1.size == 0 or set2.size == 0 nd = set1.size==0 ? set2 : set1 rv = nd.collect { |il| compare( il, op, nil ) } return rv else res = [] SyncEnumerator.new( set1, set2 ).each { |i1, i2| i1 = norm( i1 ) i2 = norm( i2 ) res << compare( i1, op, i2 ) } return res end end # If one is nodeset and other is number, compare number to each item # in nodeset s.t. number op number(string(item)) # If one is nodeset and other is string, compare string to each item # in nodeset s.t. string op string(item) # If one is nodeset and other is boolean, compare boolean to each item # in nodeset s.t. boolean op boolean(item) if set1.kind_of? Array or set2.kind_of? Array if set1.kind_of? Array a = set1 b = set2 else a = set2 b = set1 end case b when true, false return a.collect {|v| compare( Functions::boolean(v), op, b ) } when Numeric return a.collect {|v| compare( Functions::number(v), op, b )} when /^\d+(\.\d+)?$/ b = Functions::number( b ) return a.collect {|v| compare( Functions::number(v), op, b )} else b = Functions::string( b ) return a.collect { |v| compare( Functions::string(v), op, b ) } end else # If neither is nodeset, # If op is = or != # If either boolean, convert to boolean # If either number, convert to number # Else, convert to string # Else # Convert both to numbers and compare s1 = set1.to_s s2 = set2.to_s if s1 == 'true' or s1 == 'false' or s2 == 'true' or s2 == 'false' set1 = Functions::boolean( set1 ) set2 = Functions::boolean( set2 ) else if op == :eq or op == :neq if s1 =~ /^\d+(\.\d+)?$/ or s2 =~ /^\d+(\.\d+)?$/ set1 = Functions::number( s1 ) set2 = Functions::number( s2 ) else set1 = Functions::string( set1 ) set2 = Functions::string( set2 ) end else set1 = Functions::number( set1 ) set2 = Functions::number( set2 ) end end return compare( set1, op, set2 ) end return false end def compare a, op, b case op when :eq a == b when :neq a != b when :lt a < b when :lteq a <= b when :gt a > b when :gteq a >= b when :and a and b when :or a or b else false end end end end PK!D?2.2.0/rexml/attlistdecl.rbnu[#vim:ts=2 sw=2 noexpandtab: require 'rexml/child' require 'rexml/source' module REXML # This class needs: # * Documentation # * Work! Not all types of attlists are intelligently parsed, so we just # spew back out what we get in. This works, but it would be better if # we formatted the output ourselves. # # AttlistDecls provide *just* enough support to allow namespace # declarations. If you need some sort of generalized support, or have an # interesting idea about how to map the hideous, terrible design of DTD # AttlistDecls onto an intuitive Ruby interface, let me know. I'm desperate # for anything to make DTDs more palateable. class AttlistDecl < Child include Enumerable # What is this? Got me. attr_reader :element_name # Create an AttlistDecl, pulling the information from a Source. Notice # that this isn't very convenient; to create an AttlistDecl, you basically # have to format it yourself, and then have the initializer parse it. # Sorry, but for the forseeable future, DTD support in REXML is pretty # weak on convenience. Have I mentioned how much I hate DTDs? def initialize(source) super() if (source.kind_of? Array) @element_name, @pairs, @contents = *source end end # Access the attlist attribute/value pairs. # value = attlist_decl[ attribute_name ] def [](key) @pairs[key] end # Whether an attlist declaration includes the given attribute definition # if attlist_decl.include? "xmlns:foobar" def include?(key) @pairs.keys.include? key end # Iterate over the key/value pairs: # attlist_decl.each { |attribute_name, attribute_value| ... } def each(&block) @pairs.each(&block) end # Write out exactly what we got in. def write out, indent=-1 out << @contents end def node_type :attlistdecl end end end PK!Y 2.2.0/rexml/child.rbnu[require "rexml/node" module REXML ## # A Child object is something contained by a parent, and this class # contains methods to support that. Most user code will not use this # class directly. class Child include Node attr_reader :parent # The Parent of this object # Constructor. Any inheritors of this class should call super to make # sure this method is called. # parent:: # if supplied, the parent of this child will be set to the # supplied value, and self will be added to the parent def initialize( parent = nil ) @parent = nil # Declare @parent, but don't define it. The next line sets the # parent. parent.add( self ) if parent end # Replaces this object with another object. Basically, calls # Parent.replace_child # # Returns:: self def replace_with( child ) @parent.replace_child( self, child ) self end # Removes this child from the parent. # # Returns:: self def remove unless @parent.nil? @parent.delete self end self end # Sets the parent of this child to the supplied argument. # # other:: # Must be a Parent object. If this object is the same object as the # existing parent of this child, no action is taken. Otherwise, this # child is removed from the current parent (if one exists), and is added # to the new parent. # Returns:: The parent added def parent=( other ) return @parent if @parent == other @parent.delete self if defined? @parent and @parent @parent = other end alias :next_sibling :next_sibling_node alias :previous_sibling :previous_sibling_node # Sets the next sibling of this child. This can be used to insert a child # after some other child. # a = Element.new("a") # b = a.add_element("b") # c = Element.new("c") # b.next_sibling = c # # => def next_sibling=( other ) parent.insert_after self, other end # Sets the previous sibling of this child. This can be used to insert a # child before some other child. # a = Element.new("a") # b = a.add_element("b") # c = Element.new("c") # b.previous_sibling = c # # => def previous_sibling=(other) parent.insert_before self, other end # Returns:: the document this child belongs to, or nil if this child # belongs to no document def document return parent.document unless parent.nil? nil end # This doesn't yet handle encodings def bytes document.encoding to_s end end end PK!d S==2.2.0/rexml/streamlistener.rbnu[module REXML # A template for stream parser listeners. # Note that the declarations (attlistdecl, elementdecl, etc) are trivially # processed; REXML doesn't yet handle doctype entity declarations, so you # have to parse them out yourself. module StreamListener # Called when a tag is encountered. # @p name the tag name # @p attrs an array of arrays of attribute/value pairs, suitable for # use with assoc or rassoc. IE, # will result in # tag_start( "tag", # [["attr1","value1"],["attr2","value2"]]) def tag_start name, attrs end # Called when the end tag is reached. In the case of , tag_end # will be called immediately after tag_start # @p the name of the tag def tag_end name end # Called when text is encountered in the document # @p text the text content. def text text end # Called when an instruction is encountered. EG: # @p name the instruction name; in the example, "xsl" # @p instruction the rest of the instruction. In the example, # "sheet='foo'" def instruction name, instruction end # Called when a comment is encountered. # @p comment The content of the comment def comment comment end # Handles a doctype declaration. Any attributes of the doctype which are # not supplied will be nil. # EG, # @p name the name of the doctype; EG, "me" # @p pub_sys "PUBLIC", "SYSTEM", or nil. EG, "PUBLIC" # @p long_name the supplied long name, or nil. EG, "foo" # @p uri the uri of the doctype, or nil. EG, "bar" def doctype name, pub_sys, long_name, uri end # Called when the doctype is done def doctype_end end # If a doctype includes an ATTLIST declaration, it will cause this # method to be called. The content is the declaration itself, unparsed. # EG, will come to this method as "el # attr CDATA #REQUIRED". This is the same for all of the .*decl # methods. def attlistdecl element_name, attributes, raw_content end # def elementdecl content end # # The argument passed to this method is an array of the entity # declaration. It can be in a number of formats, but in general it # returns (example, result): # # ["YN", "\"Yes\"", "%"] # # ["YN", "Yes", "%"] # # ["WhatHeSaid", "He said %YN;"] # # ["open-hatch", "SYSTEM", "http://www.textuality.com/boilerplate/OpenHatch.xml"] # # ["open-hatch", "PUBLIC", "-//Textuality//TEXT Standard open-hatch boilerplate//EN", "http://www.textuality.com/boilerplate/OpenHatch.xml"] # # ["hatch-pic", "SYSTEM", "../grafix/OpenHatch.gif", "gif"] def entitydecl content end # def notationdecl content end # Called when %foo; is encountered in a doctype declaration. # @p content "foo" def entity content end # Called when is encountered in a document. # @p content "..." def cdata content end # Called when an XML PI is encountered in the document. # EG: # @p version the version attribute value. EG, "1.0" # @p encoding the encoding attribute value, or nil. EG, "utf" # @p standalone the standalone attribute value, or nil. EG, nil def xmldecl version, encoding, standalone end end end PK![%%2.2.0/rexml/document.rbnu[require "rexml/security" require "rexml/element" require "rexml/xmldecl" require "rexml/source" require "rexml/comment" require "rexml/doctype" require "rexml/instruction" require "rexml/rexml" require "rexml/parseexception" require "rexml/output" require "rexml/parsers/baseparser" require "rexml/parsers/streamparser" require "rexml/parsers/treeparser" module REXML # Represents a full XML document, including PIs, a doctype, etc. A # Document has a single child that can be accessed by root(). # Note that if you want to have an XML declaration written for a document # you create, you must add one; REXML documents do not write a default # declaration for you. See |DECLARATION| and |write|. class Document < Element # A convenient default XML declaration. If you want an XML declaration, # the easiest way to add one is mydoc << Document::DECLARATION # +DEPRECATED+ # Use: mydoc << XMLDecl.default DECLARATION = XMLDecl.default # Constructor # @param source if supplied, must be a Document, String, or IO. # Documents have their context and Element attributes cloned. # Strings are expected to be valid XML documents. IOs are expected # to be sources of valid XML documents. # @param context if supplied, contains the context of the document; # this should be a Hash. def initialize( source = nil, context = {} ) @entity_expansion_count = 0 super() @context = context return if source.nil? if source.kind_of? Document @context = source.context super source else build( source ) end end def node_type :document end # Should be obvious def clone Document.new self end # According to the XML spec, a root node has no expanded name def expanded_name '' #d = doc_type #d ? d.name : "UNDEFINED" end alias :name :expanded_name # We override this, because XMLDecls and DocTypes must go at the start # of the document def add( child ) if child.kind_of? XMLDecl if @children[0].kind_of? XMLDecl @children[0] = child else @children.unshift child end child.parent = self elsif child.kind_of? DocType # Find first Element or DocType node and insert the decl right # before it. If there is no such node, just insert the child at the # end. If there is a child and it is an DocType, then replace it. insert_before_index = @children.find_index { |x| x.kind_of?(Element) || x.kind_of?(DocType) } if insert_before_index # Not null = not end of list if @children[ insert_before_index ].kind_of? DocType @children[ insert_before_index ] = child else @children[ insert_before_index-1, 0 ] = child end else # Insert at end of list @children << child end child.parent = self else rv = super raise "attempted adding second root element to document" if @elements.size > 1 rv end end alias :<< :add def add_element(arg=nil, arg2=nil) rv = super raise "attempted adding second root element to document" if @elements.size > 1 rv end # @return the root Element of the document, or nil if this document # has no children. def root elements[1] #self #@children.find { |item| item.kind_of? Element } end # @return the DocType child of the document, if one exists, # and nil otherwise. def doctype @children.find { |item| item.kind_of? DocType } end # @return the XMLDecl of this document; if no XMLDecl has been # set, the default declaration is returned. def xml_decl rv = @children[0] return rv if rv.kind_of? XMLDecl @children.unshift(XMLDecl.default)[0] end # @return the XMLDecl version of this document as a String. # If no XMLDecl has been set, returns the default version. def version xml_decl().version end # @return the XMLDecl encoding of this document as an # Encoding object. # If no XMLDecl has been set, returns the default encoding. def encoding xml_decl().encoding end # @return the XMLDecl standalone value of this document as a String. # If no XMLDecl has been set, returns the default setting. def stand_alone? xml_decl().stand_alone? end # :call-seq: # doc.write(output=$stdout, indent=-1, transtive=false, ie_hack=false, encoding=nil) # doc.write(options={:output => $stdout, :indent => -1, :transtive => false, :ie_hack => false, :encoding => nil}) # # Write the XML tree out, optionally with indent. This writes out the # entire XML document, including XML declarations, doctype declarations, # and processing instructions (if any are given). # # A controversial point is whether Document should always write the XML # declaration () whether or not one is given by the # user (or source document). REXML does not write one if one was not # specified, because it adds unnecessary bandwidth to applications such # as XML-RPC. # # Accept Nth argument style and options Hash style as argument. # The recommended style is options Hash style for one or more # arguments case. # # _Examples_ # Document.new("").write # # output = "" # Document.new("").write(output) # # output = "" # Document.new("").write(:output => output, :indent => 2) # # See also the classes in the rexml/formatters package for the proper way # to change the default formatting of XML output. # # _Examples_ # # output = "" # tr = Transitive.new # tr.write(Document.new(""), output) # # output:: # output an object which supports '<< string'; this is where the # document will be written. # indent:: # An integer. If -1, no indenting will be used; otherwise, the # indentation will be twice this number of spaces, and children will be # indented an additional amount. For a value of 3, every item will be # indented 3 more levels, or 6 more spaces (2 * 3). Defaults to -1 # transitive:: # If transitive is true and indent is >= 0, then the output will be # pretty-printed in such a way that the added whitespace does not affect # the absolute *value* of the document -- that is, it leaves the value # and number of Text nodes in the document unchanged. # ie_hack:: # This hack inserts a space before the /> on empty tags to address # a limitation of Internet Explorer. Defaults to false # encoding:: # Encoding name as String. Change output encoding to specified encoding # instead of encoding in XML declaration. # Defaults to nil. It means encoding in XML declaration is used. def write(*arguments) if arguments.size == 1 and arguments[0].class == Hash options = arguments[0] output = options[:output] indent = options[:indent] transitive = options[:transitive] ie_hack = options[:ie_hack] encoding = options[:encoding] else output, indent, transitive, ie_hack, encoding, = *arguments end output ||= $stdout indent ||= -1 transitive = false if transitive.nil? ie_hack = false if ie_hack.nil? encoding ||= xml_decl.encoding if encoding != 'UTF-8' && !output.kind_of?(Output) output = Output.new( output, encoding ) end formatter = if indent > -1 if transitive require "rexml/formatters/transitive" REXML::Formatters::Transitive.new( indent, ie_hack ) else REXML::Formatters::Pretty.new( indent, ie_hack ) end else REXML::Formatters::Default.new( ie_hack ) end formatter.write( self, output ) end def Document::parse_stream( source, listener ) Parsers::StreamParser.new( source, listener ).parse end # Set the entity expansion limit. By default the limit is set to 10000. # # Deprecated. Use REXML::Security.entity_expansion_limit= instead. def Document::entity_expansion_limit=( val ) Security.entity_expansion_limit = val end # Get the entity expansion limit. By default the limit is set to 10000. # # Deprecated. Use REXML::Security.entity_expansion_limit= instead. def Document::entity_expansion_limit return Security.entity_expansion_limit end # Set the entity expansion limit. By default the limit is set to 10240. # # Deprecated. Use REXML::Security.entity_expansion_text_limit= instead. def Document::entity_expansion_text_limit=( val ) Security.entity_expansion_text_limit = val end # Get the entity expansion limit. By default the limit is set to 10240. # # Deprecated. Use REXML::Security.entity_expansion_text_limit instead. def Document::entity_expansion_text_limit return Security.entity_expansion_text_limit end attr_reader :entity_expansion_count def record_entity_expansion @entity_expansion_count += 1 if @entity_expansion_count > Security.entity_expansion_limit raise "number of entity expansions exceeded, processing aborted." end end def document self end private def build( source ) Parsers::TreeParser.new( source, self ).parse end end end PK!nNN2.2.0/rexml/sax2listener.rbnu[module REXML # A template for stream parser listeners. # Note that the declarations (attlistdecl, elementdecl, etc) are trivially # processed; REXML doesn't yet handle doctype entity declarations, so you # have to parse them out yourself. # === Missing methods from SAX2 # ignorable_whitespace # === Methods extending SAX2 # +WARNING+ # These methods are certainly going to change, until DTDs are fully # supported. Be aware of this. # start_document # end_document # doctype # elementdecl # attlistdecl # entitydecl # notationdecl # cdata # xmldecl # comment module SAX2Listener def start_document end def end_document end def start_prefix_mapping prefix, uri end def end_prefix_mapping prefix end def start_element uri, localname, qname, attributes end def end_element uri, localname, qname end def characters text end def processing_instruction target, data end # Handles a doctype declaration. Any attributes of the doctype which are # not supplied will be nil. # EG, # @p name the name of the doctype; EG, "me" # @p pub_sys "PUBLIC", "SYSTEM", or nil. EG, "PUBLIC" # @p long_name the supplied long name, or nil. EG, "foo" # @p uri the uri of the doctype, or nil. EG, "bar" def doctype name, pub_sys, long_name, uri end # If a doctype includes an ATTLIST declaration, it will cause this # method to be called. The content is the declaration itself, unparsed. # EG, will come to this method as "el # attr CDATA #REQUIRED". This is the same for all of the .*decl # methods. def attlistdecl(element, pairs, contents) end # def elementdecl content end # # The argument passed to this method is an array of the entity # declaration. It can be in a number of formats, but in general it # returns (example, result): # # ["%", "YN", "\"Yes\""] # # ["%", "YN", "Yes"] # # ["WhatHeSaid", "He said %YN;"] # # ["open-hatch", "SYSTEM", "http://www.textuality.com/boilerplate/OpenHatch.xml"] # # ["open-hatch", "PUBLIC", "-//Textuality//TEXT Standard open-hatch boilerplate//EN", "http://www.textuality.com/boilerplate/OpenHatch.xml"] # # ["hatch-pic", "SYSTEM", "../grafix/OpenHatch.gif", "NDATA", "gif"] def entitydecl declaration end # def notationdecl name, public_or_system, public_id, system_id end # Called when is encountered in a document. # @p content "..." def cdata content end # Called when an XML PI is encountered in the document. # EG: # @p version the version attribute value. EG, "1.0" # @p encoding the encoding attribute value, or nil. EG, "utf" # @p standalone the standalone attribute value, or nil. EG, nil # @p spaced the declaration is followed by a line break def xmldecl version, encoding, standalone end # Called when a comment is encountered. # @p comment The content of the comment def comment comment end def progress position end end end PK! *nn2.2.0/rexml/source.rbnu[# coding: US-ASCII require 'rexml/encoding' module REXML # Generates Source-s. USE THIS CLASS. class SourceFactory # Generates a Source object # @param arg Either a String, or an IO # @return a Source, or nil if a bad argument was given def SourceFactory::create_from(arg) if arg.respond_to? :read and arg.respond_to? :readline and arg.respond_to? :nil? and arg.respond_to? :eof? IOSource.new(arg) elsif arg.respond_to? :to_str require 'stringio' IOSource.new(StringIO.new(arg)) elsif arg.kind_of? Source arg else raise "#{arg.class} is not a valid input stream. It must walk \n"+ "like either a String, an IO, or a Source." end end end # A Source can be searched for patterns, and wraps buffers and other # objects and provides consumption of text class Source include Encoding # The current buffer (what we're going to read next) attr_reader :buffer # The line number of the last consumed text attr_reader :line attr_reader :encoding # Constructor # @param arg must be a String, and should be a valid XML document # @param encoding if non-null, sets the encoding of the source to this # value, overriding all encoding detection def initialize(arg, encoding=nil) @orig = @buffer = arg if encoding self.encoding = encoding else detect_encoding end @line = 0 end # Inherited from Encoding # Overridden to support optimized en/decoding def encoding=(enc) return unless super encoding_updated end # Scans the source for a given pattern. Note, that this is not your # usual scan() method. For one thing, the pattern argument has some # requirements; for another, the source can be consumed. You can easily # confuse this method. Originally, the patterns were easier # to construct and this method more robust, because this method # generated search regexps on the fly; however, this was # computationally expensive and slowed down the entire REXML package # considerably, since this is by far the most commonly called method. # @param pattern must be a Regexp, and must be in the form of # /^\s*(#{your pattern, with no groups})(.*)/. The first group # will be returned; the second group is used if the consume flag is # set. # @param consume if true, the pattern returned will be consumed, leaving # everything after it in the Source. # @return the pattern, if found, or nil if the Source is empty or the # pattern is not found. def scan(pattern, cons=false) return nil if @buffer.nil? rv = @buffer.scan(pattern) @buffer = $' if cons and rv.size>0 rv end def read end def consume( pattern ) @buffer = $' if pattern.match( @buffer ) end def match_to( char, pattern ) return pattern.match(@buffer) end def match_to_consume( char, pattern ) md = pattern.match(@buffer) @buffer = $' return md end def match(pattern, cons=false) md = pattern.match(@buffer) @buffer = $' if cons and md return md end # @return true if the Source is exhausted def empty? @buffer == "" end def position @orig.index( @buffer ) end # @return the current line in the source def current_line lines = @orig.split res = lines.grep @buffer[0..30] res = res[-1] if res.kind_of? Array lines.index( res ) if res end private def detect_encoding buffer_encoding = @buffer.encoding detected_encoding = "UTF-8" begin @buffer.force_encoding("ASCII-8BIT") if @buffer[0, 2] == "\xfe\xff" @buffer[0, 2] = "" detected_encoding = "UTF-16BE" elsif @buffer[0, 2] == "\xff\xfe" @buffer[0, 2] = "" detected_encoding = "UTF-16LE" elsif @buffer[0, 3] == "\xef\xbb\xbf" @buffer[0, 3] = "" detected_encoding = "UTF-8" end ensure @buffer.force_encoding(buffer_encoding) end self.encoding = detected_encoding end def encoding_updated if @encoding != 'UTF-8' @buffer = decode(@buffer) @to_utf = true else @to_utf = false @buffer.force_encoding ::Encoding::UTF_8 end end end # A Source that wraps an IO. See the Source class for method # documentation class IOSource < Source #attr_reader :block_size # block_size has been deprecated def initialize(arg, block_size=500, encoding=nil) @er_source = @source = arg @to_utf = false @pending_buffer = nil if encoding super("", encoding) else super(@source.read(3) || "") end if !@to_utf and @buffer.respond_to?(:force_encoding) and @source.respond_to?(:external_encoding) and @source.external_encoding != ::Encoding::UTF_8 @force_utf8 = true else @force_utf8 = false end end def scan(pattern, cons=false) rv = super # You'll notice that this next section is very similar to the same # section in match(), but just a liiittle different. This is # because it is a touch faster to do it this way with scan() # than the way match() does it; enough faster to warrent duplicating # some code if rv.size == 0 until @buffer =~ pattern or @source.nil? begin @buffer << readline rescue Iconv::IllegalSequence raise rescue @source = nil end end rv = super end rv.taint rv end def read begin @buffer << readline rescue Exception, NameError @source = nil end end def consume( pattern ) match( pattern, true ) end def match( pattern, cons=false ) rv = pattern.match(@buffer) @buffer = $' if cons and rv while !rv and @source begin @buffer << readline rv = pattern.match(@buffer) @buffer = $' if cons and rv rescue @source = nil end end rv.taint rv end def empty? super and ( @source.nil? || @source.eof? ) end def position @er_source.pos rescue 0 end # @return the current line in the source def current_line begin pos = @er_source.pos # The byte position in the source lineno = @er_source.lineno # The XML < position in the source @er_source.rewind line = 0 # The \r\n position in the source begin while @er_source.pos < pos @er_source.readline line += 1 end rescue end rescue IOError pos = -1 line = -1 end [pos, lineno, line] end private def readline str = @source.readline(@line_break) if @pending_buffer if str.nil? str = @pending_buffer else str = @pending_buffer + str end @pending_buffer = nil end return nil if str.nil? if @to_utf decode(str) else str.force_encoding(::Encoding::UTF_8) if @force_utf8 str end end def encoding_updated case @encoding when "UTF-16BE", "UTF-16LE" @source.binmode @source.set_encoding(@encoding, @encoding) end @line_break = encode(">") @pending_buffer, @buffer = @buffer, "" @pending_buffer.force_encoding(@encoding) super end end end PK!dLL2.2.0/rexml/comment.rbnu[require "rexml/child" module REXML ## # Represents an XML comment; that is, text between \ class Comment < Child include Comparable START = "" # The content text attr_accessor :string ## # Constructor. The first argument can be one of three types: # @param first If String, the contents of this comment are set to the # argument. If Comment, the argument is duplicated. If # Source, the argument is scanned for a comment. # @param second If the first argument is a Source, this argument # should be nil, not supplied, or a Parent to be set as the parent # of this object def initialize( first, second = nil ) super(second) if first.kind_of? String @string = first elsif first.kind_of? Comment @string = first.string end end def clone Comment.new self end # == DEPRECATED # See REXML::Formatters # # output:: # Where to write the string # indent:: # An integer. If -1, no indenting will be used; otherwise, the # indentation will be this number of spaces, and children will be # indented an additional amount. # transitive:: # Ignored by this class. The contents of comments are never modified. # ie_hack:: # Needed for conformity to the child API, but not used by this class. def write( output, indent=-1, transitive=false, ie_hack=false ) Kernel.warn("Comment.write is deprecated. See REXML::Formatters") indent( output, indent ) output << START output << @string output << STOP end alias :to_s :string ## # Compares this Comment to another; the contents of the comment are used # in the comparison. def <=>(other) other.to_s <=> @string end ## # Compares this Comment to another; the contents of the comment are used # in the comparison. def ==( other ) other.kind_of? Comment and (other <=> self) == 0 end def node_type :comment end end end #vim:ts=2 sw=2 noexpandtab: PK!_Ks2.2.0/rexml/light/node.rbnu[require 'rexml/xmltokens' # [ :element, parent, name, attributes, children* ] # a = Node.new # a << "B" # => B # a.b # => B # a.b[1] # => B # a.b[1]["x"] = "y" # => B # a.b[0].c # => B # a.b.c << "D" # => BD module REXML module Light # Represents a tagged XML element. Elements are characterized by # having children, attributes, and names, and can themselves be # children. class Node NAMESPLIT = /^(?:(#{XMLTokens::NCNAME_STR}):)?(#{XMLTokens::NCNAME_STR})/u PARENTS = [ :element, :document, :doctype ] # Create a new element. def initialize node=nil @node = node if node.kind_of? String node = [ :text, node ] elsif node.nil? node = [ :document, nil, nil ] elsif node[0] == :start_element node[0] = :element elsif node[0] == :start_doctype node[0] = :doctype elsif node[0] == :start_document node[0] = :document end end def size if PARENTS.include? @node[0] @node[-1].size else 0 end end def each size.times { |x| yield( at(x+4) ) } end def name at(2) end def name=( name_str, ns=nil ) pfx = '' pfx = "#{prefix(ns)}:" if ns _old_put(2, "#{pfx}#{name_str}") end def parent=( node ) _old_put(1,node) end def local_name namesplit @name end def local_name=( name_str ) _old_put( 1, "#@prefix:#{name_str}" ) end def prefix( namespace=nil ) prefix_of( self, namespace ) end def namespace( prefix=prefix() ) namespace_of( self, prefix ) end def namespace=( namespace ) @prefix = prefix( namespace ) pfx = '' pfx = "#@prefix:" if @prefix.size > 0 _old_put(1, "#{pfx}#@name") end def []( reference, ns=nil ) if reference.kind_of? String pfx = '' pfx = "#{prefix(ns)}:" if ns at(3)["#{pfx}#{reference}"] elsif reference.kind_of? Range _old_get( Range.new(4+reference.begin, reference.end, reference.exclude_end?) ) else _old_get( 4+reference ) end end def =~( path ) XPath.match( self, path ) end # Doesn't handle namespaces yet def []=( reference, ns, value=nil ) if reference.kind_of? String value = ns unless value at( 3 )[reference] = value elsif reference.kind_of? Range _old_put( Range.new(3+reference.begin, reference.end, reference.exclude_end?), ns ) else if value _old_put( 4+reference, ns, value ) else _old_put( 4+reference, ns ) end end end # Append a child to this element, optionally under a provided namespace. # The namespace argument is ignored if the element argument is an Element # object. Otherwise, the element argument is a string, the namespace (if # provided) is the namespace the element is created in. def << element if node_type() == :text at(-1) << element else newnode = Node.new( element ) newnode.parent = self self.push( newnode ) end at(-1) end def node_type _old_get(0) end def text=( foo ) replace = at(4).kind_of?(String)? 1 : 0 self._old_put(4,replace, normalizefoo) end def root context = self context = context.at(1) while context.at(1) end def has_name?( name, namespace = '' ) at(3) == name and namespace() == namespace end def children self end def parent at(1) end def to_s end private def namesplit return if @name.defined? at(2) =~ NAMESPLIT @prefix = '' || $1 @name = $2 end def namespace_of( node, prefix=nil ) if not prefix name = at(2) name =~ NAMESPLIT prefix = $1 end to_find = 'xmlns' to_find = "xmlns:#{prefix}" if not prefix.nil? ns = at(3)[ to_find ] ns ? ns : namespace_of( @node[0], prefix ) end def prefix_of( node, namespace=nil ) if not namespace name = node.name name =~ NAMESPLIT $1 else ns = at(3).find { |k,v| v == namespace } ns ? ns : prefix_of( node.parent, namespace ) end end end end end PK!>O{- - 2.2.0/rexml/xmltokens.rbnu[module REXML # Defines a number of tokens used for parsing XML. Not for general # consumption. module XMLTokens # From http://www.w3.org/TR/REC-xml/#sec-common-syn # # [4] NameStartChar ::= # ":" | # [A-Z] | # "_" | # [a-z] | # [#xC0-#xD6] | # [#xD8-#xF6] | # [#xF8-#x2FF] | # [#x370-#x37D] | # [#x37F-#x1FFF] | # [#x200C-#x200D] | # [#x2070-#x218F] | # [#x2C00-#x2FEF] | # [#x3001-#xD7FF] | # [#xF900-#xFDCF] | # [#xFDF0-#xFFFD] | # [#x10000-#xEFFFF] name_start_chars = [ ":", "A-Z", "_", "a-z", "\\u00C0-\\u00D6", "\\u00D8-\\u00F6", "\\u00F8-\\u02FF", "\\u0370-\\u037D", "\\u037F-\\u1FFF", "\\u200C-\\u200D", "\\u2070-\\u218F", "\\u2C00-\\u2FEF", "\\u3001-\\uD7FF", "\\uF900-\\uFDCF", "\\uFDF0-\\uFFFD", "\\u{10000}-\\u{EFFFF}", ] # From http://www.w3.org/TR/REC-xml/#sec-common-syn # # [4a] NameChar ::= # NameStartChar | # "-" | # "." | # [0-9] | # #xB7 | # [#x0300-#x036F] | # [#x203F-#x2040] name_chars = name_start_chars + [ "\\-", "\\.", "0-9", "\\u00B7", "\\u0300-\\u036F", "\\u203F-\\u2040", ] NAME_START_CHAR = "[#{name_start_chars.join('')}]" NAME_CHAR = "[#{name_chars.join('')}]" NAMECHAR = NAME_CHAR # deprecated. Use NAME_CHAR instead. # From http://www.w3.org/TR/xml-names11/#NT-NCName # # [6] NCNameStartChar ::= NameStartChar - ':' ncname_start_chars = name_start_chars - [":"] # From http://www.w3.org/TR/xml-names11/#NT-NCName # # [5] NCNameChar ::= NameChar - ':' ncname_chars = name_chars - [":"] NCNAME_STR = "[#{ncname_start_chars.join('')}][#{ncname_chars.join('')}]*" NAME_STR = "(?:#{NCNAME_STR}:)?#{NCNAME_STR}" NAME = "(#{NAME_START_CHAR}#{NAME_CHAR}*)" NMTOKEN = "(?:#{NAME_CHAR})+" NMTOKENS = "#{NMTOKEN}(\\s+#{NMTOKEN})*" REFERENCE = "(?:&#{NAME};|&#\\d+;|&#x[0-9a-fA-F]+;)" #REFERENCE = "(?:#{ENTITYREF}|#{CHARREF})" #ENTITYREF = "&#{NAME};" #CHARREF = "&#\\d+;|&#x[0-9a-fA-F]+;" end end PK!:2.2.0/rexml/encoding.rbnu[# coding: US-ASCII module REXML module Encoding # ID ---> Encoding name attr_reader :encoding def encoding=(encoding) encoding = encoding.name if encoding.is_a?(Encoding) if encoding.is_a?(String) original_encoding = encoding encoding = find_encoding(encoding) unless encoding raise ArgumentError, "Bad encoding name #{original_encoding}" end end return false if defined?(@encoding) and encoding == @encoding if encoding @encoding = encoding.upcase else @encoding = 'UTF-8' end true end def encode(string) string.encode(@encoding) end def decode(string) string.encode(::Encoding::UTF_8, @encoding) end private def find_encoding(name) case name when /\Ashift-jis\z/i return "SHIFT_JIS" when /\ACP-(\d+)\z/ name = "CP#{$1}" when /\AUTF-8\z/i return name end begin ::Encoding::Converter.search_convpath(name, 'UTF-8') rescue ::Encoding::ConverterNotFoundError return nil end name end end end PK!=_y@ @ 2.2.0/rexml/xpath.rbnu[require 'rexml/functions' require 'rexml/xpath_parser' module REXML # Wrapper class. Use this class to access the XPath functions. class XPath include Functions # A base Hash object, supposing to be used when initializing a # default empty namespaces set, but is currently unused. # TODO: either set the namespaces=EMPTY_HASH, or deprecate this. EMPTY_HASH = {} # Finds and returns the first node that matches the supplied xpath. # element:: # The context element # path:: # The xpath to search for. If not supplied or nil, returns the first # node matching '*'. # namespaces:: # If supplied, a Hash which defines a namespace mapping. # variables:: # If supplied, a Hash which maps $variables in the query # to values. This can be used to avoid XPath injection attacks # or to automatically handle escaping string values. # # XPath.first( node ) # XPath.first( doc, "//b"} ) # XPath.first( node, "a/x:b", { "x"=>"http://doofus" } ) # XPath.first( node, '/book/publisher/text()=$publisher', {}, {"publisher"=>"O'Reilly"}) def XPath::first element, path=nil, namespaces=nil, variables={} raise "The namespaces argument, if supplied, must be a hash object." unless namespaces.nil? or namespaces.kind_of?(Hash) raise "The variables argument, if supplied, must be a hash object." unless variables.kind_of?(Hash) parser = XPathParser.new parser.namespaces = namespaces parser.variables = variables path = "*" unless path element = [element] unless element.kind_of? Array parser.parse(path, element).flatten[0] end # Iterates over nodes that match the given path, calling the supplied # block with the match. # element:: # The context element # path:: # The xpath to search for. If not supplied or nil, defaults to '*' # namespaces:: # If supplied, a Hash which defines a namespace mapping # variables:: # If supplied, a Hash which maps $variables in the query # to values. This can be used to avoid XPath injection attacks # or to automatically handle escaping string values. # # XPath.each( node ) { |el| ... } # XPath.each( node, '/*[@attr='v']' ) { |el| ... } # XPath.each( node, 'ancestor::x' ) { |el| ... } # XPath.each( node, '/book/publisher/text()=$publisher', {}, {"publisher"=>"O'Reilly"}) \ # {|el| ... } def XPath::each element, path=nil, namespaces=nil, variables={}, &block raise "The namespaces argument, if supplied, must be a hash object." unless namespaces.nil? or namespaces.kind_of?(Hash) raise "The variables argument, if supplied, must be a hash object." unless variables.kind_of?(Hash) parser = XPathParser.new parser.namespaces = namespaces parser.variables = variables path = "*" unless path element = [element] unless element.kind_of? Array parser.parse(path, element).each( &block ) end # Returns an array of nodes matching a given XPath. def XPath::match element, path=nil, namespaces=nil, variables={} parser = XPathParser.new parser.namespaces = namespaces parser.variables = variables path = "*" unless path element = [element] unless element.kind_of? Array parser.parse(path,element) end end end PK!7(2.2.0/rexml/security.rbnu[module REXML module Security @@entity_expansion_limit = 10_000 # Set the entity expansion limit. By default the limit is set to 10000. def self.entity_expansion_limit=( val ) @@entity_expansion_limit = val end # Get the entity expansion limit. By default the limit is set to 10000. def self.entity_expansion_limit return @@entity_expansion_limit end @@entity_expansion_text_limit = 10_240 # Set the entity expansion limit. By default the limit is set to 10240. def self.entity_expansion_text_limit=( val ) @@entity_expansion_text_limit = val end # Get the entity expansion limit. By default the limit is set to 10240. def self.entity_expansion_text_limit return @@entity_expansion_text_limit end end end PK!Ͳvss2.2.0/rexml/element.rbnu[require "rexml/parent" require "rexml/namespace" require "rexml/attribute" require "rexml/cdata" require "rexml/xpath" require "rexml/parseexception" module REXML # An implementation note about namespaces: # As we parse, when we find namespaces we put them in a hash and assign # them a unique ID. We then convert the namespace prefix for the node # to the unique ID. This makes namespace lookup much faster for the # cost of extra memory use. We save the namespace prefix for the # context node and convert it back when we write it. @@namespaces = {} # Represents a tagged XML element. Elements are characterized by # having children, attributes, and names, and can themselves be # children. class Element < Parent include Namespace UNDEFINED = "UNDEFINED"; # The default name # Mechanisms for accessing attributes and child elements of this # element. attr_reader :attributes, :elements # The context holds information about the processing environment, such as # whitespace handling. attr_accessor :context # Constructor # arg:: # if not supplied, will be set to the default value. # If a String, the name of this object will be set to the argument. # If an Element, the object will be shallowly cloned; name, # attributes, and namespaces will be copied. Children will +not+ be # copied. # parent:: # if supplied, must be a Parent, and will be used as # the parent of this object. # context:: # If supplied, must be a hash containing context items. Context items # include: # * :respect_whitespace the value of this is :+all+ or an array of # strings being the names of the elements to respect # whitespace for. Defaults to :+all+. # * :compress_whitespace the value can be :+all+ or an array of # strings being the names of the elements to ignore whitespace on. # Overrides :+respect_whitespace+. # * :ignore_whitespace_nodes the value can be :+all+ or an array # of strings being the names of the elements in which to ignore # whitespace-only nodes. If this is set, Text nodes which contain only # whitespace will not be added to the document tree. # * :raw can be :+all+, or an array of strings being the names of # the elements to process in raw mode. In raw mode, special # characters in text is not converted to or from entities. def initialize( arg = UNDEFINED, parent=nil, context=nil ) super(parent) @elements = Elements.new(self) @attributes = Attributes.new(self) @context = context if arg.kind_of? String self.name = arg elsif arg.kind_of? Element self.name = arg.expanded_name arg.attributes.each_attribute{ |attribute| @attributes << Attribute.new( attribute ) } @context = arg.context end end def inspect rv = "<#@expanded_name" @attributes.each_attribute do |attr| rv << " " attr.write( rv, 0 ) end if children.size > 0 rv << "> ... " else rv << "/>" end end # Creates a shallow copy of self. # d = Document.new "" # new_a = d.root.clone # puts new_a # => "" def clone self.class.new self end # Evaluates to the root node of the document that this element # belongs to. If this element doesn't belong to a document, but does # belong to another Element, the parent's root will be returned, until the # earliest ancestor is found. # # Note that this is not the same as the document element. # In the following example, is the document element, and the root # node is the parent node of the document element. You may ask yourself # why the root node is useful: consider the doctype and XML declaration, # and any processing instructions before the document element... they # are children of the root node, or siblings of the document element. # The only time this isn't true is when an Element is created that is # not part of any Document. In this case, the ancestor that has no # parent acts as the root node. # d = Document.new '' # a = d[1] ; c = a[1][1] # d.root_node == d # TRUE # a.root_node # namely, d # c.root_node # again, d def root_node parent.nil? ? self : parent.root_node end def root return elements[1] if self.kind_of? Document return self if parent.kind_of? Document or parent.nil? return parent.root end # Evaluates to the document to which this element belongs, or nil if this # element doesn't belong to a document. def document rt = root rt.parent if rt end # Evaluates to +true+ if whitespace is respected for this element. This # is the case if: # 1. Neither :+respect_whitespace+ nor :+compress_whitespace+ has any value # 2. The context has :+respect_whitespace+ set to :+all+ or # an array containing the name of this element, and # :+compress_whitespace+ isn't set to :+all+ or an array containing the # name of this element. # The evaluation is tested against +expanded_name+, and so is namespace # sensitive. def whitespace @whitespace = nil if @context if @context[:respect_whitespace] @whitespace = (@context[:respect_whitespace] == :all or @context[:respect_whitespace].include? expanded_name) end @whitespace = false if (@context[:compress_whitespace] and (@context[:compress_whitespace] == :all or @context[:compress_whitespace].include? expanded_name) ) end @whitespace = true unless @whitespace == false @whitespace end def ignore_whitespace_nodes @ignore_whitespace_nodes = false if @context if @context[:ignore_whitespace_nodes] @ignore_whitespace_nodes = (@context[:ignore_whitespace_nodes] == :all or @context[:ignore_whitespace_nodes].include? expanded_name) end end end # Evaluates to +true+ if raw mode is set for this element. This # is the case if the context has :+raw+ set to :+all+ or # an array containing the name of this element. # # The evaluation is tested against +expanded_name+, and so is namespace # sensitive. def raw @raw = (@context and @context[:raw] and (@context[:raw] == :all or @context[:raw].include? expanded_name)) @raw end #once :whitespace, :raw, :ignore_whitespace_nodes ################################################# # Namespaces # ################################################# # Evaluates to an +Array+ containing the prefixes (names) of all defined # namespaces at this context node. # doc = Document.new("") # doc.elements['//b'].prefixes # -> ['x', 'y'] def prefixes prefixes = [] prefixes = parent.prefixes if parent prefixes |= attributes.prefixes return prefixes end def namespaces namespaces = {} namespaces = parent.namespaces if parent namespaces = namespaces.merge( attributes.namespaces ) return namespaces end # Evaluates to the URI for a prefix, or the empty string if no such # namespace is declared for this element. Evaluates recursively for # ancestors. Returns the default namespace, if there is one. # prefix:: # the prefix to search for. If not supplied, returns the default # namespace if one exists # Returns:: # the namespace URI as a String, or nil if no such namespace # exists. If the namespace is undefined, returns an empty string # doc = Document.new("") # b = doc.elements['//b'] # b.namespace # -> '1' # b.namespace("y") # -> '2' def namespace(prefix=nil) if prefix.nil? prefix = prefix() end if prefix == '' prefix = "xmlns" else prefix = "xmlns:#{prefix}" unless prefix[0,5] == 'xmlns' end ns = attributes[ prefix ] ns = parent.namespace(prefix) if ns.nil? and parent ns = '' if ns.nil? and prefix == 'xmlns' return ns end # Adds a namespace to this element. # prefix:: # the prefix string, or the namespace URI if +uri+ is not # supplied # uri:: # the namespace URI. May be nil, in which +prefix+ is used as # the URI # Evaluates to: this Element # a = Element.new("a") # a.add_namespace("xmlns:foo", "bar" ) # a.add_namespace("foo", "bar") # shorthand for previous line # a.add_namespace("twiddle") # puts a #-> def add_namespace( prefix, uri=nil ) unless uri @attributes["xmlns"] = prefix else prefix = "xmlns:#{prefix}" unless prefix =~ /^xmlns:/ @attributes[ prefix ] = uri end self end # Removes a namespace from this node. This only works if the namespace is # actually declared in this node. If no argument is passed, deletes the # default namespace. # # Evaluates to: this element # doc = Document.new "" # doc.root.delete_namespace # puts doc # -> # doc.root.delete_namespace 'foo' # puts doc # -> def delete_namespace namespace="xmlns" namespace = "xmlns:#{namespace}" unless namespace == 'xmlns' attribute = attributes.get_attribute(namespace) attribute.remove unless attribute.nil? self end ################################################# # Elements # ################################################# # Adds a child to this element, optionally setting attributes in # the element. # element:: # optional. If Element, the element is added. # Otherwise, a new Element is constructed with the argument (see # Element.initialize). # attrs:: # If supplied, must be a Hash containing String name,value # pairs, which will be used to set the attributes of the new Element. # Returns:: the Element that was added # el = doc.add_element 'my-tag' # el = doc.add_element 'my-tag', {'attr1'=>'val1', 'attr2'=>'val2'} # el = Element.new 'my-tag' # doc.add_element el def add_element element, attrs=nil raise "First argument must be either an element name, or an Element object" if element.nil? el = @elements.add(element) attrs.each do |key, value| el.attributes[key]=value end if attrs.kind_of? Hash el end # Deletes a child element. # element:: # Must be an +Element+, +String+, or +Integer+. If Element, # the element is removed. If String, the element is found (via XPath) # and removed. This means that any parent can remove any # descendant. If Integer, the Element indexed by that number will be # removed. # Returns:: the element that was removed. # doc.delete_element "/a/b/c[@id='4']" # doc.delete_element doc.elements["//k"] # doc.delete_element 1 def delete_element element @elements.delete element end # Evaluates to +true+ if this element has at least one child Element # doc = Document.new "Text" # doc.root.has_elements # -> true # doc.elements["/a/b"].has_elements # -> false # doc.elements["/a/c"].has_elements # -> false def has_elements? !@elements.empty? end # Iterates through the child elements, yielding for each Element that # has a particular attribute set. # key:: # the name of the attribute to search for # value:: # the value of the attribute # max:: # (optional) causes this method to return after yielding # for this number of matching children # name:: # (optional) if supplied, this is an XPath that filters # the children to check. # # doc = Document.new "" # # Yields b, c, d # doc.root.each_element_with_attribute( 'id' ) {|e| p e} # # Yields b, d # doc.root.each_element_with_attribute( 'id', '1' ) {|e| p e} # # Yields b # doc.root.each_element_with_attribute( 'id', '1', 1 ) {|e| p e} # # Yields d # doc.root.each_element_with_attribute( 'id', '1', 0, 'd' ) {|e| p e} def each_element_with_attribute( key, value=nil, max=0, name=nil, &block ) # :yields: Element each_with_something( proc {|child| if value.nil? child.attributes[key] != nil else child.attributes[key]==value end }, max, name, &block ) end # Iterates through the children, yielding for each Element that # has a particular text set. # text:: # the text to search for. If nil, or not supplied, will iterate # over all +Element+ children that contain at least one +Text+ node. # max:: # (optional) causes this method to return after yielding # for this number of matching children # name:: # (optional) if supplied, this is an XPath that filters # the children to check. # # doc = Document.new 'bbd' # # Yields b, c, d # doc.each_element_with_text {|e|p e} # # Yields b, c # doc.each_element_with_text('b'){|e|p e} # # Yields b # doc.each_element_with_text('b', 1){|e|p e} # # Yields d # doc.each_element_with_text(nil, 0, 'd'){|e|p e} def each_element_with_text( text=nil, max=0, name=nil, &block ) # :yields: Element each_with_something( proc {|child| if text.nil? child.has_text? else child.text == text end }, max, name, &block ) end # Synonym for Element.elements.each def each_element( xpath=nil, &block ) # :yields: Element @elements.each( xpath, &block ) end # Synonym for Element.to_a # This is a little slower than calling elements.each directly. # xpath:: any XPath by which to search for elements in the tree # Returns:: an array of Elements that match the supplied path def get_elements( xpath ) @elements.to_a( xpath ) end # Returns the next sibling that is an element, or nil if there is # no Element sibling after this one # doc = Document.new 'text' # doc.root.elements['b'].next_element #-> # doc.root.elements['c'].next_element #-> nil def next_element element = next_sibling element = element.next_sibling until element.nil? or element.kind_of? Element return element end # Returns the previous sibling that is an element, or nil if there is # no Element sibling prior to this one # doc = Document.new 'text' # doc.root.elements['c'].previous_element #-> # doc.root.elements['b'].previous_element #-> nil def previous_element element = previous_sibling element = element.previous_sibling until element.nil? or element.kind_of? Element return element end ################################################# # Text # ################################################# # Evaluates to +true+ if this element has at least one Text child def has_text? not text().nil? end # A convenience method which returns the String value of the _first_ # child text element, if one exists, and +nil+ otherwise. # # Note that an element may have multiple Text elements, perhaps # separated by other children. Be aware that this method only returns # the first Text node. # # This method returns the +value+ of the first text child node, which # ignores the +raw+ setting, so always returns normalized text. See # the Text::value documentation. # # doc = Document.new "

    some text this is bold! more text

    " # # The element 'p' has two text elements, "some text " and " more text". # doc.root.text #-> "some text " def text( path = nil ) rv = get_text(path) return rv.value unless rv.nil? nil end # Returns the first child Text node, if any, or +nil+ otherwise. # This method returns the actual +Text+ node, rather than the String content. # doc = Document.new "

    some text this is bold! more text

    " # # The element 'p' has two text elements, "some text " and " more text". # doc.root.get_text.value #-> "some text " def get_text path = nil rv = nil if path element = @elements[ path ] rv = element.get_text unless element.nil? else rv = @children.find { |node| node.kind_of? Text } end return rv end # Sets the first Text child of this object. See text() for a # discussion about Text children. # # If a Text child already exists, the child is replaced by this # content. This means that Text content can be deleted by calling # this method with a nil argument. In this case, the next Text # child becomes the first Text child. In no case is the order of # any siblings disturbed. # text:: # If a String, a new Text child is created and added to # this Element as the first Text child. If Text, the text is set # as the first Child element. If nil, then any existing first Text # child is removed. # Returns:: this Element. # doc = Document.new '' # doc.root.text = 'Sean' #-> 'Sean' # doc.root.text = 'Elliott' #-> 'Elliott' # doc.root.add_element 'c' #-> 'Elliott' # doc.root.text = 'Russell' #-> 'Russell' # doc.root.text = nil #-> '' def text=( text ) if text.kind_of? String text = Text.new( text, whitespace(), nil, raw() ) elsif !text.nil? and !text.kind_of? Text text = Text.new( text.to_s, whitespace(), nil, raw() ) end old_text = get_text if text.nil? old_text.remove unless old_text.nil? else if old_text.nil? self << text else old_text.replace_with( text ) end end return self end # A helper method to add a Text child. Actual Text instances can # be added with regular Parent methods, such as add() and <<() # text:: # if a String, a new Text instance is created and added # to the parent. If Text, the object is added directly. # Returns:: this Element # e = Element.new('a') #-> # e.add_text 'foo' #-> foo # e.add_text Text.new(' bar') #-> foo bar # Note that at the end of this example, the branch has 3 nodes; the 'e' # element and 2 Text node children. def add_text( text ) if text.kind_of? String if @children[-1].kind_of? Text @children[-1] << text return end text = Text.new( text, whitespace(), nil, raw() ) end self << text unless text.nil? return self end def node_type :element end def xpath path_elements = [] cur = self path_elements << __to_xpath_helper( self ) while cur.parent cur = cur.parent path_elements << __to_xpath_helper( cur ) end return path_elements.reverse.join( "/" ) end ################################################# # Attributes # ################################################# def attribute( name, namespace=nil ) prefix = nil if namespaces.respond_to? :key prefix = namespaces.key(namespace) if namespace else prefix = namespaces.index(namespace) if namespace end prefix = nil if prefix == 'xmlns' ret_val = attributes.get_attribute( "#{prefix ? prefix + ':' : ''}#{name}" ) return ret_val unless ret_val.nil? return nil if prefix.nil? # now check that prefix'es namespace is not the same as the # default namespace return nil unless ( namespaces[ prefix ] == namespaces[ 'xmlns' ] ) attributes.get_attribute( name ) end # Evaluates to +true+ if this element has any attributes set, false # otherwise. def has_attributes? return !@attributes.empty? end # Adds an attribute to this element, overwriting any existing attribute # by the same name. # key:: # can be either an Attribute or a String. If an Attribute, # the attribute is added to the list of Element attributes. If String, # the argument is used as the name of the new attribute, and the value # parameter must be supplied. # value:: # Required if +key+ is a String, and ignored if the first argument is # an Attribute. This is a String, and is used as the value # of the new Attribute. This should be the unnormalized value of the # attribute (without entities). # Returns:: the Attribute added # e = Element.new 'e' # e.add_attribute( 'a', 'b' ) #-> # e.add_attribute( 'x:a', 'c' ) #-> # e.add_attribute Attribute.new('b', 'd') #-> def add_attribute( key, value=nil ) if key.kind_of? Attribute @attributes << key else @attributes[key] = value end end # Add multiple attributes to this element. # hash:: is either a hash, or array of arrays # el.add_attributes( {"name1"=>"value1", "name2"=>"value2"} ) # el.add_attributes( [ ["name1","value1"], ["name2"=>"value2"] ] ) def add_attributes hash if hash.kind_of? Hash hash.each_pair {|key, value| @attributes[key] = value } elsif hash.kind_of? Array hash.each { |value| @attributes[ value[0] ] = value[1] } end end # Removes an attribute # key:: # either an Attribute or a String. In either case, the # attribute is found by matching the attribute name to the argument, # and then removed. If no attribute is found, no action is taken. # Returns:: # the attribute removed, or nil if this Element did not contain # a matching attribute # e = Element.new('E') # e.add_attribute( 'name', 'Sean' ) #-> # r = e.add_attribute( 'sur:name', 'Russell' ) #-> # e.delete_attribute( 'name' ) #-> # e.delete_attribute( r ) #-> def delete_attribute(key) attr = @attributes.get_attribute(key) attr.remove unless attr.nil? end ################################################# # Other Utilities # ################################################# # Get an array of all CData children. # IMMUTABLE def cdatas find_all { |child| child.kind_of? CData }.freeze end # Get an array of all Comment children. # IMMUTABLE def comments find_all { |child| child.kind_of? Comment }.freeze end # Get an array of all Instruction children. # IMMUTABLE def instructions find_all { |child| child.kind_of? Instruction }.freeze end # Get an array of all Text children. # IMMUTABLE def texts find_all { |child| child.kind_of? Text }.freeze end # == DEPRECATED # See REXML::Formatters # # Writes out this element, and recursively, all children. # output:: # output an object which supports '<< string'; this is where the # document will be written. # indent:: # An integer. If -1, no indenting will be used; otherwise, the # indentation will be this number of spaces, and children will be # indented an additional amount. Defaults to -1 # transitive:: # If transitive is true and indent is >= 0, then the output will be # pretty-printed in such a way that the added whitespace does not affect # the parse tree of the document # ie_hack:: # This hack inserts a space before the /> on empty tags to address # a limitation of Internet Explorer. Defaults to false # # out = '' # doc.write( out ) #-> doc is written to the string 'out' # doc.write( $stdout ) #-> doc written to the console def write(output=$stdout, indent=-1, transitive=false, ie_hack=false) Kernel.warn("#{self.class.name}.write is deprecated. See REXML::Formatters") formatter = if indent > -1 if transitive require "rexml/formatters/transitive" REXML::Formatters::Transitive.new( indent, ie_hack ) else REXML::Formatters::Pretty.new( indent, ie_hack ) end else REXML::Formatters::Default.new( ie_hack ) end formatter.write( self, output ) end private def __to_xpath_helper node rv = node.expanded_name.clone if node.parent results = node.parent.find_all {|n| n.kind_of?(REXML::Element) and n.expanded_name == node.expanded_name } if results.length > 1 idx = results.index( node ) rv << "[#{idx+1}]" end end rv end # A private helper method def each_with_something( test, max=0, name=nil ) num = 0 @elements.each( name ){ |child| yield child if test.call(child) and num += 1 return if max>0 and num == max } end end ######################################################################## # ELEMENTS # ######################################################################## # A class which provides filtering of children for Elements, and # XPath search support. You are expected to only encounter this class as # the element.elements object. Therefore, you are # _not_ expected to instantiate this yourself. class Elements include Enumerable # Constructor # parent:: the parent Element def initialize parent @element = parent end # Fetches a child element. Filters only Element children, regardless of # the XPath match. # index:: # the search parameter. This is either an Integer, which # will be used to find the index'th child Element, or an XPath, # which will be used to search for the Element. Because # of the nature of XPath searches, any element in the connected XML # document can be fetched through any other element. The # Integer index is 1-based, not 0-based. This means that the first # child element is at index 1, not 0, and the +n+th element is at index # +n+, not n-1. This is because XPath indexes element children # starting from 1, not 0, and the indexes should be the same. # name:: # optional, and only used in the first argument is an # Integer. In that case, the index'th child Element that has the # supplied name will be returned. Note again that the indexes start at 1. # Returns:: the first matching Element, or nil if no child matched # doc = Document.new '' # doc.root.elements[1] #-> # doc.root.elements['c'] #-> # doc.root.elements[2,'c'] #-> def []( index, name=nil) if index.kind_of? Integer raise "index (#{index}) must be >= 1" if index < 1 name = literalize(name) if name num = 0 @element.find { |child| child.kind_of? Element and (name.nil? ? true : child.has_name?( name )) and (num += 1) == index } else return XPath::first( @element, index ) #{ |element| # return element if element.kind_of? Element #} #return nil end end # Sets an element, replacing any previous matching element. If no # existing element is found ,the element is added. # index:: Used to find a matching element to replace. See [](). # element:: # The element to replace the existing element with # the previous element # Returns:: nil if no previous element was found. # # doc = Document.new '' # doc.root.elements[10] = Element.new('b') #-> # doc.root.elements[1] #-> # doc.root.elements[1] = Element.new('c') #-> # doc.root.elements['c'] = Element.new('d') #-> def []=( index, element ) previous = self[index] if previous.nil? @element.add element else previous.replace_with element end return previous end # Returns +true+ if there are no +Element+ children, +false+ otherwise def empty? @element.find{ |child| child.kind_of? Element}.nil? end # Returns the index of the supplied child (starting at 1), or -1 if # the element is not a child # element:: an +Element+ child def index element rv = 0 found = @element.find do |child| child.kind_of? Element and (rv += 1) and child == element end return rv if found == element return -1 end # Deletes a child Element # element:: # Either an Element, which is removed directly; an # xpath, where the first matching child is removed; or an Integer, # where the n'th Element is removed. # Returns:: the removed child # doc = Document.new '' # b = doc.root.elements[1] # doc.root.elements.delete b #-> # doc.elements.delete("a/c[@id='1']") #-> # doc.root.elements.delete 1 #-> def delete element if element.kind_of? Element @element.delete element else el = self[element] el.remove if el end end # Removes multiple elements. Filters for Element children, regardless of # XPath matching. # xpath:: all elements matching this String path are removed. # Returns:: an Array of Elements that have been removed # doc = Document.new '' # deleted = doc.elements.delete_all 'a/c' #-> [, , , ] def delete_all( xpath ) rv = [] XPath::each( @element, xpath) {|element| rv << element if element.kind_of? Element } rv.each do |element| @element.delete element element.remove end return rv end # Adds an element # element:: # if supplied, is either an Element, String, or # Source (see Element.initialize). If not supplied or nil, a # new, default Element will be constructed # Returns:: the added Element # a = Element.new('a') # a.elements.add(Element.new('b')) #-> # a.elements.add('c') #-> def add element=nil if element.nil? Element.new("", self, @element.context) elsif not element.kind_of?(Element) Element.new(element, self, @element.context) else @element << element element.context = @element.context element end end alias :<< :add # Iterates through all of the child Elements, optionally filtering # them by a given XPath # xpath:: # optional. If supplied, this is a String XPath, and is used to # filter the children, so that only matching children are yielded. Note # that XPaths are automatically filtered for Elements, so that # non-Element children will not be yielded # doc = Document.new 'sean' # doc.root.elements.each {|e|p e} #-> Yields b, c, d, b, c, d elements # doc.root.elements.each('b') {|e|p e} #-> Yields b, b elements # doc.root.elements.each('child::node()') {|e|p e} # #-> Yields , , , , , # XPath.each(doc.root, 'child::node()', &block) # #-> Yields , , , sean, , , def each( xpath=nil ) XPath::each( @element, xpath ) {|e| yield e if e.kind_of? Element } end def collect( xpath=nil ) collection = [] XPath::each( @element, xpath ) {|e| collection << yield(e) if e.kind_of?(Element) } collection end def inject( xpath=nil, initial=nil ) first = true XPath::each( @element, xpath ) {|e| if (e.kind_of? Element) if (first and initial == nil) initial = e first = false else initial = yield( initial, e ) if e.kind_of? Element end end } initial end # Returns the number of +Element+ children of the parent object. # doc = Document.new 'seanelliottrussell' # doc.root.size #-> 6, 3 element and 3 text nodes # doc.root.elements.size #-> 3 def size count = 0 @element.each {|child| count+=1 if child.kind_of? Element } count end # Returns an Array of Element children. An XPath may be supplied to # filter the children. Only Element children are returned, even if the # supplied XPath matches non-Element children. # doc = Document.new 'seanelliott' # doc.root.elements.to_a #-> [ , ] # doc.root.elements.to_a("child::node()") #-> [ , ] # XPath.match(doc.root, "child::node()") #-> [ sean, , elliott, ] def to_a( xpath=nil ) rv = XPath.match( @element, xpath ) return rv.find_all{|e| e.kind_of? Element} if xpath rv end private # Private helper class. Removes quotes from quoted strings def literalize name name = name[1..-2] if name[0] == ?' or name[0] == ?" #' name end end ######################################################################## # ATTRIBUTES # ######################################################################## # A class that defines the set of Attributes of an Element and provides # operations for accessing elements in that set. class Attributes < Hash # Constructor # element:: the Element of which this is an Attribute def initialize element @element = element end # Fetches an attribute value. If you want to get the Attribute itself, # use get_attribute() # name:: an XPath attribute name. Namespaces are relevant here. # Returns:: # the String value of the matching attribute, or +nil+ if no # matching attribute was found. This is the unnormalized value # (with entities expanded). # # doc = Document.new "" # doc.root.attributes['att'] #-> '<' # doc.root.attributes['bar:att'] #-> '2' def [](name) attr = get_attribute(name) return attr.value unless attr.nil? return nil end def to_a enum_for(:each_attribute).to_a end # Returns the number of attributes the owning Element contains. # doc = Document "" # doc.root.attributes.length #-> 3 def length c = 0 each_attribute { c+=1 } c end alias :size :length # Iterates over the attributes of an Element. Yields actual Attribute # nodes, not String values. # # doc = Document.new '' # doc.root.attributes.each_attribute {|attr| # p attr.expanded_name+" => "+attr.value # } def each_attribute # :yields: attribute each_value do |val| if val.kind_of? Attribute yield val else val.each_value { |atr| yield atr } end end end # Iterates over each attribute of an Element, yielding the expanded name # and value as a pair of Strings. # # doc = Document.new '' # doc.root.attributes.each {|name, value| p name+" => "+value } def each each_attribute do |attr| yield [attr.expanded_name, attr.value] end end # Fetches an attribute # name:: # the name by which to search for the attribute. Can be a # prefix:name namespace name. # Returns:: The first matching attribute, or nil if there was none. This # value is an Attribute node, not the String value of the attribute. # doc = Document.new '' # doc.root.attributes.get_attribute("foo").value #-> "2" # doc.root.attributes.get_attribute("x:foo").value #-> "1" def get_attribute( name ) attr = fetch( name, nil ) if attr.nil? return nil if name.nil? # Look for prefix name =~ Namespace::NAMESPLIT prefix, n = $1, $2 if prefix attr = fetch( n, nil ) # check prefix if attr == nil elsif attr.kind_of? Attribute return attr if prefix == attr.prefix else attr = attr[ prefix ] return attr end end element_document = @element.document if element_document and element_document.doctype expn = @element.expanded_name expn = element_document.doctype.name if expn.size == 0 attr_val = element_document.doctype.attribute_of(expn, name) return Attribute.new( name, attr_val ) if attr_val end return nil end if attr.kind_of? Hash attr = attr[ @element.prefix ] end return attr end # Sets an attribute, overwriting any existing attribute value by the # same name. Namespace is significant. # name:: the name of the attribute # value:: # (optional) If supplied, the value of the attribute. If # nil, any existing matching attribute is deleted. # Returns:: # Owning element # doc = Document.new "" # doc.root.attributes['y:foo'] = '2' # doc.root.attributes['foo'] = '4' # doc.root.attributes['x:foo'] = nil def []=( name, value ) if value.nil? # Delete the named attribute attr = get_attribute(name) delete attr return end unless value.kind_of? Attribute if @element.document and @element.document.doctype value = Text::normalize( value, @element.document.doctype ) else value = Text::normalize( value, nil ) end value = Attribute.new(name, value) end value.element = @element old_attr = fetch(value.name, nil) if old_attr.nil? store(value.name, value) elsif old_attr.kind_of? Hash old_attr[value.prefix] = value elsif old_attr.prefix != value.prefix # Check for conflicting namespaces raise ParseException.new( "Namespace conflict in adding attribute \"#{value.name}\": "+ "Prefix \"#{old_attr.prefix}\" = "+ "\"#{@element.namespace(old_attr.prefix)}\" and prefix "+ "\"#{value.prefix}\" = \"#{@element.namespace(value.prefix)}\"") if value.prefix != "xmlns" and old_attr.prefix != "xmlns" and @element.namespace( old_attr.prefix ) == @element.namespace( value.prefix ) store value.name, { old_attr.prefix => old_attr, value.prefix => value } else store value.name, value end return @element end # Returns an array of Strings containing all of the prefixes declared # by this set of # attributes. The array does not include the default # namespace declaration, if one exists. # doc = Document.new("") # prefixes = doc.root.attributes.prefixes #-> ['x', 'y'] def prefixes ns = [] each_attribute do |attribute| ns << attribute.name if attribute.prefix == 'xmlns' end if @element.document and @element.document.doctype expn = @element.expanded_name expn = @element.document.doctype.name if expn.size == 0 @element.document.doctype.attributes_of(expn).each { |attribute| ns << attribute.name if attribute.prefix == 'xmlns' } end ns end def namespaces namespaces = {} each_attribute do |attribute| namespaces[attribute.name] = attribute.value if attribute.prefix == 'xmlns' or attribute.name == 'xmlns' end if @element.document and @element.document.doctype expn = @element.expanded_name expn = @element.document.doctype.name if expn.size == 0 @element.document.doctype.attributes_of(expn).each { |attribute| namespaces[attribute.name] = attribute.value if attribute.prefix == 'xmlns' or attribute.name == 'xmlns' } end namespaces end # Removes an attribute # attribute:: # either a String, which is the name of the attribute to remove -- # namespaces are significant here -- or the attribute to remove. # Returns:: the owning element # doc = Document.new "" # doc.root.attributes.delete 'foo' #-> " # doc.root.attributes.delete 'x:foo' #-> " # attr = doc.root.attributes.get_attribute('y:foo') # doc.root.attributes.delete attr #-> " def delete( attribute ) name = nil prefix = nil if attribute.kind_of? Attribute name = attribute.name prefix = attribute.prefix else attribute =~ Namespace::NAMESPLIT prefix, name = $1, $2 prefix = '' unless prefix end old = fetch(name, nil) if old.kind_of? Hash # the supplied attribute is one of many old.delete(prefix) if old.size == 1 repl = nil old.each_value{|v| repl = v} store name, repl end elsif old.nil? return @element else # the supplied attribute is a top-level one super(name) end @element end # Adds an attribute, overriding any existing attribute by the # same name. Namespaces are significant. # attribute:: An Attribute def add( attribute ) self[attribute.name] = attribute end alias :<< :add # Deletes all attributes matching a name. Namespaces are significant. # name:: # A String; all attributes that match this path will be removed # Returns:: an Array of the Attributes that were removed def delete_all( name ) rv = [] each_attribute { |attribute| rv << attribute if attribute.expanded_name == name } rv.each{ |attr| attr.remove } return rv end # The +get_attribute_ns+ method retrieves a method by its namespace # and name. Thus it is possible to reliably identify an attribute # even if an XML processor has changed the prefix. # # Method contributed by Henrik Martensson def get_attribute_ns(namespace, name) result = nil each_attribute() { |attribute| if name == attribute.name && namespace == attribute.namespace() && ( !namespace.empty? || !attribute.fully_expanded_name.index(':') ) # foo will match xmlns:foo, but only if foo isn't also an attribute result = attribute if !result or !namespace.empty? or !attribute.fully_expanded_name.index(':') end } result end end end PK!cD}%%2.2.0/rexml/rexml.rbnu[# -*- encoding: utf-8 -*- # REXML is an XML toolkit for Ruby[http://www.ruby-lang.org], in Ruby. # # REXML is a _pure_ Ruby, XML 1.0 conforming, # non-validating[http://www.w3.org/TR/2004/REC-xml-20040204/#sec-conformance] # toolkit with an intuitive API. REXML passes 100% of the non-validating Oasis # tests[http://www.oasis-open.org/committees/xml-conformance/xml-test-suite.shtml], # and provides tree, stream, SAX2, pull, and lightweight APIs. REXML also # includes a full XPath[http://www.w3c.org/tr/xpath] 1.0 implementation. Since # Ruby 1.8, REXML is included in the standard Ruby distribution. # # Main page:: http://www.germane-software.com/software/rexml # Author:: Sean Russell # Date:: 2008/019 # Version:: 3.1.7.3 # # This API documentation can be downloaded from the REXML home page, or can # be accessed online[http://www.germane-software.com/software/rexml_doc] # # A tutorial is available in the REXML distribution in docs/tutorial.html, # or can be accessed # online[http://www.germane-software.com/software/rexml/docs/tutorial.html] module REXML COPYRIGHT = "Copyright © 2001-2008 Sean Russell " DATE = "2008/019" VERSION = "3.1.7.3" REVISION = %w$Revision: 39528 $[1] || '' Copyright = COPYRIGHT Version = VERSION end PK! o]]2.2.0/rexml/namespace.rbnu[require 'rexml/xmltokens' module REXML # Adds named attributes to an object. module Namespace # The name of the object, valid if set attr_reader :name, :expanded_name # The expanded name of the object, valid if name is set attr_accessor :prefix include XMLTokens NAMESPLIT = /^(?:(#{NCNAME_STR}):)?(#{NCNAME_STR})/u # Sets the name and the expanded name def name=( name ) @expanded_name = name name =~ NAMESPLIT if $1 @prefix = $1 else @prefix = "" @namespace = "" end @name = $2 end # Compares names optionally WITH namespaces def has_name?( other, ns=nil ) if ns return (namespace() == ns and name() == other) elsif other.include? ":" return fully_expanded_name == other else return name == other end end alias :local_name :name # Fully expand the name, even if the prefix wasn't specified in the # source file. def fully_expanded_name ns = prefix return "#{ns}:#@name" if ns.size > 0 return @name end end end PK!C2.2.0/rexml/parseexception.rbnu[module REXML class ParseException < RuntimeError attr_accessor :source, :parser, :continued_exception def initialize( message, source=nil, parser=nil, exception=nil ) super(message) @source = source @parser = parser @continued_exception = exception end def to_s # Quote the original exception, if there was one if @continued_exception err = @continued_exception.inspect err << "\n" err << @continued_exception.backtrace.join("\n") err << "\n...\n" else err = "" end # Get the stack trace and error message err << super # Add contextual information if @source err << "\nLine: #{line}\n" err << "Position: #{position}\n" err << "Last 80 unconsumed characters:\n" err << @source.buffer[0..80].force_encoding("ASCII-8BIT").gsub(/\n/, ' ') end err end def position @source.current_line[0] if @source and defined? @source.current_line and @source.current_line end def line @source.current_line[2] if @source and defined? @source.current_line and @source.current_line end def context @source.current_line end end end PK!u2.2.0/rexml/syncenumerator.rbnu[module REXML class SyncEnumerator include Enumerable # Creates a new SyncEnumerator which enumerates rows of given # Enumerable objects. def initialize(*enums) @gens = enums @length = @gens.collect {|x| x.size }.max end # Returns the number of enumerated Enumerable objects, i.e. the size # of each row. def size @gens.size end # Returns the number of enumerated Enumerable objects, i.e. the size # of each row. def length @gens.length end # Enumerates rows of the Enumerable objects. def each @length.times {|i| yield @gens.collect {|x| x[i]} } self end end end PK! qTT2.2.0/rexml/doctype.rbnu[require "rexml/parent" require "rexml/parseexception" require "rexml/namespace" require 'rexml/entity' require 'rexml/attlistdecl' require 'rexml/xmltokens' module REXML # Represents an XML DOCTYPE declaration; that is, the contents of . DOCTYPES can be used to declare the DTD of a document, as well as # being used to declare entities used in the document. class DocType < Parent include XMLTokens START = "" SYSTEM = "SYSTEM" PUBLIC = "PUBLIC" DEFAULT_ENTITIES = { 'gt'=>EntityConst::GT, 'lt'=>EntityConst::LT, 'quot'=>EntityConst::QUOT, "apos"=>EntityConst::APOS } # name is the name of the doctype # external_id is the referenced DTD, if given attr_reader :name, :external_id, :entities, :namespaces # Constructor # # dt = DocType.new( 'foo', '-//I/Hate/External/IDs' ) # # # dt = DocType.new( doctype_to_clone ) # # Incomplete. Shallow clone of doctype # # +Note+ that the constructor: # # Doctype.new( Source.new( "" ) ) # # is _deprecated_. Do not use it. It will probably disappear. def initialize( first, parent=nil ) @entities = DEFAULT_ENTITIES @long_name = @uri = nil if first.kind_of? String super() @name = first @external_id = parent elsif first.kind_of? DocType super( parent ) @name = first.name @external_id = first.external_id elsif first.kind_of? Array super( parent ) @name = first[0] @external_id = first[1] @long_name = first[2] @uri = first[3] elsif first.kind_of? Source super( parent ) parser = Parsers::BaseParser.new( first ) event = parser.pull if event[0] == :start_doctype @name, @external_id, @long_name, @uri, = event[1..-1] end else super() end end def node_type :doctype end def attributes_of element rv = [] each do |child| child.each do |key,val| rv << Attribute.new(key,val) end if child.kind_of? AttlistDecl and child.element_name == element end rv end def attribute_of element, attribute att_decl = find do |child| child.kind_of? AttlistDecl and child.element_name == element and child.include? attribute end return nil unless att_decl att_decl[attribute] end def clone DocType.new self end # output:: # Where to write the string # indent:: # An integer. If -1, no indentation will be used; otherwise, the # indentation will be this number of spaces, and children will be # indented an additional amount. # transitive:: # Ignored # ie_hack:: # Ignored def write( output, indent=0, transitive=false, ie_hack=false ) f = REXML::Formatters::Default.new indent( output, indent ) output << START output << ' ' output << @name output << " #@external_id" if @external_id output << " #{@long_name.inspect}" if @long_name output << " #{@uri.inspect}" if @uri unless @children.empty? output << ' [' @children.each { |child| output << "\n" f.write( child, output ) } output << "\n]" end output << STOP end def context @parent.context end def entity( name ) @entities[name].unnormalized if @entities[name] end def add child super(child) @entities = DEFAULT_ENTITIES.clone if @entities == DEFAULT_ENTITIES @entities[ child.name ] = child if child.kind_of? Entity end # This method retrieves the public identifier identifying the document's # DTD. # # Method contributed by Henrik Martensson def public case @external_id when "SYSTEM" nil when "PUBLIC" strip_quotes(@long_name) end end # This method retrieves the system identifier identifying the document's DTD # # Method contributed by Henrik Martensson def system case @external_id when "SYSTEM" strip_quotes(@long_name) when "PUBLIC" @uri.kind_of?(String) ? strip_quotes(@uri) : nil end end # This method returns a list of notations that have been declared in the # _internal_ DTD subset. Notations in the external DTD subset are not # listed. # # Method contributed by Henrik Martensson def notations children().select {|node| node.kind_of?(REXML::NotationDecl)} end # Retrieves a named notation. Only notations declared in the internal # DTD subset can be retrieved. # # Method contributed by Henrik Martensson def notation(name) notations.find { |notation_decl| notation_decl.name == name } end private # Method contributed by Henrik Martensson def strip_quotes(quoted_string) quoted_string =~ /^[\'\"].*[\'\"]$/ ? quoted_string[1, quoted_string.length-2] : quoted_string end end # We don't really handle any of these since we're not a validating # parser, so we can be pretty dumb about them. All we need to be able # to do is spew them back out on a write() # This is an abstract class. You never use this directly; it serves as a # parent class for the specific declarations. class Declaration < Child def initialize src super() @string = src end def to_s @string+'>' end # == DEPRECATED # See REXML::Formatters # def write( output, indent ) output << to_s end end public class ElementDecl < Declaration def initialize( src ) super end end class ExternalEntity < Child def initialize( src ) super() @entity = src end def to_s @entity end def write( output, indent ) output << @entity end end class NotationDecl < Child attr_accessor :public, :system def initialize name, middle, pub, sys super(nil) @name = name @middle = middle @public = pub @system = sys end def to_s notation = "" notation end def write( output, indent=-1 ) output << to_s end # This method retrieves the name of the notation. # # Method contributed by Henrik Martensson def name @name end end end PK!t㵣2.2.0/rexml/dtd/elementdecl.rbnu[require "rexml/child" module REXML module DTD class ElementDecl < Child START = "/um PATTERN_RE = /^\s*#{START}\s+((?:[:\w][-\.\w]*:)?[-!\*\.\w]*)(.*?)>/ #\s*((((["']).*?\5)|[^\/'">]*)*?)(\/)?>/um, true) def initialize match @name = match[1] @rest = match[2] end end end end PK!U2.2.0/rexml/dtd/attlistdecl.rbnu[require "rexml/child" module REXML module DTD class AttlistDecl < Child START = ")/um end end end PK!!*##2.2.0/rexml/dtd/notationdecl.rbnu[require "rexml/child" module REXML module DTD class NotationDecl < Child START = "/um SYSTEM = /^\s*#{START}\s+(\w[\w-]*)\s+(SYSTEM)\s+((["']).*?\4)\s*>/um def initialize src super() if src.match( PUBLIC ) md = src.match( PUBLIC, true ) elsif src.match( SYSTEM ) md = src.match( SYSTEM, true ) else raise ParseException.new( "error parsing notation: no matching pattern", src ) end @name = md[1] @middle = md[2] @rest = md[3] end def to_s "" end def write( output, indent ) indent( output, indent ) output << to_s end def NotationDecl.parse_source source, listener md = source.match( PATTERN_RE, true ) thing = md[0].squeeze(" \t\n\r") listener.send inspect.downcase, thing end end end end PK!|2.2.0/rexml/dtd/entitydecl.rbnu[require "rexml/child" module REXML module DTD class EntityDecl < Child START = "/um SYSTEM = /^\s*#{START}\s+(?:%\s+)?(\w+)\s+SYSTEM\s+((["']).*?\3)(?:\s+NDATA\s+\w+)?\s*>/um PLAIN = /^\s*#{START}\s+(\w+)\s+((["']).*?\3)\s*>/um PERCENT = /^\s*#{START}\s+%\s+(\w+)\s+((["']).*?\3)\s*>/um # # def initialize src super() md = nil if src.match( PUBLIC ) md = src.match( PUBLIC, true ) @middle = "PUBLIC" @content = "#{md[2]} #{md[4]}" elsif src.match( SYSTEM ) md = src.match( SYSTEM, true ) @middle = "SYSTEM" @content = md[2] elsif src.match( PLAIN ) md = src.match( PLAIN, true ) @middle = "" @content = md[2] elsif src.match( PERCENT ) md = src.match( PERCENT, true ) @middle = "" @content = md[2] end raise ParseException.new("failed Entity match", src) if md.nil? @name = md[1] end def to_s rv = " 0 rv << @content rv end def write( output, indent ) indent( output, indent ) output << to_s end def EntityDecl.parse_source source, listener md = source.match( PATTERN_RE, true ) thing = md[0].squeeze(" \t\n\r") listener.send inspect.downcase, thing end end end end PK!0ߩ2.2.0/rexml/dtd/dtd.rbnu[require "rexml/dtd/elementdecl" require "rexml/dtd/entitydecl" require "rexml/comment" require "rexml/dtd/notationdecl" require "rexml/dtd/attlistdecl" require "rexml/parent" module REXML module DTD class Parser def Parser.parse( input ) case input when String parse_helper input when File parse_helper input.read end end # Takes a String and parses it out def Parser.parse_helper( input ) contents = Parent.new while input.size > 0 case input when ElementDecl.PATTERN_RE match = $& contents << ElementDecl.new( match ) when AttlistDecl.PATTERN_RE matchdata = $~ contents << AttlistDecl.new( matchdata ) when EntityDecl.PATTERN_RE matchdata = $~ contents << EntityDecl.new( matchdata ) when Comment.PATTERN_RE matchdata = $~ contents << Comment.new( matchdata ) when NotationDecl.PATTERN_RE matchdata = $~ contents << NotationDecl.new( matchdata ) end end contents end end end end PK!`2.2.0/rexml/node.rbnu[require "rexml/parseexception" require "rexml/formatters/pretty" require "rexml/formatters/default" module REXML # Represents a node in the tree. Nodes are never encountered except as # superclasses of other objects. Nodes have siblings. module Node # @return the next sibling (nil if unset) def next_sibling_node return nil if @parent.nil? @parent[ @parent.index(self) + 1 ] end # @return the previous sibling (nil if unset) def previous_sibling_node return nil if @parent.nil? ind = @parent.index(self) return nil if ind == 0 @parent[ ind - 1 ] end # indent:: # *DEPRECATED* This parameter is now ignored. See the formatters in the # REXML::Formatters package for changing the output style. def to_s indent=nil unless indent.nil? Kernel.warn( "#{self.class.name}.to_s(indent) parameter is deprecated" ) f = REXML::Formatters::Pretty.new( indent ) f.write( self, rv = "" ) else f = REXML::Formatters::Default.new f.write( self, rv = "" ) end return rv end def indent to, ind if @parent and @parent.context and not @parent.context[:indentstyle].nil? then indentstyle = @parent.context[:indentstyle] else indentstyle = ' ' end to << indentstyle*ind unless ind<1 end def parent? false; end # Visit all subnodes of +self+ recursively def each_recursive(&block) # :yields: node self.elements.each {|node| block.call(node) node.each_recursive(&block) } end # Find (and return) first subnode (recursively) for which the block # evaluates to true. Returns +nil+ if none was found. def find_first_recursive(&block) # :yields: node each_recursive {|node| return node if block.call(node) } return nil end # Returns the position that +self+ holds in its parent's array, indexed # from 1. def index_in_parent parent.index(self)+1 end end end PK!1Iٻ 2.2.0/rexml/xmldecl.rbnu[require 'rexml/encoding' require 'rexml/source' module REXML # NEEDS DOCUMENTATION class XMLDecl < Child include Encoding DEFAULT_VERSION = "1.0"; DEFAULT_ENCODING = "UTF-8"; DEFAULT_STANDALONE = "no"; START = '<\?xml'; STOP = '\?>'; attr_accessor :version, :standalone attr_reader :writeencoding, :writethis def initialize(version=DEFAULT_VERSION, encoding=nil, standalone=nil) @writethis = true @writeencoding = !encoding.nil? if version.kind_of? XMLDecl super() @version = version.version self.encoding = version.encoding @writeencoding = version.writeencoding @standalone = version.standalone else super() @version = version self.encoding = encoding @standalone = standalone end @version = DEFAULT_VERSION if @version.nil? end def clone XMLDecl.new(self) end # indent:: # Ignored. There must be no whitespace before an XML declaration # transitive:: # Ignored # ie_hack:: # Ignored def write(writer, indent=-1, transitive=false, ie_hack=false) return nil unless @writethis or writer.kind_of? Output writer << START.sub(/\\/u, '') writer << " #{content encoding}" writer << STOP.sub(/\\/u, '') end def ==( other ) other.kind_of?(XMLDecl) and other.version == @version and other.encoding == self.encoding and other.standalone == @standalone end def xmldecl version, encoding, standalone @version = version self.encoding = encoding @standalone = standalone end def node_type :xmldecl end alias :stand_alone? :standalone alias :old_enc= :encoding= def encoding=( enc ) if enc.nil? self.old_enc = "UTF-8" @writeencoding = false else self.old_enc = enc @writeencoding = true end self.dowrite end # Only use this if you do not want the XML declaration to be written; # this object is ignored by the XML writer. Otherwise, instantiate your # own XMLDecl and add it to the document. # # Note that XML 1.1 documents *must* include an XML declaration def XMLDecl.default rv = XMLDecl.new( "1.0" ) rv.nowrite rv end def nowrite @writethis = false end def dowrite @writethis = true end def inspect START.sub(/\\/u, '') + " ... " + STOP.sub(/\\/u, '') end private def content(enc) rv = "version='#@version'" rv << " encoding='#{enc}'" if @writeencoding || enc !~ /\Autf-8\z/i rv << " standalone='#@standalone'" if @standalone rv end end end PK!"ƻo4o42.2.0/prime.rbnu[# # = prime.rb # # Prime numbers and factorization library. # # Copyright:: # Copyright (c) 1998-2008 Keiju ISHITSUKA(SHL Japan Inc.) # Copyright (c) 2008 Yuki Sonoda (Yugui) # # Documentation:: # Yuki Sonoda # require "singleton" require "forwardable" class Integer # Re-composes a prime factorization and returns the product. # # See Prime#int_from_prime_division for more details. def Integer.from_prime_division(pd) Prime.int_from_prime_division(pd) end # Returns the factorization of +self+. # # See Prime#prime_division for more details. def prime_division(generator = Prime::Generator23.new) Prime.prime_division(self, generator) end # Returns true if +self+ is a prime number, else returns false. def prime? Prime.prime?(self) end # Iterates the given block over all prime numbers. # # See +Prime+#each for more details. def Integer.each_prime(ubound, &block) # :yields: prime Prime.each(ubound, &block) end end # # The set of all prime numbers. # # == Example # # Prime.each(100) do |prime| # p prime #=> 2, 3, 5, 7, 11, ...., 97 # end # # Prime is Enumerable: # # Prime.first 5 # => [2, 3, 5, 7, 11] # # == Retrieving the instance # # +Prime+.new is obsolete. Now +Prime+ has the default instance and you can # access it as +Prime+.instance. # # For convenience, each instance method of +Prime+.instance can be accessed # as a class method of +Prime+. # # e.g. # Prime.instance.prime?(2) #=> true # Prime.prime?(2) #=> true # # == Generators # # A "generator" provides an implementation of enumerating pseudo-prime # numbers and it remembers the position of enumeration and upper bound. # Furthermore, it is an external iterator of prime enumeration which is # compatible with an Enumerator. # # +Prime+::+PseudoPrimeGenerator+ is the base class for generators. # There are few implementations of generator. # # [+Prime+::+EratosthenesGenerator+] # Uses eratosthenes' sieve. # [+Prime+::+TrialDivisionGenerator+] # Uses the trial division method. # [+Prime+::+Generator23+] # Generates all positive integers which are not divisible by either 2 or 3. # This sequence is very bad as a pseudo-prime sequence. But this # is faster and uses much less memory than the other generators. So, # it is suitable for factorizing an integer which is not large but # has many prime factors. e.g. for Prime#prime? . class Prime include Enumerable @the_instance = Prime.new # obsolete. Use +Prime+::+instance+ or class methods of +Prime+. def initialize @generator = EratosthenesGenerator.new extend OldCompatibility warn "Prime::new is obsolete. use Prime::instance or class methods of Prime." end class << self extend Forwardable include Enumerable # Returns the default instance of Prime. def instance; @the_instance end def method_added(method) # :nodoc: (class<< self;self;end).def_delegator :instance, method end end # Iterates the given block over all prime numbers. # # == Parameters # # +ubound+:: # Optional. An arbitrary positive number. # The upper bound of enumeration. The method enumerates # prime numbers infinitely if +ubound+ is nil. # +generator+:: # Optional. An implementation of pseudo-prime generator. # # == Return value # # An evaluated value of the given block at the last time. # Or an enumerator which is compatible to an +Enumerator+ # if no block given. # # == Description # # Calls +block+ once for each prime number, passing the prime as # a parameter. # # +ubound+:: # Upper bound of prime numbers. The iterator stops after it # yields all prime numbers p <= +ubound+. # # == Note # # +Prime+.+new+ returns an object extended by +Prime+::+OldCompatibility+ # in order to be compatible with Ruby 1.8, and +Prime+#each is overwritten # by +Prime+::+OldCompatibility+#+each+. # # +Prime+.+new+ is now obsolete. Use +Prime+.+instance+.+each+ or simply # +Prime+.+each+. def each(ubound = nil, generator = EratosthenesGenerator.new, &block) generator.upper_bound = ubound generator.each(&block) end # Returns true if +value+ is a prime number, else returns false. # # == Parameters # # +value+:: an arbitrary integer to be checked. # +generator+:: optional. A pseudo-prime generator. def prime?(value, generator = Prime::Generator23.new) return false if value < 2 for num in generator q,r = value.divmod num return true if q < num return false if r == 0 end end # Re-composes a prime factorization and returns the product. # # == Parameters # +pd+:: Array of pairs of integers. The each internal # pair consists of a prime number -- a prime factor -- # and a natural number -- an exponent. # # == Example # For [[p_1, e_1], [p_2, e_2], ...., [p_n, e_n]], it returns: # # p_1**e_1 * p_2**e_2 * .... * p_n**e_n. # # Prime.int_from_prime_division([[2,2], [3,1]]) #=> 12 def int_from_prime_division(pd) pd.inject(1){|value, (prime, index)| value * prime**index } end # Returns the factorization of +value+. # # == Parameters # +value+:: An arbitrary integer. # +generator+:: Optional. A pseudo-prime generator. # +generator+.succ must return the next # pseudo-prime number in the ascending # order. It must generate all prime numbers, # but may also generate non prime numbers too. # # === Exceptions # +ZeroDivisionError+:: when +value+ is zero. # # == Example # For an arbitrary integer: # # n = p_1**e_1 * p_2**e_2 * .... * p_n**e_n, # # prime_division(n) returns: # # [[p_1, e_1], [p_2, e_2], ...., [p_n, e_n]]. # # Prime.prime_division(12) #=> [[2,2], [3,1]] # def prime_division(value, generator = Prime::Generator23.new) raise ZeroDivisionError if value == 0 if value < 0 value = -value pv = [[-1, 1]] else pv = [] end for prime in generator count = 0 while (value1, mod = value.divmod(prime) mod) == 0 value = value1 count += 1 end if count != 0 pv.push [prime, count] end break if value1 <= prime end if value > 1 pv.push [value, 1] end return pv end # An abstract class for enumerating pseudo-prime numbers. # # Concrete subclasses should override succ, next, rewind. class PseudoPrimeGenerator include Enumerable def initialize(ubound = nil) @ubound = ubound end def upper_bound=(ubound) @ubound = ubound end def upper_bound @ubound end # returns the next pseudo-prime number, and move the internal # position forward. # # +PseudoPrimeGenerator+#succ raises +NotImplementedError+. def succ raise NotImplementedError, "need to define `succ'" end # alias of +succ+. def next raise NotImplementedError, "need to define `next'" end # Rewinds the internal position for enumeration. # # See +Enumerator+#rewind. def rewind raise NotImplementedError, "need to define `rewind'" end # Iterates the given block for each prime number. def each return self.dup unless block_given? if @ubound last_value = nil loop do prime = succ break last_value if prime > @ubound last_value = yield prime end else loop do yield succ end end end # see +Enumerator+#with_index. alias with_index each_with_index # see +Enumerator+#with_object. def with_object(obj) return enum_for(:with_object) unless block_given? each do |prime| yield prime, obj end end end # An implementation of +PseudoPrimeGenerator+. # # Uses +EratosthenesSieve+. class EratosthenesGenerator < PseudoPrimeGenerator def initialize @last_prime_index = -1 super end def succ @last_prime_index += 1 EratosthenesSieve.instance.get_nth_prime(@last_prime_index) end def rewind initialize end alias next succ end # An implementation of +PseudoPrimeGenerator+ which uses # a prime table generated by trial division. class TrialDivisionGenerator= @primes.length # Only check for prime factors up to the square root of the potential primes, # but without the performance hit of an actual square root calculation. if @next_to_check + 4 > @ulticheck_next_squared @ulticheck_index += 1 @ulticheck_next_squared = @primes.at(@ulticheck_index + 1) ** 2 end # Only check numbers congruent to one and five, modulo six. All others # are divisible by two or three. This also allows us to skip checking against # two and three. @primes.push @next_to_check if @primes[2..@ulticheck_index].find {|prime| @next_to_check % prime == 0 }.nil? @next_to_check += 4 @primes.push @next_to_check if @primes[2..@ulticheck_index].find {|prime| @next_to_check % prime == 0 }.nil? @next_to_check += 2 end return @primes[index] end end # Internal use. An implementation of eratosthenes' sieve class EratosthenesSieve include Singleton def initialize @primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101] # @max_checked must be an even number @max_checked = @primes.last + 1 end def get_nth_prime(n) compute_primes while @primes.size <= n @primes[n] end private def compute_primes # max_segment_size must be an even number max_segment_size = 1e6.to_i max_cached_prime = @primes.last # do not double count primes if #compute_primes is interrupted # by Timeout.timeout @max_checked = max_cached_prime + 1 if max_cached_prime > @max_checked segment_min = @max_checked segment_max = [segment_min + max_segment_size, max_cached_prime * 2].min root = Integer(Math.sqrt(segment_max).floor) sieving_primes = @primes[1 .. -1].take_while { |prime| prime <= root } offsets = Array.new(sieving_primes.size) do |i| (-(segment_min + 1 + sieving_primes[i]) / 2) % sieving_primes[i] end segment = ((segment_min + 1) .. segment_max).step(2).to_a sieving_primes.each_with_index do |prime, index| composite_index = offsets[index] while composite_index < segment.size do segment[composite_index] = nil composite_index += prime end end segment.each do |prime| @primes.push prime unless prime.nil? end @max_checked = segment_max end end # Provides a +Prime+ object with compatibility to Ruby 1.8 when instantiated via +Prime+.+new+. module OldCompatibility # Returns the next prime number and forwards internal pointer. def succ @generator.succ end alias next succ # Overwrites Prime#each. # # Iterates the given block over all prime numbers. Note that enumeration # starts from the current position of internal pointer, not rewound. def each return @generator.dup unless block_given? loop do yield succ end end end end PK!L2WbWb2.2.0/open-uri.rbnu[require 'uri' require 'stringio' require 'time' module Kernel private alias open_uri_original_open open # :nodoc: class << self alias open_uri_original_open open # :nodoc: end # Allows the opening of various resources including URIs. # # If the first argument responds to the 'open' method, 'open' is called on # it with the rest of the arguments. # # If the first argument is a string that begins with xxx://, it is parsed by # URI.parse. If the parsed object responds to the 'open' method, # 'open' is called on it with the rest of the arguments. # # Otherwise, the original Kernel#open is called. # # OpenURI::OpenRead#open provides URI::HTTP#open, URI::HTTPS#open and # URI::FTP#open, Kernel#open. # # We can accept URIs and strings that begin with http://, https:// and # ftp://. In these cases, the opened file object is extended by OpenURI::Meta. def open(name, *rest, &block) # :doc: if name.respond_to?(:open) name.open(*rest, &block) elsif name.respond_to?(:to_str) && %r{\A[A-Za-z][A-Za-z0-9+\-\.]*://} =~ name && (uri = URI.parse(name)).respond_to?(:open) uri.open(*rest, &block) else open_uri_original_open(name, *rest, &block) end end module_function :open end # OpenURI is an easy-to-use wrapper for Net::HTTP, Net::HTTPS and Net::FTP. # # == Example # # It is possible to open an http, https or ftp URL as though it were a file: # # open("http://www.ruby-lang.org/") {|f| # f.each_line {|line| p line} # } # # The opened file has several getter methods for its meta-information, as # follows, since it is extended by OpenURI::Meta. # # open("http://www.ruby-lang.org/en") {|f| # f.each_line {|line| p line} # p f.base_uri # # p f.content_type # "text/html" # p f.charset # "iso-8859-1" # p f.content_encoding # [] # p f.last_modified # Thu Dec 05 02:45:02 UTC 2002 # } # # Additional header fields can be specified by an optional hash argument. # # open("http://www.ruby-lang.org/en/", # "User-Agent" => "Ruby/#{RUBY_VERSION}", # "From" => "foo@bar.invalid", # "Referer" => "http://www.ruby-lang.org/") {|f| # # ... # } # # The environment variables such as http_proxy, https_proxy and ftp_proxy # are in effect by default. Here we disable proxy: # # open("http://www.ruby-lang.org/en/", :proxy => nil) {|f| # # ... # } # # See OpenURI::OpenRead.open and Kernel#open for more on available options. # # URI objects can be opened in a similar way. # # uri = URI.parse("http://www.ruby-lang.org/en/") # uri.open {|f| # # ... # } # # URI objects can be read directly. The returned string is also extended by # OpenURI::Meta. # # str = uri.read # p str.base_uri # # Author:: Tanaka Akira module OpenURI Options = { :proxy => true, :proxy_http_basic_authentication => true, :progress_proc => true, :content_length_proc => true, :http_basic_authentication => true, :read_timeout => true, :open_timeout => true, :ssl_ca_cert => nil, :ssl_verify_mode => nil, :ftp_active_mode => false, :redirect => true, } def OpenURI.check_options(options) # :nodoc: options.each {|k, v| next unless Symbol === k unless Options.include? k raise ArgumentError, "unrecognized option: #{k}" end } end def OpenURI.scan_open_optional_arguments(*rest) # :nodoc: if !rest.empty? && (String === rest.first || Integer === rest.first) mode = rest.shift if !rest.empty? && Integer === rest.first perm = rest.shift end end return mode, perm, rest end def OpenURI.open_uri(name, *rest) # :nodoc: uri = URI::Generic === name ? name : URI.parse(name) mode, _, rest = OpenURI.scan_open_optional_arguments(*rest) options = rest.shift if !rest.empty? && Hash === rest.first raise ArgumentError.new("extra arguments") if !rest.empty? options ||= {} OpenURI.check_options(options) if /\Arb?(?:\Z|:([^:]+))/ =~ mode encoding, = $1,Encoding.find($1) if $1 mode = nil end unless mode == nil || mode == 'r' || mode == 'rb' || mode == File::RDONLY raise ArgumentError.new("invalid access mode #{mode} (#{uri.class} resource is read only.)") end io = open_loop(uri, options) io.set_encoding(encoding) if encoding if block_given? begin yield io ensure if io.respond_to? :close! io.close! # Tempfile else io.close if !io.closed? end end else io end end def OpenURI.open_loop(uri, options) # :nodoc: proxy_opts = [] proxy_opts << :proxy_http_basic_authentication if options.include? :proxy_http_basic_authentication proxy_opts << :proxy if options.include? :proxy proxy_opts.compact! if 1 < proxy_opts.length raise ArgumentError, "multiple proxy options specified" end case proxy_opts.first when :proxy_http_basic_authentication opt_proxy, proxy_user, proxy_pass = options.fetch(:proxy_http_basic_authentication) proxy_user = proxy_user.to_str proxy_pass = proxy_pass.to_str if opt_proxy == true raise ArgumentError.new("Invalid authenticated proxy option: #{options[:proxy_http_basic_authentication].inspect}") end when :proxy opt_proxy = options.fetch(:proxy) proxy_user = nil proxy_pass = nil when nil opt_proxy = true proxy_user = nil proxy_pass = nil end case opt_proxy when true find_proxy = lambda {|u| pxy = u.find_proxy; pxy ? [pxy, nil, nil] : nil} when nil, false find_proxy = lambda {|u| nil} when String opt_proxy = URI.parse(opt_proxy) find_proxy = lambda {|u| [opt_proxy, proxy_user, proxy_pass]} when URI::Generic find_proxy = lambda {|u| [opt_proxy, proxy_user, proxy_pass]} else raise ArgumentError.new("Invalid proxy option: #{opt_proxy}") end uri_set = {} buf = nil while true redirect = catch(:open_uri_redirect) { buf = Buffer.new uri.buffer_open(buf, find_proxy.call(uri), options) nil } if redirect if redirect.relative? # Although it violates RFC2616, Location: field may have relative # URI. It is converted to absolute URI using uri as a base URI. redirect = uri + redirect end if !options.fetch(:redirect, true) raise HTTPRedirect.new(buf.io.status.join(' '), buf.io, redirect) end unless OpenURI.redirectable?(uri, redirect) raise "redirection forbidden: #{uri} -> #{redirect}" end if options.include? :http_basic_authentication # send authentication only for the URI directly specified. options = options.dup options.delete :http_basic_authentication end uri = redirect raise "HTTP redirection loop: #{uri}" if uri_set.include? uri.to_s uri_set[uri.to_s] = true else break end end io = buf.io io.base_uri = uri io end def OpenURI.redirectable?(uri1, uri2) # :nodoc: # This test is intended to forbid a redirection from http://... to # file:///etc/passwd, file:///dev/zero, etc. CVE-2011-1521 # https to http redirect is also forbidden intentionally. # It avoids sending secure cookie or referer by non-secure HTTP protocol. # (RFC 2109 4.3.1, RFC 2965 3.3, RFC 2616 15.1.3) # However this is ad hoc. It should be extensible/configurable. uri1.scheme.downcase == uri2.scheme.downcase || (/\A(?:http|ftp)\z/i =~ uri1.scheme && /\A(?:http|ftp)\z/i =~ uri2.scheme) end def OpenURI.open_http(buf, target, proxy, options) # :nodoc: if proxy proxy_uri, proxy_user, proxy_pass = proxy raise "Non-HTTP proxy URI: #{proxy_uri}" if proxy_uri.class != URI::HTTP end if target.userinfo raise ArgumentError, "userinfo not supported. [RFC3986]" end header = {} options.each {|k, v| header[k] = v if String === k } require 'net/http' klass = Net::HTTP if URI::HTTP === target # HTTP or HTTPS if proxy if proxy_user && proxy_pass klass = Net::HTTP::Proxy(proxy_uri.hostname, proxy_uri.port, proxy_user, proxy_pass) else klass = Net::HTTP::Proxy(proxy_uri.hostname, proxy_uri.port) end end target_host = target.hostname target_port = target.port request_uri = target.request_uri else # FTP over HTTP proxy target_host = proxy_uri.hostname target_port = proxy_uri.port request_uri = target.to_s if proxy_user && proxy_pass header["Proxy-Authorization"] = 'Basic ' + ["#{proxy_user}:#{proxy_pass}"].pack('m').delete("\r\n") end end http = proxy ? klass.new(target_host, target_port) : klass.new(target_host, target_port, nil) if target.class == URI::HTTPS require 'net/https' http.use_ssl = true http.verify_mode = options[:ssl_verify_mode] || OpenSSL::SSL::VERIFY_PEER store = OpenSSL::X509::Store.new if options[:ssl_ca_cert] Array(options[:ssl_ca_cert]).each do |cert| if File.directory? cert store.add_path cert else store.add_file cert end end else store.set_default_paths end http.cert_store = store end if options.include? :read_timeout http.read_timeout = options[:read_timeout] end if options.include? :open_timeout http.open_timeout = options[:open_timeout] end resp = nil http.start { req = Net::HTTP::Get.new(request_uri, header) if options.include? :http_basic_authentication user, pass = options[:http_basic_authentication] req.basic_auth user, pass end http.request(req) {|response| resp = response if options[:content_length_proc] && Net::HTTPSuccess === resp if resp.key?('Content-Length') options[:content_length_proc].call(resp['Content-Length'].to_i) else options[:content_length_proc].call(nil) end end resp.read_body {|str| buf << str if options[:progress_proc] && Net::HTTPSuccess === resp options[:progress_proc].call(buf.size) end } } } io = buf.io io.rewind io.status = [resp.code, resp.message] resp.each_name {|name| buf.io.meta_add_field2 name, resp.get_fields(name) } case resp when Net::HTTPSuccess when Net::HTTPMovedPermanently, # 301 Net::HTTPFound, # 302 Net::HTTPSeeOther, # 303 Net::HTTPTemporaryRedirect # 307 begin loc_uri = URI.parse(resp['location']) rescue URI::InvalidURIError raise OpenURI::HTTPError.new(io.status.join(' ') + ' (Invalid Location URI)', io) end throw :open_uri_redirect, loc_uri else raise OpenURI::HTTPError.new(io.status.join(' '), io) end end class HTTPError < StandardError def initialize(message, io) super(message) @io = io end attr_reader :io end # Raised on redirection, # only occurs when +redirect+ option for HTTP is +false+. class HTTPRedirect < HTTPError def initialize(message, io, uri) super(message, io) @uri = uri end attr_reader :uri end class Buffer # :nodoc: all def initialize @io = StringIO.new @size = 0 end attr_reader :size StringMax = 10240 def <<(str) @io << str @size += str.length if StringIO === @io && StringMax < @size require 'tempfile' io = Tempfile.new('open-uri') io.binmode Meta.init io, @io if Meta === @io io << @io.string @io = io end end def io Meta.init @io unless Meta === @io @io end end # Mixin for holding meta-information. module Meta def Meta.init(obj, src=nil) # :nodoc: obj.extend Meta obj.instance_eval { @base_uri = nil @meta = {} # name to string. legacy. @metas = {} # name to array of strings. } if src obj.status = src.status obj.base_uri = src.base_uri src.metas.each {|name, values| obj.meta_add_field2(name, values) } end end # returns an Array that consists of status code and message. attr_accessor :status # returns a URI that is the base of relative URIs in the data. # It may differ from the URI supplied by a user due to redirection. attr_accessor :base_uri # returns a Hash that represents header fields. # The Hash keys are downcased for canonicalization. # The Hash values are a field body. # If there are multiple field with same field name, # the field values are concatenated with a comma. attr_reader :meta # returns a Hash that represents header fields. # The Hash keys are downcased for canonicalization. # The Hash value are an array of field values. attr_reader :metas def meta_setup_encoding # :nodoc: charset = self.charset enc = nil if charset begin enc = Encoding.find(charset) rescue ArgumentError end end enc = Encoding::ASCII_8BIT unless enc if self.respond_to? :force_encoding self.force_encoding(enc) elsif self.respond_to? :string self.string.force_encoding(enc) else # Tempfile self.set_encoding enc end end def meta_add_field2(name, values) # :nodoc: name = name.downcase @metas[name] = values @meta[name] = values.join(', ') meta_setup_encoding if name == 'content-type' end def meta_add_field(name, value) # :nodoc: meta_add_field2(name, [value]) end # returns a Time that represents the Last-Modified field. def last_modified if vs = @metas['last-modified'] v = vs.join(', ') Time.httpdate(v) else nil end end # :stopdoc: RE_LWS = /[\r\n\t ]+/n RE_TOKEN = %r{[^\x00- ()<>@,;:\\"/\[\]?={}\x7f]+}n RE_QUOTED_STRING = %r{"(?:[\r\n\t !#-\[\]-~\x80-\xff]|\\[\x00-\x7f])*"}n RE_PARAMETERS = %r{(?:;#{RE_LWS}?#{RE_TOKEN}#{RE_LWS}?=#{RE_LWS}?(?:#{RE_TOKEN}|#{RE_QUOTED_STRING})#{RE_LWS}?)*}n # :startdoc: def content_type_parse # :nodoc: vs = @metas['content-type'] # The last (?:;#{RE_LWS}?)? matches extra ";" which violates RFC2045. if vs && %r{\A#{RE_LWS}?(#{RE_TOKEN})#{RE_LWS}?/(#{RE_TOKEN})#{RE_LWS}?(#{RE_PARAMETERS})(?:;#{RE_LWS}?)?\z}no =~ vs.join(', ') type = $1.downcase subtype = $2.downcase parameters = [] $3.scan(/;#{RE_LWS}?(#{RE_TOKEN})#{RE_LWS}?=#{RE_LWS}?(?:(#{RE_TOKEN})|(#{RE_QUOTED_STRING}))/no) {|att, val, qval| if qval val = qval[1...-1].gsub(/[\r\n\t !#-\[\]-~\x80-\xff]+|(\\[\x00-\x7f])/n) { $1 ? $1[1,1] : $& } end parameters << [att.downcase, val] } ["#{type}/#{subtype}", *parameters] else nil end end # returns "type/subtype" which is MIME Content-Type. # It is downcased for canonicalization. # Content-Type parameters are stripped. def content_type type, *_ = content_type_parse type || 'application/octet-stream' end # returns a charset parameter in Content-Type field. # It is downcased for canonicalization. # # If charset parameter is not given but a block is given, # the block is called and its result is returned. # It can be used to guess charset. # # If charset parameter and block is not given, # nil is returned except text type in HTTP. # In that case, "iso-8859-1" is returned as defined by RFC2616 3.7.1. def charset type, *parameters = content_type_parse if pair = parameters.assoc('charset') pair.last.downcase elsif block_given? yield elsif type && %r{\Atext/} =~ type && @base_uri && /\Ahttp\z/i =~ @base_uri.scheme "iso-8859-1" # RFC2616 3.7.1 else nil end end # Returns a list of encodings in Content-Encoding field as an array of # strings. # # The encodings are downcased for canonicalization. def content_encoding vs = @metas['content-encoding'] if vs && %r{\A#{RE_LWS}?#{RE_TOKEN}#{RE_LWS}?(?:,#{RE_LWS}?#{RE_TOKEN}#{RE_LWS}?)*}o =~ (v = vs.join(', ')) v.scan(RE_TOKEN).map {|content_coding| content_coding.downcase} else [] end end end # Mixin for HTTP and FTP URIs. module OpenRead # OpenURI::OpenRead#open provides `open' for URI::HTTP and URI::FTP. # # OpenURI::OpenRead#open takes optional 3 arguments as: # # OpenURI::OpenRead#open([mode [, perm]] [, options]) [{|io| ... }] # # OpenURI::OpenRead#open returns an IO-like object if block is not given. # Otherwise it yields the IO object and return the value of the block. # The IO object is extended with OpenURI::Meta. # # +mode+ and +perm+ are the same as Kernel#open. # # However, +mode+ must be read mode because OpenURI::OpenRead#open doesn't # support write mode (yet). # Also +perm+ is ignored because it is meaningful only for file creation. # # +options+ must be a hash. # # Each option with a string key specifies an extra header field for HTTP. # I.e., it is ignored for FTP without HTTP proxy. # # The hash may include other options, where keys are symbols: # # [:proxy] # Synopsis: # :proxy => "http://proxy.foo.com:8000/" # :proxy => URI.parse("http://proxy.foo.com:8000/") # :proxy => true # :proxy => false # :proxy => nil # # If :proxy option is specified, the value should be String, URI, # boolean or nil. # # When String or URI is given, it is treated as proxy URI. # # When true is given or the option itself is not specified, # environment variable `scheme_proxy' is examined. # `scheme' is replaced by `http', `https' or `ftp'. # # When false or nil is given, the environment variables are ignored and # connection will be made to a server directly. # # [:proxy_http_basic_authentication] # Synopsis: # :proxy_http_basic_authentication => # ["http://proxy.foo.com:8000/", "proxy-user", "proxy-password"] # :proxy_http_basic_authentication => # [URI.parse("http://proxy.foo.com:8000/"), # "proxy-user", "proxy-password"] # # If :proxy option is specified, the value should be an Array with 3 # elements. It should contain a proxy URI, a proxy user name and a proxy # password. The proxy URI should be a String, an URI or nil. The proxy # user name and password should be a String. # # If nil is given for the proxy URI, this option is just ignored. # # If :proxy and :proxy_http_basic_authentication is specified, # ArgumentError is raised. # # [:http_basic_authentication] # Synopsis: # :http_basic_authentication=>[user, password] # # If :http_basic_authentication is specified, # the value should be an array which contains 2 strings: # username and password. # It is used for HTTP Basic authentication defined by RFC 2617. # # [:content_length_proc] # Synopsis: # :content_length_proc => lambda {|content_length| ... } # # If :content_length_proc option is specified, the option value procedure # is called before actual transfer is started. # It takes one argument, which is expected content length in bytes. # # If two or more transfer is done by HTTP redirection, the procedure # is called only one for a last transfer. # # When expected content length is unknown, the procedure is called with # nil. This happens when the HTTP response has no Content-Length header. # # [:progress_proc] # Synopsis: # :progress_proc => lambda {|size| ...} # # If :progress_proc option is specified, the proc is called with one # argument each time when `open' gets content fragment from network. # The argument +size+ is the accumulated transferred size in bytes. # # If two or more transfer is done by HTTP redirection, the procedure # is called only one for a last transfer. # # :progress_proc and :content_length_proc are intended to be used for # progress bar. # For example, it can be implemented as follows using Ruby/ProgressBar. # # pbar = nil # open("http://...", # :content_length_proc => lambda {|t| # if t && 0 < t # pbar = ProgressBar.new("...", t) # pbar.file_transfer_mode # end # }, # :progress_proc => lambda {|s| # pbar.set s if pbar # }) {|f| ... } # # [:read_timeout] # Synopsis: # :read_timeout=>nil (no timeout) # :read_timeout=>10 (10 second) # # :read_timeout option specifies a timeout of read for http connections. # # [:open_timeout] # Synopsis: # :open_timeout=>nil (no timeout) # :open_timeout=>10 (10 second) # # :open_timeout option specifies a timeout of open for http connections. # # [:ssl_ca_cert] # Synopsis: # :ssl_ca_cert=>filename or an Array of filenames # # :ssl_ca_cert is used to specify CA certificate for SSL. # If it is given, default certificates are not used. # # [:ssl_verify_mode] # Synopsis: # :ssl_verify_mode=>mode # # :ssl_verify_mode is used to specify openssl verify mode. # # [:ftp_active_mode] # Synopsis: # :ftp_active_mode=>bool # # :ftp_active_mode => true is used to make ftp active mode. # Ruby 1.9 uses passive mode by default. # Note that the active mode is default in Ruby 1.8 or prior. # # [:redirect] # Synopsis: # :redirect=>bool # # +:redirect+ is true by default. :redirect => false is used to # disable all HTTP redirects. # # OpenURI::HTTPRedirect exception raised on redirection. # Using +true+ also means that redirections between http and ftp are # permitted. # def open(*rest, &block) OpenURI.open_uri(self, *rest, &block) end # OpenURI::OpenRead#read([options]) reads a content referenced by self and # returns the content as string. # The string is extended with OpenURI::Meta. # The argument +options+ is same as OpenURI::OpenRead#open. def read(options={}) self.open(options) {|f| str = f.read Meta.init str, f str } end end end module URI class HTTP def buffer_open(buf, proxy, options) # :nodoc: OpenURI.open_http(buf, self, proxy, options) end include OpenURI::OpenRead end class FTP def buffer_open(buf, proxy, options) # :nodoc: if proxy OpenURI.open_http(buf, self, proxy, options) return end require 'net/ftp' path = self.path path = path.sub(%r{\A/}, '%2F') # re-encode the beginning slash because uri library decodes it. directories = path.split(%r{/}, -1) directories.each {|d| d.gsub!(/%([0-9A-Fa-f][0-9A-Fa-f])/) { [$1].pack("H2") } } unless filename = directories.pop raise ArgumentError, "no filename: #{self.inspect}" end directories.each {|d| if /[\r\n]/ =~ d raise ArgumentError, "invalid directory: #{d.inspect}" end } if /[\r\n]/ =~ filename raise ArgumentError, "invalid filename: #{filename.inspect}" end typecode = self.typecode if typecode && /\A[aid]\z/ !~ typecode raise ArgumentError, "invalid typecode: #{typecode.inspect}" end # The access sequence is defined by RFC 1738 ftp = Net::FTP.new ftp.connect(self.hostname, self.port) ftp.passive = true if !options[:ftp_active_mode] # todo: extract user/passwd from .netrc. user = 'anonymous' passwd = nil user, passwd = self.userinfo.split(/:/) if self.userinfo ftp.login(user, passwd) directories.each {|cwd| ftp.voidcmd("CWD #{cwd}") } if typecode # xxx: typecode D is not handled. ftp.voidcmd("TYPE #{typecode.upcase}") end if options[:content_length_proc] options[:content_length_proc].call(ftp.size(filename)) end ftp.retrbinary("RETR #{filename}", 4096) { |str| buf << str options[:progress_proc].call(buf.size) if options[:progress_proc] } ftp.close buf.io.rewind end include OpenURI::OpenRead end end PK!A""2.2.0/ostruct.rbnu[# # = ostruct.rb: OpenStruct implementation # # Author:: Yukihiro Matsumoto # Documentation:: Gavin Sinclair # # OpenStruct allows the creation of data objects with arbitrary attributes. # See OpenStruct for an example. # # # An OpenStruct is a data structure, similar to a Hash, that allows the # definition of arbitrary attributes with their accompanying values. This is # accomplished by using Ruby's metaprogramming to define methods on the class # itself. # # == Examples # # require "ostruct" # # person = OpenStruct.new # person.name = "John Smith" # person.age = 70 # # person.name # => "John Smith" # person.age # => 70 # person.address # => nil # # An OpenStruct employs a Hash internally to store the attributes and values # and can even be initialized with one: # # australia = OpenStruct.new(:country => "Australia", :capital => "Canberra") # # => # # # Hash keys with spaces or characters that could normally not be used for # method calls (e.g. ()[]*) will not be immediately available # on the OpenStruct object as a method for retrieval or assignment, but can # still be reached through the Object#send method. # # measurements = OpenStruct.new("length (in inches)" => 24) # measurements.send("length (in inches)") # => 24 # # message = OpenStruct.new(:queued? => true) # message.queued? # => true # message.send("queued?=", false) # message.queued? # => false # # Removing the presence of an attribute requires the execution of the # delete_field method as setting the property value to +nil+ will not # remove the attribute. # # first_pet = OpenStruct.new(:name => "Rowdy", :owner => "John Smith") # second_pet = OpenStruct.new(:name => "Rowdy") # # first_pet.owner = nil # first_pet # => # # first_pet == second_pet # => false # # first_pet.delete_field(:owner) # first_pet # => # # first_pet == second_pet # => true # # # == Implementation # # An OpenStruct utilizes Ruby's method lookup structure to find and define the # necessary methods for properties. This is accomplished through the methods # method_missing and define_singleton_method. # # This should be a consideration if there is a concern about the performance of # the objects that are created, as there is much more overhead in the setting # of these properties compared to using a Hash or a Struct. # class OpenStruct # # Creates a new OpenStruct object. By default, the resulting OpenStruct # object will have no attributes. # # The optional +hash+, if given, will generate attributes and values # (can be a Hash, an OpenStruct or a Struct). # For example: # # require "ostruct" # hash = { "country" => "Australia", :capital => "Canberra" } # data = OpenStruct.new(hash) # # data # => # # def initialize(hash=nil) @table = {} if hash hash.each_pair do |k, v| k = k.to_sym @table[k] = v new_ostruct_member(k) end end end # Duplicates an OpenStruct object's Hash table. def initialize_copy(orig) # :nodoc: super @table = @table.dup @table.each_key{|key| new_ostruct_member(key)} end # # Converts the OpenStruct to a hash with keys representing # each attribute (as symbols) and their corresponding values. # # require "ostruct" # data = OpenStruct.new("country" => "Australia", :capital => "Canberra") # data.to_h # => {:country => "Australia", :capital => "Canberra" } # def to_h @table.dup end # # :call-seq: # ostruct.each_pair {|name, value| block } -> ostruct # ostruct.each_pair -> Enumerator # # Yields all attributes (as symbols) along with the corresponding values # or returns an enumerator if no block is given. # # require "ostruct" # data = OpenStruct.new("country" => "Australia", :capital => "Canberra") # data.each_pair.to_a # => [[:country, "Australia"], [:capital, "Canberra"]] # def each_pair return to_enum(__method__) { @table.size } unless block_given? @table.each_pair{|p| yield p} self end # # Provides marshalling support for use by the Marshal library. # def marshal_dump @table end # # Provides marshalling support for use by the Marshal library. # def marshal_load(x) @table = x @table.each_key{|key| new_ostruct_member(key)} end # # Used internally to check if the OpenStruct is able to be # modified before granting access to the internal Hash table to be modified. # def modifiable begin @modifiable = true rescue raise RuntimeError, "can't modify frozen #{self.class}", caller(3) end @table end protected :modifiable # # Used internally to defined properties on the # OpenStruct. It does this by using the metaprogramming function # define_singleton_method for both the getter method and the setter method. # def new_ostruct_member(name) name = name.to_sym unless respond_to?(name) define_singleton_method(name) { @table[name] } define_singleton_method("#{name}=") { |x| modifiable[name] = x } end name end protected :new_ostruct_member def method_missing(mid, *args) # :nodoc: mname = mid.id2name len = args.length if mname.chomp!('=') if len != 1 raise ArgumentError, "wrong number of arguments (#{len} for 1)", caller(1) end modifiable[new_ostruct_member(mname)] = args[0] elsif len == 0 @table[mid] else err = NoMethodError.new "undefined method `#{mid}' for #{self}", mid, args err.set_backtrace caller(1) raise err end end # # :call-seq: # ostruct[name] -> object # # Returns the value of an attribute. # # require "ostruct" # person = OpenStruct.new("name" => "John Smith", "age" => 70) # person[:age] # => 70, same as person.age # def [](name) @table[name.to_sym] end # # :call-seq: # ostruct[name] = obj -> obj # # Sets the value of an attribute. # # require "ostruct" # person = OpenStruct.new("name" => "John Smith", "age" => 70) # person[:age] = 42 # equivalent to person.age = 42 # person.age # => 42 # def []=(name, value) modifiable[new_ostruct_member(name)] = value end # # Removes the named field from the object. Returns the value that the field # contained if it was defined. # # require "ostruct" # # person = OpenStruct.new(name: "John", age: 70, pension: 300) # # person.delete_field("age") # => 70 # person # => # # # Setting the value to +nil+ will not remove the attribute: # # person.pension = nil # person # => # # def delete_field(name) sym = name.to_sym singleton_class.__send__(:remove_method, sym, "#{sym}=") @table.delete sym end InspectKey = :__inspect_key__ # :nodoc: # # Returns a string containing a detailed summary of the keys and values. # def inspect str = "#<#{self.class}" ids = (Thread.current[InspectKey] ||= []) if ids.include?(object_id) return str << ' ...>' end ids << object_id begin first = true for k,v in @table str << "," unless first first = false str << " #{k}=#{v.inspect}" end return str << '>' ensure ids.pop end end alias :to_s :inspect attr_reader :table # :nodoc: protected :table # # Compares this object and +other+ for equality. An OpenStruct is equal to # +other+ when +other+ is an OpenStruct and the two objects' Hash tables are # equal. # # require "ostruct" # first_pet = OpenStruct.new("name" => "Rowdy") # second_pet = OpenStruct.new(:name => "Rowdy") # third_pet = OpenStruct.new("name" => "Rowdy", :age => nil) # # first_pet == second_pet # => true # first_pet == third_pet # => false # def ==(other) return false unless other.kind_of?(OpenStruct) @table == other.table end # # Compares this object and +other+ for equality. An OpenStruct is eql? to # +other+ when +other+ is an OpenStruct and the two objects' Hash tables are # eql?. # def eql?(other) return false unless other.kind_of?(OpenStruct) @table.eql?(other.table) end # Computes a hash code for this OpenStruct. # Two OpenStruct objects with the same content will have the same hash code # (and will compare using #eql?). # # See also Object#hash. def hash @table.hash end end PK!N 2.2.0/base64.rbnu[# # = base64.rb: methods for base64-encoding and -decoding strings # # The Base64 module provides for the encoding (#encode64, #strict_encode64, # #urlsafe_encode64) and decoding (#decode64, #strict_decode64, # #urlsafe_decode64) of binary data using a Base64 representation. # # == Example # # A simple encoding and decoding. # # require "base64" # # enc = Base64.encode64('Send reinforcements') # # -> "U2VuZCByZWluZm9yY2VtZW50cw==\n" # plain = Base64.decode64(enc) # # -> "Send reinforcements" # # The purpose of using base64 to encode data is that it translates any # binary data into purely printable characters. module Base64 module_function # Returns the Base64-encoded version of +bin+. # This method complies with RFC 2045. # Line feeds are added to every 60 encoded characters. # # require 'base64' # Base64.encode64("Now is the time for all good coders\nto learn Ruby") # # Generates: # # Tm93IGlzIHRoZSB0aW1lIGZvciBhbGwgZ29vZCBjb2RlcnMKdG8gbGVhcm4g # UnVieQ== def encode64(bin) [bin].pack("m") end # Returns the Base64-decoded version of +str+. # This method complies with RFC 2045. # Characters outside the base alphabet are ignored. # # require 'base64' # str = 'VGhpcyBpcyBsaW5lIG9uZQpUaGlzIG' + # 'lzIGxpbmUgdHdvClRoaXMgaXMgbGlu' + # 'ZSB0aHJlZQpBbmQgc28gb24uLi4K' # puts Base64.decode64(str) # # Generates: # # This is line one # This is line two # This is line three # And so on... def decode64(str) str.unpack("m").first end # Returns the Base64-encoded version of +bin+. # This method complies with RFC 4648. # No line feeds are added. def strict_encode64(bin) [bin].pack("m0") end # Returns the Base64-decoded version of +str+. # This method complies with RFC 4648. # ArgumentError is raised if +str+ is incorrectly padded or contains # non-alphabet characters. Note that CR or LF are also rejected. def strict_decode64(str) str.unpack("m0").first end # Returns the Base64-encoded version of +bin+. # This method complies with ``Base 64 Encoding with URL and Filename Safe # Alphabet'' in RFC 4648. # The alphabet uses '-' instead of '+' and '_' instead of '/'. def urlsafe_encode64(bin) strict_encode64(bin).tr("+/", "-_") end # Returns the Base64-decoded version of +str+. # This method complies with ``Base 64 Encoding with URL and Filename Safe # Alphabet'' in RFC 4648. # The alphabet uses '-' instead of '+' and '_' instead of '/'. def urlsafe_decode64(str) strict_decode64(str.tr("-_", "+/")) end end PK!f2.2.0/syslog/logger.rbnu[require 'syslog' require 'logger' ## # Syslog::Logger is a Logger work-alike that logs via syslog instead of to a # file. You can use Syslog::Logger to aggregate logs between multiple # machines. # # By default, Syslog::Logger uses the program name 'ruby', but this can be # changed via the first argument to Syslog::Logger.new. # # NOTE! You can only set the Syslog::Logger program name when you initialize # Syslog::Logger for the first time. This is a limitation of the way # Syslog::Logger uses syslog (and in some ways, a limitation of the way # syslog(3) works). Attempts to change Syslog::Logger's program name after # the first initialization will be ignored. # # === Example # # The following will log to syslogd on your local machine: # # require 'syslog/logger' # # log = Syslog::Logger.new 'my_program' # log.info 'this line will be logged via syslog(3)' # # Also the facility may be set to specify the facility level which will be used: # # log.info 'this line will be logged using Syslog default facility level' # # log_local1 = Syslog::Logger.new 'my_program', Syslog::LOG_LOCAL1 # log_local1.info 'this line will be logged using local1 facility level' # # # You may need to perform some syslog.conf setup first. For a BSD machine add # the following lines to /etc/syslog.conf: # # !my_program # *.* /var/log/my_program.log # # Then touch /var/log/my_program.log and signal syslogd with a HUP # (killall -HUP syslogd, on FreeBSD). # # If you wish to have logs automatically roll over and archive, see the # newsyslog.conf(5) and newsyslog(8) man pages. class Syslog::Logger # Default formatter for log messages. class Formatter def call severity, time, progname, msg clean msg end private ## # Clean up messages so they're nice and pretty. def clean message message = message.to_s.strip message.gsub!(/\e\[[0-9;]*m/, '') # remove useless ansi color codes return message end end ## # The version of Syslog::Logger you are using. VERSION = '2.1.0' ## # Maps Logger warning types to syslog(3) warning types. # # Messages from Ruby applications are not considered as critical as messages # from other system daemons using syslog(3), so most messages are reduced by # one level. For example, a fatal message for Ruby's Logger is considered # an error for syslog(3). LEVEL_MAP = { ::Logger::UNKNOWN => Syslog::LOG_ALERT, ::Logger::FATAL => Syslog::LOG_ERR, ::Logger::ERROR => Syslog::LOG_WARNING, ::Logger::WARN => Syslog::LOG_NOTICE, ::Logger::INFO => Syslog::LOG_INFO, ::Logger::DEBUG => Syslog::LOG_DEBUG, } ## # Returns the internal Syslog object that is initialized when the # first instance is created. def self.syslog @@syslog end ## # Specifies the internal Syslog object to be used. def self.syslog= syslog @@syslog = syslog end ## # Builds a methods for level +meth+. def self.make_methods meth level = ::Logger.const_get(meth.upcase) eval <<-EOM, nil, __FILE__, __LINE__ + 1 def #{meth}(message = nil, &block) add(#{level}, message, &block) end def #{meth}? @level <= #{level} end EOM end ## # :method: unknown # # Logs a +message+ at the unknown (syslog alert) log level, or logs the # message returned from the block. ## # :method: fatal # # Logs a +message+ at the fatal (syslog err) log level, or logs the message # returned from the block. ## # :method: error # # Logs a +message+ at the error (syslog warning) log level, or logs the # message returned from the block. ## # :method: warn # # Logs a +message+ at the warn (syslog notice) log level, or logs the # message returned from the block. ## # :method: info # # Logs a +message+ at the info (syslog info) log level, or logs the message # returned from the block. ## # :method: debug # # Logs a +message+ at the debug (syslog debug) log level, or logs the # message returned from the block. Logger::Severity::constants.each do |severity| make_methods severity.downcase end ## # Log level for Logger compatibility. attr_accessor :level # Logging formatter, as a +Proc+ that will take four arguments and # return the formatted message. The arguments are: # # +severity+:: The Severity of the log message. # +time+:: A Time instance representing when the message was logged. # +progname+:: The #progname configured, or passed to the logger method. # +msg+:: The _Object_ the user passed to the log message; not necessarily a # String. # # The block should return an Object that can be written to the logging # device via +write+. The default formatter is used when no formatter is # set. attr_accessor :formatter ## # The facility argument is used to specify what type of program is logging the message. attr_accessor :facility ## # Fills in variables for Logger compatibility. If this is the first # instance of Syslog::Logger, +program_name+ may be set to change the logged # program name. The +facility+ may be set to specify the facility level which will be used. # # Due to the way syslog works, only one program name may be chosen. def initialize program_name = 'ruby', facility = nil @level = ::Logger::DEBUG @formatter = Formatter.new @@syslog ||= Syslog.open(program_name) @facility = (facility || @@syslog.facility) end ## # Almost duplicates Logger#add. +progname+ is ignored. def add severity, message = nil, progname = nil, &block severity ||= ::Logger::UNKNOWN @level <= severity and @@syslog.log( (LEVEL_MAP[severity] | @facility), '%s', formatter.call(severity, Time.now, progname, (message || block.call)) ) true end end PK!(Xњbb0gems/2.2.0/specifications/ruby-lsapi-5.6.gemspecnu[# -*- encoding: utf-8 -*- # stub: ruby-lsapi 5.6 ruby lib # stub: ext/lsapi/extconf.rb Gem::Specification.new do |s| s.name = "ruby-lsapi" s.version = "5.6" s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.require_paths = ["lib"] s.authors = ["LiteSpeed Technologies Inc."] s.date = "2024-01-22" s.description = "This is a ruby extension for fast communication with LiteSpeed Web Server." s.email = "info@litespeedtech.com" s.extensions = ["ext/lsapi/extconf.rb"] s.extra_rdoc_files = ["README"] s.files = ["README", "ext/lsapi/extconf.rb"] s.homepage = "http://www.litespeedtech.com/" s.rubygems_version = "2.4.5.5" s.summary = "A ruby extension for fast communication with LiteSpeed Web Server." s.installed_by_version = "2.4.5.5" if s.respond_to? :installed_by_version end PK!a>:gems/2.2.0/specifications/default/io-console-0.4.3.gemspecnu[# -*- encoding: utf-8 -*- # stub: io-console 0.4.3 ruby lib # stub: extconf.rb Gem::Specification.new do |s| s.name = "io-console" s.version = "0.4.3" s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.require_paths = ["lib"] s.authors = ["Nobu Nakada"] s.cert_chain = ["certs/nobu.pem"] s.date = "2015-07-01" s.description = "add console capabilities to IO instances." s.email = "nobu@ruby-lang.org" s.extensions = ["extconf.rb"] s.files = ["extconf.rb", "io/console.so", "io/console/size.rb"] s.homepage = "http://www.ruby-lang.org" s.licenses = ["ruby"] s.required_ruby_version = Gem::Requirement.new(">= 2.0.0") s.rubygems_version = "2.4.5.5" s.summary = "Console interface" end PK!{dJJ6gems/2.2.0/specifications/default/json-1.8.1.1.gemspecnu[Gem::Specification.new do |s| s.name = "json" s.version = "1.8.1.1" s.summary = "This json is bundled with Ruby" s.executables = [] s.files = ["json.rb", "json/add/bigdecimal.rb", "json/add/complex.rb", "json/add/core.rb", "json/add/date.rb", "json/add/date_time.rb", "json/add/exception.rb", "json/add/ostruct.rb", "json/add/range.rb", "json/add/rational.rb", "json/add/regexp.rb", "json/add/struct.rb", "json/add/symbol.rb", "json/add/time.rb", "json/common.rb", "json/ext.rb", "json/ext/generator.so", "json/ext/parser.so", "json/generic_object.rb", "json/version.rb"] end PK!w 4gems/2.2.0/specifications/default/rdoc-4.2.0.gemspecnu[Gem::Specification.new do |s| s.name = "rdoc" s.version = "4.2.0" s.summary = "This rdoc is bundled with Ruby" s.executables = ["rdoc", "ri"] s.files = ["rdoc.rb", "rdoc/alias.rb", "rdoc/anon_class.rb", "rdoc/any_method.rb", "rdoc/attr.rb", "rdoc/class_module.rb", "rdoc/code_object.rb", "rdoc/code_objects.rb", "rdoc/comment.rb", "rdoc/constant.rb", "rdoc/context.rb", "rdoc/context/section.rb", "rdoc/cross_reference.rb", "rdoc/encoding.rb", "rdoc/erb_partial.rb", "rdoc/erbio.rb", "rdoc/extend.rb", "rdoc/generator.rb", "rdoc/generator/darkfish.rb", "rdoc/generator/json_index.rb", "rdoc/generator/markup.rb", "rdoc/generator/pot.rb", "rdoc/generator/pot/message_extractor.rb", "rdoc/generator/pot/po.rb", "rdoc/generator/pot/po_entry.rb", "rdoc/generator/ri.rb", "rdoc/ghost_method.rb", "rdoc/i18n.rb", "rdoc/i18n/locale.rb", "rdoc/i18n/text.rb", "rdoc/include.rb", "rdoc/known_classes.rb", "rdoc/markdown.rb", "rdoc/markdown/entities.rb", "rdoc/markdown/literals_1_9.rb", "rdoc/markup.rb", "rdoc/markup/attr_changer.rb", "rdoc/markup/attr_span.rb", "rdoc/markup/attribute_manager.rb", "rdoc/markup/attributes.rb", "rdoc/markup/blank_line.rb", "rdoc/markup/block_quote.rb", "rdoc/markup/document.rb", "rdoc/markup/formatter.rb", "rdoc/markup/formatter_test_case.rb", "rdoc/markup/hard_break.rb", "rdoc/markup/heading.rb", "rdoc/markup/include.rb", "rdoc/markup/indented_paragraph.rb", "rdoc/markup/inline.rb", "rdoc/markup/list.rb", "rdoc/markup/list_item.rb", "rdoc/markup/paragraph.rb", "rdoc/markup/parser.rb", "rdoc/markup/pre_process.rb", "rdoc/markup/raw.rb", "rdoc/markup/rule.rb", "rdoc/markup/special.rb", "rdoc/markup/text_formatter_test_case.rb", "rdoc/markup/to_ansi.rb", "rdoc/markup/to_bs.rb", "rdoc/markup/to_html.rb", "rdoc/markup/to_html_crossref.rb", "rdoc/markup/to_html_snippet.rb", "rdoc/markup/to_joined_paragraph.rb", "rdoc/markup/to_label.rb", "rdoc/markup/to_markdown.rb", "rdoc/markup/to_rdoc.rb", "rdoc/markup/to_table_of_contents.rb", "rdoc/markup/to_test.rb", "rdoc/markup/to_tt_only.rb", "rdoc/markup/verbatim.rb", "rdoc/meta_method.rb", "rdoc/method_attr.rb", "rdoc/mixin.rb", "rdoc/normal_class.rb", "rdoc/normal_module.rb", "rdoc/options.rb", "rdoc/parser.rb", "rdoc/parser/c.rb", "rdoc/parser/changelog.rb", "rdoc/parser/markdown.rb", "rdoc/parser/rd.rb", "rdoc/parser/ruby.rb", "rdoc/parser/ruby_tools.rb", "rdoc/parser/simple.rb", "rdoc/parser/text.rb", "rdoc/rd.rb", "rdoc/rd/block_parser.rb", "rdoc/rd/inline.rb", "rdoc/rd/inline_parser.rb", "rdoc/rdoc.rb", "rdoc/require.rb", "rdoc/ri.rb", "rdoc/ri/driver.rb", "rdoc/ri/formatter.rb", "rdoc/ri/paths.rb", "rdoc/ri/store.rb", "rdoc/ri/task.rb", "rdoc/ruby_lex.rb", "rdoc/ruby_token.rb", "rdoc/rubygems_hook.rb", "rdoc/servlet.rb", "rdoc/single_class.rb", "rdoc/stats.rb", "rdoc/stats/normal.rb", "rdoc/stats/quiet.rb", "rdoc/stats/verbose.rb", "rdoc/store.rb", "rdoc/task.rb", "rdoc/test_case.rb", "rdoc/text.rb", "rdoc/token_stream.rb", "rdoc/tom_doc.rb", "rdoc/top_level.rb"] end PK!(7lpp7gems/2.2.0/specifications/default/psych-2.0.8.1.gemspecnu[# -*- encoding: utf-8 -*- # stub: psych 2.0.8.1 ruby lib # stub: ext/psych/extconf.rb Gem::Specification.new do |s| s.name = "psych" s.version = "2.0.8.1" s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.require_paths = ["lib"] s.authors = ["Aaron Patterson"] s.date = "2014-12-05" s.description = "Psych is a YAML parser and emitter. Psych leverages libyaml[http://pyyaml.org/wiki/LibYAML]\nfor its YAML parsing and emitting capabilities. In addition to wrapping\nlibyaml, Psych also knows how to serialize and de-serialize most Ruby objects\nto and from the YAML format." s.email = ["aaron@tenderlovemaking.com"] s.extensions = ["ext/psych/extconf.rb"] s.extra_rdoc_files = ["CHANGELOG.rdoc", "README.rdoc"] s.files = ["CHANGELOG.rdoc", "README.rdoc", "ext/psych/extconf.rb", "psych.rb", "psych.so", "psych/class_loader.rb", "psych/coder.rb", "psych/core_ext.rb", "psych/deprecated.rb", "psych/exception.rb", "psych/handler.rb", "psych/handlers/document_stream.rb", "psych/handlers/recorder.rb", "psych/json/ruby_events.rb", "psych/json/stream.rb", "psych/json/tree_builder.rb", "psych/json/yaml_events.rb", "psych/nodes.rb", "psych/nodes/alias.rb", "psych/nodes/document.rb", "psych/nodes/mapping.rb", "psych/nodes/node.rb", "psych/nodes/scalar.rb", "psych/nodes/sequence.rb", "psych/nodes/stream.rb", "psych/omap.rb", "psych/parser.rb", "psych/scalar_scanner.rb", "psych/set.rb", "psych/stream.rb", "psych/streaming.rb", "psych/syntax_error.rb", "psych/tree_builder.rb", "psych/visitors.rb", "psych/visitors/depth_first.rb", "psych/visitors/emitter.rb", "psych/visitors/json_tree.rb", "psych/visitors/to_ruby.rb", "psych/visitors/visitor.rb", "psych/visitors/yaml_tree.rb", "psych/y.rb", "test/psych/handlers/test_recorder.rb", "test/psych/json/test_stream.rb", "test/psych/nodes/test_enumerable.rb", "test/psych/test_alias_and_anchor.rb", "test/psych/test_array.rb", "test/psych/test_boolean.rb", "test/psych/test_class.rb", "test/psych/test_coder.rb", "test/psych/test_date_time.rb", "test/psych/test_deprecated.rb", "test/psych/test_document.rb", "test/psych/test_emitter.rb", "test/psych/test_encoding.rb", "test/psych/test_exception.rb", "test/psych/test_hash.rb", "test/psych/test_json_tree.rb", "test/psych/test_marshalable.rb", "test/psych/test_merge_keys.rb", "test/psych/test_nil.rb", "test/psych/test_null.rb", "test/psych/test_numeric.rb", "test/psych/test_object.rb", "test/psych/test_object_references.rb", "test/psych/test_omap.rb", "test/psych/test_parser.rb", "test/psych/test_psych.rb", "test/psych/test_safe_load.rb", "test/psych/test_scalar.rb", "test/psych/test_scalar_scanner.rb", "test/psych/test_serialize_subclasses.rb", "test/psych/test_set.rb", "test/psych/test_stream.rb", "test/psych/test_string.rb", "test/psych/test_struct.rb", "test/psych/test_symbol.rb", "test/psych/test_tainted.rb", "test/psych/test_to_yaml_properties.rb", "test/psych/test_tree_builder.rb", "test/psych/test_yaml.rb", "test/psych/test_yamldbm.rb", "test/psych/test_yamlstore.rb", "test/psych/visitors/test_depth_first.rb", "test/psych/visitors/test_emitter.rb", "test/psych/visitors/test_to_ruby.rb", "test/psych/visitors/test_yaml_tree.rb"] s.homepage = "http://github.com/tenderlove/psych" s.licenses = ["MIT"] s.rdoc_options = ["--main", "README.rdoc"] s.required_ruby_version = Gem::Requirement.new(">= 1.9.2") s.rubygems_version = "2.4.5.5" s.summary = "Psych is a YAML parser and emitter" s.test_files = ["test/psych/handlers/test_recorder.rb", "test/psych/json/test_stream.rb", "test/psych/nodes/test_enumerable.rb", "test/psych/test_alias_and_anchor.rb", "test/psych/test_array.rb", "test/psych/test_boolean.rb", "test/psych/test_class.rb", "test/psych/test_coder.rb", "test/psych/test_date_time.rb", "test/psych/test_deprecated.rb", "test/psych/test_document.rb", "test/psych/test_emitter.rb", "test/psych/test_encoding.rb", "test/psych/test_exception.rb", "test/psych/test_hash.rb", "test/psych/test_json_tree.rb", "test/psych/test_marshalable.rb", "test/psych/test_merge_keys.rb", "test/psych/test_nil.rb", "test/psych/test_null.rb", "test/psych/test_numeric.rb", "test/psych/test_object.rb", "test/psych/test_object_references.rb", "test/psych/test_omap.rb", "test/psych/test_parser.rb", "test/psych/test_psych.rb", "test/psych/test_safe_load.rb", "test/psych/test_scalar.rb", "test/psych/test_scalar_scanner.rb", "test/psych/test_serialize_subclasses.rb", "test/psych/test_set.rb", "test/psych/test_stream.rb", "test/psych/test_string.rb", "test/psych/test_struct.rb", "test/psych/test_symbol.rb", "test/psych/test_tainted.rb", "test/psych/test_to_yaml_properties.rb", "test/psych/test_tree_builder.rb", "test/psych/test_yaml.rb", "test/psych/test_yamldbm.rb", "test/psych/test_yamlstore.rb", "test/psych/visitors/test_depth_first.rb", "test/psych/visitors/test_emitter.rb", "test/psych/visitors/test_to_ruby.rb", "test/psych/visitors/test_yaml_tree.rb"] end PK!5gems/2.2.0/specifications/default/rake-10.4.2.gemspecnu[Gem::Specification.new do |s| s.name = "rake" s.version = "10.4.2" s.summary = "This rake is bundled with Ruby" s.executables = ["rake"] s.files = ["rake.rb", "rake/alt_system.rb", "rake/application.rb", "rake/backtrace.rb", "rake/clean.rb", "rake/cloneable.rb", "rake/contrib/compositepublisher.rb", "rake/contrib/ftptools.rb", "rake/contrib/publisher.rb", "rake/contrib/rubyforgepublisher.rb", "rake/contrib/sshpublisher.rb", "rake/contrib/sys.rb", "rake/cpu_counter.rb", "rake/default_loader.rb", "rake/dsl_definition.rb", "rake/early_time.rb", "rake/ext/core.rb", "rake/ext/module.rb", "rake/ext/pathname.rb", "rake/ext/string.rb", "rake/ext/time.rb", "rake/file_creation_task.rb", "rake/file_list.rb", "rake/file_task.rb", "rake/file_utils.rb", "rake/file_utils_ext.rb", "rake/gempackagetask.rb", "rake/invocation_chain.rb", "rake/invocation_exception_mixin.rb", "rake/late_time.rb", "rake/linked_list.rb", "rake/loaders/makefile.rb", "rake/multi_task.rb", "rake/name_space.rb", "rake/packagetask.rb", "rake/pathmap.rb", "rake/phony.rb", "rake/private_reader.rb", "rake/promise.rb", "rake/pseudo_status.rb", "rake/rake_module.rb", "rake/rake_test_loader.rb", "rake/rdoctask.rb", "rake/ruby182_test_unit_fix.rb", "rake/rule_recursion_overflow_error.rb", "rake/runtest.rb", "rake/scope.rb", "rake/task.rb", "rake/task_argument_error.rb", "rake/task_arguments.rb", "rake/task_manager.rb", "rake/tasklib.rb", "rake/testtask.rb", "rake/thread_history_display.rb", "rake/thread_pool.rb", "rake/trace_output.rb", "rake/version.rb", "rake/win32.rb"] end PK!ۓ,[[,gems/2.2.0/specifications/rack-1.6.4.gemspecnu[# -*- encoding: utf-8 -*- # stub: rack 1.6.4 ruby lib Gem::Specification.new do |s| s.name = "rack" s.version = "1.6.4" s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.require_paths = ["lib"] s.authors = ["Christian Neukirchen"] s.date = "2015-06-18" s.description = "Rack provides a minimal, modular and adaptable interface for developing\nweb applications in Ruby. By wrapping HTTP requests and responses in\nthe simplest way possible, it unifies and distills the API for web\nservers, web frameworks, and software in between (the so-called\nmiddleware) into a single method call.\n\nAlso see http://rack.github.io/.\n" s.email = "chneukirchen@gmail.com" s.executables = ["rackup"] s.extra_rdoc_files = ["README.rdoc", "KNOWN-ISSUES", "HISTORY.md"] s.files = ["HISTORY.md", "KNOWN-ISSUES", "README.rdoc", "bin/rackup"] s.homepage = "http://rack.github.io/" s.licenses = ["MIT"] s.rubyforge_project = "rack" s.rubygems_version = "2.4.5.5" s.summary = "a modular Ruby webserver interface" s.installed_by_version = "2.4.5.5" if s.respond_to? :installed_by_version if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q, [">= 0"]) s.add_development_dependency(%q, [">= 0"]) else s.add_dependency(%q, [">= 0"]) s.add_dependency(%q, [">= 0"]) end else s.add_dependency(%q, [">= 0"]) s.add_dependency(%q, [">= 0"]) end end PK!YE[h#gems/2.2.0/gems/rdoc-4.2.0/bin/rdocnuȯ#!/usr/bin/ruby # # RDoc: Documentation tool for source code # (see lib/rdoc/rdoc.rb for more information) # # Copyright (c) 2003 Dave Thomas # Released under the same terms as Ruby begin gem 'rdoc' rescue NameError => e # --disable-gems raise unless e.name == :gem rescue Gem::LoadError end require 'rdoc/rdoc' begin r = RDoc::RDoc.new r.document ARGV rescue Errno::ENOSPC $stderr.puts 'Ran out of space creating documentation' $stderr.puts $stderr.puts 'Please free up some space and try again' rescue SystemExit raise rescue Exception => e if $DEBUG_RDOC then $stderr.puts e.message $stderr.puts "#{e.backtrace.join "\n\t"}" $stderr.puts elsif Interrupt === e then $stderr.puts $stderr.puts 'Interrupted' else $stderr.puts "uh-oh! RDoc had a problem:" $stderr.puts e.message $stderr.puts $stderr.puts "run with --debug for full backtrace" end exit 1 end PK!ֳs!gems/2.2.0/gems/rdoc-4.2.0/bin/rinuȯ#!/usr/bin/ruby begin gem 'rdoc' rescue NameError => e # --disable-gems raise unless e.name == :gem rescue Gem::LoadError end require 'rdoc/ri/driver' RDoc::RI::Driver.run ARGV PK!|77%gems/2.2.0/gems/rack-1.6.4/bin/rackupnuȯ#!/usr/bin/env ruby require "rack" Rack::Server.start PK!EGG-gems/2.2.0/gems/rack-1.6.4/example/lobster.runu[require 'rack/lobster' use Rack::ShowExceptions run Rack::Lobster.new PK!~uu6gems/2.2.0/gems/rack-1.6.4/example/protectedlobster.rbnu[require 'rack' require 'rack/lobster' lobster = Rack::Lobster.new protected_lobster = Rack::Auth::Basic.new(lobster) do |username, password| 'secret' == password end protected_lobster.realm = 'Lobster 2.0' pretty_protected_lobster = Rack::ShowStatus.new(Rack::ShowExceptions.new(protected_lobster)) Rack::Server.start :app => pretty_protected_lobster, :Port => 9292 PK!OK!`6gems/2.2.0/gems/rack-1.6.4/example/protectedlobster.runu[require 'rack/lobster' use Rack::ShowExceptions use Rack::Auth::Basic, "Lobster 2.0" do |username, password| 'secret' == password end run Rack::Lobster.new PK!CrGAA'gems/2.2.0/gems/rack-1.6.4/KNOWN-ISSUESnu[= Known issues with Rack and ECMA-262 * Many users expect the escape() function defined in ECMA-262 to be compatible with URI. Confusion is especially strong because the documentation for the escape function includes a reference to the URI specifications. ECMA-262 escape is not however a URI escape function, it is a javascript escape function, and is not fully compatible. Most notably, for characters outside of the BMP. Users should use the more correct encodeURI functions. = Known issues with Rack and Web servers * Lighttpd sets wrong SCRIPT_NAME and PATH_INFO if you mount your FastCGI app at "/". This can be fixed by using this middleware: class LighttpdScriptNameFix def initialize(app) @app = app end def call(env) env["PATH_INFO"] = env["SCRIPT_NAME"].to_s + env["PATH_INFO"].to_s env["SCRIPT_NAME"] = "" @app.call(env) end end Of course, use this only when your app runs at "/". Since lighttpd 1.4.23, you also can use the "fix-root-scriptname" flag in fastcgi.server. = Known conflicts regarding parameter parsing * Many users have differing opinions about parameter parsing. The current parameter parsers in Rack are based on a combination of the HTTP and CGI specs, and are intended to round-trip encoding and decoding. There are some choices that may be viewed as deficiencies, specifically: - Rack does not create implicit arrays for multiple instances of a parameter - Rack returns nil when a value is not given - Rack does not support multi-type keys in parameters These issues or choices, will not be fixed before 2.0, if at all. They are very major breaking changes. Users are free to write alternative parameter parsers, and their own Request and Response wrappers. Moreover, users are encouraged to do so. PK!/A/A%gems/2.2.0/gems/rack-1.6.4/HISTORY.mdnu[Fri Jun 19 07:14:50 2015 Matthew Draper * Work around a Rails incompatibility in our private API Fri Jun 12 11:37:41 2015 Aaron Patterson * Prevent extremely deep parameters from being parsed. CVE-2015-3225 ### December 18th, Thirty sixth public release 1.6.0 ### February 7th, Thirty fifth public release 1.5.2 - Fix CVE-2013-0263, timing attack against Rack::Session::Cookie - Fix CVE-2013-0262, symlink path traversal in Rack::File - Add various methods to Session for enhanced Rails compatibility - Request#trusted_proxy? now only matches whole stirngs - Add JSON cookie coder, to be default in Rack 1.6+ due to security concerns - URLMap host matching in environments that don't set the Host header fixed - Fix a race condition that could result in overwritten pidfiles - Various documentation additions ### February 7th, Thirty fifth public release 1.4.5 - Fix CVE-2013-0263, timing attack against Rack::Session::Cookie - Fix CVE-2013-0262, symlink path traversal in Rack::File ### February 7th, Thirty fifth public release 1.1.6, 1.2.8, 1.3.10 - Fix CVE-2013-0263, timing attack against Rack::Session::Cookie ### January 28th, 2013: Thirty fourth public release 1.5.1 - Rack::Lint check_hijack now conforms to other parts of SPEC - Added hash-like methods to Abstract::ID::SessionHash for compatibility - Various documentation corrections ### January 21st, 2013: Thirty third public release 1.5.0 - Introduced hijack SPEC, for before-response and after-response hijacking - SessionHash is no longer a Hash subclass - Rack::File cache_control parameter is removed, in place of headers options - Rack::Auth::AbstractRequest#scheme now yields strings, not symbols - Rack::Utils cookie functions now format expires in RFC 2822 format - Rack::File now has a default mime type - rackup -b 'run Rack::File.new(".")', option provides command line configs - Rack::Deflater will no longer double encode bodies - Rack::Mime#match? provides convenience for Accept header matching - Rack::Utils#q_values provides splitting for Accept headers - Rack::Utils#best_q_match provides a helper for Accept headers - Rack::Handler.pick provides convenience for finding available servers - Puma added to the list of default servers (preferred over Webrick) - Various middleware now correctly close body when replacing it - Rack::Request#params is no longer persistent with only GET params - Rack::Request#update_param and #delete_param provide persistent operations - Rack::Request#trusted_proxy? now returns true for local unix sockets - Rack::Response no longer forces Content-Types - Rack::Sendfile provides local mapping configuration options - Rack::Utils#rfc2109 provides old netscape style time output - Updated HTTP status codes - Ruby 1.8.6 likely no longer passes tests, and is no longer fully supported ### January 13th, 2013: Thirty second public release 1.4.4, 1.3.9, 1.2.7, 1.1.5 - [SEC] Rack::Auth::AbstractRequest no longer symbolizes arbitrary strings - Fixed erroneous test case in the 1.3.x series ### January 7th, 2013: Thirty first public release 1.4.3 - Security: Prevent unbounded reads in large multipart boundaries ### January 7th, 2013: Thirtieth public release 1.3.8 - Security: Prevent unbounded reads in large multipart boundaries ### January 6th, 2013: Twenty ninth public release 1.4.2 - Add warnings when users do not provide a session secret - Fix parsing performance for unquoted filenames - Updated URI backports - Fix URI backport version matching, and silence constant warnings - Correct parameter parsing with empty values - Correct rackup '-I' flag, to allow multiple uses - Correct rackup pidfile handling - Report rackup line numbers correctly - Fix request loops caused by non-stale nonces with time limits - Fix reloader on Windows - Prevent infinite recursions from Response#to_ary - Various middleware better conforms to the body close specification - Updated language for the body close specification - Additional notes regarding ECMA escape compatibility issues - Fix the parsing of multiple ranges in range headers - Prevent errors from empty parameter keys - Added PATCH verb to Rack::Request - Various documentation updates - Fix session merge semantics (fixes rack-test) - Rack::Static :index can now handle multiple directories - All tests now utilize Rack::Lint (special thanks to Lars Gierth) - Rack::File cache_control parameter is now deprecated, and removed by 1.5 - Correct Rack::Directory script name escaping - Rack::Static supports header rules for sophisticated configurations - Multipart parsing now works without a Content-Length header - New logos courtesy of Zachary Scott! - Rack::BodyProxy now explicitly defines #each, useful for C extensions - Cookies that are not URI escaped no longer cause exceptions ### January 6th, 2013: Twenty eighth public release 1.3.7 - Add warnings when users do not provide a session secret - Fix parsing performance for unquoted filenames - Updated URI backports - Fix URI backport version matching, and silence constant warnings - Correct parameter parsing with empty values - Correct rackup '-I' flag, to allow multiple uses - Correct rackup pidfile handling - Report rackup line numbers correctly - Fix request loops caused by non-stale nonces with time limits - Fix reloader on Windows - Prevent infinite recursions from Response#to_ary - Various middleware better conforms to the body close specification - Updated language for the body close specification - Additional notes regarding ECMA escape compatibility issues - Fix the parsing of multiple ranges in range headers ### January 6th, 2013: Twenty seventh public release 1.2.6 - Add warnings when users do not provide a session secret - Fix parsing performance for unquoted filenames ### January 6th, 2013: Twenty sixth public release 1.1.4 - Add warnings when users do not provide a session secret ### January 22nd, 2012: Twenty fifth public release 1.4.1 - Alter the keyspace limit calculations to reduce issues with nested params - Add a workaround for multipart parsing where files contain unescaped "%" - Added Rack::Response::Helpers#method_not_allowed? (code 405) - Rack::File now returns 404 for illegal directory traversals - Rack::File now returns 405 for illegal methods (non HEAD/GET) - Rack::Cascade now catches 405 by default, as well as 404 - Cookies missing '--' no longer cause an exception to be raised - Various style changes and documentation spelling errors - Rack::BodyProxy always ensures to execute its block - Additional test coverage around cookies and secrets - Rack::Session::Cookie can now be supplied either secret or old_secret - Tests are no longer dependent on set order - Rack::Static no longer defaults to serving index files - Rack.release was fixed ### December 28th, 2011: Twenty fourth public release 1.4.0 - Ruby 1.8.6 support has officially been dropped. Not all tests pass. - Raise sane error messages for broken config.ru - Allow combining run and map in a config.ru - Rack::ContentType will not set Content-Type for responses without a body - Status code 205 does not send a response body - Rack::Response::Helpers will not rely on instance variables - Rack::Utils.build_query no longer outputs '=' for nil query values - Various mime types added - Rack::MockRequest now supports HEAD - Rack::Directory now supports files that contain RFC3986 reserved chars - Rack::File now only supports GET and HEAD requests - Rack::Server#start now passes the block to Rack::Handler::#run - Rack::Static now supports an index option - Added the Teapot status code - rackup now defaults to Thin instead of Mongrel (if installed) - Support added for HTTP_X_FORWARDED_SCHEME - Numerous bug fixes, including many fixes for new and alternate rubies ### December 28th, 2011: Twenty first public release: 1.1.3. - Security fix. http://www.ocert.org/advisories/ocert-2011-003.html Further information here: http://jruby.org/2011/12/27/jruby-1-6-5-1 ### October 17, 2011: Twentieth public release 1.3.5 - Fix annoying warnings caused by the backport in 1.3.4 ### October 1, 2011: Nineteenth public release 1.3.4 - Backport security fix from 1.9.3, also fixes some roundtrip issues in URI - Small documentation update - Fix an issue where BodyProxy could cause an infinite recursion - Add some supporting files for travis-ci ### September 16, 2011: Eighteenth public release 1.2.4 - Fix a bug with MRI regex engine to prevent XSS by malformed unicode ### September 16, 2011: Seventeenth public release 1.3.3 - Fix bug with broken query parameters in Rack::ShowExceptions - Rack::Request#cookies no longer swallows exceptions on broken input - Prevents XSS attacks enabled by bug in Ruby 1.8's regexp engine - Rack::ConditionalGet handles broken If-Modified-Since helpers ### July 16, 2011: Sixteenth public release 1.3.2 - Fix for Rails and rack-test, Rack::Utils#escape calls to_s ### July 13, 2011: Fifteenth public release 1.3.1 - Fix 1.9.1 support - Fix JRuby support - Properly handle $KCODE in Rack::Utils.escape - Make method_missing/respond_to behavior consistent for Rack::Lock, Rack::Auth::Digest::Request and Rack::Multipart::UploadedFile - Reenable passing rack.session to session middleware - Rack::CommonLogger handles streaming responses correctly - Rack::MockResponse calls close on the body object - Fix a DOS vector from MRI stdlib backport ### May 22nd, 2011: Fourteenth public release 1.2.3 - Pulled in relevant bug fixes from 1.3 - Fixed 1.8.6 support ### May 22nd, 2011: Thirteenth public release 1.3.0 - Various performance optimizations - Various multipart fixes - Various multipart refactors - Infinite loop fix for multipart - Test coverage for Rack::Server returns - Allow files with '..', but not path components that are '..' - rackup accepts handler-specific options on the command line - Request#params no longer merges POST into GET (but returns the same) - Use URI.encode_www_form_component instead. Use core methods for escaping. - Allow multi-line comments in the config file - Bug L#94 reported by Nikolai Lugovoi, query parameter unescaping. - Rack::Response now deletes Content-Length when appropriate - Rack::Deflater now supports streaming - Improved Rack::Handler loading and searching - Support for the PATCH verb - env['rack.session.options'] now contains session options - Cookies respect renew - Session middleware uses SecureRandom.hex ### March 13th, 2011: Twelfth public release 1.2.2/1.1.2. - Security fix in Rack::Auth::Digest::MD5: when authenticator returned nil, permission was granted on empty password. ### June 15th, 2010: Eleventh public release 1.2.1. - Make CGI handler rewindable - Rename spec/ to test/ to not conflict with SPEC on lesser operating systems ### June 13th, 2010: Tenth public release 1.2.0. - Removed Camping adapter: Camping 2.0 supports Rack as-is - Removed parsing of quoted values - Add Request.trace? and Request.options? - Add mime-type for .webm and .htc - Fix HTTP_X_FORWARDED_FOR - Various multipart fixes - Switch test suite to bacon ### January 3rd, 2010: Ninth public release 1.1.0. - Moved Auth::OpenID to rack-contrib. - SPEC change that relaxes Lint slightly to allow subclasses of the required types - SPEC change to document rack.input binary mode in greator detail - SPEC define optional rack.logger specification - File servers support X-Cascade header - Imported Config middleware - Imported ETag middleware - Imported Runtime middleware - Imported Sendfile middleware - New Logger and NullLogger middlewares - Added mime type for .ogv and .manifest. - Don't squeeze PATH_INFO slashes - Use Content-Type to determine POST params parsing - Update Rack::Utils::HTTP_STATUS_CODES hash - Add status code lookup utility - Response should call #to_i on the status - Add Request#user_agent - Request#host knows about forwared host - Return an empty string for Request#host if HTTP_HOST and SERVER_NAME are both missing - Allow MockRequest to accept hash params - Optimizations to HeaderHash - Refactored rackup into Rack::Server - Added Utils.build_nested_query to complement Utils.parse_nested_query - Added Utils::Multipart.build_multipart to complement Utils::Multipart.parse_multipart - Extracted set and delete cookie helpers into Utils so they can be used outside Response - Extract parse_query and parse_multipart in Request so subclasses can change their behavior - Enforce binary encoding in RewindableInput - Set correct external_encoding for handlers that don't use RewindableInput ### October 18th, 2009: Eighth public release 1.0.1. - Bump remainder of rack.versions. - Support the pure Ruby FCGI implementation. - Fix for form names containing "=": split first then unescape components - Fixes the handling of the filename parameter with semicolons in names. - Add anchor to nested params parsing regexp to prevent stack overflows - Use more compatible gzip write api instead of "<<". - Make sure that Reloader doesn't break when executed via ruby -e - Make sure WEBrick respects the :Host option - Many Ruby 1.9 fixes. ### April 25th, 2009: Seventh public release 1.0.0. - SPEC change: Rack::VERSION has been pushed to [1,0]. - SPEC change: header values must be Strings now, split on "\n". - SPEC change: Content-Length can be missing, in this case chunked transfer encoding is used. - SPEC change: rack.input must be rewindable and support reading into a buffer, wrap with Rack::RewindableInput if it isn't. - SPEC change: rack.session is now specified. - SPEC change: Bodies can now additionally respond to #to_path with a filename to be served. - NOTE: String bodies break in 1.9, use an Array consisting of a single String instead. - New middleware Rack::Lock. - New middleware Rack::ContentType. - Rack::Reloader has been rewritten. - Major update to Rack::Auth::OpenID. - Support for nested parameter parsing in Rack::Response. - Support for redirects in Rack::Response. - HttpOnly cookie support in Rack::Response. - The Rakefile has been rewritten. - Many bugfixes and small improvements. ### January 9th, 2009: Sixth public release 0.9.1. - Fix directory traversal exploits in Rack::File and Rack::Directory. ### January 6th, 2009: Fifth public release 0.9. - Rack is now managed by the Rack Core Team. - Rack::Lint is stricter and follows the HTTP RFCs more closely. - Added ConditionalGet middleware. - Added ContentLength middleware. - Added Deflater middleware. - Added Head middleware. - Added MethodOverride middleware. - Rack::Mime now provides popular MIME-types and their extension. - Mongrel Header now streams. - Added Thin handler. - Official support for swiftiplied Mongrel. - Secure cookies. - Made HeaderHash case-preserving. - Many bugfixes and small improvements. ### August 21st, 2008: Fourth public release 0.4. - New middleware, Rack::Deflater, by Christoffer Sawicki. - OpenID authentication now needs ruby-openid 2. - New Memcache sessions, by blink. - Explicit EventedMongrel handler, by Joshua Peek - Rack::Reloader is not loaded in rackup development mode. - rackup can daemonize with -D. - Many bugfixes, especially for pool sessions, URLMap, thread safety and tempfile handling. - Improved tests. - Rack moved to Git. ### February 26th, 2008: Third public release 0.3. - LiteSpeed handler, by Adrian Madrid. - SCGI handler, by Jeremy Evans. - Pool sessions, by blink. - OpenID authentication, by blink. - :Port and :File options for opening FastCGI sockets, by blink. - Last-Modified HTTP header for Rack::File, by blink. - Rack::Builder#use now accepts blocks, by Corey Jewett. (See example/protectedlobster.ru) - HTTP status 201 can contain a Content-Type and a body now. - Many bugfixes, especially related to Cookie handling. ### May 16th, 2007: Second public release 0.2. - HTTP Basic authentication. - Cookie Sessions. - Static file handler. - Improved Rack::Request. - Improved Rack::Response. - Added Rack::ShowStatus, for better default error messages. - Bug fixes in the Camping adapter. - Removed Rails adapter, was too alpha. ### March 3rd, 2007: First public release 0.1. PK!2'gems/2.2.0/gems/rack-1.6.4/rack.gemspecnu[# -*- encoding: utf-8 -*- # stub: rack 1.6.4 ruby lib Gem::Specification.new do |s| s.name = "rack" s.version = "1.6.4" s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.require_paths = ["lib"] s.authors = ["Christian Neukirchen"] s.date = "2015-06-18" s.description = "Rack provides a minimal, modular and adaptable interface for developing\nweb applications in Ruby. By wrapping HTTP requests and responses in\nthe simplest way possible, it unifies and distills the API for web\nservers, web frameworks, and software in between (the so-called\nmiddleware) into a single method call.\n\nAlso see http://rack.github.io/.\n" s.email = "chneukirchen@gmail.com" s.executables = ["rackup"] s.extra_rdoc_files = ["README.rdoc", "KNOWN-ISSUES", "HISTORY.md"] s.files = ["COPYING", "HISTORY.md", "KNOWN-ISSUES", "README.rdoc", "Rakefile", "SPEC", "bin/rackup", "contrib/rack.png", "contrib/rack.svg", "contrib/rack_logo.svg", "contrib/rdoc.css", "example/lobster.ru", "example/protectedlobster.rb", "example/protectedlobster.ru", "lib/rack.rb", "lib/rack/auth/abstract/handler.rb", "lib/rack/auth/abstract/request.rb", "lib/rack/auth/basic.rb", "lib/rack/auth/digest/md5.rb", "lib/rack/auth/digest/nonce.rb", "lib/rack/auth/digest/params.rb", "lib/rack/auth/digest/request.rb", "lib/rack/backports/uri/common_18.rb", "lib/rack/backports/uri/common_192.rb", "lib/rack/backports/uri/common_193.rb", "lib/rack/body_proxy.rb", "lib/rack/builder.rb", "lib/rack/cascade.rb", "lib/rack/chunked.rb", "lib/rack/commonlogger.rb", "lib/rack/conditionalget.rb", "lib/rack/config.rb", "lib/rack/content_length.rb", "lib/rack/content_type.rb", "lib/rack/deflater.rb", "lib/rack/directory.rb", "lib/rack/etag.rb", "lib/rack/file.rb", "lib/rack/handler.rb", "lib/rack/handler/cgi.rb", "lib/rack/handler/evented_mongrel.rb", "lib/rack/handler/fastcgi.rb", "lib/rack/handler/lsws.rb", "lib/rack/handler/mongrel.rb", "lib/rack/handler/scgi.rb", "lib/rack/handler/swiftiplied_mongrel.rb", "lib/rack/handler/thin.rb", "lib/rack/handler/webrick.rb", "lib/rack/head.rb", "lib/rack/lint.rb", "lib/rack/lobster.rb", "lib/rack/lock.rb", "lib/rack/logger.rb", "lib/rack/methodoverride.rb", "lib/rack/mime.rb", "lib/rack/mock.rb", "lib/rack/multipart.rb", "lib/rack/multipart/generator.rb", "lib/rack/multipart/parser.rb", "lib/rack/multipart/uploaded_file.rb", "lib/rack/nulllogger.rb", "lib/rack/recursive.rb", "lib/rack/reloader.rb", "lib/rack/request.rb", "lib/rack/response.rb", "lib/rack/rewindable_input.rb", "lib/rack/runtime.rb", "lib/rack/sendfile.rb", "lib/rack/server.rb", "lib/rack/session/abstract/id.rb", "lib/rack/session/cookie.rb", "lib/rack/session/memcache.rb", "lib/rack/session/pool.rb", "lib/rack/showexceptions.rb", "lib/rack/showstatus.rb", "lib/rack/static.rb", "lib/rack/tempfile_reaper.rb", "lib/rack/urlmap.rb", "lib/rack/utils.rb", "lib/rack/utils/okjson.rb", "rack.gemspec", "test/builder/anything.rb", "test/builder/comment.ru", "test/builder/end.ru", "test/builder/line.ru", "test/builder/options.ru", "test/cgi/assets/folder/test.js", "test/cgi/assets/fonts/font.eot", "test/cgi/assets/images/image.png", "test/cgi/assets/index.html", "test/cgi/assets/javascripts/app.js", "test/cgi/assets/stylesheets/app.css", "test/cgi/lighttpd.conf", "test/cgi/lighttpd.errors", "test/cgi/rackup_stub.rb", "test/cgi/sample_rackup.ru", "test/cgi/test", "test/cgi/test+directory/test+file", "test/cgi/test.fcgi", "test/cgi/test.ru", "test/gemloader.rb", "test/multipart/bad_robots", "test/multipart/binary", "test/multipart/content_type_and_no_filename", "test/multipart/empty", "test/multipart/fail_16384_nofile", "test/multipart/file1.txt", "test/multipart/filename_and_modification_param", "test/multipart/filename_and_no_name", "test/multipart/filename_with_escaped_quotes", "test/multipart/filename_with_escaped_quotes_and_modification_param", "test/multipart/filename_with_percent_escaped_quotes", "test/multipart/filename_with_unescaped_percentages", "test/multipart/filename_with_unescaped_percentages2", "test/multipart/filename_with_unescaped_percentages3", "test/multipart/filename_with_unescaped_quotes", "test/multipart/ie", "test/multipart/invalid_character", "test/multipart/mixed_files", "test/multipart/nested", "test/multipart/none", "test/multipart/semicolon", "test/multipart/text", "test/multipart/three_files_three_fields", "test/multipart/webkit", "test/rackup/config.ru", "test/registering_handler/rack/handler/registering_myself.rb", "test/spec_auth_basic.rb", "test/spec_auth_digest.rb", "test/spec_body_proxy.rb", "test/spec_builder.rb", "test/spec_cascade.rb", "test/spec_cgi.rb", "test/spec_chunked.rb", "test/spec_commonlogger.rb", "test/spec_conditionalget.rb", "test/spec_config.rb", "test/spec_content_length.rb", "test/spec_content_type.rb", "test/spec_deflater.rb", "test/spec_directory.rb", "test/spec_etag.rb", "test/spec_fastcgi.rb", "test/spec_file.rb", "test/spec_handler.rb", "test/spec_head.rb", "test/spec_lint.rb", "test/spec_lobster.rb", "test/spec_lock.rb", "test/spec_logger.rb", "test/spec_methodoverride.rb", "test/spec_mime.rb", "test/spec_mock.rb", "test/spec_mongrel.rb", "test/spec_multipart.rb", "test/spec_nulllogger.rb", "test/spec_recursive.rb", "test/spec_request.rb", "test/spec_response.rb", "test/spec_rewindable_input.rb", "test/spec_runtime.rb", "test/spec_sendfile.rb", "test/spec_server.rb", "test/spec_session_abstract_id.rb", "test/spec_session_cookie.rb", "test/spec_session_memcache.rb", "test/spec_session_pool.rb", "test/spec_showexceptions.rb", "test/spec_showstatus.rb", "test/spec_static.rb", "test/spec_tempfile_reaper.rb", "test/spec_thin.rb", "test/spec_urlmap.rb", "test/spec_utils.rb", "test/spec_version.rb", "test/spec_webrick.rb", "test/static/another/index.html", "test/static/index.html", "test/testrequest.rb", "test/unregistered_handler/rack/handler/unregistered.rb", "test/unregistered_handler/rack/handler/unregistered_long_one.rb"] s.homepage = "http://rack.github.io/" s.licenses = ["MIT"] s.rubyforge_project = "rack" s.rubygems_version = "2.4.5.5" s.summary = "a modular Ruby webserver interface" s.test_files = ["test/spec_auth_basic.rb", "test/spec_auth_digest.rb", "test/spec_body_proxy.rb", "test/spec_builder.rb", "test/spec_cascade.rb", "test/spec_cgi.rb", "test/spec_chunked.rb", "test/spec_commonlogger.rb", "test/spec_conditionalget.rb", "test/spec_config.rb", "test/spec_content_length.rb", "test/spec_content_type.rb", "test/spec_deflater.rb", "test/spec_directory.rb", "test/spec_etag.rb", "test/spec_fastcgi.rb", "test/spec_file.rb", "test/spec_handler.rb", "test/spec_head.rb", "test/spec_lint.rb", "test/spec_lobster.rb", "test/spec_lock.rb", "test/spec_logger.rb", "test/spec_methodoverride.rb", "test/spec_mime.rb", "test/spec_mock.rb", "test/spec_mongrel.rb", "test/spec_multipart.rb", "test/spec_nulllogger.rb", "test/spec_recursive.rb", "test/spec_request.rb", "test/spec_response.rb", "test/spec_rewindable_input.rb", "test/spec_runtime.rb", "test/spec_sendfile.rb", "test/spec_server.rb", "test/spec_session_abstract_id.rb", "test/spec_session_cookie.rb", "test/spec_session_memcache.rb", "test/spec_session_pool.rb", "test/spec_showexceptions.rb", "test/spec_showstatus.rb", "test/spec_static.rb", "test/spec_tempfile_reaper.rb", "test/spec_thin.rb", "test/spec_urlmap.rb", "test/spec_utils.rb", "test/spec_version.rb", "test/spec_webrick.rb"] if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q, [">= 0"]) s.add_development_dependency(%q, [">= 0"]) else s.add_dependency(%q, [">= 0"]) s.add_dependency(%q, [">= 0"]) end else s.add_dependency(%q, [">= 0"]) s.add_dependency(%q, [">= 0"]) end end PK!  2gems/2.2.0/gems/rack-1.6.4/test/spec_showstatus.rbnu[require 'rack/showstatus' require 'rack/lint' require 'rack/mock' require 'rack/utils' describe Rack::ShowStatus do def show_status(app) Rack::Lint.new Rack::ShowStatus.new(app) end should "provide a default status message" do req = Rack::MockRequest.new( show_status(lambda{|env| [404, {"Content-Type" => "text/plain", "Content-Length" => "0"}, []] })) res = req.get("/", :lint => true) res.should.be.not_found res.should.be.not.empty res["Content-Type"].should.equal("text/html") res.should =~ /404/ res.should =~ /Not Found/ end should "let the app provide additional information" do req = Rack::MockRequest.new( show_status( lambda{|env| env["rack.showstatus.detail"] = "gone too meta." [404, {"Content-Type" => "text/plain", "Content-Length" => "0"}, []] })) res = req.get("/", :lint => true) res.should.be.not_found res.should.be.not.empty res["Content-Type"].should.equal("text/html") res.should =~ /404/ res.should =~ /Not Found/ res.should =~ /too meta/ end should "escape error" do detail = "" req = Rack::MockRequest.new( show_status( lambda{|env| env["rack.showstatus.detail"] = detail [500, {"Content-Type" => "text/plain", "Content-Length" => "0"}, []] })) res = req.get("/", :lint => true) res.should.be.not.empty res["Content-Type"].should.equal("text/html") res.should =~ /500/ res.should.not.include detail res.body.should.include Rack::Utils.escape_html(detail) end should "not replace existing messages" do req = Rack::MockRequest.new( show_status( lambda{|env| [404, {"Content-Type" => "text/plain", "Content-Length" => "4"}, ["foo!"]] })) res = req.get("/", :lint => true) res.should.be.not_found res.body.should == "foo!" end should "pass on original headers" do headers = {"WWW-Authenticate" => "Basic blah"} req = Rack::MockRequest.new( show_status(lambda{|env| [401, headers, []] })) res = req.get("/", :lint => true) res["WWW-Authenticate"].should.equal("Basic blah") end should "replace existing messages if there is detail" do req = Rack::MockRequest.new( show_status( lambda{|env| env["rack.showstatus.detail"] = "gone too meta." [404, {"Content-Type" => "text/plain", "Content-Length" => "4"}, ["foo!"]] })) res = req.get("/", :lint => true) res.should.be.not_found res.should.be.not.empty res["Content-Type"].should.equal("text/html") res["Content-Length"].should.not.equal("4") res.should =~ /404/ res.should =~ /too meta/ res.body.should.not =~ /foo/ end end PK!K 6gems/2.2.0/gems/rack-1.6.4/test/spec_methodoverride.rbnu[require 'stringio' require 'rack/methodoverride' require 'rack/mock' describe Rack::MethodOverride do def app Rack::Lint.new(Rack::MethodOverride.new(lambda {|e| [200, {"Content-Type" => "text/plain"}, []] })) end should "not affect GET requests" do env = Rack::MockRequest.env_for("/?_method=delete", :method => "GET") app.call env env["REQUEST_METHOD"].should.equal "GET" end should "modify REQUEST_METHOD for POST requests when _method parameter is set" do env = Rack::MockRequest.env_for("/", :method => "POST", :input => "_method=put") app.call env env["REQUEST_METHOD"].should.equal "PUT" end should "modify REQUEST_METHOD for POST requests when X-HTTP-Method-Override is set" do env = Rack::MockRequest.env_for("/", :method => "POST", "HTTP_X_HTTP_METHOD_OVERRIDE" => "PATCH" ) app.call env env["REQUEST_METHOD"].should.equal "PATCH" end should "not modify REQUEST_METHOD if the method is unknown" do env = Rack::MockRequest.env_for("/", :method => "POST", :input => "_method=foo") app.call env env["REQUEST_METHOD"].should.equal "POST" end should "not modify REQUEST_METHOD when _method is nil" do env = Rack::MockRequest.env_for("/", :method => "POST", :input => "foo=bar") app.call env env["REQUEST_METHOD"].should.equal "POST" end should "store the original REQUEST_METHOD prior to overriding" do env = Rack::MockRequest.env_for("/", :method => "POST", :input => "_method=options") app.call env env["rack.methodoverride.original_method"].should.equal "POST" end should "not modify REQUEST_METHOD when given invalid multipart form data" do input = < "multipart/form-data, boundary=AaB03x", "CONTENT_LENGTH" => input.size.to_s, :method => "POST", :input => input) begin app.call env rescue EOFError end env["REQUEST_METHOD"].should.equal "POST" end should "not modify REQUEST_METHOD for POST requests when the params are unparseable" do env = Rack::MockRequest.env_for("/", :method => "POST", :input => "(%bad-params%)") app.call env env["REQUEST_METHOD"].should.equal "POST" end end PK!(/gems/2.2.0/gems/rack-1.6.4/test/spec_handler.rbnu[require 'rack/handler' class Rack::Handler::Lobster; end class RockLobster; end describe Rack::Handler do it "has registered default handlers" do Rack::Handler.get('cgi').should.equal Rack::Handler::CGI Rack::Handler.get('webrick').should.equal Rack::Handler::WEBrick begin Rack::Handler.get('fastcgi').should.equal Rack::Handler::FastCGI rescue LoadError end begin Rack::Handler.get('mongrel').should.equal Rack::Handler::Mongrel rescue LoadError end end should "raise LoadError if handler doesn't exist" do lambda { Rack::Handler.get('boom') }.should.raise(LoadError) lambda { Rack::Handler.get('Object') }.should.raise(LoadError) end should "get unregistered, but already required, handler by name" do Rack::Handler.get('Lobster').should.equal Rack::Handler::Lobster end should "register custom handler" do Rack::Handler.register('rock_lobster', 'RockLobster') Rack::Handler.get('rock_lobster').should.equal RockLobster end should "not need registration for properly coded handlers even if not already required" do begin $LOAD_PATH.push File.expand_path('../unregistered_handler', __FILE__) Rack::Handler.get('Unregistered').should.equal Rack::Handler::Unregistered lambda { Rack::Handler.get('UnRegistered') }.should.raise LoadError Rack::Handler.get('UnregisteredLongOne').should.equal Rack::Handler::UnregisteredLongOne ensure $LOAD_PATH.delete File.expand_path('../unregistered_handler', __FILE__) end end should "allow autoloaded handlers to be registered properly while being loaded" do path = File.expand_path('../registering_handler', __FILE__) begin $LOAD_PATH.push path Rack::Handler.get('registering_myself').should.equal Rack::Handler::RegisteringMyself ensure $LOAD_PATH.delete path end end end PK!lM*(*(0gems/2.2.0/gems/rack-1.6.4/test/spec_deflater.rbnu[require 'stringio' require 'time' # for Time#httpdate require 'rack/deflater' require 'rack/lint' require 'rack/mock' require 'zlib' describe Rack::Deflater do def build_response(status, body, accept_encoding, options = {}) body = [body] if body.respond_to? :to_str app = lambda do |env| res = [status, options['response_headers'] || {}, body] res[1]['Content-Type'] = 'text/plain' unless res[0] == 304 res end request = Rack::MockRequest.env_for('', (options['request_headers'] || {}).merge('HTTP_ACCEPT_ENCODING' => accept_encoding)) deflater = Rack::Lint.new Rack::Deflater.new(app, options['deflater_options'] || {}) deflater.call(request) end ## # Constructs response object and verifies if it yields right results # # [expected_status] expected response status, e.g. 200, 304 # [expected_body] expected response body # [accept_encoing] what Accept-Encoding header to send and expect, e.g. # 'deflate' - accepts and expects deflate encoding in response # { 'gzip' => nil } - accepts gzip but expects no encoding in response # [options] hash of request options, i.e. # 'app_status' - what status dummy app should return (may be changed by deflater at some point) # 'app_body' - what body dummy app should return (may be changed by deflater at some point) # 'request_headers' - extra reqest headers to be sent # 'response_headers' - extra response headers to be returned # 'deflater_options' - options passed to deflater middleware # [block] useful for doing some extra verification def verify(expected_status, expected_body, accept_encoding, options = {}, &block) accept_encoding, expected_encoding = if accept_encoding.kind_of?(Hash) [accept_encoding.keys.first, accept_encoding.values.first] else [accept_encoding, accept_encoding.dup] end # build response status, headers, body = build_response( options['app_status'] || expected_status, options['app_body'] || expected_body, accept_encoding, options ) # verify status status.should.equal(expected_status) # verify body unless options['skip_body_verify'] body_text = '' body.each { |part| body_text << part } deflated_body = case expected_encoding when 'deflate' inflater = Zlib::Inflate.new(-Zlib::MAX_WBITS) inflater.inflate(body_text) << inflater.finish when 'gzip' io = StringIO.new(body_text) gz = Zlib::GzipReader.new(io) tmp = gz.read gz.close tmp else body_text end deflated_body.should.equal(expected_body) end # yield full response verification yield(status, headers, body) if block_given? end should 'be able to deflate bodies that respond to each' do app_body = Object.new class << app_body; def each; yield('foo'); yield('bar'); end; end verify(200, 'foobar', 'deflate', { 'app_body' => app_body }) do |status, headers, body| headers.should.equal({ 'Content-Encoding' => 'deflate', 'Vary' => 'Accept-Encoding', 'Content-Type' => 'text/plain' }) end end should 'flush deflated chunks to the client as they become ready' do app_body = Object.new class << app_body; def each; yield('foo'); yield('bar'); end; end verify(200, app_body, 'deflate', { 'skip_body_verify' => true }) do |status, headers, body| headers.should.equal({ 'Content-Encoding' => 'deflate', 'Vary' => 'Accept-Encoding', 'Content-Type' => 'text/plain' }) buf = [] inflater = Zlib::Inflate.new(-Zlib::MAX_WBITS) body.each { |part| buf << inflater.inflate(part) } buf << inflater.finish buf.delete_if { |part| part.empty? }.join.should.equal('foobar') end end # TODO: This is really just a special case of the above... should 'be able to deflate String bodies' do verify(200, 'Hello world!', 'deflate') do |status, headers, body| headers.should.equal({ 'Content-Encoding' => 'deflate', 'Vary' => 'Accept-Encoding', 'Content-Type' => 'text/plain' }) end end should 'be able to gzip bodies that respond to each' do app_body = Object.new class << app_body; def each; yield('foo'); yield('bar'); end; end verify(200, 'foobar', 'gzip', { 'app_body' => app_body }) do |status, headers, body| headers.should.equal({ 'Content-Encoding' => 'gzip', 'Vary' => 'Accept-Encoding', 'Content-Type' => 'text/plain' }) end end should 'flush gzipped chunks to the client as they become ready' do app_body = Object.new class << app_body; def each; yield('foo'); yield('bar'); end; end verify(200, app_body, 'gzip', { 'skip_body_verify' => true }) do |status, headers, body| headers.should.equal({ 'Content-Encoding' => 'gzip', 'Vary' => 'Accept-Encoding', 'Content-Type' => 'text/plain' }) buf = [] inflater = Zlib::Inflate.new(Zlib::MAX_WBITS + 32) body.each { |part| buf << inflater.inflate(part) } buf << inflater.finish buf.delete_if { |part| part.empty? }.join.should.equal('foobar') end end should 'be able to fallback to no deflation' do verify(200, 'Hello world!', 'superzip') do |status, headers, body| headers.should.equal({ 'Vary' => 'Accept-Encoding', 'Content-Type' => 'text/plain' }) end end should 'be able to skip when there is no response entity body' do verify(304, '', { 'gzip' => nil }, { 'app_body' => [] }) do |status, headers, body| headers.should.equal({}) end end should 'handle the lack of an acceptable encoding' do app_body = 'Hello world!' not_found_body1 = 'An acceptable encoding for the requested resource / could not be found.' not_found_body2 = 'An acceptable encoding for the requested resource /foo/bar could not be found.' options1 = { 'app_status' => 200, 'app_body' => app_body, 'request_headers' => { 'PATH_INFO' => '/' } } options2 = { 'app_status' => 200, 'app_body' => app_body, 'request_headers' => { 'PATH_INFO' => '/foo/bar' } } verify(406, not_found_body1, 'identity;q=0', options1) do |status, headers, body| headers.should.equal({ 'Content-Type' => 'text/plain', 'Content-Length' => not_found_body1.length.to_s }) end verify(406, not_found_body2, 'identity;q=0', options2) do |status, headers, body| headers.should.equal({ 'Content-Type' => 'text/plain', 'Content-Length' => not_found_body2.length.to_s }) end end should 'handle gzip response with Last-Modified header' do last_modified = Time.now.httpdate options = { 'response_headers' => { 'Content-Type' => 'text/plain', 'Last-Modified' => last_modified } } verify(200, 'Hello World!', 'gzip', options) do |status, headers, body| headers.should.equal({ 'Content-Encoding' => 'gzip', 'Vary' => 'Accept-Encoding', 'Last-Modified' => last_modified, 'Content-Type' => 'text/plain' }) end end should 'do nothing when no-transform Cache-Control directive present' do options = { 'response_headers' => { 'Content-Type' => 'text/plain', 'Cache-Control' => 'no-transform' } } verify(200, 'Hello World!', { 'gzip' => nil }, options) do |status, headers, body| headers.should.not.include 'Content-Encoding' end end should 'do nothing when Content-Encoding already present' do options = { 'response_headers' => { 'Content-Type' => 'text/plain', 'Content-Encoding' => 'gzip' } } verify(200, 'Hello World!', { 'gzip' => nil }, options) end should 'deflate when Content-Encoding is identity' do options = { 'response_headers' => { 'Content-Type' => 'text/plain', 'Content-Encoding' => 'identity' } } verify(200, 'Hello World!', 'deflate', options) end should "deflate if content-type matches :include" do options = { 'response_headers' => { 'Content-Type' => 'text/plain' }, 'deflater_options' => { :include => %w(text/plain) } } verify(200, 'Hello World!', 'gzip', options) end should "deflate if content-type is included it :include" do options = { 'response_headers' => { 'Content-Type' => 'text/plain; charset=us-ascii' }, 'deflater_options' => { :include => %w(text/plain) } } verify(200, 'Hello World!', 'gzip', options) end should "not deflate if content-type is not set but given in :include" do options = { 'deflater_options' => { :include => %w(text/plain) } } verify(304, 'Hello World!', { 'gzip' => nil }, options) end should "not deflate if content-type do not match :include" do options = { 'response_headers' => { 'Content-Type' => 'text/plain' }, 'deflater_options' => { :include => %w(text/json) } } verify(200, 'Hello World!', { 'gzip' => nil }, options) end should "deflate response if :if lambda evaluates to true" do options = { 'deflater_options' => { :if => lambda { |env, status, headers, body| true } } } verify(200, 'Hello World!', 'deflate', options) end should "not deflate if :if lambda evaluates to false" do options = { 'deflater_options' => { :if => lambda { |env, status, headers, body| false } } } verify(200, 'Hello World!', { 'gzip' => nil }, options) end should "check for Content-Length via :if" do body = 'Hello World!' body_len = body.length options = { 'response_headers' => { 'Content-Length' => body_len.to_s }, 'deflater_options' => { :if => lambda { |env, status, headers, body| headers['Content-Length'].to_i >= body_len } } } verify(200, body, 'gzip', options) end end PK!CgR R /gems/2.2.0/gems/rack-1.6.4/test/spec_fastcgi.rbnu[begin require File.expand_path('../testrequest', __FILE__) require 'rack/handler/fastcgi' describe Rack::Handler::FastCGI do extend TestRequest::Helpers @host = '127.0.0.1' @port = 9203 if `which lighttpd` && !$?.success? raise "lighttpd not found" end # Keep this first. $pid = fork { ENV['RACK_ENV'] = 'deployment' ENV['RUBYLIB'] = [ File.expand_path('../../lib', __FILE__), ENV['RUBYLIB'], ].compact.join(':') Dir.chdir(File.expand_path("../cgi", __FILE__)) do exec "lighttpd -D -f lighttpd.conf" end } should "respond" do sleep 1 GET("/test") response.should.not.be.nil end should "respond via rackup server" do GET("/sample_rackup.ru") status.should.equal 200 end should "be a lighttpd" do GET("/test.fcgi") status.should.equal 200 response["SERVER_SOFTWARE"].should =~ /lighttpd/ response["HTTP_VERSION"].should.equal "HTTP/1.1" response["SERVER_PROTOCOL"].should.equal "HTTP/1.1" response["SERVER_PORT"].should.equal @port.to_s response["SERVER_NAME"].should.equal @host end should "have rack headers" do GET("/test.fcgi") response["rack.version"].should.equal [1,3] response["rack.multithread"].should.be.false response["rack.multiprocess"].should.be.true response["rack.run_once"].should.be.false end should "have CGI headers on GET" do GET("/test.fcgi") response["REQUEST_METHOD"].should.equal "GET" response["SCRIPT_NAME"].should.equal "/test.fcgi" response["REQUEST_PATH"].should.equal "/" response["PATH_INFO"].should.equal "" response["QUERY_STRING"].should.equal "" response["test.postdata"].should.equal "" GET("/test.fcgi/foo?quux=1") response["REQUEST_METHOD"].should.equal "GET" response["SCRIPT_NAME"].should.equal "/test.fcgi" response["REQUEST_PATH"].should.equal "/" response["PATH_INFO"].should.equal "/foo" response["QUERY_STRING"].should.equal "quux=1" end should "have CGI headers on POST" do POST("/test.fcgi", {"rack-form-data" => "23"}, {'X-test-header' => '42'}) status.should.equal 200 response["REQUEST_METHOD"].should.equal "POST" response["SCRIPT_NAME"].should.equal "/test.fcgi" response["REQUEST_PATH"].should.equal "/" response["QUERY_STRING"].should.equal "" response["HTTP_X_TEST_HEADER"].should.equal "42" response["test.postdata"].should.equal "rack-form-data=23" end should "support HTTP auth" do GET("/test.fcgi", {:user => "ruth", :passwd => "secret"}) response["HTTP_AUTHORIZATION"].should.equal "Basic cnV0aDpzZWNyZXQ=" end should "set status" do GET("/test.fcgi?secret") status.should.equal 403 response["rack.url_scheme"].should.equal "http" end # Keep this last. should "shutdown" do Process.kill 15, $pid Process.wait($pid).should.equal $pid end end rescue RuntimeError $stderr.puts "Skipping Rack::Handler::FastCGI tests (lighttpd is required). Install lighttpd and try again." rescue LoadError $stderr.puts "Skipping Rack::Handler::FastCGI tests (FCGI is required). `gem install fcgi` and try again." end PK!TTBRR2gems/2.2.0/gems/rack-1.6.4/test/builder/comment.runu[=begin =end run lambda { |env| [200, {'Content-Type' => 'text/plain'}, ['OK']] } PK!y^KK2gems/2.2.0/gems/rack-1.6.4/test/builder/options.runu[#\ -d run lambda { |env| [200, {'Content-Type' => 'text/plain'}, ['OK']] } PK! â.bb3gems/2.2.0/gems/rack-1.6.4/test/builder/anything.rbnu[class Anything def self.call(env) [200, {'Content-Type' => 'text/plain'}, ['OK']] end end PK!ǭMM/gems/2.2.0/gems/rack-1.6.4/test/builder/line.runu[run lambda{ |env| [200, {'Content-Type' => 'text/plain'}, [__LINE__.to_s]] } PK!ga$yy.gems/2.2.0/gems/rack-1.6.4/test/builder/end.runu[run lambda { |env| [200, {'Content-Type' => 'text/plain'}, ['OK']] } __END__ Should not be evaluated Neither should This PK!=/gems/2.2.0/gems/rack-1.6.4/test/spec_builder.rbnu[require 'rack/builder' require 'rack/lint' require 'rack/mock' require 'rack/showexceptions' require 'rack/urlmap' class NothingMiddleware def initialize(app) @app = app end def call(env) @@env = env response = @app.call(env) response end def self.env @@env end end describe Rack::Builder do def builder(&block) Rack::Lint.new Rack::Builder.new(&block) end def builder_to_app(&block) Rack::Lint.new Rack::Builder.new(&block).to_app end it "supports mapping" do app = builder_to_app do map '/' do |outer_env| run lambda { |inner_env| [200, {"Content-Type" => "text/plain"}, ['root']] } end map '/sub' do run lambda { |inner_env| [200, {"Content-Type" => "text/plain"}, ['sub']] } end end Rack::MockRequest.new(app).get("/").body.to_s.should.equal 'root' Rack::MockRequest.new(app).get("/sub").body.to_s.should.equal 'sub' end it "doesn't dupe env even when mapping" do app = builder_to_app do use NothingMiddleware map '/' do |outer_env| run lambda { |inner_env| inner_env['new_key'] = 'new_value' [200, {"Content-Type" => "text/plain"}, ['root']] } end end Rack::MockRequest.new(app).get("/").body.to_s.should.equal 'root' NothingMiddleware.env['new_key'].should.equal 'new_value' end it "chains apps by default" do app = builder_to_app do use Rack::ShowExceptions run lambda { |env| raise "bzzzt" } end Rack::MockRequest.new(app).get("/").should.be.server_error Rack::MockRequest.new(app).get("/").should.be.server_error Rack::MockRequest.new(app).get("/").should.be.server_error end it "has implicit #to_app" do app = builder do use Rack::ShowExceptions run lambda { |env| raise "bzzzt" } end Rack::MockRequest.new(app).get("/").should.be.server_error Rack::MockRequest.new(app).get("/").should.be.server_error Rack::MockRequest.new(app).get("/").should.be.server_error end it "supports blocks on use" do app = builder do use Rack::ShowExceptions use Rack::Auth::Basic do |username, password| 'secret' == password end run lambda { |env| [200, {"Content-Type" => "text/plain"}, ['Hi Boss']] } end response = Rack::MockRequest.new(app).get("/") response.should.be.client_error response.status.should.equal 401 # with auth... response = Rack::MockRequest.new(app).get("/", 'HTTP_AUTHORIZATION' => 'Basic ' + ["joe:secret"].pack("m*")) response.status.should.equal 200 response.body.to_s.should.equal 'Hi Boss' end it "has explicit #to_app" do app = builder do use Rack::ShowExceptions run lambda { |env| raise "bzzzt" } end Rack::MockRequest.new(app).get("/").should.be.server_error Rack::MockRequest.new(app).get("/").should.be.server_error Rack::MockRequest.new(app).get("/").should.be.server_error end it "can mix map and run for endpoints" do app = builder do map '/sub' do run lambda { |inner_env| [200, {"Content-Type" => "text/plain"}, ['sub']] } end run lambda { |inner_env| [200, {"Content-Type" => "text/plain"}, ['root']] } end Rack::MockRequest.new(app).get("/").body.to_s.should.equal 'root' Rack::MockRequest.new(app).get("/sub").body.to_s.should.equal 'sub' end it "accepts middleware-only map blocks" do app = builder do map('/foo') { use Rack::ShowExceptions } run lambda { |env| raise "bzzzt" } end proc { Rack::MockRequest.new(app).get("/") }.should.raise(RuntimeError) Rack::MockRequest.new(app).get("/foo").should.be.server_error end it "yields the generated app to a block for warmup" do warmed_up_app = nil app = Rack::Builder.new do warmup { |a| warmed_up_app = a } run lambda { |env| [200, {}, []] } end.to_app warmed_up_app.should.equal app end should "initialize apps once" do app = builder do class AppClass def initialize @called = 0 end def call(env) raise "bzzzt" if @called > 0 @called += 1 [200, {'Content-Type' => 'text/plain'}, ['OK']] end end use Rack::ShowExceptions run AppClass.new end Rack::MockRequest.new(app).get("/").status.should.equal 200 Rack::MockRequest.new(app).get("/").should.be.server_error end it "allows use after run" do app = builder do run lambda { |env| raise "bzzzt" } use Rack::ShowExceptions end Rack::MockRequest.new(app).get("/").should.be.server_error Rack::MockRequest.new(app).get("/").should.be.server_error Rack::MockRequest.new(app).get("/").should.be.server_error end it 'complains about a missing run' do proc do Rack::Lint.new Rack::Builder.app { use Rack::ShowExceptions } end.should.raise(RuntimeError) end describe "parse_file" do def config_file(name) File.join(File.dirname(__FILE__), 'builder', name) end it "parses commented options" do app, options = Rack::Builder.parse_file config_file('options.ru') options[:debug].should.be.true Rack::MockRequest.new(app).get("/").body.to_s.should.equal 'OK' end it "removes __END__ before evaluating app" do app, _ = Rack::Builder.parse_file config_file('end.ru') Rack::MockRequest.new(app).get("/").body.to_s.should.equal 'OK' end it "supports multi-line comments" do lambda { Rack::Builder.parse_file config_file('comment.ru') }.should.not.raise(SyntaxError) end it "requires anything not ending in .ru" do $: << File.dirname(__FILE__) app, * = Rack::Builder.parse_file 'builder/anything' Rack::MockRequest.new(app).get("/").body.to_s.should.equal 'OK' $:.pop end it "sets __LINE__ correctly" do app, _ = Rack::Builder.parse_file config_file('line.ru') Rack::MockRequest.new(app).get("/").body.to_s.should.equal '1' end end describe 'new_from_string' do it "builds a rack app from string" do app, = Rack::Builder.new_from_string "run lambda{|env| [200, {'Content-Type' => 'text/plane'}, ['OK']] }" Rack::MockRequest.new(app).get("/").body.to_s.should.equal 'OK' end end end PK!%ii.gems/2.2.0/gems/rack-1.6.4/test/spec_static.rbnu[require 'rack/static' require 'rack/lint' require 'rack/mock' class DummyApp def call(env) [200, {"Content-Type" => "text/plain"}, ["Hello World"]] end end describe Rack::Static do def static(app, *args) Rack::Lint.new Rack::Static.new(app, *args) end root = File.expand_path(File.dirname(__FILE__)) OPTIONS = {:urls => ["/cgi"], :root => root} STATIC_OPTIONS = {:urls => [""], :root => "#{root}/static", :index => 'index.html'} HASH_OPTIONS = {:urls => {"/cgi/sekret" => 'cgi/test'}, :root => root} @request = Rack::MockRequest.new(static(DummyApp.new, OPTIONS)) @static_request = Rack::MockRequest.new(static(DummyApp.new, STATIC_OPTIONS)) @hash_request = Rack::MockRequest.new(static(DummyApp.new, HASH_OPTIONS)) it "serves files" do res = @request.get("/cgi/test") res.should.be.ok res.body.should =~ /ruby/ end it "404s if url root is known but it can't find the file" do res = @request.get("/cgi/foo") res.should.be.not_found end it "calls down the chain if url root is not known" do res = @request.get("/something/else") res.should.be.ok res.body.should == "Hello World" end it "calls index file when requesting root in the given folder" do res = @static_request.get("/") res.should.be.ok res.body.should =~ /index!/ res = @static_request.get("/other/") res.should.be.not_found res = @static_request.get("/another/") res.should.be.ok res.body.should =~ /another index!/ end it "doesn't call index file if :index option was omitted" do res = @request.get("/") res.body.should == "Hello World" end it "serves hidden files" do res = @hash_request.get("/cgi/sekret") res.should.be.ok res.body.should =~ /ruby/ end it "calls down the chain if the URI is not specified" do res = @hash_request.get("/something/else") res.should.be.ok res.body.should == "Hello World" end it "supports serving fixed cache-control (legacy option)" do opts = OPTIONS.merge(:cache_control => 'public') request = Rack::MockRequest.new(static(DummyApp.new, opts)) res = request.get("/cgi/test") res.should.be.ok res.headers['Cache-Control'].should == 'public' end HEADER_OPTIONS = {:urls => ["/cgi"], :root => root, :header_rules => [ [:all, {'Cache-Control' => 'public, max-age=100'}], [:fonts, {'Cache-Control' => 'public, max-age=200'}], [%w(png jpg), {'Cache-Control' => 'public, max-age=300'}], ['/cgi/assets/folder/', {'Cache-Control' => 'public, max-age=400'}], ['cgi/assets/javascripts', {'Cache-Control' => 'public, max-age=500'}], [/\.(css|erb)\z/, {'Cache-Control' => 'public, max-age=600'}] ]} @header_request = Rack::MockRequest.new(static(DummyApp.new, HEADER_OPTIONS)) it "supports header rule :all" do # Headers for all files via :all shortcut res = @header_request.get('/cgi/assets/index.html') res.should.be.ok res.headers['Cache-Control'].should == 'public, max-age=100' end it "supports header rule :fonts" do # Headers for web fonts via :fonts shortcut res = @header_request.get('/cgi/assets/fonts/font.eot') res.should.be.ok res.headers['Cache-Control'].should == 'public, max-age=200' end it "supports file extension header rules provided as an Array" do # Headers for file extensions via array res = @header_request.get('/cgi/assets/images/image.png') res.should.be.ok res.headers['Cache-Control'].should == 'public, max-age=300' end it "supports folder rules provided as a String" do # Headers for files in folder via string res = @header_request.get('/cgi/assets/folder/test.js') res.should.be.ok res.headers['Cache-Control'].should == 'public, max-age=400' end it "supports folder header rules provided as a String not starting with a slash" do res = @header_request.get('/cgi/assets/javascripts/app.js') res.should.be.ok res.headers['Cache-Control'].should == 'public, max-age=500' end it "supports flexible header rules provided as Regexp" do # Flexible Headers via Regexp res = @header_request.get('/cgi/assets/stylesheets/app.css') res.should.be.ok res.headers['Cache-Control'].should == 'public, max-age=600' end it "prioritizes header rules over fixed cache-control setting (legacy option)" do opts = OPTIONS.merge( :cache_control => 'public, max-age=24', :header_rules => [ [:all, {'Cache-Control' => 'public, max-age=42'}] ]) request = Rack::MockRequest.new(static(DummyApp.new, opts)) res = request.get("/cgi/test") res.should.be.ok res.headers['Cache-Control'].should == 'public, max-age=42' end end PK!FNN4gems/2.2.0/gems/rack-1.6.4/test/cgi/sample_rackup.runuȯ# -*- ruby -*- require '../testrequest' run Rack::Lint.new(TestRequest.new) PK!<4``+gems/2.2.0/gems/rack-1.6.4/test/cgi/test.runuȯ#!../../bin/rackup # -*- ruby -*- require '../testrequest' run Rack::Lint.new(TestRequest.new) PK!&k<gems/2.2.0/gems/rack-1.6.4/test/cgi/test+directory/test+filenu[this file has plusses! PK!x(gems/2.2.0/gems/rack-1.6.4/test/cgi/testnuȯ#!/usr/bin/env ruby # -*- ruby -*- $: << File.join(File.dirname(__FILE__), "..", "..", "lib") require 'rack' require '../testrequest' Rack::Handler::CGI.run(Rack::Lint.new(TestRequest.new)) PK!l~113gems/2.2.0/gems/rack-1.6.4/test/cgi/lighttpd.errorsnu[2015-06-16 14:11:43: (log.c.164) server started PK!-gems/2.2.0/gems/rack-1.6.4/test/cgi/test.fcginuȯ#!/usr/bin/env ruby # -*- ruby -*- $:.unshift '../../lib' require 'rack' require '../testrequest' Rack::Handler::FastCGI.run(Rack::Lint.new(TestRequest.new)) PK!?z]]2gems/2.2.0/gems/rack-1.6.4/test/cgi/rackup_stub.rbnuȯ#!/usr/bin/env ruby # -*- ruby -*- $:.unshift '../../lib' require 'rack' Rack::Server.start PK!XHi1gems/2.2.0/gems/rack-1.6.4/test/cgi/lighttpd.confnuȯserver.modules = ("mod_fastcgi", "mod_cgi") server.document-root = "." server.errorlog = var.CWD + "/lighttpd.errors" server.port = 9203 server.bind = "127.0.0.1" server.event-handler = "select" cgi.assign = ("/test" => "", # ".ru" => "" ) fastcgi.server = ( "test.fcgi" => ("localhost" => ("min-procs" => 1, "socket" => "/tmp/rack-test-fcgi", "bin-path" => "test.fcgi")), "test.ru" => ("localhost" => ("min-procs" => 1, "socket" => "/tmp/rack-test-ru-fcgi", "bin-path" => CWD + "/rackup_stub.rb test.ru")), "sample_rackup.ru" => ("localhost" => ("min-procs" => 1, "socket" => "/tmp/rack-test-rackup-fcgi", "bin-path" => CWD + "/rackup_stub.rb sample_rackup.ru")), ) PK!o^9gems/2.2.0/gems/rack-1.6.4/test/cgi/assets/fonts/font.eotnu[### TestFile ### PK!o^>gems/2.2.0/gems/rack-1.6.4/test/cgi/assets/stylesheets/app.cssnu[### TestFile ### PK!o^5gems/2.2.0/gems/rack-1.6.4/test/cgi/assets/index.htmlnu[### TestFile ### PK!o^9gems/2.2.0/gems/rack-1.6.4/test/cgi/assets/folder/test.jsnu[### TestFile ### PK!o^;gems/2.2.0/gems/rack-1.6.4/test/cgi/assets/images/image.pngnu[### TestFile ### PK!o^=gems/2.2.0/gems/rack-1.6.4/test/cgi/assets/javascripts/app.jsnu[### TestFile ### PK!4 4 6gems/2.2.0/gems/rack-1.6.4/test/spec_content_length.rbnu[require 'rack/content_length' require 'rack/lint' require 'rack/mock' describe Rack::ContentLength do def content_length(app) Rack::Lint.new Rack::ContentLength.new(app) end def request Rack::MockRequest.env_for end should "set Content-Length on Array bodies if none is set" do app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] } response = content_length(app).call(request) response[1]['Content-Length'].should.equal '13' end should "not set Content-Length on variable length bodies" do body = lambda { "Hello World!" } def body.each ; yield call ; end app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, body] } response = content_length(app).call(request) response[1]['Content-Length'].should.be.nil end should "not change Content-Length if it is already set" do app = lambda { |env| [200, {'Content-Type' => 'text/plain', 'Content-Length' => '1'}, "Hello, World!"] } response = content_length(app).call(request) response[1]['Content-Length'].should.equal '1' end should "not set Content-Length on 304 responses" do app = lambda { |env| [304, {}, []] } response = content_length(app).call(request) response[1]['Content-Length'].should.equal nil end should "not set Content-Length when Transfer-Encoding is chunked" do app = lambda { |env| [200, {'Content-Type' => 'text/plain', 'Transfer-Encoding' => 'chunked'}, []] } response = content_length(app).call(request) response[1]['Content-Length'].should.equal nil end # Using "Connection: close" for this is fairly contended. It might be useful # to have some other way to signal this. # # should "not force a Content-Length when Connection:close" do # app = lambda { |env| [200, {'Connection' => 'close'}, []] } # response = content_length(app).call({}) # response[1]['Content-Length'].should.equal nil # end should "close bodies that need to be closed" do body = Struct.new(:body) do attr_reader :closed def each; body.join; end def close; @closed = true; end def to_ary; end end.new(%w[one two three]) app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, body] } response = content_length(app).call(request) body.closed.should.equal nil response[2].close body.closed.should.equal true end should "support single-execute bodies" do body = Struct.new(:body) do def each yield body.shift until body.empty? end def to_ary; end end.new(%w[one two three]) app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, body] } response = content_length(app).call(request) expected = %w[one two three] response[1]['Content-Length'].should.equal expected.join.size.to_s response[2].to_enum.to_a.should.equal expected end end PK!  8gems/2.2.0/gems/rack-1.6.4/test/spec_rewindable_input.rbnu[require 'stringio' require 'rack/rewindable_input' shared "a rewindable IO object" do before do @rio = Rack::RewindableInput.new(@io) end should "be able to handle to read()" do @rio.read.should.equal "hello world" end should "be able to handle to read(nil)" do @rio.read(nil).should.equal "hello world" end should "be able to handle to read(length)" do @rio.read(1).should.equal "h" end should "be able to handle to read(length, buffer)" do buffer = "" result = @rio.read(1, buffer) result.should.equal "h" result.object_id.should.equal buffer.object_id end should "be able to handle to read(nil, buffer)" do buffer = "" result = @rio.read(nil, buffer) result.should.equal "hello world" result.object_id.should.equal buffer.object_id end should "rewind to the beginning when #rewind is called" do @rio.read(1) @rio.rewind @rio.read.should.equal "hello world" end should "be able to handle gets" do @rio.gets.should == "hello world" end should "be able to handle each" do array = [] @rio.each do |data| array << data end array.should.equal(["hello world"]) end should "not buffer into a Tempfile if no data has been read yet" do @rio.instance_variable_get(:@rewindable_io).should.be.nil end should "buffer into a Tempfile when data has been consumed for the first time" do @rio.read(1) tempfile = @rio.instance_variable_get(:@rewindable_io) tempfile.should.not.be.nil @rio.read(1) tempfile2 = @rio.instance_variable_get(:@rewindable_io) tempfile2.path.should == tempfile.path end should "close the underlying tempfile upon calling #close" do @rio.read(1) tempfile = @rio.instance_variable_get(:@rewindable_io) @rio.close tempfile.should.be.closed end should "be possible to call #close when no data has been buffered yet" do lambda{ @rio.close }.should.not.raise end should "be possible to call #close multiple times" do lambda{ @rio.close @rio.close }.should.not.raise end @rio.close @rio = nil end describe Rack::RewindableInput do describe "given an IO object that is already rewindable" do before do @io = StringIO.new("hello world") end behaves_like "a rewindable IO object" end describe "given an IO object that is not rewindable" do before do @io = StringIO.new("hello world") @io.instance_eval do undef :rewind end end behaves_like "a rewindable IO object" end describe "given an IO object whose rewind method raises Errno::ESPIPE" do before do @io = StringIO.new("hello world") def @io.rewind raise Errno::ESPIPE, "You can't rewind this!" end end behaves_like "a rewindable IO object" end end PK!nn.gems/2.2.0/gems/rack-1.6.4/test/spec_logger.rbnu[require 'stringio' require 'rack/lint' require 'rack/logger' require 'rack/mock' describe Rack::Logger do app = lambda { |env| log = env['rack.logger'] log.debug("Created logger") log.info("Program started") log.warn("Nothing to do!") [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] } should "conform to Rack::Lint" do errors = StringIO.new a = Rack::Lint.new(Rack::Logger.new(app)) Rack::MockRequest.new(a).get('/', 'rack.errors' => errors) errors.string.should.match(/INFO -- : Program started/) errors.string.should.match(/WARN -- : Nothing to do/) end end PK!$hi  6gems/2.2.0/gems/rack-1.6.4/test/spec_showexceptions.rbnu[require 'rack/showexceptions' require 'rack/lint' require 'rack/mock' describe Rack::ShowExceptions do def show_exceptions(app) Rack::Lint.new Rack::ShowExceptions.new(app) end it "catches exceptions" do res = nil req = Rack::MockRequest.new( show_exceptions( lambda{|env| raise RuntimeError } )) lambda{ res = req.get("/", "HTTP_ACCEPT" => "text/html") }.should.not.raise res.should.be.a.server_error res.status.should.equal 500 res.should =~ /RuntimeError/ res.should =~ /ShowExceptions/ end it "responds with HTML only to requests accepting HTML" do res = nil req = Rack::MockRequest.new( show_exceptions( lambda{|env| raise RuntimeError, "It was never supposed to work" } )) [ # Serve text/html when the client accepts text/html ["text/html", ["/", {"HTTP_ACCEPT" => "text/html"}]], ["text/html", ["/", {"HTTP_ACCEPT" => "*/*"}]], # Serve text/plain when the client does not accept text/html ["text/plain", ["/"]], ["text/plain", ["/", {"HTTP_ACCEPT" => "application/json"}]] ].each do |exmime, rargs| lambda{ res = req.get(*rargs) }.should.not.raise res.should.be.a.server_error res.status.should.equal 500 res.content_type.should.equal exmime res.body.should.include "RuntimeError" res.body.should.include "It was never supposed to work" if exmime == "text/html" res.body.should.include '' else res.body.should.not.include '' end end end it "handles exceptions without a backtrace" do res = nil req = Rack::MockRequest.new( show_exceptions( lambda{|env| raise RuntimeError, "", [] } ) ) lambda{ res = req.get("/", "HTTP_ACCEPT" => "text/html") }.should.not.raise res.should.be.a.server_error res.status.should.equal 500 res.should =~ /RuntimeError/ res.should =~ /ShowExceptions/ res.should =~ /unknown location/ end end PK!e/gems/2.2.0/gems/rack-1.6.4/test/spec_webrick.rbnu[require 'rack/mock' require File.expand_path('../testrequest', __FILE__) Thread.abort_on_exception = true describe Rack::Handler::WEBrick do extend TestRequest::Helpers @server = WEBrick::HTTPServer.new(:Host => @host='127.0.0.1', :Port => @port=9202, :Logger => WEBrick::Log.new(nil, WEBrick::BasicLog::WARN), :AccessLog => []) @server.mount "/test", Rack::Handler::WEBrick, Rack::Lint.new(TestRequest.new) Thread.new { @server.start } trap(:INT) { @server.shutdown } should "respond" do lambda { GET("/test") }.should.not.raise end should "be a WEBrick" do GET("/test") status.should.equal 200 response["SERVER_SOFTWARE"].should =~ /WEBrick/ response["HTTP_VERSION"].should.equal "HTTP/1.1" response["SERVER_PROTOCOL"].should.equal "HTTP/1.1" response["SERVER_PORT"].should.equal "9202" response["SERVER_NAME"].should.equal "127.0.0.1" end should "have rack headers" do GET("/test") response["rack.version"].should.equal [1,3] response["rack.multithread"].should.be.true response["rack.multiprocess"].should.be.false response["rack.run_once"].should.be.false end should "have CGI headers on GET" do GET("/test") response["REQUEST_METHOD"].should.equal "GET" response["SCRIPT_NAME"].should.equal "/test" response["REQUEST_PATH"].should.equal "/test" response["PATH_INFO"].should.be.equal "" response["QUERY_STRING"].should.equal "" response["test.postdata"].should.equal "" GET("/test/foo?quux=1") response["REQUEST_METHOD"].should.equal "GET" response["SCRIPT_NAME"].should.equal "/test" response["REQUEST_PATH"].should.equal "/test/foo" response["PATH_INFO"].should.equal "/foo" response["QUERY_STRING"].should.equal "quux=1" GET("/test/foo%25encoding?quux=1") response["REQUEST_METHOD"].should.equal "GET" response["SCRIPT_NAME"].should.equal "/test" response["REQUEST_PATH"].should.equal "/test/foo%25encoding" response["PATH_INFO"].should.equal "/foo%25encoding" response["QUERY_STRING"].should.equal "quux=1" end should "have CGI headers on POST" do POST("/test", {"rack-form-data" => "23"}, {'X-test-header' => '42'}) status.should.equal 200 response["REQUEST_METHOD"].should.equal "POST" response["SCRIPT_NAME"].should.equal "/test" response["REQUEST_PATH"].should.equal "/test" response["PATH_INFO"].should.equal "" response["QUERY_STRING"].should.equal "" response["HTTP_X_TEST_HEADER"].should.equal "42" response["test.postdata"].should.equal "rack-form-data=23" end should "support HTTP auth" do GET("/test", {:user => "ruth", :passwd => "secret"}) response["HTTP_AUTHORIZATION"].should.equal "Basic cnV0aDpzZWNyZXQ=" end should "set status" do GET("/test?secret") status.should.equal 403 response["rack.url_scheme"].should.equal "http" end should "correctly set cookies" do @server.mount "/cookie-test", Rack::Handler::WEBrick, Rack::Lint.new(lambda { |req| res = Rack::Response.new res.set_cookie "one", "1" res.set_cookie "two", "2" res.finish }) Net::HTTP.start(@host, @port) { |http| res = http.get("/cookie-test") res.code.to_i.should.equal 200 res.get_fields("set-cookie").should.equal ["one=1", "two=2"] } end should "provide a .run" do block_ran = false catch(:done) { Rack::Handler::WEBrick.run(lambda {}, { :Host => '127.0.0.1', :Port => 9210, :Logger => WEBrick::Log.new(nil, WEBrick::BasicLog::WARN), :AccessLog => []}) { |server| block_ran = true server.should.be.kind_of WEBrick::HTTPServer @s = server throw :done } } block_ran.should.be.true @s.shutdown end should "return repeated headers" do @server.mount "/headers", Rack::Handler::WEBrick, Rack::Lint.new(lambda { |req| [ 401, { "Content-Type" => "text/plain", "WWW-Authenticate" => "Bar realm=X\nBaz realm=Y" }, [""] ] }) Net::HTTP.start(@host, @port) { |http| res = http.get("/headers") res.code.to_i.should.equal 401 res["www-authenticate"].should.equal "Bar realm=X, Baz realm=Y" } end should "support Rack partial hijack" do io_lambda = lambda{ |io| 5.times do io.write "David\r\n" end io.close } @server.mount "/partial", Rack::Handler::WEBrick, Rack::Lint.new(lambda{ |req| [ 200, {"rack.hijack" => io_lambda}, [""] ] }) Net::HTTP.start(@host, @port){ |http| res = http.get("/partial") res.body.should.equal "David\r\nDavid\r\nDavid\r\nDavid\r\nDavid\r\n" } end should "produce correct HTTP semantics with and without app chunking" do @server.mount "/chunked", Rack::Handler::WEBrick, Rack::Lint.new(lambda{ |req| [ 200, {"Transfer-Encoding" => "chunked"}, ["7\r\nchunked\r\n0\r\n\r\n"] ] }) Net::HTTP.start(@host, @port){ |http| res = http.get("/chunked") res["Transfer-Encoding"].should.equal "chunked" res["Content-Length"].should.equal nil res.body.should.equal "chunked" } end @server.shutdown end PK!>W2gems/2.2.0/gems/rack-1.6.4/test/spec_body_proxy.rbnu[require 'rack/body_proxy' require 'stringio' require 'ostruct' describe Rack::BodyProxy do should 'call each on the wrapped body' do called = false proxy = Rack::BodyProxy.new(['foo']) { } proxy.each do |str| called = true str.should.equal 'foo' end called.should.equal true end should 'call close on the wrapped body' do body = StringIO.new proxy = Rack::BodyProxy.new(body) { } proxy.close body.should.be.closed end should 'only call close on the wrapped body if it responds to close' do body = [] proxy = Rack::BodyProxy.new(body) { } proc { proxy.close }.should.not.raise end should 'call the passed block on close' do called = false proxy = Rack::BodyProxy.new([]) { called = true } called.should.equal false proxy.close called.should.equal true end should 'call the passed block on close even if there is an exception' do object = Object.new def object.close() raise "No!" end called = false begin proxy = Rack::BodyProxy.new(object) { called = true } called.should.equal false proxy.close rescue RuntimeError => e end raise "Expected exception to have been raised" unless e called.should.equal true end should 'allow multiple arguments in respond_to?' do body = [] proxy = Rack::BodyProxy.new(body) { } proc { proxy.respond_to?(:foo, false) }.should.not.raise end should 'not respond to :to_ary' do body = OpenStruct.new(:to_ary => true) body.respond_to?(:to_ary).should.equal true proxy = Rack::BodyProxy.new(body) { } proxy.respond_to?(:to_ary).should.equal false proxy.respond_to?("to_ary").should.equal false end should 'not close more than one time' do count = 0 proxy = Rack::BodyProxy.new([]) { count += 1; raise "Block invoked more than 1 time!" if count > 1 } 2.times { proxy.close } count.should.equal 1 end should 'be closed when the callback is triggered' do closed = false proxy = Rack::BodyProxy.new([]) { closed = proxy.closed? } proxy.close closed.should.equal true end should 'provide an #each method' do Rack::BodyProxy.method_defined?(:each).should.equal true end end PK!Qj;˳ +gems/2.2.0/gems/rack-1.6.4/test/spec_cgi.rbnu[begin require File.expand_path('../testrequest', __FILE__) require 'rack/handler/cgi' describe Rack::Handler::CGI do extend TestRequest::Helpers @host = '127.0.0.1' @port = 9203 if `which lighttpd` && !$?.success? raise "lighttpd not found" end # Keep this first. $pid = fork { ENV['RACK_ENV'] = 'deployment' ENV['RUBYLIB'] = [ File.expand_path('../../lib', __FILE__), ENV['RUBYLIB'], ].compact.join(':') Dir.chdir(File.expand_path("../cgi", __FILE__)) do exec "lighttpd -D -f lighttpd.conf" end } should "respond" do sleep 1 GET("/test") response.should.not.be.nil end should "be a lighttpd" do GET("/test") status.should.equal 200 response["SERVER_SOFTWARE"].should =~ /lighttpd/ response["HTTP_VERSION"].should.equal "HTTP/1.1" response["SERVER_PROTOCOL"].should.equal "HTTP/1.1" response["SERVER_PORT"].should.equal @port.to_s response["SERVER_NAME"].should.equal @host end should "have rack headers" do GET("/test") response["rack.version"].should.equal([1,3]) response["rack.multithread"].should.be.false response["rack.multiprocess"].should.be.true response["rack.run_once"].should.be.true end should "have CGI headers on GET" do GET("/test") response["REQUEST_METHOD"].should.equal "GET" response["SCRIPT_NAME"].should.equal "/test" response["REQUEST_PATH"].should.equal "/" response["PATH_INFO"].should.be.nil response["QUERY_STRING"].should.equal "" response["test.postdata"].should.equal "" GET("/test/foo?quux=1") response["REQUEST_METHOD"].should.equal "GET" response["SCRIPT_NAME"].should.equal "/test" response["REQUEST_PATH"].should.equal "/" response["PATH_INFO"].should.equal "/foo" response["QUERY_STRING"].should.equal "quux=1" end should "have CGI headers on POST" do POST("/test", {"rack-form-data" => "23"}, {'X-test-header' => '42'}) status.should.equal 200 response["REQUEST_METHOD"].should.equal "POST" response["SCRIPT_NAME"].should.equal "/test" response["REQUEST_PATH"].should.equal "/" response["QUERY_STRING"].should.equal "" response["HTTP_X_TEST_HEADER"].should.equal "42" response["test.postdata"].should.equal "rack-form-data=23" end should "support HTTP auth" do GET("/test", {:user => "ruth", :passwd => "secret"}) response["HTTP_AUTHORIZATION"].should.equal "Basic cnV0aDpzZWNyZXQ=" end should "set status" do GET("/test?secret") status.should.equal 403 response["rack.url_scheme"].should.equal "http" end # Keep this last. should "shutdown" do Process.kill 15, $pid Process.wait($pid).should == $pid end end rescue RuntimeError $stderr.puts "Skipping Rack::Handler::CGI tests (lighttpd is required). Install lighttpd and try again." rescue NotImplementedError $stderr.puts "Your Ruby implemenation or platform does not support fork. Skipping Rack::Handler::CGI tests." end PK!˫^1gems/2.2.0/gems/rack-1.6.4/test/static/index.htmlnu[index! PK!\W9gems/2.2.0/gems/rack-1.6.4/test/static/another/index.htmlnu[another index! PK![all,gems/2.2.0/gems/rack-1.6.4/test/spec_head.rbnu[require 'rack/head' require 'rack/lint' require 'rack/mock' describe Rack::Head do def test_response(headers = {}) body = StringIO.new "foo" app = lambda do |env| [200, {"Content-type" => "test/plain", "Content-length" => "3"}, body] end request = Rack::MockRequest.env_for("/", headers) response = Rack::Lint.new(Rack::Head.new(app)).call(request) return response, body end should "pass GET, POST, PUT, DELETE, OPTIONS, TRACE requests" do %w[GET POST PUT DELETE OPTIONS TRACE].each do |type| resp, _ = test_response("REQUEST_METHOD" => type) resp[0].should.equal(200) resp[1].should.equal({"Content-type" => "test/plain", "Content-length" => "3"}) resp[2].to_enum.to_a.should.equal(["foo"]) end end should "remove body from HEAD requests" do resp, _ = test_response("REQUEST_METHOD" => "HEAD") resp[0].should.equal(200) resp[1].should.equal({"Content-type" => "test/plain", "Content-length" => "3"}) resp[2].to_enum.to_a.should.equal([]) end should "close the body when it is removed" do resp, body = test_response("REQUEST_METHOD" => "HEAD") resp[0].should.equal(200) resp[1].should.equal({"Content-type" => "test/plain", "Content-length" => "3"}) resp[2].to_enum.to_a.should.equal([]) body.should.not.be.closed resp[2].close body.should.be.closed end end PK!;u:{{Fgems/2.2.0/gems/rack-1.6.4/test/multipart/content_type_and_no_filenamenu[--AaB03x Content-Disposition: form-data; name="text" Content-Type: text/plain; charset=US-ASCII contents --AaB03x-- PK! @z++0gems/2.2.0/gems/rack-1.6.4/test/multipart/webkitnu[------WebKitFormBoundaryWLHCs9qmcJJoyjKR Content-Disposition: form-data; name="_method" put ------WebKitFormBoundaryWLHCs9qmcJJoyjKR Content-Disposition: form-data; name="profile[blog]" ------WebKitFormBoundaryWLHCs9qmcJJoyjKR Content-Disposition: form-data; name="profile[public_email]" ------WebKitFormBoundaryWLHCs9qmcJJoyjKR Content-Disposition: form-data; name="profile[interests]" ------WebKitFormBoundaryWLHCs9qmcJJoyjKR Content-Disposition: form-data; name="profile[bio]" hello "quote" ------WebKitFormBoundaryWLHCs9qmcJJoyjKR Content-Disposition: form-data; name="media"; filename="" Content-Type: application/octet-stream ------WebKitFormBoundaryWLHCs9qmcJJoyjKR Content-Disposition: form-data; name="commit" Save ------WebKitFormBoundaryWLHCs9qmcJJoyjKR-- PK!yhPU33.gems/2.2.0/gems/rack-1.6.4/test/multipart/textnu[--AaB03x Content-Disposition: form-data; name="submit-name" Larry --AaB03x Content-Disposition: form-data; name="submit-name-with-content" Content-Type: text/plain Berry --AaB03x Content-Disposition: form-data; name="files"; filename="file1.txt" Content-Type: text/plain contents --AaB03x--PK!B(5gems/2.2.0/gems/rack-1.6.4/test/multipart/mixed_filesnu[--AaB03x Content-Disposition: form-data; name="foo" bar --AaB03x Content-Disposition: form-data; name="files" Content-Type: multipart/mixed, boundary=BbC04y --BbC04y Content-Disposition: attachment; filename="file.txt" Content-Type: text/plain contents --BbC04y Content-Disposition: attachment; filename="flowers.jpg" Content-Type: image/jpeg Content-Transfer-Encoding: binary contents --BbC04y-- --AaB03x-- PK!'RERE4gems/2.2.0/gems/rack-1.6.4/test/multipart/bad_robotsnu[--1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon Content-Disposition: form-data; name="bbbbbbbbbbbbbbb" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaa --1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon Content-Disposition: form-data; name="ccccccc" ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd --1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon Content-Disposition: form-data; name="file.name" INPUTMSG.gz --1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon Content-Disposition: form-data; name="file.content_type" application/octet-stream --1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon Content-Disposition: form-data; name="file.path" /var/tmp/uploads/4/0001728414 --1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon Content-Disposition: form-data; name="file.md5" aa73198feb4b4c1c3186f5e7466cbbcc --1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon Content-Disposition: form-data; name="file.size" 13212 --1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon Content-Disposition: form-data; name="size" 80892 --1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon Content-Disposition: form-data; name="mail_server_id" <1111111111.22222222.3333333333333.JavaMail.app@ffff-aaaa.dddd> --1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon Content-Disposition: form-data; name="addresses" {"campsy_programmer@pinkedum.com":{"domain":"pinkedum.com","name":"Campsy Programmer","type":["env_sender"],"mailbox":"campsy_programmer"},"tex@rapidcity.com":{"domain":"rapidcity.com","name":"Big Tex","type":["env_recipients","to"],"mailbox":"tex"},"group-digests@linkedin.com":{"domain":"linkedin.com","name":"Group Members","type":["from"],"mailbox":"group-digests"}} --1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon Content-Disposition: form-data; name="received_on" 2009-11-15T14:21:11Z --1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon Content-Disposition: form-data; name="id" dbfd9804d26d11deab24e3037639bf77 --1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon Content-Disposition: form-data; name="ip_address" 127.0.0.1 --1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon-- PK!ՓHgems/2.2.0/gems/rack-1.6.4/test/multipart/filename_with_unescaped_quotesnu[--AaB03x Content-Disposition: form-data; name="files"; filename="escape "quotes" Content-Type: application/octet-stream contents --AaB03x-- PK!SJIgems/2.2.0/gems/rack-1.6.4/test/multipart/filename_and_modification_paramnu[--AaB03x Content-Type: image/jpeg Content-Disposition: attachment; name="files"; filename=genome.jpeg; modification-date="Wed, 12 Feb 1997 16:29:51 -0500"; Content-Description: a complete map of the human genome contents --AaB03x-- PK!񏭕Ngems/2.2.0/gems/rack-1.6.4/test/multipart/filename_with_percent_escaped_quotesnu[--AaB03x Content-Disposition: form-data; name="files"; filename="escape %22quotes" Content-Type: application/octet-stream contents --AaB03x-- PK!Ngems/2.2.0/gems/rack-1.6.4/test/multipart/filename_with_unescaped_percentages3nu[------WebKitFormBoundary2NHc7OhsgU68l3Al Content-Disposition: form-data; name="document[attachment]"; filename="100%" Content-Type: image/jpeg contents ------WebKitFormBoundary2NHc7OhsgU68l3Al-- PK! /gems/2.2.0/gems/rack-1.6.4/test/multipart/emptynu[--AaB03x Content-Disposition: form-data; name="submit-name" Larry --AaB03x Content-Disposition: form-data; name="files"; filename="file1.txt" Content-Type: text/plain --AaB03x-- PK! ]gems/2.2.0/gems/rack-1.6.4/test/multipart/filename_with_escaped_quotes_and_modification_paramnu[--AaB03x Content-Type: image/jpeg Content-Disposition: attachment; name="files"; filename=""human" genome.jpeg"; modification-date="Wed, 12 Feb 1997 16:29:51 -0500"; Content-Description: a complete map of the human genome contents --AaB03x-- PK!0gems/2.2.0/gems/rack-1.6.4/test/multipart/nestednu[--AaB03x Content-Disposition: form-data; name="foo[submit-name]" Larry --AaB03x Content-Disposition: form-data; name="foo[files]"; filename="file1.txt" Content-Type: text/plain contents --AaB03x-- PK!xrNgems/2.2.0/gems/rack-1.6.4/test/multipart/filename_with_unescaped_percentages2nu[------WebKitFormBoundary2NHc7OhsgU68l3Al Content-Disposition: form-data; name="document[attachment]"; filename="100%a" Content-Type: image/jpeg contents ------WebKitFormBoundary2NHc7OhsgU68l3Al-- PK!DnnBgems/2.2.0/gems/rack-1.6.4/test/multipart/three_files_three_fieldsnu[--AaB03x content-disposition: form-data; name="reply" yes --AaB03x content-disposition: form-data; name="to" people --AaB03x content-disposition: form-data; name="from" others --AaB03x content-disposition: form-data; name="fileupload1"; filename="file1.jpg" Content-Type: image/jpeg Content-Transfer-Encoding: base64 /9j/4AAQSkZJRgABAQAAAQABAAD//gA+Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcg --AaB03x content-disposition: form-data; name="fileupload2"; filename="file2.jpg" Content-Type: image/jpeg Content-Transfer-Encoding: base64 /9j/4AAQSkZJRgABAQAAAQABAAD//gA+Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcg --AaB03x content-disposition: form-data; name="fileupload3"; filename="file3.jpg" Content-Type: image/jpeg Content-Transfer-Encoding: base64 /9j/4AAQSkZJRgABAQAAAQABAAD//gA+Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcg --AaB03x-- PK!fMgems/2.2.0/gems/rack-1.6.4/test/multipart/filename_with_unescaped_percentagesnu[------WebKitFormBoundary2NHc7OhsgU68l3Al Content-Disposition: form-data; name="document[attachment]"; filename="100% of a photo.jpeg" Content-Type: image/jpeg contents ------WebKitFormBoundary2NHc7OhsgU68l3Al-- PK!w3gems/2.2.0/gems/rack-1.6.4/test/multipart/file1.txtnu[contentsPK!]zjzj;gems/2.2.0/gems/rack-1.6.4/test/multipart/fail_16384_nofilenu[------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="_method" put ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="authenticity_token" XCUgSyYsZ+iHQunq/yCSKFzjeVmsXV/WcphHQ0J+05I= ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[SESE]" BooBar ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[BBBBBBBBB]" 18 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[CCCCCCCCCCCCCCCCCCC]" 0 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[STARTFOO]" 2009-11-04 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[ENDFOO]" 2009-12-01 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[DDDDDDDD]" 0 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[DDDDDDDD]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[EEEEEEEEEE]" 10000 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[FFFFFFFFF]" boskoizcool ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[GGGGGGGGGGG]" 0 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[GGGGGGGGGGG]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[YYYYYYYYYYYYYYY]" 5.00 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[ZZZZZZZZZZZZZ]" mille ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[XXXXXXXXXXXXXXXXXXXXX]" 0 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][9]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][10]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][11]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][12]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][13]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][14]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][15]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][16]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][17]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][18]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][19]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][20]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][21]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][22]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][23]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][0]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][1]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][2]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][3]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][4]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][5]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][6]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][7]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][8]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][9]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][10]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][11]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][12]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][13]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][14]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][15]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][16]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][17]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][18]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][19]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][20]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][21]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][22]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][23]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][0]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][1]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][2]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][3]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][4]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][5]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][6]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][7]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][8]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][9]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][10]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][11]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][12]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][13]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][14]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][15]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][16]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][17]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][18]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][19]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][20]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][21]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][22]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][23]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][0]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][1]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][2]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][3]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][4]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][5]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][6]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][7]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][8]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][9]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][10]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][11]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][12]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][13]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][14]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][15]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][16]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][17]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][18]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][19]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][20]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][21]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][22]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][23]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][0]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][1]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][2]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][3]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][4]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][5]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][6]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][7]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][8]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][9]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][10]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][11]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][12]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][13]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][14]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][15]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][16]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][17]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][18]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][19]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][20]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][21]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][22]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][23]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][0]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][1]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][2]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][3]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][4]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][5]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][6]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][7]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][8]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][9]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][10]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][11]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][12]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][13]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][14]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][15]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][16]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][17]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][18]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][19]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][20]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][21]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][22]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][23]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][0]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][1]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][2]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][3]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][4]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][5]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][6]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][7]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][8]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][9]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][10]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][11]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][12]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][13]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][14]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][15]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][16]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][17]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][18]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][19]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][20]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][21]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][22]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][23]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][0]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][1]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][2]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][3]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][4]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][5]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][6]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][7]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][8]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[WWWWWWWWWWWWWWWWWWWWWWWWW][678][ZEZE]" PLAPLAPLAINCINCINC ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[WWWWWWWWWWWWWWWWWWWWWWWWW][678][123412341234e]" SITE ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[WWWWWWWWWWWWWWWWWWWWWWWWW][678][12345678901]" 56 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[TARTARTAR_type]" none ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[TARTARTAR_wizard][has_hashashas_has]" 0 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[TARTARTAR_wizard][frefrefre_fre_freee]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[TARTARTAR_wizard][frefrefre_fre_frefre]" forever ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[TARTARTAR_wizard][self_block]" 0 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[TARTARTAR_wizard][GGG_RULES][][COUCOUN]" ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[TARTARTAR_wizard][GGG_RULES][][REGREG]" ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[TARTARTAR_wizard][GGG_RULES][][c1c1]" ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA_TARTARTAR_wizard_rule" ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[TARTARTAR_rule]" ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[selection_selection]" R ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[PLAPLAPLA_MEMMEMMEMM_ATTRATTRER][new][-1][selection_selection]" 1 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[PLAPLAPLA_MEMMEMMEMM_ATTRATTRER][new][-1][ba_unit_id]" 1015 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[PLAPLAPLA_MEMMEMMEMM_ATTRATTRER][new][-2][selection_selection]" 2 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[PLAPLAPLA_MEMMEMMEMM_ATTRATTRER][new][-2][ba_unit_id]" 1017 ------WebKitFormBoundaryWsY0GnpbI5U7ztzo Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[tile_name]" ------WebKitFormBoundaryWsY0GnpbI5U7ztzo-- PK!Hʜ.gems/2.2.0/gems/rack-1.6.4/test/multipart/nonenu[--AaB03x Content-Disposition: form-data; name="submit-name" Larry --AaB03x Content-Disposition: form-data; name="files"; filename="" --AaB03x-- PK!Ҿrr>gems/2.2.0/gems/rack-1.6.4/test/multipart/filename_and_no_namenu[--AaB03x Content-Disposition: form-data; filename="file1.txt" Content-Type: text/plain contents --AaB03x-- PK!3gems/2.2.0/gems/rack-1.6.4/test/multipart/semicolonnu[--AaB03x Content-Disposition: form-data; name="files"; filename="fi;le1.txt" Content-Type: text/plain contents --AaB03x--PK!qgFgems/2.2.0/gems/rack-1.6.4/test/multipart/filename_with_escaped_quotesnu[--AaB03x Content-Disposition: form-data; name="files"; filename="escape \"quotes" Content-Type: application/octet-stream contents --AaB03x-- PK!c+h+h0gems/2.2.0/gems/rack-1.6.4/test/multipart/binarynu[--AaB03x Content-Disposition: form-data; name="submit-name" Larry --AaB03x Content-Disposition: form-data; name="files"; filename="rack-logo.png" Content-Type: image/png PNG  IHDRbKGD pHYsHHFk>fIDATxy|uߓ)fr$mR" iJz @QAA@Et9@T䐴E@( BiZp=6M L&mi&# !陒|G d^>?q@ Dgz A D@@ .@ ] @ @t $ H@% K A D@@ .@ ] @ @t $ H@% KDz NR)H$P @ $ ~p: (..FM~~8iɧBI$k %I q3=xFh[PPplNiz$qry@ 8|*99P(+ a"[T.s$IB3ɗ]. pO H111nlillj&,;~- X,$Hq$ɓ'''_ jz)>1 tQ4d2YN;222( {KK nD!pRZZ:t͋|Qq[T$Q9ȋ D@(z oK#(~FR rSEE0 #6 r/QrFY֡^lbʋ"99&HTDOkK4nh/*xQQ:>`e%Յ1G+м‹IPx*99]Z@zP4L:0XE%KT<]S[pI$>JUrr2%P:1,a' >iK4zE%eZ*eم9W-*XQh!H$HTD[ 1.VPF{2a`4Mi:d&m@ \.7>"IҌ~!_B& H4:EQ@tTiitm0F1 34M+USx B 7T@|DCB ].ac`͋-4M_W/F}" v+,,ThQTzEE%4RAt ;W}E_DߣGr޽{]0HpWowU4|nZh^T ,--΋haF2ܢ=}l}4ɱcp}ՈDDQ)((XY__?#Z0k֬ӦM+W*Ajz5^B*--MTihQ!UWުT*^uzT@-[|/`Pqzꩊ 333/8ތ*/**++QVVQh2\죡?:=- ._ߝqF.[p $ *H&$,]O'}]T233_۲e;"(E ]˗ \OKtF.KA$I{ bh!lƍ'~AjRjG]!.wbe%narZqX)"e V[j,:R CQR___V]]u7D/'$x]dddB+EIJb(7999.hw{ReJV[j+NgVfl6G 3РcYV)ZD@rn\'"Jr%KV[,~`H`f8˲I^==4>}M os5/,ZKXZ慥5!,((H0xш Wk4.:::SF  $ajyx…l$0"0aaxaIdY6j*Y zOT-!MrGq^rY*煥BVR%, K4F㽼hcYV ] 84K,˦A #gDD@Kvvvq:.\, a $ $R5i-`BCD4W{(J/x KP,2$,hIFQϋeYt]48/h4??o֦{@t4 '/, 鄅 z*&Ih2M&S"m60-,e iZFt"L &JKVrC!*((#ruMiiizT*%HgD/&TYX]yZ$Y Efq0LR4ᥥ.+j玁{H4 naRi,[!.$Itw@^4T^44,tsMb\RHOO߫K'A@QzB"D"q$II[0\uXJ[xxEO@^qͭkY*jYΓ$y٫>!)((ŋĆhtgnWbqJ:^Nd2C@QO|;||e_@=[rUXXX,Noa1{IVzI^Dne4'1eA=`qdGSRR̟?(%%R&]ek@ }^@NJ4egg[gDž+WÇ>HpD }Re%8-,ڈJ9jeف=p,Ntz*X͍(&E !@WL&.J%K^U $`P= aYVbXTq͜f֬Y{g͚}\\-^u ms0)==*>>++x7X"_hZz.UbqJ*LOOߣt2F -F@ձ+p%;;2s:|ad/,p/anZ^i愄SNݣt:L&shk@$Pxoy #=p_*s8&i8|@p f|qL&;©SV$$$xE(@Q6mZ +]'_LxH i_p82XT*Wk@ Ht,$I$j8 K^XKKK:wL \nٵkѣGšZ~  iY ;Be$+Ng_0(//OVSS3⣏>z qܩRG[k@ Hʱ{Wyȑ}@ ɭfa~qV pzp83 #}Z0 n!}$!sau@7poo@ 1aY- $O@‘x!У.,76o|ׇ wp@z@  zXkxYR_VVvV\ܭ-b,%%p%%%#].h:eY)[˲"^T *yQH8 @t>% ^VFlQQXʸhk,6\~V"8jh4fXg \1tdii(5j놨X*xTZp"\Dž@ :HvaXI^ -y{VF oeh4MMM=qZ"\.{BQTRZZ:tDCDE wy?RGT)?dž@ A@x+#dLQ.Hfdd|C_Qɧ(*a1/*#xQEQ+|r5EQ 1,@!ᭌ񼕑[BhqN&tG322N2 /*NVT D%T_ N 箃eYaίч K PeX,.WTG322kȨQT2Q9%*v,6EK]] f7@LF儅V2{eLii['t:FsDќtd2YЭ`%*ٍ^GT_Eq\ݻ޽w]SaQAiD%$., \._ʸZͲvX,>[GbccK222Cee?r'PȲ{C˲bQx+*Ӽ%ɕn%ra!}X Fqĉ'9v>nWM[Um p8D6msMwwDT;JgE G ;x ~bgYI$ JUme0^͛W74}p?/0:+k'* GIYC^\ ^lҤI愄V 7i\^H*~W1 Ì`f`0(4 ]*? Z*^ic(@BDoQKK#G8rH}5Msss-~JV[+Mm +""`- ~ĉo6>PvpHD^N(\X3p4'ڔmykiii?֊eY1@ #@ʲb P\^^^ bEDk#I"oҭ,,^4"F] 4MZAmBBwSNݫtjL#ч {V0jA$I$Yt:㭕 A0L'hOQhz˲Q@t MӣrrrXpS~OA$kS̋8h4L2i|A8_d%:n^/:u깄fo10je@Qz Zi8t:_ƪIb ?bH$P᭕@ueY1 p[+$9?NDvx)>>lRmmqo`OOOO?RAB~ ѧ\X ""bcc9&ڵk_t ;w3 3;ث E^A/ԁ|A$ ү`4/D^^ޭF~>~X1qqqg͚o֬Y5vQ4z5@ :M v-Uv@}.+DV,{+i,6-eYAt ,өS/^gP]c:A&uǽV(aUN0 f7;(} D&ZVe ")j:l6xx'>WbqJ:ċw:"ɜA C@Qz ^QBC?;7\997:gƔ 2J :GA.ֈ\gtnDzweS 2UTM!*V(h ɂHǛd2Y)vMzz*b DY );:Q91~|5vzfXuh$ !HgWY]]}z֭' 87TK!m"6M{ +AMcC ݤ'wtF,KwNV[- (JgX-0#XMZ*z~jn]rrr(T-`4Miz _,ǯ H$-:V;EQ'DD8\acz8WXX3􍛧x۶mEDD۸q:$Zb+{} #n_|qݻAP(YSL{NOz1βhKӴd^2bqF9z$##D"i.?O-Be$+0EQ`"p'L&d2y 0@0e١VUgDAqHXX,8 &pRyl|WȰl?pM)G]XXx$@oxw_ܳg"p_} ///)//M !,XG-^gVF+cD 2NK$Xb+mD 6$m$IaBa gf(0 0a,;jƱ,+⻉7siV4=,**[o5!**$F |*j˟Rilláw`5hqa?)iiigOwgP^^.\x"aA83cƌw,XPy a/ ^VF+#:nei4 +#(w=;;~t:pBe  @>V iZ nai+^c418N暽a$I^䅥#\ry_q$:Hd8΁a.3 2aTEiiN*JJJ|6rHؼlCN]]k3˟_OVXR yHYX>V&??.줕q],C,7t]F{DDD@\\nwTSvvvfq\h2$&I`2z P[X~Ͳlb :iǞ8K_RgxX@nmEďiiio222~+ɯ p\?V-q'M}+O,ǭ`[-W I$I^#༰L&S,iӦ;,cй,ˊ-K,pM!/Ix׳hZ+ ~ߓOח]DmΓhUU)))jܶm[.H8hankFRRRBJsllo5kVP(lqu` `&*??hL-..~0܀\AAuֽ#pr>QmB@8 \._UVVeeZ, 2|c!2 /,,$I$IqF< 'H~&gY֓vܖ;"iz$մp M*Vy׳,[).$ygD/#FX;~xL&cТT*+Vl>~g8$`mXc'MI&5V8p9g)5ꫯu:]M0`\p%Xv3]T5cƌ-X=5L(\XhԞ8qbci:VXF ͝;?Oر#nxGïimY4yT뉳L:eEu):\h$ ,Z-KT18 <#ƕ+W>]tv;xv> Dr>|nRRRSG>?ѯ |[֭[7Onm+VlQ*={],/ YYYSC=vV˔H~ܖp2']Zvq-B’H$Xll, rv@+ۙ quSO+|F,5҅Vh`lxoŕ*0==}ĉAFFbp@ӧ$%%uzݒU8t¯=BE[w()++i\Aeر566vUݻ]n]eˎz^JZ*eJ3< ^vp΂~gJ+,@O@v;VXX8h4jyѸS &$$|7uԯz!NW-ɜP]]-q<\[A &ЕvذaCz}}'{@А E"Qq oL\\\[ol6wЗF>!m0÷$hᄈΝvǎC@[nQJJm[8L;zO@a:΂  //||~gZ|sqf4'>0ow\d2I}L:wx̙?kJEGGsg'k: tV\\0eYOk{m,[gwdڎs ޜFDqqqhw׮]+**v\q:h*@zz^_ґ_i.ux+m`JIIVpLjTL ֭[m3f\MtBKKK[-xq oCyyaы/~1%%nYI3PN8@%v1MpIԩSc-G@ZZ \(*;zV $NƚXu]t [hq|ZVX\RNF;hqv(++~ Ç3 38X$c 78η233+rx%e8[+͛]揤ٳg]|D]x7nE_ b1T*}塇^LP߳e'ϴgϞ1۷oz2Mӣ~28%%LIIdWn HWillʺ]ORRRRWWo>>5xyp1a„uap~O=3M8yh4u._ DF/4tҿ@ ٳK6oiyy+}KXr^^ޱ3gV"WPea+6sq5&& h;; _GǸqʋd2o\qL&^yT*|td^D޽{~VVVٚ5k)JomڴIaÆ{iiiִmyyy:NaۍFcT*=qܙd0 b|=_7ܠsȾ=3Smw0v RRRjw_sa @h4Oemg\oOKߵw_⾙5kYf܃Yc}N@pwqeq8?8EQ;wt\#bG"ΝaaHѰ0<1///+(//͛,[l_ 퐀"@ {U㷬%oWbyJU5t:Lv#vkm@ 'y޽ݻw7ï/=IKK|?Ѕ h~QXX8aA8bݺu)))'C=P\Xa + QSߑUpdƔ=/JIId7]Ku+@tyrOH$~{OIIɿBÞ>s-tc_k׮V]yӂ\XңTSu+\4iV^^T3qsaL> 6,//^O\bb+VX__?·dPYA8dݻw_n]ѲeˊC=PMz"$O~||<3r쟖-[VbŊ^1LOΝ;Up b1bDIIJJj={z0pL3.YfB!oIIIٳ?a֭{ 佌BIO Hsa1 #`Y!"~\~llDBC5 mfGf̘ xWq~׿XƎa<#? z补ٳg'&&n ]{6lxn] 9 CbjƲ$I{^[Cʤ[(Jv͚5f̘Tw'脄3fh! #Rl%K裏f.\ms m}=A6X xOzO}AL 0moKgϞjS^ ºkܾ  $3..;Z1 9ŕ85R*׿6tc&eHeLv"%%e߼y 'Nvɔ .A^LNN 333RTo?,s8$%%9^~[zvlqxjjrVKW?: 4?D :g_~=Pk왙3guEE1o޼g- 5}΅ŋFbhL4V d2YN;jdj2!,Z =9ڪm6a\T2 uv>y։8F*6I$p:pň(%(b9(v\+\[.`$~?blq g%9G.]:ܭ9?Z}JlP]]=`0XpS#GX,_X,>R>x6''֓'O m65ǾpႠ8u|ʕ,Y˗!33sY\\b/Pάl֟ .8^kR;n,Ze˖=xb]555ѵ^ziǺtԞ:R ?c^t{ժU111+w䌘cƌF_KLL\P()}111_̚5kEQkjj3F3l6>cJjڹfYHBrCILL\P(v* 駟j<㭪k|g_z'lR({ Ŷ?޽;e6UQQQC=\EPQ(.3.>>scbby,Kx=wqDz>h)S)/]n|/^B_UU%gL&{oժU 4 [l\P|P(|F][[ItIJe>| EB#˷8'111O?[,?z'OܻwovRR#й:vϙ3gX,7mA>==(Jʟϡ ~zX,= b7nܸF$v?Ͽ{겲64yǗ/_d-[l&!`J9sD)LEر֑#G7nvh-..~/xwї^zogϞ}… >*--H$2lv;,\p֭[:thٳ#HZ=:a֭,;r͚5P*EIV]v W*zj._|QFٗ-[VdX"|7i9gΜ'*)RL&Gv A d$ȑA]4N<)gB*pTo?9r… ۵kPүG f:ulʕ×,Y_|7VhpW*wj פ,_ŋ߹k׮555"f3},Z>glUK.uqx˖-`(`GN먮.Zr8eҥxIT*7GEEK., dff.0`@і-[s,bm59bɓ':W555޲'KsXv˖-}k׮{&113gΈ|ބgΜ@.]z'\ti2q#϶n*|;N&O>-歞z,*BP,^-ku8]v >^,`Kv4)nߩS ޤbB?禰@xKCZPP0h4ꋋSư,c8bJ:^M:N&uG-<>;є0h4h4~M?6swO9@^] w @PJwsRyeĉ}?~|qjJKKQ(G׿*Jp}cǎ}m۶L6Nh/X(`׮]0 [o=77w8aHaŋ/]߿ߒHl)))yeفp+9s ] ҶmۦM0$33H$Bp$IZredogfssssM&Sn?7ŋSSSsv#G<l!I ݑoo|G}ǿ(jAN~f͚uJϟ-[͛oqrRI' q<"))q8y9_hYY$s-اOyRR|nycΝ]@%%%V-K.裏6x=""{9JBQTUUE EE`Vp8T|SFﴬL;gΜnRt͟?ˢ9[l!">>ޤwfI||q͛uĉվV)NWT\\|lokwTA$Iҟ~iq|p;>wm'N:o޼'NX aNgOt:Qedd(H.rWFGjR $I^&I<Z  0CM6=hXC%+`4|mK-WHte Z~jaS?ApgoMq\QZT*U 劊^_XPPX^^ވiӦ|ѻ~III &,...d2E^A~ iii{Z˗/~8p;(ׯ_K<״~}X.<@[{l >x<8~}ݺu=%"!sa\.Zd>ݶ#5Nd2qNWT*U x`ή999ptRTt:YVW t eف%R=Ǎm_J͛7wK@Dz2Qcc~f@PW_/\|,OV,+0 $V\iol8^-+W|Pʻ ###A(^'xb%K6.9hl"H'N\W /۷GFu$ʕ+ E.^8D̳n~{/EQŋzH;vlcdd'[d6;P _}wdYV)Hp[sΝ{tʔ)oqVZ5kb0|AW_ɳeFAum]8. ӧWA|(9t r??fff֋D"lݺu&q3\.࿳TVV&2 #dYvHDDD5kv]Oĉ?+xWرo>T$;zp8ݻ9sNhx8~VR}U4: Ans/9(6 v`ǯpbن4=?O4MyX-Njl6po:K0j8ڹs<))jÇr GOю,**J9sfUWW'8vX4jݿ=TZhQǏnTVV y$ IҚsn+V:mD"cݺu eUYY)*>NjN53I?\-_|s=(++#FCMtiiig0 s655^|ŗiii<^v\~&55@cPRRvnٲM6ܙk&++k?ȑ#[6o|'|bBBžӧ{{n2+++V@gTTTdΜ9j#ӧO~[YYYwTRRB==""܎;ƧOMMXRR"]fj/^".qXJ 8:PxpΜ9_O6;FS- [{2t%:kV$)>kXc-RP4+?j(u IIIxǏOb;nbb 55̫x޼y NSt̙3sV^ErssZ,&L0SnnŒ8a„D"^z ÇOV)q8Qo[ppuEW)))k^jU 4M/ohk!H977be„ E>=b̈́ {`ӧOK _,;N z뭿qw)99yfS͛7SPxiH$2Y)SSO=uرcޱcG֝wP---رc+Ϗ~{ Lcc#;& RRR>ݷo¢_tI1cƌWk ޞ/jKa5kr>z޽v\/^W|ӹf͚|A޽{hѢN5Ryeƍ̜9s?XE~饗^;vlcBBBmV3~S'On}_+SRRvDE7Vmزe˞F )=|֯_ՙ3g.XHtzΜ9Jlĉ9uW:9m7)ّ뢙o8t1 =X 2^iQ}Y-Ojĝj罬V^hzd?21>0mv18nd?y>4iҹ!55uǯUwĉb$s`ĴѵvWPb`j9UyV˲e|p}eҥ-[vAb4/..~a,B3Bρ[O5k־Yf]H$yc" yJ$i|ʼF̞hmW0Z~ b-ZvM|e"r׮] Fqbqq񤆆q,*TbBR:^&2cW6_vݽ6 _c- XpEkqvmT vTQQqRAn*[^4t571-a V_Tb ۮr+R!MCOx aЉ *pd))){ϟ0%%R&]A@<_{/ZD ⭖Quk0 s577þ}dFQA5A%LV鿠2 ~e&NZ"(rjYl˗u'N\(JI|:AA?}R($%=bfXD")?p@h|ܽrDе _T*>q<--H$/q 7Y-t :N9" Hs3 oNWFT  "jpgPYe2YN۫N:2!!ųY@t$ 7[-.~xO~A@ ӃV'' QH@˜V"w]OX,ʠ*CT'@ ` 0LrjZyA@ z$ 72@ }$ H@% K A D@@ .@ ] @ ws\tEXtSoftwarewww.inkscape.org<IENDB` --AaB03x-- PK!E,gems/2.2.0/gems/rack-1.6.4/test/multipart/ienu[--AaB03x Content-Disposition: form-data; name="files"; filename="C:\Documents and Settings\Administrator\Desktop\file1.txt" Content-Type: text/plain contents --AaB03x-- PK!R҃;gems/2.2.0/gems/rack-1.6.4/test/multipart/invalid_characternu[--AaB03x Content-Disposition: form-data; name="files"; filename="invalid.txt" Content-Type: text/plain contents --AaB03x-- PK!=**,gems/2.2.0/gems/rack-1.6.4/test/gemloader.rbnu[require 'rubygems' project = 'rack' gemspec = File.expand_path("#{project}.gemspec", Dir.pwd) Gem::Specification.load(gemspec).dependencies.each do |dep| begin gem dep.name, *dep.requirement.as_list rescue Gem::LoadError warn "Cannot load #{dep.name} #{dep.requirement.to_s}" end end PK!iKK0gems/2.2.0/gems/rack-1.6.4/test/rackup/config.runu[require "#{File.dirname(__FILE__)}/../testrequest" $stderr = File.open("#{File.dirname(__FILE__)}/log_output", "w") class EnvMiddleware def initialize(app) @app = app end def call(env) # provides a way to test that lint is present if env["PATH_INFO"] == "/broken_lint" return [200, {}, ["Broken Lint"]] # provides a way to kill the process without knowing the pid elsif env["PATH_INFO"] == "/die" exit! end env["test.$DEBUG"] = $DEBUG env["test.$EVAL"] = BUKKIT if defined?(BUKKIT) env["test.$VERBOSE"] = $VERBOSE env["test.$LOAD_PATH"] = $LOAD_PATH env["test.stderr"] = File.expand_path($stderr.path) env["test.Ping"] = defined?(Ping) env["test.pid"] = Process.pid @app.call(env) end end use EnvMiddleware run TestRequest.new PK!h_%_%,gems/2.2.0/gems/rack-1.6.4/test/spec_mock.rbnu[require 'yaml' require 'rack/lint' require 'rack/mock' require 'stringio' app = Rack::Lint.new(lambda { |env| req = Rack::Request.new(env) env["mock.postdata"] = env["rack.input"].read if req.GET["error"] env["rack.errors"].puts req.GET["error"] env["rack.errors"].flush end body = req.head? ? "" : env.to_yaml Rack::Response.new(body, req.GET["status"] || 200, "Content-Type" => "text/yaml").finish }) describe Rack::MockRequest do should "return a MockResponse" do res = Rack::MockRequest.new(app).get("") res.should.be.kind_of Rack::MockResponse end should "be able to only return the environment" do env = Rack::MockRequest.env_for("") env.should.be.kind_of Hash env.should.include "rack.version" end should "return an environment with a path" do env = Rack::MockRequest.env_for("http://www.example.com/parse?location[]=1&location[]=2&age_group[]=2") env["QUERY_STRING"].should.equal "location[]=1&location[]=2&age_group[]=2" env["PATH_INFO"].should.equal "/parse" env.should.be.kind_of Hash env.should.include "rack.version" end should "provide sensible defaults" do res = Rack::MockRequest.new(app).request env = YAML.load(res.body) env["REQUEST_METHOD"].should.equal "GET" env["SERVER_NAME"].should.equal "example.org" env["SERVER_PORT"].should.equal "80" env["QUERY_STRING"].should.equal "" env["PATH_INFO"].should.equal "/" env["SCRIPT_NAME"].should.equal "" env["rack.url_scheme"].should.equal "http" env["mock.postdata"].should.be.empty end should "allow GET/POST/PUT/DELETE/HEAD" do res = Rack::MockRequest.new(app).get("", :input => "foo") env = YAML.load(res.body) env["REQUEST_METHOD"].should.equal "GET" res = Rack::MockRequest.new(app).post("", :input => "foo") env = YAML.load(res.body) env["REQUEST_METHOD"].should.equal "POST" res = Rack::MockRequest.new(app).put("", :input => "foo") env = YAML.load(res.body) env["REQUEST_METHOD"].should.equal "PUT" res = Rack::MockRequest.new(app).patch("", :input => "foo") env = YAML.load(res.body) env["REQUEST_METHOD"].should.equal "PATCH" res = Rack::MockRequest.new(app).delete("", :input => "foo") env = YAML.load(res.body) env["REQUEST_METHOD"].should.equal "DELETE" Rack::MockRequest.env_for("/", :method => "HEAD")["REQUEST_METHOD"]. should.equal "HEAD" Rack::MockRequest.env_for("/", :method => "OPTIONS")["REQUEST_METHOD"]. should.equal "OPTIONS" end should "set content length" do env = Rack::MockRequest.env_for("/", :input => "foo") env["CONTENT_LENGTH"].should.equal "3" end should "allow posting" do res = Rack::MockRequest.new(app).get("", :input => "foo") env = YAML.load(res.body) env["mock.postdata"].should.equal "foo" res = Rack::MockRequest.new(app).post("", :input => StringIO.new("foo")) env = YAML.load(res.body) env["mock.postdata"].should.equal "foo" end should "use all parts of an URL" do res = Rack::MockRequest.new(app). get("https://bla.example.org:9292/meh/foo?bar") res.should.be.kind_of Rack::MockResponse env = YAML.load(res.body) env["REQUEST_METHOD"].should.equal "GET" env["SERVER_NAME"].should.equal "bla.example.org" env["SERVER_PORT"].should.equal "9292" env["QUERY_STRING"].should.equal "bar" env["PATH_INFO"].should.equal "/meh/foo" env["rack.url_scheme"].should.equal "https" end should "set SSL port and HTTP flag on when using https" do res = Rack::MockRequest.new(app). get("https://example.org/foo") res.should.be.kind_of Rack::MockResponse env = YAML.load(res.body) env["REQUEST_METHOD"].should.equal "GET" env["SERVER_NAME"].should.equal "example.org" env["SERVER_PORT"].should.equal "443" env["QUERY_STRING"].should.equal "" env["PATH_INFO"].should.equal "/foo" env["rack.url_scheme"].should.equal "https" env["HTTPS"].should.equal "on" end should "prepend slash to uri path" do res = Rack::MockRequest.new(app). get("foo") res.should.be.kind_of Rack::MockResponse env = YAML.load(res.body) env["REQUEST_METHOD"].should.equal "GET" env["SERVER_NAME"].should.equal "example.org" env["SERVER_PORT"].should.equal "80" env["QUERY_STRING"].should.equal "" env["PATH_INFO"].should.equal "/foo" env["rack.url_scheme"].should.equal "http" end should "properly convert method name to an uppercase string" do res = Rack::MockRequest.new(app).request(:get) env = YAML.load(res.body) env["REQUEST_METHOD"].should.equal "GET" end should "accept params and build query string for GET requests" do res = Rack::MockRequest.new(app).get("/foo?baz=2", :params => {:foo => {:bar => "1"}}) env = YAML.load(res.body) env["REQUEST_METHOD"].should.equal "GET" env["QUERY_STRING"].should.include "baz=2" env["QUERY_STRING"].should.include "foo[bar]=1" env["PATH_INFO"].should.equal "/foo" env["mock.postdata"].should.equal "" end should "accept raw input in params for GET requests" do res = Rack::MockRequest.new(app).get("/foo?baz=2", :params => "foo[bar]=1") env = YAML.load(res.body) env["REQUEST_METHOD"].should.equal "GET" env["QUERY_STRING"].should.include "baz=2" env["QUERY_STRING"].should.include "foo[bar]=1" env["PATH_INFO"].should.equal "/foo" env["mock.postdata"].should.equal "" end should "accept params and build url encoded params for POST requests" do res = Rack::MockRequest.new(app).post("/foo", :params => {:foo => {:bar => "1"}}) env = YAML.load(res.body) env["REQUEST_METHOD"].should.equal "POST" env["QUERY_STRING"].should.equal "" env["PATH_INFO"].should.equal "/foo" env["CONTENT_TYPE"].should.equal "application/x-www-form-urlencoded" env["mock.postdata"].should.equal "foo[bar]=1" end should "accept raw input in params for POST requests" do res = Rack::MockRequest.new(app).post("/foo", :params => "foo[bar]=1") env = YAML.load(res.body) env["REQUEST_METHOD"].should.equal "POST" env["QUERY_STRING"].should.equal "" env["PATH_INFO"].should.equal "/foo" env["CONTENT_TYPE"].should.equal "application/x-www-form-urlencoded" env["mock.postdata"].should.equal "foo[bar]=1" end should "accept params and build multipart encoded params for POST requests" do files = Rack::Multipart::UploadedFile.new(File.join(File.dirname(__FILE__), "multipart", "file1.txt")) res = Rack::MockRequest.new(app).post("/foo", :params => { "submit-name" => "Larry", "files" => files }) env = YAML.load(res.body) env["REQUEST_METHOD"].should.equal "POST" env["QUERY_STRING"].should.equal "" env["PATH_INFO"].should.equal "/foo" env["CONTENT_TYPE"].should.equal "multipart/form-data; boundary=AaB03x" # The gsub accounts for differences in YAMLs affect on the data. env["mock.postdata"].gsub("\r", "").length.should.equal 206 end should "behave valid according to the Rack spec" do lambda { Rack::MockRequest.new(app). get("https://bla.example.org:9292/meh/foo?bar", :lint => true) }.should.not.raise(Rack::Lint::LintError) end should "call close on the original body object" do called = false body = Rack::BodyProxy.new(['hi']) { called = true } capp = proc { |e| [200, {'Content-Type' => 'text/plain'}, body] } called.should.equal false Rack::MockRequest.new(capp).get('/', :lint => true) called.should.equal true end end describe Rack::MockResponse do should "provide access to the HTTP status" do res = Rack::MockRequest.new(app).get("") res.should.be.successful res.should.be.ok res = Rack::MockRequest.new(app).get("/?status=404") res.should.not.be.successful res.should.be.client_error res.should.be.not_found res = Rack::MockRequest.new(app).get("/?status=501") res.should.not.be.successful res.should.be.server_error res = Rack::MockRequest.new(app).get("/?status=307") res.should.be.redirect res = Rack::MockRequest.new(app).get("/?status=201", :lint => true) res.should.be.empty end should "provide access to the HTTP headers" do res = Rack::MockRequest.new(app).get("") res.should.include "Content-Type" res.headers["Content-Type"].should.equal "text/yaml" res.original_headers["Content-Type"].should.equal "text/yaml" res["Content-Type"].should.equal "text/yaml" res.content_type.should.equal "text/yaml" res.content_length.should.not.equal 0 res.location.should.be.nil end should "provide access to the HTTP body" do res = Rack::MockRequest.new(app).get("") res.body.should =~ /rack/ res.should =~ /rack/ res.should.match(/rack/) res.should.satisfy { |r| r.match(/rack/) } end should "provide access to the Rack errors" do res = Rack::MockRequest.new(app).get("/?error=foo", :lint => true) res.should.be.ok res.errors.should.not.be.empty res.errors.should.include "foo" end should "allow calling body.close afterwards" do # this is exactly what rack-test does body = StringIO.new("hi") res = Rack::MockResponse.new(200, {}, body) body.close if body.respond_to?(:close) res.body.should == 'hi' end should "optionally make Rack errors fatal" do lambda { Rack::MockRequest.new(app).get("/?error=foo", :fatal => true) }.should.raise(Rack::MockRequest::FatalWarning) end end PK!Q?*2gems/2.2.0/gems/rack-1.6.4/test/spec_nulllogger.rbnu[require 'rack/lint' require 'rack/mock' require 'rack/nulllogger' describe Rack::NullLogger do should "act as a noop logger" do app = lambda { |env| env['rack.logger'].warn "b00m" [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] } logger = Rack::Lint.new(Rack::NullLogger.new(app)) res = logger.call(Rack::MockRequest.env_for) res[0..1].should.equal [ 200, {'Content-Type' => 'text/plain'} ] res[2].to_enum.to_a.should.equal ["Hello, World!"] end end PK!kLL7gems/2.2.0/gems/rack-1.6.4/test/spec_tempfile_reaper.rbnu[require 'rack/tempfile_reaper' require 'rack/lint' require 'rack/mock' describe Rack::TempfileReaper do class MockTempfile attr_reader :closed def initialize @closed = false end def close! @closed = true end end before do @env = Rack::MockRequest.env_for end def call(app) Rack::Lint.new(Rack::TempfileReaper.new(app)).call(@env) end should 'do nothing (i.e. not bomb out) without env[rack.tempfiles]' do app = lambda { |_| [200, {}, ['Hello, World!']] } response = call(app) response[2].close response[0].should.equal(200) end should 'close env[rack.tempfiles] when body is closed' do tempfile1, tempfile2 = MockTempfile.new, MockTempfile.new @env['rack.tempfiles'] = [ tempfile1, tempfile2 ] app = lambda { |_| [200, {}, ['Hello, World!']] } call(app)[2].close tempfile1.closed.should.equal true tempfile2.closed.should.equal true end should 'initialize env[rack.tempfiles] when not already present' do tempfile = MockTempfile.new app = lambda do |env| env['rack.tempfiles'] << tempfile [200, {}, ['Hello, World!']] end call(app)[2].close tempfile.closed.should.equal true end should 'append env[rack.tempfiles] when already present' do tempfile1, tempfile2 = MockTempfile.new, MockTempfile.new @env['rack.tempfiles'] = [ tempfile1 ] app = lambda do |env| env['rack.tempfiles'] << tempfile2 [200, {}, ['Hello, World!']] end call(app)[2].close tempfile1.closed.should.equal true tempfile2.closed.should.equal true end end PK!XX,gems/2.2.0/gems/rack-1.6.4/test/spec_etag.rbnu[require 'rack/etag' require 'rack/lint' require 'rack/mock' require 'time' describe Rack::ETag do def etag(app, *args) Rack::Lint.new Rack::ETag.new(app, *args) end def request Rack::MockRequest.env_for end def sendfile_body res = ['Hello World'] def res.to_path ; "/tmp/hello.txt" ; end res end should "set ETag if none is set if status is 200" do app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] } response = etag(app).call(request) response[1]['ETag'].should.equal "W/\"65a8e27d8879283831b664bd8b7f0ad4\"" end should "set ETag if none is set if status is 201" do app = lambda { |env| [201, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] } response = etag(app).call(request) response[1]['ETag'].should.equal "W/\"65a8e27d8879283831b664bd8b7f0ad4\"" end should "set Cache-Control to 'max-age=0, private, must-revalidate' (default) if none is set" do app = lambda { |env| [201, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] } response = etag(app).call(request) response[1]['Cache-Control'].should.equal 'max-age=0, private, must-revalidate' end should "set Cache-Control to chosen one if none is set" do app = lambda { |env| [201, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] } response = etag(app, nil, 'public').call(request) response[1]['Cache-Control'].should.equal 'public' end should "set a given Cache-Control even if digest could not be calculated" do app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, []] } response = etag(app, 'no-cache').call(request) response[1]['Cache-Control'].should.equal 'no-cache' end should "not set Cache-Control if it is already set" do app = lambda { |env| [201, {'Content-Type' => 'text/plain', 'Cache-Control' => 'public'}, ["Hello, World!"]] } response = etag(app).call(request) response[1]['Cache-Control'].should.equal 'public' end should "not set Cache-Control if directive isn't present" do app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] } response = etag(app, nil, nil).call(request) response[1]['Cache-Control'].should.equal nil end should "not change ETag if it is already set" do app = lambda { |env| [200, {'Content-Type' => 'text/plain', 'ETag' => '"abc"'}, ["Hello, World!"]] } response = etag(app).call(request) response[1]['ETag'].should.equal "\"abc\"" end should "not set ETag if body is empty" do app = lambda { |env| [200, {'Content-Type' => 'text/plain', 'Last-Modified' => Time.now.httpdate}, []] } response = etag(app).call(request) response[1]['ETag'].should.be.nil end should "not set ETag if Last-Modified is set" do app = lambda { |env| [200, {'Content-Type' => 'text/plain', 'Last-Modified' => Time.now.httpdate}, ["Hello, World!"]] } response = etag(app).call(request) response[1]['ETag'].should.be.nil end should "not set ETag if a sendfile_body is given" do app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, sendfile_body] } response = etag(app).call(request) response[1]['ETag'].should.be.nil end should "not set ETag if a status is not 200 or 201" do app = lambda { |env| [401, {'Content-Type' => 'text/plain'}, ['Access denied.']] } response = etag(app).call(request) response[1]['ETag'].should.be.nil end should "not set ETag if no-cache is given" do app = lambda { |env| [200, {'Content-Type' => 'text/plain', 'Cache-Control' => 'no-cache, must-revalidate'}, ['Hello, World!']] } response = etag(app).call(request) response[1]['ETag'].should.be.nil end should "close the original body" do body = StringIO.new app = lambda { |env| [200, {}, body] } response = etag(app).call(request) body.should.not.be.closed response[2].close body.should.be.closed end end PK!_7S99,gems/2.2.0/gems/rack-1.6.4/test/spec_mime.rbnu[require 'rack/mime' describe Rack::Mime do it "should return the fallback mime-type for files with no extension" do fallback = 'image/jpg' Rack::Mime.mime_type(File.extname('no_ext'), fallback).should.equal fallback end it "should always return 'application/octet-stream' for unknown file extensions" do unknown_ext = File.extname('unknown_ext.abcdefg') Rack::Mime.mime_type(unknown_ext).should.equal 'application/octet-stream' end it "should return the mime-type for a given extension" do # sanity check. it would be infeasible test every single mime-type. Rack::Mime.mime_type(File.extname('image.jpg')).should.equal 'image/jpeg' end it "should support null fallbacks" do Rack::Mime.mime_type('.nothing', nil).should.equal nil end it "should match exact mimes" do Rack::Mime.match?('text/html', 'text/html').should.equal true Rack::Mime.match?('text/html', 'text/meme').should.equal false Rack::Mime.match?('text', 'text').should.equal true Rack::Mime.match?('text', 'binary').should.equal false end it "should match class wildcard mimes" do Rack::Mime.match?('text/html', 'text/*').should.equal true Rack::Mime.match?('text/plain', 'text/*').should.equal true Rack::Mime.match?('application/json', 'text/*').should.equal false Rack::Mime.match?('text/html', 'text').should.equal true end it "should match full wildcards" do Rack::Mime.match?('text/html', '*').should.equal true Rack::Mime.match?('text/plain', '*').should.equal true Rack::Mime.match?('text/html', '*/*').should.equal true Rack::Mime.match?('text/plain', '*/*').should.equal true end it "should match type wildcard mimes" do Rack::Mime.match?('text/html', '*/html').should.equal true Rack::Mime.match?('text/plain', '*/plain').should.equal true end end PK!*'yy/gems/2.2.0/gems/rack-1.6.4/test/spec_chunked.rbnu[require 'rack/chunked' require 'rack/lint' require 'rack/mock' describe Rack::Chunked do def chunked(app) proc do |env| app = Rack::Chunked.new(app) response = Rack::Lint.new(app).call(env) # we want to use body like an array, but it only has #each response[2] = response[2].to_enum.to_a response end end before do @env = Rack::MockRequest. env_for('/', 'HTTP_VERSION' => '1.1', 'REQUEST_METHOD' => 'GET') end should 'chunk responses with no Content-Length' do app = lambda { |env| [200, {"Content-Type" => "text/plain"}, ['Hello', ' ', 'World!']] } response = Rack::MockResponse.new(*chunked(app).call(@env)) response.headers.should.not.include 'Content-Length' response.headers['Transfer-Encoding'].should.equal 'chunked' response.body.should.equal "5\r\nHello\r\n1\r\n \r\n6\r\nWorld!\r\n0\r\n\r\n" end should 'chunks empty bodies properly' do app = lambda { |env| [200, {"Content-Type" => "text/plain"}, []] } response = Rack::MockResponse.new(*chunked(app).call(@env)) response.headers.should.not.include 'Content-Length' response.headers['Transfer-Encoding'].should.equal 'chunked' response.body.should.equal "0\r\n\r\n" end should 'chunks encoded bodies properly' do body = ["\uFFFEHello", " ", "World"].map {|t| t.encode("UTF-16LE") } app = lambda { |env| [200, {"Content-Type" => "text/plain"}, body] } response = Rack::MockResponse.new(*chunked(app).call(@env)) response.headers.should.not.include 'Content-Length' response.headers['Transfer-Encoding'].should.equal 'chunked' response.body.encoding.to_s.should.equal "ASCII-8BIT" response.body.should.equal "c\r\n\xFE\xFFH\x00e\x00l\x00l\x00o\x00\r\n2\r\n \x00\r\na\r\nW\x00o\x00r\x00l\x00d\x00\r\n0\r\n\r\n".force_encoding("BINARY") end if RUBY_VERSION >= "1.9" should 'not modify response when Content-Length header present' do app = lambda { |env| [200, {"Content-Type" => "text/plain", 'Content-Length'=>'12'}, ['Hello', ' ', 'World!']] } status, headers, body = chunked(app).call(@env) status.should.equal 200 headers.should.not.include 'Transfer-Encoding' headers.should.include 'Content-Length' body.join.should.equal 'Hello World!' end should 'not modify response when client is HTTP/1.0' do app = lambda { |env| [200, {"Content-Type" => "text/plain"}, ['Hello', ' ', 'World!']] } @env['HTTP_VERSION'] = 'HTTP/1.0' status, headers, body = chunked(app).call(@env) status.should.equal 200 headers.should.not.include 'Transfer-Encoding' body.join.should.equal 'Hello World!' end should 'not modify response when client is ancient, pre-HTTP/1.0' do app = lambda { |env| [200, {"Content-Type" => "text/plain"}, ['Hello', ' ', 'World!']] } check = lambda do status, headers, body = chunked(app).call(@env.dup) status.should.equal 200 headers.should.not.include 'Transfer-Encoding' body.join.should.equal 'Hello World!' end @env.delete('HTTP_VERSION') # unicorn will do this on pre-HTTP/1.0 requests check.call @env['HTTP_VERSION'] = 'HTTP/0.9' # not sure if this happens in practice check.call end should 'not modify response when Transfer-Encoding header already present' do app = lambda { |env| [200, {"Content-Type" => "text/plain", 'Transfer-Encoding' => 'identity'}, ['Hello', ' ', 'World!']] } status, headers, body = chunked(app).call(@env) status.should.equal 200 headers['Transfer-Encoding'].should.equal 'identity' body.join.should.equal 'Hello World!' end [100, 204, 205, 304].each do |status_code| should "not modify response when status code is #{status_code}" do app = lambda { |env| [status_code, {}, []] } status, headers, _ = chunked(app).call(@env) status.should.equal status_code headers.should.not.include 'Transfer-Encoding' end end end PK!D1 1 ,gems/2.2.0/gems/rack-1.6.4/test/spec_thin.rbnu[begin require 'rack/handler/thin' require File.expand_path('../testrequest', __FILE__) require 'timeout' describe Rack::Handler::Thin do extend TestRequest::Helpers @app = Rack::Lint.new(TestRequest.new) @server = nil Thin::Logging.silent = true @thread = Thread.new do Rack::Handler::Thin.run(@app, :Host => @host='127.0.0.1', :Port => @port=9204, :tag => "tag") do |server| @server = server end end Thread.pass until @server && @server.running? should "respond" do GET("/") response.should.not.be.nil end should "be a Thin" do GET("/") status.should.equal 200 response["SERVER_SOFTWARE"].should =~ /thin/ response["HTTP_VERSION"].should.equal "HTTP/1.1" response["SERVER_PROTOCOL"].should.equal "HTTP/1.1" response["SERVER_PORT"].should.equal "9204" response["SERVER_NAME"].should.equal "127.0.0.1" end should "have rack headers" do GET("/") response["rack.version"].should.equal [1,0] response["rack.multithread"].should.equal false response["rack.multiprocess"].should.equal false response["rack.run_once"].should.equal false end should "have CGI headers on GET" do GET("/") response["REQUEST_METHOD"].should.equal "GET" response["REQUEST_PATH"].should.equal "/" response["PATH_INFO"].should.be.equal "/" response["QUERY_STRING"].should.equal "" response["test.postdata"].should.equal "" GET("/test/foo?quux=1") response["REQUEST_METHOD"].should.equal "GET" response["REQUEST_PATH"].should.equal "/test/foo" response["PATH_INFO"].should.equal "/test/foo" response["QUERY_STRING"].should.equal "quux=1" end should "have CGI headers on POST" do POST("/", {"rack-form-data" => "23"}, {'X-test-header' => '42'}) status.should.equal 200 response["REQUEST_METHOD"].should.equal "POST" response["REQUEST_PATH"].should.equal "/" response["QUERY_STRING"].should.equal "" response["HTTP_X_TEST_HEADER"].should.equal "42" response["test.postdata"].should.equal "rack-form-data=23" end should "support HTTP auth" do GET("/test", {:user => "ruth", :passwd => "secret"}) response["HTTP_AUTHORIZATION"].should.equal "Basic cnV0aDpzZWNyZXQ=" end should "set status" do GET("/test?secret") status.should.equal 403 response["rack.url_scheme"].should.equal "http" end should "set tag for server" do @server.tag.should.equal 'tag' end @server.stop! @thread.kill end rescue LoadError $stderr.puts "Skipping Rack::Handler::Thin tests (Thin is required). `gem install thin` and try again." end PK!6[""/gems/2.2.0/gems/rack-1.6.4/test/spec_runtime.rbnu[require 'rack/lint' require 'rack/mock' require 'rack/runtime' describe Rack::Runtime do def runtime_app(app, *args) Rack::Lint.new Rack::Runtime.new(app, *args) end def request Rack::MockRequest.env_for end it "sets X-Runtime is none is set" do app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, "Hello, World!"] } response = runtime_app(app).call(request) response[1]['X-Runtime'].should =~ /[\d\.]+/ end it "doesn't set the X-Runtime if it is already set" do app = lambda { |env| [200, {'Content-Type' => 'text/plain', "X-Runtime" => "foobar"}, "Hello, World!"] } response = runtime_app(app).call(request) response[1]['X-Runtime'].should == "foobar" end should "allow a suffix to be set" do app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, "Hello, World!"] } response = runtime_app(app, "Test").call(request) response[1]['X-Runtime-Test'].should =~ /[\d\.]+/ end should "allow multiple timers to be set" do app = lambda { |env| sleep 0.1; [200, {'Content-Type' => 'text/plain'}, "Hello, World!"] } runtime = runtime_app(app, "App") # wrap many times to guarantee a measurable difference 100.times do |i| runtime = Rack::Runtime.new(runtime, i.to_s) end runtime = Rack::Runtime.new(runtime, "All") response = runtime.call(request) response[1]['X-Runtime-App'].should =~ /[\d\.]+/ response[1]['X-Runtime-All'].should =~ /[\d\.]+/ Float(response[1]['X-Runtime-All']).should > Float(response[1]['X-Runtime-App']) end end PK!Zgems/2.2.0/gems/rack-1.6.4/test/unregistered_handler/rack/handler/unregistered_long_one.rbnu[module Rack module Handler # this class doesn't do anything, we're just seeing if we get it. class UnregisteredLongOne end end endPK!@eQgems/2.2.0/gems/rack-1.6.4/test/unregistered_handler/rack/handler/unregistered.rbnu[module Rack module Handler # this class doesn't do anything, we're just seeing if we get it. class Unregistered end end endPK!\V.gems/2.2.0/gems/rack-1.6.4/test/testrequest.rbnu[require 'yaml' require 'net/http' require 'rack/lint' class TestRequest NOSERIALIZE = [Method, Proc, Rack::Lint::InputWrapper] def call(env) status = env["QUERY_STRING"] =~ /secret/ ? 403 : 200 env["test.postdata"] = env["rack.input"].read minienv = env.dup # This may in the future want to replace with a dummy value instead. minienv.delete_if { |k,v| NOSERIALIZE.any? { |c| v.kind_of?(c) } } body = minienv.to_yaml size = body.respond_to?(:bytesize) ? body.bytesize : body.size [status, {"Content-Type" => "text/yaml", "Content-Length" => size.to_s}, [body]] end module Helpers attr_reader :status, :response ROOT = File.expand_path(File.dirname(__FILE__) + "/..") ENV["RUBYOPT"] = "-I#{ROOT}/lib -rubygems" def root ROOT end def rackup "#{ROOT}/bin/rackup" end def GET(path, header={}) Net::HTTP.start(@host, @port) { |http| user = header.delete(:user) passwd = header.delete(:passwd) get = Net::HTTP::Get.new(path, header) get.basic_auth user, passwd if user && passwd http.request(get) { |response| @status = response.code.to_i begin @response = YAML.load(response.body) rescue TypeError, ArgumentError @response = nil end } } end def POST(path, formdata={}, header={}) Net::HTTP.start(@host, @port) { |http| user = header.delete(:user) passwd = header.delete(:passwd) post = Net::HTTP::Post.new(path, header) post.form_data = formdata post.basic_auth user, passwd if user && passwd http.request(post) { |response| @status = response.code.to_i @response = YAML.load(response.body) } } end end end class StreamingRequest def self.call(env) [200, {"Content-Type" => "text/plain"}, new] end def each yield "hello there!\n" sleep 5 yield "that is all.\n" end end PK!'Q Q 3gems/2.2.0/gems/rack-1.6.4/test/spec_auth_digest.rbnu[require 'rack/auth/digest/md5' require 'rack/lint' require 'rack/mock' describe Rack::Auth::Digest::MD5 do def realm 'WallysWorld' end def unprotected_app Rack::Lint.new lambda { |env| friend = Rack::Utils.parse_query(env["QUERY_STRING"])["friend"] [ 200, {'Content-Type' => 'text/plain'}, ["Hi #{env['REMOTE_USER']}#{friend ? " and #{friend}" : ''}"] ] } end def protected_app Rack::Auth::Digest::MD5.new(unprotected_app, :realm => realm, :opaque => 'this-should-be-secret') do |username| { 'Alice' => 'correct-password' }[username] end end def protected_app_with_hashed_passwords app = Rack::Auth::Digest::MD5.new(unprotected_app) do |username| username == 'Alice' ? Digest::MD5.hexdigest("Alice:#{realm}:correct-password") : nil end app.realm = realm app.opaque = 'this-should-be-secret' app.passwords_hashed = true app end def partially_protected_app Rack::URLMap.new({ '/' => unprotected_app, '/protected' => protected_app }) end def protected_app_with_method_override Rack::MethodOverride.new(protected_app) end before do @request = Rack::MockRequest.new(protected_app) end def request(method, path, headers = {}, &block) response = @request.request(method, path, headers) block.call(response) if block return response end class MockDigestRequest def initialize(params) @params = params end def method_missing(sym) if @params.has_key? k = sym.to_s return @params[k] end super end def method @params['method'] end def response(password) Rack::Auth::Digest::MD5.new(nil).send :digest, self, password end end def request_with_digest_auth(method, path, username, password, options = {}, &block) request_options = {} request_options[:input] = options.delete(:input) if options.include? :input response = request(method, path, request_options) return response unless response.status == 401 if wait = options.delete(:wait) sleep wait end challenge = response['WWW-Authenticate'].split(' ', 2).last params = Rack::Auth::Digest::Params.parse(challenge) params['username'] = username params['nc'] = '00000001' params['cnonce'] = 'nonsensenonce' params['uri'] = path params['method'] = method params.update options params['response'] = MockDigestRequest.new(params).response(password) request(method, path, request_options.merge('HTTP_AUTHORIZATION' => "Digest #{params}"), &block) end def assert_digest_auth_challenge(response) response.should.be.a.client_error response.status.should.equal 401 response.should.include 'WWW-Authenticate' response.headers['WWW-Authenticate'].should =~ /^Digest / response.body.should.be.empty end def assert_bad_request(response) response.should.be.a.client_error response.status.should.equal 400 response.should.not.include 'WWW-Authenticate' end should 'challenge when no credentials are specified' do request 'GET', '/' do |response| assert_digest_auth_challenge response end end should 'return application output if correct credentials given' do request_with_digest_auth 'GET', '/', 'Alice', 'correct-password' do |response| response.status.should.equal 200 response.body.to_s.should.equal 'Hi Alice' end end should 'return application output if correct credentials given (hashed passwords)' do @request = Rack::MockRequest.new(protected_app_with_hashed_passwords) request_with_digest_auth 'GET', '/', 'Alice', 'correct-password' do |response| response.status.should.equal 200 response.body.to_s.should.equal 'Hi Alice' end end should 'rechallenge if incorrect username given' do request_with_digest_auth 'GET', '/', 'Bob', 'correct-password' do |response| assert_digest_auth_challenge response end end should 'rechallenge if incorrect password given' do request_with_digest_auth 'GET', '/', 'Alice', 'wrong-password' do |response| assert_digest_auth_challenge response end end should 'rechallenge if incorrect user and blank password given' do request_with_digest_auth 'GET', '/', 'Bob', '' do |response| assert_digest_auth_challenge response end end should 'not rechallenge if nonce is not stale' do begin Rack::Auth::Digest::Nonce.time_limit = 10 request_with_digest_auth 'GET', '/', 'Alice', 'correct-password', :wait => 1 do |response| response.status.should.equal 200 response.body.to_s.should.equal 'Hi Alice' response.headers['WWW-Authenticate'].should.not =~ /\bstale=true\b/ end ensure Rack::Auth::Digest::Nonce.time_limit = nil end end should 'rechallenge with stale parameter if nonce is stale' do begin Rack::Auth::Digest::Nonce.time_limit = 1 request_with_digest_auth 'GET', '/', 'Alice', 'correct-password', :wait => 2 do |response| assert_digest_auth_challenge response response.headers['WWW-Authenticate'].should =~ /\bstale=true\b/ end ensure Rack::Auth::Digest::Nonce.time_limit = nil end end should 'return 400 Bad Request if incorrect qop given' do request_with_digest_auth 'GET', '/', 'Alice', 'correct-password', 'qop' => 'auth-int' do |response| assert_bad_request response end end should 'return 400 Bad Request if incorrect uri given' do request_with_digest_auth 'GET', '/', 'Alice', 'correct-password', 'uri' => '/foo' do |response| assert_bad_request response end end should 'return 400 Bad Request if different auth scheme used' do request 'GET', '/', 'HTTP_AUTHORIZATION' => 'Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==' do |response| assert_bad_request response end end should 'not require credentials for unprotected path' do @request = Rack::MockRequest.new(partially_protected_app) request 'GET', '/' do |response| response.should.be.ok end end should 'challenge when no credentials are specified for protected path' do @request = Rack::MockRequest.new(partially_protected_app) request 'GET', '/protected' do |response| assert_digest_auth_challenge response end end should 'return application output if correct credentials given for protected path' do @request = Rack::MockRequest.new(partially_protected_app) request_with_digest_auth 'GET', '/protected', 'Alice', 'correct-password' do |response| response.status.should.equal 200 response.body.to_s.should.equal 'Hi Alice' end end should 'return application output when used with a query string and path as uri' do @request = Rack::MockRequest.new(partially_protected_app) request_with_digest_auth 'GET', '/protected?friend=Mike', 'Alice', 'correct-password' do |response| response.status.should.equal 200 response.body.to_s.should.equal 'Hi Alice and Mike' end end should 'return application output when used with a query string and fullpath as uri' do @request = Rack::MockRequest.new(partially_protected_app) qs_uri = '/protected?friend=Mike' request_with_digest_auth 'GET', qs_uri, 'Alice', 'correct-password', 'uri' => qs_uri do |response| response.status.should.equal 200 response.body.to_s.should.equal 'Hi Alice and Mike' end end should 'return application output if correct credentials given for POST' do request_with_digest_auth 'POST', '/', 'Alice', 'correct-password' do |response| response.status.should.equal 200 response.body.to_s.should.equal 'Hi Alice' end end should 'return application output if correct credentials given for PUT (using method override of POST)' do @request = Rack::MockRequest.new(protected_app_with_method_override) request_with_digest_auth 'POST', '/', 'Alice', 'correct-password', :input => "_method=put" do |response| response.status.should.equal 200 response.body.to_s.should.equal 'Hi Alice' end end it 'takes realm as optional constructor arg' do app = Rack::Auth::Digest::MD5.new(unprotected_app, realm) { true } realm.should == app.realm end end PK!Z%FF.gems/2.2.0/gems/rack-1.6.4/test/spec_server.rbnu[require 'rack' require 'rack/server' require 'tempfile' require 'socket' require 'open-uri' describe Rack::Server do def app lambda { |env| [200, {'Content-Type' => 'text/plain'}, ['success']] } end def with_stderr old, $stderr = $stderr, StringIO.new yield $stderr ensure $stderr = old end it "overrides :config if :app is passed in" do server = Rack::Server.new(:app => "FOO") server.app.should.equal "FOO" end should "prefer to use :builder when it is passed in" do server = Rack::Server.new(:builder => "run lambda { |env| [200, {'Content-Type' => 'text/plain'}, ['success']] }") server.app.class.should.equal Proc Rack::MockRequest.new(server.app).get("/").body.to_s.should.equal 'success' end should "allow subclasses to override middleware" do server = Class.new(Rack::Server).class_eval { def middleware; Hash.new [] end; self } server.middleware['deployment'].should.not.equal [] server.new(:app => 'foo').middleware['deployment'].should.equal [] end should "allow subclasses to override default middleware" do server = Class.new(Rack::Server).instance_eval { def default_middleware_by_environment; Hash.new [] end; self } server.middleware['deployment'].should.equal [] server.new(:app => 'foo').middleware['deployment'].should.equal [] end should "only provide default middleware for development and deployment environments" do Rack::Server.default_middleware_by_environment.keys.sort.should.equal %w(deployment development) end should "always return an empty array for unknown environments" do server = Rack::Server.new(:app => 'foo') server.middleware['production'].should.equal [] end should "not include Rack::Lint in deployment environment" do server = Rack::Server.new(:app => 'foo') server.middleware['deployment'].flatten.should.not.include(Rack::Lint) end should "not include Rack::ShowExceptions in deployment environment" do server = Rack::Server.new(:app => 'foo') server.middleware['deployment'].flatten.should.not.include(Rack::ShowExceptions) end should "include Rack::TempfileReaper in deployment environment" do server = Rack::Server.new(:app => 'foo') server.middleware['deployment'].flatten.should.include(Rack::TempfileReaper) end should "support CGI" do begin o, ENV["REQUEST_METHOD"] = ENV["REQUEST_METHOD"], 'foo' server = Rack::Server.new(:app => 'foo') server.server.name =~ /CGI/ Rack::Server.logging_middleware.call(server).should.eql(nil) ensure ENV['REQUEST_METHOD'] = o end end should "be quiet if said so" do server = Rack::Server.new(:app => "FOO", :quiet => true) Rack::Server.logging_middleware.call(server).should.eql(nil) end should "use a full path to the pidfile" do # avoids issues with daemonize chdir opts = Rack::Server.new.send(:parse_options, %w[--pid testing.pid]) opts[:pid].should.eql(::File.expand_path('testing.pid')) end should "run a server" do pidfile = Tempfile.open('pidfile') { |f| break f }.path FileUtils.rm pidfile server = Rack::Server.new( :app => app, :environment => 'none', :pid => pidfile, :Port => TCPServer.open('127.0.0.1', 0){|s| s.addr[1] }, :Host => '127.0.0.1', :daemonize => false, :server => 'webrick' ) t = Thread.new { server.start { |s| Thread.current[:server] = s } } t.join(0.01) until t[:server] && t[:server].status != :Stop body = open("http://127.0.0.1:#{server.options[:Port]}/") { |f| f.read } body.should.eql('success') Process.kill(:INT, $$) t.join open(pidfile) { |f| f.read.should.eql $$.to_s } end should "check pid file presence and running process" do pidfile = Tempfile.open('pidfile') { |f| f.write($$); break f }.path server = Rack::Server.new(:pid => pidfile) server.send(:pidfile_process_status).should.eql :running end should "check pid file presence and dead process" do dead_pid = `echo $$`.to_i pidfile = Tempfile.open('pidfile') { |f| f.write(dead_pid); break f }.path server = Rack::Server.new(:pid => pidfile) server.send(:pidfile_process_status).should.eql :dead end should "check pid file presence and exited process" do pidfile = Tempfile.open('pidfile') { |f| break f }.path ::File.delete(pidfile) server = Rack::Server.new(:pid => pidfile) server.send(:pidfile_process_status).should.eql :exited end should "check pid file presence and not owned process" do pidfile = Tempfile.open('pidfile') { |f| f.write(1); break f }.path server = Rack::Server.new(:pid => pidfile) server.send(:pidfile_process_status).should.eql :not_owned end should "not write pid file when it is created after check" do pidfile = Tempfile.open('pidfile') { |f| break f }.path ::File.delete(pidfile) server = Rack::Server.new(:pid => pidfile) ::File.open(pidfile, 'w') { |f| f.write(1) } with_stderr do |err| should.raise(SystemExit) do server.send(:write_pid) end err.rewind output = err.read output.should.match(/already running/) output.should.include? pidfile end end should "inform the user about existing pidfiles with running processes" do pidfile = Tempfile.open('pidfile') { |f| f.write(1); break f }.path server = Rack::Server.new(:pid => pidfile) with_stderr do |err| should.raise(SystemExit) do server.start end err.rewind output = err.read output.should.match(/already running/) output.should.include? pidfile end end end PK!7}/gems/2.2.0/gems/rack-1.6.4/test/spec_version.rbnu[# -*- encoding: utf-8 -*- require 'rack' describe Rack do describe 'version' do it 'defaults to a hard-coded api version' do Rack.version.should.equal("1.3") end end describe 'release' do it 'matches version in .gemspec' do gemspec_path = File.join(File.dirname(File.expand_path(__FILE__)), '../rack.gemspec') gemspec = Gem::Specification.load(gemspec_path) Rack.release.split('.').take(2).should.equal gemspec.version.to_s.split('.').take(2) end end end PK!c-N(N(0gems/2.2.0/gems/rack-1.6.4/test/spec_response.rbnu[require 'rack/response' require 'stringio' describe Rack::Response do should "have sensible default values" do response = Rack::Response.new status, header, body = response.finish status.should.equal 200 header.should.equal({}) body.each { |part| part.should.equal "" } response = Rack::Response.new status, header, body = *response status.should.equal 200 header.should.equal({}) body.each { |part| part.should.equal "" } end it "can be written to" do response = Rack::Response.new _, _, body = response.finish do response.write "foo" response.write "bar" response.write "baz" end parts = [] body.each { |part| parts << part } parts.should.equal ["foo", "bar", "baz"] end it "can set and read headers" do response = Rack::Response.new response["Content-Type"].should.equal nil response["Content-Type"] = "text/plain" response["Content-Type"].should.equal "text/plain" end it "can override the initial Content-Type with a different case" do response = Rack::Response.new("", 200, "content-type" => "text/plain") response["Content-Type"].should.equal "text/plain" end it "can set cookies" do response = Rack::Response.new response.set_cookie "foo", "bar" response["Set-Cookie"].should.equal "foo=bar" response.set_cookie "foo2", "bar2" response["Set-Cookie"].should.equal ["foo=bar", "foo2=bar2"].join("\n") response.set_cookie "foo3", "bar3" response["Set-Cookie"].should.equal ["foo=bar", "foo2=bar2", "foo3=bar3"].join("\n") end it "can set cookies with the same name for multiple domains" do response = Rack::Response.new response.set_cookie "foo", {:value => "bar", :domain => "sample.example.com"} response.set_cookie "foo", {:value => "bar", :domain => ".example.com"} response["Set-Cookie"].should.equal ["foo=bar; domain=sample.example.com", "foo=bar; domain=.example.com"].join("\n") end it "formats the Cookie expiration date accordingly to RFC 6265" do response = Rack::Response.new response.set_cookie "foo", {:value => "bar", :expires => Time.now+10} response["Set-Cookie"].should.match( /expires=..., \d\d ... \d\d\d\d \d\d:\d\d:\d\d .../) end it "can set secure cookies" do response = Rack::Response.new response.set_cookie "foo", {:value => "bar", :secure => true} response["Set-Cookie"].should.equal "foo=bar; secure" end it "can set http only cookies" do response = Rack::Response.new response.set_cookie "foo", {:value => "bar", :httponly => true} response["Set-Cookie"].should.equal "foo=bar; HttpOnly" end it "can set http only cookies with :http_only" do response = Rack::Response.new response.set_cookie "foo", {:value => "bar", :http_only => true} response["Set-Cookie"].should.equal "foo=bar; HttpOnly" end it "can set prefers :httponly for http only cookie setting when :httponly and :http_only provided" do response = Rack::Response.new response.set_cookie "foo", {:value => "bar", :httponly => false, :http_only => true} response["Set-Cookie"].should.equal "foo=bar" end it "can delete cookies" do response = Rack::Response.new response.set_cookie "foo", "bar" response.set_cookie "foo2", "bar2" response.delete_cookie "foo" response["Set-Cookie"].should.equal [ "foo2=bar2", "foo=; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 -0000" ].join("\n") end it "can delete cookies with the same name from multiple domains" do response = Rack::Response.new response.set_cookie "foo", {:value => "bar", :domain => "sample.example.com"} response.set_cookie "foo", {:value => "bar", :domain => ".example.com"} response["Set-Cookie"].should.equal ["foo=bar; domain=sample.example.com", "foo=bar; domain=.example.com"].join("\n") response.delete_cookie "foo", :domain => ".example.com" response["Set-Cookie"].should.equal ["foo=bar; domain=sample.example.com", "foo=; domain=.example.com; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 -0000"].join("\n") response.delete_cookie "foo", :domain => "sample.example.com" response["Set-Cookie"].should.equal ["foo=; domain=.example.com; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 -0000", "foo=; domain=sample.example.com; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 -0000"].join("\n") end it "can delete cookies with the same name with different paths" do response = Rack::Response.new response.set_cookie "foo", {:value => "bar", :path => "/"} response.set_cookie "foo", {:value => "bar", :path => "/path"} response["Set-Cookie"].should.equal ["foo=bar; path=/", "foo=bar; path=/path"].join("\n") response.delete_cookie "foo", :path => "/path" response["Set-Cookie"].should.equal ["foo=bar; path=/", "foo=; path=/path; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 -0000"].join("\n") end it "can do redirects" do response = Rack::Response.new response.redirect "/foo" status, header, body = response.finish status.should.equal 302 header["Location"].should.equal "/foo" response = Rack::Response.new response.redirect "/foo", 307 status, header, body = response.finish status.should.equal 307 end it "has a useful constructor" do r = Rack::Response.new("foo") status, header, body = r.finish str = ""; body.each { |part| str << part } str.should.equal "foo" r = Rack::Response.new(["foo", "bar"]) status, header, body = r.finish str = ""; body.each { |part| str << part } str.should.equal "foobar" object_with_each = Object.new def object_with_each.each yield "foo" yield "bar" end r = Rack::Response.new(object_with_each) r.write "foo" status, header, body = r.finish str = ""; body.each { |part| str << part } str.should.equal "foobarfoo" r = Rack::Response.new([], 500) r.status.should.equal 500 r = Rack::Response.new([], "200 OK") r.status.should.equal 200 end it "has a constructor that can take a block" do r = Rack::Response.new { |res| res.status = 404 res.write "foo" } status, _, body = r.finish str = ""; body.each { |part| str << part } str.should.equal "foo" status.should.equal 404 end it "doesn't return invalid responses" do r = Rack::Response.new(["foo", "bar"], 204) _, header, body = r.finish str = ""; body.each { |part| str << part } str.should.be.empty header["Content-Type"].should.equal nil header['Content-Length'].should.equal nil lambda { Rack::Response.new(Object.new) }.should.raise(TypeError). message.should =~ /stringable or iterable required/ end it "knows if it's empty" do r = Rack::Response.new r.should.be.empty r.write "foo" r.should.not.be.empty r = Rack::Response.new r.should.be.empty r.finish r.should.be.empty r = Rack::Response.new r.should.be.empty r.finish { } r.should.not.be.empty end should "provide access to the HTTP status" do res = Rack::Response.new res.status = 200 res.should.be.successful res.should.be.ok res.status = 201 res.should.be.successful res.should.be.created res.status = 202 res.should.be.successful res.should.be.accepted res.status = 400 res.should.not.be.successful res.should.be.client_error res.should.be.bad_request res.status = 401 res.should.not.be.successful res.should.be.client_error res.should.be.unauthorized res.status = 404 res.should.not.be.successful res.should.be.client_error res.should.be.not_found res.status = 405 res.should.not.be.successful res.should.be.client_error res.should.be.method_not_allowed res.status = 418 res.should.not.be.successful res.should.be.client_error res.should.be.i_m_a_teapot res.status = 422 res.should.not.be.successful res.should.be.client_error res.should.be.unprocessable res.status = 501 res.should.not.be.successful res.should.be.server_error res.status = 307 res.should.be.redirect end should "provide access to the HTTP headers" do res = Rack::Response.new res["Content-Type"] = "text/yaml" res.should.include "Content-Type" res.headers["Content-Type"].should.equal "text/yaml" res["Content-Type"].should.equal "text/yaml" res.content_type.should.equal "text/yaml" res.content_length.should.be.nil res.location.should.be.nil end it "does not add or change Content-Length when #finish()ing" do res = Rack::Response.new res.status = 200 res.finish res.headers["Content-Length"].should.be.nil res = Rack::Response.new res.status = 200 res.headers["Content-Length"] = "10" res.finish res.headers["Content-Length"].should.equal "10" end it "updates Content-Length when body appended to using #write" do res = Rack::Response.new res.status = 200 res.headers["Content-Length"].should.be.nil res.write "Hi" res.headers["Content-Length"].should.equal "2" res.write " there" res.headers["Content-Length"].should.equal "8" end it "calls close on #body" do res = Rack::Response.new res.body = StringIO.new res.close res.body.should.be.closed end it "calls close on #body when 204, 205, or 304" do res = Rack::Response.new res.body = StringIO.new res.finish res.body.should.not.be.closed res.status = 204 _, _, b = res.finish res.body.should.be.closed b.should.not.equal res.body res.body = StringIO.new res.status = 205 _, _, b = res.finish res.body.should.be.closed b.should.not.equal res.body res.body = StringIO.new res.status = 304 _, _, b = res.finish res.body.should.be.closed b.should.not.equal res.body end it "wraps the body from #to_ary to prevent infinite loops" do res = Rack::Response.new res.finish.last.should.not.respond_to?(:to_ary) lambda { res.finish.last.to_ary }.should.raise(NoMethodError) end end PK!?P  .gems/2.2.0/gems/rack-1.6.4/test/spec_config.rbnu[require 'rack/builder' require 'rack/config' require 'rack/content_length' require 'rack/lint' require 'rack/mock' describe Rack::Config do should "accept a block that modifies the environment" do app = Rack::Builder.new do use Rack::Lint use Rack::Config do |env| env['greeting'] = 'hello' end run lambda { |env| [200, {'Content-Type' => 'text/plain'}, [env['greeting'] || '']] } end response = Rack::MockRequest.new(app).get('/') response.body.should.equal('hello') end end PK!Z8/gems/2.2.0/gems/rack-1.6.4/test/spec_mongrel.rbnu[begin require 'rack' require 'rack/handler/mongrel' require File.expand_path('../testrequest', __FILE__) require 'timeout' Thread.abort_on_exception = true $tcp_defer_accept_opts = nil $tcp_cork_opts = nil describe Rack::Handler::Mongrel do extend TestRequest::Helpers @server = Mongrel::HttpServer.new(@host='127.0.0.1', @port=9201) @server.register('/test', Rack::Handler::Mongrel.new(Rack::Lint.new(TestRequest.new))) @server.register('/stream', Rack::Handler::Mongrel.new(Rack::Lint.new(StreamingRequest))) @acc = @server.run should "respond" do lambda { GET("/test") }.should.not.raise end should "be a Mongrel" do GET("/test") status.should.equal 200 response["SERVER_SOFTWARE"].should =~ /Mongrel/ response["HTTP_VERSION"].should.equal "HTTP/1.1" response["SERVER_PROTOCOL"].should.equal "HTTP/1.1" response["SERVER_PORT"].should.equal "9201" response["SERVER_NAME"].should.equal "127.0.0.1" end should "have rack headers" do GET("/test") response["rack.version"].should.equal [1,3] response["rack.multithread"].should.be.true response["rack.multiprocess"].should.be.false response["rack.run_once"].should.be.false end should "have CGI headers on GET" do GET("/test") response["REQUEST_METHOD"].should.equal "GET" response["SCRIPT_NAME"].should.equal "/test" response["REQUEST_PATH"].should.equal "/test" response["PATH_INFO"].should.be.equal "" response["QUERY_STRING"].should.equal "" response["test.postdata"].should.equal "" GET("/test/foo?quux=1") response["REQUEST_METHOD"].should.equal "GET" response["SCRIPT_NAME"].should.equal "/test" response["REQUEST_PATH"].should.equal "/test/foo" response["PATH_INFO"].should.equal "/foo" response["QUERY_STRING"].should.equal "quux=1" end should "have CGI headers on POST" do POST("/test", {"rack-form-data" => "23"}, {'X-test-header' => '42'}) status.should.equal 200 response["REQUEST_METHOD"].should.equal "POST" response["SCRIPT_NAME"].should.equal "/test" response["REQUEST_PATH"].should.equal "/test" response["QUERY_STRING"].should.equal "" response["HTTP_X_TEST_HEADER"].should.equal "42" response["test.postdata"].should.equal "rack-form-data=23" end should "support HTTP auth" do GET("/test", {:user => "ruth", :passwd => "secret"}) response["HTTP_AUTHORIZATION"].should.equal "Basic cnV0aDpzZWNyZXQ=" end should "set status" do GET("/test?secret") status.should.equal 403 response["rack.url_scheme"].should.equal "http" end should "provide a .run" do block_ran = false Thread.new { Rack::Handler::Mongrel.run(lambda {}, {:Host => '127.0.0.1', :Port => 9211}) { |server| server.should.be.kind_of Mongrel::HttpServer block_ran = true } } sleep 1 block_ran.should.be.true end should "provide a .run that maps a hash" do block_ran = false Thread.new { map = {'/'=>lambda{},'/foo'=>lambda{}} Rack::Handler::Mongrel.run(map, :map => true, :Host => '127.0.0.1', :Port => 9221) { |server| server.should.be.kind_of Mongrel::HttpServer server.classifier.uris.size.should.equal 2 server.classifier.uris.should.not.include '/arf' server.classifier.uris.should.include '/' server.classifier.uris.should.include '/foo' block_ran = true } } sleep 1 block_ran.should.be.true end should "provide a .run that maps a urlmap" do block_ran = false Thread.new { map = Rack::URLMap.new({'/'=>lambda{},'/bar'=>lambda{}}) Rack::Handler::Mongrel.run(map, {:map => true, :Host => '127.0.0.1', :Port => 9231}) { |server| server.should.be.kind_of Mongrel::HttpServer server.classifier.uris.size.should.equal 2 server.classifier.uris.should.not.include '/arf' server.classifier.uris.should.include '/' server.classifier.uris.should.include '/bar' block_ran = true } } sleep 1 block_ran.should.be.true end should "provide a .run that maps a urlmap restricting by host" do block_ran = false Thread.new { map = Rack::URLMap.new({ '/' => lambda{}, '/foo' => lambda{}, '/bar' => lambda{}, 'http://127.0.0.1/' => lambda{}, 'http://127.0.0.1/bar' => lambda{}, 'http://falsehost/arf' => lambda{}, 'http://falsehost/qux' => lambda{} }) opt = {:map => true, :Port => 9241, :Host => '127.0.0.1'} Rack::Handler::Mongrel.run(map, opt) { |server| server.should.be.kind_of Mongrel::HttpServer server.classifier.uris.should.include '/' server.classifier.handler_map['/'].size.should.equal 2 server.classifier.uris.should.include '/foo' server.classifier.handler_map['/foo'].size.should.equal 1 server.classifier.uris.should.include '/bar' server.classifier.handler_map['/bar'].size.should.equal 2 server.classifier.uris.should.not.include '/qux' server.classifier.uris.should.not.include '/arf' server.classifier.uris.size.should.equal 3 block_ran = true } } sleep 1 block_ran.should.be.true end should "stream #each part of the response" do body = '' begin Timeout.timeout(1) do Net::HTTP.start(@host, @port) do |http| get = Net::HTTP::Get.new('/stream') http.request(get) do |response| response.read_body { |part| body << part } end end end rescue Timeout::Error end body.should.not.be.empty end @acc.raise Mongrel::StopServer end rescue LoadError warn "Skipping Rack::Handler::Mongrel tests (Mongrel is required). `gem install mongrel` and try again." end PK!lKj^^1gems/2.2.0/gems/rack-1.6.4/test/spec_multipart.rbnu[require 'rack/utils' require 'rack/mock' describe Rack::Multipart do def multipart_fixture(name, boundary = "AaB03x") file = multipart_file(name) data = File.open(file, 'rb') { |io| io.read } type = "multipart/form-data; boundary=#{boundary}" length = data.respond_to?(:bytesize) ? data.bytesize : data.size { "CONTENT_TYPE" => type, "CONTENT_LENGTH" => length.to_s, :input => StringIO.new(data) } end def multipart_file(name) File.join(File.dirname(__FILE__), "multipart", name.to_s) end should "return nil if content type is not multipart" do env = Rack::MockRequest.env_for("/", "CONTENT_TYPE" => 'application/x-www-form-urlencoded') Rack::Multipart.parse_multipart(env).should.equal nil end should "parse multipart content when content type present but filename is not" do env = Rack::MockRequest.env_for("/", multipart_fixture(:content_type_and_no_filename)) params = Rack::Multipart.parse_multipart(env) params["text"].should.equal "contents" end if "<3".respond_to?(:force_encoding) should "set US_ASCII encoding based on charset" do env = Rack::MockRequest.env_for("/", multipart_fixture(:content_type_and_no_filename)) params = Rack::Multipart.parse_multipart(env) params["text"].encoding.should.equal Encoding::US_ASCII # I'm not 100% sure if making the param name encoding match the # Content-Type charset is the right thing to do. We should revisit this. params.keys.each do |key| key.encoding.should.equal Encoding::US_ASCII end end should "set BINARY encoding on things without content type" do env = Rack::MockRequest.env_for("/", multipart_fixture(:none)) params = Rack::Multipart.parse_multipart(env) params["submit-name"].encoding.should.equal Encoding::UTF_8 end should "set UTF8 encoding on names of things without content type" do env = Rack::MockRequest.env_for("/", multipart_fixture(:none)) params = Rack::Multipart.parse_multipart(env) params.keys.each do |key| key.encoding.should.equal Encoding::UTF_8 end end should "default text to UTF8" do env = Rack::MockRequest.env_for("/", multipart_fixture(:text)) params = Rack::Multipart.parse_multipart(env) params['submit-name'].encoding.should.equal Encoding::UTF_8 params['submit-name-with-content'].encoding.should.equal Encoding::UTF_8 params.keys.each do |key| key.encoding.should.equal Encoding::UTF_8 end end end should "raise RangeError if the key space is exhausted" do env = Rack::MockRequest.env_for("/", multipart_fixture(:content_type_and_no_filename)) old, Rack::Utils.key_space_limit = Rack::Utils.key_space_limit, 1 begin lambda { Rack::Multipart.parse_multipart(env) }.should.raise(RangeError) ensure Rack::Utils.key_space_limit = old end end should "parse multipart form webkit style" do env = Rack::MockRequest.env_for '/', multipart_fixture(:webkit) env['CONTENT_TYPE'] = "multipart/form-data; boundary=----WebKitFormBoundaryWLHCs9qmcJJoyjKR" params = Rack::Multipart.parse_multipart(env) params['profile']['bio'].should.include 'hello' end should "reject insanely long boundaries" do # using a pipe since a tempfile can use up too much space rd, wr = IO.pipe # we only call rewind once at start, so make sure it succeeds # and doesn't hit ESPIPE def rd.rewind; end wr.sync = true # mock out length to make this pipe look like a Tempfile def rd.length 1024 * 1024 * 8 end # write to a pipe in a background thread, this will write a lot # unless Rack (properly) shuts down the read end thr = Thread.new do begin wr.write("--AaB03x") # make the initial boundary a few gigs long longer = "0123456789" * 1024 * 1024 (1024 * 1024).times { wr.write(longer) } wr.write("\r\n") wr.write('Content-Disposition: form-data; name="a"; filename="a.txt"') wr.write("\r\n") wr.write("Content-Type: text/plain\r\n") wr.write("\r\na") wr.write("--AaB03x--\r\n") wr.close rescue => err # this is EPIPE if Rack shuts us down err end end fixture = { "CONTENT_TYPE" => "multipart/form-data; boundary=AaB03x", "CONTENT_LENGTH" => rd.length.to_s, :input => rd, } env = Rack::MockRequest.env_for '/', fixture lambda { Rack::Multipart.parse_multipart(env) }.should.raise(EOFError) rd.close err = thr.value err.should.be.instance_of Errno::EPIPE wr.close end should "parse multipart upload with text file" do env = Rack::MockRequest.env_for("/", multipart_fixture(:text)) params = Rack::Multipart.parse_multipart(env) params["submit-name"].should.equal "Larry" params["submit-name-with-content"].should.equal "Berry" params["files"][:type].should.equal "text/plain" params["files"][:filename].should.equal "file1.txt" params["files"][:head].should.equal "Content-Disposition: form-data; " + "name=\"files\"; filename=\"file1.txt\"\r\n" + "Content-Type: text/plain\r\n" params["files"][:name].should.equal "files" params["files"][:tempfile].read.should.equal "contents" end should "preserve extension in the created tempfile" do env = Rack::MockRequest.env_for("/", multipart_fixture(:text)) params = Rack::Multipart.parse_multipart(env) File.extname(params["files"][:tempfile].path).should.equal ".txt" end should "parse multipart upload with text file with no name field" do env = Rack::MockRequest.env_for("/", multipart_fixture(:filename_and_no_name)) params = Rack::Multipart.parse_multipart(env) params["file1.txt"][:type].should.equal "text/plain" params["file1.txt"][:filename].should.equal "file1.txt" params["file1.txt"][:head].should.equal "Content-Disposition: form-data; " + "filename=\"file1.txt\"\r\n" + "Content-Type: text/plain\r\n" params["file1.txt"][:name].should.equal "file1.txt" params["file1.txt"][:tempfile].read.should.equal "contents" end should "parse multipart upload file using custom tempfile class" do env = Rack::MockRequest.env_for("/", multipart_fixture(:text)) my_tempfile = "" env['rack.multipart.tempfile_factory'] = lambda { |filename, content_type| my_tempfile } params = Rack::Multipart.parse_multipart(env) params["files"][:tempfile].object_id.should.equal my_tempfile.object_id my_tempfile.should.equal "contents" end should "parse multipart upload with nested parameters" do env = Rack::MockRequest.env_for("/", multipart_fixture(:nested)) params = Rack::Multipart.parse_multipart(env) params["foo"]["submit-name"].should.equal "Larry" params["foo"]["files"][:type].should.equal "text/plain" params["foo"]["files"][:filename].should.equal "file1.txt" params["foo"]["files"][:head].should.equal "Content-Disposition: form-data; " + "name=\"foo[files]\"; filename=\"file1.txt\"\r\n" + "Content-Type: text/plain\r\n" params["foo"]["files"][:name].should.equal "foo[files]" params["foo"]["files"][:tempfile].read.should.equal "contents" end should "parse multipart upload with binary file" do env = Rack::MockRequest.env_for("/", multipart_fixture(:binary)) params = Rack::Multipart.parse_multipart(env) params["submit-name"].should.equal "Larry" params["files"][:type].should.equal "image/png" params["files"][:filename].should.equal "rack-logo.png" params["files"][:head].should.equal "Content-Disposition: form-data; " + "name=\"files\"; filename=\"rack-logo.png\"\r\n" + "Content-Type: image/png\r\n" params["files"][:name].should.equal "files" params["files"][:tempfile].read.length.should.equal 26473 end should "parse multipart upload with empty file" do env = Rack::MockRequest.env_for("/", multipart_fixture(:empty)) params = Rack::Multipart.parse_multipart(env) params["submit-name"].should.equal "Larry" params["files"][:type].should.equal "text/plain" params["files"][:filename].should.equal "file1.txt" params["files"][:head].should.equal "Content-Disposition: form-data; " + "name=\"files\"; filename=\"file1.txt\"\r\n" + "Content-Type: text/plain\r\n" params["files"][:name].should.equal "files" params["files"][:tempfile].read.should.equal "" end should "parse multipart upload with filename with semicolons" do env = Rack::MockRequest.env_for("/", multipart_fixture(:semicolon)) params = Rack::Multipart.parse_multipart(env) params["files"][:type].should.equal "text/plain" params["files"][:filename].should.equal "fi;le1.txt" params["files"][:head].should.equal "Content-Disposition: form-data; " + "name=\"files\"; filename=\"fi;le1.txt\"\r\n" + "Content-Type: text/plain\r\n" params["files"][:name].should.equal "files" params["files"][:tempfile].read.should.equal "contents" end should "parse multipart upload with filename with invalid characters" do env = Rack::MockRequest.env_for("/", multipart_fixture(:invalid_character)) params = Rack::Multipart.parse_multipart(env) params["files"][:type].should.equal "text/plain" params["files"][:filename].should.match(/invalid/) head = "Content-Disposition: form-data; " + "name=\"files\"; filename=\"invalid\xC3.txt\"\r\n" + "Content-Type: text/plain\r\n" head = head.force_encoding("ASCII-8BIT") if head.respond_to?(:force_encoding) params["files"][:head].should.equal head params["files"][:name].should.equal "files" params["files"][:tempfile].read.should.equal "contents" end should "not include file params if no file was selected" do env = Rack::MockRequest.env_for("/", multipart_fixture(:none)) params = Rack::Multipart.parse_multipart(env) params["submit-name"].should.equal "Larry" params["files"].should.equal nil params.keys.should.not.include "files" end should "parse multipart/mixed" do env = Rack::MockRequest.env_for("/", multipart_fixture(:mixed_files)) params = Rack::Utils::Multipart.parse_multipart(env) params["foo"].should.equal "bar" params["files"].should.be.instance_of String params["files"].size.should.equal 252 end should "parse multipart/mixed" do env = Rack::MockRequest.env_for("/", multipart_fixture(:mixed_files)) params = Rack::Utils::Multipart.parse_multipart(env) params["foo"].should.equal "bar" params["files"].should.be.instance_of String params["files"].size.should.equal 252 end should "parse IE multipart upload and clean up filename" do env = Rack::MockRequest.env_for("/", multipart_fixture(:ie)) params = Rack::Multipart.parse_multipart(env) params["files"][:type].should.equal "text/plain" params["files"][:filename].should.equal "file1.txt" params["files"][:head].should.equal "Content-Disposition: form-data; " + "name=\"files\"; " + 'filename="C:\Documents and Settings\Administrator\Desktop\file1.txt"' + "\r\nContent-Type: text/plain\r\n" params["files"][:name].should.equal "files" params["files"][:tempfile].read.should.equal "contents" end should "parse filename and modification param" do env = Rack::MockRequest.env_for("/", multipart_fixture(:filename_and_modification_param)) params = Rack::Multipart.parse_multipart(env) params["files"][:type].should.equal "image/jpeg" params["files"][:filename].should.equal "genome.jpeg" params["files"][:head].should.equal "Content-Type: image/jpeg\r\n" + "Content-Disposition: attachment; " + "name=\"files\"; " + "filename=genome.jpeg; " + "modification-date=\"Wed, 12 Feb 1997 16:29:51 -0500\";\r\n" + "Content-Description: a complete map of the human genome\r\n" params["files"][:name].should.equal "files" params["files"][:tempfile].read.should.equal "contents" end should "parse filename with escaped quotes" do env = Rack::MockRequest.env_for("/", multipart_fixture(:filename_with_escaped_quotes)) params = Rack::Multipart.parse_multipart(env) params["files"][:type].should.equal "application/octet-stream" params["files"][:filename].should.equal "escape \"quotes" params["files"][:head].should.equal "Content-Disposition: form-data; " + "name=\"files\"; " + "filename=\"escape \\\"quotes\"\r\n" + "Content-Type: application/octet-stream\r\n" params["files"][:name].should.equal "files" params["files"][:tempfile].read.should.equal "contents" end should "parse filename with percent escaped quotes" do env = Rack::MockRequest.env_for("/", multipart_fixture(:filename_with_percent_escaped_quotes)) params = Rack::Multipart.parse_multipart(env) params["files"][:type].should.equal "application/octet-stream" params["files"][:filename].should.equal "escape \"quotes" params["files"][:head].should.equal "Content-Disposition: form-data; " + "name=\"files\"; " + "filename=\"escape %22quotes\"\r\n" + "Content-Type: application/octet-stream\r\n" params["files"][:name].should.equal "files" params["files"][:tempfile].read.should.equal "contents" end should "parse filename with unescaped quotes" do env = Rack::MockRequest.env_for("/", multipart_fixture(:filename_with_unescaped_quotes)) params = Rack::Multipart.parse_multipart(env) params["files"][:type].should.equal "application/octet-stream" params["files"][:filename].should.equal "escape \"quotes" params["files"][:head].should.equal "Content-Disposition: form-data; " + "name=\"files\"; " + "filename=\"escape \"quotes\"\r\n" + "Content-Type: application/octet-stream\r\n" params["files"][:name].should.equal "files" params["files"][:tempfile].read.should.equal "contents" end should "parse filename with escaped quotes and modification param" do env = Rack::MockRequest.env_for("/", multipart_fixture(:filename_with_escaped_quotes_and_modification_param)) params = Rack::Multipart.parse_multipart(env) params["files"][:type].should.equal "image/jpeg" params["files"][:filename].should.equal "\"human\" genome.jpeg" params["files"][:head].should.equal "Content-Type: image/jpeg\r\n" + "Content-Disposition: attachment; " + "name=\"files\"; " + "filename=\"\"human\" genome.jpeg\"; " + "modification-date=\"Wed, 12 Feb 1997 16:29:51 -0500\";\r\n" + "Content-Description: a complete map of the human genome\r\n" params["files"][:name].should.equal "files" params["files"][:tempfile].read.should.equal "contents" end should "parse filename with unescaped percentage characters" do env = Rack::MockRequest.env_for("/", multipart_fixture(:filename_with_unescaped_percentages, "----WebKitFormBoundary2NHc7OhsgU68l3Al")) params = Rack::Multipart.parse_multipart(env) files = params["document"]["attachment"] files[:type].should.equal "image/jpeg" files[:filename].should.equal "100% of a photo.jpeg" files[:head].should.equal <<-MULTIPART Content-Disposition: form-data; name="document[attachment]"; filename="100% of a photo.jpeg"\r Content-Type: image/jpeg\r MULTIPART files[:name].should.equal "document[attachment]" files[:tempfile].read.should.equal "contents" end should "parse filename with unescaped percentage characters that look like partial hex escapes" do env = Rack::MockRequest.env_for("/", multipart_fixture(:filename_with_unescaped_percentages2, "----WebKitFormBoundary2NHc7OhsgU68l3Al")) params = Rack::Multipart.parse_multipart(env) files = params["document"]["attachment"] files[:type].should.equal "image/jpeg" files[:filename].should.equal "100%a" files[:head].should.equal <<-MULTIPART Content-Disposition: form-data; name="document[attachment]"; filename="100%a"\r Content-Type: image/jpeg\r MULTIPART files[:name].should.equal "document[attachment]" files[:tempfile].read.should.equal "contents" end should "parse filename with unescaped percentage characters that look like partial hex escapes" do env = Rack::MockRequest.env_for("/", multipart_fixture(:filename_with_unescaped_percentages3, "----WebKitFormBoundary2NHc7OhsgU68l3Al")) params = Rack::Multipart.parse_multipart(env) files = params["document"]["attachment"] files[:type].should.equal "image/jpeg" files[:filename].should.equal "100%" files[:head].should.equal <<-MULTIPART Content-Disposition: form-data; name="document[attachment]"; filename="100%"\r Content-Type: image/jpeg\r MULTIPART files[:name].should.equal "document[attachment]" files[:tempfile].read.should.equal "contents" end it "rewinds input after parsing upload" do options = multipart_fixture(:text) input = options[:input] env = Rack::MockRequest.env_for("/", options) params = Rack::Multipart.parse_multipart(env) params["submit-name"].should.equal "Larry" params["files"][:filename].should.equal "file1.txt" input.read.length.should.equal 307 end it "builds multipart body" do files = Rack::Multipart::UploadedFile.new(multipart_file("file1.txt")) data = Rack::Multipart.build_multipart("submit-name" => "Larry", "files" => files) options = { "CONTENT_TYPE" => "multipart/form-data; boundary=AaB03x", "CONTENT_LENGTH" => data.length.to_s, :input => StringIO.new(data) } env = Rack::MockRequest.env_for("/", options) params = Rack::Multipart.parse_multipart(env) params["submit-name"].should.equal "Larry" params["files"][:filename].should.equal "file1.txt" params["files"][:tempfile].read.should.equal "contents" end it "builds nested multipart body" do files = Rack::Multipart::UploadedFile.new(multipart_file("file1.txt")) data = Rack::Multipart.build_multipart("people" => [{"submit-name" => "Larry", "files" => files}]) options = { "CONTENT_TYPE" => "multipart/form-data; boundary=AaB03x", "CONTENT_LENGTH" => data.length.to_s, :input => StringIO.new(data) } env = Rack::MockRequest.env_for("/", options) params = Rack::Multipart.parse_multipart(env) params["people"][0]["submit-name"].should.equal "Larry" params["people"][0]["files"][:filename].should.equal "file1.txt" params["people"][0]["files"][:tempfile].read.should.equal "contents" end it "can parse fields that end at the end of the buffer" do input = File.read(multipart_file("bad_robots")) req = Rack::Request.new Rack::MockRequest.env_for("/", "CONTENT_TYPE" => "multipart/form-data, boundary=1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon", "CONTENT_LENGTH" => input.size, :input => input) req.POST['file.path'].should.equal "/var/tmp/uploads/4/0001728414" req.POST['addresses'].should.not.equal nil end it "builds complete params with the chunk size of 16384 slicing exactly on boundary" do begin previous_limit = Rack::Utils.multipart_part_limit Rack::Utils.multipart_part_limit = 256 data = File.open(multipart_file("fail_16384_nofile"), 'rb') { |f| f.read }.gsub(/\n/, "\r\n") options = { "CONTENT_TYPE" => "multipart/form-data; boundary=----WebKitFormBoundaryWsY0GnpbI5U7ztzo", "CONTENT_LENGTH" => data.length.to_s, :input => StringIO.new(data) } env = Rack::MockRequest.env_for("/", options) params = Rack::Multipart.parse_multipart(env) params.should.not.equal nil params.keys.should.include "AAAAAAAAAAAAAAAAAAA" params["AAAAAAAAAAAAAAAAAAA"].keys.should.include "PLAPLAPLA_MEMMEMMEMM_ATTRATTRER" params["AAAAAAAAAAAAAAAAAAA"]["PLAPLAPLA_MEMMEMMEMM_ATTRATTRER"].keys.should.include "new" params["AAAAAAAAAAAAAAAAAAA"]["PLAPLAPLA_MEMMEMMEMM_ATTRATTRER"]["new"].keys.should.include "-2" params["AAAAAAAAAAAAAAAAAAA"]["PLAPLAPLA_MEMMEMMEMM_ATTRATTRER"]["new"]["-2"].keys.should.include "ba_unit_id" params["AAAAAAAAAAAAAAAAAAA"]["PLAPLAPLA_MEMMEMMEMM_ATTRATTRER"]["new"]["-2"]["ba_unit_id"].should.equal "1017" ensure Rack::Utils.multipart_part_limit = previous_limit end end should "not reach a multi-part limit" do begin previous_limit = Rack::Utils.multipart_part_limit Rack::Utils.multipart_part_limit = 4 env = Rack::MockRequest.env_for '/', multipart_fixture(:three_files_three_fields) params = Rack::Multipart.parse_multipart(env) params['reply'].should.equal 'yes' params['to'].should.equal 'people' params['from'].should.equal 'others' ensure Rack::Utils.multipart_part_limit = previous_limit end end should "reach a multipart limit" do begin previous_limit = Rack::Utils.multipart_part_limit Rack::Utils.multipart_part_limit = 3 env = Rack::MockRequest.env_for '/', multipart_fixture(:three_files_three_fields) lambda { Rack::Multipart.parse_multipart(env) }.should.raise(Rack::Multipart::MultipartPartLimitError) ensure Rack::Utils.multipart_part_limit = previous_limit end end should "return nil if no UploadedFiles were used" do data = Rack::Multipart.build_multipart("people" => [{"submit-name" => "Larry", "files" => "contents"}]) data.should.equal nil end should "raise ArgumentError if params is not a Hash" do lambda { Rack::Multipart.build_multipart("foo=bar") }. should.raise(ArgumentError). message.should.equal "value must be a Hash" end it "can parse fields with a content type" do data = <<-EOF --1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon\r Content-Disposition: form-data; name="description"\r Content-Type: text/plain"\r \r Very very blue\r --1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon--\r EOF options = { "CONTENT_TYPE" => "multipart/form-data; boundary=1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon", "CONTENT_LENGTH" => data.length.to_s, :input => StringIO.new(data) } env = Rack::MockRequest.env_for("/", options) params = Rack::Utils::Multipart.parse_multipart(env) params.should.equal({"description"=>"Very very blue"}) end should "parse multipart upload with no content-length header" do env = Rack::MockRequest.env_for '/', multipart_fixture(:webkit) env['CONTENT_TYPE'] = "multipart/form-data; boundary=----WebKitFormBoundaryWLHCs9qmcJJoyjKR" env.delete 'CONTENT_LENGTH' params = Rack::Multipart.parse_multipart(env) params['profile']['bio'].should.include 'hello' end should "parse very long unquoted multipart file names" do data = <<-EOF --AaB03x\r Content-Type: text/plain\r Content-Disposition: attachment; name=file; filename=#{'long' * 100}\r \r contents\r --AaB03x--\r EOF options = { "CONTENT_TYPE" => "multipart/form-data; boundary=AaB03x", "CONTENT_LENGTH" => data.length.to_s, :input => StringIO.new(data) } env = Rack::MockRequest.env_for("/", options) params = Rack::Utils::Multipart.parse_multipart(env) params["file"][:filename].should.equal('long' * 100) end should "support mixed case metadata" do file = multipart_file(:text) data = File.open(file, 'rb') { |io| io.read } type = "Multipart/Form-Data; Boundary=AaB03x" length = data.respond_to?(:bytesize) ? data.bytesize : data.size e = { "CONTENT_TYPE" => type, "CONTENT_LENGTH" => length.to_s, :input => StringIO.new(data) } env = Rack::MockRequest.env_for("/", e) params = Rack::Multipart.parse_multipart(env) params["submit-name"].should.equal "Larry" params["submit-name-with-content"].should.equal "Berry" params["files"][:type].should.equal "text/plain" params["files"][:filename].should.equal "file1.txt" params["files"][:head].should.equal "Content-Disposition: form-data; " + "name=\"files\"; filename=\"file1.txt\"\r\n" + "Content-Type: text/plain\r\n" params["files"][:name].should.equal "files" params["files"][:tempfile].read.should.equal "contents" end end PK!!=,,;gems/2.2.0/gems/rack-1.6.4/test/spec_session_abstract_id.rbnu[### WARNING: there be hax in this file. require 'rack/session/abstract/id' describe Rack::Session::Abstract::ID do id = Rack::Session::Abstract::ID def silence_warning o, $VERBOSE = $VERBOSE, nil yield ensure $VERBOSE = o end def reload_id $".delete $".find { |part| part =~ %r{session/abstract/id.rb} } silence_warning { require 'rack/session/abstract/id' } end should "use securerandom when available" do begin fake = false silence_warning do ::SecureRandom = fake = true unless defined?(SecureRandom) end reload_id id::DEFAULT_OPTIONS[:secure_random].should.eql(fake || SecureRandom) ensure Object.send(:remove_const, :SecureRandom) if fake end end should "not use securerandom when unavailable" do begin sr = Object.send(:remove_const, :SecureRandom) if defined?(SecureRandom) reload_id id::DEFAULT_OPTIONS[:secure_random].should.eql false ensure ::SecureRandom = sr if defined?(sr) end end should "allow to use another securerandom provider" do secure_random = Class.new do def hex(*args) 'fake_hex' end end id = Rack::Session::Abstract::ID.new nil, :secure_random => secure_random.new id.send(:generate_sid).should.eql 'fake_hex' end end PK!" 2gems/2.2.0/gems/rack-1.6.4/test/spec_auth_basic.rbnu[require 'rack/auth/basic' require 'rack/lint' require 'rack/mock' describe Rack::Auth::Basic do def realm 'WallysWorld' end def unprotected_app Rack::Lint.new lambda { |env| [ 200, {'Content-Type' => 'text/plain'}, ["Hi #{env['REMOTE_USER']}"] ] } end def protected_app app = Rack::Auth::Basic.new(unprotected_app) { |username, password| 'Boss' == username } app.realm = realm app end before do @request = Rack::MockRequest.new(protected_app) end def request_with_basic_auth(username, password, &block) request 'HTTP_AUTHORIZATION' => 'Basic ' + ["#{username}:#{password}"].pack("m*"), &block end def request(headers = {}) yield @request.get('/', headers) end def assert_basic_auth_challenge(response) response.should.be.a.client_error response.status.should.equal 401 response.should.include 'WWW-Authenticate' response.headers['WWW-Authenticate'].should =~ /Basic realm="#{Regexp.escape(realm)}"/ response.body.should.be.empty end should 'challenge correctly when no credentials are specified' do request do |response| assert_basic_auth_challenge response end end should 'rechallenge if incorrect credentials are specified' do request_with_basic_auth 'joe', 'password' do |response| assert_basic_auth_challenge response end end should 'return application output if correct credentials are specified' do request_with_basic_auth 'Boss', 'password' do |response| response.status.should.equal 200 response.body.to_s.should.equal 'Hi Boss' end end should 'return 400 Bad Request if different auth scheme used' do request 'HTTP_AUTHORIZATION' => 'Digest params' do |response| response.should.be.a.client_error response.status.should.equal 400 response.should.not.include 'WWW-Authenticate' end end should 'return 400 Bad Request for a malformed authorization header' do request 'HTTP_AUTHORIZATION' => '' do |response| response.should.be.a.client_error response.status.should.equal 400 response.should.not.include 'WWW-Authenticate' end end it 'takes realm as optional constructor arg' do app = Rack::Auth::Basic.new(unprotected_app, realm) { true } realm.should == app.realm end end PK!##4gems/2.2.0/gems/rack-1.6.4/test/spec_session_pool.rbnu[require 'thread' require 'rack/lint' require 'rack/mock' require 'rack/session/pool' describe Rack::Session::Pool do session_key = Rack::Session::Pool::DEFAULT_OPTIONS[:key] session_match = /#{session_key}=[0-9a-fA-F]+;/ incrementor = lambda do |env| env["rack.session"]["counter"] ||= 0 env["rack.session"]["counter"] += 1 Rack::Response.new(env["rack.session"].inspect).to_a end session_id = Rack::Lint.new(lambda do |env| Rack::Response.new(env["rack.session"].inspect).to_a end) nothing = Rack::Lint.new(lambda do |env| Rack::Response.new("Nothing").to_a end) drop_session = Rack::Lint.new(lambda do |env| env['rack.session.options'][:drop] = true incrementor.call(env) end) renew_session = Rack::Lint.new(lambda do |env| env['rack.session.options'][:renew] = true incrementor.call(env) end) defer_session = Rack::Lint.new(lambda do |env| env['rack.session.options'][:defer] = true incrementor.call(env) end) incrementor = Rack::Lint.new(incrementor) it "creates a new cookie" do pool = Rack::Session::Pool.new(incrementor) res = Rack::MockRequest.new(pool).get("/") res["Set-Cookie"].should.match session_match res.body.should.equal '{"counter"=>1}' end it "determines session from a cookie" do pool = Rack::Session::Pool.new(incrementor) req = Rack::MockRequest.new(pool) cookie = req.get("/")["Set-Cookie"] req.get("/", "HTTP_COOKIE" => cookie). body.should.equal '{"counter"=>2}' req.get("/", "HTTP_COOKIE" => cookie). body.should.equal '{"counter"=>3}' end it "survives nonexistant cookies" do pool = Rack::Session::Pool.new(incrementor) res = Rack::MockRequest.new(pool). get("/", "HTTP_COOKIE" => "#{session_key}=blarghfasel") res.body.should.equal '{"counter"=>1}' end it "does not send the same session id if it did not change" do pool = Rack::Session::Pool.new(incrementor) req = Rack::MockRequest.new(pool) res0 = req.get("/") cookie = res0["Set-Cookie"][session_match] res0.body.should.equal '{"counter"=>1}' pool.pool.size.should.equal 1 res1 = req.get("/", "HTTP_COOKIE" => cookie) res1["Set-Cookie"].should.be.nil res1.body.should.equal '{"counter"=>2}' pool.pool.size.should.equal 1 res2 = req.get("/", "HTTP_COOKIE" => cookie) res2["Set-Cookie"].should.be.nil res2.body.should.equal '{"counter"=>3}' pool.pool.size.should.equal 1 end it "deletes cookies with :drop option" do pool = Rack::Session::Pool.new(incrementor) req = Rack::MockRequest.new(pool) drop = Rack::Utils::Context.new(pool, drop_session) dreq = Rack::MockRequest.new(drop) res1 = req.get("/") session = (cookie = res1["Set-Cookie"])[session_match] res1.body.should.equal '{"counter"=>1}' pool.pool.size.should.equal 1 res2 = dreq.get("/", "HTTP_COOKIE" => cookie) res2["Set-Cookie"].should.be.nil res2.body.should.equal '{"counter"=>2}' pool.pool.size.should.equal 0 res3 = req.get("/", "HTTP_COOKIE" => cookie) res3["Set-Cookie"][session_match].should.not.equal session res3.body.should.equal '{"counter"=>1}' pool.pool.size.should.equal 1 end it "provides new session id with :renew option" do pool = Rack::Session::Pool.new(incrementor) req = Rack::MockRequest.new(pool) renew = Rack::Utils::Context.new(pool, renew_session) rreq = Rack::MockRequest.new(renew) res1 = req.get("/") session = (cookie = res1["Set-Cookie"])[session_match] res1.body.should.equal '{"counter"=>1}' pool.pool.size.should.equal 1 res2 = rreq.get("/", "HTTP_COOKIE" => cookie) new_cookie = res2["Set-Cookie"] new_session = new_cookie[session_match] new_session.should.not.equal session res2.body.should.equal '{"counter"=>2}' pool.pool.size.should.equal 1 res3 = req.get("/", "HTTP_COOKIE" => new_cookie) res3.body.should.equal '{"counter"=>3}' pool.pool.size.should.equal 1 res4 = req.get("/", "HTTP_COOKIE" => cookie) res4.body.should.equal '{"counter"=>1}' pool.pool.size.should.equal 2 end it "omits cookie with :defer option" do pool = Rack::Session::Pool.new(incrementor) defer = Rack::Utils::Context.new(pool, defer_session) dreq = Rack::MockRequest.new(defer) res1 = dreq.get("/") res1["Set-Cookie"].should.equal nil res1.body.should.equal '{"counter"=>1}' pool.pool.size.should.equal 1 end # anyone know how to do this better? it "should merge sessions when multithreaded" do unless $DEBUG 1.should.equal 1 next end warn 'Running multithread tests for Session::Pool' pool = Rack::Session::Pool.new(incrementor) req = Rack::MockRequest.new(pool) res = req.get('/') res.body.should.equal '{"counter"=>1}' cookie = res["Set-Cookie"] sess_id = cookie[/#{pool.key}=([^,;]+)/,1] delta_incrementor = lambda do |env| # emulate disconjoinment of threading env['rack.session'] = env['rack.session'].dup Thread.stop env['rack.session'][(Time.now.usec*rand).to_i] = true incrementor.call(env) end tses = Rack::Utils::Context.new pool, delta_incrementor treq = Rack::MockRequest.new(tses) tnum = rand(7).to_i+5 r = Array.new(tnum) do Thread.new(treq) do |run| run.get('/', "HTTP_COOKIE" => cookie, 'rack.multithread' => true) end end.reverse.map{|t| t.run.join.value } r.each do |resp| resp['Set-Cookie'].should.equal cookie resp.body.should.include '"counter"=>2' end session = pool.pool[sess_id] session.size.should.equal tnum+1 # counter session['counter'].should.equal 2 # meeeh end it "does not return a cookie if cookie was not read/written" do app = Rack::Session::Pool.new(nothing) res = Rack::MockRequest.new(app).get("/") res["Set-Cookie"].should.be.nil end it "does not return a cookie if cookie was not written (only read)" do app = Rack::Session::Pool.new(session_id) res = Rack::MockRequest.new(app).get("/") res["Set-Cookie"].should.be.nil end it "returns even if not read/written if :expire_after is set" do app = Rack::Session::Pool.new(nothing, :expire_after => 3600) res = Rack::MockRequest.new(app).get("/", 'rack.session' => {'not' => 'empty'}) res["Set-Cookie"].should.not.be.nil end it "returns no cookie if no data was written and no session was created previously, even if :expire_after is set" do app = Rack::Session::Pool.new(nothing, :expire_after => 3600) res = Rack::MockRequest.new(app).get("/") res["Set-Cookie"].should.be.nil end end PK!VYcc-gems/2.2.0/gems/rack-1.6.4/test/spec_utils.rbnu[# -*- encoding: utf-8 -*- require 'rack/utils' require 'rack/mock' require 'timeout' describe Rack::Utils do # A helper method which checks # if certain query parameters # are equal. def equal_query_to(query) parts = query.split('&') lambda{|other| (parts & other.split('&')) == parts } end def kcodeu one8 = RUBY_VERSION.to_f < 1.9 default_kcode, $KCODE = $KCODE, 'U' if one8 yield ensure $KCODE = default_kcode if one8 end should "round trip binary data" do r = [218, 0].pack 'CC' if defined?(::Encoding) z = Rack::Utils.unescape(Rack::Utils.escape(r), Encoding::BINARY) else z = Rack::Utils.unescape(Rack::Utils.escape(r)) end r.should.equal z end should "escape correctly" do Rack::Utils.escape("fobar").should.equal "fo%3Co%3Ebar" Rack::Utils.escape("a space").should.equal "a+space" Rack::Utils.escape("q1!2\"'w$5&7/z8)?\\"). should.equal "q1%212%22%27w%245%267%2Fz8%29%3F%5C" end should "escape correctly for multibyte characters" do matz_name = "\xE3\x81\xBE\xE3\x81\xA4\xE3\x82\x82\xE3\x81\xA8".unpack("a*")[0] # Matsumoto matz_name.force_encoding("UTF-8") if matz_name.respond_to? :force_encoding Rack::Utils.escape(matz_name).should.equal '%E3%81%BE%E3%81%A4%E3%82%82%E3%81%A8' matz_name_sep = "\xE3\x81\xBE\xE3\x81\xA4 \xE3\x82\x82\xE3\x81\xA8".unpack("a*")[0] # Matsu moto matz_name_sep.force_encoding("UTF-8") if matz_name_sep.respond_to? :force_encoding Rack::Utils.escape(matz_name_sep).should.equal '%E3%81%BE%E3%81%A4+%E3%82%82%E3%81%A8' end if RUBY_VERSION[/^\d+\.\d+/] == '1.8' should "escape correctly for multibyte characters if $KCODE is set to 'U'" do kcodeu do matz_name = "\xE3\x81\xBE\xE3\x81\xA4\xE3\x82\x82\xE3\x81\xA8".unpack("a*")[0] # Matsumoto matz_name.force_encoding("UTF-8") if matz_name.respond_to? :force_encoding Rack::Utils.escape(matz_name).should.equal '%E3%81%BE%E3%81%A4%E3%82%82%E3%81%A8' matz_name_sep = "\xE3\x81\xBE\xE3\x81\xA4 \xE3\x82\x82\xE3\x81\xA8".unpack("a*")[0] # Matsu moto matz_name_sep.force_encoding("UTF-8") if matz_name_sep.respond_to? :force_encoding Rack::Utils.escape(matz_name_sep).should.equal '%E3%81%BE%E3%81%A4+%E3%82%82%E3%81%A8' end end should "unescape multibyte characters correctly if $KCODE is set to 'U'" do kcodeu do Rack::Utils.unescape('%E3%81%BE%E3%81%A4+%E3%82%82%E3%81%A8').should.equal( "\xE3\x81\xBE\xE3\x81\xA4 \xE3\x82\x82\xE3\x81\xA8".unpack("a*")[0]) end end end should "escape objects that responds to to_s" do kcodeu do Rack::Utils.escape(:id).should.equal "id" end end if "".respond_to?(:encode) should "escape non-UTF8 strings" do Rack::Utils.escape("ø".encode("ISO-8859-1")).should.equal "%F8" end end should "not hang on escaping long strings that end in % (http://redmine.ruby-lang.org/issues/5149)" do lambda { timeout(1) do lambda { URI.decode_www_form_component "A string that causes catastrophic backtracking as it gets longer %" }.should.raise(ArgumentError) end }.should.not.raise(Timeout::Error) end should "escape path spaces with %20" do Rack::Utils.escape_path("foo bar").should.equal "foo%20bar" end should "unescape correctly" do Rack::Utils.unescape("fo%3Co%3Ebar").should.equal "fobar" Rack::Utils.unescape("a+space").should.equal "a space" Rack::Utils.unescape("a%20space").should.equal "a space" Rack::Utils.unescape("q1%212%22%27w%245%267%2Fz8%29%3F%5C"). should.equal "q1!2\"'w$5&7/z8)?\\" end should "parse query strings correctly" do Rack::Utils.parse_query("foo=bar"). should.equal "foo" => "bar" Rack::Utils.parse_query("foo=\"bar\""). should.equal "foo" => "\"bar\"" Rack::Utils.parse_query("foo=bar&foo=quux"). should.equal "foo" => ["bar", "quux"] Rack::Utils.parse_query("foo=1&bar=2"). should.equal "foo" => "1", "bar" => "2" Rack::Utils.parse_query("my+weird+field=q1%212%22%27w%245%267%2Fz8%29%3F"). should.equal "my weird field" => "q1!2\"'w$5&7/z8)?" Rack::Utils.parse_query("foo%3Dbaz=bar").should.equal "foo=baz" => "bar" Rack::Utils.parse_query("=").should.equal "" => "" Rack::Utils.parse_query("=value").should.equal "" => "value" Rack::Utils.parse_query("key=").should.equal "key" => "" Rack::Utils.parse_query("&key&").should.equal "key" => nil Rack::Utils.parse_query(";key;", ";,").should.equal "key" => nil Rack::Utils.parse_query(",key,", ";,").should.equal "key" => nil Rack::Utils.parse_query(";foo=bar,;", ";,").should.equal "foo" => "bar" Rack::Utils.parse_query(",foo=bar;,", ";,").should.equal "foo" => "bar" end should "not create infinite loops with cycle structures" do ex = { "foo" => nil } ex["foo"] = ex params = Rack::Utils::KeySpaceConstrainedParams.new params['foo'] = params lambda { params.to_params_hash.to_s.should.equal ex.to_s }.should.not.raise end should "raise an exception if the params are too deep" do len = Rack::Utils.param_depth_limit lambda { Rack::Utils.parse_nested_query("foo#{"[a]" * len}=bar") }.should.raise(RangeError) lambda { Rack::Utils.parse_nested_query("foo#{"[a]" * (len - 1)}=bar") }.should.not.raise end should "parse nested query strings correctly" do Rack::Utils.parse_nested_query("foo"). should.equal "foo" => nil Rack::Utils.parse_nested_query("foo="). should.equal "foo" => "" Rack::Utils.parse_nested_query("foo=bar"). should.equal "foo" => "bar" Rack::Utils.parse_nested_query("foo=\"bar\""). should.equal "foo" => "\"bar\"" Rack::Utils.parse_nested_query("foo=bar&foo=quux"). should.equal "foo" => "quux" Rack::Utils.parse_nested_query("foo&foo="). should.equal "foo" => "" Rack::Utils.parse_nested_query("foo=1&bar=2"). should.equal "foo" => "1", "bar" => "2" Rack::Utils.parse_nested_query("&foo=1&&bar=2"). should.equal "foo" => "1", "bar" => "2" Rack::Utils.parse_nested_query("foo&bar="). should.equal "foo" => nil, "bar" => "" Rack::Utils.parse_nested_query("foo=bar&baz="). should.equal "foo" => "bar", "baz" => "" Rack::Utils.parse_nested_query("my+weird+field=q1%212%22%27w%245%267%2Fz8%29%3F"). should.equal "my weird field" => "q1!2\"'w$5&7/z8)?" Rack::Utils.parse_nested_query("a=b&pid%3D1234=1023"). should.equal "pid=1234" => "1023", "a" => "b" Rack::Utils.parse_nested_query("foo[]"). should.equal "foo" => [nil] Rack::Utils.parse_nested_query("foo[]="). should.equal "foo" => [""] Rack::Utils.parse_nested_query("foo[]=bar"). should.equal "foo" => ["bar"] Rack::Utils.parse_nested_query("foo[]=bar&foo"). should.equal "foo" => nil Rack::Utils.parse_nested_query("foo[]=bar&foo["). should.equal "foo" => ["bar"], "foo[" => nil Rack::Utils.parse_nested_query("foo[]=bar&foo[=baz"). should.equal "foo" => ["bar"], "foo[" => "baz" Rack::Utils.parse_nested_query("foo[]=bar&foo[]"). should.equal "foo" => ["bar", nil] Rack::Utils.parse_nested_query("foo[]=bar&foo[]="). should.equal "foo" => ["bar", ""] Rack::Utils.parse_nested_query("foo[]=1&foo[]=2"). should.equal "foo" => ["1", "2"] Rack::Utils.parse_nested_query("foo=bar&baz[]=1&baz[]=2&baz[]=3"). should.equal "foo" => "bar", "baz" => ["1", "2", "3"] Rack::Utils.parse_nested_query("foo[]=bar&baz[]=1&baz[]=2&baz[]=3"). should.equal "foo" => ["bar"], "baz" => ["1", "2", "3"] Rack::Utils.parse_nested_query("x[y][z]=1"). should.equal "x" => {"y" => {"z" => "1"}} Rack::Utils.parse_nested_query("x[y][z][]=1"). should.equal "x" => {"y" => {"z" => ["1"]}} Rack::Utils.parse_nested_query("x[y][z]=1&x[y][z]=2"). should.equal "x" => {"y" => {"z" => "2"}} Rack::Utils.parse_nested_query("x[y][z][]=1&x[y][z][]=2"). should.equal "x" => {"y" => {"z" => ["1", "2"]}} Rack::Utils.parse_nested_query("x[y][][z]=1"). should.equal "x" => {"y" => [{"z" => "1"}]} Rack::Utils.parse_nested_query("x[y][][z][]=1"). should.equal "x" => {"y" => [{"z" => ["1"]}]} Rack::Utils.parse_nested_query("x[y][][z]=1&x[y][][w]=2"). should.equal "x" => {"y" => [{"z" => "1", "w" => "2"}]} Rack::Utils.parse_nested_query("x[y][][v][w]=1"). should.equal "x" => {"y" => [{"v" => {"w" => "1"}}]} Rack::Utils.parse_nested_query("x[y][][z]=1&x[y][][v][w]=2"). should.equal "x" => {"y" => [{"z" => "1", "v" => {"w" => "2"}}]} Rack::Utils.parse_nested_query("x[y][][z]=1&x[y][][z]=2"). should.equal "x" => {"y" => [{"z" => "1"}, {"z" => "2"}]} Rack::Utils.parse_nested_query("x[y][][z]=1&x[y][][w]=a&x[y][][z]=2&x[y][][w]=3"). should.equal "x" => {"y" => [{"z" => "1", "w" => "a"}, {"z" => "2", "w" => "3"}]} lambda { Rack::Utils.parse_nested_query("x[y]=1&x[y]z=2") }. should.raise(Rack::Utils::ParameterTypeError). message.should.equal "expected Hash (got String) for param `y'" lambda { Rack::Utils.parse_nested_query("x[y]=1&x[]=1") }. should.raise(Rack::Utils::ParameterTypeError). message.should.match(/expected Array \(got [^)]*\) for param `x'/) lambda { Rack::Utils.parse_nested_query("x[y]=1&x[y][][w]=2") }. should.raise(Rack::Utils::ParameterTypeError). message.should.equal "expected Array (got String) for param `y'" if RUBY_VERSION.to_f > 1.9 lambda { Rack::Utils.parse_nested_query("foo%81E=1") }. should.raise(Rack::Utils::InvalidParameterError). message.should.equal "invalid byte sequence in UTF-8" end end should "build query strings correctly" do Rack::Utils.build_query("foo" => "bar").should.be equal_query_to("foo=bar") Rack::Utils.build_query("foo" => ["bar", "quux"]). should.be equal_query_to("foo=bar&foo=quux") Rack::Utils.build_query("foo" => "1", "bar" => "2"). should.be equal_query_to("foo=1&bar=2") Rack::Utils.build_query("my weird field" => "q1!2\"'w$5&7/z8)?"). should.be equal_query_to("my+weird+field=q1%212%22%27w%245%267%2Fz8%29%3F") end should "build nested query strings correctly" do Rack::Utils.build_nested_query("foo" => nil).should.equal "foo" Rack::Utils.build_nested_query("foo" => "").should.equal "foo=" Rack::Utils.build_nested_query("foo" => "bar").should.equal "foo=bar" Rack::Utils.build_nested_query("foo" => "1", "bar" => "2"). should.be equal_query_to("foo=1&bar=2") Rack::Utils.build_nested_query("foo" => 1, "bar" => 2). should.be equal_query_to("foo=1&bar=2") Rack::Utils.build_nested_query("my weird field" => "q1!2\"'w$5&7/z8)?"). should.be equal_query_to("my+weird+field=q1%212%22%27w%245%267%2Fz8%29%3F") Rack::Utils.build_nested_query("foo" => [nil]). should.equal "foo[]" Rack::Utils.build_nested_query("foo" => [""]). should.equal "foo[]=" Rack::Utils.build_nested_query("foo" => ["bar"]). should.equal "foo[]=bar" Rack::Utils.build_nested_query('foo' => []). should.equal '' Rack::Utils.build_nested_query('foo' => {}). should.equal '' Rack::Utils.build_nested_query('foo' => 'bar', 'baz' => []). should.equal 'foo=bar' Rack::Utils.build_nested_query('foo' => 'bar', 'baz' => {}). should.equal 'foo=bar' # The ordering of the output query string is unpredictable with 1.8's # unordered hash. Test that build_nested_query performs the inverse # function of parse_nested_query. [{"foo" => nil, "bar" => ""}, {"foo" => "bar", "baz" => ""}, {"foo" => ["1", "2"]}, {"foo" => "bar", "baz" => ["1", "2", "3"]}, {"foo" => ["bar"], "baz" => ["1", "2", "3"]}, {"foo" => ["1", "2"]}, {"foo" => "bar", "baz" => ["1", "2", "3"]}, {"x" => {"y" => {"z" => "1"}}}, {"x" => {"y" => {"z" => ["1"]}}}, {"x" => {"y" => {"z" => ["1", "2"]}}}, {"x" => {"y" => [{"z" => "1"}]}}, {"x" => {"y" => [{"z" => ["1"]}]}}, {"x" => {"y" => [{"z" => "1", "w" => "2"}]}}, {"x" => {"y" => [{"v" => {"w" => "1"}}]}}, {"x" => {"y" => [{"z" => "1", "v" => {"w" => "2"}}]}}, {"x" => {"y" => [{"z" => "1"}, {"z" => "2"}]}}, {"x" => {"y" => [{"z" => "1", "w" => "a"}, {"z" => "2", "w" => "3"}]}} ].each { |params| qs = Rack::Utils.build_nested_query(params) Rack::Utils.parse_nested_query(qs).should.equal params } lambda { Rack::Utils.build_nested_query("foo=bar") }. should.raise(ArgumentError). message.should.equal "value must be a Hash" end should "parse query strings that have a non-existent value" do key = "post/2011/08/27/Deux-%22rat%C3%A9s%22-de-l-Universit" Rack::Utils.parse_query(key).should.equal Rack::Utils.unescape(key) => nil end should "build query strings without = with non-existent values" do key = "post/2011/08/27/Deux-%22rat%C3%A9s%22-de-l-Universit" key = Rack::Utils.unescape(key) Rack::Utils.build_query(key => nil).should.equal Rack::Utils.escape(key) end should "parse q-values" do # XXX handle accept-extension Rack::Utils.q_values("foo;q=0.5,bar,baz;q=0.9").should.equal [ [ 'foo', 0.5 ], [ 'bar', 1.0 ], [ 'baz', 0.9 ] ] end should "select best quality match" do Rack::Utils.best_q_match("text/html", %w[text/html]).should.equal "text/html" # More specific matches are preferred Rack::Utils.best_q_match("text/*;q=0.5,text/html;q=1.0", %w[text/html]).should.equal "text/html" # Higher quality matches are preferred Rack::Utils.best_q_match("text/*;q=0.5,text/plain;q=1.0", %w[text/plain text/html]).should.equal "text/plain" # Respect requested content type Rack::Utils.best_q_match("application/json", %w[application/vnd.lotus-1-2-3 application/json]).should.equal "application/json" # All else equal, the available mimes are preferred in order Rack::Utils.best_q_match("text/*", %w[text/html text/plain]).should.equal "text/html" Rack::Utils.best_q_match("text/plain,text/html", %w[text/html text/plain]).should.equal "text/html" # When there are no matches, return nil: Rack::Utils.best_q_match("application/json", %w[text/html text/plain]).should.equal nil end should "escape html entities [&><'\"/]" do Rack::Utils.escape_html("foo").should.equal "foo" Rack::Utils.escape_html("f&o").should.equal "f&o" Rack::Utils.escape_html("fo").should.equal "f>o" Rack::Utils.escape_html("f'o").should.equal "f'o" Rack::Utils.escape_html('f"o').should.equal "f"o" Rack::Utils.escape_html("f/o").should.equal "f/o" Rack::Utils.escape_html("").should.equal "<foo></foo>" end should "escape html entities even on MRI when it's bugged" do test_escape = lambda do kcodeu do Rack::Utils.escape_html("\300<").should.equal "\300<" end end if RUBY_VERSION.to_f < 1.9 test_escape.call else test_escape.should.raise(ArgumentError) end end if "".respond_to?(:encode) should "escape html entities in unicode strings" do # the following will cause warnings if the regex is poorly encoded: Rack::Utils.escape_html("☃").should.equal "☃" end end should "figure out which encodings are acceptable" do helper = lambda do |a, b| Rack::Request.new(Rack::MockRequest.env_for("", "HTTP_ACCEPT_ENCODING" => a)) Rack::Utils.select_best_encoding(a, b) end helper.call(%w(), [["x", 1]]).should.equal(nil) helper.call(%w(identity), [["identity", 0.0]]).should.equal(nil) helper.call(%w(identity), [["*", 0.0]]).should.equal(nil) helper.call(%w(identity), [["compress", 1.0], ["gzip", 1.0]]).should.equal("identity") helper.call(%w(compress gzip identity), [["compress", 1.0], ["gzip", 1.0]]).should.equal("compress") helper.call(%w(compress gzip identity), [["compress", 0.5], ["gzip", 1.0]]).should.equal("gzip") helper.call(%w(foo bar identity), []).should.equal("identity") helper.call(%w(foo bar identity), [["*", 1.0]]).should.equal("foo") helper.call(%w(foo bar identity), [["*", 1.0], ["foo", 0.9]]).should.equal("bar") helper.call(%w(foo bar identity), [["foo", 0], ["bar", 0]]).should.equal("identity") helper.call(%w(foo bar baz identity), [["*", 0], ["identity", 0.1]]).should.equal("identity") end should "return the bytesize of String" do Rack::Utils.bytesize("FOO\xE2\x82\xAC").should.equal 6 end should "should perform constant time string comparison" do Rack::Utils.secure_compare('a', 'a').should.equal true Rack::Utils.secure_compare('a', 'b').should.equal false end should "return status code for integer" do Rack::Utils.status_code(200).should.equal 200 end should "return status code for string" do Rack::Utils.status_code("200").should.equal 200 end should "return status code for symbol" do Rack::Utils.status_code(:ok).should.equal 200 end should "return rfc2822 format from rfc2822 helper" do Rack::Utils.rfc2822(Time.at(0).gmtime).should == "Thu, 01 Jan 1970 00:00:00 -0000" end should "return rfc2109 format from rfc2109 helper" do Rack::Utils.rfc2109(Time.at(0).gmtime).should == "Thu, 01-Jan-1970 00:00:00 GMT" end should "clean directory traversal" do Rack::Utils.clean_path_info("/cgi/../cgi/test").should.equal "/cgi/test" Rack::Utils.clean_path_info(".").should.empty Rack::Utils.clean_path_info("test/..").should.empty end should "clean unsafe directory traversal to safe path" do Rack::Utils.clean_path_info("/../README.rdoc").should.equal "/README.rdoc" Rack::Utils.clean_path_info("../test/spec_utils.rb").should.equal "test/spec_utils.rb" end should "not clean directory traversal with encoded periods" do Rack::Utils.clean_path_info("/%2E%2E/README").should.equal "/%2E%2E/README" end should "clean slash only paths" do Rack::Utils.clean_path_info("/").should.equal "/" end end describe Rack::Utils, "byte_range" do should "ignore missing or syntactically invalid byte ranges" do Rack::Utils.byte_ranges({},500).should.equal nil Rack::Utils.byte_ranges({"HTTP_RANGE" => "foobar"},500).should.equal nil Rack::Utils.byte_ranges({"HTTP_RANGE" => "furlongs=123-456"},500).should.equal nil Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes="},500).should.equal nil Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=-"},500).should.equal nil Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=123,456"},500).should.equal nil # A range of non-positive length is syntactically invalid and ignored: Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=456-123"},500).should.equal nil Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=456-455"},500).should.equal nil end should "parse simple byte ranges" do Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=123-456"},500).should.equal [(123..456)] Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=123-"},500).should.equal [(123..499)] Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=-100"},500).should.equal [(400..499)] Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=0-0"},500).should.equal [(0..0)] Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=499-499"},500).should.equal [(499..499)] end should "parse several byte ranges" do Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=500-600,601-999"},1000).should.equal [(500..600),(601..999)] end should "truncate byte ranges" do Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=123-999"},500).should.equal [(123..499)] Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=600-999"},500).should.equal [] Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=-999"},500).should.equal [(0..499)] end should "ignore unsatisfiable byte ranges" do Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=500-501"},500).should.equal [] Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=500-"},500).should.equal [] Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=999-"},500).should.equal [] Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=-0"},500).should.equal [] end should "handle byte ranges of empty files" do Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=123-456"},0).should.equal [] Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=0-"},0).should.equal [] Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=-100"},0).should.equal [] Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=0-0"},0).should.equal [] Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=-0"},0).should.equal [] end end describe Rack::Utils::HeaderHash do should "retain header case" do h = Rack::Utils::HeaderHash.new("Content-MD5" => "d5ff4e2a0 ...") h['ETag'] = 'Boo!' h.to_hash.should.equal "Content-MD5" => "d5ff4e2a0 ...", "ETag" => 'Boo!' end should "check existence of keys case insensitively" do h = Rack::Utils::HeaderHash.new("Content-MD5" => "d5ff4e2a0 ...") h.should.include 'content-md5' h.should.not.include 'ETag' end should "merge case-insensitively" do h = Rack::Utils::HeaderHash.new("ETag" => 'HELLO', "content-length" => '123') merged = h.merge("Etag" => 'WORLD', 'Content-Length' => '321', "Foo" => 'BAR') merged.should.equal "Etag"=>'WORLD', "Content-Length"=>'321', "Foo"=>'BAR' end should "overwrite case insensitively and assume the new key's case" do h = Rack::Utils::HeaderHash.new("Foo-Bar" => "baz") h["foo-bar"] = "bizzle" h["FOO-BAR"].should.equal "bizzle" h.length.should.equal 1 h.to_hash.should.equal "foo-bar" => "bizzle" end should "be converted to real Hash" do h = Rack::Utils::HeaderHash.new("foo" => "bar") h.to_hash.should.be.instance_of Hash end should "convert Array values to Strings when converting to Hash" do h = Rack::Utils::HeaderHash.new("foo" => ["bar", "baz"]) h.to_hash.should.equal({ "foo" => "bar\nbaz" }) end should "replace hashes correctly" do h = Rack::Utils::HeaderHash.new("Foo-Bar" => "baz") j = {"foo" => "bar"} h.replace(j) h["foo"].should.equal "bar" end should "be able to delete the given key case-sensitively" do h = Rack::Utils::HeaderHash.new("foo" => "bar") h.delete("foo") h["foo"].should.be.nil h["FOO"].should.be.nil end should "be able to delete the given key case-insensitively" do h = Rack::Utils::HeaderHash.new("foo" => "bar") h.delete("FOO") h["foo"].should.be.nil h["FOO"].should.be.nil end should "return the deleted value when #delete is called on an existing key" do h = Rack::Utils::HeaderHash.new("foo" => "bar") h.delete("Foo").should.equal("bar") end should "return nil when #delete is called on a non-existant key" do h = Rack::Utils::HeaderHash.new("foo" => "bar") h.delete("Hello").should.be.nil end should "avoid unnecessary object creation if possible" do a = Rack::Utils::HeaderHash.new("foo" => "bar") b = Rack::Utils::HeaderHash.new(a) b.object_id.should.equal(a.object_id) b.should.equal(a) end should "convert Array values to Strings when responding to #each" do h = Rack::Utils::HeaderHash.new("foo" => ["bar", "baz"]) h.each do |k,v| k.should.equal("foo") v.should.equal("bar\nbaz") end end should "not create headers out of thin air" do h = Rack::Utils::HeaderHash.new h['foo'] h['foo'].should.be.nil h.should.not.include 'foo' end end describe Rack::Utils::Context do class ContextTest attr_reader :app def initialize app; @app=app; end def call env; context env; end def context env, app=@app; app.call(env); end end test_target1 = proc{|e| e.to_s+' world' } test_target2 = proc{|e| e.to_i+2 } test_target3 = proc{|e| nil } test_target4 = proc{|e| [200,{'Content-Type'=>'text/plain', 'Content-Length'=>'0'},['']] } test_app = ContextTest.new test_target4 should "set context correctly" do test_app.app.should.equal test_target4 c1 = Rack::Utils::Context.new(test_app, test_target1) c1.for.should.equal test_app c1.app.should.equal test_target1 c2 = Rack::Utils::Context.new(test_app, test_target2) c2.for.should.equal test_app c2.app.should.equal test_target2 end should "alter app on recontexting" do c1 = Rack::Utils::Context.new(test_app, test_target1) c2 = c1.recontext(test_target2) c2.for.should.equal test_app c2.app.should.equal test_target2 c3 = c2.recontext(test_target3) c3.for.should.equal test_app c3.app.should.equal test_target3 end should "run different apps" do c1 = Rack::Utils::Context.new test_app, test_target1 c2 = c1.recontext test_target2 c3 = c2.recontext test_target3 c4 = c3.recontext test_target4 a4 = Rack::Lint.new c4 a5 = Rack::Lint.new test_app r1 = c1.call('hello') r1.should.equal 'hello world' r2 = c2.call(2) r2.should.equal 4 r3 = c3.call(:misc_symbol) r3.should.be.nil r4 = Rack::MockRequest.new(a4).get('/') r4.status.should.equal 200 r5 = Rack::MockRequest.new(a5).get('/') r5.status.should.equal 200 r4.body.should.equal r5.body end end PK! kLLL,gems/2.2.0/gems/rack-1.6.4/test/spec_lint.rbnu[require 'stringio' require 'tempfile' require 'rack/lint' require 'rack/mock' describe Rack::Lint do def env(*args) Rack::MockRequest.env_for("/", *args) end should "pass valid request" do lambda { Rack::Lint.new(lambda { |env| [200, {"Content-type" => "test/plain", "Content-length" => "3"}, ["foo"]] }).call(env({})) }.should.not.raise end should "notice fatal errors" do lambda { Rack::Lint.new(nil).call }.should.raise(Rack::Lint::LintError). message.should.match(/No env given/) end should "notice environment errors" do lambda { Rack::Lint.new(nil).call 5 }.should.raise(Rack::Lint::LintError). message.should.match(/not a Hash/) lambda { e = env e.delete("REQUEST_METHOD") Rack::Lint.new(nil).call(e) }.should.raise(Rack::Lint::LintError). message.should.match(/missing required key REQUEST_METHOD/) lambda { e = env e.delete("SERVER_NAME") Rack::Lint.new(nil).call(e) }.should.raise(Rack::Lint::LintError). message.should.match(/missing required key SERVER_NAME/) lambda { Rack::Lint.new(nil).call(env("HTTP_CONTENT_TYPE" => "text/plain")) }.should.raise(Rack::Lint::LintError). message.should.match(/contains HTTP_CONTENT_TYPE/) lambda { Rack::Lint.new(nil).call(env("HTTP_CONTENT_LENGTH" => "42")) }.should.raise(Rack::Lint::LintError). message.should.match(/contains HTTP_CONTENT_LENGTH/) lambda { Rack::Lint.new(nil).call(env("FOO" => Object.new)) }.should.raise(Rack::Lint::LintError). message.should.match(/non-string value/) lambda { Rack::Lint.new(nil).call(env("rack.version" => "0.2")) }.should.raise(Rack::Lint::LintError). message.should.match(/must be an Array/) lambda { Rack::Lint.new(nil).call(env("rack.url_scheme" => "gopher")) }.should.raise(Rack::Lint::LintError). message.should.match(/url_scheme unknown/) lambda { Rack::Lint.new(nil).call(env("rack.session" => [])) }.should.raise(Rack::Lint::LintError). message.should.equal("session [] must respond to store and []=") lambda { Rack::Lint.new(nil).call(env("rack.logger" => [])) }.should.raise(Rack::Lint::LintError). message.should.equal("logger [] must respond to info") lambda { Rack::Lint.new(nil).call(env("rack.multipart.buffer_size" => 0)) }.should.raise(Rack::Lint::LintError). message.should.equal("rack.multipart.buffer_size must be an Integer > 0 if specified") lambda { Rack::Lint.new(nil).call(env("rack.multipart.tempfile_factory" => Tempfile)) }.should.raise(Rack::Lint::LintError). message.should.equal("rack.multipart.tempfile_factory must respond to #call") lambda { Rack::Lint.new(lambda { |env| env['rack.multipart.tempfile_factory'].call("testfile", "text/plain") }).call(env("rack.multipart.tempfile_factory" => lambda { |filename, content_type| Object.new })) }.should.raise(Rack::Lint::LintError). message.should.equal("rack.multipart.tempfile_factory return value must respond to #<<") lambda { Rack::Lint.new(nil).call(env("REQUEST_METHOD" => "FUCKUP?")) }.should.raise(Rack::Lint::LintError). message.should.match(/REQUEST_METHOD/) lambda { Rack::Lint.new(nil).call(env("SCRIPT_NAME" => "howdy")) }.should.raise(Rack::Lint::LintError). message.should.match(/must start with/) lambda { Rack::Lint.new(nil).call(env("PATH_INFO" => "../foo")) }.should.raise(Rack::Lint::LintError). message.should.match(/must start with/) lambda { Rack::Lint.new(nil).call(env("CONTENT_LENGTH" => "xcii")) }.should.raise(Rack::Lint::LintError). message.should.match(/Invalid CONTENT_LENGTH/) lambda { e = env e.delete("PATH_INFO") e.delete("SCRIPT_NAME") Rack::Lint.new(nil).call(e) }.should.raise(Rack::Lint::LintError). message.should.match(/One of .* must be set/) lambda { Rack::Lint.new(nil).call(env("SCRIPT_NAME" => "/")) }.should.raise(Rack::Lint::LintError). message.should.match(/cannot be .* make it ''/) end should "notice input errors" do lambda { Rack::Lint.new(nil).call(env("rack.input" => "")) }.should.raise(Rack::Lint::LintError). message.should.match(/does not respond to #gets/) lambda { input = Object.new def input.binmode? false end Rack::Lint.new(nil).call(env("rack.input" => input)) }.should.raise(Rack::Lint::LintError). message.should.match(/is not opened in binary mode/) lambda { input = Object.new def input.external_encoding result = Object.new def result.name "US-ASCII" end result end Rack::Lint.new(nil).call(env("rack.input" => input)) }.should.raise(Rack::Lint::LintError). message.should.match(/does not have ASCII-8BIT as its external encoding/) end should "notice error errors" do lambda { Rack::Lint.new(nil).call(env("rack.errors" => "")) }.should.raise(Rack::Lint::LintError). message.should.match(/does not respond to #puts/) end should "notice status errors" do lambda { Rack::Lint.new(lambda { |env| ["cc", {}, ""] }).call(env({})) }.should.raise(Rack::Lint::LintError). message.should.match(/must be >=100 seen as integer/) lambda { Rack::Lint.new(lambda { |env| [42, {}, ""] }).call(env({})) }.should.raise(Rack::Lint::LintError). message.should.match(/must be >=100 seen as integer/) end should "notice header errors" do lambda { Rack::Lint.new(lambda { |env| [200, Object.new, []] }).call(env({})) }.should.raise(Rack::Lint::LintError). message.should.equal("headers object should respond to #each, but doesn't (got Object as headers)") lambda { Rack::Lint.new(lambda { |env| [200, {true=>false}, []] }).call(env({})) }.should.raise(Rack::Lint::LintError). message.should.equal("header key must be a string, was TrueClass") lambda { Rack::Lint.new(lambda { |env| [200, {"Status" => "404"}, []] }).call(env({})) }.should.raise(Rack::Lint::LintError). message.should.match(/must not contain Status/) # From RFC 7230: # Most HTTP header field values are defined using common syntax # components (token, quoted-string, and comment) separated by # whitespace or specific delimiting characters. Delimiters are chosen # from the set of US-ASCII visual characters not allowed in a token # (DQUOTE and "(),/:;<=>?@[\]{}"). # # token = 1*tchar # # tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" # / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~" # / DIGIT / ALPHA # ; any VCHAR, except delimiters invalid_headers = 0.upto(31).map(&:chr) + %W<( ) , / : ; < = > ? @ [ \\ ] { } \x7F> invalid_headers.each do |invalid_header| lambda { Rack::Lint.new(lambda { |env| [200, {invalid_header => "text/plain"}, []] }).call(env({})) }.should.raise(Rack::Lint::LintError, "on invalid header: #{invalid_header}"). message.should.equal("invalid header name: #{invalid_header}") end valid_headers = 0.upto(127).map(&:chr) - invalid_headers valid_headers.each do |valid_header| lambda { Rack::Lint.new(lambda { |env| [200, {valid_header => "text/plain"}, []] }).call(env({})) }.should.not.raise(Rack::Lint::LintError, "on valid header: #{valid_header}") end lambda { Rack::Lint.new(lambda { |env| [200, {"Foo" => Object.new}, []] }).call(env({})) }.should.raise(Rack::Lint::LintError). message.should.equal("a header value must be a String, but the value of 'Foo' is a Object") lambda { Rack::Lint.new(lambda { |env| [200, {"Foo" => [1, 2, 3]}, []] }).call(env({})) }.should.raise(Rack::Lint::LintError). message.should.equal("a header value must be a String, but the value of 'Foo' is a Array") lambda { Rack::Lint.new(lambda { |env| [200, {"Foo-Bar" => "text\000plain"}, []] }).call(env({})) }.should.raise(Rack::Lint::LintError). message.should.match(/invalid header/) # line ends (010) should be allowed in header values. lambda { Rack::Lint.new(lambda { |env| [200, {"Foo-Bar" => "one\ntwo\nthree", "Content-Length" => "0", "Content-Type" => "text/plain" }, []] }).call(env({})) }.should.not.raise(Rack::Lint::LintError) # non-Hash header responses should be allowed lambda { Rack::Lint.new(lambda { |env| [200, [%w(Content-Type text/plain), %w(Content-Length 0)], []] }).call(env({})) }.should.not.raise(TypeError) end should "notice content-type errors" do # lambda { # Rack::Lint.new(lambda { |env| # [200, {"Content-length" => "0"}, []] # }).call(env({})) # }.should.raise(Rack::Lint::LintError). # message.should.match(/No Content-Type/) [100, 101, 204, 205, 304].each do |status| lambda { Rack::Lint.new(lambda { |env| [status, {"Content-type" => "text/plain", "Content-length" => "0"}, []] }).call(env({})) }.should.raise(Rack::Lint::LintError). message.should.match(/Content-Type header found/) end end should "notice content-length errors" do [100, 101, 204, 205, 304].each do |status| lambda { Rack::Lint.new(lambda { |env| [status, {"Content-length" => "0"}, []] }).call(env({})) }.should.raise(Rack::Lint::LintError). message.should.match(/Content-Length header found/) end lambda { Rack::Lint.new(lambda { |env| [200, {"Content-type" => "text/plain", "Content-Length" => "1"}, []] }).call(env({}))[2].each { } }.should.raise(Rack::Lint::LintError). message.should.match(/Content-Length header was 1, but should be 0/) end should "notice body errors" do lambda { body = Rack::Lint.new(lambda { |env| [200, {"Content-type" => "text/plain","Content-length" => "3"}, [1,2,3]] }).call(env({}))[2] body.each { |part| } }.should.raise(Rack::Lint::LintError). message.should.match(/yielded non-string/) end should "notice input handling errors" do lambda { Rack::Lint.new(lambda { |env| env["rack.input"].gets("\r\n") [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []] }).call(env({})) }.should.raise(Rack::Lint::LintError). message.should.match(/gets called with arguments/) lambda { Rack::Lint.new(lambda { |env| env["rack.input"].read(1, 2, 3) [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []] }).call(env({})) }.should.raise(Rack::Lint::LintError). message.should.match(/read called with too many arguments/) lambda { Rack::Lint.new(lambda { |env| env["rack.input"].read("foo") [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []] }).call(env({})) }.should.raise(Rack::Lint::LintError). message.should.match(/read called with non-integer and non-nil length/) lambda { Rack::Lint.new(lambda { |env| env["rack.input"].read(-1) [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []] }).call(env({})) }.should.raise(Rack::Lint::LintError). message.should.match(/read called with a negative length/) lambda { Rack::Lint.new(lambda { |env| env["rack.input"].read(nil, nil) [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []] }).call(env({})) }.should.raise(Rack::Lint::LintError). message.should.match(/read called with non-String buffer/) lambda { Rack::Lint.new(lambda { |env| env["rack.input"].read(nil, 1) [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []] }).call(env({})) }.should.raise(Rack::Lint::LintError). message.should.match(/read called with non-String buffer/) lambda { Rack::Lint.new(lambda { |env| env["rack.input"].rewind(0) [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []] }).call(env({})) }.should.raise(Rack::Lint::LintError). message.should.match(/rewind called with arguments/) weirdio = Object.new class << weirdio def gets 42 end def read 23 end def each yield 23 yield 42 end def rewind raise Errno::ESPIPE, "Errno::ESPIPE" end end eof_weirdio = Object.new class << eof_weirdio def gets nil end def read(*args) nil end def each end def rewind end end lambda { Rack::Lint.new(lambda { |env| env["rack.input"].gets [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []] }).call(env("rack.input" => weirdio)) }.should.raise(Rack::Lint::LintError). message.should.match(/gets didn't return a String/) lambda { Rack::Lint.new(lambda { |env| env["rack.input"].each { |x| } [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []] }).call(env("rack.input" => weirdio)) }.should.raise(Rack::Lint::LintError). message.should.match(/each didn't yield a String/) lambda { Rack::Lint.new(lambda { |env| env["rack.input"].read [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []] }).call(env("rack.input" => weirdio)) }.should.raise(Rack::Lint::LintError). message.should.match(/read didn't return nil or a String/) lambda { Rack::Lint.new(lambda { |env| env["rack.input"].read [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []] }).call(env("rack.input" => eof_weirdio)) }.should.raise(Rack::Lint::LintError). message.should.match(/read\(nil\) returned nil on EOF/) lambda { Rack::Lint.new(lambda { |env| env["rack.input"].rewind [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []] }).call(env("rack.input" => weirdio)) }.should.raise(Rack::Lint::LintError). message.should.match(/rewind raised Errno::ESPIPE/) lambda { Rack::Lint.new(lambda { |env| env["rack.input"].close [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []] }).call(env({})) }.should.raise(Rack::Lint::LintError). message.should.match(/close must not be called/) end should "notice error handling errors" do lambda { Rack::Lint.new(lambda { |env| env["rack.errors"].write(42) [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []] }).call(env({})) }.should.raise(Rack::Lint::LintError). message.should.match(/write not called with a String/) lambda { Rack::Lint.new(lambda { |env| env["rack.errors"].close [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []] }).call(env({})) }.should.raise(Rack::Lint::LintError). message.should.match(/close must not be called/) end should "notice HEAD errors" do lambda { Rack::Lint.new(lambda { |env| [200, {"Content-type" => "test/plain", "Content-length" => "3"}, []] }).call(env({"REQUEST_METHOD" => "HEAD"})) }.should.not.raise lambda { Rack::Lint.new(lambda { |env| [200, {"Content-type" => "test/plain", "Content-length" => "3"}, ["foo"]] }).call(env({"REQUEST_METHOD" => "HEAD"}))[2].each { } }.should.raise(Rack::Lint::LintError). message.should.match(/body was given for HEAD/) end should "pass valid read calls" do hello_str = "hello world" hello_str.force_encoding("ASCII-8BIT") if hello_str.respond_to? :force_encoding lambda { Rack::Lint.new(lambda { |env| env["rack.input"].read [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []] }).call(env({"rack.input" => StringIO.new(hello_str)})) }.should.not.raise(Rack::Lint::LintError) lambda { Rack::Lint.new(lambda { |env| env["rack.input"].read(0) [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []] }).call(env({"rack.input" => StringIO.new(hello_str)})) }.should.not.raise(Rack::Lint::LintError) lambda { Rack::Lint.new(lambda { |env| env["rack.input"].read(1) [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []] }).call(env({"rack.input" => StringIO.new(hello_str)})) }.should.not.raise(Rack::Lint::LintError) lambda { Rack::Lint.new(lambda { |env| env["rack.input"].read(nil) [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []] }).call(env({"rack.input" => StringIO.new(hello_str)})) }.should.not.raise(Rack::Lint::LintError) lambda { Rack::Lint.new(lambda { |env| env["rack.input"].read(nil, '') [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []] }).call(env({"rack.input" => StringIO.new(hello_str)})) }.should.not.raise(Rack::Lint::LintError) lambda { Rack::Lint.new(lambda { |env| env["rack.input"].read(1, '') [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []] }).call(env({"rack.input" => StringIO.new(hello_str)})) }.should.not.raise(Rack::Lint::LintError) end end describe "Rack::Lint::InputWrapper" do should "delegate :rewind to underlying IO object" do io = StringIO.new("123") wrapper = Rack::Lint::InputWrapper.new(io) wrapper.read.should.equal "123" wrapper.read.should.equal "" wrapper.rewind wrapper.read.should.equal "123" end end PK!pe 6gems/2.2.0/gems/rack-1.6.4/test/spec_conditionalget.rbnu[require 'time' require 'rack/conditionalget' require 'rack/mock' describe Rack::ConditionalGet do def conditional_get(app) Rack::Lint.new Rack::ConditionalGet.new(app) end should "set a 304 status and truncate body when If-Modified-Since hits" do timestamp = Time.now.httpdate app = conditional_get(lambda { |env| [200, {'Last-Modified'=>timestamp}, ['TEST']] }) response = Rack::MockRequest.new(app). get("/", 'HTTP_IF_MODIFIED_SINCE' => timestamp) response.status.should.equal 304 response.body.should.be.empty end should "set a 304 status and truncate body when If-Modified-Since hits and is higher than current time" do app = conditional_get(lambda { |env| [200, {'Last-Modified'=>(Time.now - 3600).httpdate}, ['TEST']] }) response = Rack::MockRequest.new(app). get("/", 'HTTP_IF_MODIFIED_SINCE' => Time.now.httpdate) response.status.should.equal 304 response.body.should.be.empty end should "set a 304 status and truncate body when If-None-Match hits" do app = conditional_get(lambda { |env| [200, {'Etag'=>'1234'}, ['TEST']] }) response = Rack::MockRequest.new(app). get("/", 'HTTP_IF_NONE_MATCH' => '1234') response.status.should.equal 304 response.body.should.be.empty end should "not set a 304 status if If-Modified-Since hits but Etag does not" do timestamp = Time.now.httpdate app = conditional_get(lambda { |env| [200, {'Last-Modified'=>timestamp, 'Etag'=>'1234', 'Content-Type' => 'text/plain'}, ['TEST']] }) response = Rack::MockRequest.new(app). get("/", 'HTTP_IF_MODIFIED_SINCE' => timestamp, 'HTTP_IF_NONE_MATCH' => '4321') response.status.should.equal 200 response.body.should.equal 'TEST' end should "set a 304 status and truncate body when both If-None-Match and If-Modified-Since hits" do timestamp = Time.now.httpdate app = conditional_get(lambda { |env| [200, {'Last-Modified'=>timestamp, 'Etag'=>'1234'}, ['TEST']] }) response = Rack::MockRequest.new(app). get("/", 'HTTP_IF_MODIFIED_SINCE' => timestamp, 'HTTP_IF_NONE_MATCH' => '1234') response.status.should.equal 304 response.body.should.be.empty end should "not affect non-GET/HEAD requests" do app = conditional_get(lambda { |env| [200, {'Etag'=>'1234', 'Content-Type' => 'text/plain'}, ['TEST']] }) response = Rack::MockRequest.new(app). post("/", 'HTTP_IF_NONE_MATCH' => '1234') response.status.should.equal 200 response.body.should.equal 'TEST' end should "not affect non-200 requests" do app = conditional_get(lambda { |env| [302, {'Etag'=>'1234', 'Content-Type' => 'text/plain'}, ['TEST']] }) response = Rack::MockRequest.new(app). get("/", 'HTTP_IF_NONE_MATCH' => '1234') response.status.should.equal 302 response.body.should.equal 'TEST' end should "not affect requests with malformed HTTP_IF_NONE_MATCH" do bad_timestamp = Time.now.strftime('%Y-%m-%d %H:%M:%S %z') app = conditional_get(lambda { |env| [200,{'Last-Modified'=>(Time.now - 3600).httpdate, 'Content-Type' => 'text/plain'}, ['TEST']] }) response = Rack::MockRequest.new(app). get("/", 'HTTP_IF_MODIFIED_SINCE' => bad_timestamp) response.status.should.equal 200 response.body.should.equal 'TEST' end end PK!Vgems/2.2.0/gems/rack-1.6.4/test/registering_handler/rack/handler/registering_myself.rbnu[module Rack module Handler class RegisteringMyself end register :registering_myself, RegisteringMyself end endPK!晟\/gems/2.2.0/gems/rack-1.6.4/test/spec_lobster.rbnu[require 'rack/lobster' require 'rack/lint' require 'rack/mock' module LobsterHelpers def lobster Rack::MockRequest.new Rack::Lint.new(Rack::Lobster.new) end def lambda_lobster Rack::MockRequest.new Rack::Lint.new(Rack::Lobster::LambdaLobster) end end describe Rack::Lobster::LambdaLobster do extend LobsterHelpers should "be a single lambda" do Rack::Lobster::LambdaLobster.should.be.kind_of Proc end should "look like a lobster" do res = lambda_lobster.get("/") res.should.be.ok res.body.should.include "(,(,,(,,,(" res.body.should.include "?flip" end should "be flippable" do res = lambda_lobster.get("/?flip") res.should.be.ok res.body.should.include "(,,,(,,(,(" end end describe Rack::Lobster do extend LobsterHelpers should "look like a lobster" do res = lobster.get("/") res.should.be.ok res.body.should.include "(,(,,(,,,(" res.body.should.include "?flip" res.body.should.include "crash" end should "be flippable" do res = lobster.get("/?flip=left") res.should.be.ok res.body.should.include "),,,),,),)" end should "provide crashing for testing purposes" do lambda { lobster.get("/?flip=crash") }.should.raise end end PK!ۂ&PP1gems/2.2.0/gems/rack-1.6.4/test/spec_recursive.rbnu[require 'rack/lint' require 'rack/recursive' require 'rack/mock' describe Rack::Recursive do @app1 = lambda { |env| res = Rack::Response.new res["X-Path-Info"] = env["PATH_INFO"] res["X-Query-String"] = env["QUERY_STRING"] res.finish do |inner_res| inner_res.write "App1" end } @app2 = lambda { |env| Rack::Response.new.finish do |res| res.write "App2" _, _, body = env['rack.recursive.include'].call(env, "/app1") body.each { |b| res.write b } end } @app3 = lambda { |env| raise Rack::ForwardRequest.new("/app1") } @app4 = lambda { |env| raise Rack::ForwardRequest.new("http://example.org/app1/quux?meh") } def recursive(map) Rack::Lint.new Rack::Recursive.new(Rack::URLMap.new(map)) end should "allow for subrequests" do res = Rack::MockRequest.new(recursive("/app1" => @app1, "/app2" => @app2)). get("/app2") res.should.be.ok res.body.should.equal "App2App1" end should "raise error on requests not below the app" do app = Rack::URLMap.new("/app1" => @app1, "/app" => recursive("/1" => @app1, "/2" => @app2)) lambda { Rack::MockRequest.new(app).get("/app/2") }.should.raise(ArgumentError). message.should =~ /can only include below/ end should "support forwarding" do app = recursive("/app1" => @app1, "/app3" => @app3, "/app4" => @app4) res = Rack::MockRequest.new(app).get("/app3") res.should.be.ok res.body.should.equal "App1" res = Rack::MockRequest.new(app).get("/app4") res.should.be.ok res.body.should.equal "App1" res["X-Path-Info"].should.equal "/quux" res["X-Query-String"].should.equal "meh" end end PK!sXw,w,8gems/2.2.0/gems/rack-1.6.4/test/spec_session_memcache.rbnu[begin require 'rack/session/memcache' require 'rack/lint' require 'rack/mock' require 'thread' describe Rack::Session::Memcache do session_key = Rack::Session::Memcache::DEFAULT_OPTIONS[:key] session_match = /#{session_key}=([0-9a-fA-F]+);/ incrementor = lambda do |env| env["rack.session"]["counter"] ||= 0 env["rack.session"]["counter"] += 1 Rack::Response.new(env["rack.session"].inspect).to_a end drop_session = Rack::Lint.new(proc do |env| env['rack.session.options'][:drop] = true incrementor.call(env) end) renew_session = Rack::Lint.new(proc do |env| env['rack.session.options'][:renew] = true incrementor.call(env) end) defer_session = Rack::Lint.new(proc do |env| env['rack.session.options'][:defer] = true incrementor.call(env) end) skip_session = Rack::Lint.new(proc do |env| env['rack.session.options'][:skip] = true incrementor.call(env) end) incrementor = Rack::Lint.new(incrementor) # test memcache connection Rack::Session::Memcache.new(incrementor) it "faults on no connection" do lambda{ Rack::Session::Memcache.new(incrementor, :memcache_server => 'nosuchserver') }.should.raise end it "connects to existing server" do test_pool = MemCache.new(incrementor, :namespace => 'test:rack:session') test_pool.namespace.should.equal 'test:rack:session' end it "passes options to MemCache" do pool = Rack::Session::Memcache.new(incrementor, :namespace => 'test:rack:session') pool.pool.namespace.should.equal 'test:rack:session' end it "creates a new cookie" do pool = Rack::Session::Memcache.new(incrementor) res = Rack::MockRequest.new(pool).get("/") res["Set-Cookie"].should.include("#{session_key}=") res.body.should.equal '{"counter"=>1}' end it "determines session from a cookie" do pool = Rack::Session::Memcache.new(incrementor) req = Rack::MockRequest.new(pool) res = req.get("/") cookie = res["Set-Cookie"] req.get("/", "HTTP_COOKIE" => cookie). body.should.equal '{"counter"=>2}' req.get("/", "HTTP_COOKIE" => cookie). body.should.equal '{"counter"=>3}' end it "determines session only from a cookie by default" do pool = Rack::Session::Memcache.new(incrementor) req = Rack::MockRequest.new(pool) res = req.get("/") sid = res["Set-Cookie"][session_match, 1] req.get("/?rack.session=#{sid}"). body.should.equal '{"counter"=>1}' req.get("/?rack.session=#{sid}"). body.should.equal '{"counter"=>1}' end it "determines session from params" do pool = Rack::Session::Memcache.new(incrementor, :cookie_only => false) req = Rack::MockRequest.new(pool) res = req.get("/") sid = res["Set-Cookie"][session_match, 1] req.get("/?rack.session=#{sid}"). body.should.equal '{"counter"=>2}' req.get("/?rack.session=#{sid}"). body.should.equal '{"counter"=>3}' end it "survives nonexistant cookies" do bad_cookie = "rack.session=blarghfasel" pool = Rack::Session::Memcache.new(incrementor) res = Rack::MockRequest.new(pool). get("/", "HTTP_COOKIE" => bad_cookie) res.body.should.equal '{"counter"=>1}' cookie = res["Set-Cookie"][session_match] cookie.should.not.match(/#{bad_cookie}/) end it "maintains freshness" do pool = Rack::Session::Memcache.new(incrementor, :expire_after => 3) res = Rack::MockRequest.new(pool).get('/') res.body.should.include '"counter"=>1' cookie = res["Set-Cookie"] res = Rack::MockRequest.new(pool).get('/', "HTTP_COOKIE" => cookie) res["Set-Cookie"].should.equal cookie res.body.should.include '"counter"=>2' puts 'Sleeping to expire session' if $DEBUG sleep 4 res = Rack::MockRequest.new(pool).get('/', "HTTP_COOKIE" => cookie) res["Set-Cookie"].should.not.equal cookie res.body.should.include '"counter"=>1' end it "does not send the same session id if it did not change" do pool = Rack::Session::Memcache.new(incrementor) req = Rack::MockRequest.new(pool) res0 = req.get("/") cookie = res0["Set-Cookie"][session_match] res0.body.should.equal '{"counter"=>1}' res1 = req.get("/", "HTTP_COOKIE" => cookie) res1["Set-Cookie"].should.be.nil res1.body.should.equal '{"counter"=>2}' res2 = req.get("/", "HTTP_COOKIE" => cookie) res2["Set-Cookie"].should.be.nil res2.body.should.equal '{"counter"=>3}' end it "deletes cookies with :drop option" do pool = Rack::Session::Memcache.new(incrementor) req = Rack::MockRequest.new(pool) drop = Rack::Utils::Context.new(pool, drop_session) dreq = Rack::MockRequest.new(drop) res1 = req.get("/") session = (cookie = res1["Set-Cookie"])[session_match] res1.body.should.equal '{"counter"=>1}' res2 = dreq.get("/", "HTTP_COOKIE" => cookie) res2["Set-Cookie"].should.equal nil res2.body.should.equal '{"counter"=>2}' res3 = req.get("/", "HTTP_COOKIE" => cookie) res3["Set-Cookie"][session_match].should.not.equal session res3.body.should.equal '{"counter"=>1}' end it "provides new session id with :renew option" do pool = Rack::Session::Memcache.new(incrementor) req = Rack::MockRequest.new(pool) renew = Rack::Utils::Context.new(pool, renew_session) rreq = Rack::MockRequest.new(renew) res1 = req.get("/") session = (cookie = res1["Set-Cookie"])[session_match] res1.body.should.equal '{"counter"=>1}' res2 = rreq.get("/", "HTTP_COOKIE" => cookie) new_cookie = res2["Set-Cookie"] new_session = new_cookie[session_match] new_session.should.not.equal session res2.body.should.equal '{"counter"=>2}' res3 = req.get("/", "HTTP_COOKIE" => new_cookie) res3.body.should.equal '{"counter"=>3}' # Old cookie was deleted res4 = req.get("/", "HTTP_COOKIE" => cookie) res4.body.should.equal '{"counter"=>1}' end it "omits cookie with :defer option but still updates the state" do pool = Rack::Session::Memcache.new(incrementor) count = Rack::Utils::Context.new(pool, incrementor) defer = Rack::Utils::Context.new(pool, defer_session) dreq = Rack::MockRequest.new(defer) creq = Rack::MockRequest.new(count) res0 = dreq.get("/") res0["Set-Cookie"].should.equal nil res0.body.should.equal '{"counter"=>1}' res0 = creq.get("/") res1 = dreq.get("/", "HTTP_COOKIE" => res0["Set-Cookie"]) res1.body.should.equal '{"counter"=>2}' res2 = dreq.get("/", "HTTP_COOKIE" => res0["Set-Cookie"]) res2.body.should.equal '{"counter"=>3}' end it "omits cookie and state update with :skip option" do pool = Rack::Session::Memcache.new(incrementor) count = Rack::Utils::Context.new(pool, incrementor) skip = Rack::Utils::Context.new(pool, skip_session) sreq = Rack::MockRequest.new(skip) creq = Rack::MockRequest.new(count) res0 = sreq.get("/") res0["Set-Cookie"].should.equal nil res0.body.should.equal '{"counter"=>1}' res0 = creq.get("/") res1 = sreq.get("/", "HTTP_COOKIE" => res0["Set-Cookie"]) res1.body.should.equal '{"counter"=>2}' res2 = sreq.get("/", "HTTP_COOKIE" => res0["Set-Cookie"]) res2.body.should.equal '{"counter"=>2}' end it "updates deep hashes correctly" do hash_check = proc do |env| session = env['rack.session'] unless session.include? 'test' session.update :a => :b, :c => { :d => :e }, :f => { :g => { :h => :i} }, 'test' => true else session[:f][:g][:h] = :j end [200, {}, [session.inspect]] end pool = Rack::Session::Memcache.new(hash_check) req = Rack::MockRequest.new(pool) res0 = req.get("/") session_id = (cookie = res0["Set-Cookie"])[session_match, 1] ses0 = pool.pool.get(session_id, true) req.get("/", "HTTP_COOKIE" => cookie) ses1 = pool.pool.get(session_id, true) ses1.should.not.equal ses0 end # anyone know how to do this better? it "cleanly merges sessions when multithreaded" do unless $DEBUG 1.should.equal 1 # fake assertion to appease the mighty bacon next end warn 'Running multithread test for Session::Memcache' pool = Rack::Session::Memcache.new(incrementor) req = Rack::MockRequest.new(pool) res = req.get('/') res.body.should.equal '{"counter"=>1}' cookie = res["Set-Cookie"] session_id = cookie[session_match, 1] delta_incrementor = lambda do |env| # emulate disconjoinment of threading env['rack.session'] = env['rack.session'].dup Thread.stop env['rack.session'][(Time.now.usec*rand).to_i] = true incrementor.call(env) end tses = Rack::Utils::Context.new pool, delta_incrementor treq = Rack::MockRequest.new(tses) tnum = rand(7).to_i+5 r = Array.new(tnum) do Thread.new(treq) do |run| run.get('/', "HTTP_COOKIE" => cookie, 'rack.multithread' => true) end end.reverse.map{|t| t.run.join.value } r.each do |request| request['Set-Cookie'].should.equal cookie request.body.should.include '"counter"=>2' end session = pool.pool.get(session_id) session.size.should.equal tnum+1 # counter session['counter'].should.equal 2 # meeeh tnum = rand(7).to_i+5 r = Array.new(tnum) do app = Rack::Utils::Context.new pool, time_delta req = Rack::MockRequest.new app Thread.new(req) do |run| run.get('/', "HTTP_COOKIE" => cookie, 'rack.multithread' => true) end end.reverse.map{|t| t.run.join.value } r.each do |request| request['Set-Cookie'].should.equal cookie request.body.should.include '"counter"=>3' end session = pool.pool.get(session_id) session.size.should.be tnum+1 session['counter'].should.be 3 drop_counter = proc do |env| env['rack.session'].delete 'counter' env['rack.session']['foo'] = 'bar' [200, {'Content-Type'=>'text/plain'}, env['rack.session'].inspect] end tses = Rack::Utils::Context.new pool, drop_counter treq = Rack::MockRequest.new(tses) tnum = rand(7).to_i+5 r = Array.new(tnum) do Thread.new(treq) do |run| run.get('/', "HTTP_COOKIE" => cookie, 'rack.multithread' => true) end end.reverse.map{|t| t.run.join.value } r.each do |request| request['Set-Cookie'].should.equal cookie request.body.should.include '"foo"=>"bar"' end session = pool.pool.get(session_id) session.size.should.be r.size+1 session['counter'].should.be.nil? session['foo'].should.equal 'bar' end end rescue RuntimeError $stderr.puts "Skipping Rack::Session::Memcache tests. Start memcached and try again." rescue LoadError $stderr.puts "Skipping Rack::Session::Memcache tests (Memcache is required). `gem install memcache-client` and try again." end PK!^jII,gems/2.2.0/gems/rack-1.6.4/test/spec_file.rbnu[require 'rack/file' require 'rack/lint' require 'rack/mock' describe Rack::File do DOCROOT = File.expand_path(File.dirname(__FILE__)) unless defined? DOCROOT def file(*args) Rack::Lint.new Rack::File.new(*args) end should "serve files" do res = Rack::MockRequest.new(file(DOCROOT)).get("/cgi/test") res.should.be.ok res.should =~ /ruby/ end should "set Last-Modified header" do res = Rack::MockRequest.new(file(DOCROOT)).get("/cgi/test") path = File.join(DOCROOT, "/cgi/test") res.should.be.ok res["Last-Modified"].should.equal File.mtime(path).httpdate end should "return 304 if file isn't modified since last serve" do path = File.join(DOCROOT, "/cgi/test") res = Rack::MockRequest.new(file(DOCROOT)). get("/cgi/test", 'HTTP_IF_MODIFIED_SINCE' => File.mtime(path).httpdate) res.status.should.equal 304 res.body.should.be.empty end should "return the file if it's modified since last serve" do path = File.join(DOCROOT, "/cgi/test") res = Rack::MockRequest.new(file(DOCROOT)). get("/cgi/test", 'HTTP_IF_MODIFIED_SINCE' => (File.mtime(path) - 100).httpdate) res.should.be.ok end should "serve files with URL encoded filenames" do res = Rack::MockRequest.new(file(DOCROOT)).get("/cgi/%74%65%73%74") # "/cgi/test" res.should.be.ok res.should =~ /ruby/ end should "allow safe directory traversal" do req = Rack::MockRequest.new(file(DOCROOT)) res = req.get('/cgi/../cgi/test') res.should.be.successful res = req.get('.') res.should.be.not_found res = req.get("test/..") res.should.be.not_found end should "not allow unsafe directory traversal" do req = Rack::MockRequest.new(file(DOCROOT)) res = req.get("/../README.rdoc") res.should.be.client_error res = req.get("../test/spec_file.rb") res.should.be.client_error res = req.get("../README.rdoc") res.should.be.client_error res.should.be.not_found end should "allow files with .. in their name" do req = Rack::MockRequest.new(file(DOCROOT)) res = req.get("/cgi/..test") res.should.be.not_found res = req.get("/cgi/test..") res.should.be.not_found res = req.get("/cgi../test..") res.should.be.not_found end should "not allow unsafe directory traversal with encoded periods" do res = Rack::MockRequest.new(file(DOCROOT)).get("/%2E%2E/README") res.should.be.client_error? res.should.be.not_found end should "allow safe directory traversal with encoded periods" do res = Rack::MockRequest.new(file(DOCROOT)).get("/cgi/%2E%2E/cgi/test") res.should.be.successful end should "404 if it can't find the file" do res = Rack::MockRequest.new(file(DOCROOT)).get("/cgi/blubb") res.should.be.not_found end should "detect SystemCallErrors" do res = Rack::MockRequest.new(file(DOCROOT)).get("/cgi") res.should.be.not_found end should "return bodies that respond to #to_path" do env = Rack::MockRequest.env_for("/cgi/test") status, _, body = Rack::File.new(DOCROOT).call(env) path = File.join(DOCROOT, "/cgi/test") status.should.equal 200 body.should.respond_to :to_path body.to_path.should.equal path end should "return correct byte range in body" do env = Rack::MockRequest.env_for("/cgi/test") env["HTTP_RANGE"] = "bytes=22-33" res = Rack::MockResponse.new(*file(DOCROOT).call(env)) res.status.should.equal 206 res["Content-Length"].should.equal "12" res["Content-Range"].should.equal "bytes 22-33/193" res.body.should.equal "-*- ruby -*-" end should "return error for unsatisfiable byte range" do env = Rack::MockRequest.env_for("/cgi/test") env["HTTP_RANGE"] = "bytes=1234-5678" res = Rack::MockResponse.new(*file(DOCROOT).call(env)) res.status.should.equal 416 res["Content-Range"].should.equal "bytes */193" end should "support custom http headers" do env = Rack::MockRequest.env_for("/cgi/test") status, heads, _ = file(DOCROOT, 'Cache-Control' => 'public, max-age=38', 'Access-Control-Allow-Origin' => '*').call(env) status.should.equal 200 heads['Cache-Control'].should.equal 'public, max-age=38' heads['Access-Control-Allow-Origin'].should.equal '*' end should "support not add custom http headers if none are supplied" do env = Rack::MockRequest.env_for("/cgi/test") status, heads, _ = file(DOCROOT).call(env) status.should.equal 200 heads['Cache-Control'].should.equal nil heads['Access-Control-Allow-Origin'].should.equal nil end should "only support GET, HEAD, and OPTIONS requests" do req = Rack::MockRequest.new(file(DOCROOT)) forbidden = %w[post put patch delete] forbidden.each do |method| res = req.send(method, "/cgi/test") res.should.be.client_error res.should.be.method_not_allowed res.headers['Allow'].split(/, */).sort.should == %w(GET HEAD OPTIONS) end allowed = %w[get head options] allowed.each do |method| res = req.send(method, "/cgi/test") res.should.be.successful end end should "set Allow correctly for OPTIONS requests" do req = Rack::MockRequest.new(file(DOCROOT)) res = req.options('/cgi/test') res.should.be.successful res.headers['Allow'].should.not.equal nil res.headers['Allow'].split(/, */).sort.should == %w(GET HEAD OPTIONS) end should "set Content-Length correctly for HEAD requests" do req = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT))) res = req.head "/cgi/test" res.should.be.successful res['Content-Length'].should.equal "193" end should "default to a mime type of text/plain" do req = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT))) res = req.get "/cgi/test" res.should.be.successful res['Content-Type'].should.equal "text/plain" end should "allow the default mime type to be set" do req = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT, nil, 'application/octet-stream'))) res = req.get "/cgi/test" res.should.be.successful res['Content-Type'].should.equal "application/octet-stream" end should "not set Content-Type if the mime type is not set" do req = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT, nil, nil))) res = req.get "/cgi/test" res.should.be.successful res['Content-Type'].should.equal nil end end PK!|{~ ~ 4gems/2.2.0/gems/rack-1.6.4/test/spec_commonlogger.rbnu[require 'rack/commonlogger' require 'rack/lint' require 'rack/mock' require 'logger' describe Rack::CommonLogger do obj = 'foobar' length = obj.size app = Rack::Lint.new lambda { |env| [200, {"Content-Type" => "text/html", "Content-Length" => length.to_s}, [obj]]} app_without_length = Rack::Lint.new lambda { |env| [200, {"Content-Type" => "text/html"}, []]} app_with_zero_length = Rack::Lint.new lambda { |env| [200, {"Content-Type" => "text/html", "Content-Length" => "0"}, []]} should "log to rack.errors by default" do res = Rack::MockRequest.new(Rack::CommonLogger.new(app)).get("/") res.errors.should.not.be.empty res.errors.should =~ /"GET \/ " 200 #{length} / end should "log to anything with +write+" do log = StringIO.new Rack::MockRequest.new(Rack::CommonLogger.new(app, log)).get("/") log.string.should =~ /"GET \/ " 200 #{length} / end should "work with standartd library logger" do logdev = StringIO.new log = Logger.new(logdev) Rack::MockRequest.new(Rack::CommonLogger.new(app, log)).get("/") logdev.string.should =~ /"GET \/ " 200 #{length} / end should "log - content length if header is missing" do res = Rack::MockRequest.new(Rack::CommonLogger.new(app_without_length)).get("/") res.errors.should.not.be.empty res.errors.should =~ /"GET \/ " 200 - / end should "log - content length if header is zero" do res = Rack::MockRequest.new(Rack::CommonLogger.new(app_with_zero_length)).get("/") res.errors.should.not.be.empty res.errors.should =~ /"GET \/ " 200 - / end def with_mock_time(t = 0) mc = class < env['SCRIPT_NAME'], 'X-PathInfo' => env['PATH_INFO'], 'Content-Type' => 'text/plain' }, [""]] } map = Rack::Lint.new(Rack::URLMap.new({ 'http://foo.org/bar' => app, '/foo' => app, '/foo/bar' => app })) res = Rack::MockRequest.new(map).get("/") res.should.be.not_found res = Rack::MockRequest.new(map).get("/qux") res.should.be.not_found res = Rack::MockRequest.new(map).get("/foo") res.should.be.ok res["X-ScriptName"].should.equal "/foo" res["X-PathInfo"].should.equal "" res = Rack::MockRequest.new(map).get("/foo/") res.should.be.ok res["X-ScriptName"].should.equal "/foo" res["X-PathInfo"].should.equal "/" res = Rack::MockRequest.new(map).get("/foo/bar") res.should.be.ok res["X-ScriptName"].should.equal "/foo/bar" res["X-PathInfo"].should.equal "" res = Rack::MockRequest.new(map).get("/foo/bar/") res.should.be.ok res["X-ScriptName"].should.equal "/foo/bar" res["X-PathInfo"].should.equal "/" res = Rack::MockRequest.new(map).get("/foo///bar//quux") res.status.should.equal 200 res.should.be.ok res["X-ScriptName"].should.equal "/foo/bar" res["X-PathInfo"].should.equal "//quux" res = Rack::MockRequest.new(map).get("/foo/quux", "SCRIPT_NAME" => "/bleh") res.should.be.ok res["X-ScriptName"].should.equal "/bleh/foo" res["X-PathInfo"].should.equal "/quux" res = Rack::MockRequest.new(map).get("/bar", 'HTTP_HOST' => 'foo.org') res.should.be.ok res["X-ScriptName"].should.equal "/bar" res["X-PathInfo"].should.be.empty res = Rack::MockRequest.new(map).get("/bar/", 'HTTP_HOST' => 'foo.org') res.should.be.ok res["X-ScriptName"].should.equal "/bar" res["X-PathInfo"].should.equal '/' end it "dispatches hosts correctly" do map = Rack::Lint.new(Rack::URLMap.new("http://foo.org/" => lambda { |env| [200, { "Content-Type" => "text/plain", "X-Position" => "foo.org", "X-Host" => env["HTTP_HOST"] || env["SERVER_NAME"], }, [""]]}, "http://subdomain.foo.org/" => lambda { |env| [200, { "Content-Type" => "text/plain", "X-Position" => "subdomain.foo.org", "X-Host" => env["HTTP_HOST"] || env["SERVER_NAME"], }, [""]]}, "http://bar.org/" => lambda { |env| [200, { "Content-Type" => "text/plain", "X-Position" => "bar.org", "X-Host" => env["HTTP_HOST"] || env["SERVER_NAME"], }, [""]]}, "/" => lambda { |env| [200, { "Content-Type" => "text/plain", "X-Position" => "default.org", "X-Host" => env["HTTP_HOST"] || env["SERVER_NAME"], }, [""]]} )) res = Rack::MockRequest.new(map).get("/") res.should.be.ok res["X-Position"].should.equal "default.org" res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "bar.org") res.should.be.ok res["X-Position"].should.equal "bar.org" res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "foo.org") res.should.be.ok res["X-Position"].should.equal "foo.org" res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "subdomain.foo.org", "SERVER_NAME" => "foo.org") res.should.be.ok res["X-Position"].should.equal "subdomain.foo.org" res = Rack::MockRequest.new(map).get("http://foo.org/") res.should.be.ok res["X-Position"].should.equal "foo.org" res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "example.org") res.should.be.ok res["X-Position"].should.equal "default.org" res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "example.org:9292", "SERVER_PORT" => "9292") res.should.be.ok res["X-Position"].should.equal "default.org" end should "be nestable" do map = Rack::Lint.new(Rack::URLMap.new("/foo" => Rack::URLMap.new("/bar" => Rack::URLMap.new("/quux" => lambda { |env| [200, { "Content-Type" => "text/plain", "X-Position" => "/foo/bar/quux", "X-PathInfo" => env["PATH_INFO"], "X-ScriptName" => env["SCRIPT_NAME"], }, [""]]} )))) res = Rack::MockRequest.new(map).get("/foo/bar") res.should.be.not_found res = Rack::MockRequest.new(map).get("/foo/bar/quux") res.should.be.ok res["X-Position"].should.equal "/foo/bar/quux" res["X-PathInfo"].should.equal "" res["X-ScriptName"].should.equal "/foo/bar/quux" end should "route root apps correctly" do map = Rack::Lint.new(Rack::URLMap.new("/" => lambda { |env| [200, { "Content-Type" => "text/plain", "X-Position" => "root", "X-PathInfo" => env["PATH_INFO"], "X-ScriptName" => env["SCRIPT_NAME"] }, [""]]}, "/foo" => lambda { |env| [200, { "Content-Type" => "text/plain", "X-Position" => "foo", "X-PathInfo" => env["PATH_INFO"], "X-ScriptName" => env["SCRIPT_NAME"] }, [""]]} )) res = Rack::MockRequest.new(map).get("/foo/bar") res.should.be.ok res["X-Position"].should.equal "foo" res["X-PathInfo"].should.equal "/bar" res["X-ScriptName"].should.equal "/foo" res = Rack::MockRequest.new(map).get("/foo") res.should.be.ok res["X-Position"].should.equal "foo" res["X-PathInfo"].should.equal "" res["X-ScriptName"].should.equal "/foo" res = Rack::MockRequest.new(map).get("/bar") res.should.be.ok res["X-Position"].should.equal "root" res["X-PathInfo"].should.equal "/bar" res["X-ScriptName"].should.equal "" res = Rack::MockRequest.new(map).get("") res.should.be.ok res["X-Position"].should.equal "root" res["X-PathInfo"].should.equal "/" res["X-ScriptName"].should.equal "" end should "not squeeze slashes" do map = Rack::Lint.new(Rack::URLMap.new("/" => lambda { |env| [200, { "Content-Type" => "text/plain", "X-Position" => "root", "X-PathInfo" => env["PATH_INFO"], "X-ScriptName" => env["SCRIPT_NAME"] }, [""]]}, "/foo" => lambda { |env| [200, { "Content-Type" => "text/plain", "X-Position" => "foo", "X-PathInfo" => env["PATH_INFO"], "X-ScriptName" => env["SCRIPT_NAME"] }, [""]]} )) res = Rack::MockRequest.new(map).get("/http://example.org/bar") res.should.be.ok res["X-Position"].should.equal "root" res["X-PathInfo"].should.equal "/http://example.org/bar" res["X-ScriptName"].should.equal "" end should "not be case sensitive with hosts" do map = Rack::Lint.new(Rack::URLMap.new("http://example.org/" => lambda { |env| [200, { "Content-Type" => "text/plain", "X-Position" => "root", "X-PathInfo" => env["PATH_INFO"], "X-ScriptName" => env["SCRIPT_NAME"] }, [""]]} )) res = Rack::MockRequest.new(map).get("http://example.org/") res.should.be.ok res["X-Position"].should.equal "root" res["X-PathInfo"].should.equal "/" res["X-ScriptName"].should.equal "" res = Rack::MockRequest.new(map).get("http://EXAMPLE.ORG/") res.should.be.ok res["X-Position"].should.equal "root" res["X-PathInfo"].should.equal "/" res["X-ScriptName"].should.equal "" end end PK!CI/gems/2.2.0/gems/rack-1.6.4/test/spec_request.rbnu[require 'stringio' require 'cgi' require 'rack/request' require 'rack/mock' require 'securerandom' describe Rack::Request do should "wrap the rack variables" do req = Rack::Request.new(Rack::MockRequest.env_for("http://example.com:8080/")) req.body.should.respond_to? :gets req.scheme.should.equal "http" req.request_method.should.equal "GET" req.should.be.get req.should.not.be.post req.should.not.be.put req.should.not.be.delete req.should.not.be.head req.should.not.be.patch req.script_name.should.equal "" req.path_info.should.equal "/" req.query_string.should.equal "" req.host.should.equal "example.com" req.port.should.equal 8080 req.content_length.should.equal "0" req.content_type.should.be.nil end should "figure out the correct host" do req = Rack::Request.new \ Rack::MockRequest.env_for("/", "HTTP_HOST" => "www2.example.org") req.host.should.equal "www2.example.org" req = Rack::Request.new \ Rack::MockRequest.env_for("/", "SERVER_NAME" => "example.org", "SERVER_PORT" => "9292") req.host.should.equal "example.org" req = Rack::Request.new \ Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org:9292") req.host.should.equal "example.org" env = Rack::MockRequest.env_for("/", "SERVER_ADDR" => "192.168.1.1", "SERVER_PORT" => "9292") env.delete("SERVER_NAME") req = Rack::Request.new(env) req.host.should.equal "192.168.1.1" env = Rack::MockRequest.env_for("/") env.delete("SERVER_NAME") req = Rack::Request.new(env) req.host.should.equal "" end should "figure out the correct port" do req = Rack::Request.new \ Rack::MockRequest.env_for("/", "HTTP_HOST" => "www2.example.org") req.port.should.equal 80 req = Rack::Request.new \ Rack::MockRequest.env_for("/", "HTTP_HOST" => "www2.example.org:81") req.port.should.equal 81 req = Rack::Request.new \ Rack::MockRequest.env_for("/", "SERVER_NAME" => "example.org", "SERVER_PORT" => "9292") req.port.should.equal 9292 req = Rack::Request.new \ Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org:9292") req.port.should.equal 9292 req = Rack::Request.new \ Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org") req.port.should.equal 80 req = Rack::Request.new \ Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org", "HTTP_X_FORWARDED_SSL" => "on") req.port.should.equal 443 req = Rack::Request.new \ Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org", "HTTP_X_FORWARDED_PROTO" => "https") req.port.should.equal 443 req = Rack::Request.new \ Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org", "HTTP_X_FORWARDED_PORT" => "9393") req.port.should.equal 9393 req = Rack::Request.new \ Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org:9393", "SERVER_PORT" => "80") req.port.should.equal 9393 req = Rack::Request.new \ Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org", "SERVER_PORT" => "9393") req.port.should.equal 80 req = Rack::Request.new \ Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost", "HTTP_X_FORWARDED_PROTO" => "https", "SERVER_PORT" => "80") req.port.should.equal 443 req = Rack::Request.new \ Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost", "HTTP_X_FORWARDED_PROTO" => "https,https", "SERVER_PORT" => "80") req.port.should.equal 443 end should "figure out the correct host with port" do req = Rack::Request.new \ Rack::MockRequest.env_for("/", "HTTP_HOST" => "www2.example.org") req.host_with_port.should.equal "www2.example.org" req = Rack::Request.new \ Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81") req.host_with_port.should.equal "localhost:81" req = Rack::Request.new \ Rack::MockRequest.env_for("/", "SERVER_NAME" => "example.org", "SERVER_PORT" => "9292") req.host_with_port.should.equal "example.org:9292" req = Rack::Request.new \ Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org:9292") req.host_with_port.should.equal "example.org:9292" req = Rack::Request.new \ Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org", "SERVER_PORT" => "9393") req.host_with_port.should.equal "example.org" end should "parse the query string" do req = Rack::Request.new(Rack::MockRequest.env_for("/?foo=bar&quux=bla")) req.query_string.should.equal "foo=bar&quux=bla" req.GET.should.equal "foo" => "bar", "quux" => "bla" req.POST.should.be.empty req.params.should.equal "foo" => "bar", "quux" => "bla" end should "not truncate query strings containing semi-colons #543 only in POST" do mr = Rack::MockRequest.env_for("/", "REQUEST_METHOD" => 'POST', :input => "foo=bar&quux=b;la") req = Rack::Request.new mr req.query_string.should.equal "" req.GET.should.be.empty req.POST.should.equal "foo" => "bar", "quux" => "b;la" req.params.should.equal req.GET.merge(req.POST) end should "use semi-colons as separators for query strings in GET" do req = Rack::Request.new(Rack::MockRequest.env_for("/?foo=bar&quux=b;la;wun=duh")) req.query_string.should.equal "foo=bar&quux=b;la;wun=duh" req.GET.should.equal "foo" => "bar", "quux" => "b", "la" => nil, "wun" => "duh" req.POST.should.be.empty req.params.should.equal "foo" => "bar", "quux" => "b", "la" => nil, "wun" => "duh" end should "limit the keys from the GET query string" do env = Rack::MockRequest.env_for("/?foo=bar") old, Rack::Utils.key_space_limit = Rack::Utils.key_space_limit, 1 begin req = Rack::Request.new(env) lambda { req.GET }.should.raise(RangeError) ensure Rack::Utils.key_space_limit = old end end should "limit the key size per nested params hash" do nested_query = Rack::MockRequest.env_for("/?foo%5Bbar%5D%5Bbaz%5D%5Bqux%5D=1") plain_query = Rack::MockRequest.env_for("/?foo_bar__baz__qux_=1") old, Rack::Utils.key_space_limit = Rack::Utils.key_space_limit, 3 begin lambda { Rack::Request.new(nested_query).GET }.should.not.raise(RangeError) lambda { Rack::Request.new(plain_query).GET }.should.raise(RangeError) ensure Rack::Utils.key_space_limit = old end end should "not unify GET and POST when calling params" do mr = Rack::MockRequest.env_for("/?foo=quux", "REQUEST_METHOD" => 'POST', :input => "foo=bar&quux=bla" ) req = Rack::Request.new mr req.params req.GET.should.equal "foo" => "quux" req.POST.should.equal "foo" => "bar", "quux" => "bla" req.params.should.equal req.GET.merge(req.POST) end should "raise if input params has invalid %-encoding" do mr = Rack::MockRequest.env_for("/?foo=quux", "REQUEST_METHOD" => 'POST', :input => "a%=1" ) req = Rack::Request.new mr lambda { req.POST }. should.raise(Rack::Utils::InvalidParameterError). message.should.equal "invalid %-encoding (a%)" end should "raise if rack.input is missing" do req = Rack::Request.new({}) lambda { req.POST }.should.raise(RuntimeError) end should "parse POST data when method is POST and no Content-Type given" do req = Rack::Request.new \ Rack::MockRequest.env_for("/?foo=quux", "REQUEST_METHOD" => 'POST', :input => "foo=bar&quux=bla") req.content_type.should.be.nil req.media_type.should.be.nil req.query_string.should.equal "foo=quux" req.GET.should.equal "foo" => "quux" req.POST.should.equal "foo" => "bar", "quux" => "bla" req.params.should.equal "foo" => "bar", "quux" => "bla" end should "limit the keys from the POST form data" do env = Rack::MockRequest.env_for("", "REQUEST_METHOD" => 'POST', :input => "foo=bar&quux=bla") old, Rack::Utils.key_space_limit = Rack::Utils.key_space_limit, 1 begin req = Rack::Request.new(env) lambda { req.POST }.should.raise(RangeError) ensure Rack::Utils.key_space_limit = old end end should "parse POST data with explicit content type regardless of method" do req = Rack::Request.new \ Rack::MockRequest.env_for("/", "CONTENT_TYPE" => 'application/x-www-form-urlencoded;foo=bar', :input => "foo=bar&quux=bla") req.content_type.should.equal 'application/x-www-form-urlencoded;foo=bar' req.media_type.should.equal 'application/x-www-form-urlencoded' req.media_type_params['foo'].should.equal 'bar' req.POST.should.equal "foo" => "bar", "quux" => "bla" req.params.should.equal "foo" => "bar", "quux" => "bla" end should "not parse POST data when media type is not form-data" do req = Rack::Request.new \ Rack::MockRequest.env_for("/?foo=quux", "REQUEST_METHOD" => 'POST', "CONTENT_TYPE" => 'text/plain;charset=utf-8', :input => "foo=bar&quux=bla") req.content_type.should.equal 'text/plain;charset=utf-8' req.media_type.should.equal 'text/plain' req.media_type_params['charset'].should.equal 'utf-8' req.POST.should.be.empty req.params.should.equal "foo" => "quux" req.body.read.should.equal "foo=bar&quux=bla" end should "parse POST data on PUT when media type is form-data" do req = Rack::Request.new \ Rack::MockRequest.env_for("/?foo=quux", "REQUEST_METHOD" => 'PUT', "CONTENT_TYPE" => 'application/x-www-form-urlencoded', :input => "foo=bar&quux=bla") req.POST.should.equal "foo" => "bar", "quux" => "bla" req.body.read.should.equal "foo=bar&quux=bla" end should "rewind input after parsing POST data" do input = StringIO.new("foo=bar&quux=bla") req = Rack::Request.new \ Rack::MockRequest.env_for("/", "CONTENT_TYPE" => 'application/x-www-form-urlencoded;foo=bar', :input => input) req.params.should.equal "foo" => "bar", "quux" => "bla" input.read.should.equal "foo=bar&quux=bla" end should "clean up Safari's ajax POST body" do req = Rack::Request.new \ Rack::MockRequest.env_for("/", 'REQUEST_METHOD' => 'POST', :input => "foo=bar&quux=bla\0") req.POST.should.equal "foo" => "bar", "quux" => "bla" end should "get value by key from params with #[]" do req = Rack::Request.new \ Rack::MockRequest.env_for("?foo=quux") req['foo'].should.equal 'quux' req[:foo].should.equal 'quux' end should "set value to key on params with #[]=" do req = Rack::Request.new \ Rack::MockRequest.env_for("?foo=duh") req['foo'].should.equal 'duh' req[:foo].should.equal 'duh' req.params.should.equal 'foo' => 'duh' req['foo'] = 'bar' req.params.should.equal 'foo' => 'bar' req['foo'].should.equal 'bar' req[:foo].should.equal 'bar' req[:foo] = 'jaz' req.params.should.equal 'foo' => 'jaz' req['foo'].should.equal 'jaz' req[:foo].should.equal 'jaz' end should "return values for the keys in the order given from values_at" do req = Rack::Request.new \ Rack::MockRequest.env_for("?foo=baz&wun=der&bar=ful") req.values_at('foo').should.equal ['baz'] req.values_at('foo', 'wun').should.equal ['baz', 'der'] req.values_at('bar', 'foo', 'wun').should.equal ['ful', 'baz', 'der'] end should "extract referrer correctly" do req = Rack::Request.new \ Rack::MockRequest.env_for("/", "HTTP_REFERER" => "/some/path") req.referer.should.equal "/some/path" req = Rack::Request.new \ Rack::MockRequest.env_for("/") req.referer.should.equal nil end should "extract user agent correctly" do req = Rack::Request.new \ Rack::MockRequest.env_for("/", "HTTP_USER_AGENT" => "Mozilla/4.0 (compatible)") req.user_agent.should.equal "Mozilla/4.0 (compatible)" req = Rack::Request.new \ Rack::MockRequest.env_for("/") req.user_agent.should.equal nil end should "treat missing content type as nil" do req = Rack::Request.new \ Rack::MockRequest.env_for("/") req.content_type.should.equal nil end should "treat empty content type as nil" do req = Rack::Request.new \ Rack::MockRequest.env_for("/", "CONTENT_TYPE" => "") req.content_type.should.equal nil end should "return nil media type for empty content type" do req = Rack::Request.new \ Rack::MockRequest.env_for("/", "CONTENT_TYPE" => "") req.media_type.should.equal nil end should "cache, but invalidates the cache" do req = Rack::Request.new \ Rack::MockRequest.env_for("/?foo=quux", "CONTENT_TYPE" => "application/x-www-form-urlencoded", :input => "foo=bar&quux=bla") req.GET.should.equal "foo" => "quux" req.GET.should.equal "foo" => "quux" req.env["QUERY_STRING"] = "bla=foo" req.GET.should.equal "bla" => "foo" req.GET.should.equal "bla" => "foo" req.POST.should.equal "foo" => "bar", "quux" => "bla" req.POST.should.equal "foo" => "bar", "quux" => "bla" req.env["rack.input"] = StringIO.new("foo=bla&quux=bar") req.POST.should.equal "foo" => "bla", "quux" => "bar" req.POST.should.equal "foo" => "bla", "quux" => "bar" end should "figure out if called via XHR" do req = Rack::Request.new(Rack::MockRequest.env_for("")) req.should.not.be.xhr req = Rack::Request.new \ Rack::MockRequest.env_for("", "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest") req.should.be.xhr end should "ssl detection" do request = Rack::Request.new(Rack::MockRequest.env_for("/")) request.scheme.should.equal "http" request.should.not.be.ssl? request = Rack::Request.new(Rack::MockRequest.env_for("/", 'HTTPS' => 'on')) request.scheme.should.equal "https" request.should.be.ssl? request = Rack::Request.new(Rack::MockRequest.env_for("/", 'rack.url_scheme' => 'https')) request.scheme.should.equal "https" request.should.be.ssl? request = Rack::Request.new(Rack::MockRequest.env_for("/", 'HTTP_HOST' => 'www.example.org:8080')) request.scheme.should.equal "http" request.should.not.be.ssl? request = Rack::Request.new(Rack::MockRequest.env_for("/", 'HTTP_HOST' => 'www.example.org:8443', 'HTTPS' => 'on')) request.scheme.should.equal "https" request.should.be.ssl? request = Rack::Request.new(Rack::MockRequest.env_for("/", 'HTTP_HOST' => 'www.example.org:8443', 'HTTP_X_FORWARDED_SSL' => 'on')) request.scheme.should.equal "https" request.should.be.ssl? request = Rack::Request.new(Rack::MockRequest.env_for("/", 'HTTP_X_FORWARDED_SCHEME' => 'https')) request.scheme.should.equal "https" request.should.be.ssl? request = Rack::Request.new(Rack::MockRequest.env_for("/", 'HTTP_X_FORWARDED_PROTO' => 'https')) request.scheme.should.equal "https" request.should.be.ssl? request = Rack::Request.new(Rack::MockRequest.env_for("/", 'HTTP_X_FORWARDED_PROTO' => 'https, http, http')) request.scheme.should.equal "https" request.should.be.ssl? end should "parse cookies" do req = Rack::Request.new \ Rack::MockRequest.env_for("", "HTTP_COOKIE" => "foo=bar;quux=h&m") req.cookies.should.equal "foo" => "bar", "quux" => "h&m" req.cookies.should.equal "foo" => "bar", "quux" => "h&m" req.env.delete("HTTP_COOKIE") req.cookies.should.equal({}) end should "always return the same hash object" do req = Rack::Request.new \ Rack::MockRequest.env_for("", "HTTP_COOKIE" => "foo=bar;quux=h&m") hash = req.cookies req.env.delete("HTTP_COOKIE") req.cookies.should.equal(hash) req.env["HTTP_COOKIE"] = "zoo=m" req.cookies.should.equal(hash) end should "modify the cookies hash in place" do req = Rack::Request.new(Rack::MockRequest.env_for("")) req.cookies.should.equal({}) req.cookies['foo'] = 'bar' req.cookies.should.equal 'foo' => 'bar' end should "not modify the params hash in place" do e = Rack::MockRequest.env_for("") req1 = Rack::Request.new(e) req1.params.should.equal({}) req1.params['foo'] = 'bar' req1.params.should.equal 'foo' => 'bar' req2 = Rack::Request.new(e) req2.params.should.equal({}) end should "modify params hash if param is in GET" do e = Rack::MockRequest.env_for("?foo=duh") req1 = Rack::Request.new(e) req1.params.should.equal 'foo' => 'duh' req1.update_param 'foo', 'bar' req1.params.should.equal 'foo' => 'bar' req2 = Rack::Request.new(e) req2.params.should.equal 'foo' => 'bar' end should "modify params hash if param is in POST" do e = Rack::MockRequest.env_for("", "REQUEST_METHOD" => 'POST', :input => 'foo=duh') req1 = Rack::Request.new(e) req1.params.should.equal 'foo' => 'duh' req1.update_param 'foo', 'bar' req1.params.should.equal 'foo' => 'bar' req2 = Rack::Request.new(e) req2.params.should.equal 'foo' => 'bar' end should "modify params hash, even if param didn't exist before" do e = Rack::MockRequest.env_for("") req1 = Rack::Request.new(e) req1.params.should.equal({}) req1.update_param 'foo', 'bar' req1.params.should.equal 'foo' => 'bar' req2 = Rack::Request.new(e) req2.params.should.equal 'foo' => 'bar' end should "modify params hash by changing only GET" do e = Rack::MockRequest.env_for("?foo=duhget") req = Rack::Request.new(e) req.GET.should.equal 'foo' => 'duhget' req.POST.should.equal({}) req.update_param 'foo', 'bar' req.GET.should.equal 'foo' => 'bar' req.POST.should.equal({}) end should "modify params hash by changing only POST" do e = Rack::MockRequest.env_for("", "REQUEST_METHOD" => 'POST', :input => "foo=duhpost") req = Rack::Request.new(e) req.GET.should.equal({}) req.POST.should.equal 'foo' => 'duhpost' req.update_param 'foo', 'bar' req.GET.should.equal({}) req.POST.should.equal 'foo' => 'bar' end should "modify params hash, even if param is defined in both POST and GET" do e = Rack::MockRequest.env_for("?foo=duhget", "REQUEST_METHOD" => 'POST', :input => "foo=duhpost") req1 = Rack::Request.new(e) req1.GET.should.equal 'foo' => 'duhget' req1.POST.should.equal 'foo' => 'duhpost' req1.params.should.equal 'foo' => 'duhpost' req1.update_param 'foo', 'bar' req1.GET.should.equal 'foo' => 'bar' req1.POST.should.equal 'foo' => 'bar' req1.params.should.equal 'foo' => 'bar' req2 = Rack::Request.new(e) req2.GET.should.equal 'foo' => 'bar' req2.POST.should.equal 'foo' => 'bar' req2.params.should.equal 'foo' => 'bar' req2.params.should.equal 'foo' => 'bar' end should "allow deleting from params hash if param is in GET" do e = Rack::MockRequest.env_for("?foo=bar") req1 = Rack::Request.new(e) req1.params.should.equal 'foo' => 'bar' req1.delete_param('foo').should.equal 'bar' req1.params.should.equal({}) req2 = Rack::Request.new(e) req2.params.should.equal({}) end should "allow deleting from params hash if param is in POST" do e = Rack::MockRequest.env_for("", "REQUEST_METHOD" => 'POST', :input => 'foo=bar') req1 = Rack::Request.new(e) req1.params.should.equal 'foo' => 'bar' req1.delete_param('foo').should.equal 'bar' req1.params.should.equal({}) req2 = Rack::Request.new(e) req2.params.should.equal({}) end should "pass through non-uri escaped cookies as-is" do req = Rack::Request.new Rack::MockRequest.env_for("", "HTTP_COOKIE" => "foo=%") req.cookies["foo"].should == "%" end should "parse cookies according to RFC 2109" do req = Rack::Request.new \ Rack::MockRequest.env_for('', 'HTTP_COOKIE' => 'foo=bar;foo=car') req.cookies.should.equal 'foo' => 'bar' end should 'parse cookies with quotes' do req = Rack::Request.new Rack::MockRequest.env_for('', { 'HTTP_COOKIE' => '$Version="1"; Customer="WILE_E_COYOTE"; $Path="/acme"; Part_Number="Rocket_Launcher_0001"; $Path="/acme"' }) req.cookies.should.equal({ '$Version' => '"1"', 'Customer' => '"WILE_E_COYOTE"', '$Path' => '"/acme"', 'Part_Number' => '"Rocket_Launcher_0001"', }) end should "provide setters" do req = Rack::Request.new(e=Rack::MockRequest.env_for("")) req.script_name.should.equal "" req.script_name = "/foo" req.script_name.should.equal "/foo" e["SCRIPT_NAME"].should.equal "/foo" req.path_info.should.equal "/" req.path_info = "/foo" req.path_info.should.equal "/foo" e["PATH_INFO"].should.equal "/foo" end should "provide the original env" do req = Rack::Request.new(e = Rack::MockRequest.env_for("")) req.env.should == e end should "restore the base URL" do Rack::Request.new(Rack::MockRequest.env_for("")).base_url. should.equal "http://example.org" Rack::Request.new(Rack::MockRequest.env_for("", "SCRIPT_NAME" => "/foo")).base_url. should.equal "http://example.org" end should "restore the URL" do Rack::Request.new(Rack::MockRequest.env_for("")).url. should.equal "http://example.org/" Rack::Request.new(Rack::MockRequest.env_for("", "SCRIPT_NAME" => "/foo")).url. should.equal "http://example.org/foo/" Rack::Request.new(Rack::MockRequest.env_for("/foo")).url. should.equal "http://example.org/foo" Rack::Request.new(Rack::MockRequest.env_for("?foo")).url. should.equal "http://example.org/?foo" Rack::Request.new(Rack::MockRequest.env_for("http://example.org:8080/")).url. should.equal "http://example.org:8080/" Rack::Request.new(Rack::MockRequest.env_for("https://example.org/")).url. should.equal "https://example.org/" Rack::Request.new(Rack::MockRequest.env_for("coffee://example.org/")).url. should.equal "coffee://example.org/" Rack::Request.new(Rack::MockRequest.env_for("coffee://example.org:443/")).url. should.equal "coffee://example.org:443/" Rack::Request.new(Rack::MockRequest.env_for("https://example.com:8080/foo?foo")).url. should.equal "https://example.com:8080/foo?foo" end should "restore the full path" do Rack::Request.new(Rack::MockRequest.env_for("")).fullpath. should.equal "/" Rack::Request.new(Rack::MockRequest.env_for("", "SCRIPT_NAME" => "/foo")).fullpath. should.equal "/foo/" Rack::Request.new(Rack::MockRequest.env_for("/foo")).fullpath. should.equal "/foo" Rack::Request.new(Rack::MockRequest.env_for("?foo")).fullpath. should.equal "/?foo" Rack::Request.new(Rack::MockRequest.env_for("http://example.org:8080/")).fullpath. should.equal "/" Rack::Request.new(Rack::MockRequest.env_for("https://example.org/")).fullpath. should.equal "/" Rack::Request.new(Rack::MockRequest.env_for("https://example.com:8080/foo?foo")).fullpath. should.equal "/foo?foo" end should "handle multiple media type parameters" do req = Rack::Request.new \ Rack::MockRequest.env_for("/", "CONTENT_TYPE" => 'text/plain; foo=BAR,baz=bizzle dizzle;BLING=bam;blong="boo";zump="zoo\"o";weird=lol"') req.should.not.be.form_data req.media_type_params.should.include 'foo' req.media_type_params['foo'].should.equal 'BAR' req.media_type_params.should.include 'baz' req.media_type_params['baz'].should.equal 'bizzle dizzle' req.media_type_params.should.not.include 'BLING' req.media_type_params.should.include 'bling' req.media_type_params['bling'].should.equal 'bam' req.media_type_params['blong'].should.equal 'boo' req.media_type_params['zump'].should.equal 'zoo\"o' req.media_type_params['weird'].should.equal 'lol"' end should "parse with junk before boundry" do # Adapted from RFC 1867. input = < "multipart/form-data, boundary=AaB03x", "CONTENT_LENGTH" => input.size, :input => input) req.POST.should.include "fileupload" req.POST.should.include "reply" req.should.be.form_data req.content_length.should.equal input.size req.media_type.should.equal 'multipart/form-data' req.media_type_params.should.include 'boundary' req.media_type_params['boundary'].should.equal 'AaB03x' req.POST["reply"].should.equal "yes" f = req.POST["fileupload"] f.should.be.kind_of Hash f[:type].should.equal "image/jpeg" f[:filename].should.equal "dj.jpg" f.should.include :tempfile f[:tempfile].size.should.equal 76 end should "not infinite loop with a malformed HTTP request" do # Adapted from RFC 1867. input = < "multipart/form-data, boundary=AaB03x", "CONTENT_LENGTH" => input.size, :input => input) lambda{req.POST}.should.raise(EOFError) end should "parse multipart form data" do # Adapted from RFC 1867. input = < "multipart/form-data, boundary=AaB03x", "CONTENT_LENGTH" => input.size, :input => input) req.POST.should.include "fileupload" req.POST.should.include "reply" req.should.be.form_data req.content_length.should.equal input.size req.media_type.should.equal 'multipart/form-data' req.media_type_params.should.include 'boundary' req.media_type_params['boundary'].should.equal 'AaB03x' req.POST["reply"].should.equal "yes" f = req.POST["fileupload"] f.should.be.kind_of Hash f[:type].should.equal "image/jpeg" f[:filename].should.equal "dj.jpg" f.should.include :tempfile f[:tempfile].size.should.equal 76 end should "MultipartPartLimitError when request has too many multipart parts if limit set" do begin data = 10000.times.map { "--AaB03x\r\nContent-Type: text/plain\r\nContent-Disposition: attachment; name=#{SecureRandom.hex(10)}; filename=#{SecureRandom.hex(10)}\r\n\r\ncontents\r\n" }.join("\r\n") data += "--AaB03x--\r" options = { "CONTENT_TYPE" => "multipart/form-data; boundary=AaB03x", "CONTENT_LENGTH" => data.length.to_s, :input => StringIO.new(data) } request = Rack::Request.new Rack::MockRequest.env_for("/", options) lambda { request.POST }.should.raise(Rack::Multipart::MultipartPartLimitError) end end should "parse big multipart form data" do input = < "multipart/form-data, boundary=AaB03x", "CONTENT_LENGTH" => input.size, :input => input) req.POST["huge"][:tempfile].size.should.equal 32768 req.POST["mean"][:tempfile].size.should.equal 10 req.POST["mean"][:tempfile].read.should.equal "--AaB03xha" end should "record tempfiles from multipart form data in env[rack.tempfiles]" do input = < "multipart/form-data, boundary=AaB03x", "CONTENT_LENGTH" => input.size, :input => input) req = Rack::Request.new(env) req.params env['rack.tempfiles'].size.should.equal(2) end should "detect invalid multipart form data" do input = < "multipart/form-data, boundary=AaB03x", "CONTENT_LENGTH" => input.size, :input => input) lambda { req.POST }.should.raise(EOFError) input = < "multipart/form-data, boundary=AaB03x", "CONTENT_LENGTH" => input.size, :input => input) lambda { req.POST }.should.raise(EOFError) input = < "multipart/form-data, boundary=AaB03x", "CONTENT_LENGTH" => input.size, :input => input) lambda { req.POST }.should.raise(EOFError) end should "consistently raise EOFError on bad multipart form data" do input = < "multipart/form-data, boundary=AaB03x", "CONTENT_LENGTH" => input.size, :input => input) lambda { req.POST }.should.raise(EOFError) lambda { req.POST }.should.raise(EOFError) end should "correctly parse the part name from Content-Id header" do input = <\r Content-Transfer-Encoding: 7bit\r \r foo\r --AaB03x--\r EOF req = Rack::Request.new Rack::MockRequest.env_for("/", "CONTENT_TYPE" => "multipart/related, boundary=AaB03x", "CONTENT_LENGTH" => input.size, :input => input) req.params.keys.should.equal [""] end should "not try to interpret binary as utf8" do if /regexp/.respond_to?(:kcode) # < 1.9 begin original_kcode = $KCODE $KCODE='UTF8' input = < "multipart/form-data, boundary=AaB03x", "CONTENT_LENGTH" => input.size, :input => input) lambda{req.POST}.should.not.raise(EOFError) req.POST["fileupload"][:tempfile].size.should.equal 4 ensure $KCODE = original_kcode end else # >= 1.9 input = < "multipart/form-data, boundary=AaB03x", "CONTENT_LENGTH" => input.size, :input => input) lambda{req.POST}.should.not.raise(EOFError) req.POST["fileupload"][:tempfile].size.should.equal 4 end end should "work around buggy 1.8.* Tempfile equality" do input = < "multipart/form-data, boundary=AaB03x", "CONTENT_LENGTH" => input.size, :input => rack_input) lambda{ req.POST }.should.not.raise lambda{ req.POST }.should.not.raise("input re-processed!") end should "use form_hash when form_input is a Tempfile" do input = "{foo: 'bar'}" rack_input = Tempfile.new("rackspec") rack_input.write(input) rack_input.rewind req = Rack::Request.new Rack::MockRequest.env_for("/", "rack.request.form_hash" => {'foo' => 'bar'}, "rack.request.form_input" => rack_input, :input => rack_input) req.POST.should.equal(req.env['rack.request.form_hash']) end should "conform to the Rack spec" do app = lambda { |env| content = Rack::Request.new(env).POST["file"].inspect size = content.respond_to?(:bytesize) ? content.bytesize : content.size [200, {"Content-Type" => "text/html", "Content-Length" => size.to_s}, [content]] } input = < "multipart/form-data, boundary=AaB03x", "CONTENT_LENGTH" => input.size.to_s, "rack.input" => StringIO.new(input) res.should.be.ok end should "parse Accept-Encoding correctly" do parser = lambda do |x| Rack::Request.new(Rack::MockRequest.env_for("", "HTTP_ACCEPT_ENCODING" => x)).accept_encoding end parser.call(nil).should.equal([]) parser.call("compress, gzip").should.equal([["compress", 1.0], ["gzip", 1.0]]) parser.call("").should.equal([]) parser.call("*").should.equal([["*", 1.0]]) parser.call("compress;q=0.5, gzip;q=1.0").should.equal([["compress", 0.5], ["gzip", 1.0]]) parser.call("gzip;q=1.0, identity; q=0.5, *;q=0").should.equal([["gzip", 1.0], ["identity", 0.5], ["*", 0] ]) parser.call("gzip ; q=0.9").should.equal([["gzip", 0.9]]) parser.call("gzip ; deflate").should.equal([["gzip", 1.0]]) end should "parse Accept-Language correctly" do parser = lambda do |x| Rack::Request.new(Rack::MockRequest.env_for("", "HTTP_ACCEPT_LANGUAGE" => x)).accept_language end parser.call(nil).should.equal([]) parser.call("fr, en").should.equal([["fr", 1.0], ["en", 1.0]]) parser.call("").should.equal([]) parser.call("*").should.equal([["*", 1.0]]) parser.call("fr;q=0.5, en;q=1.0").should.equal([["fr", 0.5], ["en", 1.0]]) parser.call("fr;q=1.0, en; q=0.5, *;q=0").should.equal([["fr", 1.0], ["en", 0.5], ["*", 0] ]) parser.call("fr ; q=0.9").should.equal([["fr", 0.9]]) parser.call("fr").should.equal([["fr", 1.0]]) end ip_app = lambda { |env| request = Rack::Request.new(env) response = Rack::Response.new response.write request.ip response.finish } should 'provide ip information' do mock = Rack::MockRequest.new(Rack::Lint.new(ip_app)) res = mock.get '/', 'REMOTE_ADDR' => '1.2.3.4' res.body.should.equal '1.2.3.4' res = mock.get '/', 'REMOTE_ADDR' => 'fe80::202:b3ff:fe1e:8329' res.body.should.equal 'fe80::202:b3ff:fe1e:8329' res = mock.get '/', 'REMOTE_ADDR' => '1.2.3.4,3.4.5.6' res.body.should.equal '1.2.3.4' end should 'deals with proxies' do mock = Rack::MockRequest.new(Rack::Lint.new(ip_app)) res = mock.get '/', 'REMOTE_ADDR' => '1.2.3.4', 'HTTP_X_FORWARDED_FOR' => '3.4.5.6' res.body.should.equal '1.2.3.4' res = mock.get '/', 'REMOTE_ADDR' => '1.2.3.4', 'HTTP_X_FORWARDED_FOR' => 'unknown' res.body.should.equal '1.2.3.4' res = mock.get '/', 'REMOTE_ADDR' => '127.0.0.1', 'HTTP_X_FORWARDED_FOR' => '3.4.5.6' res.body.should.equal '3.4.5.6' res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => 'unknown,3.4.5.6' res.body.should.equal '3.4.5.6' res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => '192.168.0.1,3.4.5.6' res.body.should.equal '3.4.5.6' res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => '10.0.0.1,3.4.5.6' res.body.should.equal '3.4.5.6' res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => '10.0.0.1, 10.0.0.1, 3.4.5.6' res.body.should.equal '3.4.5.6' res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => '127.0.0.1, 3.4.5.6' res.body.should.equal '3.4.5.6' res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => 'unknown,192.168.0.1' res.body.should.equal 'unknown' res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => 'other,unknown,192.168.0.1' res.body.should.equal 'unknown' res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => 'unknown,localhost,192.168.0.1' res.body.should.equal 'unknown' res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => '9.9.9.9, 3.4.5.6, 10.0.0.1, 172.31.4.4' res.body.should.equal '3.4.5.6' res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => '::1,2620:0:1c00:0:812c:9583:754b:ca11' res.body.should.equal '2620:0:1c00:0:812c:9583:754b:ca11' res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => '2620:0:1c00:0:812c:9583:754b:ca11,::1' res.body.should.equal '2620:0:1c00:0:812c:9583:754b:ca11' res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => 'fd5b:982e:9130:247f:0000:0000:0000:0000,2620:0:1c00:0:812c:9583:754b:ca11' res.body.should.equal '2620:0:1c00:0:812c:9583:754b:ca11' res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => '2620:0:1c00:0:812c:9583:754b:ca11,fd5b:982e:9130:247f:0000:0000:0000:0000' res.body.should.equal '2620:0:1c00:0:812c:9583:754b:ca11' res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => '1.1.1.1, 127.0.0.1', 'HTTP_CLIENT_IP' => '1.1.1.1' res.body.should.equal '1.1.1.1' res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => '8.8.8.8, 9.9.9.9' res.body.should.equal '9.9.9.9' res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => '8.8.8.8, fe80::202:b3ff:fe1e:8329' res.body.should.equal 'fe80::202:b3ff:fe1e:8329' # Unix Sockets res = mock.get '/', 'REMOTE_ADDR' => 'unix', 'HTTP_X_FORWARDED_FOR' => '3.4.5.6' res.body.should.equal '3.4.5.6' res = mock.get '/', 'REMOTE_ADDR' => 'unix:/tmp/foo', 'HTTP_X_FORWARDED_FOR' => '3.4.5.6' res.body.should.equal '3.4.5.6' end should "not allow IP spoofing via Client-IP and X-Forwarded-For headers" do mock = Rack::MockRequest.new(Rack::Lint.new(ip_app)) # IP Spoofing attempt: # Client sends X-Forwarded-For: 6.6.6.6 # Client-IP: 6.6.6.6 # Load balancer adds X-Forwarded-For: 2.2.2.3, 192.168.0.7 # App receives: X-Forwarded-For: 6.6.6.6 # X-Forwarded-For: 2.2.2.3, 192.168.0.7 # Client-IP: 6.6.6.6 # Rack env: HTTP_X_FORWARDED_FOR: '6.6.6.6, 2.2.2.3, 192.168.0.7' # HTTP_CLIENT_IP: '6.6.6.6' res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => '6.6.6.6, 2.2.2.3, 192.168.0.7', 'HTTP_CLIENT_IP' => '6.6.6.6' res.body.should.equal '2.2.2.3' end should "regard local addresses as proxies" do req = Rack::Request.new(Rack::MockRequest.env_for("/")) req.trusted_proxy?('127.0.0.1').should.equal 0 req.trusted_proxy?('10.0.0.1').should.equal 0 req.trusted_proxy?('172.16.0.1').should.equal 0 req.trusted_proxy?('172.20.0.1').should.equal 0 req.trusted_proxy?('172.30.0.1').should.equal 0 req.trusted_proxy?('172.31.0.1').should.equal 0 req.trusted_proxy?('192.168.0.1').should.equal 0 req.trusted_proxy?('::1').should.equal 0 req.trusted_proxy?('fd00::').should.equal 0 req.trusted_proxy?('localhost').should.equal 0 req.trusted_proxy?('unix').should.equal 0 req.trusted_proxy?('unix:/tmp/sock').should.equal 0 req.trusted_proxy?("unix.example.org").should.equal nil req.trusted_proxy?("example.org\n127.0.0.1").should.equal nil req.trusted_proxy?("127.0.0.1\nexample.org").should.equal nil req.trusted_proxy?("11.0.0.1").should.equal nil req.trusted_proxy?("172.15.0.1").should.equal nil req.trusted_proxy?("172.32.0.1").should.equal nil req.trusted_proxy?("2001:470:1f0b:18f8::1").should.equal nil end class MyRequest < Rack::Request def params {:foo => "bar"} end end should "allow subclass request to be instantiated after parent request" do env = Rack::MockRequest.env_for("/?foo=bar") req1 = Rack::Request.new(env) req1.GET.should.equal "foo" => "bar" req1.params.should.equal "foo" => "bar" req2 = MyRequest.new(env) req2.GET.should.equal "foo" => "bar" req2.params.should.equal :foo => "bar" end should "allow parent request to be instantiated after subclass request" do env = Rack::MockRequest.env_for("/?foo=bar") req1 = MyRequest.new(env) req1.GET.should.equal "foo" => "bar" req1.params.should.equal :foo => "bar" req2 = Rack::Request.new(env) req2.GET.should.equal "foo" => "bar" req2.params.should.equal "foo" => "bar" end should "raise TypeError every time if request parameters are broken" do broken_query = Rack::MockRequest.env_for("/?foo%5B%5D=0&foo%5Bbar%5D=1") req = Rack::Request.new(broken_query) lambda{req.GET}.should.raise(TypeError) lambda{req.params}.should.raise(TypeError) end (0x20...0x7E).collect { |a| b = a.chr c = CGI.escape(b) should "not strip '#{a}' => '#{c}' => '#{b}' escaped character from parameters when accessed as string" do url = "/?foo=#{c}bar#{c}" env = Rack::MockRequest.env_for(url) req2 = Rack::Request.new(env) req2.GET.should.equal "foo" => "#{b}bar#{b}" req2.params.should.equal "foo" => "#{b}bar#{b}" end } end PK!l4gems/2.2.0/gems/rack-1.6.4/test/spec_content_type.rbnu[require 'rack/content_type' require 'rack/lint' require 'rack/mock' describe Rack::ContentType do def content_type(app, *args) Rack::Lint.new Rack::ContentType.new(app, *args) end def request Rack::MockRequest.env_for end should "set Content-Type to default text/html if none is set" do app = lambda { |env| [200, {}, "Hello, World!"] } headers = content_type(app).call(request)[1] headers['Content-Type'].should.equal 'text/html' end should "set Content-Type to chosen default if none is set" do app = lambda { |env| [200, {}, "Hello, World!"] } headers = content_type(app, 'application/octet-stream').call(request)[1] headers['Content-Type'].should.equal 'application/octet-stream' end should "not change Content-Type if it is already set" do app = lambda { |env| [200, {'Content-Type' => 'foo/bar'}, "Hello, World!"] } headers = content_type(app).call(request)[1] headers['Content-Type'].should.equal 'foo/bar' end should "detect Content-Type case insensitive" do app = lambda { |env| [200, {'CONTENT-Type' => 'foo/bar'}, "Hello, World!"] } headers = content_type(app).call(request)[1] headers.to_a.select { |k,v| k.downcase == "content-type" }. should.equal [["CONTENT-Type","foo/bar"]] end should "not set Content-Type on 304 responses" do app = lambda { |env| [304, {}, []] } response = content_type(app, "text/html").call(request) response[1]['Content-Type'].should.equal nil end end PK!m? 336gems/2.2.0/gems/rack-1.6.4/test/spec_session_cookie.rbnu[require 'rack/session/cookie' require 'rack/lint' require 'rack/mock' describe Rack::Session::Cookie do incrementor = lambda do |env| env["rack.session"]["counter"] ||= 0 env["rack.session"]["counter"] += 1 hash = env["rack.session"].dup hash.delete("session_id") Rack::Response.new(hash.inspect).to_a end session_id = lambda do |env| Rack::Response.new(env["rack.session"].to_hash.inspect).to_a end session_option = lambda do |opt| lambda do |env| Rack::Response.new(env["rack.session.options"][opt].inspect).to_a end end nothing = lambda do |env| Rack::Response.new("Nothing").to_a end renewer = lambda do |env| env["rack.session.options"][:renew] = true Rack::Response.new("Nothing").to_a end only_session_id = lambda do |env| Rack::Response.new(env["rack.session"]["session_id"].to_s).to_a end bigcookie = lambda do |env| env["rack.session"]["cookie"] = "big" * 3000 Rack::Response.new(env["rack.session"].inspect).to_a end destroy_session = lambda do |env| env["rack.session"].destroy Rack::Response.new("Nothing").to_a end def response_for(options={}) request_options = options.fetch(:request, {}) cookie = if options[:cookie].is_a?(Rack::Response) options[:cookie]["Set-Cookie"] else options[:cookie] end request_options["HTTP_COOKIE"] = cookie || "" app_with_cookie = Rack::Session::Cookie.new(*options[:app]) app_with_cookie = Rack::Lint.new(app_with_cookie) Rack::MockRequest.new(app_with_cookie).get("/", request_options) end before do @warnings = warnings = [] Rack::Session::Cookie.class_eval do define_method(:warn) { |m| warnings << m } end end after do Rack::Session::Cookie.class_eval { remove_method :warn } end describe 'Base64' do it 'uses base64 to encode' do coder = Rack::Session::Cookie::Base64.new str = 'fuuuuu' coder.encode(str).should.equal [str].pack('m') end it 'uses base64 to decode' do coder = Rack::Session::Cookie::Base64.new str = ['fuuuuu'].pack('m') coder.decode(str).should.equal str.unpack('m').first end describe 'Marshal' do it 'marshals and base64 encodes' do coder = Rack::Session::Cookie::Base64::Marshal.new str = 'fuuuuu' coder.encode(str).should.equal [::Marshal.dump(str)].pack('m') end it 'marshals and base64 decodes' do coder = Rack::Session::Cookie::Base64::Marshal.new str = [::Marshal.dump('fuuuuu')].pack('m') coder.decode(str).should.equal ::Marshal.load(str.unpack('m').first) end it 'rescues failures on decode' do coder = Rack::Session::Cookie::Base64::Marshal.new coder.decode('lulz').should.equal nil end end describe 'JSON' do it 'marshals and base64 encodes' do coder = Rack::Session::Cookie::Base64::JSON.new obj = %w[fuuuuu] coder.encode(obj).should.equal [::Rack::Utils::OkJson.encode(obj)].pack('m') end it 'marshals and base64 decodes' do coder = Rack::Session::Cookie::Base64::JSON.new str = [::Rack::Utils::OkJson.encode(%w[fuuuuu])].pack('m') coder.decode(str).should.equal ::Rack::Utils::OkJson.decode(str.unpack('m').first) end it 'rescues failures on decode' do coder = Rack::Session::Cookie::Base64::JSON.new coder.decode('lulz').should.equal nil end end describe 'ZipJSON' do it 'jsons, deflates, and base64 encodes' do coder = Rack::Session::Cookie::Base64::ZipJSON.new obj = %w[fuuuuu] json = Rack::Utils::OkJson.encode(obj) coder.encode(obj).should.equal [Zlib::Deflate.deflate(json)].pack('m') end it 'base64 decodes, inflates, and decodes json' do coder = Rack::Session::Cookie::Base64::ZipJSON.new obj = %w[fuuuuu] json = Rack::Utils::OkJson.encode(obj) b64 = [Zlib::Deflate.deflate(json)].pack('m') coder.decode(b64).should.equal obj end it 'rescues failures on decode' do coder = Rack::Session::Cookie::Base64::ZipJSON.new coder.decode('lulz').should.equal nil end end end it "warns if no secret is given" do Rack::Session::Cookie.new(incrementor) @warnings.first.should =~ /no secret/i @warnings.clear Rack::Session::Cookie.new(incrementor, :secret => 'abc') @warnings.should.be.empty? end it 'uses a coder' do identity = Class.new { attr_reader :calls def initialize @calls = [] end def encode(str); @calls << :encode; str; end def decode(str); @calls << :decode; str; end }.new response = response_for(:app => [incrementor, { :coder => identity }]) response["Set-Cookie"].should.include("rack.session=") response.body.should.equal '{"counter"=>1}' identity.calls.should.equal [:decode, :encode] end it "creates a new cookie" do response = response_for(:app => incrementor) response["Set-Cookie"].should.include("rack.session=") response.body.should.equal '{"counter"=>1}' end it "loads from a cookie" do response = response_for(:app => incrementor) response = response_for(:app => incrementor, :cookie => response) response.body.should.equal '{"counter"=>2}' response = response_for(:app => incrementor, :cookie => response) response.body.should.equal '{"counter"=>3}' end it "renew session id" do response = response_for(:app => incrementor) cookie = response['Set-Cookie'] response = response_for(:app => only_session_id, :cookie => cookie) cookie = response['Set-Cookie'] if response['Set-Cookie'] response.body.should.not.equal "" old_session_id = response.body response = response_for(:app => renewer, :cookie => cookie) cookie = response['Set-Cookie'] if response['Set-Cookie'] response = response_for(:app => only_session_id, :cookie => cookie) response.body.should.not.equal "" response.body.should.not.equal old_session_id end it "destroys session" do response = response_for(:app => incrementor) response = response_for(:app => only_session_id, :cookie => response) response.body.should.not.equal "" old_session_id = response.body response = response_for(:app => destroy_session, :cookie => response) response = response_for(:app => only_session_id, :cookie => response) response.body.should.not.equal "" response.body.should.not.equal old_session_id end it "survives broken cookies" do response = response_for( :app => incrementor, :cookie => "rack.session=blarghfasel" ) response.body.should.equal '{"counter"=>1}' response = response_for( :app => [incrementor, { :secret => "test" }], :cookie => "rack.session=" ) response.body.should.equal '{"counter"=>1}' end it "barks on too big cookies" do lambda{ response_for(:app => bigcookie, :request => { :fatal => true }) }.should.raise(Rack::MockRequest::FatalWarning) end it "loads from a cookie with integrity hash" do app = [incrementor, { :secret => "test" }] response = response_for(:app => app) response = response_for(:app => app, :cookie => response) response.body.should.equal '{"counter"=>2}' response = response_for(:app => app, :cookie => response) response.body.should.equal '{"counter"=>3}' app = [incrementor, { :secret => "other" }] response = response_for(:app => app, :cookie => response) response.body.should.equal '{"counter"=>1}' end it "loads from a cookie wih accept-only integrity hash for graceful key rotation" do response = response_for(:app => [incrementor, { :secret => "test" }]) app = [incrementor, { :secret => "test2", :old_secret => "test" }] response = response_for(:app => app, :cookie => response) response.body.should.equal '{"counter"=>2}' app = [incrementor, { :secret => "test3", :old_secret => "test2" }] response = response_for(:app => app, :cookie => response) response.body.should.equal '{"counter"=>3}' end it "ignores tampered with session cookies" do app = [incrementor, { :secret => "test" }] response = response_for(:app => app) response.body.should.equal '{"counter"=>1}' response = response_for(:app => app, :cookie => response) response.body.should.equal '{"counter"=>2}' _, digest = response["Set-Cookie"].split("--") tampered_with_cookie = "hackerman-was-here" + "--" + digest response = response_for(:app => app, :cookie => tampered_with_cookie) response.body.should.equal '{"counter"=>1}' end it "supports either of secret or old_secret" do app = [incrementor, { :secret => "test" }] response = response_for(:app => app) response.body.should.equal '{"counter"=>1}' response = response_for(:app => app, :cookie => response) response.body.should.equal '{"counter"=>2}' app = [incrementor, { :old_secret => "test" }] response = response_for(:app => app) response.body.should.equal '{"counter"=>1}' response = response_for(:app => app, :cookie => response) response.body.should.equal '{"counter"=>2}' end it "can handle Rack::Lint middleware" do response = response_for(:app => incrementor) lint = Rack::Lint.new(session_id) response = response_for(:app => lint, :cookie => response) response.body.should.not.be.nil end it "can handle middleware that inspects the env" do class TestEnvInspector def initialize(app) @app = app end def call(env) env.inspect @app.call(env) end end response = response_for(:app => incrementor) inspector = TestEnvInspector.new(session_id) response = response_for(:app => inspector, :cookie => response) response.body.should.not.be.nil end it "returns the session id in the session hash" do response = response_for(:app => incrementor) response.body.should.equal '{"counter"=>1}' response = response_for(:app => session_id, :cookie => response) response.body.should.match(/"session_id"=>/) response.body.should.match(/"counter"=>1/) end it "does not return a cookie if set to secure but not using ssl" do app = [incrementor, { :secure => true }] response = response_for(:app => app) response["Set-Cookie"].should.be.nil response = response_for(:app => app, :request => { "HTTPS" => "on" }) response["Set-Cookie"].should.not.be.nil response["Set-Cookie"].should.match(/secure/) end it "does not return a cookie if cookie was not read/written" do response = response_for(:app => nothing) response["Set-Cookie"].should.be.nil end it "does not return a cookie if cookie was not written (only read)" do response = response_for(:app => session_id) response["Set-Cookie"].should.be.nil end it "returns even if not read/written if :expire_after is set" do app = [nothing, { :expire_after => 3600 }] request = { "rack.session" => { "not" => "empty" }} response = response_for(:app => app, :request => request) response["Set-Cookie"].should.not.be.nil end it "returns no cookie if no data was written and no session was created previously, even if :expire_after is set" do app = [nothing, { :expire_after => 3600 }] response = response_for(:app => app) response["Set-Cookie"].should.be.nil end it "exposes :secret in env['rack.session.option']" do response = response_for(:app => [session_option[:secret], { :secret => "foo" }]) response.body.should == '"foo"' end it "exposes :coder in env['rack.session.option']" do response = response_for(:app => session_option[:coder]) response.body.should.match(/Base64::Marshal/) end it "allows passing in a hash with session data from middleware in front" do request = { 'rack.session' => { :foo => 'bar' }} response = response_for(:app => session_id, :request => request) response.body.should.match(/foo/) end it "allows modifying session data with session data from middleware in front" do request = { 'rack.session' => { :foo => 'bar' }} response = response_for(:app => incrementor, :request => request) response.body.should.match(/counter/) response.body.should.match(/foo/) end it "allows more than one '--' in the cookie when calculating digests" do @counter = 0 app = lambda do |env| env["rack.session"]["message"] ||= "" env["rack.session"]["message"] << "#{(@counter += 1).to_s}--" hash = env["rack.session"].dup hash.delete("session_id") Rack::Response.new(hash["message"]).to_a end # another example of an unsafe coder is Base64.urlsafe_encode64 unsafe_coder = Class.new { def encode(hash); hash.inspect end def decode(str); eval(str) if str; end }.new _app = [ app, { :secret => "test", :coder => unsafe_coder } ] response = response_for(:app => _app) response.body.should.equal "1--" response = response_for(:app => _app, :cookie => response) response.body.should.equal "1--2--" end end PK!~~0gems/2.2.0/gems/rack-1.6.4/test/spec_sendfile.rbnu[require 'fileutils' require 'rack/lint' require 'rack/sendfile' require 'rack/mock' require 'tmpdir' describe Rack::File do should "respond to #to_path" do Rack::File.new(Dir.pwd).should.respond_to :to_path end end describe Rack::Sendfile do def sendfile_body FileUtils.touch File.join(Dir.tmpdir, "rack_sendfile") res = ['Hello World'] def res.to_path ; File.join(Dir.tmpdir, "rack_sendfile") ; end res end def simple_app(body=sendfile_body) lambda { |env| [200, {'Content-Type' => 'text/plain'}, body] } end def sendfile_app(body, mappings = []) Rack::Lint.new Rack::Sendfile.new(simple_app(body), nil, mappings) end def request(headers={}, body=sendfile_body, mappings=[]) yield Rack::MockRequest.new(sendfile_app(body, mappings)).get('/', headers) end def open_file(path) Class.new(File) do unless method_defined?(:to_path) alias :to_path :path end end.open(path, 'wb+') end it "does nothing when no X-Sendfile-Type header present" do request do |response| response.should.be.ok response.body.should.equal 'Hello World' response.headers.should.not.include 'X-Sendfile' end end it "sets X-Sendfile response header and discards body" do request 'HTTP_X_SENDFILE_TYPE' => 'X-Sendfile' do |response| response.should.be.ok response.body.should.be.empty response.headers['Content-Length'].should.equal '0' response.headers['X-Sendfile'].should.equal File.join(Dir.tmpdir, "rack_sendfile") end end it "sets X-Lighttpd-Send-File response header and discards body" do request 'HTTP_X_SENDFILE_TYPE' => 'X-Lighttpd-Send-File' do |response| response.should.be.ok response.body.should.be.empty response.headers['Content-Length'].should.equal '0' response.headers['X-Lighttpd-Send-File'].should.equal File.join(Dir.tmpdir, "rack_sendfile") end end it "sets X-Accel-Redirect response header and discards body" do headers = { 'HTTP_X_SENDFILE_TYPE' => 'X-Accel-Redirect', 'HTTP_X_ACCEL_MAPPING' => "#{Dir.tmpdir}/=/foo/bar/" } request headers do |response| response.should.be.ok response.body.should.be.empty response.headers['Content-Length'].should.equal '0' response.headers['X-Accel-Redirect'].should.equal '/foo/bar/rack_sendfile' end end it 'writes to rack.error when no X-Accel-Mapping is specified' do request 'HTTP_X_SENDFILE_TYPE' => 'X-Accel-Redirect' do |response| response.should.be.ok response.body.should.equal 'Hello World' response.headers.should.not.include 'X-Accel-Redirect' response.errors.should.include 'X-Accel-Mapping' end end it 'does nothing when body does not respond to #to_path' do request({'HTTP_X_SENDFILE_TYPE' => 'X-Sendfile'}, ['Not a file...']) do |response| response.body.should.equal 'Not a file...' response.headers.should.not.include 'X-Sendfile' end end it "sets X-Accel-Redirect response header and discards body when initialized with multiple mappings" do begin dir1 = Dir.mktmpdir dir2 = Dir.mktmpdir first_body = open_file(File.join(dir1, 'rack_sendfile')) first_body.puts 'hello world' second_body = open_file(File.join(dir2, 'rack_sendfile')) second_body.puts 'goodbye world' mappings = [ ["#{dir1}/", '/foo/bar/'], ["#{dir2}/", '/wibble/'] ] request({'HTTP_X_SENDFILE_TYPE' => 'X-Accel-Redirect'}, first_body, mappings) do |response| response.should.be.ok response.body.should.be.empty response.headers['Content-Length'].should.equal '0' response.headers['X-Accel-Redirect'].should.equal '/foo/bar/rack_sendfile' end request({'HTTP_X_SENDFILE_TYPE' => 'X-Accel-Redirect'}, second_body, mappings) do |response| response.should.be.ok response.body.should.be.empty response.headers['Content-Length'].should.equal '0' response.headers['X-Accel-Redirect'].should.equal '/wibble/rack_sendfile' end ensure FileUtils.remove_entry_secure dir1 FileUtils.remove_entry_secure dir2 end end end PK!#)qq/gems/2.2.0/gems/rack-1.6.4/test/spec_cascade.rbnu[require 'rack/cascade' require 'rack/file' require 'rack/lint' require 'rack/urlmap' require 'rack/mock' describe Rack::Cascade do def cascade(*args) Rack::Lint.new Rack::Cascade.new(*args) end docroot = File.expand_path(File.dirname(__FILE__)) app1 = Rack::File.new(docroot) app2 = Rack::URLMap.new("/crash" => lambda { |env| raise "boom" }) app3 = Rack::URLMap.new("/foo" => lambda { |env| [200, { "Content-Type" => "text/plain"}, [""]]}) should "dispatch onward on 404 and 405 by default" do cascade = cascade([app1, app2, app3]) Rack::MockRequest.new(cascade).get("/cgi/test").should.be.ok Rack::MockRequest.new(cascade).get("/foo").should.be.ok Rack::MockRequest.new(cascade).get("/toobad").should.be.not_found Rack::MockRequest.new(cascade).get("/cgi/../..").should.be.client_error # Put is not allowed by Rack::File so it'll 405. Rack::MockRequest.new(cascade).put("/foo").should.be.ok end should "dispatch onward on whatever is passed" do cascade = cascade([app1, app2, app3], [404, 403]) Rack::MockRequest.new(cascade).get("/cgi/../bla").should.be.not_found end should "return 404 if empty" do Rack::MockRequest.new(cascade([])).get('/').should.be.not_found end should "append new app" do cascade = Rack::Cascade.new([], [404, 403]) Rack::MockRequest.new(cascade).get('/').should.be.not_found cascade << app2 Rack::MockRequest.new(cascade).get('/cgi/test').should.be.not_found Rack::MockRequest.new(cascade).get('/cgi/../bla').should.be.not_found cascade << app1 Rack::MockRequest.new(cascade).get('/cgi/test').should.be.ok Rack::MockRequest.new(cascade).get('/cgi/../..').should.be.client_error Rack::MockRequest.new(cascade).get('/foo').should.be.not_found cascade << app3 Rack::MockRequest.new(cascade).get('/foo').should.be.ok end should "close the body on cascade" do body = StringIO.new closer = lambda { |env| [404, {}, body] } cascade = Rack::Cascade.new([closer, app3], [404]) Rack::MockRequest.new(cascade).get("/foo").should.be.ok body.should.be.closed end end PK!a$r1gems/2.2.0/gems/rack-1.6.4/test/spec_directory.rbnu[require 'rack/directory' require 'rack/lint' require 'rack/mock' describe Rack::Directory do DOCROOT = File.expand_path(File.dirname(__FILE__)) unless defined? DOCROOT FILE_CATCH = proc{|env| [200, {'Content-Type'=>'text/plain', "Content-Length" => "7"}, ['passed!']] } app = Rack::Lint.new(Rack::Directory.new(DOCROOT, FILE_CATCH)) should "serve directory indices" do res = Rack::MockRequest.new(Rack::Lint.new(app)). get("/cgi/") res.should.be.ok res.should =~ // end should "pass to app if file found" do res = Rack::MockRequest.new(Rack::Lint.new(app)). get("/cgi/test") res.should.be.ok res.should =~ /passed!/ end should "serve uri with URL encoded filenames" do res = Rack::MockRequest.new(Rack::Lint.new(app)). get("/%63%67%69/") # "/cgi/test" res.should.be.ok res.should =~ // res = Rack::MockRequest.new(Rack::Lint.new(app)). get("/cgi/%74%65%73%74") # "/cgi/test" res.should.be.ok res.should =~ /passed!/ end should "not allow directory traversal" do res = Rack::MockRequest.new(Rack::Lint.new(app)). get("/cgi/../test") res.should.be.forbidden res = Rack::MockRequest.new(Rack::Lint.new(app)). get("/cgi/%2E%2E/test") res.should.be.forbidden end should "404 if it can't find the file" do res = Rack::MockRequest.new(Rack::Lint.new(app)). get("/cgi/blubb") res.should.be.not_found end should "uri escape path parts" do # #265, properly escape file names mr = Rack::MockRequest.new(Rack::Lint.new(app)) res = mr.get("/cgi/test%2bdirectory") res.should.be.ok res.body.should =~ %r[/cgi/test%2Bdirectory/test%2Bfile] res = mr.get("/cgi/test%2bdirectory/test%2bfile") res.should.be.ok end should "correctly escape script name" do app2 = Rack::Builder.new do map '/script-path' do run app end end mr = Rack::MockRequest.new(Rack::Lint.new(app2)) res = mr.get("/script-path/cgi/test%2bdirectory") res.should.be.ok res.body.should =~ %r[/script-path/cgi/test%2Bdirectory/test%2Bfile] res = mr.get("/script-path/cgi/test%2bdirectory/test%2bfile") res.should.be.ok end end PK!4YUU,gems/2.2.0/gems/rack-1.6.4/test/spec_lock.rbnu[require 'rack/lint' require 'rack/lock' require 'rack/mock' class Lock attr_reader :synchronized def initialize @synchronized = false end def synchronize @synchronized = true yield end def lock @synchronized = true end def unlock @synchronized = false end end module LockHelpers def lock_app(app, lock = Lock.new) app = if lock Rack::Lock.new app, lock else Rack::Lock.new app end Rack::Lint.new app end end describe Rack::Lock do extend LockHelpers describe 'Proxy' do extend LockHelpers should 'delegate each' do env = Rack::MockRequest.env_for("/") response = Class.new { attr_accessor :close_called def initialize; @close_called = false; end def each; %w{ hi mom }.each { |x| yield x }; end }.new app = lock_app(lambda { |inner_env| [200, {"Content-Type" => "text/plain"}, response] }) response = app.call(env)[2] list = [] response.each { |x| list << x } list.should.equal %w{ hi mom } end should 'delegate to_path' do lock = Lock.new env = Rack::MockRequest.env_for("/") res = ['Hello World'] def res.to_path ; "/tmp/hello.txt" ; end app = Rack::Lock.new(lambda { |inner_env| [200, {"Content-Type" => "text/plain"}, res] }, lock) body = app.call(env)[2] body.should.respond_to :to_path body.to_path.should.equal "/tmp/hello.txt" end should 'not delegate to_path if body does not implement it' do env = Rack::MockRequest.env_for("/") res = ['Hello World'] app = lock_app(lambda { |inner_env| [200, {"Content-Type" => "text/plain"}, res] }) body = app.call(env)[2] body.should.not.respond_to :to_path end end should 'call super on close' do env = Rack::MockRequest.env_for("/") response = Class.new { attr_accessor :close_called def initialize; @close_called = false; end def close; @close_called = true; end }.new app = lock_app(lambda { |inner_env| [200, {"Content-Type" => "text/plain"}, response] }) app.call(env) response.close_called.should.equal false response.close response.close_called.should.equal true end should "not unlock until body is closed" do lock = Lock.new env = Rack::MockRequest.env_for("/") response = Object.new app = lock_app(lambda { |inner_env| [200, {"Content-Type" => "text/plain"}, response] }, lock) lock.synchronized.should.equal false response = app.call(env)[2] lock.synchronized.should.equal true response.close lock.synchronized.should.equal false end should "return value from app" do env = Rack::MockRequest.env_for("/") body = [200, {"Content-Type" => "text/plain"}, %w{ hi mom }] app = lock_app(lambda { |inner_env| body }) res = app.call(env) res[0].should.equal body[0] res[1].should.equal body[1] res[2].to_enum.to_a.should.equal ["hi", "mom"] end should "call synchronize on lock" do lock = Lock.new env = Rack::MockRequest.env_for("/") app = lock_app(lambda { |inner_env| [200, {"Content-Type" => "text/plain"}, %w{ a b c }] }, lock) lock.synchronized.should.equal false app.call(env) lock.synchronized.should.equal true end should "unlock if the app raises" do lock = Lock.new env = Rack::MockRequest.env_for("/") app = lock_app(lambda { raise Exception }, lock) lambda { app.call(env) }.should.raise(Exception) lock.synchronized.should.equal false end should "unlock if the app throws" do lock = Lock.new env = Rack::MockRequest.env_for("/") app = lock_app(lambda {|_| throw :bacon }, lock) lambda { app.call(env) }.should.throw(:bacon) lock.synchronized.should.equal false end should "set multithread flag to false" do app = lock_app(lambda { |env| env['rack.multithread'].should.equal false [200, {"Content-Type" => "text/plain"}, %w{ a b c }] }, false) app.call(Rack::MockRequest.env_for("/")) end should "reset original multithread flag when exiting lock" do app = Class.new(Rack::Lock) { def call(env) env['rack.multithread'].should.equal true super end }.new(lambda { |env| [200, {"Content-Type" => "text/plain"}, %w{ a b c }] }) Rack::Lint.new(app).call(Rack::MockRequest.env_for("/")) end end PK!'k&&&gems/2.2.0/gems/rack-1.6.4/README.rdocnu[= Rack, a modular Ruby webserver interface {Build Status}[http://travis-ci.org/rack/rack] {Dependency Status}[https://gemnasium.com/rack/rack] Rack provides a minimal, modular and adaptable interface for developing web applications in Ruby. By wrapping HTTP requests and responses in the simplest way possible, it unifies and distills the API for web servers, web frameworks, and software in between (the so-called middleware) into a single method call. The exact details of this are described in the Rack specification, which all Rack applications should conform to. == Supported web servers The included *handlers* connect all kinds of web servers to Rack: * Mongrel * EventedMongrel * SwiftipliedMongrel * WEBrick * FCGI * CGI * SCGI * LiteSpeed * Thin These web servers include Rack handlers in their distributions: * Ebb * Fuzed * Glassfish v3 * Phusion Passenger (which is mod_rack for Apache and for nginx) * Puma * Rainbows! * Reel * Unicorn * unixrack * uWSGI * yahns * Zbatery Any valid Rack app will run the same on all these handlers, without changing anything. == Supported web frameworks These frameworks include Rack adapters in their distributions: * Camping * Coset * Espresso * Halcyon * Mack * Maveric * Merb * Racktools::SimpleApplication * Ramaze * Ruby on Rails * Rum * Sinatra * Sin * Vintage * Waves * Wee * ... and many others. == Available middleware Between the server and the framework, Rack can be customized to your applications needs using middleware, for example: * Rack::URLMap, to route to multiple applications inside the same process. * Rack::CommonLogger, for creating Apache-style logfiles. * Rack::ShowException, for catching unhandled exceptions and presenting them in a nice and helpful way with clickable backtrace. * Rack::File, for serving static files. * ...many others! All these components use the same interface, which is described in detail in the Rack specification. These optional components can be used in any way you wish. == Convenience If you want to develop outside of existing frameworks, implement your own ones, or develop middleware, Rack provides many helpers to create Rack applications quickly and without doing the same web stuff all over: * Rack::Request, which also provides query string parsing and multipart handling. * Rack::Response, for convenient generation of HTTP replies and cookie handling. * Rack::MockRequest and Rack::MockResponse for efficient and quick testing of Rack application without real HTTP round-trips. == rack-contrib The plethora of useful middleware created the need for a project that collects fresh Rack middleware. rack-contrib includes a variety of add-on components for Rack and it is easy to contribute new modules. * https://github.com/rack/rack-contrib == rackup rackup is a useful tool for running Rack applications, which uses the Rack::Builder DSL to configure middleware and build up applications easily. rackup automatically figures out the environment it is run in, and runs your application as FastCGI, CGI, or standalone with Mongrel or WEBrick---all from the same configuration. == Quick start Try the lobster! Either with the embedded WEBrick starter: ruby -Ilib lib/rack/lobster.rb Or with rackup: bin/rackup -Ilib example/lobster.ru By default, the lobster is found at http://localhost:9292. == Installing with RubyGems A Gem of Rack is available at rubygems.org. You can install it with: gem install rack I also provide a local mirror of the gems (and development snapshots) at my site: gem install rack --source http://chneukirchen.org/releases/gems/ == Running the tests Testing Rack requires the bacon testing framework: bundle install --without extra # to be able to run the fast tests Or: bundle install # this assumes that you have installed native extensions! There are two rake-based test tasks: rake test tests all the fast tests (no Handlers or Adapters) rake fulltest runs all the tests The fast testsuite has no dependencies outside of the core Ruby installation and bacon. To run the test suite completely, you need: * fcgi * memcache-client * mongrel * thin The full set of tests test FCGI access with lighttpd (on port 9203) so you will need lighttpd installed as well as the FCGI libraries and the fcgi gem: Download and install lighttpd: http://www.lighttpd.net/download Installing the FCGI libraries: curl -O http://www.fastcgi.com/dist/fcgi-2.4.0.tar.gz tar xzvf fcgi-2.4.0.tar.gz cd fcgi-2.4.0 ./configure --prefix=/usr/local make sudo make install cd .. Installing the Ruby fcgi gem: gem install fcgi Furthermore, to test Memcache sessions, you need memcached (will be run on port 11211) and memcache-client installed. == Configuration Several parameters can be modified on Rack::Utils to configure Rack behaviour. e.g: Rack::Utils.key_space_limit = 128 === key_space_limit The default number of bytes to allow a single parameter key to take up. This helps prevent a rogue client from flooding a Request. Default to 65536 characters (4 kiB in worst case). === multipart_part_limit The maximum number of parts a request can contain. Accepting too many part can lead to the server running out of file handles. The default is 128, which means that a single request can't upload more than 128 files at once. Set to 0 for no limit. Can also be set via the RACK_MULTIPART_PART_LIMIT environment variable. == History See . == Contact Please post bugs, suggestions and patches to the bug tracker at . Please post security related bugs and suggestions to the core team at or rack-core@googlegroups.com. This list is not public. Due to wide usage of the library, it is strongly preferred that we manage timing in order to provide viable patches at the time of disclosure. Your assistance in this matter is greatly appreciated. Mailing list archives are available at . Git repository (send Git patches to the mailing list): * https://github.com/rack/rack * http://git.vuxu.org/cgi-bin/gitweb.cgi?p=rack-github.git You are also welcome to join the #rack channel on irc.freenode.net. == Thanks The Rack Core Team, consisting of * Christian Neukirchen (chneukirchen) * James Tucker (raggi) * Josh Peek (josh) * José Valim (josevalim) * Michael Fellinger (manveru) * Aaron Patterson (tenderlove) * Santiago Pastorino (spastorino) * Konstantin Haase (rkh) and the Rack Alumnis * Ryan Tomayko (rtomayko) * Scytrin dai Kinthra (scytrin) would like to thank: * Adrian Madrid, for the LiteSpeed handler. * Christoffer Sawicki, for the first Rails adapter and Rack::Deflater. * Tim Fletcher, for the HTTP authentication code. * Luc Heinrich for the Cookie sessions, the static file handler and bugfixes. * Armin Ronacher, for the logo and racktools. * Alex Beregszaszi, Alexander Kahn, Anil Wadghule, Aredridel, Ben Alpert, Dan Kubb, Daniel Roethlisberger, Matt Todd, Tom Robinson, Phil Hagelberg, S. Brent Faulkner, Bosko Milekic, Daniel Rodríguez Troitiño, Genki Takiuchi, Geoffrey Grosenbach, Julien Sanchez, Kamal Fariz Mahyuddin, Masayoshi Takahashi, Patrick Aljordm, Mig, Kazuhiro Nishiyama, Jon Bardin, Konstantin Haase, Larry Siden, Matias Korhonen, Sam Ruby, Simon Chiang, Tim Connor, Timur Batyrshin, and Zach Brock for bug fixing and other improvements. * Eric Wong, Hongli Lai, Jeremy Kemper for their continuous support and API improvements. * Yehuda Katz and Carl Lerche for refactoring rackup. * Brian Candler, for Rack::ContentType. * Graham Batty, for improved handler loading. * Stephen Bannasch, for bug reports and documentation. * Gary Wright, for proposing a better Rack::Response interface. * Jonathan Buch, for improvements regarding Rack::Response. * Armin Röhrl, for tracking down bugs in the Cookie generator. * Alexander Kellett for testing the Gem and reviewing the announcement. * Marcus Rückert, for help with configuring and debugging lighttpd. * The WSGI team for the well-done and documented work they've done and Rack builds up on. * All bug reporters and patch contributors not mentioned above. == Copyright Copyright (C) 2007, 2008, 2009, 2010 Christian Neukirchen Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. == Links Rack:: Official Rack repositories:: Rack Bug Tracking:: rack-devel mailing list:: Rack's Rubyforge project:: Christian Neukirchen:: PK!L+gems/2.2.0/gems/rack-1.6.4/contrib/rdoc.cssnu[/* Forked from the Darkfish templates rdoc.css file, much hacked, probably * imperfect */ html { max-width: 960px; margin: 0 auto; } body { font: 14px "Helvetica Neue", Helvetica, Tahoma, sans-serif; } body.file-popup { font-size: 90%; margin-left: 0; } h1 { color: #4183C4; } :link, :visited { color: #4183C4; text-decoration: none; } :link:hover, :visited:hover { border-bottom: 1px dotted #4183C4; } pre, pre.description { font: 12px Monaco,"Courier New","DejaVu Sans Mono","Bitstream Vera Sans Mono",monospace; padding: 1em; overflow: auto; line-height: 1.4; } /* @group Generic Classes */ .initially-hidden { display: none; } #search-field { width: 98%; } .missing-docs { font-size: 120%; background: white url(images/wrench_orange.png) no-repeat 4px center; color: #ccc; line-height: 2em; border: 1px solid #d00; opacity: 1; text-indent: 24px; letter-spacing: 3px; font-weight: bold; -webkit-border-radius: 5px; -moz-border-radius: 5px; } .target-section { border: 2px solid #dcce90; border-left-width: 8px; background: #fff3c2; } /* @end */ /* @group Index Page, Standalone file pages */ .indexpage ul { line-height: 160%; list-style: none; } .indexpage ul :link, .indexpage ul :visited { font-size: 16px; } .indexpage li { padding-left: 20px; } .indexpage ul > li { background: url(images/bullet_black.png) no-repeat left 4px; } .indexpage li.method { background: url(images/plugin.png) no-repeat left 4px; } .indexpage li.module { background: url(images/package.png) no-repeat left 4px; } .indexpage li.class { background: url(images/ruby.png) no-repeat left 4px; } .indexpage li.file { background: url(images/page_white_text.png) no-repeat left 4px; } .indexpage li li { background: url(images/tag_blue.png) no-repeat left 4px; } .indexpage li .toc-toggle { width: 16px; height: 16px; background: url(images/add.png) no-repeat; } .indexpage li .toc-toggle.open { background: url(images/delete.png) no-repeat; } /* @end */ /* @group Top-Level Structure */ .project-section, #file-metadata, #class-metadata { display: block; background: #f5f5f5; margin-bottom: 1em; padding: 0.5em; } .project-section h3, #file-metadata h3, #class-metadata h3 { margin: 0; } #metadata { float: left; width: 280px; } #documentation { margin: 2em 1em 2em 300px; } #validator-badges { clear: both; margin: 1em 1em 2em; font-size: smaller; } /* @end */ /* @group Metadata Section */ #metadata ul, #metadata dl, #metadata p { padding: 0px; list-style: none; } dl.svninfo { color: #666; margin: 0; } dl.svninfo dt { font-weight: bold; } ul.link-list li { white-space: nowrap; } ul.link-list .type { font-size: 8px; text-transform: uppercase; color: white; background: #969696; } /* @end */ /* @group Documentation Section */ .note-list { margin: 8px 0; } .label-list { margin: 8px 1.5em; border: 1px solid #ccc; } .description .label-list { font-size: 14px; } .note-list dt { font-weight: bold; } .note-list dd { } .label-list dt { font-weight: bold; background: #ddd; } .label-list dd { } .label-list dd + dt, .note-list dd + dt { margin-top: 0.7em; } #documentation .section { font-size: 90%; } #documentation h2.section-header { color: #333; font-size: 175%; } .documentation-section-title { position: relative; } .documentation-section-title .section-click-top { position: absolute; top: 6px; right: 12px; font-size: 10px; visibility: hidden; } .documentation-section-title:hover .section-click-top { visibility: visible; } #documentation h3.section-header { color: #333; font-size: 150%; } #constants-list > dl, #attributes-list > dl { margin: 1em 0 2em; border: 0; } #constants-list > dl dt, #attributes-list > dl dt { font-weight: bold; font-family: Monaco, "Andale Mono"; background: inherit; } #constants-list > dl dt a, #attributes-list > dl dt a { color: inherit; } #constants-list > dl dd, #attributes-list > dl dd { margin: 0 0 1em 0; color: #666; } .documentation-section h2 { position: relative; } .documentation-section h2 a { position: absolute; top: 8px; right: 10px; font-size: 12px; color: #9b9877; visibility: hidden; } .documentation-section h2:hover a { visibility: visible; } /* @group Method Details */ #documentation .method-source-code { display: none; } #documentation .method-detail { margin: 0.2em 0.2em; padding: 0.5em; } #documentation .method-detail:hover { background-color: #f5f5f5; } #documentation .method-heading { cursor: pointer; position: relative; font-size: 125%; line-height: 125%; font-weight: bold; color: #333; background: url(images/brick.png) no-repeat left bottom; padding-left: 20px; } #documentation .method-heading :link, #documentation .method-heading :visited { color: inherit; } #documentation .method-click-advice { position: absolute; right: 5px; font-size: 10px; color: #aaa; visibility: hidden; background: url(images/zoom.png) no-repeat right 5px; padding-right: 20px; overflow: show; } #documentation .method-heading:hover .method-click-advice { visibility: visible; } #documentation .method-alias .method-heading { color: #666; background: url(images/brick_link.png) no-repeat left bottom; } #documentation .method-description, #documentation .aliases { margin: 0 20px; color: #666; } #documentation .method-description p, #documentation .aliases p { line-height: 1.2em; } #documentation .aliases { font-style: italic; cursor: default; } #documentation .method-description p { margin-bottom: 0.5em; } #documentation .method-description ul { margin-left: 1.5em; } #documentation .attribute-method-heading { background: url(images/tag_green.png) no-repeat left bottom; } #documentation #attribute-method-details .method-detail:hover { background-color: transparent; cursor: default; } #documentation .attribute-access-type { font-size: 60%; text-transform: uppercase; vertical-align: super; } .method-section .method-source-code { background: white; } /* @group Source Code */ .ruby-constant .ruby-keyword .ruby-ivar .ruby-operator .ruby-identifier .ruby-node .ruby-comment .ruby-regexp .ruby-value { background: transparent; } /* Thanks GitHub!!! */ .ruby-constant { color: #458; font-weight: bold; } .ruby-keyword { color: black; font-weight: bold; } .ruby-ivar { color: teal; } .ruby-operator { color: #000; } .ruby-identifier { color: black; } .ruby-node { color: red; } .ruby-comment { color: #998; font-weight: bold; } .ruby-regexp { color: #009926; } .ruby-value { color: #099; } .ruby-string { color: red; } /* @group search results */ #search-section .section-header { margin: 0; padding: 0; } #search-results { width: 100%; list-style: none; margin: 0; padding: 0; } #search-results h1 { font-size: 1em; font-weight: normal; text-shadow: none; } #search-results .current { background: #eee; } #search-results li { list-style: none; line-height: 1em; padding: 0.5em; border-bottom: 1px solid black; } #search-results .search-namespace { font-weight: bold; } #search-results li em { background: yellow; font-style: normal; } #search-results pre { margin: 0.5em; } PK!0gems/2.2.0/gems/rack-1.6.4/contrib/rack_logo.svgnu[ image/svg+xml PK!1X_._.+gems/2.2.0/gems/rack-1.6.4/contrib/rack.svgnu[ image/svg+xml PK!Nź\\+gems/2.2.0/gems/rack-1.6.4/contrib/rack.pngnu[PNG  IHDR@@e6sRGBbKGD pHYs B(xtIME ,+( IDATxyyhB#mɎ96ƾ %8q9J;n%Zw>;ݑ;#؉LNDxBF 1k@4cʩ{nIT "\\N|pvu7p7-cߔThՄNU7 (V a}v$o0e(""}v4$x_@QvLe_#AtVE9.Q1?F0:wZ]Jhzm\BEʫ 9MjpQ]P.lEC-B"L{.`^NbB*nbh9("chl9%2c Q<)""T23Ż+>Iו%wcqnzHP]1KѴիn]CDD$u^MzC8BiYZ,"" ^fZT&~2Vo~5VQ9ykiӜWOLZa-"Ü4O0TtԎ@cf>R#At}ʌՊn3.~ů:3%WYLe^EFՋN3"~:s43cih\CuF-ИmN-"Rf %p!yI\j&62VϏ""RUTff MXfhգNrAfLCNX}\'cx7kttUU} uGX+Иg9""'H73?p53Ke^M;k9 CJ33v斴h\E:ozS*"1$VB 4I&{_; |S9=S" `!2<~\%}{N/ QI\=U`~p#D8M9A4zթڐDk""`4!Dvl!9㌈Afk)cD$)r+pJzS"r{53V'zwwよTiyj Rȉȟu*иj+HxUjʑ[hE(&j$gSV,SDN|!f9"2nZFH?խctb."` -3~P܇HR ' j&6*ШZD*ÿ"uc6-cƚ ]7Vt@,$2c .u2V|CINHxuy>`D]ɌU;a>y{+|{?Y"YƪR'[13V@$AƯ5Kff9oZ3Az>v3*۲2,D8[VNh7}m*CXAuRGѵwRHgAcuU5:aH8/~e)^Yf >G[kfnS= N4 o&CD 4VԒMD7u4d,U9cJZEe՛Lwg8""NU锱ZTxZfX<p8""MXfh'!^tTofJ03s:DD:Lh@S}BIDD0Z;> :E~ xCx`5U,ފ[EDQ.ѭN+k l<hYa7J]A}~H+ev+Ԑ_-IE |&Hwʫq>gѣ;<. 'S'D(QZ=ܺx<Œ(1~ߗe;"xϋ ^ \ua;jZ۴w^]f Ď(2At914F xO|)*9Ҭٰ.ˎ ;DDDڙFP=PN%-G@ q%:~L+ \F+J&CBDJHCH}XDD$BL]L^%d9 '!3$""9v] ]y\|G }^2At_$""(.S»^` >NH3\ `qrHgLS٭zLB0S΁9¡#]""=/~$^q~`$  Q,u4)Rw0x{|E=n\Bzܟk-|u^zNE0`.!r|F"]+چDD4M=2 4c %f%A-S]b""33Yĩ]43xXޚg ֧DDJa* US|?\)pBzi10X 2\H \?F{ܾS1RTz!7X&m=Dޒ`@sZ@U1PmԿ6 Z!.s1gڋ%?O<"^*Rbkmyx#/ѯ.{IE{Ĺs(ykUD̏ў%>=}ɌYl*"U1c|ޖQ{^uq@M`"k=O3 uvEC ϕUQG{~\RP5DhFm"ȉ05F{nMDgpE. PoX(Nl*"Y`}exCky_OuEz1HϠά躋Ds(Eua7DZHϯcPϙ,SujaH:MYJ3NrEj,B*钟% Ek\: )ÜbYA/!:>47b@v)3y evӝb$=ϖL.aiϏ \ӫ\N 3<=cg^7ۥrhj|m" "uQl/޾?j8f)@RukMqE 1jag 6f)$16)N+( K?E5!X,H&MԔ&EVy>~`5htKP$cmV̏ў%cFMx19ۥfu?ͪMdW3 ;(.\J' Y.K414kVhS,oDZ/5ݓ @4k6_%5Ò1-*0^gT@һ4kVh6=e9D-lC;RiZck6sV\[?*y]?Q_'.f:\ Ѥ/fHX 0V#C̢=n g K$Rue^d`f<6OS`_ {Pix*DNj.WТ@zSgў2{0sBl*0Ƨ7ႇ;"afB`=!Zti\ǫ*E )E6=27WQz> ? |/'9ŵe!s=Vʋ> |2 l)0&MH ҶkWJ'l/y<@fαOu@"U "-6n3jbkS)M`S`"! !%Lj<ԧOc.DHud:.>| / #N;X&` TىўV`~&;\ : vuNw/%]ֈt|y*Hh ڛY_G^8><7F .HSP;5-_Ci=K";}4Mod8o?,yhyByp)DzY _)s^ˋ s7-_`ΊQE);cth9`^J#5% qndU`8\ Py4kc~4F{Nm@ P=毣+9ڳ7ўR<@DD@_⛀KO灚n* 63A+DI<rrMkOs)AO|EG\Vm6)';B s-zHDz=ˉK Q=0/XE4842('DҬR\!tQ;lf G mge@" 9._*XgMM~Bs~O"'HD9 |76l|Z[TpnۀS%0iz9ݩ2(tH$"R \Lk_>K|P#PT0h'8dpO<2 sm\B L5Hr zdc BoQ3iK:D>zHw9x[0 s16肈ȉ| 2& >Nq<2.%D 0T-"?FD5_.ʉ˘x$ 56/:]"r(DzYQd\y_!˾DwcH ș^kFbGCwhn%԰POy%ぷS{?M eh@D4FDv.'x$iz=DH%vLD@ sfG=ZdN<Rcѷ)4Q)DgpuN\y"t # A+]f0-9H?N/u9O&&`vN]C1た x'R+z2TWl! o3QֱV;nv}|\c%`욳H\BKUDx\$*+zb}|<[HcT5)m L$m=}?p;BdO߇`2˻&hoױut!)9sQ|E+i pS<N v"kOE1ܯe馵sV=zI=cC:knåp6-ք_/yOUdE3PcRIמ ]s;.@,ѓ&gۖn_@R6zQn397eWnz&`e<k>al h p[/)DN#@iHy# pdeh|D$3ix6'>J+xs} .P/3zxG9ugvNnOx-좿(e~_$%3b]  #h/^yЏj-?6l>aWN cfل⚓b}<6xxVjӷ)0)IMh#@15=)6rvJ\c)+vGM CzSYOѓLHgKQOm#S"JQIU+Pb Ic:&ua,LIL):\ :p.:E6R5um ӷHfj5I_]&oOULUW nfR}Ds!rEҴٹ߇)I7׭]N"eCsoO]hW]: MR"$}s|3vBhN`<>F0-_/.&xR 0!! 1HwUk pNJbeS=s-0+s*g/&}ȝmH(+&ԫ2A1-Rv Q-2bMEFˡhm2/%|),f|}<c=0%0Me%Iz4XI!WZm&ho1Vu xNQ5S`㩇vi#z1{y!)Y/ a}<~P>m&DN:xVuNtP=p)] ?_6"ݠ.:sꤍ @3iŸMAa.RA+Lψ3bSR90qy$AZM(֘ F+J|֓*^6:\@CKڵ?p.Ut$'8bhs ?vGIL.H߳N]#]P K ic{Ax$P1rlo۳ɢ'u#zx !~eKCwӊc+9N]myU9U^ ܅E8BZسTbB;n p<_I[aԈD>ׯ!$Gosnἂ5PzoĖȉQ$t\ETqIU= 9~n_5:\l3!" P;cg .dxjkbǚ"R4ЋW/vw=Ww @3CO?M(^&"RWg8fවH@\.sPS.n0""Mpg<;[k9 4g&Z{n0 B~D)Ň(CD:LY1`iWοm `K0s >tzD!|D:+pUGn~hUD)(H*wIг ׀x~᪖B|>,("h!8->>A6F0x7$:鲻U.vf&DS~^np.coQPD)GrB IDAT腄{ ˖HZ7y}1z[>r7ގo]m7(" ϸ?VZcrh}Gsoxۍrg㍷씋("ioבr|zT-ZOX'0eQ5Esz+?O_\{6C3#w=yj):l/hg=m:uD3} xSry(J`-r{E/EtaSJ&ӊo 흿 ޢ'ڙ6bZD:C{NHҏ8o@ǺcZD@UR'E=.-бhsEDT%6o=(alިRuԳLecxwa,T\v(NiIꓧ]ԥ]G7(]ZRQu{1v" ^N:'x}w<@xE@ *kQ*"p9(꒧2Q5l O%Ll779 K,O u(Mư#(]RKO6Zs]"G+jM{ ?6JEN(oi1%-becxm 9nsJ@u`&XIߌs&\Dj"s%̈́\u@: :Zׁ/Jz|M@ 2)wώo:m 3 V>|ЄVDj" 9:F:uJNW \'B-u0˩4S*[+z˶u'I gWsOn?M0*o$t D$uf$ 9^$j',v_"x0ĩ$p_U|}k)dP #7MBԻv}+aSJ_7[a(Cу E$e2P$ďT_mwIrGJ9Ck LDS H(`lNj1\f%|ѡQ-%4Ip|  IMM \L+:4?F΋(־AB()"r4sy{Fz #@c7DG/XHa' Бx^,wԔ0$ub_?OZҪ_sN/s agOTzP(&wѣrJ|2Àrb Ds4C[[2S)R;^C\@gv<ѣrJC9Ls>EǛsҩ<->4`Yt`)$E ; պHf쥿hXxVbգn:"1zBZ*P]qtKt"Iuw.a%N5jw>GE6OMT#@"cF$rcLU"S)$.;踉R#@5T!:C)WiY=1T 5V7UFzWQ=2FDnN'*MZCwyL͑"udGu@%=+ #@5D?tC9.UVңHȔ1YGUx { ?|@"1`N^FuLrj)L qTxȉTO4Cwh:rBNF|4+*DO/p-Rt =n?ĩSՄ9S=vm~1oaT%9Y%]eٱNC ˕[բg iW= \&)e1Rrvk#Edpy\ݘw'j:V"]mH7E{+<&DD6(Dt~`&&r^>yஜ k1?fUxKNu=H>㲜$?UBHjTFBz.B:-"=!Ǽu-~ZѡuKNgL~6ߥ~" ЄTNLưmo%lOO#~z/h!ҳbѳ(z(@ 9-VFq1|DseۀoD1t SY"=P]3?[kHHD sQJLK /w_@7Ec[HD:>˦WT[c븝f@6BƼx[UpPC&`T@""Ѷ%r:=ۮ$NX,,/ǵz i4vvWP7m%a\_O<Eu ٗP {B;V{?4x3iCj;vE ԝM#a/޳:cԮcԾx?pFrG=_vQ)Dlk dR?Tvyފ UWyK(@"ҋԵ]f®sn>Q$pNQ>貯 .RvstWmBZYEO LD$QuNUGإ43s߉}3t?`Yέ/M::FDD*d3GК!gl?<(;y5= ~J{RHOJ]d.h,!Ty.®9Q)DDJ.п]5 k>]vP?"'BzB$"R:͉+1P2wFB.Ơ ZD^?",> ?8HHH(P!ydHDN 6o#Ժ,<o>JyO0!u#tTPTW0TDu8qט':4w)".o p)D)Q,%ZKR!tKx﫹9Bتj{IOrѦD:bV7:(fJHޚnύEX˦R=@"=Y[oFB疥mnQ{(Zξ8kSz $tߋFQN0j\#LIL~ 0M{ [4I#lts:۩㰤cK$f7.xl!Bg:]%+z* ne6Z5GH8`S=o!j"YP}$2`*'ȯXop) !uB]=*xud~a\ zsߐ7 ?hWH0`\Sc2x@1Ɲ6"G"e.00= LJ\ߍ⛄,N09q:u'm{ԜǗN+>B]gEx= H0MgB5ᵄG\"@FD`p-Bt?ߍhZBA '1*'Sz6B?W']H3\Aʻ)w~Py-pl}F^]} bUD9*U(ʋ"BQ=s}&;RsIs  me݇)Lę.HJ-&n8rtHd-& uj1ṉ́eWRU3鲽(@Q-&FUcDl1!u=]6P :J*Q)jHB*.-&-&&xpVǟSM(@ZDyedbB鲣1BwI9(_=bB .upnb;PW+۔p3Fo{ϡ*O[imMńH1v>nl:0ٯeydt#,{..h@l1!"h>BlN"9/8 ^@u8 9>:8?~)_K/'|lVv)$K#lsϔǀ@:iIz hck-R<;rg.i ٟfo<|8u ^I #~\bByddy(˶6R%{کl$jDPʡ^`y|qzEz|liVovvNq.U-{)#3vo"tٗՉtN?SՇ+A>O(kS%"5@L~ $1_͟_v@=~PptR=[9Ghїp<۰wٱXQ`\;\ 9 &.%tTH PyDxZBO;\@_7oJ`!0i vFG< # ]ԋ m5,0[YhbB~8/bth10 jtӘ.+*p-lt/H2jM) ˺_ޟt*Ҭ-:å"juK-dl}[wбnT 1ZBi/]97Au/r(D́e#OE.5Nرr1ηnDdKl7tټ kes*Q9^LF\Q5|)Mm.T|9+dģC+ճm*jof);]s.P7NV ^Q5eAѡI{W8AL.Kodvl.de P7o½aQI7C nQ-~%5M|]" Ѿ7gpma08q(R`J.:L7({N-]9u]N(@72Q5|,bGKXӬJI]"萈)]Yj*À7v7F;eR5_$R;: :3Psވ/uDjC7F觜>Pn7?p!5 8{(@c .@w@Me2a).|O9]r& [{RCn'lkOM= !,;)4lFTSE& pIun+p ,z 9cw|@$zBݡofݡRz.QI9yB;-%IӁ[[ӷk_D3K}j1>s@VJ(eDR \+d_)6P #E@ Ium8 9q_&('`%%.03P} <sJ@Fv4 Hb!+ }D@My K陨RIFj؞ K5-%QI5Jn`5+)À>B2߽5*O_y6_v:"RW*,W  SV-Fz `ib\G+:d!F94AƳl poϫu]/{t@R-YyTm:6Ry N(z"`5Օ ܾ\xSئP[ftH@=B|%!TUͳ8gQ17JM`U"<P8*z쎢5JNHä\t!Q5Y~QU4ZZ$͈'6ӝ.(YtUf^O0TqqKwӮfXLCd׫bE *HdHP !imBB<5n-p-W@"'zthy" n2%*;H$R:KTeZ q@r]ѤQC_-4m YKh)BMXG=k:e"n {]Nwx~q5_G5uDh&zG֑ eIDATHDJEQ}_l[qBSŵ;203ET= |9jITWISZ4v I;tZ HEQݟq4zY`,ܔ6$Rߏ\4- ÁZM0U1飚݈ U%`( i':iE*v2 DFןhmS.cW"i!H}3p)<*uMGL~bܾ|}בDdMQWǟF1GZua8FhԘ " ՗1蹚j`= 5fϓNHDz|th (A]Њ! CvIwFs |, y{ME\G(_um'1_$rOQ0߿G.oRҙu.-M t'MH@b߲ f>O u5A&{jOq=e4fp)DzI [_8Ci1pkq/0ޗ4Mȉd"V ~;9za F^jZYtFA:ctS`~I *8_ QQ c>:R<,?PzK=N(RhjHl!=V$\D%T_/3ş7k ߝ/!{V|v'wzSIALISXP+ SK$Dv)XF ̎r,_`._۔6$"u`+!MrPVw2BB4z bEюҍy 1$M3ZAZt佌EN&4{kMU\ÄH.P}K$Ja(&(A: "a+ [ƫ̈́\`-y\_p)D@39z&rBIО kW]}ԗ .~E$(+2tX75AH/`<>N;NBݡI ߔx!\<wHDl&4!(A DY>KP0&uL ۣoE#e*s忕tSR\^k5Hv q@lB5M=v\X/v@",&Ft}u]^>MHU;BDm-n^p)DJybM`ޫ . pi I"QiHфf< o'#>Ja_O?% I Hzs_^i~Tvل(F˚(`V\QXl(u@;UMx#1zSUN<%[R6Y~8Bf}1T$S)HT)Ju-VuTD2J:d=sH@z4@3VEL20ryJ$*SI'(RgBآ 6%HOT ) xL:@iq&P~+i7L7_'LEWǟ\߁}wPhJh8-惉}Y>[һJf iJ( S.Љ2XD0=2\f"4ZMT me>). )z0iJT z?iZ@|lp)/<, Ъ{iUf#W'EvzgvEؖ2s_p.YeUrh9e=Ōm@ >[i%R_=E3!7r5{ پG/ԪʾI$E+Mn5ޠ0WBflԛLk#)5Z;hs_f6Y.F"LDi /gK_ԫGQ6éSIh$`-P7S[0 XKg_M7f׀ޓ"2 KV 2+λ'BYIS #@ P$t[*)ͯ>[Ed Dni!{dF(HgkS("@yFӿkÃmc8jFhP3ct[3uˤW>;6HVt@ M0^_WtYm)o \ >𽄣C x#ZmP(OgkS#" v&ӪLdhCs\gdp)| ;H}Pa1t/^`]#ZrrR`_rzO V`f v&<9+^+ѡTP(#T ݄]""$9cpwI/iI. }W|PHJhsEx 6PfY!B!eeh>(q/L/<0)@|5 M]fhҥbΉQv{"^"jg6A*`gh.;ۘc3 '8S%sjD$3xSZ鼷e 68L׀8E"WJh+QA,S)ͫN0KFzCapS%"=..4ԇ o~~+"vz{0`>i6¬KcJDP;c \o Cs }g8`[M(ҍX;D-&Pl7ԔѹvGT(@N~{9Qq)VJ@\Bs iDqH4Z\I4:+_ʷi ɺ"MVNHԏ?NA?QAXl)='8.3,LHH}S%W0Z<:z3uKEH6{" 96y3 -3KqKEH$g:U" y?Lfn~N)p^Ϲ|$FjQ՗O'Mpa"G#oޞ zS%~ԦV;n 3>ϧ)ӴSY7qD@2 Y; w<Žn כhRk}M,NqD@2 y3ujRQL} i:Ū^y#<{hpD@2 Y)!}@69ҍ%ni:U" )ԩZBh4ؿ,dR&ڔE@2TqZ,R6RS S8`VILїUN4R(\C_""v$FI3ϼ8өQQ95>N)KRF>BzQduW.'I':U" 9*C~- ^jwi1x/g\e?;Rgz-#N(@rL-x;ri n9^ZF곜*Q)䘌N,M%oޏFjԍˀu9|+B*jyJbh-#iN4 MRG6:k^{0O(gT\zziE6V N(a~Vխ[z 't_{ʬwvPfDDzS% ~teўCp)EdO%&v2RtD<ӢyA=" R7R/'4R+@i0$U:)N3}iV)}>,.?B l""]'e#ABj)pSh]=YLy/"Us.iWM@rLYCF*X`YRy&>-MN+#T֨12ĊAQTOaqY'wDgǙs|?ɔdw9s%i$ _%˗6+`NZjxϞn^~I>HZ* :D si۳!VQQ^zxXPC(ib{l<ݓKyA gY =`4HDK Rے7yN>`HREBPYᚺ=u.IjAszJ AhHTr4UzCeTT~Qr$Uz@Cq Fݞe&~67C*6X:_#It8@An,WSN{I*AV3* (֒OdnӤ%F=$HyRҥha9;lGb9%Ij uΝs;]pp=g, XIAAꜧZLF񱥆o)޻$R~RiA QINIJiL>:$YAv>H-$IjjR>-|>vM.IԶE. hE5R$IꆭK,|/:V$IY&ܜ%O1!$IukW5y%IR6D|v0RIc'hmGS($I.nF)9`K$p$k.XiҎԒ$I$I$I$I$I$i nsIENDB`PK!u355"gems/2.2.0/gems/rack-1.6.4/COPYINGnu[Copyright (c) 2007-2015 Christian Neukirchen Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. PK!ێY Y &gems/2.2.0/gems/rack-1.6.4/lib/rack.rbnu[# Copyright (C) 2007, 2008, 2009, 2010 Christian Neukirchen # # Rack is freely distributable under the terms of an MIT-style license. # See COPYING or http://www.opensource.org/licenses/mit-license.php. # The Rack main module, serving as a namespace for all core Rack # modules and classes. # # All modules meant for use in your application are autoloaded here, # so it should be enough just to require rack.rb in your code. module Rack # The Rack protocol version number implemented. VERSION = [1,3] # Return the Rack protocol version as a dotted string. def self.version VERSION.join(".") end # Return the Rack release as a dotted string. def self.release "1.6.4" end PATH_INFO = 'PATH_INFO'.freeze REQUEST_METHOD = 'REQUEST_METHOD'.freeze SCRIPT_NAME = 'SCRIPT_NAME'.freeze QUERY_STRING = 'QUERY_STRING'.freeze CACHE_CONTROL = 'Cache-Control'.freeze CONTENT_LENGTH = 'Content-Length'.freeze CONTENT_TYPE = 'Content-Type'.freeze GET = 'GET'.freeze HEAD = 'HEAD'.freeze autoload :Builder, "rack/builder" autoload :BodyProxy, "rack/body_proxy" autoload :Cascade, "rack/cascade" autoload :Chunked, "rack/chunked" autoload :CommonLogger, "rack/commonlogger" autoload :ConditionalGet, "rack/conditionalget" autoload :Config, "rack/config" autoload :ContentLength, "rack/content_length" autoload :ContentType, "rack/content_type" autoload :ETag, "rack/etag" autoload :File, "rack/file" autoload :Deflater, "rack/deflater" autoload :Directory, "rack/directory" autoload :ForwardRequest, "rack/recursive" autoload :Handler, "rack/handler" autoload :Head, "rack/head" autoload :Lint, "rack/lint" autoload :Lock, "rack/lock" autoload :Logger, "rack/logger" autoload :MethodOverride, "rack/methodoverride" autoload :Mime, "rack/mime" autoload :NullLogger, "rack/nulllogger" autoload :Recursive, "rack/recursive" autoload :Reloader, "rack/reloader" autoload :Runtime, "rack/runtime" autoload :Sendfile, "rack/sendfile" autoload :Server, "rack/server" autoload :ShowExceptions, "rack/showexceptions" autoload :ShowStatus, "rack/showstatus" autoload :Static, "rack/static" autoload :TempfileReaper, "rack/tempfile_reaper" autoload :URLMap, "rack/urlmap" autoload :Utils, "rack/utils" autoload :Multipart, "rack/multipart" autoload :MockRequest, "rack/mock" autoload :MockResponse, "rack/mock" autoload :Request, "rack/request" autoload :Response, "rack/response" module Auth autoload :Basic, "rack/auth/basic" autoload :AbstractRequest, "rack/auth/abstract/request" autoload :AbstractHandler, "rack/auth/abstract/handler" module Digest autoload :MD5, "rack/auth/digest/md5" autoload :Nonce, "rack/auth/digest/nonce" autoload :Params, "rack/auth/digest/params" autoload :Request, "rack/auth/digest/request" end end module Session autoload :Cookie, "rack/session/cookie" autoload :Pool, "rack/session/pool" autoload :Memcache, "rack/session/memcache" end module Utils autoload :OkJson, "rack/utils/okjson" end end PK!oGOO.gems/2.2.0/gems/rack-1.6.4/lib/rack/chunked.rbnu[require 'rack/utils' module Rack # Middleware that applies chunked transfer encoding to response bodies # when the response does not include a Content-Length header. class Chunked include Rack::Utils # A body wrapper that emits chunked responses class Body TERM = "\r\n" TAIL = "0#{TERM}#{TERM}" include Rack::Utils def initialize(body) @body = body end def each term = TERM @body.each do |chunk| size = bytesize(chunk) next if size == 0 chunk = chunk.dup.force_encoding(Encoding::BINARY) if chunk.respond_to?(:force_encoding) yield [size.to_s(16), term, chunk, term].join end yield TAIL end def close @body.close if @body.respond_to?(:close) end end def initialize(app) @app = app end # pre-HTTP/1.0 (informally "HTTP/0.9") HTTP requests did not have # a version (nor response headers) def chunkable_version?(ver) case ver when "HTTP/1.0", nil, "HTTP/0.9" false else true end end def call(env) status, headers, body = @app.call(env) headers = HeaderHash.new(headers) if ! chunkable_version?(env['HTTP_VERSION']) || STATUS_WITH_NO_ENTITY_BODY.include?(status) || headers[CONTENT_LENGTH] || headers['Transfer-Encoding'] [status, headers, body] else headers.delete(CONTENT_LENGTH) headers['Transfer-Encoding'] = 'chunked' [status, headers, Body.new(body)] end end end end PK!  3gems/2.2.0/gems/rack-1.6.4/lib/rack/handler/scgi.rbnu[require 'scgi' require 'stringio' require 'rack/content_length' require 'rack/chunked' module Rack module Handler class SCGI < ::SCGI::Processor attr_accessor :app def self.run(app, options=nil) options[:Socket] = UNIXServer.new(options[:File]) if options[:File] new(options.merge(:app=>app, :host=>options[:Host], :port=>options[:Port], :socket=>options[:Socket])).listen end def self.valid_options environment = ENV['RACK_ENV'] || 'development' default_host = environment == 'development' ? 'localhost' : '0.0.0.0' { "Host=HOST" => "Hostname to listen on (default: #{default_host})", "Port=PORT" => "Port to listen on (default: 8080)", } end def initialize(settings = {}) @app = settings[:app] super(settings) end def process_request(request, input_body, socket) env = Hash[request] env.delete "HTTP_CONTENT_TYPE" env.delete "HTTP_CONTENT_LENGTH" env["REQUEST_PATH"], env[QUERY_STRING] = env["REQUEST_URI"].split('?', 2) env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"] env[PATH_INFO] = env["REQUEST_PATH"] env["QUERY_STRING"] ||= "" env["SCRIPT_NAME"] = "" rack_input = StringIO.new(input_body) rack_input.set_encoding(Encoding::BINARY) if rack_input.respond_to?(:set_encoding) env.update({"rack.version" => Rack::VERSION, "rack.input" => rack_input, "rack.errors" => $stderr, "rack.multithread" => true, "rack.multiprocess" => true, "rack.run_once" => false, "rack.url_scheme" => ["yes", "on", "1"].include?(env["HTTPS"]) ? "https" : "http" }) status, headers, body = app.call(env) begin socket.write("Status: #{status}\r\n") headers.each do |k, vs| vs.split("\n").each { |v| socket.write("#{k}: #{v}\r\n")} end socket.write("\r\n") body.each {|s| socket.write(s)} ensure body.close if body.respond_to? :close end end end end end PK!  3gems/2.2.0/gems/rack-1.6.4/lib/rack/handler/thin.rbnu[require "thin" require "rack/content_length" require "rack/chunked" module Rack module Handler class Thin def self.run(app, options={}) environment = ENV['RACK_ENV'] || 'development' default_host = environment == 'development' ? 'localhost' : '0.0.0.0' host = options.delete(:Host) || default_host port = options.delete(:Port) || 8080 args = [host, port, app, options] # Thin versions below 0.8.0 do not support additional options args.pop if ::Thin::VERSION::MAJOR < 1 && ::Thin::VERSION::MINOR < 8 server = ::Thin::Server.new(*args) yield server if block_given? server.start end def self.valid_options environment = ENV['RACK_ENV'] || 'development' default_host = environment == 'development' ? 'localhost' : '0.0.0.0' { "Host=HOST" => "Hostname to listen on (default: #{default_host})", "Port=PORT" => "Port to listen on (default: 8080)", } end end end end PK!R))3gems/2.2.0/gems/rack-1.6.4/lib/rack/handler/lsws.rbnu[require 'lsapi' require 'rack/content_length' require 'rack/rewindable_input' module Rack module Handler class LSWS def self.run(app, options=nil) while LSAPI.accept != nil serve app end end def self.serve(app) env = ENV.to_hash env.delete "HTTP_CONTENT_LENGTH" env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/" rack_input = RewindableInput.new($stdin.read.to_s) env.update( "rack.version" => Rack::VERSION, "rack.input" => rack_input, "rack.errors" => $stderr, "rack.multithread" => false, "rack.multiprocess" => true, "rack.run_once" => false, "rack.url_scheme" => ["yes", "on", "1"].include?(ENV["HTTPS"]) ? "https" : "http" ) env[QUERY_STRING] ||= "" env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"] env["REQUEST_PATH"] ||= "/" status, headers, body = app.call(env) begin send_headers status, headers send_body body ensure body.close if body.respond_to? :close end ensure rack_input.close end def self.send_headers(status, headers) print "Status: #{status}\r\n" headers.each { |k, vs| vs.split("\n").each { |v| print "#{k}: #{v}\r\n" } } print "\r\n" STDOUT.flush end def self.send_body(body) body.each { |part| print part STDOUT.flush } end end end end PK!@>gems/2.2.0/gems/rack-1.6.4/lib/rack/handler/evented_mongrel.rbnu[require 'swiftcore/evented_mongrel' module Rack module Handler class EventedMongrel < Handler::Mongrel end end end PK!J; 6gems/2.2.0/gems/rack-1.6.4/lib/rack/handler/fastcgi.rbnu[require 'fcgi' require 'socket' require 'rack/content_length' require 'rack/rewindable_input' if defined? FCGI::Stream class FCGI::Stream alias _rack_read_without_buffer read def read(n, buffer=nil) buf = _rack_read_without_buffer n buffer.replace(buf.to_s) if buffer buf end end end module Rack module Handler class FastCGI def self.run(app, options={}) if options[:File] STDIN.reopen(UNIXServer.new(options[:File])) elsif options[:Port] STDIN.reopen(TCPServer.new(options[:Host], options[:Port])) end FCGI.each { |request| serve request, app } end def self.valid_options environment = ENV['RACK_ENV'] || 'development' default_host = environment == 'development' ? 'localhost' : '0.0.0.0' { "Host=HOST" => "Hostname to listen on (default: #{default_host})", "Port=PORT" => "Port to listen on (default: 8080)", "File=PATH" => "Creates a Domain socket at PATH instead of a TCP socket. Ignores Host and Port if set.", } end def self.serve(request, app) env = request.env env.delete "HTTP_CONTENT_LENGTH" env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/" rack_input = RewindableInput.new(request.in) env.update({"rack.version" => Rack::VERSION, "rack.input" => rack_input, "rack.errors" => request.err, "rack.multithread" => false, "rack.multiprocess" => true, "rack.run_once" => false, "rack.url_scheme" => ["yes", "on", "1"].include?(env["HTTPS"]) ? "https" : "http" }) env[QUERY_STRING] ||= "" env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"] env["REQUEST_PATH"] ||= "/" env.delete "CONTENT_TYPE" if env["CONTENT_TYPE"] == "" env.delete "CONTENT_LENGTH" if env["CONTENT_LENGTH"] == "" begin status, headers, body = app.call(env) begin send_headers request.out, status, headers send_body request.out, body ensure body.close if body.respond_to? :close end ensure rack_input.close request.finish end end def self.send_headers(out, status, headers) out.print "Status: #{status}\r\n" headers.each { |k, vs| vs.split("\n").each { |v| out.print "#{k}: #{v}\r\n" } } out.print "\r\n" out.flush end def self.send_body(out, body) body.each { |part| out.print part out.flush } end end end end PK!t""2gems/2.2.0/gems/rack-1.6.4/lib/rack/handler/cgi.rbnu[require 'rack/content_length' require 'rack/rewindable_input' module Rack module Handler class CGI def self.run(app, options=nil) $stdin.binmode serve app end def self.serve(app) env = ENV.to_hash env.delete "HTTP_CONTENT_LENGTH" env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/" env.update({"rack.version" => Rack::VERSION, "rack.input" => Rack::RewindableInput.new($stdin), "rack.errors" => $stderr, "rack.multithread" => false, "rack.multiprocess" => true, "rack.run_once" => true, "rack.url_scheme" => ["yes", "on", "1"].include?(ENV["HTTPS"]) ? "https" : "http" }) env[QUERY_STRING] ||= "" env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"] env["REQUEST_PATH"] ||= "/" status, headers, body = app.call(env) begin send_headers status, headers send_body body ensure body.close if body.respond_to? :close end end def self.send_headers(status, headers) $stdout.print "Status: #{status}\r\n" headers.each { |k, vs| vs.split("\n").each { |v| $stdout.print "#{k}: #{v}\r\n" } } $stdout.print "\r\n" $stdout.flush end def self.send_body(body) body.each { |part| $stdout.print part $stdout.flush } end end end end PK!ՀRYBgems/2.2.0/gems/rack-1.6.4/lib/rack/handler/swiftiplied_mongrel.rbnu[require 'swiftcore/swiftiplied_mongrel' module Rack module Handler class SwiftipliedMongrel < Handler::Mongrel end end end PK!_x6gems/2.2.0/gems/rack-1.6.4/lib/rack/handler/webrick.rbnu[require 'webrick' require 'stringio' require 'rack/content_length' # This monkey patch allows for applications to perform their own chunking # through WEBrick::HTTPResponse iff rack is set to true. class WEBrick::HTTPResponse attr_accessor :rack alias _rack_setup_header setup_header def setup_header app_chunking = rack && @header['transfer-encoding'] == 'chunked' @chunked = app_chunking if app_chunking _rack_setup_header @chunked = false if app_chunking end end module Rack module Handler class WEBrick < ::WEBrick::HTTPServlet::AbstractServlet def self.run(app, options={}) environment = ENV['RACK_ENV'] || 'development' default_host = environment == 'development' ? 'localhost' : '0.0.0.0' options[:BindAddress] = options.delete(:Host) || default_host options[:Port] ||= 8080 @server = ::WEBrick::HTTPServer.new(options) @server.mount "/", Rack::Handler::WEBrick, app yield @server if block_given? @server.start end def self.valid_options environment = ENV['RACK_ENV'] || 'development' default_host = environment == 'development' ? 'localhost' : '0.0.0.0' { "Host=HOST" => "Hostname to listen on (default: #{default_host})", "Port=PORT" => "Port to listen on (default: 8080)", } end def self.shutdown @server.shutdown @server = nil end def initialize(server, app) super server @app = app end def service(req, res) res.rack = true env = req.meta_vars env.delete_if { |k, v| v.nil? } rack_input = StringIO.new(req.body.to_s) rack_input.set_encoding(Encoding::BINARY) if rack_input.respond_to?(:set_encoding) env.update({"rack.version" => Rack::VERSION, "rack.input" => rack_input, "rack.errors" => $stderr, "rack.multithread" => true, "rack.multiprocess" => false, "rack.run_once" => false, "rack.url_scheme" => ["yes", "on", "1"].include?(env["HTTPS"]) ? "https" : "http", "rack.hijack?" => true, "rack.hijack" => lambda { raise NotImplementedError, "only partial hijack is supported."}, "rack.hijack_io" => nil, }) env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"] env[QUERY_STRING] ||= "" unless env[PATH_INFO] == "" path, n = req.request_uri.path, env["SCRIPT_NAME"].length env[PATH_INFO] = path[n, path.length-n] end env["REQUEST_PATH"] ||= [env["SCRIPT_NAME"], env[PATH_INFO]].join status, headers, body = @app.call(env) begin res.status = status.to_i headers.each { |k, vs| next if k.downcase == "rack.hijack" if k.downcase == "set-cookie" res.cookies.concat vs.split("\n") else # Since WEBrick won't accept repeated headers, # merge the values per RFC 1945 section 4.2. res[k] = vs.split("\n").join(", ") end } io_lambda = headers["rack.hijack"] if io_lambda rd, wr = IO.pipe res.body = rd res.chunked = true io_lambda.call wr elsif body.respond_to?(:to_path) res.body = ::File.open(body.to_path, 'rb') else body.each { |part| res.body << part } end ensure body.close if body.respond_to? :close end end end end end PK!q9KK6gems/2.2.0/gems/rack-1.6.4/lib/rack/handler/mongrel.rbnu[require 'mongrel' require 'stringio' require 'rack/content_length' require 'rack/chunked' module Rack module Handler class Mongrel < ::Mongrel::HttpHandler def self.run(app, options={}) environment = ENV['RACK_ENV'] || 'development' default_host = environment == 'development' ? 'localhost' : '0.0.0.0' server = ::Mongrel::HttpServer.new( options[:Host] || default_host, options[:Port] || 8080, options[:num_processors] || 950, options[:throttle] || 0, options[:timeout] || 60) # Acts like Rack::URLMap, utilizing Mongrel's own path finding methods. # Use is similar to #run, replacing the app argument with a hash of # { path=>app, ... } or an instance of Rack::URLMap. if options[:map] if app.is_a? Hash app.each do |path, appl| path = '/'+path unless path[0] == ?/ server.register(path, Rack::Handler::Mongrel.new(appl)) end elsif app.is_a? URLMap app.instance_variable_get(:@mapping).each do |(host, path, appl)| next if !host.nil? && !options[:Host].nil? && options[:Host] != host path = '/'+path unless path[0] == ?/ server.register(path, Rack::Handler::Mongrel.new(appl)) end else raise ArgumentError, "first argument should be a Hash or URLMap" end else server.register('/', Rack::Handler::Mongrel.new(app)) end yield server if block_given? server.run.join end def self.valid_options environment = ENV['RACK_ENV'] || 'development' default_host = environment == 'development' ? 'localhost' : '0.0.0.0' { "Host=HOST" => "Hostname to listen on (default: #{default_host})", "Port=PORT" => "Port to listen on (default: 8080)", "Processors=N" => "Number of concurrent processors to accept (default: 950)", "Timeout=N" => "Time before a request is dropped for inactivity (default: 60)", "Throttle=N" => "Throttle time between socket.accept calls in hundredths of a second (default: 0)", } end def initialize(app) @app = app end def process(request, response) env = Hash[request.params] env.delete "HTTP_CONTENT_TYPE" env.delete "HTTP_CONTENT_LENGTH" env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/" rack_input = request.body || StringIO.new('') rack_input.set_encoding(Encoding::BINARY) if rack_input.respond_to?(:set_encoding) env.update({"rack.version" => Rack::VERSION, "rack.input" => rack_input, "rack.errors" => $stderr, "rack.multithread" => true, "rack.multiprocess" => false, # ??? "rack.run_once" => false, "rack.url_scheme" => ["yes", "on", "1"].include?(env["HTTPS"]) ? "https" : "http" }) env[QUERY_STRING] ||= "" status, headers, body = @app.call(env) begin response.status = status.to_i response.send_status(nil) headers.each { |k, vs| vs.split("\n").each { |v| response.header[k] = v } } response.send_header body.each { |part| response.write part response.socket.flush } ensure body.close if body.respond_to? :close end end end end end PK!6\2\2.gems/2.2.0/gems/rack-1.6.4/lib/rack/request.rbnu[require 'rack/utils' module Rack # Rack::Request provides a convenient interface to a Rack # environment. It is stateless, the environment +env+ passed to the # constructor will be directly modified. # # req = Rack::Request.new(env) # req.post? # req.params["data"] class Request # The environment of the request. attr_reader :env def initialize(env) @env = env end def body; @env["rack.input"] end def script_name; @env[SCRIPT_NAME].to_s end def path_info; @env[PATH_INFO].to_s end def request_method; @env["REQUEST_METHOD"] end def query_string; @env[QUERY_STRING].to_s end def content_length; @env['CONTENT_LENGTH'] end def content_type content_type = @env['CONTENT_TYPE'] content_type.nil? || content_type.empty? ? nil : content_type end def session; @env['rack.session'] ||= {} end def session_options; @env['rack.session.options'] ||= {} end def logger; @env['rack.logger'] end # The media type (type/subtype) portion of the CONTENT_TYPE header # without any media type parameters. e.g., when CONTENT_TYPE is # "text/plain;charset=utf-8", the media-type is "text/plain". # # For more information on the use of media types in HTTP, see: # http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7 def media_type content_type && content_type.split(/\s*[;,]\s*/, 2).first.downcase end # The media type parameters provided in CONTENT_TYPE as a Hash, or # an empty Hash if no CONTENT_TYPE or media-type parameters were # provided. e.g., when the CONTENT_TYPE is "text/plain;charset=utf-8", # this method responds with the following Hash: # { 'charset' => 'utf-8' } def media_type_params return {} if content_type.nil? Hash[*content_type.split(/\s*[;,]\s*/)[1..-1]. collect { |s| s.split('=', 2) }. map { |k,v| [k.downcase, strip_doublequotes(v)] }.flatten] end # The character set of the request body if a "charset" media type # parameter was given, or nil if no "charset" was specified. Note # that, per RFC2616, text/* media types that specify no explicit # charset are to be considered ISO-8859-1. def content_charset media_type_params['charset'] end def scheme if @env['HTTPS'] == 'on' 'https' elsif @env['HTTP_X_FORWARDED_SSL'] == 'on' 'https' elsif @env['HTTP_X_FORWARDED_SCHEME'] @env['HTTP_X_FORWARDED_SCHEME'] elsif @env['HTTP_X_FORWARDED_PROTO'] @env['HTTP_X_FORWARDED_PROTO'].split(',')[0] else @env["rack.url_scheme"] end end def ssl? scheme == 'https' end def host_with_port if forwarded = @env["HTTP_X_FORWARDED_HOST"] forwarded.split(/,\s?/).last else @env['HTTP_HOST'] || "#{@env['SERVER_NAME'] || @env['SERVER_ADDR']}:#{@env['SERVER_PORT']}" end end def port if port = host_with_port.split(/:/)[1] port.to_i elsif port = @env['HTTP_X_FORWARDED_PORT'] port.to_i elsif @env.has_key?("HTTP_X_FORWARDED_HOST") DEFAULT_PORTS[scheme] elsif @env.has_key?("HTTP_X_FORWARDED_PROTO") DEFAULT_PORTS[@env['HTTP_X_FORWARDED_PROTO'].split(',')[0]] else @env["SERVER_PORT"].to_i end end def host # Remove port number. host_with_port.to_s.sub(/:\d+\z/, '') end def script_name=(s); @env["SCRIPT_NAME"] = s.to_s end def path_info=(s); @env["PATH_INFO"] = s.to_s end # Checks the HTTP request method (or verb) to see if it was of type DELETE def delete?; request_method == "DELETE" end # Checks the HTTP request method (or verb) to see if it was of type GET def get?; request_method == GET end # Checks the HTTP request method (or verb) to see if it was of type HEAD def head?; request_method == HEAD end # Checks the HTTP request method (or verb) to see if it was of type OPTIONS def options?; request_method == "OPTIONS" end # Checks the HTTP request method (or verb) to see if it was of type LINK def link?; request_method == "LINK" end # Checks the HTTP request method (or verb) to see if it was of type PATCH def patch?; request_method == "PATCH" end # Checks the HTTP request method (or verb) to see if it was of type POST def post?; request_method == "POST" end # Checks the HTTP request method (or verb) to see if it was of type PUT def put?; request_method == "PUT" end # Checks the HTTP request method (or verb) to see if it was of type TRACE def trace?; request_method == "TRACE" end # Checks the HTTP request method (or verb) to see if it was of type UNLINK def unlink?; request_method == "UNLINK" end # The set of form-data media-types. Requests that do not indicate # one of the media types presents in this list will not be eligible # for form-data / param parsing. FORM_DATA_MEDIA_TYPES = [ 'application/x-www-form-urlencoded', 'multipart/form-data' ] # The set of media-types. Requests that do not indicate # one of the media types presents in this list will not be eligible # for param parsing like soap attachments or generic multiparts PARSEABLE_DATA_MEDIA_TYPES = [ 'multipart/related', 'multipart/mixed' ] # Default ports depending on scheme. Used to decide whether or not # to include the port in a generated URI. DEFAULT_PORTS = { 'http' => 80, 'https' => 443, 'coffee' => 80 } # Determine whether the request body contains form-data by checking # the request Content-Type for one of the media-types: # "application/x-www-form-urlencoded" or "multipart/form-data". The # list of form-data media types can be modified through the # +FORM_DATA_MEDIA_TYPES+ array. # # A request body is also assumed to contain form-data when no # Content-Type header is provided and the request_method is POST. def form_data? type = media_type meth = env["rack.methodoverride.original_method"] || env[REQUEST_METHOD] (meth == 'POST' && type.nil?) || FORM_DATA_MEDIA_TYPES.include?(type) end # Determine whether the request body contains data by checking # the request media_type against registered parse-data media-types def parseable_data? PARSEABLE_DATA_MEDIA_TYPES.include?(media_type) end # Returns the data received in the query string. def GET if @env["rack.request.query_string"] == query_string @env["rack.request.query_hash"] else p = parse_query({ :query => query_string, :separator => '&;' }) @env["rack.request.query_string"] = query_string @env["rack.request.query_hash"] = p end end # Returns the data received in the request body. # # This method support both application/x-www-form-urlencoded and # multipart/form-data. def POST if @env["rack.input"].nil? raise "Missing rack.input" elsif @env["rack.request.form_input"].equal? @env["rack.input"] @env["rack.request.form_hash"] elsif form_data? || parseable_data? unless @env["rack.request.form_hash"] = parse_multipart(env) form_vars = @env["rack.input"].read # Fix for Safari Ajax postings that always append \0 # form_vars.sub!(/\0\z/, '') # performance replacement: form_vars.slice!(-1) if form_vars[-1] == ?\0 @env["rack.request.form_vars"] = form_vars @env["rack.request.form_hash"] = parse_query({ :query => form_vars, :separator => '&' }) @env["rack.input"].rewind end @env["rack.request.form_input"] = @env["rack.input"] @env["rack.request.form_hash"] else {} end end # The union of GET and POST data. # # Note that modifications will not be persisted in the env. Use update_param or delete_param if you want to destructively modify params. def params @params ||= self.GET.merge(self.POST) rescue EOFError self.GET.dup end # Destructively update a parameter, whether it's in GET and/or POST. Returns nil. # # The parameter is updated wherever it was previous defined, so GET, POST, or both. If it wasn't previously defined, it's inserted into GET. # # env['rack.input'] is not touched. def update_param(k, v) found = false if self.GET.has_key?(k) found = true self.GET[k] = v end if self.POST.has_key?(k) found = true self.POST[k] = v end unless found self.GET[k] = v end @params = nil nil end # Destructively delete a parameter, whether it's in GET or POST. Returns the value of the deleted parameter. # # If the parameter is in both GET and POST, the POST value takes precedence since that's how #params works. # # env['rack.input'] is not touched. def delete_param(k) v = [ self.POST.delete(k), self.GET.delete(k) ].compact.first @params = nil v end # shortcut for request.params[key] def [](key) params[key.to_s] end # shortcut for request.params[key] = value # # Note that modifications will not be persisted in the env. Use update_param or delete_param if you want to destructively modify params. def []=(key, value) params[key.to_s] = value end # like Hash#values_at def values_at(*keys) keys.map{|key| params[key] } end # the referer of the client def referer @env['HTTP_REFERER'] end alias referrer referer def user_agent @env['HTTP_USER_AGENT'] end def cookies hash = @env["rack.request.cookie_hash"] ||= {} string = @env["HTTP_COOKIE"] return hash if string == @env["rack.request.cookie_string"] hash.clear # According to RFC 2109: # If multiple cookies satisfy the criteria above, they are ordered in # the Cookie header such that those with more specific Path attributes # precede those with less specific. Ordering with respect to other # attributes (e.g., Domain) is unspecified. cookies = Utils.parse_query(string, ';,') { |s| Rack::Utils.unescape(s) rescue s } cookies.each { |k,v| hash[k] = Array === v ? v.first : v } @env["rack.request.cookie_string"] = string hash end def xhr? @env["HTTP_X_REQUESTED_WITH"] == "XMLHttpRequest" end def base_url url = "#{scheme}://#{host}" url << ":#{port}" if port != DEFAULT_PORTS[scheme] url end # Tries to return a remake of the original request URL as a string. def url base_url + fullpath end def path script_name + path_info end def fullpath query_string.empty? ? path : "#{path}?#{query_string}" end def accept_encoding parse_http_accept_header(@env["HTTP_ACCEPT_ENCODING"]) end def accept_language parse_http_accept_header(@env["HTTP_ACCEPT_LANGUAGE"]) end def trusted_proxy?(ip) ip =~ /\A127\.0\.0\.1\Z|\A(10|172\.(1[6-9]|2[0-9]|30|31)|192\.168)\.|\A::1\Z|\Afd[0-9a-f]{2}:.+|\Alocalhost\Z|\Aunix\Z|\Aunix:/i end def ip remote_addrs = split_ip_addresses(@env['REMOTE_ADDR']) remote_addrs = reject_trusted_ip_addresses(remote_addrs) return remote_addrs.first if remote_addrs.any? forwarded_ips = split_ip_addresses(@env['HTTP_X_FORWARDED_FOR']) return reject_trusted_ip_addresses(forwarded_ips).last || @env["REMOTE_ADDR"] end protected def split_ip_addresses(ip_addresses) ip_addresses ? ip_addresses.strip.split(/[,\s]+/) : [] end def reject_trusted_ip_addresses(ip_addresses) ip_addresses.reject { |ip| trusted_proxy?(ip) } end def parse_query(qs) d = '&' qs, d = qs[:query], qs[:separator] if Hash === qs Utils.parse_nested_query(qs, d) end def parse_multipart(env) Rack::Multipart.parse_multipart(env) end def parse_http_accept_header(header) header.to_s.split(/\s*,\s*/).map do |part| attribute, parameters = part.split(/\s*;\s*/, 2) quality = 1.0 if parameters and /\Aq=([\d.]+)/ =~ parameters quality = $1.to_f end [attribute, quality] end end private def strip_doublequotes(s) if s[0] == ?" && s[-1] == ?" s[1..-2] else s end end end end PK!jaLL/gems/2.2.0/gems/rack-1.6.4/lib/rack/deflater.rbnu[require "zlib" require "time" # for Time.httpdate require 'rack/utils' module Rack # This middleware enables compression of http responses. # # Currently supported compression algorithms: # # * gzip # * deflate # * identity (no transformation) # # The middleware automatically detects when compression is supported # and allowed. For example no transformation is made when a cache # directive of 'no-transform' is present, or when the response status # code is one that doesn't allow an entity body. class Deflater ## # Creates Rack::Deflater middleware. # # [app] rack app instance # [options] hash of deflater options, i.e. # 'if' - a lambda enabling / disabling deflation based on returned boolean value # e.g use Rack::Deflater, :if => lambda { |env, status, headers, body| body.length > 512 } # 'include' - a list of content types that should be compressed def initialize(app, options = {}) @app = app @condition = options[:if] @compressible_types = options[:include] end def call(env) status, headers, body = @app.call(env) headers = Utils::HeaderHash.new(headers) unless should_deflate?(env, status, headers, body) return [status, headers, body] end request = Request.new(env) encoding = Utils.select_best_encoding(%w(gzip deflate identity), request.accept_encoding) # Set the Vary HTTP header. vary = headers["Vary"].to_s.split(",").map { |v| v.strip } unless vary.include?("*") || vary.include?("Accept-Encoding") headers["Vary"] = vary.push("Accept-Encoding").join(",") end case encoding when "gzip" headers['Content-Encoding'] = "gzip" headers.delete(CONTENT_LENGTH) mtime = headers.key?("Last-Modified") ? Time.httpdate(headers["Last-Modified"]) : Time.now [status, headers, GzipStream.new(body, mtime)] when "deflate" headers['Content-Encoding'] = "deflate" headers.delete(CONTENT_LENGTH) [status, headers, DeflateStream.new(body)] when "identity" [status, headers, body] when nil message = "An acceptable encoding for the requested resource #{request.fullpath} could not be found." bp = Rack::BodyProxy.new([message]) { body.close if body.respond_to?(:close) } [406, {CONTENT_TYPE => "text/plain", CONTENT_LENGTH => message.length.to_s}, bp] end end class GzipStream def initialize(body, mtime) @body = body @mtime = mtime @closed = false end def each(&block) @writer = block gzip =::Zlib::GzipWriter.new(self) gzip.mtime = @mtime @body.each { |part| gzip.write(part) gzip.flush } ensure gzip.close @writer = nil end def write(data) @writer.call(data) end def close return if @closed @closed = true @body.close if @body.respond_to?(:close) end end class DeflateStream DEFLATE_ARGS = [ Zlib::DEFAULT_COMPRESSION, # drop the zlib header which causes both Safari and IE to choke -Zlib::MAX_WBITS, Zlib::DEF_MEM_LEVEL, Zlib::DEFAULT_STRATEGY ] def initialize(body) @body = body @closed = false end def each deflator = ::Zlib::Deflate.new(*DEFLATE_ARGS) @body.each { |part| yield deflator.deflate(part, Zlib::SYNC_FLUSH) } yield deflator.finish nil ensure deflator.close end def close return if @closed @closed = true @body.close if @body.respond_to?(:close) end end private def should_deflate?(env, status, headers, body) # Skip compressing empty entity body responses and responses with # no-transform set. if Utils::STATUS_WITH_NO_ENTITY_BODY.include?(status) || headers[CACHE_CONTROL].to_s =~ /\bno-transform\b/ || (headers['Content-Encoding'] && headers['Content-Encoding'] !~ /\bidentity\b/) return false end # Skip if @compressible_types are given and does not include request's content type return false if @compressible_types && !(headers.has_key?('Content-Type') && @compressible_types.include?(headers['Content-Type'][/[^;]*/])) # Skip if @condition lambda is given and evaluates to false return false if @condition && !@condition.call(env, status, headers, body) true end end end PK!o7.gems/2.2.0/gems/rack-1.6.4/lib/rack/runtime.rbnu[module Rack # Sets an "X-Runtime" response header, indicating the response # time of the request, in seconds # # You can put it right before the application to see the processing # time, or before all the other middlewares to include time for them, # too. class Runtime def initialize(app, name = nil) @app = app @header_name = "X-Runtime" @header_name << "-#{name}" if name end FORMAT_STRING = "%0.6f" def call(env) start_time = clock_time status, headers, body = @app.call(env) request_time = clock_time - start_time if !headers.has_key?(@header_name) headers[@header_name] = FORMAT_STRING % request_time end [status, headers, body] end private if defined?(Process::CLOCK_MONOTONIC) def clock_time Process.clock_gettime(Process::CLOCK_MONOTONIC) end else def clock_time Time.now.to_f end end end end PK!o^ .gems/2.2.0/gems/rack-1.6.4/lib/rack/handler.rbnu[module Rack # *Handlers* connect web servers with Rack. # # Rack includes Handlers for Thin, WEBrick, FastCGI, CGI, SCGI # and LiteSpeed. # # Handlers usually are activated by calling MyHandler.run(myapp). # A second optional hash can be passed to include server-specific # configuration. module Handler def self.get(server) return unless server server = server.to_s unless @handlers.include? server load_error = try_require('rack/handler', server) end if klass = @handlers[server] klass.split("::").inject(Object) { |o, x| o.const_get(x) } else const_get(server, false) end rescue NameError => name_error raise load_error || name_error end # Select first available Rack handler given an `Array` of server names. # Raises `LoadError` if no handler was found. # # > pick ['thin', 'webrick'] # => Rack::Handler::WEBrick def self.pick(server_names) server_names = Array(server_names) server_names.each do |server_name| begin return get(server_name.to_s) rescue LoadError, NameError end end raise LoadError, "Couldn't find handler for: #{server_names.join(', ')}." end def self.default(options = {}) # Guess. if ENV.include?("PHP_FCGI_CHILDREN") # We already speak FastCGI options.delete :File options.delete :Port Rack::Handler::FastCGI elsif ENV.include?(REQUEST_METHOD) Rack::Handler::CGI elsif ENV.include?("RACK_HANDLER") self.get(ENV["RACK_HANDLER"]) else pick ['thin', 'puma', 'webrick'] end end # Transforms server-name constants to their canonical form as filenames, # then tries to require them but silences the LoadError if not found # # Naming convention: # # Foo # => 'foo' # FooBar # => 'foo_bar.rb' # FooBAR # => 'foobar.rb' # FOObar # => 'foobar.rb' # FOOBAR # => 'foobar.rb' # FooBarBaz # => 'foo_bar_baz.rb' def self.try_require(prefix, const_name) file = const_name.gsub(/^[A-Z]+/) { |pre| pre.downcase }. gsub(/[A-Z]+[^A-Z]/, '_\&').downcase require(::File.join(prefix, file)) nil rescue LoadError => error error end def self.register(server, klass) @handlers ||= {} @handlers[server.to_s] = klass.to_s end autoload :CGI, "rack/handler/cgi" autoload :FastCGI, "rack/handler/fastcgi" autoload :Mongrel, "rack/handler/mongrel" autoload :EventedMongrel, "rack/handler/evented_mongrel" autoload :SwiftipliedMongrel, "rack/handler/swiftiplied_mongrel" autoload :WEBrick, "rack/handler/webrick" autoload :LSWS, "rack/handler/lsws" autoload :SCGI, "rack/handler/scgi" autoload :Thin, "rack/handler/thin" register 'cgi', 'Rack::Handler::CGI' register 'fastcgi', 'Rack::Handler::FastCGI' register 'mongrel', 'Rack::Handler::Mongrel' register 'emongrel', 'Rack::Handler::EventedMongrel' register 'smongrel', 'Rack::Handler::SwiftipliedMongrel' register 'webrick', 'Rack::Handler::WEBrick' register 'lsws', 'Rack::Handler::LSWS' register 'scgi', 'Rack::Handler::SCGI' register 'thin', 'Rack::Handler::Thin' end end PK!-,o++5gems/2.2.0/gems/rack-1.6.4/lib/rack/session/cookie.rbnu[require 'openssl' require 'zlib' require 'rack/request' require 'rack/response' require 'rack/session/abstract/id' module Rack module Session # Rack::Session::Cookie provides simple cookie based session management. # By default, the session is a Ruby Hash stored as base64 encoded marshalled # data set to :key (default: rack.session). The object that encodes the # session data is configurable and must respond to +encode+ and +decode+. # Both methods must take a string and return a string. # # When the secret key is set, cookie data is checked for data integrity. # The old secret key is also accepted and allows graceful secret rotation. # # Example: # # use Rack::Session::Cookie, :key => 'rack.session', # :domain => 'foo.com', # :path => '/', # :expire_after => 2592000, # :secret => 'change_me', # :old_secret => 'also_change_me' # # All parameters are optional. # # Example of a cookie with no encoding: # # Rack::Session::Cookie.new(application, { # :coder => Rack::Session::Cookie::Identity.new # }) # # Example of a cookie with custom encoding: # # Rack::Session::Cookie.new(application, { # :coder => Class.new { # def encode(str); str.reverse; end # def decode(str); str.reverse; end # }.new # }) # class Cookie < Abstract::ID # Encode session cookies as Base64 class Base64 def encode(str) [str].pack('m') end def decode(str) str.unpack('m').first end # Encode session cookies as Marshaled Base64 data class Marshal < Base64 def encode(str) super(::Marshal.dump(str)) end def decode(str) return unless str ::Marshal.load(super(str)) rescue nil end end # N.B. Unlike other encoding methods, the contained objects must be a # valid JSON composite type, either a Hash or an Array. class JSON < Base64 def encode(obj) super(::Rack::Utils::OkJson.encode(obj)) end def decode(str) return unless str ::Rack::Utils::OkJson.decode(super(str)) rescue nil end end class ZipJSON < Base64 def encode(obj) super(Zlib::Deflate.deflate(::Rack::Utils::OkJson.encode(obj))) end def decode(str) return unless str ::Rack::Utils::OkJson.decode(Zlib::Inflate.inflate(super(str))) rescue nil end end end # Use no encoding for session cookies class Identity def encode(str); str; end def decode(str); str; end end attr_reader :coder def initialize(app, options={}) @secrets = options.values_at(:secret, :old_secret).compact warn <<-MSG unless @secrets.size >= 1 SECURITY WARNING: No secret option provided to Rack::Session::Cookie. This poses a security threat. It is strongly recommended that you provide a secret to prevent exploits that may be possible from crafted cookies. This will not be supported in future versions of Rack, and future versions will even invalidate your existing user cookies. Called from: #{caller[0]}. MSG @coder = options[:coder] ||= Base64::Marshal.new super(app, options.merge!(:cookie_only => true)) end private def get_session(env, sid) data = unpacked_cookie_data(env) data = persistent_session_id!(data) [data["session_id"], data] end def extract_session_id(env) unpacked_cookie_data(env)["session_id"] end def unpacked_cookie_data(env) env["rack.session.unpacked_cookie_data"] ||= begin request = Rack::Request.new(env) session_data = request.cookies[@key] if @secrets.size > 0 && session_data digest, session_data = session_data.reverse.split("--", 2) digest.reverse! if digest session_data.reverse! if session_data session_data = nil unless digest_match?(session_data, digest) end coder.decode(session_data) || {} end end def persistent_session_id!(data, sid=nil) data ||= {} data["session_id"] ||= sid || generate_sid data end def set_session(env, session_id, session, options) session = session.merge("session_id" => session_id) session_data = coder.encode(session) if @secrets.first session_data << "--#{generate_hmac(session_data, @secrets.first)}" end if session_data.size > (4096 - @key.size) env["rack.errors"].puts("Warning! Rack::Session::Cookie data size exceeds 4K.") nil else session_data end end def destroy_session(env, session_id, options) # Nothing to do here, data is in the client generate_sid unless options[:drop] end def digest_match?(data, digest) return unless data && digest @secrets.any? do |secret| Rack::Utils.secure_compare(digest, generate_hmac(data, secret)) end end def generate_hmac(data, secret) OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA1.new, secret, data) end end end end PK!h=3gems/2.2.0/gems/rack-1.6.4/lib/rack/session/pool.rbnu[# AUTHOR: blink ; blink#ruby-lang@irc.freenode.net # THANKS: # apeiros, for session id generation, expiry setup, and threadiness # sergio, threadiness and bugreps require 'rack/session/abstract/id' require 'thread' module Rack module Session # Rack::Session::Pool provides simple cookie based session management. # Session data is stored in a hash held by @pool. # In the context of a multithreaded environment, sessions being # committed to the pool is done in a merging manner. # # The :drop option is available in rack.session.options if you wish to # explicitly remove the session from the session cache. # # Example: # myapp = MyRackApp.new # sessioned = Rack::Session::Pool.new(myapp, # :domain => 'foo.com', # :expire_after => 2592000 # ) # Rack::Handler::WEBrick.run sessioned class Pool < Abstract::ID attr_reader :mutex, :pool DEFAULT_OPTIONS = Abstract::ID::DEFAULT_OPTIONS.merge :drop => false def initialize(app, options={}) super @pool = Hash.new @mutex = Mutex.new end def generate_sid loop do sid = super break sid unless @pool.key? sid end end def get_session(env, sid) with_lock(env) do unless sid and session = @pool[sid] sid, session = generate_sid, {} @pool.store sid, session end [sid, session] end end def set_session(env, session_id, new_session, options) with_lock(env) do @pool.store session_id, new_session session_id end end def destroy_session(env, session_id, options) with_lock(env) do @pool.delete(session_id) generate_sid unless options[:drop] end end def with_lock(env) @mutex.lock if env['rack.multithread'] yield ensure @mutex.unlock if @mutex.locked? end end end end PK!v 7gems/2.2.0/gems/rack-1.6.4/lib/rack/session/memcache.rbnu[# AUTHOR: blink ; blink#ruby-lang@irc.freenode.net require 'rack/session/abstract/id' require 'memcache' module Rack module Session # Rack::Session::Memcache provides simple cookie based session management. # Session data is stored in memcached. The corresponding session key is # maintained in the cookie. # You may treat Session::Memcache as you would Session::Pool with the # following caveats. # # * Setting :expire_after to 0 would note to the Memcache server to hang # onto the session data until it would drop it according to it's own # specifications. However, the cookie sent to the client would expire # immediately. # # Note that memcache does drop data before it may be listed to expire. For # a full description of behaviour, please see memcache's documentation. class Memcache < Abstract::ID attr_reader :mutex, :pool DEFAULT_OPTIONS = Abstract::ID::DEFAULT_OPTIONS.merge \ :namespace => 'rack:session', :memcache_server => 'localhost:11211' def initialize(app, options={}) super @mutex = Mutex.new mserv = @default_options[:memcache_server] mopts = @default_options.reject{|k,v| !MemCache::DEFAULT_OPTIONS.include? k } @pool = options[:cache] || MemCache.new(mserv, mopts) unless @pool.active? and @pool.servers.any?{|c| c.alive? } raise 'No memcache servers' end end def generate_sid loop do sid = super break sid unless @pool.get(sid, true) end end def get_session(env, sid) with_lock(env) do unless sid and session = @pool.get(sid) sid, session = generate_sid, {} unless /^STORED/ =~ @pool.add(sid, session) raise "Session collision on '#{sid.inspect}'" end end [sid, session] end end def set_session(env, session_id, new_session, options) expiry = options[:expire_after] expiry = expiry.nil? ? 0 : expiry + 1 with_lock(env) do @pool.set session_id, new_session, expiry session_id end end def destroy_session(env, session_id, options) with_lock(env) do @pool.delete(session_id) generate_sid unless options[:drop] end end def with_lock(env) @mutex.lock if env['rack.multithread'] yield rescue MemCache::MemCacheError, Errno::ECONNREFUSED if $VERBOSE warn "#{self} is unable to find memcached server." warn $!.inspect end raise ensure @mutex.unlock if @mutex.locked? end end end end PK!~Iq..:gems/2.2.0/gems/rack-1.6.4/lib/rack/session/abstract/id.rbnu[# AUTHOR: blink ; blink#ruby-lang@irc.freenode.net # bugrep: Andreas Zehnder require 'time' require 'rack/request' require 'rack/response' begin require 'securerandom' rescue LoadError # We just won't get securerandom end module Rack module Session module Abstract ENV_SESSION_KEY = 'rack.session'.freeze ENV_SESSION_OPTIONS_KEY = 'rack.session.options'.freeze # SessionHash is responsible to lazily load the session from store. class SessionHash include Enumerable attr_writer :id def self.find(env) env[ENV_SESSION_KEY] end def self.set(env, session) env[ENV_SESSION_KEY] = session end def self.set_options(env, options) env[ENV_SESSION_OPTIONS_KEY] = options.dup end def initialize(store, env) @store = store @env = env @loaded = false end def id return @id if @loaded or instance_variable_defined?(:@id) @id = @store.send(:extract_session_id, @env) end def options @env[ENV_SESSION_OPTIONS_KEY] end def each(&block) load_for_read! @data.each(&block) end def [](key) load_for_read! @data[key.to_s] end alias :fetch :[] def has_key?(key) load_for_read! @data.has_key?(key.to_s) end alias :key? :has_key? alias :include? :has_key? def []=(key, value) load_for_write! @data[key.to_s] = value end alias :store :[]= def clear load_for_write! @data.clear end def destroy clear @id = @store.send(:destroy_session, @env, id, options) end def to_hash load_for_read! @data.dup end def update(hash) load_for_write! @data.update(stringify_keys(hash)) end alias :merge! :update def replace(hash) load_for_write! @data.replace(stringify_keys(hash)) end def delete(key) load_for_write! @data.delete(key.to_s) end def inspect if loaded? @data.inspect else "#<#{self.class}:0x#{self.object_id.to_s(16)} not yet loaded>" end end def exists? return @exists if instance_variable_defined?(:@exists) @data = {} @exists = @store.send(:session_exists?, @env) end def loaded? @loaded end def empty? load_for_read! @data.empty? end def keys @data.keys end def values @data.values end private def load_for_read! load! if !loaded? && exists? end def load_for_write! load! unless loaded? end def load! @id, session = @store.send(:load_session, @env) @data = stringify_keys(session) @loaded = true end def stringify_keys(other) hash = {} other.each do |key, value| hash[key.to_s] = value end hash end end # ID sets up a basic framework for implementing an id based sessioning # service. Cookies sent to the client for maintaining sessions will only # contain an id reference. Only #get_session and #set_session are # required to be overwritten. # # All parameters are optional. # * :key determines the name of the cookie, by default it is # 'rack.session' # * :path, :domain, :expire_after, :secure, and :httponly set the related # cookie options as by Rack::Response#add_cookie # * :skip will not a set a cookie in the response nor update the session state # * :defer will not set a cookie in the response but still update the session # state if it is used with a backend # * :renew (implementation dependent) will prompt the generation of a new # session id, and migration of data to be referenced at the new id. If # :defer is set, it will be overridden and the cookie will be set. # * :sidbits sets the number of bits in length that a generated session # id will be. # # These options can be set on a per request basis, at the location of # env['rack.session.options']. Additionally the id of the session can be # found within the options hash at the key :id. It is highly not # recommended to change its value. # # Is Rack::Utils::Context compatible. # # Not included by default; you must require 'rack/session/abstract/id' # to use. class ID DEFAULT_OPTIONS = { :key => 'rack.session', :path => '/', :domain => nil, :expire_after => nil, :secure => false, :httponly => true, :defer => false, :renew => false, :sidbits => 128, :cookie_only => true, :secure_random => (::SecureRandom rescue false) } attr_reader :key, :default_options def initialize(app, options={}) @app = app @default_options = self.class::DEFAULT_OPTIONS.merge(options) @key = @default_options.delete(:key) @cookie_only = @default_options.delete(:cookie_only) initialize_sid end def call(env) context(env) end def context(env, app=@app) prepare_session(env) status, headers, body = app.call(env) commit_session(env, status, headers, body) end private def initialize_sid @sidbits = @default_options[:sidbits] @sid_secure = @default_options[:secure_random] @sid_length = @sidbits / 4 end # Generate a new session id using Ruby #rand. The size of the # session id is controlled by the :sidbits option. # Monkey patch this to use custom methods for session id generation. def generate_sid(secure = @sid_secure) if secure secure.hex(@sid_length) else "%0#{@sid_length}x" % Kernel.rand(2**@sidbits - 1) end rescue NotImplementedError generate_sid(false) end # Sets the lazy session at 'rack.session' and places options and session # metadata into 'rack.session.options'. def prepare_session(env) session_was = env[ENV_SESSION_KEY] env[ENV_SESSION_KEY] = session_class.new(self, env) env[ENV_SESSION_OPTIONS_KEY] = @default_options.dup env[ENV_SESSION_KEY].merge! session_was if session_was end # Extracts the session id from provided cookies and passes it and the # environment to #get_session. def load_session(env) sid = current_session_id(env) sid, session = get_session(env, sid) [sid, session || {}] end # Extract session id from request object. def extract_session_id(env) request = Rack::Request.new(env) sid = request.cookies[@key] sid ||= request.params[@key] unless @cookie_only sid end # Returns the current session id from the SessionHash. def current_session_id(env) env[ENV_SESSION_KEY].id end # Check if the session exists or not. def session_exists?(env) value = current_session_id(env) value && !value.empty? end # Session should be committed if it was loaded, any of specific options like :renew, :drop # or :expire_after was given and the security permissions match. Skips if skip is given. def commit_session?(env, session, options) if options[:skip] false else has_session = loaded_session?(session) || forced_session_update?(session, options) has_session && security_matches?(env, options) end end def loaded_session?(session) !session.is_a?(session_class) || session.loaded? end def forced_session_update?(session, options) force_options?(options) && session && !session.empty? end def force_options?(options) options.values_at(:max_age, :renew, :drop, :defer, :expire_after).any? end def security_matches?(env, options) return true unless options[:secure] request = Rack::Request.new(env) request.ssl? end # Acquires the session from the environment and the session id from # the session options and passes them to #set_session. If successful # and the :defer option is not true, a cookie will be added to the # response with the session's id. def commit_session(env, status, headers, body) session = env[ENV_SESSION_KEY] options = session.options if options[:drop] || options[:renew] session_id = destroy_session(env, session.id || generate_sid, options) return [status, headers, body] unless session_id end return [status, headers, body] unless commit_session?(env, session, options) session.send(:load!) unless loaded_session?(session) session_id ||= session.id session_data = session.to_hash.delete_if { |k,v| v.nil? } if not data = set_session(env, session_id, session_data, options) env["rack.errors"].puts("Warning! #{self.class.name} failed to save session. Content dropped.") elsif options[:defer] and not options[:renew] env["rack.errors"].puts("Deferring cookie for #{session_id}") if $VERBOSE else cookie = Hash.new cookie[:value] = data cookie[:expires] = Time.now + options[:expire_after] if options[:expire_after] cookie[:expires] = Time.now + options[:max_age] if options[:max_age] set_cookie(env, headers, cookie.merge!(options)) end [status, headers, body] end # Sets the cookie back to the client with session id. We skip the cookie # setting if the value didn't change (sid is the same) or expires was given. def set_cookie(env, headers, cookie) request = Rack::Request.new(env) if request.cookies[@key] != cookie[:value] || cookie[:expires] Utils.set_cookie_header!(headers, @key, cookie) end end # Allow subclasses to prepare_session for different Session classes def session_class SessionHash end # All thread safety and session retrieval procedures should occur here. # Should return [session_id, session]. # If nil is provided as the session id, generation of a new valid id # should occur within. def get_session(env, sid) raise '#get_session not implemented.' end # All thread safety and session storage procedures should occur here. # Must return the session id if the session was saved successfully, or # false if the session could not be saved. def set_session(env, sid, session, options) raise '#set_session not implemented.' end # All thread safety and session destroy procedures should occur here. # Should return a new session id or nil if options[:drop] def destroy_session(env, sid, options) raise '#destroy_session not implemented' end end end end end PK!΀ksSsS,gems/2.2.0/gems/rack-1.6.4/lib/rack/utils.rbnu[# -*- encoding: binary -*- require 'fileutils' require 'set' require 'tempfile' require 'rack/multipart' require 'time' major, minor, patch = RUBY_VERSION.split('.').map { |v| v.to_i } if major == 1 && minor < 9 require 'rack/backports/uri/common_18' elsif major == 1 && minor == 9 && patch == 2 && RUBY_PATCHLEVEL <= 328 && RUBY_ENGINE != 'jruby' require 'rack/backports/uri/common_192' elsif major == 1 && minor == 9 && patch == 3 && RUBY_PATCHLEVEL < 125 require 'rack/backports/uri/common_193' else require 'uri/common' end module Rack # Rack::Utils contains a grab-bag of useful methods for writing web # applications adopted from all kinds of Ruby libraries. module Utils # ParameterTypeError is the error that is raised when incoming structural # parameters (parsed by parse_nested_query) contain conflicting types. class ParameterTypeError < TypeError; end # InvalidParameterError is the error that is raised when incoming structural # parameters (parsed by parse_nested_query) contain invalid format or byte # sequence. class InvalidParameterError < ArgumentError; end # URI escapes. (CGI style space to +) def escape(s) URI.encode_www_form_component(s) end module_function :escape # Like URI escaping, but with %20 instead of +. Strictly speaking this is # true URI escaping. def escape_path(s) escape(s).gsub('+', '%20') end module_function :escape_path # Unescapes a URI escaped string with +encoding+. +encoding+ will be the # target encoding of the string returned, and it defaults to UTF-8 if defined?(::Encoding) def unescape(s, encoding = Encoding::UTF_8) URI.decode_www_form_component(s, encoding) end else def unescape(s, encoding = nil) URI.decode_www_form_component(s, encoding) end end module_function :unescape DEFAULT_SEP = /[&;] */n class << self attr_accessor :key_space_limit attr_accessor :param_depth_limit attr_accessor :multipart_part_limit end # The default number of bytes to allow parameter keys to take up. # This helps prevent a rogue client from flooding a Request. self.key_space_limit = 65536 # Default depth at which the parameter parser will raise an exception for # being too deep. This helps prevent SystemStackErrors self.param_depth_limit = 100 # The maximum number of parts a request can contain. Accepting too many part # can lead to the server running out of file handles. # Set to `0` for no limit. # FIXME: RACK_MULTIPART_LIMIT was introduced by mistake and it will be removed in 1.7.0 self.multipart_part_limit = (ENV['RACK_MULTIPART_PART_LIMIT'] || ENV['RACK_MULTIPART_LIMIT'] || 128).to_i # Stolen from Mongrel, with some small modifications: # Parses a query string by breaking it up at the '&' # and ';' characters. You can also use this to parse # cookies by changing the characters used in the second # parameter (which defaults to '&;'). def parse_query(qs, d = nil, &unescaper) unescaper ||= method(:unescape) params = KeySpaceConstrainedParams.new (qs || '').split(d ? /[#{d}] */n : DEFAULT_SEP).each do |p| next if p.empty? k, v = p.split('=', 2).map(&unescaper) if cur = params[k] if cur.class == Array params[k] << v else params[k] = [cur, v] end else params[k] = v end end return params.to_params_hash end module_function :parse_query # parse_nested_query expands a query string into structural types. Supported # types are Arrays, Hashes and basic value types. It is possible to supply # query strings with parameters of conflicting types, in this case a # ParameterTypeError is raised. Users are encouraged to return a 400 in this # case. def parse_nested_query(qs, d = nil) params = KeySpaceConstrainedParams.new (qs || '').split(d ? /[#{d}] */n : DEFAULT_SEP).each do |p| k, v = p.split('=', 2).map { |s| unescape(s) } normalize_params(params, k, v) end return params.to_params_hash rescue ArgumentError => e raise InvalidParameterError, e.message end module_function :parse_nested_query # normalize_params recursively expands parameters into structural types. If # the structural types represented by two different parameter names are in # conflict, a ParameterTypeError is raised. def normalize_params(params, name, v = nil, depth = Utils.param_depth_limit) raise RangeError if depth <= 0 name =~ %r(\A[\[\]]*([^\[\]]+)\]*) k = $1 || '' after = $' || '' return if k.empty? if after == "" params[k] = v elsif after == "[" params[name] = v elsif after == "[]" params[k] ||= [] raise ParameterTypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array) params[k] << v elsif after =~ %r(^\[\]\[([^\[\]]+)\]$) || after =~ %r(^\[\](.+)$) child_key = $1 params[k] ||= [] raise ParameterTypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array) if params_hash_type?(params[k].last) && !params[k].last.key?(child_key) normalize_params(params[k].last, child_key, v, depth - 1) else params[k] << normalize_params(params.class.new, child_key, v, depth - 1) end else params[k] ||= params.class.new raise ParameterTypeError, "expected Hash (got #{params[k].class.name}) for param `#{k}'" unless params_hash_type?(params[k]) params[k] = normalize_params(params[k], after, v, depth - 1) end return params end module_function :normalize_params def params_hash_type?(obj) obj.kind_of?(KeySpaceConstrainedParams) || obj.kind_of?(Hash) end module_function :params_hash_type? def build_query(params) params.map { |k, v| if v.class == Array build_query(v.map { |x| [k, x] }) else v.nil? ? escape(k) : "#{escape(k)}=#{escape(v)}" end }.join("&") end module_function :build_query def build_nested_query(value, prefix = nil) case value when Array value.map { |v| build_nested_query(v, "#{prefix}[]") }.join("&") when Hash value.map { |k, v| build_nested_query(v, prefix ? "#{prefix}[#{escape(k)}]" : escape(k)) }.reject(&:empty?).join('&') when nil prefix else raise ArgumentError, "value must be a Hash" if prefix.nil? "#{prefix}=#{escape(value)}" end end module_function :build_nested_query def q_values(q_value_header) q_value_header.to_s.split(/\s*,\s*/).map do |part| value, parameters = part.split(/\s*;\s*/, 2) quality = 1.0 if md = /\Aq=([\d.]+)/.match(parameters) quality = md[1].to_f end [value, quality] end end module_function :q_values def best_q_match(q_value_header, available_mimes) values = q_values(q_value_header) matches = values.map do |req_mime, quality| match = available_mimes.find { |am| Rack::Mime.match?(am, req_mime) } next unless match [match, quality] end.compact.sort_by do |match, quality| (match.split('/', 2).count('*') * -10) + quality end.last matches && matches.first end module_function :best_q_match ESCAPE_HTML = { "&" => "&", "<" => "<", ">" => ">", "'" => "'", '"' => """, "/" => "/" } if //.respond_to?(:encoding) ESCAPE_HTML_PATTERN = Regexp.union(*ESCAPE_HTML.keys) else # On 1.8, there is a kcode = 'u' bug that allows for XSS otherwise # TODO doesn't apply to jruby, so a better condition above might be preferable? ESCAPE_HTML_PATTERN = /#{Regexp.union(*ESCAPE_HTML.keys)}/n end # Escape ampersands, brackets and quotes to their HTML/XML entities. def escape_html(string) string.to_s.gsub(ESCAPE_HTML_PATTERN){|c| ESCAPE_HTML[c] } end module_function :escape_html def select_best_encoding(available_encodings, accept_encoding) # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html expanded_accept_encoding = accept_encoding.map { |m, q| if m == "*" (available_encodings - accept_encoding.map { |m2, _| m2 }).map { |m2| [m2, q] } else [[m, q]] end }.inject([]) { |mem, list| mem + list } encoding_candidates = expanded_accept_encoding.sort_by { |_, q| -q }.map { |m, _| m } unless encoding_candidates.include?("identity") encoding_candidates.push("identity") end expanded_accept_encoding.each { |m, q| encoding_candidates.delete(m) if q == 0.0 } return (encoding_candidates & available_encodings)[0] end module_function :select_best_encoding def set_cookie_header!(header, key, value) case value when Hash domain = "; domain=" + value[:domain] if value[:domain] path = "; path=" + value[:path] if value[:path] max_age = "; max-age=" + value[:max_age].to_s if value[:max_age] # There is an RFC mess in the area of date formatting for Cookies. Not # only are there contradicting RFCs and examples within RFC text, but # there are also numerous conflicting names of fields and partially # cross-applicable specifications. # # These are best described in RFC 2616 3.3.1. This RFC text also # specifies that RFC 822 as updated by RFC 1123 is preferred. That is a # fixed length format with space-date delimeted fields. # # See also RFC 1123 section 5.2.14. # # RFC 6265 also specifies "sane-cookie-date" as RFC 1123 date, defined # in RFC 2616 3.3.1. RFC 6265 also gives examples that clearly denote # the space delimited format. These formats are compliant with RFC 2822. # # For reference, all involved RFCs are: # RFC 822 # RFC 1123 # RFC 2109 # RFC 2616 # RFC 2822 # RFC 2965 # RFC 6265 expires = "; expires=" + rfc2822(value[:expires].clone.gmtime) if value[:expires] secure = "; secure" if value[:secure] httponly = "; HttpOnly" if (value.key?(:httponly) ? value[:httponly] : value[:http_only]) value = value[:value] end value = [value] unless Array === value cookie = escape(key) + "=" + value.map { |v| escape v }.join("&") + "#{domain}#{path}#{max_age}#{expires}#{secure}#{httponly}" case header["Set-Cookie"] when nil, '' header["Set-Cookie"] = cookie when String header["Set-Cookie"] = [header["Set-Cookie"], cookie].join("\n") when Array header["Set-Cookie"] = (header["Set-Cookie"] + [cookie]).join("\n") end nil end module_function :set_cookie_header! def delete_cookie_header!(header, key, value = {}) case header["Set-Cookie"] when nil, '' cookies = [] when String cookies = header["Set-Cookie"].split("\n") when Array cookies = header["Set-Cookie"] end cookies.reject! { |cookie| if value[:domain] cookie =~ /\A#{escape(key)}=.*domain=#{value[:domain]}/ elsif value[:path] cookie =~ /\A#{escape(key)}=.*path=#{value[:path]}/ else cookie =~ /\A#{escape(key)}=/ end } header["Set-Cookie"] = cookies.join("\n") set_cookie_header!(header, key, {:value => '', :path => nil, :domain => nil, :max_age => '0', :expires => Time.at(0) }.merge(value)) nil end module_function :delete_cookie_header! # Return the bytesize of String; uses String#size under Ruby 1.8 and # String#bytesize under 1.9. if ''.respond_to?(:bytesize) def bytesize(string) string.bytesize end else def bytesize(string) string.size end end module_function :bytesize def rfc2822(time) time.rfc2822 end module_function :rfc2822 # Modified version of stdlib time.rb Time#rfc2822 to use '%d-%b-%Y' instead # of '% %b %Y'. # It assumes that the time is in GMT to comply to the RFC 2109. # # NOTE: I'm not sure the RFC says it requires GMT, but is ambiguous enough # that I'm certain someone implemented only that option. # Do not use %a and %b from Time.strptime, it would use localized names for # weekday and month. # def rfc2109(time) wday = Time::RFC2822_DAY_NAME[time.wday] mon = Time::RFC2822_MONTH_NAME[time.mon - 1] time.strftime("#{wday}, %d-#{mon}-%Y %H:%M:%S GMT") end module_function :rfc2109 # Parses the "Range:" header, if present, into an array of Range objects. # Returns nil if the header is missing or syntactically invalid. # Returns an empty array if none of the ranges are satisfiable. def byte_ranges(env, size) # See http_range = env['HTTP_RANGE'] return nil unless http_range && http_range =~ /bytes=([^;]+)/ ranges = [] $1.split(/,\s*/).each do |range_spec| return nil unless range_spec =~ /(\d*)-(\d*)/ r0,r1 = $1, $2 if r0.empty? return nil if r1.empty? # suffix-byte-range-spec, represents trailing suffix of file r0 = size - r1.to_i r0 = 0 if r0 < 0 r1 = size - 1 else r0 = r0.to_i if r1.empty? r1 = size - 1 else r1 = r1.to_i return nil if r1 < r0 # backwards range is syntactically invalid r1 = size-1 if r1 >= size end end ranges << (r0..r1) if r0 <= r1 end ranges end module_function :byte_ranges # Constant time string comparison. # # NOTE: the values compared should be of fixed length, such as strings # that have already been processed by HMAC. This should not be used # on variable length plaintext strings because it could leak length info # via timing attacks. def secure_compare(a, b) return false unless bytesize(a) == bytesize(b) l = a.unpack("C*") r, i = 0, -1 b.each_byte { |v| r |= v ^ l[i+=1] } r == 0 end module_function :secure_compare # Context allows the use of a compatible middleware at different points # in a request handling stack. A compatible middleware must define # #context which should take the arguments env and app. The first of which # would be the request environment. The second of which would be the rack # application that the request would be forwarded to. class Context attr_reader :for, :app def initialize(app_f, app_r) raise 'running context does not respond to #context' unless app_f.respond_to? :context @for, @app = app_f, app_r end def call(env) @for.context(env, @app) end def recontext(app) self.class.new(@for, app) end def context(env, app=@app) recontext(app).call(env) end end # A case-insensitive Hash that preserves the original case of a # header when set. class HeaderHash < Hash def self.new(hash={}) HeaderHash === hash ? hash : super(hash) end def initialize(hash={}) super() @names = {} hash.each { |k, v| self[k] = v } end def each super do |k, v| yield(k, v.respond_to?(:to_ary) ? v.to_ary.join("\n") : v) end end def to_hash hash = {} each { |k,v| hash[k] = v } hash end def [](k) super(k) || super(@names[k.downcase]) end def []=(k, v) canonical = k.downcase delete k if @names[canonical] && @names[canonical] != k # .delete is expensive, don't invoke it unless necessary @names[k] = @names[canonical] = k super k, v end def delete(k) canonical = k.downcase result = super @names.delete(canonical) @names.delete_if { |name,| name.downcase == canonical } result end def include?(k) @names.include?(k) || @names.include?(k.downcase) end alias_method :has_key?, :include? alias_method :member?, :include? alias_method :key?, :include? def merge!(other) other.each { |k, v| self[k] = v } self end def merge(other) hash = dup hash.merge! other end def replace(other) clear other.each { |k, v| self[k] = v } self end end class KeySpaceConstrainedParams def initialize(limit = Utils.key_space_limit) @limit = limit @size = 0 @params = {} end def [](key) @params[key] end def []=(key, value) @size += key.size if key && !@params.key?(key) raise RangeError, 'exceeded available parameter key space' if @size > @limit @params[key] = value end def key?(key) @params.key?(key) end def to_params_hash hash = @params hash.keys.each do |key| value = hash[key] if value.kind_of?(self.class) if value.object_id == self.object_id hash[key] = hash else hash[key] = value.to_params_hash end elsif value.kind_of?(Array) value.map! {|x| x.kind_of?(self.class) ? x.to_params_hash : x} end end hash end end # Every standard HTTP code mapped to the appropriate message. # Generated with: # curl -s https://www.iana.org/assignments/http-status-codes/http-status-codes-1.csv | \ # ruby -ne 'm = /^(\d{3}),(?!Unassigned|\(Unused\))([^,]+)/.match($_) and \ # puts "#{m[1]} => \x27#{m[2].strip}\x27,"' HTTP_STATUS_CODES = { 100 => 'Continue', 101 => 'Switching Protocols', 102 => 'Processing', 200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information', 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content', 207 => 'Multi-Status', 208 => 'Already Reported', 226 => 'IM Used', 300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Found', 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 307 => 'Temporary Redirect', 308 => 'Permanent Redirect', 400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', 403 => 'Forbidden', 404 => 'Not Found', 405 => 'Method Not Allowed', 406 => 'Not Acceptable', 407 => 'Proxy Authentication Required', 408 => 'Request Timeout', 409 => 'Conflict', 410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed', 413 => 'Payload Too Large', 414 => 'URI Too Long', 415 => 'Unsupported Media Type', 416 => 'Range Not Satisfiable', 417 => 'Expectation Failed', 422 => 'Unprocessable Entity', 423 => 'Locked', 424 => 'Failed Dependency', 426 => 'Upgrade Required', 428 => 'Precondition Required', 429 => 'Too Many Requests', 431 => 'Request Header Fields Too Large', 500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable', 504 => 'Gateway Timeout', 505 => 'HTTP Version Not Supported', 506 => 'Variant Also Negotiates', 507 => 'Insufficient Storage', 508 => 'Loop Detected', 510 => 'Not Extended', 511 => 'Network Authentication Required' } # Responses with HTTP status codes that should not have an entity body STATUS_WITH_NO_ENTITY_BODY = Set.new((100..199).to_a << 204 << 205 << 304) SYMBOL_TO_STATUS_CODE = Hash[*HTTP_STATUS_CODES.map { |code, message| [message.downcase.gsub(/\s|-|'/, '_').to_sym, code] }.flatten] def status_code(status) if status.is_a?(Symbol) SYMBOL_TO_STATUS_CODE[status] || 500 else status.to_i end end module_function :status_code Multipart = Rack::Multipart PATH_SEPS = Regexp.union(*[::File::SEPARATOR, ::File::ALT_SEPARATOR].compact) def clean_path_info(path_info) parts = path_info.split PATH_SEPS clean = [] parts.each do |part| next if part.empty? || part == '.' part == '..' ? clean.pop : clean << part end clean.unshift '/' if parts.empty? || parts.first.empty? ::File.join(*clean) end module_function :clean_path_info end end PK!k+gems/2.2.0/gems/rack-1.6.4/lib/rack/head.rbnu[require 'rack/body_proxy' module Rack class Head # Rack::Head returns an empty body for all HEAD requests. It leaves # all other requests unchanged. def initialize(app) @app = app end def call(env) status, headers, body = @app.call(env) if env[REQUEST_METHOD] == HEAD [ status, headers, Rack::BodyProxy.new([]) do body.close if body.respond_to? :close end ] else [status, headers, body] end end end end PK!ix! ! 3gems/2.2.0/gems/rack-1.6.4/lib/rack/commonlogger.rbnu[require 'rack/body_proxy' module Rack # Rack::CommonLogger forwards every request to the given +app+, and # logs a line in the # {Apache common log format}[http://httpd.apache.org/docs/1.3/logs.html#common] # to the +logger+. # # If +logger+ is nil, CommonLogger will fall back +rack.errors+, which is # an instance of Rack::NullLogger. # # +logger+ can be any class, including the standard library Logger, and is # expected to have either +write+ or +<<+ method, which accepts the CommonLogger::FORMAT. # According to the SPEC, the error stream must also respond to +puts+ # (which takes a single argument that responds to +to_s+), and +flush+ # (which is called without arguments in order to make the error appear for # sure) class CommonLogger # Common Log Format: http://httpd.apache.org/docs/1.3/logs.html#common # # lilith.local - - [07/Aug/2006 23:58:02 -0400] "GET / HTTP/1.1" 500 - # # %{%s - %s [%s] "%s %s%s %s" %d %s\n} % FORMAT = %{%s - %s [%s] "%s %s%s %s" %d %s %0.4f\n} def initialize(app, logger=nil) @app = app @logger = logger end def call(env) began_at = Time.now status, header, body = @app.call(env) header = Utils::HeaderHash.new(header) body = BodyProxy.new(body) { log(env, status, header, began_at) } [status, header, body] end private def log(env, status, header, began_at) now = Time.now length = extract_content_length(header) msg = FORMAT % [ env['HTTP_X_FORWARDED_FOR'] || env["REMOTE_ADDR"] || "-", env["REMOTE_USER"] || "-", now.strftime("%d/%b/%Y:%H:%M:%S %z"), env[REQUEST_METHOD], env[PATH_INFO], env[QUERY_STRING].empty? ? "" : "?"+env[QUERY_STRING], env["HTTP_VERSION"], status.to_s[0..3], length, now - began_at ] logger = @logger || env['rack.errors'] # Standard library logger doesn't support write but it supports << which actually # calls to write on the log device without formatting if logger.respond_to?(:write) logger.write(msg) else logger << msg end end def extract_content_length(headers) value = headers[CONTENT_LENGTH] or return '-' value.to_s == '0' ? '-' : value end end end PK!aJ'0gems/2.2.0/gems/rack-1.6.4/lib/rack/directory.rbnu[require 'time' require 'rack/utils' require 'rack/mime' module Rack # Rack::Directory serves entries below the +root+ given, according to the # path info of the Rack request. If a directory is found, the file's contents # will be presented in an html based index. If a file is found, the env will # be passed to the specified +app+. # # If +app+ is not specified, a Rack::File of the same +root+ will be used. class Directory DIR_FILE = "%s%s%s%s" DIR_PAGE = <<-PAGE %s

    %s


    %s
    Name Size Type Last Modified

    PAGE attr_reader :files attr_accessor :root, :path def initialize(root, app=nil) @root = F.expand_path(root) @app = app || Rack::File.new(@root) end def call(env) dup._call(env) end F = ::File def _call(env) @env = env @script_name = env[SCRIPT_NAME] @path_info = Utils.unescape(env[PATH_INFO]) if forbidden = check_forbidden forbidden else @path = F.join(@root, @path_info) list_path end end def check_forbidden return unless @path_info.include? ".." body = "Forbidden\n" size = Rack::Utils.bytesize(body) return [403, {"Content-Type" => "text/plain", CONTENT_LENGTH => size.to_s, "X-Cascade" => "pass"}, [body]] end def list_directory @files = [['../','Parent Directory','','','']] glob = F.join(@path, '*') url_head = (@script_name.split('/') + @path_info.split('/')).map do |part| Rack::Utils.escape part end Dir[glob].sort.each do |node| stat = stat(node) next unless stat basename = F.basename(node) ext = F.extname(node) url = F.join(*url_head + [Rack::Utils.escape(basename)]) size = stat.size type = stat.directory? ? 'directory' : Mime.mime_type(ext) size = stat.directory? ? '-' : filesize_format(size) mtime = stat.mtime.httpdate url << '/' if stat.directory? basename << '/' if stat.directory? @files << [ url, basename, size, type, mtime ] end return [ 200, { CONTENT_TYPE =>'text/html; charset=utf-8'}, self ] end def stat(node, max = 10) F.stat(node) rescue Errno::ENOENT, Errno::ELOOP return nil end # TODO: add correct response if not readable, not sure if 404 is the best # option def list_path @stat = F.stat(@path) if @stat.readable? return @app.call(@env) if @stat.file? return list_directory if @stat.directory? else raise Errno::ENOENT, 'No such file or directory' end rescue Errno::ENOENT, Errno::ELOOP return entity_not_found end def entity_not_found body = "Entity not found: #{@path_info}\n" size = Rack::Utils.bytesize(body) return [404, {"Content-Type" => "text/plain", CONTENT_LENGTH => size.to_s, "X-Cascade" => "pass"}, [body]] end def each show_path = Rack::Utils.escape_html(@path.sub(/^#{@root}/,'')) files = @files.map{|f| DIR_FILE % DIR_FILE_escape(*f) }*"\n" page = DIR_PAGE % [ show_path, show_path , files ] page.each_line{|l| yield l } end # Stolen from Ramaze FILESIZE_FORMAT = [ ['%.1fT', 1 << 40], ['%.1fG', 1 << 30], ['%.1fM', 1 << 20], ['%.1fK', 1 << 10], ] def filesize_format(int) FILESIZE_FORMAT.each do |format, size| return format % (int.to_f / size) if int >= size end int.to_s + 'B' end private # Assumes url is already escaped. def DIR_FILE_escape url, *html [url, *html.map { |e| Utils.escape_html(e) }] end end end PK!t?gems/2.2.0/gems/rack-1.6.4/lib/rack/backports/uri/common_192.rbnu[# :stopdoc: # Stolen from ruby core's uri/common.rb @32618ba to fix DoS issues in 1.9.2 # # https://github.com/ruby/ruby/blob/32618ba7438a2247042bba9b5d85b5d49070f5e5/lib/uri/common.rb # # Issue: # http://redmine.ruby-lang.org/issues/5149 # # Relevant Fixes: # https://github.com/ruby/ruby/commit/b5f91deee04aa6ccbe07c23c8222b937c22a799b # https://github.com/ruby/ruby/commit/93177c1e5c3906abf14472ae0b905d8b5c72ce1b # # This should probably be removed once there is a Ruby 1.9.2 patch level that # includes this fix. require 'uri/common' module URI TBLDECWWWCOMP_ = {} unless const_defined?(:TBLDECWWWCOMP_) #:nodoc: if TBLDECWWWCOMP_.empty? 256.times do |i| h, l = i>>4, i&15 TBLDECWWWCOMP_['%%%X%X' % [h, l]] = i.chr TBLDECWWWCOMP_['%%%x%X' % [h, l]] = i.chr TBLDECWWWCOMP_['%%%X%x' % [h, l]] = i.chr TBLDECWWWCOMP_['%%%x%x' % [h, l]] = i.chr end TBLDECWWWCOMP_['+'] = ' ' TBLDECWWWCOMP_.freeze end def self.decode_www_form(str, enc=Encoding::UTF_8) return [] if str.empty? unless /\A#{WFKV_}=#{WFKV_}(?:[;&]#{WFKV_}=#{WFKV_})*\z/o =~ str raise ArgumentError, "invalid data of application/x-www-form-urlencoded (#{str})" end ary = [] $&.scan(/([^=;&]+)=([^;&]*)/) do ary << [decode_www_form_component($1, enc), decode_www_form_component($2, enc)] end ary end def self.decode_www_form_component(str, enc=Encoding::UTF_8) raise ArgumentError, "invalid %-encoding (#{str})" unless /\A[^%]*(?:%\h\h[^%]*)*\z/ =~ str str.gsub(/\+|%\h\h/, TBLDECWWWCOMP_).force_encoding(enc) end remove_const :WFKV_ if const_defined?(:WFKV_) WFKV_ = '(?:[^%#=;&]*(?:%\h\h[^%#=;&]*)*)' # :nodoc: end PK!DLhh?gems/2.2.0/gems/rack-1.6.4/lib/rack/backports/uri/common_193.rbnu[# :stopdoc: require 'uri/common' # Issue: # http://bugs.ruby-lang.org/issues/5925 # # Relevant commit: # https://github.com/ruby/ruby/commit/edb7cdf1eabaff78dfa5ffedfbc2e91b29fa9ca1 module URI 256.times do |i| TBLENCWWWCOMP_[i.chr] = '%%%02X' % i end TBLENCWWWCOMP_[' '] = '+' TBLENCWWWCOMP_.freeze 256.times do |i| h, l = i>>4, i&15 TBLDECWWWCOMP_['%%%X%X' % [h, l]] = i.chr TBLDECWWWCOMP_['%%%x%X' % [h, l]] = i.chr TBLDECWWWCOMP_['%%%X%x' % [h, l]] = i.chr TBLDECWWWCOMP_['%%%x%x' % [h, l]] = i.chr end TBLDECWWWCOMP_['+'] = ' ' TBLDECWWWCOMP_.freeze end # :startdoc: PK! z>gems/2.2.0/gems/rack-1.6.4/lib/rack/backports/uri/common_18.rbnu[# :stopdoc: # Stolen from ruby core's uri/common.rb, with modifications to support 1.8.x # # https://github.com/ruby/ruby/blob/trunk/lib/uri/common.rb # # module URI TBLENCWWWCOMP_ = {} # :nodoc: 256.times do |i| TBLENCWWWCOMP_[i.chr] = '%%%02X' % i end TBLENCWWWCOMP_[' '] = '+' TBLENCWWWCOMP_.freeze TBLDECWWWCOMP_ = {} # :nodoc: 256.times do |i| h, l = i>>4, i&15 TBLDECWWWCOMP_['%%%X%X' % [h, l]] = i.chr TBLDECWWWCOMP_['%%%x%X' % [h, l]] = i.chr TBLDECWWWCOMP_['%%%X%x' % [h, l]] = i.chr TBLDECWWWCOMP_['%%%x%x' % [h, l]] = i.chr end TBLDECWWWCOMP_['+'] = ' ' TBLDECWWWCOMP_.freeze # Encode given +s+ to URL-encoded form data. # # This method doesn't convert *, -, ., 0-9, A-Z, _, a-z, but does convert SP # (ASCII space) to + and converts others to %XX. # # This is an implementation of # http://www.w3.org/TR/html5/forms.html#url-encoded-form-data # # See URI.decode_www_form_component, URI.encode_www_form def self.encode_www_form_component(s) str = s.to_s if RUBY_VERSION < "1.9" && $KCODE =~ /u/i str.gsub(/([^ a-zA-Z0-9_.-]+)/) do '%' + $1.unpack('H2' * Rack::Utils.bytesize($1)).join('%').upcase end.tr(' ', '+') else str.gsub(/[^*\-.0-9A-Z_a-z]/) {|m| TBLENCWWWCOMP_[m]} end end # Decode given +str+ of URL-encoded form data. # # This decodes + to SP. # # See URI.encode_www_form_component, URI.decode_www_form def self.decode_www_form_component(str, enc=nil) raise ArgumentError, "invalid %-encoding (#{str})" unless /\A(?:%[0-9a-fA-F]{2}|[^%])*\z/ =~ str str.gsub(/\+|%[0-9a-fA-F]{2}/) {|m| TBLDECWWWCOMP_[m]} end end PK! 5gems/2.2.0/gems/rack-1.6.4/lib/rack/conditionalget.rbnu[require 'rack/utils' module Rack # Middleware that enables conditional GET using If-None-Match and # If-Modified-Since. The application should set either or both of the # Last-Modified or Etag response headers according to RFC 2616. When # either of the conditions is met, the response body is set to be zero # length and the response status is set to 304 Not Modified. # # Applications that defer response body generation until the body's each # message is received will avoid response body generation completely when # a conditional GET matches. # # Adapted from Michael Klishin's Merb implementation: # https://github.com/wycats/merb/blob/master/merb-core/lib/merb-core/rack/middleware/conditional_get.rb class ConditionalGet def initialize(app) @app = app end def call(env) case env[REQUEST_METHOD] when "GET", "HEAD" status, headers, body = @app.call(env) headers = Utils::HeaderHash.new(headers) if status == 200 && fresh?(env, headers) status = 304 headers.delete(CONTENT_TYPE) headers.delete(CONTENT_LENGTH) original_body = body body = Rack::BodyProxy.new([]) do original_body.close if original_body.respond_to?(:close) end end [status, headers, body] else @app.call(env) end end private def fresh?(env, headers) modified_since = env['HTTP_IF_MODIFIED_SINCE'] none_match = env['HTTP_IF_NONE_MATCH'] return false unless modified_since || none_match success = true success &&= modified_since?(to_rfc2822(modified_since), headers) if modified_since success &&= etag_matches?(none_match, headers) if none_match success end def etag_matches?(none_match, headers) etag = headers['ETag'] and etag == none_match end def modified_since?(modified_since, headers) last_modified = to_rfc2822(headers['Last-Modified']) and modified_since and modified_since >= last_modified end def to_rfc2822(since) # shortest possible valid date is the obsolete: 1 Nov 97 09:55 A # anything shorter is invalid, this avoids exceptions for common cases # most common being the empty string if since && since.length >= 16 # NOTE: there is no trivial way to write this in a non execption way # _rfc2822 returns a hash but is not that usable Time.rfc2822(since) rescue nil else nil end end end end PK!\ޢ7+7+-gems/2.2.0/gems/rack-1.6.4/lib/rack/server.rbnu[require 'optparse' module Rack class Server class Options def parse!(args) options = {} opt_parser = OptionParser.new("", 24, ' ') do |opts| opts.banner = "Usage: rackup [ruby options] [rack options] [rackup config]" opts.separator "" opts.separator "Ruby options:" lineno = 1 opts.on("-e", "--eval LINE", "evaluate a LINE of code") { |line| eval line, TOPLEVEL_BINDING, "-e", lineno lineno += 1 } opts.on("-b", "--builder BUILDER_LINE", "evaluate a BUILDER_LINE of code as a builder script") { |line| options[:builder] = line } opts.on("-d", "--debug", "set debugging flags (set $DEBUG to true)") { options[:debug] = true } opts.on("-w", "--warn", "turn warnings on for your script") { options[:warn] = true } opts.on("-q", "--quiet", "turn off logging") { options[:quiet] = true } opts.on("-I", "--include PATH", "specify $LOAD_PATH (may be used more than once)") { |path| (options[:include] ||= []).concat(path.split(":")) } opts.on("-r", "--require LIBRARY", "require the library, before executing your script") { |library| options[:require] = library } opts.separator "" opts.separator "Rack options:" opts.on("-s", "--server SERVER", "serve using SERVER (thin/puma/webrick/mongrel)") { |s| options[:server] = s } opts.on("-o", "--host HOST", "listen on HOST (default: localhost)") { |host| options[:Host] = host } opts.on("-p", "--port PORT", "use PORT (default: 9292)") { |port| options[:Port] = port } opts.on("-O", "--option NAME[=VALUE]", "pass VALUE to the server as option NAME. If no VALUE, sets it to true. Run '#{$0} -s SERVER -h' to get a list of options for SERVER") { |name| name, value = name.split('=', 2) value = true if value.nil? options[name.to_sym] = value } opts.on("-E", "--env ENVIRONMENT", "use ENVIRONMENT for defaults (default: development)") { |e| options[:environment] = e } opts.on("-D", "--daemonize", "run daemonized in the background") { |d| options[:daemonize] = d ? true : false } opts.on("-P", "--pid FILE", "file to store PID") { |f| options[:pid] = ::File.expand_path(f) } opts.separator "" opts.separator "Common options:" opts.on_tail("-h", "-?", "--help", "Show this message") do puts opts puts handler_opts(options) exit end opts.on_tail("--version", "Show version") do puts "Rack #{Rack.version} (Release: #{Rack.release})" exit end end begin opt_parser.parse! args rescue OptionParser::InvalidOption => e warn e.message abort opt_parser.to_s end options[:config] = args.last if args.last options end def handler_opts(options) begin info = [] server = Rack::Handler.get(options[:server]) || Rack::Handler.default(options) if server && server.respond_to?(:valid_options) info << "" info << "Server-specific options for #{server.name}:" has_options = false server.valid_options.each do |name, description| next if name.to_s.match(/^(Host|Port)[^a-zA-Z]/) # ignore handler's host and port options, we do our own. info << " -O %-21s %s" % [name, description] has_options = true end return "" if !has_options end info.join("\n") rescue NameError return "Warning: Could not find handler specified (#{options[:server] || 'default'}) to determine handler-specific options" end end end # Start a new rack server (like running rackup). This will parse ARGV and # provide standard ARGV rackup options, defaulting to load 'config.ru'. # # Providing an options hash will prevent ARGV parsing and will not include # any default options. # # This method can be used to very easily launch a CGI application, for # example: # # Rack::Server.start( # :app => lambda do |e| # [200, {'Content-Type' => 'text/html'}, ['hello world']] # end, # :server => 'cgi' # ) # # Further options available here are documented on Rack::Server#initialize def self.start(options = nil) new(options).start end attr_writer :options # Options may include: # * :app # a rack application to run (overrides :config) # * :config # a rackup configuration file path to load (.ru) # * :environment # this selects the middleware that will be wrapped around # your application. Default options available are: # - development: CommonLogger, ShowExceptions, and Lint # - deployment: CommonLogger # - none: no extra middleware # note: when the server is a cgi server, CommonLogger is not included. # * :server # choose a specific Rack::Handler, e.g. cgi, fcgi, webrick # * :daemonize # if true, the server will daemonize itself (fork, detach, etc) # * :pid # path to write a pid file after daemonize # * :Host # the host address to bind to (used by supporting Rack::Handler) # * :Port # the port to bind to (used by supporting Rack::Handler) # * :AccessLog # webrick access log options (or supporting Rack::Handler) # * :debug # turn on debug output ($DEBUG = true) # * :warn # turn on warnings ($-w = true) # * :include # add given paths to $LOAD_PATH # * :require # require the given libraries def initialize(options = nil) @options = options @app = options[:app] if options && options[:app] end def options @options ||= parse_options(ARGV) end def default_options environment = ENV['RACK_ENV'] || 'development' default_host = environment == 'development' ? 'localhost' : '0.0.0.0' { :environment => environment, :pid => nil, :Port => 9292, :Host => default_host, :AccessLog => [], :config => "config.ru" } end def app @app ||= options[:builder] ? build_app_from_string : build_app_and_options_from_config end class << self def logging_middleware lambda { |server| server.server.name =~ /CGI/ || server.options[:quiet] ? nil : [Rack::CommonLogger, $stderr] } end def default_middleware_by_environment m = Hash.new {|h,k| h[k] = []} m["deployment"] = [ [Rack::ContentLength], [Rack::Chunked], logging_middleware, [Rack::TempfileReaper] ] m["development"] = [ [Rack::ContentLength], [Rack::Chunked], logging_middleware, [Rack::ShowExceptions], [Rack::Lint], [Rack::TempfileReaper] ] m end def middleware default_middleware_by_environment end end def middleware self.class.middleware end def start &blk if options[:warn] $-w = true end if includes = options[:include] $LOAD_PATH.unshift(*includes) end if library = options[:require] require library end if options[:debug] $DEBUG = true require 'pp' p options[:server] pp wrapped_app pp app end check_pid! if options[:pid] # Touch the wrapped app, so that the config.ru is loaded before # daemonization (i.e. before chdir, etc). wrapped_app daemonize_app if options[:daemonize] write_pid if options[:pid] trap(:INT) do if server.respond_to?(:shutdown) server.shutdown else exit end end server.run wrapped_app, options, &blk end def server @_server ||= Rack::Handler.get(options[:server]) || Rack::Handler.default(options) end private def build_app_and_options_from_config if !::File.exist? options[:config] abort "configuration #{options[:config]} not found" end app, options = Rack::Builder.parse_file(self.options[:config], opt_parser) self.options.merge! options app end def build_app_from_string Rack::Builder.new_from_string(self.options[:builder]) end def parse_options(args) options = default_options # Don't evaluate CGI ISINDEX parameters. # http://www.meb.uni-bonn.de/docs/cgi/cl.html args.clear if ENV.include?(REQUEST_METHOD) options.merge! opt_parser.parse!(args) options[:config] = ::File.expand_path(options[:config]) ENV["RACK_ENV"] = options[:environment] options end def opt_parser Options.new end def build_app(app) middleware[options[:environment]].reverse_each do |middleware| middleware = middleware.call(self) if middleware.respond_to?(:call) next unless middleware klass, *args = middleware app = klass.new(app, *args) end app end def wrapped_app @wrapped_app ||= build_app app end def daemonize_app if RUBY_VERSION < "1.9" exit if fork Process.setsid exit if fork Dir.chdir "/" STDIN.reopen "/dev/null" STDOUT.reopen "/dev/null", "a" STDERR.reopen "/dev/null", "a" else Process.daemon end end def write_pid ::File.open(options[:pid], ::File::CREAT | ::File::EXCL | ::File::WRONLY ){ |f| f.write("#{Process.pid}") } at_exit { ::File.delete(options[:pid]) if ::File.exist?(options[:pid]) } rescue Errno::EEXIST check_pid! retry end def check_pid! case pidfile_process_status when :running, :not_owned $stderr.puts "A server is already running. Check #{options[:pid]}." exit(1) when :dead ::File.delete(options[:pid]) end end def pidfile_process_status return :exited unless ::File.exist?(options[:pid]) pid = ::File.read(options[:pid]).to_i return :dead if pid == 0 Process.kill(0, pid) :running rescue Errno::ESRCH :dead rescue Errno::EPERM :not_owned end end end PK!M D /gems/2.2.0/gems/rack-1.6.4/lib/rack/reloader.rbnu[# Copyright (c) 2009 Michael Fellinger m.fellinger@gmail.com # Rack::Reloader is subject to the terms of an MIT-style license. # See COPYING or http://www.opensource.org/licenses/mit-license.php. require 'pathname' module Rack # High performant source reloader # # This class acts as Rack middleware. # # What makes it especially suited for use in a production environment is that # any file will only be checked once and there will only be made one system # call stat(2). # # Please note that this will not reload files in the background, it does so # only when actively called. # # It is performing a check/reload cycle at the start of every request, but # also respects a cool down time, during which nothing will be done. class Reloader def initialize(app, cooldown = 10, backend = Stat) @app = app @cooldown = cooldown @last = (Time.now - cooldown) @cache = {} @mtimes = {} extend backend end def call(env) if @cooldown and Time.now > @last + @cooldown if Thread.list.size > 1 Thread.exclusive{ reload! } else reload! end @last = Time.now end @app.call(env) end def reload!(stderr = $stderr) rotation do |file, mtime| previous_mtime = @mtimes[file] ||= mtime safe_load(file, mtime, stderr) if mtime > previous_mtime end end # A safe Kernel::load, issuing the hooks depending on the results def safe_load(file, mtime, stderr = $stderr) load(file) stderr.puts "#{self.class}: reloaded `#{file}'" file rescue LoadError, SyntaxError => ex stderr.puts ex ensure @mtimes[file] = mtime end module Stat def rotation files = [$0, *$LOADED_FEATURES].uniq paths = ['./', *$LOAD_PATH].uniq files.map{|file| next if file =~ /\.(so|bundle)$/ # cannot reload compiled files found, stat = figure_path(file, paths) next unless found && stat && mtime = stat.mtime @cache[file] = found yield(found, mtime) }.compact end # Takes a relative or absolute +file+ name, a couple possible +paths+ that # the +file+ might reside in. Returns the full path and File::Stat for the # path. def figure_path(file, paths) found = @cache[file] found = file if !found and Pathname.new(file).absolute? found, stat = safe_stat(found) return found, stat if found paths.find do |possible_path| path = ::File.join(possible_path, file) found, stat = safe_stat(path) return ::File.expand_path(found), stat if found end return false, false end def safe_stat(file) return unless file stat = ::File.stat(file) return file, stat if stat.file? rescue Errno::ENOENT, Errno::ENOTDIR, Errno::ESRCH @cache.delete(file) and false end end end end PK!Llpp+gems/2.2.0/gems/rack-1.6.4/lib/rack/etag.rbnu[require 'digest/md5' module Rack # Automatically sets the ETag header on all String bodies. # # The ETag header is skipped if ETag or Last-Modified headers are sent or if # a sendfile body (body.responds_to :to_path) is given (since such cases # should be handled by apache/nginx). # # On initialization, you can pass two parameters: a Cache-Control directive # used when Etag is absent and a directive when it is present. The first # defaults to nil, while the second defaults to "max-age=0, private, must-revalidate" class ETag ETAG_STRING = 'ETag'.freeze DEFAULT_CACHE_CONTROL = "max-age=0, private, must-revalidate".freeze def initialize(app, no_cache_control = nil, cache_control = DEFAULT_CACHE_CONTROL) @app = app @cache_control = cache_control @no_cache_control = no_cache_control end def call(env) status, headers, body = @app.call(env) if etag_status?(status) && etag_body?(body) && !skip_caching?(headers) original_body = body digest, new_body = digest_body(body) body = Rack::BodyProxy.new(new_body) do original_body.close if original_body.respond_to?(:close) end headers[ETAG_STRING] = %(W/"#{digest}") if digest end unless headers[CACHE_CONTROL] if digest headers[CACHE_CONTROL] = @cache_control if @cache_control else headers[CACHE_CONTROL] = @no_cache_control if @no_cache_control end end [status, headers, body] end private def etag_status?(status) status == 200 || status == 201 end def etag_body?(body) !body.respond_to?(:to_path) end def skip_caching?(headers) (headers[CACHE_CONTROL] && headers[CACHE_CONTROL].include?('no-cache')) || headers.key?(ETAG_STRING) || headers.key?('Last-Modified') end def digest_body(body) parts = [] digest = nil body.each do |part| parts << part (digest ||= Digest::MD5.new) << part unless part.empty? end [digest && digest.hexdigest, parts] end end end PK!(-gems/2.2.0/gems/rack-1.6.4/lib/rack/static.rbnu[module Rack # The Rack::Static middleware intercepts requests for static files # (javascript files, images, stylesheets, etc) based on the url prefixes or # route mappings passed in the options, and serves them using a Rack::File # object. This allows a Rack stack to serve both static and dynamic content. # # Examples: # # Serve all requests beginning with /media from the "media" folder located # in the current directory (ie media/*): # # use Rack::Static, :urls => ["/media"] # # Serve all requests beginning with /css or /images from the folder "public" # in the current directory (ie public/css/* and public/images/*): # # use Rack::Static, :urls => ["/css", "/images"], :root => "public" # # Serve all requests to / with "index.html" from the folder "public" in the # current directory (ie public/index.html): # # use Rack::Static, :urls => {"/" => 'index.html'}, :root => 'public' # # Serve all requests normally from the folder "public" in the current # directory but uses index.html as default route for "/" # # use Rack::Static, :urls => [""], :root => 'public', :index => # 'index.html' # # Set custom HTTP Headers for based on rules: # # use Rack::Static, :root => 'public', # :header_rules => [ # [rule, {header_field => content, header_field => content}], # [rule, {header_field => content}] # ] # # Rules for selecting files: # # 1) All files # Provide the :all symbol # :all => Matches every file # # 2) Folders # Provide the folder path as a string # '/folder' or '/folder/subfolder' => Matches files in a certain folder # # 3) File Extensions # Provide the file extensions as an array # ['css', 'js'] or %w(css js) => Matches files ending in .css or .js # # 4) Regular Expressions / Regexp # Provide a regular expression # %r{\.(?:css|js)\z} => Matches files ending in .css or .js # /\.(?:eot|ttf|otf|woff2|woff|svg)\z/ => Matches files ending in # the most common web font formats (.eot, .ttf, .otf, .woff2, .woff, .svg) # Note: This Regexp is available as a shortcut, using the :fonts rule # # 5) Font Shortcut # Provide the :fonts symbol # :fonts => Uses the Regexp rule stated right above to match all common web font endings # # Rule Ordering: # Rules are applied in the order that they are provided. # List rather general rules above special ones. # # Complete example use case including HTTP header rules: # # use Rack::Static, :root => 'public', # :header_rules => [ # # Cache all static files in public caches (e.g. Rack::Cache) # # as well as in the browser # [:all, {'Cache-Control' => 'public, max-age=31536000'}], # # # Provide web fonts with cross-origin access-control-headers # # Firefox requires this when serving assets using a Content Delivery Network # [:fonts, {'Access-Control-Allow-Origin' => '*'}] # ] # class Static def initialize(app, options={}) @app = app @urls = options[:urls] || ["/favicon.ico"] @index = options[:index] root = options[:root] || Dir.pwd # HTTP Headers @header_rules = options[:header_rules] || [] # Allow for legacy :cache_control option while prioritizing global header_rules setting @header_rules.insert(0, [:all, {'Cache-Control' => options[:cache_control]}]) if options[:cache_control] @file_server = Rack::File.new(root) end def overwrite_file_path(path) @urls.kind_of?(Hash) && @urls.key?(path) || @index && path =~ /\/$/ end def route_file(path) @urls.kind_of?(Array) && @urls.any? { |url| path.index(url) == 0 } end def can_serve(path) route_file(path) || overwrite_file_path(path) end def call(env) path = env[PATH_INFO] if can_serve(path) env["PATH_INFO"] = (path =~ /\/$/ ? path + @index : @urls[path]) if overwrite_file_path(path) path = env["PATH_INFO"] response = @file_server.call(env) headers = response[1] applicable_rules(path).each do |rule, new_headers| new_headers.each { |field, content| headers[field] = content } end response else @app.call(env) end end # Convert HTTP header rules to HTTP headers def applicable_rules(path) @header_rules.find_all do |rule, new_headers| case rule when :all true when :fonts path =~ /\.(?:ttf|otf|eot|woff2|woff|svg)\z/ when String path = ::Rack::Utils.unescape(path) path.start_with?(rule) || path.start_with?('/' + rule) when Array path =~ /\.(#{rule.join('|')})\z/ when Regexp path =~ rule else false end end end end end PK!>N  :gems/2.2.0/gems/rack-1.6.4/lib/rack/multipart/generator.rbnu[module Rack module Multipart class Generator def initialize(params, first = true) @params, @first = params, first if @first && !@params.is_a?(Hash) raise ArgumentError, "value must be a Hash" end end def dump return nil if @first && !multipart? return flattened_params if !@first flattened_params.map do |name, file| if file.respond_to?(:original_filename) ::File.open(file.path, "rb") do |f| f.set_encoding(Encoding::BINARY) if f.respond_to?(:set_encoding) content_for_tempfile(f, file, name) end else content_for_other(file, name) end end.join + "--#{MULTIPART_BOUNDARY}--\r" end private def multipart? multipart = false query = lambda { |value| case value when Array value.each(&query) when Hash value.values.each(&query) when Rack::Multipart::UploadedFile multipart = true end } @params.values.each(&query) multipart end def flattened_params @flattened_params ||= begin h = Hash.new @params.each do |key, value| k = @first ? key.to_s : "[#{key}]" case value when Array value.map { |v| Multipart.build_multipart(v, false).each { |subkey, subvalue| h["#{k}[]#{subkey}"] = subvalue } } when Hash Multipart.build_multipart(value, false).each { |subkey, subvalue| h[k + subkey] = subvalue } else h[k] = value end end h end end def content_for_tempfile(io, file, name) <<-EOF --#{MULTIPART_BOUNDARY}\r Content-Disposition: form-data; name="#{name}"; filename="#{Utils.escape(file.original_filename)}"\r Content-Type: #{file.content_type}\r Content-Length: #{::File.stat(file.path).size}\r \r #{io.read}\r EOF end def content_for_other(file, name) <<-EOF --#{MULTIPART_BOUNDARY}\r Content-Disposition: form-data; name="#{name}"\r \r #{file}\r EOF end end end endPK! K"">gems/2.2.0/gems/rack-1.6.4/lib/rack/multipart/uploaded_file.rbnu[module Rack module Multipart class UploadedFile # The filename, *not* including the path, of the "uploaded" file attr_reader :original_filename # The content type of the "uploaded" file attr_accessor :content_type def initialize(path, content_type = "text/plain", binary = false) raise "#{path} file does not exist" unless ::File.exist?(path) @content_type = content_type @original_filename = ::File.basename(path) @tempfile = Tempfile.new([@original_filename, ::File.extname(path)]) @tempfile.set_encoding(Encoding::BINARY) if @tempfile.respond_to?(:set_encoding) @tempfile.binmode if binary FileUtils.copy_file(path, @tempfile.path) end def path @tempfile.path end alias_method :local_path, :path def respond_to?(*args) super or @tempfile.respond_to?(*args) end def method_missing(method_name, *args, &block) #:nodoc: @tempfile.__send__(method_name, *args, &block) end end end end PK!^Oɬ7gems/2.2.0/gems/rack-1.6.4/lib/rack/multipart/parser.rbnu[require 'rack/utils' module Rack module Multipart class MultipartPartLimitError < Errno::EMFILE; end class Parser BUFSIZE = 16384 DUMMY = Struct.new(:parse).new def self.create(env) return DUMMY unless env['CONTENT_TYPE'] =~ MULTIPART io = env['rack.input'] io.rewind content_length = env['CONTENT_LENGTH'] content_length = content_length.to_i if content_length tempfile = env['rack.multipart.tempfile_factory'] || lambda { |filename, content_type| Tempfile.new(["RackMultipart", ::File.extname(filename)]) } bufsize = env['rack.multipart.buffer_size'] || BUFSIZE new($1, io, content_length, env, tempfile, bufsize) end def initialize(boundary, io, content_length, env, tempfile, bufsize) @buf = "" if @buf.respond_to? :force_encoding @buf.force_encoding Encoding::ASCII_8BIT end @params = Utils::KeySpaceConstrainedParams.new @boundary = "--#{boundary}" @io = io @content_length = content_length @boundary_size = Utils.bytesize(@boundary) + EOL.size @env = env @tempfile = tempfile @bufsize = bufsize if @content_length @content_length -= @boundary_size end @rx = /(?:#{EOL})?#{Regexp.quote(@boundary)}(#{EOL}|--)/n @full_boundary = @boundary + EOL end def parse fast_forward_to_first_boundary opened_files = 0 loop do head, filename, content_type, name, body = get_current_head_and_filename_and_content_type_and_name_and_body if Utils.multipart_part_limit > 0 opened_files += 1 if filename raise MultipartPartLimitError, 'Maximum file multiparts in content reached' if opened_files >= Utils.multipart_part_limit end # Save the rest. if i = @buf.index(rx) body << @buf.slice!(0, i) @buf.slice!(0, @boundary_size+2) @content_length = -1 if $1 == "--" end get_data(filename, body, content_type, name, head) do |data| tag_multipart_encoding(filename, content_type, name, data) Utils.normalize_params(@params, name, data) end # break if we're at the end of a buffer, but not if it is the end of a field break if (@buf.empty? && $1 != EOL) || @content_length == -1 end @io.rewind @params.to_params_hash end private def full_boundary; @full_boundary; end def rx; @rx; end def fast_forward_to_first_boundary loop do content = @io.read(@bufsize) raise EOFError, "bad content body" unless content @buf << content while @buf.gsub!(/\A([^\n]*\n)/, '') read_buffer = $1 return if read_buffer == full_boundary end raise EOFError, "bad content body" if Utils.bytesize(@buf) >= @bufsize end end def get_current_head_and_filename_and_content_type_and_name_and_body head = nil body = '' if body.respond_to? :force_encoding body.force_encoding Encoding::ASCII_8BIT end filename = content_type = name = nil until head && @buf =~ rx if !head && i = @buf.index(EOL+EOL) head = @buf.slice!(0, i+2) # First \r\n @buf.slice!(0, 2) # Second \r\n content_type = head[MULTIPART_CONTENT_TYPE, 1] name = head[MULTIPART_CONTENT_DISPOSITION, 1] || head[MULTIPART_CONTENT_ID, 1] filename = get_filename(head) if name.nil? || name.empty? && filename name = filename end if filename (@env['rack.tempfiles'] ||= []) << body = @tempfile.call(filename, content_type) body.binmode if body.respond_to?(:binmode) end next end # Save the read body part. if head && (@boundary_size+4 < @buf.size) body << @buf.slice!(0, @buf.size - (@boundary_size+4)) end content = @io.read(@content_length && @bufsize >= @content_length ? @content_length : @bufsize) raise EOFError, "bad content body" if content.nil? || content.empty? @buf << content @content_length -= content.size if @content_length end [head, filename, content_type, name, body] end def get_filename(head) filename = nil case head when RFC2183 filename = Hash[head.scan(DISPPARM)]['filename'] filename = $1 if filename and filename =~ /^"(.*)"$/ when BROKEN_QUOTED, BROKEN_UNQUOTED filename = $1 end return unless filename if filename.scan(/%.?.?/).all? { |s| s =~ /%[0-9a-fA-F]{2}/ } filename = Utils.unescape(filename) end scrub_filename filename if filename !~ /\\[^\\"]/ filename = filename.gsub(/\\(.)/, '\1') end filename end if "<3".respond_to? :valid_encoding? def scrub_filename(filename) unless filename.valid_encoding? # FIXME: this force_encoding is for Ruby 2.0 and 1.9 support. # We can remove it after they are dropped filename.force_encoding(Encoding::ASCII_8BIT) filename.encode!(:invalid => :replace, :undef => :replace) end end CHARSET = "charset" TEXT_PLAIN = "text/plain" def tag_multipart_encoding(filename, content_type, name, body) name.force_encoding Encoding::UTF_8 return if filename encoding = Encoding::UTF_8 if content_type list = content_type.split(';') type_subtype = list.first type_subtype.strip! if TEXT_PLAIN == type_subtype rest = list.drop 1 rest.each do |param| k,v = param.split('=', 2) k.strip! v.strip! encoding = Encoding.find v if k == CHARSET end end end name.force_encoding encoding body.force_encoding encoding end else def scrub_filename(filename) end def tag_multipart_encoding(filename, content_type, name, body) end end def get_data(filename, body, content_type, name, head) data = body if filename == "" # filename is blank which means no file has been selected return elsif filename body.rewind if body.respond_to?(:rewind) # Take the basename of the upload's original filename. # This handles the full Windows paths given by Internet Explorer # (and perhaps other broken user agents) without affecting # those which give the lone filename. filename = filename.split(/[\/\\]/).last data = {:filename => filename, :type => content_type, :name => name, :tempfile => body, :head => head} elsif !filename && content_type && body.is_a?(IO) body.rewind # Generic multipart cases, not coming from a form data = {:type => content_type, :name => name, :tempfile => body, :head => head} end yield data end end end end PK!& 1gems/2.2.0/gems/rack-1.6.4/lib/rack/showstatus.rbnu[require 'erb' require 'rack/request' require 'rack/utils' module Rack # Rack::ShowStatus catches all empty responses and replaces them # with a site explaining the error. # # Additional details can be put into rack.showstatus.detail # and will be shown as HTML. If such details exist, the error page # is always rendered, even if the reply was not empty. class ShowStatus def initialize(app) @app = app @template = ERB.new(TEMPLATE) end def call(env) status, headers, body = @app.call(env) headers = Utils::HeaderHash.new(headers) empty = headers[CONTENT_LENGTH].to_i <= 0 # client or server error, or explicit message if (status.to_i >= 400 && empty) || env["rack.showstatus.detail"] # This double assignment is to prevent an "unused variable" warning on # Ruby 1.9.3. Yes, it is dumb, but I don't like Ruby yelling at me. req = req = Rack::Request.new(env) message = Rack::Utils::HTTP_STATUS_CODES[status.to_i] || status.to_s # This double assignment is to prevent an "unused variable" warning on # Ruby 1.9.3. Yes, it is dumb, but I don't like Ruby yelling at me. detail = detail = env["rack.showstatus.detail"] || message body = @template.result(binding) size = Rack::Utils.bytesize(body) [status, headers.merge(CONTENT_TYPE => "text/html", CONTENT_LENGTH => size.to_s), [body]] else [status, headers, body] end end def h(obj) # :nodoc: case obj when String Utils.escape_html(obj) else Utils.escape_html(obj.inspect) end end # :stopdoc: # adapted from Django # Copyright (c) 2005, the Lawrence Journal-World # Used under the modified BSD license: # http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5 TEMPLATE = <<'HTML' <%=h message %> at <%=h req.script_name + req.path_info %>

    <%=h message %> (<%= status.to_i %>)

    Request Method: <%=h req.request_method %>
    Request URL: <%=h req.url %>

    <%=h detail %>

    You're seeing this error because you use Rack::ShowStatus.

    HTML # :startdoc: end end PK!U g77773gems/2.2.0/gems/rack-1.6.4/lib/rack/utils/okjson.rbnu[# encoding: UTF-8 # # Copyright 2011, 2012 Keith Rarick # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. # See https://github.com/kr/okjson for updates. require 'stringio' # Some parts adapted from # https://golang.org/src/encoding/json/decode.go and # https://golang.org/src/unicode/utf8/utf8.go module Rack::Utils::OkJson Upstream = '43' extend self # Decodes a json document in string s and # returns the corresponding ruby value. # String s must be valid UTF-8. If you have # a string in some other encoding, convert # it first. # # String values in the resulting structure # will be UTF-8. def decode(s) ts = lex(s) v, ts = textparse(ts) if ts.length > 0 raise Error, 'trailing garbage' end v end # Encodes x into a json text. It may contain only # Array, Hash, String, Numeric, true, false, nil. # (Note, this list excludes Symbol.) # X itself must be an Array or a Hash. # No other value can be encoded, and an error will # be raised if x contains any other value, such as # Nan, Infinity, Symbol, and Proc, or if a Hash key # is not a String. # Strings contained in x must be valid UTF-8. def encode(x) case x when Hash then objenc(x) when Array then arrenc(x) else raise Error, 'root value must be an Array or a Hash' end end def valenc(x) case x when Hash then objenc(x) when Array then arrenc(x) when String then strenc(x) when Numeric then numenc(x) when true then "true" when false then "false" when nil then "null" else raise Error, "cannot encode #{x.class}: #{x.inspect}" end end private # Parses a "json text" in the sense of RFC 4627. # Returns the parsed value and any trailing tokens. # Note: this is almost the same as valparse, # except that it does not accept atomic values. def textparse(ts) if ts.length <= 0 raise Error, 'empty' end typ, _, val = ts[0] case typ when '{' then objparse(ts) when '[' then arrparse(ts) else raise Error, "unexpected #{val.inspect}" end end # Parses a "value" in the sense of RFC 4627. # Returns the parsed value and any trailing tokens. def valparse(ts) if ts.length <= 0 raise Error, 'empty' end typ, _, val = ts[0] case typ when '{' then objparse(ts) when '[' then arrparse(ts) when :val,:str then [val, ts[1..-1]] else raise Error, "unexpected #{val.inspect}" end end # Parses an "object" in the sense of RFC 4627. # Returns the parsed value and any trailing tokens. def objparse(ts) ts = eat('{', ts) obj = {} if ts[0][0] == '}' return obj, ts[1..-1] end k, v, ts = pairparse(ts) obj[k] = v if ts[0][0] == '}' return obj, ts[1..-1] end loop do ts = eat(',', ts) k, v, ts = pairparse(ts) obj[k] = v if ts[0][0] == '}' return obj, ts[1..-1] end end end # Parses a "member" in the sense of RFC 4627. # Returns the parsed values and any trailing tokens. def pairparse(ts) (typ, _, k), ts = ts[0], ts[1..-1] if typ != :str raise Error, "unexpected #{k.inspect}" end ts = eat(':', ts) v, ts = valparse(ts) [k, v, ts] end # Parses an "array" in the sense of RFC 4627. # Returns the parsed value and any trailing tokens. def arrparse(ts) ts = eat('[', ts) arr = [] if ts[0][0] == ']' return arr, ts[1..-1] end v, ts = valparse(ts) arr << v if ts[0][0] == ']' return arr, ts[1..-1] end loop do ts = eat(',', ts) v, ts = valparse(ts) arr << v if ts[0][0] == ']' return arr, ts[1..-1] end end end def eat(typ, ts) if ts[0][0] != typ raise Error, "expected #{typ} (got #{ts[0].inspect})" end ts[1..-1] end # Scans s and returns a list of json tokens, # excluding white space (as defined in RFC 4627). def lex(s) ts = [] while s.length > 0 typ, lexeme, val = tok(s) if typ == nil raise Error, "invalid character at #{s[0,10].inspect}" end if typ != :space ts << [typ, lexeme, val] end s = s[lexeme.length..-1] end ts end # Scans the first token in s and # returns a 3-element list, or nil # if s does not begin with a valid token. # # The first list element is one of # '{', '}', ':', ',', '[', ']', # :val, :str, and :space. # # The second element is the lexeme. # # The third element is the value of the # token for :val and :str, otherwise # it is the lexeme. def tok(s) case s[0] when ?{ then ['{', s[0,1], s[0,1]] when ?} then ['}', s[0,1], s[0,1]] when ?: then [':', s[0,1], s[0,1]] when ?, then [',', s[0,1], s[0,1]] when ?[ then ['[', s[0,1], s[0,1]] when ?] then [']', s[0,1], s[0,1]] when ?n then nulltok(s) when ?t then truetok(s) when ?f then falsetok(s) when ?" then strtok(s) when Spc, ?\t, ?\n, ?\r then [:space, s[0,1], s[0,1]] else numtok(s) end end def nulltok(s); s[0,4] == 'null' ? [:val, 'null', nil] : [] end def truetok(s); s[0,4] == 'true' ? [:val, 'true', true] : [] end def falsetok(s); s[0,5] == 'false' ? [:val, 'false', false] : [] end def numtok(s) m = /-?([1-9][0-9]+|[0-9])([.][0-9]+)?([eE][+-]?[0-9]+)?/.match(s) if m && m.begin(0) == 0 if !m[2] && !m[3] [:val, m[0], Integer(m[0])] elsif m[2] [:val, m[0], Float(m[0])] else [:val, m[0], Integer(m[1])*(10**m[3][1..-1].to_i(10))] end else [] end end def strtok(s) m = /"([^"\\]|\\["\/\\bfnrt]|\\u[0-9a-fA-F]{4})*"/.match(s) if ! m raise Error, "invalid string literal at #{abbrev(s)}" end [:str, m[0], unquote(m[0])] end def abbrev(s) t = s[0,10] p = t['`'] t = t[0,p] if p t = t + '...' if t.length < s.length '`' + t + '`' end # Converts a quoted json string literal q into a UTF-8-encoded string. # The rules are different than for Ruby, so we cannot use eval. # Unquote will raise an error if q contains control characters. def unquote(q) q = q[1...-1] a = q.dup # allocate a big enough string # In ruby >= 1.9, a[w] is a codepoint, not a byte. if rubydoesenc? a.force_encoding('UTF-8') end r, w = 0, 0 while r < q.length c = q[r] if c == ?\\ r += 1 if r >= q.length raise Error, "string literal ends with a \"\\\": \"#{q}\"" end case q[r] when ?",?\\,?/,?' a[w] = q[r] r += 1 w += 1 when ?b,?f,?n,?r,?t a[w] = Unesc[q[r]] r += 1 w += 1 when ?u r += 1 uchar = begin hexdec4(q[r,4]) rescue RuntimeError => e raise Error, "invalid escape sequence \\u#{q[r,4]}: #{e}" end r += 4 if surrogate? uchar if q.length >= r+6 uchar1 = hexdec4(q[r+2,4]) uchar = subst(uchar, uchar1) if uchar != Ucharerr # A valid pair; consume. r += 6 end end end if rubydoesenc? a[w] = '' << uchar w += 1 else w += ucharenc(a, w, uchar) end else raise Error, "invalid escape char #{q[r]} in \"#{q}\"" end elsif c == ?" || c < Spc raise Error, "invalid character in string literal \"#{q}\"" else # Copy anything else byte-for-byte. # Valid UTF-8 will remain valid UTF-8. # Invalid UTF-8 will remain invalid UTF-8. # In ruby >= 1.9, c is a codepoint, not a byte, # in which case this is still what we want. a[w] = c r += 1 w += 1 end end a[0,w] end # Encodes unicode character u as UTF-8 # bytes in string a at position i. # Returns the number of bytes written. def ucharenc(a, i, u) if u <= Uchar1max a[i] = (u & 0xff).chr 1 elsif u <= Uchar2max a[i+0] = (Utag2 | ((u>>6)&0xff)).chr a[i+1] = (Utagx | (u&Umaskx)).chr 2 elsif u <= Uchar3max a[i+0] = (Utag3 | ((u>>12)&0xff)).chr a[i+1] = (Utagx | ((u>>6)&Umaskx)).chr a[i+2] = (Utagx | (u&Umaskx)).chr 3 else a[i+0] = (Utag4 | ((u>>18)&0xff)).chr a[i+1] = (Utagx | ((u>>12)&Umaskx)).chr a[i+2] = (Utagx | ((u>>6)&Umaskx)).chr a[i+3] = (Utagx | (u&Umaskx)).chr 4 end end def hexdec4(s) if s.length != 4 raise Error, 'short' end (nibble(s[0])<<12) | (nibble(s[1])<<8) | (nibble(s[2])<<4) | nibble(s[3]) end def subst(u1, u2) if Usurr1 <= u1 && u1 < Usurr2 && Usurr2 <= u2 && u2 < Usurr3 return ((u1-Usurr1)<<10) | (u2-Usurr2) + Usurrself end return Ucharerr end def surrogate?(u) Usurr1 <= u && u < Usurr3 end def nibble(c) if ?0 <= c && c <= ?9 then c.ord - ?0.ord elsif ?a <= c && c <= ?z then c.ord - ?a.ord + 10 elsif ?A <= c && c <= ?Z then c.ord - ?A.ord + 10 else raise Error, "invalid hex code #{c}" end end def objenc(x) '{' + x.map{|k,v| keyenc(k) + ':' + valenc(v)}.join(',') + '}' end def arrenc(a) '[' + a.map{|x| valenc(x)}.join(',') + ']' end def keyenc(k) case k when String then strenc(k) else raise Error, "Hash key is not a string: #{k.inspect}" end end def strenc(s) t = StringIO.new t.putc(?") r = 0 while r < s.length case s[r] when ?" then t.print('\\"') when ?\\ then t.print('\\\\') when ?\b then t.print('\\b') when ?\f then t.print('\\f') when ?\n then t.print('\\n') when ?\r then t.print('\\r') when ?\t then t.print('\\t') else c = s[r] # In ruby >= 1.9, s[r] is a codepoint, not a byte. if rubydoesenc? begin # c.ord will raise an error if c is invalid UTF-8 if c.ord < Spc.ord c = "\\u%04x" % [c.ord] end t.write(c) rescue t.write(Ustrerr) end elsif c < Spc t.write("\\u%04x" % c) elsif Spc <= c && c <= ?~ t.putc(c) else n = ucharcopy(t, s, r) # ensure valid UTF-8 output r += n - 1 # r is incremented below end end r += 1 end t.putc(?") t.string end def numenc(x) if ((x.nan? || x.infinite?) rescue false) raise Error, "Numeric cannot be represented: #{x}" end "#{x}" end # Copies the valid UTF-8 bytes of a single character # from string s at position i to I/O object t, and # returns the number of bytes copied. # If no valid UTF-8 char exists at position i, # ucharcopy writes Ustrerr and returns 1. def ucharcopy(t, s, i) n = s.length - i raise Utf8Error if n < 1 c0 = s[i].ord # 1-byte, 7-bit sequence? if c0 < Utagx t.putc(c0) return 1 end raise Utf8Error if c0 < Utag2 # unexpected continuation byte? raise Utf8Error if n < 2 # need continuation byte c1 = s[i+1].ord raise Utf8Error if c1 < Utagx || Utag2 <= c1 # 2-byte, 11-bit sequence? if c0 < Utag3 raise Utf8Error if ((c0&Umask2)<<6 | (c1&Umaskx)) <= Uchar1max t.putc(c0) t.putc(c1) return 2 end # need second continuation byte raise Utf8Error if n < 3 c2 = s[i+2].ord raise Utf8Error if c2 < Utagx || Utag2 <= c2 # 3-byte, 16-bit sequence? if c0 < Utag4 u = (c0&Umask3)<<12 | (c1&Umaskx)<<6 | (c2&Umaskx) raise Utf8Error if u <= Uchar2max t.putc(c0) t.putc(c1) t.putc(c2) return 3 end # need third continuation byte raise Utf8Error if n < 4 c3 = s[i+3].ord raise Utf8Error if c3 < Utagx || Utag2 <= c3 # 4-byte, 21-bit sequence? if c0 < Utag5 u = (c0&Umask4)<<18 | (c1&Umaskx)<<12 | (c2&Umaskx)<<6 | (c3&Umaskx) raise Utf8Error if u <= Uchar3max t.putc(c0) t.putc(c1) t.putc(c2) t.putc(c3) return 4 end raise Utf8Error rescue Utf8Error t.write(Ustrerr) return 1 end def rubydoesenc? ::String.method_defined?(:force_encoding) end class Utf8Error < ::StandardError end class Error < ::StandardError end Utagx = 0b1000_0000 Utag2 = 0b1100_0000 Utag3 = 0b1110_0000 Utag4 = 0b1111_0000 Utag5 = 0b1111_1000 Umaskx = 0b0011_1111 Umask2 = 0b0001_1111 Umask3 = 0b0000_1111 Umask4 = 0b0000_0111 Uchar1max = (1<<7) - 1 Uchar2max = (1<<11) - 1 Uchar3max = (1<<16) - 1 Ucharerr = 0xFFFD # unicode "replacement char" Ustrerr = "\xef\xbf\xbd" # unicode "replacement char" Usurrself = 0x10000 Usurr1 = 0xd800 Usurr2 = 0xdc00 Usurr3 = 0xe000 Spc = ' '[0] Unesc = {?b=>?\b, ?f=>?\f, ?n=>?\n, ?r=>?\r, ?t=>?\t} end PK!2=5ZZ.gems/2.2.0/gems/rack-1.6.4/lib/rack/cascade.rbnu[module Rack # Rack::Cascade tries a request on several apps, and returns the # first response that is not 404 or 405 (or in a list of configurable # status codes). class Cascade NotFound = [404, {CONTENT_TYPE => "text/plain"}, []] attr_reader :apps def initialize(apps, catch=[404, 405]) @apps = []; @has_app = {} apps.each { |app| add app } @catch = {} [*catch].each { |status| @catch[status] = true } end def call(env) result = NotFound last_body = nil @apps.each do |app| # The SPEC says that the body must be closed after it has been iterated # by the server, or if it is replaced by a middleware action. Cascade # replaces the body each time a cascade happens. It is assumed that nil # does not respond to close, otherwise the previous application body # will be closed. The final application body will not be closed, as it # will be passed to the server as a result. last_body.close if last_body.respond_to? :close result = app.call(env) last_body = result[2] break unless @catch.include?(result[0].to_i) end result end def add(app) @has_app[app] = true @apps << app end def include?(app) @has_app.include? app end alias_method :<<, :add end end PK!3m0gems/2.2.0/gems/rack-1.6.4/lib/rack/recursive.rbnu[require 'uri' module Rack # Rack::ForwardRequest gets caught by Rack::Recursive and redirects # the current request to the app at +url+. # # raise ForwardRequest.new("/not-found") # class ForwardRequest < Exception attr_reader :url, :env def initialize(url, env={}) @url = URI(url) @env = env @env[PATH_INFO] = @url.path @env[QUERY_STRING] = @url.query if @url.query @env["HTTP_HOST"] = @url.host if @url.host @env["HTTP_PORT"] = @url.port if @url.port @env["rack.url_scheme"] = @url.scheme if @url.scheme super "forwarding to #{url}" end end # Rack::Recursive allows applications called down the chain to # include data from other applications (by using # rack['rack.recursive.include'][...] or raise a # ForwardRequest to redirect internally. class Recursive def initialize(app) @app = app end def call(env) dup._call(env) end def _call(env) @script_name = env[SCRIPT_NAME] @app.call(env.merge('rack.recursive.include' => method(:include))) rescue ForwardRequest => req call(env.merge(req.env)) end def include(env, path) unless path.index(@script_name) == 0 && (path[@script_name.size] == ?/ || path[@script_name.size].nil?) raise ArgumentError, "can only include below #{@script_name}, not #{path}" end env = env.merge(PATH_INFO => path, SCRIPT_NAME => @script_name, REQUEST_METHOD => "GET", "CONTENT_LENGTH" => "0", "CONTENT_TYPE" => "", "rack.input" => StringIO.new("")) @app.call(env) end end end PK!6gems/2.2.0/gems/rack-1.6.4/lib/rack/tempfile_reaper.rbnu[require 'rack/body_proxy' module Rack # Middleware tracks and cleans Tempfiles created throughout a request (i.e. Rack::Multipart) # Ideas/strategy based on posts by Eric Wong and Charles Oliver Nutter # https://groups.google.com/forum/#!searchin/rack-devel/temp/rack-devel/brK8eh-MByw/sw61oJJCGRMJ class TempfileReaper def initialize(app) @app = app end def call(env) env['rack.tempfiles'] ||= [] status, headers, body = @app.call(env) body_proxy = BodyProxy.new(body) do env['rack.tempfiles'].each { |f| f.close! } unless env['rack.tempfiles'].nil? end [status, headers, body_proxy] end end end PK! wW 7gems/2.2.0/gems/rack-1.6.4/lib/rack/rewindable_input.rbnu[# -*- encoding: binary -*- require 'tempfile' require 'rack/utils' module Rack # Class which can make any IO object rewindable, including non-rewindable ones. It does # this by buffering the data into a tempfile, which is rewindable. # # rack.input is required to be rewindable, so if your input stream IO is non-rewindable # by nature (e.g. a pipe or a socket) then you can wrap it in an object of this class # to easily make it rewindable. # # Don't forget to call #close when you're done. This frees up temporary resources that # RewindableInput uses, though it does *not* close the original IO object. class RewindableInput def initialize(io) @io = io @rewindable_io = nil @unlinked = false end def gets make_rewindable unless @rewindable_io @rewindable_io.gets end def read(*args) make_rewindable unless @rewindable_io @rewindable_io.read(*args) end def each(&block) make_rewindable unless @rewindable_io @rewindable_io.each(&block) end def rewind make_rewindable unless @rewindable_io @rewindable_io.rewind end # Closes this RewindableInput object without closing the originally # wrapped IO oject. Cleans up any temporary resources that this RewindableInput # has created. # # This method may be called multiple times. It does nothing on subsequent calls. def close if @rewindable_io if @unlinked @rewindable_io.close else @rewindable_io.close! end @rewindable_io = nil end end private # Ruby's Tempfile class has a bug. Subclass it and fix it. class Tempfile < ::Tempfile def _close @tmpfile.close if @tmpfile @data[1] = nil if @data @tmpfile = nil end end def make_rewindable # Buffer all data into a tempfile. Since this tempfile is private to this # RewindableInput object, we chmod it so that nobody else can read or write # it. On POSIX filesystems we also unlink the file so that it doesn't # even have a file entry on the filesystem anymore, though we can still # access it because we have the file handle open. @rewindable_io = Tempfile.new('RackRewindableInput') @rewindable_io.chmod(0000) @rewindable_io.set_encoding(Encoding::BINARY) if @rewindable_io.respond_to?(:set_encoding) @rewindable_io.binmode if filesystem_has_posix_semantics? # Use ::File.unlink as 1.9.1 Tempfile has a bug where unlink closes the file! ::File.unlink @rewindable_io.path raise 'Unlink failed. IO closed.' if @rewindable_io.closed? @unlinked = true end buffer = "" while @io.read(1024 * 4, buffer) entire_buffer_written_out = false while !entire_buffer_written_out written = @rewindable_io.write(buffer) entire_buffer_written_out = written == Rack::Utils.bytesize(buffer) if !entire_buffer_written_out buffer.slice!(0 .. written - 1) end end end @rewindable_io.rewind end def filesystem_has_posix_semantics? RUBY_PLATFORM !~ /(mswin|mingw|cygwin|java)/ end end end PK!j/gems/2.2.0/gems/rack-1.6.4/lib/rack/sendfile.rbnu[require 'rack/file' require 'rack/body_proxy' module Rack # = Sendfile # # The Sendfile middleware intercepts responses whose body is being # served from a file and replaces it with a server specific X-Sendfile # header. The web server is then responsible for writing the file contents # to the client. This can dramatically reduce the amount of work required # by the Ruby backend and takes advantage of the web server's optimized file # delivery code. # # In order to take advantage of this middleware, the response body must # respond to +to_path+ and the request must include an X-Sendfile-Type # header. Rack::File and other components implement +to_path+ so there's # rarely anything you need to do in your application. The X-Sendfile-Type # header is typically set in your web servers configuration. The following # sections attempt to document # # === Nginx # # Nginx supports the X-Accel-Redirect header. This is similar to X-Sendfile # but requires parts of the filesystem to be mapped into a private URL # hierarchy. # # The following example shows the Nginx configuration required to create # a private "/files/" area, enable X-Accel-Redirect, and pass the special # X-Sendfile-Type and X-Accel-Mapping headers to the backend: # # location ~ /files/(.*) { # internal; # alias /var/www/$1; # } # # location / { # proxy_redirect off; # # proxy_set_header Host $host; # proxy_set_header X-Real-IP $remote_addr; # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # # proxy_set_header X-Sendfile-Type X-Accel-Redirect; # proxy_set_header X-Accel-Mapping /var/www/=/files/; # # proxy_pass http://127.0.0.1:8080/; # } # # Note that the X-Sendfile-Type header must be set exactly as shown above. # The X-Accel-Mapping header should specify the location on the file system, # followed by an equals sign (=), followed name of the private URL pattern # that it maps to. The middleware performs a simple substitution on the # resulting path. # # See Also: http://wiki.codemongers.com/NginxXSendfile # # === lighttpd # # Lighttpd has supported some variation of the X-Sendfile header for some # time, although only recent version support X-Sendfile in a reverse proxy # configuration. # # $HTTP["host"] == "example.com" { # proxy-core.protocol = "http" # proxy-core.balancer = "round-robin" # proxy-core.backends = ( # "127.0.0.1:8000", # "127.0.0.1:8001", # ... # ) # # proxy-core.allow-x-sendfile = "enable" # proxy-core.rewrite-request = ( # "X-Sendfile-Type" => (".*" => "X-Sendfile") # ) # } # # See Also: http://redmine.lighttpd.net/wiki/lighttpd/Docs:ModProxyCore # # === Apache # # X-Sendfile is supported under Apache 2.x using a separate module: # # https://tn123.org/mod_xsendfile/ # # Once the module is compiled and installed, you can enable it using # XSendFile config directive: # # RequestHeader Set X-Sendfile-Type X-Sendfile # ProxyPassReverse / http://localhost:8001/ # XSendFile on # # === Mapping parameter # # The third parameter allows for an overriding extension of the # X-Accel-Mapping header. Mappings should be provided in tuples of internal to # external. The internal values may contain regular expression syntax, they # will be matched with case indifference. class Sendfile F = ::File def initialize(app, variation=nil, mappings=[]) @app = app @variation = variation @mappings = mappings.map do |internal, external| [/^#{internal}/i, external] end end def call(env) status, headers, body = @app.call(env) if body.respond_to?(:to_path) case type = variation(env) when 'X-Accel-Redirect' path = F.expand_path(body.to_path) if url = map_accel_path(env, path) headers[CONTENT_LENGTH] = '0' headers[type] = url obody = body body = Rack::BodyProxy.new([]) do obody.close if obody.respond_to?(:close) end else env['rack.errors'].puts "X-Accel-Mapping header missing" end when 'X-Sendfile', 'X-Lighttpd-Send-File' path = F.expand_path(body.to_path) headers[CONTENT_LENGTH] = '0' headers[type] = path obody = body body = Rack::BodyProxy.new([]) do obody.close if obody.respond_to?(:close) end when '', nil else env['rack.errors'].puts "Unknown x-sendfile variation: '#{type}'.\n" end end [status, headers, body] end private def variation(env) @variation || env['sendfile.type'] || env['HTTP_X_SENDFILE_TYPE'] end def map_accel_path(env, path) if mapping = @mappings.find { |internal,_| internal =~ path } path.sub(*mapping) elsif mapping = env['HTTP_X_ACCEL_MAPPING'] internal, external = mapping.split('=', 2).map{ |p| p.strip } path.sub(/^#{internal}/i, external) end end end end PK!o+gems/2.2.0/gems/rack-1.6.4/lib/rack/mock.rbnu[require 'uri' require 'stringio' require 'rack' require 'rack/lint' require 'rack/utils' require 'rack/response' module Rack # Rack::MockRequest helps testing your Rack application without # actually using HTTP. # # After performing a request on a URL with get/post/put/patch/delete, it # returns a MockResponse with useful helper methods for effective # testing. # # You can pass a hash with additional configuration to the # get/post/put/patch/delete. # :input:: A String or IO-like to be used as rack.input. # :fatal:: Raise a FatalWarning if the app writes to rack.errors. # :lint:: If true, wrap the application in a Rack::Lint. class MockRequest class FatalWarning < RuntimeError end class FatalWarner def puts(warning) raise FatalWarning, warning end def write(warning) raise FatalWarning, warning end def flush end def string "" end end DEFAULT_ENV = { "rack.version" => Rack::VERSION, "rack.input" => StringIO.new, "rack.errors" => StringIO.new, "rack.multithread" => true, "rack.multiprocess" => true, "rack.run_once" => false, } def initialize(app) @app = app end def get(uri, opts={}) request("GET", uri, opts) end def post(uri, opts={}) request("POST", uri, opts) end def put(uri, opts={}) request("PUT", uri, opts) end def patch(uri, opts={}) request("PATCH", uri, opts) end def delete(uri, opts={}) request("DELETE", uri, opts) end def head(uri, opts={}) request("HEAD", uri, opts) end def options(uri, opts={}) request("OPTIONS", uri, opts) end def request(method="GET", uri="", opts={}) env = self.class.env_for(uri, opts.merge(:method => method)) if opts[:lint] app = Rack::Lint.new(@app) else app = @app end errors = env["rack.errors"] status, headers, body = app.call(env) MockResponse.new(status, headers, body, errors) ensure body.close if body.respond_to?(:close) end # For historical reasons, we're pinning to RFC 2396. It's easier for users # and we get support from ruby 1.8 to 2.2 using this method. def self.parse_uri_rfc2396(uri) @parser ||= defined?(URI::RFC2396_Parser) ? URI::RFC2396_Parser.new : URI @parser.parse(uri) end # Return the Rack environment used for a request to +uri+. def self.env_for(uri="", opts={}) uri = parse_uri_rfc2396(uri) uri.path = "/#{uri.path}" unless uri.path[0] == ?/ env = DEFAULT_ENV.dup env[REQUEST_METHOD] = opts[:method] ? opts[:method].to_s.upcase : "GET" env["SERVER_NAME"] = uri.host || "example.org" env["SERVER_PORT"] = uri.port ? uri.port.to_s : "80" env[QUERY_STRING] = uri.query.to_s env[PATH_INFO] = (!uri.path || uri.path.empty?) ? "/" : uri.path env["rack.url_scheme"] = uri.scheme || "http" env["HTTPS"] = env["rack.url_scheme"] == "https" ? "on" : "off" env[SCRIPT_NAME] = opts[:script_name] || "" if opts[:fatal] env["rack.errors"] = FatalWarner.new else env["rack.errors"] = StringIO.new end if params = opts[:params] if env[REQUEST_METHOD] == "GET" params = Utils.parse_nested_query(params) if params.is_a?(String) params.update(Utils.parse_nested_query(env[QUERY_STRING])) env[QUERY_STRING] = Utils.build_nested_query(params) elsif !opts.has_key?(:input) opts["CONTENT_TYPE"] = "application/x-www-form-urlencoded" if params.is_a?(Hash) if data = Utils::Multipart.build_multipart(params) opts[:input] = data opts["CONTENT_LENGTH"] ||= data.length.to_s opts["CONTENT_TYPE"] = "multipart/form-data; boundary=#{Utils::Multipart::MULTIPART_BOUNDARY}" else opts[:input] = Utils.build_nested_query(params) end else opts[:input] = params end end end empty_str = "" empty_str.force_encoding("ASCII-8BIT") if empty_str.respond_to? :force_encoding opts[:input] ||= empty_str if String === opts[:input] rack_input = StringIO.new(opts[:input]) else rack_input = opts[:input] end rack_input.set_encoding(Encoding::BINARY) if rack_input.respond_to?(:set_encoding) env['rack.input'] = rack_input env["CONTENT_LENGTH"] ||= env["rack.input"].length.to_s opts.each { |field, value| env[field] = value if String === field } env end end # Rack::MockResponse provides useful helpers for testing your apps. # Usually, you don't create the MockResponse on your own, but use # MockRequest. class MockResponse < Rack::Response # Headers attr_reader :original_headers # Errors attr_accessor :errors def initialize(status, headers, body, errors=StringIO.new("")) @original_headers = headers @errors = errors.string if errors.respond_to?(:string) @body_string = nil super(body, status, headers) end def =~(other) body =~ other end def match(other) body.match other end def body # FIXME: apparently users of MockResponse expect the return value of # MockResponse#body to be a string. However, the real response object # returns the body as a list. # # See spec_showstatus.rb: # # should "not replace existing messages" do # ... # res.body.should == "foo!" # end super.join end def empty? [201, 204, 205, 304].include? status end end end PK!Toee-gems/2.2.0/gems/rack-1.6.4/lib/rack/logger.rbnu[require 'logger' module Rack # Sets up rack.logger to write to rack.errors stream class Logger def initialize(app, level = ::Logger::INFO) @app, @level = app, level end def call(env) logger = ::Logger.new(env['rack.errors']) logger.level = @level env['rack.logger'] = logger @app.call(env) end end end PK!!0gems/2.2.0/gems/rack-1.6.4/lib/rack/multipart.rbnu[module Rack # A multipart form data parser, adapted from IOWA. # # Usually, Rack::Request#POST takes care of calling this. module Multipart autoload :UploadedFile, 'rack/multipart/uploaded_file' autoload :Parser, 'rack/multipart/parser' autoload :Generator, 'rack/multipart/generator' EOL = "\r\n" MULTIPART_BOUNDARY = "AaB03x" MULTIPART = %r|\Amultipart/.*boundary=\"?([^\";,]+)\"?|ni TOKEN = /[^\s()<>,;:\\"\/\[\]?=]+/ CONDISP = /Content-Disposition:\s*#{TOKEN}\s*/i DISPPARM = /;\s*(#{TOKEN})=("(?:\\"|[^"])*"|#{TOKEN})/ RFC2183 = /^#{CONDISP}(#{DISPPARM})+$/i BROKEN_QUOTED = /^#{CONDISP}.*;\sfilename="(.*?)"(?:\s*$|\s*;\s*#{TOKEN}=)/i BROKEN_UNQUOTED = /^#{CONDISP}.*;\sfilename=(#{TOKEN})/i MULTIPART_CONTENT_TYPE = /Content-Type: (.*)#{EOL}/ni MULTIPART_CONTENT_DISPOSITION = /Content-Disposition:.*\s+name="?([^\";]*)"?/ni MULTIPART_CONTENT_ID = /Content-ID:\s*([^#{EOL}]*)/ni class << self def parse_multipart(env) Parser.create(env).parse end def build_multipart(params, first = true) Generator.new(params, first).dump end end end end PK!1Hv.gems/2.2.0/gems/rack-1.6.4/lib/rack/builder.rbnu[module Rack # Rack::Builder implements a small DSL to iteratively construct Rack # applications. # # Example: # # require 'rack/lobster' # app = Rack::Builder.new do # use Rack::CommonLogger # use Rack::ShowExceptions # map "/lobster" do # use Rack::Lint # run Rack::Lobster.new # end # end # # run app # # Or # # app = Rack::Builder.app do # use Rack::CommonLogger # run lambda { |env| [200, {'Content-Type' => 'text/plain'}, ['OK']] } # end # # run app # # +use+ adds middleware to the stack, +run+ dispatches to an application. # You can use +map+ to construct a Rack::URLMap in a convenient way. class Builder def self.parse_file(config, opts = Server::Options.new) options = {} if config =~ /\.ru$/ cfgfile = ::File.read(config) if cfgfile[/^#\\(.*)/] && opts options = opts.parse! $1.split(/\s+/) end cfgfile.sub!(/^__END__\n.*\Z/m, '') app = new_from_string cfgfile, config else require config app = Object.const_get(::File.basename(config, '.rb').capitalize) end return app, options end def self.new_from_string(builder_script, file="(rackup)") eval "Rack::Builder.new {\n" + builder_script + "\n}.to_app", TOPLEVEL_BINDING, file, 0 end def initialize(default_app = nil,&block) @use, @map, @run, @warmup = [], nil, default_app, nil instance_eval(&block) if block_given? end def self.app(default_app = nil, &block) self.new(default_app, &block).to_app end # Specifies middleware to use in a stack. # # class Middleware # def initialize(app) # @app = app # end # # def call(env) # env["rack.some_header"] = "setting an example" # @app.call(env) # end # end # # use Middleware # run lambda { |env| [200, { "Content-Type" => "text/plain" }, ["OK"]] } # # All requests through to this application will first be processed by the middleware class. # The +call+ method in this example sets an additional environment key which then can be # referenced in the application if required. def use(middleware, *args, &block) if @map mapping, @map = @map, nil @use << proc { |app| generate_map app, mapping } end @use << proc { |app| middleware.new(app, *args, &block) } end # Takes an argument that is an object that responds to #call and returns a Rack response. # The simplest form of this is a lambda object: # # run lambda { |env| [200, { "Content-Type" => "text/plain" }, ["OK"]] } # # However this could also be a class: # # class Heartbeat # def self.call(env) # [200, { "Content-Type" => "text/plain" }, ["OK"]] # end # end # # run Heartbeat def run(app) @run = app end # Takes a lambda or block that is used to warm-up the application. # # warmup do |app| # client = Rack::MockRequest.new(app) # client.get('/') # end # # use SomeMiddleware # run MyApp def warmup(prc=nil, &block) @warmup = prc || block end # Creates a route within the application. # # Rack::Builder.app do # map '/' do # run Heartbeat # end # end # # The +use+ method can also be used here to specify middleware to run under a specific path: # # Rack::Builder.app do # map '/' do # use Middleware # run Heartbeat # end # end # # This example includes a piece of middleware which will run before requests hit +Heartbeat+. # def map(path, &block) @map ||= {} @map[path] = block end def to_app app = @map ? generate_map(@run, @map) : @run fail "missing run or map statement" unless app app = @use.reverse.inject(app) { |a,e| e[a] } @warmup.call(app) if @warmup app end def call(env) to_app.call(env) end private def generate_map(default_app, mapping) mapped = default_app ? {'/' => default_app} : {} mapping.each { |r,b| mapped[r] = self.class.new(default_app, &b).to_app } URLMap.new(mapped) end end end PK!pe e 6gems/2.2.0/gems/rack-1.6.4/lib/rack/auth/digest/md5.rbnu[require 'rack/auth/abstract/handler' require 'rack/auth/digest/request' require 'rack/auth/digest/params' require 'rack/auth/digest/nonce' require 'digest/md5' module Rack module Auth module Digest # Rack::Auth::Digest::MD5 implements the MD5 algorithm version of # HTTP Digest Authentication, as per RFC 2617. # # Initialize with the [Rack] application that you want protecting, # and a block that looks up a plaintext password for a given username. # # +opaque+ needs to be set to a constant base64/hexadecimal string. # class MD5 < AbstractHandler attr_accessor :opaque attr_writer :passwords_hashed def initialize(app, realm=nil, opaque=nil, &authenticator) @passwords_hashed = nil if opaque.nil? and realm.respond_to? :values_at realm, opaque, @passwords_hashed = realm.values_at :realm, :opaque, :passwords_hashed end super(app, realm, &authenticator) @opaque = opaque end def passwords_hashed? !!@passwords_hashed end def call(env) auth = Request.new(env) unless auth.provided? return unauthorized end if !auth.digest? || !auth.correct_uri? || !valid_qop?(auth) return bad_request end if valid?(auth) if auth.nonce.stale? return unauthorized(challenge(:stale => true)) else env['REMOTE_USER'] = auth.username return @app.call(env) end end unauthorized end private QOP = 'auth'.freeze def params(hash = {}) Params.new do |params| params['realm'] = realm params['nonce'] = Nonce.new.to_s params['opaque'] = H(opaque) params['qop'] = QOP hash.each { |k, v| params[k] = v } end end def challenge(hash = {}) "Digest #{params(hash)}" end def valid?(auth) valid_opaque?(auth) && valid_nonce?(auth) && valid_digest?(auth) end def valid_qop?(auth) QOP == auth.qop end def valid_opaque?(auth) H(opaque) == auth.opaque end def valid_nonce?(auth) auth.nonce.valid? end def valid_digest?(auth) pw = @authenticator.call(auth.username) pw && Rack::Utils.secure_compare(digest(auth, pw), auth.response) end def md5(data) ::Digest::MD5.hexdigest(data) end alias :H :md5 def KD(secret, data) H([secret, data] * ':') end def A1(auth, password) [ auth.username, auth.realm, password ] * ':' end def A2(auth) [ auth.method, auth.uri ] * ':' end def digest(auth, password) password_hash = passwords_hashed? ? password : H(A1(auth, password)) KD(password_hash, [ auth.nonce, auth.nc, auth.cnonce, QOP, H(A2(auth)) ] * ':') end end end end end PK!Nk=:gems/2.2.0/gems/rack-1.6.4/lib/rack/auth/digest/request.rbnu[require 'rack/auth/abstract/request' require 'rack/auth/digest/params' require 'rack/auth/digest/nonce' module Rack module Auth module Digest class Request < Auth::AbstractRequest def method @env['rack.methodoverride.original_method'] || @env[REQUEST_METHOD] end def digest? "digest" == scheme end def correct_uri? request.fullpath == uri end def nonce @nonce ||= Nonce.parse(params['nonce']) end def params @params ||= Params.parse(parts.last) end def respond_to?(sym, *) super or params.has_key? sym.to_s end def method_missing(sym, *args) return super unless params.has_key?(key = sym.to_s) return params[key] if args.size == 0 raise ArgumentError, "wrong number of arguments (#{args.size} for 0)" end end end end end PK!e8gems/2.2.0/gems/rack-1.6.4/lib/rack/auth/digest/nonce.rbnu[require 'digest/md5' module Rack module Auth module Digest # Rack::Auth::Digest::Nonce is the default nonce generator for the # Rack::Auth::Digest::MD5 authentication handler. # # +private_key+ needs to set to a constant string. # # +time_limit+ can be optionally set to an integer (number of seconds), # to limit the validity of the generated nonces. class Nonce class << self attr_accessor :private_key, :time_limit end def self.parse(string) new(*string.unpack("m*").first.split(' ', 2)) end def initialize(timestamp = Time.now, given_digest = nil) @timestamp, @given_digest = timestamp.to_i, given_digest end def to_s [([ @timestamp, digest ] * ' ')].pack("m*").strip end def digest ::Digest::MD5.hexdigest([ @timestamp, self.class.private_key ] * ':') end def valid? digest == @given_digest end def stale? !self.class.time_limit.nil? && (Time.now.to_i - @timestamp) > self.class.time_limit end def fresh? !stale? end end end end end PK!# MCC9gems/2.2.0/gems/rack-1.6.4/lib/rack/auth/digest/params.rbnu[module Rack module Auth module Digest class Params < Hash def self.parse(str) Params[*split_header_value(str).map do |param| k, v = param.split('=', 2) [k, dequote(v)] end.flatten] end def self.dequote(str) # From WEBrick::HTTPUtils ret = (/\A"(.*)"\Z/ =~ str) ? $1 : str.dup ret.gsub!(/\\(.)/, "\\1") ret end def self.split_header_value(str) str.scan( /(\w+\=(?:"[^\"]+"|[^,]+))/n ).collect{ |v| v[0] } end def initialize super() yield self if block_given? end def [](k) super k.to_s end def []=(k, v) super k.to_s, v.to_s end UNQUOTED = ['nc', 'stale'] def to_s map do |k, v| "#{k}=" + (UNQUOTED.include?(k) ? v.to_s : quote(v)) end.join(', ') end def quote(str) # From WEBrick::HTTPUtils '"' << str.gsub(/[\\\"]/o, "\\\1") << '"' end end end end end PK!Ǧ1gems/2.2.0/gems/rack-1.6.4/lib/rack/auth/basic.rbnu[require 'rack/auth/abstract/handler' require 'rack/auth/abstract/request' module Rack module Auth # Rack::Auth::Basic implements HTTP Basic Authentication, as per RFC 2617. # # Initialize with the Rack application that you want protecting, # and a block that checks if a username and password pair are valid. # # See also: example/protectedlobster.rb class Basic < AbstractHandler def call(env) auth = Basic::Request.new(env) return unauthorized unless auth.provided? return bad_request unless auth.basic? if valid?(auth) env['REMOTE_USER'] = auth.username return @app.call(env) end unauthorized end private def challenge 'Basic realm="%s"' % realm end def valid?(auth) @authenticator.call(*auth.credentials) end class Request < Auth::AbstractRequest def basic? "basic" == scheme end def credentials @credentials ||= params.unpack("m*").first.split(/:/, 2) end def username credentials.first end end end end end PK!k<gems/2.2.0/gems/rack-1.6.4/lib/rack/auth/abstract/request.rbnu[require 'rack/request' module Rack module Auth class AbstractRequest def initialize(env) @env = env end def request @request ||= Request.new(@env) end def provided? !authorization_key.nil? end def parts @parts ||= @env[authorization_key].split(' ', 2) end def scheme @scheme ||= parts.first && parts.first.downcase end def params @params ||= parts.last end private AUTHORIZATION_KEYS = ['HTTP_AUTHORIZATION', 'X-HTTP_AUTHORIZATION', 'X_HTTP_AUTHORIZATION'] def authorization_key @authorization_key ||= AUTHORIZATION_KEYS.detect { |key| @env.has_key?(key) } end end end end PK!3g  <gems/2.2.0/gems/rack-1.6.4/lib/rack/auth/abstract/handler.rbnu[module Rack module Auth # Rack::Auth::AbstractHandler implements common authentication functionality. # # +realm+ should be set for all handlers. class AbstractHandler attr_accessor :realm def initialize(app, realm=nil, &authenticator) @app, @realm, @authenticator = app, realm, authenticator end private def unauthorized(www_authenticate = challenge) return [ 401, { CONTENT_TYPE => 'text/plain', CONTENT_LENGTH => '0', 'WWW-Authenticate' => www_authenticate.to_s }, [] ] end def bad_request return [ 400, { CONTENT_TYPE => 'text/plain', CONTENT_LENGTH => '0' }, [] ] end end end end PK!Tuu+gems/2.2.0/gems/rack-1.6.4/lib/rack/lint.rbnu[require 'rack/utils' require 'forwardable' module Rack # Rack::Lint validates your application and the requests and # responses according to the Rack spec. class Lint def initialize(app) @app = app @content_length = nil end # :stopdoc: class LintError < RuntimeError; end module Assertion def assert(message, &block) unless block.call raise LintError, message end end end include Assertion ## This specification aims to formalize the Rack protocol. You ## can (and should) use Rack::Lint to enforce it. ## ## When you develop middleware, be sure to add a Lint before and ## after to catch all mistakes. ## = Rack applications ## A Rack application is a Ruby object (not a class) that ## responds to +call+. def call(env=nil) dup._call(env) end def _call(env) ## It takes exactly one argument, the *environment* assert("No env given") { env } check_env env env['rack.input'] = InputWrapper.new(env['rack.input']) env['rack.errors'] = ErrorWrapper.new(env['rack.errors']) ## and returns an Array of exactly three values: status, headers, @body = @app.call(env) ## The *status*, check_status status ## the *headers*, check_headers headers check_hijack_response headers, env ## and the *body*. check_content_type status, headers check_content_length status, headers @head_request = env[REQUEST_METHOD] == "HEAD" [status, headers, self] end ## == The Environment def check_env(env) ## The environment must be an instance of Hash that includes ## CGI-like headers. The application is free to modify the ## environment. assert("env #{env.inspect} is not a Hash, but #{env.class}") { env.kind_of? Hash } ## ## The environment is required to include these variables ## (adopted from PEP333), except when they'd be empty, but see ## below. ## REQUEST_METHOD:: The HTTP request method, such as ## "GET" or "POST". This cannot ever ## be an empty string, and so is ## always required. ## SCRIPT_NAME:: The initial portion of the request ## URL's "path" that corresponds to the ## application object, so that the ## application knows its virtual ## "location". This may be an empty ## string, if the application corresponds ## to the "root" of the server. ## PATH_INFO:: The remainder of the request URL's ## "path", designating the virtual ## "location" of the request's target ## within the application. This may be an ## empty string, if the request URL targets ## the application root and does not have a ## trailing slash. This value may be ## percent-encoded when I originating from ## a URL. ## QUERY_STRING:: The portion of the request URL that ## follows the ?, if any. May be ## empty, but is always required! ## SERVER_NAME, SERVER_PORT:: ## When combined with SCRIPT_NAME and ## PATH_INFO, these variables can be ## used to complete the URL. Note, however, ## that HTTP_HOST, if present, ## should be used in preference to ## SERVER_NAME for reconstructing ## the request URL. ## SERVER_NAME and SERVER_PORT ## can never be empty strings, and so ## are always required. ## HTTP_ Variables:: Variables corresponding to the ## client-supplied HTTP request ## headers (i.e., variables whose ## names begin with HTTP_). The ## presence or absence of these ## variables should correspond with ## the presence or absence of the ## appropriate HTTP header in the ## request. See ## ## RFC3875 section 4.1.18 for ## specific behavior. ## In addition to this, the Rack environment must include these ## Rack-specific variables: ## rack.version:: The Array representing this version of Rack ## See Rack::VERSION, that corresponds to ## the version of this SPEC. ## rack.url_scheme:: +http+ or +https+, depending on the ## request URL. ## rack.input:: See below, the input stream. ## rack.errors:: See below, the error stream. ## rack.multithread:: true if the application object may be ## simultaneously invoked by another thread ## in the same process, false otherwise. ## rack.multiprocess:: true if an equivalent application object ## may be simultaneously invoked by another ## process, false otherwise. ## rack.run_once:: true if the server expects ## (but does not guarantee!) that the ## application will only be invoked this one ## time during the life of its containing ## process. Normally, this will only be true ## for a server based on CGI ## (or something similar). ## rack.hijack?:: present and true if the server supports ## connection hijacking. See below, hijacking. ## rack.hijack:: an object responding to #call that must be ## called at least once before using ## rack.hijack_io. ## It is recommended #call return rack.hijack_io ## as well as setting it in env if necessary. ## rack.hijack_io:: if rack.hijack? is true, and rack.hijack ## has received #call, this will contain ## an object resembling an IO. See hijacking. ## Additional environment specifications have approved to ## standardized middleware APIs. None of these are required to ## be implemented by the server. ## rack.session:: A hash like interface for storing ## request session data. ## The store must implement: if session = env['rack.session'] ## store(key, value) (aliased as []=); assert("session #{session.inspect} must respond to store and []=") { session.respond_to?(:store) && session.respond_to?(:[]=) } ## fetch(key, default = nil) (aliased as []); assert("session #{session.inspect} must respond to fetch and []") { session.respond_to?(:fetch) && session.respond_to?(:[]) } ## delete(key); assert("session #{session.inspect} must respond to delete") { session.respond_to?(:delete) } ## clear; assert("session #{session.inspect} must respond to clear") { session.respond_to?(:clear) } end ## rack.logger:: A common object interface for logging messages. ## The object must implement: if logger = env['rack.logger'] ## info(message, &block) assert("logger #{logger.inspect} must respond to info") { logger.respond_to?(:info) } ## debug(message, &block) assert("logger #{logger.inspect} must respond to debug") { logger.respond_to?(:debug) } ## warn(message, &block) assert("logger #{logger.inspect} must respond to warn") { logger.respond_to?(:warn) } ## error(message, &block) assert("logger #{logger.inspect} must respond to error") { logger.respond_to?(:error) } ## fatal(message, &block) assert("logger #{logger.inspect} must respond to fatal") { logger.respond_to?(:fatal) } end ## rack.multipart.buffer_size:: An Integer hint to the multipart parser as to what chunk size to use for reads and writes. if bufsize = env['rack.multipart.buffer_size'] assert("rack.multipart.buffer_size must be an Integer > 0 if specified") { bufsize.is_a?(Integer) && bufsize > 0 } end ## rack.multipart.tempfile_factory:: An object responding to #call with two arguments, the filename and content_type given for the multipart form field, and returning an IO-like object that responds to #<< and optionally #rewind. This factory will be used to instantiate the tempfile for each multipart form file upload field, rather than the default class of Tempfile. if tempfile_factory = env['rack.multipart.tempfile_factory'] assert("rack.multipart.tempfile_factory must respond to #call") { tempfile_factory.respond_to?(:call) } env['rack.multipart.tempfile_factory'] = lambda do |filename, content_type| io = tempfile_factory.call(filename, content_type) assert("rack.multipart.tempfile_factory return value must respond to #<<") { io.respond_to?(:<<) } io end end ## The server or the application can store their own data in the ## environment, too. The keys must contain at least one dot, ## and should be prefixed uniquely. The prefix rack. ## is reserved for use with the Rack core distribution and other ## accepted specifications and must not be used otherwise. ## %w[REQUEST_METHOD SERVER_NAME SERVER_PORT QUERY_STRING rack.version rack.input rack.errors rack.multithread rack.multiprocess rack.run_once].each { |header| assert("env missing required key #{header}") { env.include? header } } ## The environment must not contain the keys ## HTTP_CONTENT_TYPE or HTTP_CONTENT_LENGTH ## (use the versions without HTTP_). %w[HTTP_CONTENT_TYPE HTTP_CONTENT_LENGTH].each { |header| assert("env contains #{header}, must use #{header[5,-1]}") { not env.include? header } } ## The CGI keys (named without a period) must have String values. env.each { |key, value| next if key.include? "." # Skip extensions assert("env variable #{key} has non-string value #{value.inspect}") { value.kind_of? String } } ## There are the following restrictions: ## * rack.version must be an array of Integers. assert("rack.version must be an Array, was #{env["rack.version"].class}") { env["rack.version"].kind_of? Array } ## * rack.url_scheme must either be +http+ or +https+. assert("rack.url_scheme unknown: #{env["rack.url_scheme"].inspect}") { %w[http https].include? env["rack.url_scheme"] } ## * There must be a valid input stream in rack.input. check_input env["rack.input"] ## * There must be a valid error stream in rack.errors. check_error env["rack.errors"] ## * There may be a valid hijack stream in rack.hijack_io check_hijack env ## * The REQUEST_METHOD must be a valid token. assert("REQUEST_METHOD unknown: #{env[REQUEST_METHOD]}") { env["REQUEST_METHOD"] =~ /\A[0-9A-Za-z!\#$%&'*+.^_`|~-]+\z/ } ## * The SCRIPT_NAME, if non-empty, must start with / assert("SCRIPT_NAME must start with /") { !env.include?("SCRIPT_NAME") || env["SCRIPT_NAME"] == "" || env["SCRIPT_NAME"] =~ /\A\// } ## * The PATH_INFO, if non-empty, must start with / assert("PATH_INFO must start with /") { !env.include?("PATH_INFO") || env["PATH_INFO"] == "" || env["PATH_INFO"] =~ /\A\// } ## * The CONTENT_LENGTH, if given, must consist of digits only. assert("Invalid CONTENT_LENGTH: #{env["CONTENT_LENGTH"]}") { !env.include?("CONTENT_LENGTH") || env["CONTENT_LENGTH"] =~ /\A\d+\z/ } ## * One of SCRIPT_NAME or PATH_INFO must be ## set. PATH_INFO should be / if ## SCRIPT_NAME is empty. assert("One of SCRIPT_NAME or PATH_INFO must be set (make PATH_INFO '/' if SCRIPT_NAME is empty)") { env["SCRIPT_NAME"] || env["PATH_INFO"] } ## SCRIPT_NAME never should be /, but instead be empty. assert("SCRIPT_NAME cannot be '/', make it '' and PATH_INFO '/'") { env["SCRIPT_NAME"] != "/" } end ## === The Input Stream ## ## The input stream is an IO-like object which contains the raw HTTP ## POST data. def check_input(input) ## When applicable, its external encoding must be "ASCII-8BIT" and it ## must be opened in binary mode, for Ruby 1.9 compatibility. assert("rack.input #{input} does not have ASCII-8BIT as its external encoding") { input.external_encoding.name == "ASCII-8BIT" } if input.respond_to?(:external_encoding) assert("rack.input #{input} is not opened in binary mode") { input.binmode? } if input.respond_to?(:binmode?) ## The input stream must respond to +gets+, +each+, +read+ and +rewind+. [:gets, :each, :read, :rewind].each { |method| assert("rack.input #{input} does not respond to ##{method}") { input.respond_to? method } } end class InputWrapper include Assertion def initialize(input) @input = input end ## * +gets+ must be called without arguments and return a string, ## or +nil+ on EOF. def gets(*args) assert("rack.input#gets called with arguments") { args.size == 0 } v = @input.gets assert("rack.input#gets didn't return a String") { v.nil? or v.kind_of? String } v end ## * +read+ behaves like IO#read. ## Its signature is read([length, [buffer]]). ## ## If given, +length+ must be a non-negative Integer (>= 0) or +nil+, ## and +buffer+ must be a String and may not be nil. ## ## If +length+ is given and not nil, then this method reads at most ## +length+ bytes from the input stream. ## ## If +length+ is not given or nil, then this method reads ## all data until EOF. ## ## When EOF is reached, this method returns nil if +length+ is given ## and not nil, or "" if +length+ is not given or is nil. ## ## If +buffer+ is given, then the read data will be placed ## into +buffer+ instead of a newly created String object. def read(*args) assert("rack.input#read called with too many arguments") { args.size <= 2 } if args.size >= 1 assert("rack.input#read called with non-integer and non-nil length") { args.first.kind_of?(Integer) || args.first.nil? } assert("rack.input#read called with a negative length") { args.first.nil? || args.first >= 0 } end if args.size >= 2 assert("rack.input#read called with non-String buffer") { args[1].kind_of?(String) } end v = @input.read(*args) assert("rack.input#read didn't return nil or a String") { v.nil? or v.kind_of? String } if args[0].nil? assert("rack.input#read(nil) returned nil on EOF") { !v.nil? } end v end ## * +each+ must be called without arguments and only yield Strings. def each(*args) assert("rack.input#each called with arguments") { args.size == 0 } @input.each { |line| assert("rack.input#each didn't yield a String") { line.kind_of? String } yield line } end ## * +rewind+ must be called without arguments. It rewinds the input ## stream back to the beginning. It must not raise Errno::ESPIPE: ## that is, it may not be a pipe or a socket. Therefore, handler ## developers must buffer the input data into some rewindable object ## if the underlying input stream is not rewindable. def rewind(*args) assert("rack.input#rewind called with arguments") { args.size == 0 } assert("rack.input#rewind raised Errno::ESPIPE") { begin @input.rewind true rescue Errno::ESPIPE false end } end ## * +close+ must never be called on the input stream. def close(*args) assert("rack.input#close must not be called") { false } end end ## === The Error Stream def check_error(error) ## The error stream must respond to +puts+, +write+ and +flush+. [:puts, :write, :flush].each { |method| assert("rack.error #{error} does not respond to ##{method}") { error.respond_to? method } } end class ErrorWrapper include Assertion def initialize(error) @error = error end ## * +puts+ must be called with a single argument that responds to +to_s+. def puts(str) @error.puts str end ## * +write+ must be called with a single argument that is a String. def write(str) assert("rack.errors#write not called with a String") { str.kind_of? String } @error.write str end ## * +flush+ must be called without arguments and must be called ## in order to make the error appear for sure. def flush @error.flush end ## * +close+ must never be called on the error stream. def close(*args) assert("rack.errors#close must not be called") { false } end end class HijackWrapper include Assertion extend Forwardable REQUIRED_METHODS = [ :read, :write, :read_nonblock, :write_nonblock, :flush, :close, :close_read, :close_write, :closed? ] def_delegators :@io, *REQUIRED_METHODS def initialize(io) @io = io REQUIRED_METHODS.each do |meth| assert("rack.hijack_io must respond to #{meth}") { io.respond_to? meth } end end end ## === Hijacking # # AUTHORS: n.b. The trailing whitespace between paragraphs is important and # should not be removed. The whitespace creates paragraphs in the RDoc # output. # ## ==== Request (before status) def check_hijack(env) if env['rack.hijack?'] ## If rack.hijack? is true then rack.hijack must respond to #call. original_hijack = env['rack.hijack'] assert("rack.hijack must respond to call") { original_hijack.respond_to?(:call) } env['rack.hijack'] = proc do ## rack.hijack must return the io that will also be assigned (or is ## already present, in rack.hijack_io. io = original_hijack.call HijackWrapper.new(io) ## ## rack.hijack_io must respond to: ## read, write, read_nonblock, write_nonblock, flush, close, ## close_read, close_write, closed? ## ## The semantics of these IO methods must be a best effort match to ## those of a normal ruby IO or Socket object, using standard ## arguments and raising standard exceptions. Servers are encouraged ## to simply pass on real IO objects, although it is recognized that ## this approach is not directly compatible with SPDY and HTTP 2.0. ## ## IO provided in rack.hijack_io should preference the ## IO::WaitReadable and IO::WaitWritable APIs wherever supported. ## ## There is a deliberate lack of full specification around ## rack.hijack_io, as semantics will change from server to server. ## Users are encouraged to utilize this API with a knowledge of their ## server choice, and servers may extend the functionality of ## hijack_io to provide additional features to users. The purpose of ## rack.hijack is for Rack to "get out of the way", as such, Rack only ## provides the minimum of specification and support. env['rack.hijack_io'] = HijackWrapper.new(env['rack.hijack_io']) io end else ## ## If rack.hijack? is false, then rack.hijack should not be set. assert("rack.hijack? is false, but rack.hijack is present") { env['rack.hijack'].nil? } ## ## If rack.hijack? is false, then rack.hijack_io should not be set. assert("rack.hijack? is false, but rack.hijack_io is present") { env['rack.hijack_io'].nil? } end end ## ==== Response (after headers) ## It is also possible to hijack a response after the status and headers ## have been sent. def check_hijack_response(headers, env) # this check uses headers like a hash, but the spec only requires # headers respond to #each headers = Rack::Utils::HeaderHash.new(headers) ## In order to do this, an application may set the special header ## rack.hijack to an object that responds to call ## accepting an argument that conforms to the rack.hijack_io ## protocol. ## ## After the headers have been sent, and this hijack callback has been ## called, the application is now responsible for the remaining lifecycle ## of the IO. The application is also responsible for maintaining HTTP ## semantics. Of specific note, in almost all cases in the current SPEC, ## applications will have wanted to specify the header Connection:close in ## HTTP/1.1, and not Connection:keep-alive, as there is no protocol for ## returning hijacked sockets to the web server. For that purpose, use the ## body streaming API instead (progressively yielding strings via each). ## ## Servers must ignore the body part of the response tuple when ## the rack.hijack response API is in use. if env['rack.hijack?'] && headers['rack.hijack'] assert('rack.hijack header must respond to #call') { headers['rack.hijack'].respond_to? :call } original_hijack = headers['rack.hijack'] headers['rack.hijack'] = proc do |io| original_hijack.call HijackWrapper.new(io) end else ## ## The special response header rack.hijack must only be set ## if the request env has rack.hijack? true. assert('rack.hijack header must not be present if server does not support hijacking') { headers['rack.hijack'].nil? } end end ## ==== Conventions ## * Middleware should not use hijack unless it is handling the whole ## response. ## * Middleware may wrap the IO object for the response pattern. ## * Middleware should not wrap the IO object for the request pattern. The ## request pattern is intended to provide the hijacker with "raw tcp". ## == The Response ## === The Status def check_status(status) ## This is an HTTP status. When parsed as integer (+to_i+), it must be ## greater than or equal to 100. assert("Status must be >=100 seen as integer") { status.to_i >= 100 } end ## === The Headers def check_headers(header) ## The header must respond to +each+, and yield values of key and value. assert("headers object should respond to #each, but doesn't (got #{header.class} as headers)") { header.respond_to? :each } header.each { |key, value| ## Special headers starting "rack." are for communicating with the ## server, and must not be sent back to the client. next if key =~ /^rack\..+$/ ## The header keys must be Strings. assert("header key must be a string, was #{key.class}") { key.kind_of? String } ## The header must not contain a +Status+ key. assert("header must not contain Status") { key.downcase != "status" } ## The header must conform to RFC7230 token specification, i.e. cannot ## contain non-printable ASCII, DQUOTE or "(),/:;<=>?@[\]{}". assert("invalid header name: #{key}") { key !~ /[\(\),\/:;<=>\?@\[\\\]{}[:cntrl:]]/ } ## The values of the header must be Strings, assert("a header value must be a String, but the value of " + "'#{key}' is a #{value.class}") { value.kind_of? String } ## consisting of lines (for multiple header values, e.g. multiple ## Set-Cookie values) separated by "\\n". value.split("\n").each { |item| ## The lines must not contain characters below 037. assert("invalid header value #{key}: #{item.inspect}") { item !~ /[\000-\037]/ } } } end ## === The Content-Type def check_content_type(status, headers) headers.each { |key, value| ## There must not be a Content-Type, when the +Status+ is 1xx, ## 204, 205 or 304. if key.downcase == "content-type" assert("Content-Type header found in #{status} response, not allowed") { not Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include? status.to_i } return end } end ## === The Content-Length def check_content_length(status, headers) headers.each { |key, value| if key.downcase == 'content-length' ## There must not be a Content-Length header when the ## +Status+ is 1xx, 204, 205 or 304. assert("Content-Length header found in #{status} response, not allowed") { not Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include? status.to_i } @content_length = value end } end def verify_content_length(bytes) if @head_request assert("Response body was given for HEAD request, but should be empty") { bytes == 0 } elsif @content_length assert("Content-Length header was #{@content_length}, but should be #{bytes}") { @content_length == bytes.to_s } end end ## === The Body def each @closed = false bytes = 0 ## The Body must respond to +each+ assert("Response body must respond to each") do @body.respond_to?(:each) end @body.each { |part| ## and must only yield String values. assert("Body yielded non-string value #{part.inspect}") { part.kind_of? String } bytes += Rack::Utils.bytesize(part) yield part } verify_content_length(bytes) ## ## The Body itself should not be an instance of String, as this will ## break in Ruby 1.9. ## ## If the Body responds to +close+, it will be called after iteration. If ## the body is replaced by a middleware after action, the original body ## must be closed first, if it responds to close. # XXX howto: assert("Body has not been closed") { @closed } ## ## If the Body responds to +to_path+, it must return a String ## identifying the location of a file whose contents are identical ## to that produced by calling +each+; this may be used by the ## server as an alternative, possibly more efficient way to ## transport the response. if @body.respond_to?(:to_path) assert("The file identified by body.to_path does not exist") { ::File.exist? @body.to_path } end ## ## The Body commonly is an Array of Strings, the application ## instance itself, or a File-like object. end def close @closed = true @body.close if @body.respond_to?(:close) end # :startdoc: end end ## == Thanks ## Some parts of this specification are adopted from PEP333: Python ## Web Server Gateway Interface ## v1.0 (http://www.python.org/dev/peps/pep-0333/). I'd like to thank ## everyone involved in that effort. PK! -gems/2.2.0/gems/rack-1.6.4/lib/rack/urlmap.rbnu[module Rack # Rack::URLMap takes a hash mapping urls or paths to apps, and # dispatches accordingly. Support for HTTP/1.1 host names exists if # the URLs start with http:// or https://. # # URLMap modifies the SCRIPT_NAME and PATH_INFO such that the part # relevant for dispatch is in the SCRIPT_NAME, and the rest in the # PATH_INFO. This should be taken care of when you need to # reconstruct the URL in order to create links. # # URLMap dispatches in such a way that the longest paths are tried # first, since they are most specific. class URLMap NEGATIVE_INFINITY = -1.0 / 0.0 INFINITY = 1.0 / 0.0 def initialize(map = {}) remap(map) end def remap(map) @mapping = map.map { |location, app| if location =~ %r{\Ahttps?://(.*?)(/.*)} host, location = $1, $2 else host = nil end unless location[0] == ?/ raise ArgumentError, "paths need to start with /" end location = location.chomp('/') match = Regexp.new("^#{Regexp.quote(location).gsub('/', '/+')}(.*)", nil, 'n') [host, location, match, app] }.sort_by do |(host, location, _, _)| [host ? -host.size : INFINITY, -location.size] end end def call(env) path = env[PATH_INFO] script_name = env['SCRIPT_NAME'] hHost = env['HTTP_HOST'] sName = env['SERVER_NAME'] sPort = env['SERVER_PORT'] @mapping.each do |host, location, match, app| unless casecmp?(hHost, host) \ || casecmp?(sName, host) \ || (!host && (casecmp?(hHost, sName) || casecmp?(hHost, sName+':'+sPort))) next end next unless m = match.match(path.to_s) rest = m[1] next unless !rest || rest.empty? || rest[0] == ?/ env['SCRIPT_NAME'] = (script_name + location) env['PATH_INFO'] = rest return app.call(env) end [404, {CONTENT_TYPE => "text/plain", "X-Cascade" => "pass"}, ["Not Found: #{path}"]] ensure env['PATH_INFO'] = path env['SCRIPT_NAME'] = script_name end private def casecmp?(v1, v2) # if both nil, or they're the same string return true if v1 == v2 # if either are nil... (but they're not the same) return false if v1.nil? return false if v2.nil? # otherwise check they're not case-insensitive the same v1.casecmp(v2).zero? end end end PK! [[+gems/2.2.0/gems/rack-1.6.4/lib/rack/file.rbnu[require 'time' require 'rack/utils' require 'rack/mime' module Rack # Rack::File serves files below the +root+ directory given, according to the # path info of the Rack request. # e.g. when Rack::File.new("/etc") is used, you can access 'passwd' file # as http://localhost:9292/passwd # # Handlers can detect if bodies are a Rack::File, and use mechanisms # like sendfile on the +path+. class File ALLOWED_VERBS = %w[GET HEAD OPTIONS] ALLOW_HEADER = ALLOWED_VERBS.join(', ') attr_accessor :root attr_accessor :path attr_accessor :cache_control alias :to_path :path def initialize(root, headers={}, default_mime = 'text/plain') @root = root @headers = headers @default_mime = default_mime end def call(env) dup._call(env) end F = ::File def _call(env) unless ALLOWED_VERBS.include? env[REQUEST_METHOD] return fail(405, "Method Not Allowed", {'Allow' => ALLOW_HEADER}) end path_info = Utils.unescape(env[PATH_INFO]) clean_path_info = Utils.clean_path_info(path_info) @path = F.join(@root, clean_path_info) available = begin F.file?(@path) && F.readable?(@path) rescue SystemCallError false end if available serving(env) else fail(404, "File not found: #{path_info}") end end def serving(env) if env["REQUEST_METHOD"] == "OPTIONS" return [200, {'Allow' => ALLOW_HEADER, CONTENT_LENGTH => '0'}, []] end last_modified = F.mtime(@path).httpdate return [304, {}, []] if env['HTTP_IF_MODIFIED_SINCE'] == last_modified headers = { "Last-Modified" => last_modified } headers[CONTENT_TYPE] = mime_type if mime_type # Set custom headers @headers.each { |field, content| headers[field] = content } if @headers response = [ 200, headers, env[REQUEST_METHOD] == "HEAD" ? [] : self ] size = filesize ranges = Rack::Utils.byte_ranges(env, size) if ranges.nil? || ranges.length > 1 # No ranges, or multiple ranges (which we don't support): # TODO: Support multiple byte-ranges response[0] = 200 @range = 0..size-1 elsif ranges.empty? # Unsatisfiable. Return error, and file size: response = fail(416, "Byte range unsatisfiable") response[1]["Content-Range"] = "bytes */#{size}" return response else # Partial content: @range = ranges[0] response[0] = 206 response[1]["Content-Range"] = "bytes #{@range.begin}-#{@range.end}/#{size}" size = @range.end - @range.begin + 1 end response[2] = [response_body] unless response_body.nil? response[1][CONTENT_LENGTH] = size.to_s response end def each F.open(@path, "rb") do |file| file.seek(@range.begin) remaining_len = @range.end-@range.begin+1 while remaining_len > 0 part = file.read([8192, remaining_len].min) break unless part remaining_len -= part.length yield part end end end private def fail(status, body, headers = {}) body += "\n" [ status, { CONTENT_TYPE => "text/plain", CONTENT_LENGTH => body.size.to_s, "X-Cascade" => "pass" }.merge!(headers), [body] ] end # The MIME type for the contents of the file located at @path def mime_type Mime.mime_type(F.extname(@path), @default_mime) end def filesize # If response_body is present, use its size. return Rack::Utils.bytesize(response_body) if response_body # We check via File::size? whether this file provides size info # via stat (e.g. /proc files often don't), otherwise we have to # figure it out by reading the whole file into memory. F.size?(@path) || Utils.bytesize(F.read(@path)) end # By default, the response body for file requests is nil. # In this case, the response body will be generated later # from the file at @path def response_body nil end end end PK!Go3gems/2.2.0/gems/rack-1.6.4/lib/rack/content_type.rbnu[require 'rack/utils' module Rack # Sets the Content-Type header on responses which don't have one. # # Builder Usage: # use Rack::ContentType, "text/plain" # # When no content type argument is provided, "text/html" is assumed. class ContentType include Rack::Utils def initialize(app, content_type = "text/html") @app, @content_type = app, content_type end def call(env) status, headers, body = @app.call(env) headers = Utils::HeaderHash.new(headers) unless STATUS_WITH_NO_ENTITY_BODY.include?(status) headers[CONTENT_TYPE] ||= @content_type end [status, headers, body] end end end PK!+I\1gems/2.2.0/gems/rack-1.6.4/lib/rack/body_proxy.rbnu[module Rack class BodyProxy def initialize(body, &block) @body, @block, @closed = body, block, false end def respond_to?(*args) return false if args.first.to_s =~ /^to_ary$/ super or @body.respond_to?(*args) end def close return if @closed @closed = true begin @body.close if @body.respond_to? :close ensure @block.call end end def closed? @closed end # N.B. This method is a special case to address the bug described by #434. # We are applying this special case for #each only. Future bugs of this # class will be handled by requesting users to patch their ruby # implementation, to save adding too many methods in this class. def each(*args, &block) @body.each(*args, &block) end def method_missing(*args, &block) super if args.first.to_s =~ /^to_ary$/ @body.__send__(*args, &block) end end end PK!S5gems/2.2.0/gems/rack-1.6.4/lib/rack/methodoverride.rbnu[module Rack class MethodOverride HTTP_METHODS = %w(GET HEAD PUT POST DELETE OPTIONS PATCH LINK UNLINK) METHOD_OVERRIDE_PARAM_KEY = "_method".freeze HTTP_METHOD_OVERRIDE_HEADER = "HTTP_X_HTTP_METHOD_OVERRIDE".freeze ALLOWED_METHODS = ["POST"] def initialize(app) @app = app end def call(env) if allowed_methods.include?(env[REQUEST_METHOD]) method = method_override(env) if HTTP_METHODS.include?(method) env["rack.methodoverride.original_method"] = env[REQUEST_METHOD] env[REQUEST_METHOD] = method end end @app.call(env) end def method_override(env) req = Request.new(env) method = method_override_param(req) || env[HTTP_METHOD_OVERRIDE_HEADER] method.to_s.upcase end private def allowed_methods ALLOWED_METHODS end def method_override_param(req) req.POST[METHOD_OVERRIDE_PARAM_KEY] rescue Utils::InvalidParameterError, Utils::ParameterTypeError end end end PK!W{{-gems/2.2.0/gems/rack-1.6.4/lib/rack/config.rbnu[module Rack # Rack::Config modifies the environment using the block given during # initialization. # # Example: # use Rack::Config do |env| # env['my-key'] = 'some-value' # end class Config def initialize(app, &block) @app = app @block = block end def call(env) @block.call(env) @app.call(env) end end end PK!P1gems/2.2.0/gems/rack-1.6.4/lib/rack/nulllogger.rbnu[module Rack class NullLogger def initialize(app) @app = app end def call(env) env['rack.logger'] = self @app.call(env) end def info(progname = nil, &block); end def debug(progname = nil, &block); end def warn(progname = nil, &block); end def error(progname = nil, &block); end def fatal(progname = nil, &block); end def unknown(progname = nil, &block); end def info? ; end def debug? ; end def warn? ; end def error? ; end def fatal? ; end def level ; end def progname ; end def datetime_format ; end def formatter ; end def sev_threshold ; end def level=(level); end def progname=(progname); end def datetime_format=(datetime_format); end def formatter=(formatter); end def sev_threshold=(sev_threshold); end def close ; end def add(severity, message = nil, progname = nil, &block); end def <<(msg); end end end PK!q..5gems/2.2.0/gems/rack-1.6.4/lib/rack/showexceptions.rbnu[require 'ostruct' require 'erb' require 'rack/request' require 'rack/utils' module Rack # Rack::ShowExceptions catches all exceptions raised from the app it # wraps. It shows a useful backtrace with the sourcefile and # clickable context, the whole Rack environment and the request # data. # # Be careful when you use this on public-facing sites as it could # reveal information helpful to attackers. class ShowExceptions CONTEXT = 7 def initialize(app) @app = app @template = ERB.new(TEMPLATE) end def call(env) @app.call(env) rescue StandardError, LoadError, SyntaxError => e exception_string = dump_exception(e) env["rack.errors"].puts(exception_string) env["rack.errors"].flush if accepts_html?(env) content_type = "text/html" body = pretty(env, e) else content_type = "text/plain" body = exception_string end [ 500, { CONTENT_TYPE => content_type, CONTENT_LENGTH => Rack::Utils.bytesize(body).to_s, }, [body], ] end def prefers_plaintext?(env) !accepts_html(env) end def accepts_html?(env) Rack::Utils.best_q_match(env["HTTP_ACCEPT"], %w[text/html]) end private :accepts_html? def dump_exception(exception) string = "#{exception.class}: #{exception.message}\n" string << exception.backtrace.map { |l| "\t#{l}" }.join("\n") string end def pretty(env, exception) req = Rack::Request.new(env) # This double assignment is to prevent an "unused variable" warning on # Ruby 1.9.3. Yes, it is dumb, but I don't like Ruby yelling at me. path = path = (req.script_name + req.path_info).squeeze("/") # This double assignment is to prevent an "unused variable" warning on # Ruby 1.9.3. Yes, it is dumb, but I don't like Ruby yelling at me. frames = frames = exception.backtrace.map { |line| frame = OpenStruct.new if line =~ /(.*?):(\d+)(:in `(.*)')?/ frame.filename = $1 frame.lineno = $2.to_i frame.function = $4 begin lineno = frame.lineno-1 lines = ::File.readlines(frame.filename) frame.pre_context_lineno = [lineno-CONTEXT, 0].max frame.pre_context = lines[frame.pre_context_lineno...lineno] frame.context_line = lines[lineno].chomp frame.post_context_lineno = [lineno+CONTEXT, lines.size].min frame.post_context = lines[lineno+1..frame.post_context_lineno] rescue end frame else nil end }.compact @template.result(binding) end def h(obj) # :nodoc: case obj when String Utils.escape_html(obj) else Utils.escape_html(obj.inspect) end end # :stopdoc: # adapted from Django # Copyright (c) 2005, the Lawrence Journal-World # Used under the modified BSD license: # http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5 TEMPLATE = <<'HTML' <%=h exception.class %> at <%=h path %>

    <%=h exception.class %> at <%=h path %>

    <%=h exception.message %>

    Ruby <% if first = frames.first %> <%=h first.filename %>: in <%=h first.function %>, line <%=h frames.first.lineno %> <% else %> unknown location <% end %>
    Web <%=h req.request_method %> <%=h(req.host + path)%>

    Jump to:

    Traceback (innermost first)

      <% frames.each { |frame| %>
    • <%=h frame.filename %>: in <%=h frame.function %> <% if frame.context_line %>
      <% if frame.pre_context %>
        <% frame.pre_context.each { |line| %>
      1. <%=h line %>
      2. <% } %>
      <% end %>
      1. <%=h frame.context_line %>...
      <% if frame.post_context %>
        <% frame.post_context.each { |line| %>
      1. <%=h line %>
      2. <% } %>
      <% end %>
      <% end %>
    • <% } %>

    Request information

    GET

    <% if req.GET and not req.GET.empty? %> <% req.GET.sort_by { |k, v| k.to_s }.each { |key, val| %> <% } %>
    Variable Value
    <%=h key %>
    <%=h val.inspect %>
    <% else %>

    No GET data.

    <% end %>

    POST

    <% if req.POST and not req.POST.empty? %> <% req.POST.sort_by { |k, v| k.to_s }.each { |key, val| %> <% } %>
    Variable Value
    <%=h key %>
    <%=h val.inspect %>
    <% else %>

    No POST data.

    <% end %> <% unless req.cookies.empty? %> <% req.cookies.each { |key, val| %> <% } %>
    Variable Value
    <%=h key %>
    <%=h val.inspect %>
    <% else %>

    No cookie data.

    <% end %>

    Rack ENV

    <% env.sort_by { |k, v| k.to_s }.each { |key, val| %> <% } %>
    Variable Value
    <%=h key %>
    <%=h val %>

    You're seeing this error because you use Rack::ShowExceptions.

    HTML # :startdoc: end end PK!d.gems/2.2.0/gems/rack-1.6.4/lib/rack/lobster.rbnu[require 'zlib' require 'rack/request' require 'rack/response' module Rack # Paste has a Pony, Rack has a Lobster! class Lobster LobsterString = Zlib::Inflate.inflate("eJx9kEEOwyAMBO99xd7MAcytUhPlJyj2 P6jy9i4k9EQyGAnBarEXeCBqSkntNXsi/ZCvC48zGQoZKikGrFMZvgS5ZHd+aGWVuWwhVF0 t1drVmiR42HcWNz5w3QanT+2gIvTVCiE1lm1Y0eU4JGmIIbaKwextKn8rvW+p5PIwFl8ZWJ I8jyiTlhTcYXkekJAzTyYN6E08A+dk8voBkAVTJQ==".delete("\n ").unpack("m*")[0]) LambdaLobster = lambda { |env| if env[QUERY_STRING].include?("flip") lobster = LobsterString.split("\n"). map { |line| line.ljust(42).reverse }. join("\n") href = "?" else lobster = LobsterString href = "?flip" end content = ["Lobstericious!", "
    ", lobster, "
    ", "flip!"] length = content.inject(0) { |a,e| a+e.size }.to_s [200, {CONTENT_TYPE => "text/html", CONTENT_LENGTH => length}, content] } def call(env) req = Request.new(env) if req.GET["flip"] == "left" lobster = LobsterString.split("\n").map do |line| line.ljust(42).reverse. gsub('\\', 'TEMP'). gsub('/', '\\'). gsub('TEMP', '/'). gsub('{','}'). gsub('(',')') end.join("\n") href = "?flip=right" elsif req.GET["flip"] == "crash" raise "Lobster crashed" else lobster = LobsterString href = "?flip=left" end res = Response.new res.write "Lobstericious!" res.write "
    "
          res.write lobster
          res.write "
    " res.write "

    flip!

    " res.write "

    crash!

    " res.finish end end end if $0 == __FILE__ require 'rack' require 'rack/showexceptions' Rack::Server.start( :app => Rack::ShowExceptions.new(Rack::Lint.new(Rack::Lobster.new)), :Port => 9292 ) end PK!43YY+gems/2.2.0/gems/rack-1.6.4/lib/rack/lock.rbnu[require 'thread' require 'rack/body_proxy' module Rack # Rack::Lock locks every request inside a mutex, so that every request # will effectively be executed synchronously. class Lock FLAG = 'rack.multithread'.freeze def initialize(app, mutex = Mutex.new) @app, @mutex = app, mutex end def call(env) old, env[FLAG] = env[FLAG], false @mutex.lock response = @app.call(env) body = BodyProxy.new(response[2]) { @mutex.unlock } response[2] = body response ensure @mutex.unlock unless body env[FLAG] = old end end end PK!@ HH5gems/2.2.0/gems/rack-1.6.4/lib/rack/content_length.rbnu[require 'rack/utils' require 'rack/body_proxy' module Rack # Sets the Content-Length header on responses with fixed-length bodies. class ContentLength include Rack::Utils def initialize(app) @app = app end def call(env) status, headers, body = @app.call(env) headers = HeaderHash.new(headers) if !STATUS_WITH_NO_ENTITY_BODY.include?(status.to_i) && !headers[CONTENT_LENGTH] && !headers['Transfer-Encoding'] && body.respond_to?(:to_ary) obody = body body, length = [], 0 obody.each { |part| body << part; length += bytesize(part) } body = BodyProxy.new(body) do obody.close if obody.respond_to?(:close) end headers[CONTENT_LENGTH] = length.to_s end [status, headers, body] end end end PK!l׋RR/gems/2.2.0/gems/rack-1.6.4/lib/rack/response.rbnu[require 'rack/request' require 'rack/utils' require 'rack/body_proxy' require 'time' module Rack # Rack::Response provides a convenient interface to create a Rack # response. # # It allows setting of headers and cookies, and provides useful # defaults (a OK response containing HTML). # # You can use Response#write to iteratively generate your response, # but note that this is buffered by Rack::Response until you call # +finish+. +finish+ however can take a block inside which calls to # +write+ are synchronous with the Rack response. # # Your application's +call+ should end returning Response#finish. class Response attr_accessor :length CHUNKED = 'chunked'.freeze TRANSFER_ENCODING = 'Transfer-Encoding'.freeze def initialize(body=[], status=200, header={}) @status = status.to_i @header = Utils::HeaderHash.new.merge(header) @chunked = CHUNKED == @header[TRANSFER_ENCODING] @writer = lambda { |x| @body << x } @block = nil @length = 0 @body = [] if body.respond_to? :to_str write body.to_str elsif body.respond_to?(:each) body.each { |part| write part.to_s } else raise TypeError, "stringable or iterable required" end yield self if block_given? end attr_reader :header attr_accessor :status, :body def [](key) header[key] end def []=(key, value) header[key] = value end def set_cookie(key, value) Utils.set_cookie_header!(header, key, value) end def delete_cookie(key, value={}) Utils.delete_cookie_header!(header, key, value) end def redirect(target, status=302) self.status = status self["Location"] = target end def finish(&block) @block = block if [204, 205, 304].include?(status.to_i) header.delete CONTENT_TYPE header.delete CONTENT_LENGTH close [status.to_i, header, []] else [status.to_i, header, BodyProxy.new(self){}] end end alias to_a finish # For *response alias to_ary finish # For implicit-splat on Ruby 1.9.2 def each(&callback) @body.each(&callback) @writer = callback @block.call(self) if @block end # Append to body and update Content-Length. # # NOTE: Do not mix #write and direct #body access! # def write(str) s = str.to_s @length += Rack::Utils.bytesize(s) unless @chunked @writer.call s header[CONTENT_LENGTH] = @length.to_s unless @chunked str end def close body.close if body.respond_to?(:close) end def empty? @block == nil && @body.empty? end alias headers header module Helpers def invalid?; status < 100 || status >= 600; end def informational?; status >= 100 && status < 200; end def successful?; status >= 200 && status < 300; end def redirection?; status >= 300 && status < 400; end def client_error?; status >= 400 && status < 500; end def server_error?; status >= 500 && status < 600; end def ok?; status == 200; end def created?; status == 201; end def accepted?; status == 202; end def bad_request?; status == 400; end def unauthorized?; status == 401; end def forbidden?; status == 403; end def not_found?; status == 404; end def method_not_allowed?; status == 405; end def i_m_a_teapot?; status == 418; end def unprocessable?; status == 422; end def redirect?; [301, 302, 303, 307].include? status; end # Headers attr_reader :headers, :original_headers def include?(header) !!headers[header] end def content_type headers[CONTENT_TYPE] end def content_length cl = headers[CONTENT_LENGTH] cl ? cl.to_i : cl end def location headers["Location"] end end include Helpers end end PK!I{{+gems/2.2.0/gems/rack-1.6.4/lib/rack/mime.rbnu[module Rack module Mime # Returns String with mime type if found, otherwise use +fallback+. # +ext+ should be filename extension in the '.ext' format that # File.extname(file) returns. # +fallback+ may be any object # # Also see the documentation for MIME_TYPES # # Usage: # Rack::Mime.mime_type('.foo') # # This is a shortcut for: # Rack::Mime::MIME_TYPES.fetch('.foo', 'application/octet-stream') def mime_type(ext, fallback='application/octet-stream') MIME_TYPES.fetch(ext.to_s.downcase, fallback) end module_function :mime_type # Returns true if the given value is a mime match for the given mime match # specification, false otherwise. # # Rack::Mime.match?('text/html', 'text/*') => true # Rack::Mime.match?('text/plain', '*') => true # Rack::Mime.match?('text/html', 'application/json') => false def match?(value, matcher) v1, v2 = value.split('/', 2) m1, m2 = matcher.split('/', 2) (m1 == '*' || v1 == m1) && (m2.nil? || m2 == '*' || m2 == v2) end module_function :match? # List of most common mime-types, selected various sources # according to their usefulness in a webserving scope for Ruby # users. # # To amend this list with your local mime.types list you can use: # # require 'webrick/httputils' # list = WEBrick::HTTPUtils.load_mime_types('/etc/mime.types') # Rack::Mime::MIME_TYPES.merge!(list) # # N.B. On Ubuntu the mime.types file does not include the leading period, so # users may need to modify the data before merging into the hash. # # To add the list mongrel provides, use: # # require 'mongrel/handlers' # Rack::Mime::MIME_TYPES.merge!(Mongrel::DirHandler::MIME_TYPES) MIME_TYPES = { ".123" => "application/vnd.lotus-1-2-3", ".3dml" => "text/vnd.in3d.3dml", ".3g2" => "video/3gpp2", ".3gp" => "video/3gpp", ".a" => "application/octet-stream", ".acc" => "application/vnd.americandynamics.acc", ".ace" => "application/x-ace-compressed", ".acu" => "application/vnd.acucobol", ".aep" => "application/vnd.audiograph", ".afp" => "application/vnd.ibm.modcap", ".ai" => "application/postscript", ".aif" => "audio/x-aiff", ".aiff" => "audio/x-aiff", ".ami" => "application/vnd.amiga.ami", ".appcache" => "text/cache-manifest", ".apr" => "application/vnd.lotus-approach", ".asc" => "application/pgp-signature", ".asf" => "video/x-ms-asf", ".asm" => "text/x-asm", ".aso" => "application/vnd.accpac.simply.aso", ".asx" => "video/x-ms-asf", ".atc" => "application/vnd.acucorp", ".atom" => "application/atom+xml", ".atomcat" => "application/atomcat+xml", ".atomsvc" => "application/atomsvc+xml", ".atx" => "application/vnd.antix.game-component", ".au" => "audio/basic", ".avi" => "video/x-msvideo", ".bat" => "application/x-msdownload", ".bcpio" => "application/x-bcpio", ".bdm" => "application/vnd.syncml.dm+wbxml", ".bh2" => "application/vnd.fujitsu.oasysprs", ".bin" => "application/octet-stream", ".bmi" => "application/vnd.bmi", ".bmp" => "image/bmp", ".box" => "application/vnd.previewsystems.box", ".btif" => "image/prs.btif", ".bz" => "application/x-bzip", ".bz2" => "application/x-bzip2", ".c" => "text/x-c", ".c4g" => "application/vnd.clonk.c4group", ".cab" => "application/vnd.ms-cab-compressed", ".cc" => "text/x-c", ".ccxml" => "application/ccxml+xml", ".cdbcmsg" => "application/vnd.contact.cmsg", ".cdkey" => "application/vnd.mediastation.cdkey", ".cdx" => "chemical/x-cdx", ".cdxml" => "application/vnd.chemdraw+xml", ".cdy" => "application/vnd.cinderella", ".cer" => "application/pkix-cert", ".cgm" => "image/cgm", ".chat" => "application/x-chat", ".chm" => "application/vnd.ms-htmlhelp", ".chrt" => "application/vnd.kde.kchart", ".cif" => "chemical/x-cif", ".cii" => "application/vnd.anser-web-certificate-issue-initiation", ".cil" => "application/vnd.ms-artgalry", ".cla" => "application/vnd.claymore", ".class" => "application/octet-stream", ".clkk" => "application/vnd.crick.clicker.keyboard", ".clkp" => "application/vnd.crick.clicker.palette", ".clkt" => "application/vnd.crick.clicker.template", ".clkw" => "application/vnd.crick.clicker.wordbank", ".clkx" => "application/vnd.crick.clicker", ".clp" => "application/x-msclip", ".cmc" => "application/vnd.cosmocaller", ".cmdf" => "chemical/x-cmdf", ".cml" => "chemical/x-cml", ".cmp" => "application/vnd.yellowriver-custom-menu", ".cmx" => "image/x-cmx", ".com" => "application/x-msdownload", ".conf" => "text/plain", ".cpio" => "application/x-cpio", ".cpp" => "text/x-c", ".cpt" => "application/mac-compactpro", ".crd" => "application/x-mscardfile", ".crl" => "application/pkix-crl", ".crt" => "application/x-x509-ca-cert", ".csh" => "application/x-csh", ".csml" => "chemical/x-csml", ".csp" => "application/vnd.commonspace", ".css" => "text/css", ".csv" => "text/csv", ".curl" => "application/vnd.curl", ".cww" => "application/prs.cww", ".cxx" => "text/x-c", ".daf" => "application/vnd.mobius.daf", ".davmount" => "application/davmount+xml", ".dcr" => "application/x-director", ".dd2" => "application/vnd.oma.dd2+xml", ".ddd" => "application/vnd.fujixerox.ddd", ".deb" => "application/x-debian-package", ".der" => "application/x-x509-ca-cert", ".dfac" => "application/vnd.dreamfactory", ".diff" => "text/x-diff", ".dis" => "application/vnd.mobius.dis", ".djv" => "image/vnd.djvu", ".djvu" => "image/vnd.djvu", ".dll" => "application/x-msdownload", ".dmg" => "application/octet-stream", ".dna" => "application/vnd.dna", ".doc" => "application/msword", ".docx" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document", ".dot" => "application/msword", ".dp" => "application/vnd.osgi.dp", ".dpg" => "application/vnd.dpgraph", ".dsc" => "text/prs.lines.tag", ".dtd" => "application/xml-dtd", ".dts" => "audio/vnd.dts", ".dtshd" => "audio/vnd.dts.hd", ".dv" => "video/x-dv", ".dvi" => "application/x-dvi", ".dwf" => "model/vnd.dwf", ".dwg" => "image/vnd.dwg", ".dxf" => "image/vnd.dxf", ".dxp" => "application/vnd.spotfire.dxp", ".ear" => "application/java-archive", ".ecelp4800" => "audio/vnd.nuera.ecelp4800", ".ecelp7470" => "audio/vnd.nuera.ecelp7470", ".ecelp9600" => "audio/vnd.nuera.ecelp9600", ".ecma" => "application/ecmascript", ".edm" => "application/vnd.novadigm.edm", ".edx" => "application/vnd.novadigm.edx", ".efif" => "application/vnd.picsel", ".ei6" => "application/vnd.pg.osasli", ".eml" => "message/rfc822", ".eol" => "audio/vnd.digital-winds", ".eot" => "application/vnd.ms-fontobject", ".eps" => "application/postscript", ".es3" => "application/vnd.eszigno3+xml", ".esf" => "application/vnd.epson.esf", ".etx" => "text/x-setext", ".exe" => "application/x-msdownload", ".ext" => "application/vnd.novadigm.ext", ".ez" => "application/andrew-inset", ".ez2" => "application/vnd.ezpix-album", ".ez3" => "application/vnd.ezpix-package", ".f" => "text/x-fortran", ".f77" => "text/x-fortran", ".f90" => "text/x-fortran", ".fbs" => "image/vnd.fastbidsheet", ".fdf" => "application/vnd.fdf", ".fe_launch" => "application/vnd.denovo.fcselayout-link", ".fg5" => "application/vnd.fujitsu.oasysgp", ".fli" => "video/x-fli", ".flo" => "application/vnd.micrografx.flo", ".flv" => "video/x-flv", ".flw" => "application/vnd.kde.kivio", ".flx" => "text/vnd.fmi.flexstor", ".fly" => "text/vnd.fly", ".fm" => "application/vnd.framemaker", ".fnc" => "application/vnd.frogans.fnc", ".for" => "text/x-fortran", ".fpx" => "image/vnd.fpx", ".fsc" => "application/vnd.fsc.weblaunch", ".fst" => "image/vnd.fst", ".ftc" => "application/vnd.fluxtime.clip", ".fti" => "application/vnd.anser-web-funds-transfer-initiation", ".fvt" => "video/vnd.fvt", ".fzs" => "application/vnd.fuzzysheet", ".g3" => "image/g3fax", ".gac" => "application/vnd.groove-account", ".gdl" => "model/vnd.gdl", ".gem" => "application/octet-stream", ".gemspec" => "text/x-script.ruby", ".ghf" => "application/vnd.groove-help", ".gif" => "image/gif", ".gim" => "application/vnd.groove-identity-message", ".gmx" => "application/vnd.gmx", ".gph" => "application/vnd.flographit", ".gqf" => "application/vnd.grafeq", ".gram" => "application/srgs", ".grv" => "application/vnd.groove-injector", ".grxml" => "application/srgs+xml", ".gtar" => "application/x-gtar", ".gtm" => "application/vnd.groove-tool-message", ".gtw" => "model/vnd.gtw", ".gv" => "text/vnd.graphviz", ".gz" => "application/x-gzip", ".h" => "text/x-c", ".h261" => "video/h261", ".h263" => "video/h263", ".h264" => "video/h264", ".hbci" => "application/vnd.hbci", ".hdf" => "application/x-hdf", ".hh" => "text/x-c", ".hlp" => "application/winhlp", ".hpgl" => "application/vnd.hp-hpgl", ".hpid" => "application/vnd.hp-hpid", ".hps" => "application/vnd.hp-hps", ".hqx" => "application/mac-binhex40", ".htc" => "text/x-component", ".htke" => "application/vnd.kenameaapp", ".htm" => "text/html", ".html" => "text/html", ".hvd" => "application/vnd.yamaha.hv-dic", ".hvp" => "application/vnd.yamaha.hv-voice", ".hvs" => "application/vnd.yamaha.hv-script", ".icc" => "application/vnd.iccprofile", ".ice" => "x-conference/x-cooltalk", ".ico" => "image/vnd.microsoft.icon", ".ics" => "text/calendar", ".ief" => "image/ief", ".ifb" => "text/calendar", ".ifm" => "application/vnd.shana.informed.formdata", ".igl" => "application/vnd.igloader", ".igs" => "model/iges", ".igx" => "application/vnd.micrografx.igx", ".iif" => "application/vnd.shana.informed.interchange", ".imp" => "application/vnd.accpac.simply.imp", ".ims" => "application/vnd.ms-ims", ".ipk" => "application/vnd.shana.informed.package", ".irm" => "application/vnd.ibm.rights-management", ".irp" => "application/vnd.irepository.package+xml", ".iso" => "application/octet-stream", ".itp" => "application/vnd.shana.informed.formtemplate", ".ivp" => "application/vnd.immervision-ivp", ".ivu" => "application/vnd.immervision-ivu", ".jad" => "text/vnd.sun.j2me.app-descriptor", ".jam" => "application/vnd.jam", ".jar" => "application/java-archive", ".java" => "text/x-java-source", ".jisp" => "application/vnd.jisp", ".jlt" => "application/vnd.hp-jlyt", ".jnlp" => "application/x-java-jnlp-file", ".joda" => "application/vnd.joost.joda-archive", ".jp2" => "image/jp2", ".jpeg" => "image/jpeg", ".jpg" => "image/jpeg", ".jpgv" => "video/jpeg", ".jpm" => "video/jpm", ".js" => "application/javascript", ".json" => "application/json", ".karbon" => "application/vnd.kde.karbon", ".kfo" => "application/vnd.kde.kformula", ".kia" => "application/vnd.kidspiration", ".kml" => "application/vnd.google-earth.kml+xml", ".kmz" => "application/vnd.google-earth.kmz", ".kne" => "application/vnd.kinar", ".kon" => "application/vnd.kde.kontour", ".kpr" => "application/vnd.kde.kpresenter", ".ksp" => "application/vnd.kde.kspread", ".ktz" => "application/vnd.kahootz", ".kwd" => "application/vnd.kde.kword", ".latex" => "application/x-latex", ".lbd" => "application/vnd.llamagraphics.life-balance.desktop", ".lbe" => "application/vnd.llamagraphics.life-balance.exchange+xml", ".les" => "application/vnd.hhe.lesson-player", ".link66" => "application/vnd.route66.link66+xml", ".log" => "text/plain", ".lostxml" => "application/lost+xml", ".lrm" => "application/vnd.ms-lrm", ".ltf" => "application/vnd.frogans.ltf", ".lvp" => "audio/vnd.lucent.voice", ".lwp" => "application/vnd.lotus-wordpro", ".m3u" => "audio/x-mpegurl", ".m4a" => "audio/mp4a-latm", ".m4v" => "video/mp4", ".ma" => "application/mathematica", ".mag" => "application/vnd.ecowin.chart", ".man" => "text/troff", ".manifest" => "text/cache-manifest", ".mathml" => "application/mathml+xml", ".mbk" => "application/vnd.mobius.mbk", ".mbox" => "application/mbox", ".mc1" => "application/vnd.medcalcdata", ".mcd" => "application/vnd.mcd", ".mdb" => "application/x-msaccess", ".mdi" => "image/vnd.ms-modi", ".mdoc" => "text/troff", ".me" => "text/troff", ".mfm" => "application/vnd.mfmp", ".mgz" => "application/vnd.proteus.magazine", ".mid" => "audio/midi", ".midi" => "audio/midi", ".mif" => "application/vnd.mif", ".mime" => "message/rfc822", ".mj2" => "video/mj2", ".mlp" => "application/vnd.dolby.mlp", ".mmd" => "application/vnd.chipnuts.karaoke-mmd", ".mmf" => "application/vnd.smaf", ".mml" => "application/mathml+xml", ".mmr" => "image/vnd.fujixerox.edmics-mmr", ".mng" => "video/x-mng", ".mny" => "application/x-msmoney", ".mov" => "video/quicktime", ".movie" => "video/x-sgi-movie", ".mp3" => "audio/mpeg", ".mp4" => "video/mp4", ".mp4a" => "audio/mp4", ".mp4s" => "application/mp4", ".mp4v" => "video/mp4", ".mpc" => "application/vnd.mophun.certificate", ".mpeg" => "video/mpeg", ".mpg" => "video/mpeg", ".mpga" => "audio/mpeg", ".mpkg" => "application/vnd.apple.installer+xml", ".mpm" => "application/vnd.blueice.multipass", ".mpn" => "application/vnd.mophun.application", ".mpp" => "application/vnd.ms-project", ".mpy" => "application/vnd.ibm.minipay", ".mqy" => "application/vnd.mobius.mqy", ".mrc" => "application/marc", ".ms" => "text/troff", ".mscml" => "application/mediaservercontrol+xml", ".mseq" => "application/vnd.mseq", ".msf" => "application/vnd.epson.msf", ".msh" => "model/mesh", ".msi" => "application/x-msdownload", ".msl" => "application/vnd.mobius.msl", ".msty" => "application/vnd.muvee.style", ".mts" => "model/vnd.mts", ".mus" => "application/vnd.musician", ".mvb" => "application/x-msmediaview", ".mwf" => "application/vnd.mfer", ".mxf" => "application/mxf", ".mxl" => "application/vnd.recordare.musicxml", ".mxml" => "application/xv+xml", ".mxs" => "application/vnd.triscape.mxs", ".mxu" => "video/vnd.mpegurl", ".n" => "application/vnd.nokia.n-gage.symbian.install", ".nc" => "application/x-netcdf", ".ngdat" => "application/vnd.nokia.n-gage.data", ".nlu" => "application/vnd.neurolanguage.nlu", ".nml" => "application/vnd.enliven", ".nnd" => "application/vnd.noblenet-directory", ".nns" => "application/vnd.noblenet-sealer", ".nnw" => "application/vnd.noblenet-web", ".npx" => "image/vnd.net-fpx", ".nsf" => "application/vnd.lotus-notes", ".oa2" => "application/vnd.fujitsu.oasys2", ".oa3" => "application/vnd.fujitsu.oasys3", ".oas" => "application/vnd.fujitsu.oasys", ".obd" => "application/x-msbinder", ".oda" => "application/oda", ".odc" => "application/vnd.oasis.opendocument.chart", ".odf" => "application/vnd.oasis.opendocument.formula", ".odg" => "application/vnd.oasis.opendocument.graphics", ".odi" => "application/vnd.oasis.opendocument.image", ".odp" => "application/vnd.oasis.opendocument.presentation", ".ods" => "application/vnd.oasis.opendocument.spreadsheet", ".odt" => "application/vnd.oasis.opendocument.text", ".oga" => "audio/ogg", ".ogg" => "application/ogg", ".ogv" => "video/ogg", ".ogx" => "application/ogg", ".org" => "application/vnd.lotus-organizer", ".otc" => "application/vnd.oasis.opendocument.chart-template", ".otf" => "application/vnd.oasis.opendocument.formula-template", ".otg" => "application/vnd.oasis.opendocument.graphics-template", ".oth" => "application/vnd.oasis.opendocument.text-web", ".oti" => "application/vnd.oasis.opendocument.image-template", ".otm" => "application/vnd.oasis.opendocument.text-master", ".ots" => "application/vnd.oasis.opendocument.spreadsheet-template", ".ott" => "application/vnd.oasis.opendocument.text-template", ".oxt" => "application/vnd.openofficeorg.extension", ".p" => "text/x-pascal", ".p10" => "application/pkcs10", ".p12" => "application/x-pkcs12", ".p7b" => "application/x-pkcs7-certificates", ".p7m" => "application/pkcs7-mime", ".p7r" => "application/x-pkcs7-certreqresp", ".p7s" => "application/pkcs7-signature", ".pas" => "text/x-pascal", ".pbd" => "application/vnd.powerbuilder6", ".pbm" => "image/x-portable-bitmap", ".pcl" => "application/vnd.hp-pcl", ".pclxl" => "application/vnd.hp-pclxl", ".pcx" => "image/x-pcx", ".pdb" => "chemical/x-pdb", ".pdf" => "application/pdf", ".pem" => "application/x-x509-ca-cert", ".pfr" => "application/font-tdpfr", ".pgm" => "image/x-portable-graymap", ".pgn" => "application/x-chess-pgn", ".pgp" => "application/pgp-encrypted", ".pic" => "image/x-pict", ".pict" => "image/pict", ".pkg" => "application/octet-stream", ".pki" => "application/pkixcmp", ".pkipath" => "application/pkix-pkipath", ".pl" => "text/x-script.perl", ".plb" => "application/vnd.3gpp.pic-bw-large", ".plc" => "application/vnd.mobius.plc", ".plf" => "application/vnd.pocketlearn", ".pls" => "application/pls+xml", ".pm" => "text/x-script.perl-module", ".pml" => "application/vnd.ctc-posml", ".png" => "image/png", ".pnm" => "image/x-portable-anymap", ".pntg" => "image/x-macpaint", ".portpkg" => "application/vnd.macports.portpkg", ".ppd" => "application/vnd.cups-ppd", ".ppm" => "image/x-portable-pixmap", ".pps" => "application/vnd.ms-powerpoint", ".ppt" => "application/vnd.ms-powerpoint", ".prc" => "application/vnd.palm", ".pre" => "application/vnd.lotus-freelance", ".prf" => "application/pics-rules", ".ps" => "application/postscript", ".psb" => "application/vnd.3gpp.pic-bw-small", ".psd" => "image/vnd.adobe.photoshop", ".ptid" => "application/vnd.pvi.ptid1", ".pub" => "application/x-mspublisher", ".pvb" => "application/vnd.3gpp.pic-bw-var", ".pwn" => "application/vnd.3m.post-it-notes", ".py" => "text/x-script.python", ".pya" => "audio/vnd.ms-playready.media.pya", ".pyv" => "video/vnd.ms-playready.media.pyv", ".qam" => "application/vnd.epson.quickanime", ".qbo" => "application/vnd.intu.qbo", ".qfx" => "application/vnd.intu.qfx", ".qps" => "application/vnd.publishare-delta-tree", ".qt" => "video/quicktime", ".qtif" => "image/x-quicktime", ".qxd" => "application/vnd.quark.quarkxpress", ".ra" => "audio/x-pn-realaudio", ".rake" => "text/x-script.ruby", ".ram" => "audio/x-pn-realaudio", ".rar" => "application/x-rar-compressed", ".ras" => "image/x-cmu-raster", ".rb" => "text/x-script.ruby", ".rcprofile" => "application/vnd.ipunplugged.rcprofile", ".rdf" => "application/rdf+xml", ".rdz" => "application/vnd.data-vision.rdz", ".rep" => "application/vnd.businessobjects", ".rgb" => "image/x-rgb", ".rif" => "application/reginfo+xml", ".rl" => "application/resource-lists+xml", ".rlc" => "image/vnd.fujixerox.edmics-rlc", ".rld" => "application/resource-lists-diff+xml", ".rm" => "application/vnd.rn-realmedia", ".rmp" => "audio/x-pn-realaudio-plugin", ".rms" => "application/vnd.jcp.javame.midlet-rms", ".rnc" => "application/relax-ng-compact-syntax", ".roff" => "text/troff", ".rpm" => "application/x-redhat-package-manager", ".rpss" => "application/vnd.nokia.radio-presets", ".rpst" => "application/vnd.nokia.radio-preset", ".rq" => "application/sparql-query", ".rs" => "application/rls-services+xml", ".rsd" => "application/rsd+xml", ".rss" => "application/rss+xml", ".rtf" => "application/rtf", ".rtx" => "text/richtext", ".ru" => "text/x-script.ruby", ".s" => "text/x-asm", ".saf" => "application/vnd.yamaha.smaf-audio", ".sbml" => "application/sbml+xml", ".sc" => "application/vnd.ibm.secure-container", ".scd" => "application/x-msschedule", ".scm" => "application/vnd.lotus-screencam", ".scq" => "application/scvp-cv-request", ".scs" => "application/scvp-cv-response", ".sdkm" => "application/vnd.solent.sdkm+xml", ".sdp" => "application/sdp", ".see" => "application/vnd.seemail", ".sema" => "application/vnd.sema", ".semd" => "application/vnd.semd", ".semf" => "application/vnd.semf", ".setpay" => "application/set-payment-initiation", ".setreg" => "application/set-registration-initiation", ".sfd" => "application/vnd.hydrostatix.sof-data", ".sfs" => "application/vnd.spotfire.sfs", ".sgm" => "text/sgml", ".sgml" => "text/sgml", ".sh" => "application/x-sh", ".shar" => "application/x-shar", ".shf" => "application/shf+xml", ".sig" => "application/pgp-signature", ".sit" => "application/x-stuffit", ".sitx" => "application/x-stuffitx", ".skp" => "application/vnd.koan", ".slt" => "application/vnd.epson.salt", ".smi" => "application/smil+xml", ".snd" => "audio/basic", ".so" => "application/octet-stream", ".spf" => "application/vnd.yamaha.smaf-phrase", ".spl" => "application/x-futuresplash", ".spot" => "text/vnd.in3d.spot", ".spp" => "application/scvp-vp-response", ".spq" => "application/scvp-vp-request", ".src" => "application/x-wais-source", ".srx" => "application/sparql-results+xml", ".sse" => "application/vnd.kodak-descriptor", ".ssf" => "application/vnd.epson.ssf", ".ssml" => "application/ssml+xml", ".stf" => "application/vnd.wt.stf", ".stk" => "application/hyperstudio", ".str" => "application/vnd.pg.format", ".sus" => "application/vnd.sus-calendar", ".sv4cpio" => "application/x-sv4cpio", ".sv4crc" => "application/x-sv4crc", ".svd" => "application/vnd.svd", ".svg" => "image/svg+xml", ".svgz" => "image/svg+xml", ".swf" => "application/x-shockwave-flash", ".swi" => "application/vnd.arastra.swi", ".t" => "text/troff", ".tao" => "application/vnd.tao.intent-module-archive", ".tar" => "application/x-tar", ".tbz" => "application/x-bzip-compressed-tar", ".tcap" => "application/vnd.3gpp2.tcap", ".tcl" => "application/x-tcl", ".tex" => "application/x-tex", ".texi" => "application/x-texinfo", ".texinfo" => "application/x-texinfo", ".text" => "text/plain", ".tif" => "image/tiff", ".tiff" => "image/tiff", ".tmo" => "application/vnd.tmobile-livetv", ".torrent" => "application/x-bittorrent", ".tpl" => "application/vnd.groove-tool-template", ".tpt" => "application/vnd.trid.tpt", ".tr" => "text/troff", ".tra" => "application/vnd.trueapp", ".trm" => "application/x-msterminal", ".tsv" => "text/tab-separated-values", ".ttf" => "application/octet-stream", ".twd" => "application/vnd.simtech-mindmapper", ".txd" => "application/vnd.genomatix.tuxedo", ".txf" => "application/vnd.mobius.txf", ".txt" => "text/plain", ".ufd" => "application/vnd.ufdl", ".umj" => "application/vnd.umajin", ".unityweb" => "application/vnd.unity", ".uoml" => "application/vnd.uoml+xml", ".uri" => "text/uri-list", ".ustar" => "application/x-ustar", ".utz" => "application/vnd.uiq.theme", ".uu" => "text/x-uuencode", ".vcd" => "application/x-cdlink", ".vcf" => "text/x-vcard", ".vcg" => "application/vnd.groove-vcard", ".vcs" => "text/x-vcalendar", ".vcx" => "application/vnd.vcx", ".vis" => "application/vnd.visionary", ".viv" => "video/vnd.vivo", ".vrml" => "model/vrml", ".vsd" => "application/vnd.visio", ".vsf" => "application/vnd.vsf", ".vtu" => "model/vnd.vtu", ".vxml" => "application/voicexml+xml", ".war" => "application/java-archive", ".wav" => "audio/x-wav", ".wax" => "audio/x-ms-wax", ".wbmp" => "image/vnd.wap.wbmp", ".wbs" => "application/vnd.criticaltools.wbs+xml", ".wbxml" => "application/vnd.wap.wbxml", ".webm" => "video/webm", ".wm" => "video/x-ms-wm", ".wma" => "audio/x-ms-wma", ".wmd" => "application/x-ms-wmd", ".wmf" => "application/x-msmetafile", ".wml" => "text/vnd.wap.wml", ".wmlc" => "application/vnd.wap.wmlc", ".wmls" => "text/vnd.wap.wmlscript", ".wmlsc" => "application/vnd.wap.wmlscriptc", ".wmv" => "video/x-ms-wmv", ".wmx" => "video/x-ms-wmx", ".wmz" => "application/x-ms-wmz", ".woff" => "application/font-woff", ".woff2" => "application/font-woff2", ".wpd" => "application/vnd.wordperfect", ".wpl" => "application/vnd.ms-wpl", ".wps" => "application/vnd.ms-works", ".wqd" => "application/vnd.wqd", ".wri" => "application/x-mswrite", ".wrl" => "model/vrml", ".wsdl" => "application/wsdl+xml", ".wspolicy" => "application/wspolicy+xml", ".wtb" => "application/vnd.webturbo", ".wvx" => "video/x-ms-wvx", ".x3d" => "application/vnd.hzn-3d-crossword", ".xar" => "application/vnd.xara", ".xbd" => "application/vnd.fujixerox.docuworks.binder", ".xbm" => "image/x-xbitmap", ".xdm" => "application/vnd.syncml.dm+xml", ".xdp" => "application/vnd.adobe.xdp+xml", ".xdw" => "application/vnd.fujixerox.docuworks", ".xenc" => "application/xenc+xml", ".xer" => "application/patch-ops-error+xml", ".xfdf" => "application/vnd.adobe.xfdf", ".xfdl" => "application/vnd.xfdl", ".xhtml" => "application/xhtml+xml", ".xif" => "image/vnd.xiff", ".xls" => "application/vnd.ms-excel", ".xlsx" => "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", ".xml" => "application/xml", ".xo" => "application/vnd.olpc-sugar", ".xop" => "application/xop+xml", ".xpm" => "image/x-xpixmap", ".xpr" => "application/vnd.is-xpr", ".xps" => "application/vnd.ms-xpsdocument", ".xpw" => "application/vnd.intercon.formnet", ".xsl" => "application/xml", ".xslt" => "application/xslt+xml", ".xsm" => "application/vnd.syncml+xml", ".xspf" => "application/xspf+xml", ".xul" => "application/vnd.mozilla.xul+xml", ".xwd" => "image/x-xwindowdump", ".xyz" => "chemical/x-xyz", ".yaml" => "text/yaml", ".yml" => "text/yaml", ".zaz" => "application/vnd.zzazz.deck+xml", ".zip" => "application/zip", ".zmm" => "application/vnd.handheld-entertainment+xml", } end end PK!q54 #gems/2.2.0/gems/rack-1.6.4/Rakefilenu[# Rakefile for Rack. -*-ruby-*- desc "Run all the tests" task :default => [:test] desc "Install gem dependencies" task :deps do require 'rubygems' spec = Gem::Specification.load('rack.gemspec') spec.dependencies.each do |dep| reqs = dep.requirements_list reqs = (["-v"] * reqs.size).zip(reqs).flatten # Use system over sh, because we want to ignore errors! system Gem.ruby, "-S", "gem", "install", '--conservative', dep.name, *reqs end end desc "Make an archive as .tar.gz" task :dist => %w[chmod ChangeLog SPEC rdoc] do sh "git archive --format=tar --prefix=#{release}/ HEAD^{tree} >#{release}.tar" sh "pax -waf #{release}.tar -s ':^:#{release}/:' SPEC ChangeLog doc rack.gemspec" sh "gzip -f -9 #{release}.tar" end desc "Make an official release" task :officialrelease do puts "Official build for #{release}..." sh "rm -rf stage" sh "git clone --shared . stage" sh "cd stage && rake officialrelease_really" sh "mv stage/#{release}.tar.gz stage/#{release}.gem ." end task :officialrelease_really => %w[SPEC dist gem] do sh "shasum #{release}.tar.gz #{release}.gem" end def release "rack-#{File.read("rack.gemspec")[/s.version *= *"(.*?)"/, 1]}" end desc "Make binaries executable" task :chmod do Dir["bin/*"].each { |binary| File.chmod(0755, binary) } Dir["test/cgi/test*"].each { |binary| File.chmod(0755, binary) } end desc "Generate a ChangeLog" task :changelog => %w[ChangeLog] file '.git/index' file "ChangeLog" => '.git/index' do File.open("ChangeLog", "w") { |out| log = `git log -z` log.force_encoding(Encoding::BINARY) if log.respond_to?(:force_encoding) log.split("\0").map { |chunk| author = chunk[/Author: (.*)/, 1].strip date = chunk[/Date: (.*)/, 1].strip desc, detail = $'.strip.split("\n", 2) detail ||= "" detail = detail.gsub(/.*darcs-hash:.*/, '') detail.rstrip! out.puts "#{date} #{author}" out.puts " * #{desc.strip}" out.puts detail unless detail.empty? out.puts } } end file 'lib/rack/lint.rb' desc "Generate Rack Specification" file "SPEC" => 'lib/rack/lint.rb' do File.open("SPEC", "wb") { |file| IO.foreach("lib/rack/lint.rb") { |line| if line =~ /## (.*)/ file.puts $1 end } } end desc "Run all the fast + platform agnostic tests" task :test => 'SPEC' do opts = ENV['TEST'] || '-a' specopts = ENV['TESTOPTS'] || "-q -t '^(?!Rack::Adapter|Rack::Session::Memcache|Rack::Server|Rack::Handler)'" sh "bacon -w -I./lib:./test #{opts} #{specopts}" end desc "Run all the tests we run on CI" task :ci => :fulltest desc "Run all the tests" task :fulltest => %w[SPEC chmod] do opts = ENV['TEST'] || '-a' specopts = ENV['TESTOPTS'] || '-q' sh "bacon -r./test/gemloader -I./lib:./test -w #{opts} #{specopts}" end task :gem => ["SPEC"] do sh "gem build rack.gemspec" end task :doc => :rdoc desc "Generate RDoc documentation" task :rdoc => %w[ChangeLog SPEC] do sh(*%w{rdoc --line-numbers --main README.rdoc --title 'Rack\ Documentation' --charset utf-8 -U -o doc} + %w{README.rdoc KNOWN-ISSUES SPEC ChangeLog} + `git ls-files lib/\*\*/\*.rb`.strip.split) cp "contrib/rdoc.css", "doc/rdoc.css" end task :pushdoc => %w[rdoc] do sh "rsync -avz doc/ rack.rubyforge.org:/var/www/gforge-projects/rack/doc/" end task :pushsite => %w[pushdoc] do sh "cd site && git gc" sh "rsync -avz site/ rack.rubyforge.org:/var/www/gforge-projects/rack/" sh "cd site && git push" end PK!"&8&8gems/2.2.0/gems/rack-1.6.4/SPECnu[This specification aims to formalize the Rack protocol. You can (and should) use Rack::Lint to enforce it. When you develop middleware, be sure to add a Lint before and after to catch all mistakes. = Rack applications A Rack application is a Ruby object (not a class) that responds to +call+. It takes exactly one argument, the *environment* and returns an Array of exactly three values: The *status*, the *headers*, and the *body*. == The Environment The environment must be an instance of Hash that includes CGI-like headers. The application is free to modify the environment. The environment is required to include these variables (adopted from PEP333), except when they'd be empty, but see below. REQUEST_METHOD:: The HTTP request method, such as "GET" or "POST". This cannot ever be an empty string, and so is always required. SCRIPT_NAME:: The initial portion of the request URL's "path" that corresponds to the application object, so that the application knows its virtual "location". This may be an empty string, if the application corresponds to the "root" of the server. PATH_INFO:: The remainder of the request URL's "path", designating the virtual "location" of the request's target within the application. This may be an empty string, if the request URL targets the application root and does not have a trailing slash. This value may be percent-encoded when I originating from a URL. QUERY_STRING:: The portion of the request URL that follows the ?, if any. May be empty, but is always required! SERVER_NAME, SERVER_PORT:: When combined with SCRIPT_NAME and PATH_INFO, these variables can be used to complete the URL. Note, however, that HTTP_HOST, if present, should be used in preference to SERVER_NAME for reconstructing the request URL. SERVER_NAME and SERVER_PORT can never be empty strings, and so are always required. HTTP_ Variables:: Variables corresponding to the client-supplied HTTP request headers (i.e., variables whose names begin with HTTP_). The presence or absence of these variables should correspond with the presence or absence of the appropriate HTTP header in the request. See RFC3875 section 4.1.18 for specific behavior. In addition to this, the Rack environment must include these Rack-specific variables: rack.version:: The Array representing this version of Rack See Rack::VERSION, that corresponds to the version of this SPEC. rack.url_scheme:: +http+ or +https+, depending on the request URL. rack.input:: See below, the input stream. rack.errors:: See below, the error stream. rack.multithread:: true if the application object may be simultaneously invoked by another thread in the same process, false otherwise. rack.multiprocess:: true if an equivalent application object may be simultaneously invoked by another process, false otherwise. rack.run_once:: true if the server expects (but does not guarantee!) that the application will only be invoked this one time during the life of its containing process. Normally, this will only be true for a server based on CGI (or something similar). rack.hijack?:: present and true if the server supports connection hijacking. See below, hijacking. rack.hijack:: an object responding to #call that must be called at least once before using rack.hijack_io. It is recommended #call return rack.hijack_io as well as setting it in env if necessary. rack.hijack_io:: if rack.hijack? is true, and rack.hijack has received #call, this will contain an object resembling an IO. See hijacking. Additional environment specifications have approved to standardized middleware APIs. None of these are required to be implemented by the server. rack.session:: A hash like interface for storing request session data. The store must implement: store(key, value) (aliased as []=); fetch(key, default = nil) (aliased as []); delete(key); clear; rack.logger:: A common object interface for logging messages. The object must implement: info(message, &block) debug(message, &block) warn(message, &block) error(message, &block) fatal(message, &block) rack.multipart.buffer_size:: An Integer hint to the multipart parser as to what chunk size to use for reads and writes. rack.multipart.tempfile_factory:: An object responding to #call with two arguments, the filename and content_type given for the multipart form field, and returning an IO-like object that responds to #<< and optionally #rewind. This factory will be used to instantiate the tempfile for each multipart form file upload field, rather than the default class of Tempfile. The server or the application can store their own data in the environment, too. The keys must contain at least one dot, and should be prefixed uniquely. The prefix rack. is reserved for use with the Rack core distribution and other accepted specifications and must not be used otherwise. The environment must not contain the keys HTTP_CONTENT_TYPE or HTTP_CONTENT_LENGTH (use the versions without HTTP_). The CGI keys (named without a period) must have String values. There are the following restrictions: * rack.version must be an array of Integers. * rack.url_scheme must either be +http+ or +https+. * There must be a valid input stream in rack.input. * There must be a valid error stream in rack.errors. * There may be a valid hijack stream in rack.hijack_io * The REQUEST_METHOD must be a valid token. * The SCRIPT_NAME, if non-empty, must start with / * The PATH_INFO, if non-empty, must start with / * The CONTENT_LENGTH, if given, must consist of digits only. * One of SCRIPT_NAME or PATH_INFO must be set. PATH_INFO should be / if SCRIPT_NAME is empty. SCRIPT_NAME never should be /, but instead be empty. === The Input Stream The input stream is an IO-like object which contains the raw HTTP POST data. When applicable, its external encoding must be "ASCII-8BIT" and it must be opened in binary mode, for Ruby 1.9 compatibility. The input stream must respond to +gets+, +each+, +read+ and +rewind+. * +gets+ must be called without arguments and return a string, or +nil+ on EOF. * +read+ behaves like IO#read. Its signature is read([length, [buffer]]). If given, +length+ must be a non-negative Integer (>= 0) or +nil+, and +buffer+ must be a String and may not be nil. If +length+ is given and not nil, then this method reads at most +length+ bytes from the input stream. If +length+ is not given or nil, then this method reads all data until EOF. When EOF is reached, this method returns nil if +length+ is given and not nil, or "" if +length+ is not given or is nil. If +buffer+ is given, then the read data will be placed into +buffer+ instead of a newly created String object. * +each+ must be called without arguments and only yield Strings. * +rewind+ must be called without arguments. It rewinds the input stream back to the beginning. It must not raise Errno::ESPIPE: that is, it may not be a pipe or a socket. Therefore, handler developers must buffer the input data into some rewindable object if the underlying input stream is not rewindable. * +close+ must never be called on the input stream. === The Error Stream The error stream must respond to +puts+, +write+ and +flush+. * +puts+ must be called with a single argument that responds to +to_s+. * +write+ must be called with a single argument that is a String. * +flush+ must be called without arguments and must be called in order to make the error appear for sure. * +close+ must never be called on the error stream. === Hijacking ==== Request (before status) If rack.hijack? is true then rack.hijack must respond to #call. rack.hijack must return the io that will also be assigned (or is already present, in rack.hijack_io. rack.hijack_io must respond to: read, write, read_nonblock, write_nonblock, flush, close, close_read, close_write, closed? The semantics of these IO methods must be a best effort match to those of a normal ruby IO or Socket object, using standard arguments and raising standard exceptions. Servers are encouraged to simply pass on real IO objects, although it is recognized that this approach is not directly compatible with SPDY and HTTP 2.0. IO provided in rack.hijack_io should preference the IO::WaitReadable and IO::WaitWritable APIs wherever supported. There is a deliberate lack of full specification around rack.hijack_io, as semantics will change from server to server. Users are encouraged to utilize this API with a knowledge of their server choice, and servers may extend the functionality of hijack_io to provide additional features to users. The purpose of rack.hijack is for Rack to "get out of the way", as such, Rack only provides the minimum of specification and support. If rack.hijack? is false, then rack.hijack should not be set. If rack.hijack? is false, then rack.hijack_io should not be set. ==== Response (after headers) It is also possible to hijack a response after the status and headers have been sent. In order to do this, an application may set the special header rack.hijack to an object that responds to call accepting an argument that conforms to the rack.hijack_io protocol. After the headers have been sent, and this hijack callback has been called, the application is now responsible for the remaining lifecycle of the IO. The application is also responsible for maintaining HTTP semantics. Of specific note, in almost all cases in the current SPEC, applications will have wanted to specify the header Connection:close in HTTP/1.1, and not Connection:keep-alive, as there is no protocol for returning hijacked sockets to the web server. For that purpose, use the body streaming API instead (progressively yielding strings via each). Servers must ignore the body part of the response tuple when the rack.hijack response API is in use. The special response header rack.hijack must only be set if the request env has rack.hijack? true. ==== Conventions * Middleware should not use hijack unless it is handling the whole response. * Middleware may wrap the IO object for the response pattern. * Middleware should not wrap the IO object for the request pattern. The request pattern is intended to provide the hijacker with "raw tcp". == The Response === The Status This is an HTTP status. When parsed as integer (+to_i+), it must be greater than or equal to 100. === The Headers The header must respond to +each+, and yield values of key and value. Special headers starting "rack." are for communicating with the server, and must not be sent back to the client. The header keys must be Strings. The header must not contain a +Status+ key. The header must conform to RFC7230 token specification, i.e. cannot contain non-printable ASCII, DQUOTE or "(),/:;<=>?@[\]{}". The values of the header must be Strings, consisting of lines (for multiple header values, e.g. multiple Set-Cookie values) separated by "\\n". The lines must not contain characters below 037. === The Content-Type There must not be a Content-Type, when the +Status+ is 1xx, 204, 205 or 304. === The Content-Length There must not be a Content-Length header when the +Status+ is 1xx, 204, 205 or 304. === The Body The Body must respond to +each+ and must only yield String values. The Body itself should not be an instance of String, as this will break in Ruby 1.9. If the Body responds to +close+, it will be called after iteration. If the body is replaced by a middleware after action, the original body must be closed first, if it responds to close. If the Body responds to +to_path+, it must return a String identifying the location of a file whose contents are identical to that produced by calling +each+; this may be used by the server as an alternative, possibly more efficient way to transport the response. The Body commonly is an Array of Strings, the application instance itself, or a File-like object. == Thanks Some parts of this specification are adopted from PEP333: Python Web Server Gateway Interface v1.0 (http://www.python.org/dev/peps/pep-0333/). I'd like to thank everyone involved in that effort. PK!##BB'gems/2.2.0/gems/ruby-lsapi-5.6/setup.rbnu[# # setup.rb # # Copyright (c) 2000-2005 Minero Aoki # # This program is free software. # You can distribute/modify this program under the terms of # the GNU LGPL, Lesser General Public License version 2.1. # unless Enumerable.method_defined?(:map) # Ruby 1.4.6 module Enumerable alias map collect end end unless File.respond_to?(:read) # Ruby 1.6 def File.read(fname) open(fname) {|f| return f.read } end end unless Errno.const_defined?(:ENOTEMPTY) # Windows? module Errno class ENOTEMPTY # We do not raise this exception, implementation is not needed. end end end def File.binread(fname) open(fname, 'rb') {|f| return f.read } end # for corrupted Windows' stat(2) def File.dir?(path) File.directory?((path[-1,1] == '/') ? path : path + '/') end class ConfigTable include Enumerable def initialize(rbconfig) @rbconfig = rbconfig @items = [] @table = {} # options @install_prefix = nil @config_opt = nil @verbose = true @no_harm = false end attr_accessor :install_prefix attr_accessor :config_opt attr_writer :verbose def verbose? @verbose end attr_writer :no_harm def no_harm? @no_harm end def [](key) lookup(key).resolve(self) end def []=(key, val) lookup(key).set val end def names @items.map {|i| i.name } end def each(&block) @items.each(&block) end def key?(name) @table.key?(name) end def lookup(name) @table[name] or setup_rb_error "no such config item: #{name}" end def add(item) @items.push item @table[item.name] = item end def remove(name) item = lookup(name) @items.delete_if {|i| i.name == name } @table.delete_if {|name, i| i.name == name } item end def load_script(path, inst = nil) if File.file?(path) MetaConfigEnvironment.new(self, inst).instance_eval File.read(path), path end end def savefile '.config' end def load_savefile begin File.foreach(savefile()) do |line| k, v = *line.split(/=/, 2) self[k] = v.strip end rescue Errno::ENOENT setup_rb_error $!.message + "\n#{File.basename($0)} config first" end end def save @items.each {|i| i.value } File.open(savefile(), 'w') {|f| @items.each do |i| f.printf "%s=%s\n", i.name, i.value if i.value? and i.value end } end def load_standard_entries standard_entries(@rbconfig).each do |ent| add ent end end def standard_entries(rbconfig) c = rbconfig rubypath = File.join(c['bindir'], c['ruby_install_name'] + c['EXEEXT']) major = c['MAJOR'].to_i minor = c['MINOR'].to_i teeny = c['TEENY'].to_i version = "#{major}.#{minor}" # ruby ver. >= 1.4.4? newpath_p = ((major >= 2) or ((major == 1) and ((minor >= 5) or ((minor == 4) and (teeny >= 4))))) if c['rubylibdir'] # V > 1.6.3 libruby = "#{c['prefix']}/lib/ruby" librubyver = c['rubylibdir'] librubyverarch = c['archdir'] siteruby = c['sitedir'] siterubyver = c['sitelibdir'] siterubyverarch = c['sitearchdir'] elsif newpath_p # 1.4.4 <= V <= 1.6.3 libruby = "#{c['prefix']}/lib/ruby" librubyver = "#{c['prefix']}/lib/ruby/#{version}" librubyverarch = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}" siteruby = c['sitedir'] siterubyver = "$siteruby/#{version}" siterubyverarch = "$siterubyver/#{c['arch']}" else # V < 1.4.4 libruby = "#{c['prefix']}/lib/ruby" librubyver = "#{c['prefix']}/lib/ruby/#{version}" librubyverarch = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}" siteruby = "#{c['prefix']}/lib/ruby/#{version}/site_ruby" siterubyver = siteruby siterubyverarch = "$siterubyver/#{c['arch']}" end parameterize = lambda {|path| path.sub(/\A#{Regexp.quote(c['prefix'])}/, '$prefix') } if arg = c['configure_args'].split.detect {|arg| /--with-make-prog=/ =~ arg } makeprog = arg.sub(/'/, '').split(/=/, 2)[1] else makeprog = 'make' end [ ExecItem.new('installdirs', 'std/site/home', 'std: install under libruby; site: install under site_ruby; home: install under $HOME')\ {|val, table| case val when 'std' table['rbdir'] = '$librubyver' table['sodir'] = '$librubyverarch' when 'site' table['rbdir'] = '$siterubyver' table['sodir'] = '$siterubyverarch' when 'home' setup_rb_error '$HOME was not set' unless ENV['HOME'] table['prefix'] = ENV['HOME'] table['rbdir'] = '$libdir/ruby' table['sodir'] = '$libdir/ruby' end }, PathItem.new('prefix', 'path', c['prefix'], 'path prefix of target environment'), PathItem.new('bindir', 'path', parameterize.call(c['bindir']), 'the directory for commands'), PathItem.new('libdir', 'path', parameterize.call(c['libdir']), 'the directory for libraries'), PathItem.new('datadir', 'path', parameterize.call(c['datadir']), 'the directory for shared data'), PathItem.new('mandir', 'path', parameterize.call(c['mandir']), 'the directory for man pages'), PathItem.new('sysconfdir', 'path', parameterize.call(c['sysconfdir']), 'the directory for system configuration files'), PathItem.new('localstatedir', 'path', parameterize.call(c['localstatedir']), 'the directory for local state data'), PathItem.new('libruby', 'path', libruby, 'the directory for ruby libraries'), PathItem.new('librubyver', 'path', librubyver, 'the directory for standard ruby libraries'), PathItem.new('librubyverarch', 'path', librubyverarch, 'the directory for standard ruby extensions'), PathItem.new('siteruby', 'path', siteruby, 'the directory for version-independent aux ruby libraries'), PathItem.new('siterubyver', 'path', siterubyver, 'the directory for aux ruby libraries'), PathItem.new('siterubyverarch', 'path', siterubyverarch, 'the directory for aux ruby binaries'), PathItem.new('rbdir', 'path', '$siterubyver', 'the directory for ruby scripts'), PathItem.new('sodir', 'path', '$siterubyverarch', 'the directory for ruby extentions'), PathItem.new('rubypath', 'path', rubypath, 'the path to set to #! line'), ProgramItem.new('rubyprog', 'name', rubypath, 'the ruby program using for installation'), ProgramItem.new('makeprog', 'name', makeprog, 'the make program to compile ruby extentions'), SelectItem.new('shebang', 'all/ruby/never', 'ruby', 'shebang line (#!) editing mode'), BoolItem.new('without-ext', 'yes/no', 'no', 'does not compile/install ruby extentions') ] end private :standard_entries def load_multipackage_entries multipackage_entries().each do |ent| add ent end end def multipackage_entries [ PackageSelectionItem.new('with', 'name,name...', '', 'ALL', 'package names that you want to install'), PackageSelectionItem.new('without', 'name,name...', '', 'NONE', 'package names that you do not want to install') ] end private :multipackage_entries ALIASES = { 'std-ruby' => 'librubyver', 'stdruby' => 'librubyver', 'rubylibdir' => 'librubyver', 'archdir' => 'librubyverarch', 'site-ruby-common' => 'siteruby', # For backward compatibility 'site-ruby' => 'siterubyver', # For backward compatibility 'bin-dir' => 'bindir', 'bin-dir' => 'bindir', 'rb-dir' => 'rbdir', 'so-dir' => 'sodir', 'data-dir' => 'datadir', 'ruby-path' => 'rubypath', 'ruby-prog' => 'rubyprog', 'ruby' => 'rubyprog', 'make-prog' => 'makeprog', 'make' => 'makeprog' } def fixup ALIASES.each do |ali, name| @table[ali] = @table[name] end @items.freeze @table.freeze @options_re = /\A--(#{@table.keys.join('|')})(?:=(.*))?\z/ end def parse_opt(opt) m = @options_re.match(opt) or setup_rb_error "config: unknown option #{opt}" m.to_a[1,2] end def dllext @rbconfig['DLEXT'] end def value_config?(name) lookup(name).value? end class Item def initialize(name, template, default, desc) @name = name.freeze @template = template @value = default @default = default @description = desc end attr_reader :name attr_reader :description attr_accessor :default alias help_default default def help_opt "--#{@name}=#{@template}" end def value? true end def value @value end def resolve(table) @value.gsub(%r<\$([^/]+)>) { table[$1] } end def set(val) @value = check(val) end private def check(val) setup_rb_error "config: --#{name} requires argument" unless val val end end class BoolItem < Item def config_type 'bool' end def help_opt "--#{@name}" end private def check(val) return 'yes' unless val case val when /\Ay(es)?\z/i, /\At(rue)?\z/i then 'yes' when /\An(o)?\z/i, /\Af(alse)\z/i then 'no' else setup_rb_error "config: --#{@name} accepts only yes/no for argument" end end end class PathItem < Item def config_type 'path' end private def check(path) setup_rb_error "config: --#{@name} requires argument" unless path path[0,1] == '$' ? path : File.expand_path(path) end end class ProgramItem < Item def config_type 'program' end end class SelectItem < Item def initialize(name, selection, default, desc) super @ok = selection.split('/') end def config_type 'select' end private def check(val) unless @ok.include?(val.strip) setup_rb_error "config: use --#{@name}=#{@template} (#{val})" end val.strip end end class ExecItem < Item def initialize(name, selection, desc, &block) super name, selection, nil, desc @ok = selection.split('/') @action = block end def config_type 'exec' end def value? false end def resolve(table) setup_rb_error "$#{name()} wrongly used as option value" end undef set def evaluate(val, table) v = val.strip.downcase unless @ok.include?(v) setup_rb_error "invalid option --#{@name}=#{val} (use #{@template})" end @action.call v, table end end class PackageSelectionItem < Item def initialize(name, template, default, help_default, desc) super name, template, default, desc @help_default = help_default end attr_reader :help_default def config_type 'package' end private def check(val) unless File.dir?("packages/#{val}") setup_rb_error "config: no such package: #{val}" end val end end class MetaConfigEnvironment def initialize(config, installer) @config = config @installer = installer end def config_names @config.names end def config?(name) @config.key?(name) end def bool_config?(name) @config.lookup(name).config_type == 'bool' end def path_config?(name) @config.lookup(name).config_type == 'path' end def value_config?(name) @config.lookup(name).config_type != 'exec' end def add_config(item) @config.add item end def add_bool_config(name, default, desc) @config.add BoolItem.new(name, 'yes/no', default ? 'yes' : 'no', desc) end def add_path_config(name, default, desc) @config.add PathItem.new(name, 'path', default, desc) end def set_config_default(name, default) @config.lookup(name).default = default end def remove_config(name) @config.remove(name) end # For only multipackage def packages raise '[setup.rb fatal] multi-package metaconfig API packages() called for single-package; contact application package vendor' unless @installer @installer.packages end # For only multipackage def declare_packages(list) raise '[setup.rb fatal] multi-package metaconfig API declare_packages() called for single-package; contact application package vendor' unless @installer @installer.packages = list end end end # class ConfigTable # This module requires: #verbose?, #no_harm? module FileOperations def mkdir_p(dirname, prefix = nil) dirname = prefix + File.expand_path(dirname) if prefix $stderr.puts "mkdir -p #{dirname}" if verbose? return if no_harm? # Does not check '/', it's too abnormal. dirs = File.expand_path(dirname).split(%r<(?=/)>) if /\A[a-z]:\z/i =~ dirs[0] disk = dirs.shift dirs[0] = disk + dirs[0] end dirs.each_index do |idx| path = dirs[0..idx].join('') Dir.mkdir path unless File.dir?(path) end end def rm_f(path) $stderr.puts "rm -f #{path}" if verbose? return if no_harm? force_remove_file path end def rm_rf(path) $stderr.puts "rm -rf #{path}" if verbose? return if no_harm? remove_tree path end def remove_tree(path) if File.symlink?(path) remove_file path elsif File.dir?(path) remove_tree0 path else force_remove_file path end end def remove_tree0(path) Dir.foreach(path) do |ent| next if ent == '.' next if ent == '..' entpath = "#{path}/#{ent}" if File.symlink?(entpath) remove_file entpath elsif File.dir?(entpath) remove_tree0 entpath else force_remove_file entpath end end begin Dir.rmdir path rescue Errno::ENOTEMPTY # directory may not be empty end end def move_file(src, dest) force_remove_file dest begin File.rename src, dest rescue File.open(dest, 'wb') {|f| f.write File.binread(src) } File.chmod File.stat(src).mode, dest File.unlink src end end def force_remove_file(path) begin remove_file path rescue end end def remove_file(path) File.chmod 0777, path File.unlink path end def install(from, dest, mode, prefix = nil) $stderr.puts "install #{from} #{dest}" if verbose? return if no_harm? realdest = prefix ? prefix + File.expand_path(dest) : dest realdest = File.join(realdest, File.basename(from)) if File.dir?(realdest) str = File.binread(from) if diff?(str, realdest) verbose_off { rm_f realdest if File.exist?(realdest) } File.open(realdest, 'wb') {|f| f.write str } File.chmod mode, realdest File.open("#{objdir_root()}/InstalledFiles", 'a') {|f| if prefix f.puts realdest.sub(prefix, '') else f.puts realdest end } end end def diff?(new_content, path) return true unless File.exist?(path) new_content != File.binread(path) end def command(*args) $stderr.puts args.join(' ') if verbose? system(*args) or raise RuntimeError, "system(#{args.map{|a| a.inspect }.join(' ')}) failed" end def ruby(*args) command config('rubyprog'), *args end def make(task = nil) command(*[config('makeprog'), task].compact) end def extdir?(dir) File.exist?("#{dir}/MANIFEST") or File.exist?("#{dir}/extconf.rb") end def files_of(dir) Dir.open(dir) {|d| return d.select {|ent| File.file?("#{dir}/#{ent}") } } end DIR_REJECT = %w( . .. CVS SCCS RCS CVS.adm .svn ) def directories_of(dir) Dir.open(dir) {|d| return d.select {|ent| File.dir?("#{dir}/#{ent}") } - DIR_REJECT } end end # This module requires: #srcdir_root, #objdir_root, #relpath module HookScriptAPI def get_config(key) @config[key] end alias config get_config # obsolete: use metaconfig to change configuration def set_config(key, val) @config[key] = val end # # srcdir/objdir (works only in the package directory) # def curr_srcdir "#{srcdir_root()}/#{relpath()}" end def curr_objdir "#{objdir_root()}/#{relpath()}" end def srcfile(path) "#{curr_srcdir()}/#{path}" end def srcexist?(path) File.exist?(srcfile(path)) end def srcdirectory?(path) File.dir?(srcfile(path)) end def srcfile?(path) File.file?(srcfile(path)) end def srcentries(path = '.') Dir.open("#{curr_srcdir()}/#{path}") {|d| return d.to_a - %w(. ..) } end def srcfiles(path = '.') srcentries(path).select {|fname| File.file?(File.join(curr_srcdir(), path, fname)) } end def srcdirectories(path = '.') srcentries(path).select {|fname| File.dir?(File.join(curr_srcdir(), path, fname)) } end end class ToplevelInstaller Version = '3.4.1' Copyright = 'Copyright (c) 2000-2005 Minero Aoki' TASKS = [ [ 'all', 'do config, setup, then install' ], [ 'config', 'saves your configurations' ], [ 'show', 'shows current configuration' ], [ 'setup', 'compiles ruby extentions and others' ], [ 'install', 'installs files' ], [ 'test', 'run all tests in test/' ], [ 'clean', "does `make clean' for each extention" ], [ 'distclean',"does `make distclean' for each extention" ] ] def ToplevelInstaller.invoke config = ConfigTable.new(load_rbconfig()) config.load_standard_entries config.load_multipackage_entries if multipackage? config.fixup klass = (multipackage?() ? ToplevelInstallerMulti : ToplevelInstaller) klass.new(File.dirname($0), config).invoke end def ToplevelInstaller.multipackage? File.dir?(File.dirname($0) + '/packages') end def ToplevelInstaller.load_rbconfig if arg = ARGV.detect {|arg| /\A--rbconfig=/ =~ arg } ARGV.delete(arg) load File.expand_path(arg.split(/=/, 2)[1]) $".push 'rbconfig.rb' else require 'rbconfig' end ::Config::CONFIG end def initialize(ardir_root, config) @ardir = File.expand_path(ardir_root) @config = config # cache @valid_task_re = nil end def config(key) @config[key] end def inspect "#<#{self.class} #{__id__()}>" end def invoke run_metaconfigs case task = parsearg_global() when nil, 'all' parsearg_config init_installers exec_config exec_setup exec_install else case task when 'config', 'test' ; when 'clean', 'distclean' @config.load_savefile if File.exist?(@config.savefile) else @config.load_savefile end __send__ "parsearg_#{task}" init_installers __send__ "exec_#{task}" end end def run_metaconfigs @config.load_script "#{@ardir}/metaconfig" end def init_installers @installer = Installer.new(@config, @ardir, File.expand_path('.')) end # # Hook Script API bases # def srcdir_root @ardir end def objdir_root '.' end def relpath '.' end # # Option Parsing # def parsearg_global while arg = ARGV.shift case arg when /\A\w+\z/ setup_rb_error "invalid task: #{arg}" unless valid_task?(arg) return arg when '-q', '--quiet' @config.verbose = false when '--verbose' @config.verbose = true when '--help' print_usage $stdout exit 0 when '--version' puts "#{File.basename($0)} version #{Version}" exit 0 when '--copyright' puts Copyright exit 0 else setup_rb_error "unknown global option '#{arg}'" end end nil end def valid_task?(t) valid_task_re() =~ t end def valid_task_re @valid_task_re ||= /\A(?:#{TASKS.map {|task,desc| task }.join('|')})\z/ end def parsearg_no_options unless ARGV.empty? task = caller(0).first.slice(%r<`parsearg_(\w+)'>, 1) setup_rb_error "#{task}: unknown options: #{ARGV.join(' ')}" end end alias parsearg_show parsearg_no_options alias parsearg_setup parsearg_no_options alias parsearg_test parsearg_no_options alias parsearg_clean parsearg_no_options alias parsearg_distclean parsearg_no_options def parsearg_config evalopt = [] set = [] @config.config_opt = [] while i = ARGV.shift if /\A--?\z/ =~ i @config.config_opt = ARGV.dup break end name, value = *@config.parse_opt(i) if @config.value_config?(name) @config[name] = value else evalopt.push [name, value] end set.push name end evalopt.each do |name, value| @config.lookup(name).evaluate value, @config end # Check if configuration is valid set.each do |n| @config[n] if @config.value_config?(n) end end def parsearg_install @config.no_harm = false @config.install_prefix = '' while a = ARGV.shift case a when '--no-harm' @config.no_harm = true when /\A--prefix=/ path = a.split(/=/, 2)[1] path = File.expand_path(path) unless path[0,1] == '/' @config.install_prefix = path else setup_rb_error "install: unknown option #{a}" end end end def print_usage(out) out.puts 'Typical Installation Procedure:' out.puts " $ ruby #{File.basename $0} config" out.puts " $ ruby #{File.basename $0} setup" out.puts " # ruby #{File.basename $0} install (may require root privilege)" out.puts out.puts 'Detailed Usage:' out.puts " ruby #{File.basename $0} " out.puts " ruby #{File.basename $0} [] []" fmt = " %-24s %s\n" out.puts out.puts 'Global options:' out.printf fmt, '-q,--quiet', 'suppress message outputs' out.printf fmt, ' --verbose', 'output messages verbosely' out.printf fmt, ' --help', 'print this message' out.printf fmt, ' --version', 'print version and quit' out.printf fmt, ' --copyright', 'print copyright and quit' out.puts out.puts 'Tasks:' TASKS.each do |name, desc| out.printf fmt, name, desc end fmt = " %-24s %s [%s]\n" out.puts out.puts 'Options for CONFIG or ALL:' @config.each do |item| out.printf fmt, item.help_opt, item.description, item.help_default end out.printf fmt, '--rbconfig=path', 'rbconfig.rb to load',"running ruby's" out.puts out.puts 'Options for INSTALL:' out.printf fmt, '--no-harm', 'only display what to do if given', 'off' out.printf fmt, '--prefix=path', 'install path prefix', '' out.puts end # # Task Handlers # def exec_config @installer.exec_config @config.save # must be final end def exec_setup @installer.exec_setup end def exec_install @installer.exec_install end def exec_test @installer.exec_test end def exec_show @config.each do |i| printf "%-20s %s\n", i.name, i.value if i.value? end end def exec_clean @installer.exec_clean end def exec_distclean @installer.exec_distclean end end # class ToplevelInstaller class ToplevelInstallerMulti < ToplevelInstaller include FileOperations def initialize(ardir_root, config) super @packages = directories_of("#{@ardir}/packages") raise 'no package exists' if @packages.empty? @root_installer = Installer.new(@config, @ardir, File.expand_path('.')) end def run_metaconfigs @config.load_script "#{@ardir}/metaconfig", self @packages.each do |name| @config.load_script "#{@ardir}/packages/#{name}/metaconfig" end end attr_reader :packages def packages=(list) raise 'package list is empty' if list.empty? list.each do |name| raise "directory packages/#{name} does not exist"\ unless File.dir?("#{@ardir}/packages/#{name}") end @packages = list end def init_installers @installers = {} @packages.each do |pack| @installers[pack] = Installer.new(@config, "#{@ardir}/packages/#{pack}", "packages/#{pack}") end with = extract_selection(config('with')) without = extract_selection(config('without')) @selected = @installers.keys.select {|name| (with.empty? or with.include?(name)) \ and not without.include?(name) } end def extract_selection(list) a = list.split(/,/) a.each do |name| setup_rb_error "no such package: #{name}" unless @installers.key?(name) end a end def print_usage(f) super f.puts 'Inluded packages:' f.puts ' ' + @packages.sort.join(' ') f.puts end # # Task Handlers # def exec_config run_hook 'pre-config' each_selected_installers {|inst| inst.exec_config } run_hook 'post-config' @config.save # must be final end def exec_setup run_hook 'pre-setup' each_selected_installers {|inst| inst.exec_setup } run_hook 'post-setup' end def exec_install run_hook 'pre-install' each_selected_installers {|inst| inst.exec_install } run_hook 'post-install' end def exec_test run_hook 'pre-test' each_selected_installers {|inst| inst.exec_test } run_hook 'post-test' end def exec_clean rm_f @config.savefile run_hook 'pre-clean' each_selected_installers {|inst| inst.exec_clean } run_hook 'post-clean' end def exec_distclean rm_f @config.savefile run_hook 'pre-distclean' each_selected_installers {|inst| inst.exec_distclean } run_hook 'post-distclean' end # # lib # def each_selected_installers Dir.mkdir 'packages' unless File.dir?('packages') @selected.each do |pack| $stderr.puts "Processing the package `#{pack}' ..." if verbose? Dir.mkdir "packages/#{pack}" unless File.dir?("packages/#{pack}") Dir.chdir "packages/#{pack}" yield @installers[pack] Dir.chdir '../..' end end def run_hook(id) @root_installer.run_hook id end # module FileOperations requires this def verbose? @config.verbose? end # module FileOperations requires this def no_harm? @config.no_harm? end end # class ToplevelInstallerMulti class Installer FILETYPES = %w( bin lib ext data conf man ) include FileOperations include HookScriptAPI def initialize(config, srcroot, objroot) @config = config @srcdir = File.expand_path(srcroot) @objdir = File.expand_path(objroot) @currdir = '.' end def inspect "#<#{self.class} #{File.basename(@srcdir)}>" end def noop(rel) end # # Hook Script API base methods # def srcdir_root @srcdir end def objdir_root @objdir end def relpath @currdir end # # Config Access # # module FileOperations requires this def verbose? @config.verbose? end # module FileOperations requires this def no_harm? @config.no_harm? end def verbose_off begin save, @config.verbose = @config.verbose?, false yield ensure @config.verbose = save end end # # TASK config # def exec_config exec_task_traverse 'config' end alias config_dir_bin noop alias config_dir_lib noop def config_dir_ext(rel) extconf if extdir?(curr_srcdir()) end alias config_dir_data noop alias config_dir_conf noop alias config_dir_man noop def extconf ruby "#{curr_srcdir()}/extconf.rb", *@config.config_opt end # # TASK setup # def exec_setup exec_task_traverse 'setup' end def setup_dir_bin(rel) files_of(curr_srcdir()).each do |fname| update_shebang_line "#{curr_srcdir()}/#{fname}" end end alias setup_dir_lib noop def setup_dir_ext(rel) make if extdir?(curr_srcdir()) end alias setup_dir_data noop alias setup_dir_conf noop alias setup_dir_man noop def update_shebang_line(path) return if no_harm? return if config('shebang') == 'never' old = Shebang.load(path) if old $stderr.puts "warning: #{path}: Shebang line includes too many args. It is not portable and your program may not work." if old.args.size > 1 new = new_shebang(old) return if new.to_s == old.to_s else return unless config('shebang') == 'all' new = Shebang.new(config('rubypath')) end $stderr.puts "updating shebang: #{File.basename(path)}" if verbose? open_atomic_writer(path) {|output| File.open(path, 'rb') {|f| f.gets if old # discard output.puts new.to_s output.print f.read } } end def new_shebang(old) if /\Aruby/ =~ File.basename(old.cmd) Shebang.new(config('rubypath'), old.args) elsif File.basename(old.cmd) == 'env' and old.args.first == 'ruby' Shebang.new(config('rubypath'), old.args[1..-1]) else return old unless config('shebang') == 'all' Shebang.new(config('rubypath')) end end def open_atomic_writer(path, &block) tmpfile = File.basename(path) + '.tmp' begin File.open(tmpfile, 'wb', &block) File.rename tmpfile, File.basename(path) ensure File.unlink tmpfile if File.exist?(tmpfile) end end class Shebang def Shebang.load(path) line = nil File.open(path) {|f| line = f.gets } return nil unless /\A#!/ =~ line parse(line) end def Shebang.parse(line) cmd, *args = *line.strip.sub(/\A\#!/, '').split(' ') new(cmd, args) end def initialize(cmd, args = []) @cmd = cmd @args = args end attr_reader :cmd attr_reader :args def to_s "#! #{@cmd}" + (@args.empty? ? '' : " #{@args.join(' ')}") end end # # TASK install # def exec_install rm_f 'InstalledFiles' exec_task_traverse 'install' end def install_dir_bin(rel) install_files targetfiles(), "#{config('bindir')}/#{rel}", 0755 end def install_dir_lib(rel) install_files libfiles(), "#{config('rbdir')}/#{rel}", 0644 end def install_dir_ext(rel) return unless extdir?(curr_srcdir()) install_files rubyextentions('.'), "#{config('sodir')}/#{File.dirname(rel)}", 0555 end def install_dir_data(rel) install_files targetfiles(), "#{config('datadir')}/#{rel}", 0644 end def install_dir_conf(rel) # FIXME: should not remove current config files # (rename previous file to .old/.org) install_files targetfiles(), "#{config('sysconfdir')}/#{rel}", 0644 end def install_dir_man(rel) install_files targetfiles(), "#{config('mandir')}/#{rel}", 0644 end def install_files(list, dest, mode) mkdir_p dest, @config.install_prefix list.each do |fname| install fname, dest, mode, @config.install_prefix end end def libfiles glob_reject(%w(*.y *.output), targetfiles()) end def rubyextentions(dir) ents = glob_select("*.#{@config.dllext}", targetfiles()) if ents.empty? setup_rb_error "no ruby extention exists: 'ruby #{$0} setup' first" end ents end def targetfiles mapdir(existfiles() - hookfiles()) end def mapdir(ents) ents.map {|ent| if File.exist?(ent) then ent # objdir else "#{curr_srcdir()}/#{ent}" # srcdir end } end # picked up many entries from cvs-1.11.1/src/ignore.c JUNK_FILES = %w( core RCSLOG tags TAGS .make.state .nse_depinfo #* .#* cvslog.* ,* .del-* *.olb *~ *.old *.bak *.BAK *.orig *.rej _$* *$ *.org *.in .* ) def existfiles glob_reject(JUNK_FILES, (files_of(curr_srcdir()) | files_of('.'))) end def hookfiles %w( pre-%s post-%s pre-%s.rb post-%s.rb ).map {|fmt| %w( config setup install clean ).map {|t| sprintf(fmt, t) } }.flatten end def glob_select(pat, ents) re = globs2re([pat]) ents.select {|ent| re =~ ent } end def glob_reject(pats, ents) re = globs2re(pats) ents.reject {|ent| re =~ ent } end GLOB2REGEX = { '.' => '\.', '$' => '\$', '#' => '\#', '*' => '.*' } def globs2re(pats) /\A(?:#{ pats.map {|pat| pat.gsub(/[\.\$\#\*]/) {|ch| GLOB2REGEX[ch] } }.join('|') })\z/ end # # TASK test # TESTDIR = 'test' def exec_test unless File.directory?('test') $stderr.puts 'no test in this package' if verbose? return end $stderr.puts 'Running tests...' if verbose? begin require 'test/unit' rescue LoadError setup_rb_error 'test/unit cannot loaded. You need Ruby 1.8 or later to invoke this task.' end runner = Test::Unit::AutoRunner.new(true) runner.to_run << TESTDIR runner.run end # # TASK clean # def exec_clean exec_task_traverse 'clean' rm_f @config.savefile rm_f 'InstalledFiles' end alias clean_dir_bin noop alias clean_dir_lib noop alias clean_dir_data noop alias clean_dir_conf noop alias clean_dir_man noop def clean_dir_ext(rel) return unless extdir?(curr_srcdir()) make 'clean' if File.file?('Makefile') end # # TASK distclean # def exec_distclean exec_task_traverse 'distclean' rm_f @config.savefile rm_f 'InstalledFiles' end alias distclean_dir_bin noop alias distclean_dir_lib noop def distclean_dir_ext(rel) return unless extdir?(curr_srcdir()) make 'distclean' if File.file?('Makefile') end alias distclean_dir_data noop alias distclean_dir_conf noop alias distclean_dir_man noop # # Traversing # def exec_task_traverse(task) run_hook "pre-#{task}" FILETYPES.each do |type| if type == 'ext' and config('without-ext') == 'yes' $stderr.puts 'skipping ext/* by user option' if verbose? next end traverse task, type, "#{task}_dir_#{type}" end run_hook "post-#{task}" end def traverse(task, rel, mid) dive_into(rel) { run_hook "pre-#{task}" __send__ mid, rel.sub(%r[\A.*?(?:/|\z)], '') directories_of(curr_srcdir()).each do |d| traverse task, "#{rel}/#{d}", mid end run_hook "post-#{task}" } end def dive_into(rel) return unless File.dir?("#{@srcdir}/#{rel}") dir = File.basename(rel) Dir.mkdir dir unless File.dir?(dir) prevdir = Dir.pwd Dir.chdir dir $stderr.puts '---> ' + rel if verbose? @currdir = rel yield Dir.chdir prevdir $stderr.puts '<--- ' + rel if verbose? @currdir = File.dirname(rel) end def run_hook(id) path = [ "#{curr_srcdir()}/#{id}", "#{curr_srcdir()}/#{id}.rb" ].detect {|cand| File.file?(cand) } return unless path begin instance_eval File.read(path), path, 1 rescue raise if $DEBUG setup_rb_error "hook #{path} failed:\n" + $!.message end end end # class Installer class SetupError < StandardError; end def setup_rb_error(msg) raise SetupError, msg end if $0 == __FILE__ begin ToplevelInstaller.invoke rescue SetupError raise if $DEBUG $stderr.puts $!.message $stderr.puts "Try 'ruby #{$0} --help' for detailed usage." exit 1 end end PK!?BMM7gems/2.2.0/gems/ruby-lsapi-5.6/scripts/lsruby_runner.rbnuȯ#!/opt/alt/ruby22/bin/ruby require 'lsapi' class CodeCache def [](filename) mtime = File.mtime( filename ) entry = @cache[filename]; if entry != nil return entry end code = compile(filename) #entry = CodeEntry.new( filename, mtime, code ) @cache[filename] = code return code end private def initialize @cache = {} end def compile(filename) open(filename) do |f| s = f.read s.untaint binding = eval_string_wrap("binding") return eval(format("Proc.new {\n%s\n}", s), binding, filename, 0) end end end $count = 0; $cache = CodeCache.new while true $req = LSAPI.accept break if $req == nil filename = ENV['SCRIPT_FILENAME'] filename.untaint filename =~ %r{^(\/.*?)\/*([^\/]+)$} path = $1 Dir.chdir( path ) #load( filename, true ) code = $cache[filename] code.call end class CodeEntry public :path, :name, :mtime, :opcode def initizlize( filename, mtime, opcode ) filename =~ %r{^(\/.*?)\/*([^\/]+)$} @path = $1 @name = $2 @mtime = mtime @opcode = opcode end end PK!5r!!1gems/2.2.0/gems/ruby-lsapi-5.6/ext/lsapi/Makefilenu[ SHELL = /bin/sh # V=0 quiet, V=1 verbose. other values don't work. V = 0 Q1 = $(V:1=) Q = $(Q1:0=@) ECHO1 = $(V:1=@:) ECHO = $(ECHO1:0=@echo) NULLCMD = : #### Start of system configuration section. #### srcdir = . topdir = /opt/alt/ruby22/include/ruby-2.2.0 hdrdir = $(topdir) arch_hdrdir = /opt/alt/ruby22/include/ruby-2.2.0/x86_64-linux PATH_SEPARATOR = : VPATH = $(srcdir):$(arch_hdrdir)/ruby:$(hdrdir)/ruby prefix = $(DESTDIR)/opt/alt/ruby22 rubysitearchprefix = $(rubylibprefix)/$(sitearch) rubyarchprefix = $(rubylibprefix)/$(arch) rubylibprefix = $(libdir)/$(RUBY_BASE_NAME) exec_prefix = $(DESTDIR)/opt/alt/ruby22 vendorarchhdrdir = $(vendorhdrdir)/$(sitearch) sitearchhdrdir = $(sitehdrdir)/$(sitearch) rubyarchhdrdir = $(rubyhdrdir)/$(arch) vendorhdrdir = $(rubyhdrdir)/vendor_ruby sitehdrdir = $(rubyhdrdir)/site_ruby rubyhdrdir = $(includedir)/$(RUBY_VERSION_NAME) vendorarchdir = $(vendorlibdir)/$(sitearch) vendorlibdir = $(vendordir)/$(ruby_version) vendordir = $(rubylibprefix)/vendor_ruby sitearchdir = $(DESTDIR)./.gem.20240125-3705149-blbl4i sitelibdir = $(DESTDIR)./.gem.20240125-3705149-blbl4i sitedir = $(rubylibprefix)/site_ruby rubyarchdir = $(rubylibdir)/$(arch) rubylibdir = $(rubylibprefix)/$(ruby_version) sitearchincludedir = $(includedir)/$(sitearch) archincludedir = $(includedir)/$(arch) sitearchlibdir = $(libdir)/$(sitearch) archlibdir = $(libdir)/$(arch) ridir = $(datarootdir)/$(RI_BASE_NAME) mandir = $(DESTDIR)/opt/alt/ruby22/share/man localedir = $(datarootdir)/locale libdir = $(exec_prefix)/lib64 psdir = $(docdir) pdfdir = $(docdir) dvidir = $(docdir) htmldir = $(docdir) infodir = $(DESTDIR)/opt/alt/ruby22/share/info docdir = $(datarootdir)/doc/$(PACKAGE) oldincludedir = $(DESTDIR)/usr/include includedir = $(DESTDIR)/opt/alt/ruby22/include localstatedir = $(DESTDIR)/var sharedstatedir = $(DESTDIR)/var/lib sysconfdir = $(DESTDIR)/etc datadir = $(DESTDIR)/opt/alt/ruby22/share datarootdir = $(prefix)/share libexecdir = $(DESTDIR)/opt/alt/ruby22/libexec sbindir = $(DESTDIR)/opt/alt/ruby22/sbin bindir = $(exec_prefix)/bin archdir = $(rubyarchdir) CC = gcc CXX = g++ LIBRUBY = $(LIBRUBY_SO) LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a LIBRUBYARG_SHARED = -Wl,-R$(libdir) -L$(libdir) -l$(RUBY_SO_NAME) LIBRUBYARG_STATIC = -Wl,-R$(libdir) -L$(libdir) -l$(RUBY_SO_NAME)-static empty = OUTFLAG = -o $(empty) COUTFLAG = -o $(empty) RUBY_EXTCONF_H = cflags = $(optflags) $(debugflags) $(warnflags) optflags = -O3 -fno-fast-math debugflags = -ggdb3 warnflags = -Wall -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Wunused-variable -Wpointer-arith -Wwrite-strings -Wdeclaration-after-statement -Wimplicit-function-declaration -Wdeprecated-declarations -Wno-packed-bitfield-compat CCDLFLAGS = -fPIC CFLAGS = $(CCDLFLAGS) -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection $(ARCH_FLAG) INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir)/ruby/backward -I$(hdrdir) -I$(srcdir) DEFS = CPPFLAGS = $(DEFS) $(cppflags) -DRUBY_2 CXXFLAGS = $(CCDLFLAGS) -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection $(ARCH_FLAG) ldflags = -L. -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -L/opt/alt/openssl/lib64 -L/opt/alt/ruby22/lib64 -Wl,-rpath=/opt/alt/openssl/lib64,-rpath=/opt/alt/ruby22/lib64 -fstack-protector -rdynamic -Wl,-export-dynamic dldflags = ARCH_FLAG = -m64 DLDFLAGS = $(ldflags) $(dldflags) $(ARCH_FLAG) LDSHARED = $(CC) -shared LDSHAREDXX = $(CXX) -shared AR = ar EXEEXT = RUBY_INSTALL_NAME = $(RUBY_BASE_NAME) RUBY_SO_NAME = ruby RUBYW_INSTALL_NAME = RUBY_VERSION_NAME = $(RUBY_BASE_NAME)-$(ruby_version) RUBYW_BASE_NAME = rubyw RUBY_BASE_NAME = ruby arch = x86_64-linux sitearch = $(arch) ruby_version = 2.2.0 ruby = $(bindir)/$(RUBY_BASE_NAME) RUBY = $(ruby) ruby_headers = $(hdrdir)/ruby.h $(hdrdir)/ruby/ruby.h $(hdrdir)/ruby/defines.h $(hdrdir)/ruby/missing.h $(hdrdir)/ruby/intern.h $(hdrdir)/ruby/st.h $(hdrdir)/ruby/subst.h $(arch_hdrdir)/ruby/config.h RM = rm -f RM_RF = $(RUBY) -run -e rm -- -rf RMDIRS = rmdir --ignore-fail-on-non-empty -p MAKEDIRS = /usr/bin/mkdir -p INSTALL = /usr/bin/install -c INSTALL_PROG = $(INSTALL) -m 0755 INSTALL_DATA = $(INSTALL) -m 644 COPY = cp TOUCH = exit > #### End of system configuration section. #### preload = libpath = . $(libdir) LIBPATH = -L. -L$(libdir) -Wl,-R$(libdir) DEFFILE = CLEANFILES = mkmf.log DISTCLEANFILES = DISTCLEANDIRS = extout = extout_prefix = target_prefix = LOCAL_LIBS = LIBS = $(LIBRUBYARG_SHARED) -lpthread -ldl -lcrypt -lm -lc ORIG_SRCS = lsapilib.c lsruby.c SRCS = $(ORIG_SRCS) OBJS = lsapilib.o lsruby.o HDRS = $(srcdir)/lsapidef.h $(srcdir)/lsapilib.h TARGET = lsapi TARGET_NAME = lsapi TARGET_ENTRY = Init_$(TARGET_NAME) DLLIB = $(TARGET).so EXTSTATIC = STATIC_LIB = TIMESTAMP_DIR = . BINDIR = $(bindir) RUBYCOMMONDIR = $(sitedir)$(target_prefix) RUBYLIBDIR = $(sitelibdir)$(target_prefix) RUBYARCHDIR = $(sitearchdir)$(target_prefix) HDRDIR = $(rubyhdrdir)/ruby$(target_prefix) ARCHHDRDIR = $(rubyhdrdir)/$(arch)/ruby$(target_prefix) TARGET_SO = $(DLLIB) CLEANLIBS = $(TARGET).so CLEANOBJS = *.o *.bak all: $(DLLIB) static: $(STATIC_LIB) .PHONY: all install static install-so install-rb .PHONY: clean clean-so clean-static clean-rb clean-static:: clean-rb-default:: clean-rb:: clean-so:: clean: clean-so clean-static clean-rb-default clean-rb -$(Q)$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES) .*.time distclean-rb-default:: distclean-rb:: distclean-so:: distclean-static:: distclean: clean distclean-so distclean-static distclean-rb-default distclean-rb -$(Q)$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log -$(Q)$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES) -$(Q)$(RMDIRS) $(DISTCLEANDIRS) 2> /dev/null || true realclean: distclean install: install-so install-rb install-so: $(DLLIB) $(TIMESTAMP_DIR)/.RUBYARCHDIR.time $(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR) clean-static:: -$(Q)$(RM) $(STATIC_LIB) install-rb: pre-install-rb install-rb-default install-rb-default: pre-install-rb-default pre-install-rb: Makefile pre-install-rb-default: Makefile pre-install-rb-default: @$(NULLCMD) $(TIMESTAMP_DIR)/.RUBYARCHDIR.time: $(Q) $(MAKEDIRS) $(@D) $(RUBYARCHDIR) $(Q) $(TOUCH) $@ site-install: site-install-so site-install-rb site-install-so: install-so site-install-rb: install-rb .SUFFIXES: .c .m .cc .mm .cxx .cpp .o .S .cc.o: $(ECHO) compiling $(<) $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $< .cc.S: $(ECHO) translating $(<) $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $< .mm.o: $(ECHO) compiling $(<) $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $< .mm.S: $(ECHO) translating $(<) $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $< .cxx.o: $(ECHO) compiling $(<) $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $< .cxx.S: $(ECHO) translating $(<) $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $< .cpp.o: $(ECHO) compiling $(<) $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $< .cpp.S: $(ECHO) translating $(<) $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $< .c.o: $(ECHO) compiling $(<) $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $< .c.S: $(ECHO) translating $(<) $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -S $< .m.o: $(ECHO) compiling $(<) $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $< .m.S: $(ECHO) translating $(<) $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -S $< $(DLLIB): $(OBJS) Makefile $(ECHO) linking shared-object $(DLLIB) -$(Q)$(RM) $(@) $(Q) $(LDSHARED) -o $@ $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS) $(OBJS): $(HDRS) $(ruby_headers) PK!W q,,3gems/2.2.0/gems/ruby-lsapi-5.6/ext/lsapi/lsapidef.hnu[/* Copyright (c) 2002-2018, Lite Speed Technologies Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the Lite Speed Technologies Inc nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _LSAPIDEF_H_ #define _LSAPIDEF_H_ #include #if defined (c_plusplus) || defined (__cplusplus) extern "C" { #endif enum { H_ACCEPT = 0, H_ACC_CHARSET, H_ACC_ENCODING, H_ACC_LANG, H_AUTHORIZATION, H_CONNECTION, H_CONTENT_TYPE, H_CONTENT_LENGTH, H_COOKIE, H_COOKIE2, H_HOST, H_PRAGMA, H_REFERER, H_USERAGENT, H_CACHE_CTRL, H_IF_MODIFIED_SINCE, H_IF_MATCH, H_IF_NO_MATCH, H_IF_RANGE, H_IF_UNMOD_SINCE, H_KEEP_ALIVE, H_RANGE, H_X_FORWARDED_FOR, H_VIA, H_TRANSFER_ENCODING }; #define LSAPI_SOCK_FILENO 0 #define LSAPI_VERSION_B0 'L' #define LSAPI_VERSION_B1 'S' /* Values for m_flag in lsapi_packet_header */ #define LSAPI_ENDIAN_LITTLE 0 #define LSAPI_ENDIAN_BIG 1 #define LSAPI_ENDIAN_BIT 1 #if defined(__i386__)||defined( __x86_64 )||defined( __x86_64__ ) #define LSAPI_ENDIAN LSAPI_ENDIAN_LITTLE #else #define LSAPI_ENDIAN LSAPI_ENDIAN_BIG #endif /* Values for m_type in lsapi_packet_header */ #define LSAPI_BEGIN_REQUEST 1 #define LSAPI_ABORT_REQUEST 2 #define LSAPI_RESP_HEADER 3 #define LSAPI_RESP_STREAM 4 #define LSAPI_RESP_END 5 #define LSAPI_STDERR_STREAM 6 #define LSAPI_REQ_RECEIVED 7 #define LSAPI_CONN_CLOSE 8 #define LSAPI_INTERNAL_ERROR 9 #define LSAPI_MAX_HEADER_LEN 65535 #define LSAPI_MAX_DATA_PACKET_LEN 16384 #define LSAPI_RESP_HTTP_HEADER_MAX 32768 #define LSAPI_PACKET_HEADER_LEN 8 struct lsapi_packet_header { char m_versionB0; /* LSAPI protocol version */ char m_versionB1; char m_type; char m_flag; union { int32_t m_iLen; /* include this header */ char m_bytes[4]; }m_packetLen; }; /* LSAPI request header packet 1. struct lsapi_req_header 2. struct lsapi_http_header_index 3. lsapi_header_offset * unknownHeaders 4. org http request header 5. request body if available */ struct lsapi_req_header { struct lsapi_packet_header m_pktHeader; int32_t m_httpHeaderLen; int32_t m_reqBodyLen; int32_t m_scriptFileOff; /* path to the script file. */ int32_t m_scriptNameOff; /* decrypted URI, without pathinfo, */ int32_t m_queryStringOff; /* Query string inside env */ int32_t m_requestMethodOff; int32_t m_cntUnknownHeaders; int32_t m_cntEnv; int32_t m_cntSpecialEnv; } ; struct lsapi_http_header_index { uint16_t m_headerLen[H_TRANSFER_ENCODING+1]; int32_t m_headerOff[H_TRANSFER_ENCODING+1]; } ; struct lsapi_header_offset { int32_t nameOff; int32_t nameLen; int32_t valueOff; int32_t valueLen; } ; struct lsapi_resp_info { int32_t m_cntHeaders; int32_t m_status; }; struct lsapi_resp_header { struct lsapi_packet_header m_pktHeader; struct lsapi_resp_info m_respInfo; }; #if defined (c_plusplus) || defined (__cplusplus) } #endif #endif PK!dCR[R[1gems/2.2.0/gems/ruby-lsapi-5.6/ext/lsapi/lsruby.cnu[ #include "ruby.h" #if defined( RUBY_VERSION_CODE ) && RUBY_VERSION_CODE < 180 #include "util.h" #else #include #include #endif #include "lsapilib.h" #include #include #include #include #include #include #include #include #include #ifndef RUBY_API_VERSION_CODE #define RUBY_API_VERSION_CODE (RUBY_API_VERSION_MAJOR*10000+RUBY_API_VERSION_MINOR*100+RUBY_API_VERSION_TEENY) #endif /* RUBY_EXTERN VALUE ruby_errinfo; */ RUBY_EXTERN VALUE rb_stdin; RUBY_EXTERN VALUE rb_stdout; #if defined( RUBY_VERSION_CODE ) && RUBY_VERSION_CODE < 180 RUBY_EXTERN VALUE rb_defout; #endif static VALUE orig_stdin; static VALUE orig_stdout; static VALUE orig_stderr; #if defined( RUBY_VERSION_CODE ) && RUBY_VERSION_CODE < 180 static VALUE orig_defout; #endif static VALUE orig_env; static VALUE env_copy; static VALUE lsapi_env; static int MAX_BODYBUF_LENGTH = (10 * 1024 * 1024); #if RUBY_API_VERSION_CODE >= 20700 # if defined rb_tainted_str_new # undef rb_tainted_str_new # endif # define rb_tainted_str_new(p,l) rb_str_new((p),(l)) #endif /* static VALUE lsapi_objrefs; */ typedef struct lsapi_data { LSAPI_Request * req; VALUE env; ssize_t (* fn_write)( LSAPI_Request *, const char * , size_t ); }lsapi_data; static VALUE cLSAPI; static VALUE s_req = Qnil; static lsapi_data * s_req_data; static VALUE s_req_stderr = Qnil; static lsapi_data * s_stderr_data; static pid_t s_pid = 0; typedef struct lsapi_body { char *bodyBuf; //we put small one into memory, otherwise, into a memory mapping file, and we still use the bodyBuf to access this mapping int bodyLen; //expected length got form content-length int bodyCurrentLen; //current length by read() readBodyToReqBuf int curPos; }lsapi_body; static lsapi_body s_body; static char sTempFile[1024] = {0}; /* * static void lsapi_ruby_setenv(const char *name, const char *value) * { * if (!name) return; * * if (value && *value) * ruby_setenv(name, value); * else * ruby_unsetenv(name); } * * */ static void lsapi_mark( lsapi_data * data ) { rb_gc_mark( data->env ); } /* * static void lsapi_free_data( lsapi_data * data ) * { * free( data ); } * * */ static int add_env_rails( const char * pKey, int keyLen, const char * pValue, int valLen, void * arg ) { char * p; int len; /* Fixup some environment variables for rails */ switch( *pKey ) { case 'Q': if ( strcmp( pKey, "QUERY_STRING" ) == 0 ) { if ( !*pValue ) return 1; } break; case 'R': if (( *(pKey+8) == 'U' )&&( strcmp( pKey, "REQUEST_URI" ) == 0 )) { p = strchr( pValue, '?' ); if ( p ) { len = valLen - ( p - pValue ) - 1; /* * valLen = p - pValue; *p++ = 0; */ } else { p = (char *)pValue + valLen; len = 0; } rb_hash_aset( lsapi_env,rb_tainted_str_new("PATH_INFO", 9), rb_tainted_str_new(pValue, p - pValue)); rb_hash_aset( lsapi_env,rb_tainted_str_new("REQUEST_PATH", 12), rb_tainted_str_new(pValue, p - pValue)); if ( *p == '?' ) ++p; rb_hash_aset( lsapi_env,rb_tainted_str_new("QUERY_STRING", 12), rb_tainted_str_new(p, len)); } break; case 'S': if ( strcmp( pKey, "SCRIPT_NAME" ) == 0 ) { pValue = "/"; valLen = 1; } break; case 'P': if ( strcmp( pKey, "PATH_INFO" ) == 0 ) return 1; default: break; } /* lsapi_ruby_setenv(pKey, pValue ); */ rb_hash_aset( lsapi_env,rb_tainted_str_new(pKey, keyLen), rb_tainted_str_new(pValue, valLen)); return 1; } static int add_env_no_fix( const char * pKey, int keyLen, const char * pValue, int valLen, void * arg ) { rb_hash_aset( lsapi_env,rb_tainted_str_new(pKey, keyLen), rb_tainted_str_new(pValue, valLen)); return 1; } typedef int (*fn_add_env)( const char * pKey, int keyLen, const char * pValue, int valLen, void * arg ); fn_add_env s_fn_add_env = add_env_no_fix; static void clear_env() { /* rb_funcall( lsapi_env, rb_intern( "clear" ), 0 ); */ rb_funcall( lsapi_env, rb_intern( "replace" ), 1, env_copy ); } static void setup_cgi_env( lsapi_data * data ) { clear_env(); LSAPI_ForeachHeader_r( data->req, s_fn_add_env, data ); LSAPI_ForeachEnv_r( data->req, s_fn_add_env, data ); } static VALUE lsapi_s_accept( VALUE self ) { int pid; if ( LSAPI_Prefork_Accept_r( &g_req ) == -1 ) return Qnil; else { if (s_body.bodyBuf != NULL) free (s_body.bodyBuf); s_body.bodyBuf = NULL; s_body.bodyLen = -1; s_body.bodyCurrentLen = 0; s_body.curPos = 0; pid = getpid(); if ( pid != s_pid ) { s_pid = pid; rb_funcall( Qnil, rb_intern( "srand" ), 0 ); } setup_cgi_env( s_req_data ); return s_req; } } static VALUE lsapi_s_accept_new_conn(VALUE self) { if (LSAPI_Accept_Before_Fork(&g_req) == -1 ) return Qnil; else return s_req; } static VALUE lsapi_s_postfork_child(VALUE self) { LSAPI_Postfork_Child(&g_req); return s_req; } static VALUE lsapi_s_postfork_parent(VALUE self) { LSAPI_Postfork_Parent(&g_req); return s_req; } /* * static int chdir_file( const char * pFile ) * { * char * p = strrchr( pFile, '/' ); * int ret; * if ( !p ) * return -1; *p = 0; ret = chdir( pFile ); *p = '/'; return ret; } */ static VALUE lsapi_eval_string_wrap(VALUE self, VALUE str) { #if RUBY_API_VERSION_CODE < 20700 if (rb_safe_level() >= 4) { Check_Type(str, T_STRING); } else #endif { SafeStringValue(str); } return rb_eval_string_wrap(StringValuePtr(str), NULL); } static VALUE lsapi_process( VALUE self ) { /* lsapi_data *data; const char * pScriptPath; Data_Get_Struct(self,lsapi_data, data); pScriptPath = LSAPI_GetScriptFileName_r( data->req ); */ /* * if ( chdir_file( pScriptPath ) == -1 ) * { * lsapi_send_error( 404 ); * } * rb_load_file( pScriptPath ); */ return Qnil; } static VALUE lsapi_putc(VALUE self, VALUE c) { char ch = NUM2CHR(c); lsapi_data *data; Data_Get_Struct(self,lsapi_data, data); if ( (*data->fn_write)( data->req, &ch, 1 ) == 1 ) return c; else return INT2NUM( EOF ); } static VALUE lsapi_write( VALUE self, VALUE str ) { lsapi_data *data; int len; Data_Get_Struct(self,lsapi_data, data); /* len = LSAPI_Write_r( data->req, RSTRING_PTR(str), RSTRING_LEN(str) ); */ if (TYPE(str) != T_STRING) str = rb_obj_as_string(str); len = (*data->fn_write)( data->req, RSTRING_PTR(str), RSTRING_LEN(str) ); return INT2NUM( len ); } static VALUE lsapi_print( int argc, VALUE *argv, VALUE out ) { int i; VALUE line; /* if no argument given, print `$_' */ if (argc == 0) { argc = 1; line = rb_lastline_get(); argv = &line; } for (i = 0; i0) { lsapi_write(out, rb_output_fs); } switch (TYPE(argv[i])) { case T_NIL: lsapi_write(out, rb_str_new2("nil")); break; default: lsapi_write(out, argv[i]); break; } } if (!NIL_P(rb_output_rs)) { lsapi_write(out, rb_output_rs); } return Qnil; } static VALUE lsapi_printf(int argc, VALUE *argv, VALUE out) { lsapi_write(out, rb_f_sprintf(argc, argv)); return Qnil; } static VALUE lsapi_puts _((int, VALUE*, VALUE)); #if RUBY_API_VERSION_CODE >= 10900 static VALUE lsapi_puts_ary(VALUE ary, VALUE out, int recur ) { VALUE tmp; long i; if (recur) { tmp = rb_str_new2("[...]"); rb_io_puts(1, &tmp, out); return Qnil; } for (i=0; i= 10900 rb_exec_recursive(lsapi_puts_ary, argv[i], out); #else rb_protect_inspect(lsapi_puts_ary, argv[i], out); #endif continue; default: line = argv[i]; break; } line = rb_obj_as_string(line); lsapi_write(out, line); if (*( RSTRING_PTR(line) + RSTRING_LEN(line) - 1 ) != '\n') { lsapi_write(out, rb_default_rs); } } return Qnil; } static VALUE lsapi_addstr(VALUE out, VALUE str) { lsapi_write(out, str); return out; } static VALUE lsapi_flush( VALUE self ) { /* * lsapi_data *data; * Data_Get_Struct(self,lsapi_data, data); */ LSAPI_Flush_r( &g_req ); return Qnil; } static VALUE lsapi_getc( VALUE self ) { int ch; /* * lsapi_data *data; * Data_Get_Struct(self,lsapi_data, data); */ #if RUBY_API_VERSION_CODE < 20700 if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) { rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO"); } #endif ch = LSAPI_ReqBodyGetChar_r( &g_req ); if ( ch == EOF ) return Qnil; return INT2NUM( ch ); } static inline int isBodyWriteToFile() { return ((s_body.bodyLen >= MAX_BODYBUF_LENGTH)? (1): (0)); } //create a temp file and open it, if failed, fd = -1 static inline int createTempFile() { int fd = -1; char *sfn = strdup(sTempFile); if ((fd = mkstemp(sfn)) == -1) { fprintf(stderr, "%s: %s\n", sfn, strerror(errno)); } else unlink(sfn); free(sfn); return fd; } //return 1 if error occured! //if already created, always OK (0) static int createBodyBuf() { int fd = -1; if (s_body.bodyLen == -1) { s_body.bodyLen = LSAPI_GetReqBodyLen_r(&g_req); //Error if get a zeor length, should not happen if (s_body.bodyLen < 0) { //Wrong bode length will be treated as 0 s_body.bodyLen = 0; } if (s_body.bodyLen > 0) { if (isBodyWriteToFile()) { //create file mapping fd = createTempFile(); if (fd == -1) { return 1; } if (ftruncate(fd, s_body.bodyLen) == 0) { perror("ftruncate() failed. \n"); close(fd); return 1; } s_body.bodyBuf = mmap(NULL, s_body.bodyLen, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (s_body.bodyBuf == MAP_FAILED) { perror("File mapping failed. \n"); close(fd); return 1; } close(fd); //close since needn't it anymore } else { s_body.bodyBuf = (char *)calloc(s_body.bodyLen, sizeof(char)); if (s_body.bodyBuf == NULL) { perror("Memory calloc error"); return 1; } } } } return 0; } static inline int isAllBodyRead() { return (s_body.bodyCurrentLen < s_body.bodyLen)? 0 : 1; } static inline int isEofBodyBuf() { return (s_body.curPos < s_body.bodyLen) ? 0 : 1; } //try to read length as times pagesize (such as 8KB * N) static int readBodyBuf(const int needRead) { const int blockSize = 8192; char *buff = s_body.bodyBuf + s_body.bodyCurrentLen; int nRead; int readMore = (needRead + blockSize -1) / blockSize * blockSize; int remain = LSAPI_GetReqBodyRemain_r( &g_req ); //Only when not enough left, needReadChange will be changed!!! if (remain < readMore) readMore = remain; if ( readMore <= 0 ) return 0; nRead = LSAPI_ReadReqBody_r(&g_req, buff, readMore); if ( nRead > 0 ) s_body.bodyCurrentLen += nRead; return nRead; } static VALUE lsapi_gets( VALUE self ) { VALUE str; const int blkSize = 4096; int n; char *p = NULL; #if RUBY_API_VERSION_CODE < 20700 if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) { rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO"); } #endif if (createBodyBuf() == 1) { return Qnil; } //comment: while((p = memmem(s_body.bodyBuf + s_body.curPos, s_body.bodyCurrentLen - s_body.curPos, "\n", 1)) == NULL) { if (isAllBodyRead() == 1) break; //read one page and check, then reply readBodyBuf(blkSize); } p = memmem(s_body.bodyBuf + s_body.curPos, s_body.bodyCurrentLen - s_body.curPos, "\n", 1); if (p != NULL) n = p - s_body.bodyBuf - s_body.curPos + 1; else n = s_body.bodyCurrentLen - s_body.curPos; str = rb_str_buf_new( n ); #if RUBY_API_VERSION_CODE < 20700 OBJ_TAINT(str); #endif if (n > 0) { rb_str_buf_cat( str, s_body.bodyBuf + s_body.curPos, n ); s_body.curPos += n; } return str; } static VALUE lsapi_read(int argc, VALUE *argv, VALUE self) { VALUE str; int n; int needRead; int nRead; #if RUBY_API_VERSION_CODE < 20700 if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) { rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO"); } #endif if (createBodyBuf() == 1) { return Qnil; } //we need to consider these 4 cases: //1, need all data since argc == 0, we may have all data 2, or not //3, need a length of data (argv >= 1), we may have enough data already read, 4, or not if (argc == 0) n = s_body.bodyLen - s_body.curPos; else { n = NUM2INT(argv[0]); //request that length from currentpos if (n < 0) return Qnil; if (n > s_body.bodyLen - s_body.curPos) n = s_body.bodyLen - s_body.curPos; } needRead = s_body.curPos + n - s_body.bodyCurrentLen; if (needRead < 0) needRead = 0; str = rb_str_buf_new( n ); #if RUBY_API_VERSION_CODE < 20700 OBJ_TAINT(str); #endif if (n == 0) return str; //copy already have part first if (n - needRead != 0) { rb_str_buf_cat( str, s_body.bodyBuf + s_body.curPos, n - needRead); s_body.curPos += (n - needRead); } if (needRead > 0) { //try to read needRead, but may be less (changed) when read the end of the data nRead = readBodyBuf(needRead); if (nRead > 0) { n = ((nRead < needRead) ? nRead : needRead); rb_str_buf_cat( str, s_body.bodyBuf + s_body.curPos, n ); s_body.curPos += n; } } return str; } static VALUE lsapi_rewind(VALUE self) { s_body.curPos = 0; return self; } static VALUE lsapi_each(VALUE self) { VALUE str; lsapi_rewind(self); while(isEofBodyBuf() != 1) { str = lsapi_gets(self); rb_yield(str); } return self; } static VALUE lsapi_eof(VALUE self) { return (LSAPI_GetReqBodyRemain_r( &g_req ) <= 0) ? Qtrue : Qfalse; } static VALUE lsapi_binmode(VALUE self) { return self; } static VALUE lsapi_isatty(VALUE self) { return Qfalse; } static VALUE lsapi_sync(VALUE self) { return Qfalse; } static VALUE lsapi_setsync(VALUE self,VALUE sync) { return Qfalse; } static VALUE lsapi_close(VALUE self) { LSAPI_Flush_r( &g_req ); if (isBodyWriteToFile()) { //msync(s_body.bodyBuf, s_body.bodyLen, MS_SYNC); //sleep(5); munmap(s_body.bodyBuf, s_body.bodyLen); } else free(s_body.bodyBuf); s_body.bodyBuf = NULL; s_body.bodyLen = -1; s_body.bodyCurrentLen = 0; s_body.curPos = 0; //Should the temp be deleted here?! return Qnil; } static VALUE lsapi_reopen( int argc, VALUE *argv, VALUE self) { VALUE orig_verbose; if ( self == s_req_stderr ) { /* constant silence hack */ orig_verbose = (VALUE)ruby_verbose; ruby_verbose = Qnil; rb_define_global_const("STDERR", orig_stderr); ruby_verbose = (VALUE)orig_verbose; return rb_funcall2( orig_stderr, rb_intern( "reopen" ), argc, argv ); } return self; } static void readMaxBodyBufLength() { int n; const char *p = getenv( "LSAPI_MAX_BODYBUF_LENGTH" ); if ( p ) { n = atoi( p ); if (n > 0) { if (strstr(p, "M") || strstr(p, "m")) MAX_BODYBUF_LENGTH = n * 1024 * 1024; else if (strstr(p, "K") || strstr(p, "k")) MAX_BODYBUF_LENGTH = n * 1024; else MAX_BODYBUF_LENGTH = n; } } } static void readTempFileTemplate() { const char *p = getenv( "LSAPI_TEMPFILE" ); if (p == NULL || strlen(p) > 1024 - 7) p = "/tmp/lsapi.XXXXXX"; strcpy(sTempFile, p); if (strlen(p) <= 6 || strcmp(p + (strlen(p) - 6), "XXXXXX") != 0) strcat(sTempFile, ".XXXXXX"); } static void initBodyBuf() { s_body.bodyBuf = NULL; s_body.bodyLen = -1; s_body.bodyCurrentLen = 0; s_body.curPos = 0; } void Init_lsapi() { VALUE orig_verbose; char * p; int prefork = 0; LSAPI_Init(); initBodyBuf(); readMaxBodyBufLength(); readTempFileTemplate(); p = getenv("LSAPI_CHILDREN"); if (p && atoi(p) > 1) prefork = 1; #ifdef rb_thread_select LSAPI_Init_Env_Parameters( rb_thread_select ); #else LSAPI_Init_Env_Parameters( select ); #endif s_pid = getpid(); p = getenv( "RACK_ROOT" ); if ( p ) { if ( chdir( p ) == -1 ) perror( "chdir()" ); } if ( p || getenv( "RACK_ENV" ) ) s_fn_add_env = add_env_rails; orig_stdin = rb_stdin; orig_stdout = rb_stdout; orig_stderr = rb_stderr; #if defined( RUBY_VERSION_CODE ) && RUBY_VERSION_CODE < 180 orig_defout = rb_defout; #endif orig_env = rb_const_get( rb_cObject, rb_intern("ENV") ); env_copy = rb_funcall( orig_env, rb_intern( "to_hash" ), 0 ); /* tell the garbage collector it is a global variable, do not recycle it. */ rb_global_variable(&env_copy); rb_hash_aset( env_copy,rb_tainted_str_new("GATEWAY_Irewindable_input.rbNTERFACE", 17), rb_tainted_str_new("CGI/1.2", 7)); rb_define_global_function("eval_string_wrap", lsapi_eval_string_wrap, 1); cLSAPI = rb_define_class("LSAPI", rb_cObject); rb_define_singleton_method(cLSAPI, "accept", lsapi_s_accept, 0); if (prefork) { rb_define_singleton_method(cLSAPI, "accept_new_connection", lsapi_s_accept_new_conn, 0); rb_define_singleton_method(cLSAPI, "postfork_child", lsapi_s_postfork_child, 0); rb_define_singleton_method(cLSAPI, "postfork_parent", lsapi_s_postfork_parent, 0); } rb_define_method(cLSAPI, "process", lsapi_process, 0 ); /* rb_define_method(cLSAPI, "initialize", lsapi_initialize, 0); */ rb_define_method(cLSAPI, "putc", lsapi_putc, 1); rb_define_method(cLSAPI, "write", lsapi_write, 1); rb_define_method(cLSAPI, "print", lsapi_print, -1); rb_define_method(cLSAPI, "printf", lsapi_printf, -1); rb_define_method(cLSAPI, "puts", lsapi_puts, -1); rb_define_method(cLSAPI, "<<", lsapi_addstr, 1); rb_define_method(cLSAPI, "flush", lsapi_flush, 0); rb_define_method(cLSAPI, "getc", lsapi_getc, 0); /* rb_define_method(cLSAPI, "ungetc", lsapi_ungetc, 1); */ rb_define_method(cLSAPI, "gets", lsapi_gets, 0); //TEST: adding readline function to make irb happy? /*rb_define_method(cLSAPI, "readline", lsapi_gets, 0); */ rb_define_method(cLSAPI, "read", lsapi_read, -1); rb_define_method(cLSAPI, "rewind", lsapi_rewind, 0); rb_define_method(cLSAPI, "each", lsapi_each, 0); rb_define_method(cLSAPI, "eof", lsapi_eof, 0); rb_define_method(cLSAPI, "eof?", lsapi_eof, 0); rb_define_method(cLSAPI, "close", lsapi_close, 0); /* rb_define_method(cLSAPI, "closed?", lsapi_closed, 0); */ rb_define_method(cLSAPI, "binmode", lsapi_binmode, 0); rb_define_method(cLSAPI, "isatty", lsapi_isatty, 0); rb_define_method(cLSAPI, "tty?", lsapi_isatty, 0); rb_define_method(cLSAPI, "sync", lsapi_sync, 0); rb_define_method(cLSAPI, "sync=", lsapi_setsync, 1); rb_define_method(cLSAPI, "reopen", lsapi_reopen, -1 ); s_req = Data_Make_Struct( cLSAPI, lsapi_data, lsapi_mark, free, s_req_data ); s_req_data->req = &g_req; s_req_data->fn_write = LSAPI_Write_r; rb_stdin = rb_stdout = s_req; #if defined( RUBY_VERSION_CODE ) && RUBY_VERSION_CODE < 180 rb_defout = s_req; #endif rb_global_variable(&s_req ); s_req_stderr = Data_Make_Struct( cLSAPI, lsapi_data, lsapi_mark, free, s_stderr_data ); s_stderr_data->req = &g_req; s_stderr_data->fn_write = LSAPI_Write_Stderr_r; rb_stderr = s_req_stderr; rb_global_variable(&s_req_stderr ); /* constant silence hack */ orig_verbose = (VALUE)ruby_verbose; ruby_verbose = Qnil; lsapi_env = rb_hash_new(); clear_env(); /* redefine ENV using a hash table, should be faster than char **environment */ rb_define_global_const("ENV", lsapi_env); rb_define_global_const("STDERR", rb_stderr); ruby_verbose = (VALUE)orig_verbose; return; } PK!7Zw3gems/2.2.0/gems/ruby-lsapi-5.6/ext/lsapi/extconf.rbnu[require 'mkmf' dir_config( 'lsapi' ) if ( have_library( "socket" )) have_library( "nsl" ) end if RUBY_VERSION =~ /1.9/ then $CPPFLAGS += " -DRUBY_19" end if RUBY_VERSION =~ /2/ then $CPPFLAGS += " -DRUBY_2" end create_makefile( "lsapi" ) PK!:gems/2.2.0/gems/ruby-lsapi-5.6/ext/lsapi/.RUBYARCHDIR.timenu[PK!'1gems/2.2.0/gems/ruby-lsapi-5.6/ext/lsapi/lsruby.onu[ELF>@@98 ,.+/*0)1fDHff.HHH+HHODH1f1fATIHUSHcHcLHH=HH[]A\ff.H5SHHtH=Hٺ1[DH=HHHHH=HfHH=Hc5;5H=|6HHHfDf?IH=HH+9M1~+HHcHc5H5~Hfff.@UHSH HHm t]uaHHHtT؃tJ tEHH؉уu5HM u@HHpH}HH[]HD@HuHHMH tHPHpfSHCH[ff.SHHH[ÐHH=HHHH=HHHH=tHHHUSHH=H=HtHH9t H5Ht[1ҿ11HH-H;HHuHuH;HHHH[]fH=HHSHHt$~0H|$H\$H1HH[@H\$HH|$ff.@AWAVAUAATIUSHH:?:@:A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z:[:\:]:^:_:`:a:b:c:e:f:g:h:i:j:k:l:m:n:o:p:q:r:s:t:u:v:w:x:y:z:{:|:}:~::::::::::(::::::no: , 9 7, H = 8H 9H :H ;<H =H >H @,F      !qh "s"t k m n  o  p  uF  ,G  h                $  ( o o  4  9  9               ! "h " 4I 6 7 !I / 1 2  3  4 # : < = ? @ B C E( F0 G8 I@ JH KP L!X O` Ph Qp Rx T' V' W' X' Y' Z' \' ]' _ ` a b c d e f g h i$k'$m'($n'8$oG    G  -h  TG h  9 j)%9qs)G&jG-.P      9   l    **q'||    *55?JJT_jul%:O  !{!O" O" _" o _ 9 o 9  9   ! I 9  9@(":(#:)$: )(: )*: ),: ).  9*req;*env<: =)&->|)@: )B: )C$ )E: )F$ )G~  I K L M NOl)Q  %9)R  A+  ,4{D#-6 :.p7 -8 /0Z*K 1fA2U 2T3/0[&K 1fA2U 2T73D#:4h#<!56v#6#457 7G71sA2Us2T02Q:8A2U 8A2Us2TM8A2Us2Tm8A2Us2TK1A2Us2Tk4N#=&56\#4 7(7(7771A2U 2Ts2Qv2R 96"* 76768A2U 1A2Us457@f7G71sA2T02Q::A8A2U :A:A8A2U :A:B8B2Q08B2U 8+B?2U 2T78+Bc2U 2TA88B{2Q}8EB2U 2T 2Q18RB2U 8_B2T 2Q 2R08kB-2T 2Q 2R08kB^2T 2Q 2R18kB2T 2Q 2R18kB2T 2Q 2R 8kB2T 2Q 2R 8kB%2T 2Q 2R 8kBV2T 2Q 2R18kB2T 2Q 2R08kB2T 2Q 2R08kB2T 2Q 2R08kB2T 2Q 2R 8kBL2T 2Q 2R08kB}2T 2Q 2R08kB2T 2Q 2R08kB2T 2Q 2R08kB 2T 2Q 2R08kBA 2T 2Q 2R08kBr 2T 2Q 2R08kB 2T 2Q 2R08kB 2T 2Q 2R08kB!2T 2Q 2R18kB7!2T 2Q 2R 8xBS!2U12TH8Bx!2Q 2R|8B!2U 8xB!2U12TH8B!2Q 2R|8B!2U :B:B:B:,28BJ"2U 8Bi"2U :B8_B"2T 2Q 2R08_B"2T 2Q 2R08_B #2T 2Q 2R08B(#2U 1A2U ;- <" h#=p$< #=n =p>:#? ?-?9:@ :A0 *K B:go$C :D}) :B:B:BB:$E":UE-:TF:$?:>:$?!:B:#%E":UB:+~%E:UG5 H6B:C;&C:.str :9;& %7M&3) 8(-&2Us:B>:[&?!:By:(CyCy*Cy6:.str{ :.n| -} -~ 46 Q'76:B:C:C:2)8C'2Us $ &8U('2U}8+C'2U|2Qs $ &8+C'2U|2Q} $ &18C2T >J:U(?J :=strL :@M=nN =pO B5 a)C5"I7 -8 -9 -: @; 45;)H6:ECJ0J+K Q)=fd K})=fd =sfn J>:)? :=ch B:)C!::BB:f*Lout!:Lstr,:1,2Us2TT>:*??*Mout6:=i @ :>l: +Maryl#:Moutl.:?l7=tmpn :=io Bc:+CcCc,Loutc8:8QC+2UU2TT1,2UsB?:O,C?C?,Lout?8:.iA 0B :@4-6QN,7?68^Ck,2U~2T38,,2Uv8,,2Uv8,,2Uv8,,2Uv:kC:xCN3:-C3!:Lstr3-:-5$.len6 467-761C2Uv2T<4-69 -7?61C2UsB':#/C':Lc'+:Och) W-*$4M6).7_6P6U768B.2Us:C46+.761C2Uv2T<Q/2TW2Q1:xCB: V/E#:UB:a0C+:Lstr7::C8C/2T58C/2Us8C/2T08C02Us:CR: `0S,::CR: 0S+::CR:-0S,::CR:2S$:Tpid /r1)K 1fA2U 2T5U2 172:,28C12Qs1D2Qs:D:B:A1B2U82Q0V ,2W)$X M2/2)K 1fA2U 2T7YB2Q1R B3S)S3SHSTZarg#G8+BJ32UQ2T R $ &8+Bn32U|2Ts $ &18B2QvRk 5Sk(Sk2SkGSkSZargl"GTpn [leno 8+BF42U|2T~8+Bj42Us2Tv $ &88B42Q|8D42U|2T?8+B42U|2T8+B42U 2T988B42Qw8+B52U|2T8+BA52U 2T<88BZ52Qw8+Bx52U2T}8+B52U 2T<18B2Q}\a 5Sa&$]'D^6W?^-6W<>M6Mobj:>Pk6MxP:>:6Mx:??C>G6Mobj:>6Mx:_ 7WW_\57W\W\`iU7?i_d7Wd!Wd<ab;&7cM&Ub$7c$Ub#87#7#7#d#P#7#7#7#56#e#81fA2U 2T6:B:B8B82U :BY4D2QU2RTb2);fD)96<9H 6D})42) ;56D)4Q):56c)6o)4U7 :7r77f71AD2T12Q 2Rs8MD=:2U 8YDU:2Us8fDm:2Us8B:2Us:sD:D1B2Us8D:2Uv2Ts8D;2U02Ts2Q32R12Xv2Y08D;2Uv8B<;2U 8DT;2Uv8Bs;2U 1D2Uv8D;2T11B2U b(h=7(d$(g1(d>(hI(i(J<H(56$(d1(6>(6I(D$)_ 8U(}<2U 8D<2U|"2Tv2Q 2R18C<2Uv1+C2U|2Qv:C:2)18C2T b)o=7)6)9)=7)jd)18C2T :C:Db*@7*7*7*k*@6*9k6y>76767}61D2U}4k6y>76767}61D2U}9k6y:?76767}6:D9*'l?7*7*7*j'k*@d*8^C?2U 2T51D2U12Tw2Qv8D @2U12Tw2Qv:xCbf*PfA7x*7*7*d*d*if*QAH*H*Hx*56*6*4-6@7?68D@2U 2Qs:C8,A2Us2T~8,6A2Us1^C2U|2T31,2Uslmlwno/tmp/lsapi.XXXXXXno .XXXXXXlm{lnltl lllllll{mlm{lllll  mm L l3 l lllFlllm lll|plll#ll"l*lll}mml^mllmZ m!Hl l9 m% ll m 9la llqmo lsruby.cll&l% : ; 9 I$ >  $ > &I I7I I !I/  : ; 9  : ; 9 I8 : ; 9 <4: ; 9 I?<!4: ;9 I?<: ; 9 I> I: ;9 (   : ;9  : ;9 I8  : ;9  : ;9 I : ;9  : ;9 I8  : ;9 I : ;9 I 8 'I: ;9 I > I: ; 9 ! : ; 9 " : ; 9 I# : ; 9 $ : ; 9 I8%!I/&'I' : ;9 (4: ; 9 I)4: ; 9 I* : ; 9 I8 +4: ; 9 I?,.?: ;9 @B-4: ;9 IB.4: ;9 IB/ U04: ;9 I112B31RB UX YW 41RB UX YW 5 U641B71B8191RB X YW :1;.: ;9 <.: ;9 =4: ;9 I>.: ;9 'I ?: ;9 I@4: ;9 IA B.: ;9 'I@BC: ;9 IBD1RB X YW E: ;9 IF.: ;9 'IG1RB X YW H1I4: ;9 IJ.: ;9 I K.: ;9 I L: ;9 IBM: ;9 IN.: ;9 'I@BO4: ;9 IP1RB UX YW QR.: ; 9 'I@BS: ; 9 IBT4: ; 9 IBU1RB UX Y W V.: ; 9 ' W: ; 9 IX.: ; 9 @BYB1Z: ; 9 IB[4: ; 9 I \.: ; 9 '@B]B1^.: ; 9 'I _.?: ; 9 'I 4`.?: ;9 'I ab.1@Bc1d41e 1Uf41 g41h41 i1UX YW j k41l.?<n: ;9 m.?<n: ; 9 n.?<n: ; o6p.?<nGVpPPP0V0V;0*PP=S;SPSLXPXhShSSh|Sh|   P`oUoU U S P P U S PP j Uj V t Ut V U V U V  U  VP j Tj \ t Tt \ T \  T  \P j Qj S t Qt S Q S Q S  Q  S P 9 \9 < P< q \q t P \  S< C S P ] S v}  v} $0 $+( v} $0 $+(& . P P| U UUu@1U $ &".1 $ &".PQ.1Q@OUO^UUSPTTU/UT/TQ.S./QpUU1pT]TTWpQVQQV0 /SX]S0 s $ &3$}"/I s $ &3$}"@YUY^V^U@QTQSS^VVPHYUY^V^SSPUVUVPsTsSTSPpsTsSSSSUVUUT0?U?PUP_U_pUpUUUUPgP,VSU\UTSTQQRRXXBUBGSSSSETEVTTVTVTV[Q[o\Q\ Q \;R;[]R]R]^R]^[X[XXX X XP_ P_08U8=U EUESQUS ETEVRTV EQEQAEQEQAVRTVASQUSI\\2}VV' 1  1 N V )P)}VVPN VP9S1 S 1   p  U 9 U9 S a Ua S  P C \U a \ C SU a S P P U & S& , U, 6 S6 7 U7 O S + P, 5 P7 O SP U ] U ] UU ] U<UP T V T V T<VP Q Q  Q <Q S s S S    y  y ]   y U ]   yU] U7U  Q 7Q T7V QUQNUNZUZpU QTQNTN]T]pT QQQS!Q!NSNaQacScpQ7Q0UP^=?P?N^QUU,;-HHLQU^^ p#%,VAmtw|N 2'    | C X h p7(PX/P=;=h|| -4;DhQo /opt/alt/ruby22/include/ruby-2.2.0/ruby/usr/include/bits/usr/include/usr/lib/gcc/x86_64-redhat-linux/8/include/usr/include/bits/types/usr/include/sys/usr/include/netinetlsruby.clsapilib.hruby.hstdio2.hstdlib.hstring_fortified.hstddef.htypes.hstruct_FILE.hFILE.hstdio.hsys_errlist.htypes.hstdint-intn.hstdint-uintn.hunistd.hgetopt_core.hmath.hintern.hversion.hlsapidef.htime.hstruct_iovec.herrno.hsockaddr.hsocket.hin.hsignal.hstring.hdefines.hmman.hutil.h  JK?K| #t>iK>KK{KY;./*X **}( // RX} t     0Yf q\:>X. t" u t/u* uZ ^  %gfu Z3 X |t |< tXX uKy 'XX" t  f. f *8u J<t  X    ot@5< t-< ti J [t rJiX    L( ffr X< )9= t; K1 t lQJ/f J LXHKy XX" t L 2  =t<UMtUX&<< ` 0z X .    =Yl  uX[wt Z " h   m gutX  h fY:g< KXfKY sbXtv  SY|X |X<   L/$ eX< z < zt yt5Y|X |.X z  Z rh Y   *xp*&su&qwZ7v -uY 6t|yt ru=KZ/uvpuI==[X=XvXuv0X>f~z t gz t &p(*( uv #G< Y(%[$ rb_mWaitWritable_sys_errlistm_pScriptFileRUBY_Qnilrb_eNoMemError_unused2rb_cBignum_filenorb_cMethodrb_obj_wb_unprotectrb_eSyntaxErrorm_cntUnknownHeadersH_AUTHORIZATIONsockaddr_isoblockSizem_pIovecEndstrcpym_pRespBufPos__uint8_tdmarkRUBY_DATA_FUNCm_pktHeaderrb_eIOErrorm_bytesm_pHeaderrb_data_object_get_shortbufsockaddr_inrb_cFilerb_eSignalunlinklsapi_dataRUBY_T_ARRAYrb_eKeyErroradd_env_rails__environlsapi_addstrsa_datauint16_tm_totalLensin_zerorb_eZeroDivErrorin_port_t_flagslsapi_getscallocm_respPktHeader__off_tcreateTempFiledfreerb_global_variable_lockRUBY_T_UNDEFrb_cStringrb_eEOFErroratoim_pHttpHeaderLSAPI_GetReqBodyRemain_rm_pScriptNamerb_mKernelm_pEnvListrb_output_fsint32_t__fmtsa_familym_specialEnvListSizerb_cModulesockaddr_ns__u6_addr8RUBY_T_FALSErb_funcallrb_cIntegerRUBY_T_FILE_IO_write_endm_iLensockaddrrb_cTrueClasss_addrnameLenLSAPI_Postfork_Childfreerb_data_object_allocrb_fsm_requestMethodOffRUBY_T_COMPLEXrb_eEncCompatErrorruby_special_constsvalLen__stack_chk_failruby_description/builddir/build/BUILD/opt/alt/ruby22/lib64/ruby/gems/2.2.0/gems/ruby-lsapi-5.6/ext/lsapisin_familyRStringm_fdListenMAX_BODYBUF_LENGTHlsapi_bodym_statusm_reqBodyLenrb_eNameErroroptargneedReadrb_eRegexpErrorrb_cBasicObjectRUBY_T_STRUCTrb_cRationalrb_cFloatrb_cClassrb_cStatsys_errlistin_addr_tbasicRUBY_QtrueLSAPI_ReqBodyGetChar_rpKey__uint16_tsin_portRUBY_T_STRINGrb_cContrb_cFalseClassm_flagreadMaxBodyBufLengthm_pQueryString_chainRUBY_T_MODULErb_eArgErrorrb_eInterruptrecurrb_funcallvsockaddr_ununsigned charcapanReadm_cntSpecialEnv_IO_lock_tRUBY_T_ZOMBIEfloatLSAPI_key_value_pairLSAPI_ForeachHeader_rrb_stderrlsapi_eachm_cntHeadersrb_str_catbodyBufRUBY_T_FIXNUMrb_eSecurityErrorisEofBodyBuflsapi_processlsapi_flushoff_tchild_statusRUBY_SYMBOL_FLAGrb_mComparableH_X_FORWARDED_FOR__fprintf_chkm_queryStringOffrb_define_global_functionRUBY_FLONUM_FLAGrb_stdoutH_CONTENT_LENGTHruby_engine_IO_write_ptrrb_output_rslsapi_packet_headerLSAPI_ReadReqBody_rrb_eFatallsapi_http_header_indexsTempFilelineclosesharedlsapi_printfRUBY_T_OBJECTFILEH_COOKIEs_fn_add_envmunmapbodyCurrentLenLSAPI_Accept_Before_Forkrb_cNumerics_req_stderrrb_cHashsize_tH_CONNECTIONrb_rsuint8_tH_CONTENT_TYPERArraylsapi_markm_headerLenperrorlsapi_envruby_release_daterb_cDirsetup_cgi_env_IO_save_baseioveclsapi_eofenvironlsapi_child_statusreadTempFileTemplatesockaddr_x25rb_eLoadErrorsin6_flowinfom_pIovecToWriteorig_stderrm_respHeaderLen_wide_dataH_IF_MATCH__in6_uH_ACC_CHARSETruby_versionorig_stdout__streamsigngamruby_copyrightm_reqBufSizerb_eExceptionrb_yieldadd_env_no_fixRUBY_T_FLOATRUBY_T_CLASSrb_cDataftruncatelsapi_requestrb_cComplexfprintfrb_check_typeRUBY_T_HASHsyncRUBY_T_NODEchdir__ssize_t__srcrb_mErrnolsapi_closeH_IF_RANGEnameOffruby_api_versionstrerrorsa_family_tm_packetLenruby_xcallocreadMorein6_addrisBodyWriteToFilesin6_addrrb_mWaitReadablelsapi_setsyncm_respPktHeaderEndLSAPI_Postfork_Parentrb_check_safe_objfn_add_envlsapi_printrb_eSystemCallErrorrb_intern2stderrm_pHeaderIndexprogram_invocation_short_namerb_safe_levelrb_cUnboundMethodrb_f_sprintf_IO_save_endrb_const_get__nptrLSAPI_InitLSAPI_Requestrb_eScriptErrorrb_tainted_str_newfn_writelsapi_syncm_bufProcessedstdoutreadBodyBufoptoptlsapi_reopenruby_sourcefilerb_mGCrb_eIndexErrorm_httpHeaderLencurPosH_IF_NO_MATCHlsapi_s_acceptpreforkRUBY_T_DATAbuffkeyLen__builtin_strchrLSAPI_Flush_rshort unsigned intsigned chartz_dsttimeGNU C17 8.5.0 20210514 (Red Hat 8.5.0-20) -mtune=generic -m64 -march=x86-64 -g -O2 -fPIC -fexceptions -fstack-protector-strong -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection=full -fplugin=annobinfilenamelsruby.clsapi_header_offset__off64_tsockaddr_eon_IO_read_base_offsetm_pIovecrb_string_value_ptrrb_eFloatDomainError_IO_buf_endm_respInfoopterrrb_define_singleton_methodlsapi_puts_aryrb_cFixnum_modeblkSize_IO_write_basevalueLenInit_lsapirb_eStandardErrorrb_cSymbolrb_argv0H_CACHE_CTRLH_COOKIE2__destrb_cMatchrb_cEncodinglsapi_isattyH_USERAGENTLSAPI_ForeachEnv_rlong intRUBY_T_NONErb_mProcessrb_mFileTestremain_IO_markerrb_cEnumeratorm_pRespBufEnd__builtin___memcpy_chkrb_io_putslsapi_s_postfork_childrb_define_global_constrb_obj_as_stringm_bufReadin_addruint32_tsockaddr_in6__pid_t_IO_codecvtH_RANGERDatastrtolg_reqlong doublerb_cRangeiov_lenlsapi_resp_inforb_cObjectlong unsigned intlsapi_req_headerrb_gc_markinitBodyBufruby_strdupm_headerOffrb_eNotImpError__errno_locationlsapi_s_postfork_parentcharsockaddr_inarpm_pSpecialEnvListsin6_scope_idrb_cIOstdinsin_addrRUBY_T_BIGNUM_IO_buf_baseRUBY_T_RATIONALs_bodyrb_eTypeErrorRBasicrb_eNoMethodError_IO_read_endRUBY_T_ICLASSrb_num2intcLSAPIRUBY_SPECIAL_SHIFT_IO_FILEH_IF_UNMOD_SINCEm_fdRUBY_T_SYMBOLH_HOSTrb_num2char_inline_IO_wide_datastrlen__u6_addr16s_pidselfrb_eSystemExitisAllBodyReadm_respHeaderrb_cThreadm_envListSizem_pAppDataruby_platformsockaddr_ax25rb_eThreadError__pad5rb_str_new_static__u6_addr32rb_cNilClassm_type_markersrb_stdinrb_eStopIterationm_scriptFileOffklassrb_define_classH_VIA_codecvtm_pRespHeaderBufEndH_PRAGMArb_cRandomdoubleruby_sourcelinemkstemplsapi_putcargcssize_tstrcatlsapi_writelsapi_putsorig_stdinRUBY_FIXNUM_FLAGargvrb_eRuntimeErrorm_pRespHeaderBuf__int32_trb_cProc__uint32_tRUBY_IMMEDIATE_MASKrb_hash_asetdataH_REFERERrb_cStructLSAPI_Prefork_Accept_rheap_sys_siglistm_pUnknownHeaderrb_typem_reqStateRUBY_T_NILrb_cTimerb_eSysStackErrorm_pRespBufrb_num2int_inlineprogram_invocation_namerb_cArrayrb_eEncodingErrorrb_ruby_verbose_ptrrb_cBindingrb_intern_id_cacheH_TRANSFER_ENCODINGH_IF_MODIFIED_SINCEsin6_family_freeres_bufRUBY_T_MATCHlong long unsigned intpid_t_cur_columnlsapi_rewinds_reqrb_eRangeErrorm_pRespHeaderBufPoss_stderr_datarb_eval_string_wrapgetpidm_cntEnvRUBY_T_MASKrb_lastline_get_IO_backup_baseH_KEEP_ALIVE__memcpy_chk_IO_read_ptrrb_eMathDomainErrorrb_fix2intLSAPI_GetReqBodyLen_rrb_gc_writebarrier_unprotectrb_exec_recursivegetenv_freeres_listrb_eLocalJumpErrorrb_raise_sys_nerrlsapi_readtimezonepReqlsapi_getcrb_hash_newclear_envrb_cRegexplsapi_binmode_old_offsetstrchrm_pReqBufrb_cNameErrorMesgvalueOffoptindH_ACC_LANGlong long intin6addr_loopback_flags2VALUErb_mMathRUBY_T_TRUEmemmemsockaddr_atruby_value_typem_scriptNameOffH_ACCEPTm_lLastActivelsapi_resp_headersys_nerrin6addr_anym_pRequestMethods_req_dataiov_basem_lReqBegincreateBodyBufm_versionB0m_versionB1rb_str_buf_newrb_define_methodRUBY_FLONUM_MASKruby_patchlevelRUBY_T_REGEXPm_pIovecCurLSAPI_Init_Env_Parametersorig_envm_reqBodyReadRUBY_Qundeflsapi_s_accept_new_connsockaddr_dlunsigned intbodyLensockaddr_ipxrb_default_rsshort intrb_string_value_vtable_offsetpValueenv_copymmaporig_verboserb_mEnumerableRUBY_Qfalseflagstz_minuteswestsys_siglistH_ACC_ENCODINGsin6_portlsapi_eval_string_wrapGCC: (GNU) 8.5.0 20210514 (Red Hat 8.5.0-20)GNUzRx  0D+Xl(BFGA kFBMH^ J  HUgHQ G $ayd(<EDL ] CAJ hELEY HW HW-Hd(EAD  DAJ aED y AE H8FBB E(D0C8GPm 8F0A(B BBBG ,ZAD J ABL 4oAD  AAK pP \FBD C(G0 (D ABBE j (D ABBE | (G DBBA HLhFBB B(A0A8G@ 8D0A(B BBBD CKw oEA J F A 8FBA D(D@ (A ABBA ((EDG0 AAI HTPFBB A(A0 (F BBBH {(F BBB@OFBB A(D0D@  0A(A BBBJ <{FBA A(D0 (A ABBF   - )  ?.Yt/01 5 C _"y @"[0+[h` h)wCpPwmB x-M# < E-_=w0 =^@^`g01IaU1p@//BPg0 PpP p 2p-Jh X  ha;Vd   N  @)N C [P f   h   C O   o O ; <W P f < G @ G  P  p  P p8 Q pO] w ;        p  ` "$%'./0123-4   @ )  3   L S  b Z# x) / 5 ; A G M S Y _  e (k q $w *} f n s y                    1 G V  % + 7 G \ p ()*+,             + 8 N c |        (/CZfrz 1NYk|{"-:Mgw.annobin_lsruby.c.annobin_lsruby.c_end.annobin_lsruby.c.hot.annobin_lsruby.c_end.hot.annobin_lsruby.c.unlikely.annobin_lsruby.c_end.unlikely.annobin_lsruby.c.startup.annobin_lsruby.c_end.startup.annobin_lsruby.c.exit.annobin_lsruby.c_end.exit.annobin_lsapi_process.start.annobin_lsapi_process.endlsapi_process.annobin_lsapi_rewind.start.annobin_lsapi_rewind.endlsapi_rewinds_body.annobin_lsapi_eof.start.annobin_lsapi_eof.endlsapi_eof.annobin_lsapi_binmode.start.annobin_lsapi_binmode.endlsapi_binmode.annobin_lsapi_isatty.start.annobin_lsapi_isatty.endlsapi_isatty.annobin_lsapi_setsync.start.annobin_lsapi_setsync.endlsapi_setsync.annobin_add_env_no_fix.start.annobin_add_env_no_fix.endadd_env_no_fixlsapi_env.annobin_clear_env.start.annobin_clear_env.endclear_envrb_intern_id_cache.13276env_copy.annobin_lsapi_mark.start.annobin_lsapi_mark.endlsapi_mark.annobin_lsapi_flush.start.annobin_lsapi_flush.endlsapi_flush.annobin_lsapi_close.start.annobin_lsapi_close.endlsapi_closeMAX_BODYBUF_LENGTH.annobin_readBodyBuf.start.annobin_readBodyBuf.endreadBodyBuf.annobin_lsapi_write.start.annobin_lsapi_write.endlsapi_write.annobin_lsapi_addstr.start.annobin_lsapi_addstr.endlsapi_addstr.annobin_lsapi_printf.start.annobin_lsapi_printf.endlsapi_printf.annobin_lsapi_s_postfork_parent.start.annobin_lsapi_s_postfork_parent.endlsapi_s_postfork_parents_req.annobin_lsapi_s_postfork_child.start.annobin_lsapi_s_postfork_child.endlsapi_s_postfork_child.annobin_lsapi_s_accept_new_conn.start.annobin_lsapi_s_accept_new_conn.endlsapi_s_accept_new_conn.annobin_lsapi_s_accept.start.annobin_lsapi_s_accept.endlsapi_s_accepts_pidrb_intern_id_cache.13285s_req_data.annobin_lsapi_eval_string_wrap.start.annobin_lsapi_eval_string_wrap.endlsapi_eval_string_wrap.annobin_add_env_rails.start.annobin_add_env_rails.endadd_env_rails.annobin_lsapi_reopen.start.annobin_lsapi_reopen.endlsapi_reopens_req_stderrorig_stderrrb_intern_id_cache.13448.annobin_createBodyBuf.start.annobin_createBodyBuf.endcreateBodyBufsTempFile.annobin_lsapi_read.start.annobin_lsapi_read.endlsapi_read.annobin_lsapi_gets.start.annobin_lsapi_gets.endlsapi_gets.annobin_lsapi_each.start.annobin_lsapi_each.endlsapi_each.annobin_lsapi_getc.start.annobin_lsapi_getc.endlsapi_getc.annobin_lsapi_puts_ary.start.annobin_lsapi_puts_ary.endlsapi_puts_ary.annobin_lsapi_sync.start.annobin_lsapi_sync.endlsapi_sync.annobin_lsapi_putc.start.annobin_lsapi_putc.endlsapi_putc.annobin_lsapi_puts.start.annobin_lsapi_puts.endlsapi_puts.annobin_lsapi_print.start.annobin_lsapi_print.endlsapi_print.annobin_Init_lsapi.start.annobin_Init_lsapi.endrb_intern_id_cache.13464rb_intern_id_cache.13466orig_envcLSAPIs_stderr_data.LC0.LC1.LC7.LC5.LC4.LC6.LC3.LC2.LC8.LC9.LC13.LC11.LC10.LC12.LC14.LC15.LC16.LC17.LC18.LC19.LC56.LC21.LC22.LC26.LC27.LC28.LC29.LC30.LC34.LC35.LC36.LC37.LC38.LC39.LC40.LC41.LC42.LC43.LC44.LC45.LC46.LC47.LC48.LC49.LC50.LC51.LC52.LC53.LC54.LC24.LC20.LC31.LC32.LC33.LC25.LC23.LC55.text.group.text.hot.group.text.unlikely.group.text.startup.group.text.exit.group_GLOBAL_OFFSET_TABLE_g_reqrb_tainted_str_newrb_hash_asetrb_funcallrb_intern2rb_gc_markLSAPI_Flush_rmunmapfreeLSAPI_ReadReqBody_rrb_check_typerb_obj_as_stringrb_f_sprintfLSAPI_Postfork_ParentLSAPI_Postfork_ChildLSAPI_Accept_Before_ForkLSAPI_Prefork_Accept_rgetpids_fn_add_envLSAPI_ForeachHeader_rLSAPI_ForeachEnv_rrb_safe_levelrb_string_value_ptrrb_eval_string_wraprb_string_valuerb_check_safe_objstrchrrb_ruby_verbose_ptrrb_define_global_constrb_funcallvruby_strdupmkstempunlinkftruncatemmapperror__errno_locationstrerror__fprintf_chkrb_str_buf_newrb_str_catrb_num2intrb_fix2intrb_eSecurityErrorrb_raisememmemrb_yieldLSAPI_ReqBodyGetChar_rrb_gc_writebarrier_unprotectrb_io_putsrb_str_new_static__stack_chk_failrb_exec_recursiverb_default_rsrb_output_fsrb_output_rsrb_lastline_getInit_lsapiLSAPI_InitgetenvstrtolstrlenselectLSAPI_Init_Env_Parameterschdirrb_stderrrb_cObjectrb_const_getrb_global_variablerb_define_global_functionrb_define_classrb_define_singleton_methodrb_define_methodruby_xcallocrb_data_object_allocLSAPI_Write_rrb_stdoutrb_stdinLSAPI_Write_Stderr_rrb_hash_new__memcpy_chkH7*t|t'K*Pk*pwD} <8DH*H<%HV;*@G[*`g{**<8DHT T(d4*CRYx}>bpwt(1<tDT`itt|t'BJQXdip  C*D <&.5D? a h<y  < @    * # 4 9  @  g  D L H F LP <X ^ L  L D  L <  L *  6  < D H  L  ' L1 <9 ? Ls *z   D H  D L  * : *A K    18F* 6S* *!`*"#%8DH&''9 @E&U(qxL<&'*)*T&+**, *-).07LS|Z|_/kp||01l2l3l 3'l:?3FlY^3elx}3l3l3l3l3l 3l).35lEJ3Qlaf3ml}3l3l3l3l3l 3l%*31lDI3Plch3w4~*ld5d**6*7*8/4l \5\*9%,;/@HT:[titpu<;< l 2'l7<2ClSX2pu & '2 9  ( L T" ""["[ [h@[Hhlhtwhwww,4`h---= -(=L=T^=^^^ 1@H1l1t1,4/`h//P/PPp P(pLpTp  @ H l t       , 4 N ` h N N  N     (  L  T     O  O O  <@ O H <l <t G < G G  G , 4 p` h p p  p   ; (;     M 1 E) . < C 7L \S #Z 6_ m gr ~    , N  L  t   (' 44 eA N [ ch u       Y  ' n  H \ s+ 8 4 E R 7_ al y E      K J ' c 3 ? [ fg s  h  Q q  #       _  v " ) . ; W j p v ,|   {   ^ a          )  .  W  D   Y  & 3, 2 8 b> : D AJ P W f t  j { # ' |N j[ { # :  |   |( 6 CD d q ~ o  \            N' 4 SA N { [ h u   ^  I  K  u a  D  + 8 E R <_  l y ] o  C  d  1  0 g" D/ #< zI V c p }    c Q   X 6 "   m& 3 @ M  Z g t 5       Y  "  N2 N ` Z i f 5r ~ 4   R  f  +   d     W  ?   r " }( . 4 ~: @ P q\ #i v c o           - : uH NU L b L : }   V       " / < BU b o |       I :      ' 4 A QN {[ h u     +      5     $+ 8 NE R _ T l vy   $  *   @ *  6 k w   x    C + X+ R8 E R _ }  +      L  ! 6 PK  r   + (7 C z  J    (  p m   % 2; HQ _ ^xg t} y @  y Zp  5h+ 8A N`W dXm z  D    @ f@ L   &"9 E I X A\ ;a m q v   1  y1 @ p( p1 5 > 1B +KT e ~i zn1+ +&=/ < E I Rh[ l 6p 2y u} q@    I1Y+4 PE I Ngt11-Pct11 @Um(d|11$1*1f.$C1nPP_Ct1s@b1yp1 1 &;1HWl1y@1 1 21 P N11>Mjb1o ~10101 ` & 13 `B W 1d ps  1 p . 1 @ M 1 !l!1S(! 8!{T!i!0y!!!!!0!?!!D"L"X"f,"yA"1K"`"1Lj"w"$"11"p"@"1G"P"\"1V"0 ##1)#:#1E# 4O# i# # } # E# # # # ## f #`$ $ >!$ :*$t3$tH$tU$b$p$  |$$ $ 5 $ I $ $ $ $ $`% $% 0%0G% Z%4c%4% % % % }% w% % % % % % & & & .& <& zN& \& h&P & E& N& :& & 8& (& & & & & & o& e& & & & o' ` ' \'| ' `.' 2' 7' D' R'k _' l' '& '\ ' ' 'm( ( 2( V( j b(y( ( ( ( ( ( ) ( % ( o( ( ( ( ( ( (( @ )) $%) 3) UR) 4~) ) ) ) ?)@) ) ) )T)  *-* 9 1* 3 B* F* K*g* ey* E* * p* * > + +.+ E:+ >+ C+ O+ S+ d+ ? h+ 9 m++(+ W +p+ E+ + + + + + a + W , , , p+,/4, E, = I, 9 O,l, ,&,X,u,,, Y,@ - - - +- /- 4- @- 0D- ,U- hY- fb-Hk- |- - -Z-^- - - -- :-P-  . . . n". f6. B. F. O.pX. i. m. v.. P. E. A.... . . {../$/ 10/G/ W/ c/z/ / / / / /////00 y(00?0 J0 N0 S0Da0 7l0P0 0 X0 T0d0 0p0 0 0 00 0 1 1 1 *1 .1 31 <1 I1R1c11w1,1 01 G1 E111G1V1111#2 2 -2 42K2 T2 a2j2!{212 2 22 2 p2 j2 2 2 2 2 2 2 3 O 3 K3  3 %3K3o33 33 3 3 3 3 P3 >3 3 3 3 3 3 4 4 ~4 4 )4fG4tk444 4541)4H4X5m3513B5[5y55155 A 505 5 }5 y5=5 6 6 T!6 .6 FN6 l6 l6 (6 p6 56 6 R6 n6 V 7 7 n)7 V 67 H7 V7  g7 y s7 77p7 7 7 7 <7 28 8 8A8 `(8 ,8 58 098 (B8 F8 K8 `T8 X8 a8 j8{81S8F8N8h81L8m8899A9J9c9l9 y9 9 89 099 9 9 9 9 ,9 &9 9 09 w9 u9 9 9 :1Z: 4:@>:V:*n:2:::' :C:e;};3;1b=;U;= j;1xt;D ;;;1; ; ; < < < K< E-< 1< :< >< G< P< e< ~< <1< <= <: <v < =m= := >= G= K= T=7 ]=7 z= ~= =7 =O =m= = =P = = = >  > g> _> #> ,> 5> R> 3 V> / _> w c> s l> p> u> > > > > > !> !> .!> *!> >> ? f!? d!? !? !$? !(? !-???H?e? !i? !r? 1"v? -"? n"? j"??!?1?5? @< @ ;@ "?@ "H@ #L@ #U@ #Y@ x#l@ @ @ #$@ !$@ Q$@ G$@@ @ $@ $@@P @AA7A:RAbgA w kA w tA xA A A A 3A A A A A A  A  A A A A A F A F B B B @B @B I#B I,B - 0B - 9B =B FB JB SB WB `B dB lB pB yB }B B B B B B B B NB NB X B X B B B B B B B B B OB OC I C IC C C {#C {,C 0C 9C =C FC 0JC 0RC VC _C hcC hlC pC yC #}C #C  C  C eC eC C C C C qC qC : C : C $ C $ C C C C C C D D D D D 3 D 3(D ),D )5D D9D DBD FD ND @RD @ZD 2^D 2gD rkD rtD hxD hD D D D D D D uD uD D D D D D D jD jD ,D ,E E  AI A@@ A@< LM @k L| @1ZF D^ D Dy! D ~ 4H0\`pp0@ `(@@l0Pp< P P   P @,PX p.symtab.strtab.shstrtab.rela.text.data.bss.rela.gnu.build.attributes.text.hot.rela.gnu.build.attributes.hot.text.unlikely.rela.gnu.build.attributes.unlikely.text.startup.rela.gnu.build.attributes.startup.text.exit.rela.gnu.build.attributes.exit.rodata.str1.1.rodata.str1.8.rela.data.rel.local.rodata.cst16.rela.debug_info.debug_abbrev.rela.debug_loc.rela.debug_aranges.debug_ranges.rela.debug_line.debug_str.comment.text.hot.zzz.text.unlikely.zzz.text.startup.zzz.text.exit.zzz.note.GNU-stack.note.gnu.property.rela.eh_frame.group/@6/T6/l6/6/6 ;@x $6&,  6 01@0 6 LP([P(V@ =06 u * *@P=06++@=06--@=062/2x1M'1"@=671J1 EE@={6Vvi}$d@h6 y0t@06"ޢިU@ 6%030Q.uL   %  @8647 `P6PK! *331gems/2.2.0/gems/ruby-lsapi-5.6/ext/lsapi/lsapi.sonuȯELF>U@@,@8 @HH   ! !P ( ( !( !  888$$((( Std((( PtdQtdRtd  ! !GNU3u ApdC H‚3@(L`qCSlP*fRn}'3qѮl>&Sɶ ܮʼnSO`[is|&߱RD/y7řkՊ eY&09=By:%/=ejOzJ6'l#mNULCB1{!\$O#W23S=apbU06aD7jp#7ĴDIΊ=\4yݾCEкQuo rSѮIo|q%h6 󝵛 ' =qX[u  f   U ysOzu    E [MQ j E k & q !  1 RT s  @ +r  u >[  = & cH  'I   0x* n` m K :2p -, 2B F"X  EN   k @ @ 0~F sD :  { 5 wiw  `z! [ ' X! V pZ\ g Pp  o Џ1 r Y ` r9   tl {j PW ~ `- t]   0p sY @p  5 o y$ l! u U V E pw sS o7 pM p(    Ж  }F psJ pz `! B P   ![ `g  @ (! l @6 `p @  `!__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizecompareValueLocationset_skip_writesigactionsigemptyset__stack_chk_failreallocfcntlacceptsetsockoptmmapmemsetsetsidread__errno_locationclosewritevkillgetppid__ctype_b_locstrncpystrchrstrcasecmpstrtolgetaddrinfomemcpyfreeaddrinfoinet_addrLSAPI_Log__vfprintf_chk__snprintf_chkgetuid__fprintf_chkgettimeofdaylocaltime_rwaitpidforksystemexitlsapi_perrorstrerrorLSAPI_is_suEXEC_DaemonLSAPI_StopLSAPI_IsRunningLSAPI_Register_Pgrp_Timer_CallbackLSAPI_InitRequestmallocgetpeernamedup2LSAPI_Initgeteuidsignalg_reqdlopendlsymLSAPI_Is_Listen_rLSAPI_Is_ListenLSAPI_Reset_rLSAPI_Release_rfreeLSAPI_GetHeader_rLSAPI_ReqBodyGetChar_rLSAPI_ReqBodyGetLine_rmemchrmemmoveLSAPI_ReadReqBody_rFlush_RespBuf_rLSAPI_GetEnv_rstrcmp__ctype_toupper_locLSAPI_ForeachOrgHeader_rqsortLSAPI_ForeachHeader_rLSAPI_ForeachEnv_rLSAPI_ForeachSpecialEnv_rLSAPI_FinalizeRespHeaders_rLSAPI_Flush_rLSAPI_Write_Stderr_rgetpidgetcwdmemccpy__realpath_chkLSAPI_Finish_rLSAPI_End_Response_rLSAPI_Write_rLSAPI_sendfile_rsendfileLSAPI_AppendRespHeader2_rstrlenLSAPI_AppendRespHeader_rLSAPI_CreateListenSock2socketbindlistenunlinkLSAPI_ParseSockAddrLSAPI_CreateListenSockLSAPI_Init_Prefork_ServersetpgidsysconfLSAPI_Set_Server_fdLSAPI_reset_server_stateis_enough_free_memLSAPI_Postfork_ChildLSAPI_Postfork_ParenttimeLSAPI_Accept_Before_Fork__fdelt_chkusleepsched_yieldLSAPI_Set_Max_ReqsLSAPI_Set_Max_IdleLSAPI_Set_Max_ChildrenLSAPI_Set_Extra_ChildrenLSAPI_Set_Max_Process_TimeLSAPI_Set_Max_Idle_ChildrenLSAPI_Set_Server_Max_Idle_SecsLSAPI_Set_Slow_Req_MsecsLSAPI_Get_Slow_Req_MsecsLSAPI_No_Check_ppidLSAPI_Get_ppidLSAPI_Init_Env_Parametersgetenvgetpwnamdlerrorsetrlimit__fxstatsetreuidLSAPI_ErrResponse_rlsapi_MD5Initlsapi_MD5Updatelsapi_MD5FinalgetpwuidsetgidsetgroupssetuidstrtollprctlinitgroupsLSAPI_Accept_rLSAPI_Prefork_Accept_rsigaddsetsigprocmaskLSAPI_Set_Restored_Parent_PidLSAPI_Inc_Req_Processedselectrb_tainted_str_newrb_hash_asetrb_funcallrb_intern2rb_gc_markmunmaprb_check_typerb_obj_as_stringrb_f_sprintfs_fn_add_envrb_safe_levelrb_string_value_ptrrb_eval_string_wraprb_string_valuerb_check_safe_objrb_ruby_verbose_ptrrb_define_global_constrb_funcallvruby_strdupmkstempftruncaterb_str_buf_newrb_str_catrb_num2intrb_fix2intrb_eSecurityErrorrb_raisememmemrb_yieldrb_gc_writebarrier_unprotectrb_io_putsrb_str_new_staticrb_exec_recursiverb_default_rsrb_output_fsrb_output_rsrb_lastline_getInit_lsapichdirrb_stderrrb_cObjectrb_const_getrb_global_variablerb_define_global_functionrb_define_classrb_define_singleton_methodrb_define_methodruby_xcallocrb_data_object_allocrb_stdoutrb_stdinrb_hash_new__memcpy_chklibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6__environ_edata__bss_start_endGLIBC_2.2.5GLIBC_2.14GLIBC_2.15GLIBC_2.4GLIBC_2.3.4GLIBC_2.3/opt/alt/ruby22/lib64:/opt/alt/openssl/lib64   C  ui 3  ui  f   ii  ti  ui  ii   !V !@V ! !@ !QH !P !X !` !h !p !x ! ! ! ! ! ! ! ! ! ! !& !. !3 !: !B !M ![ !m !v ! ! !( !0 !8 !@ !` !h !p !x ! ! !/ !? !L ![ !g !t !~ ! ! ! ! ! ! ! ! ! !) !4 !I !R!X!X!i!y(!!0!D#!X!H!P!X!`!h!p!x! !#!5!!?!K!M!U!Y8!Y!Z!!!p!}!!! !(!0!8!@!H!P!X!`!h!p! x! ! ! ! !!!!!!!!!!!!!!!!! !(!0!8!@!H!P!X!!`!"h!$p!%x!!&!'!(!!)!*!!+!,!!!!-!.!/!0!!!! !1(!20!38!@!4H!P!X!6`!7h!8p!9x!:!;!<!=!@!A!B!C!!D!E!F!G!H!I!!J!!L!N!O !P(!Q0!R8!@!SH!TP!X!V`!h!Wp!Xx![!\!]!^!_!`!a!b!!c!!d!e!f!g!h!i!j!k!l! !m(!n0!o8!@!H!qP!rX!s`!th!up!x!v!w!y!z!{!|!~!!!!!!!!!!!!!! !(!0!8!@!H!P!X!`!h!p!HHq HtH5 % hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?h@hAhBhChDhEhFhGqhHahIQhJAhK1hL!hMhNhOhPhQhRhShThUhVhWqhXahYQhZAh[1h\!h]h^h_h`hahbhchdhehfhgqhhahiQhjAhk1hl!hmhnhohphqhrhshthuhvhwqhxahyQhzAh{1h|!h}h~hhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D%ݿ D%տ D%Ϳ D%ſ D% D% D% D% DH= H H9tHf Ht H=Y H5R H)HHH?HHtH HtfD= u+UH= Ht H= yd ]wff.> ÐHGH+FHcAVIH@AUATL$USHtQHHtIHIL9r 0HI9v'KHSMsH;Յ[]A\A]A^[D]A\A]A^øff.f=N D ÐO AWDD_AVAUATUSD6^nAxj׋G3G D!3G V\$ЋW^$DD1\$!3WAʋN Fp $E‰L$A1A1DD^ !D1G;νD\$DEDVDT$A!A1EE|A 1AD!E1DD*ƇGD1D!A1A1DDN DL$E F0D!DnA1D1DGFEDf Dd$D^(A!A1EEؘiA 1AD!1DDDʋ^0D1D!A1DE [D 1!D1DDN,A1DL$G\EA!Df8A1ED"kA 1AD!1DDN4EqDD1!1DE CyD 1!D1DDV<1G!I!1DDD$ Eb%1!1DDD$E@@1!1DDD$ EQZ^&1!1DE6Ƕ1!1DD]/։ 1!1DESD1!1DE ؉ 1!1DDD$E01!1DDD$ E!1!1DE7É1!1DDD$ E 1!1DDD$A0ZEAA1A!A1AA㩉A AD1!1t$DD1!A ogD1 1D!FL*1DD$Ή1AA!B9A1DD$A AD1D$qDD11‹D$ 0"amD1G 81Ɖ11DDD$ ED꾤11DDD$AKAA1A5`KA1AЉApA 1AD1D1D1A ~(D 1G'111DDD$ A0AA1A1AЋT$A2A1D1֋T$ 9ىDD11D11C|A A1A1AD$A0eVĉA1D1AD")Dt$ D D1A *CDG# 1  1DD9Ή 1DDY[e\$  1DE Dt$ щ1DE3}D\$  1DDD$E] 1DEO~oA AD 1DE ,DT$ A1ADE6CDt$ AN 1A~SADEAA A1A5:ADA AD 1Љ3*\$D D1DFӆ[ ]A\A]A^ 1։ 1DƉA4A_ OW GOW ATI1USHdH%(H$1HHH<$t)H$dH3%(u tIfH)I~HPHcH9vHIH)Hx t sE)EAOr1kS5 t-=' t+1Tu[81[@9[ÐAVAUATUHSHHPdH%(H$H1H fDHHDB uLd$@HLDD$@Ƅ$? TH=7 18tI DH=Ab HcH54bHHV [ÉD1?H= @HW(Hw`HLJHHLJ0HHWHVHWHWHWHWH)81HSHHHtHHtHHtH{@Ht1[fDHtGwBLHcAT4t/HcApHHH€:t HH1ff.fHtPtJSHcH;}HSHH[~ Hcи[ÃAWAVAUATUSHZHHHD$H:GH%HIHIIILfDA)HcHL9HcIOIvI HLHtML)HLHXHHAIA$D)EH[]A\A]A^A_LHHHAL|$II)AM?DLLHcH~A-H1|v@AVAUATUSHIHHHHHH+E1HH9HcHO؋)HH~)H9HwHHNHHIELL)Ht6Eu@HHDZHu4?8u 0 uMt-M[L]A\A]A^H~IHH)uIDHO(HW8HLJLSH)ʍBHGpH0HpH@Hwp~HcHHH HPHO8HGpAWAVAUATUSHHHT$HHH<$IH=i]HcB$HH@H,H9rZf.HH9vGH3LLuHCH[]A\A]A^A_HD$L9IM9f.1H[]A\A]A^A_H$1L= L@Al4tI4LHHuHD$HcP 1~H $HLMtM9sHH$ID$HD$@IcMIcmH,$L| L9)A\$);H8HD$'-t _HHI9tHU:t8IcU IcEH$H€:H $HcHcAVHH€:@AVAUATUSL$HH $L9uHdH%(H$@1HHHHHHE1L LhfHHcHcT4t7 qHM HIcAHL EHT DT t HHuHHcP HHL L9IcIHLfHH I9HcHHc0AHLcP IHcHHBDBHJH H2JAuH ̔ L$DIH Ic L^EtaE1@AI E9~CAMIUIAuI}ӅH$@dH3%(u6H@[]A\A]A^D1@IcU ff.AWAVAUATUSHXHt$ HT$dH%(H$H1HIH1E1L-mgHL%C HHHcHcT4t/HHAAtI@4 +HH5X1rrDH߹SfDHH5\X1CHtvt]SHtCuWHC(H9C8tHHCpHҏ HHHH@HCp@H1[@c뢸ff.Huu1fSHtRubHC(H9C8tH HCpH5 HHHH@HCpH{:1[1HO@H9OPv닸AWAVAUATUSHHH|I֨,aHHt$H>L{8IHC0L)H9>Lt$L+{(LA@LLfIM)MK H@σLSLCpNIHDI0HI@HKpM~HC(MxIH E1I@HC8HL1HMLIHHKpH9eH-thILM)MUI9t H tDL+t$HL[]A\A]A^A_DM@@M)( IHt$HLHk8f.HAVLAUIATIUSHu\H߉;AD${LǃLSHu0{L[L]A\A]A^+[H]A\A]A^Hff.AWAVAUATUSHHHHD$ 0xIHIHLc\CHcT t u(HDLcLH t tLÅ~6HcAT t u#H@Å~ALH t tE<AG=I|$PHHTI9T$Hs7HI+t$@L2%))I|$PLHHcAMt$PHLIFID$PA:I|$P]MD$PII@ID$PAIc$0fET8HЃA$0D$ H[]A\A]A^A_D$ ff.H HB=0AUATUSHcHfDA< t< uH؅uH[]A\A]IHPHHDI9D$Hs3HI+t$@L2%))tQI|$PHHA0I\$PHCID$PIc$0fET8HЃA$0H1[]A\A]øSDAUATAUHSH?dH%(HD$1D$ff t1fHL$dH3 %(H[]A\A]ÐA1ҾÃtʼnǺ1ԿHL$Aߺ蘿u#DHuDo謾߻D H:DeOAkDH}An聾}N3Htff.USHdH%(H$1HHu/HeH$dH3%(uHĘ[]褿@1H=r tAUATA'USH 'DNuDq H@AHH HHtH- D 9Ɖlj UDk H DcEuSH8dH%(H$(1-HtH H= H=O>HE1 H螹H=I>ڳHt 1Hvh H=5>贳HHt 1HMIAąWE1H=>耳Ht 1Hϊ H=>ZHtHǺ 1OH==3HЊ H==HtHǺ 1谸9ĶH==H1 HxOH==賲HtHǺ 1OشH==茲HtHǺ 1(H==eHtHǺ 1ʺH=r=>HtHǺ 1ڷ胲H=b=Ht=H=`=Ht 1H蝷 _H=H=ӱHt 1Hoʼn D^ P B EH==ٶH=" u P 5 H==SH 1HՈ …tՈ Hu HHHHD L=L =L=C HLt@HֹL€D t%HtAHHt9HLuHfDHJHHJHuHHu1ۉH$(dH3%(H8[]A\A]fDփ H膲D~( H=.9xHHiHǺ11諵ÃHT$ƿD$(?H5߄ رHWH` Htxc@dx@D  E9Dk E)ZfH=m8褬> HK] 2 u $ '  ' )fՅtbHà H-DHH5?1SAHc螲L%g HHu asÅt=s B u L 5R `HH50?uHH5>1U HH5>Fff.AVIAUEATIUHSHt4Hu!(fDHHtHLWH]HuMtEL[1]A\A]A^ÐIcLLH#EgHGHHܺvT2HGAWAVAAUIATUHoSH1HGO@ƉWDW?t;AĉDHH|@D)A9rhAGt4LL$HL9A?vWEfAIIIH޺@HH@HLL9uA?DLHH[]A\A]A^A_鼱IATLfUHSFH?LHz?)ƒw=t19rLHfCAD$AD$ ID$071)HCHLHCP?o H{1HMHHCPH)KXH[]A\ff.fAWAVAUATUSHdH%(H$1Ht^ IAfMcg IoA_@LH3HuM8u = | uٽH$dH3 %( HĨ[]A\A]A^A_f~AAuIALJf8LS|xr@tPHf@HPXN MgA;G ZA9~uEo)HHcIHLD"Hu$85z uAMgA9ID$,HD$HcIIDhAh(A9}A /HcIH4@HEHAIIh$A9}A HcIH4@HHAIIHl$p(ILHIILp$hMIc@o9gIcP[9SIcpG9?IcH39+IHHHHIHT$IIc@ H)IHHIHHHIHIIcHIHHHD$I9E1DL4t9dfH H IGAG IPH f@ f@ HHP P H HPPHHPPHHPPHHPPf@f@f@HH#PP H H'P#P$H$H+P'P(f@f@!f@%H(P+f@)I1 fDIHcȋL4t#fBIHT4 rfB@2JHHuMIcP IHHH9pH@ppHH@ppHH@ppHH@ppHH@ppHH@ppHH@ppHH@pHH9wMApIbIc@ IH0*z ALJt`y y Ay 1LHc诩IHIGAo IuID%y D-y B(AA1IcH4IILI 9HqH=G. IJDB(9xHqH=". XIJB($AD$IKAzHL$;Mbfox Lt$ LAoL$AT$Ml$)$蘪 LLHL$LHLLH$ID$H$I3L$H1H D$$Dl$EDDl$âH=4x IHIDw MH=w t"LDLŃP|$gEt$A9uHt$~D Ń5w $A?D5w t AH5)LHtHHrw f)Ww #AH5i 1H@H5+19LH 1HoIH531H531ݨD%v v DD$H=uv IHtZEW7E1111ݤH=3H5*1`E|$蟦M2;|$wE1H5*LuI}臧Ń1H5*LKfD=u -u {u ED$AIFH5)1膧HH)H51H1a1H5*L ܟ1H532LA#LH 3Hp 臣1H5)Laff.AVAUATUSHdH%(H$1D$ HHѡ ;1Ll$Ld$Lt$ HklBp {ul;LLD$CHt Ht@H4t Ht{1f|$=s u|H4tH舴H@o d1H$dH3 %(u}HĠ[]A\A]A^Ds {H5e ,Hfы{LA՜;۝ff.AWAVAUATUSHD=4s dH%(H$1ExH H-ir H}r ;.e DH-s Ht 1AHEDrn EH$L|$PDcA:E1AfD 5n ED}r EtHr Ht @fLH1HIcgDHD$PHD$XA ?)ѺHH D9#11A|$MHm D9#Hr Ht @D9#d AD91葳fH$dH34%(' H[]A\A]A^A_KL$HDŽ$hMl$H$L謞H$LHHD$@AHLDŽ$hH$eH$LHHD$08PH$LHHD$8+H$`L HHD$(H$ LHHD$HəADžHD$PE1Ll$`HD$H$HD$H$`HD$fD%o EHo Ht H=k 1tIL9t<1ձL5EDu EME1V&Hk LH1HHc}赚}LD$LHD$PHD$X ?)ѺH1H T`1Fk  8Ht$(1ҿ }x=_5n tHo Ht @f,D9# DCHn Ht@Hn HtDc1DN j =m {H5` HH!n Ht*HQn HB(@H1n Ht@Hm H@苖8B-DAD9M=Ri 蝟=6i Hqm HtDHPm Ht A9H1m HtD҉T$$DE ~:E~5WT$$A軙A謙AuDE UM D9vHl AHtDH5'1覞D$W0 H=!GT$fD}蠩C1mH|$IH|$HT$Ht$1P61E Mt AMgMg{E1CCHt$1ҿH=)'f; >fDD$$O0d T$$WH=T$7T$fDD#AfDNk RDf EBHk H29f {H5e] 蠔H{wH=C(F茓H=(0莖MAH… H{H֘ %d Bad request header - ERROR#1 ParseRequest error SUEXEC_AUTHSUEXEC_UGIDLSAPI: setgid()LSAPI: initgroups()LSAPI: setgroups()LSAPI: setuid()Bad request header - ERROR#2 lsapi_accept() errorPragma: no-cacheRetry-After: 60Content-Type: text/htmlDEBUGNOTICEWARNERRORCRITFATALAcceptAccept-CharsetAccept-EncodingAccept-LanguageAuthorizationConnectionContent-TypeContent-LengthCookieCookie2HostPragmaRefererUser-AgentCache-ControlIf-Modified-SinceIf-MatchIf-None-MatchIf-RangeIf-Unmodified-SinceKeep-AliveX-Forwarded-ForViaTransfer-EncodingHTTP_ACCEPTHTTP_ACCEPT_CHARSETHTTP_ACCEPT_ENCODINGHTTP_ACCEPT_LANGUAGEHTTP_AUTHORIZATIONHTTP_CONNECTIONCONTENT_TYPECONTENT_LENGTHHTTP_COOKIEHTTP_COOKIE2HTTP_HOSTHTTP_PRAGMAHTTP_REFERERHTTP_USER_AGENTHTTP_CACHE_CONTROLHTTP_IF_MODIFIED_SINCEHTTP_IF_MATCHHTTP_IF_NONE_MATCHHTTP_IF_RANGEHTTP_IF_UNMODIFIED_SINCEHTTP_KEEP_ALIVEHTTP_RANGEHTTP_X_FORWARDED_FORHTTP_VIAHTTP_TRANSFER_ENCODING%04d-%02d-%02d %02d:%02d:%02d.%06d Child process with pid: %d was killed by signal: %d, core dumped: %s Possible runaway process, UID: %d, PPID: %d, PID: %d, reqCount: %d, process time: %ld, checkpoint time: %ld, start time: %ld gdb --batch -ex "attach %d" -ex "set height 0" -ex "bt" >&2;PATH=$PATH:/usr/sbin lsof -p %d >&2Force killing runaway process PID: %d with SIGKILL Killing runaway process PID: %d with SIGTERM Children tracking is wrong: Cur Children: %d, count: %d, idle: %d, dying: %d LSAPI: LVE jail(%d) result: %d, error: %s ! Invalid custom stderr log pathFailed to open custom stderr logCan't set signal handler for SIGCHILDReached max children process limit: %d, extra: %d, current: %d, busy: %d, please increase LSAPI_CHILDREN. LSAPI: failed to open secret file: %s! LSAPI: failed to check state of file: %s! LSAPI: file permission check failure: %s LSAPI: failed to read secret from secret file: %s LSAPI: Unable to initialize LVERequest header does match total size, total: %d, real: %ld LSAPI: missing SUEXEC_UGID env, use default user! LSAPI: SUEXEC_AUTH authentication failed, use default user! LSAPI: lve_enter() failure, reached resource limit.prctl: Failed to set dumpable, core dump may not be available!sigprocmask(SIG_BLOCK) to block SIGCHLDsigprocmask( SIG_SETMASK ) to restore SIGMASK in childfork() failed, please increase process limitsigprocmask( SIG_SETMASK ) to restore SIGMASKCache-Control: private, no-cache, no-store, must-revalidate, max-age=0PID 508 Resource Limit Is Reached

    Resource Limit Is Reached

    The website is temporarily unable to service your request as it exceeded resource limit. Please try again later.
              replacesrandQUERY_STRINGREQUEST_URIPATH_INFOREQUEST_PATHSCRIPT_NAMESTDERRreopenftruncate() failed. File mapping failed. Memory calloc error[...]nilLSAPI_MAX_BODYBUF_LENGTHLSAPI_TEMPFILEXXXXXXRACK_ROOTchdir()to_hashCGI/1.2eval_string_wrapLSAPIacceptaccept_new_connectionpostfork_childpostfork_parentprocessputcwriteprintprintfputs<<flushgetcgetsreadrewindeacheofeof?closebinmodeisattytty?syncsync=RACK_ENVInsecure: operation on untainted IOGATEWAY_Irewindable_input.rbNTERFACE/tmp/lsapi.XXXXX;z0Ze p8pLp`pt0q@qPqx0@ydyxz`z{|$}t} ~<`d$PpH p 0 @ P   0 D `X t  p 8 `L ЗP d px    h 0 p (tP0Pp@<`PdxpЯ,@T0hP|pа4`tP0L 0$P8L`tP``0\0xPp ,@xp@@p`p@HzRx $0V FJ w?:*3$"D` \@lp  AABG EO D  A @ ThY|JED4S ]Ph H XAHlFBB B(A0A8LP 8A0A(B BBBH < FBB A(A0 (D BBBI \i`p FBB B(A0A8DP~ 8A0A(B BBBA k 8A0A(B BBBH Lȇ$FBB A(A0H Q D 0A(A BBBH L$FBB B(A0A8G 8A0A(B BBBF txFF$|nCXJLTlFBB B(A0A8DA 8A0A(B BBBA `( tBBB B(A0A8G I K I L N N w 8A0A(B BBBI 0 BMD GL  AABA < =BAA G L@I@U  AABG $ TWEHG ( ag H SHL FBB B(A0A8DPS 8D0A(B BBBF T bIE D(C0P (F BBBM Q(H BBBAH |FBB B(A0A8DP 8A0A(B BBBA T< CBA A(G0` (A ABBD  (C ABBA J8 ؖ-FBD D(D@T (A ABBB  ̗( ؗlECGF AAI L !cBG A(D0 (A ABBE XD0` t Z T10 pFAA G@7  AABF  @LsL FBB B(A0A8G 8A0A(B BBBG < P d x   ̞ ؞   ܞ؞ <Ԟ FBA K(G (A ABBG <XFEE D(D0M (C BBBB (HFBH E(A0E8I@ 8A0A(B BBBE (FED ABH$H BBB B(A0A8G 8A0A(B BBBJ DpܴFBB A(A0G 0A(A BBBF LD FBB B(A0A8G  8A0A(B BBBA 4 H\+p,($( BFGA kFBDMH^ J x tHU |gHQ G <ayd(T(EDL ] CAJ ELEY HW HW-Hd(EAD  DAJ ,aED y AE HPFBB E(D0C8GPm 8F0A(B BBBG ,ZAD J ABL 40oAD  AAK pP \FBD C(G0 (D ABBE j (D ABBE | (G DBBA HdhFBB B(A0A8G@ 8D0A(B BBBD CKw PoEA J F A 8FBA D(D@ (A ABBA ,P(@LEDG0 AAI HlPFBB A(A0 (F BBBH {(F BBB@OFBB A(D0D@  0A(A BBBJ 8{FBA A(D0 (A ABBF GNUV@V !Q&.3:BM[mv/?L[gt~)4IR$ 3 C N \ f  @ l ! !o`  ! 0x' o&oo%oD( !P@`@p@@@@@@@@@AA A0A@APA`ApAAAAAAAAABB B0B@BPB`BpBBBBBBBBBCC C0C@CPC`CpCCCCCCCCCDD D0D@DPD`DpDDDDDDDDDEE E0E@EPE`EpEEEEEEEEEFF F0F@FPF`FpFFFFFFFFFGG G0G@GPG`GpGGGGGGGGGHH H0H@HPH`HpHHHHHHHHHII I0I@IPI`IpIIIIIIIIIJJ J0J@JPJ`JpJJJJJJJJJK,LSLSLSLSXXiy!D#!GA$3a1 @y GA$3p1113V$GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA$3p11130kGA*GA$annobin gcc 8.5.0 20210514GA$plugin name: annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFYV:GA+GLIBCXX_ASSERTIONSlsapi.so-5.6-1.el8.x86_64.debug7zXZִF!t/O1]?Eh=ڊ2Na8_~ *~, 4?}8P4H3.R/qFvk-B3kI89N?{gÏ"-ndcLgPr/? Ҽhc1*6j[|29 ]WtuÊMmv#.-y"l*(~:nmv(Bo)I6qDpyHN7Q ڦ?r&j86K:4Kđ2̙U٠jŸ:o.0?v #K$f|Wj.'eU~R̛ǧG䃶B~>KZ`z]/(rNOnLC i1)[t {_;Ƽ@vigrR׹+nx%.5pv#kWM`T$@ƠB9uy@9/TޘF8~qB'^/42eGUrx&l8i;uUiv}I,deU)Q.Ml_rz\$/Hك dˇ Ebqj Wgtz:A0tW]zֺV aOBDo\-&!&)LlQ WY%EC(٘v r$h t2QchKdtbӲ79U$@o:䪯'SyL!Cq[Uf<4f%4VCim1;is"&j6 )-v<+=d>GRnW@ B,{#ve C2l'L4p _3YM)eG+tg]MQPsUwl/?yZK$~:DF BHւs4y(\&U?Z3~\]H xŎ 60&<< Ln{ЧaxD27EF}yR*U3頌ԇg?)~#/*3rk UG$wJL$z-I t^79,b !F"! W]]y,rj-} DuÜc{O7M5x?bK' ؛|:޾?Ut^^ iD$UU #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "lsapilib.h" #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) #include #endif #if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) \ || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) #include #endif #include #ifndef uint32 #define uint32 uint32_t #endif struct lsapi_MD5Context { uint32 buf[4]; uint32 bits[2]; unsigned char in[64]; }; void lsapi_MD5Init(struct lsapi_MD5Context *context); void lsapi_MD5Update(struct lsapi_MD5Context *context, unsigned char const *buf, unsigned len); void lsapi_MD5Final(unsigned char digest[16], struct lsapi_MD5Context *context); /* * This is needed to make RSAREF happy on some MS-DOS compilers. */ typedef struct lsapi_MD5Context lsapi_MD5_CTX; #define LSAPI_ST_REQ_HEADER 1 #define LSAPI_ST_REQ_BODY 2 #define LSAPI_ST_RESP_HEADER 4 #define LSAPI_ST_RESP_BODY 8 #define LSAPI_ST_BACKGROUND 16 #define LSAPI_RESP_BUF_SIZE 8192 #define LSAPI_INIT_RESP_HEADER_LEN 4096 enum { LSAPI_STATE_IDLE, LSAPI_STATE_CONNECTED, LSAPI_STATE_ACCEPTING, }; typedef struct lsapi_child_status { int m_pid; long m_tmStart; volatile short m_iKillSent; volatile char m_inProcess; volatile char m_state; volatile int m_iReqCounter; volatile long m_tmWaitBegin; volatile long m_tmReqBegin; volatile long m_tmLastCheckPoint; } lsapi_child_status; static lsapi_child_status * s_worker_status = NULL; static int g_inited = 0; static int g_running = 1; static int s_ppid; static int s_restored_ppid = 0; static int s_pid = 0; static int s_slow_req_msecs = 0; static int s_keep_listener = 1; static int s_dump_debug_info = 0; static int s_pid_dump_debug_info = 0; static int s_req_processed = 0; static int s_skip_write = 0; static int (*pthread_atfork_func)(void (*prepare)(void), void (*parent)(void), void (*child)(void)) = NULL; static int *s_busy_workers = NULL; static int *s_accepting_workers = NULL; static int *s_global_counter = &s_req_processed; static int s_max_busy_workers = -1; static char *s_stderr_log_path = NULL; static int s_stderr_is_pipe = 0; static int s_ignore_pid = -1; static size_t s_total_pages = 1; static size_t s_min_avail_pages = 256 * 1024; static size_t *s_avail_pages = &s_total_pages; LSAPI_Request g_req = { .m_fdListen = -1, .m_fd = -1 }; static char s_secret[24]; static LSAPI_On_Timer_pf s_proc_group_timer_cb = NULL; void Flush_RespBuf_r( LSAPI_Request * pReq ); static int lsapi_reopen_stderr(const char *p); static const char *CGI_HEADERS[H_TRANSFER_ENCODING+1] = { "HTTP_ACCEPT", "HTTP_ACCEPT_CHARSET", "HTTP_ACCEPT_ENCODING", "HTTP_ACCEPT_LANGUAGE", "HTTP_AUTHORIZATION", "HTTP_CONNECTION", "CONTENT_TYPE", "CONTENT_LENGTH", "HTTP_COOKIE", "HTTP_COOKIE2", "HTTP_HOST", "HTTP_PRAGMA", "HTTP_REFERER", "HTTP_USER_AGENT", "HTTP_CACHE_CONTROL", "HTTP_IF_MODIFIED_SINCE", "HTTP_IF_MATCH", "HTTP_IF_NONE_MATCH", "HTTP_IF_RANGE", "HTTP_IF_UNMODIFIED_SINCE", "HTTP_KEEP_ALIVE", "HTTP_RANGE", "HTTP_X_FORWARDED_FOR", "HTTP_VIA", "HTTP_TRANSFER_ENCODING" }; static int CGI_HEADER_LEN[H_TRANSFER_ENCODING+1] = { 11, 19, 20, 20, 18, 15, 12, 14, 11, 12, 9, 11, 12, 15, 18, 22, 13, 18, 13, 24, 15, 10, 20, 8, 22 }; static const char *HTTP_HEADERS[H_TRANSFER_ENCODING+1] = { "Accept", "Accept-Charset", "Accept-Encoding", "Accept-Language", "Authorization", "Connection", "Content-Type", "Content-Length", "Cookie", "Cookie2", "Host", "Pragma", "Referer", "User-Agent", "Cache-Control", "If-Modified-Since", "If-Match", "If-None-Match", "If-Range", "If-Unmodified-Since", "Keep-Alive", "Range", "X-Forwarded-For", "Via", "Transfer-Encoding" }; static int HTTP_HEADER_LEN[H_TRANSFER_ENCODING+1] = { 6, 14, 15, 15, 13, 10, 12, 14, 6, 7, 4, 6, 7, 10, //user-agent 13,17, 8, 13, 8, 19, 10, 5, 15, 3, 17 }; static const char *s_log_level_names[8] = { "", "DEBUG","INFO", "NOTICE", "WARN", "ERROR", "CRIT", "FATAL" }; void LSAPI_Log(int flag, const char * fmt, ...) { char buf[1024]; char *p = buf; if ((flag & LSAPI_LOG_TIMESTAMP_BITS) && !(s_stderr_is_pipe)) { struct timeval tv; struct tm tm; gettimeofday(&tv, NULL); localtime_r(&tv.tv_sec, &tm); if (flag & LSAPI_LOG_TIMESTAMP_FULL) { p += snprintf(p, 1024, "%04d-%02d-%02d %02d:%02d:%02d.%06d ", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, (int)tv.tv_usec); } else if (flag & LSAPI_LOG_TIMESTAMP_HMS) { p += snprintf(p, 1024, "%02d:%02d:%02d ", tm.tm_hour, tm.tm_min, tm.tm_sec); } } int level = flag & LSAPI_LOG_LEVEL_BITS; if (level && level <= LSAPI_LOG_FLAG_FATAL) { p += snprintf(p, 100, "[%s] ", s_log_level_names[level]); } if (flag & LSAPI_LOG_PID) { p += snprintf(p, 100, "[UID:%d][%d] ", getuid(), s_pid); } if (p > buf) fprintf(stderr, "%.*s", (int)(p - buf), buf); va_list ap; va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); } #ifdef LSAPI_DEBUG #define DBGLOG_FLAG (LSAPI_LOG_TIMESTAMP_FULL|LSAPI_LOG_FLAG_DEBUG|LSAPI_LOG_PID) #define lsapi_dbg(...) LSAPI_Log(DBGLOG_FLAG, __VA_ARGS__) #else #define lsapi_dbg(...) #endif #define lsapi_log(...) LSAPI_Log(LSAPI_LOG_TIMESTAMP_FULL|LSAPI_LOG_PID, __VA_ARGS__) void lsapi_perror(const char * pMessage, int err_no) { lsapi_log("%s, errno: %d (%s)\n", pMessage, err_no, strerror(err_no)); } static int lsapi_parent_dead() { // Return non-zero if the parent is dead. 0 if still alive. if (!s_ppid) { // not checking, so not dead return(0); } if (s_restored_ppid) { if (kill(s_restored_ppid,0) == -1) { if (errno == EPERM) { return(0); // no permission, but it's still there. } return(1); // Dead } return(0); // it worked, so it's not dead } return(s_ppid != getppid()); } static void lsapi_sigpipe( int sig ) { } static void lsapi_siguser1( int sig ) { g_running = 0; } #ifndef sighandler_t typedef void (*sighandler_t)(int); #endif static void lsapi_signal(int signo, sighandler_t handler) { struct sigaction sa; sigaction(signo, NULL, &sa); if (sa.sa_handler == SIG_DFL) { sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = handler; sigaction(signo, &sa, NULL); } } static int s_enable_core_dump = 0; static void lsapi_enable_core_dump(void) { #if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) \ || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) int mib[2]; size_t len; #if !defined(__OpenBSD__) len = 2; if ( sysctlnametomib("kern.sugid_coredump", mib, &len) == 0 ) { len = sizeof(s_enable_core_dump); if (sysctl(mib, 2, NULL, 0, &s_enable_core_dump, len) == -1) perror( "sysctl: Failed to set 'kern.sugid_coredump', " "core dump may not be available!"); } #else int set = 3; len = sizeof(set); mib[0] = CTL_KERN; mib[1] = KERN_NOSUIDCOREDUMP; if (sysctl(mib, 2, NULL, 0, &set, len) == 0) { s_enable_core_dump = 1; } #endif #endif #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) if (prctl(PR_SET_DUMPABLE, s_enable_core_dump,0,0,0) == -1) perror( "prctl: Failed to set dumpable, " "core dump may not be available!"); #endif } static inline void lsapi_buildPacketHeader( struct lsapi_packet_header * pHeader, char type, int len ) { pHeader->m_versionB0 = LSAPI_VERSION_B0; /* LSAPI protocol version */ pHeader->m_versionB1 = LSAPI_VERSION_B1; pHeader->m_type = type; pHeader->m_flag = LSAPI_ENDIAN; pHeader->m_packetLen.m_iLen = len; } static int lsapi_set_nblock( int fd, int nonblock ) { int val = fcntl( fd, F_GETFL, 0 ); if ( nonblock ) { if (!( val & O_NONBLOCK )) { return fcntl( fd, F_SETFL, val | O_NONBLOCK ); } } else { if ( val & O_NONBLOCK ) { return fcntl( fd, F_SETFL, val &(~O_NONBLOCK) ); } } return 0; } static int lsapi_close( int fd ) { int ret; while( 1 ) { ret = close( fd ); if (( ret == -1 )&&( errno == EINTR )&&(g_running)) continue; return ret; } } static void lsapi_close_connection(LSAPI_Request *pReq) { if (pReq->m_fd == -1) return; lsapi_close(pReq->m_fd); pReq->m_fd = -1; if (s_busy_workers) __atomic_fetch_sub(s_busy_workers, 1, __ATOMIC_SEQ_CST); if (s_worker_status) __atomic_store_n(&s_worker_status->m_state, LSAPI_STATE_IDLE, __ATOMIC_SEQ_CST); } static inline ssize_t lsapi_read( int fd, void * pBuf, size_t len ) { ssize_t ret; while( 1 ) { ret = read( fd, (char *)pBuf, len ); if (( ret == -1 )&&( errno == EINTR )&&(g_running)) continue; return ret; } } /* static int lsapi_write( int fd, const void * pBuf, int len ) { int ret; const char * pCur; const char * pEnd; if ( len == 0 ) return 0; pCur = (const char *)pBuf; pEnd = pCur + len; while( g_running && (pCur < pEnd) ) { ret = write( fd, pCur, pEnd - pCur ); if ( ret >= 0) pCur += ret; else if (( ret == -1 )&&( errno != EINTR )) return ret; } return pCur - (const char *)pBuf; } */ static int lsapi_writev( int fd, struct iovec ** pVec, int count, int totalLen ) { int ret; int left = totalLen; int n = count; if (s_skip_write) return totalLen; while(( left > 0 )&&g_running ) { ret = writev( fd, *pVec, n ); if ( ret > 0 ) { left -= ret; if (( left <= 0)||( !g_running )) return totalLen - left; while( ret > 0 ) { if ( (*pVec)->iov_len <= (unsigned int )ret ) { ret -= (*pVec)->iov_len; ++(*pVec); } else { (*pVec)->iov_base = (char *)(*pVec)->iov_base + ret; (*pVec)->iov_len -= ret; break; } } } else if ( ret == -1 ) { if ( errno == EAGAIN ) { if ( totalLen - left > 0 ) return totalLen - left; else return -1; } else if ( errno != EINTR ) return ret; } } return totalLen - left; } /* static int getTotalLen( struct iovec * pVec, int count ) { struct iovec * pEnd = pVec + count; int total = 0; while( pVec < pEnd ) { total += pVec->iov_len; ++pVec; } return total; } */ static inline int allocateBuf( LSAPI_Request * pReq, int size ) { char * pBuf = (char *)realloc( pReq->m_pReqBuf, size ); if ( pBuf ) { pReq->m_pReqBuf = pBuf; pReq->m_reqBufSize = size; pReq->m_pHeader = (struct lsapi_req_header *)pReq->m_pReqBuf; return 0; } return -1; } static int allocateIovec( LSAPI_Request * pReq, int n ) { struct iovec * p = (struct iovec *)realloc( pReq->m_pIovec, sizeof(struct iovec) * n ); if ( !p ) return -1; pReq->m_pIovecToWrite = p + ( pReq->m_pIovecToWrite - pReq->m_pIovec ); pReq->m_pIovecCur = p + ( pReq->m_pIovecCur - pReq->m_pIovec ); pReq->m_pIovec = p; pReq->m_pIovecEnd = p + n; return 0; } static int allocateRespHeaderBuf( LSAPI_Request * pReq, int size ) { char * p = (char *)realloc( pReq->m_pRespHeaderBuf, size ); if ( !p ) return -1; pReq->m_pRespHeaderBufPos = p + ( pReq->m_pRespHeaderBufPos - pReq->m_pRespHeaderBuf ); pReq->m_pRespHeaderBuf = p; pReq->m_pRespHeaderBufEnd = p + size; return 0; } static inline int verifyHeader( struct lsapi_packet_header * pHeader, char pktType ) { if (( LSAPI_VERSION_B0 != pHeader->m_versionB0 )|| ( LSAPI_VERSION_B1 != pHeader->m_versionB1 )|| ( pktType != pHeader->m_type )) return -1; if ( LSAPI_ENDIAN != (pHeader->m_flag & LSAPI_ENDIAN_BIT )) { register char b; b = pHeader->m_packetLen.m_bytes[0]; pHeader->m_packetLen.m_bytes[0] = pHeader->m_packetLen.m_bytes[3]; pHeader->m_packetLen.m_bytes[3] = b; b = pHeader->m_packetLen.m_bytes[1]; pHeader->m_packetLen.m_bytes[1] = pHeader->m_packetLen.m_bytes[2]; pHeader->m_packetLen.m_bytes[2] = b; } return pHeader->m_packetLen.m_iLen; } static int allocateEnvList( struct LSAPI_key_value_pair ** pEnvList, int *curSize, int newSize ) { struct LSAPI_key_value_pair * pBuf; if ( *curSize >= newSize ) return 0; if ( newSize > 8192 ) return -1; pBuf = (struct LSAPI_key_value_pair *)realloc( *pEnvList, newSize * sizeof(struct LSAPI_key_value_pair) ); if ( pBuf ) { *pEnvList = pBuf; *curSize = newSize; return 0; } else return -1; } static inline int isPipe( int fd ) { char achPeer[128]; socklen_t len = 128; if (( getpeername( fd, (struct sockaddr *)achPeer, &len ) != 0 )&& ( errno == ENOTCONN )) return 0; else return 1; } static int parseEnv( struct LSAPI_key_value_pair * pEnvList, int count, char **pBegin, char * pEnd ) { struct LSAPI_key_value_pair * pEnvEnd; int keyLen = 0, valLen = 0; if ( count > 8192 ) return -1; pEnvEnd = pEnvList + count; while( pEnvList != pEnvEnd ) { if ( pEnd - *pBegin < 4 ) return -1; keyLen = *((unsigned char *)((*pBegin)++)); keyLen = (keyLen << 8) + *((unsigned char *)((*pBegin)++)); valLen = *((unsigned char *)((*pBegin)++)); valLen = (valLen << 8) + *((unsigned char *)((*pBegin)++)); if ( *pBegin + keyLen + valLen > pEnd ) return -1; if (( !keyLen )||( !valLen )) return -1; pEnvList->pKey = *pBegin; *pBegin += keyLen; pEnvList->pValue = *pBegin; *pBegin += valLen; pEnvList->keyLen = keyLen - 1; pEnvList->valLen = valLen - 1; ++pEnvList; } if ( memcmp( *pBegin, "\0\0\0\0", 4 ) != 0 ) return -1; *pBegin += 4; return 0; } static inline void swapIntEndian( int * pInteger ) { char * p = (char *)pInteger; register char b; b = p[0]; p[0] = p[3]; p[3] = b; b = p[1]; p[1] = p[2]; p[2] = b; } static inline void fixEndian( LSAPI_Request * pReq ) { struct lsapi_req_header *p= pReq->m_pHeader; swapIntEndian( &p->m_httpHeaderLen ); swapIntEndian( &p->m_reqBodyLen ); swapIntEndian( &p->m_scriptFileOff ); swapIntEndian( &p->m_scriptNameOff ); swapIntEndian( &p->m_queryStringOff ); swapIntEndian( &p->m_requestMethodOff ); swapIntEndian( &p->m_cntUnknownHeaders ); swapIntEndian( &p->m_cntEnv ); swapIntEndian( &p->m_cntSpecialEnv ); } static void fixHeaderIndexEndian( LSAPI_Request * pReq ) { int i; for( i = 0; i < H_TRANSFER_ENCODING; ++i ) { if ( pReq->m_pHeaderIndex->m_headerOff[i] ) { register char b; char * p = (char *)(&pReq->m_pHeaderIndex->m_headerLen[i]); b = p[0]; p[0] = p[1]; p[1] = b; swapIntEndian( &pReq->m_pHeaderIndex->m_headerOff[i] ); } } if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 ) { struct lsapi_header_offset * pCur, *pEnd; pCur = pReq->m_pUnknownHeader; pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders; while( pCur < pEnd ) { swapIntEndian( &pCur->nameOff ); swapIntEndian( &pCur->nameLen ); swapIntEndian( &pCur->valueOff ); swapIntEndian( &pCur->valueLen ); ++pCur; } } } static int validateHeaders( LSAPI_Request * pReq ) { int totalLen = pReq->m_pHeader->m_httpHeaderLen; int i; for(i = 0; i < H_TRANSFER_ENCODING; ++i) { if ( pReq->m_pHeaderIndex->m_headerOff[i] ) { if (pReq->m_pHeaderIndex->m_headerOff[i] > totalLen || pReq->m_pHeaderIndex->m_headerLen[i] + pReq->m_pHeaderIndex->m_headerOff[i] > totalLen) return -1; } } if (pReq->m_pHeader->m_cntUnknownHeaders > 0) { struct lsapi_header_offset * pCur, *pEnd; pCur = pReq->m_pUnknownHeader; pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders; while( pCur < pEnd ) { if (pCur->nameOff > totalLen || pCur->nameOff + pCur->nameLen > totalLen || pCur->valueOff > totalLen || pCur->valueOff + pCur->valueLen > totalLen) return -1; ++pCur; } } return 0; } static uid_t s_uid = 0; static uid_t s_defaultUid; //web server need set this static gid_t s_defaultGid; #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) #define LSAPI_LVE_DISABLED 0 #define LSAPI_LVE_ENABLED 1 #define LSAPI_CAGEFS_ENABLED 2 #define LSAPI_CAGEFS_NO_SUEXEC 3 struct liblve; static int s_enable_lve = LSAPI_LVE_DISABLED; static struct liblve * s_lve = NULL; static void *s_liblve; static int (*fp_lve_is_available)(void) = NULL; static int (*fp_lve_instance_init)(struct liblve *) = NULL; static int (*fp_lve_destroy)(struct liblve *) = NULL; static int (*fp_lve_enter)(struct liblve *, uint32_t, int32_t, int32_t, uint32_t *) = NULL; static int (*fp_lve_leave)(struct liblve *, uint32_t *) = NULL; static int (*fp_lve_jail)( struct passwd *, char *) = NULL; static int lsapi_load_lve_lib(void) { s_liblve = dlopen("liblve.so.0", RTLD_NOW | RTLD_GLOBAL); if (s_liblve) { fp_lve_is_available = dlsym(s_liblve, "lve_is_available"); if (dlerror() == NULL) { if ( !(*fp_lve_is_available)() ) { int uid = getuid(); if ( uid ) { if (setreuid( s_uid, uid )) {}; if ( !(*fp_lve_is_available)() ) s_enable_lve = 0; if (setreuid( uid, s_uid )) {}; } } } } else { s_enable_lve = LSAPI_LVE_DISABLED; } return (s_liblve)? 0 : -1; } static int init_lve_ex(void) { int rc; if ( !s_liblve ) return -1; fp_lve_instance_init = dlsym(s_liblve, "lve_instance_init"); fp_lve_destroy = dlsym(s_liblve, "lve_destroy"); fp_lve_enter = dlsym(s_liblve, "lve_enter"); fp_lve_leave = dlsym(s_liblve, "lve_leave"); if ( s_enable_lve >= LSAPI_CAGEFS_ENABLED ) fp_lve_jail = dlsym(s_liblve, "jail" ); if ( s_lve == NULL ) { rc = (*fp_lve_instance_init)(NULL); s_lve = malloc(rc); } rc = (*fp_lve_instance_init)(s_lve); if (rc != 0) { perror( "LSAPI: Unable to initialize LVE" ); free( s_lve ); s_lve = NULL; return -1; } return 0; } #endif static int readSecret( const char * pSecretFile ) { struct stat st; int fd = open( pSecretFile, O_RDONLY , 0600 ); if ( fd == -1 ) { lsapi_log("LSAPI: failed to open secret file: %s!\n", pSecretFile ); return -1; } if ( fstat( fd, &st ) == -1 ) { lsapi_log("LSAPI: failed to check state of file: %s!\n", pSecretFile ); close( fd ); return -1; } /* if ( st.st_uid != s_uid ) { lsapi_log("LSAPI: file owner check failure: %s!\n", pSecretFile ); close( fd ); return -1; } */ if ( st.st_mode & 0077 ) { lsapi_log("LSAPI: file permission check failure: %s\n", pSecretFile ); close( fd ); return -1; } if ( read( fd, s_secret, 16 ) < 16 ) { lsapi_log("LSAPI: failed to read secret from secret file: %s\n", pSecretFile ); close( fd ); return -1; } close( fd ); return 0; } int LSAPI_is_suEXEC_Daemon(void) { if (( !s_uid )&&( s_secret[0] )) return 1; else return 0; } static int LSAPI_perror_r( LSAPI_Request * pReq, const char * pErr1, const char *pErr2 ) { char achError[4096]; int n = snprintf(achError, sizeof(achError), "[UID:%d][%d] %s:%s: %s\n", getuid(), getpid(), pErr1, (pErr2)?pErr2:"", strerror(errno)); if (n > (int)sizeof(achError)) n = sizeof(achError); if ( pReq ) LSAPI_Write_Stderr_r( pReq, achError, n ); else if (write( STDERR_FILENO, achError, n )) {}; return 0; } #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) static int lsapi_lve_error( LSAPI_Request * pReq ) { static const char * headers[] = { "Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0", "Pragma: no-cache", "Retry-After: 60", "Content-Type: text/html", NULL }; static const char achBody[] = "\n" "\n508 Resource Limit Is Reached\n" "\n" "

    Resource Limit Is Reached

    \n" "The website is temporarily unable to service your request as it exceeded resource limit.\n" "Please try again later.\n" "
    \n" "\n"; LSAPI_ErrResponse_r( pReq, 508, headers, achBody, sizeof( achBody ) - 1 ); return 0; } static int lsapi_enterLVE( LSAPI_Request * pReq, uid_t uid ) { if ( s_lve && uid ) //root user should not do that { uint32_t cookie; int ret = -1; ret = (*fp_lve_enter)(s_lve, uid, -1, -1, &cookie); if ( ret < 0 ) { //lsapi_log("enter LVE (%d) : result: %d !\n", uid, ret ); LSAPI_perror_r(pReq, "LSAPI: lve_enter() failure, reached resource limit.", NULL ); lsapi_lve_error( pReq ); return -1; } } return 0; } static int lsapi_jailLVE( LSAPI_Request * pReq, uid_t uid, struct passwd * pw ) { int ret = 0; char error_msg[1024] = ""; ret = (*fp_lve_jail)( pw, error_msg ); if ( ret < 0 ) { lsapi_log("LSAPI: LVE jail(%d) result: %d, error: %s !\n", uid, ret, error_msg ); LSAPI_perror_r( pReq, "LSAPI: jail() failure.", NULL ); return -1; } return ret; } static int lsapi_initLVE(void) { const char * pEnv; if ( (pEnv = getenv( "LSAPI_LVE_ENABLE" ))!= NULL ) { s_enable_lve = atol( pEnv ); pEnv = NULL; } else if ( (pEnv = getenv( "LVE_ENABLE" ))!= NULL ) { s_enable_lve = atol( pEnv ); pEnv = NULL; } if ( s_enable_lve && !s_uid ) { lsapi_load_lve_lib(); if ( s_enable_lve ) { return init_lve_ex(); } } return 0; } #endif static int setUID_LVE(LSAPI_Request * pReq, uid_t uid, gid_t gid, const char * pChroot) { int rv; struct passwd * pw; pw = getpwuid( uid ); #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) if ( s_lve ) { if( lsapi_enterLVE( pReq, uid ) == -1 ) return -1; if ( pw && fp_lve_jail) { rv = lsapi_jailLVE( pReq, uid, pw ); if ( rv == -1 ) return -1; if (( rv == 1 )&&(s_enable_lve == LSAPI_CAGEFS_NO_SUEXEC )) //this mode only use cageFS, does not use suEXEC { uid = s_defaultUid; gid = s_defaultGid; pw = getpwuid( uid ); } } } #endif //if ( !uid || !gid ) //do not allow root //{ // return -1; //} #if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) \ || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) if ( s_enable_core_dump ) lsapi_enable_core_dump(); #endif rv = setgid(gid); if (rv == -1) { LSAPI_perror_r(pReq, "LSAPI: setgid()", NULL); return -1; } if ( pw && (pw->pw_gid == gid )) { rv = initgroups( pw->pw_name, gid ); if (rv == -1) { LSAPI_perror_r(pReq, "LSAPI: initgroups()", NULL); return -1; } } else { rv = setgroups(1, &gid); if (rv == -1) { LSAPI_perror_r(pReq, "LSAPI: setgroups()", NULL); } } if ( pChroot ) { rv = chroot( pChroot ); if ( rv == -1 ) { LSAPI_perror_r(pReq, "LSAPI: chroot()", NULL); return -1; } } rv = setuid(uid); if (rv == -1) { LSAPI_perror_r(pReq, "LSAPI: setuid()", NULL); return -1; } #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) if ( s_enable_core_dump ) lsapi_enable_core_dump(); #endif return 0; } static int lsapi_suexec_auth( LSAPI_Request *pReq, char * pAuth, int len, char * pUgid, int ugidLen ) { lsapi_MD5_CTX md5ctx; unsigned char achMD5[16]; if ( len < 32 ) return -1; memmove( achMD5, pAuth + 16, 16 ); memmove( pAuth + 16, s_secret, 16 ); lsapi_MD5Init( &md5ctx ); lsapi_MD5Update( &md5ctx, (unsigned char *)pAuth, 32 ); lsapi_MD5Update( &md5ctx, (unsigned char *)pUgid, 8 ); lsapi_MD5Final( (unsigned char *)pAuth + 16, &md5ctx); if ( memcmp( achMD5, pAuth + 16, 16 ) == 0 ) return 0; return 1; } static int lsapi_changeUGid( LSAPI_Request * pReq ) { int uid = s_defaultUid; int gid = s_defaultGid; const char *pStderrLog; const char *pChroot = NULL; struct LSAPI_key_value_pair * pEnv; struct LSAPI_key_value_pair * pAuth; int i; if ( s_uid ) return 0; //with special ID 0x00 //authenticate the suEXEC request; //first one should be MD5( nonce + lscgid secret ) //remember to clear the secret after verification //it should be set at the end of special env i = pReq->m_pHeader->m_cntSpecialEnv - 1; if ( i >= 0 ) { pEnv = pReq->m_pSpecialEnvList + i; if (( *pEnv->pKey == '\000' )&& ( strcmp( pEnv->pKey+1, "SUEXEC_AUTH" ) == 0 )) { --pReq->m_pHeader->m_cntSpecialEnv; pAuth = pEnv--; if (( *pEnv->pKey == '\000' )&& ( strcmp( pEnv->pKey+1, "SUEXEC_UGID" ) == 0 )) { --pReq->m_pHeader->m_cntSpecialEnv; uid = *(uint32_t *)pEnv->pValue; gid = *(((uint32_t *)pEnv->pValue) + 1 ); //lsapi_log("LSAPI: SUEXEC_UGID set UID: %d, GID: %d\n", uid, gid ); } else { lsapi_log("LSAPI: missing SUEXEC_UGID env, use default user!\n" ); pEnv = NULL; } if ( pEnv&& lsapi_suexec_auth( pReq, pAuth->pValue, pAuth->valLen, pEnv->pValue, pEnv->valLen ) == 0 ) { //read UID, GID from specialEnv } else { //authentication error lsapi_log("LSAPI: SUEXEC_AUTH authentication failed, use default user!\n" ); uid = 0; } } else { //lsapi_log("LSAPI: no SUEXEC_AUTH env, use default user!\n" ); } } if ( !uid ) { uid = s_defaultUid; gid = s_defaultGid; } //change uid if ( setUID_LVE( pReq, uid, gid, pChroot ) == -1 ) { return -1; } s_uid = uid; if ( pReq->m_fdListen != -1 ) { close( pReq->m_fdListen ); pReq->m_fdListen = -1; } pStderrLog = LSAPI_GetEnv_r( pReq, "LSAPI_STDERR_LOG"); if (pStderrLog) lsapi_reopen_stderr(pStderrLog); return 0; } static int parseContentLenFromHeader(LSAPI_Request * pReq) { const char * pContentLen = LSAPI_GetHeader_r( pReq, H_CONTENT_LENGTH ); if ( pContentLen ) pReq->m_reqBodyLen = strtoll( pContentLen, NULL, 10 ); return 0; } static int parseRequest( LSAPI_Request * pReq, int totalLen ) { int shouldFixEndian; char * pBegin = pReq->m_pReqBuf + sizeof( struct lsapi_req_header ); char * pEnd = pReq->m_pReqBuf + totalLen; shouldFixEndian = ( LSAPI_ENDIAN != ( pReq->m_pHeader->m_pktHeader.m_flag & LSAPI_ENDIAN_BIT ) ); if ( shouldFixEndian ) { fixEndian( pReq ); } if ( (pReq->m_specialEnvListSize < pReq->m_pHeader->m_cntSpecialEnv )&& allocateEnvList( &pReq->m_pSpecialEnvList, &pReq->m_specialEnvListSize, pReq->m_pHeader->m_cntSpecialEnv ) == -1 ) return -1; if ( (pReq->m_envListSize < pReq->m_pHeader->m_cntEnv )&& allocateEnvList( &pReq->m_pEnvList, &pReq->m_envListSize, pReq->m_pHeader->m_cntEnv ) == -1 ) return -1; if ( parseEnv( pReq->m_pSpecialEnvList, pReq->m_pHeader->m_cntSpecialEnv, &pBegin, pEnd ) == -1 ) return -1; if ( parseEnv( pReq->m_pEnvList, pReq->m_pHeader->m_cntEnv, &pBegin, pEnd ) == -1 ) return -1; if (pReq->m_pHeader->m_scriptFileOff < 0 || pReq->m_pHeader->m_scriptFileOff >= totalLen || pReq->m_pHeader->m_scriptNameOff < 0 || pReq->m_pHeader->m_scriptNameOff >= totalLen || pReq->m_pHeader->m_queryStringOff < 0 || pReq->m_pHeader->m_queryStringOff >= totalLen || pReq->m_pHeader->m_requestMethodOff < 0 || pReq->m_pHeader->m_requestMethodOff >= totalLen) { lsapi_log("Bad request header - ERROR#1\n"); return -1; } pReq->m_pScriptFile = pReq->m_pReqBuf + pReq->m_pHeader->m_scriptFileOff; pReq->m_pScriptName = pReq->m_pReqBuf + pReq->m_pHeader->m_scriptNameOff; pReq->m_pQueryString = pReq->m_pReqBuf + pReq->m_pHeader->m_queryStringOff; pReq->m_pRequestMethod = pReq->m_pReqBuf + pReq->m_pHeader->m_requestMethodOff; pBegin = pReq->m_pReqBuf + (( pBegin - pReq->m_pReqBuf + 7 ) & (~0x7)); pReq->m_pHeaderIndex = ( struct lsapi_http_header_index * )pBegin; pBegin += sizeof( struct lsapi_http_header_index ); pReq->m_pUnknownHeader = (struct lsapi_header_offset *)pBegin; pBegin += sizeof( struct lsapi_header_offset) * pReq->m_pHeader->m_cntUnknownHeaders; pReq->m_pHttpHeader = pBegin; pBegin += pReq->m_pHeader->m_httpHeaderLen; if ( pBegin != pEnd ) { lsapi_log("Request header does match total size, total: %d, " "real: %ld\n", totalLen, pBegin - pReq->m_pReqBuf ); return -1; } if ( shouldFixEndian ) { fixHeaderIndexEndian( pReq ); } if (validateHeaders(pReq) == -1) { lsapi_log("Bad request header - ERROR#2\n"); return -1; } pReq->m_reqBodyLen = pReq->m_pHeader->m_reqBodyLen; if ( pReq->m_reqBodyLen == -2 ) { parseContentLenFromHeader(pReq); } return 0; } //OPTIMIZATION static char s_accept_notify = 0; static char s_schedule_notify = 0; static char s_notify_scheduled = 0; static char s_notified_pid = 0; static struct lsapi_packet_header s_ack = {'L', 'S', LSAPI_REQ_RECEIVED, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} }; static struct lsapi_packet_header s_conn_close_pkt = {'L', 'S', LSAPI_CONN_CLOSE, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} }; static inline int send_notification_pkt( int fd, struct lsapi_packet_header *pkt ) { if ( write( fd, pkt, LSAPI_PACKET_HEADER_LEN ) < LSAPI_PACKET_HEADER_LEN ) return -1; return 0; } static inline int send_req_received_notification( int fd ) { return send_notification_pkt(fd, &s_ack); } static inline int send_conn_close_notification( int fd ) { return send_notification_pkt(fd, &s_conn_close_pkt); } //static void lsapi_sigalarm( int sig ) //{ // if ( s_notify_scheduled ) // { // s_notify_scheduled = 0; // if ( g_req.m_fd != -1 ) // write_req_received_notification( g_req.m_fd ); // } //} static inline int lsapi_schedule_notify(void) { if ( !s_notify_scheduled ) { alarm( 2 ); s_notify_scheduled = 1; } return 0; } static inline int notify_req_received( int fd ) { if ( s_schedule_notify ) return lsapi_schedule_notify(); return send_req_received_notification( fd ); } static inline int lsapi_notify_pid( int fd ) { char achBuf[16]; lsapi_buildPacketHeader( (struct lsapi_packet_header *)achBuf, LSAPI_STDERR_STREAM, 8 + LSAPI_PACKET_HEADER_LEN ); memmove( &achBuf[8], "\0PID", 4 ); *((int *)&achBuf[12]) = getpid(); if ( write( fd, achBuf, 16 ) < 16 ) return -1; return 0; } static int readReq( LSAPI_Request * pReq ) { int len; int packetLen; if ( !pReq ) return -1; if ( pReq->m_reqBufSize < 8192 ) { if ( allocateBuf( pReq, 8192 ) == -1 ) return -1; } while ( pReq->m_bufRead < LSAPI_PACKET_HEADER_LEN ) { len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf, pReq->m_reqBufSize ); if ( len <= 0 ) return -1; pReq->m_bufRead += len; } pReq->m_reqState = LSAPI_ST_REQ_HEADER; packetLen = verifyHeader( &pReq->m_pHeader->m_pktHeader, LSAPI_BEGIN_REQUEST ); if ( packetLen < 0 ) { lsapi_log("packetLen < 0\n"); return -1; } if ( packetLen > LSAPI_MAX_HEADER_LEN ) { lsapi_log("packetLen > %d\n", LSAPI_MAX_HEADER_LEN ); return -1; } if ( packetLen + 1024 > pReq->m_reqBufSize ) { if ( allocateBuf( pReq, packetLen + 1024 ) == -1 ) return -1; } while( packetLen > pReq->m_bufRead ) { len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf + pReq->m_bufRead, packetLen - pReq->m_bufRead ); if ( len <= 0 ) return -1; pReq->m_bufRead += len; } if ( parseRequest( pReq, packetLen ) < 0 ) { lsapi_log("ParseRequest error\n"); return -1; } pReq->m_reqState = LSAPI_ST_REQ_BODY | LSAPI_ST_RESP_HEADER; if ( !s_uid ) { if ( lsapi_changeUGid( pReq ) ) return -1; memset(s_secret, 0, sizeof(s_secret)); } pReq->m_bufProcessed = packetLen; //OPTIMIZATION if ( !s_accept_notify && !s_notified_pid ) return notify_req_received( pReq->m_fd ); else { s_notified_pid = 0; return 0; } } int LSAPI_Init(void) { if ( !g_inited ) { s_uid = geteuid(); s_secret[0] = 0; lsapi_signal(SIGPIPE, lsapi_sigpipe); lsapi_signal(SIGUSR1, lsapi_siguser1); #if defined(SIGXFSZ) && defined(SIG_IGN) signal(SIGXFSZ, SIG_IGN); #endif /* let STDOUT function as STDERR, just in case writing to STDOUT directly */ dup2( 2, 1 ); if ( LSAPI_InitRequest( &g_req, LSAPI_SOCK_FILENO ) == -1 ) return -1; g_inited = 1; s_ppid = getppid(); void *pthread_lib = dlopen("libpthread.so", RTLD_LAZY); if (pthread_lib) pthread_atfork_func = dlsym(pthread_lib, "pthread_atfork"); } return 0; } void LSAPI_Stop(void) { g_running = 0; } int LSAPI_IsRunning(void) { return g_running; } void LSAPI_Register_Pgrp_Timer_Callback(LSAPI_On_Timer_pf cb) { s_proc_group_timer_cb = cb; } int LSAPI_InitRequest( LSAPI_Request * pReq, int fd ) { int newfd; if ( !pReq ) return -1; memset( pReq, 0, sizeof( LSAPI_Request ) ); if ( allocateIovec( pReq, 16 ) == -1 ) return -1; pReq->m_pRespBuf = pReq->m_pRespBufPos = (char *)malloc( LSAPI_RESP_BUF_SIZE ); if ( !pReq->m_pRespBuf ) return -1; pReq->m_pRespBufEnd = pReq->m_pRespBuf + LSAPI_RESP_BUF_SIZE; pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec + 1; pReq->m_respPktHeaderEnd = &pReq->m_respPktHeader[5]; if ( allocateRespHeaderBuf( pReq, LSAPI_INIT_RESP_HEADER_LEN ) == -1 ) return -1; if ( fd == STDIN_FILENO ) { fd = dup( fd ); newfd = open( "/dev/null", O_RDWR ); dup2( newfd, STDIN_FILENO ); } if ( isPipe( fd ) ) { pReq->m_fdListen = -1; pReq->m_fd = fd; } else { pReq->m_fdListen = fd; pReq->m_fd = -1; lsapi_set_nblock( fd, 1 ); } return 0; } int LSAPI_Is_Listen( void ) { return LSAPI_Is_Listen_r( &g_req ); } int LSAPI_Is_Listen_r( LSAPI_Request * pReq) { return pReq->m_fdListen != -1; } int LSAPI_Accept_r( LSAPI_Request * pReq ) { char achPeer[128]; socklen_t len; int nodelay = 1; if ( !pReq ) return -1; if ( LSAPI_Finish_r( pReq ) == -1 ) return -1; lsapi_set_nblock( pReq->m_fdListen , 0 ); while( g_running ) { if ( pReq->m_fd == -1 ) { if ( pReq->m_fdListen != -1) { len = sizeof( achPeer ); pReq->m_fd = accept( pReq->m_fdListen, (struct sockaddr *)&achPeer, &len ); if ( pReq->m_fd == -1 ) { if (( errno == EINTR )||( errno == EAGAIN)) continue; else return -1; } else { if (s_worker_status) __atomic_store_n(&s_worker_status->m_state, LSAPI_STATE_CONNECTED, __ATOMIC_SEQ_CST); if (s_busy_workers) __atomic_fetch_add(s_busy_workers, 1, __ATOMIC_SEQ_CST); lsapi_set_nblock( pReq->m_fd , 0 ); if (((struct sockaddr *)&achPeer)->sa_family == AF_INET ) { setsockopt(pReq->m_fd, IPPROTO_TCP, TCP_NODELAY, (char *)&nodelay, sizeof(nodelay)); } //init_conn_key( pReq->m_fd ); //OPTIMIZATION if ( s_accept_notify ) if ( notify_req_received( pReq->m_fd ) == -1 ) return -1; } } else return -1; } if ( !readReq( pReq ) ) break; //abort(); lsapi_close_connection(pReq); LSAPI_Reset_r( pReq ); } return 0; } static struct lsapi_packet_header finish_close[2] = { {'L', 'S', LSAPI_RESP_END, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} }, {'L', 'S', LSAPI_CONN_CLOSE, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} } }; int LSAPI_Finish_r( LSAPI_Request * pReq ) { /* finish req body */ if ( !pReq ) return -1; if (pReq->m_reqState) { if ( pReq->m_fd != -1 ) { if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) { LSAPI_FinalizeRespHeaders_r( pReq ); } if ( pReq->m_pRespBufPos != pReq->m_pRespBuf ) { Flush_RespBuf_r( pReq ); } pReq->m_pIovecCur->iov_base = (void *)finish_close; pReq->m_pIovecCur->iov_len = LSAPI_PACKET_HEADER_LEN; pReq->m_totalLen += LSAPI_PACKET_HEADER_LEN; ++pReq->m_pIovecCur; LSAPI_Flush_r( pReq ); } LSAPI_Reset_r( pReq ); } return 0; } int LSAPI_End_Response_r(LSAPI_Request * pReq) { if (!pReq) return -1; if (pReq->m_reqState & LSAPI_ST_BACKGROUND) return 0; if (pReq->m_reqState) { if ( pReq->m_fd != -1 ) { if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) { if ( pReq->m_pRespHeaderBufPos <= pReq->m_pRespHeaderBuf ) return 0; LSAPI_FinalizeRespHeaders_r( pReq ); } if ( pReq->m_pRespBufPos != pReq->m_pRespBuf ) { Flush_RespBuf_r( pReq ); } pReq->m_pIovecCur->iov_base = (void *)finish_close; pReq->m_pIovecCur->iov_len = LSAPI_PACKET_HEADER_LEN << 1; pReq->m_totalLen += LSAPI_PACKET_HEADER_LEN << 1; ++pReq->m_pIovecCur; LSAPI_Flush_r( pReq ); lsapi_close_connection(pReq); } pReq->m_reqState |= LSAPI_ST_BACKGROUND; } return 0; } void LSAPI_Reset_r( LSAPI_Request * pReq ) { pReq->m_pRespBufPos = pReq->m_pRespBuf; pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec + 1; pReq->m_pRespHeaderBufPos = pReq->m_pRespHeaderBuf; memset( &pReq->m_pHeaderIndex, 0, (char *)(pReq->m_respHeaderLen) - (char *)&pReq->m_pHeaderIndex ); } int LSAPI_Release_r( LSAPI_Request * pReq ) { if ( pReq->m_pReqBuf ) free( pReq->m_pReqBuf ); if ( pReq->m_pSpecialEnvList ) free( pReq->m_pSpecialEnvList ); if ( pReq->m_pEnvList ) free( pReq->m_pEnvList ); if ( pReq->m_pRespHeaderBuf ) free( pReq->m_pRespHeaderBuf ); return 0; } char * LSAPI_GetHeader_r( LSAPI_Request * pReq, int headerIndex ) { int off; if ( !pReq || ((unsigned int)headerIndex > H_TRANSFER_ENCODING) ) return NULL; off = pReq->m_pHeaderIndex->m_headerOff[ headerIndex ]; if ( !off ) return NULL; if ( *(pReq->m_pHttpHeader + off + pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) ) { *( pReq->m_pHttpHeader + off + pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) = 0; } return pReq->m_pHttpHeader + off; } static int readBodyToReqBuf( LSAPI_Request * pReq ) { off_t bodyLeft; ssize_t len = pReq->m_bufRead - pReq->m_bufProcessed; if ( len > 0 ) return len; pReq->m_bufRead = pReq->m_bufProcessed = pReq->m_pHeader->m_pktHeader.m_packetLen.m_iLen; bodyLeft = pReq->m_reqBodyLen - pReq->m_reqBodyRead; len = pReq->m_reqBufSize - pReq->m_bufRead; if ( len < 0 ) return -1; if ( len > bodyLeft ) len = bodyLeft; len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf + pReq->m_bufRead, len ); if ( len > 0 ) pReq->m_bufRead += len; return len; } int LSAPI_ReqBodyGetChar_r( LSAPI_Request * pReq ) { if (!pReq || (pReq->m_fd ==-1) ) return EOF; if ( pReq->m_bufProcessed >= pReq->m_bufRead ) { if ( readBodyToReqBuf( pReq ) <= 0 ) return EOF; } ++pReq->m_reqBodyRead; return (unsigned char)*(pReq->m_pReqBuf + pReq->m_bufProcessed++); } int LSAPI_ReqBodyGetLine_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen, int *getLF ) { ssize_t len; ssize_t left; char * pBufEnd = pBuf + bufLen - 1; char * pBufCur = pBuf; char * pCur; char * p; if (!pReq || pReq->m_fd == -1 || !pBuf || !getLF) return -1; *getLF = 0; while( (left = pBufEnd - pBufCur ) > 0 ) { len = pReq->m_bufRead - pReq->m_bufProcessed; if ( len <= 0 ) { if ( (len = readBodyToReqBuf( pReq )) <= 0 ) { *getLF = 1; break; } } if ( len > left ) len = left; pCur = pReq->m_pReqBuf + pReq->m_bufProcessed; p = memchr( pCur, '\n', len ); if ( p ) len = p - pCur + 1; memmove( pBufCur, pCur, len ); pBufCur += len; pReq->m_bufProcessed += len; pReq->m_reqBodyRead += len; if ( p ) { *getLF = 1; break; } } *pBufCur = 0; return pBufCur - pBuf; } ssize_t LSAPI_ReadReqBody_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen ) { ssize_t len; off_t total; /* char *pOldBuf = pBuf; */ if (!pReq || pReq->m_fd == -1 || !pBuf || (ssize_t)bufLen < 0) return -1; total = pReq->m_reqBodyLen - pReq->m_reqBodyRead; if ( total <= 0 ) return 0; if ( total < (ssize_t)bufLen ) bufLen = total; total = 0; len = pReq->m_bufRead - pReq->m_bufProcessed; if ( len > 0 ) { if ( len > (ssize_t)bufLen ) len = bufLen; memmove( pBuf, pReq->m_pReqBuf + pReq->m_bufProcessed, len ); pReq->m_bufProcessed += len; total += len; pBuf += len; bufLen -= len; } while( bufLen > 0 ) { len = lsapi_read( pReq->m_fd, pBuf, bufLen ); if ( len > 0 ) { total += len; pBuf += len; bufLen -= len; } else if ( len <= 0 ) { if ( !total) return -1; break; } } pReq->m_reqBodyRead += total; return total; } ssize_t LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, size_t len ) { struct lsapi_packet_header * pHeader; const char * pEnd; const char * p; ssize_t bufLen; ssize_t toWrite; ssize_t packetLen; int skip = 0; if (!pReq || !pBuf) return -1; if (pReq->m_reqState & LSAPI_ST_BACKGROUND) return len; if (pReq->m_fd == -1) return -1; if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) { LSAPI_FinalizeRespHeaders_r( pReq ); /* if ( *pBuf == '\r' ) { ++skip; } if ( *pBuf == '\n' ) { ++skip; } */ } pReq->m_reqState |= LSAPI_ST_RESP_BODY; if ( ((ssize_t)len - skip) < pReq->m_pRespBufEnd - pReq->m_pRespBufPos ) { memmove( pReq->m_pRespBufPos, pBuf + skip, len - skip ); pReq->m_pRespBufPos += len - skip; return len; } pHeader = pReq->m_respPktHeader; p = pBuf + skip; pEnd = pBuf + len; bufLen = pReq->m_pRespBufPos - pReq->m_pRespBuf; while( ( toWrite = pEnd - p ) > 0 ) { packetLen = toWrite + bufLen; if ( LSAPI_MAX_DATA_PACKET_LEN < packetLen) { packetLen = LSAPI_MAX_DATA_PACKET_LEN; toWrite = packetLen - bufLen; } lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM, packetLen + LSAPI_PACKET_HEADER_LEN ); pReq->m_totalLen += packetLen + LSAPI_PACKET_HEADER_LEN; pReq->m_pIovecCur->iov_base = (void *)pHeader; pReq->m_pIovecCur->iov_len = LSAPI_PACKET_HEADER_LEN; ++pReq->m_pIovecCur; ++pHeader; if ( bufLen > 0 ) { pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespBuf; pReq->m_pIovecCur->iov_len = bufLen; pReq->m_pRespBufPos = pReq->m_pRespBuf; ++pReq->m_pIovecCur; bufLen = 0; } pReq->m_pIovecCur->iov_base = (void *)p; pReq->m_pIovecCur->iov_len = toWrite; ++pReq->m_pIovecCur; p += toWrite; if ( pHeader >= pReq->m_respPktHeaderEnd - 1) { if ( LSAPI_Flush_r( pReq ) == -1 ) return -1; pHeader = pReq->m_respPktHeader; } } if ( pHeader != pReq->m_respPktHeader ) if ( LSAPI_Flush_r( pReq ) == -1 ) return -1; return p - pBuf; } #if defined(__FreeBSD__ ) ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size ) { ssize_t ret; off_t written; ret = sendfile( fdIn, fdOut, *off, size, NULL, &written, 0 ); if ( written > 0 ) { ret = written; *off += ret; } return ret; } #endif #if defined(__OpenBSD__) || defined(__NetBSD__) ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size ) { ssize_t ret; off_t written = 0; const size_t bufsiz = 16384; unsigned char in[bufsiz] = {0}; if (lseek(fdIn, *off, SEEK_SET) == -1) { return -1; } while (size > 0) { size_t tor = size > sizeof(in) ? sizeof(in) : size; ssize_t c = read(fdIn, in, tor); if (c <= 0) { goto end; } ssize_t w = write(fdOut, in, c); if (w > 0) written += w; if (w != c) { goto end; } size -= c; } end: *off += written; return 0; } #endif #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size ) { ssize_t ret; off_t len = size; ret = sendfile( fdIn, fdOut, *off, &len, NULL, 0 ); if (( ret == 0 )&&( len > 0 )) { ret = len; *off += len; } return ret; } #endif #if defined(sun) || defined(__sun) #include ssize_t gsendfile( int fdOut, int fdIn, off_t *off, size_t size ) { int n = 0 ; sendfilevec_t vec[1]; vec[n].sfv_fd = fdIn; vec[n].sfv_flag = 0; vec[n].sfv_off = *off; vec[n].sfv_len = size; ++n; size_t written; ssize_t ret = sendfilev( fdOut, vec, n, &written ); if (( !ret )||( errno == EAGAIN )) ret = written; if ( ret > 0 ) *off += ret; return ret; } #endif #if defined(linux) || defined(__linux) || defined(__linux__) || \ defined(__gnu_linux__) #include #define gsendfile sendfile #endif #if defined(HPUX) ssize_t gsendfile( int fdOut, int fdIn, off_t * off, size_t size ) { return sendfile( fdOut, fdIn, off, size, NULL, 0 ); } #endif ssize_t LSAPI_sendfile_r( LSAPI_Request * pReq, int fdIn, off_t* off, size_t size ) { struct lsapi_packet_header * pHeader = pReq->m_respPktHeader; if ( !pReq || (pReq->m_fd == -1) || fdIn == -1 ) return -1; if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) { LSAPI_FinalizeRespHeaders_r( pReq ); } pReq->m_reqState |= LSAPI_ST_RESP_BODY; LSAPI_Flush_r(pReq); lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM, size + LSAPI_PACKET_HEADER_LEN ); if (write(pReq->m_fd, (const char *) pHeader, LSAPI_PACKET_HEADER_LEN ) != LSAPI_PACKET_HEADER_LEN) return -1; return gsendfile( pReq->m_fd, fdIn, off, size ); } void Flush_RespBuf_r( LSAPI_Request * pReq ) { struct lsapi_packet_header * pHeader = pReq->m_respPktHeader; int bufLen = pReq->m_pRespBufPos - pReq->m_pRespBuf; pReq->m_reqState |= LSAPI_ST_RESP_BODY; lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM, bufLen + LSAPI_PACKET_HEADER_LEN ); pReq->m_totalLen += bufLen + LSAPI_PACKET_HEADER_LEN; pReq->m_pIovecCur->iov_base = (void *)pHeader; pReq->m_pIovecCur->iov_len = LSAPI_PACKET_HEADER_LEN; ++pReq->m_pIovecCur; ++pHeader; if ( bufLen > 0 ) { pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespBuf; pReq->m_pIovecCur->iov_len = bufLen; pReq->m_pRespBufPos = pReq->m_pRespBuf; ++pReq->m_pIovecCur; bufLen = 0; } } int LSAPI_Flush_r( LSAPI_Request * pReq ) { int ret = 0; int n; if ( !pReq ) return -1; n = pReq->m_pIovecCur - pReq->m_pIovecToWrite; if (( 0 == n )&&( pReq->m_pRespBufPos == pReq->m_pRespBuf )) return 0; if ( pReq->m_fd == -1 ) { pReq->m_pRespBufPos = pReq->m_pRespBuf; pReq->m_totalLen = 0; pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec; return -1; } if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) { LSAPI_FinalizeRespHeaders_r( pReq ); } if ( pReq->m_pRespBufPos != pReq->m_pRespBuf ) { Flush_RespBuf_r( pReq ); } n = pReq->m_pIovecCur - pReq->m_pIovecToWrite; if ( n > 0 ) { ret = lsapi_writev( pReq->m_fd, &pReq->m_pIovecToWrite, n, pReq->m_totalLen ); if ( ret < pReq->m_totalLen ) { lsapi_close_connection(pReq); ret = -1; } pReq->m_totalLen = 0; pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec; } return ret; } ssize_t LSAPI_Write_Stderr_r( LSAPI_Request * pReq, const char * pBuf, size_t len ) { struct lsapi_packet_header header; const char * pEnd; const char * p; ssize_t packetLen; ssize_t totalLen; int ret; struct iovec iov[2]; struct iovec *pIov; if ( !pReq ) return -1; if (s_stderr_log_path || pReq->m_fd == -1 || pReq->m_fd == pReq->m_fdListen) return write( 2, pBuf, len ); if ( pReq->m_pRespBufPos != pReq->m_pRespBuf ) { LSAPI_Flush_r( pReq ); } p = pBuf; pEnd = pBuf + len; while( ( packetLen = pEnd - p ) > 0 ) { if ( LSAPI_MAX_DATA_PACKET_LEN < packetLen) { packetLen = LSAPI_MAX_DATA_PACKET_LEN; } lsapi_buildPacketHeader( &header, LSAPI_STDERR_STREAM, packetLen + LSAPI_PACKET_HEADER_LEN ); totalLen = packetLen + LSAPI_PACKET_HEADER_LEN; iov[0].iov_base = (void *)&header; iov[0].iov_len = LSAPI_PACKET_HEADER_LEN; iov[1].iov_base = (void *)p; iov[1].iov_len = packetLen; p += packetLen; pIov = iov; ret = lsapi_writev( pReq->m_fd, &pIov, 2, totalLen ); if ( ret < totalLen ) { lsapi_close_connection(pReq); ret = -1; } } return p - pBuf; } static char * GetHeaderVar( LSAPI_Request * pReq, const char * name ) { int i; char * pValue; for( i = 0; i < H_TRANSFER_ENCODING; ++i ) { if ( pReq->m_pHeaderIndex->m_headerOff[i] ) { if ( strcmp( name, CGI_HEADERS[i] ) == 0 ) { pValue = pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i]; if ( *(pValue + pReq->m_pHeaderIndex->m_headerLen[i]) != '\0') { *(pValue + pReq->m_pHeaderIndex->m_headerLen[i]) = '\0'; } return pValue; } } } if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 ) { const char *p; char *pKey; char *pKeyEnd; int keyLen; struct lsapi_header_offset * pCur, *pEnd; pCur = pReq->m_pUnknownHeader; pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders; while( pCur < pEnd ) { pKey = pReq->m_pHttpHeader + pCur->nameOff; keyLen = pCur->nameLen; pKeyEnd = pKey + keyLen; p = &name[5]; while(( pKey < pKeyEnd )&&( *p )) { char ch = toupper( *pKey ); if ((ch != *p )||(( *p == '_' )&&( ch != '-'))) break; ++p; ++pKey; } if (( pKey == pKeyEnd )&& (!*p )) { pValue = pReq->m_pHttpHeader + pCur->valueOff; if ( *(pValue + pCur->valueLen) != '\0') { *(pValue + pCur->valueLen) = '\0'; } return pValue; } ++pCur; } } return NULL; } char * LSAPI_GetEnv_r( LSAPI_Request * pReq, const char * name ) { struct LSAPI_key_value_pair * pBegin = pReq->m_pEnvList; struct LSAPI_key_value_pair * pEnd = pBegin + pReq->m_pHeader->m_cntEnv; if ( !pReq || !name ) return NULL; if ( strncmp( name, "HTTP_", 5 ) == 0 ) { return GetHeaderVar( pReq, name ); } while( pBegin < pEnd ) { if ( strcmp( name, pBegin->pKey ) == 0 ) return pBegin->pValue; ++pBegin; } return NULL; } struct _headerInfo { const char * _name; int _nameLen; const char * _value; int _valueLen; }; int compareValueLocation(const void * v1, const void *v2 ) { return ((const struct _headerInfo *)v1)->_value - ((const struct _headerInfo *)v2)->_value; } int LSAPI_ForeachOrgHeader_r( LSAPI_Request * pReq, LSAPI_CB_EnvHandler fn, void * arg ) { int i; int len = 0; char * pValue; int ret; int count = 0; struct _headerInfo headers[512]; if ( !pReq || !fn ) return -1; if ( !pReq->m_pHeaderIndex ) return 0; for( i = 0; i < H_TRANSFER_ENCODING; ++i ) { if ( pReq->m_pHeaderIndex->m_headerOff[i] ) { len = pReq->m_pHeaderIndex->m_headerLen[i]; pValue = pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i]; *(pValue + len ) = 0; headers[count]._name = HTTP_HEADERS[i]; headers[count]._nameLen = HTTP_HEADER_LEN[i]; headers[count]._value = pValue; headers[count]._valueLen = len; ++count; //ret = (*fn)( HTTP_HEADERS[i], HTTP_HEADER_LEN[i], // pValue, len, arg ); //if ( ret <= 0 ) // return ret; } } if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 ) { char *pKey; int keyLen; struct lsapi_header_offset * pCur, *pEnd; pCur = pReq->m_pUnknownHeader; pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders; while( pCur < pEnd ) { pKey = pReq->m_pHttpHeader + pCur->nameOff; keyLen = pCur->nameLen; *(pKey + keyLen ) = 0; pValue = pReq->m_pHttpHeader + pCur->valueOff; *(pValue + pCur->valueLen ) = 0; headers[count]._name = pKey; headers[count]._nameLen = keyLen; headers[count]._value = pValue; headers[count]._valueLen = pCur->valueLen; ++count; if ( count == 512 ) break; //ret = (*fn)( pKey, keyLen, // pValue, pCur->valueLen, arg ); //if ( ret <= 0 ) // return ret; ++pCur; } } qsort( headers, count, sizeof( struct _headerInfo ), compareValueLocation ); for( i = 0; i < count; ++i ) { ret = (*fn)( headers[i]._name, headers[i]._nameLen, headers[i]._value, headers[i]._valueLen, arg ); if ( ret <= 0 ) return ret; } return count; } int LSAPI_ForeachHeader_r( LSAPI_Request * pReq, LSAPI_CB_EnvHandler fn, void * arg ) { int i; int len = 0; char * pValue; int ret; int count = 0; if ( !pReq || !fn ) return -1; for( i = 0; i < H_TRANSFER_ENCODING; ++i ) { if ( pReq->m_pHeaderIndex->m_headerOff[i] ) { len = pReq->m_pHeaderIndex->m_headerLen[i]; pValue = pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i]; *(pValue + len ) = 0; ret = (*fn)( CGI_HEADERS[i], CGI_HEADER_LEN[i], pValue, len, arg ); ++count; if ( ret <= 0 ) return ret; } } if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 ) { char achHeaderName[256]; char *p; char *pKey; char *pKeyEnd ; int keyLen; struct lsapi_header_offset * pCur, *pEnd; pCur = pReq->m_pUnknownHeader; pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders; while( pCur < pEnd ) { pKey = pReq->m_pHttpHeader + pCur->nameOff; keyLen = pCur->nameLen; if ( keyLen > 250 ) keyLen = 250; pKeyEnd = pKey + keyLen; memcpy( achHeaderName, "HTTP_", 5 ); p = &achHeaderName[5]; while( pKey < pKeyEnd ) { char ch = *pKey++; if ( ch == '-' ) *p++ = '_'; else *p++ = toupper( ch ); } *p = 0; keyLen += 5; pValue = pReq->m_pHttpHeader + pCur->valueOff; *(pValue + pCur->valueLen ) = 0; ret = (*fn)( achHeaderName, keyLen, pValue, pCur->valueLen, arg ); if ( ret <= 0 ) return ret; ++pCur; } } return count + pReq->m_pHeader->m_cntUnknownHeaders; } static int EnvForeach( struct LSAPI_key_value_pair * pEnv, int n, LSAPI_CB_EnvHandler fn, void * arg ) { struct LSAPI_key_value_pair * pEnd = pEnv + n; int ret; if ( !pEnv || !fn ) return -1; while( pEnv < pEnd ) { ret = (*fn)( pEnv->pKey, pEnv->keyLen, pEnv->pValue, pEnv->valLen, arg ); if ( ret <= 0 ) return ret; ++pEnv; } return n; } int LSAPI_ForeachEnv_r( LSAPI_Request * pReq, LSAPI_CB_EnvHandler fn, void * arg ) { if ( !pReq || !fn ) return -1; if ( pReq->m_pHeader->m_cntEnv > 0 ) { return EnvForeach( pReq->m_pEnvList, pReq->m_pHeader->m_cntEnv, fn, arg ); } return 0; } int LSAPI_ForeachSpecialEnv_r( LSAPI_Request * pReq, LSAPI_CB_EnvHandler fn, void * arg ) { if ( !pReq || !fn ) return -1; if ( pReq->m_pHeader->m_cntSpecialEnv > 0 ) { return EnvForeach( pReq->m_pSpecialEnvList, pReq->m_pHeader->m_cntSpecialEnv, fn, arg ); } return 0; } int LSAPI_FinalizeRespHeaders_r( LSAPI_Request * pReq ) { if ( !pReq || !pReq->m_pIovec ) return -1; if ( !( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) ) return 0; pReq->m_reqState &= ~LSAPI_ST_RESP_HEADER; if ( pReq->m_pRespHeaderBufPos > pReq->m_pRespHeaderBuf ) { pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespHeaderBuf; pReq->m_pIovecCur->iov_len = pReq->m_pRespHeaderBufPos - pReq->m_pRespHeaderBuf; pReq->m_totalLen += pReq->m_pIovecCur->iov_len; ++pReq->m_pIovecCur; } pReq->m_pIovec->iov_len = sizeof( struct lsapi_resp_header) + pReq->m_respHeader.m_respInfo.m_cntHeaders * sizeof( short ); pReq->m_totalLen += pReq->m_pIovec->iov_len; lsapi_buildPacketHeader( &pReq->m_respHeader.m_pktHeader, LSAPI_RESP_HEADER, pReq->m_totalLen ); pReq->m_pIovec->iov_base = (void *)&pReq->m_respHeader; pReq->m_pIovecToWrite = pReq->m_pIovec; return 0; } int LSAPI_AppendRespHeader2_r( LSAPI_Request * pReq, const char * pHeaderName, const char * pHeaderValue ) { int nameLen, valLen, len; if ( !pReq || !pHeaderName || !pHeaderValue ) return -1; if ( pReq->m_reqState & LSAPI_ST_RESP_BODY ) return -1; if ( pReq->m_respHeader.m_respInfo.m_cntHeaders >= LSAPI_MAX_RESP_HEADERS ) return -1; nameLen = strlen( pHeaderName ); valLen = strlen( pHeaderValue ); if ( nameLen == 0 ) return -1; while( nameLen > 0 ) { char ch = *(pHeaderName + nameLen - 1 ); if (( ch == '\n' )||( ch == '\r' )) --nameLen; else break; } if ( nameLen <= 0 ) return 0; while( valLen > 0 ) { char ch = *(pHeaderValue + valLen - 1 ); if (( ch == '\n' )||( ch == '\r' )) --valLen; else break; } len = nameLen + valLen + 1; if ( len > LSAPI_RESP_HTTP_HEADER_MAX ) return -1; if ( pReq->m_pRespHeaderBufPos + len + 1 > pReq->m_pRespHeaderBufEnd ) { int newlen = pReq->m_pRespHeaderBufPos + len + 4096 - pReq->m_pRespHeaderBuf; newlen -= newlen % 4096; if ( allocateRespHeaderBuf( pReq, newlen ) == -1 ) return -1; } memmove( pReq->m_pRespHeaderBufPos, pHeaderName, nameLen ); pReq->m_pRespHeaderBufPos += nameLen; *pReq->m_pRespHeaderBufPos++ = ':'; memmove( pReq->m_pRespHeaderBufPos, pHeaderValue, valLen ); pReq->m_pRespHeaderBufPos += valLen; *pReq->m_pRespHeaderBufPos++ = 0; ++len; /* add one byte padding for \0 */ pReq->m_respHeaderLen[pReq->m_respHeader.m_respInfo.m_cntHeaders] = len; ++pReq->m_respHeader.m_respInfo.m_cntHeaders; return 0; } int LSAPI_AppendRespHeader_r( LSAPI_Request * pReq, const char * pBuf, int len ) { if ( !pReq || !pBuf || len <= 0 || len > LSAPI_RESP_HTTP_HEADER_MAX ) return -1; if ( pReq->m_reqState & LSAPI_ST_RESP_BODY ) return -1; if ( pReq->m_respHeader.m_respInfo.m_cntHeaders >= LSAPI_MAX_RESP_HEADERS ) return -1; while( len > 0 ) { char ch = *(pBuf + len - 1 ); if (( ch == '\n' )||( ch == '\r' )) --len; else break; } if ( len <= 0 ) return 0; if ( pReq->m_pRespHeaderBufPos + len + 1 > pReq->m_pRespHeaderBufEnd ) { int newlen = pReq->m_pRespHeaderBufPos + len + 4096 - pReq->m_pRespHeaderBuf; newlen -= newlen % 4096; if ( allocateRespHeaderBuf( pReq, newlen ) == -1 ) return -1; } memmove( pReq->m_pRespHeaderBufPos, pBuf, len ); pReq->m_pRespHeaderBufPos += len; *pReq->m_pRespHeaderBufPos++ = 0; ++len; /* add one byte padding for \0 */ pReq->m_respHeaderLen[pReq->m_respHeader.m_respInfo.m_cntHeaders] = len; ++pReq->m_respHeader.m_respInfo.m_cntHeaders; return 0; } int LSAPI_CreateListenSock2( const struct sockaddr * pServerAddr, int backlog ) { int ret; int fd; int flag = 1; int addr_len; switch( pServerAddr->sa_family ) { case AF_INET: addr_len = 16; break; case AF_INET6: addr_len = sizeof( struct sockaddr_in6 ); break; case AF_UNIX: addr_len = sizeof( struct sockaddr_un ); unlink( ((struct sockaddr_un *)pServerAddr)->sun_path ); break; default: return -1; } fd = socket( pServerAddr->sa_family, SOCK_STREAM, 0 ); if ( fd == -1 ) return -1; fcntl( fd, F_SETFD, FD_CLOEXEC ); if(setsockopt( fd, SOL_SOCKET, SO_REUSEADDR, (char *)( &flag ), sizeof(flag)) == 0) { ret = bind( fd, pServerAddr, addr_len ); if ( !ret ) { ret = listen( fd, backlog ); if ( !ret ) return fd; } } ret = errno; close(fd); errno = ret; return -1; } int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr ) { char achAddr[256]; char * p = achAddr; char * pEnd; struct addrinfo *res, hints; int doAddrInfo = 0; int port; if ( !pBind ) return -1; while( isspace( *pBind ) ) ++pBind; strncpy(achAddr, pBind, 255); achAddr[255] = 0; switch( *p ) { case '/': pAddr->sa_family = AF_UNIX; strncpy( ((struct sockaddr_un *)pAddr)->sun_path, p, sizeof(((struct sockaddr_un *)pAddr)->sun_path) ); return 0; case '[': pAddr->sa_family = AF_INET6; ++p; pEnd = strchr( p, ']' ); if ( !pEnd ) return -1; *pEnd++ = 0; if ( *p == '*' ) { strcpy( achAddr, "::" ); p = achAddr; } doAddrInfo = 1; break; default: pAddr->sa_family = AF_INET; pEnd = strchr( p, ':' ); if ( !pEnd ) return -1; *pEnd++ = 0; doAddrInfo = 0; if ( *p == '*' ) { ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = htonl(INADDR_ANY); } else if (!strcasecmp( p, "localhost" ) ) ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = htonl( INADDR_LOOPBACK ); else { #ifdef HAVE_INET_PTON if (!inet_pton(AF_INET, p, &((struct sockaddr_in *)pAddr)->sin_addr)) #else ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = inet_addr( p ); if ( ((struct sockaddr_in *)pAddr)->sin_addr.s_addr == INADDR_BROADCAST) #endif { doAddrInfo = 1; } } break; } if ( *pEnd == ':' ) ++pEnd; port = atoi( pEnd ); if (( port <= 0 )||( port > 65535 )) return -1; if ( doAddrInfo ) { memset(&hints, 0, sizeof(hints)); hints.ai_family = pAddr->sa_family; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; if ( getaddrinfo(p, NULL, &hints, &res) ) { return -1; } memcpy(pAddr, res->ai_addr, res->ai_addrlen); freeaddrinfo(res); } if ( pAddr->sa_family == AF_INET ) ((struct sockaddr_in *)pAddr)->sin_port = htons( port ); else ((struct sockaddr_in6 *)pAddr)->sin6_port = htons( port ); return 0; } int LSAPI_CreateListenSock( const char * pBind, int backlog ) { char serverAddr[128]; int ret; int fd = -1; ret = LSAPI_ParseSockAddr( pBind, (struct sockaddr *)serverAddr ); if ( !ret ) { fd = LSAPI_CreateListenSock2( (struct sockaddr *)serverAddr, backlog ); } return fd; } static fn_select_t g_fnSelect = select; typedef struct _lsapi_prefork_server { int m_fd; int m_iMaxChildren; int m_iExtraChildren; int m_iCurChildren; int m_iMaxIdleChildren; int m_iServerMaxIdle; int m_iChildrenMaxIdleTime; int m_iMaxReqProcessTime; int m_iAvoidFork; lsapi_child_status * m_pChildrenStatus; lsapi_child_status * m_pChildrenStatusCur; lsapi_child_status * m_pChildrenStatusEnd; }lsapi_prefork_server; static lsapi_prefork_server * g_prefork_server = NULL; int LSAPI_Init_Prefork_Server( int max_children, fn_select_t fp, int avoidFork ) { if ( g_prefork_server ) return 0; if ( max_children <= 1 ) return -1; if ( max_children >= 10000) max_children = 10000; if (s_max_busy_workers == 0) s_max_busy_workers = max_children / 2 + 1; g_prefork_server = (lsapi_prefork_server *)malloc( sizeof( lsapi_prefork_server ) ); if ( !g_prefork_server ) return -1; memset( g_prefork_server, 0, sizeof( lsapi_prefork_server ) ); if ( fp != NULL ) g_fnSelect = fp; s_ppid = getppid(); s_pid = getpid(); setpgid( s_pid, s_pid ); #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) s_total_pages = sysconf(_SC_PHYS_PAGES); #endif g_prefork_server->m_iAvoidFork = avoidFork; g_prefork_server->m_iMaxChildren = max_children; g_prefork_server->m_iExtraChildren = ( avoidFork ) ? 0 : (max_children / 3) ; g_prefork_server->m_iMaxIdleChildren = ( avoidFork ) ? (max_children + 1) : (max_children / 3); if ( g_prefork_server->m_iMaxIdleChildren == 0 ) g_prefork_server->m_iMaxIdleChildren = 1; g_prefork_server->m_iChildrenMaxIdleTime = 300; g_prefork_server->m_iMaxReqProcessTime = 3600; setsid(); return 0; } void LSAPI_Set_Server_fd( int fd ) { if( g_prefork_server ) g_prefork_server->m_fd = fd; } static int lsapi_accept( int fdListen ) { int fd; int nodelay = 1; socklen_t len; char achPeer[128]; len = sizeof( achPeer ); fd = accept( fdListen, (struct sockaddr *)&achPeer, &len ); if ( fd != -1 ) { if (((struct sockaddr *)&achPeer)->sa_family == AF_INET ) { setsockopt( fd, IPPROTO_TCP, TCP_NODELAY, (char *)&nodelay, sizeof(nodelay)); } //OPTIMIZATION //if ( s_accept_notify ) // notify_req_received( fd ); } return fd; } static unsigned int s_max_reqs = UINT_MAX; static int s_max_idle_secs = 300; static int s_stop; static void lsapi_cleanup(int signal) { s_stop = signal; } static lsapi_child_status * find_child_status( int pid ) { lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus; lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatusEnd; while( pStatus < pEnd ) { if ( pStatus->m_pid == pid ) { if (pid == 0) { memset(pStatus, 0, sizeof( *pStatus ) ); pStatus->m_pid = -1; } if ( pStatus + 1 > g_prefork_server->m_pChildrenStatusCur ) g_prefork_server->m_pChildrenStatusCur = pStatus + 1; return pStatus; } ++pStatus; } return NULL; } void LSAPI_reset_server_state( void ) { /* Reset child status */ g_prefork_server->m_iCurChildren = 0; lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus; lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatusEnd; while( pStatus < pEnd ) { pStatus->m_pid = 0; ++pStatus; } if (s_busy_workers) __atomic_store_n(s_busy_workers, 0, __ATOMIC_SEQ_CST); if (s_accepting_workers) __atomic_store_n(s_accepting_workers, 0, __ATOMIC_SEQ_CST); } static void lsapi_sigchild( int signal ) { int status, pid; char expect_connected = LSAPI_STATE_CONNECTED; char expect_accepting = LSAPI_STATE_ACCEPTING; lsapi_child_status * child_status; if (g_prefork_server == NULL) return; while( 1 ) { pid = waitpid( -1, &status, WNOHANG|WUNTRACED ); if ( pid <= 0 ) { break; } if ( WIFSIGNALED( status )) { int sig_num = WTERMSIG( status ); #ifdef WCOREDUMP const char * dump = WCOREDUMP( status ) ? "yes" : "no"; #else const char * dump = "unknown"; #endif lsapi_log("Child process with pid: %d was killed by signal: " "%d, core dumped: %s\n", pid, sig_num, dump ); } if ( pid == s_pid_dump_debug_info ) { pid = 0; continue; } if ( pid == s_ignore_pid ) { pid = 0; s_ignore_pid = -1; continue; } child_status = find_child_status( pid ); if ( child_status ) { if (__atomic_compare_exchange_n(&child_status->m_state, &expect_connected, LSAPI_STATE_IDLE, 1, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) { if (s_busy_workers) __atomic_fetch_sub(s_busy_workers, 1, __ATOMIC_SEQ_CST); } else if (__atomic_compare_exchange_n(&child_status->m_state, &expect_accepting, LSAPI_STATE_IDLE, 1, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) { if (s_accepting_workers) __atomic_fetch_sub(s_accepting_workers, 1, __ATOMIC_SEQ_CST); } child_status->m_pid = 0; --g_prefork_server->m_iCurChildren; } } while(( g_prefork_server->m_pChildrenStatusCur > g_prefork_server->m_pChildrenStatus ) &&( g_prefork_server->m_pChildrenStatusCur[-1].m_pid == 0 )) --g_prefork_server->m_pChildrenStatusCur; } static int lsapi_init_children_status(void) { char * pBuf; int size = 4096; int max_children; if (g_prefork_server->m_pChildrenStatus) return 0; max_children = g_prefork_server->m_iMaxChildren + g_prefork_server->m_iExtraChildren; size = max_children * sizeof( lsapi_child_status ) * 2 + 3 * sizeof(int); size = (size + 4095) / 4096 * 4096; pBuf =( char*) mmap( NULL, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0 ); if ( pBuf == MAP_FAILED ) { perror( "Anonymous mmap() failed" ); return -1; } memset( pBuf, 0, size ); g_prefork_server->m_pChildrenStatus = (lsapi_child_status *)pBuf; g_prefork_server->m_pChildrenStatusCur = (lsapi_child_status *)pBuf; g_prefork_server->m_pChildrenStatusEnd = (lsapi_child_status *)pBuf + max_children; s_busy_workers = (int *)g_prefork_server->m_pChildrenStatusEnd; s_accepting_workers = s_busy_workers + 1; s_global_counter = s_accepting_workers + 1; s_avail_pages = (size_t *)(s_global_counter + 1); setsid(); return 0; } static void dump_debug_info( lsapi_child_status * pStatus, long tmCur ) { char achCmd[1024]; if ( s_pid_dump_debug_info ) { if ( kill( s_pid_dump_debug_info, 0 ) == 0 ) return; } lsapi_log("Possible runaway process, UID: %d, PPID: %d, PID: %d, " "reqCount: %d, process time: %ld, checkpoint time: %ld, start " "time: %ld\n", getuid(), getppid(), pStatus->m_pid, pStatus->m_iReqCounter, tmCur - pStatus->m_tmReqBegin, tmCur - pStatus->m_tmLastCheckPoint, tmCur - pStatus->m_tmStart ); s_pid_dump_debug_info = fork(); if (s_pid_dump_debug_info == 0) { snprintf( achCmd, 1024, "gdb --batch -ex \"attach %d\" -ex \"set height 0\" " "-ex \"bt\" >&2;PATH=$PATH:/usr/sbin lsof -p %d >&2", pStatus->m_pid, pStatus->m_pid ); if ( system( achCmd ) == -1 ) perror( "system()" ); exit( 0 ); } } static void lsapi_check_child_status( long tmCur ) { int idle = 0; int tobekilled; int dying = 0; int count = 0; lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus; lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatusCur; while( pStatus < pEnd ) { tobekilled = 0; if ( pStatus->m_pid != 0 && pStatus->m_pid != -1) { ++count; if ( !pStatus->m_inProcess ) { if (g_prefork_server->m_iCurChildren - dying > g_prefork_server->m_iMaxChildren || idle > g_prefork_server->m_iMaxIdleChildren) { ++pStatus->m_iKillSent; //tobekilled = SIGUSR1; } else { if (s_max_idle_secs> 0 && tmCur - pStatus->m_tmWaitBegin > s_max_idle_secs + 5) { ++pStatus->m_iKillSent; //tobekilled = SIGUSR1; } } if (!pStatus->m_iKillSent) ++idle; } else { if (tmCur - pStatus->m_tmReqBegin > g_prefork_server->m_iMaxReqProcessTime) { if ((pStatus->m_iKillSent % 5) == 0 && s_dump_debug_info) dump_debug_info( pStatus, tmCur ); if ( pStatus->m_iKillSent > 5 ) { tobekilled = SIGKILL; lsapi_log("Force killing runaway process PID: %d" " with SIGKILL\n", pStatus->m_pid ); } else { tobekilled = SIGTERM; lsapi_log("Killing runaway process PID: %d with " "SIGTERM\n", pStatus->m_pid ); } } } if ( tobekilled ) { if (( kill( pStatus->m_pid, tobekilled ) == -1 ) && ( errno == ESRCH )) { pStatus->m_pid = 0; --count; } else { ++pStatus->m_iKillSent; ++dying; } } } ++pStatus; } if ( abs( g_prefork_server->m_iCurChildren - count ) > 1 ) { lsapi_log("Children tracking is wrong: Cur Children: %d," " count: %d, idle: %d, dying: %d\n", g_prefork_server->m_iCurChildren, count, idle, dying ); } } //static int lsapi_all_children_must_die(void) //{ // int maxWait; // int sec =0; // g_prefork_server->m_iMaxReqProcessTime = 10; // g_prefork_server->m_iMaxIdleChildren = -1; // maxWait = 15; // // while( g_prefork_server->m_iCurChildren && (sec < maxWait) ) // { // lsapi_check_child_status(time(NULL)); // sleep( 1 ); // sec++; // } // if ( g_prefork_server->m_iCurChildren != 0 ) // kill( -getpgrp(), SIGKILL ); // return 0; //} void set_skip_write(void) { s_skip_write = 1; } int is_enough_free_mem(void) { #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) //minimum 1GB or 10% available free memory return (*s_avail_pages > s_min_avail_pages || (*s_avail_pages * 10) / s_total_pages > 0); #endif return 1; } static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, LSAPI_Request * pReq ) { struct sigaction act, old_term, old_quit, old_int, old_usr1, old_child; lsapi_child_status * child_status; int wait_secs = 0; int ret = 0; int pid; time_t lastTime = 0; time_t curTime = 0; fd_set readfds; struct timeval timeout; sigset_t mask; sigset_t orig_mask; lsapi_init_children_status(); act.sa_flags = 0; act.sa_handler = lsapi_sigchild; sigemptyset(&(act.sa_mask)); if( sigaction( SIGCHLD, &act, &old_child ) ) { perror( "Can't set signal handler for SIGCHILD" ); return -1; } /* Set up handler to kill children upon exit */ act.sa_flags = 0; act.sa_handler = lsapi_cleanup; sigemptyset(&(act.sa_mask)); if( sigaction( SIGTERM, &act, &old_term ) || sigaction( SIGINT, &act, &old_int ) || sigaction( SIGUSR1, &act, &old_usr1 ) || sigaction( SIGQUIT, &act, &old_quit )) { perror( "Can't set signals" ); return -1; } while( !s_stop ) { if (s_proc_group_timer_cb != NULL) { s_proc_group_timer_cb(&s_ignore_pid); } curTime = time( NULL ); if (curTime != lastTime ) { lastTime = curTime; if (lsapi_parent_dead()) break; lsapi_check_child_status(curTime ); if (pServer->m_iServerMaxIdle) { if ( pServer->m_iCurChildren <= 0 ) { ++wait_secs; if ( wait_secs > pServer->m_iServerMaxIdle ) return -1; } else wait_secs = 0; } } #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) *s_avail_pages = sysconf(_SC_AVPHYS_PAGES); // lsapi_log("Memory total: %zd, free: %zd, free %%%zd\n", // s_total_pages, *s_avail_pages, *s_avail_pages * 100 / s_total_pages); #endif FD_ZERO( &readfds ); FD_SET( pServer->m_fd, &readfds ); timeout.tv_sec = 1; timeout.tv_usec = 0; ret = (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout); if (ret == 1 ) { int accepting = 0; if (s_accepting_workers) accepting = __atomic_load_n(s_accepting_workers, __ATOMIC_SEQ_CST); if (pServer->m_iCurChildren > 0 && accepting > 0) { usleep(400); while(accepting-- > 0) sched_yield(); continue; } } else if ( ret == -1 ) { if ( errno == EINTR ) continue; /* perror( "select()" ); */ break; } else { continue; } if (pServer->m_iCurChildren >= pServer->m_iMaxChildren + pServer->m_iExtraChildren) { lsapi_log("Reached max children process limit: %d, extra: %d," " current: %d, busy: %d, please increase LSAPI_CHILDREN.\n", pServer->m_iMaxChildren, pServer->m_iExtraChildren, pServer->m_iCurChildren, s_busy_workers ? *s_busy_workers : -1 ); usleep( 100000 ); continue; } pReq->m_fd = lsapi_accept( pServer->m_fd ); if ( pReq->m_fd != -1 ) { wait_secs = 0; child_status = find_child_status( 0 ); sigemptyset( &mask ); sigaddset( &mask, SIGCHLD ); if ( sigprocmask(SIG_BLOCK, &mask, &orig_mask) < 0 ) { perror( "sigprocmask(SIG_BLOCK) to block SIGCHLD" ); } pid = fork(); if ( !pid ) { setsid(); if (sigprocmask(SIG_SETMASK, &orig_mask, NULL) < 0) perror( "sigprocmask( SIG_SETMASK ) to restore SIGMASK in child" ); g_prefork_server = NULL; s_ppid = getppid(); s_pid = getpid(); s_req_processed = 0; s_proc_group_timer_cb = NULL; s_worker_status = child_status; if (pthread_atfork_func) (*pthread_atfork_func)(NULL, NULL, set_skip_write); __atomic_store_n(&s_worker_status->m_state, LSAPI_STATE_CONNECTED, __ATOMIC_SEQ_CST); if (s_busy_workers) __atomic_add_fetch(s_busy_workers, 1, __ATOMIC_SEQ_CST); lsapi_set_nblock( pReq->m_fd, 0 ); //keep it open if busy_count is used. if (!s_keep_listener && s_busy_workers && *s_busy_workers > (pServer->m_iMaxChildren >> 1)) s_keep_listener = 1; if ((s_uid == 0 || !s_keep_listener || !is_enough_free_mem()) && pReq->m_fdListen != -1 ) { close( pReq->m_fdListen ); pReq->m_fdListen = -1; } /* don't catch our signals */ sigaction( SIGCHLD, &old_child, 0 ); sigaction( SIGTERM, &old_term, 0 ); sigaction( SIGQUIT, &old_quit, 0 ); sigaction( SIGINT, &old_int, 0 ); sigaction( SIGUSR1, &old_usr1, 0 ); //init_conn_key( pReq->m_fd ); lsapi_notify_pid( pReq->m_fd ); s_notified_pid = 1; //if ( s_accept_notify ) // return notify_req_received( pReq->m_fd ); return 0; } else if ( pid == -1 ) { lsapi_perror("fork() failed, please increase process limit", errno); if (child_status) child_status->m_pid = 0; } else { ++pServer->m_iCurChildren; if ( child_status ) { child_status->m_pid = pid; child_status->m_tmWaitBegin = curTime; child_status->m_tmStart = curTime; } } close( pReq->m_fd ); pReq->m_fd = -1; if (sigprocmask(SIG_SETMASK, &orig_mask, NULL) < 0) perror( "sigprocmask( SIG_SETMASK ) to restore SIGMASK" ); } else { if (( errno == EINTR )||( errno == EAGAIN)) continue; lsapi_perror("accept() failed", errno); return -1; } } sigaction( SIGUSR1, &old_usr1, 0 ); //kill( -getpgrp(), SIGUSR1 ); //lsapi_all_children_must_die(); /* Sorry, children ;-) */ return -1; } static struct sigaction old_term, old_quit, old_int, old_usr1, old_child; int LSAPI_Postfork_Child(LSAPI_Request * pReq) { int max_children = g_prefork_server->m_iMaxChildren; s_pid = getpid(); __atomic_store_n(&pReq->child_status->m_pid, s_pid, __ATOMIC_SEQ_CST); s_worker_status = pReq->child_status; setsid(); g_prefork_server = NULL; s_ppid = getppid(); s_req_processed = 0; s_proc_group_timer_cb = NULL; if (pthread_atfork_func) (*pthread_atfork_func)(NULL, NULL, set_skip_write); __atomic_store_n(&s_worker_status->m_state, LSAPI_STATE_CONNECTED, __ATOMIC_SEQ_CST); if (s_busy_workers) __atomic_add_fetch(s_busy_workers, 1, __ATOMIC_SEQ_CST); lsapi_set_nblock( pReq->m_fd, 0 ); //keep it open if busy_count is used. if (!s_keep_listener && s_busy_workers && *s_busy_workers > (max_children >> 1)) s_keep_listener = 1; if ((s_uid == 0 || !s_keep_listener || !is_enough_free_mem()) && pReq->m_fdListen != -1 ) { close(pReq->m_fdListen); pReq->m_fdListen = -1; } //init_conn_key( pReq->m_fd ); lsapi_notify_pid(pReq->m_fd); s_notified_pid = 1; //if ( s_accept_notify ) // return notify_req_received( pReq->m_fd ); return 0; } int LSAPI_Postfork_Parent(LSAPI_Request * pReq) { ++g_prefork_server->m_iCurChildren; if (pReq->child_status) { time_t curTime = time( NULL ); pReq->child_status->m_tmWaitBegin = curTime; pReq->child_status->m_tmStart = curTime; } close(pReq->m_fd); pReq->m_fd = -1; return 0; } int LSAPI_Accept_Before_Fork(LSAPI_Request * pReq) { time_t lastTime = 0; time_t curTime = 0; fd_set readfds; struct timeval timeout; int wait_secs = 0; int ret = 0; lsapi_prefork_server * pServer = g_prefork_server; struct sigaction act; lsapi_init_children_status(); act.sa_flags = 0; act.sa_handler = lsapi_sigchild; sigemptyset(&(act.sa_mask)); if (sigaction(SIGCHLD, &act, &old_child)) { perror( "Can't set signal handler for SIGCHILD" ); return -1; } /* Set up handler to kill children upon exit */ act.sa_flags = 0; act.sa_handler = lsapi_cleanup; sigemptyset(&(act.sa_mask)); if (sigaction(SIGTERM, &act, &old_term) || sigaction(SIGINT, &act, &old_int ) || sigaction(SIGUSR1, &act, &old_usr1) || sigaction(SIGQUIT, &act, &old_quit)) { perror( "Can't set signals" ); return -1; } s_stop = 0; pReq->m_reqState = 0; while(!s_stop) { if (s_proc_group_timer_cb != NULL) { s_proc_group_timer_cb(&s_ignore_pid); } curTime = time(NULL); if (curTime != lastTime) { lastTime = curTime; if (lsapi_parent_dead()) break; lsapi_check_child_status(curTime); if (pServer->m_iServerMaxIdle) { if (pServer->m_iCurChildren <= 0) { ++wait_secs; if ( wait_secs > pServer->m_iServerMaxIdle ) return -1; } else wait_secs = 0; } } #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) *s_avail_pages = sysconf(_SC_AVPHYS_PAGES); // lsapi_log("Memory total: %zd, free: %zd, free %%%zd\n", // s_total_pages, *s_avail_pages, *s_avail_pages * 100 / s_total_pages); #endif FD_ZERO(&readfds); FD_SET(pServer->m_fd, &readfds); timeout.tv_sec = 1; timeout.tv_usec = 0; ret = (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout); if (ret == 1 ) { int accepting = 0; if (s_accepting_workers) accepting = __atomic_load_n(s_accepting_workers, __ATOMIC_SEQ_CST); if (pServer->m_iCurChildren > 0 && accepting > 0) { usleep( 400); while(accepting-- > 0) sched_yield(); continue; } } else if (ret == -1) { if (errno == EINTR) continue; /* perror( "select()" ); */ break; } else { continue; } if (pServer->m_iCurChildren >= pServer->m_iMaxChildren + pServer->m_iExtraChildren) { lsapi_log("Reached max children process limit: %d, extra: %d," " current: %d, busy: %d, please increase LSAPI_CHILDREN.\n", pServer->m_iMaxChildren, pServer->m_iExtraChildren, pServer->m_iCurChildren, s_busy_workers ? *s_busy_workers : -1); usleep(100000); continue; } pReq->m_fd = lsapi_accept(pServer->m_fd); if (pReq->m_fd != -1) { wait_secs = 0; pReq->child_status = find_child_status(0); ret = 0; break; } else { if ((errno == EINTR) || (errno == EAGAIN)) continue; lsapi_perror("accept() failed", errno); ret = -1; break; } } sigaction(SIGCHLD, &old_child, 0); sigaction(SIGTERM, &old_term, 0); sigaction(SIGQUIT, &old_quit, 0); sigaction(SIGINT, &old_int, 0); sigaction(SIGUSR1, &old_usr1, 0); return ret; } int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq ) { int fd; int ret; int wait_secs; fd_set readfds; struct timeval timeout; if (s_skip_write) return -1; LSAPI_Finish_r( pReq ); if ( g_prefork_server ) { if ( g_prefork_server->m_fd != -1 ) if ( lsapi_prefork_server_accept( g_prefork_server, pReq ) == -1 ) return -1; } else if (s_req_processed > 0 && s_max_busy_workers > 0 && s_busy_workers) { ret = __atomic_load_n(s_busy_workers, __ATOMIC_SEQ_CST); if (ret >= s_max_busy_workers) { send_conn_close_notification(pReq->m_fd); lsapi_close_connection(pReq); } } if ( (unsigned int)s_req_processed > s_max_reqs ) return -1; if ( s_worker_status ) { s_worker_status->m_tmWaitBegin = time( NULL ); } while( g_running ) { if ( pReq->m_fd != -1 ) { fd = pReq->m_fd; } else if ( pReq->m_fdListen != -1 ) fd = pReq->m_fdListen; else { break; } wait_secs = 0; while( 1 ) { if ( !g_running ) return -1; if (s_req_processed && s_worker_status && s_worker_status->m_iKillSent) return -1; FD_ZERO( &readfds ); FD_SET( fd, &readfds ); timeout.tv_sec = 1; timeout.tv_usec = 0; if (fd == pReq->m_fdListen) { if (s_worker_status) __atomic_store_n(&s_worker_status->m_state, LSAPI_STATE_ACCEPTING, __ATOMIC_SEQ_CST); if (s_accepting_workers) __atomic_fetch_add(s_accepting_workers, 1, __ATOMIC_SEQ_CST); } ret = (*g_fnSelect)(fd+1, &readfds, NULL, NULL, &timeout); if (fd == pReq->m_fdListen) { if (s_accepting_workers) __atomic_fetch_sub(s_accepting_workers, 1, __ATOMIC_SEQ_CST); if (s_worker_status) __atomic_store_n(&s_worker_status->m_state, LSAPI_STATE_IDLE, __ATOMIC_SEQ_CST); } if ( ret == 0 ) { if ( s_worker_status ) { s_worker_status->m_inProcess = 0; if (fd == pReq->m_fdListen) { if (s_keep_listener == 0 || !is_enough_free_mem()) return -1; if (s_keep_listener == 1) { int wait_time = 10; if (s_busy_workers) wait_time += *s_busy_workers * 10; if (s_accepting_workers) wait_time >>= (*s_accepting_workers); if (wait_secs >= wait_time) return -1; } } } ++wait_secs; if (( s_max_idle_secs > 0 )&&(wait_secs >= s_max_idle_secs )) return -1; if ( lsapi_parent_dead() ) return -1; } else if ( ret == -1 ) { if ( errno == EINTR ) continue; else return -1; } else if ( ret >= 1 ) { if (s_req_processed && s_worker_status && s_worker_status->m_iKillSent) return -1; if ( fd == pReq->m_fdListen ) { pReq->m_fd = lsapi_accept( pReq->m_fdListen ); if ( pReq->m_fd != -1 ) { if (s_worker_status) __atomic_store_n(&s_worker_status->m_state, LSAPI_STATE_CONNECTED, __ATOMIC_SEQ_CST); if (s_busy_workers) __atomic_fetch_add(s_busy_workers, 1, __ATOMIC_SEQ_CST); fd = pReq->m_fd; lsapi_set_nblock( fd, 0 ); //init_conn_key( pReq->m_fd ); if (!s_keep_listener) { close( pReq->m_fdListen ); pReq->m_fdListen = -1; } if ( s_accept_notify ) if ( notify_req_received( pReq->m_fd ) == -1 ) return -1; } else { if (( errno == EINTR )||( errno == EAGAIN)) continue; lsapi_perror( "lsapi_accept() error", errno ); return -1; } } else break; } } if ( !readReq( pReq ) ) { if ( s_worker_status ) { s_worker_status->m_iKillSent = 0; s_worker_status->m_inProcess = 1; ++s_worker_status->m_iReqCounter; s_worker_status->m_tmReqBegin = s_worker_status->m_tmLastCheckPoint = time(NULL); } ++s_req_processed; return 0; } lsapi_close_connection(pReq); LSAPI_Reset_r( pReq ); } return -1; } void LSAPI_Set_Max_Reqs( int reqs ) { s_max_reqs = reqs - 1; } void LSAPI_Set_Max_Idle( int secs ) { s_max_idle_secs = secs; } void LSAPI_Set_Max_Children( int maxChildren ) { if ( g_prefork_server ) g_prefork_server->m_iMaxChildren = maxChildren; } void LSAPI_Set_Extra_Children( int extraChildren ) { if (( g_prefork_server )&&( extraChildren >= 0 )) g_prefork_server->m_iExtraChildren = extraChildren; } void LSAPI_Set_Max_Process_Time( int secs ) { if (( g_prefork_server )&&( secs > 0 )) g_prefork_server->m_iMaxReqProcessTime = secs; } void LSAPI_Set_Max_Idle_Children( int maxIdleChld ) { if (( g_prefork_server )&&( maxIdleChld > 0 )) g_prefork_server->m_iMaxIdleChildren = maxIdleChld; } void LSAPI_Set_Server_Max_Idle_Secs( int serverMaxIdle ) { if ( g_prefork_server ) g_prefork_server->m_iServerMaxIdle = serverMaxIdle; } void LSAPI_Set_Slow_Req_Msecs( int msecs ) { s_slow_req_msecs = msecs; } int LSAPI_Get_Slow_Req_Msecs(void) { return s_slow_req_msecs; } void LSAPI_No_Check_ppid(void) { s_ppid = 0; } int LSAPI_Get_ppid(void) { return(s_ppid); } #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) #include #else extern char ** environ; #endif static void unset_lsapi_envs(void) { char **env; #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) env = *_NSGetEnviron(); #else env = environ; #endif while( env != NULL && *env != NULL ) { if (!strncmp(*env, "LSAPI_", 6) || !strncmp( *env, "PHP_LSAPI_", 10 ) || (!strncmp( *env, "PHPRC=", 6 )&&(!s_uid))) { char ** del = env; do *del = del[1]; while( *del++ ); } else ++env; } } static int lsapi_initSuEXEC(void) { int i; struct passwd * pw; s_defaultUid = 0; s_defaultGid = 0; if ( s_uid == 0 ) { const char * p = getenv( "LSAPI_DEFAULT_UID" ); if ( p ) { i = atoi( p ); if ( i > 0 ) s_defaultUid = i; } p = getenv( "LSAPI_DEFAULT_GID" ); if ( p ) { i = atoi( p ); if ( i > 0 ) s_defaultGid = i; } p = getenv( "LSAPI_SECRET" ); if (( !p )||( readSecret(p) == -1 )) return -1; if ( g_prefork_server ) { if ( g_prefork_server->m_iMaxChildren < 100 ) g_prefork_server->m_iMaxChildren = 100; if ( g_prefork_server->m_iExtraChildren < 1000 ) g_prefork_server->m_iExtraChildren = 1000; } } if ( !s_defaultUid || !s_defaultGid ) { pw = getpwnam( "nobody" ); if ( pw ) { if ( !s_defaultUid ) s_defaultUid = pw->pw_uid; if ( !s_defaultGid ) s_defaultGid = pw->pw_gid; } else { if ( !s_defaultUid ) s_defaultUid = 10000; if ( !s_defaultGid ) s_defaultGid = 10000; } } return 0; } static int lsapi_check_path(const char *p, char *final, int max_len) { char resolved_path[PATH_MAX+1]; int len = 0; char *end; if (*p != '/') { if (getcwd(final, max_len) == NULL) return -1; len = strlen(final); *(final + len) = '/'; ++len; } end = memccpy(&final[len], p, '\0', PATH_MAX - len); if (!end) { errno = EINVAL; return -1; } p = final; if (realpath(p, resolved_path) == NULL && errno != ENOENT && errno != EACCES) return -1; if (strncmp(resolved_path, "/etc/", 5) == 0) { errno = EPERM; return -1; } return 0; } static int lsapi_reopen_stderr2(const char *full_path) { int newfd = open(full_path, O_WRONLY | O_CREAT | O_APPEND, 0644); if (newfd == -1) { LSAPI_perror_r(NULL, "Failed to open custom stderr log", full_path); return -1; } if (newfd != 2) { dup2(newfd, 2); close(newfd); dup2(2, 1); } if (s_stderr_log_path && full_path != s_stderr_log_path) { free(s_stderr_log_path); s_stderr_log_path = NULL; } s_stderr_log_path = strdup(full_path); return 0; } static int lsapi_reopen_stderr(const char *p) { char full_path[PATH_MAX]; if (s_uid == 0) return -1; if (lsapi_check_path(p, full_path, PATH_MAX) == -1) { LSAPI_perror_r(NULL, "Invalid custom stderr log path", p); return -1; } return lsapi_reopen_stderr2(full_path); } int LSAPI_Init_Env_Parameters( fn_select_t fp ) { const char *p; char ch; int n; int avoidFork = 0; p = getenv("LSAPI_STDERR_LOG"); if (p) { lsapi_reopen_stderr(p); } if (!s_stderr_log_path) s_stderr_is_pipe = isPipe(STDERR_FILENO); p = getenv( "PHP_LSAPI_MAX_REQUESTS" ); if ( !p ) p = getenv( "LSAPI_MAX_REQS" ); if ( p ) { n = atoi( p ); if ( n > 0 ) LSAPI_Set_Max_Reqs( n ); } p = getenv( "LSAPI_KEEP_LISTEN" ); if ( p ) { n = atoi( p ); s_keep_listener = n; } p = getenv( "LSAPI_AVOID_FORK" ); if ( p ) { avoidFork = atoi( p ); if (avoidFork) { s_keep_listener = 2; ch = *(p + strlen(p) - 1); if ( ch == 'G' || ch == 'g' ) avoidFork *= 1024 * 1024 * 1024; else if ( ch == 'M' || ch == 'm' ) avoidFork *= 1024 * 1024; if (avoidFork >= 1024 * 10240) s_min_avail_pages = avoidFork / 4096; } } p = getenv( "LSAPI_ACCEPT_NOTIFY" ); if ( p ) { s_accept_notify = atoi( p ); } p = getenv( "LSAPI_SLOW_REQ_MSECS" ); if ( p ) { n = atoi( p ); LSAPI_Set_Slow_Req_Msecs( n ); } #if defined( RLIMIT_CORE ) p = getenv( "LSAPI_ALLOW_CORE_DUMP" ); if ( !p ) { struct rlimit limit = { 0, 0 }; setrlimit( RLIMIT_CORE, &limit ); } else s_enable_core_dump = 1; #endif p = getenv( "LSAPI_MAX_IDLE" ); if ( p ) { n = atoi( p ); LSAPI_Set_Max_Idle( n ); } if ( LSAPI_Is_Listen() ) { n = 0; p = getenv( "PHP_LSAPI_CHILDREN" ); if ( !p ) p = getenv( "LSAPI_CHILDREN" ); if ( p ) n = atoi( p ); if ( n > 1 ) { LSAPI_Init_Prefork_Server( n, fp, avoidFork != 0 ); LSAPI_Set_Server_fd( g_req.m_fdListen ); } p = getenv( "LSAPI_EXTRA_CHILDREN" ); if ( p ) LSAPI_Set_Extra_Children( atoi( p ) ); p = getenv( "LSAPI_MAX_IDLE_CHILDREN" ); if ( p ) LSAPI_Set_Max_Idle_Children( atoi( p ) ); p = getenv( "LSAPI_PGRP_MAX_IDLE" ); if ( p ) { LSAPI_Set_Server_Max_Idle_Secs( atoi( p ) ); } p = getenv( "LSAPI_MAX_PROCESS_TIME" ); if ( p ) LSAPI_Set_Max_Process_Time( atoi( p ) ); if ( getenv( "LSAPI_PPID_NO_CHECK" ) ) { LSAPI_No_Check_ppid(); } p = getenv("LSAPI_MAX_BUSY_WORKER"); if (p) { n = atoi(p); s_max_busy_workers = n; if (n >= 0) LSAPI_No_Check_ppid(); } p = getenv( "LSAPI_DUMP_DEBUG_INFO" ); if ( p ) s_dump_debug_info = atoi( p ); if ( lsapi_initSuEXEC() == -1 ) return -1; #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) lsapi_initLVE(); #endif } unset_lsapi_envs(); return 0; } int LSAPI_ErrResponse_r( LSAPI_Request * pReq, int code, const char ** pRespHeaders, const char * pBody, int bodyLen ) { LSAPI_SetRespStatus_r( pReq, code ); if ( pRespHeaders ) { while( *pRespHeaders ) { LSAPI_AppendRespHeader_r( pReq, *pRespHeaders, strlen( *pRespHeaders ) ); ++pRespHeaders; } } if ( pBody &&( bodyLen > 0 )) { LSAPI_Write_r( pReq, pBody, bodyLen ); } LSAPI_Finish_r( pReq ); return 0; } static void lsapi_MD5Transform(uint32 buf[4], uint32 const in[16]); /* * Note: this code is harmless on little-endian machines. */ static void byteReverse(unsigned char *buf, unsigned longs) { uint32 t; do { t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | ((unsigned) buf[1] << 8 | buf[0]); *(uint32 *) buf = t; buf += 4; } while (--longs); } /* * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious * initialization constants. */ void lsapi_MD5Init(struct lsapi_MD5Context *ctx) { ctx->buf[0] = 0x67452301; ctx->buf[1] = 0xefcdab89; ctx->buf[2] = 0x98badcfe; ctx->buf[3] = 0x10325476; ctx->bits[0] = 0; ctx->bits[1] = 0; } /* * Update context to reflect the concatenation of another buffer full * of bytes. */ void lsapi_MD5Update(struct lsapi_MD5Context *ctx, unsigned char const *buf, unsigned len) { register uint32 t; /* Update bitcount */ t = ctx->bits[0]; if ((ctx->bits[0] = t + ((uint32) len << 3)) < t) ctx->bits[1]++; /* Carry from low to high */ ctx->bits[1] += len >> 29; t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ /* Handle any leading odd-sized chunks */ if (t) { unsigned char *p = (unsigned char *) ctx->in + t; t = 64 - t; if (len < t) { memmove(p, buf, len); return; } memmove(p, buf, t); byteReverse(ctx->in, 16); lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in); buf += t; len -= t; } /* Process data in 64-byte chunks */ while (len >= 64) { memmove(ctx->in, buf, 64); byteReverse(ctx->in, 16); lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in); buf += 64; len -= 64; } /* Handle any remaining bytes of data. */ memmove(ctx->in, buf, len); } /* * Final wrap-up - pad to 64-byte boundary with the bit pattern * 1 0* (64-bit count of bits processed, MSB-first) */ void lsapi_MD5Final(unsigned char digest[16], struct lsapi_MD5Context *ctx) { unsigned int count; unsigned char *p; /* Compute number of bytes mod 64 */ count = (ctx->bits[0] >> 3) & 0x3F; /* Set the first char of padding to 0x80. This is safe since there is always at least one byte free */ p = ctx->in + count; *p++ = 0x80; /* Bytes of padding needed to make 64 bytes */ count = 64 - 1 - count; /* Pad out to 56 mod 64 */ if (count < 8) { /* Two lots of padding: Pad the first block to 64 bytes */ memset(p, 0, count); byteReverse(ctx->in, 16); lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in); /* Now fill the next block with 56 bytes */ memset(ctx->in, 0, 56); } else { /* Pad block to 56 bytes */ memset(p, 0, count - 8); } byteReverse(ctx->in, 14); /* Append length in bits and transform */ ((uint32 *) ctx->in)[14] = ctx->bits[0]; ((uint32 *) ctx->in)[15] = ctx->bits[1]; lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in); byteReverse((unsigned char *) ctx->buf, 4); memmove(digest, ctx->buf, 16); memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */ } /* The four core functions - F1 is optimized somewhat */ /* #define F1(x, y, z) (x & y | ~x & z) */ #define F1(x, y, z) (z ^ (x & (y ^ z))) #define F2(x, y, z) F1(z, x, y) #define F3(x, y, z) (x ^ y ^ z) #define F4(x, y, z) (y ^ (x | ~z)) /* This is the central step in the MD5 algorithm. */ #define MD5STEP(f, w, x, y, z, data, s) \ ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) /* * The core of the MD5 algorithm, this alters an existing MD5 hash to * reflect the addition of 16 longwords of new data. MD5Update blocks * the data and converts bytes into longwords for this routine. */ static void lsapi_MD5Transform(uint32 buf[4], uint32 const in[16]) { register uint32 a, b, c, d; a = buf[0]; b = buf[1]; c = buf[2]; d = buf[3]; MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); buf[0] += a; buf[1] += b; buf[2] += c; buf[3] += d; } int LSAPI_Set_Restored_Parent_Pid(int pid) { int old_ppid = s_ppid; s_restored_ppid = pid; return old_ppid; } int LSAPI_Inc_Req_Processed(int cnt) { return __atomic_add_fetch(s_global_counter, cnt, __ATOMIC_SEQ_CST); } PK!Y//3gems/2.2.0/gems/ruby-lsapi-5.6/ext/lsapi/lsapilib.hnu[/* Copyright (c) 2002-2018, Lite Speed Technologies Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the Lite Speed Technologies Inc nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _LSAPILIB_H_ #define _LSAPILIB_H_ #if defined (c_plusplus) || defined (__cplusplus) extern "C" { #endif #include "lsapidef.h" #include #include #include struct LSAPI_key_value_pair { char * pKey; char * pValue; int keyLen; int valLen; }; struct lsapi_child_status; #define LSAPI_MAX_RESP_HEADERS 1000 typedef struct lsapi_request { int m_fdListen; int m_fd; long m_lLastActive; long m_lReqBegin; char * m_pReqBuf; int m_reqBufSize; char * m_pRespBuf; char * m_pRespBufEnd; char * m_pRespBufPos; char * m_pRespHeaderBuf; char * m_pRespHeaderBufEnd; char * m_pRespHeaderBufPos; struct lsapi_child_status * child_status; struct iovec * m_pIovec; struct iovec * m_pIovecEnd; struct iovec * m_pIovecCur; struct iovec * m_pIovecToWrite; struct lsapi_packet_header * m_respPktHeaderEnd; struct lsapi_req_header * m_pHeader; struct LSAPI_key_value_pair * m_pEnvList; struct LSAPI_key_value_pair * m_pSpecialEnvList; int m_envListSize; int m_specialEnvListSize; struct lsapi_http_header_index * m_pHeaderIndex; struct lsapi_header_offset * m_pUnknownHeader; char * m_pScriptFile; char * m_pScriptName; char * m_pQueryString; char * m_pHttpHeader; char * m_pRequestMethod; int m_totalLen; int m_reqState; off_t m_reqBodyLen; off_t m_reqBodyRead; int m_bufProcessed; int m_bufRead; struct lsapi_packet_header m_respPktHeader[5]; struct lsapi_resp_header m_respHeader; short m_respHeaderLen[LSAPI_MAX_RESP_HEADERS]; void * m_pAppData; }LSAPI_Request; extern LSAPI_Request g_req; /* return: >0 continue, ==0 stop, -1 failed */ typedef int (*LSAPI_CB_EnvHandler )( const char * pKey, int keyLen, const char * pValue, int valLen, void * arg ); int LSAPI_Init(void); void LSAPI_Stop(void); int LSAPI_Is_Listen_r( LSAPI_Request * pReq); int LSAPI_InitRequest( LSAPI_Request * pReq, int fd ); int LSAPI_Accept_r( LSAPI_Request * pReq ); void LSAPI_Reset_r( LSAPI_Request * pReq ); int LSAPI_Finish_r( LSAPI_Request * pReq ); int LSAPI_Release_r( LSAPI_Request * pReq ); char * LSAPI_GetHeader_r( LSAPI_Request * pReq, int headerIndex ); int LSAPI_ForeachHeader_r( LSAPI_Request * pReq, LSAPI_CB_EnvHandler fn, void * arg ); int LSAPI_ForeachOrgHeader_r( LSAPI_Request * pReq, LSAPI_CB_EnvHandler fn, void * arg ); int LSAPI_ForeachEnv_r( LSAPI_Request * pReq, LSAPI_CB_EnvHandler fn, void * arg ); int LSAPI_ForeachSpecialEnv_r( LSAPI_Request * pReq, LSAPI_CB_EnvHandler fn, void * arg ); char * LSAPI_GetEnv_r( LSAPI_Request * pReq, const char * name ); ssize_t LSAPI_ReadReqBody_r( LSAPI_Request * pReq, char * pBuf, size_t len ); int LSAPI_ReqBodyGetChar_r( LSAPI_Request * pReq ); int LSAPI_ReqBodyGetLine_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen, int *getLF ); int LSAPI_FinalizeRespHeaders_r( LSAPI_Request * pReq ); ssize_t LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, size_t len ); ssize_t LSAPI_sendfile_r( LSAPI_Request * pReq, int fdIn, off_t* off, size_t size ); ssize_t LSAPI_Write_Stderr_r( LSAPI_Request * pReq, const char * pBuf, size_t len ); int LSAPI_Flush_r( LSAPI_Request * pReq ); int LSAPI_AppendRespHeader_r( LSAPI_Request * pReq, const char * pBuf, int len ); int LSAPI_AppendRespHeader2_r( LSAPI_Request * pReq, const char * pHeaderName, const char * pHeaderValue ); int LSAPI_ErrResponse_r( LSAPI_Request * pReq, int code, const char ** pRespHeaders, const char * pBody, int bodyLen ); static inline int LSAPI_SetRespStatus_r( LSAPI_Request * pReq, int code ) { if ( !pReq ) return -1; pReq->m_respHeader.m_respInfo.m_status = code; return 0; } static inline int LSAPI_SetAppData_r( LSAPI_Request * pReq, void * data ) { if ( !pReq ) return -1; pReq->m_pAppData = data; return 0; } static inline void * LSAPI_GetAppData_r( LSAPI_Request * pReq ) { if ( !pReq ) return NULL; return pReq->m_pAppData; } static inline char * LSAPI_GetQueryString_r( LSAPI_Request * pReq ) { if ( pReq ) return pReq->m_pQueryString; return NULL; } static inline char * LSAPI_GetScriptFileName_r( LSAPI_Request * pReq ) { if ( pReq ) return pReq->m_pScriptFile; return NULL; } static inline char * LSAPI_GetScriptName_r( LSAPI_Request * pReq ) { if ( pReq ) return pReq->m_pScriptName; return NULL; } static inline char * LSAPI_GetRequestMethod_r( LSAPI_Request * pReq) { if ( pReq ) return pReq->m_pRequestMethod; return NULL; } static inline off_t LSAPI_GetReqBodyLen_r( LSAPI_Request * pReq ) { if ( pReq ) return pReq->m_reqBodyLen; return -1; } static inline off_t LSAPI_GetReqBodyRemain_r( LSAPI_Request * pReq ) { if ( pReq ) return pReq->m_reqBodyLen - pReq->m_reqBodyRead; return -1; } int LSAPI_End_Response_r(LSAPI_Request * pReq); int LSAPI_Is_Listen(void); static inline int LSAPI_Accept( void ) { return LSAPI_Accept_r( &g_req ); } static inline int LSAPI_Finish(void) { return LSAPI_Finish_r( &g_req ); } static inline char * LSAPI_GetHeader( int headerIndex ) { return LSAPI_GetHeader_r( &g_req, headerIndex ); } static inline int LSAPI_ForeachHeader( LSAPI_CB_EnvHandler fn, void * arg ) { return LSAPI_ForeachHeader_r( &g_req, fn, arg ); } static inline int LSAPI_ForeachOrgHeader( LSAPI_CB_EnvHandler fn, void * arg ) { return LSAPI_ForeachOrgHeader_r( &g_req, fn, arg ); } static inline int LSAPI_ForeachEnv( LSAPI_CB_EnvHandler fn, void * arg ) { return LSAPI_ForeachEnv_r( &g_req, fn, arg ); } static inline int LSAPI_ForeachSpecialEnv( LSAPI_CB_EnvHandler fn, void * arg ) { return LSAPI_ForeachSpecialEnv_r( &g_req, fn, arg ); } static inline char * LSAPI_GetEnv( const char * name ) { return LSAPI_GetEnv_r( &g_req, name ); } static inline char * LSAPI_GetQueryString(void) { return LSAPI_GetQueryString_r( &g_req ); } static inline char * LSAPI_GetScriptFileName(void) { return LSAPI_GetScriptFileName_r( &g_req ); } static inline char * LSAPI_GetScriptName(void) { return LSAPI_GetScriptName_r( &g_req ); } static inline char * LSAPI_GetRequestMethod(void) { return LSAPI_GetRequestMethod_r( &g_req ); } static inline off_t LSAPI_GetReqBodyLen(void) { return LSAPI_GetReqBodyLen_r( &g_req ); } static inline off_t LSAPI_GetReqBodyRemain(void) { return LSAPI_GetReqBodyRemain_r( &g_req ); } static inline ssize_t LSAPI_ReadReqBody( char * pBuf, size_t len ) { return LSAPI_ReadReqBody_r( &g_req, pBuf, len ); } static inline int LSAPI_ReqBodyGetChar(void) { return LSAPI_ReqBodyGetChar_r( &g_req ); } static inline int LSAPI_ReqBodyGetLine( char * pBuf, int len, int *getLF ) { return LSAPI_ReqBodyGetLine_r( &g_req, pBuf, len, getLF ); } static inline int LSAPI_FinalizeRespHeaders(void) { return LSAPI_FinalizeRespHeaders_r( &g_req ); } static inline ssize_t LSAPI_Write( const char * pBuf, ssize_t len ) { return LSAPI_Write_r( &g_req, pBuf, len ); } static inline ssize_t LSAPI_sendfile( int fdIn, off_t* off, size_t size ) { return LSAPI_sendfile_r(&g_req, fdIn, off, size ); } static inline ssize_t LSAPI_Write_Stderr( const char * pBuf, ssize_t len ) { return LSAPI_Write_Stderr_r( &g_req, pBuf, len ); } static inline int LSAPI_Flush(void) { return LSAPI_Flush_r( &g_req ); } static inline int LSAPI_AppendRespHeader( char * pBuf, int len ) { return LSAPI_AppendRespHeader_r( &g_req, pBuf, len ); } static inline int LSAPI_SetRespStatus( int code ) { return LSAPI_SetRespStatus_r( &g_req, code ); } static inline int LSAPI_ErrResponse( int code, const char ** pRespHeaders, const char * pBody, int bodyLen ) { return LSAPI_ErrResponse_r( &g_req, code, pRespHeaders, pBody, bodyLen ); } static inline int LSAPI_End_Response(void) { return LSAPI_End_Response_r( &g_req ); } int LSAPI_IsRunning(void); int LSAPI_CreateListenSock( const char * pBind, int backlog ); typedef int (*fn_select_t)( int, fd_set *, fd_set *, fd_set *, struct timeval * ); int LSAPI_Init_Prefork_Server( int max_children, fn_select_t fp, int avoidFork ); void LSAPI_Set_Server_fd( int fd ); int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq ); void LSAPI_No_Check_ppid(void); void LSAPI_Set_Max_Reqs( int reqs ); void LSAPI_Set_Max_Idle( int secs ); void LSAPI_Set_Max_Children( int maxChildren ); void LSAPI_Set_Max_Idle_Children( int maxIdleChld ); void LSAPI_Set_Server_Max_Idle_Secs( int serverMaxIdle ); void LSAPI_Set_Max_Process_Time( int secs ); int LSAPI_Init_Env_Parameters( fn_select_t fp ); void LSAPI_Set_Slow_Req_Msecs( int msecs ); int LSAPI_Get_Slow_Req_Msecs(void); int LSAPI_is_suEXEC_Daemon(void); int LSAPI_Set_Restored_Parent_Pid(int pid); typedef void (*LSAPI_On_Timer_pf)(int *forked_child_pid); void LSAPI_Register_Pgrp_Timer_Callback(LSAPI_On_Timer_pf); int LSAPI_Inc_Req_Processed(int cnt); int LSAPI_Accept_Before_Fork(LSAPI_Request * pReq); int LSAPI_Postfork_Child(LSAPI_Request * pReq); int LSAPI_Postfork_Parent(LSAPI_Request * pReq); #define LSAPI_LOG_LEVEL_BITS 0xff #define LSAPI_LOG_FLAG_NONE 0 #define LSAPI_LOG_FLAG_DEBUG 1 #define LSAPI_LOG_FLAG_INFO 2 #define LSAPI_LOG_FLAG_NOTICE 3 #define LSAPI_LOG_FLAG_WARN 4 #define LSAPI_LOG_FLAG_ERROR 5 #define LSAPI_LOG_FLAG_CRIT 6 #define LSAPI_LOG_FLAG_FATAL 7 #define LSAPI_LOG_TIMESTAMP_BITS (0xff00) #define LSAPI_LOG_TIMESTAMP_FULL (0x100) #define LSAPI_LOG_TIMESTAMP_HMS (0x200) #define LSAPI_LOG_TIMESTAMP_STDERR (0x400) #define LSAPI_LOG_PID (0x10000) void LSAPI_Log(int flag, const char * fmt, ...) #if __GNUC__ __attribute__((format(printf, 2, 3))) #endif ; #if defined (c_plusplus) || defined (__cplusplus) } #endif #endif PK!泟((3gems/2.2.0/gems/ruby-lsapi-5.6/ext/lsapi/lsapilib.onu[ELF>@@=< 02/3.4-5ff.ÐHGH+FHcAVIH@AUATL$USHtQHHtIHIL9r 0HI9v'KHSMsH;Յ[]A\A]A^[D]A\A]A^øff.f=DÐO AWDD_AVAUATUSD6^nAxj׋G3G D!3G V\$ЋW^$DD1\$!3WAʋN Fp $E‰L$A1A1DD^ !D1G;νD\$DEDVDT$A!A1EE|A 1AD!E1DD*ƇGD1D!A1A1DDN DL$E F0D!DnA1D1DGFEDf Dd$D^(A!A1EEؘiA 1AD!1DDDʋ^0D1D!A1DE [D 1!D1DDN,A1DL$G\EA!Df8A1ED"kA 1AD!1DDN4EqDD1!1DE CyD 1!D1DDV<1G!I!1DDD$ Eb%1!1DDD$E@@1!1DDD$ EQZ^&1!1DE6Ƕ1!1DD]/։ 1!1DESD1!1DE ؉ 1!1DDD$E01!1DDD$ E!1!1DE7É1!1DDD$ E 1!1DDD$A0ZEAA1A!A1AA㩉A AD1!1t$DD1!A ogD1 1D!FL*1DD$Ή1AA!B9A1DD$A AD1D$qDD11‹D$ 0"amD1G 81Ɖ11DDD$ ED꾤11DDD$AKAA1A5`KA1AЉApA 1AD1D1D1A ~(D 1G'111DDD$ A0AA1A1AЋT$A2A1D1֋T$ 9ىDD11D11C|A A1A1AD$A0eVĉA1D1AD")Dt$ D D1A *CDG# 1  1DD9Ή 1DDY[e\$  1DE Dt$ щ1DE3}D\$  1DDD$E] 1DEO~oA AD 1DE ,DT$ A1ADE6CDt$ AN 1A~SADEAA A1A5:ADA AD 1Љ3*\$D D1DFӆ[ ]A\A]A^ 1։ 1DƉA4A_ OW GOW ATI1USHdH%(H$1HHH<$t)H$dH3%(u TH=1tIH=HcH5HH[ÉD1?H=HW(Hw`HLJHHLJ0HHWHVHWHWHWHWH)81HSHHHtHHtHHtH{@Ht1[fDHtGwBLHcAT4t/HcApHHH€:t HH1ff.fHtPtJSHcH;}HSHH[~ Hcи[ÃAWAVAUATUSHZHHHD$H:GH%HIHIIILfDA)HcHL9HcIOIvI HLHtML)HLHXHHAIA$D)EH[]A\A]A^A_LHHHAL|$II)AM?DLLHcH~A-H1|v@AVAUATUSHIHHHHHH+E1HH9HcHO؋)HH~)H9HwHHNHHIELL)Ht6Eu@HHDHu48u uMt-M[L]A\A]A^H~IHH)uIDHO(HW8HLJLSH)ʍBHGpH0HpH@Hwp~HcHHH HPHO8HGpAWAVAUATUSHHHT$HHH<$IH=HcB$HH@H,H9rZf.HH9vGH3LuHCH[]A\A]A^A_HD$L9IM9f.1H[]A\A]A^A_H$1L=L@Al4tI4LHHuHD$HcP 1~H $HLMtM9sHH$ID$HD$@IcMIcmH,$L| L9)A\$)H8HD$'-t _HHI9tHU:t8IcU IcEH$H€:H $HcHcAVHH€:@AVAUATUSL$HH $L9uHdH%(H$@1HHHHHHE1L LfHHcHcT4t7 qHM HIcAHL EHT DT t HHuHHcP HHL L9IcIHLfHH I9HcHHc0AHLcP IHcHHBDBHJH H2JAuH L$DIH Ic LEtaE1@AI E9~CAMIUIAuI}ӅH$@dH3%(u6H@[]A\A]A^D1@IcUff.AWAVAUATUSHXHt$ HT$dH%(H$H1HIH1E1L-HL%HHHcHcT4t/HHAAtIL{8IHC0L)H9>Lt$L+{(LA@LLfIM)MK H@σLSLCpNIHDI0HI@HKpM~HC(MxIH E1I@HC8HL1HMLIHHKpH9eHthILM)MUI9t HtDL+t$HL[]A\A]A^A_DM@@M)(IHt$HLHk8f.HAVLAUIATIUSHu\H߉AD${LǃLSHu0{L[L]A\A]A^[H]A\A]A^Hff.AWAVAUATUSHHHHD$ 0xIHIHLc\CHcT t u(HDLcLH t tLÅ~6HcAT t u#H@Å~ALH t tE<AG=I|$PHHTI9T$Hs7HI+t$@L2%))I|$PLHHcAMt$PHLIFID$PA:I|$PMD$PII@ID$PAIc$0fET8HЃA$0D$ H[]A\A]A^A_D$ ff.H HB=0AUATUSHcHfDA< t< uH؅uH[]A\A]IHPHHDI9D$Hs3HI+t$@L2%))tQI|$PHHAI\$PHCID$PIc$0fET8HЃA$0H1[]A\A]øSDAUATAUHSH?dH%(HD$1D$ff t1fHL$dH3 %(H[]A\A]ÐA1ҾÃtʼnǺ1HL$Aߺu#DHuDo߻D HDeOAkDH}An}NHtff.USHdH%(H$1HHu/HH$dH3%(uHĘ[]@1H=tAUATA'USH'DNuDH@AHHHHtH-ƉljUDk HDcEufH H IGAG IPH f@ f@ HHP P H HPPHHPPHHPPHHPPf@f@f@HH#PP H H'P#P$H$H+P'P(f@f@!f@%H(P+f@)I1 fDIHcȋL4t#fBIHT4 rfB@2JHHuMIcP IHHH9pH@ppHH@ppHH@ppHH@ppHH@ppHH@ppHH@ppHH@pHH9wMApIbIc@ IH0ALJt` A1LHcIHIGAo IuID%D-B(AA1IcH4IILI 9HqH= IJDB(9xHqH= XIJB($AD$IKAzHL$;MbfoLt$ LAoL$AT$Ml$)$ LLHL$LHLLH$ID$H$I3L$H1H D$$Dl$EDDl$H=IHIDMH=t"LDLŃP|$Et$A9uHt$DŃ5$A?D5t AH5LHtHHf)#AH51H@H51LH 1HIH51H51D%DD$H=IHtZEW7E1111H=H51E|$M2;|$E1H5LuI}Ń1H5LKfD=-ED$AIFH51HH)H5H11H5L 1H5LA#LH H1H5Laff.AVAUATUSHdH%(H$1D$ HH ;1Ll$Ld$Lt$ Hkl{ul;LLD$CHHt@HHt{1f|$=u|H4tH舴Hd1H$dH3 %(u}HĠ[]A\A]A^D {H5Hfы{LA;ff.AWAVAUATUSHD=dH%(H$1ExHH-H};DH-Ht 1HEDEH$L|$PDcA:E1AfD EDEtHHt @fLH1HIcDHD$PHD$XA ?)ѺHH D9#11A|$MHD9#HHt @D9#AD91葳fH$dH34%(' H[]A\A]A^A_KL$HDŽ$hMl$H$LH$LHHD$@AHLDŽ$hH$H$LHHD$0PH$LHHD$8+H$`L HHD$(H$ LHHD$HADžHD$PE1Ll$`HD$H$HD$H$`HD$fD%EHHt H=1IL9t<1ձL5EDu EME1VHLH1HHc}}LD$LHD$PHD$X ?)ѺH1H T`1 8Ht$(1ҿ x=_5tHHt @f,D9# DCHHt@HHtDc1DN ={H5HHHt*HHB(@HHt@HH@8B-DAD9M==H HtDHHt A9HHtD҉T$$DE ~:E~5T$$AAAuDE UM D9vHAHtDH51D$0 H=T$fD}蠩C1mH|$IH|$HT$Ht$161E Mt AMgMg{E1CHt$1ҿH=f;>fDD$$0d T$$WH=T$T$fDD#AfDRDEBHH29{H5H{wH=H=0MAH… H{HH=Ht$1ҿHL=HHHtH11L=AGHHt{1蝦D-EuHHt!E9~;t Ht$@1ҿL$Ht$01ҿHt$H1ҿHt$81ҿHt$(1ҿ kHLSH$$L$H=%,H=QHHt*fC1CD$CCT$HC(HC fD=ff.@H,LSLSLSLS GA$3p1113GA$running gcc 8.5.0 20210514GA$annobin gcc 8.5.0 20210514GA$plugin name: annobin GA*GOW*GA*GA+stack_clashGA*cf_protection GA*FORTIFYGA+GLIBCXX_ASSERTIONSGA*GA!GA+omit_frame_pointerGA*GA!stack_realign GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA$3p1113GA$running gcc 8.5.0 20210514GA$annobin gcc 8.5.0 20210514GA$plugin name: annobin GA*GOW*GA*GA+stack_clashGA*cf_protection GA*FORTIFYGA+GLIBCXX_ASSERTIONSGA*GA!GA+omit_frame_pointerGA*GA!stack_realign GA$3p1113GA$running gcc 8.5.0 20210514GA$annobin gcc 8.5.0 20210514GA$plugin name: annobin GA*GOW*GA*GA+stack_clashGA*cf_protection GA*FORTIFYGA+GLIBCXX_ASSERTIONSGA*GA!GA+omit_frame_pointerGA*GA!stack_realign GA$3p1113GA$running gcc 8.5.0 20210514GA$annobin gcc 8.5.0 20210514GA$plugin name: annobin GA*GOW*GA*GA+stack_clashGA*cf_protection GA*FORTIFYGA+GLIBCXX_ASSERTIONSGA*GA!GA+omit_frame_pointerGA*GA!stack_realign GA$3p1113GA$running gcc 8.5.0 20210514GA$annobin gcc 8.5.0 20210514GA$plugin name: annobin GA*GOW*GA*GA+stack_clashGA*cf_protection GA*FORTIFYGA+GLIBCXX_ASSERTIONSGA*GA!GA+omit_frame_pointerGA*GA!stack_realignAnonymous mmap() failedlocalhost%02d:%02d:%02d [%s] [UID:%d][%d] %.*syesnosystem()%s, errno: %d (%s) /dev/nulllibpthread.sopthread_atforkHTTP_[UID:%d][%d] %s:%s: %s LSAPI: jail() failure./etc/Can't set signalsaccept() failedLSAPI_STDERR_LOGPHP_LSAPI_MAX_REQUESTSLSAPI_MAX_REQSLSAPI_KEEP_LISTENLSAPI_AVOID_FORKLSAPI_ACCEPT_NOTIFYLSAPI_SLOW_REQ_MSECSLSAPI_ALLOW_CORE_DUMPLSAPI_MAX_IDLEPHP_LSAPI_CHILDRENLSAPI_CHILDRENLSAPI_EXTRA_CHILDRENLSAPI_MAX_IDLE_CHILDRENLSAPI_PGRP_MAX_IDLELSAPI_MAX_PROCESS_TIMELSAPI_PPID_NO_CHECKLSAPI_MAX_BUSY_WORKERLSAPI_DUMP_DEBUG_INFOnobodyLSAPI_DEFAULT_UIDLSAPI_DEFAULT_GIDLSAPI_SECRETLSAPI_LVE_ENABLELVE_ENABLEliblve.so.0lve_is_availablelve_instance_initlve_destroylve_enterlve_leavejailLSAPI_PHP_LSAPI_PHPRC=packetLen < 0 packetLen > %d Bad request header - ERROR#1 ParseRequest error SUEXEC_AUTHSUEXEC_UGIDLSAPI: setgid()LSAPI: initgroups()LSAPI: setgroups()LSAPI: setuid()Bad request header - ERROR#2 lsapi_accept() errorPragma: no-cacheRetry-After: 60Content-Type: text/htmlDEBUGINFONOTICEWARNERRORCRITFATALAcceptAccept-CharsetAccept-EncodingAccept-LanguageAuthorizationConnectionContent-TypeContent-LengthCookieCookie2HostPragmaRefererUser-AgentCache-ControlIf-Modified-SinceIf-MatchIf-None-MatchIf-RangeIf-Unmodified-SinceKeep-AliveRangeX-Forwarded-ForViaTransfer-EncodingHTTP_ACCEPTHTTP_ACCEPT_CHARSETHTTP_ACCEPT_ENCODINGHTTP_ACCEPT_LANGUAGEHTTP_AUTHORIZATIONHTTP_CONNECTIONCONTENT_TYPECONTENT_LENGTHHTTP_COOKIEHTTP_COOKIE2HTTP_HOSTHTTP_PRAGMAHTTP_REFERERHTTP_USER_AGENTHTTP_CACHE_CONTROLHTTP_IF_MODIFIED_SINCEHTTP_IF_MATCHHTTP_IF_NONE_MATCHHTTP_IF_RANGEHTTP_IF_UNMODIFIED_SINCEHTTP_KEEP_ALIVEHTTP_RANGEHTTP_X_FORWARDED_FORHTTP_VIAHTTP_TRANSFER_ENCODING%04d-%02d-%02d %02d:%02d:%02d.%06d Child process with pid: %d was killed by signal: %d, core dumped: %s Possible runaway process, UID: %d, PPID: %d, PID: %d, reqCount: %d, process time: %ld, checkpoint time: %ld, start time: %ld gdb --batch -ex "attach %d" -ex "set height 0" -ex "bt" >&2;PATH=$PATH:/usr/sbin lsof -p %d >&2Force killing runaway process PID: %d with SIGKILL Killing runaway process PID: %d with SIGTERM Children tracking is wrong: Cur Children: %d, count: %d, idle: %d, dying: %d LSAPI: LVE jail(%d) result: %d, error: %s ! Invalid custom stderr log pathFailed to open custom stderr logCan't set signal handler for SIGCHILDReached max children process limit: %d, extra: %d, current: %d, busy: %d, please increase LSAPI_CHILDREN. LSAPI: failed to open secret file: %s! LSAPI: failed to check state of file: %s! LSAPI: file permission check failure: %s LSAPI: failed to read secret from secret file: %s LSAPI: Unable to initialize LVERequest header does match total size, total: %d, real: %ld LSAPI: missing SUEXEC_UGID env, use default user! LSAPI: SUEXEC_AUTH authentication failed, use default user! LSAPI: lve_enter() failure, reached resource limit.prctl: Failed to set dumpable, core dump may not be available!sigprocmask(SIG_BLOCK) to block SIGCHLDsigprocmask( SIG_SETMASK ) to restore SIGMASK in childfork() failed, please increase process limitsigprocmask( SIG_SETMASK ) to restore SIGMASKCache-Control: private, no-cache, no-store, must-revalidate, max-age=0PID 508 Resource Limit Is Reached

    Resource Limit Is Reached

    The website is temporarily unable to service your request as it exceeded resource limit. Please try again later.
              ^ d/4-//// %-/Ga '9 (_intG )@/G G @ @ G @ G     G  `@ A C $E (J 0NL8PX@[+H\+X]+hj$xp4G- - N1 ooGGXa&& E18: ;1?A B C1GOI JK1 OQ RS TU1ac Ed EC^&e&g1 Y[ E]ah 1l5no 1tfv Ew x@ Cp3&5&<&Db_rtL&VO&i&p&y5G1$ +& ( * 0 { f|HCIRT Cv&"7&$ R  E+v"&T.1 4 c G@4HH//-Gldy"m - 911; CmGFy<d(eGfI@I@IEIE"1 36 |7 |8 |9 | : |(; |0< |8= |@@ |HA |PB |XD `F hHpItJ xM9NNO Q Y [ \ ] ^ E_ `b g+J  G J J  G4'  < ' ' '   T h4I ' T X@!      !!"! ! ! ""F " E" #!X@$  i0%9"# # # 4  G  "&4 &6 &7  < |"0'1 '3 |'4 |'6 '7 '8 |'9 | ': |(jtm8(, ( ( ( (  ( (((( ( ((0|< G'), ') ')'), ') ')H*! B@,H      !"#$%&'()*+,-./0123456789:;<<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'-$|'-2 '-7 '-; .U.m.4/"/*/!B@/) !)./23\^bgl00/{C/&/ &/ -&/ =-G=GMG"/h/ 4M'/h'/h"// ///-GK/,/ ///M/K0050708090: 0; F 0<0= | 0>( ,"n11 1 GkB@2,     C2q&2s9&2t"2k2m 2n 2o 2p 2u",22 2 92 9 2 92 92 92 92 9 2 9$2 9("222 4G9G"22 92 92 92 9 "2G2 92 9"2o2"2"/" / 1 | 2 | 3  4 k : < = ? @ B| C  E|( F|0 G|8 I|@ J|H K|P L!VX O ` P h Q p R x T'\ V'b W'h X'h Y' Z' \'n ]'t _| `| a| b| c| d e f g h iL k'zL m'G(L n'8L oE "0pVr s uhvwxz{ |(vGa=G q' s w9   EM X9    $EM x7=RH H"XOYbufP =Q YinRG-G?]!NB@j~            9     H  H  H  |      l "G * ^GN G t N  t G M>CQ L L @  J l E m  9    9#!  9 9 #! @! !9Z! #!  g!F!9! ! |'  ! m!        # # *"G&%" K "  K@ V#          ( 0 8M " z# V# @      #  -     H! x$2cnt!U$2pid'U  : YO%2buf'#!U#in>74r"4TsUs]4U T 4UsT  [5m4UsT 5UsT ,5UsT Q5UsT v5UsT 5U ʳY5U YU ;W6%;O";#;Y2x6k%2w~}׳6U2T~QwY7U 9Y,7U YK7U Yj7U Y7U Y7U ;Y7U Y7U <ytY,8U YK8U G<Yw8U ;Y8U ;Y8U <Y8U Q;Y'9U YF9U ^9Us<Y9U Y9U Q;{X9TvQ | $0.MX] ":!p], _ ":3:=GE `: E- G % :!p%) %2| %= ' :len( end) |:=G ;i pw!)p7 2;env ! )del! D TD ( ;*$U(;**U(<*'U(G<*&U(v<*$U(<*"U( <*U( =   H  -5+fd ret    ~ Et;=   5 >__d U| $ &585> 8! O EOOOOw PyPz%P{2P|?P~LPYPfPsPPPPtPtPuPvNPP p?P>QT?Q?U  y @y!y 9C@7@Ä*UvT|Q@T7@U}C AUAT|Qt7"AU}CGAU?T|QtClAU2T|QtCAU:T|QtCAU3T|Qt3AU OAU0KQ BU|[%BUV3KBT}Q0R0XtC|BU:TtQ0BU T BU [WVBUu7BUthCUtTAtDCU0TtQtLtCU2TtQCU  CU CU  DU 8DU tiDU2TtQ03DU0T0Q DT0LCDUATtQ0CEU?TtQ0C8EU3TtQ0C\EU2TtQ0CEU:TtQ0EU QU  ?yj"FQy-?y+Qy+y #/ y+y #  yy*T Q8ly 9G~y+y yy*T Q8zqQGUsOhGU03GU|TvQ0R0X[WGU|GU|T0Q HU LGHUs?Ãsx_HUsHUs?ÃsqpHUsOHU0M M M .5+ O 4 P 4Q }R E} S retT  V z#EactX ~;I   5I__d ;1J  #JU T7VJU|CJUATvQ 7JU|CJU?TvQ CJU2TvQ CKU:TvQ C@KU3TvQ 3[KU OrKU0KQKU}[KUV3KT|Q0R0XC LUAT Q0C2LU?T Q0C[LU3T Q0CLU2T Q0CLU:T Q0LU T LU [W )MU HMU gMU VMUu> @N > +5+5N C 4OU0L pO  *5+  y6 GOy!y@ 7NÄ 9O*UsTwQ@3OU0T0Q OT0LQ: Q : @z# ; 95+act=  =  = % = / >  >  ?  @ retA pidB  C 4 D 4 E  F E H  I FP   FQ__d )  D/ 1T+ : 6R  ,        %RU T   F lY  *  5 =X~ret pfd YSYUUTsZqYUsTv88 Z 8 ' 8 @ : Zp; | < |res=  = , > ? ZG -[  6[  Gret fd  D  ZT1Q0ZUsT2Q1[UsT1Q2RDX4?[UsTvQ} ][UsT|L,[Uv 8 [  /5+  B!len LF[ch )   ^  05+  C  ,   len ;\ch ;\ch 57]  U|  x]TTQ~  ]T}Qv]UvU} t^* 25+U- Ä F^  05+#fn !#arg ,E@p_QTRQt Fp_ t )5+#fnu !#argu ,E@p_QTRQ6a s` a 6h#nb #fnb (#argb 3E d #hrete qX} b  ,5+#fn !#arg ,Ei len! " |ret# $ ;Zb7 Z}p8 | 9 | : | ;  < &t < -t5(achK % O Fa__cO 9 ̋F 1b݋r}U~T}#X|3bUv3$|"T v2$}"X|$_d /5+#fn!#arg,Ei len  |ret  _d~5c |  &t -tEdUwQ R E=dUwT| $ &Q R 3QdXvA"pd=G d2v1'U2v27T|'f (5+ ; #h #h['ff$Ff$9fSf^fNkfelfwfffffUffUff9RU|Ts3$"RU|q|f q-5+ q@is t |)p | |  &t -t)ch) )__c8< -g </5+ <B!len<O >  ?p@ A - B -retC iovDg E  gGh $5+ret n .ph6$)CP]qTshhUshUs?Ãs^(iNi*'5+U "\  -Ä -j +5+ 5#offBj N "\ jÄg5jUs*RjT~Q8Z^yjTTQQRR^8 - k (5+ ;!lenH "\  p! " - # - $ - %  - l .5+ ;| Hlen -    l$UvQ|-o ʊlۊ@U~TvQsln -5+ :| G THlen -  -  |  |  |p |  >n#nTQsTQsmo no% ooU~jUT:Qs]mo -5++moo%ooUs o .5+  len -|Sp*+5+U 5off yJqp y&5+(nYp n%5+-`t}$qKzq K*5+h-qUsgEqUseqUs?Ãs^Us-r -%5+hqUsgqUsqpqUs^Ft %5+=X~ElenF ~~ ?yPsQy-?y+Qy+y / y+y   yy*T Q8zqhsUssT0sT|Q}sT0xsUssUv?ÃsqptUs8tT6Q1R~X4 yt*(5+Ut@FtU %w (5+#fd2  `Tu}$q  uvT Y' >vk%'w~~׳/vUvT~Q~ HveY'U T2ʳvU vUsT vUvT1wU0wT0( Sw2cb;*UD Tx EۄwU=T ۄxU:T ;xUIT1WxU2T1t{xU T0xU T1T A y A%5+lenC D 4/y!fd4) 6 /y?yG+^y!fd+,s y!fd5 y!fd 7y!fd.!pktN\ *z *5+ 4   |  | Wz 65+ D z D.5+uidF gidG H I J#h K#hiL 1 >{ 1.5+ 2|!len2 2+| 26 4 5>{-N{G { '5+!uid3L!gid>@ Prv pw! { 6 | +5+#uid7L#pwL!ret  Tw3o|UQTs|U T Q|Xs}|UvT Q0 $} ,5+!uid8L) ret  r} -5+r} } }G}=G#4}6{  {,5+ {? {R} ":_n~ i~ ~$zUvT Q1R X rf~U|Tv*~U2DrJ [ J%stLSfdM ) zrc+   )uid  -5+  i ) &t -t7 O 35+i F2bp|) &t -t7v /5+pb7 )Hp |b6t Y t4h tB*u! Q u#| w#h x xh!fdh j=XlenkF R ف R<ف SH S+ U#hh> >>\ >L)bF62 G 235+ 2=p4 |vTv$ Ă $+5+!n$5p&  05+ :  | i!fd 2i < Gret  n  -!fd' 2E!len?ret -7 у 35+ !fdret 6 U#fd# +val UsT3Q0@UUT47wф wJ\ x&!lenx0tR :A  A A2EsaC~CWUvT0Qs7oUsCUvTsQ0:8 υ2sig8!U:3 2sig3 Uu (7   .mUs@U T QURTvvwxfmt'PVbuf Tvyp |z Eap  u5VtvEuVtm u{iևzU|T Q1R X \i/XzU|T Q1R X õuUsT0ϵUsTu +۵T1Q}Ru\i-zUsTdQ1R X Yv3$" izUsTdQ1R X  > [[OT1Q X|rW  :5+ D.|ʊ|."-" "E"%.k|6kkk.\|`\\.>E>E>>.'E̋'E''.EG.8 18.did d<P.A]__sA]__nAAP.%|Ռ%%|sz' 8n n8i i8 B  BS.)s))PW11W"m"m,moooo-o ʊۊ@U~TvQ|,aq$ÃSу G$% L8Us+ $Ã, )6CP]UvQ|,Ot  OfT0,YYYYY}YYY}Y}YYG g)U|TsQ N ʑ)UvT|Ql  UsT0Q: ` T}q ̋ ݋ Uv 6\ SG) U|T:51U|T )OU}T]AzU}T0Q}R}NU|[U},UUUUQUQVV[UC ה$UUUUVVNVV+VU T|QgU TvQ3VUu,flEfggg,g9gDgQg^gkgxgf< ggf%g,g9gDgQg^gkgxg e6)CP]qTwQ2R} Z ÄgU~U~?Ã~*7U2T~,9= ::п `:b :}:r::_:: , 2sUwT 9 %ɌUsT|Q јTvQ0 3:g 6E:R:HGeY'UsT AQ UsڙUvT2LUvU2T1}U0T Qs9 ]  :% :}U0T QU,jjjjjjjjjkQk j jjjjjjjjkk S $Ä? cUTQvg{UsgUs^,[[[[}[ [$[$[>[,[>[3g[U|- TvQs,Y8YYYYYYYQYY@tUUTT,{X!#XXX-{X XXX՞U@T1[UU,x xxx oO/ʊ  ۊ@UsTvQ| xA hxxx߁1V۠O  o@iš%8ʊۊ@U}T|Qv yn yyzz~zA %Aˁ+5R %5ˁvT v $ &33$A %Aˁ+5R %5ˁvT v $ &33$  wODO X]%j v v[ v v v6 v vȦ v-vS K$% >#)&+v %O23@ v  v ڨ$ v $-v $*z1 ԩ"?o363A* @ 'n* A * A B1B( 1 : ; 9 I8 41B11 4: ;9 I 1RBUX YW  : ;9 IB 4: ;9 IB : ;9 I I: ; 9 I4: ;9 I1RBX YW .?<n: ; 9 4: ;9 I4: ;9 IBI41 U.: ;9 'I : ; 9 I!I/ .?: ;9 'I@B4: ; 9 I41 : ;9 I8 .?<n: ;9 I!: ;9 I" : ; 9 #: ;9 IB$1% & : ; 9 I'4: ; 9 I?<(.?: ;9 '@B) *: ;9 I+1RBX YW ,.1@B-1RBUX YW ..?: ; 9 'I 4/$ > 0(1 : ; 9 2: ;9 I34&I5 6.: ;9 'I@B7.: ;9 ' 8.?: ;9 'I 9'I:.: ;9 '@B; U<7I=!I/> 1?1B@B1A.?<n: ; B> I: ; 9 C : ; 9 D.?: ;9 'I@BE4: ;9 IF G5IH4: ;9 I?<I : ; I8 J<K : ;9 L : ; 9 I8M: ;9 IN 1UO 1PQ41 R'S1X YW T.?: ;9 '@BU 1UV4: ; 9 IW.: ; 9 'I X> I: ; 9 Y : ; 9 I8 ZB1[1UX YW \1RBX Y W ]: ; 9 I^% _$ > ` a : ; 9 b : ; 9 Ic'd&eIf : ; g: ; 9 h!i(j : ; 9 k : ; 9 l4G: ; 9 m'InB1o.?: ;9 'I@Bp4: ;9 I qrBs.: ;9 'I t.: ;9 ' u.: ;9 I v.?: ; 9 '@Bw: ; 9 IBx: ; 9 IBy4: ; 9 IBz4: ; 9 IB{1RBUX Y W |4: ; 9 I}1UX YW ~.?<n.?<n: ;9 6ddqd T)TuPPP(PPsPPKP[P"R+RRJQ^Q5Q5<v <Q{ PTt _X ~XX[TiT2TAXX[P[aQxT4T@PP{P{t XRr t;# $  %!r"p;# $  %!r"u?[gRSRbRHRQRR {RTKTiQX%vXvzr TiTTQq Ru .Q2QHQ+Q4QQoQQ;QQXP iR~Rv FRFW{ _Rz QK$KU$KKVKKUKIKTIKKSKK|hKKTK.KP.KPKQpKuKQuK}K?p K$KQ$KLKUpK}KU3KFK q 3KFK03KFKUQKpK8QKpK0QKpK\pKyK 7p yK}KQpK~K0pK}KUKK@KKUKKSKKVKKXKK0KKSKK|hJlJUlJJ]JJUJJ]JJUJJUJ0JT0JJSJJTJJTJJSJJTJJs@JJSJJSJJQJJ^JJQJJQJJ^JJ^7JTJPWJZJp?ZJaJPaJtJ\tJJPJJ_lJJUJJ | v"|JJ_|JJSJJTJJT|JJUJJ | v"JJ@JJSJJTJJs@JJ}JJ ~ JJQJJ\JJu`IIUII\IIUII\`IITIIT`IIQIIVIIvxIIVIIV`IIRII^IIRII^`IIXII]IIXII]dIITdIIUP@c@Uc@CVCrDUrDEVE.EU.EeEVeElFUlF;GV;GTIU@@P@@P@@P@APA0AS0ACAPVAiAP}AAPAAPAAPABP$B7BPKB^BPrBBPBBPBBPrDDSDDPDEPEEPEESlFFPDDsp"1DDP@@P@@PjApAPAAPAA0AAPBBPDDPDD0.E4EP:EQEP~@A0A!AP$AC\rDDPDD\DD0DD\DE0EE\lFF\FF0FH\H@I\EITI\@@P@@PAAPAAS5ACAP[AiAPAAPAAPBBP)B7BPPB^BPwBBPBBPBBPFGP"G,GP'CQCPE#EP HQHPFFPG!GP;GPGPPGTGUTGGVHHVHHQHHVI;IVEITIVFFPG!GPDGPGPPGTGUTGGVHHVHHQHHVI;IVEITIVWGpGPpGGSHHSI%IS%I6IP6I@ISEITISDGWG0DGPGPPGTGUTGWGV`GeG}eGpGQpGqG}`GpGPpGqGSGG@GG GGS]CtCP{C}C0G HP H HPfCtCPHHPHIS]>,?0,?C?]p;u<0<<P<=]=>]>,?0,?C?]p;u<0u<`=}=>}>>T>>}>,?0,?,?},?C?0p;u<0u<@=V@=V=PV==V==P=>V>>V>,?0,?0?V>?C?0p;`=S=:?S<< s $ &<<U=>0Z>c>0c>{>^{>>~>>~~>>~: ;U ;/;S/;0;U;;P99U9:S::U::S::U9S:\::S::@::6::W::4:: ::H4U4U U $$6U404^^ $^$6040000T9r0? $0404_\_\mm_ $_$60404K\KV\V\ $V$60SS 6S]] 6]USUSUST.V.T  wS  P ' S' W v(d r Pr x S     p`# p`# <$ c ~`# <$d x ~`# <$ vv" P c ^d x ^  \  0  P  S89P8:9QP+ PQQ + Q # 0 # 0 # P  U s U ) P) > S> k Pk n Sn r Pr s S 7L7UL77U 7H7TH7w7Vw7x7Tx77VM7Z7Px77P55U56V6?6U?66V66U66V66U56T6?6T?6F6TF66\66T66T66\66T66P66P66\T6g6Pg66S66UF66]66n2(3U(34\44U223T23(4V(404T044T223Q234]44Q63Y3PY3c3pc3t3Pt3~3^33p33P33S34P4,4,4h4L3p3Qp3~3R33Q33R3 4T 4 4tp 44T414^4(4V(404T0414T404|I4R4QR4S4VI4R4TR4S4]I4R4|_(l(Pl(v(u_(v(3_(l(ul(v(P''U''U''U''T''Q''T''T''Q''R''Q''QP''U''U''UP''T''Q''T''TP''Q''R''Q''Q0`U`SSU0`T`^TT0`Q`VQVQQ0`R`]R]RRD\~1$~"3$U"T $ &33$U"\~1$~"3$U"T $ &33$U"\`iP{P0%%U%&S&&}&+'U+'9'}9'@'U@'E'U0%%T%&_&9'}9'@'T@'E'}0%%Q%9'|9'@'Q@'E'|%%V%%vb%%0%%p 9'@'0%%Q&&Q%%P&&Pb%%0%%^%%~%&^&'}+'9'}9'@'0c&u&}u&&]&&}&&}&&]+'9'}K&&_+'9'_c&&S+'9'SK&X&V_&u&Vu&&}&&t&&T&&}#+'9'V%'\+'9'\&&P&'}+'9'}&&V&&v8$8&2$p"&& v8$8&2$p"c&c&5c&c& c&c&^#|$U|$$U$$U$ %U %%U%$%U#w#Tw#$S$$T$%S%%T%$%T#w#Qw#$V$$Q$%V% %Q %%V%%Q%$%Q##P##p$$0$$0$$^$%^<#w#0##r ##t %%0##Q$$q$!$qpI$Y$RY$m$q %%qp$$P$$P$%P<#w#0w##\##|#,$\,$_$|_$$\$%\ %%\%%0$!$T3$m$T %%T%%q`$!$X>$B$RB$$X %%X#$P %%P#$Y %%Y !U!7!S7!p!wp!{!{!!U!!S!*"w*""U""w !T uF!q!S!!S!!s""S""P""P{!!|I"o"|o""P{!!VD""V""v""V{!!_I""_{!!}D"d"}{!!]""]{!!^""^o""q2$u"""q2$u"o""v8$8&2$u"""v8$8&2$u"""v8$8&2$u"((U(=)S=)>)U>)Q)UQ)b)Sb))U()0) )P!)&) &)<)P>))0(( uu@()Q>)Q) uu@b)|) uu@()P( )s ))T))s()s()Pt u T p p# p`# tp# Q P 4 T2D2UD22S22~~22U22S22~~22U22U2D2TD22V22T22T22T22V22T22T2D2QD22]22Q22Q22Q22]22Q22Q2D2RD22\22R22R22R22\22R22R2)2u)22^22U#22^22U#22uU2Z2|Z2u2PU2u24U2u2^`U< ]< H UH b ]b k U`T< VH b V`Q5 SH [ S[ ^ sp^ b SP}q $ &}} $ &P\H b PP0< \H b \P\V 0 SH H S 0 VH H V 0 ^H H ^ PH b P  S  V  ^ZUZ^UH^H\UQTQ]TH]H\TZQZHQH\QZRZ\RH\H\RlSHS?ZSZ_H_HRSP\QTQZ]ZVUVVUHVH\TT__PPSS__UVU(4^(3 p $ &37 s $ &USUSUUSss $ &0yTyTMYQYn t2$x"#4nyRU)S)*UUPU0//U/0S0 0U 0#0S#0)0U./U/[/S[/\/U\/a/Ua/o/So/u/UWWUWXSXXUXYSYYUYPYSPYUYUY#YsY#YsY#YsY0Y Y#Ys U S"U"rSrU'T'V"]V]_P_rVrTdlP3  303}@3}S?LPL}\V]d2]d 3JP,2,U2,h,Vh,k,Uk,,V,<,T<,j,\j,k,Tk,,\,G,QG,,Q-,H,0H,L,Pk,,P,,R+:+U:++\++U++\+:+T:++^++T++^+:+Q:+V+SV++Q++P++p $  $-(q++ q++  U uh U T T q Rq w Rw y Ry R q Zw Z 0  [  p * X- q [q 0 0 T t  u|#- 4 T4 7 pD W T^ b tb q u|#q 00 C UC n Sn p Up w S0 G TG o Vo w TH _ P_ i sp u P U S U S U U S T V T V T V P P P0_U_VUV07T7\T\@JUJrVrvQvwU@UTUcScvRvwT@UV}U}V.U.VU@T|]|}T}.].5T5]v\S} S R.:v:\S\S P}Pv  \c c c\SWRWXuSWQWX]SWs} }d}S dUS.  (s U  S  U  S $ U$ * U Q$ * Q P ) P) * u t $ & P  \  \ T  V  V  ^  ^ P ] $ P \ V ^G P P U V U VU T _ T _T Q \ Q \Q R ^ R z^zRR P S %P%XSXdPdS R ] ]R U SS(S T VT9V 4}4]}*\kPS(P(QS*S04^0QTPThSsS'<'<S',},<\l\UvFQSs0s0s}Q | Q|V\dUdU}P_U_/0/LPLn__UdSPnSSPSdnPPQQRX))U)*^**U**U**U**U))T)*~**T**~**T**~))Q))w)*Q**Q**Q**Q**Q))Q))w)*Q))T)*~))U)*^**S)*~*`*_`*v*v**_&*f*Qf****}x**Qj**]**P{**P**]{**2{**w{**~{**P**]{**2D*T*qT*j*PD*j*6D*j*\,-U--V-T.UT..V..Q..U..U..V..U..V..U,- T.q. .. .. .. ,-W--ST.q.S..S..S..S,-U-{-V{--ST.q.S..U..V..S..V,V-0V-h-U..0r--P..P- - - -W{--_--\{--S{-- -.S*.T.S..S--P--V*.;.P;.T.V..P..V-- A--Sq..V..Q..U000U01S11U11S11U11S000T0111T1111T1111T11000Q00V01Q11Q11V11Q11V00V01Q11Q11V01111101S11S11S00]0 1T 11x1b1Tn11T11T01V11V000F1^F1R1rpR11^11^0-1_-151x511_11_0b1Yq11Y11Y11Y00R11R11 @00400T11V1111_45U5%5U%5/5U/55\55U55\55U45T5%5T%5F5TF55V55T55V55T45Q5%5Q%5P5QP55Q55Q55S55s55}%55S55}55S55P55st"%575P75F5st"1F5f5vs"1K5`5T`5b5tpb5f5Tq55Sq55Vq55|7 7U 77U77U7 7T 77T77T77U78U88U88U77T78V88T88V88T88V77Q78]88Q88]88Q88]77Q78]88Q88]88]77T78V88T88V88V77U7^8\88\K LU LWL_WLLULP_P$PU$POW_OWTWUTWW_LLP,LWL\LL\,LWLVLLV,LWLSLLS=LGLPLLP,L=L\,L=LV,L=LSLP_OPOW_TWW_qMMPLPSOPDUS\UOWSTWWSLL1LLPLLQ8MqMV8MqM\.MqM]NMXMPqMMP8MNMV8MNM\8MNM]MPSOP,RS\UUSV0VSW/WSMP_OP,R_\UU_V0V_W/W_MM p1OPQ p1MP\OP,R\\UU\V0V\W/W\MNVMNMNMNVMNMNMNPNONVNONNON!NONV!NON!NON8NONPyOO_RiR_RDU_\UV_5VV_4WOW_TWW_yOO#R,R#\UhU#yO{O0{OOPOOpOOPOOROPQ_OPQPOPkPpOPQpSPkPQkPyPp kPQp oPyPQyPPpyPQp}PPQPPpPPpPQp PPpPPpPQp PPpPPpPQpPPQPPpPPp PQp PPp!PPp$PQp$ PPp%PPp(PQp(PPQPPp)QEQPEQIQp"Q'Qp1$q""Q.Qp1$q"3QEQQ3QEQQ6QEQRiQQPQQppQRPpQRQQQPQQppQQPQRppQQRQQRQQRQQR\UU_iUUPvRRVvRR_RRPRU_UV_5VV_4WOW_TWW_RDS\DSGSPGSSwST\UU\UU0UU\RKS]KSSPSS~ST]UU]TUPRU0UV05VV04WOW0TWW0R SZ SSzhUUzhUU0 SSZUUZRRpRSXUUX_SS__SSz|_SSRSS~_SSz_SSzSS\SS}pSS@SS SS]TT0UV05VV0VV04WJW0TWW0WW0T T~UUP8VXV\VVVTT_UV_5VV_VV_4WJW_TWW_WW_^TpTPyTTPTTPTTPUUPUVVAVXVPiVVPVVPVVPVVVVVP4WIWPWWPWWVT2TP2TT]UUP5V@VP@VXV]XVzV0VV]VV]VVPTWW] TT_UU_XVzV_VV_TWW_ T3T 3T;TPTWgWPhWW_UUHUU0UU U4UU4UU4UUDU U4UPJP P$PU$PJP_.PJPP,d       9>ACFQxx| *)SX 05:@nOh"'3"'3TY}O[]dRV] 0 P P  0 P P {!!!"""{!!""`"h"p""""`"h"""%'0'9'.&5&B&G&c&c&_(e(l(v(((() )))* **`*f*{**D*D*I*Q*;+>+c+n+q++,,,-X.x.....,,- --.0.X...0111110000U2U2`2j2D3c3k3~333334%4,41464<4I4S455+5555q5w5{55777 8 888888s:}:::s:}:::::::::O<T<<<<<=>`>>@@@@BQC E0EFH HXHHHI;IEITIFGHHI;IEITIDGGHHI;IEITIQCChEpFH HXHHHIhEEXHHHIEpFHHdIdIxII_JJJJ|J|JJJJJJJJJJJJJJJpKpKuKwKyK~KKKKKKKKK,LWLLL0LWLLLWL\LL POPiSiSUUUUOWTWWMPOP,R\UUV5VW4WyOyOOOOP\PaPdPhPkP\PaPdPhPkPrPvPyPrPvPyPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPQQQQQQQQQQQQQQQQQQQQQQQRiSiSUUV5VV4W@WEWOWTW`WcWWUSeSiSiSiSSSSUS_S_SeSiSiSiSSSSiSqSSSSSTTUV8VV4W@WEWOWTW`WcWWTTTTUUUV8VV4W@WEWOWTW`WcWW T;TUUTW`WcWW T;TTW`WcWWUUUUUDUYYYYY0YYYZ ZUZaZZZ@[]^_`_`8`` aHaaa0bstruct_FILE.hFILE.hstdio.hsys_errlist.hresource.hstruct_iovec.hsocket.hsocket_type.hsockaddr.htime.hpwd.hstruct_tm.htime.hunistd.hctype.hconfname.hgetopt_core.hstdint-uintn.hin.hnetdb.hun.hlsapidef.hstring.hresource.hdlfcn.hsocket.herrno.hselect2.hsched.hmman.hsendfile.huio.hstrings.hinet.hwait.hprctl.hgrp.h KK.K5J/I#KK1 0 z zJ Z " OJJ = ...v <K gfJ.T2KxJ.n=@<YDw<<=:/;<;/u;=IK=H</փ-K-=>:X-=;=0:/;=I<//sf=H</[G-K-=18=;=0:X;=-/I=;/?Gf-K-=I<-=;=-/e=-/t0//-</-</-</-<///-<///-J=t=Y-</ȑ-</J>Xtu-=ttu;/K-=-/X-/t;/gK-=Y-=;=J;=/K-=-/X;/u-=ttu-=K;</f;=;/fu-=t.V>,>t;=/.K-=-/t-=-//-/-X.I</t.W=-/0,0,<.W=-/t/t;=;/H ># K# = l Z< < h u$I$K="IY<IJ =$J$<=;"<J = vXF.L L = /d f.L u /O7@p$tik<=<>V L a$f mX Xm< .>m<X N1+ pk " kJJ k.XX"~K k  [ X O(kX  < kX  b>= E<>:<Y<; = vk<q R< !l   l<lz/ f X< Kffkv ~*~ X$ rJ~ # .?f h ~~<  .<1 ~) < ~t)X ~<= jtt        Z-JJXft X L!s gf  fF J Y Y :"foXXXJlt0 hd/ L. XN6g J yi< X$   Z  4tKK  ;:|". < Z IY6t(f+K"JMX"X< mJ< & AJX0J XXXV$J)I!4f<9X!Jh  .$r.XX`KJ Jt5<uY"J q<% 3$x.`XYBW[$g   F x \ *2. F^ \t;:j KK-uYIX Ki+JJK2KKu\/ u  u  (tX |  x(9?JL6J9xX<u1tu6,XJK,@g L,K /sJK u XQy  X KEW \ g x. < %  /s u Z ptt  /t.X  o tK !f J/ kt Zs gY  Z Y g Y  #!xwJKxJK K!JK sJ  s< ! KJ9J!JK!s  f K =J YYt YYt YYJ YY<xK t<YL ,<W ue [A<v v .KXe#!CJ;Cg K E dX ` x DNK$ JG MY<," g <    =  &> t u X   Y r< f Kr  < r rJ huJL |   fX.X  ]u u<   Z = = y<kJK,&J"Irt &s=r< !rff  "yJD!IK L%; K%H K KKK.7 .XB#I1u#J Q  F Z  KNJ U  X  hJ.$ .Xhr / X L*~Jf-S. LKI u YZ .HJ K Y)%fX80JJ )X%<XX$%4HJL<0YBL=;B=Vv<)/Mt z0<6u  zt/  L4K"vI4H =" @"F %#K%W Yz Q*uJf  uJ K mJJ .I  <vJ uMF =0J u) Y%#K,K"9 =& =X YsJY FX:JJ Z L N*<xX<JX>tJ e < 7/t  L4K xH4 = K *vJfJ  uJ  Y.W mJt mX K t Km \x JYKWiX<JJz NS =;0WX Y)? K  LeJf<Ki*_8tK )^ ~tf<_K z.` ztf< XKJZfv*=gJ Z AK=%, =%H KM, tY,Lho!(fot(= -K l X|K<x < o.K Ms f sf tJt    Z 93JJM _< . jy 93JJ Kw ' K"f/ s XM X X mXL  f   yr rX' =P Yr J:h6t YGu  uf>= . f  K  ^tj  !tJ<   jF % =%H K  Z7)K LK)8 K! K 2%o = K%: K2 GK  _X#< ]< <& Y ZX [f<Ȃ _Xy q   KK&,N>:hZs"  [sf  "Ui Xi g Y .. - sX ... K fh00< =  h+< Y  u<   Y Jz   . L+< g  /.  L g J JK*X.X v6= Y; u/ Xl f? lJXY lf"Kl "K8G8=P.4XK%      J.Jp<J*<X v6= Y;. / Xl f lJXY"=8G8= I/..c<<jBz<  sX&`" f [Z M   L  Y 0 U= =Y K ^f 4I gYK$/ fY L y^ /K-%]  K+/X>0XX<uj Yv Xg Y IgZ$Hv&L<X(.= /.u.Z .fJOwX(WuO=.ft"<*w  <K t Y /?N&tuKK  h g G] t Y t YtM   t  Y IgYJvYY g r Y >v t YK, <Y ._ho<x }KYWJtbXK X 9    ft "u ; <u WY rXu WY X"0", XX LXJ<f?JfjK t Y*=K t ,=K t 0=K t .=K t Y,=KgjKK 2K zt/ Y Z  c    Zc  cf  Zc <<   a,<  Zci  Zc x    Zc w X     c       Yc  v    Yc  v    Zc  w    Yc  v  Z [    Zc   g     Yb  f }r       g {  g1J }  <1-u-).K.X UJ.< Z .)J KIK XxK +zz< O=>;g< 0:>< Y6 2 _< < Z    \_<   _X<   _ @ /        J       f :v ZYw Yu    Zv  .X t   tXI/ /    u ~ft  Zr> Z J  z  X/X < zX   tX /  `ggWK>X u ~X~ }XYX |X |<Y ^  X ./ XR XUJ Y   h.eX> tYvtYK   M U -/](tq $~Zv <Qyt/Z t   t Z*(t N   bX J| < y  !#J Y  Z+KZ)=1K- M< <Y v.u. }Jt ZY< gJ f"<  /  np < }2NX)     ~ |X}Y"Xg![qg!p'Y>tYK&CXK%.ZY&i fYp<x u   Zv X w ~9}5Xl t.Z7j.+"<g7/W5K/I Mu_Kg\K _SC_THREAD_SPORADIC_SERVERpthread_atfork_functotalLSAPI_Set_Max_Process_Timelsapi_parent_dead__fxstatparseContentLenFromHeaderugidLen_SC_2_SW_DEVm_pScriptFileLSAPI_Stopsi_addr_lsb_unused2_SC_TIMERSm_iReqCounter_fileno_SC_SHELL_SC_MEMORY_PROTECTION_SC_SCHAR_MAX__pathtm_secH_AUTHORIZATION_SC_THREAD_SAFE_FUNCTIONS_SC_UCHAR_MAXmax_lenfreeaddrinfogid_tverifyHeader_SC_C_LANG_SUPPORTm_pIovecEndstrcpy__uint8_tIPPROTO_TPpw_uidwaitpidHTTP_HEADER_LEN_SC_TTY_NAME_MAX_SC_PASS_MAXLSAPI_ErrResponse_rsi_uidm_bytes_SC_2_PBS_TRACKfp_lve_destroym_pHeader_IO_buf_end__RLIM_NLIMITS_SC_SELECT_shortbufrlimitsockaddr_insa_family_tSOCK_DCCP_SC_BC_STRING_MAX_ISpunctis_enough_free_meminet_addr_SC_TRACE_INHERITinit_lve_exnewSizem_tmStartliblvesetgroups_SC_SEMAPHORES_SC_EQUIV_CLASS_MAXread__environ_sigpollsa_datauint16_t__builtin_memmoveai_protocol_valuem_pChildrenStatusCurIPPROTO_UDPoverflow_arg_areatime_tsin_zero_SC_DEVICE_SPECIFICin_port_t_flagsachMD5_SC_THREAD_THREADS_MAXerror_msg_SC_LEVEL3_CACHE_SIZE_SC_TRACEreg_save_areacalloc_archm_respPktHeaderg_running__off_t_addr_bndlsapi_cleanupachHeaderNamest_size_SC_THREAD_PROCESS_SHAREDallocateBuf_SC_JOB_CONTROLgetppidtm_isdstswapIntEndianlsapi_check_child_statussignal_locks_max_idle_secslsapi_set_nblockenvirons_schedule_notifysetUID_LVE_SC_NL_NMAX__RLIMIT_NPROCRLIMIT_DATApServeratoluint32_tinitgroups_SC_POLLm_pHttpHeader_SC_V6_ILP32_OFF32_SC_TRACE_SYS_MAXm_pScriptName__builtin_va_listst_blksizeRLIMIT_NOFILEm_pEnvList_SC_BASE_sigchldLSAPI_Set_Max_Idle_Childrenint32_t_SC_LONG_BITfixEndianLSAPI_GetEnv_r_upper__fmtsa_familym_specialEnvListSizepw_passwd_SC_CLOCK_SELECTIONmasklsapi_resp_infosigaction__RLIMIT_RTTIME_SC_V7_LPBIG_OFFBIGbodyLeftfcntllastTime_SC_AIO_LISTIO_MAXLSAPI_Init_Prefork_ServerpErr1pErr2st_gidm_cntHeaderss_notify_scheduledm_envListSizeacceptinggettimeofdaypBufai_addrm_iAvoidForks_secret_timerlsapi_MD5Context__syscall_slong_t__builtin_memset_SC_FILE_SYSTEMsa_restorerm_pChildrenStatusEnd_IO_write_endtype_SC_SCHAR_MIN_SC_LINE_MAXLSAPI_SetRespStatus_rlsapi_MD5_CTX__resst_nlinks_addr_SC_TZNAME_MAX__va_list_tag_syscallst_ctimnameLen__builtin___snprintf_chkLSAPI_Postfork_Child_SC_2_VERSIONfree_SC_2_PBS_CHECKPOINTIPPROTO_MPLS__sigset_tm_requestMethodOffm_tmWaitBeginreadSecretreadReq__tznameatoig_initedgetaddrinfovalLens_acklsapi_jailLVE__d0_SC_LEVEL4_CACHE_ASSOClsapi_MD5Final_SC_NL_LANGMAXdoAddrInfo__stack_chk_failmemcpy_killcurSize/builddir/build/BUILD/opt/alt/ruby22/lib64/ruby/gems/2.2.0/gems/ruby-lsapi-5.6/ext/lsapiRLIMIT_STACKIPPROTO_IPIPdlopenbacklogsin_family_SC_LEVEL1_ICACHE_ASSOCpIovrlim_maxm_iKillSentm_fdListen_SC_AIO_PRIO_DELTA_MAXvalidateHeadersst_atimm_statusm_reqBodyLensig_numoptargSOCK_RAWsnprintfold_int_SC_2_C_BINDs_enable_lve__clock_tparseRequestIPPROTO_RAWstrdupbufLen_SC_PRIORITY_SCHEDULING_SC_SS_REPL_MAXsys_errlistsival_ptrpStderrLogsetpgid__uid_tdaylightsi_stimeoptoptLSAPI_ReqBodyGetChar_rpKeysun_family__uint16_t_SC_FSYNCsin_portgetpeernameLSAPI_is_suEXEC_DaemonLSAPI_Is_Listen_rLSAPI_End_Response_r_SC_FILE_ATTRIBUTESsetreuidserverAddr_SC_NZEROm_pQueryString__gnuc_va_list_SC_2_C_DEV_chainpContentLen_call_addrEnvForeachnewfdm_iServerMaxIdleSOCK_NONBLOCKusleepSOCK_RDM_SC_SYMLOOP_MAXsockaddr_un_ISblankunsigned charIPPROTO_MAX_SC_MQ_OPEN_MAXSOCK_DGRAMm_tmReqBegin__fd_mask__blkcnt_tlsapi_enterLVE__builtin_calloc_IO_lock_tLSAPI_Is_ListenIPPROTO_COMPLSAPI_key_value_pairlsapi_check_pathLSAPI_ForeachHeader_rpHeaderName_SC_SEM_NSEMS_MAX_SC_USHRT_MAXLSAPI_FinalizeRespHeaders_r__read_alias__fdelt_chkshouldFixEndianpBody_SC_STREAM_MAX_SC_ASYNCHRONOUS_IOserverMaxIdle__open_alias_SC_READER_WRITER_LOCKS_SC_CPUTIME__getcwd_alias_SC_2_PBS_LOCATE_SC_DEVICE_IOsa_flagspVecgeteuid_SC_SIGNALS__ctype_b_loc_SC_V7_ILP32_OFFBIGstatusoff_tchild_statuss_notified_pids_max_reqsH_X_FORWARDED_FORs_pid_dump_debug_info_ISalpha__fprintf_chktm_zone__mode_tm_queryStringOff_SC_V7_LP64_OFF64_SC_NPROCESSORS_CONF__RLIMIT_SIGPENDINGfdInlsapi_changeUGidtv_usec_SC_XOPEN_XCU_VERSIONold_childold_termLSAPI_sendfile_rlsapi_lve_erroraccept_SC_MEMLOCKallocateRespHeaderBuf_ISprintsched_yieldpMessages_liblvepValueH_CONTENT_LENGTHm_tmLastCheckPoint__vfprintf_chk_ISalnum_SC_SEM_VALUE_MAXs_req_processedstrtollopen_SC_XOPEN_XPG2_SC_XOPEN_XPG3_SC_XOPEN_XPG4LSAPI_STATE_CONNECTED_IO_write_ptr_SC_REALTIME_SIGNALSsystemlsapi_packet_headerIPPROTO_ENCAP_ISspacelsapi_suexec_authgetLFg_prefork_serverva_list__suseconds_treqsexitLSAPI_CreateListenSock2__rlim_ts_ignore_pid__RLIMIT_MEMLOCKpCurpHeaderValue__sizesizes_slow_req_msecslsapi_init_children_statusgetuidFILEH_COOKIELSAPI_ParseSockAddrdlsympthread_lib_SC_PII_INTERNET_DGRAM_SC_SINGLE_PROCESSbyteReversedump_debug_infoLSAPI_Accept_Before_Fork_SC_SHRT_MAX_ISxdigit_SC_RAW_SOCKETSfp_lve_enterLSAPI_AppendRespHeader_rsize_tH_CONNECTIONLSAPI_GetHeader_r_SC_MULTI_PROCESSs_stderr_log_pathm_statefp_lve_instance_init_SC_BC_BASE_MAXH_CONTENT_TYPELSAPI_STATE_ACCEPTING_SC_RTSIG_MAX_SC_NETWORKINGachCmdH_ACCEPT_SC_GETGR_R_SIZE_MAXperrorcompareValueLocation_SC_THREAD_ATTR_STACKADDR_SC_LEVEL2_CACHE_ASSOC_SC_IOV_MAX_SC_TRACE_EVENT_NAME_MAX_SC_PII_INTERNETIPPROTO_IGMPpServerAddrlsapi_acceptlsapi_initLVE_IO_save_baseLSAPI_Release_riovecold_usr1maxIdleChldsocklen_tm_iMaxChildren_SC_2_UPEai_canonnameIPPROTO_IPV6_SC_DELAYTIMER_MAXpw_dirsa_mask__sigval_tLSAPI_Set_Extra_Childrens_restored_ppidsin6_flowinfototalLenm_pid_SC_SYSTEM_DATABASElsapi_prefork_server_acceptm_pIovecToWritecodem_respHeaderLen_wide_dataH_IF_MATCHai_family__nlink_tsi_addrst_inost_modeLSAPI_IsRunning_SC_T_IOV_MAXCGI_HEADER_LENIPPROTO_DCCP__in6_uGetHeaderVarH_ACC_CHARSET__stream_SC_XOPEN_STREAMSm_iMaxIdleChildrensendfile_IScntrlm_reqBufSizelsapi_child_statusprctlallocateEnvList_ISupperpStatuserr_nosival_intsi_codem_pReqBufwait_timestrcasecmpH_IF_UNMOD_SINCEpw_name_SC_TRACE_USER_EVENT_MAX__socklen_tsend_notification_pktlsapi_requestpKeyEndcurTimefprintflsapi_writev__ssize_t__srclsapi_closepChrootH_IF_RANGEtimespecnameOff__u6_addr8strerror__RLIMIT_RSSavoidForkm_packetLenLSAPI_ReadReqBody_rIPPROTO_MPTCP_SC_2_FORT_RUNbindfp_lve_leave__valin6_addr_SC_ADVISORY_INFOpacketLen__timezone__ctype_toupper_locsin6_addr_SC_TIMER_MAXpBufCur_SC_THREADSunset_lsapi_envs__sighandler_t_SC_USER_GROUPS_RLSAPI_Set_Server_fdLSAPI_CreateListenSock__RLIMIT_LOCKSm_respPktHeaderEndLSAPI_On_Timer_pfLSAPI_Set_Max_Reqs_SC_UINT_MAXst_uids_conn_close_pktLSAPI_Postfork_ParentpEndpktTypelsapilib.cset_skip_write_SC_TRACE_NAME_MAX_lowers_busy_workers_SC_THREAD_DESTRUCTOR_ITERATIONSm_flagmemsetlevelstderrm_pHeaderIndexnameidle_SC_CHILD_MAXlsapi_reopen_stderr2_IO_save_endtm_min__nptrLSAPI_InitLSAPI_Request_SC_V6_LP64_OFF64flag_SC_NGROUPS_MAXm_bufProcessedfixHeaderIndexEndianstdoutfp_offsetlsapi_MD5TransformLSAPI_Write_Stderr_r__time_t_SC_THREAD_ROBUST_PRIO_INHERITgp_offset_padLSAPI_ForeachOrgHeader_rsigaddsetLSAPI_Inc_Req_Processedm_httpHeaderLendyingrealpathtm_yday_SC_SSIZE_MAX_SC_PII_OSI_CLTS_SC_SYSTEM_DATABASE_RmsecspAuth_SC_LEVEL1_DCACHE_SIZEkeyLenextraChildrenLSAPI_Flush_rshort unsigned intrlim_cursigned charLSAPI_Reset_rs_lveold_ppidLSAPI_CB_EnvHandler_valueLen__blksize_t_SC_STREAMSSOCK_STREAMdigestpBufEndGNU C17 8.5.0 20210514 (Red Hat 8.5.0-20) -mtune=generic -m64 -march=x86-64 -g -O2 -fPIC -fexceptions -fstack-protector-strong -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection=full -fplugin=annobin_SC_PAGESIZE_SC_THREAD_PRIORITY_SCHEDULINGcountsi_pidIPPROTO_MTPs_stop_SC_CHARCLASS_NAME_MAXlsapi_header_offsetstrchrvfprintfsetgid_boundstm_wday__off64_t__fd__lenachBuf_sigsys_IO_read_base_SC_XBS5_ILP32_OFFBIGsend_req_received_notification_offsetIPPROTO_EGPLSAPI_reset_server_statesockaddrsigset_ts_defaultGids_keep_listenersecsm_cntUnknownHeadersreadfdsai_addrlenlongsopterr_SC_DEVICE_SPECIFIC_RLSAPI_Set_Restored_Parent_Pidpw_gecos_modem_iExtraChildrenLSAPI_No_Check_ppid_SC_PIPE_IO_write_base_SC_XOPEN_CRYPTvalueLenm_respInfotz_dsttime_SC_PHYS_PAGESlsapi_enable_core_dumpH_CACHE_CTRLH_COOKIE2_SC_ATEXIT_MAX__desttm_monclose_SC_SHRT_MIN_SC_FIFObitstimeH_USERAGENTs_min_avail_pages_SC_USER_GROUPSm_lLastActiveLSAPI_ForeachEnv_rlong intSOCK_PACKETsa_sigactionnotify_req_received_SC_XBS5_ILP32_OFF32dumps_worker_status_IO_marker__builtin_strncpys_ppidtm_yearlimitmax_children_SC_2_PBS_MESSAGEm_pRespBufEndtimevalorig_masktmCur_SC_XOPEN_REALTIME_THREADSfp_lve_is_availablepAddrs_defaultUidm_pChildrenStatus__fds_bits_SC_SPIN_LOCKSLSAPI_Set_Server_Max_Idle_Secswritem_bufRead_SC_SPORADIC_SERVERlsapi_close_connectionuint8_t_SC_LEVEL1_DCACHE_LINESIZE__sigaction_handlerlsapi_signal_SC_PRIORITIZED_IOin_addrSOCK_SEQPACKET__pid_t_IO_codecvt_SC_GETPW_R_SIZE_MAXpUgidheadershints_SC_XOPEN_VERSIONH_RANGE_SC_BC_SCALE_MAX_SC_2_C_VERSIONdup2strtolg_reqlong doubleparseEnvai_socktype_SC_THREAD_KEYS_MAXiov_len_SC_LEVEL4_CACHE_LINESIZEfd_setlsapi_MD5Init_SC_NL_TEXTMAXnonblocklong unsigned intlsapi_req_header_SC_LOGIN_NAME_MAXfind_child_statusIPPROTO_PIM_SC_XBS5_LP64_OFF64_SC_SPAWNmaxChildrennewlensi_statussigemptyset_pkeym_headerOff__RLIMIT_OFILEHTTP_HEADERS_SC_2_PBSs_proc_group_timer_cbpw_gid__errno_location_SC_XBS5_LPBIG_OFFBIG_SC_WORD_BITchar_SC_2_PBS_ACCOUNTINGm_pSpecialEnvListsin6_scope_idstdin_SC_AIO_MAX__oflag_SC_2_CHAR_TERMresolved_path_SC_LEVEL1_ICACHE_LINESIZE_IO_buf_baseai_flagsrealloc_SC_XOPEN_SHM__dev_t_SC_XOPEN_ENH_I18Nold_quitRLIMIT_CPU__glibc_reserved_IO_read_end_SC_ULONG_MAX_SC_TYPED_MEMORY_OBJECTS_SC_TIMEOUTS_SC_LEVEL2_CACHE_SIZEfinal_SC_XOPEN_UNIXm_pRespBufPos_IO_FILEin_addr_tm_fdH_HOST_IO_wide_datacookiestrlentzname_sifields_SC_LEVEL2_CACHE_LINESIZE__u6_addr16s_pidIPPROTO_AHLSAPI_ReqBodyGetLine_rtm_hoursetsidFlush_RespBuf_r_SC_THREAD_STACK_MINisPipe_SC_PII_OSI_Mm_respHeaders_global_counterRLIMIT_AS_SC_NL_MSGMAXsi_signom_pAppData__RLIMIT_MSGQUEUEachAddrm_inProcess_SC_THREAD_ROBUST_PRIO_PROTECT_ISgraph_lsapi_prefork_servertm_mdaypIntegerlsapi_siguser1__pad0_SC_BC_DIM_MAX__pad5_SC_LEVEL1_DCACHE_ASSOCmallocs_dump_debug_infos_avail_pages__u6_addr32_headerInfom_typesi_errnofinish_closelistensigno_SC_XOPEN_REALTIME_markersLSAPI_InitRequest_SC_SAVED_IDSpBindm_scriptFileOff_SC_INT_MAXsi_bands_log_level_namess_skip_writeH_VIAmemccpy_codecvtforkIPPROTO_ESPm_pRespHeaderBufEnd_SC_TRACE_LOGgetpwnamtimeout_SC_THREAD_PRIO_PROTECTg_fnSelectRLIMIT_FSIZE__builtin_memcpyst_rdevlsapi_http_header_indexpEnv_SC_OPEN_MAXst_devssize_tdlerrorheaderIndex_SC_UIO_MAXIOVLSAPI_Logm_pRespHeaderBuf__int32_tH_PRAGMA__uint32_tqsortpSecretFile__RLIMIT_NLIMITS__daylightIPPROTO_RSVPstrncpyH_REFERERIPPROTO_UDPLITESOCK_CLOEXECLSAPI_Set_Slow_Req_MsecsLSAPI_Prefork_Accept_r_sys_siglisthandler_SC_CHAR_MAXLSAPI_Get_ppid_ISlowerpEnvEndsigprocmaskm_pUnknownHeadergetpwuidm_reqState_SC_PII_XTIpRespHeadersleftkillsysconfm_pRespBufm_iCurChildrensocketLSAPI_Write_r_SC_PII_OSI_COTSm_totalLenpasswdm_pIovecs_stderr_is_pipefstat__snprintf_chk_SC_PII_SOCKET__gid_tlsapi_sigpipe_SC_V6_LPBIG_OFFBIG_SC_MQ_PRIO_MAXgetcwdH_TRANSFER_ENCODINGH_IF_MODIFIED_SINCE__bsxai_nexts_enable_core_dump_SC_TRACE_EVENT_FILTERnodelaysin6_family__resolved_freeres_buf_sigfaultm_iChildrenMaxIdleTime_SC_THREAD_CPUTIMEsi_utimetv_sec_SC_VERSIONm_cntSpecialEnv_SC_C_LANG_SUPPORT_Rlong long unsigned intmemmovesa_handlersin_addr_cur_columnlsapi_load_lve_libtoWriteuid_t_SC_PIIsi_fd_SC_MAPPED_FILES_SC_LEVEL4_CACHE_SIZEIPPROTO_BEETPHfp_lve_jail_SC_2_FORT_DEVIPPROTO_IPm_pRespHeaderBufPosst_blockslsapi_initSuEXEC__bswap_16getpid__buf_SC_2_LOCALEDEFm_cntEnvlocaltime_r_SC_LEVEL1_ICACHE_SIZEreadBodyToReqBuftm_gmtoffIPPROTO_PUP_namesigval_IO_backup_baseH_KEEP_ALIVE_IO_read_ptr_SC_CHAR_BITLSAPI_Register_Pgrp_Timer_Callbackmd5ctx__socket_type__nbytes_nameLengetenv_freeres_list__aps_max_busy_workersIPPROTO_ETHERNETH_IF_NO_MATCHpEnvListrlim_tlsapi_readsun_pathtimezoneCGI_HEADERSsi_overrun__bswap_32pReq_SC_INT_MINlsapi_MD5Update_SC_RE_DUP_MAX_SC_PII_INTERNET_STREAMachBodyachPeerheader_SC_THREAD_ATTR_STACKSIZEfull_path_old_offset_SC_SIGQUEUE_MAXsiginfo_t_SC_FD_MGMTexpect_connected_SC_SYNCHRONIZED_IOLSAPI_STATE_IDLEvalueOffsighandler_t_SC_V7_ILP32_OFF32skipunlinksend_conn_close_notificationoptinds_accept_notifywritevH_ACC_LANG_SC_EXPR_NEST_MAX_SC_LEVEL3_CACHE_LINESIZElong long intm_pktHeaderin6addr_loopbackports_accepting_workersIPPROTO_IDP_flags2lsapi_prefork_serverallocateIovec_SC_MESSAGE_PASSING__ch_SC_REGEX_VERSIONm_iLenLSAPI_Set_Max_Children__d1setuidtv_nsecm_scriptNameOfflsapi_perror_SC_FILE_LOCKING_SC_AVPHYS_PAGES_SC_MB_LEN_MAXpHeader_ISdigitsockaddr_in6IPPROTO_SCTP_SC_PII_OSI_SC_ARG_MAX__ino_tsetsockopt_SC_MEMLOCK_RANGELSAPI_Finish_r_SC_SHARED_MEMORY_OBJECTSlsapi_resp_headersys_nerrin6addr_anym_pRequestMethodachError_SC_CHAR_MIN__realpath_chkiov_basem_lReqBegins_uids_total_pagespw_shell__namem_versionB0m_versionB1IPPROTO_GRE_SC_XOPEN_LEGACY_SC_NL_ARGMAXRLIMIT_COREsi_tidtobekilled_SC_THREAD_PRIO_INHERIT_SC_LEVEL3_CACHE_ASSOC_SC_NPROCESSORS_ONLNm_headerLenexpect_acceptingm_pIovecCurfdListenLSAPI_Init_Env_Parametersaddr_len_SC_HOST_NAME_MAXIPPROTO_TCPLSAPI_AppendRespHeader2_r_SC_COLL_WEIGHTS_MAX_SC_MONOTONIC_CLOCK__rlimit_resourcem_reqBodyReadLSAPI_Set_Max_Idle_SC_CLK_TCKLSAPI_ForeachSpecialEnv_rlsapi_buildPacketHeaderLSAPI_perror_r_SC_NL_SETMAXunsigned int_SC_BARRIERSbodyLenpBeginLSAPI_Accept_rwait_secslsapi_reopen_stderrstrcmpst_mtim__statbuf__RLIMIT_NICEfn_select_tshort intlsapi_notify_pidsi_sigvalsetrlimit_vtable_offsetaddrinfo_SC_IPV6mmapIPPROTO_ICMPlsapi_sigchild_SC_REGEXPlsapi_schedule_notifyLSAPI_Get_Slow_Req_Msecs_SC_V6_ILP32_OFFBIGstatmemchrtz_minuteswestsys_siglistH_ACC_ENCODINGsin6_portm_iMaxReqProcessTime__RLIMIT_RTPRIOGCC: (GNU) 8.5.0 20210514 (Red Hat 8.5.0-20)GNUzRx 0D LXsEIB E(A0z (A BBBI A (D BBBA  @YGJB B(A0A80F(B DBb0BFC G  AABK Hk(\GADJ n AAA 4UAGK R CAG L JCG AG] AJ t C KFLBBE A(H0H (D BBBD  (D BBBA PXvFB A(D0D (A BBBB L(A BBBA$aAAD XAAHBBB B(A0A8D@N 8C0A(B BBBH $ OAf Q C E H@HYBBB A(D0J 0A(A BBBF xFEA C(G   (A ABBD M I c A  E M A k E E E E H V HFBB B(A0A8D`` 8A0A(B BBBD lT+BBB B(A0D8JYHPC Mi 8A0A(B BBBE LTMDd6BBB B(A0A8DP 8A0A(B BBBG  8J0H(G DBBK $,7EFF IIOTh|  4FAA G>  AABG EO D  A  (Y<JEDXS l]Ph H XAHlFBB B(A0A8LP 8A0A(B BBBH < FBB A(A0 (D BBBI i`0FBB B(A0A8DP~ 8A0A(B BBBA k 8A0A(B BBBH L$FBB A(A0H Q D 0A(A BBBH LFBB B(A0A8G 8A0A(B BBBF 4FHF\$pnCXJLlFBB B(A0A8DA 8A0A(B BBBA `BBB B(A0A8G I K I L N N w 8A0A(B BBBI 0L BMD GL  AABA < =BAA G L@I@U  AABG $ TWEHG ag H SH FBB B(A0A8DPS 8D0A(B BBBF TX bIE D(C0P (F BBBM Q(H BBBAH FBB B(A0A8DP 8A0A(B BBBA T CBA A(G0` (A ABBD  (C ABBA J8T -FBD D(D@T (A ABBB  ( lECGF AAI L !cBG A(D0 (A ABBE XD0 4 ZH 10\ pFAA G@7  AABF  @LsL FBB B(A0A8G 8A0A(B BBBG   $ 8 L ` t     <  FBA K(G (A ABBG <FEE D(D0M (C BBBB X(HlFBH E(A0E8I@ 8A0A(B BBBE (FED ABH BBB B(A0A8G 8A0A(B BBBJ D0FBB A(A0G 0A(A BBBF Lx FBB B(A0A8G  8A0A(B BBBA    1 -  E2a~345.IWul -- "0s-Je s z )Y)2L0Yz+ k + w 0 Gw : X Ui s  s    x 5 P _ s(0x *  * # N0 al |  O& - =h9Y9 @ $@O e` rU+66 %  7 6S wm w   l      4 f   x    ]  '  ; ]\ m{ m     *+ *L k    \ \" k C k b    "   " $%@ `d0$%UE'xdE'''''D(m())* *+7+F+c,~, 0,.,=.u/*7u/[)0})011224C4k55667!7G7k78d X 8 8+8S:9y:9q9P q9: #h 3 (B:g0;0;H?   @  H?'^?GR^?tk?k????,?V?~???@,@T@z @+@+@?@?@;K@WK@TI ) p h d ` P H @# 80 X6TIYIzIJJJJ K(K?WTK \(b $o(|WUYUYZd Zd>qdiqdd!#$&()+2345671828F"KO(pRP [oy#)/5;AG8MXSY_ekqw+}=Nbw*@V %]+o17=CpIO@U[Tahgtms8yp6&(P,-./0) >Mcmy 1   " / 9 @C R a h v      @7      ! !'! #S!3!8!C!RK!@ Q!X!^!` p!p!Y!J!!0S!]!l!!!` "p i" %","@"#$Y"_"0%u"P'F"'F"'"(")l""""# #.#/1#00?#2P#Y#2s#z#4#5-#####7# 7l#7! $$$!$85$8ZN$@91a$9pv$:@$$0;$$$$P?$`? $p?%?%?:%?V%?u%@ % @ %0@%@@ %P@ %%%%&&& &`I4&I(B&JR&Ka&j&q&{&&&&&W&`Y &&&`d&d '.annobin_lsapilib.c.annobin_lsapilib.c_end.annobin_lsapilib.c.hot.annobin_lsapilib.c_end.hot.annobin_lsapilib.c.unlikely.annobin_lsapilib.c_end.unlikely.annobin_lsapilib.c.startup.annobin_lsapilib.c_end.startup.annobin_lsapilib.c.exit.annobin_lsapilib.c_end.exit.annobin_lsapi_sigpipe.start.annobin_lsapi_sigpipe.endlsapi_sigpipe.annobin_lsapi_siguser1.start.annobin_lsapi_siguser1.endlsapi_siguser1g_running.annobin_compareValueLocation.start.annobin_compareValueLocation.end.annobin_EnvForeach.start.annobin_EnvForeach.endEnvForeach.annobin_lsapi_cleanup.start.annobin_lsapi_cleanup.endlsapi_cleanups_stop.annobin_set_skip_write.start.annobin_set_skip_write.ends_skip_write.annobin_lsapi_MD5Transform.start.annobin_lsapi_MD5Transform.endlsapi_MD5Transform.annobin_lsapi_signal.start.annobin_lsapi_signal.endlsapi_signal.annobin_find_child_status.start.annobin_find_child_status.endfind_child_statusg_prefork_server.annobin_allocateRespHeaderBuf.start.annobin_allocateRespHeaderBuf.endallocateRespHeaderBuf.annobin_lsapi_set_nblock.start.annobin_lsapi_set_nblock.endlsapi_set_nblock.annobin_lsapi_accept.start.annobin_lsapi_accept.endlsapi_accept.annobin_parseEnv.start.annobin_parseEnv.endparseEnv.annobin_lsapi_init_children_status.start.annobin_lsapi_init_children_status.endlsapi_init_children_statuss_busy_workerss_accepting_workerss_avail_pagess_global_counter.annobin_readBodyToReqBuf.part.2.start.annobin_readBodyToReqBuf.part.2.endreadBodyToReqBuf.part.2.annobin_lsapi_close_connection.isra.4.start.annobin_lsapi_close_connection.isra.4.endlsapi_close_connection.isra.4s_worker_status.annobin_lsapi_writev.part.6.start.annobin_lsapi_writev.part.6.endlsapi_writev.part.6.annobin_lsapi_parent_dead.start.annobin_lsapi_parent_dead.endlsapi_parent_deads_ppids_restored_ppid.annobin_LSAPI_ParseSockAddr.part.13.start.annobin_LSAPI_ParseSockAddr.part.13.endLSAPI_ParseSockAddr.part.13.annobin_LSAPI_Log.start.annobin_LSAPI_Log.ends_stderr_is_pipes_log_level_namess_pid.annobin_lsapi_sigchild.start.annobin_lsapi_sigchild.endlsapi_sigchilds_pid_dump_debug_infos_ignore_pid.annobin_dump_debug_info.start.annobin_dump_debug_info.end.annobin_lsapi_check_child_status.start.annobin_lsapi_check_child_status.endlsapi_check_child_statuss_max_idle_secss_dump_debug_info.annobin_lsapi_perror.start.annobin_lsapi_perror.end.annobin_LSAPI_is_suEXEC_Daemon.start.annobin_LSAPI_is_suEXEC_Daemon.ends_uids_secret.annobin_LSAPI_Stop.start.annobin_LSAPI_Stop.end.annobin_LSAPI_IsRunning.start.annobin_LSAPI_IsRunning.end.annobin_LSAPI_Register_Pgrp_Timer_Callback.start.annobin_LSAPI_Register_Pgrp_Timer_Callback.ends_proc_group_timer_cb.annobin_LSAPI_InitRequest.start.annobin_LSAPI_InitRequest.end.annobin_LSAPI_Init.start.annobin_LSAPI_Init.endg_initedpthread_atfork_func.annobin_LSAPI_Is_Listen_r.start.annobin_LSAPI_Is_Listen_r.end.annobin_LSAPI_Is_Listen.start.annobin_LSAPI_Is_Listen.end.annobin_LSAPI_Reset_r.start.annobin_LSAPI_Reset_r.end.annobin_LSAPI_Release_r.start.annobin_LSAPI_Release_r.end.annobin_LSAPI_GetHeader_r.start.annobin_LSAPI_GetHeader_r.end.annobin_LSAPI_ReqBodyGetChar_r.start.annobin_LSAPI_ReqBodyGetChar_r.end.annobin_LSAPI_ReqBodyGetLine_r.start.annobin_LSAPI_ReqBodyGetLine_r.end.annobin_LSAPI_ReadReqBody_r.start.annobin_LSAPI_ReadReqBody_r.end.annobin_Flush_RespBuf_r.start.annobin_Flush_RespBuf_r.end.annobin_LSAPI_GetEnv_r.start.annobin_LSAPI_GetEnv_r.endCGI_HEADERS.annobin_LSAPI_ForeachOrgHeader_r.start.annobin_LSAPI_ForeachOrgHeader_r.endHTTP_HEADERSHTTP_HEADER_LEN.annobin_LSAPI_ForeachHeader_r.start.annobin_LSAPI_ForeachHeader_r.endCGI_HEADER_LEN.annobin_LSAPI_ForeachEnv_r.start.annobin_LSAPI_ForeachEnv_r.end.annobin_LSAPI_ForeachSpecialEnv_r.start.annobin_LSAPI_ForeachSpecialEnv_r.end.annobin_LSAPI_FinalizeRespHeaders_r.start.annobin_LSAPI_FinalizeRespHeaders_r.end.annobin_LSAPI_Flush_r.start.annobin_LSAPI_Flush_r.end.annobin_LSAPI_Write_Stderr_r.start.annobin_LSAPI_Write_Stderr_r.ends_stderr_log_path.annobin_LSAPI_perror_r.start.annobin_LSAPI_perror_r.endLSAPI_perror_r.annobin_lsapi_jailLVE.start.annobin_lsapi_jailLVE.endlsapi_jailLVEfp_lve_jail.annobin_lsapi_reopen_stderr.start.annobin_lsapi_reopen_stderr.endlsapi_reopen_stderr.annobin_LSAPI_Finish_r.start.annobin_LSAPI_Finish_r.endfinish_close.annobin_LSAPI_End_Response_r.start.annobin_LSAPI_End_Response_r.end.annobin_LSAPI_Write_r.start.annobin_LSAPI_Write_r.end.annobin_LSAPI_sendfile_r.start.annobin_LSAPI_sendfile_r.end.annobin_LSAPI_AppendRespHeader2_r.start.annobin_LSAPI_AppendRespHeader2_r.end.annobin_LSAPI_AppendRespHeader_r.start.annobin_LSAPI_AppendRespHeader_r.end.annobin_LSAPI_CreateListenSock2.start.annobin_LSAPI_CreateListenSock2.end.annobin_LSAPI_ParseSockAddr.start.annobin_LSAPI_ParseSockAddr.end.annobin_LSAPI_CreateListenSock.start.annobin_LSAPI_CreateListenSock.end.annobin_LSAPI_Init_Prefork_Server.start.annobin_LSAPI_Init_Prefork_Server.ends_max_busy_workersg_fnSelects_total_pages.annobin_LSAPI_Set_Server_fd.start.annobin_LSAPI_Set_Server_fd.end.annobin_LSAPI_reset_server_state.start.annobin_LSAPI_reset_server_state.end.annobin_is_enough_free_mem.start.annobin_is_enough_free_mem.ends_min_avail_pages.annobin_LSAPI_Postfork_Child.start.annobin_LSAPI_Postfork_Child.ends_req_processeds_keep_listeners_notified_pid.annobin_LSAPI_Postfork_Parent.start.annobin_LSAPI_Postfork_Parent.end.annobin_LSAPI_Accept_Before_Fork.start.annobin_LSAPI_Accept_Before_Fork.endold_childold_termold_intold_usr1old_quit.annobin_LSAPI_Set_Max_Reqs.start.annobin_LSAPI_Set_Max_Reqs.ends_max_reqs.annobin_LSAPI_Set_Max_Idle.start.annobin_LSAPI_Set_Max_Idle.end.annobin_LSAPI_Set_Max_Children.start.annobin_LSAPI_Set_Max_Children.end.annobin_LSAPI_Set_Extra_Children.start.annobin_LSAPI_Set_Extra_Children.end.annobin_LSAPI_Set_Max_Process_Time.start.annobin_LSAPI_Set_Max_Process_Time.end.annobin_LSAPI_Set_Max_Idle_Children.start.annobin_LSAPI_Set_Max_Idle_Children.end.annobin_LSAPI_Set_Server_Max_Idle_Secs.start.annobin_LSAPI_Set_Server_Max_Idle_Secs.end.annobin_LSAPI_Set_Slow_Req_Msecs.start.annobin_LSAPI_Set_Slow_Req_Msecs.ends_slow_req_msecs.annobin_LSAPI_Get_Slow_Req_Msecs.start.annobin_LSAPI_Get_Slow_Req_Msecs.end.annobin_LSAPI_No_Check_ppid.start.annobin_LSAPI_No_Check_ppid.end.annobin_LSAPI_Get_ppid.start.annobin_LSAPI_Get_ppid.end.annobin_LSAPI_Init_Env_Parameters.start.annobin_LSAPI_Init_Env_Parameters.ends_accept_notifys_enable_core_dumps_defaultUids_defaultGids_enable_lves_liblvefp_lve_is_availablefp_lve_instance_initfp_lve_enters_lve.annobin_LSAPI_ErrResponse_r.start.annobin_LSAPI_ErrResponse_r.end.annobin_lsapi_MD5Init.start.annobin_lsapi_MD5Init.end.annobin_lsapi_MD5Update.start.annobin_lsapi_MD5Update.end.annobin_lsapi_MD5Final.start.annobin_lsapi_MD5Final.end.annobin_readReq.start.annobin_readReq.endreadReqs_ackachBody.7025headers.7024.annobin_LSAPI_Accept_r.start.annobin_LSAPI_Accept_r.end.annobin_LSAPI_Prefork_Accept_r.start.annobin_LSAPI_Prefork_Accept_r.ends_conn_close_pkt.annobin_LSAPI_Set_Restored_Parent_Pid.start.annobin_LSAPI_Set_Restored_Parent_Pid.end.annobin_LSAPI_Inc_Req_Processed.start.annobin_LSAPI_Inc_Req_Processed.end.LC0.LC1.LC4.LC5.LC6.LC3.LC2.LC7.LC8.LC9.LC10.LC11.LC12.LC13.LC14.LC15.LC16.LC17.LC18.LC19.LC20.LC21.LC22.LC23.LC24.LC25.LC26.LC27.LC31.LC32.LC30.LC29.LC33.LC34.LC36.LC37.LC38.LC39.LC40.LC41.LC42.LC44.LC45.LC46.LC47.LC48.LC49.LC50.LC51.LC59.LC69.LC70.LC71.LC43.LC35.LC61.LC62.LC63.LC64.LC65.LC66.LC67.LC68.LC52.LC53.LC54.LC60.LC58.LC57.LC55.LC56.LC87.LC76.LC77.LC78.LC72.LC79.LC80.LC86.LC74.LC84.LC83.LC73.LC75.LC82.LC81.LC85.LC92.LC91.LC88.LC90.LC89.text.group.text.hot.group.text.unlikely.group.text.startup.group.text.exit.groupcompareValueLocationset_skip_write_GLOBAL_OFFSET_TABLE_sigactionsigemptyset__stack_chk_failreallocfcntlsetsockoptmmapmemsetsetsidread__errno_locationwritevkillgetppid__ctype_b_locstrncpystrchrstrcasecmpstrtolgetaddrinfomemcpyfreeaddrinfoinet_addrLSAPI_Log__vfprintf_chk__snprintf_chkgetuid__fprintf_chkgettimeofdaylocaltime_rwaitpidforksystemlsapi_perrorstrerrorLSAPI_is_suEXEC_DaemonLSAPI_StopLSAPI_IsRunningLSAPI_Register_Pgrp_Timer_CallbackLSAPI_InitRequestmallocgetpeernamedup2LSAPI_Initgeteuidg_reqdlopendlsymLSAPI_Is_Listen_rLSAPI_Is_ListenLSAPI_Reset_rLSAPI_Release_rfreeLSAPI_GetHeader_rLSAPI_ReqBodyGetChar_rLSAPI_ReqBodyGetLine_rmemchrmemmoveLSAPI_ReadReqBody_rFlush_RespBuf_rLSAPI_GetEnv_rstrcmp__ctype_toupper_locLSAPI_ForeachOrgHeader_rqsortLSAPI_ForeachHeader_rLSAPI_ForeachEnv_rLSAPI_ForeachSpecialEnv_rLSAPI_FinalizeRespHeaders_rLSAPI_Flush_rLSAPI_Write_Stderr_rgetpidgetcwdmemccpy__realpath_chkstrdupLSAPI_Finish_rLSAPI_End_Response_rLSAPI_Write_rLSAPI_sendfile_rsendfileLSAPI_AppendRespHeader2_rstrlenLSAPI_AppendRespHeader_rLSAPI_CreateListenSock2socketbindlistenunlinkLSAPI_ParseSockAddrLSAPI_CreateListenSockLSAPI_Init_Prefork_ServercallocsetpgidsysconfLSAPI_Set_Server_fdLSAPI_reset_server_stateis_enough_free_memLSAPI_Postfork_ChildLSAPI_Postfork_ParenttimeLSAPI_Accept_Before_Fork__fdelt_chkusleepsched_yieldLSAPI_Set_Max_ReqsLSAPI_Set_Max_IdleLSAPI_Set_Max_ChildrenLSAPI_Set_Extra_ChildrenLSAPI_Set_Max_Process_TimeLSAPI_Set_Max_Idle_ChildrenLSAPI_Set_Server_Max_Idle_SecsLSAPI_Set_Slow_Req_MsecsLSAPI_Get_Slow_Req_MsecsLSAPI_No_Check_ppidLSAPI_Get_ppidLSAPI_Init_Env_Parametersgetenvgetpwnamenvirondlerrorsetrlimit__fxstatsetreuidLSAPI_ErrResponse_rlsapi_MD5Initlsapi_MD5Updatelsapi_MD5FinalgetpwuidsetgidsetgroupssetuidstrtollprctlinitgroupsLSAPI_Accept_rLSAPI_Prefork_Accept_rsigaddsetsigprocmaskLSAPI_Set_Restored_Parent_PidLSAPI_Inc_Req_Processedselectd \D   h o    2 9 H $O ,T g -o    h C M X h c z  h  h h a 8g.J5*T/0 *1%>Kw235R4Y5`6v\  "X 3/8M7`io89p3:?K_;<Rf=h{d h t8~KW>`i{h*$?*/?@GNw*"  ( h !A`!!!a"j#<q#\p$*}$$*$ %%%&A'((Y)))b***7+A+N+BW+_+}+C++++D,,{,D,,E,,h -n---F----.8.?.N.Y.~.G...H./*/ L/T/i/// /0_1111Q2v22/33-4O4|5N6h66666666I7W7777` 7` 77888#8-828<8G8T {8889'9G9$Q9L f9T 99999999999p:*:#:<:d G:Z:` d:h::::#:::: ;!;H;;;;;;|;;<<<<,<9<V<x<t<\ <<<$< :=S=e=o=}=|====<====>/>I6>@> F>w> > >>J>?K ??L#?D?Y?f?w?????@&@6@F@_@M@@@N@@@O@@@d @P@A'AQ,A@AFA%MARRAfAmAtASyAAhATAAAAAUAAAVA BBBW B4B;BBBXGB[BbBiBYnBBBBZBBB[BBB` B\BBBBhC` C\C]#C2Cd?CdEC`TC^YCqCwC\ChC*ChC_C`CazD` DDL D DbDDcE%E`1ENEUE*\EpEduEELEeEEDEE\EfEEgE<EEhEEiF4 FFjF%F,,FTGFkLFSFTXF_FPFFFFFlFFFdGm GG(G`/Gn4GQGmGG|GGGGdG`HoHH\"Hd,H`6H`DH\ZHXyHLHpHHHH<HTHHhHHDHXIh IIq+Ir7IAIKIsIIIIJJzK9LDLOLh JMUMdMh M4NOtOPuP*P.RhDR%JR$]R#}RRdR`RvSwmS|S!S"S"S# T$TT/T4GT+uT%T&T'TlThTTMTUU|*U$1UGUxSUeU}U(UyUUzUUdU`U$UTU)V{V V|,V=V%eV%V}V*V~V[VdV`V$VWW+W9WPWYWyWWW WWXh BXUXhXX$XXh XY$ YGYQYxYYYYYYYYh #Zh 3Z?ZeZ ZZZp[[[[[\C\\\t\\ \\\$] ^]u]]]]^^4^d B^$X^$]^s^^^^^_d __c +_D_c__ _ _ __I__ ` `%`\`k`-|`.```.``` a,aJ5abaqa` aa` aaaaaaabbh 3bK8bGbXb.gbpbvb{bbbbbbpb*bbbd bc` ch$cCcTcecvcccccc#ccLccd dd9dKdVdfdldd, s|2J + (LT-- -@-Hlt,4)`h)))+ (+ L+ Tw + w w  w   s @ Hs ls t s   x  x ,x 4* `x h* *  *     (LT99 9 @ 9H l t       , 4 6` h 6 6 w 6 w w  w( L T         @ H l t     ]  ], ]4 m` ]h m m  m    (LT**** @Hlt\\\k \k ,k 4 `k h  " ""$% "($%L$%TE'$%E'E''E'' ''@'H'l't('(()(),)4*`)h**+*++, +(,L,T.,..u/.u/ u/)0@u/H)0l)0t1)011212,244`2h4454556 5(6L6T7677777 78@7H8l8t8888:98:9,:94q9`:9hq9q9:q9::0; :(0;L0;TH?0;H?H?^?H?^? ^?k?@^?Hk?lk?t?k??????,?4?`?h??????@ ?(@L@T@@@@+@@+@ +@?@@+@H?@l?@tK@?@K@K@TIK@TI,TI4I`TIhIIJIJJJ J( JL JT K J K K W K W !W!UY@!WH!UYl!UYt!Zd!UY!Zd!Zd!qd"Zd"qd,"qd4"d`"qdh"d % & ' (]CC C(X 01CC3C9C> CE(CJ0CP8CU@C[HCbPCqXC`ChCpCxCCCCCCCCCCCC+C4CHCSCYCiCm C(C0C8C@CHCPCXC`ChCpC!xC+C7CDCTCgC~CCCCCCCC  $ $ $. ) #0 $ < $\C $7J $%Q $xV $d $7n $J z $+ $+ $! $& $ $l- $G4 $2 $ $q $k  $# $ " $. $H: $zM $Y $ e $q $ $$& $d $ $o, $ $ 4 $ $@ $ $ ) $  $ $ $y $  $, $9 $v.F $3T $\8a $9+n ${ $ $ $ $j $H) $+ $ $  $/ $  $q7  $ $ '5 $A $rM $/b $s $F  $  $(0 $ $  $/ $ $ $z5 $51 $7( $5 $B $7Y $f $s $% $m. $  $ $ $y $% $ $ $[ $D*( $/? $! L $Y $Qp $z| $  $ $9 $9. $M $ $( $) $  $H) $', $18 $^ $.j $! $ $# $' $s $$ $>, $w8 $2 $.. $@+: $^F $"S $v.` $n $  $# $$ $  $ $ $p $ $ $< $'( $5 $L0B $'O $\ $ i $v $E $& $I $ $/0 $ $) $  $ $.3 $1 $. $7 $o, $9 $F $y*S $` $0m $,.z $^) $ $ $" $ $E" $# $' $r $^&& $2 $M> $4Z $ f $6x $'~ $* $ $ $n5 $  $ $% $( $t $ $F $s $( $7 $8 $ $+ $U $1 $y $o $  $, $49 $$G $S $0e $k $ q $L w $c } $# $ $! $, $N $ $ $ $V $ 1 $h8 $ !( $'-5 $CB $O $\ $%i $ v $  $5 $ $ $1( $() $i! $i" $c $ $ $ 0 $*= $ I $+U $a $'m $ y $ 1 $C $;4 $m $6 $ $,+ $ $ $ $* $ $ $ $ $# $2 $U  $/ $  $Z4 $ $Y3 $$ ${4* $10 $d&6 $ < $ B $ H $-N $}.T $Z $` $xf $l $1r $x $i~ $O) $I$ $ $]6 $* $2 $f $l1 $ $  $f  $  $^/ $R $ $/ $/ $, $]- $R $/4 $ $d $\+ $- ${1 $V  $ -& $, $l(2 $&8 $> $5D $J $$P $#%V $\ $b $$h $P(n $t $z $1 $ $5 $* $ $^ $5 $! $3 $S! $ $/$ $ $z' $  $& $& $x& $Z$ $ $ $ $ $Y0  $S, $4 $8* $P1" $f( $&. $34 $ : $@ $ F $XL $R $v!X $O^ $d $*'j $p $`5v $ | $( $h $7 $$ $" $ $T% $& $O5 $) $" $ $!7 $0 $ $. $ $9 $Z. $e $ $g  $1 $!  $  $  $3 $$ $r6* $(0 $m6 $< $!B $#H $8N $r3T $Z $` $h%f $Y#l $r $x $~ $Q' $8' $! $  $% $)& $T $" $  $l  $ $$  $ $H8 $ $- $%6 $2 $- $ $* $/ $  $& $" $e) $#  $^'& $, $'2 $8 $5> $2D $-/J $ P $$V $7\ $b $M2h $n $Lt $z $  $9 $ $ $K $| $Q $( $E  $2 $`  $  $# $^ $ $' $# $9 $m/? $7E $cK $ Q $76W $] $0c $i $"3o $u $C{ $ $+ $C5 $* $( $ $C/ $2 $H% $# $"4 $+ $9  $0 $  $D $  $ $ $' $)N $y[ $Pn $4z $2 $ $  $_  $. $ $4 $. $8 $c $ $P&- $7; $&I $W $$e $ys $O  $ $ $- $|  $?  $1 $ $e  $8 $2 $% $ " $y( $F. $'4 $I!: $'@ $+F $+L $!R $& $ $ $T $,  $ $& $ 3 $@ $4M $-Z $,g $0 t $6 $ $O# $W $z( $ $( $ $z $ $  $( $L" $/ $d < $ I $W $ $v$ $ $7+ $hO $i $! $ $&2 $ $ $ $5" $  $gl $ $b"1: $SGP $ (]f $s| $ h  $) $ $ $^* $ $ ,5 $3BK $(X0a $0nd w $: $7- $`  $ 5X  $!P  $)( # $09 $%Fx_ $)1l  $4 $%@ $` $L* $@2 $- p $5 l( $"6 h? $ M dV $s d `m $ r $ X $6 P $" H $T @ $0*! $8!8[! $f! $R/!0! $2!)! $K! $~! $!(! $ !(" $" +" $)9"B" $)P" $"0^" $0l" $z" $" $*"" $)" $'" $" $ " $," $" $= # $C.# $8# $,# $":# $H# $0W# $63d# $ar# # $## $"## $## $## $&## $^ $@ $ $$"$ $0$9$ $CF$ $R$dy$ $} $`d$ $$ $ $ $ $$ 1$ - % % j % ~$% R3% 7% pF% hJ% @V% $ ^%Ku% $% % % X% P% $% % % ( % " %3K%3K% s % q %  &  &  &  &QK$&QKA&  E&  N&  R&  [& 8 _& 6 i&pKs& " & _ & [ &  &  &  &  &~K&K& "`&  &  &  &  & M & K 'K ' "' r !' p *'  .'  7'  ;'  A'QK_'K' $\1'J'  '  '  '  ' h ' \ '  '  ' "@ ( ( (dJD(|JN( "p_( c( l( p( y( @}( <(J(J(J( "( ( ( ( ) )  )J/)J9) "J) $N)  W) d[) bd) h) m)J{)J) $$)I) $) $Z ) $ *`I"* $K1.* 2* 7* $C* G* L* $,X* \\* Ra* $m* q* v* $.7* <* 4*dI* "* * * * *I*I*I+IB+ $6N+P@p+ t+ + + + + + + + $+ + +pF+ $q"+F ,@,@3, 7, <,@Y,@c, " t, 6x, 4},@,A,A, ], Y,A,5A,5A- - -DA:-[AD-[Aa- e- j-jA-A-A- - -A-A-A- - .A!.B+.BH. )L. 'Q.Bn.)Bx.)B. N. L.8B.PB.PB. s. q._B/wB/wB// 3/ 8/BU/B_/B|/ / /B/B/B/ / /B/B/ " 0 " 0  0 0 E 0 ?)0 " 60 :0 C0FM0Fj0 rn0 ps0F0G0G0 0 0"G0DG0 " 0 0 1 " 1 1 r 1DG*1DGG1 K1 T1 AX1 ;]1UG1`G1`G1 1 1 1 1qG1G1G 2 2 2 A2 ?%2 o)2 m.2GE2U2Gm2H2H2;I2]2F2C]2G3Co 38G3C&3'C73CVG3QCQ3 "@ ^3 "@ g3 k3 t3fC~3fC3 3 3uC3hE3 " 3H3  3 3H 4H#4I84yEM4C^4Ey4C4E4E4 " 4 " 4 Z4 V4E4C4E4C5E#5C-5FH5CR5"Fm5Cw5PF5]5\F5H5]C5C5 H5C5C5C6C*6 .6 760DL6 P6 \6Ff6F6 4 6 2 6F6F6F6@6C7@7@#7C-7@B7C+L7@a7C=k70A7CN7VA7Cb7qA7}A7Cw7A7C7A8A8A#8C-8AB8CL8BY8$Bn8Cx8?B8KB8C8fB8rB8C8B8B8C8B 9B9C*(9B=9C@G9D_9Dl9D9C9E9C95E9RE9`E9EI9 $V7: $14: ${F: $1S: $7 a: $E~: $t': $]: $&: $/; $3; $`,?;@@R; $ Z;0@m; $/8y; @; $,;@; $; $*#;?; $; $B;? < $< $5!<?8< $. H< $:P<?g< $@w< $3<p?< $r%< $6<`?< $. < $z<P?< $= \ = X = $',=`Y-= $K19=  ==  M= !!Q= !b= !f= !k= $L7w= ="{= /"= $G = $*= "= $ = $3=aZ= "= "=iZ >(_ > $,> #0> #:>@[D> "U> ($Y> $b> ($f> $o> $s> $x> "> %> %> 0&> &> 5'> +'> '> '> (> '> I)> /))? "A?]Z? W*^? S*c?]u?`_? *? *?_?_?_?c? "? +? +? "@c@ " @ +$@ +-@ +1@ +:@  ,>@ ,H@cR@co@ 1,s@ /,|@ W,@ U,@ },@ {,@c@c@E[@t[@[ A[#A[HA[mA"\AG\A\A` A\A\A\B\&Bb]LBy]YB]}B_B]B_B@`BS`B``Bo`C`EC`RC`_C`C`C]CaC9aCCCaC](CaCaD]D$J>2Ju;?J;WJ;wJJ;J;JJ<J@J!< KK=<7KAK<RK` \K<sK<K<K<K>=KW=Ks=K L=$L3L=ML\L=vL@L=LL:>L]LD>L>L> M> MC*M??MCIM'?^M]hM5?MH?M $M:M $K1M 2M  2M ;M $M a2M _2M;N%;N $N95N $K1AN 2EN 2JN $w"VN 3ZN 3cN:mN " ~N *3N (3N " N:N " N O3N M3N u3N s3N 3N 3N:N "P N 3N 3O 3O 3O 4O 4O:'O:HO9UO9bO9oO:OO::O:O:O:O $O $O $K1 P $P $&&P $^ 3P $@P $MP $ZP $L7P $(P $P $G P $*P $P $"P $ P $3Q $Q $Q@91Q $9QLQ $TQkQ $"wQ G4{Q 94Q $hQ 4Q 4Q $5Q o5Q c5Q $Q 6Q 5Q $Q 6Q 6Q $Q ^7Q X7Q $Q 7Q 7QCR]P&RO=R[R]eR|RR R]RR $RR $R 8R 7S $"S 8S 8S $,S6SSS 8WS 8`S  9dS  9mS 69qS 29vSS]S S3S<SdS]pTm&T>TUTjTCRtTT $T T $T y9T o9T $T 9T 9T $w"T :T :T U U ;$U ;-U B;1U @;:U j;>U f;CU dU UX Us UCU $7U $U $U $2V $5V $V $= ,V $0";V $CV8ZV $fV ;jV ;oV ${V ;V ;V $6%VV $V ;V ;V $V *<V $<V V W u< W s<W <W <"W <&W <-W $5WLW $\W $|hW W $5W <W <W .=W "=W $ .W $1W Xl 0Xs NX $VX8|X $DX $w"X $X $/X 7X $"*X =X =X $ X =X =Y $ Y X>#Y T>5YM7TY[7rY7Y $0Y $"*Y $"Y $(Y $Y $)$Y $ Y $ 3Z $"Z59Z $pEZ >IZ >NZ $ ZZ J?^Z :?oZ @sZ ?Z P@Z J@Z $Z $6Z @Z @ZR6Zl6Z6[6@[6^[6k[6x[6[6[ $[ $K1[ $[ $~%[ $C6 \2"\ $K1.\ @2\ @7\ $lC\ /AG\ 'AL\ $X\ A\\ Aa\ $m\ Aq\ Av\ $ \ LB\ FB\ B\ B\ "P \ B\ B\ " \ (C\ $C\3\ $~%\ dC] ^C]4]4)] " :] C>] CG] CK] CT] +DX] )D]]14}]I4] " ] TD] PD] D] D] D] D]S4]33]3^ $^'&^ $K19^_(C^ "P^ DT^ D]^ )Ea^ 'Ej^ QEn^ MEu^ $6^'^ $K1^ E^ E^ E^ E^ KF^ CF^'^ $!^P'_ $K1"_ F&_ F6_ G:_ FK_ kGO_ cGT_'q_ $, }_0_ $'+_ G_ G_ 6H_ .H_ H_ H_ 5I_ )I_ $_ I_ I` J ` J`{ ` $V,`0%C` $K1O` JS` Jc` Kg` Kx` L|` L` lL` hL` L` L` $?` L` L` 9M` 5M` $` }M` oM` "@` $ a &Na Na $: !a N%a N*a $6a N:a N?a $9Ka 4OOa &OTa $`a Oda Oia $ua Pya P~ax&a cPa aPa&a $a Pa Pa&ac&a "pb Pb Pb Qb P(b /Q,b -Q2b&[b%bE'b $b#b $K1b ^Qb RQb Qb Qb Rb }Rc JSc >Sc Sc S!c $?-c NT1c BTBc TFc TKc $Wc 5U[c #U`c $!$rc#c $: c Uc Uc $9c cVc [Vc $c Vc Vc $c Vc Vc$cd$4d>d$Rd$%qd $}d d $}d d $K1d EWd 3Wd $cd  Xd  Xd $67 e 4Xe 0Xe $$e "`;e "`De rXHe lXQe XUe X^e "ke Xoe Xxe RY|e JYe Ye Ye Ye Ye *Ze &Ze dZe `Ze "e Ze Ze "e Ze Zee"e!fd!(f $X:f $K1Gf $c_f $?xf $: f $f $9f $f $f $f $3f $K1g $ g $1-g $Eg $Rg $qyg $ g $Ng(g $K1g e[g Y[g [g [g o\g g\g(h "h \h \(h ],h ]5h h]9h f]>h "Lh ]Ph ]Zh)qh(h!)h])h $@(hp h $K1h $4h ]h ]h $ i T^ i R^i i " *i y^.i w^7i ^;i ^Di ^Hi ^Oi $[i2ri $K1~i ^i ^i $i _i _i y`i i`i $i 7ai 'ai $4i ai aiU2i " i bi bj b j bj bj bjU26jz2Sj2zj2j $,j $K1j $j $4j $j $ j $/k $k $`2!k $0-k`Dk $K1Pk cTk  cYk $ek cik cnk $ zk c~k ck ddk Xdk $/k  ek ekk "k nek jek ek ekl l "l e!l e*l f.l f7l Af;l =f@l "Il {fMl wfVl `l }l fl fl fl fl fl fl l! l $(ll $K1m *gm  g m $m gm gm $ *m h.m h3m $[?m thCm jhTm hXm h]m $,im (imm  irm $~m im im $m im im $m jm jm jm jmm " m km km Tkm Pkm kn kn$nCn(Mn(jn knn ksn(n ln kn4nn $# nn $K1n Tln Hloo+o l/o l4oNo mRo mWono $/o $K1o $o $o0o $K1o $P+o ;mo 7mo zmo tmp $p(p $K14p m8p m=pJpWpdp&rp $zpp $K1p #np npp "p qnp onp np np $ p/q $K1 q nq nq/.q/Fq/fq!0{q $l4q.q $K1q Doq 8oq#/qP/qX/qm/ r $=7rW,r $K18r os(QsWisXsFXsXsXsXsXtXtKY9tUYGt $ St`jt $K1zt $tpttt $*tt $K1t Eqt ;qt qu qu $7 u Mru Kru(u "9u rr=u prFu rJu rYu3cu "@tu rxu ru ru ru "@u  su  su<uuu Esu Csu v0vCv]Mv "^v jsbv hskv sov stvdvCovvv=vOwmw&w $f0.wTw $`wsw ${ww $ww "w $Jw sw swwwwx x~ vB~ vK~ vO~ vY~+~C~;+~E+~[+~c+~+~+~+ $t $ $r 6 $+\ ${ $. $  $K1 $q $ $ $ $K14 $A $P $s^ $K1w $ $0) $$ ̀ $0؀ w܀ w $ jw fw $67 $ w w $x,& x*  x/ $9; Sx? GxD $ P xT xZ $e(x $1 $ $0 $& $́ $ $x $4 $ $&0 = $K1I yM yR $^ Fzb @zq zu zzH $K3 $K1ł $ׂ $K1 $ $ $ $|* $7 $qQ $,p $ 1 $ $m#ă $K1҃ $ $2  , z0 z5 $$A {E {V &|Z  |_  $6 $4 $S҄ $%!܄ $#0 $) w| o| $K, | |5`Xp $9)Ѕ $t-؅ $P $3@, $-8 E}< =}A $M }Q }VVnwC[ $k+@ $ʆ ~Ά  ~ކ ~ ~ \ H $G 6 0.0eo "P     ܀ ڀ̇]ۇcc   / - W U$NC"YBvOS " ~ z ˆ ˈ ψ ԈX # , G0 E9 n= lBjC2~ "    ĉ ȉ ͉C8 " "#  , P0 N5)KCF\iw $s $K1 $ $- $/ $ˊ $>܊ $u $/ $0 $+ $b! $* $z7 $H $b!T $a $@r $b!~ $m3 $z $. $b! $ $z͋ $ ދ $b! $ $z $K $s $, $0? $P $s\ $j $U $ $ $$5 $!.֌ $ $ $  $ $H-( $u5 $y7I $Z $f $p&t $@1 $- $/ $- ύ Ӎ t܍   H B "    ' @+ <0 "09 |= vF P m Džq Ņz ~     Ŏ0 @ @  6 4!G 9Q Lw Vw v c Y ߆ Ն [ Q ه ͇ŏ mɏ aҏ ֏  e+5 "`BPgy [ S   & Đ Ȑ    X R''$ ( 1 ʋ5 ȋ> B G<lv " , * S Q z vϑFّ "  Nx "1 ٌ5 ׌> B K (O $Yc "Pt ex a   ͍ ˍ "˒ ϒ ؒ ܒ  k (C2P{9ؓ Cܓ ? " "$ ( |1 V5 J> B ؏K vO pX "e i r v {z”ؔ)      ?# 1T)^){  ޒ 5 1 q m)  ɕ ԓ͕ ̓֕ <ڕ 4   Ô {* " * . 7 ";  D HH FQ nU lZ " h l u Εy ̕~*D* "p Ö ̖ 0Ж .ٖ Vݖ T)**8*J,e i y|, "  y     "̗ MЗ Gٗ ݗ - "@ ԙ ҙ   -7{-A{-^ #b k ^o \t{-  -r-Ҙ].ߘ..- "p  # "p, 0 9-C-` d m q v---<.ۙC.R..%]X;x.Ex.b ٛf ӛkx..]8.00ך 1ۚ % ɜ   "0, "= 0A (J N W [ ` "i Bm 6v ɟz ş    {   J D0ƛ "ܛ    11 " + / 8 /< -A1dc1|114 `Ü R̜  М ٜ ݜ  " / # 5# ' 1>5J FN @Sg5lq5v "P      ޥ5ǝ7   ] W7=7X \ e i r v 7 " ? 5   3 -7֞8'868@88(KC G |P <T :b,Ll "} c _   ת Ӫ "   0L0Lݟ I G n l  =L!HL4L> " O S X " a e n 2r *{LL    LѠ ۬ՠ ٬8M8M   % #! J% H*@M? qC mL@MV@Ms w  έ ̭  NMYMʡMԡ "     "    ^ T'M1MN ϯR ͯ[ _ h l qMMM D B i gȢ ̢ ѢM  MNN< ް@ ܰI M V +Z )_Ny!N!N S Q x v  !Nԣ ȱأ Ʊݣ8NyO " " ' "0 4 = A JO_ @c >l ep c|OPOP  OP Ť ΤOPؤ "0 Գ ҳ "0   "  kP! "p2 G6 E; "pD nH lQ U `yPj "{   "  ߴ  P "ĥ Cȥ Aͥ "֥ jڥ h  P "`   "` ޵# ܵ, 0 ;PE "V +Z )_ "h Rl Pu {y wP "   " ۶ ٶ ¦ ͦPצ "` ( & "` O M v tP "- 1 6 "? ÷C L P ]Q{Q ' #"Q a _ç ǧ Ч3Qڧ3Q  3Q ݸ ۸ " .bQC +G %P xT v]Qg "x |  " ۹ ׹  Q "0¨ "0Ш :Ԩ 8ߨQ "p "p _ ]Q" "0 "> B P\UZ\Uw { \U κ ̺iUUթpNN P)C30VQC6[/Wu]vRvR   ê ȪvRݪ = ;R R "' j+ `0 "9 = ٻF J ~S W ` (d m q z  ~  E ?_S "p    ɫ ߾ͫ ۾֫ ګ  C = "S " " & / 3 < @ FS^SSSǬTѬ "`       6 ( "  ( *, 5U? "U Y b "t xx rhWhW  hW­W 3T&hW=]RU\UuVV] TϮ\TyTTT6UNAV[iVhVCVVCɯVJWC W"C3T@T[CeUrU]8U]pİUΰU     6 4U ". d2 b;UE " R V _UiU  UU   ñ ȱ5Uٱ(P CTWU2C< WVC&m Pw P * ( T P P ò Ȳ.P߲TW $@ $ $. $g $' $' $7 $7 $o$ $o$( $, $4 $b8 $bA $>E $M $p!Q $p!Z $0^ $0g $*k $*s $w $ $ $ $ $ $D $D $H+ $H+ $ $ $ ³ $ ˳ $})ϳ $})س $h ܳ $h $% $% $ $ $ $ $\ $\  $! $! $/" $/+ $I#/ $I#8 $%< $%D $H $P $!T $!\ $,` $,i $m $u $,y $, $* $* $9( $9( $ $ $, $, $N- $ $ô $̴ $д $ٴ $7ݴ $7 $ $ $O4 $O4 $, $, $" $" $a $a! $)% $)- $e21 $e2: $> $F $+J $+S $j7W $j7_ $c $k $a8o $a8w $&{ $& $j$ $j$ $ $ $ $ $ $ĵ $ȵ $е $/Ե $/ܵ $j $j $ $ $2 $2 $+ $P" $  $* $" $* $D. $D6 $': $'B $ F $ O $eS $e\ $` $h $l $t $-x $E $4 $4 $q* $q* $ $ $J $ $ $ $ $ȶ $̶ $Զ $,ض $, $T $T $ $ $3 $3 $ $T+'-(- 38]QCp(sCovC]C",C2C85CF ʿI(   4H \00L`0     \ 0  $L@ X0@Xl`p,@\0p` p 4 #0%8P'L'`'t()+P , , . / 00\ 2 2 4X 5 7  7 7$ 88 8L @9` 9 : 0; P? `?( p?< ?P ?d ?x ? @  @ 0@ @@ P@`I\IpJKK4W|`Y`dd.symtab.strtab.shstrtab.rela.text.data.bss.rela.gnu.build.attributes.text.hot.rela.gnu.build.attributes.hot.text.unlikely.rela.gnu.build.attributes.unlikely.text.startup.rela.gnu.build.attributes.startup.text.exit.rela.gnu.build.attributes.exit.rodata.str1.1.rodata.str1.8.rodata.rela.data.rel.local.rela.data.rel.rela.data.rel.ro.local.rela.debug_info.debug_abbrev.rela.debug_loc.rela.debug_aranges.debug_ranges.rela.debug_line.debug_str.comment.text.hot.zzz.text.unlikely.zzz.text.startup.zzz.text.exit.zzz.note.GNU-stack.note.gnu.property.rela.eh_frame.groupP@:PT:Pl:P:P: d@(A@G:&`ep ,n 6np"1@h : LP[PV@80: u  @h0:@0:@ȩ0:22/"D /@8 *@:Dx?@:S N@p:khf@\:!wza i@ :$/0@0:&/`LJR@H:)0]80.LLuLLL LLLLLL.P FpA@(:8`4; '8WPK!3gems/2.2.0/gems/ruby-lsapi-5.6/rails/dispatch.lsapinuȯ#!/opt/alt/ruby22/bin/ruby if GC.respond_to?(:copy_on_write_friendly=) GC.copy_on_write_friendly = true end require File.dirname(__FILE__) + "/../config/environment" unless defined?(RAILS_ROOT) # If you're using RubyGems and mod_ruby, this require should be changed to an absolute path one, like: # "/usr/local/lib/ruby/gems/1.8/gems/rails-0.8.0/lib/dispatcher" -- otherwise performance is severely impaired require "dispatcher" require "lsapi" while LSAPI.accept != nil Dispatcher.dispatch end PK!DA9gems/2.2.0/gems/ruby-lsapi-5.6/examples/lsapi_with_cgi.rbnuȯ#!/opt/alt/ruby22/bin/ruby require 'lsapi' require 'cgi' while LSAPI.accept != nil cgi = CGI.new name = cgi['name'] puts cgi.header puts "Hello #{name}!
    " if name puts "You are from #{cgi.remote_addr}
    " end PK!oX  4gems/2.2.0/gems/ruby-lsapi-5.6/examples/testlsapi.rbnuȯ#!/opt/alt/ruby22/bin/ruby require 'lsapi' $count = 0; while LSAPI.accept != nil print "HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\nHello World! \##{$count}
    \r\n" ENV.each_pair {|key, value| print "#{key} is #{value}
    \r\n" } $count = $count + 1 end PK!whf:,gems/2.2.0/gems/ruby-lsapi-5.6/lsapi.gemspecnu[Gem::Specification.new do |s| s.name = %q{ruby-lsapi} s.version = "5.6" s.date = %q{2024-01-22} s.description = "This is a ruby extension for fast communication with LiteSpeed Web Server." s.summary = %q{A ruby extension for fast communication with LiteSpeed Web Server.} s.has_rdoc = false s.authors = ["LiteSpeed Technologies Inc."] s.email = "info@litespeedtech.com" s.homepage = "http://www.litespeedtech.com/" s.rubyforge_project = "ruby-lsapi" s.files = ["lsapi.gemspec", "README", "examples", "examples/testlsapi.rb", "examples/lsapi_with_cgi.rb", "ext", "ext/lsapi", "ext/lsapi/extconf.rb", "ext/lsapi/lsapidef.h", "ext/lsapi/lsapilib.c", "ext/lsapi/lsapilib.h", "ext/lsapi/lsruby.c", "rails", "rails/dispatch.lsapi", "scripts", "scripts/lsruby_runner.rb", "setup.rb"] s.extra_rdoc_files = ["README"] s.extensions << "ext/lsapi/extconf.rb" s.require_paths << "lib" end PK!]L33+gems/2.2.0/gems/ruby-lsapi-5.6/lib/lsapi.sonuȯELF>U@@,@8 @HH   ! !P ( ( !( !  888$$((( Std((( PtdQtdRtd  ! !GNU3u ApdC H‚3@(L`qCSlP*fRn}'3qѮl>&Sɶ ܮʼnSO`[is|&߱RD/y7řkՊ eY&09=By:%/=ejOzJ6'l#mNULCB1{!\$O#W23S=apbU06aD7jp#7ĴDIΊ=\4yݾCEкQuo rSѮIo|q%h6 󝵛 ' =qX[u  f   U ysOzu    E [MQ j E k & q !  1 RT s  @ +r  u >[  = & cH  'I   0x* n` m K :2p -, 2B F"X  EN   k @ @ 0~F sD :  { 5 wiw  `z! [ ' X! V pZ\ g Pp  o Џ1 r Y ` r9   tl {j PW ~ `- t]   0p sY @p  5 o y$ l! u U V E pw sS o7 pM p(    Ж  }F psJ pz `! B P   ![ `g  @ (! l @6 `p @  `!__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizecompareValueLocationset_skip_writesigactionsigemptyset__stack_chk_failreallocfcntlacceptsetsockoptmmapmemsetsetsidread__errno_locationclosewritevkillgetppid__ctype_b_locstrncpystrchrstrcasecmpstrtolgetaddrinfomemcpyfreeaddrinfoinet_addrLSAPI_Log__vfprintf_chk__snprintf_chkgetuid__fprintf_chkgettimeofdaylocaltime_rwaitpidforksystemexitlsapi_perrorstrerrorLSAPI_is_suEXEC_DaemonLSAPI_StopLSAPI_IsRunningLSAPI_Register_Pgrp_Timer_CallbackLSAPI_InitRequestmallocgetpeernamedup2LSAPI_Initgeteuidsignalg_reqdlopendlsymLSAPI_Is_Listen_rLSAPI_Is_ListenLSAPI_Reset_rLSAPI_Release_rfreeLSAPI_GetHeader_rLSAPI_ReqBodyGetChar_rLSAPI_ReqBodyGetLine_rmemchrmemmoveLSAPI_ReadReqBody_rFlush_RespBuf_rLSAPI_GetEnv_rstrcmp__ctype_toupper_locLSAPI_ForeachOrgHeader_rqsortLSAPI_ForeachHeader_rLSAPI_ForeachEnv_rLSAPI_ForeachSpecialEnv_rLSAPI_FinalizeRespHeaders_rLSAPI_Flush_rLSAPI_Write_Stderr_rgetpidgetcwdmemccpy__realpath_chkLSAPI_Finish_rLSAPI_End_Response_rLSAPI_Write_rLSAPI_sendfile_rsendfileLSAPI_AppendRespHeader2_rstrlenLSAPI_AppendRespHeader_rLSAPI_CreateListenSock2socketbindlistenunlinkLSAPI_ParseSockAddrLSAPI_CreateListenSockLSAPI_Init_Prefork_ServersetpgidsysconfLSAPI_Set_Server_fdLSAPI_reset_server_stateis_enough_free_memLSAPI_Postfork_ChildLSAPI_Postfork_ParenttimeLSAPI_Accept_Before_Fork__fdelt_chkusleepsched_yieldLSAPI_Set_Max_ReqsLSAPI_Set_Max_IdleLSAPI_Set_Max_ChildrenLSAPI_Set_Extra_ChildrenLSAPI_Set_Max_Process_TimeLSAPI_Set_Max_Idle_ChildrenLSAPI_Set_Server_Max_Idle_SecsLSAPI_Set_Slow_Req_MsecsLSAPI_Get_Slow_Req_MsecsLSAPI_No_Check_ppidLSAPI_Get_ppidLSAPI_Init_Env_Parametersgetenvgetpwnamdlerrorsetrlimit__fxstatsetreuidLSAPI_ErrResponse_rlsapi_MD5Initlsapi_MD5Updatelsapi_MD5FinalgetpwuidsetgidsetgroupssetuidstrtollprctlinitgroupsLSAPI_Accept_rLSAPI_Prefork_Accept_rsigaddsetsigprocmaskLSAPI_Set_Restored_Parent_PidLSAPI_Inc_Req_Processedselectrb_tainted_str_newrb_hash_asetrb_funcallrb_intern2rb_gc_markmunmaprb_check_typerb_obj_as_stringrb_f_sprintfs_fn_add_envrb_safe_levelrb_string_value_ptrrb_eval_string_wraprb_string_valuerb_check_safe_objrb_ruby_verbose_ptrrb_define_global_constrb_funcallvruby_strdupmkstempftruncaterb_str_buf_newrb_str_catrb_num2intrb_fix2intrb_eSecurityErrorrb_raisememmemrb_yieldrb_gc_writebarrier_unprotectrb_io_putsrb_str_new_staticrb_exec_recursiverb_default_rsrb_output_fsrb_output_rsrb_lastline_getInit_lsapichdirrb_stderrrb_cObjectrb_const_getrb_global_variablerb_define_global_functionrb_define_classrb_define_singleton_methodrb_define_methodruby_xcallocrb_data_object_allocrb_stdoutrb_stdinrb_hash_new__memcpy_chklibruby.so.2.2libpthread.so.0libdl.so.2libcrypt.so.1libm.so.6libc.so.6__environ_edata__bss_start_endGLIBC_2.2.5GLIBC_2.14GLIBC_2.15GLIBC_2.4GLIBC_2.3.4GLIBC_2.3/opt/alt/ruby22/lib64:/opt/alt/openssl/lib64   C  ui 3  ui  f   ii  ti  ui  ii   !V !@V ! !@ !QH !P !X !` !h !p !x ! ! ! ! ! ! ! ! ! ! !& !. !3 !: !B !M ![ !m !v ! ! !( !0 !8 !@ !` !h !p !x ! ! !/ !? !L ![ !g !t !~ ! ! ! ! ! ! ! ! ! !) !4 !I !R!X!X!i!y(!!0!D#!X!H!P!X!`!h!p!x! !#!5!!?!K!M!U!Y8!Y!Z!!!p!}!!! !(!0!8!@!H!P!X!`!h!p! x! ! ! ! !!!!!!!!!!!!!!!!! !(!0!8!@!H!P!X!!`!"h!$p!%x!!&!'!(!!)!*!!+!,!!!!-!.!/!0!!!! !1(!20!38!@!4H!P!X!6`!7h!8p!9x!:!;!<!=!@!A!B!C!!D!E!F!G!H!I!!J!!L!N!O !P(!Q0!R8!@!SH!TP!X!V`!h!Wp!Xx![!\!]!^!_!`!a!b!!c!!d!e!f!g!h!i!j!k!l! !m(!n0!o8!@!H!qP!rX!s`!th!up!x!v!w!y!z!{!|!~!!!!!!!!!!!!!! !(!0!8!@!H!P!X!`!h!p!HHq HtH5 % hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?h@hAhBhChDhEhFhGqhHahIQhJAhK1hL!hMhNhOhPhQhRhShThUhVhWqhXahYQhZAh[1h\!h]h^h_h`hahbhchdhehfhgqhhahiQhjAhk1hl!hmhnhohphqhrhshthuhvhwqhxahyQhzAh{1h|!h}h~hhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D%ݿ D%տ D%Ϳ D%ſ D% D% D% D% DH= H H9tHf Ht H=Y H5R H)HHH?HHtH HtfD= u+UH= Ht H= yd ]wff.> ÐHGH+FHcAVIH@AUATL$USHtQHHtIHIL9r 0HI9v'KHSMsH;Յ[]A\A]A^[D]A\A]A^øff.f=N D ÐO AWDD_AVAUATUSD6^nAxj׋G3G D!3G V\$ЋW^$DD1\$!3WAʋN Fp $E‰L$A1A1DD^ !D1G;νD\$DEDVDT$A!A1EE|A 1AD!E1DD*ƇGD1D!A1A1DDN DL$E F0D!DnA1D1DGFEDf Dd$D^(A!A1EEؘiA 1AD!1DDDʋ^0D1D!A1DE [D 1!D1DDN,A1DL$G\EA!Df8A1ED"kA 1AD!1DDN4EqDD1!1DE CyD 1!D1DDV<1G!I!1DDD$ Eb%1!1DDD$E@@1!1DDD$ EQZ^&1!1DE6Ƕ1!1DD]/։ 1!1DESD1!1DE ؉ 1!1DDD$E01!1DDD$ E!1!1DE7É1!1DDD$ E 1!1DDD$A0ZEAA1A!A1AA㩉A AD1!1t$DD1!A ogD1 1D!FL*1DD$Ή1AA!B9A1DD$A AD1D$qDD11‹D$ 0"amD1G 81Ɖ11DDD$ ED꾤11DDD$AKAA1A5`KA1AЉApA 1AD1D1D1A ~(D 1G'111DDD$ A0AA1A1AЋT$A2A1D1֋T$ 9ىDD11D11C|A A1A1AD$A0eVĉA1D1AD")Dt$ D D1A *CDG# 1  1DD9Ή 1DDY[e\$  1DE Dt$ щ1DE3}D\$  1DDD$E] 1DEO~oA AD 1DE ,DT$ A1ADE6CDt$ AN 1A~SADEAA A1A5:ADA AD 1Љ3*\$D D1DFӆ[ ]A\A]A^ 1։ 1DƉA4A_ OW GOW ATI1USHdH%(H$1HHH<$t)H$dH3%(u tIfH)I~HPHcH9vHIH)Hx t sE)EAOr1kS5 t-=' t+1Tu[81[@9[ÐAVAUATUHSHHPdH%(H$H1H fDHHDB uLd$@HLDD$@Ƅ$? TH=7 18tI DH=Ab HcH54bHHV [ÉD1?H= @HW(Hw`HLJHHLJ0HHWHVHWHWHWHWH)81HSHHHtHHtHHtH{@Ht1[fDHtGwBLHcAT4t/HcApHHH€:t HH1ff.fHtPtJSHcH;}HSHH[~ Hcи[ÃAWAVAUATUSHZHHHD$H:GH%HIHIIILfDA)HcHL9HcIOIvI HLHtML)HLHXHHAIA$D)EH[]A\A]A^A_LHHHAL|$II)AM?DLLHcH~A-H1|v@AVAUATUSHIHHHHHH+E1HH9HcHO؋)HH~)H9HwHHNHHIELL)Ht6Eu@HHDZHu4?8u 0 uMt-M[L]A\A]A^H~IHH)uIDHO(HW8HLJLSH)ʍBHGpH0HpH@Hwp~HcHHH HPHO8HGpAWAVAUATUSHHHT$HHH<$IH=i]HcB$HH@H,H9rZf.HH9vGH3LLuHCH[]A\A]A^A_HD$L9IM9f.1H[]A\A]A^A_H$1L= L@Al4tI4LHHuHD$HcP 1~H $HLMtM9sHH$ID$HD$@IcMIcmH,$L| L9)A\$);H8HD$'-t _HHI9tHU:t8IcU IcEH$H€:H $HcHcAVHH€:@AVAUATUSL$HH $L9uHdH%(H$@1HHHHHHE1L LhfHHcHcT4t7 qHM HIcAHL EHT DT t HHuHHcP HHL L9IcIHLfHH I9HcHHc0AHLcP IHcHHBDBHJH H2JAuH ̔ L$DIH Ic L^EtaE1@AI E9~CAMIUIAuI}ӅH$@dH3%(u6H@[]A\A]A^D1@IcU ff.AWAVAUATUSHXHt$ HT$dH%(H$H1HIH1E1L-mgHL%C HHHcHcT4t/HHAAtI@4 +HH5X1rrDH߹SfDHH5\X1CHtvt]SHtCuWHC(H9C8tHHCpHҏ HHHH@HCp@H1[@c뢸ff.Huu1fSHtRubHC(H9C8tH HCpH5 HHHH@HCpH{:1[1HO@H9OPv닸AWAVAUATUSHHH|I֨,aHHt$H>L{8IHC0L)H9>Lt$L+{(LA@LLfIM)MK H@σLSLCpNIHDI0HI@HKpM~HC(MxIH E1I@HC8HL1HMLIHHKpH9eH-thILM)MUI9t H tDL+t$HL[]A\A]A^A_DM@@M)( IHt$HLHk8f.HAVLAUIATIUSHu\H߉;AD${LǃLSHu0{L[L]A\A]A^+[H]A\A]A^Hff.AWAVAUATUSHHHHD$ 0xIHIHLc\CHcT t u(HDLcLH t tLÅ~6HcAT t u#H@Å~ALH t tE<AG=I|$PHHTI9T$Hs7HI+t$@L2%))I|$PLHHcAMt$PHLIFID$PA:I|$P]MD$PII@ID$PAIc$0fET8HЃA$0D$ H[]A\A]A^A_D$ ff.H HB=0AUATUSHcHfDA< t< uH؅uH[]A\A]IHPHHDI9D$Hs3HI+t$@L2%))tQI|$PHHA0I\$PHCID$PIc$0fET8HЃA$0H1[]A\A]øSDAUATAUHSH?dH%(HD$1D$ff t1fHL$dH3 %(H[]A\A]ÐA1ҾÃtʼnǺ1ԿHL$Aߺ蘿u#DHuDo謾߻D H:DeOAkDH}An聾}N3Htff.USHdH%(H$1HHu/HeH$dH3%(uHĘ[]褿@1H=r tAUATA'USH 'DNuDq H@AHH HHtH- D 9Ɖlj UDk H DcEuSH8dH%(H$(1-HtH H= H=O>HE1 H螹H=I>ڳHt 1Hvh H=5>贳HHt 1HMIAąWE1H=>耳Ht 1Hϊ H=>ZHtHǺ 1OH==3HЊ H==HtHǺ 1谸9ĶH==H1 HxOH==賲HtHǺ 1OشH==茲HtHǺ 1(H==eHtHǺ 1ʺH=r=>HtHǺ 1ڷ胲H=b=Ht=H=`=Ht 1H蝷 _H=H=ӱHt 1Hoʼn D^ P B EH==ٶH=" u P 5 H==SH 1HՈ …tՈ Hu HHHHD L=L =L=C HLt@HֹL€D t%HtAHHt9HLuHfDHJHHJHuHHu1ۉH$(dH3%(H8[]A\A]fDփ H膲D~( H=.9xHHiHǺ11諵ÃHT$ƿD$(?H5߄ رHWH` Htxc@dx@D  E9Dk E)ZfH=m8褬> HK] 2 u $ '  ' )fՅtbHà H-DHH5?1SAHc螲L%g HHu asÅt=s B u L 5R `HH50?uHH5>1U HH5>Fff.AVIAUEATIUHSHt4Hu!(fDHHtHLWH]HuMtEL[1]A\A]A^ÐIcLLH#EgHGHHܺvT2HGAWAVAAUIATUHoSH1HGO@ƉWDW?t;AĉDHH|@D)A9rhAGt4LL$HL9A?vWEfAIIIH޺@HH@HLL9uA?DLHH[]A\A]A^A_鼱IATLfUHSFH?LHz?)ƒw=t19rLHfCAD$AD$ ID$071)HCHLHCP?o H{1HMHHCPH)KXH[]A\ff.fAWAVAUATUSHdH%(H$1Ht^ IAfMcg IoA_@LH3HuM8u = | uٽH$dH3 %( HĨ[]A\A]A^A_f~AAuIALJf8LS|xr@tPHf@HPXN MgA;G ZA9~uEo)HHcIHLD"Hu$85z uAMgA9ID$,HD$HcIIDhAh(A9}A /HcIH4@HEHAIIh$A9}A HcIH4@HHAIIHl$p(ILHIILp$hMIc@o9gIcP[9SIcpG9?IcH39+IHHHHIHT$IIc@ H)IHHIHHHIHIIcHIHHHD$I9E1DL4t9dfH H IGAG IPH f@ f@ HHP P H HPPHHPPHHPPHHPPf@f@f@HH#PP H H'P#P$H$H+P'P(f@f@!f@%H(P+f@)I1 fDIHcȋL4t#fBIHT4 rfB@2JHHuMIcP IHHH9pH@ppHH@ppHH@ppHH@ppHH@ppHH@ppHH@ppHH@pHH9wMApIbIc@ IH0*z ALJt`y y Ay 1LHc诩IHIGAo IuID%y D-y B(AA1IcH4IILI 9HqH=G. IJDB(9xHqH=". XIJB($AD$IKAzHL$;Mbfox Lt$ LAoL$AT$Ml$)$蘪 LLHL$LHLLH$ID$H$I3L$H1H D$$Dl$EDDl$âH=4x IHIDw MH=w t"LDLŃP|$gEt$A9uHt$~D Ń5w $A?D5w t AH5)LHtHHrw f)Ww #AH5i 1H@H5+19LH 1HoIH531H531ݨD%v v DD$H=uv IHtZEW7E1111ݤH=3H5*1`E|$蟦M2;|$wE1H5*LuI}臧Ń1H5*LKfD=u -u {u ED$AIFH5)1膧HH)H51H1a1H5*L ܟ1H532LA#LH 3Hp 臣1H5)Laff.AVAUATUSHdH%(H$1D$ HHѡ ;1Ll$Ld$Lt$ HklBp {ul;LLD$CHt Ht@H4t Ht{1f|$=s u|H4tH舴H@o d1H$dH3 %(u}HĠ[]A\A]A^Ds {H5e ,Hfы{LA՜;۝ff.AWAVAUATUSHD=4s dH%(H$1ExH H-ir H}r ;.e DH-s Ht 1AHEDrn EH$L|$PDcA:E1AfD 5n ED}r EtHr Ht @fLH1HIcgDHD$PHD$XA ?)ѺHH D9#11A|$MHm D9#Hr Ht @D9#d AD91葳fH$dH34%(' H[]A\A]A^A_KL$HDŽ$hMl$H$L謞H$LHHD$@AHLDŽ$hH$eH$LHHD$08PH$LHHD$8+H$`L HHD$(H$ LHHD$HəADžHD$PE1Ll$`HD$H$HD$H$`HD$fD%o EHo Ht H=k 1tIL9t<1ձL5EDu EME1V&Hk LH1HHc}赚}LD$LHD$PHD$X ?)ѺH1H T`1Fk  8Ht$(1ҿ }x=_5n tHo Ht @f,D9# DCHn Ht@Hn HtDc1DN j =m {H5` HH!n Ht*HQn HB(@H1n Ht@Hm H@苖8B-DAD9M=Ri 蝟=6i Hqm HtDHPm Ht A9H1m HtD҉T$$DE ~:E~5WT$$A軙A謙AuDE UM D9vHl AHtDH5'1覞D$W0 H=!GT$fD}蠩C1mH|$IH|$HT$Ht$1P61E Mt AMgMg{E1CCHt$1ҿH=)'f; >fDD$$O0d T$$WH=T$7T$fDD#AfDNk RDf EBHk H29f {H5e] 蠔H{wH=C(F茓H=(0莖MAH… H{H֘ %d Bad request header - ERROR#1 ParseRequest error SUEXEC_AUTHSUEXEC_UGIDLSAPI: setgid()LSAPI: initgroups()LSAPI: setgroups()LSAPI: setuid()Bad request header - ERROR#2 lsapi_accept() errorPragma: no-cacheRetry-After: 60Content-Type: text/htmlDEBUGNOTICEWARNERRORCRITFATALAcceptAccept-CharsetAccept-EncodingAccept-LanguageAuthorizationConnectionContent-TypeContent-LengthCookieCookie2HostPragmaRefererUser-AgentCache-ControlIf-Modified-SinceIf-MatchIf-None-MatchIf-RangeIf-Unmodified-SinceKeep-AliveX-Forwarded-ForViaTransfer-EncodingHTTP_ACCEPTHTTP_ACCEPT_CHARSETHTTP_ACCEPT_ENCODINGHTTP_ACCEPT_LANGUAGEHTTP_AUTHORIZATIONHTTP_CONNECTIONCONTENT_TYPECONTENT_LENGTHHTTP_COOKIEHTTP_COOKIE2HTTP_HOSTHTTP_PRAGMAHTTP_REFERERHTTP_USER_AGENTHTTP_CACHE_CONTROLHTTP_IF_MODIFIED_SINCEHTTP_IF_MATCHHTTP_IF_NONE_MATCHHTTP_IF_RANGEHTTP_IF_UNMODIFIED_SINCEHTTP_KEEP_ALIVEHTTP_RANGEHTTP_X_FORWARDED_FORHTTP_VIAHTTP_TRANSFER_ENCODING%04d-%02d-%02d %02d:%02d:%02d.%06d Child process with pid: %d was killed by signal: %d, core dumped: %s Possible runaway process, UID: %d, PPID: %d, PID: %d, reqCount: %d, process time: %ld, checkpoint time: %ld, start time: %ld gdb --batch -ex "attach %d" -ex "set height 0" -ex "bt" >&2;PATH=$PATH:/usr/sbin lsof -p %d >&2Force killing runaway process PID: %d with SIGKILL Killing runaway process PID: %d with SIGTERM Children tracking is wrong: Cur Children: %d, count: %d, idle: %d, dying: %d LSAPI: LVE jail(%d) result: %d, error: %s ! Invalid custom stderr log pathFailed to open custom stderr logCan't set signal handler for SIGCHILDReached max children process limit: %d, extra: %d, current: %d, busy: %d, please increase LSAPI_CHILDREN. LSAPI: failed to open secret file: %s! LSAPI: failed to check state of file: %s! LSAPI: file permission check failure: %s LSAPI: failed to read secret from secret file: %s LSAPI: Unable to initialize LVERequest header does match total size, total: %d, real: %ld LSAPI: missing SUEXEC_UGID env, use default user! LSAPI: SUEXEC_AUTH authentication failed, use default user! LSAPI: lve_enter() failure, reached resource limit.prctl: Failed to set dumpable, core dump may not be available!sigprocmask(SIG_BLOCK) to block SIGCHLDsigprocmask( SIG_SETMASK ) to restore SIGMASK in childfork() failed, please increase process limitsigprocmask( SIG_SETMASK ) to restore SIGMASKCache-Control: private, no-cache, no-store, must-revalidate, max-age=0PID 508 Resource Limit Is Reached

    Resource Limit Is Reached

    The website is temporarily unable to service your request as it exceeded resource limit. Please try again later.
              replacesrandQUERY_STRINGREQUEST_URIPATH_INFOREQUEST_PATHSCRIPT_NAMESTDERRreopenftruncate() failed. File mapping failed. Memory calloc error[...]nilLSAPI_MAX_BODYBUF_LENGTHLSAPI_TEMPFILEXXXXXXRACK_ROOTchdir()to_hashCGI/1.2eval_string_wrapLSAPIacceptaccept_new_connectionpostfork_childpostfork_parentprocessputcwriteprintprintfputs<<flushgetcgetsreadrewindeacheofeof?closebinmodeisattytty?syncsync=RACK_ENVInsecure: operation on untainted IOGATEWAY_Irewindable_input.rbNTERFACE/tmp/lsapi.XXXXX;z0Ze p8pLp`pt0q@qPqx0@ydyxz`z{|$}t} ~<`d$PpH p 0 @ P   0 D `X t  p 8 `L ЗP d px    h 0 p (tP0Pp@<`PdxpЯ,@T0hP|pа4`tP0L 0$P8L`tP``0\0xPp ,@xp@@p`p@HzRx $0V FJ w?:*3$"D` \@lp  AABG EO D  A @ ThY|JED4S ]Ph H XAHlFBB B(A0A8LP 8A0A(B BBBH < FBB A(A0 (D BBBI \i`p FBB B(A0A8DP~ 8A0A(B BBBA k 8A0A(B BBBH Lȇ$FBB A(A0H Q D 0A(A BBBH L$FBB B(A0A8G 8A0A(B BBBF txFF$|nCXJLTlFBB B(A0A8DA 8A0A(B BBBA `( tBBB B(A0A8G I K I L N N w 8A0A(B BBBI 0 BMD GL  AABA < =BAA G L@I@U  AABG $ TWEHG ( ag H SHL FBB B(A0A8DPS 8D0A(B BBBF T bIE D(C0P (F BBBM Q(H BBBAH |FBB B(A0A8DP 8A0A(B BBBA T< CBA A(G0` (A ABBD  (C ABBA J8 ؖ-FBD D(D@T (A ABBB  ̗( ؗlECGF AAI L !cBG A(D0 (A ABBE XD0` t Z T10 pFAA G@7  AABF  @LsL FBB B(A0A8G 8A0A(B BBBG < P d x   ̞ ؞   ܞ؞ <Ԟ FBA K(G (A ABBG <XFEE D(D0M (C BBBB (HFBH E(A0E8I@ 8A0A(B BBBE (FED ABH$H BBB B(A0A8G 8A0A(B BBBJ DpܴFBB A(A0G 0A(A BBBF LD FBB B(A0A8G  8A0A(B BBBA 4 H\+p,($( BFGA kFBDMH^ J x tHU |gHQ G <ayd(T(EDL ] CAJ ELEY HW HW-Hd(EAD  DAJ ,aED y AE HPFBB E(D0C8GPm 8F0A(B BBBG ,ZAD J ABL 40oAD  AAK pP \FBD C(G0 (D ABBE j (D ABBE | (G DBBA HdhFBB B(A0A8G@ 8D0A(B BBBD CKw PoEA J F A 8FBA D(D@ (A ABBA ,P(@LEDG0 AAI HlPFBB A(A0 (F BBBH {(F BBB@OFBB A(D0D@  0A(A BBBJ 8{FBA A(D0 (A ABBF GNUV@V !Q&.3:BM[mv/?L[gt~)4IR$ 3 C N \ f  @ l ! !o`  ! 0x' o&oo%oD( !P@`@p@@@@@@@@@AA A0A@APA`ApAAAAAAAAABB B0B@BPB`BpBBBBBBBBBCC C0C@CPC`CpCCCCCCCCCDD D0D@DPD`DpDDDDDDDDDEE E0E@EPE`EpEEEEEEEEEFF F0F@FPF`FpFFFFFFFFFGG G0G@GPG`GpGGGGGGGGGHH H0H@HPH`HpHHHHHHHHHII I0I@IPI`IpIIIIIIIIIJJ J0J@JPJ`JpJJJJJJJJJK,LSLSLSLSXXiy!D#!GA$3a1 @y GA$3p1113V$GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA$3p11130kGA*GA$annobin gcc 8.5.0 20210514GA$plugin name: annobinGA$running gcc 8.5.0 20210514GA*GA*GA! GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*GOW*GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign GA*FORTIFYV:GA+GLIBCXX_ASSERTIONSlsapi.so-5.6-1.el8.x86_64.debugZ'7zXZִF!t/O1]?Eh=ڊ2Na8_~ *~, 4?}8P4H3.R/qFvk-B3kI89N?{gÏ"-ndcLgPr/? Ҽhc1*6j[|29 ]WtuÊMmv#.-y"l*(~:nmv(Bo)I6qDpyHN7Q ڦ?r&j86K:4Kđ2̙U٠jŸ:o.0?v #K$f|Wj.'eU~R̛ǧG䃶B~>KZ`z]/(rNOnLC i1)[t {_;Ƽ@vigrR׹+nx%.5pv#kWM`T$@ƠB9uy@9/TޘF8~qB'^/42eGUrx&l8i;uUiv}I,deU)Q.Ml_rz\$/Hك dˇ Ebqj Wgtz:A0tW]zֺV aOBDo\-&!&)LlQ WY%EC(٘v r$h t2QchKdtbӲ79U$@o:䪯'SyL!Cq[Uf<4f%4VCim1;is"&j6 )-v<+=d>GRnW@ B,{#ve C2l'L4p _3YM)eG+tg]MQPsUwl/?yZK$~:DF BHւs4y(\&U?Z3~\]H xŎ 60&<< Ln{ЧaxD27EF}yR*U3頌ԇg?)~#/*3rk UG$wJL$z-I t^79,b !F"! W]]y,rj-} DuÜc{O7M5x?bK' ؛|:޾?Ut^^ iD$UU ... end There is no need to change the way that how CGI environment variables are being accessed in your scripts. You can find some examples under examples/ folder. Ruby Script Runner ^^^^^^^^^^^^^^^^^^ If you don't want to change your existing Ruby CGI code, you can use our Ruby script runner under scripts/ folder. You need to configure lsruby_runner.rb as a LSAPI application, then add a script handler for "rb" suffix. Rails dispatcher ^^^^^^^^^^^^^^^^ With Ruby LSAPI, we proudly provide a optimum platform for Rails application deployment. Ruby LSAPI has the following advantages over other solutions. * Easy configuration, deploy a Rails application only take a few clicks with our Rails easy configuration * Fast startup, the expensive Rails framework initialization only takes place once when multiple processes need to be started * Resource efficience, ruby processes can be started on demand, idle process will be stop. To use LSAPI with Ruby on Rails, please check out our toturial http://www.litespeedtech.com/support/wiki/doku.php There are a few environment variables that can be tweaked to tune ruby LSAPI process. * LSAPI_CHILDREN (default: 0) LSAPI_CHILDREN controls the maximum number of children processes can be started by the first ruby process started by web server. When set to <=1, the first ruby process will handle request by itself, without starting any child process. When LSAPI_CHILDREN is >1, the LSAPI application is stared in "Self Managed Mode", which will start children processes based on demand. With Rails easy configuration, LSAPI_CHILDREN is set to the value of "Max Connections" by web server, no need to set it explicitly. Usually, there is no need to set value of LSAPI_CHILDREN over 100 in most server environment. * LSAPI_AVOID_FORK (default: 0) LSAPI_AVOID_FORK specifies the policy of the internal process manager in "Self Managed Mode". When set to 0, the internal process manager will stop and start children process on demand to save system resource. This is preferred in a shared hosting environment. When set to 1, the internal process manager will try to avoid freqently stopping and starting children process. This might be preferred in a dedicate hosting environment. * LSAPI_EXTRA_CHILDREN (default: 1/3 of LSAPI_CHILDREN or 0) LSAPI_EXTRA_CHILDREN controls the maximum number of extra children processes can be started when some or all existing children processes are in malfunctioning state. Total number of children processes will be reduced to LSAPI_CHILDREN level as soon as service is back to normal. When LSAPI_AVOID_FORK is set to 0, the default value is 1/3 of LSAPI_CHIDLREN, When LSAPI_AVOID_FORK is set to 1, the default value is 0. * LSAPI_MAX_REQS (default value: 10000) LSAPI_MAX_REQS specifies the maximum number of requests each child process will handle before it exits automatically. This parameter can help reducing memory usage when there are memory leaks in the application. * LSAPI_MAX_IDLE (default value: 300 seconds) In Self Managed Mode, LSAPI_MAX_IDLE controls how long a idle child process will wait for a new request before exit. This option help releasing system resources taken by idle processes. * LSAPI_MAX_IDLE_CHILDREN (default value: 1/3 of LSAPI_CHILDREN or LSAPI_CHILDREN) In Self Managed Mode, LSAI_MAX_IDLE_CHILDREN controls how many idle children processes are allowed. Excessive idle children processes will be killed by the parent process. When LSAPI_AVOID_FORK is set to 0, the default value is 1/3 of LSAPI_CHIDLREN, When LSAPI_AVOID_FORK is set to 1, the default value is LSAPI_CHILDREN. * LSAPI_MAX_PROCESS_TIME (default value: 300 seconds) In Self Managed Mode, LSAPI_MAX_PROCESS_TIME controls the maximum processing time allowed when processing a request. If a child process can not finish processing of a request in the given time period, it will be killed by the parent process. This option can help getting rid of dead or runaway child process. * LSAPI_PGRP_MAX_IDLE (default value: FOREVER ) In Self Managed Mode, LSAPI_PGRP_MAX_IDLE controls how long the parent process will wait before exiting when there is no child process. This option help releasing system resources taken by an idle parent process. * LSAPI_PPID_NO_CHECK By default a LSAPI application check the existence of its parent process and exits automatically if the parent process died. This is to reduce orphan process when web server is restarted. However, it is desireable to disable this feature, such as when a LSAPI process was started manually from command line. LSAPI_PPID_NO_CHECK should be set when you want to disable the checking of existence of parent process. License ------- LSAPI library code is under BSD license LSAPI ruby extension code is under Ruby license * (()) (Japanese) * (()) (English) Copyright --------- Copyright (C) 2006 Lite Speed Technologies Inc. PK!$gems/2.2.0/gems/rake-10.4.2/bin/rakenuȯ#!/usr/bin/ruby #-- # Copyright (c) 2003, 2004, 2005, 2006, 2007 Jim Weirich # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. #++ begin require 'rubygems' gem 'rake' rescue LoadError end require 'rake' Rake.application.run PK!#gems/2.2.0/cache/ruby-lsapi-5.6.gemnu[metadata.gz0000444000000000000000000000107014554463574013455 0ustar00wheelwheel00000000000000|geT0+^zC$+BHp]BLCwwN-j/H3~32,37 [ey3 h 3RC#(i<qb?V[bA:='br ud 4To`;%":1#FӠ+9*K _FB&+g5/2=_3k`ӀQT`!szd.Gě֓Yt; OPptn@KJBt)lJ)ŵ؈2AUp_0?i-A.}R,#data.tar.gz0000444000000000000000000013520614554463574013404 0ustar00wheelwheel00000000000000|ge{_Ȳ(=fM3+C|6X\-NlK!oU/2Ya&`jZ/?1w_lGϟ|(}"P iIefԦ?9t.z$Q /kK~j`9=mZ$ %i-$vdF0.iv9tkI?%'=p o2ӌI8 (#w=bH0ʂd3NjDMj Kc't߅5tm`Y! l W<] $kPZ'q8gGDxܑ|L)a/qXL;a֢H9@i ,0GtğwqX5BhtGlf!)z**`McC?HO'8*2_^ ̀$^`锕46Tѝ~B>L`Qeq;d4̂tȂ(,+0DD.IŜ|B6u)$ ԑ~w>(ZPXW(ZZG u R)k.0yҟ,8L=Q'S&ٸ΂Y f|qdtB"q GQKh(+*[Dױm;:/䄢єNZQۤ SQq͉ 1?\nBLX:ѹvo{6AthU7gLnqrY. P1oFOb~^ÀFy1j6ڼfܸ2J$֠qka+F^W+_/\r; pn,! yAE1U%  5I.΁M?jo%;|{6TFż>rT9sN }\%9VidJ@*J4n3ub^5rA&nH @Ô~ΰIF2]bsȢ˲9?Qx=4@p4x# VaV>4ʚ VmH4m ix=3fp9/H7mR/O7ղ__O_)g58i{6ngFGA4*T"z7PW; j[H j$'ғ!x_ӋFHol;jp_덮xj={k_>_?';4ٙ vhYV3;Sb6.@P죵v4D~ I)~~ Qn` 7v |C^lac2Xa?GNim&;FXvƿ i4jlF܂7y ۡ^\vNds#Z5OvVGgm` H-v kW? ?zavgl{݃n?6wZf1lOIxEtx0B1 ۣC~8RQ?mSfc(,# RafHl"N4 P|Tz⦏C`flwHƓJsjq"z EҔv6|NKEQ vo!y{~zAٰ{s9<jk\H׋~w0 }{wq`9&^Na7b&mԮFΏɻn-|{3l_됋N;aNܭEbgIkQr?e{#0M *&f`1 i0J?nʜhfՍQ]jC(Ѝn S@Ijidc"cl0e):*rĈh1=T6v {8FtFEf 5 @vi83ЃYKoWۣ?EeϱQI/_VῬY e. C7h͓(ғ$b= dS=iLO>A-Hڢ'בoL14fZ[I~rmF=TyƝzJxN]XA"\O԰/"F)?;!a|e%a9(NFsGo"nkR˼Ym0Z|R#)L<#:Zy2\Ʒ18 7# ς uAɝ#Qsqqڵ Ceg:V'3 ݔv72 D~;zA=>e$CDڧDL"-i'5jXZދ¬^ƈ}h.c/kh@2h;{XLeiYM5puf/?4IܩnC^LAo#=&7|Nӫ[Go HRP@@){w@ ⪽.9-͟ȁhx9~Nco3oۮeiP^jGΰK,5T~=!=Du-8ɇXz9Yg^픷iWg ({z@FrLa zGͱ ?ѷUKe!_`Ay\^qȩfx"S5pDɓz#HD>9<=+a׮= SkwUޜ$< XSS,Q, F {Sz 86&l59P qG~ nR+1n{4xGo7T"B.aþ7D$Z"Fztys@7Rj]/\atW1B :Of[љPAUՃ GmB!

    F^aA'CQgyCA\I?S_F3 4)Z_O`cDϡ0IMc)S{I$d$f,>ғ9'oR]Wcf+l;y}xOh vכ4p -}/Y.Gmd#pH!>r(`u(|1['Χݟ'se3هJyfѹdc0baIlč]6!-I3 N-y h4ip1nH4aB mޒ/0fc #Ly6 (1{3K0ԕTR4i{Ocmk j`mHCbSJ4rz#7k1Ƙ+ ׸pٞ?&8EQ[jejزZB P>!L*EkP1ћ7MZ/7t4(S՜>)ʤ: ko'#g z `yvۉ:4ӏʊqi7=C6!z14=)bt[FhAfQic/ ޿ 4^+yFStwX?q&5 zaTg1} h;]\cJ$ R @#&1,Q E5Z@wߵpXM"kaL59i#OApZ@װl((Pɚ3bqɳM@h 8TJgxɸ_#䝝@9#od/]\Eh#`xwcwp0lXd"P'=n;ز4J ?쁍t@fYL2#Nԭt :B}d0|6ٰg=)6@tp8RkB*&֦M|dQdӶޔd,@A.-Ʉv>vg} yMk4X[knclbHcTmT3,sƼ|"Se <$tm>\;`D6`@~F$n*V(gJ!;5wT e Y`#ouȚPlTV3->tٯqؿ|' JKDN-Z[LvN;:p>Rl>;$P77y9;JJr$q:gy8!q\c)~@\֓2: 8v;688dV+Pܔ{mJ"(,:ȆT[r,W( åSi᳑d넱L =U671ݒ״-H`Dy|$#x vRce?#T[iyՐjb=@̢`+DZ6.Zz{ڳyypH(m(x4IL%ִ4(3dNEOL70́_[F:i`1U` W:VπtblV_ hW""N Uf "˭BHaB> ,m@:uYw~@%QrF5^zHGX%hݎӰ5ktOL'F.Г^m>(22PϪzVA]r{)UA*HjV(A-Jf#1hHy`] .b|q)mBY) P'3fՄWRlr!{.[p@_\`ٚ)HzI]SM0OG7Ao(NG׼L@REOa|n>Xc9XvD(jTbv>DZwuVp /cJ9Vf76ES5Te{hAoٗU\6saSqzdW6Ƶ-؈9fS^&?6`H=NzDLxq ml .ll<ՙqhV>[{$\ pL-~r-v5#~+J1+ >7%do%IP|"H?aqGLV ,ѯEюC)z\\SNXc!RI($$zᾲn5Δ/ :XB %VAgE!+^h`Wu0sVڬ\2ZMO*u]&1]6 E8~-t_2 踵'7a*]N6go8wdϴ"UvNY`ם}v .v3${NW^Ȑnf*riJWיE9oLX/qI'A~uu\um06iX/Xvo?&In:eL5^WT~F R7 Y*^LV'F=`V5ɹ?:?;4IeK}D^ 6iBÿ"ߧO؍@%dac/I:lԭVB6maɟ`|mY\R.G5 "V9~3 ɻNZ~^~QTϰ$0!Iش'~f0 Ա#?őS/2+>8gjS k P@Mm9Iz&ttE1'V'Hhw̿O_|djK~0'wAށ:ź_+ wE_Bok\šA~aӷ ͮNH)(J@a Y k lK$bw^Ϛ T5UH2k>:!;;Ig=]i~cHqոR,sG5yuot]4x]r`gGY>Bߏia_L3/i:I֯o.UOsrP59k :|KyEUxiZlμؙ',f {mM2:&4ku4U_2] ѡƕc@1Dmڦh׀%p|T̼uPߙ(@5"?)?Go <"m{*(DS|h\U9ڙmaCV t2u86ڔޑRf.c44$|_#sź<ɾ{%P/~U !!eM*{h"~cuf/:h4jE08B-A܀D[b&f&b*s9qqOs?rb=`'t!yb) O2ԒM蝝ڿoLM7H(~$Bկe3j3UUO8ƚ4fV}~u0(S^}Y4$pUi 4yVX> f6M!F|̨F15[G:C&92rhUeo4{\D##Dqx _*ԧH;ׁ &̊#K'U_~R9g~ܭngj2YCoOé(JȞc  0@XBH 4!% &X!m:!QhM AyO`hv=XHckK"y%P [ScK?/ Si59e4\u cX\z5w[?_'NQWp8*ZFQU,m lg|QVIYP}ȭheg@v0 Ф".m?NYv7rf-OhPd_}&Qi,:ww?FSD#&da@@ 8DRYlW]nr#[nF!(AX0wcH.-_yO ;ΌBH/U1NAy}S߈Q,N~RFؼ/&[OEh8~Ndt?-aޫ@TL8W(ܾdSWk耸FveG v$"|Khe6mwCRH5=~\e3zf}cҬB=1 !{TTҮ(3W^LeTt ʮ_T"1I^kIV|.o('.qVmGގqtyCF-Y7HeUQZ+9D}㏥/[>]e6؉H;$_6{.8JCck@{>+@ъP2Hsh)YLu:w 3 r㍮u,;g!-Ams9 }9 Ofw[mj J[o-JfŅPŻ, ĂgiHf93j;adȝ bt TAq\) ͼJul@5ADP j{I ^Nmgb{_ԞzQ{"!/ba9丰L/Èy ??=}$OOm}B<ww=jjv|f_/:?uvX #zn_+! ј@+3("yݩQ?f5 ^W4MZ6{eg$9)#Ս\Sj?f:0g~`M嘍=}+-y z嚺h^jAZM].X2.8vE^\$r#``J7ݝխ"XVFM2;#k.&)K _ IGݧf+#聅8p]FEH&ڻ]1u +yOf2.2YrƷ 5fZf3+\UA 4}ѴLO+'6ئGS4o-3Բ۾b [ҢYx=!`V%%.Z ]]!s5x  &QlAj{&|#+hOwn&-&BV8g^5!_Դ>Ě:bG ]N8X]܁iKV/x)U"iʴ }[-%J(y hKd+^ߡnC;7b:15 j,ť/vx̲aDb@2+i^䬡Ab&48:02Ux~9$ES~Ps" dׯP@^2ދg񉼶% AwR:?_t.Gs_ OUU‰3^JУ4LN;Rx g$N>zH`"A^rMhw.^yd}sNYV5F<ޟwq̽a8p]'OO*3QW[/#$j17+Ed\]䒑ŢѠ~h< -=UH8yDBi`xsy z1MȕqwYMW%*۠I ,hBh ug#`8lZm:.e"3cr)0!_w=+(t&TivϿ:B߯ b{Pby/C &n(e?{Xs_Y髗 `.}W;]`eCpotw?Z<{fAINO'pocygXs fwXsq C1L-PлϽE/{p hD>?8Swv`z1wm,*9ͽn1OǍls %ţ'kc$-NΎ'YZ*qd̞g%6{<K"mKu~ ݳU@nH:\ȗR묇xO0ϫ`ڮ-O/4}-u1ru? p<n8i}k.btεbe 40Rck =Bf9@Jk83Ju`77(x2_lyC}zaktuIhvtV[(#Ĭax6P& `L\27%CAx.Q4V!11RgYJP![gS/Wf,F0 EFFasQL0 JBO3NńzS?kpg9dW 78~P6[B {6XgEAWY礄uޅ-dC{̘rȵ2 Z(bA']90n]WT;@łqzZJ5| n:SMډ> ?lHW * DKԚ8,F]2J|ϥ~ ]dlIFx>s\OD1¢X@0}1G9":oqx-pz[L,. +}A Kix5eRU0a=(`M9ڌ(=pURgEbY@a' :bYexB*DH1e*smW|oA*SUV f+Y[Tvi3艦?Y .*;Th`7*aKL;3(1Ue77'r h |))e7z...FP˶; 70ɚt P&OxBFk.3M9R< f+rX05u[L8o)oZ QiZ_!pvZs0EShϐ5H_x=k_4һXE jnzJ lr8ƼZoj]3h^+H-伊=:br9!xc7%~i?UWɼ擂 +8t!ɥ^vQ'T2E&{Qm6RvK$ދk ,byS ++^^vgVij&V9vW/DsXJvn'oKc񫣴#zcHh wWܑ-/ <-$b#i:b Fu疠. tZ|;CZUF%FPUMe\sx\w`^]+KiSP5_pLa$p"2ȇ)P$M〼Nѡ훃(HAOQ( ߷?pN/чtr@B0xG< 0(Vk{>x)ʪ (}[M^'4Jx&]V xݎŜ""F寍Ux*)d du}un1!#{ T%<p`YG0q<:k܃&Дn$sk0pzR+6K93H-|r[vWf۲VU3v-eGXV zW݀ƃma4p >׾`5#ͷi0}8Tg~#9٤iQZ(#:-=+ffyJay[|H ; l+խL;cԴ]fU99uO:N';3?5;o3@!uw?826\+fNz;i^ mWe{%"@vvTvh-K*67vU1d#lI 2nöCMY1K˔*N ~*Qa~ r*$K jT "U|RB݉Ryi|t?]n{QA*+JI׀֬<-]ڋ'f% blyUtoӪVWd LCɩV@NyƗ7~ ]i]|NC| 5qPŝ;tn507uYf~˳V;![%9F#с#'ʌX[ٴ'kױ: :ynYtm̗?'GqtC9.tT"ԡ, }:xOY,FA2y}Ou_,?2#ǒ>P*O >WH7ƚyU+fU%rZX tG |Q6?X("e[{;^xkMB_X] `4b ⠲vXxYsٕ~传K i}ێҥӫu'Fl'io3pLg%m,v<; v@m7XdK%by]Y˼sݜ'Kne:.F_x h5E'ڥ#֊4jcFEXc/ڻm2ΞI,b}Z]Ss3%k L{#b`~ئ JQ0D;ĥ5oE+)`q⻥ȖIԨ}j:miG3JG[~2X еJ_3LUks:_%li3ҥY_0!-U?C71Ueh~өLg M=1ul4@\F31!獦rZ R-x(j%ZFQǩ*j6))Uu#j4t.,R5]r>>,~lK;xv@< /\ !@#,sx}~_]8Ly:,^eKs8&(kMBMz{"* ) 1M6p2ԥ/-Ɵ~O~G\0q t23R?(6UϑSEM|yHOlߔ9+ۿ7_&kˣ*pD|]a>oY*U%c5b4HUe*x><5tz6Wz ܷ) M~#~'Yt˼ם:xhe8h}8ݪN$촻X:Bab\NZuclKD~i^(B E!0g&xqN4'-2mt>P46 7)~fA y UB]QDތ^+)\̧Z拾g*"0/zrMXD0H#`<[DBq0Ւ/5Al>z׊M#|A@S͛N>R_!->8?/%wQ':屆<ǯ ^ј5< XK*O*Öo28&{% o'c8 aEưO>Mt,n0Q9@[4SOG>$ȯ&Ss#=GI"%ȕ0M('i  L}yuދy_|P(ۘb|bM)/Dv\K( P4IgDE e K։K;AefdzGnڳmna:¹ѳj.EζQYQl^ZsjNj ڶ$[$L1\kjFjh?MGz E9Q vzCPif=HT4ܥ] 75)ad$wbQ|*gUNo督`] &>ZfiM}6N!q=aت%h6pv~= /_xBB۳*}bDZ骅a QK eєm?3b`.#Ѿ(c$QWkMxdbeF:2 ~`f̙@[o}JH|J⃭ۏۢo? &uƹ A,UxinJkcEKRCUcwlL[t{5y;(9W 7-X; FXq5D^LQѼI4_h :W YIkU٥=[t8QcD@zSΜELH4pM/Cy0&TCOSόͼhe@V(+]gR5 {bL]L7ԩÇ/x9FU-ob%xd/hNfKrj3, 5?-ɫh'& )z;V,H: )Blj͘?kŦ3cj,_ aU&_QF*e)h85a]aOS)a/pr.Pd< mPSH}8feel{*ñ!'Q*&V"b';N:ݣ:'jxlݍ 0ey=a=|wQ+|/fɒ9Pt t(^s]Rڞ̆u_%sȒ0A""ߏaR1N9Sn޵!GkcNM^pDwp sî㲡)-8QիEMAp-2W6]: WZekP|QVPP%inʝժwtmjLu+[gt xZuڅ[;lj*G#5\/kꀛC<[[tAmRU\I7pX mmi묻.sYHEmK;P"$_hɽ"Mcu@6mؑjűSLcaF[BX[:AvB=jlzAf3^Gixn|a|\x3ƏЍT#ԝX;E*$0k(g1t" xMcR38sWm寙Tx{]nLXy M\1 YSh6R9:d/Oi|O=z([Pi -Җֶ֪5C#d*1cw8ovPRh tv}E4 "{%hn`^O⃱XK"yYUd,)ny|& }5c̰C1-5?A=Ӏ,{!v;Rp@OcYFZgVt`'5`HW^}2(COA;M^dn `}w3|"Mvҫ0'dk{E(\b 4iD .HQK74| z><[([.lA@j⫀= #R夗@5\W1OP欯;{zN߈*JRCBqjٗ/Y*JV&-MO0$X~ʣנwr9跫vr#;ӝ*$&0S>|`mmb}x2B*7ąB`TC_T쥋9(S f2O@FȲaJ_4"i\ Zb{9~DέUJdZzΎ3斯"ͼqp-\$X{~KT{j/b8ceUH ƓntD 說2[:?0OA0Jj0,AoM ۍ簘u2ǝ,ybgGPW᜽%l/F&S-ɧaQГߛIC@ɝYŌOސ86P댏fDjqr갡pn7]򴚡sU6%H.ޘv>s#M~LQ4f!1fA2cy b&۬eNg+6d4oUD5-Z< Wqu^X(c+"|Tz~)K`oai 4b'SBZ)[]Hjy+6T,މtFFGWtcW՜6 ^p(X(OLRUu&"ڰlȖB(hԻ]p/rk_ZD`/hZb jX-̓*wG?oе]q_-FO4,hA ߖ*P(X \EF*P8+.I?zKWt@tZ s7nTl$t{pn[@7Xrs[00Tjf>Ef%kzB ZUWd%HE> E%rdŢrXԲeeQUqtKLEe*r-B-wǓ4Kl^ǒM  hϳ Ͽx{2mӂѮ*}I'(|,M88V V~oKs`MkbV)}(~5f=ԘFPN_~ލNivj7^xꉚ/y>6glģqt]tb.Ve,iGIaΤu-tѺ˓?˓tݡ `TaH!T[tl5q(KGڳVn9)ʍ:u/d e -;~.gu|*;nyRmp:)uºǏZq8`=H *M]k&+?mʻSyZ%Fw:B``[Z0SY7X $ &>g+KN+Y0uZ=$@6 צ]?n/Aϝ% U)8h^Ik (=; $<40K[h *AZLzgpjMI/tWb:e=W(VOU%~vaq 'P gGMz2pJ3a1ûAbhf04Z.H Үx1eM3Q %mv~aN- #6m0QTҺ݆zS9c&Va]iKz;xa+K*<ԋn)4n1AB\rf|SX Ԥ^^F&4p??K^ mox5e/9 ǽS Su'5'PkyM8rkiWO.7v}}+ "m&)SO_^YNm`J6yd˥^h杝{ǿ-kvS #DwV\D8E찌 ̐{-v Ϛȃ2񂌕huVa]+"|=&};NW+]-L E!%)llAiq{ބjBŵDu h A"{왒 1> W/]:wVx$ժ㸣r' +bhT;q?uW~&)4e Bo/~wJ\~~_3o)g܌k: KΔOA{G7'^|PeiQs8)nWsNGzb, qM~a]j'ZASmt6 U+s1Qo=&SYN#4Mھ)[K8p*O9byi JSh&ps5TKL"OzAS^s ^VQԔTkwwG/ gj1yClT}9;5޳8 ^&Lو_}YbY6 k {]K*WY@A~ъq>*/%T0nj_j@%*.a6h} _mC_/ڀZͤQ٠EU&Ą}wWI}k & Ŕ^f&4U(Nb`?# 30F #h}6t~qOk20HQIZO[~zZ!s,7Տ3rwY~ǣI`>cֳx3g?sxF#ьx'hh RQi#Fx!=D; BdK'X dSh19'5*"t?SLG g,u]4+?k`O9Z%oA$'$LCބ7"6$Sno{9 5: ɞ RSx!jW~^;2.)Õ PG\m\)iasVp8 {s4b5:8- -yc{sE]%- |w]rE~Y+чpD|c{Ķf4f;ot;ۛ[F]4Fzuڃo5H4Z獺NA]#Ŧ7վ4M0ݪ٦;Սz)m zS፶T#fF4dRMCmv:ls ymw2SMVQV׳޺ߣڣ4om?X 2NKRţFu.nVOK@U [u4KMKRQo&>)1P}k37kBMJ,p[h@DoޯU7{$IZبmlgiǯ[;$V7;ݝls^ j^mNbvuiNb7zv)6eJrsQu3Ӝ.w4%ĶzQ)ӫIzv4?ڨklvϩhzz[ďdjJ7`s} EuG+77:Aoldh }QIflU3IlNЁ]8'A}GiR~MJ ՝l,S2'$"6zG$!^s4J&67;&%i_v'de6w66{ZIIlLs`+fe׫F9 m՝Z8)07׷zI uz~mR{N'ۤĖ:;[GrN9#=nt:}}GS%'̴z֘~uUrQDJR؉7^0id%R9Lv18t9 ;I]+CϺw8蔯~1*3[ț 俱ꟁy4U [Vɿj0LW3u Vkj ߣ,`g VнrD N9w02jZʹiD3{=!F| ;`O9%J\eN|=X4@l`Lʒp^.,FQ0LkPrLCVb/~'E-B@hЀ1bݡY)[!Ck %'-BуH*F{aw>Rp6W])jMH:LKDC+Z#| @"F %qH<(8u&ɟ YQ؟]#Q rc$"AA83"9EM/z8:g;qSdy$_4O-rgoMpр/>Щtp^0[\}wx =?k5[Z qsqǎNY܋ ]~I8k޶'EX_+4}A=9Ʃ4NNc}OD`eV#;n:jj6{y(R5ϰBŇ1єqil5_?7lQ)ȄPvZG!>cܔO쯦 ('pk@ex[в|7>?f=vU0($0 9υM??Z=f3ִ"C`l}KYT%L?׍J!؈y)7OMI*X<| ᜊ1A+Y* d:hr|OcJg߂ŽD͢ н0Z67Z]>|`U7v '=n.IU,*ì%>Z  W;Zd5-z1 8չ?Ktd/)\fb<"Ԟ @Wߍҩ0$VzyuE~w)N{F@!tgq1v"^J[΢Ly7bg0 &`Ȧ[`rƲ$i tb vkp^3$|,XxvH&#]Xq/=GE( #w>xkBrXG.ŮYf8LұkOϡwE]L;YC8E'w'7TKIp܀Jܕa'lھLn'{1Zp2u-^M6ix0HMgw:O; z/I bJMxS~&l@ڄZt3yߴ *ĄKLBbX|bbsR{,ZL HEa[ &T&F$ "5, вDJKRQmq͉nqȣ5N4o3#C&6(wE@R,q)8jdGRt!㳗)-^_{wM=ޝ2h98]9eJd1kQ8vTYf[ol U>i_ʫH`IMB~{9p{KvI=Gok0 KɫQQyu| b^j7UjP0GQKz(!V㗃cc#Fkl8с7) M%oX1+{""D<[aGX{4^ȬRU((&nW^P/]z,ѰX$u'=#ꑗ= gx/ jn~&T6A\(Z E%ezS~e׃[T%pCAzAG ܡ {䣠"%ZJc{*xW'p5 Tp("xƿ;8O6 z_ }TB ZF^D^$D 9j >v_*t2 1G7߇l%x VU"XXWQHM(jL4=і'XUXXVWXc#.6Y[&7O.=$pMFjP1_ eVKُǒpO]|9fX\7G~w`C&)%Gړl wGsI (hgY{:Qx*)iV ~lyl; ){SicdψcyjۡDy$mfh8 &CPZI]~ s>iw/E1=ERKO&JZHVcK:521'HM*>/L)߃%+%)E,o])H}q9̜bΕF+҅¯Td|I 8+{*Oվƴa)zEԉn܆%f>*KNIbF),qƶE׮,ҮG6pطLd&W#V GsDLh WJH F"R".͞c\`Uc{ʹymub]r9 k ٠K->ϺZ.G~QksҼU[CmH?vJ1`t\Ӻ;| p&Jŭ]j "AxVfQ"TNbBinlH{KB泈=,J`U͵V}Tu7%MM$/]m gk`l[pE|If}ݢr|aIƋCH0yp{鲷1i[b`:ECQ9!Vr m CIvWT`yi t0(R=U*ɲ}x$޺m-~<_`jؠqv 5Hc8Hj7 q(AM\"{PG${ tF ]ޏ)MP(Ǟ;eݖ{"wAKr$Uϒ{hq K> w;{tmZ׃zơb]hVFZG&'/"мܥ.^JYs9;V {[  Dvnnx7.|s``*D|,X$ cv-_b}~LNDGGJcezy^L KZ2Ve^GT{|6 E+zlX_C!;HϤ)Ȍ;\כO7SR '?2tsOGb쭀.$niKJBn[X -·= ή|VdiG3;Y2E1:q\1?bs@lNՅ}DO"Vwe/j1\Fq`UEܶBnR EC`7V^X`*a)wNkPqERoO/W/V|mi,K|}jyxqW4HŘ(T٘z\fiG4X`,_i҄va׋H Fo.3wb6!ڱ-y 2TRTw>٧vY-UxhA<&zfFו 6 6Xl`BP /wO1{uIbE&Νہ*\gnyOٓ,x~֚!z>%Љ0Wf/q:pr2ް+XOyi[sRzūIfqA;sq81e@軁LgǗn6kdxc-A,I7ws&I i3PsKlǦN 'r'5I& a*M1y9a2A'tѮX#Cw,JqUiKhiOU/aR-8iE7)Ȅ}^ܤG.]*K=omX};t헺ցcaDۈ4 ޑq=J'AyW$,;ܔ;0=AJO\٬}V$vƑf_trHhkOg?F35=Խ.╞mmK۾*Ț(&dʻ!:_j_M2"( 9k?>0&ަm4pqg/me[bj~}rƕ69l/(]}[E!uS $si'C@w}۽?«c2G8H",kT噭ڲ`x\ ` 44(af{ŧ?OONZ˸҄#^Qyk ;q3:8t#)0&F/ŏ2H~ ke Xg!9(\s $Q]i -$m *HBzәݛYⅬ(a3-k8:h5~9xn Sgis|<8ljy{i WJ\q#!B!Q_uўV4}w~ / 9A '. }4iS/ˡwؿ  Tmseۑ.ߦg^oݪDUO%~4l@Ua4泮~h:KoDҌьɒZv}a?[,2gejjeL _U;)!ڝVC7ZՒ$891#=/g]<5  \ ##in ǔ$ǍGYЁj̟2,%gFk |]Pçy߽hAP*imHѯCu{OBTc; \Y=f l~dm[q_/%K=DYM5HVo`#I3q&{3Mu(JX w*dtB;ʪ0C-*V+}Ԇ3R#҈qi|tӪQD,~o&jjSۅe̍r$p`s ٌKD'}v,Ӡ \<Ⅶ!teZUFA$ qee0B?h߫Z-ƿWhwR]2c)Î;+vTFsK%"Z;*67[ygvZXu^DBCha^R`,< :Z"+`hF7 `vŎAtRGp>wwaF՞B N@Oxџ!?EMy^mݫq8 /AĚn9AytφP?3^`8W( k;w5Mv+rvW.eпi<.=x?@= :m@\iJx*/p;|OY++) 3@`d)ڷVCIQogSȠq*Pjp:) {>²+^ρulPG4_Zo~eM+ð+pov@uzYEj;rm?o*axN?gro0ţk]F|\\V /Άh%OӃ=0`쳛p^y -"&W%1^OaVEDp>C334t1؅a`*W+ZSRiA~PRN5M|7ϑc_@l{ڕeIN_ժUߪY!wvCH*'/ EwoMirVw/G[$g]\V؃2t bN >)>u2Y L&N2}'D~'MLO F]<%N1mík&"dW7 L~~9#>KD ̋|%Ԓ򘀏/ ~ KƪEy9MA7`DrŠ\dVt{u(#g|OŒr& nс B?z*էU*ns3A ,ߣ)_ 4Ɇ߃娲2 Oz58-Ovq ';_QoHYuqy3kQYǟ|+_bс c,Ԫ[xzO9A4 OW3uSYdo@ 8zL˩?BmGavO2TxYi=E~ H eS 6FSC?_cG&W@[3]tLj ˉBc<A!*Vݑ?)[{7[9O!p8}J3%MYrƹ'"iǺ,M9@.y=i<-{WqK J-~'hzϡN:zjL =J4|2 zuiPu $蕕|`r+L; q$VH - ګ`p?Á2IyQZT%:.>SNxAmЀv4'i_k??! <"  +WUH'ᰍ7ό_I}U?gFh5*N!b^6ϵ޵JUcR@VE|jW6ɦS tTH>7E28oܟS]eMeH6P`7AZ%+#u ֮OA?R,,hc?4PC+++ʏCF'"4l ֿ}ytEwYޜD4HL  x+Vx1r>  H|q53!S`s~*f(SL{g Ȁ81EB/VY\@7OZ^_+櫲xfJA5p0*&0󏸺xOr2yfOp;.BV}8=?~4]$Ņc($d|٩w:g4హ.XG "h/s3 /"q+NğOI(~ĐtZ??Ed@`-:7D(@FE%I GR<'^@Zii р(\zBA?Z"lPEyl0Ve,Qbx\Bܖ X8/!_KD‘'צq3Y&-e rǥuCE|D"!%*@p!l+g(os2fi(61? JU[Rd X?bOR1>UJrHU)6QTQaq *?7ZTVJͧb.C UP!}?%7cpL$/|;Hi:=+{r4x+_Ny8 fFyTⶮF&n'1dIVkw۟8mLJ}tӐ1TJ<4ޅ#Oc>D'u႑2lHu1>}Ja _bGKF$ԛ܄H|pR5FJurT G"(=#}c?qL~b_)QE<a8 6&*fK/ `'VRub"'*axv3S6g[sxߠVK\Q9񕁙ȒQ"˕rzĸ5G6 +i;T;n,pi7+mE8 G̓>nX+0Uj) %zR֟ PN6AuӒkU^7Ž<3M9}e$bδBu$ ]UĹ«U (]/P0k!M"ƫk,uR /ud_VN(XIMmՔ5oo3/hv!, KE<)yښE$F\_Z(^yX|᷊@V|g;͋ po8|?kz}V_؃C8g‹#z]cKW1NE<7|Ɍ ?$sQW=4 㚈.Eh_v)?Ӂ ي1z7gEz7P_.6 \É4RR| ր yLLPjjH"U,d%G}"U|Z?8J=iXcn&T-$'VWH"$ 0/#3穷XMZhfAnr93n3Np^sk"/6քLh62LAVrE<8JmDO fd4]HMb%8s$E'|}b@5BLōkiΌQp>}?D3I( T &dH>*1&ˤ$ jBXZSD[#3Hyʖvp@MGrbm}+!x$IIh%9B>I1>٪R(`9:'tltBa-7:R{X]zeS ddkI$ӶBK!cB0d '91W/,h} VbMt$AvKAEf=Yhn-䌽Aԣ(vC&g}37&H9rĘ1*$3Y@N:e#{ ;h3 ÙW4JGe!G"e^̗s)IbrI[K!(V(y F{Z+/k ME, &f5>qt>Xh@X\W^|d8ƙ4abhpxs~{HLpEsY=mD֊DSqL ǶP:; )`6]\t )m7T&+1! }|(FסN(KtSip r V:J |2]~B5nxN& T"K[rL@+^7IS 8w$Sm&oSQ"W)5˿#"`|L[D XSWϓ2&S)F[?#ڛmgwZ& BM.LE iTZ,ԜJmVpA,f~jvfg0Ib6o \FEȊZ,1鍮al$֒p67^ BqYmƃW?=NNz/xdc q)ɫ7\ey' IXRur‚lxջPn`3TR\a?𭰮(sBYƺXd]}"W exna6vOvjhkiJ42>-^1l@RƊ&z􅘦A4/4jlFu}ڳk Nh5U\D]]VE>Sⱹ 3RjBV.:ѧ6z+*؎"'ۊOn8@(#w\Jn!Vq_& 7)_´EmP YD)UgC 9' -,`|i:0"X(}~Mtpk6 FdJVX7`$yJktQ3e[eH9s X':σ&E872ʗcR:J3ֽEBJlQX) `8WSd8ngi ؽ+_H_9ӿ5M݆HmRDIO2$4<2"*GA7= “ǯsq+xS|+p(dzeM*^C}m o'i$0<},l(=Tfk9V\=$Q܂uS$c ]6K3;!XF2]H@'8 FiQQ$~mfeƴ>HF!06RwB))R(.F'<>k:(>`Ζ!k!p]>DKaڕ8*<ȱ;uDaEyE}1Qd(#21JWYoa6,j&MDA.ShTYk| =Aݸ%Jv2Kw*~~*v4Ya*{b6<Pn+*(+gCw|ܨ6l}^&dxSůO2Vݵ@4N%k"ʋTZX M:Eۍ>iY]쎥/_69~He!6Qsm>{'6r(=&|R<M X ԃI-V8]MS^!(=QXQ]m(6C7|ALfVnO nx{ ArүS8kSO+$ (δʨ͢+Tc55 %[C}Ït2gF3Nl8c]9'EŽ |u+R4tat*@`觫;@F'tRoZ.ZOew!%P)IvX _90jMNckWk/ P M>yzOE7EV3 %+IslqxZX7LzB{ig0FCy-\4tӘMv~]bٺԩX\:O]Fewi(KJpMaiƓd-~V )ϔj98T9I0&^1KG8%!|ޮU 'MƩ?ZTP mEmT*Keat# xUqqog a9&pqx%+`,V:6?2ua2'|Gѐ/f,϶N¿T[]n&w|d7ԂXs.FL$:ސZ()αƘM MEHj(Z2UbD{%)3}L6iG  fLk.:)s>Hf^"Qsc? Yt| *"<bRGj6xH~>F2Jѧ05ŦSM.Z״BFv- 6nu4/I7;-@EiXaf( E!x\ck,>S8(Ȫ =4<2AiyS $W"zg]: ?T&NQMtgjC^bIoc (b\:*F/ZFA!ޙv'M<%r+$ӓrK>u+ck ~n\бF06BĎ{(I ].|9ʹqzv6t? MFa, 5 tT\iPFCywSuR(|ܦzl9:xux&\P( &q?d+ # *+^0\[E vG}~~Y9W~ `ʫF )1/ξ<Ė_8W"FJ~/DS%, `S? A}ehȪhCKA+1M(Q}xPzaPѿ'F_<6^53Kye@~XVUjw%t0ϯ.(xaEW5^@'Hk5Z/|olηM.sDxrQp*,/$:C 7JYu Lc9ʌp.vVAKC;LOݲւdXԂwwYxJt9EsQ\'V7ǕRW8.xLm,VEJ_,rrUC>]m28*^bi o , `>,xv-D;C^8ĵK}L`KR] ܤR1P3VUZؼ0cF,f,2Seqݕ y!ԮE" ys1>o+)4B cy papMa!\#wo)h85b pk C/_g8pP^} GhߊfXhڳHOkbK=?ӑڳv!dC.";mU]^;^6YrMvkkkO K 9R,Fv{BĠB=;o/^BR _؅rA Xl/z6ݠqR+2HM-~h<*J)D cT>_n*'Ϳp cv&=ށ~x4-hlGTRnL<-"$9i. =o!7֕^8FOz\dYD _+yaDchecksums.yaml.gz0000444000000000000000000000041414554463574014624 0ustar00wheelwheel00000000000000|gee;V0 "O[9,KT4T;n3/{=b#>y`w !Yk0@ҬDuZ`E@w"` My0qsrFQ$9 <",G;Tb 2*dk0'P>'TsgJgqnKWMSk,cW8$W\.* %y*/_ 0QPK!HMgems/2.2.0/cache/rack-1.6.4.gemnu[metadata.gz0000444000000000000000000000360513572305410013442 0ustar00wheelwheel00000000000000]Y]ܶ}ׯPH;@,Ʈ )#C I(x ژsI^RrWUn|ܬji([3eլuXnIi@@Tǣe[]<_]/.P]Psdq\7,f2QQmBSh1EVU`[g\/h ZtKB6P"EeBӴ̉O\d_tA:W1_\c{gyA,x+&ŕ,ZT"fk ymHmYN1f<̜;tM̚F _6sI8߽id[U-)ּj ;ƍԚcG17q[#P߰Y@5y nMQV!pRli5l QVr&E!ȚZbm4TLT2`Rh).iij3^l7 iQŸXyY;%"VK4u5TG2U>3}BQL3ޮ--B 9/!7;8]0.Q>bV0ejR !sm#$NnN QB ܒw桼r*|e,uzk!諷j[̋3{NgȊ)ѪKy:դ6̴+ J5 [%*,AHRzA Ɩ!禬>ڍ6de*.FXfdR5`legcgB HQ_LpHKJSݲ^*46GȤh0h%ʻ"$H _|RJʴ2S,YoX6e"$[|oD;l'VdJnL}-vV.so7N'/;/ebLu2>djHu:@g83aٯ-1(tRu`4Mϥ ڣ bД;;}'Q~uܨv$f5Ҷdt9ӟR;'x& ȕizEU dN~~"&i?a3wQN$pU.|.ZݐuQ9Xw02u G+B] QbvR/ΙRgZ'1p5:g]90Р u6aJuINpggRD`Ï>HT`u-!6RXʊT{HpI_p>d3lQ#5<@\hu7~.+aSv=Pp1- rW˳ 1ܰBT;i,yime/@ҚF*⵽3mptWКmC~(ewT,銮data.tar.gz0000444000000000000000000066622513572305410013375 0ustar00wheelwheel00000000000000]|Te0**Laf))H#z 73w2LcLBh\iDAW]pl "YQX9ynwgv%;i9<JG$wJHc?3g'gfLJ BZQb$9cOA ;zG "@D4n'^ܑ+ K0>7ЈKs.WLXhh- 0LM7 *J0Z ƕ&ѰL_lEBC[Rh/ylƕTW BEW>AUR^h+PQe*),-ó1@ф|hW^Q-TCȻ*;2{UA1_RZR=b**.>*<2`Li^P9a *^f/L?Gq^i)-o ̾!ayv+̿4"T Р^c ΃TT *ʫO Zk;ayU%\|QU􏠃JI ڕY/V! =a'Sh+:6S?[~KFl>J3ҳOQHFFB !m@NzVNv@P&^7 !0.ʹLc0.P Ze! 묕r p !طWYb2i#g9ryЛ_t0$,]R jx(Rd:C*CR4擼MKBP > f *&c6z-JNW KM^C0uE0+$X"6CMC#(ۖaP$T'iM (âYh:sr1@^vLD;`LaDm\.A Ɂr :..0 -Nl?vfD@z\5P`f0BE/ a9SG: 9i5 B)\[xWD¯ !6B~ݘ21(x.% hB"#A6'0!#08lLɥUBSE%x](12a:BPvJ]名QEsɲeOcTr%x<Ѓ zwyPV$ڿ&YVƂ vmkfL3<:e U@Z>&n k$͜h+h]QZnI"An8B2h\>=B-(YL7Qaơ7eh#V9RP*-^5 wxu kajfPz"E1=dR[\[/6,jP{DL_FN {OE In 0 u~} D8"t:v x XNɈI*&Pj07m${5;HJ^"A`G }O q>=$#!F" ހE] 8ptG苂6Nش 0ND=|b0 p$"lqCۙ6H$$V ,Ј& 5 #l?\Bquu%"# &w;F ()z^W"A4E3q1s@'d1f:bL8L94LEyP oD8T4P?qe@I,fAA2͙qVY r49>EeBBiKt%P锑+ ۣR a)_=a_N!vZ R %r]2Y ay w#$_ΐ   _>e*+"A,SAhhf@QROpƍP]DM:(up0Ծ\jZ ʞ4!Mѯ$8pa(0 -d"s -AS `Ӵ4$I~E2S> za"D (GלEHsˡ#o!` eg跦ߔ "F2.6CEb:gN<+eh!T:#^F@8% ہ" (.B$z]*_3߈o|LmUjk6phU2',Jof}1\Ä$de'dz֨kVZKzn ʹgGWI@ b{^a*h27p8vRۤZ~L1*@Eqfdp+zHnVyK!CZ-Y"}bX\*z&EA % P z},`#Oppe D}5! օrWFT& -km5 [Wk&2)n$y BEpclA[0CyPӭԦF;Kv(itP`[K[dk L * !jb&Z$l|~2RrX,ઢu\\ %?l*%WBrx[HŘ93 9mZS51=d:L%.l@RI]{QOk-Z$Bh$I ͂Fڈ x>d40"$&W`d-sŒF#,ӨKH16^Eň%E1YUT9h` ,]]rP m8*DAF8jBvqlNހ)Γa f3PyZ: Lяd5ȝ ($Q-$n@] ;bv_DՌ)WUh/qLͬyVa>[c*"a($?A6Gv(RYIrHȴE٧p4 9B] Bf*=DZ5-- Ћ !AH=NG:S3R3tkk5ҒMwZ~*R4T~bˬAPKL.D})1i:6Ȗ |֫)8ē  T>űv\ѹ%skFc`#X@ 55UFq/)ƭ6\Vc!Xr_vqr".^QJ#ule@%Et|+d Ы؊(U; |hь\PibHP%Oռ.k0)Hql|QI(+2zUR2yJ uFB42Ri|64S=0a;;>HE 5hr\VQ`tp,|3Ds P#xT4nS9Wz6uBޖm6(Q 2~L%;*,>F܅~y4S܀([DPD3V44aS (At wr𦎡()*VYjlrCA]EF H8 EVUx[TK@pjN~p;}d(R"Hhffȥ9ŋ54Arrv8ψ$BY:h-Hje?ʇ88ݫwTԋ^փKhU>h@-`8FѾW-Y񓻣XЇE&ġr9FwfSak`Qv#һ,XEtQT< % ŇP&*?=_QʏΫAQAaJgcāܾZ4TkfGV> F@ H'p@~Z4."%k1Säc/bpak)+Sv7Z8>5*WLxY¯ nKH1b0Z; 0^{^ɠ,Nu#Y6@XiIqXdz'D C![% PUȃDZFf`[Hc,/G g9пN̨{I#406TE"hd;3=Fk(oTd>Jb{6qZ nTN1AD{c 6NqU:#$HFL/BAV7L1 e5XXn op2u@ӟ, I՟hwIP$ xixs;=(b}rKBG%|Ճ Ļn0AY6\C bz~Vo4{gB w4"h*mRLhʵ J9a0i1 y {l[- i``9s`$]i-iS40<@JV@oT ##hE~%_ͬq"H!Bb0(aj ((IeFH$.昘YMlrVAW7=4 %pA#2ڡ=I7-kfa)65{Gw:3&g |nJsqler) !M E@@f,ȫ!fZh( w@E35 Rb4Y'rH@`6QJ5(٨l6IkѬX= CsK <|gu}B*󵩔 E1V ipyaUB;' ;]B $.$2xrC%-ىAФ+hR A+^Ih&wءA Ϭ*EA ;Ue~סaK#@XlSt_[hNlwC#0p:EKb=%!ԩ$Ddi| :"Р$! |j YgRKU2-[FfFFf_f#ᩇ2KQebȍYaȾ:A 9sWT lZ2Ei%x6sͤ|:t$|B)F|~]#>8uLD h||עA*"с⦠ 0!!GK O~0HЈm J>^gSO0- ]D?a@g 0&A7OGf'Β؀o !}i If ycU0i W|~ ꌨsiH b :EJfgzѻ@XáIfIMjHX[Jh{,`lei@f-2JxSXd0eaO~*X_-;X5)4iNXK=#)RL*e j^pa%W7ƈШHtM*L~mGzKZQlÐ@/f20K@#&PlqF!`=F0dC_ܵKg45 Hw25&3"?^&|w@0#n7&*:&sA5$XS ,zc83/4 {Tt:Rr`&tPL#e/h$i 34a3dNAB=*+U!UUVti3 @S'50W crY۪ˈȐ' I" $ F9 "AI`#`1?!atk` R>Mc[0Ч V'_4'292î^>C̙&28' ?DEYi]t{ȝKNVeJ.ҎaT ZCI Zig%X\( ʁj4̢)?[wŀT'5U=CحaB7+V3o!F Y28(*T<~k1Jc~gbPaWq;:eL%Q ]-hؿ aS]AJ -_X$,0`*6@`DݦH9))n|EM&j)ɨ;DuJVJӰx( * ,\XE#:tE(~_ڣ(jD^H&O-]V*T/ܘnDzLzEE[ 쇕{2aXD(Vu 웬w3 ^TGuHh4dQ.EkK :\ Y,:,܀"u2}+Z ϸ&êEkcE> 4E_FEx1qPFZf2H3)-ȗ4lD!D!u&Rr 0Fo!_Kx[8:PaUI$]aM#B''f#6Y> 3g5_;]/-UCV nr3sS#JQ7zƂ%#._fk0ґ Ћ%'&^_5a+^R|ȷ_HOHOOfU4;ɽ:208$zjʆfDx},/ژA]/5PV)WHbb@`46YӤu-$q"Av(^+Z_]c 2Ļwhid||vvfw3)KQ &b41'Δ}aENj3DL4T 4%/jq0WU YtmzQlUI'~5Wa>@OU5O 1UE&NҘI& q3/)vH^1%xSQ CEoj mҒ@ 3TC0lTa踮`u%RތT* K&&.\pC?̍cъyQ80T[I,(,aI tR{HlRk8{m6Qp;cB6Oшl0J*3ddI ` lkM1U/C%8K`Y̫0؊LLgE&ߋxB(ȼޑ2 Up"mzp ҍj2&qtZ"07Ȟk4M8BSn7VD%,0zroZk!23B#r&!6sX0;C*1 ppgLp+IoTGMӆG?7f'j2m@1}zIF#):Bg%)$8z/&a,k0V A%2G"̻tÎEػuukV@1L7FҞbhRfdRD7IRkM 'ل%(L.#e/70i%D" YA?U×dfȆw0Qu))mヒ^B$gsT->uvdݹP wg F-D-X!1gjD6#}05jTAF-&yQ*o8CcfS' ֐;uA'BX ;b+[N[*植I x} 7ơwob44`[FۭڛI=.AD$s&OJU MBJbN K6Z)s BAB iօrh))$JVsd^NJm%jK*鬓S؅a#Ҏ^@k{DQLY_`Yab}U)d<(u"Ҩ4DMh5M}l_Zݮ$;_RW5!Sx=n󰤜FZgT(<9͜lÛ$`Th|CC*\VhRj#$PT̍n!} N}ٷ|dezmC֔}ՁJjKq-Th9̱ѽB4P/ncl\٢皛 ̝M+|ZBďH1߰wOg 'jc4(k渇]N!xW{`{^R){+Es {r)S>1u7d(?X4^-PLW+NJ;U^2PQYhff & 51/Ĝpp9s*''M@(k`-8kslDp:s:hLCمFhJFH䨱C)jAFBrb/ Lˠ`FV,C^_0-{ڢ`Bى*/u*Bȣ ҷq6fV:Gw|ڱ`?VkXG,Oo),Dn@:FRڹB`Qcy[`+Oq29>H: 1n*es* m:V!#&?@MlJe[eImC%ZGϬQ&Tll8 r C߃S\ɘs`s?ܷnfVZVlgKb^$tD2K7,JTGO u눐2?~!*m,^+I/= x>Q)J_Ÿj`E JIñ$LCZS4zI$X"$ S+XX:P,d{!a8[1[@ВX*~ZދI?XiL,,VX7Uf7l(djC죁Uה٫+ £Z1͖筢CGO{7fnieKY^`!Ķr+߭P=ĸ,^D'vvܟ1U ]z\ȈjAx3;9V;Xur, xxǸa8y- -S-3h6,=hJ(fj ΋q'K;XlP%U: (1#э¶| lH,7[ eyJ[h+ YoVVhH eNFZ1y*e jB0wteYa)oQ!&+ O++2Zx3+#H!nXbI}J4ժ%^7㲴x4 t8TJεX'=q% -a4:TLtke!Z$.Clƪ gee1bfX~,\"$6f1`\'sDVǿV:JDaX!A NVB^xji**jw&8s7D@uu[Xd,ǛISCngٽbYt[@suBX!"sԮUSoޯgh)\RIQ2,DwiCgxτy0% $E@ 8KN8~:Ņ:TIEh8T_PE߄wx* K%$_uVkPjnK<J 0eK rP?mEK-K/jXOa ~Kc@s\ Gu*JKl\w˒ũ!g817 S2S[z+-/J54Ӆ3DnЮK9l^IM \QV (]5Y9k{BoʞcH[/% b0\y%t D2?o=4` . Iu{X:8fbvmlJ6DX5umG h\' ֗K ``/PM.0fߖGT%{ Xkwd"Z2+͒8"alƚ1Qi-DhW#5zD7i%< Leh8/i㨃-76xQ 57lL:Z l-) fhk,%?r-u@etCSjȱ. &CҢlLP}wuà `T\/G9qdm Rd⏃p^`fxr39R5tڨ]N \cxćv;lF`&W#zSF+G#xT Q3CD$ń)+I骷=MwN{j a-DjsJ͟ͳ[T-&Uڳϼ̩\;>TtUI'"%\7*P$NjBx@k8j+3pj-Ư J ѣ2qbBziH{w` Pahԡ 啡єUԣz bʥk~MZ1m*xp~r[H5'sN>xUc|*_"gȫvZxJ5Ŋ2+fӍA/Y5 KfsQL@f iiSw~F.̺Ux9=" ⎲ j3"~j y<}|ZYoTNY8mP+q캌tQ7W 0YSc0ޛԾѸ !%9hpj;$-96|):d1e1ESEHtdYZ%ĕVVef2@K,syd? )rBH#NqdlxFդ }̙SFZ=Ffe5L<9{-J;@M΍Ifu!bcj@J74V".[`V,5BF)t (*>j(l؄{f1fz'iJ~9Z1u sO'tqń, thOv=ܘkzg2Za!0쁊"|N^m`Nqcf#6\iQ&VX[)B:$*n]`!&D-" & aFYލ>@jHV/FD]Y*TP߄w33GVJmiBQKjH JAAɀy1UuM7g m}jQ~oa_K^tW$h^4z\$[MƲ6vɏVf9 ;geeqE#d J Z:OUo_ yF& 'h~kz&+N:aKE?^?C}:|yn|\C ?T;ź~?:kFpi;|`…+g쬝vEГp@yƛ/Ql/,c/J8ۻt}!'<>4|>冄;GN}}[ v^mtܭ~;iي./|/x/yyyڥ_Y6WyW7Tߞyc nuI X?{Ev* LX~mm` .e@°st{cz,[ ߘ7鍱N^pH|enßXx8%) `4 Y1sSVOf[+]_ޮsln+GҾޚL|Oܹm,ߎXvW>}#GwWi71]W,;nt)>s{lv|k_bܹ%˯vͩ.6w|wSo gI+][ӳr妯wxxj堾4zȕls2Ű^Ov?١}[⥇otӦw6{9Ig= 8K{rC_qMlX|"S˾zcHW)^|e϶Kwұppps1㫑U>nzs .su]X{pN#]3wCgl{i`6yB׿X/x37Mut'֜y0oC~{GZ¦5' ?[>|MZWQ;N惻\c٦G*Ҫ(-;ݛV?:Ňnw^~Cm-d~tG7tyjw{KW?xMߝ~gݿ%;Uu7_:ug+㟽}/Kݷ }S-PP~s<~rf:;? ߴ0|ש3 =KȈWrwpu͉֚{9`vn2͗td*W#rю[5{&y?p;RϾ;}tlpc۶W샯zp,\v|g۟sZ0iye|jȼo;gRz_NJ>_]sWvڼU :h٠gβ.OLUcɆ'ֿu|-^C{#/Nv>Ka:~췠yYw:̡7fggݲ~ۺuox욅ܴjozEv]|(S7379wNZ|cܷIWJOulp߰?Ϲ={t;';78 _3iX3Ч;.HqNLp N,5ꁇn<]6;ڰŝf~лmS]Kc/L{k<nd''R ֽ5>/n#RШ"͗4sU޾)#3fҪ>v׍mZ0ߝ|ԟMˡ#^Tdq,ؓ 7d-yf3㷟M^WLYWsW˺_joͱӅxHց_s{A:9e[^ysic+_zzɘ{m˯~yD 'lG8p=p{=N':vyu}ddZ~%0gO=C>;gpCL-|,E*Ʀ#'Pc+vz\(73si#t"] .OwhSG Kپjʨ>%7ٲt'ӧ\ՙ|Oڶ7~瑃:s(),rӤ셫^8uJ/ߒt]F^oJ=Eo8bS>tpۏ.Zf{w;SXXʢW*s,'\uc3<r+]h.=rQ^u-8nYO Y⽂~w_Ӕ K9f->닯YH\E;رӺ}u{.򺄫K?q.,=~HiN_.!G.?=29Nԟf̼;>E;޵fi{z/ƅ HYu6|U]'Ǿ}cv_5yY}ϻ?p/~?;uh]zG9L>]ilօyw^hmIcJ|{uMx'珬y]}OrpUώcV8 Yϒ)5&wa =L t}n!2E[]8',?w}Ԑ/RjL uډ?|n9݁^o֜Wy7%'GHwΫ77(-hS??[wGpklUnY8tGvMi?{;S׶xW Zʇ6du_%~xu'n.۫ʤo,(z_TGdYZeFfQ>}%?w鞏?8q}sLB{O[v]7N3]a.M>M4|sy}MlR^tR7M.7 '.|̦kݗK9[6]癢etuA`­׎276fWlOM^#O4-76ݲgL՞Uˢ '>"'nًóؓ}f׭_޸/_^yWJԺm݆|:a]o?.WzrϠM@7}W0x׿}(Opw+*c'O4eؕ_ 6ߝ3cߒ>=xxSښvzYgZ7jէopHNA4w!+ۧ՜<veWOg/,_t[ƭ~pkr|Vw஌?\MI۳aq惢;6<-p\#O^¦r~F*mu{g6'\<̀>?͸wm'~aػ_jOH]{~5囟d7⚓i*'w:yd7!?itū[y"T1{2 NxۓysrSz}{W߄{|/9 wUj5??7]My{^pF,_w.[˵O޵7M{9y,GjbO,zU^*ӡ:^G{v<=E%}˲`rd wȮ;}WM7SW0j%yNS#K8y1ϡ&ڷ'_9 zn{/MٻU} vuyk̴/^ѹ]eSֳg|p[7~ͼ?|t}'o7蝿e끻W' r?H?C/XjjG3ۜTկ_{Wf^K\tuh/lg=QKѻTtc1y캄;o~wҫ''p3W˷wnr:n[Zǖʢ{Gu}_ܴKR[ݽU f_c[3ξtM.+niE&+ܪhxO?GgªϚ[N<ȶu[rݼ s07`΀+s&Nz;ڂ;;,[pMڵY7_=o}^غUsUJqrig_NPv訯~s_w\ܶwe¢nZIZr4!X1$m?ú+-׿u~^ZqOg}zӔC3Z/Q9ˇZ*nt.p+ξ )Wm',|qќ{ ՌO]ekhrÁ7m} o~JvV4mˋ:scܹ3;Ԝ)ЭIp053/k6:At+w>_|]=6: zwanCSY`.sI%@E$ig?73ws9wP=J\1>H ~ $}58%G>nCsϠ XBp'Tφv rN(Uǎ QTSWKr /dbp q; f`/}k~.vc^+ǦQ!z)w(Ϊ T_/F+jLjTq}j.S'4o#+=2/_d?z2 " J{uNiK״_ YTҎ3N$nYӵ#~|=~0rNh7kk¶ WkWk(e ck=e;鼿_3ATfw (>ō"kVZ?xZ3n偷lI_^R]U%-߹0;AwCZVeKr7,𺝡4^.L3Jn^YqD|HѰ8?/O`F}"wij9]c+C@Mx{\1)/y,* X>(Ϩj!h SM#!<7u33kƺDwҾH Q퀦pX]4⍌޾f!&69,y7NZv,X̖.r$yJj-WA|noKK)JHQ:[]ʟ)@S?/!.nʊ6Bк`.`4ՕTaJ;H:9vy^=S-D`K< \yQn]}7\kNtCYlMNuPu[;_Աn3Q1Z$3}aMˍ/yO]E)$>%z_;A6Tݕbx`EOj4Ms U-gv;R9Dip7tD[^Z8DD㇣+6Vt`r^}Sӏ挩_ث{UzZv@ޮ 8 r ^yO5~pV~،|;Qca#D}a(6ڣ;]*xXmc`J抶̴ROON D>Ǿ Oa n 6?+3h'+\8)B"w]}"˫Oźmŷ(Ӎr|Au6>.(aMeoa8\rjx'~ei"UT*5=עlK~_j 3YzNI2 qW!-$US%0qIԄs\gŚke:2iz*45pO|N6+6/979¡C[x=`[y"gl%uٔ}([٢7:"-nTxw'%4&H?,HW;J*Y4,)ʬ{>􎔵$||2SpO{O=}֗Ƴ A;z_Ơ2$ zKV-ސ z7DU5xiJ$w-uFl2Qr]2N])1/tApW7wyT,F`QiWr(sm>0Hԑr'm>XA˚$y꺡X)nZ } tzvjg{},,DN2]7`n8p wDVo8J-z C=SP9nLJYEZ)qɪ0)ږ|g ׮}t~N_._JOts7/D .*)ƇҼ oSXΦ*Hn׈2r Kkh U:pu"fw)a\,1_$7&t$@ӝеJ9a#@SfPbazS \؟{B 'i1&TvGw(Ń]ِc#Q!gMBWDQ,v8^qۦgb6fާ9{T7+h>i5 'g73 FsN+!& ~ }1 !ZPQVT@X.wN&+ZDXW]c3#>yI"[qF~fhu%wll ׇ Uf4NDœ^aKChbp.rtYH+7^w6h%RJ{u$S7J? x ܅JCbPDM {`6Glw_RLm<~5{q|ԵRke7܇}w:*Hc|eg^2U2i64&v]~{R3֛6lEkLɺ(C:ҢōPp"ׯqD J\ ,>c3Sj!@GLwU_%0~|$R#9vuON4^q5h4w>A`dw!MRd}p}J٦xuA;WsX}z_w}q;m\'pr|*2v/TQ_4(@S4uz\RqR ,8H́,T>lS3 {c 0UQ>zVNu ӘHZ:ͲesV)@!-e)o )T}?\ˋR3>ۤ~Wt.{: tܭD M)Ə 3;©XO(t!KpAEOIͭ8V/)sޱtj \N3Yξy7#֒X,>*^<|z85aUd;tfL[),IĕF6d@E4~#VEO8i&.]?D>Я$LBI. O{fQ2!z<;X7Gʨ%ttQusȝb;I9[МW<"%Pi 6//h)+uA0\ ad,Xzj=s:>ۮ0E/-/2IhdK4cU9ѹJ:DLVFQt'0 zG0\>(;YTRc 3^ 7zDz=qmD"5x}a}Vv&0{&2n`vó2'\rs9,Wk9k^7_nn8_YUد[ %U:;[* ՑPX,T̡"~6JSAE$êspXƑ/ eX/`$t]X!hĐ ~O- $LAW /|-ͼ;ʫ_KTH[ɦ! ϚP<cbꇂv҆-SCAeYZ2Hq@L=+4-9pٶw އ lZ-uL8!h+s=1v'<)cM$)=r2]3LV G2過:i5` FDI7;ћ 7Ja1Vy?4!>T}A2فjn7ޖR=Φ^=Qc%+|2 aokEpu+Ő5S{)\9< k1R{pnfvN"7m`%pR VAQ*xpqµsstlMtFioP=L y sHzXjd>@b򬢭оeCH'S4mۖV,扱spOPwHZWIlzOpJ:)bZSP!\\\ЛJ N =ɞ[|?E˦UGf=P%33P.*(|(J՝p:A^_Ynb4wy8'{^mـ"k6oKpO_,(/& 55ks 'NX 8~ЂY+uaxrj-`QU}ݨ9U&wohf87_7cK}BTw*.G@m<4\5)[ T煈9aOhs‰)W/ItA \>nDQIh5'1vfQkY H)iYtc0 NɮT/T։FPnVѱ[>^&R4'p6h0oң=נR( GmMţ;jJc u%*} ,'|  $# \ퟙC\xd'5]zczN/U Gt+\z:g4%f嬖 L~DoCK~ K2`gP fB Lz=xu:J6=ǢhN{ƨ'szU)^jێM)^k(L 3VR>1ϓ .F|lsB.zҁ% $ߨ"n,7"Sd~M8luKMi#ƒn o:d2+Y2b jͯ~)lCmٰJoNՒ۽<@ 2Q=|(=-Jפ6"Q;!GB wf;oH;ޘύC?ِk(3uD#﫤-xa,ǐXżu24A2}#<(xEnD.3O._+!Y#}n9<^\Jؐ{סjl ǫKʍz;#HxLr~$6ȺjͻC=7;d4xCͰ %$H rY8[BL|<}dD ,9"l;9Q9 3Mj񊷿<~72.Mpif!',հ N |t>dLEƸ酝Tb&_6|ZY &y+8ԧ$}-[~a#S7_E0Uh֨@ǂaRu/u1Шb<;1s =t] Ak0ƒꁎ_,dzJ lr_)N];V>+їm} RoH71 cnb!b&/ʆ97<rdVԑsvJ/l |Of[kܣE*nooWb`!EL$9EH'[`@ _ gěi\LoH̴*2FaQQqf6x#=H!X:V^/9m6ɷx<-*Gؤ/jg씐 [ʅӔS5m-Rg32G=6d"j^БR05F?1nWpٻQD; L?$Iu{xK0,VXP3a7kKp УNj55@0>J"n:йwJJ: j̡mpfՐNwFA3"YόOֽAA1}ue`>~bѵ IKCtZl7 ɭeUG?a@e7mpxYLTr*[GZm)P<҃<6aD/:puF\4E`u\Zqx%va,7J~n_z8ňYeoI`YP{ S>eOtТy*14QX_ّ{ eg2k*`6,@֥$Q7?")uW}X11 )x/U:R+"M- Rx@GϿeQP8ܸP@}6Gy+*r=9kՋ4xEE H3#Svٔ?1 Z@\S !XIEP7:rx[^-՘ELqOF?(,Fʎ{CŔT6d1r 埽@rƤԝ_+M8ތO m-)e,JHH8"VL4B J[3o*Tb7,)e,Om%n l\iJԣ⥰Yu#C6$W戢.t|-c 2p# D@AN!ߞ=>ૠ)+Hr1/Q|2REuA+!Յ@]ʆDںG=kpS|}/p%L~a{}|BwsϚBK6G"$ fn9 }^c*b9}<{}s`fXG-5:s=z`(ҟ+X0k#/*Qߞ5BG{~3y lq̅l20TL ZeoM%9ajYiTXI)_ AGfg nT!AwvDl7ހCoZǖTZf )X%\,(,|tX%JLAE1uK2/T /GnYƩ#@W 2OM|>7aygq+jDzS%E{ٔ֋ @mIVb{}A>_ДV|i8+{)6T,`M7lժXoW'. B%O۠{/`FZ':>rM %MV՛jʑB_[EE`uA6Gi$@rQ'u}kWF,n!Fg]Z^$)@q6ٯK bHRܯd}PJɇ^ـ88O/'W1ۏ Ǖelq5F&sm&`㺯.nr1]>91~u̧kU96ĦF=^ּ'oaJjzxmlүX`iR>Hc3~5XHF lI](,y_0I>>orz5No%H$S4I8Q(\\8捡XlŦ]7⷗\^ 5i)H$\5{A(H3ytVC ^wEvhjP.RһR6ؕVT՞^@?#-kcXCO߶цkS * @[qӿŹuP1W~S֘O1_LԎZ LqLkz}j}un%"^I-8?i]bOI$[JM#%mlE*z /8CZ! kRmZE=&j;rg&P+U6<SX"q~M;alz J.0MKD hQ]̿ rR+}m/A:GB4=ERkaL-!"U7raR E4`q{ʢW$ $搌_fO;_Ԗowf8h):?QWDB}d?ݱD[[y qEE8S\Q}L.N4Ejl-YURlԣ$* j#gq}}@1a33ykI]"vxKl͓PÞr\CH] WᕩX}b揫"p`EPA:-;t`: <|kh>P&<^}`?~~J2eNy2BuUّzi+-V8ys?jj4ԩF96K?uq?,ho'q04t>O@R+X$) bF{sa|K&GV$PEdv<@c6n)>'FƂ C҇skbG8vwCӶ]+~Ju,U&ɇgt6W$dʹ.ِj=NQjx gF~Ɍ VrӧzI(}b5cD[KsG'S JAoeePEpSlK ܩj'D\J\pm  &wDZ2.w|}Rي)QC"8W?%C~y%FTʬ\c(մaSM-X 7%[~ƶE4 y$lwVF&p Kwp q OdZzW BjN]ߓ4irgF˙̱Y%Ze79<9Z,As-$_0N:M@f6y,X'Jxs q%/.yv=Jl6Iwaғ5);>|66J[^f]ҺMGJI,%vec);Yx6ݏ8Exoߞz׍n=3Cst A+8 DaLפ,yqm["lQ6Ư Y%}ǟQ%MX):ZfNfoFN"r`(h!X6}Xfx!V&8QCF^^̉4q 2ThKY@j Dse~uzýYBP e|l/Eՙ-õ,?cS"t_1LSE5ut\s]V MK"``$"؀,1G|9j~oNzK>F 2EƺQiۮOvonxӺ {X1badӗxq@Y۵CJoڀ3]*7S}+b[2G@vL gk6\fs5c%I0 bc A/%v˦tO'N;JY1y|/%qV FI2X)p~[ߥv)cPġr]\|s[=oߍm9k_Z|O۞1GI%@8C Ax!Ӡ}G( "8r$=SF)d)q͟4A 3X Qh-6x$֘H:2+$t{Q~ţějٕ̐2!HB+[2ȼ|wpk~5f?ImfOH7lS U 1߶iJ'kJ[)ʙ62;8/&7$zP'JLb3'r-NgbEoYyT?$|Z4!%8Ҩu;(_xa=ӤׂX_%Un`02eqdЎ@Ī%PbWKsFū> KQwAJmk'fLc *6RǴE⻢B+܇%[Hʢ*.4j嚢O_y;+0˩fS|6-͛Y#!]_ }V 4Qݜ.F#T/ UPyU+M%Nh'M7#oCW#>"yoripϨ f1i^M尬I-8dz,-]gehb1߄58(6Ok9yl|IGP9۸U'˅ R:'!+wM?MⷲfKpQY28G=~T Ąމ4@.^/4jTDྈ?^c2fEu=z>l91jr;vS2۵SI>=8i^)kZ'"pZΒcß2|6Uu $5K;:0Y=EGʣn #'Q"]|rJA ܒt«qgCΡ.Z&@uPpfP 'Opǡ¼O:{z C ,aoh>Ŵ#y jU;P,/(&7іSmSxOB3i]n~O8ԃ\1iAY u^-9USK cd[L%ѭiWe+$ĚojWGhTyu=KAq {W:=DnܰT1 ProStܚ}W: * .9NsVIg[r3C5@/!l[49P'τKG. ĭ68UZPӰ G8g_7Rh1=%MFs*}~i zHk{va!IM σ&)Tj﹊'5@3Nn\,dj}n #c<jK~uU8 `$sqq~@-"˃H yqH$A7a2@=F/ >:XA{Hd|\r/<b|Pn*$I®O9ķDдAXT3oJZzeL ,㢗%;jyR߼\#h9MvD_ZGeEM;9CZvwQ')3{c,y8m?2UzF~`C ZPJ|6u7Z$4*$N(u5R=9jyȜ)EN慌>e~F%PEc]\.䌤^r0wje~,. #JM^f'8+"h_Wgܑ sH; IIp.*PzYlVi˖&cEw2Y+Pb]BH";[nSHQ0#eV'2,NpЕ}mQ%KHrk=7іGF>>;d/ X`URF>ǻXcbk vuj: J"Ɗ3灺xIo>;뀉GF#~*Lى2Pp/Xq$9ǢF@%fί|GIz";ńw ̀ī 2*(qܝŊӁWnR)wVrOtѻ-YL}\hk̉uij}t*WIYES>}(xCh Q=R^l׿i[}IDvRWdQ˧W9UHr}G~)||/XXNe'wa+³aD ymY= עA#E)#7=Hy "&irY2yI_*QIB3Ch͈uZ$ɺ)1ڮ?]6-g!crz=}ϬvmZ'SÄNC[]" /ȉUFo@zk\y[ LZd9rq)#}}Bhb&,:&e=3I5M Pv]ĦˎngoR![A@3t EKFi|PI][3HOs&2D~M*U`J-K\m#?Xi̮ I.tD nc}SM k'~y4|{!Bk3m?A ESUM边!eNpEBj{-ґ`q:գHFwH> ?ۜxV 5;?wm1j12͡!٨/ҙ/]P n& hZhb64C((S79=; UHjcͤ[M$%7`e_ʜyߨnᨘż7H˼% 3|] $h:$;zX4k|.}br")֨>vOiVXHӵ0ר3d> X?wobAFO 6!Nm2.%Rf o@9TT~@-=g2xa8ng ׋ʷmI<0Omϳj%go{4̍6vvB5 >7ṿ60$y؁" Q Y-Yy=;ٳsÛYqvY]]7UY `X$(G2)L6$2l-})3$)ڢۢ,~{Y=ǽeۮ?^O{ݿvcK?+?{gWG?o7}Wx/蟚O_oӿӋ밳%SxO~?_ߞȟ{K'w~_mx|wo3W k7Ow_?_y3W2./ß(w/}ӗo~_o~A=s__?m׿y/~w~♫W/~G~_z훮Ϳ_~ڏ~?o3?o__~s[~晫|?G^K._З•~og>??ovyw>sG~~c~'_{߈~3W7~?臟zo?c?r{g'~~m?|W~uKw7|<#3z?ehW{Iϯ^yg_q%J$>A{ŇǣO*'Q7\hO~e;_7&x kt{;l]G殎iE44@~h+~amy² |w2߿ԘL?ޟLqlaCe뚃~UqN9*c{R~sSx68F BQQ;aTb{h=ڪV|Rsڊ)_Ur܇ew\.v^rq;^{| LnX(Qrxx Ӹ8U48Wn%쪼t`VBvI㺸n Ay0G9 OxN7Ĭ7;`RH_<ao'4F-EZ<`OF9! v uCKD5hzc㏐g_՚`Az{4?<ϏOy f{}~L\\ߚLQȋBk~?J A|uJiHo/QJuyXw{{TҼ?)4?<8ag3>j?nOhxpLm&*<<ZXpxةK *):*۩t:U-8M;YuHu(쾈tUgs-$k+{22u2bA)jxJҴE*.:Yw^+ a'j+iTއTu4avJ_WYtUWk$;e*kfq z^ͧ-$Ij͗_Mdv(۟,MTB t{z3'AO^ 𚝕AQvn-UtR-jp1*_>O;3 +לY>c׀6ר_._;,ǓAiz/ٞCܥ-./wX@fx0@xȜT [x vC ǻ\$W5./@`xzjs-nip0GمѤozY fCY#;-Z }eܧW^sxwDRtTH+2|@] d8hCH8o%Wv®&Eڵ$vE_$zJ@uu"}Gҙl 7vmB[--Mo4NԍkERsY+sqޓB(*(6.VdLk̶I[,g%ßmӺV Ѻrpd )Bi:6Eezš(~ JMB:1|mo6n ҍqk& ۶v*Ш37& C1\DGݓHΈ?l 3JZ2A5 -"`eBqs#D.tj6ȈAQ̕n0_|BdQ~(0Y1ꪡ(˻,HZ3-BRB($!ђѹ qr};MVu-D-r6.lxk/IcmkDJZp"dX B":At1%#0 $ND:![Va|Ru"! p2}gqF^ ڔ;^cmJQ :fx2THm:ަX{TSֳc,8/Xۆ13P33*3BORfYt# M3m X+vzِdj=4v% JŁ^îSeaF7h|9g!6L#N ':>!)̪W9졞{uw {r?tP̶N0\XO4ͱ\,VL]V-:ze\ ezpvFu,W9P+:WeFc@Q2qEX$9O 3\LgQ9 :KgIFAwH*'YvQ 4-" /(AӤ)jk#4T'$,i #V*(RNBKe@i%"4Ms2%­,Hef2 G~·iN?#*i|T(L"yb"]X'IʣD"fBZzԦ{s(쑦9#״1m\҉$LT$EEi҆oQIg9hBF?:NrMJQ܂4HR̢qQTGIuAJҪ{"@ Qtq-hI8bXH,&i\ yBRSW`I S L P1 `T7L+ kyƒic"`JxWh#EAy)7 3^lLTF˝vN0<5w'(i D1o DNx-{I$%}VZaRƎ)T$ # Fg[A11+w4IK,ueL2IɨPgxY$mANM KXVF)jik .u)Xg^R@ZiZzJ$0#)FhSw&QFL[*M̆,xjͳ& at:v:1 i$>3b2& E8; RvTq+BL͒@k!"B.tG嘈'4%|R" -H1 1ng`|YFh%\;M0O2BSHj)i,F2%VVA +#5Yп,yjDfmIҹ- / e<:41H"g6-1PHV=aEA3`i+IH 0d вYfC#'U!e"ybK8$فYsJ&) T!T:jnBBۄĂ9К;PGƬrJ'smUPcXP'2g9*+IR0!Ab9V(a!.?3^z0`*!':ͬ%JiRJ'nkUm> ͉͓<=-dFs&M][.@+HZ$֟) 4C¶bCZhuNVi4`-֞\ysmBWI: -nJ\p \(5Ѵ$ 2(*bCҘV(UNiHP^] #(_Hre5/NR#P˘QemS n(Fe`>yع"Ti]Y̭dɰ4UV0Hrcw^$W32[_!Xy i?1G,46Y=u<%y&X26GTId

    T]ŽX7viE.+Qbvh4 f;%iO]iu@v~YxC%ko`n!d=(ۆ9L7 `()2AAH/~F$GcAvSX!&e''T&M01/Eb\)$kF c #2$&w4!܍ Wdv\3Bh9|r2f#XYd&1BIm[,Ōt04obR2VgM6E hJf $u-x#B$84 7 qC3H!IoI~A2eYz Y9wؠ"SL~J"_*10T uZ*+ $c9&CMc%E ,YPxSMZdR&!uă,BOnLoZpJ6U mIMiw2 C>Њ|pV0Hu t#"9,gT tX^EhbIxH!d#`4 6` S=Jeh[ɘI5Hh \%dLdVD. In%&\Z$`ܢ^\` 鈻HIF"BԴT+?i*XTyHSN.fdC3ɤ6P JD3bF[HjV]lq+hmԌ4!Z쌒LKxr X`pE2'$4HKqǭsZEB146S ,3 (7U nHQtjA3o!#$ .9o19hR-)Y -#YdaRs) i:L0ܐTN\8V&b'/=rYZOX)טAF3%r-, `DfGQ`#KHf@:x7S)$=q9dQIxT@&!!1)i[ t]73=kvD;FMv \4!ELdZÑe0Ŋ㢵$71}i^qMRJI鱐{I6>jC햤کc[Q qidv-ܝ DIԝw*bY!1J& 靉Mm.WS8AHA& +Z&4INSK"O^uUt\Ho$vʵ;JYh%ޕzSiKGn(|>KVNI Մb (TL8#=huES( 8lWK(M.YJ3' YA1ޘ{.F (|Y5ZH*F]]|PB4a4 <hH&3&rUX)< e!r2W|A^G"4@@c4%2Òv! tѽT4r@*?ӤHI28r@ 4v̈MJk<h4NTfc2,b7L,Q/ Rx#jH! vP Fbw!l\@ISłC?iW\ {%IBUZ2 USsYʤEh2D&[a38Si[T&ƨ3FGbL\K(3xSO;AP, 9Q¤3 &) Bjc Bl"a ecIU,\.=) +Ɂ°"v] +$h\6c&G+`2ɉp^%]Xz 5'G-"Q0{(pJyvP  EJf b)ą(ٷڗ(81,E&FjDbr8eAt !Xq-p01x*MCĸe<lڕ. NQ⵩l$"FK$H ƪI8]㘚=quxJ L$5ʂK'YexOi81cu)Bcaa,rv_H,RG`d6Yp"̸TcDeWԆ+ºJ±-ִ"-@QQ8Iji*SAq&!#lئq"(r`yX8Lܴaxc")"!9*9[ 5$ED˗\vd(8RaPDspK1iqYؕY41A3Y/ ̙?fNI@(TP0@L|7-":DՆXC4ȁwdYJEl7in\ah ,"$%OSKM7UUaԢ_.@ʺЍO@^-r+ XkIdi,A k"8wV,.s%F@ #Ni ?xˬ,pT qH L.4|3 fFL J (\Bw`a1{!{19Upo`{g>F`9N{y=WX :Xkvk:brbrbb=R`6ƭ,dXC ]I*}+XI4 )ΈX$V&hb H|)]ʎG1UӅƄHy0bq% "buyT'4ŧبW}2nZ4JMJUZ5 ȟZ(UhA47ވS2'7)2||(NDBH@,ϫΦ|H$E)5\ S">\kcPb%I'QR&{]SA!B".*,kdt3#;n.*gqc 럙 OY #9@9UHȉq*<6{tdK4eĀa .b`[xpiL`1)٘xWa%L9Mqd:E S;N2NsE8KbmIWU>R}Qm&Į y\Ilj)šUxXPi8?.8?ݲS/&u];g]; O21/g,2wཱིt9p5ay_bIazӠiψp)Ybe^>x5k2\j&,zI]R5s M#q\a_V'9݉PWGB X%(\±XM+VS*뱵XCk"h1RFҌUѸ(5|F/vUBk媁5뒵\E=3r5H^ϜP9Hӎ35* =rh`M1ػ e*7\MqƑG qhWbgIP'\MYԾXZ$ߊ4Z+VRڸk"Զb5sabF^Wv+?mU4Ϛ~ڡT0jP+UIE 41R8RQ&JU!%*AD,uaa ņ%RR.H*aa)`$m{X :, I.a)_*9a)R(G鞖b!%>-ł?!lq͚W0Ig@P xj=+e4w;Y)/M\u*Zv[Pg3dEʹ{V1eZR@q=+5geKT}XrdB1HDAmhω !1wNnq$BtRF0:[X*šoK537ai sK]=,ERj'YKT3D!a)oX$a)$DRj9-s.Z=-$y.C,B. 6gru*6-^ HA'CF mPwq&]%;_DىR%GA5743 4 ! *'"6 /1vX!xfkeQl*gҊf%aZa{d$ZFTk=!.eR8iRP^&!`$0B2xx  ORm0o 2kӬQwqQa_yVW &&ik=gˤ`43IXr䬓$Q$hDT;v&b茲J̦JIPY*aNzkl6^׮5XcS϶*JqiDUj) I !*=C2UzF\-\%wi@'!`i"&!@;iBd2Ab݅چ%h+AJE$vi6ier#XÁ93UJC*au"`Kљ#){ZdNb]MqFX3]C>kس[=JNrI0B0rV2 sB`(e`srM5A p3T !kX5 npWŸIڽ$w2z"?p)As,¤z vrsNZe.Jv 35w_V&J.]0D(dzCO,0AA`g$|p#o.6xaYyG,NY4lj%\,f X9vǥuGlGIeIMbn܄e/Ti=TfhrC&9 k}M,p10qZթjąTPrDTP0,msA !Yꦂ#sN*%%m*(,ZdTPX\$SA4tTPK$zjJ >e86\s&M#UfW 8qSA c3츰: UL*(@(SAK !M\?;q$ZO}a7^.(lgRA)PnשB:*X0.  ͳ#9l=1*=&'Qʹv0/R$BbcM*1TPxTP #/r[]u.zlAUɠ8n1l69-dP0>?׹d=Ź.B عmr\P`!0 @(<6T9PF K^h9b r\P"P 8Ss.krA13O ܆\_q \PS ʅ9LֹrgrAst;h6dB{(]kdR"gSdrAٶ׼_+Y?5[~9 ,yC{( q/yRxf6͏g]ea7yrU/k5HcȈ$8)A#6ԖB5IdR fRs֎k;x+u+| x lN 'bHZ 7)^!(U*yFrvƬ4۲Dx 'sq bdӖ%[`3ljfX<)tnڮ4ھEO) zP.M>}%XWjiJ4^,_68oHީ; o%J'qu0:nZ淋R؂x;R+k&o0iKD V#=LYNrg&6!Vm_kx!k7zDnWk ?`j1^V$rZN/, xMn(㬓HmP|XA{&I -¥CA}xրL<; ,pRYH IĬ;/=3O?/f`|dh>ʿ*5^gG>KKCypTS={sr_'v ^`69Gerov`8? t[bG@Xve(8",`:GւEx N^ H1r1?< &dŻ$Wr1e *@';|{^Ά֤.Ƹ=LӪEy):(g/DUzkGOFnpNEyrY]:ksbbA?d[ '45TMMOfr?Y,&4qALg%y6wbv}2'˓lHV>X﬿\~ep %&p{YtL;'FWbJ`0R1~cɃ]4/bQWJ!)}\sB"Dw8.p0(eQjkeo?>#YsA\{<6a漹ϤwF<8wXwqhvl|Xv-~{VN"1Dߤۭ;Ց} OFCڿAD 4sԥnv|O>SN`pmg *ǓZ?aɈFDcg~YN,ҍ~\m~9V׈p0xVZƃވy a١F?棗- [`@|]Lvq!2oDv_ql9cmch8PҬ}\M;-'RNmUB8>gGOcé;,@CO6h;Y>b^Lx e&AK a'48( ʶ6ۉd}l_,gph'aDp7-H㝯>MH/_a)#{+y'ܳ5a7䝕aGIs$j (THo$zA Źs$RĠ{ǐIXU#[LHg$Ho/.8MDu|^4?&s]Ӹe-G5uy<-tm0ドh/4W):XԼ՗YrWF Yqf)zE< ɌPi9%ݳߛ>VO A_KDܭl˕[ʊz@[ 1ғ6n0ܺ^t4=o1L`13&u]=į?mz^[MAmQMkpatB+̡}Q:NV ?azKM^#-fFxĎhkHpO17N =*[7y}OdcsA3;8`b$æzD"[{!7zXP%EMȪY2wHz=- |1GBaD0`)zOBGp vہEei0{"'?WLBq8tDޞ/Ay^qmӅۮڔ+p.UNlJ -gsԚNֲm^ϮJR pa4`jxD 5ߓJs\jl-7?엧PDn띄'.[qsݸC۟]53YoGO^H+4NS [4޼+}4|ޞ4fXb5Oe{'1mqnohi (}ag%Ay[g|f'3 F4 nAS,YY፾έ50=U6+k\KH,:rA=ΗScVɈdՊ׳!oq2ʳMGͶ?y|t.kx73Nh80ux2rf V`< _|85?b^[v/5Zn%9J<O_UeoTVLNBtnf3^/Eqͺ9GPQ%DmspKaNtb4,ʯжŌp 6][xS5iN\Ixg첎Xi-Ϗzӕ3 jPyϕe{ i//5$/KvƜi/i=*G#hIJtV6f#G>r+|;ʝdN6}yeoV~rH1# XM"s~z|m ʌgNdArT`T7΢3c$v` .Z;{b~7Qt| 1)29Ǥlz8+ŋ|ZH?6pnpbha"m9Q9ښ)]Ryno: .q'}}BH/?0Uؤ,<_w'XwHp"3o_'=ҿAHZ{FĿs l^ 0:ߜFaph6/1Bq z/lԝwb4>vnSs03ZG8CioT1?7&R?Z~8 Ѱ_eڹUk&hZy jd&Bƃ/1]%*h?pI:%u~@WqZ|~xQIo(Q9+;| 8Y~( b."HB|sV?37%E{9pA~ġɸ_j{”h[S[QEc&xWJ+ &mr6d,9%XYWƄhƽo^C;{';3vB|Oagio&6%9`8D8B1uţh=Ͼ;/mЏk..WݯY&X$jr CstVIfx'Cs;mK\%.IJ-T7 oflxtkw@1*Mf46Jj{@òL;e̻/Mٙz[rfao}5]L;n;wwE'I6}ǿOe lTU81۾t6ϐ{-J&xǏ/>}it6OfŪZbi^K7?{tygF 4'*=h;<;mdxNG'KKꍛW7^ނw۷_6>}|~ʺ9¶:5T1G7G7wQ( ?USO، j(2έF G Kϔ\beq4>1rGǂ83.a4.ĞV` Y?3>p^'|XwJܹ&,':`}2| uww]!Śk~ЏMD*`vxqs7n_ԭ+77ŽBvyלҦ[a:r0ftWe^UmlȲa|}#xV~K9V 9aVB@63o6!1xZg-BjT?!'kk3#lȗS^6I*N Rf).p/]9S-&/|qr[x^IΤq\wtZVU_|ExJ2oi`VD8>їNݪαU:jpjBX#; "9Пز wNzlJ|j'{g{ҟ]6+us㽘--r4/7j*6fߺ/rxf5^9*;xR7``:p|%Gc )u^\c[߯[ͅ_% GZiHso; B'2Y.L@ 5jﰝC R'iڤ'i5!eY'Ӿ&hlIR5hyEp \_ʽ6+nCвkCN6=Өr^Se`{˛r!4;zun\qh/EvF4Y],.+trJʎ%FдKm2f 3d"҂'Qi&;vc揾uжVpNXtf=7S}fWf W`IcWpP?zoUh8tUݒ+ς'e x2@ѣqMsfk(50ߪw*M.(~U W 3c'[`j WvxŃmg[ Ak{'Co~L@9y'(L_ark Mҋ_K|* U͝XdI=vrqoZ{n| "9"wL H,[w}Imc" FzǑtwgQFcyf7}']1x&"SRp({s |3Z8w|\qOFx;x|qpNx8"WўPC=IxHݼl6;Zj]T>§^Oݸ}e~2bkU,Ʋso{zp>شmwh9(_^p7,n5ЕoFc$?N6w&a΄؇TE5:?N3>?׾\EDF5ЋdwpH7䏋>tXΩ' ESTvx}){Q\rl%XPks_/܏,7GlU&Nܪlę lܞyдݛηV# s $m-1\.R] ބnpN8=;Wf 9?MƇA!`U[,Z?!*+eV|B7*c/ī_ d:w$b2*,~syP!DGg7V<)0(y!gFB!_q̯1-H䱿uڕͫ?~kx7ǧڤd=Ti Pqҝa4iƳ>ƟA(Aouz|彎T'~,JX`yxb0uvpe;_8ϙƧ榑sKAբO}{6ȣU'/x ;Ԗaiiwo kf3=Dx5"-JHg-c>]N{pLNd"Nc~74. Ǐ~|炗K;Ocݕ-=qc:m;9N]! xVwPw֭wCk>ݷwܳw{-Z5vكko}P#)/%a 9BI?gTXe{~:SUYxi\EkḔkF!K^NB򒖣>^>,O(.vӃ"e^Oe㤟q_$wˊb)+rQ"ԽH,~~HBŤJ&#D%}ClCS`^p[@g֌Q:|]8"o*+RG2_t$_8AZ2WMqӔJM9I1Ձ+Fʓuܨ& {4 Muso'?E)w.| `?:^ f0p y o{TLJL{}^k8>W'ѣnʒ[5ܴ%`8y!8CqC[qAe[:|ػ_.ǽ#3yvH%ZJWP'}ڜ`ST{{'~k/v|%ށ:GJ•_}5|etq 9Fjo]!IQ}<6l_8^y}uERV?APE>uӬ[ύ7g!sfTfRnom3igGA9;#?t;7>qWB44`$R  <| Sxv977<`4>;Y:L<ԳDwOCo=Elm7z&Sߋd{~2i7gZC3~݊KS[;H>0mL;;; v(#rAQlkol~0wޛso~q'pbh{8ٓ}ZKK^ ލϗEW~bӬ2} $Z6HǙJn5c/d3!ty4kJtA& &rUݩ(ҲR~sH}9~ҚF^}kW>}ǯ>!uL,7XGq6_6 Gޱij-/8TΎSvswF4q F+4Mn녋եZb̢oz0e 5[Pekz:ԙU"F-ӖUKz~l\!?9'IkҝOKsfy`I鹾{jjd}}Oߵwl_x(g sqXNJ2V%#5EQwvQXato^9!S:5|8c}p4ln^gA9+ M7eRZŧݬj SHn͹3E5" ӣ tS$ *&G˔NM_lQPŠ`.D BW⭤ѐ_GC"`RiAQ2W>-5ZzFg?]&cS7$8x:Dhu]ޯC[@RɏF|wz5]C&_A nŭ'n0ǪսUC#mNTW|P;Vxc>sMV=IlK.*l>N(QK/$^j+">%LRFnꑒ霱:Y'"PSal  Ѱ,gxۑ`=1c}mxeB"625Nj[0Wgv\I3]LhYӺ(ثۓ0l_^}BmOO :cҝt(#?Ui+wbZs\ÑI~NKZih.ˇHhx)69. 3jZM'nc'9kU;>,2JڷX=W=]UxҀ`|<W\~d\[ݕ]G=2L.'Kߒɗ,OW*IQ[N9$uտ^HVu *kPa4(Ԟ E$)z'oNݳ*`q r&2*)yv;wZ!S[j$-U\IM`;E_D-{O([=;1FLnS b;U`2Sgx5Fl:^Q ^nHr_TrnZ?{oض$ +z=-|$ˎbˉfl+).H$,4^nqrO̮%Ս>}v|7F-%2}~t 5o??<~v|Gm#ėБCxp<mx6MRI) 4ƒDjSYǯO%铡U7ެu'݇&MZhpPuYɷ`%D(*)`n{tTRV=iWkpݑT1pt>L*aZf Sz/'NˆuW4x ȃt6krt5ar.\eX K؁mq7-q K ̰Oa9Yg:ofN`Pn_6O9;?4P!6y( TalfV)XI觯~tTA-UXQ bMէoc-D \t i` a3JQ%Fth3Λ<\,jťP2Yj~2p &'T/(D7F:~ʭ:y~ώR1ۥJ^>짬a-Ƨ]HcZ֘nepE޷{{F6u6eA BO7(#ֺ(4W'7׬ۨAGϯ̯ƂF9[t5 []c+^=9пV*?{Jp]G *&aXin_؋C$k.#k΃֡R~~#_MEN e ' ]!8D9RF2( 6@闶aEv*n6Adf>LšCuU ˒_P}WN4pj}2y,iDIy\nQ;=?V;r;o'G Yb6O AaM`*םBsLD Ѓu,hy-zA@"-`J{^Iޡ=.iZ`w''kEFԤTഅˊF ݅3h=Nj/#~(;+!PMRйCKAxF)Ic)59`"Rb@x0l8F^iDV vZ<cTk ) DjO?ܿ#sTci<!Z7~F5{ΛZNoQj!f^ ?E5s.._STT^Rx BnE7ルsw6W F9ÈuO WFV+3fC'Vف#(M( @kj{0qlr=kN{!Hd^"dÆRIKqcOA?plQǃV>9P Jp~/`eܧQ))sbPwF l |91q5Ld*c *ENBF.TsA쎑TI &ќ8Q_|+|])LִvF)dV+ˆBJmLB'~(ҎLPbHizNāwHT1RтcW}5OWM5kE]hrYe _"VGh&{%[{1WG~4'CmM{D?Xib(`AM#dGal1jQ2- s %2 ත_ 4?"L S!nj BtM^(R/]>t?`w=HVb r#nji}~|}qIq2`:^?yl['w@D ~?9Mًml-̛q0ǸO-`M9ܔ~gdh!jbZ dֿ#2i2l}[8YJbuҏa,$Pw l#d QaBpE5̹iOOe?ml<ަx)5ޥŀ{yLŊк>àmkVp{[yENXT;!Jyn %0@iv>cOU=#{/{8FZ9>涳Wt2;l$}AV1U$K־EAqٳ7ׇR;NK$P퉳GB>gC 5rWIxDZU%`_7Nh+=A2dyln Մ\{!{rfF;3S1߿ߴ>VV-ML9H'(,& l"nò@EEޮ7ol~f(2žU~YD" ЦuB-uGWl].5c#ye4 G<ɒano2TtM'M=-2Lm&[{2mYmO4.򟱓H7Sӿ0"pYܷHǛRH)=Pk#3۫ ACu#0^`ʹu4!.^EO%JozݏPk0ewG.ԋr"(9z}o<9yTj'O:Z\Oi=ɬ Ȅ7[JuP U ^1:u@OMJfvKA+Ρ^:ƺ_7fFXpqӍaeRK{A_Dvnw^w;3y[.GQp}u1Bai* 3p WPCM^[|i)Jv57lXj2ND]]8sJKXK'O걽|$+ S۷? vvn%I".wۻzEv'o~o7=]R616ePrSz ]! m0Qr,p%+E]rRA[Vjqx=2Bg|8[OAQ̿K/so {d,0^ g\U4ʜ*Uhtr#z|%MaQWTB$& >ŽnZDPf$iVPԽpa#nܣE5 ¥ a8 I)yu>';*e .9RR0\LQ|X8X_*y?f;V/C+&l09W74xϏ/y"=loF-jRi8Un]}]#s7BPlVhqu #k"QU9> N_(m98ЧOڃaξ)Ke1XY'ѻB TЎ|[FJ9-Tq9)hD8o*j܍Uo0B9zKpy8wH8BtK˿Bkx˧*#wwvs_nf ?krL.=j3olj k Y9chՑY4B'b囲tC}͐QLq,pvj\?;}.gsLxp[+?|ysPޝ_`.F'h9?>y}vv)iQoZ@T`-zꛍ:#DK%]qw|n_}_3hݴ2miM0S F_qZ7E*zyAӪ s7 kMc~_7$7FhB3%yg`l 6A/23s@pp)+) aaYj G]r6Ȝf#LzQAQS8O ;]bB;uQԔl/t(ڴ As(MQs >ZFGXCިSrX),Ց&M$ G`D7‘WHU(?]5a(^S|eYQcT"Q+ŒILO{1(..,YfZ&Hx&[{k7;ل Qsۉ] ?t]ȏ~"bbaк}#~:we"szf(/ /]z>X܇D[@5(X-Kڲv +PO/%=%5:R*Nԙj 6d"6J\msT<&Ӗ6NkvOT[, "@Wŷ56m_QyP_kϤ`#WQkf$IM*4ZȲ6S+;2YaV w\E5I7F(FX7TgSexRJvPtQbit?Qd/94Yq,oSrlK67hnpQ5a]ԱjgiU=0K˜@NG(Egƙ̋Lu)rgɑȚ.R3jK6oש7@ЅC-Whydjk ^k(_Gb%?tFo~z}O^+z;JH% 9f'E*^ A31R{f6T](맲᳿w:|ѩ2ӔtYL5~2<ȗ Cd(L(n= g|aȃ,-EStPKc˔Po ėW>LC 3xjI  "b:&gYpD䃳x؃bzʐ8~ nVcg}gd32, `GL.~p I[<_փ|~1]5w%0Zpdx6&zєm J_kOuN6f ڰۅߞf.<wOA.xnDd,E*veI1%8nMD\A;w UI&Edxrӑ՝F.Dwʦ0M_ I'$BlwYG]ymAeTEh 7yjejM;D` VͣĒI@Y#pw)>i@8&/k{C O#*Qx[(K3 ⟀tÐ 7\1 (kd]?,nk7HӣT(cF`$3H1[!Ew9k%F=Rn)e SYB({|ZkDveS}8[HA(c':,pWkՖ0g94Zӧ.iKhVꨊő)k˴GupaMRd.UQ}^\ṛi@ſC&L{4Gn☊{NGʗ_>pU;Gn?_: %LFnffT@<#TWR8 V_'eUL4 Oe&J1F͢ŭ$%Ւ =L*sȷ>z eJ+xL_Ț>%F(؛B {wzL J|>W|p+x~82s׌(nƁ?&Nn.ϣ[zk,@Ͻea6m[Foэs飑QQ#4I##/u`:ʥZUV ,|X,{0pEcS''NJ@vr T{-ǯE. hWfVd<ɭwR\"@5& bXcH6֥*mN jD4q LX tPr*˗CVCU@ f0 mK]"ަa?6䕣="7Q})J]JSD-"xDOVd]7GT\7V!VL3ڪLsxgRsn08 "3z'.5{?-nj~8hZ5W}b}] -oC K p6qrͿIfUNoTO9M+&w@7;qͨ (o>Y3޽^rz($qwzg`QO l@Fv~&s|J\'ݰ[Vp\ ڵ5uC$`{s|$i,Ǔݴj0A&4r&oe"UÏan%]x+(NQzp%;pN2*jK⢎yX N~^N-7Z$NC0򑋑-śS^|9k5& y3kG~{pTCUŵ`n8~뎓5;;qLʶ@h{e >1͕0yn ee!zԫ7LV8*y8[zn[O?3Jװ>wFǽ.F.W(X~䛲#!K5IUسH}Zm'3~oVvX" hraVo gi) Rg]zxG%n+tF/ vYt9MϿ?ڻ<{Ɏ}/Q $/1i(2j*_5!2r%F36"X|f lTjEI8Άact`"\8c'‰*zm {#ip S,D6MKyِxB?/يmq}ƣ*2[xzm5>V&n&%7З@o}.ʜޑ:Y;x ,Oϱhii,K{T_8WXUTC0z6B_km f,h؉l-h5V;Gyկ$`הGp?|,gaF8i@8r(N8 F4raEKrӿ̪LaF 2 tk+jNx[\B;\Y!<-@6;%Ur>X8nuGրVZtoId,%~$mF4}}u!iV8%t@A܊A %|SC>V_ w.QفV߇297(xų[ODb,8C8@!b m <w>3Θ&ࠚT!F\9ӴW.0tPKq}Z,c"x8 f~0mA9;: ޜG;ZQ[AM#QthLspv)ced~<:a"ִjɌ0V&mQ^fmN_Q9sLg!*|[5Q/ GF`9XݴU&zX2dj{+[(m@Xف-w(Qce7MEa>kXN!ъ6(rhE̖6H"#g"a2#70܏g-ʪ0N tjmLɺ`z=\(XLn|1eW Dʸ#Wl8q}TA4NDh =i/`ٶ^3qLב 7&acSRJؚSx),aiίUD8S)mw k$tu&>4jFF9t,ȶgd .DCɝK(ZsH9TU=vY5 A۟a,9*;% :v9,vD!͚k,`Xf4EG,XtDˊeȕ^ pɺ:Del4w&稢8Hkv 1uELWP* 7#y/k "1YoQO)%BQ:QB*hyc-9TӤvhh~ dDNXJ~웜N#xXoijgZ Y6YG(E˃_S^QiR@ 4%%`8tcmVh?  7WDי'Wq.06g)0MbR UaȉӏDa9=Շϴ5@;h#ð]A.ȝK2cw*&"#q7}Rkn:Xz/8Vn"MGJ*X dB [c6Q`aҎ6W4 8pA#m0 ^pINVL:!9߰*KEyRr Z% Rh\r`b/!΂4g`אCnOtտTֶB i2Sž(dRs oZl}(yMʼn%rGA{cj(eZw0I1-MD[MH㑫@$Ot@6NfMdn sѩMj rǓLPz`M<>5=-[E|Yi DlP41F8Mrƴlrߴ ٢5y8,A{ym\_ܕi.2&צCdiF 74xNkg;@TE:RFWk8ʝX}JYi;>IA+VFg/S;ɪʼnXCW?b0rwIT^Ȗ~MB + >f =0Ο:'`hTΜU8 Jt (; #YhUG6&!h0 h-7Ⱦʹ/)6S"/Ȇ1}37$rk@ÿwu̥;[[y{~o|˭P|u)e<<(sS:5֦J5S;65y]tMϩϜtͦ6+pl:-i$5S^3v7BL>S f7PXR"'9(EO FG"Y$":Om[e` EU @%v; gu9L#O/!W<֔̅=ъVB8Q|LUkWPTYf&VN6USF~]iFչB9E|;hωcboʢ9wfDt+kxa'Ņٳַ?h\uBa칁:p=HGZ䲞]Rd;ᓜ lc3I4sPtFHޔymCNk^DL@-yb(aH" - jZ[(O2h3XrmZI?*8SlUȝ܅),bV ȱ&L \TvJ,{ފ~buMprH6T[>*C=p-t59:yVF_0>N>f򁵣(0ODb0L:Lf+<+-ʗ[\FRtDA;T3'X[:0$NyqvMᗗ WC+v[ gZ|͜Ttj?Bh'H 2֥cJ3c66Ɔ =HBtFvN;-1B~kh$0AhylOErSt7[V qMg<"̭Ba[lMō7BT:o,mhn8Dp-T(7pGI*- ^M h0*-H-XDArWpFѝ2-S+N 'A^NGf^Ry:õzXiǵ)9(]X=>TJ (ZJ/KrXKssKBedH`h,DDrͬ_U)Z'Ssճq{]ld<7lbe_ʣ.MJ7R?6Xa.r+W1p`]AAhzFG+#Oņ%?5vsCCD-)ɓ4*N P$c5SLJJAN.9H 0:WEHTZDDzMI?~#Hm>[RTsPR4\Iʰ!eYc'[MyK,n6F_nCl B wȫ#U!6EV}*Zpmd+8xåX"bSDqqiDȺ]į)}2)>\oWZgg(&¾sM9"m 8~ Ǩ|I*7L30rz漌l{IbaCh| VGæ%HALb$hA8B4j$j-7;8ڏĊRgOcW[ tM#iEhސa$&MNDxi\JyV$R,Kg&S8 ;я5hX47>S SD^̐ )hBLK'O0<{W"k+kM9V b& ;f/FT_Ԡp"G tjDa`lNmsHD>O/ !+ݐUY⻒+oK+@O'gd5.8Y淎Y9߿}يv/I+79Ӫ[ȒR)c}b 4L:,a{iFJhni43[5}jG,M=pyh,F>̩I)mr^do |D1M2?w"H'!].-J* d;мP-;1D*:DSܠ4 c8AkR%~{}p!S\`:LQ MmxS@%+#\ \sw2L3<1D)AG1 s(!'&RHd2>7[:ɨ+nTC),K*Qkyf8Z"ݕpsB/,i:"x8n35`*W3i6sBIy '6 /Eӓ9[kZ_Ľ^"MDX3&G%!@V7 QTOd:An`V4rݩX67YZzS.:wހ* ]W+Z: Onj)dZùBA{G )3NvfX$L)W) ?=L%sje-4Yz۬%Kk p R)rg( ^1Þ(P;q(-@N ;o.22.d-tkae_4er©^.S%O&ImN+К,x0*I(Kƾ-&LY(?&jݭMiD'!a<]w'sBJ#o ֟6P R ٓxaXT$ )sh11ɑc~8ID(L(- >ݚ$4j_Ya7웏ƈvbzV}@F"?}s^@/"'߶[a`]Yg1]̽~3 K1Q[VeQj$Rc mk}+`7"vi>tQ`qO_<7j pN[xq7$B4>ܴ'_l4;}|o/?^StE,z4wD< lͷ[^}]^tAym#yV&P0Y dx̍ɖJ IuzY[j:Oκ,AQqԠe"v[$ P0hD=j/7 U𙓴QFfQ+D۷E~"9 ) +R3KGԋ;I2Afl%00 Zr